wlan_utility.c 66 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363
  1. /*
  2. * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /**
  18. * DOC: This file contains definition for mandatory legacy API
  19. */
  20. #include "qdf_str.h"
  21. #include "wlan_utility.h"
  22. #include <wlan_cmn.h>
  23. #include "wlan_osif_priv.h"
  24. #include <net/cfg80211.h>
  25. #include <qdf_module.h>
  26. #include <wlan_vdev_mlme_api.h>
  27. #include "cfg_ucfg_api.h"
  28. #include <wlan_serialization_api.h>
  29. #include "wlan_cm_api.h"
  30. /* CRC polynomial 0xedb88320 */
  31. static unsigned long const wlan_shortssid_table[] = {
  32. 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
  33. 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
  34. 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
  35. 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
  36. 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
  37. 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
  38. 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
  39. 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
  40. 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
  41. 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
  42. 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
  43. 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
  44. 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
  45. 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
  46. 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
  47. 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
  48. 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
  49. 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
  50. 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
  51. 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
  52. 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
  53. 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
  54. 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
  55. 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
  56. 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
  57. 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
  58. 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
  59. 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
  60. 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
  61. 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
  62. 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
  63. 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
  64. 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
  65. 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
  66. 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
  67. 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
  68. 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
  69. 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
  70. 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
  71. 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
  72. 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
  73. 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
  74. 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
  75. };
  76. uint32_t wlan_construct_shortssid(uint8_t *ssid, uint8_t ssid_len)
  77. {
  78. uint32_t shortssid = 0xffffffff;
  79. uint8_t i;
  80. if (!ssid || ssid_len > WLAN_SSID_MAX_LEN)
  81. return shortssid;
  82. for (i = 0; i < ssid_len; i++)
  83. shortssid = wlan_shortssid_table[(shortssid ^ ssid[i]) & 0xff] ^
  84. (shortssid >> 8);
  85. return (shortssid ^ 0xffffffff);
  86. }
  87. uint32_t wlan_chan_to_freq(uint8_t chan)
  88. {
  89. if (chan == 0 )
  90. return 0;
  91. if (chan < WLAN_24_GHZ_CHANNEL_14)
  92. return WLAN_24_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ;
  93. else if (chan == WLAN_24_GHZ_CHANNEL_14)
  94. return WLAN_CHAN_14_FREQ;
  95. else if (chan < WLAN_24_GHZ_CHANNEL_27)
  96. /* ch 15 - ch 26 */
  97. return WLAN_CHAN_15_FREQ +
  98. (chan - WLAN_24_GHZ_CHANNEL_15) * WLAN_CHAN_SPACING_20MHZ;
  99. else if (chan == WLAN_5_GHZ_CHANNEL_170)
  100. return WLAN_CHAN_170_FREQ;
  101. else
  102. return WLAN_5_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ;
  103. }
  104. uint8_t wlan_freq_to_chan(uint32_t freq)
  105. {
  106. uint8_t chan;
  107. if (freq == 0)
  108. return 0;
  109. if (freq > WLAN_24_GHZ_BASE_FREQ && freq < WLAN_CHAN_14_FREQ)
  110. chan = ((freq - WLAN_24_GHZ_BASE_FREQ) /
  111. WLAN_CHAN_SPACING_5MHZ);
  112. else if (freq == WLAN_CHAN_14_FREQ)
  113. chan = WLAN_24_GHZ_CHANNEL_14;
  114. else if ((freq > WLAN_24_GHZ_BASE_FREQ) &&
  115. (freq < WLAN_5_GHZ_BASE_FREQ))
  116. chan = (((freq - WLAN_CHAN_15_FREQ) /
  117. WLAN_CHAN_SPACING_20MHZ) +
  118. WLAN_24_GHZ_CHANNEL_15);
  119. else
  120. chan = (freq - WLAN_5_GHZ_BASE_FREQ) /
  121. WLAN_CHAN_SPACING_5MHZ;
  122. return chan;
  123. }
  124. void
  125. wlan_get_320_center_freq(qdf_freq_t freq,
  126. qdf_freq_t *center_freq1,
  127. qdf_freq_t *center_freq2)
  128. {
  129. *center_freq1 = 0;
  130. *center_freq2 = 0;
  131. if ((freq >= 5500) && (freq <= 5800)) {
  132. *center_freq1 = 5650;
  133. } else if ((freq >= 5955) && (freq <= 6095)) {
  134. *center_freq1 = 6105;
  135. } else if ((freq >= 6115) && (freq <= 6255)) {
  136. *center_freq1 = 6105;
  137. *center_freq2 = 6265;
  138. } else if ((freq >= 6275) && (freq <= 6415)) {
  139. *center_freq1 = 6265;
  140. *center_freq2 = 6425;
  141. } else if ((freq >= 6435) && (freq <= 6575)) {
  142. *center_freq1 = 6425;
  143. *center_freq2 = 6585;
  144. } else if ((freq >= 6595) && (freq <= 6735)) {
  145. *center_freq1 = 6585;
  146. *center_freq2 = 6745;
  147. } else if ((freq >= 6755) && (freq <= 6895)) {
  148. *center_freq1 = 6745;
  149. *center_freq2 = 6905;
  150. } else if ((freq >= 6915) && (freq <= 7055)) {
  151. *center_freq1 = 6905;
  152. }
  153. }
  154. bool wlan_is_ie_valid(const uint8_t *ie, size_t ie_len)
  155. {
  156. uint8_t elen;
  157. while (ie_len) {
  158. if (ie_len < 2)
  159. return false;
  160. elen = ie[1];
  161. ie_len -= 2;
  162. ie += 2;
  163. if (elen > ie_len)
  164. return false;
  165. ie_len -= elen;
  166. ie += elen;
  167. }
  168. return true;
  169. }
  170. static const uint8_t *wlan_get_ie_ptr_from_eid_n_oui(uint8_t eid,
  171. const uint8_t *oui,
  172. uint8_t oui_size,
  173. const uint8_t *ie,
  174. uint16_t ie_len)
  175. {
  176. int32_t left = ie_len;
  177. const uint8_t *ptr = ie;
  178. uint8_t elem_id, elem_len;
  179. while (left >= 2) {
  180. elem_id = ptr[0];
  181. elem_len = ptr[1];
  182. left -= 2;
  183. if (elem_len > left)
  184. return NULL;
  185. if (eid == elem_id) {
  186. /* if oui is not provide eid match is enough */
  187. if (!oui)
  188. return ptr;
  189. /*
  190. * if oui is provided and oui_size is more than left
  191. * bytes, then we cannot have match
  192. */
  193. if (oui_size > left)
  194. return NULL;
  195. if (qdf_mem_cmp(&ptr[2], oui, oui_size) == 0)
  196. return ptr;
  197. }
  198. left -= elem_len;
  199. ptr += (elem_len + 2);
  200. }
  201. return NULL;
  202. }
  203. void wlan_iecap_set(uint8_t *iecap,
  204. uint8_t bit_pos,
  205. uint8_t tot_bits,
  206. uint32_t value)
  207. {
  208. uint8_t fit_bits;
  209. uint8_t byte_cnt;
  210. uint8_t prev_fit_bits = 0;
  211. uint32_t shift_value;
  212. /* calculate byte position of the field in IE capability */
  213. byte_cnt = bit_pos / 8;
  214. /* calculate the bit position in the start byte that needs to be set */
  215. bit_pos = bit_pos % 8;
  216. fit_bits = 8 - bit_pos;
  217. fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits;
  218. while ((bit_pos + tot_bits) > 8) {
  219. /* clear the target bit */
  220. QDF_SET_BITS(iecap[byte_cnt], bit_pos, fit_bits, value);
  221. tot_bits = tot_bits - fit_bits;
  222. bit_pos = bit_pos + fit_bits;
  223. if (bit_pos == 8) {
  224. bit_pos = 0;
  225. byte_cnt++;
  226. }
  227. prev_fit_bits = prev_fit_bits + fit_bits;
  228. fit_bits = 8 - bit_pos;
  229. fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits;
  230. }
  231. if ((bit_pos + tot_bits) <= 8) {
  232. /* clear the target bit */
  233. shift_value = value >> prev_fit_bits;
  234. QDF_SET_BITS(iecap[byte_cnt], bit_pos, fit_bits, shift_value);
  235. }
  236. }
  237. uint32_t wlan_iecap_get(uint8_t *iecap,
  238. uint8_t bit_pos,
  239. uint32_t tot_bits)
  240. {
  241. uint8_t fit_bits;
  242. uint8_t byte_cnt;
  243. uint8_t temp_val;
  244. uint8_t cur_bit_pos = 0;
  245. uint32_t val = 0;
  246. /* calculate byte position of the field in IE capability */
  247. byte_cnt = bit_pos / 8;
  248. temp_val = *(iecap + byte_cnt);
  249. /* calculate the bit position in the start byte */
  250. bit_pos = bit_pos % 8;
  251. fit_bits = 8 - bit_pos;
  252. fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits;
  253. while ((tot_bits + bit_pos) > 8) {
  254. val |= QDF_GET_BITS(temp_val, bit_pos, fit_bits) << cur_bit_pos;
  255. tot_bits = tot_bits - fit_bits;
  256. bit_pos = bit_pos + fit_bits;
  257. if (bit_pos == 8) {
  258. bit_pos = 0;
  259. byte_cnt++;
  260. temp_val = *(iecap + byte_cnt);
  261. }
  262. cur_bit_pos = cur_bit_pos + fit_bits;
  263. fit_bits = 8 - bit_pos;
  264. fit_bits = (tot_bits > fit_bits) ? 8 - bit_pos : tot_bits;
  265. }
  266. if ((bit_pos + tot_bits) <= 8)
  267. val |= QDF_GET_BITS(temp_val, bit_pos, fit_bits) << cur_bit_pos;
  268. return val;
  269. }
  270. const uint8_t *wlan_get_ie_ptr_from_eid(uint8_t eid,
  271. const uint8_t *ie,
  272. int ie_len)
  273. {
  274. return wlan_get_ie_ptr_from_eid_n_oui(eid, NULL, 0, ie, ie_len);
  275. }
  276. const uint8_t *wlan_get_vendor_ie_ptr_from_oui(const uint8_t *oui,
  277. uint8_t oui_size,
  278. const uint8_t *ie,
  279. uint16_t ie_len)
  280. {
  281. return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_VENDOR,
  282. oui, oui_size, ie, ie_len);
  283. }
  284. const uint8_t *wlan_get_ext_ie_ptr_from_ext_id(const uint8_t *oui,
  285. uint8_t oui_size,
  286. const uint8_t *ie,
  287. uint16_t ie_len)
  288. {
  289. return wlan_get_ie_ptr_from_eid_n_oui(WLAN_MAC_EID_EXT,
  290. oui, oui_size, ie, ie_len);
  291. }
  292. static inline
  293. QDF_STATUS wlan_get_elemunit_info(bool is_subelem,
  294. uint8_t subelemfragid,
  295. uint8_t *elemunit_fragid,
  296. qdf_size_t *elemunit_hdrlen,
  297. qdf_size_t *elemunit_maxpayloadlen,
  298. int *elemunit_id_pos,
  299. int *elemunit_len_pos,
  300. int *elemunit_idext_pos)
  301. {
  302. /* Helper function to populate information about the given element unit.
  303. * Here, an 'element unit' refers to either an 802.11 element or a
  304. * 802.11 subelement.
  305. *
  306. * Populating this information in a central helper here allows for
  307. * better control over handling of future variances, and also for common
  308. * code for handling different types of element units.
  309. */
  310. if (is_subelem) {
  311. /* Populate the subelement header length */
  312. if (elemunit_hdrlen)
  313. *elemunit_hdrlen = sizeof(struct subelem_header);
  314. /* Populate the subelement's max payload length */
  315. if (elemunit_maxpayloadlen)
  316. *elemunit_maxpayloadlen = WLAN_MAX_SUBELEM_LEN;
  317. /* Populate the index position for the subelement ID */
  318. if (elemunit_id_pos)
  319. *elemunit_id_pos = qdf_offsetof(struct subelem_header,
  320. subelem_id);
  321. /* Populate the index position for the subelement length */
  322. if (elemunit_len_pos)
  323. *elemunit_len_pos = qdf_offsetof(struct subelem_header,
  324. subelem_len);
  325. /* Mark that there is (currently) no valid value for subelement
  326. * ID extension.
  327. */
  328. if (elemunit_idext_pos)
  329. *elemunit_idext_pos = -1;
  330. /* Populate the subelement fragment ID (which can vary by
  331. * protocol area). This could also have been directly populated
  332. * by the caller, but we populate it here for uniformity and
  333. * future control of variability.
  334. */
  335. if (elemunit_fragid)
  336. *elemunit_fragid = subelemfragid;
  337. } else {
  338. /* Populate the element header length */
  339. if (elemunit_hdrlen)
  340. *elemunit_hdrlen = sizeof(struct ie_header);
  341. /* Populate the element's max payload length */
  342. if (elemunit_maxpayloadlen)
  343. *elemunit_maxpayloadlen = WLAN_MAX_IE_LEN;
  344. /* Populate the index position for the element ID */
  345. if (elemunit_id_pos)
  346. *elemunit_id_pos = qdf_offsetof(struct ie_header,
  347. ie_id);
  348. /* Populate the index position for the element length */
  349. if (elemunit_len_pos)
  350. *elemunit_len_pos = qdf_offsetof(struct ie_header,
  351. ie_len);
  352. /* Populate the index position for the element ID extension
  353. */
  354. if (elemunit_idext_pos)
  355. *elemunit_idext_pos =
  356. qdf_offsetof(struct extn_ie_header, ie_extn_id);
  357. /* Populate the element fragment ID. */
  358. if (elemunit_fragid)
  359. *elemunit_fragid = WLAN_ELEMID_FRAGMENT;
  360. }
  361. return QDF_STATUS_SUCCESS;
  362. }
  363. static QDF_STATUS
  364. wlan_get_elemsubelem_fragseq_creationparams(bool is_subelem,
  365. uint8_t id,
  366. qdf_size_t payloadlen,
  367. bool *is_frag_required,
  368. qdf_size_t *expected_fragseqlen,
  369. qdf_size_t *prepayload_leadbytes,
  370. uint32_t *num_maxsizefrags,
  371. qdf_size_t *smallerfrag_size,
  372. qdf_size_t *extrahdrbytes)
  373. {
  374. /* elemunit, i.e. 'element unit' here refers to either an 802.11 element
  375. * or a 802.11 subelement.
  376. */
  377. qdf_size_t elemunit_hdrlen;
  378. qdf_size_t elemunit_maxpayloadlen;
  379. qdf_size_t tmp_expected_fragseqlen;
  380. qdf_size_t tmp_prepayload_leadbytes;
  381. uint32_t tmp_num_maxsizefrags;
  382. qdf_size_t tmp_smallerfrag_size;
  383. qdf_size_t tmp_extrahdrbytes;
  384. QDF_STATUS ret;
  385. /* Helper function to determine element or subelement fragment sequence
  386. * creation parameters. Currently, this helper determines the following
  387. * parameters (it is mandatory for the caller to provide the pointer
  388. * for the first parameter, those for the remaining are optional):
  389. *
  390. * - Whether fragmentation is required
  391. * If fragmentation is required then the following are determined, else
  392. * they should be ignored by the caller:
  393. * - Expected fragment sequence length (inclusive of payload and all
  394. * headers)
  395. * - The lead bytes that occur before the payload (i.e. the lead
  396. * element/subelement's header, and if applicable, the element's
  397. * element ID extension)
  398. * - The number of max sized fragments (inclusive of the lead element)
  399. * - The size of the smaller sized fragment at the end (non-zero if such
  400. * a fragment would be present, zero if it would be absent)
  401. * - The number of extra header bytes that would be introduced (not
  402. * inclusive of the header of the lead fragment).
  403. */
  404. if (!is_frag_required) {
  405. qdf_nofl_err("Pointer to indication of whether fragmentation is required or not is NULL");
  406. return QDF_STATUS_E_NULL_VALUE;
  407. }
  408. ret = wlan_get_elemunit_info(is_subelem,
  409. 0,
  410. NULL,
  411. &elemunit_hdrlen,
  412. &elemunit_maxpayloadlen,
  413. NULL,
  414. NULL,
  415. NULL);
  416. if (QDF_IS_STATUS_ERROR(ret)) {
  417. qdf_rl_nofl_err("Get elem unit info: Error %d",
  418. ret);
  419. return QDF_STATUS_E_FAILURE;
  420. }
  421. if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM)) {
  422. if (payloadlen <= (elemunit_maxpayloadlen - 1)) {
  423. *is_frag_required = false;
  424. return QDF_STATUS_SUCCESS;
  425. }
  426. } else {
  427. if (payloadlen <= elemunit_maxpayloadlen) {
  428. *is_frag_required = false;
  429. return QDF_STATUS_SUCCESS;
  430. }
  431. }
  432. *is_frag_required = true;
  433. if (!expected_fragseqlen &&
  434. !prepayload_leadbytes && !num_maxsizefrags &&
  435. !smallerfrag_size && !extrahdrbytes)
  436. return QDF_STATUS_SUCCESS;
  437. tmp_expected_fragseqlen = 0;
  438. tmp_prepayload_leadbytes = 0;
  439. tmp_num_maxsizefrags = 0;
  440. tmp_smallerfrag_size = 0;
  441. tmp_extrahdrbytes = 0;
  442. /* As per the standard, the information to be fragmented is divided into
  443. * M + N portions, where the following define each variable:
  444. *
  445. * I)For an element without an Element ID Extension field, or for a
  446. * subelement:
  447. * L is the size of the information in octets (this does not include the
  448. * element/subelement header)
  449. * M is L/255 floored
  450. * N is equal to 1 if L mod 255 > 0 and equal to 0 otherwise.
  451. * The size of each of the M fragments is 255 octets
  452. * If N is 1, then the size of this single fragment is L mod 255 octets
  453. *
  454. * II) For an element with an Element ID Extension field:
  455. * L is the size of the information in octets (this does not include the
  456. * element header and the element ID extension field)
  457. * M is (L + 1)/255 floored
  458. * N is equal to 1 if (L - 254) mod 255 > 0 and equal to 0 otherwise.
  459. * The size of each of the M fragments is 255 octets
  460. * If N is 1, then the size of this single fragment is (L - 254) mod 255
  461. * octets.
  462. *
  463. * For both I and II above, the mapping of code variables is as follows:
  464. * payloadlen = L
  465. * tmp_num_maxsizefrags = M
  466. * tmp_smallerfrag_size = Size of N if N is 1, else 0
  467. * Additionally, elemunit_maxpayloadlen is used to denote the value
  468. * 255 for future extensibility if and when required.
  469. */
  470. if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM)) {
  471. tmp_num_maxsizefrags = (payloadlen + 1) /
  472. elemunit_maxpayloadlen;
  473. tmp_smallerfrag_size =
  474. (payloadlen - (elemunit_maxpayloadlen - 1)) %
  475. elemunit_maxpayloadlen;
  476. } else {
  477. tmp_num_maxsizefrags = payloadlen / elemunit_maxpayloadlen;
  478. tmp_smallerfrag_size = payloadlen %
  479. elemunit_maxpayloadlen;
  480. }
  481. /* Determine the number of extra bytes introduced due to the headers of
  482. * non-leading fragments.
  483. */
  484. tmp_extrahdrbytes = (tmp_num_maxsizefrags - 1) * elemunit_hdrlen;
  485. if (tmp_smallerfrag_size)
  486. tmp_extrahdrbytes += elemunit_hdrlen;
  487. if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM))
  488. tmp_prepayload_leadbytes = elemunit_hdrlen + 1;
  489. else
  490. tmp_prepayload_leadbytes = elemunit_hdrlen;
  491. tmp_expected_fragseqlen = tmp_prepayload_leadbytes +
  492. payloadlen + tmp_extrahdrbytes;
  493. if (expected_fragseqlen)
  494. *expected_fragseqlen = tmp_expected_fragseqlen;
  495. if (prepayload_leadbytes)
  496. *prepayload_leadbytes = tmp_prepayload_leadbytes;
  497. if (num_maxsizefrags)
  498. *num_maxsizefrags = tmp_num_maxsizefrags;
  499. if (smallerfrag_size)
  500. *smallerfrag_size = tmp_smallerfrag_size;
  501. if (extrahdrbytes)
  502. *extrahdrbytes = tmp_extrahdrbytes;
  503. return QDF_STATUS_SUCCESS;
  504. }
  505. static QDF_STATUS
  506. wlan_create_elemsubelem_fragseq(bool inline_frag,
  507. bool is_subelem,
  508. uint8_t id,
  509. uint8_t idext,
  510. uint8_t subelemfragid,
  511. uint8_t *payloadbuff,
  512. qdf_size_t payloadbuff_maxsize,
  513. qdf_size_t payloadlen,
  514. uint8_t *fragbuff,
  515. qdf_size_t fragbuff_maxsize,
  516. qdf_size_t *fragseqlen)
  517. {
  518. /* elemunit, i.e. 'element unit' here refers to either an 802.11 element
  519. * or a 802.11 subelement.
  520. */
  521. uint8_t elemunit_fragid;
  522. qdf_size_t elemunit_hdrlen;
  523. qdf_size_t elemunit_maxpayloadlen;
  524. int elemunit_id_pos;
  525. int elemunit_len_pos;
  526. int elemunit_idext_pos;
  527. uint8_t *curr_elemunit_ptr;
  528. /* Whether fragmentation is required */
  529. bool is_frag_required;
  530. /*Fragment sequence length (inclusive of payload and all headers) */
  531. qdf_size_t expected_fragseqlen;
  532. /* Number of fragments with the maximum size */
  533. uint32_t num_maxsizefrags;
  534. /* Size of the last fragment which is smaller than the maximum (if
  535. * present). If such a fragment is not present, this size will be zero.
  536. */
  537. qdf_size_t smallerfrag_size;
  538. /* The number of extra header bytes that would be introduced (not
  539. * inclusive of the header of the lead fragment).
  540. */
  541. qdf_size_t extrahdrbytes;
  542. /* The number of extra header bytes remaining to be introduced */
  543. qdf_size_t extrahdrbytes_remaining;
  544. /* The lead bytes that occur before the payload */
  545. qdf_size_t prepayload_leadbytes;
  546. /* used for inline copy, the extra bytes needed in the payload buffer
  547. * due to difference in destination and source.
  548. * Note that the caller should ensure there is enough bytes beyond
  549. * valid data until payloadbuff_maxsize*/
  550. qdf_size_t payloadbuff_shiftsize;
  551. /* Miscellaneous variables */
  552. uint8_t *src;
  553. uint8_t *dst;
  554. uint16_t i;
  555. qdf_size_t bytes_to_transfer;
  556. QDF_STATUS ret;
  557. /* Helper function to create an element or subelement fragment sequence.
  558. * Refer to the documentation of the public APIs which call this helper,
  559. * for more information. These APIs are mainly wrappers over this
  560. * helper.
  561. */
  562. ret = wlan_get_elemunit_info(is_subelem,
  563. subelemfragid,
  564. &elemunit_fragid,
  565. &elemunit_hdrlen,
  566. &elemunit_maxpayloadlen,
  567. &elemunit_id_pos,
  568. &elemunit_len_pos,
  569. &elemunit_idext_pos);
  570. if (QDF_IS_STATUS_ERROR(ret)) {
  571. qdf_rl_nofl_err("Get elem unit info: Error %d",
  572. ret);
  573. return QDF_STATUS_E_FAILURE;
  574. }
  575. ret = wlan_get_elemsubelem_fragseq_creationparams(is_subelem,
  576. id,
  577. payloadlen,
  578. &is_frag_required,
  579. &expected_fragseqlen,
  580. &prepayload_leadbytes,
  581. &num_maxsizefrags,
  582. &smallerfrag_size,
  583. &extrahdrbytes);
  584. if (QDF_IS_STATUS_ERROR(ret))
  585. return ret;
  586. if (!is_frag_required) {
  587. /* We treat this as an error since the caller is expected to
  588. * have first determined requirements related to fragmentation,
  589. * including whether fragmentation is required or not.
  590. */
  591. if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM))
  592. qdf_nofl_err("Fragmentation inapplicable for elem with elem ID ext and post elem ID ext payload len %zu",
  593. payloadlen);
  594. else
  595. qdf_nofl_err("Fragmentation inapplicable for subelem/elem without elem ID ext and with payload len %zu",
  596. payloadlen);
  597. return QDF_STATUS_E_INVAL;
  598. }
  599. if (!payloadbuff) {
  600. qdf_nofl_err("Payload buff is NULL");
  601. return QDF_STATUS_E_NULL_VALUE;
  602. }
  603. if (payloadbuff_maxsize == 0) {
  604. qdf_nofl_err("Payload buff max size is 0");
  605. return QDF_STATUS_E_INVAL;
  606. }
  607. if (payloadbuff_maxsize < payloadlen) {
  608. qdf_nofl_err("Payload buff max size %zu < payload len %zu",
  609. payloadbuff_maxsize,
  610. payloadlen);
  611. return QDF_STATUS_E_INVAL;
  612. }
  613. if (inline_frag) {
  614. if (payloadbuff_maxsize < expected_fragseqlen) {
  615. qdf_nofl_err("Inline frag buff max size %zu < frag sequence expected len %zu",
  616. payloadbuff_maxsize,
  617. expected_fragseqlen);
  618. return QDF_STATUS_E_INVAL;
  619. }
  620. } else {
  621. if (!fragbuff) {
  622. qdf_nofl_err("Frag sequence buff is NULL");
  623. return QDF_STATUS_E_NULL_VALUE;
  624. }
  625. if (fragbuff_maxsize == 0) {
  626. qdf_nofl_err("Frag sequence buff max size is 0");
  627. return QDF_STATUS_E_INVAL;
  628. }
  629. if (fragbuff_maxsize < expected_fragseqlen) {
  630. qdf_nofl_err("Frag sequence buff max size %zu < frag sequence expected len %zu",
  631. fragbuff_maxsize,
  632. expected_fragseqlen);
  633. return QDF_STATUS_E_INVAL;
  634. }
  635. }
  636. if (!fragseqlen) {
  637. qdf_nofl_err("Pointer to location of frag sequence len is NULL");
  638. return QDF_STATUS_E_NULL_VALUE;
  639. }
  640. /* Preferably, ensure that error checks (if any) for future changes are
  641. * executed before this point. We wouldn't want to touch the destination
  642. * buffer unless we are sure we can successfully execute (especially for
  643. * the inline mode).
  644. */
  645. /* We rely on wlan_get_elemsubelem_fragseq_creationparams() to give us
  646. * sane values for extrahdrbytes and other parameters.
  647. */
  648. extrahdrbytes_remaining = extrahdrbytes;
  649. /* We need to accommodate elemunit_hdrlen bytes for each non-leading
  650. * fragment by moving the non-leading fragment to a higher location.
  651. * Shift bytes and form fragment elements/subelements starting with the
  652. * last fragment and going backwards from there.
  653. */
  654. /* First move/copy the smaller sized fragment if present */
  655. if (smallerfrag_size) {
  656. /* The source for the copy/move is just after the end of all the
  657. * max sized fragments (including the lead fragment). The
  658. * element unit header is present for the lead fragment alone.
  659. */
  660. src = payloadbuff + elemunit_hdrlen +
  661. (num_maxsizefrags * elemunit_maxpayloadlen);
  662. /* The destination for the copy/move is computed to reflect a
  663. * shift by extrahdrbytes_remaining to accommodate the headers
  664. * for the smaller fragment and all the non-lead max sized
  665. * fragments.
  666. */
  667. if (inline_frag)
  668. dst = src + extrahdrbytes_remaining;
  669. else
  670. dst = fragbuff + elemunit_hdrlen +
  671. (num_maxsizefrags * elemunit_maxpayloadlen) +
  672. extrahdrbytes_remaining;
  673. bytes_to_transfer = smallerfrag_size;
  674. /* Account for increased size due to shift in data */
  675. if (inline_frag && (dst > src))
  676. payloadbuff_shiftsize = (dst - src);
  677. else
  678. payloadbuff_shiftsize = 0;
  679. /* In the case of inline fragmentation, if the payload buffer
  680. * has additional contents beyond the payload, include those
  681. * contents in the move/copy.
  682. */
  683. if (inline_frag &&
  684. (payloadbuff_maxsize > (prepayload_leadbytes + payloadlen)))
  685. bytes_to_transfer += (payloadbuff_maxsize -
  686. prepayload_leadbytes -
  687. payloadlen -
  688. payloadbuff_shiftsize);
  689. if (inline_frag)
  690. qdf_mem_move(dst, src, bytes_to_transfer);
  691. else
  692. qdf_mem_copy(dst, src, bytes_to_transfer);
  693. /* Copy/move of payload done. Set fragment ID and length in
  694. * element unit header.
  695. */
  696. curr_elemunit_ptr = dst - elemunit_hdrlen;
  697. curr_elemunit_ptr[elemunit_id_pos] = elemunit_fragid;
  698. curr_elemunit_ptr[elemunit_len_pos] = smallerfrag_size;
  699. extrahdrbytes_remaining -= elemunit_hdrlen;
  700. }
  701. /* Next, move/copy the non-lead max-sized fragments, if present.
  702. * Fragments at higher memory locations are processed first.
  703. */
  704. for (i = num_maxsizefrags; i > 1; i--) {
  705. /* Process the 'i'th max-sized fragment. The lead max-sized
  706. * fragment has i=1 and is not processed in this 'for' loop.
  707. * Also note that 'previous .* fragments' in comments for this
  708. * 'for' loop refers to fragments in lower memory locations as
  709. * compared to the current, i.e. 'i'th max-sized fragment.
  710. */
  711. /* The source for the copy/move is just after the end of all the
  712. * previous max-sized fragments (including the lead fragment).
  713. * The element unit header is present for the lead fragment
  714. * alone.
  715. */
  716. src = payloadbuff + elemunit_hdrlen +
  717. ((i - 1) * elemunit_maxpayloadlen);
  718. /* The destination for the copy/move is computed to reflect a
  719. * shift by extrahdrbytes_remaining to accommodate the headers
  720. * for the current non-lead max-sized fragment and all the
  721. * previous max-sized non-lead fragments.
  722. */
  723. if (inline_frag)
  724. dst = src + extrahdrbytes_remaining;
  725. else
  726. dst = fragbuff + elemunit_hdrlen +
  727. ((i - 1) * elemunit_maxpayloadlen) +
  728. extrahdrbytes_remaining;
  729. bytes_to_transfer = elemunit_maxpayloadlen;
  730. /* Account for increased size due to shift in data */
  731. if (inline_frag && (dst > src))
  732. payloadbuff_shiftsize = (dst - src);
  733. else
  734. payloadbuff_shiftsize = 0;
  735. /* In the case of inline fragmentation, if this is the last
  736. * non-lead max-sized fragment (i.e. at the highest memory
  737. * location), if the payload buffer has additional contents
  738. * beyond the payload, and these additional contents have not
  739. * already been taken care of by the presence (and processing)
  740. * of a smaller fragment, include the additional contents in the
  741. * move/copy.
  742. */
  743. if (inline_frag &&
  744. (i == num_maxsizefrags) &&
  745. (payloadbuff_maxsize > (prepayload_leadbytes +
  746. payloadlen)) &&
  747. !smallerfrag_size)
  748. bytes_to_transfer += (payloadbuff_maxsize -
  749. prepayload_leadbytes -
  750. payloadlen -
  751. payloadbuff_shiftsize);
  752. if (inline_frag)
  753. qdf_mem_move(dst, src, bytes_to_transfer);
  754. else
  755. qdf_mem_copy(dst, src, bytes_to_transfer);
  756. /* Copy/move of payload done. Set fragment ID and length in
  757. * element unit header.
  758. */
  759. curr_elemunit_ptr = dst - elemunit_hdrlen;
  760. curr_elemunit_ptr[elemunit_id_pos] = elemunit_fragid;
  761. curr_elemunit_ptr[elemunit_len_pos] = elemunit_maxpayloadlen;
  762. extrahdrbytes_remaining -= elemunit_hdrlen;
  763. }
  764. /* Update the element unit pointer for the lead max-sized fragment.
  765. *
  766. * Copy the payload of the lead max-sized fragment if inline
  767. * fragmentation is not being used.
  768. */
  769. if (inline_frag) {
  770. curr_elemunit_ptr = payloadbuff;
  771. } else {
  772. qdf_mem_copy(fragbuff + elemunit_hdrlen,
  773. payloadbuff + elemunit_hdrlen,
  774. elemunit_maxpayloadlen);
  775. curr_elemunit_ptr = fragbuff;
  776. }
  777. /* Set IDs and length in the header for the leading fragment */
  778. curr_elemunit_ptr[elemunit_id_pos] = id;
  779. curr_elemunit_ptr[elemunit_len_pos] = elemunit_maxpayloadlen;
  780. if (!is_subelem && (id == WLAN_ELEMID_EXTN_ELEM))
  781. curr_elemunit_ptr[elemunit_idext_pos] = idext;
  782. *fragseqlen = expected_fragseqlen;
  783. return QDF_STATUS_SUCCESS;
  784. }
  785. static inline QDF_STATUS
  786. wlan_get_elemsubelem_successorfrag(bool is_subelem,
  787. uint8_t subelemfragid,
  788. uint8_t *curr_elemunit_ptr,
  789. uint8_t *buff,
  790. qdf_size_t buff_maxsize,
  791. uint8_t **successorfrag,
  792. qdf_size_t *successorfrag_totallen,
  793. qdf_size_t *successorfrag_payloadlen)
  794. {
  795. /* elemunit, i.e. 'element unit' here refers to either an 802.11 element
  796. * or a 802.11 subelement.
  797. */
  798. uint8_t elemunit_fragid;
  799. qdf_size_t elemunit_hdrlen;
  800. qdf_size_t elemunit_maxpayloadlen;
  801. int elemunit_id_pos;
  802. int elemunit_len_pos;
  803. qdf_size_t curr_elemunit_totallen;
  804. uint8_t *next_elemunit_ptr;
  805. qdf_size_t next_elemunit_totallen;
  806. QDF_STATUS ret;
  807. /* This helper checks if the very next element unit after the current
  808. * one is a valid fragment element unit and that there is sufficient
  809. * space in the buffer for this next element, and if so, it returns a
  810. * pointer to this fragment element unit as well as the total length of
  811. * this fragment element unit and the length of the payload of this
  812. * fragment element unit.
  813. */
  814. ret = wlan_get_elemunit_info(is_subelem,
  815. subelemfragid,
  816. &elemunit_fragid,
  817. &elemunit_hdrlen,
  818. &elemunit_maxpayloadlen,
  819. &elemunit_id_pos,
  820. &elemunit_len_pos,
  821. NULL);
  822. if (QDF_IS_STATUS_ERROR(ret)) {
  823. qdf_rl_nofl_err("Get elem unit info: Error %d",
  824. ret);
  825. return QDF_STATUS_E_FAILURE;
  826. }
  827. if (!curr_elemunit_ptr) {
  828. qdf_nofl_err("Ptr to curr elem unit is NULL");
  829. return QDF_STATUS_E_NULL_VALUE;
  830. }
  831. if (!buff) {
  832. qdf_nofl_err("Elem unit buff is NULL");
  833. return QDF_STATUS_E_NULL_VALUE;
  834. }
  835. if (buff_maxsize == 0) {
  836. qdf_nofl_err("Max size of elem unit buff is 0");
  837. return QDF_STATUS_E_INVAL;
  838. }
  839. if (!successorfrag) {
  840. qdf_nofl_err("Double ptr to successor frag is NULL");
  841. return QDF_STATUS_E_NULL_VALUE;
  842. }
  843. if (!successorfrag_totallen) {
  844. qdf_nofl_err("Ptr to successor frag total len is NULL");
  845. return QDF_STATUS_E_NULL_VALUE;
  846. }
  847. if (!successorfrag_payloadlen) {
  848. qdf_nofl_err("Ptr to successor frag payload len is NULL");
  849. return QDF_STATUS_E_NULL_VALUE;
  850. }
  851. if ((buff + buff_maxsize) < (curr_elemunit_ptr + elemunit_hdrlen)) {
  852. qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (header size of elem unit %zu)",
  853. buff_maxsize - (curr_elemunit_ptr - buff),
  854. curr_elemunit_ptr - buff,
  855. elemunit_hdrlen);
  856. return QDF_STATUS_E_PROTO;
  857. }
  858. curr_elemunit_totallen =
  859. elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos];
  860. if ((buff + buff_maxsize) <
  861. (curr_elemunit_ptr + curr_elemunit_totallen)) {
  862. qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (indicated total len of elem unit %zu)",
  863. buff_maxsize - (curr_elemunit_ptr - buff),
  864. curr_elemunit_ptr - buff,
  865. curr_elemunit_totallen);
  866. return QDF_STATUS_E_PROTO;
  867. }
  868. if ((buff + buff_maxsize) ==
  869. (curr_elemunit_ptr + curr_elemunit_totallen)) {
  870. /* We have reached the end of the buffer. There is no successor
  871. * fragment.
  872. */
  873. *successorfrag = NULL;
  874. return QDF_STATUS_SUCCESS;
  875. }
  876. next_elemunit_ptr = curr_elemunit_ptr + curr_elemunit_totallen;
  877. if ((buff + buff_maxsize) < (next_elemunit_ptr + elemunit_hdrlen)) {
  878. qdf_rl_nofl_err("(Space %zu after next elem unit offset %zu in elem unit buff) < (header size of elem unit %zu)",
  879. buff_maxsize - (next_elemunit_ptr - buff),
  880. next_elemunit_ptr - buff,
  881. elemunit_hdrlen);
  882. return QDF_STATUS_E_PROTO;
  883. }
  884. next_elemunit_totallen =
  885. elemunit_hdrlen + next_elemunit_ptr[elemunit_len_pos];
  886. if ((buff + buff_maxsize) <
  887. (next_elemunit_ptr + next_elemunit_totallen)) {
  888. qdf_rl_nofl_err("(Space %zu after next elem unit offset %zu in elem unit buff) < (indicated total len of elem unit %zu)",
  889. buff_maxsize - (next_elemunit_ptr - buff),
  890. next_elemunit_ptr - buff,
  891. next_elemunit_totallen);
  892. return QDF_STATUS_E_PROTO;
  893. }
  894. if (next_elemunit_ptr[elemunit_id_pos] != elemunit_fragid) {
  895. *successorfrag = NULL;
  896. return QDF_STATUS_SUCCESS;
  897. }
  898. /* We should not be seeing a successor fragment if the length of the
  899. * current element unit is lesser than the max.
  900. */
  901. if (curr_elemunit_ptr[elemunit_len_pos] != elemunit_maxpayloadlen) {
  902. qdf_rl_nofl_err("Potential successor frag found though (len %u of payload of curr elem unit) != (max payload len %zu)",
  903. curr_elemunit_ptr[elemunit_len_pos],
  904. elemunit_maxpayloadlen);
  905. return QDF_STATUS_E_PROTO;
  906. }
  907. if (next_elemunit_ptr[elemunit_len_pos] == 0) {
  908. qdf_rl_nofl_err("Potential successor frag len is 0");
  909. return QDF_STATUS_E_PROTO;
  910. }
  911. *successorfrag = next_elemunit_ptr;
  912. *successorfrag_totallen = next_elemunit_totallen;
  913. *successorfrag_payloadlen = next_elemunit_ptr[elemunit_len_pos];
  914. return QDF_STATUS_SUCCESS;
  915. }
  916. static QDF_STATUS
  917. wlan_get_elemsubelem_fragseq_info(bool is_subelem,
  918. uint8_t subelemfragid,
  919. uint8_t *buff,
  920. qdf_size_t buff_maxsize,
  921. bool *is_fragseq,
  922. qdf_size_t *fragseq_totallen,
  923. qdf_size_t *fragseq_payloadlen)
  924. {
  925. /* elemunit, i.e. 'element unit' here refers to either an 802.11 element
  926. * or a 802.11 subelement.
  927. */
  928. qdf_size_t elemunit_hdrlen;
  929. int elemunit_id_pos;
  930. int elemunit_len_pos;
  931. uint8_t *curr_elemunit_ptr;
  932. qdf_size_t curr_elemunit_totallen;
  933. qdf_size_t fragseq_currtotallen;
  934. qdf_size_t fragseq_currpayloadlen;
  935. uint8_t *successorfrag;
  936. qdf_size_t successorfrag_totallen;
  937. qdf_size_t successorfrag_payloadlen;
  938. QDF_STATUS ret;
  939. /* Helper function to get element or subelement fragment sequence
  940. * information. Refer to the documentation of the public APIs which
  941. * call this helper, for more information. These APIs are mainly
  942. * wrappers over this helper.
  943. *
  944. * If this helper reports that an element fragment sequence is present,
  945. * it also serves to check for the sanity of various lengths and
  946. * protocol requirements related to the fragment sequence (either by
  947. * itself or though other helpers).
  948. */
  949. ret = wlan_get_elemunit_info(is_subelem,
  950. 0,
  951. NULL,
  952. &elemunit_hdrlen,
  953. NULL,
  954. &elemunit_id_pos,
  955. &elemunit_len_pos,
  956. NULL);
  957. if (QDF_IS_STATUS_ERROR(ret)) {
  958. qdf_rl_nofl_err("Get elem unit info: Error %d",
  959. ret);
  960. return QDF_STATUS_E_FAILURE;
  961. }
  962. if (!buff) {
  963. qdf_nofl_err("Elem unit buff is NULL");
  964. return QDF_STATUS_E_NULL_VALUE;
  965. }
  966. if (buff_maxsize == 0) {
  967. qdf_nofl_err("Max size of elem unit buff is 0");
  968. return QDF_STATUS_E_INVAL;
  969. }
  970. if (!is_fragseq) {
  971. qdf_nofl_err("Ptr to status of frag seq presence is NULL");
  972. return QDF_STATUS_E_NULL_VALUE;
  973. }
  974. if (!fragseq_totallen) {
  975. qdf_nofl_err("Ptr to total len of frag seq is NULL");
  976. return QDF_STATUS_E_NULL_VALUE;
  977. }
  978. if (!fragseq_payloadlen) {
  979. qdf_nofl_err("Ptr to payload len of frag seq is NULL");
  980. return QDF_STATUS_E_NULL_VALUE;
  981. }
  982. curr_elemunit_ptr = buff;
  983. fragseq_currtotallen = 0;
  984. fragseq_currpayloadlen = 0;
  985. if ((buff + buff_maxsize) < (curr_elemunit_ptr + elemunit_hdrlen)) {
  986. qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (header size of elem unit %zu)",
  987. buff_maxsize - (curr_elemunit_ptr - buff),
  988. curr_elemunit_ptr - buff,
  989. elemunit_hdrlen);
  990. return QDF_STATUS_E_PROTO;
  991. }
  992. curr_elemunit_totallen =
  993. elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos];
  994. if ((buff + buff_maxsize) <
  995. (curr_elemunit_ptr + curr_elemunit_totallen)) {
  996. qdf_rl_nofl_err("(Space %zu after curr elem unit offset %zu in elem unit buff) < (indicated total len of elem unit %zu)",
  997. buff_maxsize - (curr_elemunit_ptr - buff),
  998. curr_elemunit_ptr - buff,
  999. curr_elemunit_totallen);
  1000. return QDF_STATUS_E_PROTO;
  1001. }
  1002. successorfrag = NULL;
  1003. ret = wlan_get_elemsubelem_successorfrag(is_subelem,
  1004. subelemfragid,
  1005. curr_elemunit_ptr,
  1006. buff,
  1007. buff_maxsize,
  1008. &successorfrag,
  1009. &successorfrag_totallen,
  1010. &successorfrag_payloadlen);
  1011. if (QDF_IS_STATUS_ERROR(ret))
  1012. return ret;
  1013. if (!successorfrag) {
  1014. *is_fragseq = false;
  1015. *fragseq_totallen = 0;
  1016. *fragseq_payloadlen = 0;
  1017. return QDF_STATUS_SUCCESS;
  1018. }
  1019. fragseq_currtotallen += curr_elemunit_totallen;
  1020. if (!is_subelem &&
  1021. (curr_elemunit_ptr[elemunit_id_pos] == WLAN_ELEMID_EXTN_ELEM)) {
  1022. fragseq_currpayloadlen +=
  1023. (curr_elemunit_ptr[elemunit_len_pos] - 1);
  1024. } else {
  1025. fragseq_currpayloadlen +=
  1026. curr_elemunit_ptr[elemunit_len_pos];
  1027. }
  1028. while (successorfrag) {
  1029. /* wlan_get_elemsubelem_successorfrag() has already validated
  1030. * the length values for the successor fragment.
  1031. */
  1032. fragseq_currtotallen += successorfrag_totallen;
  1033. fragseq_currpayloadlen += successorfrag_payloadlen;
  1034. curr_elemunit_ptr = successorfrag;
  1035. successorfrag = NULL;
  1036. ret = wlan_get_elemsubelem_successorfrag(is_subelem,
  1037. subelemfragid,
  1038. curr_elemunit_ptr,
  1039. buff,
  1040. buff_maxsize,
  1041. &successorfrag,
  1042. &successorfrag_totallen,
  1043. &successorfrag_payloadlen);
  1044. if (QDF_IS_STATUS_ERROR(ret))
  1045. return ret;
  1046. }
  1047. *is_fragseq = true;
  1048. *fragseq_totallen = fragseq_currtotallen;
  1049. *fragseq_payloadlen = fragseq_currpayloadlen;
  1050. return QDF_STATUS_SUCCESS;
  1051. }
  1052. static QDF_STATUS wlan_defrag_elemsubelem_fragseq(bool inline_defrag,
  1053. bool is_subelem,
  1054. uint8_t subelemfragid,
  1055. uint8_t *fragbuff,
  1056. qdf_size_t fragbuff_maxsize,
  1057. uint8_t *defragbuff,
  1058. qdf_size_t defragbuff_maxsize,
  1059. qdf_size_t *defragpayload_len)
  1060. {
  1061. /* elemunit, i.e. 'element unit' here refers to either an 802.11 element
  1062. * or a 802.11 subelement.
  1063. */
  1064. uint8_t elemunit_fragid;
  1065. qdf_size_t elemunit_hdrlen;
  1066. int elemunit_id_pos;
  1067. int elemunit_len_pos;
  1068. int elemunit_idext_pos;
  1069. bool is_fragseq;
  1070. qdf_size_t fragseq_totallen;
  1071. qdf_size_t fragseq_payloadlen;
  1072. uint8_t *curr_elemunit_ptr;
  1073. qdf_size_t curr_elemunit_payloadlen;
  1074. qdf_size_t curr_elemunit_totallen;
  1075. uint8_t *src;
  1076. uint8_t *dst;
  1077. /* Current length of the defragmented payload */
  1078. qdf_size_t defragpayload_currlen;
  1079. /* Remaining length available in the source buffer containing the
  1080. * fragment sequence, after element units processed so far.
  1081. */
  1082. qdf_size_t fragbuff_remlen;
  1083. QDF_STATUS ret;
  1084. /* Helper function to de-fragment element or subelement fragment
  1085. * sequence. Refer to the documentation of the public APIs which call
  1086. * this helper, for more information. Those APIs are mainly wrappers
  1087. * over this helper.
  1088. */
  1089. ret = wlan_get_elemunit_info(is_subelem,
  1090. subelemfragid,
  1091. &elemunit_fragid,
  1092. &elemunit_hdrlen,
  1093. NULL,
  1094. &elemunit_id_pos,
  1095. &elemunit_len_pos,
  1096. &elemunit_idext_pos);
  1097. if (QDF_IS_STATUS_ERROR(ret)) {
  1098. qdf_rl_nofl_err("Get elem unit info: Error %d",
  1099. ret);
  1100. return QDF_STATUS_E_FAILURE;
  1101. }
  1102. if (!fragbuff) {
  1103. qdf_nofl_err("Src buff for frag seq is NULL");
  1104. return QDF_STATUS_E_NULL_VALUE;
  1105. }
  1106. if (fragbuff_maxsize == 0) {
  1107. qdf_nofl_err("Size of src buff for frag seq is 0");
  1108. return QDF_STATUS_E_INVAL;
  1109. }
  1110. if (!inline_defrag) {
  1111. if (!defragbuff) {
  1112. qdf_nofl_err("Dest buff for defragged payload is NULL");
  1113. return QDF_STATUS_E_NULL_VALUE;
  1114. }
  1115. if (defragbuff_maxsize == 0) {
  1116. qdf_nofl_err("Size of dest buff for defragged payload is 0");
  1117. return QDF_STATUS_E_INVAL;
  1118. }
  1119. }
  1120. if (!defragpayload_len) {
  1121. qdf_nofl_err("Ptr to len of defragged payload is NULL");
  1122. return QDF_STATUS_E_NULL_VALUE;
  1123. }
  1124. ret = wlan_get_elemsubelem_fragseq_info(is_subelem,
  1125. subelemfragid,
  1126. fragbuff,
  1127. fragbuff_maxsize,
  1128. &is_fragseq,
  1129. &fragseq_totallen,
  1130. &fragseq_payloadlen);
  1131. if (QDF_IS_STATUS_ERROR(ret))
  1132. return ret;
  1133. if (!is_fragseq) {
  1134. /* We treat this as an error since the caller is supposed to
  1135. * check this.
  1136. */
  1137. qdf_rl_nofl_err("Frag seq not found at start of src buff for frag seq");
  1138. return QDF_STATUS_E_INVAL;
  1139. }
  1140. /* fragseq_totallen is known to be smaller than or equal to
  1141. * fragbuff_maxsize since wlan_get_elemsubelem_fragseq_info() is bound
  1142. * by fragbuff_maxsize in the search for a fragment sequence and it's
  1143. * total length.
  1144. */
  1145. if (!inline_defrag && (defragbuff_maxsize < fragseq_payloadlen)) {
  1146. qdf_rl_nofl_err("(Size of dest buff for defragged payload %zu) < (size of frag seq payload %zu)",
  1147. defragbuff_maxsize, fragseq_payloadlen);
  1148. return QDF_STATUS_E_INVAL;
  1149. }
  1150. defragpayload_currlen = 0;
  1151. fragbuff_remlen = fragbuff_maxsize;
  1152. /* We have already validated through wlan_get_elemsubelem_fragseq_info()
  1153. * that the elements we are about to access below are within the bounds
  1154. * of fragbuff.
  1155. */
  1156. curr_elemunit_ptr = fragbuff;
  1157. if (!is_subelem &&
  1158. (curr_elemunit_ptr[elemunit_id_pos] == WLAN_ELEMID_EXTN_ELEM)) {
  1159. curr_elemunit_payloadlen =
  1160. curr_elemunit_ptr[elemunit_len_pos] - 1;
  1161. src = curr_elemunit_ptr + elemunit_hdrlen + 1;
  1162. } else {
  1163. curr_elemunit_payloadlen = curr_elemunit_ptr[elemunit_len_pos];
  1164. src = curr_elemunit_ptr + elemunit_hdrlen;
  1165. }
  1166. curr_elemunit_totallen =
  1167. elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos];
  1168. if (inline_defrag) {
  1169. /* There is no need to move any bytes in the lead element. Set
  1170. * dst=src so that the next update for dst can happen in a
  1171. * manner uniform with the non-inlined defrag case.
  1172. */
  1173. dst = src;
  1174. } else {
  1175. dst = defragbuff;
  1176. qdf_mem_copy(dst, src, curr_elemunit_payloadlen);
  1177. }
  1178. defragpayload_currlen += curr_elemunit_payloadlen;
  1179. fragbuff_remlen -= curr_elemunit_totallen;
  1180. dst += curr_elemunit_payloadlen;
  1181. curr_elemunit_ptr += curr_elemunit_totallen;
  1182. /* We have already validated through wlan_get_elemsubelem_fragseq_info()
  1183. * that at least one non-lead fragment element is present as required in
  1184. * the standard.
  1185. */
  1186. while (curr_elemunit_ptr[elemunit_id_pos] == elemunit_fragid) {
  1187. curr_elemunit_payloadlen = curr_elemunit_ptr[elemunit_len_pos];
  1188. curr_elemunit_totallen =
  1189. elemunit_hdrlen + curr_elemunit_ptr[elemunit_len_pos];
  1190. src = curr_elemunit_ptr + elemunit_hdrlen;
  1191. if (inline_defrag)
  1192. qdf_mem_move(dst, src, curr_elemunit_payloadlen);
  1193. else
  1194. qdf_mem_copy(dst, src, curr_elemunit_payloadlen);
  1195. defragpayload_currlen += curr_elemunit_payloadlen;
  1196. fragbuff_remlen -= curr_elemunit_totallen;
  1197. if (fragbuff_remlen == 0)
  1198. break;
  1199. dst += curr_elemunit_payloadlen;
  1200. curr_elemunit_ptr += curr_elemunit_totallen;
  1201. }
  1202. if (inline_defrag && (fragbuff_remlen != 0)) {
  1203. /* Move the residual content after the fragments, in the source
  1204. * buffer.
  1205. */
  1206. src = curr_elemunit_ptr;
  1207. qdf_mem_move(dst, src, fragbuff_remlen);
  1208. }
  1209. *defragpayload_len = defragpayload_currlen;
  1210. return QDF_STATUS_SUCCESS;
  1211. }
  1212. QDF_STATUS
  1213. wlan_get_elem_fragseq_requirements(uint8_t elemid,
  1214. qdf_size_t payloadlen,
  1215. bool *is_frag_required,
  1216. qdf_size_t *required_fragbuff_size)
  1217. {
  1218. return wlan_get_elemsubelem_fragseq_creationparams(false,
  1219. elemid,
  1220. payloadlen,
  1221. is_frag_required,
  1222. required_fragbuff_size,
  1223. NULL,
  1224. NULL,
  1225. NULL,
  1226. NULL);
  1227. }
  1228. QDF_STATUS wlan_create_elem_fragseq(bool inline_frag,
  1229. uint8_t elemid,
  1230. uint8_t elemidext,
  1231. uint8_t *payloadbuff,
  1232. qdf_size_t payloadbuff_maxsize,
  1233. qdf_size_t payloadlen,
  1234. uint8_t *fragbuff,
  1235. qdf_size_t fragbuff_maxsize,
  1236. qdf_size_t *fragseqlen)
  1237. {
  1238. return wlan_create_elemsubelem_fragseq(inline_frag,
  1239. false,
  1240. elemid,
  1241. elemidext,
  1242. 0,
  1243. payloadbuff,
  1244. payloadbuff_maxsize,
  1245. payloadlen,
  1246. fragbuff,
  1247. fragbuff_maxsize,
  1248. fragseqlen);
  1249. }
  1250. QDF_STATUS
  1251. wlan_get_subelem_fragseq_requirements(uint8_t subelemid,
  1252. qdf_size_t payloadlen,
  1253. bool *is_frag_required,
  1254. qdf_size_t *required_fragbuff_size)
  1255. {
  1256. return wlan_get_elemsubelem_fragseq_creationparams(true,
  1257. subelemid,
  1258. payloadlen,
  1259. is_frag_required,
  1260. required_fragbuff_size,
  1261. NULL,
  1262. NULL,
  1263. NULL,
  1264. NULL);
  1265. }
  1266. QDF_STATUS wlan_create_subelem_fragseq(bool inline_frag,
  1267. uint8_t subelemid,
  1268. uint8_t subelemfragid,
  1269. uint8_t *payloadbuff,
  1270. qdf_size_t payloadbuff_maxsize,
  1271. qdf_size_t payloadlen,
  1272. uint8_t *fragbuff,
  1273. qdf_size_t fragbuff_maxsize,
  1274. qdf_size_t *fragseqlen)
  1275. {
  1276. return wlan_create_elemsubelem_fragseq(inline_frag,
  1277. true,
  1278. subelemid,
  1279. 0,
  1280. subelemfragid,
  1281. payloadbuff,
  1282. payloadbuff_maxsize,
  1283. payloadlen,
  1284. fragbuff,
  1285. fragbuff_maxsize,
  1286. fragseqlen);
  1287. }
  1288. QDF_STATUS wlan_get_elem_fragseq_info(uint8_t *elembuff,
  1289. qdf_size_t elembuff_maxsize,
  1290. bool *is_fragseq,
  1291. qdf_size_t *fragseq_totallen,
  1292. qdf_size_t *fragseq_payloadlen)
  1293. {
  1294. return wlan_get_elemsubelem_fragseq_info(false,
  1295. 0,
  1296. elembuff,
  1297. elembuff_maxsize,
  1298. is_fragseq,
  1299. fragseq_totallen,
  1300. fragseq_payloadlen);
  1301. }
  1302. QDF_STATUS wlan_defrag_elem_fragseq(bool inline_defrag,
  1303. uint8_t *fragbuff,
  1304. qdf_size_t fragbuff_maxsize,
  1305. uint8_t *defragbuff,
  1306. qdf_size_t defragbuff_maxsize,
  1307. qdf_size_t *defragpayload_len)
  1308. {
  1309. return wlan_defrag_elemsubelem_fragseq(inline_defrag,
  1310. false,
  1311. 0,
  1312. fragbuff,
  1313. fragbuff_maxsize,
  1314. defragbuff,
  1315. defragbuff_maxsize,
  1316. defragpayload_len);
  1317. }
  1318. QDF_STATUS wlan_get_subelem_fragseq_info(uint8_t subelemfragid,
  1319. uint8_t *subelembuff,
  1320. qdf_size_t subelembuff_maxsize,
  1321. bool *is_fragseq,
  1322. qdf_size_t *fragseq_totallen,
  1323. qdf_size_t *fragseq_payloadlen)
  1324. {
  1325. return wlan_get_elemsubelem_fragseq_info(true,
  1326. subelemfragid,
  1327. subelembuff,
  1328. subelembuff_maxsize,
  1329. is_fragseq,
  1330. fragseq_totallen,
  1331. fragseq_payloadlen);
  1332. }
  1333. QDF_STATUS wlan_defrag_subelem_fragseq(bool inline_defrag,
  1334. uint8_t subelemfragid,
  1335. uint8_t *fragbuff,
  1336. qdf_size_t fragbuff_maxsize,
  1337. uint8_t *defragbuff,
  1338. qdf_size_t defragbuff_maxsize,
  1339. qdf_size_t *defragpayload_len)
  1340. {
  1341. return wlan_defrag_elemsubelem_fragseq(inline_defrag,
  1342. true,
  1343. subelemfragid,
  1344. fragbuff,
  1345. fragbuff_maxsize,
  1346. defragbuff,
  1347. defragbuff_maxsize,
  1348. defragpayload_len);
  1349. }
  1350. bool wlan_is_emulation_platform(uint32_t phy_version)
  1351. {
  1352. if ((phy_version == 0xABC0) || (phy_version == 0xABC1) ||
  1353. (phy_version == 0xABC2) || (phy_version == 0xABC3) ||
  1354. (phy_version == 0xFFFF) || (phy_version == 0xABCD))
  1355. return true;
  1356. return false;
  1357. }
  1358. uint32_t wlan_get_pdev_id_from_vdev_id(struct wlan_objmgr_psoc *psoc,
  1359. uint8_t vdev_id,
  1360. wlan_objmgr_ref_dbgid dbg_id)
  1361. {
  1362. struct wlan_objmgr_vdev *vdev;
  1363. struct wlan_objmgr_pdev *pdev = NULL;
  1364. uint32_t pdev_id = WLAN_INVALID_PDEV_ID;
  1365. vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
  1366. vdev_id, dbg_id);
  1367. if (vdev) {
  1368. pdev = wlan_vdev_get_pdev(vdev);
  1369. if (pdev)
  1370. pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
  1371. wlan_objmgr_vdev_release_ref(vdev, dbg_id);
  1372. }
  1373. return pdev_id;
  1374. }
  1375. qdf_export_symbol(wlan_get_pdev_id_from_vdev_id);
  1376. static void wlan_vdev_active(struct wlan_objmgr_pdev *pdev, void *object,
  1377. void *arg)
  1378. {
  1379. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  1380. uint8_t *flag = (uint8_t *)arg;
  1381. wlan_vdev_obj_lock(vdev);
  1382. if (wlan_vdev_mlme_is_active(vdev) == QDF_STATUS_SUCCESS)
  1383. *flag = 1;
  1384. wlan_vdev_obj_unlock(vdev);
  1385. }
  1386. QDF_STATUS wlan_vdev_is_up(struct wlan_objmgr_vdev *vdev)
  1387. {
  1388. return wlan_vdev_allow_connect_n_tx(vdev);
  1389. }
  1390. qdf_export_symbol(wlan_vdev_is_up);
  1391. QDF_STATUS wlan_util_is_vdev_active(struct wlan_objmgr_pdev *pdev,
  1392. wlan_objmgr_ref_dbgid dbg_id)
  1393. {
  1394. uint8_t flag = 0;
  1395. if (!pdev)
  1396. return QDF_STATUS_E_INVAL;
  1397. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, wlan_vdev_active,
  1398. &flag, 0, dbg_id);
  1399. if (flag == 1)
  1400. return QDF_STATUS_SUCCESS;
  1401. return QDF_STATUS_E_INVAL;
  1402. }
  1403. qdf_export_symbol(wlan_util_is_vdev_active);
  1404. void wlan_util_change_map_index(unsigned long *map, uint8_t id, uint8_t set)
  1405. {
  1406. if (set)
  1407. qdf_set_bit(id, map);
  1408. else
  1409. qdf_clear_bit(id, map);
  1410. }
  1411. bool wlan_util_map_index_is_set(unsigned long *map, uint8_t id)
  1412. {
  1413. return qdf_test_bit(id, map);
  1414. }
  1415. bool wlan_util_map_is_any_index_set(unsigned long *map, unsigned long nbytes)
  1416. {
  1417. return !qdf_bitmap_empty(map, QDF_CHAR_BIT * nbytes);
  1418. }
  1419. static void wlan_vdev_chan_change_pending(struct wlan_objmgr_pdev *pdev,
  1420. void *object, void *arg)
  1421. {
  1422. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  1423. unsigned long *vdev_id_map = (unsigned long *)arg;
  1424. uint8_t id = 0;
  1425. struct wlan_objmgr_psoc *psoc;
  1426. psoc = wlan_pdev_get_psoc(pdev);
  1427. if (!psoc)
  1428. return;
  1429. wlan_vdev_obj_lock(vdev);
  1430. if (wlan_vdev_chan_config_valid(vdev) == QDF_STATUS_SUCCESS) {
  1431. id = wlan_vdev_get_id(vdev);
  1432. /* Invalid vdev id */
  1433. if (id >= wlan_psoc_get_max_vdev_count(psoc)) {
  1434. wlan_vdev_obj_unlock(vdev);
  1435. return;
  1436. }
  1437. wlan_util_change_map_index(vdev_id_map, id, 1);
  1438. }
  1439. wlan_vdev_obj_unlock(vdev);
  1440. }
  1441. QDF_STATUS wlan_pdev_chan_change_pending_vdevs(struct wlan_objmgr_pdev *pdev,
  1442. unsigned long *vdev_id_map,
  1443. wlan_objmgr_ref_dbgid dbg_id)
  1444. {
  1445. if (!pdev)
  1446. return QDF_STATUS_E_INVAL;
  1447. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  1448. wlan_vdev_chan_change_pending,
  1449. vdev_id_map, 0, dbg_id);
  1450. return QDF_STATUS_SUCCESS;
  1451. }
  1452. static void wlan_vdev_down_pending(struct wlan_objmgr_pdev *pdev,
  1453. void *object, void *arg)
  1454. {
  1455. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  1456. unsigned long *vdev_id_map = (unsigned long *)arg;
  1457. uint8_t id = 0;
  1458. struct wlan_objmgr_psoc *psoc;
  1459. enum wlan_serialization_cmd_type cmd_type;
  1460. psoc = wlan_pdev_get_psoc(pdev);
  1461. if (!psoc)
  1462. return;
  1463. if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev))
  1464. return;
  1465. cmd_type = wlan_serialization_get_vdev_active_cmd_type(vdev);
  1466. wlan_vdev_obj_lock(vdev);
  1467. if ((wlan_vdev_mlme_is_init_state(vdev) != QDF_STATUS_SUCCESS) ||
  1468. (cmd_type == WLAN_SER_CMD_VDEV_START_BSS)) {
  1469. id = wlan_vdev_get_id(vdev);
  1470. /* Invalid vdev id */
  1471. if (id >= wlan_psoc_get_max_vdev_count(psoc)) {
  1472. wlan_vdev_obj_unlock(vdev);
  1473. return;
  1474. }
  1475. wlan_util_change_map_index(vdev_id_map, id, 1);
  1476. }
  1477. wlan_vdev_obj_unlock(vdev);
  1478. }
  1479. static void wlan_vdev_ap_down_pending(struct wlan_objmgr_pdev *pdev,
  1480. void *object, void *arg)
  1481. {
  1482. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  1483. unsigned long *vdev_id_map = (unsigned long *)arg;
  1484. uint8_t id = 0;
  1485. struct wlan_objmgr_psoc *psoc;
  1486. enum wlan_serialization_cmd_type cmd_type;
  1487. psoc = wlan_pdev_get_psoc(pdev);
  1488. if (!psoc)
  1489. return;
  1490. if (wlan_vdev_mlme_get_opmode(vdev) != QDF_SAP_MODE)
  1491. return;
  1492. if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev))
  1493. return;
  1494. cmd_type = wlan_serialization_get_vdev_active_cmd_type(vdev);
  1495. wlan_vdev_obj_lock(vdev);
  1496. if ((wlan_vdev_mlme_is_init_state(vdev) != QDF_STATUS_SUCCESS) ||
  1497. (cmd_type == WLAN_SER_CMD_VDEV_START_BSS)) {
  1498. id = wlan_vdev_get_id(vdev);
  1499. /* Invalid vdev id */
  1500. if (id >= wlan_psoc_get_max_vdev_count(psoc)) {
  1501. wlan_vdev_obj_unlock(vdev);
  1502. return;
  1503. }
  1504. wlan_util_change_map_index(vdev_id_map, id, 1);
  1505. }
  1506. wlan_vdev_obj_unlock(vdev);
  1507. }
  1508. QDF_STATUS wlan_pdev_chan_change_pending_vdevs_down(
  1509. struct wlan_objmgr_pdev *pdev,
  1510. unsigned long *vdev_id_map,
  1511. wlan_objmgr_ref_dbgid dbg_id)
  1512. {
  1513. if (!pdev)
  1514. return QDF_STATUS_E_INVAL;
  1515. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  1516. wlan_vdev_down_pending,
  1517. vdev_id_map, 0, dbg_id);
  1518. return QDF_STATUS_SUCCESS;
  1519. }
  1520. QDF_STATUS wlan_pdev_chan_change_pending_ap_vdevs_down(
  1521. struct wlan_objmgr_pdev *pdev,
  1522. unsigned long *vdev_id_map,
  1523. wlan_objmgr_ref_dbgid dbg_id)
  1524. {
  1525. if (!pdev)
  1526. return QDF_STATUS_E_INVAL;
  1527. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  1528. wlan_vdev_ap_down_pending,
  1529. vdev_id_map, 0, dbg_id);
  1530. return QDF_STATUS_SUCCESS;
  1531. }
  1532. #ifdef WLAN_FEATURE_11BE
  1533. static inline bool
  1534. wlan_chan_puncture_eq(struct wlan_channel *chan1, struct wlan_channel *chan2)
  1535. {
  1536. if (chan1->puncture_bitmap == chan2->puncture_bitmap)
  1537. return true;
  1538. return false;
  1539. }
  1540. #else
  1541. static inline bool
  1542. wlan_chan_puncture_eq(struct wlan_channel *chan1, struct wlan_channel *chan2)
  1543. {
  1544. return true;
  1545. }
  1546. #endif /* WLAN_FEATURE_11BE */
  1547. QDF_STATUS wlan_chan_eq(struct wlan_channel *chan1, struct wlan_channel *chan2)
  1548. {
  1549. if ((chan1->ch_ieee == chan2->ch_ieee) &&
  1550. (chan1->ch_freq_seg2 == chan2->ch_freq_seg2) &&
  1551. wlan_chan_puncture_eq(chan1, chan2))
  1552. return QDF_STATUS_SUCCESS;
  1553. return QDF_STATUS_E_FAILURE;
  1554. }
  1555. void wlan_chan_copy(struct wlan_channel *tgt, struct wlan_channel *src)
  1556. {
  1557. qdf_mem_copy(tgt, src, sizeof(struct wlan_channel));
  1558. }
  1559. struct wlan_channel *wlan_vdev_get_active_channel(struct wlan_objmgr_vdev *vdev)
  1560. {
  1561. struct wlan_channel *comp_vdev_chan = NULL;
  1562. if (wlan_vdev_chan_config_valid(vdev) == QDF_STATUS_SUCCESS) {
  1563. /* compare with BSS channel, when vdev is active, since desired
  1564. * channel gets update, if channel is triggered in another path
  1565. */
  1566. if (wlan_vdev_mlme_is_active(vdev) == QDF_STATUS_SUCCESS)
  1567. comp_vdev_chan = wlan_vdev_mlme_get_bss_chan(vdev);
  1568. else
  1569. comp_vdev_chan = wlan_vdev_mlme_get_des_chan(vdev);
  1570. }
  1571. return comp_vdev_chan;
  1572. }
  1573. /**
  1574. * struct wlan_check_bssid_context - bssid check context
  1575. * @bssid: bssid to be checked
  1576. * @connected: connected by vdev or not
  1577. * @vdev_id: vdev id of connected vdev
  1578. */
  1579. struct wlan_check_bssid_context {
  1580. struct qdf_mac_addr bssid;
  1581. bool connected;
  1582. uint8_t vdev_id;
  1583. };
  1584. /**
  1585. * wlan_get_connected_vdev_handler() - check vdev connected on bssid
  1586. * @psoc: psoc object
  1587. * @obj: vdev object
  1588. * @args: handler context
  1589. *
  1590. * This function will check whether vdev is connected on bssid or not and
  1591. * update the result to handler context accordingly.
  1592. *
  1593. * Return: void
  1594. */
  1595. static void wlan_get_connected_vdev_handler(struct wlan_objmgr_psoc *psoc,
  1596. void *obj, void *args)
  1597. {
  1598. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj;
  1599. struct wlan_check_bssid_context *context =
  1600. (struct wlan_check_bssid_context *)args;
  1601. struct qdf_mac_addr bss_peer_mac;
  1602. enum QDF_OPMODE op_mode;
  1603. if (context->connected)
  1604. return;
  1605. op_mode = wlan_vdev_mlme_get_opmode(vdev);
  1606. if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE)
  1607. return;
  1608. if (wlan_cm_is_vdev_disconnected(vdev))
  1609. return;
  1610. if (wlan_vdev_get_bss_peer_mac(vdev, &bss_peer_mac) !=
  1611. QDF_STATUS_SUCCESS)
  1612. return;
  1613. if (qdf_is_macaddr_equal(&bss_peer_mac, &context->bssid)) {
  1614. context->connected = true;
  1615. context->vdev_id = wlan_vdev_get_id(vdev);
  1616. }
  1617. }
  1618. bool wlan_get_connected_vdev_from_psoc_by_bssid(struct wlan_objmgr_psoc *psoc,
  1619. uint8_t *bssid,
  1620. uint8_t *vdev_id)
  1621. {
  1622. struct wlan_check_bssid_context context;
  1623. qdf_mem_zero(&context, sizeof(struct wlan_check_bssid_context));
  1624. qdf_mem_copy(context.bssid.bytes, bssid, QDF_MAC_ADDR_SIZE);
  1625. wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
  1626. wlan_get_connected_vdev_handler,
  1627. &context, true, WLAN_OSIF_SCAN_ID);
  1628. if (context.connected)
  1629. *vdev_id = context.vdev_id;
  1630. return context.connected;
  1631. }
  1632. qdf_export_symbol(wlan_get_connected_vdev_from_psoc_by_bssid);
  1633. bool wlan_get_connected_vdev_by_bssid(struct wlan_objmgr_pdev *pdev,
  1634. uint8_t *bssid, uint8_t *vdev_id)
  1635. {
  1636. return wlan_get_connected_vdev_from_psoc_by_bssid(
  1637. wlan_pdev_get_psoc(pdev), bssid, vdev_id);
  1638. }
  1639. qdf_export_symbol(wlan_get_connected_vdev_by_bssid);
  1640. #ifdef WLAN_FEATURE_11BE_MLO
  1641. /**
  1642. * struct wlan_check_mld_addr_context - mld mac addr check context
  1643. * @mld_addr: mld_addrto be checked
  1644. * @connected: connected by vdev or not
  1645. * @vdev_id: vdev id of connected vdev
  1646. */
  1647. struct wlan_check_mld_addr_context {
  1648. struct qdf_mac_addr mld_addr;
  1649. bool connected;
  1650. uint8_t vdev_id;
  1651. };
  1652. /**
  1653. * wlan_get_connected_mlo_dev_ctx_handler() - check vdev connected on mld mac
  1654. * @psoc: psoc object
  1655. * @obj: vdev object
  1656. * @args: handler context
  1657. *
  1658. * This function will check whether vdev is connected on mld mac or not and
  1659. * update the result to handler context accordingly.
  1660. *
  1661. * Return: void
  1662. */
  1663. static void wlan_get_connected_mlo_dev_ctx_handler(
  1664. struct wlan_objmgr_psoc *psoc,
  1665. void *obj, void *args)
  1666. {
  1667. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj;
  1668. struct wlan_check_mld_addr_context *context =
  1669. (struct wlan_check_mld_addr_context *)args;
  1670. struct qdf_mac_addr bss_peer_mld_mac;
  1671. enum QDF_OPMODE op_mode;
  1672. if (context->connected)
  1673. return;
  1674. op_mode = wlan_vdev_mlme_get_opmode(vdev);
  1675. if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE)
  1676. return;
  1677. if (wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS)
  1678. return;
  1679. if (QDF_IS_STATUS_ERROR(wlan_vdev_get_bss_peer_mld_mac(
  1680. vdev, &bss_peer_mld_mac)))
  1681. return;
  1682. if (qdf_is_macaddr_equal(&bss_peer_mld_mac, &context->mld_addr)) {
  1683. context->connected = true;
  1684. context->vdev_id = wlan_vdev_get_id(vdev);
  1685. }
  1686. }
  1687. bool wlan_get_connected_vdev_by_mld_addr(struct wlan_objmgr_psoc *psoc,
  1688. uint8_t *mld_mac, uint8_t *vdev_id)
  1689. {
  1690. struct wlan_check_mld_addr_context context;
  1691. qdf_mem_zero(&context, sizeof(struct wlan_check_mld_addr_context));
  1692. qdf_copy_macaddr(&context.mld_addr, (struct qdf_mac_addr *)mld_mac);
  1693. wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
  1694. wlan_get_connected_mlo_dev_ctx_handler,
  1695. &context, true, WLAN_MLME_OBJMGR_ID);
  1696. if (context.connected)
  1697. *vdev_id = context.vdev_id;
  1698. return context.connected;
  1699. }
  1700. #endif
  1701. static void wlan_pdev_chan_match(struct wlan_objmgr_pdev *pdev, void *object,
  1702. void *arg)
  1703. {
  1704. struct wlan_objmgr_vdev *comp_vdev = (struct wlan_objmgr_vdev *)object;
  1705. struct wlan_vdev_ch_check_filter *ch_filter = arg;
  1706. struct wlan_channel vdev_chan, *chan;
  1707. struct wlan_channel *iter_vdev_chan;
  1708. if (ch_filter->flag)
  1709. return;
  1710. if (comp_vdev == ch_filter->vdev)
  1711. return;
  1712. wlan_vdev_obj_lock(comp_vdev);
  1713. chan = wlan_vdev_get_active_channel(comp_vdev);
  1714. if (!chan) {
  1715. wlan_vdev_obj_unlock(comp_vdev);
  1716. return;
  1717. }
  1718. wlan_chan_copy(&vdev_chan, chan);
  1719. wlan_vdev_obj_unlock(comp_vdev);
  1720. wlan_vdev_obj_lock(ch_filter->vdev);
  1721. iter_vdev_chan = wlan_vdev_mlme_get_des_chan(ch_filter->vdev);
  1722. if (wlan_chan_eq(&vdev_chan, iter_vdev_chan)
  1723. != QDF_STATUS_SUCCESS) {
  1724. ch_filter->flag = 1;
  1725. qdf_debug("==> iter vdev id: %d: ieee %d, mode %d",
  1726. wlan_vdev_get_id(comp_vdev),
  1727. vdev_chan.ch_ieee,
  1728. vdev_chan.ch_phymode);
  1729. qdf_debug("fl %016llx, fl-ext %08x, s1 %d, s2 %d ",
  1730. vdev_chan.ch_flags, vdev_chan.ch_flagext,
  1731. vdev_chan.ch_freq_seg1,
  1732. vdev_chan.ch_freq_seg2);
  1733. qdf_debug("==> base vdev id: %d: ieee %d mode %d",
  1734. wlan_vdev_get_id(ch_filter->vdev),
  1735. iter_vdev_chan->ch_ieee,
  1736. iter_vdev_chan->ch_phymode);
  1737. qdf_debug("fl %016llx, fl-ext %08x s1 %d, s2 %d",
  1738. iter_vdev_chan->ch_flags,
  1739. iter_vdev_chan->ch_flagext,
  1740. iter_vdev_chan->ch_freq_seg1,
  1741. iter_vdev_chan->ch_freq_seg2);
  1742. }
  1743. wlan_vdev_obj_unlock(ch_filter->vdev);
  1744. }
  1745. QDF_STATUS wlan_util_pdev_vdevs_deschan_match(struct wlan_objmgr_pdev *pdev,
  1746. struct wlan_objmgr_vdev *vdev,
  1747. wlan_objmgr_ref_dbgid dbg_id)
  1748. {
  1749. struct wlan_vdev_ch_check_filter ch_filter;
  1750. if (!pdev)
  1751. return QDF_STATUS_E_INVAL;
  1752. if (wlan_pdev_nif_feat_cap_get(pdev, WLAN_PDEV_F_CHAN_CONCURRENCY))
  1753. return QDF_STATUS_SUCCESS;
  1754. if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == QDF_STATUS_SUCCESS) {
  1755. ch_filter.flag = 0;
  1756. ch_filter.vdev = vdev;
  1757. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  1758. wlan_pdev_chan_match,
  1759. &ch_filter, 0, dbg_id);
  1760. wlan_objmgr_vdev_release_ref(vdev, dbg_id);
  1761. if (ch_filter.flag == 0)
  1762. return QDF_STATUS_SUCCESS;
  1763. }
  1764. return QDF_STATUS_E_FAILURE;
  1765. }
  1766. static void wlan_vdev_restart_progress(struct wlan_objmgr_pdev *pdev,
  1767. void *object, void *arg)
  1768. {
  1769. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  1770. uint8_t *flag = (uint8_t *)arg;
  1771. wlan_vdev_obj_lock(vdev);
  1772. if (wlan_vdev_is_restart_progress(vdev) == QDF_STATUS_SUCCESS)
  1773. *flag = 1;
  1774. wlan_vdev_obj_unlock(vdev);
  1775. }
  1776. QDF_STATUS wlan_util_is_pdev_restart_progress(struct wlan_objmgr_pdev *pdev,
  1777. wlan_objmgr_ref_dbgid dbg_id)
  1778. {
  1779. uint8_t flag = 0;
  1780. if (!pdev)
  1781. return QDF_STATUS_E_INVAL;
  1782. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  1783. wlan_vdev_restart_progress,
  1784. &flag, 0, dbg_id);
  1785. if (flag == 1)
  1786. return QDF_STATUS_SUCCESS;
  1787. return QDF_STATUS_E_INVAL;
  1788. }
  1789. static void wlan_vdev_scan_allowed(struct wlan_objmgr_pdev *pdev, void *object,
  1790. void *arg)
  1791. {
  1792. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  1793. uint8_t *flag = (uint8_t *)arg;
  1794. wlan_vdev_obj_lock(vdev);
  1795. if (wlan_vdev_mlme_is_scan_allowed(vdev) != QDF_STATUS_SUCCESS)
  1796. *flag = 1;
  1797. wlan_vdev_obj_unlock(vdev);
  1798. }
  1799. QDF_STATUS wlan_util_is_pdev_scan_allowed(struct wlan_objmgr_pdev *pdev,
  1800. wlan_objmgr_ref_dbgid dbg_id)
  1801. {
  1802. uint8_t flag = 0;
  1803. if (!pdev)
  1804. return QDF_STATUS_E_INVAL;
  1805. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  1806. wlan_vdev_scan_allowed,
  1807. &flag, 0, dbg_id);
  1808. if (flag == 1)
  1809. return QDF_STATUS_E_FAILURE;
  1810. return QDF_STATUS_SUCCESS;
  1811. }
  1812. void
  1813. wlan_util_stats_get_rssi(bool db2dbm_enabled, int32_t bcn_snr, int32_t dat_snr,
  1814. int8_t *rssi)
  1815. {
  1816. uint32_t snr;
  1817. if (db2dbm_enabled) {
  1818. if (TGT_IS_VALID_RSSI(bcn_snr))
  1819. *rssi = bcn_snr;
  1820. else if (TGT_IS_VALID_RSSI(dat_snr))
  1821. *rssi = dat_snr;
  1822. else
  1823. *rssi = TGT_NOISE_FLOOR_DBM;
  1824. } else {
  1825. if (TGT_IS_VALID_SNR(bcn_snr))
  1826. snr = bcn_snr;
  1827. else if (TGT_IS_VALID_SNR(dat_snr))
  1828. snr = dat_snr;
  1829. else
  1830. snr = TGT_INVALID_SNR;
  1831. /* Get the absolute rssi value from the current rssi value */
  1832. *rssi = snr + TGT_NOISE_FLOOR_DBM;
  1833. }
  1834. }
  1835. /**
  1836. * wlan_util_get_mode_specific_peer_count - This api gives vdev mode specific
  1837. * peer count`
  1838. * @pdev: PDEV object
  1839. * @object: vdev object
  1840. * @arg: argument passed by caller
  1841. *
  1842. * Return: void
  1843. */
  1844. static void
  1845. wlan_util_get_mode_specific_peer_count(struct wlan_objmgr_pdev *pdev,
  1846. void *object, void *arg)
  1847. {
  1848. struct wlan_objmgr_vdev *vdev = object;
  1849. uint16_t temp_count = 0;
  1850. struct wlan_op_mode_peer_count *count = arg;
  1851. wlan_vdev_obj_lock(vdev);
  1852. if (wlan_vdev_mlme_get_opmode(vdev) == count->opmode) {
  1853. temp_count = wlan_vdev_get_peer_count(vdev);
  1854. /* Decrement the self peer count */
  1855. if (temp_count > 1)
  1856. count->peer_count += (temp_count - 1);
  1857. }
  1858. wlan_vdev_obj_unlock(vdev);
  1859. }
  1860. uint16_t wlan_util_get_peer_count_for_mode(struct wlan_objmgr_pdev *pdev,
  1861. enum QDF_OPMODE mode)
  1862. {
  1863. struct wlan_op_mode_peer_count count;
  1864. count.opmode = mode;
  1865. count.peer_count = 0;
  1866. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  1867. wlan_util_get_mode_specific_peer_count, &count,
  1868. 0, WLAN_OBJMGR_ID);
  1869. return count.peer_count;
  1870. }
  1871. #ifdef CONFIG_QCA_MINIDUMP
  1872. static bool wlan_minidump_log_enabled(struct wlan_objmgr_psoc *psoc,
  1873. enum wlan_minidump_host_data type)
  1874. {
  1875. bool setval = false;
  1876. switch (type) {
  1877. case WLAN_MD_CP_EXT_PDEV:
  1878. if (cfg_get(psoc, CFG_OL_MD_CP_EXT_PDEV))
  1879. setval = true;
  1880. break;
  1881. case WLAN_MD_CP_EXT_PSOC:
  1882. if (cfg_get(psoc, CFG_OL_MD_CP_EXT_PSOC))
  1883. setval = true;
  1884. break;
  1885. case WLAN_MD_CP_EXT_VDEV:
  1886. if (cfg_get(psoc, CFG_OL_MD_CP_EXT_VDEV))
  1887. setval = true;
  1888. break;
  1889. case WLAN_MD_CP_EXT_PEER:
  1890. if (cfg_get(psoc, CFG_OL_MD_CP_EXT_PEER))
  1891. setval = true;
  1892. break;
  1893. case WLAN_MD_DP_SOC:
  1894. if (cfg_get(psoc, CFG_OL_MD_DP_SOC))
  1895. setval = true;
  1896. break;
  1897. case WLAN_MD_DP_PDEV:
  1898. if (cfg_get(psoc, CFG_OL_MD_DP_PDEV))
  1899. setval = true;
  1900. break;
  1901. case WLAN_MD_DP_PEER:
  1902. if (cfg_get(psoc, CFG_OL_MD_DP_PEER))
  1903. setval = true;
  1904. break;
  1905. case WLAN_MD_DP_SRNG_REO_DEST:
  1906. case WLAN_MD_DP_SRNG_REO_EXCEPTION:
  1907. case WLAN_MD_DP_SRNG_RX_REL:
  1908. case WLAN_MD_DP_SRNG_REO_REINJECT:
  1909. case WLAN_MD_DP_SRNG_REO_CMD:
  1910. case WLAN_MD_DP_SRNG_REO_STATUS:
  1911. if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_REO))
  1912. setval = true;
  1913. break;
  1914. case WLAN_MD_DP_SRNG_TCL_DATA:
  1915. case WLAN_MD_DP_SRNG_TCL_CMD:
  1916. case WLAN_MD_DP_SRNG_TCL_STATUS:
  1917. case WLAN_MD_DP_SRNG_TX_COMP:
  1918. if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_TCL))
  1919. setval = true;
  1920. break;
  1921. case WLAN_MD_DP_SRNG_WBM_DESC_REL:
  1922. case WLAN_MD_DP_SRNG_WBM_IDLE_LINK:
  1923. if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_WBM))
  1924. setval = true;
  1925. break;
  1926. case WLAN_MD_DP_LINK_DESC_BANK:
  1927. if (cfg_get(psoc, CFG_OL_MD_DP_LINK_DESC_BANK))
  1928. setval = true;
  1929. break;
  1930. case WLAN_MD_DP_SRNG_RXDMA_MON_BUF:
  1931. case WLAN_MD_DP_SRNG_RXDMA_MON_DST:
  1932. case WLAN_MD_DP_SRNG_RXDMA_MON_DESC:
  1933. case WLAN_MD_DP_SRNG_RXDMA_ERR_DST:
  1934. case WLAN_MD_DP_SRNG_RXDMA_MON_STATUS:
  1935. if (cfg_get(psoc, CFG_OL_MD_DP_SRNG_RXDMA))
  1936. setval = true;
  1937. break;
  1938. case WLAN_MD_DP_HAL_SOC:
  1939. if (cfg_get(psoc, CFG_OL_MD_DP_HAL_SOC))
  1940. setval = true;
  1941. break;
  1942. case WLAN_MD_OBJMGR_PSOC:
  1943. case WLAN_MD_OBJMGR_PSOC_TGT_INFO:
  1944. if (cfg_get(psoc, CFG_OL_MD_OBJMGR_PSOC))
  1945. setval = true;
  1946. break;
  1947. case WLAN_MD_OBJMGR_PDEV:
  1948. case WLAN_MD_OBJMGR_PDEV_MLME:
  1949. if (cfg_get(psoc, CFG_OL_MD_OBJMGR_PDEV))
  1950. setval = true;
  1951. break;
  1952. case WLAN_MD_OBJMGR_VDEV_MLME:
  1953. case WLAN_MD_OBJMGR_VDEV_SM:
  1954. case WLAN_MD_OBJMGR_VDEV:
  1955. if (cfg_get(psoc, CFG_OL_MD_OBJMGR_VDEV))
  1956. setval = true;
  1957. break;
  1958. default:
  1959. qdf_debug("Minidump: Type not implemented");
  1960. }
  1961. return setval;
  1962. }
  1963. #else /* CONFIG_QCA_MINIDUMP */
  1964. static bool wlan_minidump_log_enabled(struct wlan_objmgr_psoc *psoc,
  1965. enum wlan_minidump_host_data type)
  1966. {
  1967. return false;
  1968. }
  1969. #endif
  1970. void wlan_minidump_log(void *start_addr, const size_t size,
  1971. void *psoc_obj,
  1972. enum wlan_minidump_host_data type,
  1973. const char *name)
  1974. {
  1975. struct wlan_objmgr_psoc *psoc;
  1976. if (!psoc_obj) {
  1977. qdf_debug("Minidump: Psoc is NULL");
  1978. return;
  1979. }
  1980. psoc = (struct wlan_objmgr_psoc *)psoc_obj;
  1981. if (psoc && wlan_minidump_log_enabled(psoc, type))
  1982. qdf_minidump_log(start_addr, size, name);
  1983. }
  1984. qdf_export_symbol(wlan_minidump_log);
  1985. void wlan_minidump_remove(void *start_addr, const size_t size,
  1986. void *psoc_obj,
  1987. enum wlan_minidump_host_data type,
  1988. const char *name)
  1989. {
  1990. struct wlan_objmgr_psoc *psoc;
  1991. if (!psoc_obj) {
  1992. qdf_debug("Minidump: Psoc is NULL");
  1993. return;
  1994. }
  1995. psoc = (struct wlan_objmgr_psoc *)psoc_obj;
  1996. if (psoc && wlan_minidump_log_enabled(psoc, type))
  1997. qdf_minidump_remove(start_addr, size, name);
  1998. }
  1999. qdf_export_symbol(wlan_minidump_remove);
  2000. static void vdev_cac_in_progress(struct wlan_objmgr_pdev *pdev,
  2001. void *object, void *arg)
  2002. {
  2003. struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
  2004. bool *cac_is_in_progress = (bool *)arg;
  2005. if (*cac_is_in_progress)
  2006. return;
  2007. if (wlan_vdev_is_dfs_cac_wait(vdev) == QDF_STATUS_SUCCESS)
  2008. *cac_is_in_progress = true;
  2009. }
  2010. bool wlan_util_is_vdev_in_cac_wait(struct wlan_objmgr_pdev *pdev,
  2011. wlan_objmgr_ref_dbgid dbg_id)
  2012. {
  2013. bool cac_is_in_progress = false;
  2014. wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
  2015. vdev_cac_in_progress,
  2016. &cac_is_in_progress, 0,
  2017. dbg_id);
  2018. return cac_is_in_progress;
  2019. }
  2020. qdf_export_symbol(wlan_util_is_vdev_in_cac_wait);