phydm_beamforming.c 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2017 Realtek Corporation.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * The full GNU General Public License is included in this distribution in the
  15. * file called LICENSE.
  16. *
  17. * Contact Information:
  18. * wlanfae <wlanfae@realtek.com>
  19. * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  20. * Hsinchu 300, Taiwan.
  21. *
  22. * Larry Finger <Larry.Finger@lwfinger.net>
  23. *
  24. *****************************************************************************/
  25. #include "mp_precomp.h"
  26. #include "phydm_precomp.h"
  27. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  28. #if WPP_SOFTWARE_TRACE
  29. #include "phydm_beamforming.tmh"
  30. #endif
  31. #endif
  32. #if (BEAMFORMING_SUPPORT == 1)
  33. void phydm_get_txbf_device_num(
  34. void *dm_void,
  35. u8 macid)
  36. {
  37. #if (defined(CONFIG_PHYDM_ANTENNA_DIVERSITY)) /*@For BDC*/
  38. #if (DM_ODM_SUPPORT_TYPE == ODM_AP)
  39. struct dm_struct *dm = (struct dm_struct *)dm_void;
  40. struct cmn_sta_info *sta = dm->phydm_sta_info[macid];
  41. struct bf_cmn_info *bf = NULL;
  42. struct _BF_DIV_COEX_ *dm_bdc_table = &dm->dm_bdc_table;
  43. u8 act_as_bfer = 0;
  44. u8 act_as_bfee = 0;
  45. if (is_sta_active(sta)) {
  46. bf = &(sta->bf_info);
  47. } else {
  48. PHYDM_DBG(dm, DBG_TXBF, "[Warning] %s invalid sta_info\n",
  49. __func__);
  50. return;
  51. }
  52. if (sta->support_wireless_set & WIRELESS_VHT) {
  53. if (bf->vht_beamform_cap & BEAMFORMING_VHT_BEAMFORMEE_ENABLE)
  54. act_as_bfer = 1;
  55. if (bf->vht_beamform_cap & BEAMFORMING_VHT_BEAMFORMER_ENABLE)
  56. act_as_bfee = 1;
  57. } else if (sta->support_wireless_set & WIRELESS_HT) {
  58. if (bf->ht_beamform_cap & BEAMFORMING_HT_BEAMFORMEE_ENABLE)
  59. act_as_bfer = 1;
  60. if (bf->ht_beamform_cap & BEAMFORMING_HT_BEAMFORMER_ENABLE)
  61. act_as_bfee = 1;
  62. }
  63. if (act_as_bfer))
  64. { /* Our Device act as BFer */
  65. dm_bdc_table->w_bfee_client[macid] = true;
  66. dm_bdc_table->num_txbfee_client++;
  67. }
  68. else
  69. dm_bdc_table->w_bfee_client[macid] = false;
  70. if (act_as_bfee))
  71. { /* Our Device act as BFee */
  72. dm_bdc_table->w_bfer_client[macid] = true;
  73. dm_bdc_table->num_txbfer_client++;
  74. }
  75. else
  76. dm_bdc_table->w_bfer_client[macid] = false;
  77. #endif
  78. #endif
  79. }
  80. struct _RT_BEAMFORM_STAINFO *
  81. phydm_sta_info_init(
  82. struct dm_struct *dm,
  83. u16 sta_idx)
  84. {
  85. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  86. struct _RT_BEAMFORM_STAINFO *entry = &beam_info->beamform_sta_info;
  87. struct sta_info *sta = dm->odm_sta_info[sta_idx];
  88. struct cmn_sta_info *cmn_sta = dm->phydm_sta_info[sta_idx];
  89. //void *adapter = dm->adapter;
  90. ADAPTER * adapter = dm->adapter;
  91. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  92. PMGNT_INFO p_MgntInfo = &((adapter)->MgntInfo);
  93. PRT_HIGH_THROUGHPUT p_ht_info = GET_HT_INFO(p_MgntInfo);
  94. PRT_VERY_HIGH_THROUGHPUT p_vht_info = GET_VHT_INFO(p_MgntInfo);
  95. #endif
  96. if (!is_sta_active(cmn_sta)) {
  97. PHYDM_DBG(dm, DBG_TXBF, "%s => sta_info(mac_id:%d) failed\n",
  98. __func__, sta_idx);
  99. #if (DM_ODM_SUPPORT_TYPE == ODM_CE)
  100. rtw_warn_on(1);
  101. #endif
  102. return entry;
  103. }
  104. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  105. odm_move_memory(dm, (PVOID)(entry->my_mac_addr), (PVOID)(adapter->CurrentAddress), 6);
  106. #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
  107. odm_move_memory(dm, entry->my_mac_addr, adapter_mac_addr(sta->padapter), 6);
  108. #endif
  109. entry->aid = cmn_sta->aid;
  110. entry->ra = cmn_sta->mac_addr;
  111. entry->mac_id = cmn_sta->mac_id;
  112. entry->bw = cmn_sta->bw_mode;
  113. entry->cur_beamform = cmn_sta->bf_info.ht_beamform_cap;
  114. entry->ht_beamform_cap = cmn_sta->bf_info.ht_beamform_cap;
  115. #if ODM_IC_11AC_SERIES_SUPPORT
  116. if (cmn_sta->support_wireless_set & WIRELESS_VHT) {
  117. entry->cur_beamform_vht = cmn_sta->bf_info.vht_beamform_cap;
  118. entry->vht_beamform_cap = cmn_sta->bf_info.vht_beamform_cap;
  119. }
  120. #endif
  121. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN) /*To Be Removed */
  122. entry->ht_beamform_cap = p_ht_info->HtBeamformCap; /*To Be Removed*/
  123. entry->vht_beamform_cap = p_vht_info->VhtBeamformCap; /*To Be Removed*/
  124. if (sta_idx == 0) { /*@client mode*/
  125. #if ODM_IC_11AC_SERIES_SUPPORT
  126. if (cmn_sta->support_wireless_set & WIRELESS_VHT)
  127. entry->cur_beamform_vht = p_vht_info->VhtCurBeamform;
  128. #endif
  129. }
  130. #endif
  131. PHYDM_DBG(dm, DBG_TXBF, "wireless_set = 0x%x, staidx = %d\n",
  132. cmn_sta->support_wireless_set, sta_idx);
  133. PHYDM_DBG(dm, DBG_TXBF,
  134. "entry->cur_beamform = 0x%x, entry->cur_beamform_vht = 0x%x\n",
  135. entry->cur_beamform, entry->cur_beamform_vht);
  136. return entry;
  137. }
  138. void phydm_sta_info_update(
  139. struct dm_struct *dm,
  140. u16 sta_idx,
  141. struct _RT_BEAMFORMEE_ENTRY *beamform_entry)
  142. {
  143. struct cmn_sta_info *sta = dm->phydm_sta_info[sta_idx];
  144. if (!is_sta_active(sta))
  145. return;
  146. sta->bf_info.p_aid = beamform_entry->p_aid;
  147. sta->bf_info.g_id = beamform_entry->g_id;
  148. }
  149. struct _RT_BEAMFORMEE_ENTRY *
  150. phydm_beamforming_get_bfee_entry_by_addr(
  151. void *dm_void,
  152. u8 *RA,
  153. u8 *idx)
  154. {
  155. struct dm_struct *dm = (struct dm_struct *)dm_void;
  156. u8 i = 0;
  157. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  158. for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {
  159. if (beam_info->beamformee_entry[i].is_used && (eq_mac_addr(RA, beam_info->beamformee_entry[i].mac_addr))) {
  160. *idx = i;
  161. return &beam_info->beamformee_entry[i];
  162. }
  163. }
  164. return NULL;
  165. }
  166. struct _RT_BEAMFORMER_ENTRY *
  167. phydm_beamforming_get_bfer_entry_by_addr(
  168. void *dm_void,
  169. u8 *TA,
  170. u8 *idx)
  171. {
  172. struct dm_struct *dm = (struct dm_struct *)dm_void;
  173. u8 i = 0;
  174. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  175. for (i = 0; i < BEAMFORMER_ENTRY_NUM; i++) {
  176. if (beam_info->beamformer_entry[i].is_used && (eq_mac_addr(TA, beam_info->beamformer_entry[i].mac_addr))) {
  177. *idx = i;
  178. return &beam_info->beamformer_entry[i];
  179. }
  180. }
  181. return NULL;
  182. }
  183. struct _RT_BEAMFORMEE_ENTRY *
  184. phydm_beamforming_get_entry_by_mac_id(
  185. void *dm_void,
  186. u8 mac_id,
  187. u8 *idx)
  188. {
  189. struct dm_struct *dm = (struct dm_struct *)dm_void;
  190. u8 i = 0;
  191. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  192. for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {
  193. if (beam_info->beamformee_entry[i].is_used && mac_id == beam_info->beamformee_entry[i].mac_id) {
  194. *idx = i;
  195. return &beam_info->beamformee_entry[i];
  196. }
  197. }
  198. return NULL;
  199. }
  200. enum beamforming_cap
  201. phydm_beamforming_get_entry_beam_cap_by_mac_id(
  202. void *dm_void,
  203. u8 mac_id)
  204. {
  205. struct dm_struct *dm = (struct dm_struct *)dm_void;
  206. u8 i = 0;
  207. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  208. enum beamforming_cap beamform_entry_cap = BEAMFORMING_CAP_NONE;
  209. for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {
  210. if (beam_info->beamformee_entry[i].is_used && mac_id == beam_info->beamformee_entry[i].mac_id) {
  211. beamform_entry_cap = beam_info->beamformee_entry[i].beamform_entry_cap;
  212. i = BEAMFORMEE_ENTRY_NUM;
  213. }
  214. }
  215. return beamform_entry_cap;
  216. }
  217. struct _RT_BEAMFORMEE_ENTRY *
  218. phydm_beamforming_get_free_bfee_entry(
  219. void *dm_void,
  220. u8 *idx)
  221. {
  222. struct dm_struct *dm = (struct dm_struct *)dm_void;
  223. u8 i = 0;
  224. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  225. for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {
  226. if (beam_info->beamformee_entry[i].is_used == false) {
  227. *idx = i;
  228. return &beam_info->beamformee_entry[i];
  229. }
  230. }
  231. return NULL;
  232. }
  233. struct _RT_BEAMFORMER_ENTRY *
  234. phydm_beamforming_get_free_bfer_entry(
  235. void *dm_void,
  236. u8 *idx)
  237. {
  238. struct dm_struct *dm = (struct dm_struct *)dm_void;
  239. u8 i = 0;
  240. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  241. PHYDM_DBG(dm, DBG_TXBF, "%s ===>\n", __func__);
  242. for (i = 0; i < BEAMFORMER_ENTRY_NUM; i++) {
  243. if (beam_info->beamformer_entry[i].is_used == false) {
  244. *idx = i;
  245. return &beam_info->beamformer_entry[i];
  246. }
  247. }
  248. return NULL;
  249. }
  250. /*@
  251. * Description: Get the first entry index of MU Beamformee.
  252. *
  253. * Return value: index of the first MU sta.
  254. *
  255. * 2015.05.25. Created by tynli.
  256. *
  257. */
  258. u8 phydm_beamforming_get_first_mu_bfee_entry_idx(
  259. void *dm_void)
  260. {
  261. struct dm_struct *dm = (struct dm_struct *)dm_void;
  262. u8 idx = 0xFF;
  263. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  264. boolean is_found = false;
  265. for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {
  266. if (beam_info->beamformee_entry[idx].is_used && beam_info->beamformee_entry[idx].is_mu_sta) {
  267. PHYDM_DBG(dm, DBG_TXBF, "[%s] idx=%d!\n", __func__,
  268. idx);
  269. is_found = true;
  270. break;
  271. }
  272. }
  273. if (!is_found)
  274. idx = 0xFF;
  275. return idx;
  276. }
  277. /*@Add SU BFee and MU BFee*/
  278. struct _RT_BEAMFORMEE_ENTRY *
  279. beamforming_add_bfee_entry(
  280. void *dm_void,
  281. struct _RT_BEAMFORM_STAINFO *sta,
  282. enum beamforming_cap beamform_cap,
  283. u8 num_of_sounding_dim,
  284. u8 comp_steering_num_of_bfer,
  285. u8 *idx)
  286. {
  287. struct dm_struct *dm = (struct dm_struct *)dm_void;
  288. struct _RT_BEAMFORMEE_ENTRY *entry = phydm_beamforming_get_free_bfee_entry(dm, idx);
  289. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  290. if (entry != NULL) {
  291. entry->is_used = true;
  292. entry->aid = sta->aid;
  293. entry->mac_id = sta->mac_id;
  294. entry->sound_bw = sta->bw;
  295. odm_move_memory(dm, entry->my_mac_addr, sta->my_mac_addr, 6);
  296. if (phydm_acting_determine(dm, phydm_acting_as_ap)) {
  297. /*@BSSID[44:47] xor BSSID[40:43]*/
  298. u16 bssid = ((sta->my_mac_addr[5] & 0xf0) >> 4) ^ (sta->my_mac_addr[5] & 0xf);
  299. /*@(dec(A) + dec(B)*32) mod 512*/
  300. entry->p_aid = (sta->aid + bssid * 32) & 0x1ff;
  301. entry->g_id = 63;
  302. PHYDM_DBG(dm, DBG_TXBF,
  303. "%s: BFee P_AID addressed to STA=%d\n",
  304. __func__, entry->p_aid);
  305. } else if (phydm_acting_determine(dm, phydm_acting_as_ibss)) {
  306. /*@ad hoc mode*/
  307. entry->p_aid = 0;
  308. entry->g_id = 63;
  309. PHYDM_DBG(dm, DBG_TXBF, "%s: BFee P_AID as IBSS=%d\n",
  310. __func__, entry->p_aid);
  311. } else {
  312. /*@client mode*/
  313. entry->p_aid = sta->ra[5];
  314. /*@BSSID[39:47]*/
  315. entry->p_aid = (entry->p_aid << 1) | (sta->ra[4] >> 7);
  316. entry->g_id = 0;
  317. PHYDM_DBG(dm, DBG_TXBF,
  318. "%s: BFee P_AID addressed to AP=0x%X\n",
  319. __func__, entry->p_aid);
  320. }
  321. cp_mac_addr(entry->mac_addr, sta->ra);
  322. entry->is_txbf = false;
  323. entry->is_sound = false;
  324. entry->sound_period = 400;
  325. entry->beamform_entry_cap = beamform_cap;
  326. entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
  327. /* @entry->log_seq = 0xff; Move to beamforming_add_bfer_entry*/
  328. /* @entry->log_retry_cnt = 0; Move to beamforming_add_bfer_entry*/
  329. /* @entry->LogSuccessCnt = 0; Move to beamforming_add_bfer_entry*/
  330. entry->log_status_fail_cnt = 0;
  331. entry->num_of_sounding_dim = num_of_sounding_dim;
  332. entry->comp_steering_num_of_bfer = comp_steering_num_of_bfer;
  333. if (beamform_cap & BEAMFORMER_CAP_VHT_MU) {
  334. dm->beamforming_info.beamformee_mu_cnt += 1;
  335. entry->is_mu_sta = true;
  336. dm->beamforming_info.first_mu_bfee_index = phydm_beamforming_get_first_mu_bfee_entry_idx(dm);
  337. } else if (beamform_cap & (BEAMFORMER_CAP_VHT_SU | BEAMFORMER_CAP_HT_EXPLICIT)) {
  338. dm->beamforming_info.beamformee_su_cnt += 1;
  339. entry->is_mu_sta = false;
  340. }
  341. return entry;
  342. } else
  343. return NULL;
  344. }
  345. /*@Add SU BFee and MU BFer*/
  346. struct _RT_BEAMFORMER_ENTRY *
  347. beamforming_add_bfer_entry(
  348. void *dm_void,
  349. struct _RT_BEAMFORM_STAINFO *sta,
  350. enum beamforming_cap beamform_cap,
  351. u8 num_of_sounding_dim,
  352. u8 *idx)
  353. {
  354. struct dm_struct *dm = (struct dm_struct *)dm_void;
  355. struct _RT_BEAMFORMER_ENTRY *entry = phydm_beamforming_get_free_bfer_entry(dm, idx);
  356. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  357. if (entry != NULL) {
  358. entry->is_used = true;
  359. odm_move_memory(dm, entry->my_mac_addr, sta->my_mac_addr, 6);
  360. if (phydm_acting_determine(dm, phydm_acting_as_ap)) {
  361. /*@BSSID[44:47] xor BSSID[40:43]*/
  362. u16 bssid = ((sta->my_mac_addr[5] & 0xf0) >> 4) ^ (sta->my_mac_addr[5] & 0xf);
  363. entry->p_aid = (sta->aid + bssid * 32) & 0x1ff;
  364. entry->g_id = 63;
  365. /*@(dec(A) + dec(B)*32) mod 512*/
  366. } else if (phydm_acting_determine(dm, phydm_acting_as_ibss)) {
  367. entry->p_aid = 0;
  368. entry->g_id = 63;
  369. } else {
  370. entry->p_aid = sta->ra[5];
  371. /*@BSSID[39:47]*/
  372. entry->p_aid = (entry->p_aid << 1) | (sta->ra[4] >> 7);
  373. entry->g_id = 0;
  374. PHYDM_DBG(dm, DBG_TXBF,
  375. "%s: P_AID addressed to AP=0x%X\n", __func__,
  376. entry->p_aid);
  377. }
  378. cp_mac_addr(entry->mac_addr, sta->ra);
  379. entry->beamform_entry_cap = beamform_cap;
  380. entry->pre_log_seq = 0; /*@Modified by Jeffery @2015-04-13*/
  381. entry->log_seq = 0; /*@Modified by Jeffery @2014-10-29*/
  382. entry->log_retry_cnt = 0; /*@Modified by Jeffery @2014-10-29*/
  383. entry->log_success = 0; /*@log_success is NOT needed to be accumulated, so LogSuccessCnt->log_success, 2015-04-13, Jeffery*/
  384. entry->clock_reset_times = 0; /*@Modified by Jeffery @2015-04-13*/
  385. entry->num_of_sounding_dim = num_of_sounding_dim;
  386. if (beamform_cap & BEAMFORMEE_CAP_VHT_MU) {
  387. dm->beamforming_info.beamformer_mu_cnt += 1;
  388. entry->is_mu_ap = true;
  389. entry->aid = sta->aid;
  390. } else if (beamform_cap & (BEAMFORMEE_CAP_VHT_SU | BEAMFORMEE_CAP_HT_EXPLICIT)) {
  391. dm->beamforming_info.beamformer_su_cnt += 1;
  392. entry->is_mu_ap = false;
  393. }
  394. return entry;
  395. } else
  396. return NULL;
  397. }
  398. #if 0
  399. boolean
  400. beamforming_remove_entry(
  401. void *adapter,
  402. u8 *RA,
  403. u8 *idx
  404. )
  405. {
  406. HAL_DATA_TYPE *hal_data = GET_HAL_DATA(((PADAPTER)adapter));
  407. struct dm_struct *dm = &hal_data->DM_OutSrc;
  408. struct _RT_BEAMFORMER_ENTRY *bfer_entry = phydm_beamforming_get_bfer_entry_by_addr(dm, RA, idx);
  409. struct _RT_BEAMFORMEE_ENTRY *entry = phydm_beamforming_get_bfee_entry_by_addr(dm, RA, idx);
  410. boolean ret = false;
  411. RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s Start!\n", __func__));
  412. RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s, bfer_entry=0x%x\n", __func__, bfer_entry));
  413. RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s, entry=0x%x\n", __func__, entry));
  414. if (entry != NULL) {
  415. entry->is_used = false;
  416. entry->beamform_entry_cap = BEAMFORMING_CAP_NONE;
  417. /*@entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;*/
  418. entry->is_beamforming_in_progress = false;
  419. ret = true;
  420. }
  421. if (bfer_entry != NULL) {
  422. bfer_entry->is_used = false;
  423. bfer_entry->beamform_entry_cap = BEAMFORMING_CAP_NONE;
  424. ret = true;
  425. }
  426. return ret;
  427. }
  428. #endif
  429. /* Used for beamforming_start_v1 */
  430. void phydm_beamforming_ndpa_rate(
  431. void *dm_void,
  432. enum channel_width BW,
  433. u8 rate)
  434. {
  435. u16 ndpa_rate = rate;
  436. struct dm_struct *dm = (struct dm_struct *)dm_void;
  437. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  438. if (ndpa_rate == 0) {
  439. if (dm->rssi_min > 30) /* @link RSSI > 30% */
  440. ndpa_rate = ODM_RATE24M;
  441. else
  442. ndpa_rate = ODM_RATE6M;
  443. }
  444. if (ndpa_rate < ODM_RATEMCS0)
  445. BW = (enum channel_width)CHANNEL_WIDTH_20;
  446. ndpa_rate = (ndpa_rate << 8) | BW;
  447. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_RATE, (u8 *)&ndpa_rate);
  448. }
  449. /* Used for beamforming_start_sw and beamforming_start_fw */
  450. void phydm_beamforming_dym_ndpa_rate(
  451. void *dm_void)
  452. {
  453. u16 ndpa_rate = ODM_RATE6M, BW;
  454. struct dm_struct *dm = (struct dm_struct *)dm_void;
  455. ndpa_rate = ODM_RATE6M;
  456. BW = CHANNEL_WIDTH_20;
  457. ndpa_rate = ndpa_rate << 8 | BW;
  458. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_RATE, (u8 *)&ndpa_rate);
  459. PHYDM_DBG(dm, DBG_TXBF, "%s End, NDPA rate = 0x%X\n", __func__,
  460. ndpa_rate);
  461. }
  462. /*@
  463. * SW Sounding : SW Timer unit 1ms
  464. * HW Timer unit (1/32000) s 32k is clock.
  465. * FW Sounding : FW Timer unit 10ms
  466. */
  467. void beamforming_dym_period(
  468. void *dm_void,
  469. u8 status)
  470. {
  471. u8 idx;
  472. boolean is_change_period = false;
  473. u16 sound_period_sw, sound_period_fw;
  474. struct dm_struct *dm = (struct dm_struct *)dm_void;
  475. struct _RT_BEAMFORMEE_ENTRY *beamform_entry;
  476. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  477. struct _RT_SOUNDING_INFO *sound_info = &beam_info->sounding_info;
  478. struct _RT_BEAMFORMEE_ENTRY *entry = &beam_info->beamformee_entry[beam_info->beamformee_cur_idx];
  479. PHYDM_DBG(dm, DBG_TXBF, "[%s] Start!\n", __func__);
  480. /* @3 TODO per-client throughput caculation. */
  481. if ((*dm->current_tx_tp + *dm->current_rx_tp > 2) && (entry->log_status_fail_cnt <= 20 || status)) {
  482. sound_period_sw = 40; /* @40ms */
  483. sound_period_fw = 40; /* @From H2C cmd, unit = 10ms */
  484. } else {
  485. sound_period_sw = 4000; /* @4s */
  486. sound_period_fw = 400;
  487. }
  488. PHYDM_DBG(dm, DBG_TXBF, "[%s]sound_period_sw=%d, sound_period_fw=%d\n",
  489. __func__, sound_period_sw, sound_period_fw);
  490. for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {
  491. beamform_entry = beam_info->beamformee_entry + idx;
  492. if (beamform_entry->default_csi_cnt > 20) {
  493. /*@Modified by David*/
  494. sound_period_sw = 4000;
  495. sound_period_fw = 400;
  496. }
  497. PHYDM_DBG(dm, DBG_TXBF, "[%s] period = %d\n", __func__,
  498. sound_period_sw);
  499. if ((beamform_entry->beamform_entry_cap & (BEAMFORMER_CAP_HT_EXPLICIT | BEAMFORMER_CAP_VHT_SU)) == 0)
  500. continue;
  501. if (sound_info->sound_mode == SOUNDING_FW_VHT_TIMER || sound_info->sound_mode == SOUNDING_FW_HT_TIMER) {
  502. if (beamform_entry->sound_period != sound_period_fw) {
  503. beamform_entry->sound_period = sound_period_fw;
  504. is_change_period = true; /*Only FW sounding need to send H2C packet to change sound period. */
  505. }
  506. } else if (beamform_entry->sound_period != sound_period_sw)
  507. beamform_entry->sound_period = sound_period_sw;
  508. }
  509. if (is_change_period)
  510. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_FW_NDPA, (u8 *)&idx);
  511. }
  512. boolean
  513. beamforming_send_ht_ndpa_packet(
  514. void *dm_void,
  515. u8 *RA,
  516. enum channel_width BW,
  517. u8 q_idx)
  518. {
  519. boolean ret = true;
  520. struct dm_struct *dm = (struct dm_struct *)dm_void;
  521. if (q_idx == BEACON_QUEUE)
  522. ret = send_fw_ht_ndpa_packet(dm, RA, BW);
  523. else
  524. ret = send_sw_ht_ndpa_packet(dm, RA, BW);
  525. return ret;
  526. }
  527. boolean
  528. beamforming_send_vht_ndpa_packet(
  529. void *dm_void,
  530. u8 *RA,
  531. u16 AID,
  532. enum channel_width BW,
  533. u8 q_idx)
  534. {
  535. struct dm_struct *dm = (struct dm_struct *)dm_void;
  536. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  537. boolean ret = true;
  538. hal_com_txbf_set(dm, TXBF_SET_GET_TX_RATE, NULL);
  539. if (beam_info->tx_bf_data_rate >= ODM_RATEVHTSS3MCS7 && beam_info->tx_bf_data_rate <= ODM_RATEVHTSS3MCS9 && !beam_info->snding3ss)
  540. PHYDM_DBG(dm, DBG_TXBF, "@%s: 3SS VHT 789 don't sounding\n",
  541. __func__);
  542. else {
  543. if (q_idx == BEACON_QUEUE) /* Send to reserved page => FW NDPA */
  544. ret = send_fw_vht_ndpa_packet(dm, RA, AID, BW);
  545. else {
  546. #ifdef SUPPORT_MU_BF
  547. #if (SUPPORT_MU_BF == 1)
  548. beam_info->is_mu_sounding = true;
  549. ret = send_sw_vht_mu_ndpa_packet(dm, BW);
  550. #else
  551. beam_info->is_mu_sounding = false;
  552. ret = send_sw_vht_ndpa_packet(dm, RA, AID, BW);
  553. #endif
  554. #else
  555. beam_info->is_mu_sounding = false;
  556. ret = send_sw_vht_ndpa_packet(dm, RA, AID, BW);
  557. #endif
  558. }
  559. }
  560. return ret;
  561. }
  562. enum beamforming_notify_state
  563. phydm_beamfomring_is_sounding(
  564. void *dm_void,
  565. struct _RT_BEAMFORMING_INFO *beam_info,
  566. u8 *idx)
  567. {
  568. enum beamforming_notify_state is_sounding = BEAMFORMING_NOTIFY_NONE;
  569. struct _RT_BEAMFORMING_OID_INFO beam_oid_info = beam_info->beamforming_oid_info;
  570. struct dm_struct *dm = (struct dm_struct *)dm_void;
  571. u8 i;
  572. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  573. /*@if(( Beamforming_GetBeamCap(beam_info) & BEAMFORMER_CAP) == 0)*/
  574. /*@is_sounding = BEAMFORMING_NOTIFY_RESET;*/
  575. if (beam_oid_info.sound_oid_mode == sounding_stop_all_timer) {
  576. is_sounding = BEAMFORMING_NOTIFY_RESET;
  577. goto out;
  578. }
  579. for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {
  580. PHYDM_DBG(dm, DBG_TXBF,
  581. "@%s: BFee Entry %d is_used=%d, is_sound=%d\n",
  582. __func__, i, beam_info->beamformee_entry[i].is_used,
  583. beam_info->beamformee_entry[i].is_sound);
  584. if (beam_info->beamformee_entry[i].is_used && !beam_info->beamformee_entry[i].is_sound) {
  585. PHYDM_DBG(dm, DBG_TXBF, "%s: Add BFee entry %d\n",
  586. __func__, i);
  587. *idx = i;
  588. if (beam_info->beamformee_entry[i].is_mu_sta)
  589. is_sounding = BEAMFORMEE_NOTIFY_ADD_MU;
  590. else
  591. is_sounding = BEAMFORMEE_NOTIFY_ADD_SU;
  592. }
  593. if (!beam_info->beamformee_entry[i].is_used && beam_info->beamformee_entry[i].is_sound) {
  594. PHYDM_DBG(dm, DBG_TXBF, "%s: Delete BFee entry %d\n",
  595. __func__, i);
  596. *idx = i;
  597. if (beam_info->beamformee_entry[i].is_mu_sta)
  598. is_sounding = BEAMFORMEE_NOTIFY_DELETE_MU;
  599. else
  600. is_sounding = BEAMFORMEE_NOTIFY_DELETE_SU;
  601. }
  602. }
  603. out:
  604. PHYDM_DBG(dm, DBG_TXBF, "%s End, is_sounding = %d\n", __func__,
  605. is_sounding);
  606. return is_sounding;
  607. }
  608. /* This function is unused */
  609. u8 phydm_beamforming_sounding_idx(
  610. void *dm_void,
  611. struct _RT_BEAMFORMING_INFO *beam_info)
  612. {
  613. u8 idx = 0;
  614. struct _RT_BEAMFORMING_OID_INFO beam_oid_info = beam_info->beamforming_oid_info;
  615. struct dm_struct *dm = (struct dm_struct *)dm_void;
  616. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  617. if (beam_oid_info.sound_oid_mode == SOUNDING_SW_HT_TIMER || beam_oid_info.sound_oid_mode == SOUNDING_SW_VHT_TIMER ||
  618. beam_oid_info.sound_oid_mode == SOUNDING_HW_HT_TIMER || beam_oid_info.sound_oid_mode == SOUNDING_HW_VHT_TIMER)
  619. idx = beam_oid_info.sound_oid_idx;
  620. else {
  621. u8 i;
  622. for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {
  623. if (beam_info->beamformee_entry[i].is_used && !beam_info->beamformee_entry[i].is_sound) {
  624. idx = i;
  625. break;
  626. }
  627. }
  628. }
  629. return idx;
  630. }
  631. enum sounding_mode
  632. phydm_beamforming_sounding_mode(
  633. void *dm_void,
  634. struct _RT_BEAMFORMING_INFO *beam_info,
  635. u8 idx)
  636. {
  637. struct dm_struct *dm = (struct dm_struct *)dm_void;
  638. u8 support_interface = dm->support_interface;
  639. struct _RT_BEAMFORMEE_ENTRY beam_entry = beam_info->beamformee_entry[idx];
  640. struct _RT_BEAMFORMING_OID_INFO beam_oid_info = beam_info->beamforming_oid_info;
  641. enum sounding_mode mode = beam_oid_info.sound_oid_mode;
  642. if (beam_oid_info.sound_oid_mode == SOUNDING_SW_VHT_TIMER || beam_oid_info.sound_oid_mode == SOUNDING_HW_VHT_TIMER) {
  643. if (beam_entry.beamform_entry_cap & BEAMFORMER_CAP_VHT_SU)
  644. mode = beam_oid_info.sound_oid_mode;
  645. else
  646. mode = sounding_stop_all_timer;
  647. } else if (beam_oid_info.sound_oid_mode == SOUNDING_SW_HT_TIMER || beam_oid_info.sound_oid_mode == SOUNDING_HW_HT_TIMER) {
  648. if (beam_entry.beamform_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT)
  649. mode = beam_oid_info.sound_oid_mode;
  650. else
  651. mode = sounding_stop_all_timer;
  652. } else if (beam_entry.beamform_entry_cap & BEAMFORMER_CAP_VHT_SU) {
  653. if (support_interface == ODM_ITRF_USB && !(dm->support_ic_type & (ODM_RTL8814A | ODM_RTL8822B)))
  654. mode = SOUNDING_FW_VHT_TIMER;
  655. else
  656. mode = SOUNDING_SW_VHT_TIMER;
  657. } else if (beam_entry.beamform_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT) {
  658. if (support_interface == ODM_ITRF_USB && !(dm->support_ic_type & (ODM_RTL8814A | ODM_RTL8822B)))
  659. mode = SOUNDING_FW_HT_TIMER;
  660. else
  661. mode = SOUNDING_SW_HT_TIMER;
  662. } else
  663. mode = sounding_stop_all_timer;
  664. PHYDM_DBG(dm, DBG_TXBF, "[%s] support_interface=%d, mode=%d\n",
  665. __func__, support_interface, mode);
  666. return mode;
  667. }
  668. u16 phydm_beamforming_sounding_time(
  669. void *dm_void,
  670. struct _RT_BEAMFORMING_INFO *beam_info,
  671. enum sounding_mode mode,
  672. u8 idx)
  673. {
  674. u16 sounding_time = 0xffff;
  675. struct _RT_BEAMFORMEE_ENTRY beam_entry = beam_info->beamformee_entry[idx];
  676. struct _RT_BEAMFORMING_OID_INFO beam_oid_info = beam_info->beamforming_oid_info;
  677. struct dm_struct *dm = (struct dm_struct *)dm_void;
  678. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  679. if (mode == SOUNDING_HW_HT_TIMER || mode == SOUNDING_HW_VHT_TIMER)
  680. sounding_time = beam_oid_info.sound_oid_period * 32;
  681. else if (mode == SOUNDING_SW_HT_TIMER || mode == SOUNDING_SW_VHT_TIMER)
  682. /*@Modified by David*/
  683. sounding_time = beam_entry.sound_period; /*@beam_oid_info.sound_oid_period;*/
  684. else
  685. sounding_time = beam_entry.sound_period;
  686. return sounding_time;
  687. }
  688. enum channel_width
  689. phydm_beamforming_sounding_bw(
  690. void *dm_void,
  691. struct _RT_BEAMFORMING_INFO *beam_info,
  692. enum sounding_mode mode,
  693. u8 idx)
  694. {
  695. enum channel_width sounding_bw = CHANNEL_WIDTH_20;
  696. struct _RT_BEAMFORMEE_ENTRY beam_entry = beam_info->beamformee_entry[idx];
  697. struct _RT_BEAMFORMING_OID_INFO beam_oid_info = beam_info->beamforming_oid_info;
  698. struct dm_struct *dm = (struct dm_struct *)dm_void;
  699. if (mode == SOUNDING_HW_HT_TIMER || mode == SOUNDING_HW_VHT_TIMER)
  700. sounding_bw = beam_oid_info.sound_oid_bw;
  701. else if (mode == SOUNDING_SW_HT_TIMER || mode == SOUNDING_SW_VHT_TIMER)
  702. /*@Modified by David*/
  703. sounding_bw = beam_entry.sound_bw; /*@beam_oid_info.sound_oid_bw;*/
  704. else
  705. sounding_bw = beam_entry.sound_bw;
  706. PHYDM_DBG(dm, DBG_TXBF, "%s, sounding_bw=0x%X\n", __func__,
  707. sounding_bw);
  708. return sounding_bw;
  709. }
  710. boolean
  711. phydm_beamforming_select_beam_entry(
  712. void *dm_void,
  713. struct _RT_BEAMFORMING_INFO *beam_info)
  714. {
  715. struct _RT_SOUNDING_INFO *sound_info = &beam_info->sounding_info;
  716. struct dm_struct *dm = (struct dm_struct *)dm_void;
  717. /*@entry.is_sound is different between first and latter NDPA, and should not be used as BFee entry selection*/
  718. /*@BTW, latter modification should sync to the selection mechanism of AP/ADSL instead of the fixed sound_idx.*/
  719. sound_info->sound_idx = phydm_beamforming_sounding_idx(dm, beam_info);
  720. /*sound_info->sound_idx = 0;*/
  721. if (sound_info->sound_idx < BEAMFORMEE_ENTRY_NUM)
  722. sound_info->sound_mode = phydm_beamforming_sounding_mode(dm, beam_info, sound_info->sound_idx);
  723. else
  724. sound_info->sound_mode = sounding_stop_all_timer;
  725. if (sounding_stop_all_timer == sound_info->sound_mode) {
  726. PHYDM_DBG(dm, DBG_TXBF,
  727. "[%s] Return because of sounding_stop_all_timer\n",
  728. __func__);
  729. return false;
  730. } else {
  731. sound_info->sound_bw = phydm_beamforming_sounding_bw(dm, beam_info, sound_info->sound_mode, sound_info->sound_idx);
  732. sound_info->sound_period = phydm_beamforming_sounding_time(dm, beam_info, sound_info->sound_mode, sound_info->sound_idx);
  733. return true;
  734. }
  735. }
  736. /*SU BFee Entry Only*/
  737. boolean
  738. phydm_beamforming_start_period(
  739. void *dm_void)
  740. {
  741. struct dm_struct *dm = (struct dm_struct *)dm_void;
  742. boolean ret = true;
  743. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  744. struct _RT_SOUNDING_INFO *sound_info = &beam_info->sounding_info;
  745. phydm_beamforming_dym_ndpa_rate(dm);
  746. phydm_beamforming_select_beam_entry(dm, beam_info); /* @Modified */
  747. if (sound_info->sound_mode == SOUNDING_SW_VHT_TIMER || sound_info->sound_mode == SOUNDING_SW_HT_TIMER)
  748. odm_set_timer(dm, &beam_info->beamforming_timer, sound_info->sound_period);
  749. else if (sound_info->sound_mode == SOUNDING_HW_VHT_TIMER || sound_info->sound_mode == SOUNDING_HW_HT_TIMER ||
  750. sound_info->sound_mode == SOUNDING_AUTO_VHT_TIMER || sound_info->sound_mode == SOUNDING_AUTO_HT_TIMER) {
  751. HAL_HW_TIMER_TYPE timer_type = HAL_TIMER_TXBF;
  752. u32 val = (sound_info->sound_period | (timer_type << 16));
  753. /* @HW timer stop: All IC has the same setting */
  754. phydm_set_hw_reg_handler_interface(dm, HW_VAR_HW_REG_TIMER_STOP, (u8 *)(&timer_type));
  755. /* odm_write_1byte(dm, 0x15F, 0); */
  756. /* @HW timer init: All IC has the same setting, but 92E & 8812A only write 2 bytes */
  757. phydm_set_hw_reg_handler_interface(dm, HW_VAR_HW_REG_TIMER_INIT, (u8 *)(&val));
  758. /* odm_write_1byte(dm, 0x164, 1); */
  759. /* odm_write_4byte(dm, 0x15C, val); */
  760. /* @HW timer start: All IC has the same setting */
  761. phydm_set_hw_reg_handler_interface(dm, HW_VAR_HW_REG_TIMER_START, (u8 *)(&timer_type));
  762. /* odm_write_1byte(dm, 0x15F, 0x5); */
  763. } else if (sound_info->sound_mode == SOUNDING_FW_VHT_TIMER || sound_info->sound_mode == SOUNDING_FW_HT_TIMER)
  764. ret = beamforming_start_fw(dm, sound_info->sound_idx);
  765. else
  766. ret = false;
  767. PHYDM_DBG(dm, DBG_TXBF,
  768. "[%s] sound_idx=%d, sound_mode=%d, sound_bw=%d, sound_period=%d\n",
  769. __func__, sound_info->sound_idx, sound_info->sound_mode,
  770. sound_info->sound_bw, sound_info->sound_period);
  771. return ret;
  772. }
  773. /* Used after beamforming_leave, and will clear the setting of the "already deleted" entry
  774. *SU BFee Entry Only*/
  775. void phydm_beamforming_end_period_sw(
  776. void *dm_void)
  777. {
  778. struct dm_struct *dm = (struct dm_struct *)dm_void;
  779. /*void *adapter = dm->adapter;*/
  780. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  781. struct _RT_SOUNDING_INFO *sound_info = &beam_info->sounding_info;
  782. HAL_HW_TIMER_TYPE timer_type = HAL_TIMER_TXBF;
  783. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  784. if (sound_info->sound_mode == SOUNDING_SW_VHT_TIMER || sound_info->sound_mode == SOUNDING_SW_HT_TIMER)
  785. odm_cancel_timer(dm, &beam_info->beamforming_timer);
  786. else if (sound_info->sound_mode == SOUNDING_HW_VHT_TIMER || sound_info->sound_mode == SOUNDING_HW_HT_TIMER ||
  787. sound_info->sound_mode == SOUNDING_AUTO_VHT_TIMER || sound_info->sound_mode == SOUNDING_AUTO_HT_TIMER)
  788. /*@HW timer stop: All IC has the same setting*/
  789. phydm_set_hw_reg_handler_interface(dm, HW_VAR_HW_REG_TIMER_STOP, (u8 *)(&timer_type));
  790. /*odm_write_1byte(dm, 0x15F, 0);*/
  791. }
  792. void phydm_beamforming_end_period_fw(
  793. void *dm_void)
  794. {
  795. struct dm_struct *dm = (struct dm_struct *)dm_void;
  796. u8 idx = 0;
  797. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_FW_NDPA, (u8 *)&idx);
  798. PHYDM_DBG(dm, DBG_TXBF, "[%s]\n", __func__);
  799. }
  800. /*SU BFee Entry Only*/
  801. void phydm_beamforming_clear_entry_sw(
  802. void *dm_void,
  803. boolean is_delete,
  804. u8 delete_idx)
  805. {
  806. u8 idx = 0;
  807. struct _RT_BEAMFORMEE_ENTRY *beamform_entry = NULL;
  808. struct dm_struct *dm = (struct dm_struct *)dm_void;
  809. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  810. if (is_delete) {
  811. if (delete_idx < BEAMFORMEE_ENTRY_NUM) {
  812. beamform_entry = beam_info->beamformee_entry + delete_idx;
  813. if (!(!beamform_entry->is_used && beamform_entry->is_sound)) {
  814. PHYDM_DBG(dm, DBG_TXBF,
  815. "[%s] SW delete_idx is wrong!!!!!\n",
  816. __func__);
  817. return;
  818. }
  819. }
  820. PHYDM_DBG(dm, DBG_TXBF, "[%s] SW delete BFee entry %d\n",
  821. __func__, delete_idx);
  822. if (beamform_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSING) {
  823. beamform_entry->is_beamforming_in_progress = false;
  824. beamform_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
  825. } else if (beamform_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
  826. beamform_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
  827. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_STATUS, (u8 *)&delete_idx);
  828. }
  829. beamform_entry->is_sound = false;
  830. return;
  831. }
  832. for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {
  833. beamform_entry = beam_info->beamformee_entry + idx;
  834. /*Used after is_sounding=RESET, and will clear the setting of "ever sounded" entry, which is not necessarily be deleted.*/
  835. /*This function is mainly used in case "beam_oid_info.sound_oid_mode == sounding_stop_all_timer".*/
  836. /*@However, setting oid doesn't delete entries (is_used is still true), new entries may fail to be added in.*/
  837. if (!beamform_entry->is_sound)
  838. continue;
  839. PHYDM_DBG(dm, DBG_TXBF, "[%s] SW reset BFee entry %d\n",
  840. __func__, idx);
  841. /*@
  842. * If End procedure is
  843. * 1. Between (Send NDPA, C2H packet return), reset state to initialized.
  844. * After C2H packet return , status bit will be set to zero.
  845. *
  846. * 2. After C2H packet, then reset state to initialized and clear status bit.
  847. */
  848. if (beamform_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSING)
  849. phydm_beamforming_end_sw(dm, 0);
  850. else if (beamform_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
  851. beamform_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZED;
  852. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_STATUS, (u8 *)&idx);
  853. }
  854. beamform_entry->is_sound = false;
  855. }
  856. }
  857. void phydm_beamforming_clear_entry_fw(
  858. void *dm_void,
  859. boolean is_delete,
  860. u8 delete_idx)
  861. {
  862. u8 idx = 0;
  863. struct _RT_BEAMFORMEE_ENTRY *beamform_entry = NULL;
  864. struct dm_struct *dm = (struct dm_struct *)dm_void;
  865. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  866. if (is_delete) {
  867. if (delete_idx < BEAMFORMEE_ENTRY_NUM) {
  868. beamform_entry = beam_info->beamformee_entry + delete_idx;
  869. if (!(!beamform_entry->is_used && beamform_entry->is_sound)) {
  870. PHYDM_DBG(dm, DBG_TXBF,
  871. "[%s] FW delete_idx is wrong!!!!!\n",
  872. __func__);
  873. return;
  874. }
  875. }
  876. PHYDM_DBG(dm, DBG_TXBF, "%s: FW delete BFee entry %d\n",
  877. __func__, delete_idx);
  878. beamform_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
  879. beamform_entry->is_sound = false;
  880. } else {
  881. for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {
  882. beamform_entry = beam_info->beamformee_entry + idx;
  883. /*Used after is_sounding=RESET, and will clear the setting of "ever sounded" entry, which is not necessarily be deleted.*/
  884. /*This function is mainly used in case "beam_oid_info.sound_oid_mode == sounding_stop_all_timer".*/
  885. /*@However, setting oid doesn't delete entries (is_used is still true), new entries may fail to be added in.*/
  886. if (beamform_entry->is_sound) {
  887. PHYDM_DBG(dm, DBG_TXBF,
  888. "[%s]FW reset BFee entry %d\n",
  889. __func__, idx);
  890. /*@
  891. * If End procedure is
  892. * 1. Between (Send NDPA, C2H packet return), reset state to initialized.
  893. * After C2H packet return , status bit will be set to zero.
  894. *
  895. * 2. After C2H packet, then reset state to initialized and clear status bit.
  896. */
  897. beamform_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZED;
  898. beamform_entry->is_sound = false;
  899. }
  900. }
  901. }
  902. }
  903. /*@
  904. * Called :
  905. * 1. Add and delete entry : beamforming_enter/beamforming_leave
  906. * 2. FW trigger : Beamforming_SetTxBFen
  907. * 3. Set OID_RT_BEAMFORMING_PERIOD : beamforming_control_v2
  908. */
  909. void phydm_beamforming_notify(
  910. void *dm_void)
  911. {
  912. u8 idx = BEAMFORMEE_ENTRY_NUM;
  913. enum beamforming_notify_state is_sounding = BEAMFORMING_NOTIFY_NONE;
  914. struct dm_struct *dm = (struct dm_struct *)dm_void;
  915. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  916. struct _RT_SOUNDING_INFO *sound_info = &beam_info->sounding_info;
  917. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  918. is_sounding = phydm_beamfomring_is_sounding(dm, beam_info, &idx);
  919. PHYDM_DBG(dm, DBG_TXBF, "%s, Before notify, is_sounding=%d, idx=%d\n",
  920. __func__, is_sounding, idx);
  921. PHYDM_DBG(dm, DBG_TXBF, "%s: beam_info->beamformee_su_cnt = %d\n",
  922. __func__, beam_info->beamformee_su_cnt);
  923. switch (is_sounding) {
  924. case BEAMFORMEE_NOTIFY_ADD_SU:
  925. PHYDM_DBG(dm, DBG_TXBF, "%s: BEAMFORMEE_NOTIFY_ADD_SU\n",
  926. __func__);
  927. phydm_beamforming_start_period(dm);
  928. break;
  929. case BEAMFORMEE_NOTIFY_DELETE_SU:
  930. PHYDM_DBG(dm, DBG_TXBF, "%s: BEAMFORMEE_NOTIFY_DELETE_SU\n",
  931. __func__);
  932. if (sound_info->sound_mode == SOUNDING_FW_HT_TIMER || sound_info->sound_mode == SOUNDING_FW_VHT_TIMER) {
  933. phydm_beamforming_clear_entry_fw(dm, true, idx);
  934. if (beam_info->beamformee_su_cnt == 0) { /* @For 2->1 entry, we should not cancel SW timer */
  935. phydm_beamforming_end_period_fw(dm);
  936. PHYDM_DBG(dm, DBG_TXBF, "%s: No BFee left\n",
  937. __func__);
  938. }
  939. } else {
  940. phydm_beamforming_clear_entry_sw(dm, true, idx);
  941. if (beam_info->beamformee_su_cnt == 0) { /* @For 2->1 entry, we should not cancel SW timer */
  942. phydm_beamforming_end_period_sw(dm);
  943. PHYDM_DBG(dm, DBG_TXBF, "%s: No BFee left\n",
  944. __func__);
  945. }
  946. }
  947. break;
  948. case BEAMFORMEE_NOTIFY_ADD_MU:
  949. PHYDM_DBG(dm, DBG_TXBF, "%s: BEAMFORMEE_NOTIFY_ADD_MU\n",
  950. __func__);
  951. if (beam_info->beamformee_mu_cnt == 2) {
  952. /*@if (sound_info->sound_mode == SOUNDING_SW_VHT_TIMER || sound_info->sound_mode == SOUNDING_SW_HT_TIMER)
  953. odm_set_timer(dm, &beam_info->beamforming_timer, sound_info->sound_period);*/
  954. odm_set_timer(dm, &beam_info->beamforming_timer, 1000); /*@Do MU sounding every 1sec*/
  955. } else
  956. PHYDM_DBG(dm, DBG_TXBF,
  957. "%s: Less or larger than 2 MU STAs, not to set timer\n",
  958. __func__);
  959. break;
  960. case BEAMFORMEE_NOTIFY_DELETE_MU:
  961. PHYDM_DBG(dm, DBG_TXBF, "%s: BEAMFORMEE_NOTIFY_DELETE_MU\n",
  962. __func__);
  963. if (beam_info->beamformee_mu_cnt == 1) {
  964. /*@if (sound_info->sound_mode == SOUNDING_SW_VHT_TIMER || sound_info->sound_mode == SOUNDING_SW_HT_TIMER)*/ {
  965. odm_cancel_timer(dm, &beam_info->beamforming_timer);
  966. PHYDM_DBG(dm, DBG_TXBF,
  967. "%s: Less than 2 MU STAs, stop sounding\n",
  968. __func__);
  969. }
  970. }
  971. break;
  972. case BEAMFORMING_NOTIFY_RESET:
  973. if (sound_info->sound_mode == SOUNDING_FW_HT_TIMER || sound_info->sound_mode == SOUNDING_FW_VHT_TIMER) {
  974. phydm_beamforming_clear_entry_fw(dm, false, idx);
  975. phydm_beamforming_end_period_fw(dm);
  976. } else {
  977. phydm_beamforming_clear_entry_sw(dm, false, idx);
  978. phydm_beamforming_end_period_sw(dm);
  979. }
  980. break;
  981. default:
  982. break;
  983. }
  984. }
  985. boolean
  986. beamforming_init_entry(
  987. void *dm_void,
  988. u16 sta_idx,
  989. u8 *bfer_bfee_idx)
  990. {
  991. struct dm_struct *dm = (struct dm_struct *)dm_void;
  992. struct cmn_sta_info *cmn_sta = dm->phydm_sta_info[sta_idx];
  993. struct _RT_BEAMFORMEE_ENTRY *beamform_entry = NULL;
  994. struct _RT_BEAMFORMER_ENTRY *beamformer_entry = NULL;
  995. struct _RT_BEAMFORM_STAINFO *sta = NULL;
  996. enum beamforming_cap beamform_cap = BEAMFORMING_CAP_NONE;
  997. u8 bfer_idx = 0xF, bfee_idx = 0xF;
  998. u8 num_of_sounding_dim = 0, comp_steering_num_of_bfer = 0;
  999. if (!is_sta_active(cmn_sta)) {
  1000. PHYDM_DBG(dm, DBG_TXBF, "%s => sta_info(mac_id:%d) failed\n",
  1001. __func__, sta_idx);
  1002. #if (DM_ODM_SUPPORT_TYPE == ODM_CE)
  1003. rtw_warn_on(1);
  1004. #endif
  1005. return false;
  1006. }
  1007. sta = phydm_sta_info_init(dm, sta_idx);
  1008. /*The current setting does not support Beaforming*/
  1009. if (BEAMFORMING_CAP_NONE == sta->ht_beamform_cap && BEAMFORMING_CAP_NONE == sta->vht_beamform_cap) {
  1010. PHYDM_DBG(dm, DBG_TXBF,
  1011. "The configuration disabled Beamforming! Skip...\n");
  1012. return false;
  1013. }
  1014. if (!(cmn_sta->support_wireless_set & (WIRELESS_VHT | WIRELESS_HT)))
  1015. return false;
  1016. else {
  1017. if (cmn_sta->support_wireless_set & WIRELESS_HT) { /*@HT*/
  1018. if (TEST_FLAG(sta->cur_beamform, BEAMFORMING_HT_BEAMFORMER_ENABLE)) { /*We are Beamformee because the STA is Beamformer*/
  1019. beamform_cap = (enum beamforming_cap)(beamform_cap | BEAMFORMEE_CAP_HT_EXPLICIT);
  1020. num_of_sounding_dim = (sta->cur_beamform & BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP) >> 6;
  1021. }
  1022. /*We are Beamformer because the STA is Beamformee*/
  1023. if (TEST_FLAG(sta->cur_beamform, BEAMFORMING_HT_BEAMFORMEE_ENABLE) ||
  1024. TEST_FLAG(sta->ht_beamform_cap, BEAMFORMING_HT_BEAMFORMER_TEST)) {
  1025. beamform_cap = (enum beamforming_cap)(beamform_cap | BEAMFORMER_CAP_HT_EXPLICIT);
  1026. comp_steering_num_of_bfer = (sta->cur_beamform & BEAMFORMING_HT_BEAMFORMER_STEER_NUM) >> 4;
  1027. }
  1028. PHYDM_DBG(dm, DBG_TXBF,
  1029. "[%s] HT cur_beamform=0x%X, beamform_cap=0x%X\n",
  1030. __func__, sta->cur_beamform, beamform_cap);
  1031. PHYDM_DBG(dm, DBG_TXBF,
  1032. "[%s] HT num_of_sounding_dim=%d, comp_steering_num_of_bfer=%d\n",
  1033. __func__, num_of_sounding_dim,
  1034. comp_steering_num_of_bfer);
  1035. }
  1036. #if (ODM_IC_11AC_SERIES_SUPPORT == 1)
  1037. if (cmn_sta->support_wireless_set & WIRELESS_VHT) { /*VHT*/
  1038. /* We are Beamformee because the STA is SU Beamformer*/
  1039. if (TEST_FLAG(sta->cur_beamform_vht, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {
  1040. beamform_cap = (enum beamforming_cap)(beamform_cap | BEAMFORMEE_CAP_VHT_SU);
  1041. num_of_sounding_dim = (sta->cur_beamform_vht & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM) >> 12;
  1042. }
  1043. /* We are Beamformer because the STA is SU Beamformee*/
  1044. if (TEST_FLAG(sta->cur_beamform_vht, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) ||
  1045. TEST_FLAG(sta->vht_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_TEST)) {
  1046. beamform_cap = (enum beamforming_cap)(beamform_cap | BEAMFORMER_CAP_VHT_SU);
  1047. comp_steering_num_of_bfer = (sta->cur_beamform_vht & BEAMFORMING_VHT_BEAMFORMER_STS_CAP) >> 8;
  1048. }
  1049. /* We are Beamformee because the STA is MU Beamformer*/
  1050. if (TEST_FLAG(sta->cur_beamform_vht, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) {
  1051. beamform_cap = (enum beamforming_cap)(beamform_cap | BEAMFORMEE_CAP_VHT_MU);
  1052. num_of_sounding_dim = (sta->cur_beamform_vht & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM) >> 12;
  1053. }
  1054. /* We are Beamformer because the STA is MU Beamformee*/
  1055. if (phydm_acting_determine(dm, phydm_acting_as_ap)) { /* Only AP mode supports to act an MU beamformer */
  1056. if (TEST_FLAG(sta->cur_beamform_vht, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE) ||
  1057. TEST_FLAG(sta->vht_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_TEST)) {
  1058. beamform_cap = (enum beamforming_cap)(beamform_cap | BEAMFORMER_CAP_VHT_MU);
  1059. comp_steering_num_of_bfer = (sta->cur_beamform_vht & BEAMFORMING_VHT_BEAMFORMER_STS_CAP) >> 8;
  1060. }
  1061. }
  1062. PHYDM_DBG(dm, DBG_TXBF,
  1063. "[%s]VHT cur_beamform_vht=0x%X, beamform_cap=0x%X\n",
  1064. __func__, sta->cur_beamform_vht,
  1065. beamform_cap);
  1066. PHYDM_DBG(dm, DBG_TXBF,
  1067. "[%s]VHT num_of_sounding_dim=0x%X, comp_steering_num_of_bfer=0x%X\n",
  1068. __func__, num_of_sounding_dim,
  1069. comp_steering_num_of_bfer);
  1070. }
  1071. #endif
  1072. }
  1073. if (beamform_cap == BEAMFORMING_CAP_NONE)
  1074. return false;
  1075. PHYDM_DBG(dm, DBG_TXBF, "[%s] Self BF Entry Cap = 0x%02X\n", __func__,
  1076. beamform_cap);
  1077. /*We are BFee, so the entry is BFer*/
  1078. if (beamform_cap & (BEAMFORMEE_CAP_VHT_MU | BEAMFORMEE_CAP_VHT_SU | BEAMFORMEE_CAP_HT_EXPLICIT)) {
  1079. beamformer_entry = phydm_beamforming_get_bfer_entry_by_addr(dm, sta->ra, &bfer_idx);
  1080. if (beamformer_entry == NULL) {
  1081. beamformer_entry = beamforming_add_bfer_entry(dm, sta, beamform_cap, num_of_sounding_dim, &bfer_idx);
  1082. if (beamformer_entry == NULL)
  1083. PHYDM_DBG(dm, DBG_TXBF,
  1084. "[%s]Not enough BFer entry!!!!!\n",
  1085. __func__);
  1086. }
  1087. }
  1088. /*We are BFer, so the entry is BFee*/
  1089. if (beamform_cap & (BEAMFORMER_CAP_VHT_MU | BEAMFORMER_CAP_VHT_SU | BEAMFORMER_CAP_HT_EXPLICIT)) {
  1090. beamform_entry = phydm_beamforming_get_bfee_entry_by_addr(dm, sta->ra, &bfee_idx);
  1091. /*@if BFeeIdx = 0xF, that represent for no matched MACID among all linked entrys */
  1092. PHYDM_DBG(dm, DBG_TXBF, "[%s] Get BFee entry 0x%X by address\n",
  1093. __func__, bfee_idx);
  1094. if (beamform_entry == NULL) {
  1095. beamform_entry = beamforming_add_bfee_entry(dm, sta, beamform_cap, num_of_sounding_dim, comp_steering_num_of_bfer, &bfee_idx);
  1096. PHYDM_DBG(dm, DBG_TXBF,
  1097. "[%s]: sta->AID=%d, sta->mac_id=%d\n",
  1098. __func__, sta->aid, sta->mac_id);
  1099. PHYDM_DBG(dm, DBG_TXBF, "[%s]: Add BFee entry %d\n",
  1100. __func__, bfee_idx);
  1101. if (beamform_entry == NULL)
  1102. return false;
  1103. else
  1104. beamform_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
  1105. } else {
  1106. /*@Entry has been created. If entry is initialing or progressing then errors occur.*/
  1107. if (beamform_entry->beamform_entry_state != BEAMFORMING_ENTRY_STATE_INITIALIZED &&
  1108. beamform_entry->beamform_entry_state != BEAMFORMING_ENTRY_STATE_PROGRESSED)
  1109. return false;
  1110. else
  1111. beamform_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
  1112. }
  1113. beamform_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZED;
  1114. phydm_sta_info_update(dm, sta_idx, beamform_entry);
  1115. }
  1116. *bfer_bfee_idx = (bfer_idx << 4) | bfee_idx;
  1117. PHYDM_DBG(dm, DBG_TXBF,
  1118. "[%s] End: bfer_idx=0x%X, bfee_idx=0x%X, bfer_bfee_idx=0x%X\n",
  1119. __func__, bfer_idx, bfee_idx, *bfer_bfee_idx);
  1120. return true;
  1121. }
  1122. void beamforming_deinit_entry(
  1123. void *dm_void,
  1124. u8 *RA)
  1125. {
  1126. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1127. u8 idx = 0;
  1128. struct _RT_BEAMFORMER_ENTRY *bfer_entry = phydm_beamforming_get_bfer_entry_by_addr(dm, RA, &idx);
  1129. struct _RT_BEAMFORMEE_ENTRY *bfee_entry = phydm_beamforming_get_bfee_entry_by_addr(dm, RA, &idx);
  1130. boolean ret = false;
  1131. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  1132. if (bfee_entry != NULL) {
  1133. PHYDM_DBG(dm, DBG_TXBF, "%s, bfee_entry\n", __func__);
  1134. bfee_entry->is_used = false;
  1135. bfee_entry->beamform_entry_cap = BEAMFORMING_CAP_NONE;
  1136. bfee_entry->is_beamforming_in_progress = false;
  1137. if (bfee_entry->is_mu_sta) {
  1138. dm->beamforming_info.beamformee_mu_cnt -= 1;
  1139. dm->beamforming_info.first_mu_bfee_index = phydm_beamforming_get_first_mu_bfee_entry_idx(dm);
  1140. } else
  1141. dm->beamforming_info.beamformee_su_cnt -= 1;
  1142. ret = true;
  1143. }
  1144. if (bfer_entry != NULL) {
  1145. PHYDM_DBG(dm, DBG_TXBF, "%s, bfer_entry\n", __func__);
  1146. bfer_entry->is_used = false;
  1147. bfer_entry->beamform_entry_cap = BEAMFORMING_CAP_NONE;
  1148. if (bfer_entry->is_mu_ap)
  1149. dm->beamforming_info.beamformer_mu_cnt -= 1;
  1150. else
  1151. dm->beamforming_info.beamformer_su_cnt -= 1;
  1152. ret = true;
  1153. }
  1154. if (ret == true)
  1155. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_LEAVE, (u8 *)&idx);
  1156. PHYDM_DBG(dm, DBG_TXBF, "%s End, idx = 0x%X\n", __func__, idx);
  1157. }
  1158. boolean
  1159. beamforming_start_v1(
  1160. void *dm_void,
  1161. u8 *RA,
  1162. boolean mode,
  1163. enum channel_width BW,
  1164. u8 rate)
  1165. {
  1166. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1167. u8 idx = 0;
  1168. struct _RT_BEAMFORMEE_ENTRY *entry;
  1169. boolean ret = true;
  1170. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  1171. entry = phydm_beamforming_get_bfee_entry_by_addr(dm, RA, &idx);
  1172. if (entry->is_used == false) {
  1173. entry->is_beamforming_in_progress = false;
  1174. return false;
  1175. } else {
  1176. if (entry->is_beamforming_in_progress)
  1177. return false;
  1178. entry->is_beamforming_in_progress = true;
  1179. if (mode == 1) {
  1180. if (!(entry->beamform_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT)) {
  1181. entry->is_beamforming_in_progress = false;
  1182. return false;
  1183. }
  1184. } else if (mode == 0) {
  1185. if (!(entry->beamform_entry_cap & BEAMFORMER_CAP_VHT_SU)) {
  1186. entry->is_beamforming_in_progress = false;
  1187. return false;
  1188. }
  1189. }
  1190. if (entry->beamform_entry_state != BEAMFORMING_ENTRY_STATE_INITIALIZED && entry->beamform_entry_state != BEAMFORMING_ENTRY_STATE_PROGRESSED) {
  1191. entry->is_beamforming_in_progress = false;
  1192. return false;
  1193. } else {
  1194. entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSING;
  1195. entry->is_sound = true;
  1196. }
  1197. }
  1198. entry->sound_bw = BW;
  1199. beam_info->beamformee_cur_idx = idx;
  1200. phydm_beamforming_ndpa_rate(dm, BW, rate);
  1201. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_STATUS, (u8 *)&idx);
  1202. if (mode == 1)
  1203. ret = beamforming_send_ht_ndpa_packet(dm, RA, BW, NORMAL_QUEUE);
  1204. else
  1205. ret = beamforming_send_vht_ndpa_packet(dm, RA, entry->aid, BW, NORMAL_QUEUE);
  1206. if (ret == false) {
  1207. beamforming_leave(dm, RA);
  1208. entry->is_beamforming_in_progress = false;
  1209. return false;
  1210. }
  1211. PHYDM_DBG(dm, DBG_TXBF, "%s idx %d\n", __func__, idx);
  1212. return true;
  1213. }
  1214. boolean
  1215. beamforming_start_sw(
  1216. void *dm_void,
  1217. u8 idx,
  1218. u8 mode,
  1219. enum channel_width BW)
  1220. {
  1221. u8 *ra = NULL;
  1222. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1223. struct _RT_BEAMFORMEE_ENTRY *entry;
  1224. boolean ret = true;
  1225. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  1226. #ifdef SUPPORT_MU_BF
  1227. #if (SUPPORT_MU_BF == 1)
  1228. u8 i, poll_sta_cnt = 0;
  1229. boolean is_get_first_bfee = false;
  1230. #endif
  1231. #endif
  1232. if (beam_info->is_mu_sounding) {
  1233. beam_info->is_mu_sounding_in_progress = true;
  1234. entry = &beam_info->beamformee_entry[idx];
  1235. ra = entry->mac_addr;
  1236. } else {
  1237. entry = &beam_info->beamformee_entry[idx];
  1238. if (entry->is_used == false) {
  1239. PHYDM_DBG(dm, DBG_TXBF,
  1240. "Skip Beamforming, no entry for idx =%d\n",
  1241. idx);
  1242. entry->is_beamforming_in_progress = false;
  1243. return false;
  1244. }
  1245. if (entry->is_beamforming_in_progress) {
  1246. PHYDM_DBG(dm, DBG_TXBF,
  1247. "is_beamforming_in_progress, skip...\n");
  1248. return false;
  1249. }
  1250. entry->is_beamforming_in_progress = true;
  1251. ra = entry->mac_addr;
  1252. if (mode == SOUNDING_SW_HT_TIMER || mode == SOUNDING_HW_HT_TIMER || mode == SOUNDING_AUTO_HT_TIMER) {
  1253. if (!(entry->beamform_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT)) {
  1254. entry->is_beamforming_in_progress = false;
  1255. PHYDM_DBG(dm, DBG_TXBF,
  1256. "%s Return by not support BEAMFORMER_CAP_HT_EXPLICIT <==\n",
  1257. __func__);
  1258. return false;
  1259. }
  1260. } else if (mode == SOUNDING_SW_VHT_TIMER || mode == SOUNDING_HW_VHT_TIMER || mode == SOUNDING_AUTO_VHT_TIMER) {
  1261. if (!(entry->beamform_entry_cap & BEAMFORMER_CAP_VHT_SU)) {
  1262. entry->is_beamforming_in_progress = false;
  1263. PHYDM_DBG(dm, DBG_TXBF,
  1264. "%s Return by not support BEAMFORMER_CAP_VHT_SU <==\n",
  1265. __func__);
  1266. return false;
  1267. }
  1268. }
  1269. if (entry->beamform_entry_state != BEAMFORMING_ENTRY_STATE_INITIALIZED && entry->beamform_entry_state != BEAMFORMING_ENTRY_STATE_PROGRESSED) {
  1270. entry->is_beamforming_in_progress = false;
  1271. PHYDM_DBG(dm, DBG_TXBF,
  1272. "%s Return by incorrect beamform_entry_state(%d) <==\n",
  1273. __func__, entry->beamform_entry_state);
  1274. return false;
  1275. } else {
  1276. entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSING;
  1277. entry->is_sound = true;
  1278. }
  1279. beam_info->beamformee_cur_idx = idx;
  1280. }
  1281. /*@2014.12.22 Luke: Need to be checked*/
  1282. /*@GET_TXBF_INFO(adapter)->fTxbfSet(adapter, TXBF_SET_SOUNDING_STATUS, (u8*)&idx);*/
  1283. if (mode == SOUNDING_SW_HT_TIMER || mode == SOUNDING_HW_HT_TIMER || mode == SOUNDING_AUTO_HT_TIMER)
  1284. ret = beamforming_send_ht_ndpa_packet(dm, ra, BW, NORMAL_QUEUE);
  1285. else
  1286. ret = beamforming_send_vht_ndpa_packet(dm, ra, entry->aid, BW, NORMAL_QUEUE);
  1287. if (ret == false) {
  1288. beamforming_leave(dm, ra);
  1289. entry->is_beamforming_in_progress = false;
  1290. return false;
  1291. }
  1292. /*@--------------------------
  1293. * Send BF Report Poll for MU BF
  1294. --------------------------*/
  1295. #ifdef SUPPORT_MU_BF
  1296. #if (SUPPORT_MU_BF == 1)
  1297. if (beam_info->beamformee_mu_cnt <= 1)
  1298. goto out;
  1299. /* @More than 1 MU STA*/
  1300. for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {
  1301. entry = &beam_info->beamformee_entry[i];
  1302. if (!entry->is_mu_sta)
  1303. continue;
  1304. if (!is_get_first_bfee) {
  1305. is_get_first_bfee = true;
  1306. continue;
  1307. }
  1308. poll_sta_cnt++;
  1309. if (poll_sta_cnt == (beam_info->beamformee_mu_cnt - 1)) /* The last STA*/
  1310. send_sw_vht_bf_report_poll(dm, entry->mac_addr, true);
  1311. else
  1312. send_sw_vht_bf_report_poll(dm, entry->mac_addr, false);
  1313. }
  1314. out:
  1315. #endif
  1316. #endif
  1317. return true;
  1318. }
  1319. boolean
  1320. beamforming_start_fw(
  1321. void *dm_void,
  1322. u8 idx)
  1323. {
  1324. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1325. struct _RT_BEAMFORMEE_ENTRY *entry;
  1326. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  1327. entry = &beam_info->beamformee_entry[idx];
  1328. if (entry->is_used == false) {
  1329. PHYDM_DBG(dm, DBG_TXBF,
  1330. "Skip Beamforming, no entry for idx =%d\n", idx);
  1331. return false;
  1332. }
  1333. entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSING;
  1334. entry->is_sound = true;
  1335. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_FW_NDPA, (u8 *)&idx);
  1336. PHYDM_DBG(dm, DBG_TXBF, "[%s] End, idx=0x%X\n", __func__, idx);
  1337. return true;
  1338. }
  1339. void beamforming_check_sounding_success(
  1340. void *dm_void,
  1341. boolean status)
  1342. {
  1343. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1344. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  1345. struct _RT_BEAMFORMEE_ENTRY *entry = &beam_info->beamformee_entry[beam_info->beamformee_cur_idx];
  1346. PHYDM_DBG(dm, DBG_TXBF, "[David]@%s Start!\n", __func__);
  1347. if (status == 1) {
  1348. if (entry->log_status_fail_cnt == 21)
  1349. beamforming_dym_period(dm, status);
  1350. entry->log_status_fail_cnt = 0;
  1351. } else if (entry->log_status_fail_cnt <= 20) {
  1352. entry->log_status_fail_cnt++;
  1353. PHYDM_DBG(dm, DBG_TXBF, "%s log_status_fail_cnt %d\n", __func__,
  1354. entry->log_status_fail_cnt);
  1355. }
  1356. if (entry->log_status_fail_cnt > 20) {
  1357. entry->log_status_fail_cnt = 21;
  1358. PHYDM_DBG(dm, DBG_TXBF,
  1359. "%s log_status_fail_cnt > 20, Stop SOUNDING\n",
  1360. __func__);
  1361. beamforming_dym_period(dm, status);
  1362. }
  1363. }
  1364. void phydm_beamforming_end_sw(
  1365. void *dm_void,
  1366. boolean status)
  1367. {
  1368. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1369. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  1370. struct _RT_BEAMFORMEE_ENTRY *entry = &beam_info->beamformee_entry[beam_info->beamformee_cur_idx];
  1371. if (beam_info->is_mu_sounding) {
  1372. PHYDM_DBG(dm, DBG_TXBF, "%s: MU sounding done\n", __func__);
  1373. beam_info->is_mu_sounding_in_progress = false;
  1374. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_STATUS,
  1375. (u8 *)&beam_info->beamformee_cur_idx);
  1376. } else {
  1377. if (entry->beamform_entry_state != BEAMFORMING_ENTRY_STATE_PROGRESSING) {
  1378. PHYDM_DBG(dm, DBG_TXBF, "[%s] BeamformStatus %d\n",
  1379. __func__, entry->beamform_entry_state);
  1380. return;
  1381. }
  1382. if (beam_info->tx_bf_data_rate >= ODM_RATEVHTSS3MCS7 && beam_info->tx_bf_data_rate <= ODM_RATEVHTSS3MCS9 && !beam_info->snding3ss) {
  1383. PHYDM_DBG(dm, DBG_TXBF,
  1384. "[%s] VHT3SS 7,8,9, do not apply V matrix.\n",
  1385. __func__);
  1386. entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZED;
  1387. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_STATUS,
  1388. (u8 *)&beam_info->beamformee_cur_idx);
  1389. } else if (status == 1) {
  1390. entry->log_status_fail_cnt = 0;
  1391. entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSED;
  1392. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_STATUS,
  1393. (u8 *)&beam_info->beamformee_cur_idx);
  1394. } else {
  1395. entry->log_status_fail_cnt++;
  1396. entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZED;
  1397. hal_com_txbf_set(dm, TXBF_SET_TX_PATH_RESET,
  1398. (u8 *)&beam_info->beamformee_cur_idx);
  1399. PHYDM_DBG(dm, DBG_TXBF, "[%s] log_status_fail_cnt %d\n",
  1400. __func__, entry->log_status_fail_cnt);
  1401. }
  1402. if (entry->log_status_fail_cnt > 50) {
  1403. PHYDM_DBG(dm, DBG_TXBF,
  1404. "%s log_status_fail_cnt > 50, Stop SOUNDING\n",
  1405. __func__);
  1406. entry->is_sound = false;
  1407. beamforming_deinit_entry(dm, entry->mac_addr);
  1408. /*@Modified by David - Every action of deleting entry should follow by Notify*/
  1409. phydm_beamforming_notify(dm);
  1410. }
  1411. entry->is_beamforming_in_progress = false;
  1412. }
  1413. PHYDM_DBG(dm, DBG_TXBF, "%s: status=%d\n", __func__, status);
  1414. }
  1415. void beamforming_timer_callback(
  1416. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  1417. void *dm_void
  1418. #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
  1419. void *context
  1420. #endif
  1421. )
  1422. {
  1423. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  1424. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1425. #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
  1426. void *adapter = (void *)context;
  1427. PHAL_DATA_TYPE hal_data = GET_HAL_DATA(((PADAPTER)adapter));
  1428. struct dm_struct *dm = &hal_data->odmpriv;
  1429. #endif
  1430. boolean ret = false;
  1431. struct _RT_BEAMFORMING_INFO *beam_info = &(dm->beamforming_info);
  1432. struct _RT_BEAMFORMEE_ENTRY *entry = &(beam_info->beamformee_entry[beam_info->beamformee_cur_idx]);
  1433. struct _RT_SOUNDING_INFO *sound_info = &(beam_info->sounding_info);
  1434. boolean is_beamforming_in_progress;
  1435. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  1436. if (beam_info->is_mu_sounding)
  1437. is_beamforming_in_progress = beam_info->is_mu_sounding_in_progress;
  1438. else
  1439. is_beamforming_in_progress = entry->is_beamforming_in_progress;
  1440. if (is_beamforming_in_progress) {
  1441. PHYDM_DBG(dm, DBG_TXBF,
  1442. "is_beamforming_in_progress, reset it\n");
  1443. phydm_beamforming_end_sw(dm, 0);
  1444. }
  1445. ret = phydm_beamforming_select_beam_entry(dm, beam_info);
  1446. #if (SUPPORT_MU_BF == 1)
  1447. if (ret && beam_info->beamformee_mu_cnt > 1)
  1448. ret = 1;
  1449. else
  1450. ret = 0;
  1451. #endif
  1452. if (ret)
  1453. ret = beamforming_start_sw(dm, sound_info->sound_idx, sound_info->sound_mode, sound_info->sound_bw);
  1454. else
  1455. PHYDM_DBG(dm, DBG_TXBF,
  1456. "%s, Error value return from BeamformingStart_V2\n",
  1457. __func__);
  1458. if (beam_info->beamformee_su_cnt != 0 || beam_info->beamformee_mu_cnt > 1) {
  1459. if (sound_info->sound_mode == SOUNDING_SW_VHT_TIMER || sound_info->sound_mode == SOUNDING_SW_HT_TIMER)
  1460. odm_set_timer(dm, &beam_info->beamforming_timer, sound_info->sound_period);
  1461. else {
  1462. u32 val = (sound_info->sound_period << 16) | HAL_TIMER_TXBF;
  1463. phydm_set_hw_reg_handler_interface(dm, HW_VAR_HW_REG_TIMER_RESTART, (u8 *)(&val));
  1464. }
  1465. }
  1466. }
  1467. void beamforming_sw_timer_callback(
  1468. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  1469. struct phydm_timer_list *timer
  1470. #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
  1471. void *function_context
  1472. #endif
  1473. )
  1474. {
  1475. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  1476. void *adapter = (void *)timer->Adapter;
  1477. HAL_DATA_TYPE *hal_data = GET_HAL_DATA(((PADAPTER)adapter));
  1478. struct dm_struct *dm = &hal_data->DM_OutSrc;
  1479. PHYDM_DBG(dm, DBG_TXBF, "[%s] Start!\n", __func__);
  1480. beamforming_timer_callback(dm);
  1481. #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
  1482. struct dm_struct *dm = (struct dm_struct *)function_context;
  1483. void *adapter = dm->adapter;
  1484. if (*dm->is_net_closed == true)
  1485. return;
  1486. phydm_run_in_thread_cmd(dm, beamforming_timer_callback, adapter);
  1487. #endif
  1488. }
  1489. void phydm_beamforming_init(
  1490. void *dm_void)
  1491. {
  1492. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1493. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  1494. struct _RT_BEAMFORMING_OID_INFO *beam_oid_info = &beam_info->beamforming_oid_info;
  1495. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  1496. void *adapter = dm->adapter;
  1497. HAL_DATA_TYPE *hal_data = GET_HAL_DATA(((PADAPTER)adapter));
  1498. #ifdef BEAMFORMING_VERSION_1
  1499. if (hal_data->beamforming_version != BEAMFORMING_VERSION_1) {
  1500. return;
  1501. }
  1502. #endif
  1503. #endif
  1504. beam_oid_info->sound_oid_mode = SOUNDING_STOP_OID_TIMER;
  1505. PHYDM_DBG(dm, DBG_TXBF, "%s mode (%d)\n", __func__,
  1506. beam_oid_info->sound_oid_mode);
  1507. beam_info->beamformee_su_cnt = 0;
  1508. beam_info->beamformer_su_cnt = 0;
  1509. beam_info->beamformee_mu_cnt = 0;
  1510. beam_info->beamformer_mu_cnt = 0;
  1511. beam_info->beamformee_mu_reg_maping = 0;
  1512. beam_info->mu_ap_index = 0;
  1513. beam_info->is_mu_sounding = false;
  1514. beam_info->first_mu_bfee_index = 0xFF;
  1515. beam_info->apply_v_matrix = true;
  1516. beam_info->snding3ss = false;
  1517. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  1518. beam_info->source_adapter = dm->adapter;
  1519. #endif
  1520. hal_com_txbf_beamform_init(dm);
  1521. }
  1522. boolean
  1523. phydm_acting_determine(
  1524. void *dm_void,
  1525. enum phydm_acting_type type)
  1526. {
  1527. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1528. boolean ret = false;
  1529. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  1530. void *adapter = dm->beamforming_info.source_adapter;
  1531. #else
  1532. struct _ADAPTER *adapter = dm->adapter;
  1533. #endif
  1534. #if (DM_ODM_SUPPORT_TYPE & ODM_WIN)
  1535. if (type == phydm_acting_as_ap)
  1536. ret = ACTING_AS_AP(adapter);
  1537. else if (type == phydm_acting_as_ibss)
  1538. ret = ACTING_AS_IBSS(((PADAPTER)(adapter)));
  1539. #elif (DM_ODM_SUPPORT_TYPE & ODM_CE)
  1540. struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
  1541. if (type == phydm_acting_as_ap)
  1542. ret = check_fwstate(pmlmepriv, WIFI_AP_STATE);
  1543. else if (type == phydm_acting_as_ibss)
  1544. ret = check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
  1545. #endif
  1546. return ret;
  1547. }
  1548. void beamforming_enter(
  1549. void *dm_void,
  1550. u16 sta_idx)
  1551. {
  1552. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1553. u8 bfer_bfee_idx = 0xff;
  1554. if (beamforming_init_entry(dm, sta_idx, &bfer_bfee_idx))
  1555. hal_com_txbf_set(dm, TXBF_SET_SOUNDING_ENTER, (u8 *)&bfer_bfee_idx);
  1556. PHYDM_DBG(dm, DBG_TXBF, "[%s] End!\n", __func__);
  1557. }
  1558. void beamforming_leave(
  1559. void *dm_void,
  1560. u8 *RA)
  1561. {
  1562. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1563. if (RA != NULL) {
  1564. beamforming_deinit_entry(dm, RA);
  1565. phydm_beamforming_notify(dm);
  1566. }
  1567. PHYDM_DBG(dm, DBG_TXBF, "[%s] End!!\n", __func__);
  1568. }
  1569. #if 0
  1570. /* Nobody calls this function */
  1571. void
  1572. phydm_beamforming_set_txbf_en(
  1573. void *dm_void,
  1574. u8 mac_id,
  1575. boolean is_txbf
  1576. )
  1577. {
  1578. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1579. u8 idx = 0;
  1580. struct _RT_BEAMFORMEE_ENTRY *entry;
  1581. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  1582. entry = phydm_beamforming_get_entry_by_mac_id(dm, mac_id, &idx);
  1583. if (entry == NULL)
  1584. return;
  1585. else
  1586. entry->is_txbf = is_txbf;
  1587. PHYDM_DBG(dm, DBG_TXBF, "%s mac_id %d TxBF %d\n", __func__,
  1588. entry->mac_id, entry->is_txbf);
  1589. phydm_beamforming_notify(dm);
  1590. }
  1591. #endif
  1592. enum beamforming_cap
  1593. phydm_beamforming_get_beam_cap(
  1594. void *dm_void,
  1595. struct _RT_BEAMFORMING_INFO *beam_info)
  1596. {
  1597. u8 i;
  1598. boolean is_self_beamformer = false;
  1599. boolean is_self_beamformee = false;
  1600. struct _RT_BEAMFORMEE_ENTRY beamformee_entry;
  1601. struct _RT_BEAMFORMER_ENTRY beamformer_entry;
  1602. enum beamforming_cap beamform_cap = BEAMFORMING_CAP_NONE;
  1603. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1604. PHYDM_DBG(dm, DBG_TXBF, "[%s] Start!\n", __func__);
  1605. for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {
  1606. beamformee_entry = beam_info->beamformee_entry[i];
  1607. if (beamformee_entry.is_used) {
  1608. is_self_beamformer = true;
  1609. PHYDM_DBG(dm, DBG_TXBF,
  1610. "[%s] BFee entry %d is_used=true\n", __func__,
  1611. i);
  1612. break;
  1613. }
  1614. }
  1615. for (i = 0; i < BEAMFORMER_ENTRY_NUM; i++) {
  1616. beamformer_entry = beam_info->beamformer_entry[i];
  1617. if (beamformer_entry.is_used) {
  1618. is_self_beamformee = true;
  1619. PHYDM_DBG(dm, DBG_TXBF,
  1620. "[%s]: BFer entry %d is_used=true\n",
  1621. __func__, i);
  1622. break;
  1623. }
  1624. }
  1625. if (is_self_beamformer)
  1626. beamform_cap = (enum beamforming_cap)(beamform_cap | BEAMFORMER_CAP);
  1627. if (is_self_beamformee)
  1628. beamform_cap = (enum beamforming_cap)(beamform_cap | BEAMFORMEE_CAP);
  1629. return beamform_cap;
  1630. }
  1631. boolean
  1632. beamforming_control_v1(
  1633. void *dm_void,
  1634. u8 *RA,
  1635. u8 AID,
  1636. u8 mode,
  1637. enum channel_width BW,
  1638. u8 rate)
  1639. {
  1640. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1641. boolean ret = true;
  1642. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  1643. PHYDM_DBG(dm, DBG_TXBF, "AID (%d), mode (%d), BW (%d)\n", AID, mode,
  1644. BW);
  1645. switch (mode) {
  1646. case 0:
  1647. ret = beamforming_start_v1(dm, RA, 0, BW, rate);
  1648. break;
  1649. case 1:
  1650. ret = beamforming_start_v1(dm, RA, 1, BW, rate);
  1651. break;
  1652. case 2:
  1653. phydm_beamforming_ndpa_rate(dm, BW, rate);
  1654. ret = beamforming_send_vht_ndpa_packet(dm, RA, AID, BW, NORMAL_QUEUE);
  1655. break;
  1656. case 3:
  1657. phydm_beamforming_ndpa_rate(dm, BW, rate);
  1658. ret = beamforming_send_ht_ndpa_packet(dm, RA, BW, NORMAL_QUEUE);
  1659. break;
  1660. }
  1661. return ret;
  1662. }
  1663. /*Only OID uses this function*/
  1664. boolean
  1665. phydm_beamforming_control_v2(
  1666. void *dm_void,
  1667. u8 idx,
  1668. u8 mode,
  1669. enum channel_width BW,
  1670. u16 period)
  1671. {
  1672. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1673. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  1674. struct _RT_BEAMFORMING_OID_INFO *beam_oid_info = &beam_info->beamforming_oid_info;
  1675. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  1676. PHYDM_DBG(dm, DBG_TXBF, "idx (%d), mode (%d), BW (%d), period (%d)\n",
  1677. idx, mode, BW, period);
  1678. beam_oid_info->sound_oid_idx = idx;
  1679. beam_oid_info->sound_oid_mode = (enum sounding_mode)mode;
  1680. beam_oid_info->sound_oid_bw = BW;
  1681. beam_oid_info->sound_oid_period = period;
  1682. phydm_beamforming_notify(dm);
  1683. return true;
  1684. }
  1685. void phydm_beamforming_watchdog(
  1686. void *dm_void)
  1687. {
  1688. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1689. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  1690. PHYDM_DBG(dm, DBG_TXBF, "%s Start!\n", __func__);
  1691. if (beam_info->beamformee_su_cnt == 0)
  1692. return;
  1693. beamforming_dym_period(dm, 0);
  1694. }
  1695. enum beamforming_cap
  1696. phydm_get_beamform_cap(
  1697. void *dm_void)
  1698. {
  1699. struct dm_struct *dm = (struct dm_struct *)dm_void;
  1700. struct cmn_sta_info *sta = NULL;
  1701. struct bf_cmn_info *bf_info = NULL;
  1702. struct _RT_BEAMFORMING_INFO *beam_info = &dm->beamforming_info;
  1703. void *adapter = dm->adapter;
  1704. enum beamforming_cap beamform_cap = BEAMFORMING_CAP_NONE;
  1705. u8 macid;
  1706. u8 ht_curbeamformcap = 0;
  1707. u16 vht_curbeamformcap = 0;
  1708. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  1709. PMGNT_INFO p_MgntInfo = &(((PADAPTER)(adapter))->MgntInfo);
  1710. PRT_VERY_HIGH_THROUGHPUT p_vht_info = GET_VHT_INFO(p_MgntInfo);
  1711. PRT_HIGH_THROUGHPUT p_ht_info = GET_HT_INFO(p_MgntInfo);
  1712. ht_curbeamformcap = p_ht_info->HtCurBeamform;
  1713. vht_curbeamformcap = p_vht_info->VhtCurBeamform;
  1714. PHYDM_DBG(dm, DBG_ANT_DIV,
  1715. "[%s] WIN ht_curcap = %d ; vht_curcap = %d\n", __func__,
  1716. ht_curbeamformcap, vht_curbeamformcap);
  1717. if (TEST_FLAG(ht_curbeamformcap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) /*We are Beamformee because the STA is Beamformer*/
  1718. beamform_cap = (enum beamforming_cap)(beamform_cap | (BEAMFORMEE_CAP_HT_EXPLICIT | BEAMFORMEE_CAP));
  1719. /*We are Beamformer because the STA is Beamformee*/
  1720. if (TEST_FLAG(ht_curbeamformcap, BEAMFORMING_HT_BEAMFORMEE_ENABLE))
  1721. beamform_cap = (enum beamforming_cap)(beamform_cap | (BEAMFORMER_CAP_HT_EXPLICIT | BEAMFORMER_CAP));
  1722. #if (ODM_IC_11AC_SERIES_SUPPORT == 1)
  1723. /* We are Beamformee because the STA is SU Beamformer*/
  1724. if (TEST_FLAG(vht_curbeamformcap, BEAMFORMING_VHT_BEAMFORMER_ENABLE))
  1725. beamform_cap = (enum beamforming_cap)(beamform_cap | (BEAMFORMEE_CAP_VHT_SU | BEAMFORMEE_CAP));
  1726. /* We are Beamformer because the STA is SU Beamformee*/
  1727. if (TEST_FLAG(vht_curbeamformcap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE))
  1728. beamform_cap = (enum beamforming_cap)(beamform_cap | (BEAMFORMER_CAP_VHT_SU | BEAMFORMER_CAP));
  1729. /* We are Beamformee because the STA is MU Beamformer*/
  1730. if (TEST_FLAG(vht_curbeamformcap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE))
  1731. beamform_cap = (enum beamforming_cap)(beamform_cap | (BEAMFORMEE_CAP_VHT_MU | BEAMFORMEE_CAP));
  1732. #endif
  1733. #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)
  1734. for (macid = 0; macid < ODM_ASSOCIATE_ENTRY_NUM; macid++) {
  1735. sta = dm->phydm_sta_info[macid];
  1736. if (!is_sta_active(sta))
  1737. continue;
  1738. bf_info = &sta->bf_info;
  1739. vht_curbeamformcap = bf_info->vht_beamform_cap;
  1740. ht_curbeamformcap = bf_info->ht_beamform_cap;
  1741. if (TEST_FLAG(ht_curbeamformcap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) /*We are Beamformee because the STA is Beamformer*/
  1742. beamform_cap = (enum beamforming_cap)(beamform_cap | (BEAMFORMEE_CAP_HT_EXPLICIT | BEAMFORMEE_CAP));
  1743. /*We are Beamformer because the STA is Beamformee*/
  1744. if (TEST_FLAG(ht_curbeamformcap, BEAMFORMING_HT_BEAMFORMEE_ENABLE))
  1745. beamform_cap = (enum beamforming_cap)(beamform_cap | (BEAMFORMER_CAP_HT_EXPLICIT | BEAMFORMER_CAP));
  1746. #if (ODM_IC_11AC_SERIES_SUPPORT == 1)
  1747. /* We are Beamformee because the STA is SU Beamformer*/
  1748. if (TEST_FLAG(vht_curbeamformcap, BEAMFORMING_VHT_BEAMFORMER_ENABLE))
  1749. beamform_cap = (enum beamforming_cap)(beamform_cap | (BEAMFORMEE_CAP_VHT_SU | BEAMFORMEE_CAP));
  1750. /* We are Beamformer because the STA is SU Beamformee*/
  1751. if (TEST_FLAG(vht_curbeamformcap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE))
  1752. beamform_cap = (enum beamforming_cap)(beamform_cap | (BEAMFORMER_CAP_VHT_SU | BEAMFORMER_CAP));
  1753. /* We are Beamformee because the STA is MU Beamformer*/
  1754. if (TEST_FLAG(vht_curbeamformcap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE))
  1755. beamform_cap = (enum beamforming_cap)(beamform_cap | (BEAMFORMEE_CAP_VHT_MU | BEAMFORMEE_CAP));
  1756. #endif
  1757. }
  1758. PHYDM_DBG(dm, DBG_ANT_DIV, "[%s] CE ht_curcap = %d ; vht_curcap = %d\n",
  1759. __func__, ht_curbeamformcap, vht_curbeamformcap);
  1760. #endif
  1761. return beamform_cap;
  1762. }
  1763. #endif