wow.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. // SPDX-License-Identifier: BSD-3-Clause-Clear
  2. /*
  3. * Copyright (c) 2020 The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/delay.h>
  7. #include "mac.h"
  8. #include <net/mac80211.h>
  9. #include "core.h"
  10. #include "hif.h"
  11. #include "debug.h"
  12. #include "wmi.h"
  13. #include "wow.h"
  14. #include "dp_rx.h"
  15. static const struct wiphy_wowlan_support ath11k_wowlan_support = {
  16. .flags = WIPHY_WOWLAN_DISCONNECT |
  17. WIPHY_WOWLAN_MAGIC_PKT |
  18. WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
  19. WIPHY_WOWLAN_GTK_REKEY_FAILURE,
  20. .pattern_min_len = WOW_MIN_PATTERN_SIZE,
  21. .pattern_max_len = WOW_MAX_PATTERN_SIZE,
  22. .max_pkt_offset = WOW_MAX_PKT_OFFSET,
  23. };
  24. int ath11k_wow_enable(struct ath11k_base *ab)
  25. {
  26. struct ath11k *ar = ath11k_ab_to_ar(ab, 0);
  27. int i, ret;
  28. clear_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags);
  29. for (i = 0; i < ATH11K_WOW_RETRY_NUM; i++) {
  30. reinit_completion(&ab->htc_suspend);
  31. ret = ath11k_wmi_wow_enable(ar);
  32. if (ret) {
  33. ath11k_warn(ab, "failed to issue wow enable: %d\n", ret);
  34. return ret;
  35. }
  36. ret = wait_for_completion_timeout(&ab->htc_suspend, 3 * HZ);
  37. if (ret == 0) {
  38. ath11k_warn(ab,
  39. "timed out while waiting for htc suspend completion\n");
  40. return -ETIMEDOUT;
  41. }
  42. if (test_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags))
  43. /* success, suspend complete received */
  44. return 0;
  45. ath11k_warn(ab, "htc suspend not complete, retrying (try %d)\n",
  46. i);
  47. msleep(ATH11K_WOW_RETRY_WAIT_MS);
  48. }
  49. ath11k_warn(ab, "htc suspend not complete, failing after %d tries\n", i);
  50. return -ETIMEDOUT;
  51. }
  52. int ath11k_wow_wakeup(struct ath11k_base *ab)
  53. {
  54. struct ath11k *ar = ath11k_ab_to_ar(ab, 0);
  55. int ret;
  56. /* In the case of WCN6750, WoW wakeup is done
  57. * by sending SMP2P power save exit message
  58. * to the target processor.
  59. */
  60. if (ab->hw_params.smp2p_wow_exit)
  61. return 0;
  62. reinit_completion(&ab->wow.wakeup_completed);
  63. ret = ath11k_wmi_wow_host_wakeup_ind(ar);
  64. if (ret) {
  65. ath11k_warn(ab, "failed to send wow wakeup indication: %d\n",
  66. ret);
  67. return ret;
  68. }
  69. ret = wait_for_completion_timeout(&ab->wow.wakeup_completed, 3 * HZ);
  70. if (ret == 0) {
  71. ath11k_warn(ab, "timed out while waiting for wow wakeup completion\n");
  72. return -ETIMEDOUT;
  73. }
  74. return 0;
  75. }
  76. static int ath11k_wow_vif_cleanup(struct ath11k_vif *arvif)
  77. {
  78. struct ath11k *ar = arvif->ar;
  79. int i, ret;
  80. for (i = 0; i < WOW_EVENT_MAX; i++) {
  81. ret = ath11k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 0);
  82. if (ret) {
  83. ath11k_warn(ar->ab, "failed to issue wow wakeup for event %s on vdev %i: %d\n",
  84. wow_wakeup_event(i), arvif->vdev_id, ret);
  85. return ret;
  86. }
  87. }
  88. for (i = 0; i < ar->wow.max_num_patterns; i++) {
  89. ret = ath11k_wmi_wow_del_pattern(ar, arvif->vdev_id, i);
  90. if (ret) {
  91. ath11k_warn(ar->ab, "failed to delete wow pattern %d for vdev %i: %d\n",
  92. i, arvif->vdev_id, ret);
  93. return ret;
  94. }
  95. }
  96. return 0;
  97. }
  98. static int ath11k_wow_cleanup(struct ath11k *ar)
  99. {
  100. struct ath11k_vif *arvif;
  101. int ret;
  102. lockdep_assert_held(&ar->conf_mutex);
  103. list_for_each_entry(arvif, &ar->arvifs, list) {
  104. ret = ath11k_wow_vif_cleanup(arvif);
  105. if (ret) {
  106. ath11k_warn(ar->ab, "failed to clean wow wakeups on vdev %i: %d\n",
  107. arvif->vdev_id, ret);
  108. return ret;
  109. }
  110. }
  111. return 0;
  112. }
  113. /* Convert a 802.3 format to a 802.11 format.
  114. * +------------+-----------+--------+----------------+
  115. * 802.3: |dest mac(6B)|src mac(6B)|type(2B)| body... |
  116. * +------------+-----------+--------+----------------+
  117. * |__ |_______ |____________ |________
  118. * | | | |
  119. * +--+------------+----+-----------+---------------+-----------+
  120. * 802.11: |4B|dest mac(6B)| 6B |src mac(6B)| 8B |type(2B)| body... |
  121. * +--+------------+----+-----------+---------------+-----------+
  122. */
  123. /* clang stack usage explodes if this is inlined */
  124. static noinline_for_stack
  125. void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
  126. const struct cfg80211_pkt_pattern *old)
  127. {
  128. u8 hdr_8023_pattern[ETH_HLEN] = {};
  129. u8 hdr_8023_bit_mask[ETH_HLEN] = {};
  130. u8 hdr_80211_pattern[WOW_HDR_LEN] = {};
  131. u8 hdr_80211_bit_mask[WOW_HDR_LEN] = {};
  132. u8 bytemask[WOW_MAX_PATTERN_SIZE] = {};
  133. int total_len = old->pkt_offset + old->pattern_len;
  134. int hdr_80211_end_offset;
  135. struct ieee80211_hdr_3addr *new_hdr_pattern =
  136. (struct ieee80211_hdr_3addr *)hdr_80211_pattern;
  137. struct ieee80211_hdr_3addr *new_hdr_mask =
  138. (struct ieee80211_hdr_3addr *)hdr_80211_bit_mask;
  139. struct ethhdr *old_hdr_pattern = (struct ethhdr *)hdr_8023_pattern;
  140. struct ethhdr *old_hdr_mask = (struct ethhdr *)hdr_8023_bit_mask;
  141. int hdr_len = sizeof(*new_hdr_pattern);
  142. struct rfc1042_hdr *new_rfc_pattern =
  143. (struct rfc1042_hdr *)(hdr_80211_pattern + hdr_len);
  144. struct rfc1042_hdr *new_rfc_mask =
  145. (struct rfc1042_hdr *)(hdr_80211_bit_mask + hdr_len);
  146. int rfc_len = sizeof(*new_rfc_pattern);
  147. int i;
  148. /* convert bitmask to bytemask */
  149. for (i = 0; i < old->pattern_len; i++)
  150. if (old->mask[i / 8] & BIT(i % 8))
  151. bytemask[i] = 0xff;
  152. memcpy(hdr_8023_pattern + old->pkt_offset,
  153. old->pattern, ETH_HLEN - old->pkt_offset);
  154. memcpy(hdr_8023_bit_mask + old->pkt_offset,
  155. bytemask, ETH_HLEN - old->pkt_offset);
  156. /* Copy destination address */
  157. memcpy(new_hdr_pattern->addr1, old_hdr_pattern->h_dest, ETH_ALEN);
  158. memcpy(new_hdr_mask->addr1, old_hdr_mask->h_dest, ETH_ALEN);
  159. /* Copy source address */
  160. memcpy(new_hdr_pattern->addr3, old_hdr_pattern->h_source, ETH_ALEN);
  161. memcpy(new_hdr_mask->addr3, old_hdr_mask->h_source, ETH_ALEN);
  162. /* Copy logic link type */
  163. memcpy(&new_rfc_pattern->snap_type,
  164. &old_hdr_pattern->h_proto,
  165. sizeof(old_hdr_pattern->h_proto));
  166. memcpy(&new_rfc_mask->snap_type,
  167. &old_hdr_mask->h_proto,
  168. sizeof(old_hdr_mask->h_proto));
  169. /* Compute new pkt_offset */
  170. if (old->pkt_offset < ETH_ALEN)
  171. new->pkt_offset = old->pkt_offset +
  172. offsetof(struct ieee80211_hdr_3addr, addr1);
  173. else if (old->pkt_offset < offsetof(struct ethhdr, h_proto))
  174. new->pkt_offset = old->pkt_offset +
  175. offsetof(struct ieee80211_hdr_3addr, addr3) -
  176. offsetof(struct ethhdr, h_source);
  177. else
  178. new->pkt_offset = old->pkt_offset + hdr_len + rfc_len - ETH_HLEN;
  179. /* Compute new hdr end offset */
  180. if (total_len > ETH_HLEN)
  181. hdr_80211_end_offset = hdr_len + rfc_len;
  182. else if (total_len > offsetof(struct ethhdr, h_proto))
  183. hdr_80211_end_offset = hdr_len + rfc_len + total_len - ETH_HLEN;
  184. else if (total_len > ETH_ALEN)
  185. hdr_80211_end_offset = total_len - ETH_ALEN +
  186. offsetof(struct ieee80211_hdr_3addr, addr3);
  187. else
  188. hdr_80211_end_offset = total_len +
  189. offsetof(struct ieee80211_hdr_3addr, addr1);
  190. new->pattern_len = hdr_80211_end_offset - new->pkt_offset;
  191. memcpy((u8 *)new->pattern,
  192. hdr_80211_pattern + new->pkt_offset,
  193. new->pattern_len);
  194. memcpy((u8 *)new->mask,
  195. hdr_80211_bit_mask + new->pkt_offset,
  196. new->pattern_len);
  197. if (total_len > ETH_HLEN) {
  198. /* Copy frame body */
  199. memcpy((u8 *)new->pattern + new->pattern_len,
  200. (void *)old->pattern + ETH_HLEN - old->pkt_offset,
  201. total_len - ETH_HLEN);
  202. memcpy((u8 *)new->mask + new->pattern_len,
  203. bytemask + ETH_HLEN - old->pkt_offset,
  204. total_len - ETH_HLEN);
  205. new->pattern_len += total_len - ETH_HLEN;
  206. }
  207. }
  208. static int ath11k_wmi_pno_check_and_convert(struct ath11k *ar, u32 vdev_id,
  209. struct cfg80211_sched_scan_request *nd_config,
  210. struct wmi_pno_scan_req *pno)
  211. {
  212. int i, j;
  213. u8 ssid_len;
  214. pno->enable = 1;
  215. pno->vdev_id = vdev_id;
  216. pno->uc_networks_count = nd_config->n_match_sets;
  217. if (!pno->uc_networks_count ||
  218. pno->uc_networks_count > WMI_PNO_MAX_SUPP_NETWORKS)
  219. return -EINVAL;
  220. if (nd_config->n_channels > WMI_PNO_MAX_NETW_CHANNELS_EX)
  221. return -EINVAL;
  222. /* Filling per profile params */
  223. for (i = 0; i < pno->uc_networks_count; i++) {
  224. ssid_len = nd_config->match_sets[i].ssid.ssid_len;
  225. if (ssid_len == 0 || ssid_len > 32)
  226. return -EINVAL;
  227. pno->a_networks[i].ssid.ssid_len = ssid_len;
  228. memcpy(pno->a_networks[i].ssid.ssid,
  229. nd_config->match_sets[i].ssid.ssid,
  230. nd_config->match_sets[i].ssid.ssid_len);
  231. pno->a_networks[i].authentication = 0;
  232. pno->a_networks[i].encryption = 0;
  233. pno->a_networks[i].bcast_nw_type = 0;
  234. /* Copying list of valid channel into request */
  235. pno->a_networks[i].channel_count = nd_config->n_channels;
  236. pno->a_networks[i].rssi_threshold = nd_config->match_sets[i].rssi_thold;
  237. for (j = 0; j < nd_config->n_channels; j++) {
  238. pno->a_networks[i].channels[j] =
  239. nd_config->channels[j]->center_freq;
  240. }
  241. }
  242. /* set scan to passive if no SSIDs are specified in the request */
  243. if (nd_config->n_ssids == 0)
  244. pno->do_passive_scan = true;
  245. else
  246. pno->do_passive_scan = false;
  247. for (i = 0; i < nd_config->n_ssids; i++) {
  248. j = 0;
  249. while (j < pno->uc_networks_count) {
  250. if (pno->a_networks[j].ssid.ssid_len ==
  251. nd_config->ssids[i].ssid_len &&
  252. (memcmp(pno->a_networks[j].ssid.ssid,
  253. nd_config->ssids[i].ssid,
  254. pno->a_networks[j].ssid.ssid_len) == 0)) {
  255. pno->a_networks[j].bcast_nw_type = BCAST_HIDDEN;
  256. break;
  257. }
  258. j++;
  259. }
  260. }
  261. if (nd_config->n_scan_plans == 2) {
  262. pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
  263. pno->fast_scan_max_cycles = nd_config->scan_plans[0].iterations;
  264. pno->slow_scan_period =
  265. nd_config->scan_plans[1].interval * MSEC_PER_SEC;
  266. } else if (nd_config->n_scan_plans == 1) {
  267. pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
  268. pno->fast_scan_max_cycles = 1;
  269. pno->slow_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
  270. } else {
  271. ath11k_warn(ar->ab, "Invalid number of scan plans %d !!",
  272. nd_config->n_scan_plans);
  273. }
  274. if (nd_config->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
  275. /* enable mac randomization */
  276. pno->enable_pno_scan_randomization = 1;
  277. memcpy(pno->mac_addr, nd_config->mac_addr, ETH_ALEN);
  278. memcpy(pno->mac_addr_mask, nd_config->mac_addr_mask, ETH_ALEN);
  279. }
  280. pno->delay_start_time = nd_config->delay;
  281. /* Current FW does not support min-max range for dwell time */
  282. pno->active_max_time = WMI_ACTIVE_MAX_CHANNEL_TIME;
  283. pno->passive_max_time = WMI_PASSIVE_MAX_CHANNEL_TIME;
  284. return 0;
  285. }
  286. static int ath11k_vif_wow_set_wakeups(struct ath11k_vif *arvif,
  287. struct cfg80211_wowlan *wowlan)
  288. {
  289. int ret, i;
  290. unsigned long wow_mask = 0;
  291. struct ath11k *ar = arvif->ar;
  292. const struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
  293. int pattern_id = 0;
  294. /* Setup requested WOW features */
  295. switch (arvif->vdev_type) {
  296. case WMI_VDEV_TYPE_IBSS:
  297. __set_bit(WOW_BEACON_EVENT, &wow_mask);
  298. fallthrough;
  299. case WMI_VDEV_TYPE_AP:
  300. __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
  301. __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
  302. __set_bit(WOW_PROBE_REQ_WPS_IE_EVENT, &wow_mask);
  303. __set_bit(WOW_AUTH_REQ_EVENT, &wow_mask);
  304. __set_bit(WOW_ASSOC_REQ_EVENT, &wow_mask);
  305. __set_bit(WOW_HTT_EVENT, &wow_mask);
  306. __set_bit(WOW_RA_MATCH_EVENT, &wow_mask);
  307. break;
  308. case WMI_VDEV_TYPE_STA:
  309. if (wowlan->disconnect) {
  310. __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
  311. __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
  312. __set_bit(WOW_BMISS_EVENT, &wow_mask);
  313. __set_bit(WOW_CSA_IE_EVENT, &wow_mask);
  314. }
  315. if (wowlan->magic_pkt)
  316. __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask);
  317. if (wowlan->nd_config) {
  318. struct wmi_pno_scan_req *pno;
  319. int ret;
  320. pno = kzalloc_obj(*pno);
  321. if (!pno)
  322. return -ENOMEM;
  323. ar->nlo_enabled = true;
  324. ret = ath11k_wmi_pno_check_and_convert(ar, arvif->vdev_id,
  325. wowlan->nd_config, pno);
  326. if (!ret) {
  327. ath11k_wmi_wow_config_pno(ar, arvif->vdev_id, pno);
  328. __set_bit(WOW_NLO_DETECTED_EVENT, &wow_mask);
  329. }
  330. kfree(pno);
  331. }
  332. break;
  333. default:
  334. break;
  335. }
  336. for (i = 0; i < wowlan->n_patterns; i++) {
  337. u8 ath_pattern[WOW_MAX_PATTERN_SIZE] = {};
  338. u8 ath_bitmask[WOW_MAX_PATTERN_SIZE] = {};
  339. struct cfg80211_pkt_pattern new_pattern = {};
  340. new_pattern.pattern = ath_pattern;
  341. new_pattern.mask = ath_bitmask;
  342. if (patterns[i].pattern_len > WOW_MAX_PATTERN_SIZE)
  343. continue;
  344. if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode ==
  345. ATH11K_HW_TXRX_NATIVE_WIFI) {
  346. if (patterns[i].pkt_offset < ETH_HLEN) {
  347. ath11k_wow_convert_8023_to_80211(&new_pattern,
  348. &patterns[i]);
  349. } else {
  350. int j;
  351. new_pattern = patterns[i];
  352. new_pattern.mask = ath_bitmask;
  353. /* convert bitmask to bytemask */
  354. for (j = 0; j < patterns[i].pattern_len; j++)
  355. if (patterns[i].mask[j / 8] & BIT(j % 8))
  356. ath_bitmask[j] = 0xff;
  357. new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN;
  358. }
  359. }
  360. if (WARN_ON(new_pattern.pattern_len > WOW_MAX_PATTERN_SIZE))
  361. return -EINVAL;
  362. ret = ath11k_wmi_wow_add_pattern(ar, arvif->vdev_id,
  363. pattern_id,
  364. new_pattern.pattern,
  365. new_pattern.mask,
  366. new_pattern.pattern_len,
  367. new_pattern.pkt_offset);
  368. if (ret) {
  369. ath11k_warn(ar->ab, "failed to add pattern %i to vdev %i: %d\n",
  370. pattern_id,
  371. arvif->vdev_id, ret);
  372. return ret;
  373. }
  374. pattern_id++;
  375. __set_bit(WOW_PATTERN_MATCH_EVENT, &wow_mask);
  376. }
  377. for (i = 0; i < WOW_EVENT_MAX; i++) {
  378. if (!test_bit(i, &wow_mask))
  379. continue;
  380. ret = ath11k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 1);
  381. if (ret) {
  382. ath11k_warn(ar->ab, "failed to enable wakeup event %s on vdev %i: %d\n",
  383. wow_wakeup_event(i), arvif->vdev_id, ret);
  384. return ret;
  385. }
  386. }
  387. return 0;
  388. }
  389. static int ath11k_wow_set_wakeups(struct ath11k *ar,
  390. struct cfg80211_wowlan *wowlan)
  391. {
  392. struct ath11k_vif *arvif;
  393. int ret;
  394. lockdep_assert_held(&ar->conf_mutex);
  395. list_for_each_entry(arvif, &ar->arvifs, list) {
  396. ret = ath11k_vif_wow_set_wakeups(arvif, wowlan);
  397. if (ret) {
  398. ath11k_warn(ar->ab, "failed to set wow wakeups on vdev %i: %d\n",
  399. arvif->vdev_id, ret);
  400. return ret;
  401. }
  402. }
  403. return 0;
  404. }
  405. static int ath11k_vif_wow_clean_nlo(struct ath11k_vif *arvif)
  406. {
  407. int ret = 0;
  408. struct ath11k *ar = arvif->ar;
  409. switch (arvif->vdev_type) {
  410. case WMI_VDEV_TYPE_STA:
  411. if (ar->nlo_enabled) {
  412. struct wmi_pno_scan_req *pno;
  413. pno = kzalloc_obj(*pno);
  414. if (!pno)
  415. return -ENOMEM;
  416. pno->enable = 0;
  417. ar->nlo_enabled = false;
  418. ret = ath11k_wmi_wow_config_pno(ar, arvif->vdev_id, pno);
  419. kfree(pno);
  420. }
  421. break;
  422. default:
  423. break;
  424. }
  425. return ret;
  426. }
  427. static int ath11k_wow_nlo_cleanup(struct ath11k *ar)
  428. {
  429. struct ath11k_vif *arvif;
  430. int ret;
  431. lockdep_assert_held(&ar->conf_mutex);
  432. list_for_each_entry(arvif, &ar->arvifs, list) {
  433. ret = ath11k_vif_wow_clean_nlo(arvif);
  434. if (ret) {
  435. ath11k_warn(ar->ab, "failed to clean nlo settings on vdev %i: %d\n",
  436. arvif->vdev_id, ret);
  437. return ret;
  438. }
  439. }
  440. return 0;
  441. }
  442. static int ath11k_wow_set_hw_filter(struct ath11k *ar)
  443. {
  444. struct ath11k_vif *arvif;
  445. u32 bitmap;
  446. int ret;
  447. lockdep_assert_held(&ar->conf_mutex);
  448. list_for_each_entry(arvif, &ar->arvifs, list) {
  449. bitmap = WMI_HW_DATA_FILTER_DROP_NON_ICMPV6_MC |
  450. WMI_HW_DATA_FILTER_DROP_NON_ARP_BC;
  451. ret = ath11k_wmi_hw_data_filter_cmd(ar, arvif->vdev_id,
  452. bitmap,
  453. true);
  454. if (ret) {
  455. ath11k_warn(ar->ab, "failed to set hw data filter on vdev %i: %d\n",
  456. arvif->vdev_id, ret);
  457. return ret;
  458. }
  459. }
  460. return 0;
  461. }
  462. static int ath11k_wow_clear_hw_filter(struct ath11k *ar)
  463. {
  464. struct ath11k_vif *arvif;
  465. int ret;
  466. lockdep_assert_held(&ar->conf_mutex);
  467. list_for_each_entry(arvif, &ar->arvifs, list) {
  468. ret = ath11k_wmi_hw_data_filter_cmd(ar, arvif->vdev_id, 0, false);
  469. if (ret) {
  470. ath11k_warn(ar->ab, "failed to clear hw data filter on vdev %i: %d\n",
  471. arvif->vdev_id, ret);
  472. return ret;
  473. }
  474. }
  475. return 0;
  476. }
  477. static int ath11k_wow_arp_ns_offload(struct ath11k *ar, bool enable)
  478. {
  479. struct ath11k_vif *arvif;
  480. int ret;
  481. lockdep_assert_held(&ar->conf_mutex);
  482. list_for_each_entry(arvif, &ar->arvifs, list) {
  483. if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
  484. continue;
  485. ret = ath11k_wmi_arp_ns_offload(ar, arvif, enable);
  486. if (ret) {
  487. ath11k_warn(ar->ab, "failed to set arp ns offload vdev %i: enable %d, ret %d\n",
  488. arvif->vdev_id, enable, ret);
  489. return ret;
  490. }
  491. }
  492. return 0;
  493. }
  494. static int ath11k_gtk_rekey_offload(struct ath11k *ar, bool enable)
  495. {
  496. struct ath11k_vif *arvif;
  497. int ret;
  498. lockdep_assert_held(&ar->conf_mutex);
  499. list_for_each_entry(arvif, &ar->arvifs, list) {
  500. if (arvif->vdev_type != WMI_VDEV_TYPE_STA ||
  501. !arvif->is_up ||
  502. !arvif->rekey_data.enable_offload)
  503. continue;
  504. /* get rekey info before disable rekey offload */
  505. if (!enable) {
  506. ret = ath11k_wmi_gtk_rekey_getinfo(ar, arvif);
  507. if (ret) {
  508. ath11k_warn(ar->ab, "failed to request rekey info vdev %i, ret %d\n",
  509. arvif->vdev_id, ret);
  510. return ret;
  511. }
  512. }
  513. ret = ath11k_wmi_gtk_rekey_offload(ar, arvif, enable);
  514. if (ret) {
  515. ath11k_warn(ar->ab, "failed to offload gtk reky vdev %i: enable %d, ret %d\n",
  516. arvif->vdev_id, enable, ret);
  517. return ret;
  518. }
  519. }
  520. return 0;
  521. }
  522. static int ath11k_wow_protocol_offload(struct ath11k *ar, bool enable)
  523. {
  524. int ret;
  525. ret = ath11k_wow_arp_ns_offload(ar, enable);
  526. if (ret) {
  527. ath11k_warn(ar->ab, "failed to offload ARP and NS %d %d\n",
  528. enable, ret);
  529. return ret;
  530. }
  531. ret = ath11k_gtk_rekey_offload(ar, enable);
  532. if (ret) {
  533. ath11k_warn(ar->ab, "failed to offload gtk rekey %d %d\n",
  534. enable, ret);
  535. return ret;
  536. }
  537. return 0;
  538. }
  539. static int ath11k_wow_set_keepalive(struct ath11k *ar,
  540. enum wmi_sta_keepalive_method method,
  541. u32 interval)
  542. {
  543. struct ath11k_vif *arvif;
  544. int ret;
  545. lockdep_assert_held(&ar->conf_mutex);
  546. list_for_each_entry(arvif, &ar->arvifs, list) {
  547. ret = ath11k_mac_vif_set_keepalive(arvif, method, interval);
  548. if (ret)
  549. return ret;
  550. }
  551. return 0;
  552. }
  553. int ath11k_wow_op_suspend(struct ieee80211_hw *hw,
  554. struct cfg80211_wowlan *wowlan)
  555. {
  556. struct ath11k *ar = hw->priv;
  557. int ret;
  558. ret = ath11k_mac_wait_tx_complete(ar);
  559. if (ret) {
  560. ath11k_warn(ar->ab, "failed to wait tx complete: %d\n", ret);
  561. return ret;
  562. }
  563. mutex_lock(&ar->conf_mutex);
  564. ret = ath11k_dp_rx_pktlog_stop(ar->ab, true);
  565. if (ret) {
  566. ath11k_warn(ar->ab,
  567. "failed to stop dp rx (and timer) pktlog during wow suspend: %d\n",
  568. ret);
  569. goto exit;
  570. }
  571. ret = ath11k_wow_cleanup(ar);
  572. if (ret) {
  573. ath11k_warn(ar->ab, "failed to clear wow wakeup events: %d\n",
  574. ret);
  575. goto exit;
  576. }
  577. ret = ath11k_wow_set_wakeups(ar, wowlan);
  578. if (ret) {
  579. ath11k_warn(ar->ab, "failed to set wow wakeup events: %d\n",
  580. ret);
  581. goto cleanup;
  582. }
  583. ret = ath11k_wow_protocol_offload(ar, true);
  584. if (ret) {
  585. ath11k_warn(ar->ab, "failed to set wow protocol offload events: %d\n",
  586. ret);
  587. goto cleanup;
  588. }
  589. ret = ath11k_wow_set_hw_filter(ar);
  590. if (ret) {
  591. ath11k_warn(ar->ab, "failed to set hw filter: %d\n",
  592. ret);
  593. goto cleanup;
  594. }
  595. ret = ath11k_wow_set_keepalive(ar,
  596. WMI_STA_KEEPALIVE_METHOD_NULL_FRAME,
  597. WMI_STA_KEEPALIVE_INTERVAL_DEFAULT);
  598. if (ret) {
  599. ath11k_warn(ar->ab, "failed to enable wow keepalive: %d\n", ret);
  600. goto cleanup;
  601. }
  602. ret = ath11k_wow_enable(ar->ab);
  603. if (ret) {
  604. ath11k_warn(ar->ab, "failed to start wow: %d\n", ret);
  605. goto cleanup;
  606. }
  607. ret = ath11k_dp_rx_pktlog_stop(ar->ab, false);
  608. if (ret) {
  609. ath11k_warn(ar->ab,
  610. "failed to stop dp rx pktlog during wow suspend: %d\n",
  611. ret);
  612. goto cleanup;
  613. }
  614. ath11k_ce_stop_shadow_timers(ar->ab);
  615. ath11k_dp_stop_shadow_timers(ar->ab);
  616. ath11k_hif_irq_disable(ar->ab);
  617. ath11k_hif_ce_irq_disable(ar->ab);
  618. ret = ath11k_hif_suspend(ar->ab);
  619. if (ret) {
  620. ath11k_warn(ar->ab, "failed to suspend hif: %d\n", ret);
  621. goto wakeup;
  622. }
  623. goto exit;
  624. wakeup:
  625. ath11k_wow_wakeup(ar->ab);
  626. cleanup:
  627. ath11k_wow_cleanup(ar);
  628. exit:
  629. mutex_unlock(&ar->conf_mutex);
  630. return ret ? 1 : 0;
  631. }
  632. void ath11k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
  633. {
  634. struct ath11k *ar = hw->priv;
  635. mutex_lock(&ar->conf_mutex);
  636. device_set_wakeup_enable(ar->ab->dev, enabled);
  637. mutex_unlock(&ar->conf_mutex);
  638. }
  639. int ath11k_wow_op_resume(struct ieee80211_hw *hw)
  640. {
  641. struct ath11k *ar = hw->priv;
  642. int ret;
  643. mutex_lock(&ar->conf_mutex);
  644. ret = ath11k_hif_resume(ar->ab);
  645. if (ret) {
  646. ath11k_warn(ar->ab, "failed to resume hif: %d\n", ret);
  647. goto exit;
  648. }
  649. ath11k_hif_ce_irq_enable(ar->ab);
  650. ath11k_hif_irq_enable(ar->ab);
  651. ret = ath11k_dp_rx_pktlog_start(ar->ab);
  652. if (ret) {
  653. ath11k_warn(ar->ab, "failed to start rx pktlog from wow: %d\n", ret);
  654. goto exit;
  655. }
  656. ret = ath11k_wow_wakeup(ar->ab);
  657. if (ret) {
  658. ath11k_warn(ar->ab, "failed to wakeup from wow: %d\n", ret);
  659. goto exit;
  660. }
  661. ret = ath11k_wow_nlo_cleanup(ar);
  662. if (ret) {
  663. ath11k_warn(ar->ab, "failed to cleanup nlo: %d\n", ret);
  664. goto exit;
  665. }
  666. ret = ath11k_wow_clear_hw_filter(ar);
  667. if (ret) {
  668. ath11k_warn(ar->ab, "failed to clear hw filter: %d\n", ret);
  669. goto exit;
  670. }
  671. ret = ath11k_wow_protocol_offload(ar, false);
  672. if (ret) {
  673. ath11k_warn(ar->ab, "failed to clear wow protocol offload events: %d\n",
  674. ret);
  675. goto exit;
  676. }
  677. ret = ath11k_wow_set_keepalive(ar,
  678. WMI_STA_KEEPALIVE_METHOD_NULL_FRAME,
  679. WMI_STA_KEEPALIVE_INTERVAL_DISABLE);
  680. if (ret) {
  681. ath11k_warn(ar->ab, "failed to disable wow keepalive: %d\n", ret);
  682. goto exit;
  683. }
  684. exit:
  685. if (ret) {
  686. switch (ar->state) {
  687. case ATH11K_STATE_ON:
  688. ar->state = ATH11K_STATE_RESTARTING;
  689. ret = 1;
  690. break;
  691. case ATH11K_STATE_OFF:
  692. case ATH11K_STATE_RESTARTING:
  693. case ATH11K_STATE_RESTARTED:
  694. case ATH11K_STATE_WEDGED:
  695. case ATH11K_STATE_FTM:
  696. ath11k_warn(ar->ab, "encountered unexpected device state %d on resume, cannot recover\n",
  697. ar->state);
  698. ret = -EIO;
  699. break;
  700. }
  701. }
  702. mutex_unlock(&ar->conf_mutex);
  703. return ret;
  704. }
  705. int ath11k_wow_init(struct ath11k *ar)
  706. {
  707. if (!test_bit(WMI_TLV_SERVICE_WOW, ar->wmi->wmi_ab->svc_map))
  708. return 0;
  709. ar->wow.wowlan_support = ath11k_wowlan_support;
  710. if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode ==
  711. ATH11K_HW_TXRX_NATIVE_WIFI) {
  712. ar->wow.wowlan_support.pattern_max_len -= WOW_MAX_REDUCE;
  713. ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE;
  714. }
  715. if (test_bit(WMI_TLV_SERVICE_NLO, ar->wmi->wmi_ab->svc_map)) {
  716. ar->wow.wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT;
  717. ar->wow.wowlan_support.max_nd_match_sets = WMI_PNO_MAX_SUPP_NETWORKS;
  718. }
  719. ar->wow.max_num_patterns = ATH11K_WOW_PATTERNS;
  720. ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns;
  721. ar->hw->wiphy->wowlan = &ar->wow.wowlan_support;
  722. device_set_wakeup_capable(ar->ab->dev, true);
  723. return 0;
  724. }