wow.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  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. #include "mac.h"
  18. #include <net/mac80211.h>
  19. #include "hif.h"
  20. #include "core.h"
  21. #include "debug.h"
  22. #include "wmi.h"
  23. #include "wmi-ops.h"
  24. static const struct wiphy_wowlan_support ath10k_wowlan_support = {
  25. .flags = WIPHY_WOWLAN_DISCONNECT |
  26. WIPHY_WOWLAN_MAGIC_PKT,
  27. .pattern_min_len = WOW_MIN_PATTERN_SIZE,
  28. .pattern_max_len = WOW_MAX_PATTERN_SIZE,
  29. .max_pkt_offset = WOW_MAX_PKT_OFFSET,
  30. };
  31. static int ath10k_wow_vif_cleanup(struct ath10k_vif *arvif)
  32. {
  33. struct ath10k *ar = arvif->ar;
  34. int i, ret;
  35. for (i = 0; i < WOW_EVENT_MAX; i++) {
  36. ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 0);
  37. if (ret) {
  38. ath10k_warn(ar, "failed to issue wow wakeup for event %s on vdev %i: %d\n",
  39. wow_wakeup_event(i), arvif->vdev_id, ret);
  40. return ret;
  41. }
  42. }
  43. for (i = 0; i < ar->wow.max_num_patterns; i++) {
  44. ret = ath10k_wmi_wow_del_pattern(ar, arvif->vdev_id, i);
  45. if (ret) {
  46. ath10k_warn(ar, "failed to delete wow pattern %d for vdev %i: %d\n",
  47. i, arvif->vdev_id, ret);
  48. return ret;
  49. }
  50. }
  51. return 0;
  52. }
  53. static int ath10k_wow_cleanup(struct ath10k *ar)
  54. {
  55. struct ath10k_vif *arvif;
  56. int ret;
  57. lockdep_assert_held(&ar->conf_mutex);
  58. list_for_each_entry(arvif, &ar->arvifs, list) {
  59. ret = ath10k_wow_vif_cleanup(arvif);
  60. if (ret) {
  61. ath10k_warn(ar, "failed to clean wow wakeups on vdev %i: %d\n",
  62. arvif->vdev_id, ret);
  63. return ret;
  64. }
  65. }
  66. return 0;
  67. }
  68. /**
  69. * Convert a 802.3 format to a 802.11 format.
  70. * +------------+-----------+--------+----------------+
  71. * 802.3: |dest mac(6B)|src mac(6B)|type(2B)| body... |
  72. * +------------+-----------+--------+----------------+
  73. * |__ |_______ |____________ |________
  74. * | | | |
  75. * +--+------------+----+-----------+---------------+-----------+
  76. * 802.11: |4B|dest mac(6B)| 6B |src mac(6B)| 8B |type(2B)| body... |
  77. * +--+------------+----+-----------+---------------+-----------+
  78. */
  79. static void ath10k_wow_convert_8023_to_80211
  80. (struct cfg80211_pkt_pattern *new,
  81. const struct cfg80211_pkt_pattern *old)
  82. {
  83. u8 hdr_8023_pattern[ETH_HLEN] = {};
  84. u8 hdr_8023_bit_mask[ETH_HLEN] = {};
  85. u8 hdr_80211_pattern[WOW_HDR_LEN] = {};
  86. u8 hdr_80211_bit_mask[WOW_HDR_LEN] = {};
  87. int total_len = old->pkt_offset + old->pattern_len;
  88. int hdr_80211_end_offset;
  89. struct ieee80211_hdr_3addr *new_hdr_pattern =
  90. (struct ieee80211_hdr_3addr *)hdr_80211_pattern;
  91. struct ieee80211_hdr_3addr *new_hdr_mask =
  92. (struct ieee80211_hdr_3addr *)hdr_80211_bit_mask;
  93. struct ethhdr *old_hdr_pattern = (struct ethhdr *)hdr_8023_pattern;
  94. struct ethhdr *old_hdr_mask = (struct ethhdr *)hdr_8023_bit_mask;
  95. int hdr_len = sizeof(*new_hdr_pattern);
  96. struct rfc1042_hdr *new_rfc_pattern =
  97. (struct rfc1042_hdr *)(hdr_80211_pattern + hdr_len);
  98. struct rfc1042_hdr *new_rfc_mask =
  99. (struct rfc1042_hdr *)(hdr_80211_bit_mask + hdr_len);
  100. int rfc_len = sizeof(*new_rfc_pattern);
  101. memcpy(hdr_8023_pattern + old->pkt_offset,
  102. old->pattern, ETH_HLEN - old->pkt_offset);
  103. memcpy(hdr_8023_bit_mask + old->pkt_offset,
  104. old->mask, ETH_HLEN - old->pkt_offset);
  105. /* Copy destination address */
  106. memcpy(new_hdr_pattern->addr1, old_hdr_pattern->h_dest, ETH_ALEN);
  107. memcpy(new_hdr_mask->addr1, old_hdr_mask->h_dest, ETH_ALEN);
  108. /* Copy source address */
  109. memcpy(new_hdr_pattern->addr3, old_hdr_pattern->h_source, ETH_ALEN);
  110. memcpy(new_hdr_mask->addr3, old_hdr_mask->h_source, ETH_ALEN);
  111. /* Copy logic link type */
  112. memcpy(&new_rfc_pattern->snap_type,
  113. &old_hdr_pattern->h_proto,
  114. sizeof(old_hdr_pattern->h_proto));
  115. memcpy(&new_rfc_mask->snap_type,
  116. &old_hdr_mask->h_proto,
  117. sizeof(old_hdr_mask->h_proto));
  118. /* Caculate new pkt_offset */
  119. if (old->pkt_offset < ETH_ALEN)
  120. new->pkt_offset = old->pkt_offset +
  121. offsetof(struct ieee80211_hdr_3addr, addr1);
  122. else if (old->pkt_offset < offsetof(struct ethhdr, h_proto))
  123. new->pkt_offset = old->pkt_offset +
  124. offsetof(struct ieee80211_hdr_3addr, addr3) -
  125. offsetof(struct ethhdr, h_source);
  126. else
  127. new->pkt_offset = old->pkt_offset + hdr_len + rfc_len - ETH_HLEN;
  128. /* Caculate new hdr end offset */
  129. if (total_len > ETH_HLEN)
  130. hdr_80211_end_offset = hdr_len + rfc_len;
  131. else if (total_len > offsetof(struct ethhdr, h_proto))
  132. hdr_80211_end_offset = hdr_len + rfc_len + total_len - ETH_HLEN;
  133. else if (total_len > ETH_ALEN)
  134. hdr_80211_end_offset = total_len - ETH_ALEN +
  135. offsetof(struct ieee80211_hdr_3addr, addr3);
  136. else
  137. hdr_80211_end_offset = total_len +
  138. offsetof(struct ieee80211_hdr_3addr, addr1);
  139. new->pattern_len = hdr_80211_end_offset - new->pkt_offset;
  140. memcpy((u8 *)new->pattern,
  141. hdr_80211_pattern + new->pkt_offset,
  142. new->pattern_len);
  143. memcpy((u8 *)new->mask,
  144. hdr_80211_bit_mask + new->pkt_offset,
  145. new->pattern_len);
  146. if (total_len > ETH_HLEN) {
  147. /* Copy frame body */
  148. memcpy((u8 *)new->pattern + new->pattern_len,
  149. (void *)old->pattern + ETH_HLEN - old->pkt_offset,
  150. total_len - ETH_HLEN);
  151. memcpy((u8 *)new->mask + new->pattern_len,
  152. (void *)old->mask + ETH_HLEN - old->pkt_offset,
  153. total_len - ETH_HLEN);
  154. new->pattern_len += total_len - ETH_HLEN;
  155. }
  156. }
  157. static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
  158. struct cfg80211_wowlan *wowlan)
  159. {
  160. int ret, i;
  161. unsigned long wow_mask = 0;
  162. struct ath10k *ar = arvif->ar;
  163. const struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
  164. int pattern_id = 0;
  165. /* Setup requested WOW features */
  166. switch (arvif->vdev_type) {
  167. case WMI_VDEV_TYPE_IBSS:
  168. __set_bit(WOW_BEACON_EVENT, &wow_mask);
  169. /* fall through */
  170. case WMI_VDEV_TYPE_AP:
  171. __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
  172. __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
  173. __set_bit(WOW_PROBE_REQ_WPS_IE_EVENT, &wow_mask);
  174. __set_bit(WOW_AUTH_REQ_EVENT, &wow_mask);
  175. __set_bit(WOW_ASSOC_REQ_EVENT, &wow_mask);
  176. __set_bit(WOW_HTT_EVENT, &wow_mask);
  177. __set_bit(WOW_RA_MATCH_EVENT, &wow_mask);
  178. break;
  179. case WMI_VDEV_TYPE_STA:
  180. if (wowlan->disconnect) {
  181. __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
  182. __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
  183. __set_bit(WOW_BMISS_EVENT, &wow_mask);
  184. __set_bit(WOW_CSA_IE_EVENT, &wow_mask);
  185. }
  186. if (wowlan->magic_pkt)
  187. __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask);
  188. break;
  189. default:
  190. break;
  191. }
  192. for (i = 0; i < wowlan->n_patterns; i++) {
  193. u8 bitmask[WOW_MAX_PATTERN_SIZE] = {};
  194. u8 ath_pattern[WOW_MAX_PATTERN_SIZE] = {};
  195. u8 ath_bitmask[WOW_MAX_PATTERN_SIZE] = {};
  196. struct cfg80211_pkt_pattern new_pattern = {};
  197. struct cfg80211_pkt_pattern old_pattern = patterns[i];
  198. int j;
  199. new_pattern.pattern = ath_pattern;
  200. new_pattern.mask = ath_bitmask;
  201. if (patterns[i].pattern_len > WOW_MAX_PATTERN_SIZE)
  202. continue;
  203. /* convert bytemask to bitmask */
  204. for (j = 0; j < patterns[i].pattern_len; j++)
  205. if (patterns[i].mask[j / 8] & BIT(j % 8))
  206. bitmask[j] = 0xff;
  207. old_pattern.mask = bitmask;
  208. new_pattern = old_pattern;
  209. if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) {
  210. if (patterns[i].pkt_offset < ETH_HLEN)
  211. ath10k_wow_convert_8023_to_80211(&new_pattern,
  212. &old_pattern);
  213. else
  214. new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN;
  215. }
  216. if (WARN_ON(new_pattern.pattern_len > WOW_MAX_PATTERN_SIZE))
  217. return -EINVAL;
  218. ret = ath10k_wmi_wow_add_pattern(ar, arvif->vdev_id,
  219. pattern_id,
  220. new_pattern.pattern,
  221. new_pattern.mask,
  222. new_pattern.pattern_len,
  223. new_pattern.pkt_offset);
  224. if (ret) {
  225. ath10k_warn(ar, "failed to add pattern %i to vdev %i: %d\n",
  226. pattern_id,
  227. arvif->vdev_id, ret);
  228. return ret;
  229. }
  230. pattern_id++;
  231. __set_bit(WOW_PATTERN_MATCH_EVENT, &wow_mask);
  232. }
  233. for (i = 0; i < WOW_EVENT_MAX; i++) {
  234. if (!test_bit(i, &wow_mask))
  235. continue;
  236. ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 1);
  237. if (ret) {
  238. ath10k_warn(ar, "failed to enable wakeup event %s on vdev %i: %d\n",
  239. wow_wakeup_event(i), arvif->vdev_id, ret);
  240. return ret;
  241. }
  242. }
  243. return 0;
  244. }
  245. static int ath10k_wow_set_wakeups(struct ath10k *ar,
  246. struct cfg80211_wowlan *wowlan)
  247. {
  248. struct ath10k_vif *arvif;
  249. int ret;
  250. lockdep_assert_held(&ar->conf_mutex);
  251. list_for_each_entry(arvif, &ar->arvifs, list) {
  252. ret = ath10k_vif_wow_set_wakeups(arvif, wowlan);
  253. if (ret) {
  254. ath10k_warn(ar, "failed to set wow wakeups on vdev %i: %d\n",
  255. arvif->vdev_id, ret);
  256. return ret;
  257. }
  258. }
  259. return 0;
  260. }
  261. static int ath10k_wow_enable(struct ath10k *ar)
  262. {
  263. int ret;
  264. lockdep_assert_held(&ar->conf_mutex);
  265. reinit_completion(&ar->target_suspend);
  266. ret = ath10k_wmi_wow_enable(ar);
  267. if (ret) {
  268. ath10k_warn(ar, "failed to issue wow enable: %d\n", ret);
  269. return ret;
  270. }
  271. ret = wait_for_completion_timeout(&ar->target_suspend, 3 * HZ);
  272. if (ret == 0) {
  273. ath10k_warn(ar, "timed out while waiting for suspend completion\n");
  274. return -ETIMEDOUT;
  275. }
  276. return 0;
  277. }
  278. static int ath10k_wow_wakeup(struct ath10k *ar)
  279. {
  280. int ret;
  281. lockdep_assert_held(&ar->conf_mutex);
  282. reinit_completion(&ar->wow.wakeup_completed);
  283. ret = ath10k_wmi_wow_host_wakeup_ind(ar);
  284. if (ret) {
  285. ath10k_warn(ar, "failed to send wow wakeup indication: %d\n",
  286. ret);
  287. return ret;
  288. }
  289. ret = wait_for_completion_timeout(&ar->wow.wakeup_completed, 3 * HZ);
  290. if (ret == 0) {
  291. ath10k_warn(ar, "timed out while waiting for wow wakeup completion\n");
  292. return -ETIMEDOUT;
  293. }
  294. return 0;
  295. }
  296. int ath10k_wow_op_suspend(struct ieee80211_hw *hw,
  297. struct cfg80211_wowlan *wowlan)
  298. {
  299. struct ath10k *ar = hw->priv;
  300. int ret;
  301. mutex_lock(&ar->conf_mutex);
  302. if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
  303. ar->running_fw->fw_file.fw_features))) {
  304. ret = 1;
  305. goto exit;
  306. }
  307. ret = ath10k_wow_cleanup(ar);
  308. if (ret) {
  309. ath10k_warn(ar, "failed to clear wow wakeup events: %d\n",
  310. ret);
  311. goto exit;
  312. }
  313. ret = ath10k_wow_set_wakeups(ar, wowlan);
  314. if (ret) {
  315. ath10k_warn(ar, "failed to set wow wakeup events: %d\n",
  316. ret);
  317. goto cleanup;
  318. }
  319. ret = ath10k_wow_enable(ar);
  320. if (ret) {
  321. ath10k_warn(ar, "failed to start wow: %d\n", ret);
  322. goto cleanup;
  323. }
  324. ret = ath10k_hif_suspend(ar);
  325. if (ret) {
  326. ath10k_warn(ar, "failed to suspend hif: %d\n", ret);
  327. goto wakeup;
  328. }
  329. goto exit;
  330. wakeup:
  331. ath10k_wow_wakeup(ar);
  332. cleanup:
  333. ath10k_wow_cleanup(ar);
  334. exit:
  335. mutex_unlock(&ar->conf_mutex);
  336. return ret ? 1 : 0;
  337. }
  338. void ath10k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
  339. {
  340. struct ath10k *ar = hw->priv;
  341. mutex_lock(&ar->conf_mutex);
  342. if (test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
  343. ar->running_fw->fw_file.fw_features)) {
  344. device_set_wakeup_enable(ar->dev, enabled);
  345. }
  346. mutex_unlock(&ar->conf_mutex);
  347. }
  348. int ath10k_wow_op_resume(struct ieee80211_hw *hw)
  349. {
  350. struct ath10k *ar = hw->priv;
  351. int ret;
  352. mutex_lock(&ar->conf_mutex);
  353. if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
  354. ar->running_fw->fw_file.fw_features))) {
  355. ret = 1;
  356. goto exit;
  357. }
  358. ret = ath10k_hif_resume(ar);
  359. if (ret) {
  360. ath10k_warn(ar, "failed to resume hif: %d\n", ret);
  361. goto exit;
  362. }
  363. ret = ath10k_wow_wakeup(ar);
  364. if (ret)
  365. ath10k_warn(ar, "failed to wakeup from wow: %d\n", ret);
  366. exit:
  367. if (ret) {
  368. switch (ar->state) {
  369. case ATH10K_STATE_ON:
  370. ar->state = ATH10K_STATE_RESTARTING;
  371. ret = 1;
  372. break;
  373. case ATH10K_STATE_OFF:
  374. case ATH10K_STATE_RESTARTING:
  375. case ATH10K_STATE_RESTARTED:
  376. case ATH10K_STATE_UTF:
  377. case ATH10K_STATE_WEDGED:
  378. ath10k_warn(ar, "encountered unexpected device state %d on resume, cannot recover\n",
  379. ar->state);
  380. ret = -EIO;
  381. break;
  382. }
  383. }
  384. mutex_unlock(&ar->conf_mutex);
  385. return ret;
  386. }
  387. int ath10k_wow_init(struct ath10k *ar)
  388. {
  389. if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
  390. ar->running_fw->fw_file.fw_features))
  391. return 0;
  392. if (WARN_ON(!test_bit(WMI_SERVICE_WOW, ar->wmi.svc_map)))
  393. return -EINVAL;
  394. ar->wow.wowlan_support = ath10k_wowlan_support;
  395. if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) {
  396. ar->wow.wowlan_support.pattern_max_len -= WOW_MAX_REDUCE;
  397. ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE;
  398. }
  399. ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns;
  400. ar->hw->wiphy->wowlan = &ar->wow.wowlan_support;
  401. device_set_wakeup_capable(ar->dev, true);
  402. return 0;
  403. }