smd.c 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126
  1. /*
  2. * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
  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 ANY
  11. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  17. #include <linux/etherdevice.h>
  18. #include <linux/firmware.h>
  19. #include <linux/bitops.h>
  20. #include "smd.h"
  21. static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
  22. {
  23. struct wcn36xx_hal_cfg *entry;
  24. u32 *val;
  25. if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) {
  26. wcn36xx_err("Not enough room for TLV entry\n");
  27. return -ENOMEM;
  28. }
  29. entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len);
  30. entry->id = id;
  31. entry->len = sizeof(u32);
  32. entry->pad_bytes = 0;
  33. entry->reserve = 0;
  34. val = (u32 *) (entry + 1);
  35. *val = value;
  36. *len += sizeof(*entry) + sizeof(u32);
  37. return 0;
  38. }
  39. static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn,
  40. struct ieee80211_sta *sta,
  41. struct wcn36xx_hal_config_bss_params *bss_params)
  42. {
  43. if (IEEE80211_BAND_5GHZ == WCN36XX_BAND(wcn))
  44. bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE;
  45. else if (sta && sta->ht_cap.ht_supported)
  46. bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE;
  47. else if (sta && (sta->supp_rates[IEEE80211_BAND_2GHZ] & 0x7f))
  48. bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE;
  49. else
  50. bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE;
  51. }
  52. static inline u8 is_cap_supported(unsigned long caps, unsigned long flag)
  53. {
  54. return caps & flag ? 1 : 0;
  55. }
  56. static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
  57. struct ieee80211_sta *sta,
  58. struct wcn36xx_hal_config_bss_params *bss_params)
  59. {
  60. if (sta && sta->ht_cap.ht_supported) {
  61. unsigned long caps = sta->ht_cap.cap;
  62. bss_params->ht = sta->ht_cap.ht_supported;
  63. bss_params->tx_channel_width_set = is_cap_supported(caps,
  64. IEEE80211_HT_CAP_SUP_WIDTH_20_40);
  65. bss_params->lsig_tx_op_protection_full_support =
  66. is_cap_supported(caps,
  67. IEEE80211_HT_CAP_LSIG_TXOP_PROT);
  68. bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode;
  69. bss_params->lln_non_gf_coexist =
  70. !!(vif->bss_conf.ht_operation_mode &
  71. IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
  72. /* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */
  73. bss_params->dual_cts_protection = 0;
  74. /* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */
  75. bss_params->ht20_coexist = 0;
  76. }
  77. }
  78. static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
  79. struct wcn36xx_hal_config_sta_params *sta_params)
  80. {
  81. if (sta->ht_cap.ht_supported) {
  82. unsigned long caps = sta->ht_cap.cap;
  83. sta_params->ht_capable = sta->ht_cap.ht_supported;
  84. sta_params->tx_channel_width_set = is_cap_supported(caps,
  85. IEEE80211_HT_CAP_SUP_WIDTH_20_40);
  86. sta_params->lsig_txop_protection = is_cap_supported(caps,
  87. IEEE80211_HT_CAP_LSIG_TXOP_PROT);
  88. sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor;
  89. sta_params->max_ampdu_density = sta->ht_cap.ampdu_density;
  90. sta_params->max_amsdu_size = is_cap_supported(caps,
  91. IEEE80211_HT_CAP_MAX_AMSDU);
  92. sta_params->sgi_20Mhz = is_cap_supported(caps,
  93. IEEE80211_HT_CAP_SGI_20);
  94. sta_params->sgi_40mhz = is_cap_supported(caps,
  95. IEEE80211_HT_CAP_SGI_40);
  96. sta_params->green_field_capable = is_cap_supported(caps,
  97. IEEE80211_HT_CAP_GRN_FLD);
  98. sta_params->delayed_ba_support = is_cap_supported(caps,
  99. IEEE80211_HT_CAP_DELAY_BA);
  100. sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps,
  101. IEEE80211_HT_CAP_DSSSCCK40);
  102. }
  103. }
  104. static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
  105. struct ieee80211_vif *vif,
  106. struct ieee80211_sta *sta,
  107. struct wcn36xx_hal_config_sta_params *sta_params)
  108. {
  109. struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
  110. struct wcn36xx_sta *priv_sta = NULL;
  111. if (vif->type == NL80211_IFTYPE_ADHOC ||
  112. vif->type == NL80211_IFTYPE_AP ||
  113. vif->type == NL80211_IFTYPE_MESH_POINT) {
  114. sta_params->type = 1;
  115. sta_params->sta_index = 0xFF;
  116. } else {
  117. sta_params->type = 0;
  118. sta_params->sta_index = 1;
  119. }
  120. sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
  121. /*
  122. * In STA mode ieee80211_sta contains bssid and ieee80211_vif
  123. * contains our mac address. In AP mode we are bssid so vif
  124. * contains bssid and ieee80211_sta contains mac.
  125. */
  126. if (NL80211_IFTYPE_STATION == vif->type)
  127. memcpy(&sta_params->mac, vif->addr, ETH_ALEN);
  128. else
  129. memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
  130. sta_params->encrypt_type = priv_vif->encrypt_type;
  131. sta_params->short_preamble_supported =
  132. !(WCN36XX_FLAGS(wcn) &
  133. IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE);
  134. sta_params->rifs_mode = 0;
  135. sta_params->rmf = 0;
  136. sta_params->action = 0;
  137. sta_params->uapsd = 0;
  138. sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
  139. sta_params->max_ampdu_duration = 0;
  140. sta_params->bssid_index = priv_vif->bss_index;
  141. sta_params->p2p = 0;
  142. if (sta) {
  143. priv_sta = (struct wcn36xx_sta *)sta->drv_priv;
  144. if (NL80211_IFTYPE_STATION == vif->type)
  145. memcpy(&sta_params->bssid, sta->addr, ETH_ALEN);
  146. else
  147. memcpy(&sta_params->mac, sta->addr, ETH_ALEN);
  148. sta_params->wmm_enabled = sta->wme;
  149. sta_params->max_sp_len = sta->max_sp;
  150. sta_params->aid = priv_sta->aid;
  151. wcn36xx_smd_set_sta_ht_params(sta, sta_params);
  152. memcpy(&sta_params->supported_rates, &priv_sta->supported_rates,
  153. sizeof(priv_sta->supported_rates));
  154. } else {
  155. wcn36xx_set_default_rates(&sta_params->supported_rates);
  156. }
  157. }
  158. static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
  159. {
  160. int ret = 0;
  161. wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
  162. init_completion(&wcn->hal_rsp_compl);
  163. ret = wcn->ctrl_ops->tx(wcn->hal_buf, len);
  164. if (ret) {
  165. wcn36xx_err("HAL TX failed\n");
  166. goto out;
  167. }
  168. if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
  169. msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
  170. wcn36xx_err("Timeout while waiting SMD response\n");
  171. ret = -ETIME;
  172. goto out;
  173. }
  174. out:
  175. return ret;
  176. }
  177. #define INIT_HAL_MSG(msg_body, type) \
  178. do { \
  179. memset(&msg_body, 0, sizeof(msg_body)); \
  180. msg_body.header.msg_type = type; \
  181. msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
  182. msg_body.header.len = sizeof(msg_body); \
  183. } while (0) \
  184. #define PREPARE_HAL_BUF(send_buf, msg_body) \
  185. do { \
  186. memset(send_buf, 0, msg_body.header.len); \
  187. memcpy(send_buf, &msg_body, sizeof(msg_body)); \
  188. } while (0) \
  189. static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
  190. {
  191. struct wcn36xx_fw_msg_status_rsp *rsp;
  192. if (len < sizeof(struct wcn36xx_hal_msg_header) +
  193. sizeof(struct wcn36xx_fw_msg_status_rsp))
  194. return -EIO;
  195. rsp = (struct wcn36xx_fw_msg_status_rsp *)
  196. (buf + sizeof(struct wcn36xx_hal_msg_header));
  197. if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
  198. return rsp->status;
  199. return 0;
  200. }
  201. int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
  202. {
  203. const struct firmware *nv;
  204. struct nv_data *nv_d;
  205. struct wcn36xx_hal_nv_img_download_req_msg msg_body;
  206. int fw_bytes_left;
  207. int ret;
  208. u16 fm_offset = 0;
  209. ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev);
  210. if (ret) {
  211. wcn36xx_err("Failed to load nv file %s: %d\n",
  212. WLAN_NV_FILE, ret);
  213. goto out_free_nv;
  214. }
  215. nv_d = (struct nv_data *)nv->data;
  216. INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
  217. msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
  218. msg_body.frag_number = 0;
  219. /* hal_buf must be protected with mutex */
  220. mutex_lock(&wcn->hal_mutex);
  221. do {
  222. fw_bytes_left = nv->size - fm_offset - 4;
  223. if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
  224. msg_body.last_fragment = 0;
  225. msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
  226. } else {
  227. msg_body.last_fragment = 1;
  228. msg_body.nv_img_buffer_size = fw_bytes_left;
  229. /* Do not forget update general message len */
  230. msg_body.header.len = sizeof(msg_body) + fw_bytes_left;
  231. }
  232. /* Add load NV request message header */
  233. memcpy(wcn->hal_buf, &msg_body, sizeof(msg_body));
  234. /* Add NV body itself */
  235. memcpy(wcn->hal_buf + sizeof(msg_body),
  236. &nv_d->table + fm_offset,
  237. msg_body.nv_img_buffer_size);
  238. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  239. if (ret)
  240. goto out_unlock;
  241. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf,
  242. wcn->hal_rsp_len);
  243. if (ret) {
  244. wcn36xx_err("hal_load_nv response failed err=%d\n",
  245. ret);
  246. goto out_unlock;
  247. }
  248. msg_body.frag_number++;
  249. fm_offset += WCN36XX_NV_FRAGMENT_SIZE;
  250. } while (msg_body.last_fragment != 1);
  251. out_unlock:
  252. mutex_unlock(&wcn->hal_mutex);
  253. out_free_nv:
  254. release_firmware(nv);
  255. return ret;
  256. }
  257. static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
  258. {
  259. struct wcn36xx_hal_mac_start_rsp_msg *rsp;
  260. if (len < sizeof(*rsp))
  261. return -EIO;
  262. rsp = (struct wcn36xx_hal_mac_start_rsp_msg *)buf;
  263. if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status)
  264. return -EIO;
  265. memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version,
  266. WCN36XX_HAL_VERSION_LENGTH);
  267. memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version,
  268. WCN36XX_HAL_VERSION_LENGTH);
  269. /* null terminate the strings, just in case */
  270. wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
  271. wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
  272. wcn->fw_revision = rsp->start_rsp_params.version.revision;
  273. wcn->fw_version = rsp->start_rsp_params.version.version;
  274. wcn->fw_minor = rsp->start_rsp_params.version.minor;
  275. wcn->fw_major = rsp->start_rsp_params.version.major;
  276. wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n",
  277. wcn->wlan_version, wcn->crm_version);
  278. wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n",
  279. wcn->fw_major, wcn->fw_minor,
  280. wcn->fw_version, wcn->fw_revision,
  281. rsp->start_rsp_params.stations,
  282. rsp->start_rsp_params.bssids);
  283. return 0;
  284. }
  285. int wcn36xx_smd_start(struct wcn36xx *wcn)
  286. {
  287. struct wcn36xx_hal_mac_start_req_msg msg_body;
  288. int ret = 0;
  289. mutex_lock(&wcn->hal_mutex);
  290. INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ);
  291. msg_body.params.type = DRIVER_TYPE_PRODUCTION;
  292. msg_body.params.len = 0;
  293. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  294. wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n",
  295. msg_body.params.type);
  296. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  297. if (ret) {
  298. wcn36xx_err("Sending hal_start failed\n");
  299. goto out;
  300. }
  301. ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len);
  302. if (ret) {
  303. wcn36xx_err("hal_start response failed err=%d\n", ret);
  304. goto out;
  305. }
  306. out:
  307. mutex_unlock(&wcn->hal_mutex);
  308. return ret;
  309. }
  310. int wcn36xx_smd_stop(struct wcn36xx *wcn)
  311. {
  312. struct wcn36xx_hal_mac_stop_req_msg msg_body;
  313. int ret = 0;
  314. mutex_lock(&wcn->hal_mutex);
  315. INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ);
  316. msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL;
  317. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  318. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  319. if (ret) {
  320. wcn36xx_err("Sending hal_stop failed\n");
  321. goto out;
  322. }
  323. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  324. if (ret) {
  325. wcn36xx_err("hal_stop response failed err=%d\n", ret);
  326. goto out;
  327. }
  328. out:
  329. mutex_unlock(&wcn->hal_mutex);
  330. return ret;
  331. }
  332. int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode)
  333. {
  334. struct wcn36xx_hal_init_scan_req_msg msg_body;
  335. int ret = 0;
  336. mutex_lock(&wcn->hal_mutex);
  337. INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ);
  338. msg_body.mode = mode;
  339. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  340. wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode);
  341. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  342. if (ret) {
  343. wcn36xx_err("Sending hal_init_scan failed\n");
  344. goto out;
  345. }
  346. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  347. if (ret) {
  348. wcn36xx_err("hal_init_scan response failed err=%d\n", ret);
  349. goto out;
  350. }
  351. out:
  352. mutex_unlock(&wcn->hal_mutex);
  353. return ret;
  354. }
  355. int wcn36xx_smd_start_scan(struct wcn36xx *wcn)
  356. {
  357. struct wcn36xx_hal_start_scan_req_msg msg_body;
  358. int ret = 0;
  359. mutex_lock(&wcn->hal_mutex);
  360. INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
  361. msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
  362. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  363. wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n",
  364. msg_body.scan_channel);
  365. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  366. if (ret) {
  367. wcn36xx_err("Sending hal_start_scan failed\n");
  368. goto out;
  369. }
  370. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  371. if (ret) {
  372. wcn36xx_err("hal_start_scan response failed err=%d\n", ret);
  373. goto out;
  374. }
  375. out:
  376. mutex_unlock(&wcn->hal_mutex);
  377. return ret;
  378. }
  379. int wcn36xx_smd_end_scan(struct wcn36xx *wcn)
  380. {
  381. struct wcn36xx_hal_end_scan_req_msg msg_body;
  382. int ret = 0;
  383. mutex_lock(&wcn->hal_mutex);
  384. INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
  385. msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
  386. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  387. wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n",
  388. msg_body.scan_channel);
  389. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  390. if (ret) {
  391. wcn36xx_err("Sending hal_end_scan failed\n");
  392. goto out;
  393. }
  394. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  395. if (ret) {
  396. wcn36xx_err("hal_end_scan response failed err=%d\n", ret);
  397. goto out;
  398. }
  399. out:
  400. mutex_unlock(&wcn->hal_mutex);
  401. return ret;
  402. }
  403. int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
  404. enum wcn36xx_hal_sys_mode mode)
  405. {
  406. struct wcn36xx_hal_finish_scan_req_msg msg_body;
  407. int ret = 0;
  408. mutex_lock(&wcn->hal_mutex);
  409. INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ);
  410. msg_body.mode = mode;
  411. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  412. wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n",
  413. msg_body.mode);
  414. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  415. if (ret) {
  416. wcn36xx_err("Sending hal_finish_scan failed\n");
  417. goto out;
  418. }
  419. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  420. if (ret) {
  421. wcn36xx_err("hal_finish_scan response failed err=%d\n", ret);
  422. goto out;
  423. }
  424. out:
  425. mutex_unlock(&wcn->hal_mutex);
  426. return ret;
  427. }
  428. static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len)
  429. {
  430. struct wcn36xx_hal_switch_channel_rsp_msg *rsp;
  431. int ret = 0;
  432. ret = wcn36xx_smd_rsp_status_check(buf, len);
  433. if (ret)
  434. return ret;
  435. rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf;
  436. wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n",
  437. rsp->channel_number, rsp->status);
  438. return ret;
  439. }
  440. int wcn36xx_smd_switch_channel(struct wcn36xx *wcn,
  441. struct ieee80211_vif *vif, int ch)
  442. {
  443. struct wcn36xx_hal_switch_channel_req_msg msg_body;
  444. int ret = 0;
  445. mutex_lock(&wcn->hal_mutex);
  446. INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ);
  447. msg_body.channel_number = (u8)ch;
  448. msg_body.tx_mgmt_power = 0xbf;
  449. msg_body.max_tx_power = 0xbf;
  450. memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN);
  451. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  452. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  453. if (ret) {
  454. wcn36xx_err("Sending hal_switch_channel failed\n");
  455. goto out;
  456. }
  457. ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len);
  458. if (ret) {
  459. wcn36xx_err("hal_switch_channel response failed err=%d\n", ret);
  460. goto out;
  461. }
  462. out:
  463. mutex_unlock(&wcn->hal_mutex);
  464. return ret;
  465. }
  466. static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len)
  467. {
  468. struct wcn36xx_hal_update_scan_params_resp *rsp;
  469. rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf;
  470. /* Remove the PNO version bit */
  471. rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK));
  472. if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) {
  473. wcn36xx_warn("error response from update scan\n");
  474. return rsp->status;
  475. }
  476. return 0;
  477. }
  478. int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn)
  479. {
  480. struct wcn36xx_hal_update_scan_params_req msg_body;
  481. int ret = 0;
  482. mutex_lock(&wcn->hal_mutex);
  483. INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
  484. msg_body.dot11d_enabled = 0;
  485. msg_body.dot11d_resolved = 0;
  486. msg_body.channel_count = 26;
  487. msg_body.active_min_ch_time = 60;
  488. msg_body.active_max_ch_time = 120;
  489. msg_body.passive_min_ch_time = 60;
  490. msg_body.passive_max_ch_time = 110;
  491. msg_body.state = 0;
  492. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  493. wcn36xx_dbg(WCN36XX_DBG_HAL,
  494. "hal update scan params channel_count %d\n",
  495. msg_body.channel_count);
  496. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  497. if (ret) {
  498. wcn36xx_err("Sending hal_update_scan_params failed\n");
  499. goto out;
  500. }
  501. ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf,
  502. wcn->hal_rsp_len);
  503. if (ret) {
  504. wcn36xx_err("hal_update_scan_params response failed err=%d\n",
  505. ret);
  506. goto out;
  507. }
  508. out:
  509. mutex_unlock(&wcn->hal_mutex);
  510. return ret;
  511. }
  512. static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
  513. struct ieee80211_vif *vif,
  514. void *buf,
  515. size_t len)
  516. {
  517. struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
  518. struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
  519. if (len < sizeof(*rsp))
  520. return -EINVAL;
  521. rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf;
  522. if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
  523. wcn36xx_warn("hal add sta self failure: %d\n",
  524. rsp->status);
  525. return rsp->status;
  526. }
  527. wcn36xx_dbg(WCN36XX_DBG_HAL,
  528. "hal add sta self status %d self_sta_index %d dpu_index %d\n",
  529. rsp->status, rsp->self_sta_index, rsp->dpu_index);
  530. priv_vif->self_sta_index = rsp->self_sta_index;
  531. priv_vif->self_dpu_desc_index = rsp->dpu_index;
  532. return 0;
  533. }
  534. int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif)
  535. {
  536. struct wcn36xx_hal_add_sta_self_req msg_body;
  537. int ret = 0;
  538. mutex_lock(&wcn->hal_mutex);
  539. INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ);
  540. memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN);
  541. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  542. wcn36xx_dbg(WCN36XX_DBG_HAL,
  543. "hal add sta self self_addr %pM status %d\n",
  544. msg_body.self_addr, msg_body.status);
  545. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  546. if (ret) {
  547. wcn36xx_err("Sending hal_add_sta_self failed\n");
  548. goto out;
  549. }
  550. ret = wcn36xx_smd_add_sta_self_rsp(wcn,
  551. vif,
  552. wcn->hal_buf,
  553. wcn->hal_rsp_len);
  554. if (ret) {
  555. wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret);
  556. goto out;
  557. }
  558. out:
  559. mutex_unlock(&wcn->hal_mutex);
  560. return ret;
  561. }
  562. int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr)
  563. {
  564. struct wcn36xx_hal_del_sta_self_req_msg msg_body;
  565. int ret = 0;
  566. mutex_lock(&wcn->hal_mutex);
  567. INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ);
  568. memcpy(&msg_body.self_addr, addr, ETH_ALEN);
  569. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  570. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  571. if (ret) {
  572. wcn36xx_err("Sending hal_delete_sta_self failed\n");
  573. goto out;
  574. }
  575. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  576. if (ret) {
  577. wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
  578. ret);
  579. goto out;
  580. }
  581. out:
  582. mutex_unlock(&wcn->hal_mutex);
  583. return ret;
  584. }
  585. int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index)
  586. {
  587. struct wcn36xx_hal_delete_sta_req_msg msg_body;
  588. int ret = 0;
  589. mutex_lock(&wcn->hal_mutex);
  590. INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ);
  591. msg_body.sta_index = sta_index;
  592. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  593. wcn36xx_dbg(WCN36XX_DBG_HAL,
  594. "hal delete sta sta_index %d\n",
  595. msg_body.sta_index);
  596. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  597. if (ret) {
  598. wcn36xx_err("Sending hal_delete_sta failed\n");
  599. goto out;
  600. }
  601. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  602. if (ret) {
  603. wcn36xx_err("hal_delete_sta response failed err=%d\n", ret);
  604. goto out;
  605. }
  606. out:
  607. mutex_unlock(&wcn->hal_mutex);
  608. return ret;
  609. }
  610. static int wcn36xx_smd_join_rsp(void *buf, size_t len)
  611. {
  612. struct wcn36xx_hal_join_rsp_msg *rsp;
  613. if (wcn36xx_smd_rsp_status_check(buf, len))
  614. return -EIO;
  615. rsp = (struct wcn36xx_hal_join_rsp_msg *)buf;
  616. wcn36xx_dbg(WCN36XX_DBG_HAL,
  617. "hal rsp join status %d tx_mgmt_power %d\n",
  618. rsp->status, rsp->tx_mgmt_power);
  619. return 0;
  620. }
  621. int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch)
  622. {
  623. struct wcn36xx_hal_join_req_msg msg_body;
  624. int ret = 0;
  625. mutex_lock(&wcn->hal_mutex);
  626. INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ);
  627. memcpy(&msg_body.bssid, bssid, ETH_ALEN);
  628. memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN);
  629. msg_body.channel = ch;
  630. if (conf_is_ht40_minus(&wcn->hw->conf))
  631. msg_body.secondary_channel_offset =
  632. PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
  633. else if (conf_is_ht40_plus(&wcn->hw->conf))
  634. msg_body.secondary_channel_offset =
  635. PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
  636. else
  637. msg_body.secondary_channel_offset =
  638. PHY_SINGLE_CHANNEL_CENTERED;
  639. msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE;
  640. msg_body.max_tx_power = 0xbf;
  641. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  642. wcn36xx_dbg(WCN36XX_DBG_HAL,
  643. "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n",
  644. msg_body.bssid, msg_body.self_sta_mac_addr,
  645. msg_body.channel, msg_body.link_state);
  646. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  647. if (ret) {
  648. wcn36xx_err("Sending hal_join failed\n");
  649. goto out;
  650. }
  651. ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len);
  652. if (ret) {
  653. wcn36xx_err("hal_join response failed err=%d\n", ret);
  654. goto out;
  655. }
  656. out:
  657. mutex_unlock(&wcn->hal_mutex);
  658. return ret;
  659. }
  660. int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid,
  661. const u8 *sta_mac,
  662. enum wcn36xx_hal_link_state state)
  663. {
  664. struct wcn36xx_hal_set_link_state_req_msg msg_body;
  665. int ret = 0;
  666. mutex_lock(&wcn->hal_mutex);
  667. INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ);
  668. memcpy(&msg_body.bssid, bssid, ETH_ALEN);
  669. memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN);
  670. msg_body.state = state;
  671. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  672. wcn36xx_dbg(WCN36XX_DBG_HAL,
  673. "hal set link state bssid %pM self_mac_addr %pM state %d\n",
  674. msg_body.bssid, msg_body.self_mac_addr, msg_body.state);
  675. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  676. if (ret) {
  677. wcn36xx_err("Sending hal_set_link_st failed\n");
  678. goto out;
  679. }
  680. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  681. if (ret) {
  682. wcn36xx_err("hal_set_link_st response failed err=%d\n", ret);
  683. goto out;
  684. }
  685. out:
  686. mutex_unlock(&wcn->hal_mutex);
  687. return ret;
  688. }
  689. static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
  690. const struct wcn36xx_hal_config_sta_params *orig,
  691. struct wcn36xx_hal_config_sta_params_v1 *v1)
  692. {
  693. /* convert orig to v1 format */
  694. memcpy(&v1->bssid, orig->bssid, ETH_ALEN);
  695. memcpy(&v1->mac, orig->mac, ETH_ALEN);
  696. v1->aid = orig->aid;
  697. v1->type = orig->type;
  698. v1->listen_interval = orig->listen_interval;
  699. v1->ht_capable = orig->ht_capable;
  700. v1->max_ampdu_size = orig->max_ampdu_size;
  701. v1->max_ampdu_density = orig->max_ampdu_density;
  702. v1->sgi_40mhz = orig->sgi_40mhz;
  703. v1->sgi_20Mhz = orig->sgi_20Mhz;
  704. memcpy(&v1->supported_rates, &orig->supported_rates,
  705. sizeof(orig->supported_rates));
  706. v1->sta_index = orig->sta_index;
  707. }
  708. static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
  709. struct ieee80211_sta *sta,
  710. void *buf,
  711. size_t len)
  712. {
  713. struct wcn36xx_hal_config_sta_rsp_msg *rsp;
  714. struct config_sta_rsp_params *params;
  715. struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
  716. if (len < sizeof(*rsp))
  717. return -EINVAL;
  718. rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf;
  719. params = &rsp->params;
  720. if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
  721. wcn36xx_warn("hal config sta response failure: %d\n",
  722. params->status);
  723. return -EIO;
  724. }
  725. sta_priv->sta_index = params->sta_index;
  726. sta_priv->dpu_desc_index = params->dpu_index;
  727. wcn36xx_dbg(WCN36XX_DBG_HAL,
  728. "hal config sta rsp status %d sta_index %d bssid_index %d p2p %d\n",
  729. params->status, params->sta_index, params->bssid_index,
  730. params->p2p);
  731. return 0;
  732. }
  733. static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn,
  734. const struct wcn36xx_hal_config_sta_req_msg *orig)
  735. {
  736. struct wcn36xx_hal_config_sta_req_msg_v1 msg_body;
  737. struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params;
  738. INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
  739. wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params,
  740. &msg_body.sta_params);
  741. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  742. wcn36xx_dbg(WCN36XX_DBG_HAL,
  743. "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
  744. sta->action, sta->sta_index, sta->bssid_index,
  745. sta->bssid, sta->type, sta->mac, sta->aid);
  746. return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  747. }
  748. int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
  749. struct ieee80211_sta *sta)
  750. {
  751. struct wcn36xx_hal_config_sta_req_msg msg;
  752. struct wcn36xx_hal_config_sta_params *sta_params;
  753. int ret = 0;
  754. mutex_lock(&wcn->hal_mutex);
  755. INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
  756. sta_params = &msg.sta_params;
  757. wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
  758. if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
  759. ret = wcn36xx_smd_config_sta_v1(wcn, &msg);
  760. } else {
  761. PREPARE_HAL_BUF(wcn->hal_buf, msg);
  762. wcn36xx_dbg(WCN36XX_DBG_HAL,
  763. "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
  764. sta_params->action, sta_params->sta_index,
  765. sta_params->bssid_index, sta_params->bssid,
  766. sta_params->type, sta_params->mac, sta_params->aid);
  767. ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
  768. }
  769. if (ret) {
  770. wcn36xx_err("Sending hal_config_sta failed\n");
  771. goto out;
  772. }
  773. ret = wcn36xx_smd_config_sta_rsp(wcn,
  774. sta,
  775. wcn->hal_buf,
  776. wcn->hal_rsp_len);
  777. if (ret) {
  778. wcn36xx_err("hal_config_sta response failed err=%d\n", ret);
  779. goto out;
  780. }
  781. out:
  782. mutex_unlock(&wcn->hal_mutex);
  783. return ret;
  784. }
  785. static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
  786. const struct wcn36xx_hal_config_bss_req_msg *orig)
  787. {
  788. struct wcn36xx_hal_config_bss_req_msg_v1 msg_body;
  789. struct wcn36xx_hal_config_bss_params_v1 *bss = &msg_body.bss_params;
  790. struct wcn36xx_hal_config_sta_params_v1 *sta = &bss->sta;
  791. INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_BSS_REQ);
  792. /* convert orig to v1 */
  793. memcpy(&msg_body.bss_params.bssid,
  794. &orig->bss_params.bssid, ETH_ALEN);
  795. memcpy(&msg_body.bss_params.self_mac_addr,
  796. &orig->bss_params.self_mac_addr, ETH_ALEN);
  797. msg_body.bss_params.bss_type = orig->bss_params.bss_type;
  798. msg_body.bss_params.oper_mode = orig->bss_params.oper_mode;
  799. msg_body.bss_params.nw_type = orig->bss_params.nw_type;
  800. msg_body.bss_params.short_slot_time_supported =
  801. orig->bss_params.short_slot_time_supported;
  802. msg_body.bss_params.lla_coexist = orig->bss_params.lla_coexist;
  803. msg_body.bss_params.llb_coexist = orig->bss_params.llb_coexist;
  804. msg_body.bss_params.llg_coexist = orig->bss_params.llg_coexist;
  805. msg_body.bss_params.ht20_coexist = orig->bss_params.ht20_coexist;
  806. msg_body.bss_params.lln_non_gf_coexist =
  807. orig->bss_params.lln_non_gf_coexist;
  808. msg_body.bss_params.lsig_tx_op_protection_full_support =
  809. orig->bss_params.lsig_tx_op_protection_full_support;
  810. msg_body.bss_params.rifs_mode = orig->bss_params.rifs_mode;
  811. msg_body.bss_params.beacon_interval = orig->bss_params.beacon_interval;
  812. msg_body.bss_params.dtim_period = orig->bss_params.dtim_period;
  813. msg_body.bss_params.tx_channel_width_set =
  814. orig->bss_params.tx_channel_width_set;
  815. msg_body.bss_params.oper_channel = orig->bss_params.oper_channel;
  816. msg_body.bss_params.ext_channel = orig->bss_params.ext_channel;
  817. msg_body.bss_params.reserved = orig->bss_params.reserved;
  818. memcpy(&msg_body.bss_params.ssid,
  819. &orig->bss_params.ssid,
  820. sizeof(orig->bss_params.ssid));
  821. msg_body.bss_params.action = orig->bss_params.action;
  822. msg_body.bss_params.rateset = orig->bss_params.rateset;
  823. msg_body.bss_params.ht = orig->bss_params.ht;
  824. msg_body.bss_params.obss_prot_enabled =
  825. orig->bss_params.obss_prot_enabled;
  826. msg_body.bss_params.rmf = orig->bss_params.rmf;
  827. msg_body.bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode;
  828. msg_body.bss_params.dual_cts_protection =
  829. orig->bss_params.dual_cts_protection;
  830. msg_body.bss_params.max_probe_resp_retry_limit =
  831. orig->bss_params.max_probe_resp_retry_limit;
  832. msg_body.bss_params.hidden_ssid = orig->bss_params.hidden_ssid;
  833. msg_body.bss_params.proxy_probe_resp =
  834. orig->bss_params.proxy_probe_resp;
  835. msg_body.bss_params.edca_params_valid =
  836. orig->bss_params.edca_params_valid;
  837. memcpy(&msg_body.bss_params.acbe,
  838. &orig->bss_params.acbe,
  839. sizeof(orig->bss_params.acbe));
  840. memcpy(&msg_body.bss_params.acbk,
  841. &orig->bss_params.acbk,
  842. sizeof(orig->bss_params.acbk));
  843. memcpy(&msg_body.bss_params.acvi,
  844. &orig->bss_params.acvi,
  845. sizeof(orig->bss_params.acvi));
  846. memcpy(&msg_body.bss_params.acvo,
  847. &orig->bss_params.acvo,
  848. sizeof(orig->bss_params.acvo));
  849. msg_body.bss_params.ext_set_sta_key_param_valid =
  850. orig->bss_params.ext_set_sta_key_param_valid;
  851. memcpy(&msg_body.bss_params.ext_set_sta_key_param,
  852. &orig->bss_params.ext_set_sta_key_param,
  853. sizeof(orig->bss_params.acvo));
  854. msg_body.bss_params.wcn36xx_hal_persona =
  855. orig->bss_params.wcn36xx_hal_persona;
  856. msg_body.bss_params.spectrum_mgt_enable =
  857. orig->bss_params.spectrum_mgt_enable;
  858. msg_body.bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power;
  859. msg_body.bss_params.max_tx_power = orig->bss_params.max_tx_power;
  860. wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta,
  861. &msg_body.bss_params.sta);
  862. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  863. wcn36xx_dbg(WCN36XX_DBG_HAL,
  864. "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
  865. bss->bssid, bss->self_mac_addr, bss->bss_type,
  866. bss->oper_mode, bss->nw_type);
  867. wcn36xx_dbg(WCN36XX_DBG_HAL,
  868. "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
  869. sta->bssid, sta->action, sta->sta_index,
  870. sta->bssid_index, sta->aid, sta->type, sta->mac);
  871. return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  872. }
  873. static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
  874. struct ieee80211_vif *vif,
  875. void *buf,
  876. size_t len)
  877. {
  878. struct wcn36xx_hal_config_bss_rsp_msg *rsp;
  879. struct wcn36xx_hal_config_bss_rsp_params *params;
  880. struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
  881. if (len < sizeof(*rsp))
  882. return -EINVAL;
  883. rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf;
  884. params = &rsp->bss_rsp_params;
  885. if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
  886. wcn36xx_warn("hal config bss response failure: %d\n",
  887. params->status);
  888. return -EIO;
  889. }
  890. wcn36xx_dbg(WCN36XX_DBG_HAL,
  891. "hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
  892. " sta_idx %d self_idx %d bcast_idx %d mac %pM"
  893. " power %d ucast_dpu_signature %d\n",
  894. params->status, params->bss_index, params->dpu_desc_index,
  895. params->bss_sta_index, params->bss_self_sta_index,
  896. params->bss_bcast_sta_idx, params->mac,
  897. params->tx_mgmt_power, params->ucast_dpu_signature);
  898. priv_vif->bss_index = params->bss_index;
  899. if (priv_vif->sta) {
  900. priv_vif->sta->bss_sta_index = params->bss_sta_index;
  901. priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index;
  902. }
  903. priv_vif->ucast_dpu_signature = params->ucast_dpu_signature;
  904. return 0;
  905. }
  906. int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
  907. struct ieee80211_sta *sta, const u8 *bssid,
  908. bool update)
  909. {
  910. struct wcn36xx_hal_config_bss_req_msg msg;
  911. struct wcn36xx_hal_config_bss_params *bss;
  912. struct wcn36xx_hal_config_sta_params *sta_params;
  913. struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
  914. int ret = 0;
  915. mutex_lock(&wcn->hal_mutex);
  916. INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ);
  917. bss = &msg.bss_params;
  918. sta_params = &bss->sta;
  919. WARN_ON(is_zero_ether_addr(bssid));
  920. memcpy(&bss->bssid, bssid, ETH_ALEN);
  921. memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN);
  922. if (vif->type == NL80211_IFTYPE_STATION) {
  923. bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE;
  924. /* STA */
  925. bss->oper_mode = 1;
  926. bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
  927. } else if (vif->type == NL80211_IFTYPE_AP) {
  928. bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
  929. /* AP */
  930. bss->oper_mode = 0;
  931. bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
  932. } else if (vif->type == NL80211_IFTYPE_ADHOC ||
  933. vif->type == NL80211_IFTYPE_MESH_POINT) {
  934. bss->bss_type = WCN36XX_HAL_IBSS_MODE;
  935. /* STA */
  936. bss->oper_mode = 1;
  937. } else {
  938. wcn36xx_warn("Unknown type for bss config: %d\n", vif->type);
  939. }
  940. if (vif->type == NL80211_IFTYPE_STATION)
  941. wcn36xx_smd_set_bss_nw_type(wcn, sta, bss);
  942. else
  943. bss->nw_type = WCN36XX_HAL_11N_NW_TYPE;
  944. bss->short_slot_time_supported = vif->bss_conf.use_short_slot;
  945. bss->lla_coexist = 0;
  946. bss->llb_coexist = 0;
  947. bss->llg_coexist = 0;
  948. bss->rifs_mode = 0;
  949. bss->beacon_interval = vif->bss_conf.beacon_int;
  950. bss->dtim_period = vif_priv->dtim_period;
  951. wcn36xx_smd_set_bss_ht_params(vif, sta, bss);
  952. bss->oper_channel = WCN36XX_HW_CHANNEL(wcn);
  953. if (conf_is_ht40_minus(&wcn->hw->conf))
  954. bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
  955. else if (conf_is_ht40_plus(&wcn->hw->conf))
  956. bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
  957. else
  958. bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE;
  959. bss->reserved = 0;
  960. wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
  961. /* wcn->ssid is only valid in AP and IBSS mode */
  962. bss->ssid.length = vif_priv->ssid.length;
  963. memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length);
  964. bss->obss_prot_enabled = 0;
  965. bss->rmf = 0;
  966. bss->max_probe_resp_retry_limit = 0;
  967. bss->hidden_ssid = vif->bss_conf.hidden_ssid;
  968. bss->proxy_probe_resp = 0;
  969. bss->edca_params_valid = 0;
  970. /* FIXME: set acbe, acbk, acvi and acvo */
  971. bss->ext_set_sta_key_param_valid = 0;
  972. /* FIXME: set ext_set_sta_key_param */
  973. bss->spectrum_mgt_enable = 0;
  974. bss->tx_mgmt_power = 0;
  975. bss->max_tx_power = WCN36XX_MAX_POWER(wcn);
  976. bss->action = update;
  977. wcn36xx_dbg(WCN36XX_DBG_HAL,
  978. "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
  979. bss->bssid, bss->self_mac_addr, bss->bss_type,
  980. bss->oper_mode, bss->nw_type);
  981. wcn36xx_dbg(WCN36XX_DBG_HAL,
  982. "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
  983. sta_params->bssid, sta_params->action,
  984. sta_params->sta_index, sta_params->bssid_index,
  985. sta_params->aid, sta_params->type,
  986. sta_params->mac);
  987. if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
  988. ret = wcn36xx_smd_config_bss_v1(wcn, &msg);
  989. } else {
  990. PREPARE_HAL_BUF(wcn->hal_buf, msg);
  991. ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
  992. }
  993. if (ret) {
  994. wcn36xx_err("Sending hal_config_bss failed\n");
  995. goto out;
  996. }
  997. ret = wcn36xx_smd_config_bss_rsp(wcn,
  998. vif,
  999. wcn->hal_buf,
  1000. wcn->hal_rsp_len);
  1001. if (ret) {
  1002. wcn36xx_err("hal_config_bss response failed err=%d\n", ret);
  1003. goto out;
  1004. }
  1005. out:
  1006. mutex_unlock(&wcn->hal_mutex);
  1007. return ret;
  1008. }
  1009. int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
  1010. {
  1011. struct wcn36xx_hal_delete_bss_req_msg msg_body;
  1012. struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
  1013. int ret = 0;
  1014. mutex_lock(&wcn->hal_mutex);
  1015. INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
  1016. msg_body.bss_index = priv_vif->bss_index;
  1017. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1018. wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index);
  1019. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1020. if (ret) {
  1021. wcn36xx_err("Sending hal_delete_bss failed\n");
  1022. goto out;
  1023. }
  1024. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1025. if (ret) {
  1026. wcn36xx_err("hal_delete_bss response failed err=%d\n", ret);
  1027. goto out;
  1028. }
  1029. out:
  1030. mutex_unlock(&wcn->hal_mutex);
  1031. return ret;
  1032. }
  1033. int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
  1034. struct sk_buff *skb_beacon, u16 tim_off,
  1035. u16 p2p_off)
  1036. {
  1037. struct wcn36xx_hal_send_beacon_req_msg msg_body;
  1038. int ret = 0;
  1039. mutex_lock(&wcn->hal_mutex);
  1040. INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
  1041. /* TODO need to find out why this is needed? */
  1042. msg_body.beacon_length = skb_beacon->len + 6;
  1043. if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) {
  1044. memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32));
  1045. memcpy(&(msg_body.beacon[4]), skb_beacon->data,
  1046. skb_beacon->len);
  1047. } else {
  1048. wcn36xx_err("Beacon is to big: beacon size=%d\n",
  1049. msg_body.beacon_length);
  1050. return -ENOMEM;
  1051. }
  1052. memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
  1053. /* TODO need to find out why this is needed? */
  1054. msg_body.tim_ie_offset = tim_off+4;
  1055. msg_body.p2p_ie_offset = p2p_off;
  1056. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1057. wcn36xx_dbg(WCN36XX_DBG_HAL,
  1058. "hal send beacon beacon_length %d\n",
  1059. msg_body.beacon_length);
  1060. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1061. if (ret) {
  1062. wcn36xx_err("Sending hal_send_beacon failed\n");
  1063. goto out;
  1064. }
  1065. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1066. if (ret) {
  1067. wcn36xx_err("hal_send_beacon response failed err=%d\n", ret);
  1068. goto out;
  1069. }
  1070. out:
  1071. mutex_unlock(&wcn->hal_mutex);
  1072. return ret;
  1073. }
  1074. int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
  1075. struct ieee80211_vif *vif,
  1076. struct sk_buff *skb)
  1077. {
  1078. struct wcn36xx_hal_send_probe_resp_req_msg msg;
  1079. int ret = 0;
  1080. mutex_lock(&wcn->hal_mutex);
  1081. INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
  1082. if (skb->len > BEACON_TEMPLATE_SIZE) {
  1083. wcn36xx_warn("probe response template is too big: %d\n",
  1084. skb->len);
  1085. return -E2BIG;
  1086. }
  1087. msg.probe_resp_template_len = skb->len;
  1088. memcpy(&msg.probe_resp_template, skb->data, skb->len);
  1089. memcpy(msg.bssid, vif->addr, ETH_ALEN);
  1090. PREPARE_HAL_BUF(wcn->hal_buf, msg);
  1091. wcn36xx_dbg(WCN36XX_DBG_HAL,
  1092. "hal update probe rsp len %d bssid %pM\n",
  1093. msg.probe_resp_template_len, msg.bssid);
  1094. ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
  1095. if (ret) {
  1096. wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
  1097. goto out;
  1098. }
  1099. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1100. if (ret) {
  1101. wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
  1102. ret);
  1103. goto out;
  1104. }
  1105. out:
  1106. mutex_unlock(&wcn->hal_mutex);
  1107. return ret;
  1108. }
  1109. int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
  1110. enum ani_ed_type enc_type,
  1111. u8 keyidx,
  1112. u8 keylen,
  1113. u8 *key,
  1114. u8 sta_index)
  1115. {
  1116. struct wcn36xx_hal_set_sta_key_req_msg msg_body;
  1117. int ret = 0;
  1118. mutex_lock(&wcn->hal_mutex);
  1119. INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
  1120. msg_body.set_sta_key_params.sta_index = sta_index;
  1121. msg_body.set_sta_key_params.enc_type = enc_type;
  1122. msg_body.set_sta_key_params.key[0].id = keyidx;
  1123. msg_body.set_sta_key_params.key[0].unicast = 1;
  1124. msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
  1125. msg_body.set_sta_key_params.key[0].pae_role = 0;
  1126. msg_body.set_sta_key_params.key[0].length = keylen;
  1127. memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
  1128. msg_body.set_sta_key_params.single_tid_rc = 1;
  1129. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1130. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1131. if (ret) {
  1132. wcn36xx_err("Sending hal_set_stakey failed\n");
  1133. goto out;
  1134. }
  1135. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1136. if (ret) {
  1137. wcn36xx_err("hal_set_stakey response failed err=%d\n", ret);
  1138. goto out;
  1139. }
  1140. out:
  1141. mutex_unlock(&wcn->hal_mutex);
  1142. return ret;
  1143. }
  1144. int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
  1145. enum ani_ed_type enc_type,
  1146. u8 keyidx,
  1147. u8 keylen,
  1148. u8 *key)
  1149. {
  1150. struct wcn36xx_hal_set_bss_key_req_msg msg_body;
  1151. int ret = 0;
  1152. mutex_lock(&wcn->hal_mutex);
  1153. INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
  1154. msg_body.bss_idx = 0;
  1155. msg_body.enc_type = enc_type;
  1156. msg_body.num_keys = 1;
  1157. msg_body.keys[0].id = keyidx;
  1158. msg_body.keys[0].unicast = 0;
  1159. msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY;
  1160. msg_body.keys[0].pae_role = 0;
  1161. msg_body.keys[0].length = keylen;
  1162. memcpy(msg_body.keys[0].key, key, keylen);
  1163. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1164. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1165. if (ret) {
  1166. wcn36xx_err("Sending hal_set_bsskey failed\n");
  1167. goto out;
  1168. }
  1169. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1170. if (ret) {
  1171. wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret);
  1172. goto out;
  1173. }
  1174. out:
  1175. mutex_unlock(&wcn->hal_mutex);
  1176. return ret;
  1177. }
  1178. int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
  1179. enum ani_ed_type enc_type,
  1180. u8 keyidx,
  1181. u8 sta_index)
  1182. {
  1183. struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
  1184. int ret = 0;
  1185. mutex_lock(&wcn->hal_mutex);
  1186. INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
  1187. msg_body.sta_idx = sta_index;
  1188. msg_body.enc_type = enc_type;
  1189. msg_body.key_id = keyidx;
  1190. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1191. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1192. if (ret) {
  1193. wcn36xx_err("Sending hal_remove_stakey failed\n");
  1194. goto out;
  1195. }
  1196. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1197. if (ret) {
  1198. wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret);
  1199. goto out;
  1200. }
  1201. out:
  1202. mutex_unlock(&wcn->hal_mutex);
  1203. return ret;
  1204. }
  1205. int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
  1206. enum ani_ed_type enc_type,
  1207. u8 keyidx)
  1208. {
  1209. struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
  1210. int ret = 0;
  1211. mutex_lock(&wcn->hal_mutex);
  1212. INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
  1213. msg_body.bss_idx = 0;
  1214. msg_body.enc_type = enc_type;
  1215. msg_body.key_id = keyidx;
  1216. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1217. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1218. if (ret) {
  1219. wcn36xx_err("Sending hal_remove_bsskey failed\n");
  1220. goto out;
  1221. }
  1222. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1223. if (ret) {
  1224. wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
  1225. goto out;
  1226. }
  1227. out:
  1228. mutex_unlock(&wcn->hal_mutex);
  1229. return ret;
  1230. }
  1231. int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
  1232. {
  1233. struct wcn36xx_hal_enter_bmps_req_msg msg_body;
  1234. struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
  1235. int ret = 0;
  1236. mutex_lock(&wcn->hal_mutex);
  1237. INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
  1238. msg_body.bss_index = vif_priv->bss_index;
  1239. msg_body.tbtt = vif->bss_conf.sync_tsf;
  1240. msg_body.dtim_period = vif_priv->dtim_period;
  1241. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1242. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1243. if (ret) {
  1244. wcn36xx_err("Sending hal_enter_bmps failed\n");
  1245. goto out;
  1246. }
  1247. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1248. if (ret) {
  1249. wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret);
  1250. goto out;
  1251. }
  1252. out:
  1253. mutex_unlock(&wcn->hal_mutex);
  1254. return ret;
  1255. }
  1256. int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
  1257. {
  1258. struct wcn36xx_hal_enter_bmps_req_msg msg_body;
  1259. struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
  1260. int ret = 0;
  1261. mutex_lock(&wcn->hal_mutex);
  1262. INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
  1263. msg_body.bss_index = vif_priv->bss_index;
  1264. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1265. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1266. if (ret) {
  1267. wcn36xx_err("Sending hal_exit_bmps failed\n");
  1268. goto out;
  1269. }
  1270. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1271. if (ret) {
  1272. wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
  1273. goto out;
  1274. }
  1275. out:
  1276. mutex_unlock(&wcn->hal_mutex);
  1277. return ret;
  1278. }
  1279. int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
  1280. {
  1281. struct wcn36xx_hal_set_power_params_req_msg msg_body;
  1282. int ret = 0;
  1283. mutex_lock(&wcn->hal_mutex);
  1284. INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
  1285. /*
  1286. * When host is down ignore every second dtim
  1287. */
  1288. if (ignore_dtim) {
  1289. msg_body.ignore_dtim = 1;
  1290. msg_body.dtim_period = 2;
  1291. }
  1292. msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
  1293. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1294. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1295. if (ret) {
  1296. wcn36xx_err("Sending hal_set_power_params failed\n");
  1297. goto out;
  1298. }
  1299. out:
  1300. mutex_unlock(&wcn->hal_mutex);
  1301. return ret;
  1302. }
  1303. /* Notice: This function should be called after associated, or else it
  1304. * will be invalid
  1305. */
  1306. int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
  1307. struct ieee80211_vif *vif,
  1308. int packet_type)
  1309. {
  1310. struct wcn36xx_hal_keep_alive_req_msg msg_body;
  1311. struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
  1312. int ret = 0;
  1313. mutex_lock(&wcn->hal_mutex);
  1314. INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
  1315. if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
  1316. msg_body.bss_index = vif_priv->bss_index;
  1317. msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
  1318. msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
  1319. } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
  1320. /* TODO: it also support ARP response type */
  1321. } else {
  1322. wcn36xx_warn("unknow keep alive packet type %d\n", packet_type);
  1323. return -EINVAL;
  1324. }
  1325. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1326. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1327. if (ret) {
  1328. wcn36xx_err("Sending hal_exit_bmps failed\n");
  1329. goto out;
  1330. }
  1331. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1332. if (ret) {
  1333. wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
  1334. goto out;
  1335. }
  1336. out:
  1337. mutex_unlock(&wcn->hal_mutex);
  1338. return ret;
  1339. }
  1340. int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
  1341. u32 arg3, u32 arg4, u32 arg5)
  1342. {
  1343. struct wcn36xx_hal_dump_cmd_req_msg msg_body;
  1344. int ret = 0;
  1345. mutex_lock(&wcn->hal_mutex);
  1346. INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
  1347. msg_body.arg1 = arg1;
  1348. msg_body.arg2 = arg2;
  1349. msg_body.arg3 = arg3;
  1350. msg_body.arg4 = arg4;
  1351. msg_body.arg5 = arg5;
  1352. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1353. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1354. if (ret) {
  1355. wcn36xx_err("Sending hal_dump_cmd failed\n");
  1356. goto out;
  1357. }
  1358. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1359. if (ret) {
  1360. wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret);
  1361. goto out;
  1362. }
  1363. out:
  1364. mutex_unlock(&wcn->hal_mutex);
  1365. return ret;
  1366. }
  1367. static inline void set_feat_caps(u32 *bitmap,
  1368. enum place_holder_in_cap_bitmap cap)
  1369. {
  1370. int arr_idx, bit_idx;
  1371. if (cap < 0 || cap > 127) {
  1372. wcn36xx_warn("error cap idx %d\n", cap);
  1373. return;
  1374. }
  1375. arr_idx = cap / 32;
  1376. bit_idx = cap % 32;
  1377. bitmap[arr_idx] |= (1 << bit_idx);
  1378. }
  1379. static inline int get_feat_caps(u32 *bitmap,
  1380. enum place_holder_in_cap_bitmap cap)
  1381. {
  1382. int arr_idx, bit_idx;
  1383. int ret = 0;
  1384. if (cap < 0 || cap > 127) {
  1385. wcn36xx_warn("error cap idx %d\n", cap);
  1386. return -EINVAL;
  1387. }
  1388. arr_idx = cap / 32;
  1389. bit_idx = cap % 32;
  1390. ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0;
  1391. return ret;
  1392. }
  1393. static inline void clear_feat_caps(u32 *bitmap,
  1394. enum place_holder_in_cap_bitmap cap)
  1395. {
  1396. int arr_idx, bit_idx;
  1397. if (cap < 0 || cap > 127) {
  1398. wcn36xx_warn("error cap idx %d\n", cap);
  1399. return;
  1400. }
  1401. arr_idx = cap / 32;
  1402. bit_idx = cap % 32;
  1403. bitmap[arr_idx] &= ~(1 << bit_idx);
  1404. }
  1405. int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
  1406. {
  1407. struct wcn36xx_hal_feat_caps_msg msg_body;
  1408. int ret = 0;
  1409. mutex_lock(&wcn->hal_mutex);
  1410. INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
  1411. set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
  1412. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1413. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1414. if (ret) {
  1415. wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
  1416. goto out;
  1417. }
  1418. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1419. if (ret) {
  1420. wcn36xx_err("hal_feature_caps_exchange response failed err=%d\n",
  1421. ret);
  1422. goto out;
  1423. }
  1424. out:
  1425. mutex_unlock(&wcn->hal_mutex);
  1426. return ret;
  1427. }
  1428. int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
  1429. struct ieee80211_sta *sta,
  1430. u16 tid,
  1431. u16 *ssn,
  1432. u8 direction,
  1433. u8 sta_index)
  1434. {
  1435. struct wcn36xx_hal_add_ba_session_req_msg msg_body;
  1436. int ret = 0;
  1437. mutex_lock(&wcn->hal_mutex);
  1438. INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
  1439. msg_body.sta_index = sta_index;
  1440. memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
  1441. msg_body.dialog_token = 0x10;
  1442. msg_body.tid = tid;
  1443. /* Immediate BA because Delayed BA is not supported */
  1444. msg_body.policy = 1;
  1445. msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
  1446. msg_body.timeout = 0;
  1447. if (ssn)
  1448. msg_body.ssn = *ssn;
  1449. msg_body.direction = direction;
  1450. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1451. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1452. if (ret) {
  1453. wcn36xx_err("Sending hal_add_ba_session failed\n");
  1454. goto out;
  1455. }
  1456. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1457. if (ret) {
  1458. wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
  1459. goto out;
  1460. }
  1461. out:
  1462. mutex_unlock(&wcn->hal_mutex);
  1463. return ret;
  1464. }
  1465. int wcn36xx_smd_add_ba(struct wcn36xx *wcn)
  1466. {
  1467. struct wcn36xx_hal_add_ba_req_msg msg_body;
  1468. int ret = 0;
  1469. mutex_lock(&wcn->hal_mutex);
  1470. INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
  1471. msg_body.session_id = 0;
  1472. msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
  1473. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1474. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1475. if (ret) {
  1476. wcn36xx_err("Sending hal_add_ba failed\n");
  1477. goto out;
  1478. }
  1479. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1480. if (ret) {
  1481. wcn36xx_err("hal_add_ba response failed err=%d\n", ret);
  1482. goto out;
  1483. }
  1484. out:
  1485. mutex_unlock(&wcn->hal_mutex);
  1486. return ret;
  1487. }
  1488. int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index)
  1489. {
  1490. struct wcn36xx_hal_del_ba_req_msg msg_body;
  1491. int ret = 0;
  1492. mutex_lock(&wcn->hal_mutex);
  1493. INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
  1494. msg_body.sta_index = sta_index;
  1495. msg_body.tid = tid;
  1496. msg_body.direction = 0;
  1497. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1498. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1499. if (ret) {
  1500. wcn36xx_err("Sending hal_del_ba failed\n");
  1501. goto out;
  1502. }
  1503. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1504. if (ret) {
  1505. wcn36xx_err("hal_del_ba response failed err=%d\n", ret);
  1506. goto out;
  1507. }
  1508. out:
  1509. mutex_unlock(&wcn->hal_mutex);
  1510. return ret;
  1511. }
  1512. int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
  1513. {
  1514. struct wcn36xx_hal_trigger_ba_req_msg msg_body;
  1515. struct wcn36xx_hal_trigget_ba_req_candidate *candidate;
  1516. int ret = 0;
  1517. mutex_lock(&wcn->hal_mutex);
  1518. INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
  1519. msg_body.session_id = 0;
  1520. msg_body.candidate_cnt = 1;
  1521. msg_body.header.len += sizeof(*candidate);
  1522. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1523. candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *)
  1524. (wcn->hal_buf + sizeof(msg_body));
  1525. candidate->sta_index = sta_index;
  1526. candidate->tid_bitmap = 1;
  1527. ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
  1528. if (ret) {
  1529. wcn36xx_err("Sending hal_trigger_ba failed\n");
  1530. goto out;
  1531. }
  1532. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1533. if (ret) {
  1534. wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
  1535. goto out;
  1536. }
  1537. out:
  1538. mutex_unlock(&wcn->hal_mutex);
  1539. return ret;
  1540. }
  1541. static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
  1542. {
  1543. struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf;
  1544. if (len != sizeof(*rsp)) {
  1545. wcn36xx_warn("Bad TX complete indication\n");
  1546. return -EIO;
  1547. }
  1548. wcn36xx_dxe_tx_ack_ind(wcn, rsp->status);
  1549. return 0;
  1550. }
  1551. static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
  1552. void *buf,
  1553. size_t len)
  1554. {
  1555. struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf;
  1556. struct ieee80211_vif *vif = NULL;
  1557. struct wcn36xx_vif *tmp;
  1558. /* Old FW does not have bss index */
  1559. if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
  1560. list_for_each_entry(tmp, &wcn->vif_list, list) {
  1561. wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
  1562. tmp->bss_index);
  1563. vif = container_of((void *)tmp,
  1564. struct ieee80211_vif,
  1565. drv_priv);
  1566. ieee80211_connection_loss(vif);
  1567. }
  1568. return 0;
  1569. }
  1570. if (len != sizeof(*rsp)) {
  1571. wcn36xx_warn("Corrupted missed beacon indication\n");
  1572. return -EIO;
  1573. }
  1574. list_for_each_entry(tmp, &wcn->vif_list, list) {
  1575. if (tmp->bss_index == rsp->bss_index) {
  1576. wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
  1577. rsp->bss_index);
  1578. vif = container_of((void *)tmp,
  1579. struct ieee80211_vif,
  1580. drv_priv);
  1581. ieee80211_connection_loss(vif);
  1582. return 0;
  1583. }
  1584. }
  1585. wcn36xx_warn("BSS index %d not found\n", rsp->bss_index);
  1586. return -ENOENT;
  1587. }
  1588. static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
  1589. void *buf,
  1590. size_t len)
  1591. {
  1592. struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
  1593. struct wcn36xx_vif *tmp;
  1594. struct ieee80211_sta *sta = NULL;
  1595. if (len != sizeof(*rsp)) {
  1596. wcn36xx_warn("Corrupted delete sta indication\n");
  1597. return -EIO;
  1598. }
  1599. list_for_each_entry(tmp, &wcn->vif_list, list) {
  1600. if (sta && (tmp->sta->sta_index == rsp->sta_id)) {
  1601. sta = container_of((void *)tmp->sta,
  1602. struct ieee80211_sta,
  1603. drv_priv);
  1604. wcn36xx_dbg(WCN36XX_DBG_HAL,
  1605. "delete station indication %pM index %d\n",
  1606. rsp->addr2,
  1607. rsp->sta_id);
  1608. ieee80211_report_low_ack(sta, 0);
  1609. return 0;
  1610. }
  1611. }
  1612. wcn36xx_warn("STA with addr %pM and index %d not found\n",
  1613. rsp->addr2,
  1614. rsp->sta_id);
  1615. return -ENOENT;
  1616. }
  1617. int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
  1618. {
  1619. struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
  1620. size_t len;
  1621. int ret = 0;
  1622. mutex_lock(&wcn->hal_mutex);
  1623. INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
  1624. PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
  1625. body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf;
  1626. len = msg_body.header.len;
  1627. put_cfg_tlv_u32(wcn, &len, cfg_id, value);
  1628. body->header.len = len;
  1629. body->len = len - sizeof(*body);
  1630. ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
  1631. if (ret) {
  1632. wcn36xx_err("Sending hal_update_cfg failed\n");
  1633. goto out;
  1634. }
  1635. ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
  1636. if (ret) {
  1637. wcn36xx_err("hal_update_cfg response failed err=%d\n", ret);
  1638. goto out;
  1639. }
  1640. out:
  1641. mutex_unlock(&wcn->hal_mutex);
  1642. return ret;
  1643. }
  1644. static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
  1645. {
  1646. struct wcn36xx_hal_msg_header *msg_header = buf;
  1647. struct wcn36xx_hal_ind_msg *msg_ind;
  1648. wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
  1649. switch (msg_header->msg_type) {
  1650. case WCN36XX_HAL_START_RSP:
  1651. case WCN36XX_HAL_CONFIG_STA_RSP:
  1652. case WCN36XX_HAL_CONFIG_BSS_RSP:
  1653. case WCN36XX_HAL_ADD_STA_SELF_RSP:
  1654. case WCN36XX_HAL_STOP_RSP:
  1655. case WCN36XX_HAL_DEL_STA_SELF_RSP:
  1656. case WCN36XX_HAL_DELETE_STA_RSP:
  1657. case WCN36XX_HAL_INIT_SCAN_RSP:
  1658. case WCN36XX_HAL_START_SCAN_RSP:
  1659. case WCN36XX_HAL_END_SCAN_RSP:
  1660. case WCN36XX_HAL_FINISH_SCAN_RSP:
  1661. case WCN36XX_HAL_DOWNLOAD_NV_RSP:
  1662. case WCN36XX_HAL_DELETE_BSS_RSP:
  1663. case WCN36XX_HAL_SEND_BEACON_RSP:
  1664. case WCN36XX_HAL_SET_LINK_ST_RSP:
  1665. case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP:
  1666. case WCN36XX_HAL_SET_BSSKEY_RSP:
  1667. case WCN36XX_HAL_SET_STAKEY_RSP:
  1668. case WCN36XX_HAL_RMV_STAKEY_RSP:
  1669. case WCN36XX_HAL_RMV_BSSKEY_RSP:
  1670. case WCN36XX_HAL_ENTER_BMPS_RSP:
  1671. case WCN36XX_HAL_SET_POWER_PARAMS_RSP:
  1672. case WCN36XX_HAL_EXIT_BMPS_RSP:
  1673. case WCN36XX_HAL_KEEP_ALIVE_RSP:
  1674. case WCN36XX_HAL_DUMP_COMMAND_RSP:
  1675. case WCN36XX_HAL_ADD_BA_SESSION_RSP:
  1676. case WCN36XX_HAL_ADD_BA_RSP:
  1677. case WCN36XX_HAL_DEL_BA_RSP:
  1678. case WCN36XX_HAL_TRIGGER_BA_RSP:
  1679. case WCN36XX_HAL_UPDATE_CFG_RSP:
  1680. case WCN36XX_HAL_JOIN_RSP:
  1681. case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
  1682. case WCN36XX_HAL_CH_SWITCH_RSP:
  1683. case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
  1684. memcpy(wcn->hal_buf, buf, len);
  1685. wcn->hal_rsp_len = len;
  1686. complete(&wcn->hal_rsp_compl);
  1687. break;
  1688. case WCN36XX_HAL_OTA_TX_COMPL_IND:
  1689. case WCN36XX_HAL_MISSED_BEACON_IND:
  1690. case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
  1691. mutex_lock(&wcn->hal_ind_mutex);
  1692. msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
  1693. msg_ind->msg_len = len;
  1694. msg_ind->msg = kmalloc(len, GFP_KERNEL);
  1695. memcpy(msg_ind->msg, buf, len);
  1696. list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
  1697. queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
  1698. wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
  1699. mutex_unlock(&wcn->hal_ind_mutex);
  1700. break;
  1701. default:
  1702. wcn36xx_err("SMD_EVENT (%d) not supported\n",
  1703. msg_header->msg_type);
  1704. }
  1705. }
  1706. static void wcn36xx_ind_smd_work(struct work_struct *work)
  1707. {
  1708. struct wcn36xx *wcn =
  1709. container_of(work, struct wcn36xx, hal_ind_work);
  1710. struct wcn36xx_hal_msg_header *msg_header;
  1711. struct wcn36xx_hal_ind_msg *hal_ind_msg;
  1712. mutex_lock(&wcn->hal_ind_mutex);
  1713. hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
  1714. struct wcn36xx_hal_ind_msg,
  1715. list);
  1716. msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
  1717. switch (msg_header->msg_type) {
  1718. case WCN36XX_HAL_OTA_TX_COMPL_IND:
  1719. wcn36xx_smd_tx_compl_ind(wcn,
  1720. hal_ind_msg->msg,
  1721. hal_ind_msg->msg_len);
  1722. break;
  1723. case WCN36XX_HAL_MISSED_BEACON_IND:
  1724. wcn36xx_smd_missed_beacon_ind(wcn,
  1725. hal_ind_msg->msg,
  1726. hal_ind_msg->msg_len);
  1727. break;
  1728. case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
  1729. wcn36xx_smd_delete_sta_context_ind(wcn,
  1730. hal_ind_msg->msg,
  1731. hal_ind_msg->msg_len);
  1732. break;
  1733. default:
  1734. wcn36xx_err("SMD_EVENT (%d) not supported\n",
  1735. msg_header->msg_type);
  1736. }
  1737. list_del(wcn->hal_ind_queue.next);
  1738. kfree(hal_ind_msg->msg);
  1739. kfree(hal_ind_msg);
  1740. mutex_unlock(&wcn->hal_ind_mutex);
  1741. }
  1742. int wcn36xx_smd_open(struct wcn36xx *wcn)
  1743. {
  1744. int ret = 0;
  1745. wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
  1746. if (!wcn->hal_ind_wq) {
  1747. wcn36xx_err("failed to allocate wq\n");
  1748. ret = -ENOMEM;
  1749. goto out;
  1750. }
  1751. INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
  1752. INIT_LIST_HEAD(&wcn->hal_ind_queue);
  1753. mutex_init(&wcn->hal_ind_mutex);
  1754. ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
  1755. if (ret) {
  1756. wcn36xx_err("failed to open control channel\n");
  1757. goto free_wq;
  1758. }
  1759. return ret;
  1760. free_wq:
  1761. destroy_workqueue(wcn->hal_ind_wq);
  1762. out:
  1763. return ret;
  1764. }
  1765. void wcn36xx_smd_close(struct wcn36xx *wcn)
  1766. {
  1767. wcn->ctrl_ops->close();
  1768. destroy_workqueue(wcn->hal_ind_wq);
  1769. mutex_destroy(&wcn->hal_ind_mutex);
  1770. }