wmi.c 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789
  1. /*
  2. * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <linux/moduleparam.h>
  17. #include <linux/etherdevice.h>
  18. #include <linux/if_arp.h>
  19. #include "wil6210.h"
  20. #include "txrx.h"
  21. #include "wmi.h"
  22. #include "trace.h"
  23. static uint max_assoc_sta = WIL6210_MAX_CID;
  24. module_param(max_assoc_sta, uint, S_IRUGO | S_IWUSR);
  25. MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP");
  26. int agg_wsize; /* = 0; */
  27. module_param(agg_wsize, int, S_IRUGO | S_IWUSR);
  28. MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;"
  29. " 0 - use default; < 0 - don't auto-establish");
  30. u8 led_id = WIL_LED_INVALID_ID;
  31. module_param(led_id, byte, S_IRUGO);
  32. MODULE_PARM_DESC(led_id,
  33. " 60G device led enablement. Set the led ID (0-2) to enable");
  34. /**
  35. * WMI event receiving - theory of operations
  36. *
  37. * When firmware about to report WMI event, it fills memory area
  38. * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
  39. * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler.
  40. *
  41. * @wmi_recv_cmd reads event, allocates memory chunk and attaches it to the
  42. * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up
  43. * and handles events within the @wmi_event_worker. Every event get detached
  44. * from list, processed and deleted.
  45. *
  46. * Purpose for this mechanism is to release IRQ thread; otherwise,
  47. * if WMI event handling involves another WMI command flow, this 2-nd flow
  48. * won't be completed because of blocked IRQ thread.
  49. */
  50. /**
  51. * Addressing - theory of operations
  52. *
  53. * There are several buses present on the WIL6210 card.
  54. * Same memory areas are visible at different address on
  55. * the different busses. There are 3 main bus masters:
  56. * - MAC CPU (ucode)
  57. * - User CPU (firmware)
  58. * - AHB (host)
  59. *
  60. * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing
  61. * AHB addresses starting from 0x880000
  62. *
  63. * Internally, firmware uses addresses that allows faster access but
  64. * are invisible from the host. To read from these addresses, alternative
  65. * AHB address must be used.
  66. *
  67. * Memory mapping
  68. * Linker address PCI/Host address
  69. * 0x880000 .. 0xa80000 2Mb BAR0
  70. * 0x800000 .. 0x807000 0x900000 .. 0x907000 28k DCCM
  71. * 0x840000 .. 0x857000 0x908000 .. 0x91f000 92k PERIPH
  72. */
  73. /**
  74. * @fw_mapping provides memory remapping table
  75. *
  76. * array size should be in sync with the declaration in the wil6210.h
  77. */
  78. const struct fw_map fw_mapping[] = {
  79. /* FW code RAM 256k */
  80. {0x000000, 0x040000, 0x8c0000, "fw_code", true},
  81. /* FW data RAM 32k */
  82. {0x800000, 0x808000, 0x900000, "fw_data", true},
  83. /* periph data 128k */
  84. {0x840000, 0x860000, 0x908000, "fw_peri", true},
  85. /* various RGF 40k */
  86. {0x880000, 0x88a000, 0x880000, "rgf", true},
  87. /* AGC table 4k */
  88. {0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true},
  89. /* Pcie_ext_rgf 4k */
  90. {0x88b000, 0x88c000, 0x88b000, "rgf_ext", true},
  91. /* mac_ext_rgf 512b */
  92. {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true},
  93. /* upper area 548k */
  94. {0x8c0000, 0x949000, 0x8c0000, "upper", true},
  95. /* UCODE areas - accessible by debugfs blobs but not by
  96. * wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
  97. */
  98. /* ucode code RAM 128k */
  99. {0x000000, 0x020000, 0x920000, "uc_code", false},
  100. /* ucode data RAM 16k */
  101. {0x800000, 0x804000, 0x940000, "uc_data", false},
  102. };
  103. struct blink_on_off_time led_blink_time[] = {
  104. {WIL_LED_BLINK_ON_SLOW_MS, WIL_LED_BLINK_OFF_SLOW_MS},
  105. {WIL_LED_BLINK_ON_MED_MS, WIL_LED_BLINK_OFF_MED_MS},
  106. {WIL_LED_BLINK_ON_FAST_MS, WIL_LED_BLINK_OFF_FAST_MS},
  107. };
  108. u8 led_polarity = LED_POLARITY_LOW_ACTIVE;
  109. /**
  110. * return AHB address for given firmware internal (linker) address
  111. * @x - internal address
  112. * If address have no valid AHB mapping, return 0
  113. */
  114. static u32 wmi_addr_remap(u32 x)
  115. {
  116. uint i;
  117. for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
  118. if (fw_mapping[i].fw &&
  119. ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)))
  120. return x + fw_mapping[i].host - fw_mapping[i].from;
  121. }
  122. return 0;
  123. }
  124. /**
  125. * Check address validity for WMI buffer; remap if needed
  126. * @ptr - internal (linker) fw/ucode address
  127. *
  128. * Valid buffer should be DWORD aligned
  129. *
  130. * return address for accessing buffer from the host;
  131. * if buffer is not valid, return NULL.
  132. */
  133. void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
  134. {
  135. u32 off;
  136. u32 ptr = le32_to_cpu(ptr_);
  137. if (ptr % 4)
  138. return NULL;
  139. ptr = wmi_addr_remap(ptr);
  140. if (ptr < WIL6210_FW_HOST_OFF)
  141. return NULL;
  142. off = HOSTADDR(ptr);
  143. if (off > WIL6210_MEM_SIZE - 4)
  144. return NULL;
  145. return wil->csr + off;
  146. }
  147. /**
  148. * Check address validity
  149. */
  150. void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
  151. {
  152. u32 off;
  153. if (ptr % 4)
  154. return NULL;
  155. if (ptr < WIL6210_FW_HOST_OFF)
  156. return NULL;
  157. off = HOSTADDR(ptr);
  158. if (off > WIL6210_MEM_SIZE - 4)
  159. return NULL;
  160. return wil->csr + off;
  161. }
  162. int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
  163. struct wil6210_mbox_hdr *hdr)
  164. {
  165. void __iomem *src = wmi_buffer(wil, ptr);
  166. if (!src)
  167. return -EINVAL;
  168. wil_memcpy_fromio_32(hdr, src, sizeof(*hdr));
  169. return 0;
  170. }
  171. static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
  172. {
  173. struct {
  174. struct wil6210_mbox_hdr hdr;
  175. struct wmi_cmd_hdr wmi;
  176. } __packed cmd = {
  177. .hdr = {
  178. .type = WIL_MBOX_HDR_TYPE_WMI,
  179. .flags = 0,
  180. .len = cpu_to_le16(sizeof(cmd.wmi) + len),
  181. },
  182. .wmi = {
  183. .mid = 0,
  184. .command_id = cpu_to_le16(cmdid),
  185. },
  186. };
  187. struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx;
  188. struct wil6210_mbox_ring_desc d_head;
  189. u32 next_head;
  190. void __iomem *dst;
  191. void __iomem *head = wmi_addr(wil, r->head);
  192. uint retry;
  193. int rc = 0;
  194. if (sizeof(cmd) + len > r->entry_size) {
  195. wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
  196. (int)(sizeof(cmd) + len), r->entry_size);
  197. return -ERANGE;
  198. }
  199. might_sleep();
  200. if (!test_bit(wil_status_fwready, wil->status)) {
  201. wil_err(wil, "WMI: cannot send command while FW not ready\n");
  202. return -EAGAIN;
  203. }
  204. if (!head) {
  205. wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
  206. return -EINVAL;
  207. }
  208. wil_halp_vote(wil);
  209. /* read Tx head till it is not busy */
  210. for (retry = 5; retry > 0; retry--) {
  211. wil_memcpy_fromio_32(&d_head, head, sizeof(d_head));
  212. if (d_head.sync == 0)
  213. break;
  214. msleep(20);
  215. }
  216. if (d_head.sync != 0) {
  217. wil_err(wil, "WMI head busy\n");
  218. rc = -EBUSY;
  219. goto out;
  220. }
  221. /* next head */
  222. next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size);
  223. wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
  224. /* wait till FW finish with previous command */
  225. for (retry = 5; retry > 0; retry--) {
  226. if (!test_bit(wil_status_fwready, wil->status)) {
  227. wil_err(wil, "WMI: cannot send command while FW not ready\n");
  228. rc = -EAGAIN;
  229. goto out;
  230. }
  231. r->tail = wil_r(wil, RGF_MBOX +
  232. offsetof(struct wil6210_mbox_ctl, tx.tail));
  233. if (next_head != r->tail)
  234. break;
  235. msleep(20);
  236. }
  237. if (next_head == r->tail) {
  238. wil_err(wil, "WMI ring full\n");
  239. rc = -EBUSY;
  240. goto out;
  241. }
  242. dst = wmi_buffer(wil, d_head.addr);
  243. if (!dst) {
  244. wil_err(wil, "invalid WMI buffer: 0x%08x\n",
  245. le32_to_cpu(d_head.addr));
  246. rc = -EAGAIN;
  247. goto out;
  248. }
  249. cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
  250. /* set command */
  251. wil_dbg_wmi(wil, "WMI command 0x%04x [%d]\n", cmdid, len);
  252. wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
  253. sizeof(cmd), true);
  254. wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
  255. len, true);
  256. wil_memcpy_toio_32(dst, &cmd, sizeof(cmd));
  257. wil_memcpy_toio_32(dst + sizeof(cmd), buf, len);
  258. /* mark entry as full */
  259. wil_w(wil, r->head + offsetof(struct wil6210_mbox_ring_desc, sync), 1);
  260. /* advance next ptr */
  261. wil_w(wil, RGF_MBOX + offsetof(struct wil6210_mbox_ctl, tx.head),
  262. r->head = next_head);
  263. trace_wil6210_wmi_cmd(&cmd.wmi, buf, len);
  264. /* interrupt to FW */
  265. wil_w(wil, RGF_USER_USER_ICR + offsetof(struct RGF_ICR, ICS),
  266. SW_INT_MBOX);
  267. out:
  268. wil_halp_unvote(wil);
  269. return rc;
  270. }
  271. int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
  272. {
  273. int rc;
  274. mutex_lock(&wil->wmi_mutex);
  275. rc = __wmi_send(wil, cmdid, buf, len);
  276. mutex_unlock(&wil->wmi_mutex);
  277. return rc;
  278. }
  279. /*=== Event handlers ===*/
  280. static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
  281. {
  282. struct wireless_dev *wdev = wil->wdev;
  283. struct wmi_ready_event *evt = d;
  284. wil->n_mids = evt->numof_additional_mids;
  285. wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n",
  286. wil->fw_version, le32_to_cpu(evt->sw_version),
  287. evt->mac, wil->n_mids);
  288. /* ignore MAC address, we already have it from the boot loader */
  289. strlcpy(wdev->wiphy->fw_version, wil->fw_version,
  290. sizeof(wdev->wiphy->fw_version));
  291. wil_set_recovery_state(wil, fw_recovery_idle);
  292. set_bit(wil_status_fwready, wil->status);
  293. /* let the reset sequence continue */
  294. complete(&wil->wmi_ready);
  295. }
  296. static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
  297. {
  298. struct wmi_rx_mgmt_packet_event *data = d;
  299. struct wiphy *wiphy = wil_to_wiphy(wil);
  300. struct ieee80211_mgmt *rx_mgmt_frame =
  301. (struct ieee80211_mgmt *)data->payload;
  302. int flen = len - offsetof(struct wmi_rx_mgmt_packet_event, payload);
  303. int ch_no;
  304. u32 freq;
  305. struct ieee80211_channel *channel;
  306. s32 signal;
  307. __le16 fc;
  308. u32 d_len;
  309. u16 d_status;
  310. if (flen < 0) {
  311. wil_err(wil, "MGMT Rx: short event, len %d\n", len);
  312. return;
  313. }
  314. d_len = le32_to_cpu(data->info.len);
  315. if (d_len != flen) {
  316. wil_err(wil,
  317. "MGMT Rx: length mismatch, d_len %d should be %d\n",
  318. d_len, flen);
  319. return;
  320. }
  321. ch_no = data->info.channel + 1;
  322. freq = ieee80211_channel_to_frequency(ch_no, NL80211_BAND_60GHZ);
  323. channel = ieee80211_get_channel(wiphy, freq);
  324. signal = data->info.sqi;
  325. d_status = le16_to_cpu(data->info.status);
  326. fc = rx_mgmt_frame->frame_control;
  327. wil_dbg_wmi(wil, "MGMT Rx: channel %d MCS %d SNR %d SQI %d%%\n",
  328. data->info.channel, data->info.mcs, data->info.snr,
  329. data->info.sqi);
  330. wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len,
  331. le16_to_cpu(fc));
  332. wil_dbg_wmi(wil, "qid %d mid %d cid %d\n",
  333. data->info.qid, data->info.mid, data->info.cid);
  334. wil_hex_dump_wmi("MGMT Rx ", DUMP_PREFIX_OFFSET, 16, 1, rx_mgmt_frame,
  335. d_len, true);
  336. if (!channel) {
  337. wil_err(wil, "Frame on unsupported channel\n");
  338. return;
  339. }
  340. if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
  341. struct cfg80211_bss *bss;
  342. u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
  343. u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
  344. u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
  345. const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
  346. size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
  347. u.beacon.variable);
  348. wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
  349. wil_dbg_wmi(wil, "TSF : 0x%016llx\n", tsf);
  350. wil_dbg_wmi(wil, "Beacon interval : %d\n", bi);
  351. wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET, 16, 1, ie_buf,
  352. ie_len, true);
  353. wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
  354. bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
  355. d_len, signal, GFP_KERNEL);
  356. if (bss) {
  357. wil_dbg_wmi(wil, "Added BSS %pM\n",
  358. rx_mgmt_frame->bssid);
  359. cfg80211_put_bss(wiphy, bss);
  360. } else {
  361. wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
  362. }
  363. } else {
  364. mutex_lock(&wil->p2p_wdev_mutex);
  365. cfg80211_rx_mgmt(wil->radio_wdev, freq, signal,
  366. (void *)rx_mgmt_frame, d_len, 0);
  367. mutex_unlock(&wil->p2p_wdev_mutex);
  368. }
  369. }
  370. static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
  371. {
  372. struct wmi_tx_mgmt_packet_event *data = d;
  373. struct ieee80211_mgmt *mgmt_frame =
  374. (struct ieee80211_mgmt *)data->payload;
  375. int flen = len - offsetof(struct wmi_tx_mgmt_packet_event, payload);
  376. wil_hex_dump_wmi("MGMT Tx ", DUMP_PREFIX_OFFSET, 16, 1, mgmt_frame,
  377. flen, true);
  378. }
  379. static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
  380. void *d, int len)
  381. {
  382. mutex_lock(&wil->p2p_wdev_mutex);
  383. if (wil->scan_request) {
  384. struct wmi_scan_complete_event *data = d;
  385. int status = le32_to_cpu(data->status);
  386. struct cfg80211_scan_info info = {
  387. .aborted = ((status != WMI_SCAN_SUCCESS) &&
  388. (status != WMI_SCAN_ABORT_REJECTED)),
  389. };
  390. wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", status);
  391. wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
  392. wil->scan_request, info.aborted);
  393. del_timer_sync(&wil->scan_timer);
  394. cfg80211_scan_done(wil->scan_request, &info);
  395. wil->radio_wdev = wil->wdev;
  396. wil->scan_request = NULL;
  397. wake_up_interruptible(&wil->wq);
  398. if (wil->p2p.pending_listen_wdev) {
  399. wil_dbg_misc(wil, "Scheduling delayed listen\n");
  400. schedule_work(&wil->p2p.delayed_listen_work);
  401. }
  402. } else {
  403. wil_err(wil, "SCAN_COMPLETE while not scanning\n");
  404. }
  405. mutex_unlock(&wil->p2p_wdev_mutex);
  406. }
  407. static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
  408. {
  409. struct net_device *ndev = wil_to_ndev(wil);
  410. struct wireless_dev *wdev = wil->wdev;
  411. struct wmi_connect_event *evt = d;
  412. int ch; /* channel number */
  413. struct station_info sinfo;
  414. u8 *assoc_req_ie, *assoc_resp_ie;
  415. size_t assoc_req_ielen, assoc_resp_ielen;
  416. /* capinfo(u16) + listen_interval(u16) + IEs */
  417. const size_t assoc_req_ie_offset = sizeof(u16) * 2;
  418. /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
  419. const size_t assoc_resp_ie_offset = sizeof(u16) * 3;
  420. int rc;
  421. if (len < sizeof(*evt)) {
  422. wil_err(wil, "Connect event too short : %d bytes\n", len);
  423. return;
  424. }
  425. if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len +
  426. evt->assoc_resp_len) {
  427. wil_err(wil,
  428. "Connect event corrupted : %d != %d + %d + %d + %d\n",
  429. len, (int)sizeof(*evt), evt->beacon_ie_len,
  430. evt->assoc_req_len, evt->assoc_resp_len);
  431. return;
  432. }
  433. if (evt->cid >= WIL6210_MAX_CID) {
  434. wil_err(wil, "Connect CID invalid : %d\n", evt->cid);
  435. return;
  436. }
  437. ch = evt->channel + 1;
  438. wil_info(wil, "Connect %pM channel [%d] cid %d\n",
  439. evt->bssid, ch, evt->cid);
  440. wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
  441. evt->assoc_info, len - sizeof(*evt), true);
  442. /* figure out IE's */
  443. assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len +
  444. assoc_req_ie_offset];
  445. assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset;
  446. if (evt->assoc_req_len <= assoc_req_ie_offset) {
  447. assoc_req_ie = NULL;
  448. assoc_req_ielen = 0;
  449. }
  450. assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len +
  451. evt->assoc_req_len +
  452. assoc_resp_ie_offset];
  453. assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset;
  454. if (evt->assoc_resp_len <= assoc_resp_ie_offset) {
  455. assoc_resp_ie = NULL;
  456. assoc_resp_ielen = 0;
  457. }
  458. mutex_lock(&wil->mutex);
  459. if (test_bit(wil_status_resetting, wil->status) ||
  460. !test_bit(wil_status_fwready, wil->status)) {
  461. wil_err(wil, "status_resetting, cancel connect event, CID %d\n",
  462. evt->cid);
  463. mutex_unlock(&wil->mutex);
  464. /* no need for cleanup, wil_reset will do that */
  465. return;
  466. }
  467. if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
  468. (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
  469. if (!test_bit(wil_status_fwconnecting, wil->status)) {
  470. wil_err(wil, "Not in connecting state\n");
  471. mutex_unlock(&wil->mutex);
  472. return;
  473. }
  474. del_timer_sync(&wil->connect_timer);
  475. } else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
  476. (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
  477. if (wil->sta[evt->cid].status != wil_sta_unused) {
  478. wil_err(wil, "%s: AP: Invalid status %d for CID %d\n",
  479. __func__, wil->sta[evt->cid].status, evt->cid);
  480. mutex_unlock(&wil->mutex);
  481. return;
  482. }
  483. }
  484. /* FIXME FW can transmit only ucast frames to peer */
  485. /* FIXME real ring_id instead of hard coded 0 */
  486. ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid);
  487. wil->sta[evt->cid].status = wil_sta_conn_pending;
  488. rc = wil_tx_init(wil, evt->cid);
  489. if (rc) {
  490. wil_err(wil, "%s: config tx vring failed for CID %d, rc (%d)\n",
  491. __func__, evt->cid, rc);
  492. wmi_disconnect_sta(wil, wil->sta[evt->cid].addr,
  493. WLAN_REASON_UNSPECIFIED, false);
  494. } else {
  495. wil_info(wil, "%s: successful connection to CID %d\n",
  496. __func__, evt->cid);
  497. }
  498. if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
  499. (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
  500. if (rc) {
  501. netif_carrier_off(ndev);
  502. wil_err(wil,
  503. "%s: cfg80211_connect_result with failure\n",
  504. __func__);
  505. cfg80211_connect_result(ndev, evt->bssid, NULL, 0,
  506. NULL, 0,
  507. WLAN_STATUS_UNSPECIFIED_FAILURE,
  508. GFP_KERNEL);
  509. goto out;
  510. } else {
  511. cfg80211_connect_result(ndev, evt->bssid,
  512. assoc_req_ie, assoc_req_ielen,
  513. assoc_resp_ie, assoc_resp_ielen,
  514. WLAN_STATUS_SUCCESS,
  515. GFP_KERNEL);
  516. }
  517. } else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
  518. (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
  519. if (rc)
  520. goto out;
  521. memset(&sinfo, 0, sizeof(sinfo));
  522. sinfo.generation = wil->sinfo_gen++;
  523. if (assoc_req_ie) {
  524. sinfo.assoc_req_ies = assoc_req_ie;
  525. sinfo.assoc_req_ies_len = assoc_req_ielen;
  526. }
  527. cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
  528. } else {
  529. wil_err(wil, "%s: unhandled iftype %d for CID %d\n",
  530. __func__, wdev->iftype, evt->cid);
  531. goto out;
  532. }
  533. wil->sta[evt->cid].status = wil_sta_connected;
  534. set_bit(wil_status_fwconnected, wil->status);
  535. wil_update_net_queues_bh(wil, NULL, false);
  536. out:
  537. if (rc)
  538. wil->sta[evt->cid].status = wil_sta_unused;
  539. clear_bit(wil_status_fwconnecting, wil->status);
  540. mutex_unlock(&wil->mutex);
  541. }
  542. static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
  543. void *d, int len)
  544. {
  545. struct wmi_disconnect_event *evt = d;
  546. u16 reason_code = le16_to_cpu(evt->protocol_reason_status);
  547. wil_info(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
  548. evt->bssid, reason_code, evt->disconnect_reason);
  549. wil->sinfo_gen++;
  550. mutex_lock(&wil->mutex);
  551. wil6210_disconnect(wil, evt->bssid, reason_code, true);
  552. mutex_unlock(&wil->mutex);
  553. }
  554. /*
  555. * Firmware reports EAPOL frame using WME event.
  556. * Reconstruct Ethernet frame and deliver it via normal Rx
  557. */
  558. static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
  559. void *d, int len)
  560. {
  561. struct net_device *ndev = wil_to_ndev(wil);
  562. struct wmi_eapol_rx_event *evt = d;
  563. u16 eapol_len = le16_to_cpu(evt->eapol_len);
  564. int sz = eapol_len + ETH_HLEN;
  565. struct sk_buff *skb;
  566. struct ethhdr *eth;
  567. int cid;
  568. struct wil_net_stats *stats = NULL;
  569. wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len,
  570. evt->src_mac);
  571. cid = wil_find_cid(wil, evt->src_mac);
  572. if (cid >= 0)
  573. stats = &wil->sta[cid].stats;
  574. if (eapol_len > 196) { /* TODO: revisit size limit */
  575. wil_err(wil, "EAPOL too large\n");
  576. return;
  577. }
  578. skb = alloc_skb(sz, GFP_KERNEL);
  579. if (!skb) {
  580. wil_err(wil, "Failed to allocate skb\n");
  581. return;
  582. }
  583. eth = (struct ethhdr *)skb_put(skb, ETH_HLEN);
  584. ether_addr_copy(eth->h_dest, ndev->dev_addr);
  585. ether_addr_copy(eth->h_source, evt->src_mac);
  586. eth->h_proto = cpu_to_be16(ETH_P_PAE);
  587. memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len);
  588. skb->protocol = eth_type_trans(skb, ndev);
  589. if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) {
  590. ndev->stats.rx_packets++;
  591. ndev->stats.rx_bytes += sz;
  592. if (stats) {
  593. stats->rx_packets++;
  594. stats->rx_bytes += sz;
  595. }
  596. } else {
  597. ndev->stats.rx_dropped++;
  598. if (stats)
  599. stats->rx_dropped++;
  600. }
  601. }
  602. static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len)
  603. {
  604. struct wmi_vring_en_event *evt = d;
  605. u8 vri = evt->vring_index;
  606. wil_dbg_wmi(wil, "Enable vring %d\n", vri);
  607. if (vri >= ARRAY_SIZE(wil->vring_tx)) {
  608. wil_err(wil, "Enable for invalid vring %d\n", vri);
  609. return;
  610. }
  611. wil->vring_tx_data[vri].dot1x_open = true;
  612. if (vri == wil->bcast_vring) /* no BA for bcast */
  613. return;
  614. if (agg_wsize >= 0)
  615. wil_addba_tx_request(wil, vri, agg_wsize);
  616. }
  617. static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
  618. int len)
  619. {
  620. struct wmi_ba_status_event *evt = d;
  621. struct vring_tx_data *txdata;
  622. wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
  623. evt->ringid,
  624. evt->status == WMI_BA_AGREED ? "OK" : "N/A",
  625. evt->agg_wsize, __le16_to_cpu(evt->ba_timeout),
  626. evt->amsdu ? "+" : "-");
  627. if (evt->ringid >= WIL6210_MAX_TX_RINGS) {
  628. wil_err(wil, "invalid ring id %d\n", evt->ringid);
  629. return;
  630. }
  631. if (evt->status != WMI_BA_AGREED) {
  632. evt->ba_timeout = 0;
  633. evt->agg_wsize = 0;
  634. evt->amsdu = 0;
  635. }
  636. txdata = &wil->vring_tx_data[evt->ringid];
  637. txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
  638. txdata->agg_wsize = evt->agg_wsize;
  639. txdata->agg_amsdu = evt->amsdu;
  640. txdata->addba_in_progress = false;
  641. }
  642. static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d,
  643. int len)
  644. {
  645. struct wmi_rcp_addba_req_event *evt = d;
  646. wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token,
  647. evt->ba_param_set, evt->ba_timeout,
  648. evt->ba_seq_ctrl);
  649. }
  650. static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
  651. __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
  652. {
  653. struct wmi_delba_event *evt = d;
  654. u8 cid, tid;
  655. u16 reason = __le16_to_cpu(evt->reason);
  656. struct wil_sta_info *sta;
  657. struct wil_tid_ampdu_rx *r;
  658. might_sleep();
  659. parse_cidxtid(evt->cidxtid, &cid, &tid);
  660. wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n",
  661. cid, tid,
  662. evt->from_initiator ? "originator" : "recipient",
  663. reason);
  664. if (!evt->from_initiator) {
  665. int i;
  666. /* find Tx vring it belongs to */
  667. for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
  668. if ((wil->vring2cid_tid[i][0] == cid) &&
  669. (wil->vring2cid_tid[i][1] == tid)) {
  670. struct vring_tx_data *txdata =
  671. &wil->vring_tx_data[i];
  672. wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
  673. txdata->agg_timeout = 0;
  674. txdata->agg_wsize = 0;
  675. txdata->addba_in_progress = false;
  676. break; /* max. 1 matching ring */
  677. }
  678. }
  679. if (i >= ARRAY_SIZE(wil->vring2cid_tid))
  680. wil_err(wil, "DELBA: unable to find Tx vring\n");
  681. return;
  682. }
  683. sta = &wil->sta[cid];
  684. spin_lock_bh(&sta->tid_rx_lock);
  685. r = sta->tid_rx[tid];
  686. sta->tid_rx[tid] = NULL;
  687. wil_tid_ampdu_rx_free(wil, r);
  688. spin_unlock_bh(&sta->tid_rx_lock);
  689. }
  690. /**
  691. * Some events are ignored for purpose; and need not be interpreted as
  692. * "unhandled events"
  693. */
  694. static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len)
  695. {
  696. wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len);
  697. }
  698. static const struct {
  699. int eventid;
  700. void (*handler)(struct wil6210_priv *wil, int eventid,
  701. void *data, int data_len);
  702. } wmi_evt_handlers[] = {
  703. {WMI_READY_EVENTID, wmi_evt_ready},
  704. {WMI_FW_READY_EVENTID, wmi_evt_ignore},
  705. {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt},
  706. {WMI_TX_MGMT_PACKET_EVENTID, wmi_evt_tx_mgmt},
  707. {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete},
  708. {WMI_CONNECT_EVENTID, wmi_evt_connect},
  709. {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect},
  710. {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx},
  711. {WMI_BA_STATUS_EVENTID, wmi_evt_ba_status},
  712. {WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req},
  713. {WMI_DELBA_EVENTID, wmi_evt_delba},
  714. {WMI_VRING_EN_EVENTID, wmi_evt_vring_en},
  715. {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore},
  716. };
  717. /*
  718. * Run in IRQ context
  719. * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
  720. * that will be eventually handled by the @wmi_event_worker in the thread
  721. * context of thread "wil6210_wmi"
  722. */
  723. void wmi_recv_cmd(struct wil6210_priv *wil)
  724. {
  725. struct wil6210_mbox_ring_desc d_tail;
  726. struct wil6210_mbox_hdr hdr;
  727. struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
  728. struct pending_wmi_event *evt;
  729. u8 *cmd;
  730. void __iomem *src;
  731. ulong flags;
  732. unsigned n;
  733. unsigned int num_immed_reply = 0;
  734. if (!test_bit(wil_status_mbox_ready, wil->status)) {
  735. wil_err(wil, "Reset in progress. Cannot handle WMI event\n");
  736. return;
  737. }
  738. for (n = 0;; n++) {
  739. u16 len;
  740. bool q;
  741. bool immed_reply = false;
  742. r->head = wil_r(wil, RGF_MBOX +
  743. offsetof(struct wil6210_mbox_ctl, rx.head));
  744. if (r->tail == r->head)
  745. break;
  746. wil_dbg_wmi(wil, "Mbox head %08x tail %08x\n",
  747. r->head, r->tail);
  748. /* read cmd descriptor from tail */
  749. wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail),
  750. sizeof(struct wil6210_mbox_ring_desc));
  751. if (d_tail.sync == 0) {
  752. wil_err(wil, "Mbox evt not owned by FW?\n");
  753. break;
  754. }
  755. /* read cmd header from descriptor */
  756. if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
  757. wil_err(wil, "Mbox evt at 0x%08x?\n",
  758. le32_to_cpu(d_tail.addr));
  759. break;
  760. }
  761. len = le16_to_cpu(hdr.len);
  762. wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
  763. le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
  764. hdr.flags);
  765. /* read cmd buffer from descriptor */
  766. src = wmi_buffer(wil, d_tail.addr) +
  767. sizeof(struct wil6210_mbox_hdr);
  768. evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event,
  769. event.wmi) + len, 4),
  770. GFP_KERNEL);
  771. if (!evt)
  772. break;
  773. evt->event.hdr = hdr;
  774. cmd = (void *)&evt->event.wmi;
  775. wil_memcpy_fromio_32(cmd, src, len);
  776. /* mark entry as empty */
  777. wil_w(wil, r->tail +
  778. offsetof(struct wil6210_mbox_ring_desc, sync), 0);
  779. /* indicate */
  780. if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
  781. (len >= sizeof(struct wmi_cmd_hdr))) {
  782. struct wmi_cmd_hdr *wmi = &evt->event.wmi;
  783. u16 id = le16_to_cpu(wmi->command_id);
  784. u32 tstamp = le32_to_cpu(wmi->fw_timestamp);
  785. spin_lock_irqsave(&wil->wmi_ev_lock, flags);
  786. if (wil->reply_id && wil->reply_id == id) {
  787. if (wil->reply_buf) {
  788. memcpy(wil->reply_buf, wmi,
  789. min(len, wil->reply_size));
  790. immed_reply = true;
  791. }
  792. }
  793. spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
  794. wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n",
  795. id, wmi->mid, tstamp);
  796. trace_wil6210_wmi_event(wmi, &wmi[1],
  797. len - sizeof(*wmi));
  798. }
  799. wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET, 16, 1,
  800. &evt->event.hdr, sizeof(hdr) + len, true);
  801. /* advance tail */
  802. r->tail = r->base + ((r->tail - r->base +
  803. sizeof(struct wil6210_mbox_ring_desc)) % r->size);
  804. wil_w(wil, RGF_MBOX +
  805. offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail);
  806. if (immed_reply) {
  807. wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n",
  808. __func__, wil->reply_id);
  809. kfree(evt);
  810. num_immed_reply++;
  811. complete(&wil->wmi_call);
  812. } else {
  813. /* add to the pending list */
  814. spin_lock_irqsave(&wil->wmi_ev_lock, flags);
  815. list_add_tail(&evt->list, &wil->pending_wmi_ev);
  816. spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
  817. q = queue_work(wil->wmi_wq, &wil->wmi_event_worker);
  818. wil_dbg_wmi(wil, "queue_work -> %d\n", q);
  819. }
  820. }
  821. /* normally, 1 event per IRQ should be processed */
  822. wil_dbg_wmi(wil, "%s -> %d events queued, %d completed\n", __func__,
  823. n - num_immed_reply, num_immed_reply);
  824. }
  825. int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
  826. u16 reply_id, void *reply, u8 reply_size, int to_msec)
  827. {
  828. int rc;
  829. unsigned long remain;
  830. mutex_lock(&wil->wmi_mutex);
  831. spin_lock(&wil->wmi_ev_lock);
  832. wil->reply_id = reply_id;
  833. wil->reply_buf = reply;
  834. wil->reply_size = reply_size;
  835. spin_unlock(&wil->wmi_ev_lock);
  836. rc = __wmi_send(wil, cmdid, buf, len);
  837. if (rc)
  838. goto out;
  839. remain = wait_for_completion_timeout(&wil->wmi_call,
  840. msecs_to_jiffies(to_msec));
  841. if (0 == remain) {
  842. wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n",
  843. cmdid, reply_id, to_msec);
  844. rc = -ETIME;
  845. } else {
  846. wil_dbg_wmi(wil,
  847. "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
  848. cmdid, reply_id,
  849. to_msec - jiffies_to_msecs(remain));
  850. }
  851. out:
  852. spin_lock(&wil->wmi_ev_lock);
  853. wil->reply_id = 0;
  854. wil->reply_buf = NULL;
  855. wil->reply_size = 0;
  856. spin_unlock(&wil->wmi_ev_lock);
  857. mutex_unlock(&wil->wmi_mutex);
  858. return rc;
  859. }
  860. int wmi_echo(struct wil6210_priv *wil)
  861. {
  862. struct wmi_echo_cmd cmd = {
  863. .value = cpu_to_le32(0x12345678),
  864. };
  865. return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd),
  866. WMI_ECHO_RSP_EVENTID, NULL, 0, 50);
  867. }
  868. int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
  869. {
  870. struct wmi_set_mac_address_cmd cmd;
  871. ether_addr_copy(cmd.mac, addr);
  872. wil_dbg_wmi(wil, "Set MAC %pM\n", addr);
  873. return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
  874. }
  875. int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
  876. {
  877. int rc = 0;
  878. struct wmi_led_cfg_cmd cmd = {
  879. .led_mode = enable,
  880. .id = led_id,
  881. .slow_blink_cfg.blink_on =
  882. cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].on_ms),
  883. .slow_blink_cfg.blink_off =
  884. cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].off_ms),
  885. .medium_blink_cfg.blink_on =
  886. cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].on_ms),
  887. .medium_blink_cfg.blink_off =
  888. cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].off_ms),
  889. .fast_blink_cfg.blink_on =
  890. cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].on_ms),
  891. .fast_blink_cfg.blink_off =
  892. cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].off_ms),
  893. .led_polarity = led_polarity,
  894. };
  895. struct {
  896. struct wmi_cmd_hdr wmi;
  897. struct wmi_led_cfg_done_event evt;
  898. } __packed reply;
  899. if (led_id == WIL_LED_INVALID_ID)
  900. goto out;
  901. if (led_id > WIL_LED_MAX_ID) {
  902. wil_err(wil, "Invalid led id %d\n", led_id);
  903. rc = -EINVAL;
  904. goto out;
  905. }
  906. wil_dbg_wmi(wil,
  907. "%s led %d\n",
  908. enable ? "enabling" : "disabling", led_id);
  909. rc = wmi_call(wil, WMI_LED_CFG_CMDID, &cmd, sizeof(cmd),
  910. WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply),
  911. 100);
  912. if (rc)
  913. goto out;
  914. if (reply.evt.status) {
  915. wil_err(wil, "led %d cfg failed with status %d\n",
  916. led_id, le32_to_cpu(reply.evt.status));
  917. rc = -EINVAL;
  918. }
  919. out:
  920. return rc;
  921. }
  922. int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
  923. u8 chan, u8 hidden_ssid, u8 is_go)
  924. {
  925. int rc;
  926. struct wmi_pcp_start_cmd cmd = {
  927. .bcon_interval = cpu_to_le16(bi),
  928. .network_type = wmi_nettype,
  929. .disable_sec_offload = 1,
  930. .channel = chan - 1,
  931. .pcp_max_assoc_sta = max_assoc_sta,
  932. .hidden_ssid = hidden_ssid,
  933. .is_go = is_go,
  934. };
  935. struct {
  936. struct wmi_cmd_hdr wmi;
  937. struct wmi_pcp_started_event evt;
  938. } __packed reply;
  939. if (!wil->privacy)
  940. cmd.disable_sec = 1;
  941. if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
  942. (cmd.pcp_max_assoc_sta <= 0)) {
  943. wil_info(wil,
  944. "Requested connection limit %u, valid values are 1 - %d. Setting to %d\n",
  945. max_assoc_sta, WIL6210_MAX_CID, WIL6210_MAX_CID);
  946. cmd.pcp_max_assoc_sta = WIL6210_MAX_CID;
  947. }
  948. /*
  949. * Processing time may be huge, in case of secure AP it takes about
  950. * 3500ms for FW to start AP
  951. */
  952. rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd),
  953. WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000);
  954. if (rc)
  955. return rc;
  956. if (reply.evt.status != WMI_FW_STATUS_SUCCESS)
  957. rc = -EINVAL;
  958. if (wmi_nettype != WMI_NETTYPE_P2P)
  959. /* Don't fail due to error in the led configuration */
  960. wmi_led_cfg(wil, true);
  961. return rc;
  962. }
  963. int wmi_pcp_stop(struct wil6210_priv *wil)
  964. {
  965. int rc;
  966. rc = wmi_led_cfg(wil, false);
  967. if (rc)
  968. return rc;
  969. return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0,
  970. WMI_PCP_STOPPED_EVENTID, NULL, 0, 20);
  971. }
  972. int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid)
  973. {
  974. struct wmi_set_ssid_cmd cmd = {
  975. .ssid_len = cpu_to_le32(ssid_len),
  976. };
  977. if (ssid_len > sizeof(cmd.ssid))
  978. return -EINVAL;
  979. memcpy(cmd.ssid, ssid, ssid_len);
  980. return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd));
  981. }
  982. int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
  983. {
  984. int rc;
  985. struct {
  986. struct wmi_cmd_hdr wmi;
  987. struct wmi_set_ssid_cmd cmd;
  988. } __packed reply;
  989. int len; /* reply.cmd.ssid_len in CPU order */
  990. rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID,
  991. &reply, sizeof(reply), 20);
  992. if (rc)
  993. return rc;
  994. len = le32_to_cpu(reply.cmd.ssid_len);
  995. if (len > sizeof(reply.cmd.ssid))
  996. return -EINVAL;
  997. *ssid_len = len;
  998. memcpy(ssid, reply.cmd.ssid, len);
  999. return 0;
  1000. }
  1001. int wmi_set_channel(struct wil6210_priv *wil, int channel)
  1002. {
  1003. struct wmi_set_pcp_channel_cmd cmd = {
  1004. .channel = channel - 1,
  1005. };
  1006. return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd));
  1007. }
  1008. int wmi_get_channel(struct wil6210_priv *wil, int *channel)
  1009. {
  1010. int rc;
  1011. struct {
  1012. struct wmi_cmd_hdr wmi;
  1013. struct wmi_set_pcp_channel_cmd cmd;
  1014. } __packed reply;
  1015. rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0,
  1016. WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20);
  1017. if (rc)
  1018. return rc;
  1019. if (reply.cmd.channel > 3)
  1020. return -EINVAL;
  1021. *channel = reply.cmd.channel + 1;
  1022. return 0;
  1023. }
  1024. int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi)
  1025. {
  1026. int rc;
  1027. struct wmi_p2p_cfg_cmd cmd = {
  1028. .discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER,
  1029. .bcon_interval = cpu_to_le16(bi),
  1030. .channel = channel - 1,
  1031. };
  1032. struct {
  1033. struct wmi_cmd_hdr wmi;
  1034. struct wmi_p2p_cfg_done_event evt;
  1035. } __packed reply;
  1036. wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n");
  1037. rc = wmi_call(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd),
  1038. WMI_P2P_CFG_DONE_EVENTID, &reply, sizeof(reply), 300);
  1039. if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
  1040. wil_err(wil, "P2P_CFG failed. status %d\n", reply.evt.status);
  1041. rc = -EINVAL;
  1042. }
  1043. return rc;
  1044. }
  1045. int wmi_start_listen(struct wil6210_priv *wil)
  1046. {
  1047. int rc;
  1048. struct {
  1049. struct wmi_cmd_hdr wmi;
  1050. struct wmi_listen_started_event evt;
  1051. } __packed reply;
  1052. wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n");
  1053. rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
  1054. WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 300);
  1055. if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
  1056. wil_err(wil, "device failed to start listen. status %d\n",
  1057. reply.evt.status);
  1058. rc = -EINVAL;
  1059. }
  1060. return rc;
  1061. }
  1062. int wmi_start_search(struct wil6210_priv *wil)
  1063. {
  1064. int rc;
  1065. struct {
  1066. struct wmi_cmd_hdr wmi;
  1067. struct wmi_search_started_event evt;
  1068. } __packed reply;
  1069. wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n");
  1070. rc = wmi_call(wil, WMI_START_SEARCH_CMDID, NULL, 0,
  1071. WMI_SEARCH_STARTED_EVENTID, &reply, sizeof(reply), 300);
  1072. if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
  1073. wil_err(wil, "device failed to start search. status %d\n",
  1074. reply.evt.status);
  1075. rc = -EINVAL;
  1076. }
  1077. return rc;
  1078. }
  1079. int wmi_stop_discovery(struct wil6210_priv *wil)
  1080. {
  1081. int rc;
  1082. wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n");
  1083. rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
  1084. WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100);
  1085. if (rc)
  1086. wil_err(wil, "Failed to stop discovery\n");
  1087. return rc;
  1088. }
  1089. int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
  1090. const void *mac_addr, int key_usage)
  1091. {
  1092. struct wmi_delete_cipher_key_cmd cmd = {
  1093. .key_index = key_index,
  1094. };
  1095. if (mac_addr)
  1096. memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
  1097. return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
  1098. }
  1099. int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
  1100. const void *mac_addr, int key_len, const void *key,
  1101. int key_usage)
  1102. {
  1103. struct wmi_add_cipher_key_cmd cmd = {
  1104. .key_index = key_index,
  1105. .key_usage = key_usage,
  1106. .key_len = key_len,
  1107. };
  1108. if (!key || (key_len > sizeof(cmd.key)))
  1109. return -EINVAL;
  1110. memcpy(cmd.key, key, key_len);
  1111. if (mac_addr)
  1112. memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
  1113. return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
  1114. }
  1115. int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
  1116. {
  1117. static const char *const names[] = {
  1118. [WMI_FRAME_BEACON] = "BEACON",
  1119. [WMI_FRAME_PROBE_REQ] = "PROBE_REQ",
  1120. [WMI_FRAME_PROBE_RESP] = "WMI_FRAME_PROBE_RESP",
  1121. [WMI_FRAME_ASSOC_REQ] = "WMI_FRAME_ASSOC_REQ",
  1122. [WMI_FRAME_ASSOC_RESP] = "WMI_FRAME_ASSOC_RESP",
  1123. };
  1124. int rc;
  1125. u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
  1126. struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL);
  1127. if (!cmd) {
  1128. rc = -ENOMEM;
  1129. goto out;
  1130. }
  1131. if (!ie)
  1132. ie_len = 0;
  1133. cmd->mgmt_frm_type = type;
  1134. /* BUG: FW API define ieLen as u8. Will fix FW */
  1135. cmd->ie_len = cpu_to_le16(ie_len);
  1136. memcpy(cmd->ie_info, ie, ie_len);
  1137. rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len);
  1138. kfree(cmd);
  1139. out:
  1140. if (rc) {
  1141. const char *name = type < ARRAY_SIZE(names) ?
  1142. names[type] : "??";
  1143. wil_err(wil, "set_ie(%d %s) failed : %d\n", type, name, rc);
  1144. }
  1145. return rc;
  1146. }
  1147. /**
  1148. * wmi_rxon - turn radio on/off
  1149. * @on: turn on if true, off otherwise
  1150. *
  1151. * Only switch radio. Channel should be set separately.
  1152. * No timeout for rxon - radio turned on forever unless some other call
  1153. * turns it off
  1154. */
  1155. int wmi_rxon(struct wil6210_priv *wil, bool on)
  1156. {
  1157. int rc;
  1158. struct {
  1159. struct wmi_cmd_hdr wmi;
  1160. struct wmi_listen_started_event evt;
  1161. } __packed reply;
  1162. wil_info(wil, "%s(%s)\n", __func__, on ? "on" : "off");
  1163. if (on) {
  1164. rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
  1165. WMI_LISTEN_STARTED_EVENTID,
  1166. &reply, sizeof(reply), 100);
  1167. if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
  1168. rc = -EINVAL;
  1169. } else {
  1170. rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
  1171. WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20);
  1172. }
  1173. return rc;
  1174. }
  1175. int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
  1176. {
  1177. struct wireless_dev *wdev = wil->wdev;
  1178. struct net_device *ndev = wil_to_ndev(wil);
  1179. struct wmi_cfg_rx_chain_cmd cmd = {
  1180. .action = WMI_RX_CHAIN_ADD,
  1181. .rx_sw_ring = {
  1182. .max_mpdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)),
  1183. .ring_mem_base = cpu_to_le64(vring->pa),
  1184. .ring_size = cpu_to_le16(vring->size),
  1185. },
  1186. .mid = 0, /* TODO - what is it? */
  1187. .decap_trans_type = WMI_DECAP_TYPE_802_3,
  1188. .reorder_type = WMI_RX_SW_REORDER,
  1189. .host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh),
  1190. };
  1191. struct {
  1192. struct wmi_cmd_hdr wmi;
  1193. struct wmi_cfg_rx_chain_done_event evt;
  1194. } __packed evt;
  1195. int rc;
  1196. if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
  1197. struct ieee80211_channel *ch = wdev->preset_chandef.chan;
  1198. cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
  1199. if (ch)
  1200. cmd.sniffer_cfg.channel = ch->hw_value - 1;
  1201. cmd.sniffer_cfg.phy_info_mode =
  1202. cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
  1203. cmd.sniffer_cfg.phy_support =
  1204. cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
  1205. ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS);
  1206. } else {
  1207. /* Initialize offload (in non-sniffer mode).
  1208. * Linux IP stack always calculates IP checksum
  1209. * HW always calculate TCP/UDP checksum
  1210. */
  1211. cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS);
  1212. }
  1213. if (rx_align_2)
  1214. cmd.l2_802_3_offload_ctrl |=
  1215. L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK;
  1216. /* typical time for secure PCP is 840ms */
  1217. rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
  1218. WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
  1219. if (rc)
  1220. return rc;
  1221. vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
  1222. wil_dbg_misc(wil, "Rx init: status %d tail 0x%08x\n",
  1223. le32_to_cpu(evt.evt.status), vring->hwtail);
  1224. if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS)
  1225. rc = -EINVAL;
  1226. return rc;
  1227. }
  1228. int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
  1229. {
  1230. int rc;
  1231. struct wmi_temp_sense_cmd cmd = {
  1232. .measure_baseband_en = cpu_to_le32(!!t_bb),
  1233. .measure_rf_en = cpu_to_le32(!!t_rf),
  1234. .measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW),
  1235. };
  1236. struct {
  1237. struct wmi_cmd_hdr wmi;
  1238. struct wmi_temp_sense_done_event evt;
  1239. } __packed reply;
  1240. rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd),
  1241. WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100);
  1242. if (rc)
  1243. return rc;
  1244. if (t_bb)
  1245. *t_bb = le32_to_cpu(reply.evt.baseband_t1000);
  1246. if (t_rf)
  1247. *t_rf = le32_to_cpu(reply.evt.rf_t1000);
  1248. return 0;
  1249. }
  1250. int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason,
  1251. bool full_disconnect)
  1252. {
  1253. int rc;
  1254. u16 reason_code;
  1255. struct wmi_disconnect_sta_cmd cmd = {
  1256. .disconnect_reason = cpu_to_le16(reason),
  1257. };
  1258. struct {
  1259. struct wmi_cmd_hdr wmi;
  1260. struct wmi_disconnect_event evt;
  1261. } __packed reply;
  1262. ether_addr_copy(cmd.dst_mac, mac);
  1263. wil_dbg_wmi(wil, "%s(%pM, reason %d)\n", __func__, mac, reason);
  1264. rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd),
  1265. WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), 1000);
  1266. /* failure to disconnect in reasonable time treated as FW error */
  1267. if (rc) {
  1268. wil_fw_error_recovery(wil);
  1269. return rc;
  1270. }
  1271. if (full_disconnect) {
  1272. /* call event handler manually after processing wmi_call,
  1273. * to avoid deadlock - disconnect event handler acquires
  1274. * wil->mutex while it is already held here
  1275. */
  1276. reason_code = le16_to_cpu(reply.evt.protocol_reason_status);
  1277. wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
  1278. reply.evt.bssid, reason_code,
  1279. reply.evt.disconnect_reason);
  1280. wil->sinfo_gen++;
  1281. wil6210_disconnect(wil, reply.evt.bssid, reason_code, true);
  1282. }
  1283. return 0;
  1284. }
  1285. int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout)
  1286. {
  1287. struct wmi_vring_ba_en_cmd cmd = {
  1288. .ringid = ringid,
  1289. .agg_max_wsize = size,
  1290. .ba_timeout = cpu_to_le16(timeout),
  1291. .amsdu = 0,
  1292. };
  1293. wil_dbg_wmi(wil, "%s(ring %d size %d timeout %d)\n", __func__,
  1294. ringid, size, timeout);
  1295. return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd));
  1296. }
  1297. int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason)
  1298. {
  1299. struct wmi_vring_ba_dis_cmd cmd = {
  1300. .ringid = ringid,
  1301. .reason = cpu_to_le16(reason),
  1302. };
  1303. wil_dbg_wmi(wil, "%s(ring %d reason %d)\n", __func__,
  1304. ringid, reason);
  1305. return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd));
  1306. }
  1307. int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason)
  1308. {
  1309. struct wmi_rcp_delba_cmd cmd = {
  1310. .cidxtid = cidxtid,
  1311. .reason = cpu_to_le16(reason),
  1312. };
  1313. wil_dbg_wmi(wil, "%s(CID %d TID %d reason %d)\n", __func__,
  1314. cidxtid & 0xf, (cidxtid >> 4) & 0xf, reason);
  1315. return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd));
  1316. }
  1317. int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
  1318. u16 status, bool amsdu, u16 agg_wsize, u16 timeout)
  1319. {
  1320. int rc;
  1321. struct wmi_rcp_addba_resp_cmd cmd = {
  1322. .cidxtid = mk_cidxtid(cid, tid),
  1323. .dialog_token = token,
  1324. .status_code = cpu_to_le16(status),
  1325. /* bit 0: A-MSDU supported
  1326. * bit 1: policy (should be 0 for us)
  1327. * bits 2..5: TID
  1328. * bits 6..15: buffer size
  1329. */
  1330. .ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) |
  1331. (agg_wsize << 6)),
  1332. .ba_timeout = cpu_to_le16(timeout),
  1333. };
  1334. struct {
  1335. struct wmi_cmd_hdr wmi;
  1336. struct wmi_rcp_addba_resp_sent_event evt;
  1337. } __packed reply;
  1338. wil_dbg_wmi(wil,
  1339. "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
  1340. cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-");
  1341. rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd),
  1342. WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply),
  1343. 100);
  1344. if (rc)
  1345. return rc;
  1346. if (reply.evt.status) {
  1347. wil_err(wil, "ADDBA response failed with status %d\n",
  1348. le16_to_cpu(reply.evt.status));
  1349. rc = -EINVAL;
  1350. }
  1351. return rc;
  1352. }
  1353. int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
  1354. enum wmi_ps_profile_type ps_profile)
  1355. {
  1356. int rc;
  1357. struct wmi_ps_dev_profile_cfg_cmd cmd = {
  1358. .ps_profile = ps_profile,
  1359. };
  1360. struct {
  1361. struct wmi_cmd_hdr wmi;
  1362. struct wmi_ps_dev_profile_cfg_event evt;
  1363. } __packed reply;
  1364. u32 status;
  1365. wil_dbg_wmi(wil, "Setting ps dev profile %d\n", ps_profile);
  1366. reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR);
  1367. rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, &cmd, sizeof(cmd),
  1368. WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply),
  1369. 100);
  1370. if (rc)
  1371. return rc;
  1372. status = le32_to_cpu(reply.evt.status);
  1373. if (status != WMI_PS_CFG_CMD_STATUS_SUCCESS) {
  1374. wil_err(wil, "ps dev profile cfg failed with status %d\n",
  1375. status);
  1376. rc = -EINVAL;
  1377. }
  1378. return rc;
  1379. }
  1380. int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short)
  1381. {
  1382. int rc;
  1383. struct wmi_set_mgmt_retry_limit_cmd cmd = {
  1384. .mgmt_retry_limit = retry_short,
  1385. };
  1386. struct {
  1387. struct wmi_cmd_hdr wmi;
  1388. struct wmi_set_mgmt_retry_limit_event evt;
  1389. } __packed reply;
  1390. wil_dbg_wmi(wil, "Setting mgmt retry short %d\n", retry_short);
  1391. if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
  1392. return -ENOTSUPP;
  1393. reply.evt.status = WMI_FW_STATUS_FAILURE;
  1394. rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, &cmd, sizeof(cmd),
  1395. WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
  1396. 100);
  1397. if (rc)
  1398. return rc;
  1399. if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
  1400. wil_err(wil, "set mgmt retry limit failed with status %d\n",
  1401. reply.evt.status);
  1402. rc = -EINVAL;
  1403. }
  1404. return rc;
  1405. }
  1406. int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short)
  1407. {
  1408. int rc;
  1409. struct {
  1410. struct wmi_cmd_hdr wmi;
  1411. struct wmi_get_mgmt_retry_limit_event evt;
  1412. } __packed reply;
  1413. wil_dbg_wmi(wil, "getting mgmt retry short\n");
  1414. if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
  1415. return -ENOTSUPP;
  1416. reply.evt.mgmt_retry_limit = 0;
  1417. rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, NULL, 0,
  1418. WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
  1419. 100);
  1420. if (rc)
  1421. return rc;
  1422. if (retry_short)
  1423. *retry_short = reply.evt.mgmt_retry_limit;
  1424. return 0;
  1425. }
  1426. int wmi_abort_scan(struct wil6210_priv *wil)
  1427. {
  1428. int rc;
  1429. wil_dbg_wmi(wil, "sending WMI_ABORT_SCAN_CMDID\n");
  1430. rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, NULL, 0);
  1431. if (rc)
  1432. wil_err(wil, "Failed to abort scan (%d)\n", rc);
  1433. return rc;
  1434. }
  1435. void wmi_event_flush(struct wil6210_priv *wil)
  1436. {
  1437. struct pending_wmi_event *evt, *t;
  1438. wil_dbg_wmi(wil, "%s()\n", __func__);
  1439. list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
  1440. list_del(&evt->list);
  1441. kfree(evt);
  1442. }
  1443. }
  1444. static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
  1445. void *d, int len)
  1446. {
  1447. uint i;
  1448. for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) {
  1449. if (wmi_evt_handlers[i].eventid == id) {
  1450. wmi_evt_handlers[i].handler(wil, id, d, len);
  1451. return true;
  1452. }
  1453. }
  1454. return false;
  1455. }
  1456. static void wmi_event_handle(struct wil6210_priv *wil,
  1457. struct wil6210_mbox_hdr *hdr)
  1458. {
  1459. u16 len = le16_to_cpu(hdr->len);
  1460. if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
  1461. (len >= sizeof(struct wmi_cmd_hdr))) {
  1462. struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]);
  1463. void *evt_data = (void *)(&wmi[1]);
  1464. u16 id = le16_to_cpu(wmi->command_id);
  1465. wil_dbg_wmi(wil, "Handle WMI 0x%04x (reply_id 0x%04x)\n",
  1466. id, wil->reply_id);
  1467. /* check if someone waits for this event */
  1468. if (wil->reply_id && wil->reply_id == id) {
  1469. WARN_ON(wil->reply_buf);
  1470. wmi_evt_call_handler(wil, id, evt_data,
  1471. len - sizeof(*wmi));
  1472. wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n",
  1473. __func__, id);
  1474. complete(&wil->wmi_call);
  1475. return;
  1476. }
  1477. /* unsolicited event */
  1478. /* search for handler */
  1479. if (!wmi_evt_call_handler(wil, id, evt_data,
  1480. len - sizeof(*wmi))) {
  1481. wil_info(wil, "Unhandled event 0x%04x\n", id);
  1482. }
  1483. } else {
  1484. wil_err(wil, "Unknown event type\n");
  1485. print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1,
  1486. hdr, sizeof(*hdr) + len, true);
  1487. }
  1488. }
  1489. /*
  1490. * Retrieve next WMI event from the pending list
  1491. */
  1492. static struct list_head *next_wmi_ev(struct wil6210_priv *wil)
  1493. {
  1494. ulong flags;
  1495. struct list_head *ret = NULL;
  1496. spin_lock_irqsave(&wil->wmi_ev_lock, flags);
  1497. if (!list_empty(&wil->pending_wmi_ev)) {
  1498. ret = wil->pending_wmi_ev.next;
  1499. list_del(ret);
  1500. }
  1501. spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
  1502. return ret;
  1503. }
  1504. /*
  1505. * Handler for the WMI events
  1506. */
  1507. void wmi_event_worker(struct work_struct *work)
  1508. {
  1509. struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
  1510. wmi_event_worker);
  1511. struct pending_wmi_event *evt;
  1512. struct list_head *lh;
  1513. wil_dbg_wmi(wil, "Start %s\n", __func__);
  1514. while ((lh = next_wmi_ev(wil)) != NULL) {
  1515. evt = list_entry(lh, struct pending_wmi_event, list);
  1516. wmi_event_handle(wil, &evt->event.hdr);
  1517. kfree(evt);
  1518. }
  1519. wil_dbg_wmi(wil, "Finished %s\n", __func__);
  1520. }