main.c 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691
  1. /*
  2. * Copyright (c) 2013 Eugene Krasnikov <[email protected]>
  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/module.h>
  18. #include <linux/firmware.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/of_address.h>
  21. #include <linux/of_device.h>
  22. #include <linux/of_irq.h>
  23. #include <linux/rpmsg.h>
  24. #include <linux/soc/qcom/smem_state.h>
  25. #include <linux/soc/qcom/wcnss_ctrl.h>
  26. #include <net/ipv6.h>
  27. #include "wcn36xx.h"
  28. #include "testmode.h"
  29. #include "firmware.h"
  30. unsigned int wcn36xx_dbg_mask;
  31. module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644);
  32. MODULE_PARM_DESC(debug_mask, "Debugging mask");
  33. #define CHAN2G(_freq, _idx) { \
  34. .band = NL80211_BAND_2GHZ, \
  35. .center_freq = (_freq), \
  36. .hw_value = (_idx), \
  37. .max_power = 25, \
  38. }
  39. #define CHAN5G(_freq, _idx, _phy_val) { \
  40. .band = NL80211_BAND_5GHZ, \
  41. .center_freq = (_freq), \
  42. .hw_value = (_phy_val) << HW_VALUE_PHY_SHIFT | HW_VALUE_CHANNEL(_idx), \
  43. .max_power = 25, \
  44. }
  45. /* The wcn firmware expects channel values to matching
  46. * their mnemonic values. So use these for .hw_value. */
  47. static struct ieee80211_channel wcn_2ghz_channels[] = {
  48. CHAN2G(2412, 1), /* Channel 1 */
  49. CHAN2G(2417, 2), /* Channel 2 */
  50. CHAN2G(2422, 3), /* Channel 3 */
  51. CHAN2G(2427, 4), /* Channel 4 */
  52. CHAN2G(2432, 5), /* Channel 5 */
  53. CHAN2G(2437, 6), /* Channel 6 */
  54. CHAN2G(2442, 7), /* Channel 7 */
  55. CHAN2G(2447, 8), /* Channel 8 */
  56. CHAN2G(2452, 9), /* Channel 9 */
  57. CHAN2G(2457, 10), /* Channel 10 */
  58. CHAN2G(2462, 11), /* Channel 11 */
  59. CHAN2G(2467, 12), /* Channel 12 */
  60. CHAN2G(2472, 13), /* Channel 13 */
  61. CHAN2G(2484, 14) /* Channel 14 */
  62. };
  63. static struct ieee80211_channel wcn_5ghz_channels[] = {
  64. CHAN5G(5180, 36, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  65. CHAN5G(5200, 40, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
  66. CHAN5G(5220, 44, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  67. CHAN5G(5240, 48, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
  68. CHAN5G(5260, 52, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  69. CHAN5G(5280, 56, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
  70. CHAN5G(5300, 60, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  71. CHAN5G(5320, 64, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
  72. CHAN5G(5500, 100, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  73. CHAN5G(5520, 104, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
  74. CHAN5G(5540, 108, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  75. CHAN5G(5560, 112, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
  76. CHAN5G(5580, 116, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  77. CHAN5G(5600, 120, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
  78. CHAN5G(5620, 124, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  79. CHAN5G(5640, 128, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
  80. CHAN5G(5660, 132, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  81. CHAN5G(5680, 136, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
  82. CHAN5G(5700, 140, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  83. CHAN5G(5720, 144, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
  84. CHAN5G(5745, 149, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
  85. CHAN5G(5765, 153, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
  86. CHAN5G(5785, 157, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
  87. CHAN5G(5805, 161, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
  88. CHAN5G(5825, 165, 0)
  89. };
  90. #define RATE(_bitrate, _hw_rate, _flags) { \
  91. .bitrate = (_bitrate), \
  92. .flags = (_flags), \
  93. .hw_value = (_hw_rate), \
  94. .hw_value_short = (_hw_rate) \
  95. }
  96. static struct ieee80211_rate wcn_2ghz_rates[] = {
  97. RATE(10, HW_RATE_INDEX_1MBPS, 0),
  98. RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
  99. RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
  100. RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
  101. RATE(60, HW_RATE_INDEX_6MBPS, 0),
  102. RATE(90, HW_RATE_INDEX_9MBPS, 0),
  103. RATE(120, HW_RATE_INDEX_12MBPS, 0),
  104. RATE(180, HW_RATE_INDEX_18MBPS, 0),
  105. RATE(240, HW_RATE_INDEX_24MBPS, 0),
  106. RATE(360, HW_RATE_INDEX_36MBPS, 0),
  107. RATE(480, HW_RATE_INDEX_48MBPS, 0),
  108. RATE(540, HW_RATE_INDEX_54MBPS, 0)
  109. };
  110. static struct ieee80211_rate wcn_5ghz_rates[] = {
  111. RATE(60, HW_RATE_INDEX_6MBPS, 0),
  112. RATE(90, HW_RATE_INDEX_9MBPS, 0),
  113. RATE(120, HW_RATE_INDEX_12MBPS, 0),
  114. RATE(180, HW_RATE_INDEX_18MBPS, 0),
  115. RATE(240, HW_RATE_INDEX_24MBPS, 0),
  116. RATE(360, HW_RATE_INDEX_36MBPS, 0),
  117. RATE(480, HW_RATE_INDEX_48MBPS, 0),
  118. RATE(540, HW_RATE_INDEX_54MBPS, 0)
  119. };
  120. static struct ieee80211_supported_band wcn_band_2ghz = {
  121. .channels = wcn_2ghz_channels,
  122. .n_channels = ARRAY_SIZE(wcn_2ghz_channels),
  123. .bitrates = wcn_2ghz_rates,
  124. .n_bitrates = ARRAY_SIZE(wcn_2ghz_rates),
  125. .ht_cap = {
  126. .cap = IEEE80211_HT_CAP_GRN_FLD |
  127. IEEE80211_HT_CAP_SGI_20 |
  128. IEEE80211_HT_CAP_DSSSCCK40 |
  129. IEEE80211_HT_CAP_LSIG_TXOP_PROT |
  130. IEEE80211_HT_CAP_SGI_40 |
  131. IEEE80211_HT_CAP_SUP_WIDTH_20_40,
  132. .ht_supported = true,
  133. .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
  134. .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
  135. .mcs = {
  136. .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
  137. .rx_highest = cpu_to_le16(72),
  138. .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
  139. }
  140. }
  141. };
  142. static struct ieee80211_supported_band wcn_band_5ghz = {
  143. .channels = wcn_5ghz_channels,
  144. .n_channels = ARRAY_SIZE(wcn_5ghz_channels),
  145. .bitrates = wcn_5ghz_rates,
  146. .n_bitrates = ARRAY_SIZE(wcn_5ghz_rates),
  147. .ht_cap = {
  148. .cap = IEEE80211_HT_CAP_GRN_FLD |
  149. IEEE80211_HT_CAP_SGI_20 |
  150. IEEE80211_HT_CAP_DSSSCCK40 |
  151. IEEE80211_HT_CAP_LSIG_TXOP_PROT |
  152. IEEE80211_HT_CAP_SGI_40 |
  153. IEEE80211_HT_CAP_SUP_WIDTH_20_40,
  154. .ht_supported = true,
  155. .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
  156. .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
  157. .mcs = {
  158. .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
  159. .rx_highest = cpu_to_le16(150),
  160. .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
  161. }
  162. }
  163. };
  164. #ifdef CONFIG_PM
  165. static const struct wiphy_wowlan_support wowlan_support = {
  166. .flags = WIPHY_WOWLAN_ANY |
  167. WIPHY_WOWLAN_MAGIC_PKT |
  168. WIPHY_WOWLAN_SUPPORTS_GTK_REKEY
  169. };
  170. #endif
  171. static inline u8 get_sta_index(struct ieee80211_vif *vif,
  172. struct wcn36xx_sta *sta_priv)
  173. {
  174. return NL80211_IFTYPE_STATION == vif->type ?
  175. sta_priv->bss_sta_index :
  176. sta_priv->sta_index;
  177. }
  178. static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
  179. {
  180. int i;
  181. for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) {
  182. if (wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, i)) {
  183. wcn36xx_dbg(WCN36XX_DBG_MAC, "FW Cap %s\n",
  184. wcn36xx_firmware_get_cap_name(i));
  185. }
  186. }
  187. }
  188. static int wcn36xx_start(struct ieee80211_hw *hw)
  189. {
  190. struct wcn36xx *wcn = hw->priv;
  191. int ret;
  192. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n");
  193. /* SMD initialization */
  194. ret = wcn36xx_smd_open(wcn);
  195. if (ret) {
  196. wcn36xx_err("Failed to open smd channel: %d\n", ret);
  197. goto out_err;
  198. }
  199. /* Allocate memory pools for Mgmt BD headers and Data BD headers */
  200. ret = wcn36xx_dxe_allocate_mem_pools(wcn);
  201. if (ret) {
  202. wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret);
  203. goto out_smd_close;
  204. }
  205. ret = wcn36xx_dxe_alloc_ctl_blks(wcn);
  206. if (ret) {
  207. wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret);
  208. goto out_free_dxe_pool;
  209. }
  210. ret = wcn36xx_smd_load_nv(wcn);
  211. if (ret) {
  212. wcn36xx_err("Failed to push NV to chip\n");
  213. goto out_free_dxe_ctl;
  214. }
  215. ret = wcn36xx_smd_start(wcn);
  216. if (ret) {
  217. wcn36xx_err("Failed to start chip\n");
  218. goto out_free_dxe_ctl;
  219. }
  220. if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
  221. ret = wcn36xx_smd_feature_caps_exchange(wcn);
  222. if (ret)
  223. wcn36xx_warn("Exchange feature caps failed\n");
  224. else
  225. wcn36xx_feat_caps_info(wcn);
  226. }
  227. /* DMA channel initialization */
  228. ret = wcn36xx_dxe_init(wcn);
  229. if (ret) {
  230. wcn36xx_err("DXE init failed\n");
  231. goto out_smd_stop;
  232. }
  233. wcn36xx_debugfs_init(wcn);
  234. INIT_LIST_HEAD(&wcn->vif_list);
  235. spin_lock_init(&wcn->dxe_lock);
  236. spin_lock_init(&wcn->survey_lock);
  237. return 0;
  238. out_smd_stop:
  239. wcn36xx_smd_stop(wcn);
  240. out_free_dxe_ctl:
  241. wcn36xx_dxe_free_ctl_blks(wcn);
  242. out_free_dxe_pool:
  243. wcn36xx_dxe_free_mem_pools(wcn);
  244. out_smd_close:
  245. wcn36xx_smd_close(wcn);
  246. out_err:
  247. return ret;
  248. }
  249. static void wcn36xx_stop(struct ieee80211_hw *hw)
  250. {
  251. struct wcn36xx *wcn = hw->priv;
  252. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n");
  253. mutex_lock(&wcn->scan_lock);
  254. if (wcn->scan_req) {
  255. struct cfg80211_scan_info scan_info = {
  256. .aborted = true,
  257. };
  258. ieee80211_scan_completed(wcn->hw, &scan_info);
  259. }
  260. wcn->scan_req = NULL;
  261. mutex_unlock(&wcn->scan_lock);
  262. wcn36xx_debugfs_exit(wcn);
  263. wcn36xx_smd_stop(wcn);
  264. wcn36xx_dxe_deinit(wcn);
  265. wcn36xx_smd_close(wcn);
  266. wcn36xx_dxe_free_mem_pools(wcn);
  267. wcn36xx_dxe_free_ctl_blks(wcn);
  268. }
  269. static void wcn36xx_change_ps(struct wcn36xx *wcn, bool enable)
  270. {
  271. struct ieee80211_vif *vif = NULL;
  272. struct wcn36xx_vif *tmp;
  273. list_for_each_entry(tmp, &wcn->vif_list, list) {
  274. vif = wcn36xx_priv_to_vif(tmp);
  275. if (enable && !wcn->sw_scan) {
  276. if (vif->cfg.ps) /* ps allowed ? */
  277. wcn36xx_pmc_enter_bmps_state(wcn, vif);
  278. } else {
  279. wcn36xx_pmc_exit_bmps_state(wcn, vif);
  280. }
  281. }
  282. }
  283. static void wcn36xx_change_opchannel(struct wcn36xx *wcn, int ch)
  284. {
  285. struct ieee80211_vif *vif = NULL;
  286. struct wcn36xx_vif *tmp;
  287. struct ieee80211_supported_band *band;
  288. struct ieee80211_channel *channel = NULL;
  289. unsigned long flags;
  290. int i, j;
  291. for (i = 0; i < ARRAY_SIZE(wcn->hw->wiphy->bands); i++) {
  292. band = wcn->hw->wiphy->bands[i];
  293. if (!band)
  294. break;
  295. for (j = 0; j < band->n_channels; j++) {
  296. if (HW_VALUE_CHANNEL(band->channels[j].hw_value) == ch) {
  297. channel = &band->channels[j];
  298. break;
  299. }
  300. }
  301. if (channel)
  302. break;
  303. }
  304. if (!channel) {
  305. wcn36xx_err("Cannot tune to channel %d\n", ch);
  306. return;
  307. }
  308. spin_lock_irqsave(&wcn->survey_lock, flags);
  309. wcn->band = band;
  310. wcn->channel = channel;
  311. spin_unlock_irqrestore(&wcn->survey_lock, flags);
  312. list_for_each_entry(tmp, &wcn->vif_list, list) {
  313. vif = wcn36xx_priv_to_vif(tmp);
  314. wcn36xx_smd_switch_channel(wcn, vif, ch);
  315. }
  316. return;
  317. }
  318. static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
  319. {
  320. struct wcn36xx *wcn = hw->priv;
  321. int ret;
  322. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
  323. mutex_lock(&wcn->conf_mutex);
  324. if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
  325. int ch = WCN36XX_HW_CHANNEL(wcn);
  326. wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
  327. ch);
  328. if (wcn->sw_scan_opchannel == ch && wcn->sw_scan_channel) {
  329. /* If channel is the initial operating channel, we may
  330. * want to receive/transmit regular data packets, then
  331. * simply stop the scan session and exit PS mode.
  332. */
  333. if (wcn->sw_scan_channel)
  334. wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel);
  335. if (wcn->sw_scan_init) {
  336. wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN,
  337. wcn->sw_scan_vif);
  338. }
  339. } else if (wcn->sw_scan) {
  340. /* A scan is ongoing, do not change the operating
  341. * channel, but start a scan session on the channel.
  342. */
  343. if (wcn->sw_scan_channel)
  344. wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel);
  345. if (!wcn->sw_scan_init) {
  346. /* This can fail if we are unable to notify the
  347. * operating channel.
  348. */
  349. ret = wcn36xx_smd_init_scan(wcn,
  350. HAL_SYS_MODE_SCAN,
  351. wcn->sw_scan_vif);
  352. if (ret) {
  353. mutex_unlock(&wcn->conf_mutex);
  354. return -EIO;
  355. }
  356. }
  357. wcn36xx_smd_start_scan(wcn, ch);
  358. } else {
  359. wcn36xx_change_opchannel(wcn, ch);
  360. }
  361. }
  362. if (changed & IEEE80211_CONF_CHANGE_PS)
  363. wcn36xx_change_ps(wcn, hw->conf.flags & IEEE80211_CONF_PS);
  364. if (changed & IEEE80211_CONF_CHANGE_IDLE) {
  365. if (hw->conf.flags & IEEE80211_CONF_IDLE)
  366. wcn36xx_smd_enter_imps(wcn);
  367. else
  368. wcn36xx_smd_exit_imps(wcn);
  369. }
  370. mutex_unlock(&wcn->conf_mutex);
  371. return 0;
  372. }
  373. static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
  374. unsigned int changed,
  375. unsigned int *total, u64 multicast)
  376. {
  377. struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
  378. struct wcn36xx *wcn = hw->priv;
  379. struct wcn36xx_vif *tmp;
  380. struct ieee80211_vif *vif = NULL;
  381. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
  382. mutex_lock(&wcn->conf_mutex);
  383. *total &= FIF_ALLMULTI;
  384. fp = (void *)(unsigned long)multicast;
  385. list_for_each_entry(tmp, &wcn->vif_list, list) {
  386. vif = wcn36xx_priv_to_vif(tmp);
  387. /* FW handles MC filtering only when connected as STA */
  388. if (*total & FIF_ALLMULTI)
  389. wcn36xx_smd_set_mc_list(wcn, vif, NULL);
  390. else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc)
  391. wcn36xx_smd_set_mc_list(wcn, vif, fp);
  392. }
  393. mutex_unlock(&wcn->conf_mutex);
  394. kfree(fp);
  395. }
  396. static u64 wcn36xx_prepare_multicast(struct ieee80211_hw *hw,
  397. struct netdev_hw_addr_list *mc_list)
  398. {
  399. struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
  400. struct netdev_hw_addr *ha;
  401. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac prepare multicast list\n");
  402. fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
  403. if (!fp) {
  404. wcn36xx_err("Out of memory setting filters.\n");
  405. return 0;
  406. }
  407. fp->mc_addr_count = 0;
  408. /* update multicast filtering parameters */
  409. if (netdev_hw_addr_list_count(mc_list) <=
  410. WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS) {
  411. netdev_hw_addr_list_for_each(ha, mc_list) {
  412. memcpy(fp->mc_addr[fp->mc_addr_count],
  413. ha->addr, ETH_ALEN);
  414. fp->mc_addr_count++;
  415. }
  416. }
  417. return (u64)(unsigned long)fp;
  418. }
  419. static void wcn36xx_tx(struct ieee80211_hw *hw,
  420. struct ieee80211_tx_control *control,
  421. struct sk_buff *skb)
  422. {
  423. struct wcn36xx *wcn = hw->priv;
  424. struct wcn36xx_sta *sta_priv = NULL;
  425. if (control->sta)
  426. sta_priv = wcn36xx_sta_to_priv(control->sta);
  427. if (wcn36xx_start_tx(wcn, sta_priv, skb))
  428. ieee80211_free_txskb(wcn->hw, skb);
  429. }
  430. static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
  431. struct ieee80211_vif *vif,
  432. struct ieee80211_sta *sta,
  433. struct ieee80211_key_conf *key_conf)
  434. {
  435. struct wcn36xx *wcn = hw->priv;
  436. struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
  437. struct wcn36xx_sta *sta_priv = sta ? wcn36xx_sta_to_priv(sta) : NULL;
  438. int ret = 0;
  439. u8 key[WLAN_MAX_KEY_LEN];
  440. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n");
  441. wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n",
  442. cmd, key_conf->cipher, key_conf->keyidx,
  443. key_conf->keylen, key_conf->flags);
  444. wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ",
  445. key_conf->key,
  446. key_conf->keylen);
  447. mutex_lock(&wcn->conf_mutex);
  448. switch (key_conf->cipher) {
  449. case WLAN_CIPHER_SUITE_WEP40:
  450. vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
  451. break;
  452. case WLAN_CIPHER_SUITE_WEP104:
  453. vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP104;
  454. break;
  455. case WLAN_CIPHER_SUITE_CCMP:
  456. vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP;
  457. break;
  458. case WLAN_CIPHER_SUITE_TKIP:
  459. vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP;
  460. break;
  461. default:
  462. wcn36xx_err("Unsupported key type 0x%x\n",
  463. key_conf->cipher);
  464. ret = -EOPNOTSUPP;
  465. goto out;
  466. }
  467. switch (cmd) {
  468. case SET_KEY:
  469. if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) {
  470. /*
  471. * Supplicant is sending key in the wrong order:
  472. * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b)
  473. * but HW expects it to be in the order as described in
  474. * IEEE 802.11 spec (see chapter 11.7) like this:
  475. * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b)
  476. */
  477. memcpy(key, key_conf->key, 16);
  478. memcpy(key + 16, key_conf->key + 24, 8);
  479. memcpy(key + 24, key_conf->key + 16, 8);
  480. } else {
  481. memcpy(key, key_conf->key, key_conf->keylen);
  482. }
  483. if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) {
  484. sta_priv->is_data_encrypted = true;
  485. /* Reconfigure bss with encrypt_type */
  486. if (NL80211_IFTYPE_STATION == vif->type) {
  487. wcn36xx_smd_config_bss(wcn,
  488. vif,
  489. sta,
  490. sta->addr,
  491. true);
  492. wcn36xx_smd_config_sta(wcn, vif, sta);
  493. }
  494. wcn36xx_smd_set_stakey(wcn,
  495. vif_priv->encrypt_type,
  496. key_conf->keyidx,
  497. key_conf->keylen,
  498. key,
  499. get_sta_index(vif, sta_priv));
  500. } else {
  501. wcn36xx_smd_set_bsskey(wcn,
  502. vif_priv->encrypt_type,
  503. vif_priv->bss_index,
  504. key_conf->keyidx,
  505. key_conf->keylen,
  506. key);
  507. if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
  508. (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
  509. list_for_each_entry(sta_priv,
  510. &vif_priv->sta_list, list) {
  511. sta_priv->is_data_encrypted = true;
  512. wcn36xx_smd_set_stakey(wcn,
  513. vif_priv->encrypt_type,
  514. key_conf->keyidx,
  515. key_conf->keylen,
  516. key,
  517. get_sta_index(vif, sta_priv));
  518. }
  519. }
  520. }
  521. break;
  522. case DISABLE_KEY:
  523. if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
  524. if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX)
  525. wcn36xx_smd_remove_bsskey(wcn,
  526. vif_priv->encrypt_type,
  527. vif_priv->bss_index,
  528. key_conf->keyidx);
  529. vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
  530. } else {
  531. sta_priv->is_data_encrypted = false;
  532. /* do not remove key if disassociated */
  533. if (sta_priv->aid)
  534. wcn36xx_smd_remove_stakey(wcn,
  535. vif_priv->encrypt_type,
  536. key_conf->keyidx,
  537. get_sta_index(vif, sta_priv));
  538. }
  539. break;
  540. default:
  541. wcn36xx_err("Unsupported key cmd 0x%x\n", cmd);
  542. ret = -EOPNOTSUPP;
  543. goto out;
  544. }
  545. out:
  546. mutex_unlock(&wcn->conf_mutex);
  547. return ret;
  548. }
  549. static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
  550. struct ieee80211_vif *vif,
  551. struct ieee80211_scan_request *hw_req)
  552. {
  553. struct wcn36xx *wcn = hw->priv;
  554. if (!wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
  555. /* fallback to mac80211 software scan */
  556. return 1;
  557. }
  558. /* Firmware scan offload is limited to 48 channels, fallback to
  559. * software driven scanning otherwise.
  560. */
  561. if (hw_req->req.n_channels > 48) {
  562. wcn36xx_warn("Offload scan aborted, n_channels=%u",
  563. hw_req->req.n_channels);
  564. return 1;
  565. }
  566. mutex_lock(&wcn->scan_lock);
  567. if (wcn->scan_req) {
  568. mutex_unlock(&wcn->scan_lock);
  569. return -EBUSY;
  570. }
  571. wcn->scan_aborted = false;
  572. wcn->scan_req = &hw_req->req;
  573. mutex_unlock(&wcn->scan_lock);
  574. wcn36xx_smd_update_channel_list(wcn, &hw_req->req);
  575. return wcn36xx_smd_start_hw_scan(wcn, vif, &hw_req->req);
  576. }
  577. static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw,
  578. struct ieee80211_vif *vif)
  579. {
  580. struct wcn36xx *wcn = hw->priv;
  581. mutex_lock(&wcn->scan_lock);
  582. wcn->scan_aborted = true;
  583. mutex_unlock(&wcn->scan_lock);
  584. if (wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
  585. /* ieee80211_scan_completed will be called on FW scan
  586. * indication */
  587. wcn36xx_smd_stop_hw_scan(wcn);
  588. }
  589. }
  590. static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
  591. struct ieee80211_vif *vif,
  592. const u8 *mac_addr)
  593. {
  594. struct wcn36xx *wcn = hw->priv;
  595. struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
  596. wcn36xx_dbg(WCN36XX_DBG_MAC, "sw_scan_start");
  597. wcn->sw_scan = true;
  598. wcn->sw_scan_vif = vif;
  599. wcn->sw_scan_channel = 0;
  600. if (vif_priv->sta_assoc)
  601. wcn->sw_scan_opchannel = WCN36XX_HW_CHANNEL(wcn);
  602. else
  603. wcn->sw_scan_opchannel = 0;
  604. }
  605. static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
  606. struct ieee80211_vif *vif)
  607. {
  608. struct wcn36xx *wcn = hw->priv;
  609. wcn36xx_dbg(WCN36XX_DBG_MAC, "sw_scan_complete");
  610. /* ensure that any scan session is finished */
  611. if (wcn->sw_scan_channel)
  612. wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel);
  613. if (wcn->sw_scan_init) {
  614. wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN,
  615. wcn->sw_scan_vif);
  616. }
  617. wcn->sw_scan = false;
  618. wcn->sw_scan_opchannel = 0;
  619. }
  620. static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
  621. enum nl80211_band band)
  622. {
  623. int i, size;
  624. u16 *rates_table;
  625. struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
  626. u32 rates = sta->deflink.supp_rates[band];
  627. memset(&sta_priv->supported_rates, 0,
  628. sizeof(sta_priv->supported_rates));
  629. sta_priv->supported_rates.op_rate_mode = STA_11n;
  630. size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates);
  631. rates_table = sta_priv->supported_rates.dsss_rates;
  632. if (band == NL80211_BAND_2GHZ) {
  633. for (i = 0; i < size; i++) {
  634. if (rates & 0x01) {
  635. rates_table[i] = wcn_2ghz_rates[i].hw_value;
  636. rates = rates >> 1;
  637. }
  638. }
  639. }
  640. size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates);
  641. rates_table = sta_priv->supported_rates.ofdm_rates;
  642. for (i = 0; i < size; i++) {
  643. if (rates & 0x01) {
  644. rates_table[i] = wcn_5ghz_rates[i].hw_value;
  645. rates = rates >> 1;
  646. }
  647. }
  648. if (sta->deflink.ht_cap.ht_supported) {
  649. BUILD_BUG_ON(sizeof(sta->deflink.ht_cap.mcs.rx_mask) >
  650. sizeof(sta_priv->supported_rates.supported_mcs_set));
  651. memcpy(sta_priv->supported_rates.supported_mcs_set,
  652. sta->deflink.ht_cap.mcs.rx_mask,
  653. sizeof(sta->deflink.ht_cap.mcs.rx_mask));
  654. }
  655. if (sta->deflink.vht_cap.vht_supported) {
  656. sta_priv->supported_rates.op_rate_mode = STA_11ac;
  657. sta_priv->supported_rates.vht_rx_mcs_map =
  658. sta->deflink.vht_cap.vht_mcs.rx_mcs_map;
  659. sta_priv->supported_rates.vht_tx_mcs_map =
  660. sta->deflink.vht_cap.vht_mcs.tx_mcs_map;
  661. }
  662. }
  663. void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates)
  664. {
  665. u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = {
  666. HW_RATE_INDEX_6MBPS,
  667. HW_RATE_INDEX_9MBPS,
  668. HW_RATE_INDEX_12MBPS,
  669. HW_RATE_INDEX_18MBPS,
  670. HW_RATE_INDEX_24MBPS,
  671. HW_RATE_INDEX_36MBPS,
  672. HW_RATE_INDEX_48MBPS,
  673. HW_RATE_INDEX_54MBPS
  674. };
  675. u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = {
  676. HW_RATE_INDEX_1MBPS,
  677. HW_RATE_INDEX_2MBPS,
  678. HW_RATE_INDEX_5_5MBPS,
  679. HW_RATE_INDEX_11MBPS
  680. };
  681. rates->op_rate_mode = STA_11n;
  682. memcpy(rates->dsss_rates, dsss_rates,
  683. sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES);
  684. memcpy(rates->ofdm_rates, ofdm_rates,
  685. sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES);
  686. rates->supported_mcs_set[0] = 0xFF;
  687. }
  688. void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates)
  689. {
  690. rates->op_rate_mode = STA_11ac;
  691. rates->vht_rx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
  692. rates->vht_tx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
  693. }
  694. static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
  695. struct ieee80211_vif *vif,
  696. struct ieee80211_bss_conf *bss_conf,
  697. u64 changed)
  698. {
  699. struct wcn36xx *wcn = hw->priv;
  700. struct sk_buff *skb = NULL;
  701. u16 tim_off, tim_len;
  702. enum wcn36xx_hal_link_state link_state;
  703. struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
  704. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%llx\n",
  705. vif, changed);
  706. mutex_lock(&wcn->conf_mutex);
  707. if (changed & BSS_CHANGED_BEACON_INFO) {
  708. wcn36xx_dbg(WCN36XX_DBG_MAC,
  709. "mac bss changed dtim period %d\n",
  710. bss_conf->dtim_period);
  711. vif_priv->dtim_period = bss_conf->dtim_period;
  712. }
  713. if (changed & BSS_CHANGED_BSSID) {
  714. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n",
  715. bss_conf->bssid);
  716. if (!is_zero_ether_addr(bss_conf->bssid)) {
  717. vif_priv->is_joining = true;
  718. vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
  719. wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr,
  720. WCN36XX_HAL_LINK_PREASSOC_STATE);
  721. wcn36xx_smd_join(wcn, bss_conf->bssid,
  722. vif->addr, WCN36XX_HW_CHANNEL(wcn));
  723. wcn36xx_smd_config_bss(wcn, vif, NULL,
  724. bss_conf->bssid, false);
  725. } else {
  726. vif_priv->is_joining = false;
  727. wcn36xx_smd_delete_bss(wcn, vif);
  728. wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr,
  729. WCN36XX_HAL_LINK_IDLE_STATE);
  730. vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
  731. }
  732. }
  733. if (changed & BSS_CHANGED_SSID) {
  734. wcn36xx_dbg(WCN36XX_DBG_MAC,
  735. "mac bss changed ssid\n");
  736. wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ",
  737. vif->cfg.ssid, vif->cfg.ssid_len);
  738. vif_priv->ssid.length = vif->cfg.ssid_len;
  739. memcpy(&vif_priv->ssid.ssid,
  740. vif->cfg.ssid,
  741. vif->cfg.ssid_len);
  742. }
  743. if (changed & BSS_CHANGED_ASSOC) {
  744. vif_priv->is_joining = false;
  745. if (vif->cfg.assoc) {
  746. struct ieee80211_sta *sta;
  747. struct wcn36xx_sta *sta_priv;
  748. wcn36xx_dbg(WCN36XX_DBG_MAC,
  749. "mac assoc bss %pM vif %pM AID=%d\n",
  750. bss_conf->bssid,
  751. vif->addr,
  752. vif->cfg.aid);
  753. vif_priv->sta_assoc = true;
  754. /*
  755. * Holding conf_mutex ensures mutal exclusion with
  756. * wcn36xx_sta_remove() and as such ensures that sta
  757. * won't be freed while we're operating on it. As such
  758. * we do not need to hold the rcu_read_lock().
  759. */
  760. sta = ieee80211_find_sta(vif, bss_conf->bssid);
  761. if (!sta) {
  762. wcn36xx_err("sta %pM is not found\n",
  763. bss_conf->bssid);
  764. goto out;
  765. }
  766. sta_priv = wcn36xx_sta_to_priv(sta);
  767. wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
  768. wcn36xx_smd_set_link_st(wcn, bss_conf->bssid,
  769. vif->addr,
  770. WCN36XX_HAL_LINK_POSTASSOC_STATE);
  771. wcn36xx_smd_config_bss(wcn, vif, sta,
  772. bss_conf->bssid,
  773. true);
  774. sta_priv->aid = vif->cfg.aid;
  775. /*
  776. * config_sta must be called from because this is the
  777. * place where AID is available.
  778. */
  779. wcn36xx_smd_config_sta(wcn, vif, sta);
  780. if (vif->type == NL80211_IFTYPE_STATION)
  781. wcn36xx_smd_add_beacon_filter(wcn, vif);
  782. wcn36xx_enable_keep_alive_null_packet(wcn, vif);
  783. } else {
  784. wcn36xx_dbg(WCN36XX_DBG_MAC,
  785. "disassociated bss %pM vif %pM AID=%d\n",
  786. bss_conf->bssid,
  787. vif->addr,
  788. vif->cfg.aid);
  789. vif_priv->sta_assoc = false;
  790. wcn36xx_smd_set_link_st(wcn,
  791. bss_conf->bssid,
  792. vif->addr,
  793. WCN36XX_HAL_LINK_IDLE_STATE);
  794. }
  795. }
  796. if (changed & BSS_CHANGED_AP_PROBE_RESP) {
  797. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n");
  798. skb = ieee80211_proberesp_get(hw, vif);
  799. if (!skb) {
  800. wcn36xx_err("failed to alloc probereq skb\n");
  801. goto out;
  802. }
  803. wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb);
  804. dev_kfree_skb(skb);
  805. }
  806. if (changed & BSS_CHANGED_BEACON_ENABLED ||
  807. changed & BSS_CHANGED_BEACON) {
  808. wcn36xx_dbg(WCN36XX_DBG_MAC,
  809. "mac bss changed beacon enabled %d\n",
  810. bss_conf->enable_beacon);
  811. if (bss_conf->enable_beacon) {
  812. vif_priv->dtim_period = bss_conf->dtim_period;
  813. vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
  814. wcn36xx_smd_config_bss(wcn, vif, NULL,
  815. vif->addr, false);
  816. skb = ieee80211_beacon_get_tim(hw, vif, &tim_off,
  817. &tim_len, 0);
  818. if (!skb) {
  819. wcn36xx_err("failed to alloc beacon skb\n");
  820. goto out;
  821. }
  822. wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0);
  823. dev_kfree_skb(skb);
  824. if (vif->type == NL80211_IFTYPE_ADHOC ||
  825. vif->type == NL80211_IFTYPE_MESH_POINT)
  826. link_state = WCN36XX_HAL_LINK_IBSS_STATE;
  827. else
  828. link_state = WCN36XX_HAL_LINK_AP_STATE;
  829. wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
  830. link_state);
  831. } else {
  832. wcn36xx_smd_delete_bss(wcn, vif);
  833. wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
  834. WCN36XX_HAL_LINK_IDLE_STATE);
  835. }
  836. }
  837. out:
  838. mutex_unlock(&wcn->conf_mutex);
  839. }
  840. /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */
  841. static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
  842. {
  843. struct wcn36xx *wcn = hw->priv;
  844. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value);
  845. mutex_lock(&wcn->conf_mutex);
  846. wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value);
  847. mutex_unlock(&wcn->conf_mutex);
  848. return 0;
  849. }
  850. static void wcn36xx_remove_interface(struct ieee80211_hw *hw,
  851. struct ieee80211_vif *vif)
  852. {
  853. struct wcn36xx *wcn = hw->priv;
  854. struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
  855. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
  856. mutex_lock(&wcn->conf_mutex);
  857. list_del(&vif_priv->list);
  858. wcn36xx_smd_delete_sta_self(wcn, vif->addr);
  859. mutex_unlock(&wcn->conf_mutex);
  860. }
  861. static int wcn36xx_add_interface(struct ieee80211_hw *hw,
  862. struct ieee80211_vif *vif)
  863. {
  864. struct wcn36xx *wcn = hw->priv;
  865. struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
  866. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n",
  867. vif, vif->type);
  868. if (!(NL80211_IFTYPE_STATION == vif->type ||
  869. NL80211_IFTYPE_AP == vif->type ||
  870. NL80211_IFTYPE_ADHOC == vif->type ||
  871. NL80211_IFTYPE_MESH_POINT == vif->type)) {
  872. wcn36xx_warn("Unsupported interface type requested: %d\n",
  873. vif->type);
  874. return -EOPNOTSUPP;
  875. }
  876. mutex_lock(&wcn->conf_mutex);
  877. vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
  878. INIT_LIST_HEAD(&vif_priv->sta_list);
  879. list_add(&vif_priv->list, &wcn->vif_list);
  880. wcn36xx_smd_add_sta_self(wcn, vif);
  881. mutex_unlock(&wcn->conf_mutex);
  882. return 0;
  883. }
  884. static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  885. struct ieee80211_sta *sta)
  886. {
  887. struct wcn36xx *wcn = hw->priv;
  888. struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
  889. struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
  890. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
  891. vif, sta->addr);
  892. mutex_lock(&wcn->conf_mutex);
  893. spin_lock_init(&sta_priv->ampdu_lock);
  894. sta_priv->vif = vif_priv;
  895. list_add(&sta_priv->list, &vif_priv->sta_list);
  896. /*
  897. * For STA mode HW will be configured on BSS_CHANGED_ASSOC because
  898. * at this stage AID is not available yet.
  899. */
  900. if (NL80211_IFTYPE_STATION != vif->type) {
  901. wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
  902. sta_priv->aid = sta->aid;
  903. wcn36xx_smd_config_sta(wcn, vif, sta);
  904. }
  905. mutex_unlock(&wcn->conf_mutex);
  906. return 0;
  907. }
  908. static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
  909. struct ieee80211_vif *vif,
  910. struct ieee80211_sta *sta)
  911. {
  912. struct wcn36xx *wcn = hw->priv;
  913. struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
  914. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
  915. vif, sta->addr, sta_priv->sta_index);
  916. mutex_lock(&wcn->conf_mutex);
  917. list_del(&sta_priv->list);
  918. wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
  919. sta_priv->vif = NULL;
  920. mutex_unlock(&wcn->conf_mutex);
  921. return 0;
  922. }
  923. #ifdef CONFIG_PM
  924. static struct ieee80211_vif *wcn36xx_get_first_assoc_vif(struct wcn36xx *wcn)
  925. {
  926. struct wcn36xx_vif *vif_priv = NULL;
  927. struct ieee80211_vif *vif = NULL;
  928. list_for_each_entry(vif_priv, &wcn->vif_list, list) {
  929. if (vif_priv->sta_assoc) {
  930. vif = wcn36xx_priv_to_vif(vif_priv);
  931. break;
  932. }
  933. }
  934. return vif;
  935. }
  936. static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow)
  937. {
  938. struct wcn36xx *wcn = hw->priv;
  939. struct ieee80211_vif *vif = NULL;
  940. int ret = 0;
  941. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n");
  942. mutex_lock(&wcn->conf_mutex);
  943. vif = wcn36xx_get_first_assoc_vif(wcn);
  944. if (vif) {
  945. ret = wcn36xx_smd_arp_offload(wcn, vif, true);
  946. if (ret)
  947. goto out;
  948. ret = wcn36xx_smd_ipv6_ns_offload(wcn, vif, true);
  949. if (ret)
  950. goto out;
  951. ret = wcn36xx_smd_gtk_offload(wcn, vif, true);
  952. if (ret)
  953. goto out;
  954. ret = wcn36xx_smd_set_power_params(wcn, true);
  955. if (ret)
  956. goto out;
  957. ret = wcn36xx_smd_wlan_host_suspend_ind(wcn);
  958. }
  959. /* Disable IRQ, we don't want to handle any packet before mac80211 is
  960. * resumed and ready to receive packets.
  961. */
  962. disable_irq(wcn->tx_irq);
  963. disable_irq(wcn->rx_irq);
  964. out:
  965. mutex_unlock(&wcn->conf_mutex);
  966. return ret;
  967. }
  968. static int wcn36xx_resume(struct ieee80211_hw *hw)
  969. {
  970. struct wcn36xx *wcn = hw->priv;
  971. struct ieee80211_vif *vif = NULL;
  972. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n");
  973. mutex_lock(&wcn->conf_mutex);
  974. vif = wcn36xx_get_first_assoc_vif(wcn);
  975. if (vif) {
  976. wcn36xx_smd_host_resume(wcn);
  977. wcn36xx_smd_set_power_params(wcn, false);
  978. wcn36xx_smd_gtk_offload_get_info(wcn, vif);
  979. wcn36xx_smd_gtk_offload(wcn, vif, false);
  980. wcn36xx_smd_ipv6_ns_offload(wcn, vif, false);
  981. wcn36xx_smd_arp_offload(wcn, vif, false);
  982. }
  983. enable_irq(wcn->tx_irq);
  984. enable_irq(wcn->rx_irq);
  985. mutex_unlock(&wcn->conf_mutex);
  986. return 0;
  987. }
  988. static void wcn36xx_set_rekey_data(struct ieee80211_hw *hw,
  989. struct ieee80211_vif *vif,
  990. struct cfg80211_gtk_rekey_data *data)
  991. {
  992. struct wcn36xx *wcn = hw->priv;
  993. struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
  994. mutex_lock(&wcn->conf_mutex);
  995. memcpy(vif_priv->rekey_data.kek, data->kek, NL80211_KEK_LEN);
  996. memcpy(vif_priv->rekey_data.kck, data->kck, NL80211_KCK_LEN);
  997. vif_priv->rekey_data.replay_ctr =
  998. cpu_to_le64(be64_to_cpup((__be64 *)data->replay_ctr));
  999. vif_priv->rekey_data.valid = true;
  1000. mutex_unlock(&wcn->conf_mutex);
  1001. }
  1002. #endif
  1003. static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
  1004. struct ieee80211_vif *vif,
  1005. struct ieee80211_ampdu_params *params)
  1006. {
  1007. struct wcn36xx *wcn = hw->priv;
  1008. struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(params->sta);
  1009. struct ieee80211_sta *sta = params->sta;
  1010. enum ieee80211_ampdu_mlme_action action = params->action;
  1011. u16 tid = params->tid;
  1012. u16 *ssn = &params->ssn;
  1013. int ret = 0;
  1014. int session;
  1015. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
  1016. action, tid);
  1017. mutex_lock(&wcn->conf_mutex);
  1018. switch (action) {
  1019. case IEEE80211_AMPDU_RX_START:
  1020. sta_priv->tid = tid;
  1021. session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0,
  1022. get_sta_index(vif, sta_priv));
  1023. if (session < 0) {
  1024. ret = session;
  1025. goto out;
  1026. }
  1027. wcn36xx_smd_add_ba(wcn, session);
  1028. break;
  1029. case IEEE80211_AMPDU_RX_STOP:
  1030. wcn36xx_smd_del_ba(wcn, tid, 0, get_sta_index(vif, sta_priv));
  1031. break;
  1032. case IEEE80211_AMPDU_TX_START:
  1033. spin_lock_bh(&sta_priv->ampdu_lock);
  1034. sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
  1035. spin_unlock_bh(&sta_priv->ampdu_lock);
  1036. /* Replace the mac80211 ssn with the firmware one */
  1037. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu ssn = %u\n", *ssn);
  1038. wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv), tid, ssn);
  1039. wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu fw-ssn = %u\n", *ssn);
  1040. /* Start BA session */
  1041. session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
  1042. get_sta_index(vif, sta_priv));
  1043. if (session < 0) {
  1044. ret = session;
  1045. goto out;
  1046. }
  1047. ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
  1048. break;
  1049. case IEEE80211_AMPDU_TX_OPERATIONAL:
  1050. spin_lock_bh(&sta_priv->ampdu_lock);
  1051. sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL;
  1052. spin_unlock_bh(&sta_priv->ampdu_lock);
  1053. break;
  1054. case IEEE80211_AMPDU_TX_STOP_FLUSH:
  1055. case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
  1056. case IEEE80211_AMPDU_TX_STOP_CONT:
  1057. spin_lock_bh(&sta_priv->ampdu_lock);
  1058. sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE;
  1059. spin_unlock_bh(&sta_priv->ampdu_lock);
  1060. wcn36xx_smd_del_ba(wcn, tid, 1, get_sta_index(vif, sta_priv));
  1061. ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
  1062. break;
  1063. default:
  1064. wcn36xx_err("Unknown AMPDU action\n");
  1065. }
  1066. out:
  1067. mutex_unlock(&wcn->conf_mutex);
  1068. return ret;
  1069. }
  1070. #if IS_ENABLED(CONFIG_IPV6)
  1071. static void wcn36xx_ipv6_addr_change(struct ieee80211_hw *hw,
  1072. struct ieee80211_vif *vif,
  1073. struct inet6_dev *idev)
  1074. {
  1075. struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
  1076. struct inet6_ifaddr *ifa;
  1077. int idx = 0;
  1078. memset(vif_priv->tentative_addrs, 0, sizeof(vif_priv->tentative_addrs));
  1079. read_lock_bh(&idev->lock);
  1080. list_for_each_entry(ifa, &idev->addr_list, if_list) {
  1081. vif_priv->target_ipv6_addrs[idx] = ifa->addr;
  1082. if (ifa->flags & IFA_F_TENTATIVE)
  1083. __set_bit(idx, vif_priv->tentative_addrs);
  1084. idx++;
  1085. if (idx >= WCN36XX_HAL_IPV6_OFFLOAD_ADDR_MAX)
  1086. break;
  1087. wcn36xx_dbg(WCN36XX_DBG_MAC, "%pI6 %s\n", &ifa->addr,
  1088. (ifa->flags & IFA_F_TENTATIVE) ? "tentative" : NULL);
  1089. }
  1090. read_unlock_bh(&idev->lock);
  1091. vif_priv->num_target_ipv6_addrs = idx;
  1092. }
  1093. #endif
  1094. static void wcn36xx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  1095. u32 queues, bool drop)
  1096. {
  1097. struct wcn36xx *wcn = hw->priv;
  1098. if (wcn36xx_dxe_tx_flush(wcn)) {
  1099. wcn36xx_err("Failed to flush hardware tx queues\n");
  1100. }
  1101. }
  1102. static int wcn36xx_get_survey(struct ieee80211_hw *hw, int idx,
  1103. struct survey_info *survey)
  1104. {
  1105. struct wcn36xx *wcn = hw->priv;
  1106. struct ieee80211_supported_band *sband;
  1107. struct wcn36xx_chan_survey *chan_survey;
  1108. int band_idx;
  1109. unsigned long flags;
  1110. sband = wcn->hw->wiphy->bands[NL80211_BAND_2GHZ];
  1111. band_idx = idx;
  1112. if (band_idx >= sband->n_channels) {
  1113. band_idx -= sband->n_channels;
  1114. sband = wcn->hw->wiphy->bands[NL80211_BAND_5GHZ];
  1115. }
  1116. if (!sband || band_idx >= sband->n_channels)
  1117. return -ENOENT;
  1118. spin_lock_irqsave(&wcn->survey_lock, flags);
  1119. chan_survey = &wcn->chan_survey[idx];
  1120. survey->channel = &sband->channels[band_idx];
  1121. survey->noise = chan_survey->rssi - chan_survey->snr;
  1122. survey->filled = 0;
  1123. if (chan_survey->rssi > -100 && chan_survey->rssi < 0)
  1124. survey->filled |= SURVEY_INFO_NOISE_DBM;
  1125. if (survey->channel == wcn->channel)
  1126. survey->filled |= SURVEY_INFO_IN_USE;
  1127. spin_unlock_irqrestore(&wcn->survey_lock, flags);
  1128. wcn36xx_dbg(WCN36XX_DBG_MAC,
  1129. "ch %d rssi %d snr %d noise %d filled %x freq %d\n",
  1130. HW_VALUE_CHANNEL(survey->channel->hw_value),
  1131. chan_survey->rssi, chan_survey->snr, survey->noise,
  1132. survey->filled, survey->channel->center_freq);
  1133. return 0;
  1134. }
  1135. static void wcn36xx_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  1136. struct ieee80211_sta *sta, struct station_info *sinfo)
  1137. {
  1138. struct wcn36xx *wcn;
  1139. u8 sta_index;
  1140. int status;
  1141. wcn = hw->priv;
  1142. sta_index = get_sta_index(vif, wcn36xx_sta_to_priv(sta));
  1143. status = wcn36xx_smd_get_stats(wcn, sta_index, HAL_GLOBAL_CLASS_A_STATS_INFO, sinfo);
  1144. if (status)
  1145. wcn36xx_err("wcn36xx_smd_get_stats failed\n");
  1146. }
  1147. static const struct ieee80211_ops wcn36xx_ops = {
  1148. .start = wcn36xx_start,
  1149. .stop = wcn36xx_stop,
  1150. .add_interface = wcn36xx_add_interface,
  1151. .remove_interface = wcn36xx_remove_interface,
  1152. #ifdef CONFIG_PM
  1153. .suspend = wcn36xx_suspend,
  1154. .resume = wcn36xx_resume,
  1155. .set_rekey_data = wcn36xx_set_rekey_data,
  1156. #endif
  1157. .config = wcn36xx_config,
  1158. .prepare_multicast = wcn36xx_prepare_multicast,
  1159. .configure_filter = wcn36xx_configure_filter,
  1160. .tx = wcn36xx_tx,
  1161. .set_key = wcn36xx_set_key,
  1162. .hw_scan = wcn36xx_hw_scan,
  1163. .cancel_hw_scan = wcn36xx_cancel_hw_scan,
  1164. .sw_scan_start = wcn36xx_sw_scan_start,
  1165. .sw_scan_complete = wcn36xx_sw_scan_complete,
  1166. .bss_info_changed = wcn36xx_bss_info_changed,
  1167. .set_rts_threshold = wcn36xx_set_rts_threshold,
  1168. .sta_add = wcn36xx_sta_add,
  1169. .sta_remove = wcn36xx_sta_remove,
  1170. .sta_statistics = wcn36xx_sta_statistics,
  1171. .ampdu_action = wcn36xx_ampdu_action,
  1172. #if IS_ENABLED(CONFIG_IPV6)
  1173. .ipv6_addr_change = wcn36xx_ipv6_addr_change,
  1174. #endif
  1175. .flush = wcn36xx_flush,
  1176. .get_survey = wcn36xx_get_survey,
  1177. CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd)
  1178. };
  1179. static void
  1180. wcn36xx_set_ieee80211_vht_caps(struct ieee80211_sta_vht_cap *vht_cap)
  1181. {
  1182. vht_cap->vht_supported = true;
  1183. vht_cap->cap = (IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 |
  1184. IEEE80211_VHT_CAP_SHORT_GI_80 |
  1185. IEEE80211_VHT_CAP_RXSTBC_1 |
  1186. IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
  1187. IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
  1188. 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT |
  1189. 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
  1190. vht_cap->vht_mcs.rx_mcs_map =
  1191. cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 |
  1192. IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 |
  1193. IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
  1194. IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
  1195. IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
  1196. IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
  1197. IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
  1198. IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
  1199. vht_cap->vht_mcs.rx_highest = cpu_to_le16(433);
  1200. vht_cap->vht_mcs.tx_highest = vht_cap->vht_mcs.rx_highest;
  1201. vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
  1202. }
  1203. static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
  1204. {
  1205. static const u32 cipher_suites[] = {
  1206. WLAN_CIPHER_SUITE_WEP40,
  1207. WLAN_CIPHER_SUITE_WEP104,
  1208. WLAN_CIPHER_SUITE_TKIP,
  1209. WLAN_CIPHER_SUITE_CCMP,
  1210. };
  1211. ieee80211_hw_set(wcn->hw, TIMING_BEACON_ONLY);
  1212. ieee80211_hw_set(wcn->hw, AMPDU_AGGREGATION);
  1213. ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
  1214. ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
  1215. ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
  1216. ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
  1217. ieee80211_hw_set(wcn->hw, REPORTS_TX_ACK_STATUS);
  1218. wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
  1219. BIT(NL80211_IFTYPE_AP) |
  1220. BIT(NL80211_IFTYPE_ADHOC) |
  1221. BIT(NL80211_IFTYPE_MESH_POINT);
  1222. wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz;
  1223. if (wcn->rf_id != RF_IRIS_WCN3620)
  1224. wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz;
  1225. if (wcn->rf_id == RF_IRIS_WCN3680)
  1226. wcn36xx_set_ieee80211_vht_caps(&wcn_band_5ghz.vht_cap);
  1227. wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
  1228. wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN;
  1229. wcn->hw->wiphy->cipher_suites = cipher_suites;
  1230. wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
  1231. #ifdef CONFIG_PM
  1232. wcn->hw->wiphy->wowlan = &wowlan_support;
  1233. #endif
  1234. wcn->hw->max_listen_interval = 200;
  1235. wcn->hw->queues = 4;
  1236. SET_IEEE80211_DEV(wcn->hw, wcn->dev);
  1237. wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta);
  1238. wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif);
  1239. wiphy_ext_feature_set(wcn->hw->wiphy,
  1240. NL80211_EXT_FEATURE_CQM_RSSI_LIST);
  1241. return 0;
  1242. }
  1243. static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
  1244. struct platform_device *pdev)
  1245. {
  1246. struct device_node *mmio_node;
  1247. struct device_node *iris_node;
  1248. int index;
  1249. int ret;
  1250. /* Set TX IRQ */
  1251. ret = platform_get_irq_byname(pdev, "tx");
  1252. if (ret < 0)
  1253. return ret;
  1254. wcn->tx_irq = ret;
  1255. /* Set RX IRQ */
  1256. ret = platform_get_irq_byname(pdev, "rx");
  1257. if (ret < 0)
  1258. return ret;
  1259. wcn->rx_irq = ret;
  1260. /* Acquire SMSM tx enable handle */
  1261. wcn->tx_enable_state = qcom_smem_state_get(&pdev->dev,
  1262. "tx-enable", &wcn->tx_enable_state_bit);
  1263. if (IS_ERR(wcn->tx_enable_state)) {
  1264. wcn36xx_err("failed to get tx-enable state\n");
  1265. return PTR_ERR(wcn->tx_enable_state);
  1266. }
  1267. /* Acquire SMSM tx rings empty handle */
  1268. wcn->tx_rings_empty_state = qcom_smem_state_get(&pdev->dev,
  1269. "tx-rings-empty", &wcn->tx_rings_empty_state_bit);
  1270. if (IS_ERR(wcn->tx_rings_empty_state)) {
  1271. wcn36xx_err("failed to get tx-rings-empty state\n");
  1272. return PTR_ERR(wcn->tx_rings_empty_state);
  1273. }
  1274. mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0);
  1275. if (!mmio_node) {
  1276. wcn36xx_err("failed to acquire qcom,mmio reference\n");
  1277. return -EINVAL;
  1278. }
  1279. wcn->is_pronto = !!of_device_is_compatible(mmio_node, "qcom,pronto");
  1280. /* Map the CCU memory */
  1281. index = of_property_match_string(mmio_node, "reg-names", "ccu");
  1282. wcn->ccu_base = of_iomap(mmio_node, index);
  1283. if (!wcn->ccu_base) {
  1284. wcn36xx_err("failed to map ccu memory\n");
  1285. ret = -ENOMEM;
  1286. goto put_mmio_node;
  1287. }
  1288. /* Map the DXE memory */
  1289. index = of_property_match_string(mmio_node, "reg-names", "dxe");
  1290. wcn->dxe_base = of_iomap(mmio_node, index);
  1291. if (!wcn->dxe_base) {
  1292. wcn36xx_err("failed to map dxe memory\n");
  1293. ret = -ENOMEM;
  1294. goto unmap_ccu;
  1295. }
  1296. /* External RF module */
  1297. iris_node = of_get_child_by_name(mmio_node, "iris");
  1298. if (iris_node) {
  1299. if (of_device_is_compatible(iris_node, "qcom,wcn3620"))
  1300. wcn->rf_id = RF_IRIS_WCN3620;
  1301. if (of_device_is_compatible(iris_node, "qcom,wcn3660") ||
  1302. of_device_is_compatible(iris_node, "qcom,wcn3660b"))
  1303. wcn->rf_id = RF_IRIS_WCN3660;
  1304. if (of_device_is_compatible(iris_node, "qcom,wcn3680"))
  1305. wcn->rf_id = RF_IRIS_WCN3680;
  1306. of_node_put(iris_node);
  1307. }
  1308. of_node_put(mmio_node);
  1309. return 0;
  1310. unmap_ccu:
  1311. iounmap(wcn->ccu_base);
  1312. put_mmio_node:
  1313. of_node_put(mmio_node);
  1314. return ret;
  1315. }
  1316. static int wcn36xx_probe(struct platform_device *pdev)
  1317. {
  1318. struct ieee80211_hw *hw;
  1319. struct wcn36xx *wcn;
  1320. void *wcnss;
  1321. int ret;
  1322. const u8 *addr;
  1323. int n_channels;
  1324. wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
  1325. wcnss = dev_get_drvdata(pdev->dev.parent);
  1326. hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
  1327. if (!hw) {
  1328. wcn36xx_err("failed to alloc hw\n");
  1329. ret = -ENOMEM;
  1330. goto out_err;
  1331. }
  1332. platform_set_drvdata(pdev, hw);
  1333. wcn = hw->priv;
  1334. wcn->hw = hw;
  1335. wcn->dev = &pdev->dev;
  1336. wcn->first_boot = true;
  1337. mutex_init(&wcn->conf_mutex);
  1338. mutex_init(&wcn->hal_mutex);
  1339. mutex_init(&wcn->scan_lock);
  1340. __skb_queue_head_init(&wcn->amsdu);
  1341. wcn->hal_buf = devm_kmalloc(wcn->dev, WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
  1342. if (!wcn->hal_buf) {
  1343. ret = -ENOMEM;
  1344. goto out_wq;
  1345. }
  1346. n_channels = wcn_band_2ghz.n_channels + wcn_band_5ghz.n_channels;
  1347. wcn->chan_survey = devm_kmalloc(wcn->dev, n_channels, GFP_KERNEL);
  1348. if (!wcn->chan_survey) {
  1349. ret = -ENOMEM;
  1350. goto out_wq;
  1351. }
  1352. ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
  1353. if (ret < 0) {
  1354. wcn36xx_err("failed to set DMA mask: %d\n", ret);
  1355. goto out_wq;
  1356. }
  1357. wcn->nv_file = WLAN_NV_FILE;
  1358. ret = of_property_read_string(wcn->dev->parent->of_node, "firmware-name", &wcn->nv_file);
  1359. if (ret < 0 && ret != -EINVAL) {
  1360. wcn36xx_err("failed to read \"firmware-name\" property: %d\n", ret);
  1361. goto out_wq;
  1362. }
  1363. wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process, hw);
  1364. if (IS_ERR(wcn->smd_channel)) {
  1365. wcn36xx_err("failed to open WLAN_CTRL channel\n");
  1366. ret = PTR_ERR(wcn->smd_channel);
  1367. goto out_wq;
  1368. }
  1369. addr = of_get_property(pdev->dev.of_node, "local-mac-address", &ret);
  1370. if (addr && ret != ETH_ALEN) {
  1371. wcn36xx_err("invalid local-mac-address\n");
  1372. ret = -EINVAL;
  1373. goto out_destroy_ept;
  1374. } else if (addr) {
  1375. wcn36xx_info("mac address: %pM\n", addr);
  1376. SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
  1377. }
  1378. ret = wcn36xx_platform_get_resources(wcn, pdev);
  1379. if (ret)
  1380. goto out_destroy_ept;
  1381. wcn36xx_init_ieee80211(wcn);
  1382. ret = ieee80211_register_hw(wcn->hw);
  1383. if (ret)
  1384. goto out_unmap;
  1385. return 0;
  1386. out_unmap:
  1387. iounmap(wcn->ccu_base);
  1388. iounmap(wcn->dxe_base);
  1389. out_destroy_ept:
  1390. rpmsg_destroy_ept(wcn->smd_channel);
  1391. out_wq:
  1392. ieee80211_free_hw(hw);
  1393. out_err:
  1394. return ret;
  1395. }
  1396. static int wcn36xx_remove(struct platform_device *pdev)
  1397. {
  1398. struct ieee80211_hw *hw = platform_get_drvdata(pdev);
  1399. struct wcn36xx *wcn = hw->priv;
  1400. wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
  1401. release_firmware(wcn->nv);
  1402. ieee80211_unregister_hw(hw);
  1403. qcom_smem_state_put(wcn->tx_enable_state);
  1404. qcom_smem_state_put(wcn->tx_rings_empty_state);
  1405. rpmsg_destroy_ept(wcn->smd_channel);
  1406. iounmap(wcn->dxe_base);
  1407. iounmap(wcn->ccu_base);
  1408. __skb_queue_purge(&wcn->amsdu);
  1409. mutex_destroy(&wcn->hal_mutex);
  1410. ieee80211_free_hw(hw);
  1411. return 0;
  1412. }
  1413. static const struct of_device_id wcn36xx_of_match[] = {
  1414. { .compatible = "qcom,wcnss-wlan" },
  1415. {}
  1416. };
  1417. MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
  1418. static struct platform_driver wcn36xx_driver = {
  1419. .probe = wcn36xx_probe,
  1420. .remove = wcn36xx_remove,
  1421. .driver = {
  1422. .name = "wcn36xx",
  1423. .of_match_table = wcn36xx_of_match,
  1424. },
  1425. };
  1426. module_platform_driver(wcn36xx_driver);
  1427. MODULE_LICENSE("Dual BSD/GPL");
  1428. MODULE_AUTHOR("Eugene Krasnikov [email protected]");
  1429. MODULE_FIRMWARE(WLAN_NV_FILE);