1 /* 2 * Copyright (c) 2015-2017 Qualcomm Atheros, Inc. 3 * Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "mac.h" 19 20 #include <net/mac80211.h> 21 #include "hif.h" 22 #include "core.h" 23 #include "debug.h" 24 #include "wmi.h" 25 #include "wmi-ops.h" 26 27 static const struct wiphy_wowlan_support ath10k_wowlan_support = { 28 .flags = WIPHY_WOWLAN_DISCONNECT | 29 WIPHY_WOWLAN_MAGIC_PKT, 30 .pattern_min_len = WOW_MIN_PATTERN_SIZE, 31 .pattern_max_len = WOW_MAX_PATTERN_SIZE, 32 .max_pkt_offset = WOW_MAX_PKT_OFFSET, 33 }; 34 35 static int ath10k_wow_vif_cleanup(struct ath10k_vif *arvif) 36 { 37 struct ath10k *ar = arvif->ar; 38 int i, ret; 39 40 for (i = 0; i < WOW_EVENT_MAX; i++) { 41 ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 0); 42 if (ret) { 43 ath10k_warn(ar, "failed to issue wow wakeup for event %s on vdev %i: %d\n", 44 wow_wakeup_event(i), arvif->vdev_id, ret); 45 return ret; 46 } 47 } 48 49 for (i = 0; i < ar->wow.max_num_patterns; i++) { 50 ret = ath10k_wmi_wow_del_pattern(ar, arvif->vdev_id, i); 51 if (ret) { 52 ath10k_warn(ar, "failed to delete wow pattern %d for vdev %i: %d\n", 53 i, arvif->vdev_id, ret); 54 return ret; 55 } 56 } 57 58 return 0; 59 } 60 61 static int ath10k_wow_cleanup(struct ath10k *ar) 62 { 63 struct ath10k_vif *arvif; 64 int ret; 65 66 lockdep_assert_held(&ar->conf_mutex); 67 68 list_for_each_entry(arvif, &ar->arvifs, list) { 69 ret = ath10k_wow_vif_cleanup(arvif); 70 if (ret) { 71 ath10k_warn(ar, "failed to clean wow wakeups on vdev %i: %d\n", 72 arvif->vdev_id, ret); 73 return ret; 74 } 75 } 76 77 return 0; 78 } 79 80 /** 81 * Convert a 802.3 format to a 802.11 format. 82 * +------------+-----------+--------+----------------+ 83 * 802.3: |dest mac(6B)|src mac(6B)|type(2B)| body... | 84 * +------------+-----------+--------+----------------+ 85 * |__ |_______ |____________ |________ 86 * | | | | 87 * +--+------------+----+-----------+---------------+-----------+ 88 * 802.11: |4B|dest mac(6B)| 6B |src mac(6B)| 8B |type(2B)| body... | 89 * +--+------------+----+-----------+---------------+-----------+ 90 */ 91 static void ath10k_wow_convert_8023_to_80211 92 (struct cfg80211_pkt_pattern *new, 93 const struct cfg80211_pkt_pattern *old) 94 { 95 u8 hdr_8023_pattern[ETH_HLEN] = {}; 96 u8 hdr_8023_bit_mask[ETH_HLEN] = {}; 97 u8 hdr_80211_pattern[WOW_HDR_LEN] = {}; 98 u8 hdr_80211_bit_mask[WOW_HDR_LEN] = {}; 99 100 int total_len = old->pkt_offset + old->pattern_len; 101 int hdr_80211_end_offset; 102 103 struct ieee80211_hdr_3addr *new_hdr_pattern = 104 (struct ieee80211_hdr_3addr *)hdr_80211_pattern; 105 struct ieee80211_hdr_3addr *new_hdr_mask = 106 (struct ieee80211_hdr_3addr *)hdr_80211_bit_mask; 107 struct ethhdr *old_hdr_pattern = (struct ethhdr *)hdr_8023_pattern; 108 struct ethhdr *old_hdr_mask = (struct ethhdr *)hdr_8023_bit_mask; 109 int hdr_len = sizeof(*new_hdr_pattern); 110 111 struct rfc1042_hdr *new_rfc_pattern = 112 (struct rfc1042_hdr *)(hdr_80211_pattern + hdr_len); 113 struct rfc1042_hdr *new_rfc_mask = 114 (struct rfc1042_hdr *)(hdr_80211_bit_mask + hdr_len); 115 int rfc_len = sizeof(*new_rfc_pattern); 116 117 memcpy(hdr_8023_pattern + old->pkt_offset, 118 old->pattern, ETH_HLEN - old->pkt_offset); 119 memcpy(hdr_8023_bit_mask + old->pkt_offset, 120 old->mask, ETH_HLEN - old->pkt_offset); 121 122 /* Copy destination address */ 123 memcpy(new_hdr_pattern->addr1, old_hdr_pattern->h_dest, ETH_ALEN); 124 memcpy(new_hdr_mask->addr1, old_hdr_mask->h_dest, ETH_ALEN); 125 126 /* Copy source address */ 127 memcpy(new_hdr_pattern->addr3, old_hdr_pattern->h_source, ETH_ALEN); 128 memcpy(new_hdr_mask->addr3, old_hdr_mask->h_source, ETH_ALEN); 129 130 /* Copy logic link type */ 131 memcpy(&new_rfc_pattern->snap_type, 132 &old_hdr_pattern->h_proto, 133 sizeof(old_hdr_pattern->h_proto)); 134 memcpy(&new_rfc_mask->snap_type, 135 &old_hdr_mask->h_proto, 136 sizeof(old_hdr_mask->h_proto)); 137 138 /* Caculate new pkt_offset */ 139 if (old->pkt_offset < ETH_ALEN) 140 new->pkt_offset = old->pkt_offset + 141 offsetof(struct ieee80211_hdr_3addr, addr1); 142 else if (old->pkt_offset < offsetof(struct ethhdr, h_proto)) 143 new->pkt_offset = old->pkt_offset + 144 offsetof(struct ieee80211_hdr_3addr, addr3) - 145 offsetof(struct ethhdr, h_source); 146 else 147 new->pkt_offset = old->pkt_offset + hdr_len + rfc_len - ETH_HLEN; 148 149 /* Caculate new hdr end offset */ 150 if (total_len > ETH_HLEN) 151 hdr_80211_end_offset = hdr_len + rfc_len; 152 else if (total_len > offsetof(struct ethhdr, h_proto)) 153 hdr_80211_end_offset = hdr_len + rfc_len + total_len - ETH_HLEN; 154 else if (total_len > ETH_ALEN) 155 hdr_80211_end_offset = total_len - ETH_ALEN + 156 offsetof(struct ieee80211_hdr_3addr, addr3); 157 else 158 hdr_80211_end_offset = total_len + 159 offsetof(struct ieee80211_hdr_3addr, addr1); 160 161 new->pattern_len = hdr_80211_end_offset - new->pkt_offset; 162 163 memcpy((u8 *)new->pattern, 164 hdr_80211_pattern + new->pkt_offset, 165 new->pattern_len); 166 memcpy((u8 *)new->mask, 167 hdr_80211_bit_mask + new->pkt_offset, 168 new->pattern_len); 169 170 if (total_len > ETH_HLEN) { 171 /* Copy frame body */ 172 memcpy((u8 *)new->pattern + new->pattern_len, 173 (void *)old->pattern + ETH_HLEN - old->pkt_offset, 174 total_len - ETH_HLEN); 175 memcpy((u8 *)new->mask + new->pattern_len, 176 (void *)old->mask + ETH_HLEN - old->pkt_offset, 177 total_len - ETH_HLEN); 178 179 new->pattern_len += total_len - ETH_HLEN; 180 } 181 } 182 183 static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif, 184 struct cfg80211_wowlan *wowlan) 185 { 186 int ret, i; 187 unsigned long wow_mask = 0; 188 struct ath10k *ar = arvif->ar; 189 const struct cfg80211_pkt_pattern *patterns = wowlan->patterns; 190 int pattern_id = 0; 191 192 /* Setup requested WOW features */ 193 switch (arvif->vdev_type) { 194 case WMI_VDEV_TYPE_IBSS: 195 __set_bit(WOW_BEACON_EVENT, &wow_mask); 196 /* fall through */ 197 case WMI_VDEV_TYPE_AP: 198 __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask); 199 __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask); 200 __set_bit(WOW_PROBE_REQ_WPS_IE_EVENT, &wow_mask); 201 __set_bit(WOW_AUTH_REQ_EVENT, &wow_mask); 202 __set_bit(WOW_ASSOC_REQ_EVENT, &wow_mask); 203 __set_bit(WOW_HTT_EVENT, &wow_mask); 204 __set_bit(WOW_RA_MATCH_EVENT, &wow_mask); 205 break; 206 case WMI_VDEV_TYPE_STA: 207 if (wowlan->disconnect) { 208 __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask); 209 __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask); 210 __set_bit(WOW_BMISS_EVENT, &wow_mask); 211 __set_bit(WOW_CSA_IE_EVENT, &wow_mask); 212 } 213 214 if (wowlan->magic_pkt) 215 __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask); 216 break; 217 default: 218 break; 219 } 220 221 for (i = 0; i < wowlan->n_patterns; i++) { 222 u8 bitmask[WOW_MAX_PATTERN_SIZE] = {}; 223 u8 ath_pattern[WOW_MAX_PATTERN_SIZE] = {}; 224 u8 ath_bitmask[WOW_MAX_PATTERN_SIZE] = {}; 225 struct cfg80211_pkt_pattern new_pattern = {}; 226 struct cfg80211_pkt_pattern old_pattern = patterns[i]; 227 int j; 228 229 new_pattern.pattern = ath_pattern; 230 new_pattern.mask = ath_bitmask; 231 if (patterns[i].pattern_len > WOW_MAX_PATTERN_SIZE) 232 continue; 233 /* convert bytemask to bitmask */ 234 for (j = 0; j < patterns[i].pattern_len; j++) 235 if (patterns[i].mask[j / 8] & BIT(j % 8)) 236 bitmask[j] = 0xff; 237 old_pattern.mask = bitmask; 238 new_pattern = old_pattern; 239 240 if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) { 241 if (patterns[i].pkt_offset < ETH_HLEN) 242 ath10k_wow_convert_8023_to_80211(&new_pattern, 243 &old_pattern); 244 else 245 new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN; 246 } 247 248 if (WARN_ON(new_pattern.pattern_len > WOW_MAX_PATTERN_SIZE)) 249 return -EINVAL; 250 251 ret = ath10k_wmi_wow_add_pattern(ar, arvif->vdev_id, 252 pattern_id, 253 new_pattern.pattern, 254 new_pattern.mask, 255 new_pattern.pattern_len, 256 new_pattern.pkt_offset); 257 if (ret) { 258 ath10k_warn(ar, "failed to add pattern %i to vdev %i: %d\n", 259 pattern_id, 260 arvif->vdev_id, ret); 261 return ret; 262 } 263 264 pattern_id++; 265 __set_bit(WOW_PATTERN_MATCH_EVENT, &wow_mask); 266 } 267 268 for (i = 0; i < WOW_EVENT_MAX; i++) { 269 if (!test_bit(i, &wow_mask)) 270 continue; 271 ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 1); 272 if (ret) { 273 ath10k_warn(ar, "failed to enable wakeup event %s on vdev %i: %d\n", 274 wow_wakeup_event(i), arvif->vdev_id, ret); 275 return ret; 276 } 277 } 278 279 return 0; 280 } 281 282 static int ath10k_wow_set_wakeups(struct ath10k *ar, 283 struct cfg80211_wowlan *wowlan) 284 { 285 struct ath10k_vif *arvif; 286 int ret; 287 288 lockdep_assert_held(&ar->conf_mutex); 289 290 list_for_each_entry(arvif, &ar->arvifs, list) { 291 ret = ath10k_vif_wow_set_wakeups(arvif, wowlan); 292 if (ret) { 293 ath10k_warn(ar, "failed to set wow wakeups on vdev %i: %d\n", 294 arvif->vdev_id, ret); 295 return ret; 296 } 297 } 298 299 return 0; 300 } 301 302 static int ath10k_wow_enable(struct ath10k *ar) 303 { 304 int ret; 305 306 lockdep_assert_held(&ar->conf_mutex); 307 308 reinit_completion(&ar->target_suspend); 309 310 ret = ath10k_wmi_wow_enable(ar); 311 if (ret) { 312 ath10k_warn(ar, "failed to issue wow enable: %d\n", ret); 313 return ret; 314 } 315 316 ret = wait_for_completion_timeout(&ar->target_suspend, 3 * HZ); 317 if (ret == 0) { 318 ath10k_warn(ar, "timed out while waiting for suspend completion\n"); 319 return -ETIMEDOUT; 320 } 321 322 return 0; 323 } 324 325 static int ath10k_wow_wakeup(struct ath10k *ar) 326 { 327 int ret; 328 329 lockdep_assert_held(&ar->conf_mutex); 330 331 reinit_completion(&ar->wow.wakeup_completed); 332 333 ret = ath10k_wmi_wow_host_wakeup_ind(ar); 334 if (ret) { 335 ath10k_warn(ar, "failed to send wow wakeup indication: %d\n", 336 ret); 337 return ret; 338 } 339 340 ret = wait_for_completion_timeout(&ar->wow.wakeup_completed, 3 * HZ); 341 if (ret == 0) { 342 ath10k_warn(ar, "timed out while waiting for wow wakeup completion\n"); 343 return -ETIMEDOUT; 344 } 345 346 return 0; 347 } 348 349 int ath10k_wow_op_suspend(struct ieee80211_hw *hw, 350 struct cfg80211_wowlan *wowlan) 351 { 352 struct ath10k *ar = hw->priv; 353 int ret; 354 355 mutex_lock(&ar->conf_mutex); 356 357 if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, 358 ar->running_fw->fw_file.fw_features))) { 359 ret = 1; 360 goto exit; 361 } 362 363 ret = ath10k_wow_cleanup(ar); 364 if (ret) { 365 ath10k_warn(ar, "failed to clear wow wakeup events: %d\n", 366 ret); 367 goto exit; 368 } 369 370 ret = ath10k_wow_set_wakeups(ar, wowlan); 371 if (ret) { 372 ath10k_warn(ar, "failed to set wow wakeup events: %d\n", 373 ret); 374 goto cleanup; 375 } 376 377 ret = ath10k_wow_enable(ar); 378 if (ret) { 379 ath10k_warn(ar, "failed to start wow: %d\n", ret); 380 goto cleanup; 381 } 382 383 ret = ath10k_hif_suspend(ar); 384 if (ret) { 385 ath10k_warn(ar, "failed to suspend hif: %d\n", ret); 386 goto wakeup; 387 } 388 389 goto exit; 390 391 wakeup: 392 ath10k_wow_wakeup(ar); 393 394 cleanup: 395 ath10k_wow_cleanup(ar); 396 397 exit: 398 mutex_unlock(&ar->conf_mutex); 399 return ret ? 1 : 0; 400 } 401 402 void ath10k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled) 403 { 404 struct ath10k *ar = hw->priv; 405 406 mutex_lock(&ar->conf_mutex); 407 if (test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, 408 ar->running_fw->fw_file.fw_features)) { 409 device_set_wakeup_enable(ar->dev, enabled); 410 } 411 mutex_unlock(&ar->conf_mutex); 412 } 413 414 int ath10k_wow_op_resume(struct ieee80211_hw *hw) 415 { 416 struct ath10k *ar = hw->priv; 417 int ret; 418 419 mutex_lock(&ar->conf_mutex); 420 421 if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, 422 ar->running_fw->fw_file.fw_features))) { 423 ret = 1; 424 goto exit; 425 } 426 427 ret = ath10k_hif_resume(ar); 428 if (ret) { 429 ath10k_warn(ar, "failed to resume hif: %d\n", ret); 430 goto exit; 431 } 432 433 ret = ath10k_wow_wakeup(ar); 434 if (ret) 435 ath10k_warn(ar, "failed to wakeup from wow: %d\n", ret); 436 437 exit: 438 if (ret) { 439 switch (ar->state) { 440 case ATH10K_STATE_ON: 441 ar->state = ATH10K_STATE_RESTARTING; 442 ret = 1; 443 break; 444 case ATH10K_STATE_OFF: 445 case ATH10K_STATE_RESTARTING: 446 case ATH10K_STATE_RESTARTED: 447 case ATH10K_STATE_UTF: 448 case ATH10K_STATE_WEDGED: 449 ath10k_warn(ar, "encountered unexpected device state %d on resume, cannot recover\n", 450 ar->state); 451 ret = -EIO; 452 break; 453 } 454 } 455 456 mutex_unlock(&ar->conf_mutex); 457 return ret; 458 } 459 460 int ath10k_wow_init(struct ath10k *ar) 461 { 462 if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, 463 ar->running_fw->fw_file.fw_features)) 464 return 0; 465 466 if (WARN_ON(!test_bit(WMI_SERVICE_WOW, ar->wmi.svc_map))) 467 return -EINVAL; 468 469 ar->wow.wowlan_support = ath10k_wowlan_support; 470 471 if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) { 472 ar->wow.wowlan_support.pattern_max_len -= WOW_MAX_REDUCE; 473 ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE; 474 } 475 476 ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns; 477 ar->hw->wiphy->wowlan = &ar->wow.wowlan_support; 478 479 device_set_wakeup_capable(ar->dev, true); 480 481 return 0; 482 } 483