phydm_beamforming.c 64 KB

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