wmi.c 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853
  1. /*
  2. * Copyright (c) 2012-2017 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, 0644);
  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, 0644);
  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, 0444);
  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 aid %d\n",
  439. evt->bssid, ch, evt->cid, evt->aid);
  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. if (test_bit(wil_status_resetting, wil->status) ||
  459. !test_bit(wil_status_fwready, wil->status)) {
  460. wil_err(wil, "status_resetting, cancel connect event, CID %d\n",
  461. evt->cid);
  462. /* no need for cleanup, wil_reset will do that */
  463. return;
  464. }
  465. mutex_lock(&wil->mutex);
  466. if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
  467. (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
  468. if (!test_bit(wil_status_fwconnecting, wil->status)) {
  469. wil_err(wil, "Not in connecting state\n");
  470. mutex_unlock(&wil->mutex);
  471. return;
  472. }
  473. del_timer_sync(&wil->connect_timer);
  474. } else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
  475. (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
  476. if (wil->sta[evt->cid].status != wil_sta_unused) {
  477. wil_err(wil, "AP: Invalid status %d for CID %d\n",
  478. wil->sta[evt->cid].status, evt->cid);
  479. mutex_unlock(&wil->mutex);
  480. return;
  481. }
  482. }
  483. /* FIXME FW can transmit only ucast frames to peer */
  484. /* FIXME real ring_id instead of hard coded 0 */
  485. ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid);
  486. wil->sta[evt->cid].status = wil_sta_conn_pending;
  487. rc = wil_tx_init(wil, evt->cid);
  488. if (rc) {
  489. wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n",
  490. evt->cid, rc);
  491. wmi_disconnect_sta(wil, wil->sta[evt->cid].addr,
  492. WLAN_REASON_UNSPECIFIED, false, false);
  493. } else {
  494. wil_info(wil, "successful connection to CID %d\n", evt->cid);
  495. }
  496. if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
  497. (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
  498. if (rc) {
  499. netif_carrier_off(ndev);
  500. wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
  501. wil_err(wil, "cfg80211_connect_result with failure\n");
  502. cfg80211_connect_result(ndev, evt->bssid, NULL, 0,
  503. NULL, 0,
  504. WLAN_STATUS_UNSPECIFIED_FAILURE,
  505. GFP_KERNEL);
  506. goto out;
  507. } else {
  508. struct wiphy *wiphy = wil_to_wiphy(wil);
  509. cfg80211_ref_bss(wiphy, wil->bss);
  510. cfg80211_connect_bss(ndev, evt->bssid, wil->bss,
  511. assoc_req_ie, assoc_req_ielen,
  512. assoc_resp_ie, assoc_resp_ielen,
  513. WLAN_STATUS_SUCCESS, GFP_KERNEL,
  514. NL80211_TIMEOUT_UNSPECIFIED);
  515. }
  516. wil->bss = NULL;
  517. } else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
  518. (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
  519. if (rc) {
  520. if (disable_ap_sme)
  521. /* notify new_sta has failed */
  522. cfg80211_del_sta(ndev, evt->bssid, GFP_KERNEL);
  523. goto out;
  524. }
  525. memset(&sinfo, 0, sizeof(sinfo));
  526. sinfo.generation = wil->sinfo_gen++;
  527. if (assoc_req_ie) {
  528. sinfo.assoc_req_ies = assoc_req_ie;
  529. sinfo.assoc_req_ies_len = assoc_req_ielen;
  530. }
  531. cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
  532. } else {
  533. wil_err(wil, "unhandled iftype %d for CID %d\n", wdev->iftype,
  534. evt->cid);
  535. goto out;
  536. }
  537. wil->sta[evt->cid].status = wil_sta_connected;
  538. wil->sta[evt->cid].aid = evt->aid;
  539. set_bit(wil_status_fwconnected, wil->status);
  540. wil_update_net_queues_bh(wil, NULL, false);
  541. out:
  542. if (rc)
  543. wil->sta[evt->cid].status = wil_sta_unused;
  544. clear_bit(wil_status_fwconnecting, wil->status);
  545. mutex_unlock(&wil->mutex);
  546. }
  547. static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
  548. void *d, int len)
  549. {
  550. struct wmi_disconnect_event *evt = d;
  551. u16 reason_code = le16_to_cpu(evt->protocol_reason_status);
  552. wil_info(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
  553. evt->bssid, reason_code, evt->disconnect_reason);
  554. wil->sinfo_gen++;
  555. if (test_bit(wil_status_resetting, wil->status) ||
  556. !test_bit(wil_status_fwready, wil->status)) {
  557. wil_err(wil, "status_resetting, cancel disconnect event\n");
  558. /* no need for cleanup, wil_reset will do that */
  559. return;
  560. }
  561. mutex_lock(&wil->mutex);
  562. wil6210_disconnect(wil, evt->bssid, reason_code, true);
  563. mutex_unlock(&wil->mutex);
  564. }
  565. /*
  566. * Firmware reports EAPOL frame using WME event.
  567. * Reconstruct Ethernet frame and deliver it via normal Rx
  568. */
  569. static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
  570. void *d, int len)
  571. {
  572. struct net_device *ndev = wil_to_ndev(wil);
  573. struct wmi_eapol_rx_event *evt = d;
  574. u16 eapol_len = le16_to_cpu(evt->eapol_len);
  575. int sz = eapol_len + ETH_HLEN;
  576. struct sk_buff *skb;
  577. struct ethhdr *eth;
  578. int cid;
  579. struct wil_net_stats *stats = NULL;
  580. wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len,
  581. evt->src_mac);
  582. cid = wil_find_cid(wil, evt->src_mac);
  583. if (cid >= 0)
  584. stats = &wil->sta[cid].stats;
  585. if (eapol_len > 196) { /* TODO: revisit size limit */
  586. wil_err(wil, "EAPOL too large\n");
  587. return;
  588. }
  589. skb = alloc_skb(sz, GFP_KERNEL);
  590. if (!skb) {
  591. wil_err(wil, "Failed to allocate skb\n");
  592. return;
  593. }
  594. eth = (struct ethhdr *)skb_put(skb, ETH_HLEN);
  595. ether_addr_copy(eth->h_dest, ndev->dev_addr);
  596. ether_addr_copy(eth->h_source, evt->src_mac);
  597. eth->h_proto = cpu_to_be16(ETH_P_PAE);
  598. memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len);
  599. skb->protocol = eth_type_trans(skb, ndev);
  600. if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) {
  601. ndev->stats.rx_packets++;
  602. ndev->stats.rx_bytes += sz;
  603. if (stats) {
  604. stats->rx_packets++;
  605. stats->rx_bytes += sz;
  606. }
  607. } else {
  608. ndev->stats.rx_dropped++;
  609. if (stats)
  610. stats->rx_dropped++;
  611. }
  612. }
  613. static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len)
  614. {
  615. struct wmi_vring_en_event *evt = d;
  616. u8 vri = evt->vring_index;
  617. struct wireless_dev *wdev = wil_to_wdev(wil);
  618. wil_dbg_wmi(wil, "Enable vring %d\n", vri);
  619. if (vri >= ARRAY_SIZE(wil->vring_tx)) {
  620. wil_err(wil, "Enable for invalid vring %d\n", vri);
  621. return;
  622. }
  623. if (wdev->iftype != NL80211_IFTYPE_AP || !disable_ap_sme)
  624. /* in AP mode with disable_ap_sme, this is done by
  625. * wil_cfg80211_change_station()
  626. */
  627. wil->vring_tx_data[vri].dot1x_open = true;
  628. if (vri == wil->bcast_vring) /* no BA for bcast */
  629. return;
  630. if (agg_wsize >= 0)
  631. wil_addba_tx_request(wil, vri, agg_wsize);
  632. }
  633. static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
  634. int len)
  635. {
  636. struct wmi_ba_status_event *evt = d;
  637. struct vring_tx_data *txdata;
  638. wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
  639. evt->ringid,
  640. evt->status == WMI_BA_AGREED ? "OK" : "N/A",
  641. evt->agg_wsize, __le16_to_cpu(evt->ba_timeout),
  642. evt->amsdu ? "+" : "-");
  643. if (evt->ringid >= WIL6210_MAX_TX_RINGS) {
  644. wil_err(wil, "invalid ring id %d\n", evt->ringid);
  645. return;
  646. }
  647. if (evt->status != WMI_BA_AGREED) {
  648. evt->ba_timeout = 0;
  649. evt->agg_wsize = 0;
  650. evt->amsdu = 0;
  651. }
  652. txdata = &wil->vring_tx_data[evt->ringid];
  653. txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
  654. txdata->agg_wsize = evt->agg_wsize;
  655. txdata->agg_amsdu = evt->amsdu;
  656. txdata->addba_in_progress = false;
  657. }
  658. static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d,
  659. int len)
  660. {
  661. struct wmi_rcp_addba_req_event *evt = d;
  662. wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token,
  663. evt->ba_param_set, evt->ba_timeout,
  664. evt->ba_seq_ctrl);
  665. }
  666. static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
  667. __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
  668. {
  669. struct wmi_delba_event *evt = d;
  670. u8 cid, tid;
  671. u16 reason = __le16_to_cpu(evt->reason);
  672. struct wil_sta_info *sta;
  673. struct wil_tid_ampdu_rx *r;
  674. might_sleep();
  675. parse_cidxtid(evt->cidxtid, &cid, &tid);
  676. wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n",
  677. cid, tid,
  678. evt->from_initiator ? "originator" : "recipient",
  679. reason);
  680. if (!evt->from_initiator) {
  681. int i;
  682. /* find Tx vring it belongs to */
  683. for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
  684. if ((wil->vring2cid_tid[i][0] == cid) &&
  685. (wil->vring2cid_tid[i][1] == tid)) {
  686. struct vring_tx_data *txdata =
  687. &wil->vring_tx_data[i];
  688. wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
  689. txdata->agg_timeout = 0;
  690. txdata->agg_wsize = 0;
  691. txdata->addba_in_progress = false;
  692. break; /* max. 1 matching ring */
  693. }
  694. }
  695. if (i >= ARRAY_SIZE(wil->vring2cid_tid))
  696. wil_err(wil, "DELBA: unable to find Tx vring\n");
  697. return;
  698. }
  699. sta = &wil->sta[cid];
  700. spin_lock_bh(&sta->tid_rx_lock);
  701. r = sta->tid_rx[tid];
  702. sta->tid_rx[tid] = NULL;
  703. wil_tid_ampdu_rx_free(wil, r);
  704. spin_unlock_bh(&sta->tid_rx_lock);
  705. }
  706. /**
  707. * Some events are ignored for purpose; and need not be interpreted as
  708. * "unhandled events"
  709. */
  710. static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len)
  711. {
  712. wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len);
  713. }
  714. static const struct {
  715. int eventid;
  716. void (*handler)(struct wil6210_priv *wil, int eventid,
  717. void *data, int data_len);
  718. } wmi_evt_handlers[] = {
  719. {WMI_READY_EVENTID, wmi_evt_ready},
  720. {WMI_FW_READY_EVENTID, wmi_evt_ignore},
  721. {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt},
  722. {WMI_TX_MGMT_PACKET_EVENTID, wmi_evt_tx_mgmt},
  723. {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete},
  724. {WMI_CONNECT_EVENTID, wmi_evt_connect},
  725. {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect},
  726. {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx},
  727. {WMI_BA_STATUS_EVENTID, wmi_evt_ba_status},
  728. {WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req},
  729. {WMI_DELBA_EVENTID, wmi_evt_delba},
  730. {WMI_VRING_EN_EVENTID, wmi_evt_vring_en},
  731. {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore},
  732. };
  733. /*
  734. * Run in IRQ context
  735. * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
  736. * that will be eventually handled by the @wmi_event_worker in the thread
  737. * context of thread "wil6210_wmi"
  738. */
  739. void wmi_recv_cmd(struct wil6210_priv *wil)
  740. {
  741. struct wil6210_mbox_ring_desc d_tail;
  742. struct wil6210_mbox_hdr hdr;
  743. struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
  744. struct pending_wmi_event *evt;
  745. u8 *cmd;
  746. void __iomem *src;
  747. ulong flags;
  748. unsigned n;
  749. unsigned int num_immed_reply = 0;
  750. if (!test_bit(wil_status_mbox_ready, wil->status)) {
  751. wil_err(wil, "Reset in progress. Cannot handle WMI event\n");
  752. return;
  753. }
  754. for (n = 0;; n++) {
  755. u16 len;
  756. bool q;
  757. bool immed_reply = false;
  758. r->head = wil_r(wil, RGF_MBOX +
  759. offsetof(struct wil6210_mbox_ctl, rx.head));
  760. if (r->tail == r->head)
  761. break;
  762. wil_dbg_wmi(wil, "Mbox head %08x tail %08x\n",
  763. r->head, r->tail);
  764. /* read cmd descriptor from tail */
  765. wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail),
  766. sizeof(struct wil6210_mbox_ring_desc));
  767. if (d_tail.sync == 0) {
  768. wil_err(wil, "Mbox evt not owned by FW?\n");
  769. break;
  770. }
  771. /* read cmd header from descriptor */
  772. if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
  773. wil_err(wil, "Mbox evt at 0x%08x?\n",
  774. le32_to_cpu(d_tail.addr));
  775. break;
  776. }
  777. len = le16_to_cpu(hdr.len);
  778. wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
  779. le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
  780. hdr.flags);
  781. /* read cmd buffer from descriptor */
  782. src = wmi_buffer(wil, d_tail.addr) +
  783. sizeof(struct wil6210_mbox_hdr);
  784. evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event,
  785. event.wmi) + len, 4),
  786. GFP_KERNEL);
  787. if (!evt)
  788. break;
  789. evt->event.hdr = hdr;
  790. cmd = (void *)&evt->event.wmi;
  791. wil_memcpy_fromio_32(cmd, src, len);
  792. /* mark entry as empty */
  793. wil_w(wil, r->tail +
  794. offsetof(struct wil6210_mbox_ring_desc, sync), 0);
  795. /* indicate */
  796. if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
  797. (len >= sizeof(struct wmi_cmd_hdr))) {
  798. struct wmi_cmd_hdr *wmi = &evt->event.wmi;
  799. u16 id = le16_to_cpu(wmi->command_id);
  800. u32 tstamp = le32_to_cpu(wmi->fw_timestamp);
  801. spin_lock_irqsave(&wil->wmi_ev_lock, flags);
  802. if (wil->reply_id && wil->reply_id == id) {
  803. if (wil->reply_buf) {
  804. memcpy(wil->reply_buf, wmi,
  805. min(len, wil->reply_size));
  806. immed_reply = true;
  807. }
  808. }
  809. spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
  810. wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n",
  811. id, wmi->mid, tstamp);
  812. trace_wil6210_wmi_event(wmi, &wmi[1],
  813. len - sizeof(*wmi));
  814. }
  815. wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET, 16, 1,
  816. &evt->event.hdr, sizeof(hdr) + len, true);
  817. /* advance tail */
  818. r->tail = r->base + ((r->tail - r->base +
  819. sizeof(struct wil6210_mbox_ring_desc)) % r->size);
  820. wil_w(wil, RGF_MBOX +
  821. offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail);
  822. if (immed_reply) {
  823. wil_dbg_wmi(wil, "recv_cmd: Complete WMI 0x%04x\n",
  824. wil->reply_id);
  825. kfree(evt);
  826. num_immed_reply++;
  827. complete(&wil->wmi_call);
  828. } else {
  829. /* add to the pending list */
  830. spin_lock_irqsave(&wil->wmi_ev_lock, flags);
  831. list_add_tail(&evt->list, &wil->pending_wmi_ev);
  832. spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
  833. q = queue_work(wil->wmi_wq, &wil->wmi_event_worker);
  834. wil_dbg_wmi(wil, "queue_work -> %d\n", q);
  835. }
  836. }
  837. /* normally, 1 event per IRQ should be processed */
  838. wil_dbg_wmi(wil, "recv_cmd: -> %d events queued, %d completed\n",
  839. n - num_immed_reply, num_immed_reply);
  840. }
  841. int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
  842. u16 reply_id, void *reply, u8 reply_size, int to_msec)
  843. {
  844. int rc;
  845. unsigned long remain;
  846. mutex_lock(&wil->wmi_mutex);
  847. spin_lock(&wil->wmi_ev_lock);
  848. wil->reply_id = reply_id;
  849. wil->reply_buf = reply;
  850. wil->reply_size = reply_size;
  851. reinit_completion(&wil->wmi_call);
  852. spin_unlock(&wil->wmi_ev_lock);
  853. rc = __wmi_send(wil, cmdid, buf, len);
  854. if (rc)
  855. goto out;
  856. remain = wait_for_completion_timeout(&wil->wmi_call,
  857. msecs_to_jiffies(to_msec));
  858. if (0 == remain) {
  859. wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n",
  860. cmdid, reply_id, to_msec);
  861. rc = -ETIME;
  862. } else {
  863. wil_dbg_wmi(wil,
  864. "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
  865. cmdid, reply_id,
  866. to_msec - jiffies_to_msecs(remain));
  867. }
  868. out:
  869. spin_lock(&wil->wmi_ev_lock);
  870. wil->reply_id = 0;
  871. wil->reply_buf = NULL;
  872. wil->reply_size = 0;
  873. spin_unlock(&wil->wmi_ev_lock);
  874. mutex_unlock(&wil->wmi_mutex);
  875. return rc;
  876. }
  877. int wmi_echo(struct wil6210_priv *wil)
  878. {
  879. struct wmi_echo_cmd cmd = {
  880. .value = cpu_to_le32(0x12345678),
  881. };
  882. return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd),
  883. WMI_ECHO_RSP_EVENTID, NULL, 0, 50);
  884. }
  885. int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
  886. {
  887. struct wmi_set_mac_address_cmd cmd;
  888. ether_addr_copy(cmd.mac, addr);
  889. wil_dbg_wmi(wil, "Set MAC %pM\n", addr);
  890. return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
  891. }
  892. int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
  893. {
  894. int rc = 0;
  895. struct wmi_led_cfg_cmd cmd = {
  896. .led_mode = enable,
  897. .id = led_id,
  898. .slow_blink_cfg.blink_on =
  899. cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].on_ms),
  900. .slow_blink_cfg.blink_off =
  901. cpu_to_le32(led_blink_time[WIL_LED_TIME_SLOW].off_ms),
  902. .medium_blink_cfg.blink_on =
  903. cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].on_ms),
  904. .medium_blink_cfg.blink_off =
  905. cpu_to_le32(led_blink_time[WIL_LED_TIME_MED].off_ms),
  906. .fast_blink_cfg.blink_on =
  907. cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].on_ms),
  908. .fast_blink_cfg.blink_off =
  909. cpu_to_le32(led_blink_time[WIL_LED_TIME_FAST].off_ms),
  910. .led_polarity = led_polarity,
  911. };
  912. struct {
  913. struct wmi_cmd_hdr wmi;
  914. struct wmi_led_cfg_done_event evt;
  915. } __packed reply;
  916. if (led_id == WIL_LED_INVALID_ID)
  917. goto out;
  918. if (led_id > WIL_LED_MAX_ID) {
  919. wil_err(wil, "Invalid led id %d\n", led_id);
  920. rc = -EINVAL;
  921. goto out;
  922. }
  923. wil_dbg_wmi(wil,
  924. "%s led %d\n",
  925. enable ? "enabling" : "disabling", led_id);
  926. rc = wmi_call(wil, WMI_LED_CFG_CMDID, &cmd, sizeof(cmd),
  927. WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply),
  928. 100);
  929. if (rc)
  930. goto out;
  931. if (reply.evt.status) {
  932. wil_err(wil, "led %d cfg failed with status %d\n",
  933. led_id, le32_to_cpu(reply.evt.status));
  934. rc = -EINVAL;
  935. }
  936. out:
  937. return rc;
  938. }
  939. int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
  940. u8 chan, u8 hidden_ssid, u8 is_go)
  941. {
  942. int rc;
  943. struct wmi_pcp_start_cmd cmd = {
  944. .bcon_interval = cpu_to_le16(bi),
  945. .network_type = wmi_nettype,
  946. .disable_sec_offload = 1,
  947. .channel = chan - 1,
  948. .pcp_max_assoc_sta = max_assoc_sta,
  949. .hidden_ssid = hidden_ssid,
  950. .is_go = is_go,
  951. .disable_ap_sme = disable_ap_sme,
  952. .abft_len = wil->abft_len,
  953. };
  954. struct {
  955. struct wmi_cmd_hdr wmi;
  956. struct wmi_pcp_started_event evt;
  957. } __packed reply;
  958. if (!wil->privacy)
  959. cmd.disable_sec = 1;
  960. if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
  961. (cmd.pcp_max_assoc_sta <= 0)) {
  962. wil_info(wil,
  963. "Requested connection limit %u, valid values are 1 - %d. Setting to %d\n",
  964. max_assoc_sta, WIL6210_MAX_CID, WIL6210_MAX_CID);
  965. cmd.pcp_max_assoc_sta = WIL6210_MAX_CID;
  966. }
  967. if (disable_ap_sme &&
  968. !test_bit(WMI_FW_CAPABILITY_DISABLE_AP_SME,
  969. wil->fw_capabilities)) {
  970. wil_err(wil, "disable_ap_sme not supported by FW\n");
  971. return -EOPNOTSUPP;
  972. }
  973. /*
  974. * Processing time may be huge, in case of secure AP it takes about
  975. * 3500ms for FW to start AP
  976. */
  977. rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd),
  978. WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000);
  979. if (rc)
  980. return rc;
  981. if (reply.evt.status != WMI_FW_STATUS_SUCCESS)
  982. rc = -EINVAL;
  983. if (wmi_nettype != WMI_NETTYPE_P2P)
  984. /* Don't fail due to error in the led configuration */
  985. wmi_led_cfg(wil, true);
  986. return rc;
  987. }
  988. int wmi_pcp_stop(struct wil6210_priv *wil)
  989. {
  990. int rc;
  991. rc = wmi_led_cfg(wil, false);
  992. if (rc)
  993. return rc;
  994. return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0,
  995. WMI_PCP_STOPPED_EVENTID, NULL, 0, 20);
  996. }
  997. int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid)
  998. {
  999. struct wmi_set_ssid_cmd cmd = {
  1000. .ssid_len = cpu_to_le32(ssid_len),
  1001. };
  1002. if (ssid_len > sizeof(cmd.ssid))
  1003. return -EINVAL;
  1004. memcpy(cmd.ssid, ssid, ssid_len);
  1005. return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd));
  1006. }
  1007. int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
  1008. {
  1009. int rc;
  1010. struct {
  1011. struct wmi_cmd_hdr wmi;
  1012. struct wmi_set_ssid_cmd cmd;
  1013. } __packed reply;
  1014. int len; /* reply.cmd.ssid_len in CPU order */
  1015. rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID,
  1016. &reply, sizeof(reply), 20);
  1017. if (rc)
  1018. return rc;
  1019. len = le32_to_cpu(reply.cmd.ssid_len);
  1020. if (len > sizeof(reply.cmd.ssid))
  1021. return -EINVAL;
  1022. *ssid_len = len;
  1023. memcpy(ssid, reply.cmd.ssid, len);
  1024. return 0;
  1025. }
  1026. int wmi_set_channel(struct wil6210_priv *wil, int channel)
  1027. {
  1028. struct wmi_set_pcp_channel_cmd cmd = {
  1029. .channel = channel - 1,
  1030. };
  1031. return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd));
  1032. }
  1033. int wmi_get_channel(struct wil6210_priv *wil, int *channel)
  1034. {
  1035. int rc;
  1036. struct {
  1037. struct wmi_cmd_hdr wmi;
  1038. struct wmi_set_pcp_channel_cmd cmd;
  1039. } __packed reply;
  1040. rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0,
  1041. WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20);
  1042. if (rc)
  1043. return rc;
  1044. if (reply.cmd.channel > 3)
  1045. return -EINVAL;
  1046. *channel = reply.cmd.channel + 1;
  1047. return 0;
  1048. }
  1049. int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi)
  1050. {
  1051. int rc;
  1052. struct wmi_p2p_cfg_cmd cmd = {
  1053. .discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER,
  1054. .bcon_interval = cpu_to_le16(bi),
  1055. .channel = channel - 1,
  1056. };
  1057. struct {
  1058. struct wmi_cmd_hdr wmi;
  1059. struct wmi_p2p_cfg_done_event evt;
  1060. } __packed reply;
  1061. wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n");
  1062. rc = wmi_call(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd),
  1063. WMI_P2P_CFG_DONE_EVENTID, &reply, sizeof(reply), 300);
  1064. if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
  1065. wil_err(wil, "P2P_CFG failed. status %d\n", reply.evt.status);
  1066. rc = -EINVAL;
  1067. }
  1068. return rc;
  1069. }
  1070. int wmi_start_listen(struct wil6210_priv *wil)
  1071. {
  1072. int rc;
  1073. struct {
  1074. struct wmi_cmd_hdr wmi;
  1075. struct wmi_listen_started_event evt;
  1076. } __packed reply;
  1077. wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n");
  1078. rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
  1079. WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 300);
  1080. if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
  1081. wil_err(wil, "device failed to start listen. status %d\n",
  1082. reply.evt.status);
  1083. rc = -EINVAL;
  1084. }
  1085. return rc;
  1086. }
  1087. int wmi_start_search(struct wil6210_priv *wil)
  1088. {
  1089. int rc;
  1090. struct {
  1091. struct wmi_cmd_hdr wmi;
  1092. struct wmi_search_started_event evt;
  1093. } __packed reply;
  1094. wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n");
  1095. rc = wmi_call(wil, WMI_START_SEARCH_CMDID, NULL, 0,
  1096. WMI_SEARCH_STARTED_EVENTID, &reply, sizeof(reply), 300);
  1097. if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
  1098. wil_err(wil, "device failed to start search. status %d\n",
  1099. reply.evt.status);
  1100. rc = -EINVAL;
  1101. }
  1102. return rc;
  1103. }
  1104. int wmi_stop_discovery(struct wil6210_priv *wil)
  1105. {
  1106. int rc;
  1107. wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n");
  1108. rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
  1109. WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100);
  1110. if (rc)
  1111. wil_err(wil, "Failed to stop discovery\n");
  1112. return rc;
  1113. }
  1114. int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
  1115. const void *mac_addr, int key_usage)
  1116. {
  1117. struct wmi_delete_cipher_key_cmd cmd = {
  1118. .key_index = key_index,
  1119. };
  1120. if (mac_addr)
  1121. memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
  1122. return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
  1123. }
  1124. int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
  1125. const void *mac_addr, int key_len, const void *key,
  1126. int key_usage)
  1127. {
  1128. struct wmi_add_cipher_key_cmd cmd = {
  1129. .key_index = key_index,
  1130. .key_usage = key_usage,
  1131. .key_len = key_len,
  1132. };
  1133. if (!key || (key_len > sizeof(cmd.key)))
  1134. return -EINVAL;
  1135. memcpy(cmd.key, key, key_len);
  1136. if (mac_addr)
  1137. memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
  1138. return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
  1139. }
  1140. int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
  1141. {
  1142. static const char *const names[] = {
  1143. [WMI_FRAME_BEACON] = "BEACON",
  1144. [WMI_FRAME_PROBE_REQ] = "PROBE_REQ",
  1145. [WMI_FRAME_PROBE_RESP] = "WMI_FRAME_PROBE_RESP",
  1146. [WMI_FRAME_ASSOC_REQ] = "WMI_FRAME_ASSOC_REQ",
  1147. [WMI_FRAME_ASSOC_RESP] = "WMI_FRAME_ASSOC_RESP",
  1148. };
  1149. int rc;
  1150. u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
  1151. struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL);
  1152. if (!cmd) {
  1153. rc = -ENOMEM;
  1154. goto out;
  1155. }
  1156. if (!ie)
  1157. ie_len = 0;
  1158. cmd->mgmt_frm_type = type;
  1159. /* BUG: FW API define ieLen as u8. Will fix FW */
  1160. cmd->ie_len = cpu_to_le16(ie_len);
  1161. memcpy(cmd->ie_info, ie, ie_len);
  1162. rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len);
  1163. kfree(cmd);
  1164. out:
  1165. if (rc) {
  1166. const char *name = type < ARRAY_SIZE(names) ?
  1167. names[type] : "??";
  1168. wil_err(wil, "set_ie(%d %s) failed : %d\n", type, name, rc);
  1169. }
  1170. return rc;
  1171. }
  1172. /**
  1173. * wmi_rxon - turn radio on/off
  1174. * @on: turn on if true, off otherwise
  1175. *
  1176. * Only switch radio. Channel should be set separately.
  1177. * No timeout for rxon - radio turned on forever unless some other call
  1178. * turns it off
  1179. */
  1180. int wmi_rxon(struct wil6210_priv *wil, bool on)
  1181. {
  1182. int rc;
  1183. struct {
  1184. struct wmi_cmd_hdr wmi;
  1185. struct wmi_listen_started_event evt;
  1186. } __packed reply;
  1187. wil_info(wil, "(%s)\n", on ? "on" : "off");
  1188. if (on) {
  1189. rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
  1190. WMI_LISTEN_STARTED_EVENTID,
  1191. &reply, sizeof(reply), 100);
  1192. if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
  1193. rc = -EINVAL;
  1194. } else {
  1195. rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
  1196. WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20);
  1197. }
  1198. return rc;
  1199. }
  1200. int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
  1201. {
  1202. struct wireless_dev *wdev = wil->wdev;
  1203. struct net_device *ndev = wil_to_ndev(wil);
  1204. struct wmi_cfg_rx_chain_cmd cmd = {
  1205. .action = WMI_RX_CHAIN_ADD,
  1206. .rx_sw_ring = {
  1207. .max_mpdu_size = cpu_to_le16(
  1208. wil_mtu2macbuf(wil->rx_buf_len)),
  1209. .ring_mem_base = cpu_to_le64(vring->pa),
  1210. .ring_size = cpu_to_le16(vring->size),
  1211. },
  1212. .mid = 0, /* TODO - what is it? */
  1213. .decap_trans_type = WMI_DECAP_TYPE_802_3,
  1214. .reorder_type = WMI_RX_SW_REORDER,
  1215. .host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh),
  1216. };
  1217. struct {
  1218. struct wmi_cmd_hdr wmi;
  1219. struct wmi_cfg_rx_chain_done_event evt;
  1220. } __packed evt;
  1221. int rc;
  1222. if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
  1223. struct ieee80211_channel *ch = wdev->preset_chandef.chan;
  1224. cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
  1225. if (ch)
  1226. cmd.sniffer_cfg.channel = ch->hw_value - 1;
  1227. cmd.sniffer_cfg.phy_info_mode =
  1228. cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
  1229. cmd.sniffer_cfg.phy_support =
  1230. cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
  1231. ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS);
  1232. } else {
  1233. /* Initialize offload (in non-sniffer mode).
  1234. * Linux IP stack always calculates IP checksum
  1235. * HW always calculate TCP/UDP checksum
  1236. */
  1237. cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS);
  1238. }
  1239. if (rx_align_2)
  1240. cmd.l2_802_3_offload_ctrl |=
  1241. L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK;
  1242. /* typical time for secure PCP is 840ms */
  1243. rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
  1244. WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
  1245. if (rc)
  1246. return rc;
  1247. vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
  1248. wil_dbg_misc(wil, "Rx init: status %d tail 0x%08x\n",
  1249. le32_to_cpu(evt.evt.status), vring->hwtail);
  1250. if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS)
  1251. rc = -EINVAL;
  1252. return rc;
  1253. }
  1254. int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
  1255. {
  1256. int rc;
  1257. struct wmi_temp_sense_cmd cmd = {
  1258. .measure_baseband_en = cpu_to_le32(!!t_bb),
  1259. .measure_rf_en = cpu_to_le32(!!t_rf),
  1260. .measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW),
  1261. };
  1262. struct {
  1263. struct wmi_cmd_hdr wmi;
  1264. struct wmi_temp_sense_done_event evt;
  1265. } __packed reply;
  1266. rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd),
  1267. WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100);
  1268. if (rc)
  1269. return rc;
  1270. if (t_bb)
  1271. *t_bb = le32_to_cpu(reply.evt.baseband_t1000);
  1272. if (t_rf)
  1273. *t_rf = le32_to_cpu(reply.evt.rf_t1000);
  1274. return 0;
  1275. }
  1276. int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac,
  1277. u16 reason, bool full_disconnect, bool del_sta)
  1278. {
  1279. int rc;
  1280. u16 reason_code;
  1281. struct wmi_disconnect_sta_cmd disc_sta_cmd = {
  1282. .disconnect_reason = cpu_to_le16(reason),
  1283. };
  1284. struct wmi_del_sta_cmd del_sta_cmd = {
  1285. .disconnect_reason = cpu_to_le16(reason),
  1286. };
  1287. struct {
  1288. struct wmi_cmd_hdr wmi;
  1289. struct wmi_disconnect_event evt;
  1290. } __packed reply;
  1291. wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason);
  1292. wil->locally_generated_disc = true;
  1293. if (del_sta) {
  1294. ether_addr_copy(del_sta_cmd.dst_mac, mac);
  1295. rc = wmi_call(wil, WMI_DEL_STA_CMDID, &del_sta_cmd,
  1296. sizeof(del_sta_cmd), WMI_DISCONNECT_EVENTID,
  1297. &reply, sizeof(reply), 1000);
  1298. } else {
  1299. ether_addr_copy(disc_sta_cmd.dst_mac, mac);
  1300. rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &disc_sta_cmd,
  1301. sizeof(disc_sta_cmd), WMI_DISCONNECT_EVENTID,
  1302. &reply, sizeof(reply), 1000);
  1303. }
  1304. /* failure to disconnect in reasonable time treated as FW error */
  1305. if (rc) {
  1306. wil_fw_error_recovery(wil);
  1307. return rc;
  1308. }
  1309. if (full_disconnect) {
  1310. /* call event handler manually after processing wmi_call,
  1311. * to avoid deadlock - disconnect event handler acquires
  1312. * wil->mutex while it is already held here
  1313. */
  1314. reason_code = le16_to_cpu(reply.evt.protocol_reason_status);
  1315. wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
  1316. reply.evt.bssid, reason_code,
  1317. reply.evt.disconnect_reason);
  1318. wil->sinfo_gen++;
  1319. wil6210_disconnect(wil, reply.evt.bssid, reason_code, true);
  1320. }
  1321. return 0;
  1322. }
  1323. int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout)
  1324. {
  1325. struct wmi_vring_ba_en_cmd cmd = {
  1326. .ringid = ringid,
  1327. .agg_max_wsize = size,
  1328. .ba_timeout = cpu_to_le16(timeout),
  1329. .amsdu = 0,
  1330. };
  1331. wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d)\n", ringid, size,
  1332. timeout);
  1333. return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd));
  1334. }
  1335. int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason)
  1336. {
  1337. struct wmi_vring_ba_dis_cmd cmd = {
  1338. .ringid = ringid,
  1339. .reason = cpu_to_le16(reason),
  1340. };
  1341. wil_dbg_wmi(wil, "delba_tx: (ring %d reason %d)\n", ringid, reason);
  1342. return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd));
  1343. }
  1344. int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason)
  1345. {
  1346. struct wmi_rcp_delba_cmd cmd = {
  1347. .cidxtid = cidxtid,
  1348. .reason = cpu_to_le16(reason),
  1349. };
  1350. wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf,
  1351. (cidxtid >> 4) & 0xf, reason);
  1352. return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd));
  1353. }
  1354. int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
  1355. u16 status, bool amsdu, u16 agg_wsize, u16 timeout)
  1356. {
  1357. int rc;
  1358. struct wmi_rcp_addba_resp_cmd cmd = {
  1359. .cidxtid = mk_cidxtid(cid, tid),
  1360. .dialog_token = token,
  1361. .status_code = cpu_to_le16(status),
  1362. /* bit 0: A-MSDU supported
  1363. * bit 1: policy (should be 0 for us)
  1364. * bits 2..5: TID
  1365. * bits 6..15: buffer size
  1366. */
  1367. .ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) |
  1368. (agg_wsize << 6)),
  1369. .ba_timeout = cpu_to_le16(timeout),
  1370. };
  1371. struct {
  1372. struct wmi_cmd_hdr wmi;
  1373. struct wmi_rcp_addba_resp_sent_event evt;
  1374. } __packed reply;
  1375. wil_dbg_wmi(wil,
  1376. "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
  1377. cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-");
  1378. rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd),
  1379. WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply),
  1380. 100);
  1381. if (rc)
  1382. return rc;
  1383. if (reply.evt.status) {
  1384. wil_err(wil, "ADDBA response failed with status %d\n",
  1385. le16_to_cpu(reply.evt.status));
  1386. rc = -EINVAL;
  1387. }
  1388. return rc;
  1389. }
  1390. int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
  1391. enum wmi_ps_profile_type ps_profile)
  1392. {
  1393. int rc;
  1394. struct wmi_ps_dev_profile_cfg_cmd cmd = {
  1395. .ps_profile = ps_profile,
  1396. };
  1397. struct {
  1398. struct wmi_cmd_hdr wmi;
  1399. struct wmi_ps_dev_profile_cfg_event evt;
  1400. } __packed reply;
  1401. u32 status;
  1402. wil_dbg_wmi(wil, "Setting ps dev profile %d\n", ps_profile);
  1403. reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR);
  1404. rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, &cmd, sizeof(cmd),
  1405. WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply),
  1406. 100);
  1407. if (rc)
  1408. return rc;
  1409. status = le32_to_cpu(reply.evt.status);
  1410. if (status != WMI_PS_CFG_CMD_STATUS_SUCCESS) {
  1411. wil_err(wil, "ps dev profile cfg failed with status %d\n",
  1412. status);
  1413. rc = -EINVAL;
  1414. }
  1415. return rc;
  1416. }
  1417. int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short)
  1418. {
  1419. int rc;
  1420. struct wmi_set_mgmt_retry_limit_cmd cmd = {
  1421. .mgmt_retry_limit = retry_short,
  1422. };
  1423. struct {
  1424. struct wmi_cmd_hdr wmi;
  1425. struct wmi_set_mgmt_retry_limit_event evt;
  1426. } __packed reply;
  1427. wil_dbg_wmi(wil, "Setting mgmt retry short %d\n", retry_short);
  1428. if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
  1429. return -ENOTSUPP;
  1430. reply.evt.status = WMI_FW_STATUS_FAILURE;
  1431. rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, &cmd, sizeof(cmd),
  1432. WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
  1433. 100);
  1434. if (rc)
  1435. return rc;
  1436. if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
  1437. wil_err(wil, "set mgmt retry limit failed with status %d\n",
  1438. reply.evt.status);
  1439. rc = -EINVAL;
  1440. }
  1441. return rc;
  1442. }
  1443. int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short)
  1444. {
  1445. int rc;
  1446. struct {
  1447. struct wmi_cmd_hdr wmi;
  1448. struct wmi_get_mgmt_retry_limit_event evt;
  1449. } __packed reply;
  1450. wil_dbg_wmi(wil, "getting mgmt retry short\n");
  1451. if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities))
  1452. return -ENOTSUPP;
  1453. reply.evt.mgmt_retry_limit = 0;
  1454. rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, NULL, 0,
  1455. WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
  1456. 100);
  1457. if (rc)
  1458. return rc;
  1459. if (retry_short)
  1460. *retry_short = reply.evt.mgmt_retry_limit;
  1461. return 0;
  1462. }
  1463. int wmi_abort_scan(struct wil6210_priv *wil)
  1464. {
  1465. int rc;
  1466. wil_dbg_wmi(wil, "sending WMI_ABORT_SCAN_CMDID\n");
  1467. rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, NULL, 0);
  1468. if (rc)
  1469. wil_err(wil, "Failed to abort scan (%d)\n", rc);
  1470. return rc;
  1471. }
  1472. int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid)
  1473. {
  1474. int rc;
  1475. struct wmi_new_sta_cmd cmd = {
  1476. .aid = aid,
  1477. };
  1478. wil_dbg_wmi(wil, "new sta %pM, aid %d\n", mac, aid);
  1479. ether_addr_copy(cmd.dst_mac, mac);
  1480. rc = wmi_send(wil, WMI_NEW_STA_CMDID, &cmd, sizeof(cmd));
  1481. if (rc)
  1482. wil_err(wil, "Failed to send new sta (%d)\n", rc);
  1483. return rc;
  1484. }
  1485. void wmi_event_flush(struct wil6210_priv *wil)
  1486. {
  1487. ulong flags;
  1488. struct pending_wmi_event *evt, *t;
  1489. wil_dbg_wmi(wil, "event_flush\n");
  1490. spin_lock_irqsave(&wil->wmi_ev_lock, flags);
  1491. list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
  1492. list_del(&evt->list);
  1493. kfree(evt);
  1494. }
  1495. spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
  1496. }
  1497. static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
  1498. void *d, int len)
  1499. {
  1500. uint i;
  1501. for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) {
  1502. if (wmi_evt_handlers[i].eventid == id) {
  1503. wmi_evt_handlers[i].handler(wil, id, d, len);
  1504. return true;
  1505. }
  1506. }
  1507. return false;
  1508. }
  1509. static void wmi_event_handle(struct wil6210_priv *wil,
  1510. struct wil6210_mbox_hdr *hdr)
  1511. {
  1512. u16 len = le16_to_cpu(hdr->len);
  1513. if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
  1514. (len >= sizeof(struct wmi_cmd_hdr))) {
  1515. struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]);
  1516. void *evt_data = (void *)(&wmi[1]);
  1517. u16 id = le16_to_cpu(wmi->command_id);
  1518. wil_dbg_wmi(wil, "Handle WMI 0x%04x (reply_id 0x%04x)\n",
  1519. id, wil->reply_id);
  1520. /* check if someone waits for this event */
  1521. if (wil->reply_id && wil->reply_id == id) {
  1522. WARN_ON(wil->reply_buf);
  1523. wmi_evt_call_handler(wil, id, evt_data,
  1524. len - sizeof(*wmi));
  1525. wil_dbg_wmi(wil, "event_handle: Complete WMI 0x%04x\n",
  1526. id);
  1527. complete(&wil->wmi_call);
  1528. return;
  1529. }
  1530. /* unsolicited event */
  1531. /* search for handler */
  1532. if (!wmi_evt_call_handler(wil, id, evt_data,
  1533. len - sizeof(*wmi))) {
  1534. wil_info(wil, "Unhandled event 0x%04x\n", id);
  1535. }
  1536. } else {
  1537. wil_err(wil, "Unknown event type\n");
  1538. print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1,
  1539. hdr, sizeof(*hdr) + len, true);
  1540. }
  1541. }
  1542. /*
  1543. * Retrieve next WMI event from the pending list
  1544. */
  1545. static struct list_head *next_wmi_ev(struct wil6210_priv *wil)
  1546. {
  1547. ulong flags;
  1548. struct list_head *ret = NULL;
  1549. spin_lock_irqsave(&wil->wmi_ev_lock, flags);
  1550. if (!list_empty(&wil->pending_wmi_ev)) {
  1551. ret = wil->pending_wmi_ev.next;
  1552. list_del(ret);
  1553. }
  1554. spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
  1555. return ret;
  1556. }
  1557. /*
  1558. * Handler for the WMI events
  1559. */
  1560. void wmi_event_worker(struct work_struct *work)
  1561. {
  1562. struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
  1563. wmi_event_worker);
  1564. struct pending_wmi_event *evt;
  1565. struct list_head *lh;
  1566. wil_dbg_wmi(wil, "event_worker: Start\n");
  1567. while ((lh = next_wmi_ev(wil)) != NULL) {
  1568. evt = list_entry(lh, struct pending_wmi_event, list);
  1569. wmi_event_handle(wil, &evt->event.hdr);
  1570. kfree(evt);
  1571. }
  1572. wil_dbg_wmi(wil, "event_worker: Finished\n");
  1573. }