wmi_unified_pmo_tlv.c 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210
  1. /*
  2. * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for
  5. * any purpose with or without fee is hereby granted, provided that the
  6. * above copyright notice and this permission notice appear in all
  7. * copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  10. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  12. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. * PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include <osdep.h>
  19. #include "wmi.h"
  20. #include "wmi_unified_priv.h"
  21. #include "wmi_unified_pmo_api.h"
  22. #ifdef FEATURE_WLAN_D0WOW
  23. /**
  24. * send_d0wow_enable_cmd_tlv() - WMI d0 wow enable function
  25. * @param wmi_handle: handle to WMI.
  26. * @mac_id: radio context
  27. *
  28. * Return: 0 on success and error code on failure.
  29. */
  30. static QDF_STATUS send_d0wow_enable_cmd_tlv(wmi_unified_t wmi_handle,
  31. uint8_t mac_id)
  32. {
  33. wmi_d0_wow_enable_disable_cmd_fixed_param *cmd;
  34. wmi_buf_t buf;
  35. int32_t len;
  36. QDF_STATUS status;
  37. len = sizeof(wmi_d0_wow_enable_disable_cmd_fixed_param);
  38. buf = wmi_buf_alloc(wmi_handle, len);
  39. if (!buf) {
  40. return QDF_STATUS_E_NOMEM;
  41. }
  42. cmd = (wmi_d0_wow_enable_disable_cmd_fixed_param *) wmi_buf_data(buf);
  43. WMITLV_SET_HDR(&cmd->tlv_header,
  44. WMITLV_TAG_STRUC_wmi_d0_wow_enable_disable_cmd_fixed_param,
  45. WMITLV_GET_STRUCT_TLVLEN
  46. (wmi_d0_wow_enable_disable_cmd_fixed_param));
  47. cmd->enable = true;
  48. wmi_mtrace(WMI_D0_WOW_ENABLE_DISABLE_CMDID, NO_SESSION, 0);
  49. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  50. WMI_D0_WOW_ENABLE_DISABLE_CMDID);
  51. if (QDF_IS_STATUS_ERROR(status))
  52. wmi_buf_free(buf);
  53. return status;
  54. }
  55. /**
  56. * send_d0wow_disable_cmd_tlv() - WMI d0 wow disable function
  57. * @param wmi_handle: handle to WMI.
  58. * @mac_id: radio context
  59. *
  60. * Return: 0 on success and error code on failure.
  61. */
  62. static QDF_STATUS send_d0wow_disable_cmd_tlv(wmi_unified_t wmi_handle,
  63. uint8_t mac_id)
  64. {
  65. wmi_d0_wow_enable_disable_cmd_fixed_param *cmd;
  66. wmi_buf_t buf;
  67. int32_t len;
  68. QDF_STATUS status;
  69. len = sizeof(wmi_d0_wow_enable_disable_cmd_fixed_param);
  70. buf = wmi_buf_alloc(wmi_handle, len);
  71. if (!buf) {
  72. return QDF_STATUS_E_NOMEM;
  73. }
  74. cmd = (wmi_d0_wow_enable_disable_cmd_fixed_param *) wmi_buf_data(buf);
  75. WMITLV_SET_HDR(&cmd->tlv_header,
  76. WMITLV_TAG_STRUC_wmi_d0_wow_enable_disable_cmd_fixed_param,
  77. WMITLV_GET_STRUCT_TLVLEN
  78. (wmi_d0_wow_enable_disable_cmd_fixed_param));
  79. cmd->enable = false;
  80. wmi_mtrace(WMI_D0_WOW_ENABLE_DISABLE_CMDID, NO_SESSION, 0);
  81. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  82. WMI_D0_WOW_ENABLE_DISABLE_CMDID);
  83. if (QDF_IS_STATUS_ERROR(status))
  84. wmi_buf_free(buf);
  85. return status;
  86. }
  87. void wmi_d0wow_attach_tlv(struct wmi_unified *wmi_handle)
  88. {
  89. struct wmi_ops *ops = wmi_handle->ops;
  90. ops->send_d0wow_enable_cmd = send_d0wow_enable_cmd_tlv;
  91. ops->send_d0wow_disable_cmd = send_d0wow_disable_cmd_tlv;
  92. }
  93. #endif /* FEATURE_WLAN_D0WOW */
  94. /**
  95. * send_add_wow_wakeup_event_cmd_tlv() - Configures wow wakeup events.
  96. * @wmi_handle: wmi handle
  97. * @vdev_id: vdev id
  98. * @bitmap: Event bitmap
  99. * @enable: enable/disable
  100. *
  101. * Return: CDF status
  102. */
  103. static QDF_STATUS send_add_wow_wakeup_event_cmd_tlv(wmi_unified_t wmi_handle,
  104. uint32_t vdev_id,
  105. uint32_t *bitmap,
  106. bool enable)
  107. {
  108. WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *cmd;
  109. uint16_t len;
  110. wmi_buf_t buf;
  111. int ret;
  112. len = sizeof(WMI_WOW_ADD_DEL_EVT_CMD_fixed_param);
  113. buf = wmi_buf_alloc(wmi_handle, len);
  114. if (!buf) {
  115. return QDF_STATUS_E_NOMEM;
  116. }
  117. cmd = (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *) wmi_buf_data(buf);
  118. WMITLV_SET_HDR(&cmd->tlv_header,
  119. WMITLV_TAG_STRUC_WMI_WOW_ADD_DEL_EVT_CMD_fixed_param,
  120. WMITLV_GET_STRUCT_TLVLEN
  121. (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param));
  122. cmd->vdev_id = vdev_id;
  123. cmd->is_add = enable;
  124. qdf_mem_copy(&(cmd->event_bitmaps[0]), bitmap, sizeof(uint32_t) *
  125. WMI_WOW_MAX_EVENT_BM_LEN);
  126. wmi_debug("Wakeup pattern 0x%x%x%x%x %s in fw", cmd->event_bitmaps[0],
  127. cmd->event_bitmaps[1], cmd->event_bitmaps[2],
  128. cmd->event_bitmaps[3], enable ? "enabled" : "disabled");
  129. wmi_mtrace(WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, cmd->vdev_id, 0);
  130. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  131. WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
  132. if (ret) {
  133. wmi_err("Failed to config wow wakeup event");
  134. wmi_buf_free(buf);
  135. return QDF_STATUS_E_FAILURE;
  136. }
  137. return QDF_STATUS_SUCCESS;
  138. }
  139. /**
  140. * send_wow_patterns_to_fw_cmd_tlv() - Sends WOW patterns to FW.
  141. * @wmi_handle: wmi handle
  142. * @vdev_id: vdev id
  143. * @ptrn_id: pattern id
  144. * @ptrn: pattern
  145. * @ptrn_len: pattern length
  146. * @ptrn_offset: pattern offset
  147. * @mask: mask
  148. * @mask_len: mask length
  149. * @user: true for user configured pattern and false for default pattern
  150. * @default_patterns: default patterns
  151. *
  152. * Return: CDF status
  153. */
  154. static QDF_STATUS send_wow_patterns_to_fw_cmd_tlv(wmi_unified_t wmi_handle,
  155. uint8_t vdev_id, uint8_t ptrn_id,
  156. const uint8_t *ptrn, uint8_t ptrn_len,
  157. uint8_t ptrn_offset, const uint8_t *mask,
  158. uint8_t mask_len, bool user,
  159. uint8_t default_patterns)
  160. {
  161. WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
  162. WOW_BITMAP_PATTERN_T *bitmap_pattern;
  163. wmi_buf_t buf;
  164. uint8_t *buf_ptr;
  165. int32_t len;
  166. int ret;
  167. len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
  168. WMI_TLV_HDR_SIZE +
  169. 1 * sizeof(WOW_BITMAP_PATTERN_T) +
  170. WMI_TLV_HDR_SIZE +
  171. 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
  172. WMI_TLV_HDR_SIZE +
  173. 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
  174. WMI_TLV_HDR_SIZE +
  175. 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
  176. WMI_TLV_HDR_SIZE +
  177. 0 * sizeof(uint32_t) + WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t);
  178. buf = wmi_buf_alloc(wmi_handle, len);
  179. if (!buf) {
  180. return QDF_STATUS_E_NOMEM;
  181. }
  182. cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
  183. buf_ptr = (uint8_t *) cmd;
  184. WMITLV_SET_HDR(&cmd->tlv_header,
  185. WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
  186. WMITLV_GET_STRUCT_TLVLEN
  187. (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
  188. cmd->vdev_id = vdev_id;
  189. cmd->pattern_id = ptrn_id;
  190. cmd->pattern_type = WOW_BITMAP_PATTERN;
  191. buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
  192. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  193. sizeof(WOW_BITMAP_PATTERN_T));
  194. buf_ptr += WMI_TLV_HDR_SIZE;
  195. bitmap_pattern = (WOW_BITMAP_PATTERN_T *) buf_ptr;
  196. WMITLV_SET_HDR(&bitmap_pattern->tlv_header,
  197. WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T,
  198. WMITLV_GET_STRUCT_TLVLEN(WOW_BITMAP_PATTERN_T));
  199. qdf_mem_copy(&bitmap_pattern->patternbuf[0], ptrn, ptrn_len);
  200. qdf_mem_copy(&bitmap_pattern->bitmaskbuf[0], mask, mask_len);
  201. bitmap_pattern->pattern_offset = ptrn_offset;
  202. bitmap_pattern->pattern_len = ptrn_len;
  203. if (bitmap_pattern->pattern_len > WOW_DEFAULT_BITMAP_PATTERN_SIZE)
  204. bitmap_pattern->pattern_len = WOW_DEFAULT_BITMAP_PATTERN_SIZE;
  205. if (bitmap_pattern->pattern_len > WOW_DEFAULT_BITMASK_SIZE)
  206. bitmap_pattern->pattern_len = WOW_DEFAULT_BITMASK_SIZE;
  207. bitmap_pattern->bitmask_len = bitmap_pattern->pattern_len;
  208. bitmap_pattern->pattern_id = ptrn_id;
  209. wmi_debug("vdev: %d, ptrn id: %d, ptrn len: %d, ptrn offset: %d user %d",
  210. cmd->vdev_id, cmd->pattern_id, bitmap_pattern->pattern_len,
  211. bitmap_pattern->pattern_offset, user);
  212. wmi_debug("Pattern: ");
  213. QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
  214. &bitmap_pattern->patternbuf[0],
  215. bitmap_pattern->pattern_len);
  216. wmi_debug("Mask: ");
  217. QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
  218. &bitmap_pattern->bitmaskbuf[0],
  219. bitmap_pattern->pattern_len);
  220. buf_ptr += sizeof(WOW_BITMAP_PATTERN_T);
  221. /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
  222. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  223. buf_ptr += WMI_TLV_HDR_SIZE;
  224. /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
  225. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  226. buf_ptr += WMI_TLV_HDR_SIZE;
  227. /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
  228. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  229. buf_ptr += WMI_TLV_HDR_SIZE;
  230. /* Fill TLV for pattern_info_timeout but no data. */
  231. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
  232. buf_ptr += WMI_TLV_HDR_SIZE;
  233. /* Fill TLV for ratelimit_interval with dummy data as this fix elem */
  234. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 1 * sizeof(uint32_t));
  235. buf_ptr += WMI_TLV_HDR_SIZE;
  236. *(uint32_t *) buf_ptr = 0;
  237. wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
  238. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  239. WMI_WOW_ADD_WAKE_PATTERN_CMDID);
  240. if (ret) {
  241. wmi_err("Failed to send wow ptrn to fw");
  242. wmi_buf_free(buf);
  243. return QDF_STATUS_E_FAILURE;
  244. }
  245. return QDF_STATUS_SUCCESS;
  246. }
  247. /**
  248. * fill_arp_offload_params_tlv() - Fill ARP offload data
  249. * @wmi_handle: wmi handle
  250. * @offload_req: offload request
  251. * @buf_ptr: buffer pointer
  252. *
  253. * To fill ARP offload data to firmware
  254. * when target goes to wow mode.
  255. *
  256. * Return: None
  257. */
  258. static void fill_arp_offload_params_tlv(wmi_unified_t wmi_handle,
  259. struct pmo_arp_offload_params *offload_req, uint8_t **buf_ptr)
  260. {
  261. int i;
  262. WMI_ARP_OFFLOAD_TUPLE *arp_tuple;
  263. bool enable_or_disable = offload_req->enable;
  264. WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  265. (WMI_MAX_ARP_OFFLOADS*sizeof(WMI_ARP_OFFLOAD_TUPLE)));
  266. *buf_ptr += WMI_TLV_HDR_SIZE;
  267. for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) {
  268. arp_tuple = (WMI_ARP_OFFLOAD_TUPLE *)*buf_ptr;
  269. WMITLV_SET_HDR(&arp_tuple->tlv_header,
  270. WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE,
  271. WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE));
  272. /* Fill data for ARP and NS in the first tupple for LA */
  273. if ((enable_or_disable & PMO_OFFLOAD_ENABLE) && (i == 0)) {
  274. /* Copy the target ip addr and flags */
  275. arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID;
  276. qdf_mem_copy(&arp_tuple->target_ipaddr,
  277. offload_req->host_ipv4_addr,
  278. WMI_IPV4_ADDR_LEN);
  279. wmi_debug("ARPOffload IP4 address: %pI4",
  280. offload_req->host_ipv4_addr);
  281. }
  282. *buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE);
  283. }
  284. }
  285. #ifdef WLAN_NS_OFFLOAD
  286. /**
  287. * fill_ns_offload_params_tlv() - Fill NS offload data
  288. * @wmi|_handle: wmi handle
  289. * @offload_req: offload request
  290. * @buf_ptr: buffer pointer
  291. *
  292. * To fill NS offload data to firmware
  293. * when target goes to wow mode.
  294. *
  295. * Return: None
  296. */
  297. static void fill_ns_offload_params_tlv(wmi_unified_t wmi_handle,
  298. struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
  299. {
  300. int i;
  301. WMI_NS_OFFLOAD_TUPLE *ns_tuple;
  302. WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  303. (WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE)));
  304. *buf_ptr += WMI_TLV_HDR_SIZE;
  305. for (i = 0; i < WMI_MAX_NS_OFFLOADS; i++) {
  306. ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)*buf_ptr;
  307. WMITLV_SET_HDR(&ns_tuple->tlv_header,
  308. WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
  309. (sizeof(WMI_NS_OFFLOAD_TUPLE) - WMI_TLV_HDR_SIZE));
  310. /*
  311. * Fill data only for NS offload in the first ARP tuple for LA
  312. */
  313. if ((ns_req->enable & PMO_OFFLOAD_ENABLE)) {
  314. ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
  315. /* Copy the target/solicitation/remote ip addr */
  316. if (ns_req->target_ipv6_addr_valid[i])
  317. qdf_mem_copy(&ns_tuple->target_ipaddr[0],
  318. &ns_req->target_ipv6_addr[i],
  319. sizeof(WMI_IPV6_ADDR));
  320. qdf_mem_copy(&ns_tuple->solicitation_ipaddr,
  321. &ns_req->self_ipv6_addr[i],
  322. sizeof(WMI_IPV6_ADDR));
  323. if (ns_req->target_ipv6_addr_ac_type[i]) {
  324. ns_tuple->flags |=
  325. WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
  326. }
  327. wmi_debug("Index %d NS solicitedIp %pI6, targetIp %pI6",
  328. i, &ns_req->self_ipv6_addr[i],
  329. &ns_req->target_ipv6_addr[i]);
  330. /* target MAC is optional, check if it is valid,
  331. * if this is not valid, the target will use the known
  332. * local MAC address rather than the tuple
  333. */
  334. WMI_CHAR_ARRAY_TO_MAC_ADDR(
  335. ns_req->self_macaddr.bytes,
  336. &ns_tuple->target_mac);
  337. if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
  338. (ns_tuple->target_mac.mac_addr47to32 != 0)) {
  339. ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
  340. }
  341. }
  342. *buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
  343. }
  344. }
  345. /**
  346. * fill_nsoffload_ext_tlv() - Fill NS offload ext data
  347. * @wmi: wmi handle
  348. * @offload_req: offload request
  349. * @buf_ptr: buffer pointer
  350. *
  351. * To fill extended NS offload extended data to firmware
  352. * when target goes to wow mode.
  353. *
  354. * Return: None
  355. */
  356. static void fill_nsoffload_ext_tlv(wmi_unified_t wmi_handle,
  357. struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
  358. {
  359. int i;
  360. WMI_NS_OFFLOAD_TUPLE *ns_tuple;
  361. uint32_t count, num_ns_ext_tuples;
  362. count = ns_req->num_ns_offload_count;
  363. num_ns_ext_tuples = ns_req->num_ns_offload_count -
  364. WMI_MAX_NS_OFFLOADS;
  365. /* Populate extended NS offload tuples */
  366. WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  367. (num_ns_ext_tuples * sizeof(WMI_NS_OFFLOAD_TUPLE)));
  368. *buf_ptr += WMI_TLV_HDR_SIZE;
  369. for (i = WMI_MAX_NS_OFFLOADS; i < count; i++) {
  370. ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)*buf_ptr;
  371. WMITLV_SET_HDR(&ns_tuple->tlv_header,
  372. WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
  373. (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE));
  374. /*
  375. * Fill data only for NS offload in the first ARP tuple for LA
  376. */
  377. if ((ns_req->enable & PMO_OFFLOAD_ENABLE)) {
  378. ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
  379. /* Copy the target/solicitation/remote ip addr */
  380. if (ns_req->target_ipv6_addr_valid[i])
  381. qdf_mem_copy(&ns_tuple->target_ipaddr[0],
  382. &ns_req->target_ipv6_addr[i],
  383. sizeof(WMI_IPV6_ADDR));
  384. qdf_mem_copy(&ns_tuple->solicitation_ipaddr,
  385. &ns_req->self_ipv6_addr[i],
  386. sizeof(WMI_IPV6_ADDR));
  387. if (ns_req->target_ipv6_addr_ac_type[i]) {
  388. ns_tuple->flags |=
  389. WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
  390. }
  391. wmi_debug("Index %d NS solicitedIp %pI6, targetIp %pI6",
  392. i, &ns_req->self_ipv6_addr[i],
  393. &ns_req->target_ipv6_addr[i]);
  394. /* target MAC is optional, check if it is valid,
  395. * if this is not valid, the target will use the
  396. * known local MAC address rather than the tuple
  397. */
  398. WMI_CHAR_ARRAY_TO_MAC_ADDR(
  399. ns_req->self_macaddr.bytes,
  400. &ns_tuple->target_mac);
  401. if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
  402. (ns_tuple->target_mac.mac_addr47to32 != 0)) {
  403. ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
  404. }
  405. }
  406. *buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
  407. }
  408. }
  409. #else
  410. static void fill_ns_offload_params_tlv(wmi_unified_t wmi_handle,
  411. struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
  412. {
  413. }
  414. static void fill_nsoffload_ext_tlv(wmi_unified_t wmi_handle,
  415. struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
  416. {
  417. }
  418. #endif
  419. /**
  420. * send_enable_arp_ns_offload_cmd_tlv() - enable ARP NS offload
  421. * @wma: wmi handle
  422. * @arp_offload_req: arp offload request
  423. * @ns_offload_req: ns offload request
  424. * @arp_only: flag
  425. *
  426. * To configure ARP NS off load data to firmware
  427. * when target goes to wow mode.
  428. *
  429. * Return: QDF Status
  430. */
  431. static QDF_STATUS send_enable_arp_ns_offload_cmd_tlv(wmi_unified_t wmi_handle,
  432. struct pmo_arp_offload_params *arp_offload_req,
  433. struct pmo_ns_offload_params *ns_offload_req,
  434. uint8_t vdev_id)
  435. {
  436. int32_t res;
  437. WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd;
  438. uint8_t *buf_ptr;
  439. wmi_buf_t buf;
  440. int32_t len;
  441. uint32_t count = 0, num_ns_ext_tuples = 0;
  442. count = ns_offload_req->num_ns_offload_count;
  443. /*
  444. * TLV place holder size for array of NS tuples
  445. * TLV place holder size for array of ARP tuples
  446. */
  447. len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) +
  448. WMI_TLV_HDR_SIZE +
  449. WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE) +
  450. WMI_TLV_HDR_SIZE +
  451. WMI_MAX_ARP_OFFLOADS * sizeof(WMI_ARP_OFFLOAD_TUPLE);
  452. /*
  453. * If there are more than WMI_MAX_NS_OFFLOADS addresses then allocate
  454. * extra length for extended NS offload tuples which follows ARP offload
  455. * tuples. Host needs to fill this structure in following format:
  456. * 2 NS ofload tuples
  457. * 2 ARP offload tuples
  458. * N numbers of extended NS offload tuples if HDD has given more than
  459. * 2 NS offload addresses
  460. */
  461. if (count > WMI_MAX_NS_OFFLOADS) {
  462. num_ns_ext_tuples = count - WMI_MAX_NS_OFFLOADS;
  463. len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples
  464. * sizeof(WMI_NS_OFFLOAD_TUPLE);
  465. }
  466. buf = wmi_buf_alloc(wmi_handle, len);
  467. if (!buf) {
  468. return QDF_STATUS_E_NOMEM;
  469. }
  470. buf_ptr = (uint8_t *) wmi_buf_data(buf);
  471. cmd = (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *) buf_ptr;
  472. WMITLV_SET_HDR(&cmd->tlv_header,
  473. WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param,
  474. WMITLV_GET_STRUCT_TLVLEN
  475. (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param));
  476. cmd->flags = 0;
  477. cmd->vdev_id = vdev_id;
  478. cmd->num_ns_ext_tuples = num_ns_ext_tuples;
  479. wmi_debug("ARP NS Offload vdev_id: %d", cmd->vdev_id);
  480. buf_ptr += sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param);
  481. fill_ns_offload_params_tlv(wmi_handle, ns_offload_req, &buf_ptr);
  482. fill_arp_offload_params_tlv(wmi_handle, arp_offload_req, &buf_ptr);
  483. if (num_ns_ext_tuples)
  484. fill_nsoffload_ext_tlv(wmi_handle, ns_offload_req, &buf_ptr);
  485. wmi_mtrace(WMI_SET_ARP_NS_OFFLOAD_CMDID, cmd->vdev_id, 0);
  486. res = wmi_unified_cmd_send(wmi_handle, buf, len,
  487. WMI_SET_ARP_NS_OFFLOAD_CMDID);
  488. if (res) {
  489. wmi_err("Failed to enable ARP NDP/NSffload");
  490. wmi_buf_free(buf);
  491. return QDF_STATUS_E_FAILURE;
  492. }
  493. return QDF_STATUS_SUCCESS;
  494. }
  495. /**
  496. * send_add_clear_mcbc_filter_cmd_tlv() - set mcast filter command to fw
  497. * @wmi_handle: wmi handle
  498. * @vdev_id: vdev id
  499. * @multicastAddr: mcast address
  500. * @clearList: clear list flag
  501. *
  502. * Return: QDF_STATUS_SUCCESS for success or error code
  503. */
  504. static QDF_STATUS send_add_clear_mcbc_filter_cmd_tlv(wmi_unified_t wmi_handle,
  505. uint8_t vdev_id,
  506. struct qdf_mac_addr multicast_addr,
  507. bool clearList)
  508. {
  509. WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd;
  510. wmi_buf_t buf;
  511. int err;
  512. buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
  513. if (!buf) {
  514. return QDF_STATUS_E_NOMEM;
  515. }
  516. cmd = (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *) wmi_buf_data(buf);
  517. qdf_mem_zero(cmd, sizeof(*cmd));
  518. WMITLV_SET_HDR(&cmd->tlv_header,
  519. WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param,
  520. WMITLV_GET_STRUCT_TLVLEN
  521. (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param));
  522. cmd->action =
  523. (clearList ? WMI_MCAST_FILTER_DELETE : WMI_MCAST_FILTER_SET);
  524. cmd->vdev_id = vdev_id;
  525. WMI_CHAR_ARRAY_TO_MAC_ADDR(multicast_addr.bytes, &cmd->mcastbdcastaddr);
  526. wmi_debug("Action:%d; vdev_id:%d; clearList:%d; MCBC MAC Addr: "QDF_MAC_ADDR_FMT,
  527. cmd->action, vdev_id, clearList,
  528. QDF_MAC_ADDR_REF(multicast_addr.bytes));
  529. wmi_mtrace(WMI_SET_MCASTBCAST_FILTER_CMDID, cmd->vdev_id, 0);
  530. err = wmi_unified_cmd_send(wmi_handle, buf,
  531. sizeof(*cmd),
  532. WMI_SET_MCASTBCAST_FILTER_CMDID);
  533. if (err) {
  534. wmi_err("Failed to send set_param cmd");
  535. wmi_buf_free(buf);
  536. return QDF_STATUS_E_FAILURE;
  537. }
  538. return QDF_STATUS_SUCCESS;
  539. }
  540. /**
  541. * send_multiple_add_clear_mcbc_filter_cmd_tlv() - send multiple mcast filter
  542. * command to fw
  543. * @wmi_handle: wmi handle
  544. * @vdev_id: vdev id
  545. * @mcast_filter_params: mcast filter params
  546. *
  547. * Return: QDF_STATUS_SUCCESS for success or error code
  548. */
  549. static QDF_STATUS send_multiple_add_clear_mcbc_filter_cmd_tlv(
  550. wmi_unified_t wmi_handle,
  551. uint8_t vdev_id,
  552. struct pmo_mcast_filter_params *filter_param)
  553. {
  554. WMI_SET_MULTIPLE_MCAST_FILTER_CMD_fixed_param *cmd;
  555. uint8_t *buf_ptr;
  556. wmi_buf_t buf;
  557. int err;
  558. int i;
  559. uint8_t *mac_addr_src_ptr = NULL;
  560. wmi_mac_addr *mac_addr_dst_ptr;
  561. uint32_t len = sizeof(*cmd) + WMI_TLV_HDR_SIZE +
  562. sizeof(wmi_mac_addr) * filter_param->multicast_addr_cnt;
  563. buf = wmi_buf_alloc(wmi_handle, len);
  564. if (!buf) {
  565. return QDF_STATUS_E_NOMEM;
  566. }
  567. buf_ptr = (uint8_t *) wmi_buf_data(buf);
  568. cmd = (WMI_SET_MULTIPLE_MCAST_FILTER_CMD_fixed_param *)
  569. wmi_buf_data(buf);
  570. qdf_mem_zero(cmd, sizeof(*cmd));
  571. WMITLV_SET_HDR(&cmd->tlv_header,
  572. WMITLV_TAG_STRUC_wmi_set_multiple_mcast_filter_cmd_fixed_param,
  573. WMITLV_GET_STRUCT_TLVLEN
  574. (WMI_SET_MULTIPLE_MCAST_FILTER_CMD_fixed_param));
  575. cmd->operation =
  576. ((filter_param->action == 0) ? WMI_MULTIPLE_MCAST_FILTER_DELETE
  577. : WMI_MULTIPLE_MCAST_FILTER_ADD);
  578. cmd->vdev_id = vdev_id;
  579. cmd->num_mcastaddrs = filter_param->multicast_addr_cnt;
  580. buf_ptr += sizeof(*cmd);
  581. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
  582. sizeof(wmi_mac_addr) *
  583. filter_param->multicast_addr_cnt);
  584. if (filter_param->multicast_addr_cnt == 0)
  585. goto send_cmd;
  586. mac_addr_src_ptr = (uint8_t *)&filter_param->multicast_addr;
  587. mac_addr_dst_ptr = (wmi_mac_addr *)
  588. (buf_ptr + WMI_TLV_HDR_SIZE);
  589. for (i = 0; i < filter_param->multicast_addr_cnt; i++) {
  590. WMI_CHAR_ARRAY_TO_MAC_ADDR(mac_addr_src_ptr, mac_addr_dst_ptr);
  591. mac_addr_src_ptr += ATH_MAC_LEN;
  592. mac_addr_dst_ptr++;
  593. }
  594. send_cmd:
  595. wmi_mtrace(WMI_SET_MULTIPLE_MCAST_FILTER_CMDID, cmd->vdev_id, 0);
  596. err = wmi_unified_cmd_send(wmi_handle, buf,
  597. len,
  598. WMI_SET_MULTIPLE_MCAST_FILTER_CMDID);
  599. if (err) {
  600. wmi_err("Failed to send set_param cmd");
  601. wmi_buf_free(buf);
  602. return QDF_STATUS_E_FAILURE;
  603. }
  604. return QDF_STATUS_SUCCESS;
  605. }
  606. static QDF_STATUS send_conf_hw_filter_cmd_tlv(wmi_unified_t wmi,
  607. struct pmo_hw_filter_params *req)
  608. {
  609. QDF_STATUS status;
  610. wmi_hw_data_filter_cmd_fixed_param *cmd;
  611. wmi_buf_t wmi_buf;
  612. if (!req) {
  613. wmi_err("req is null");
  614. return QDF_STATUS_E_INVAL;
  615. }
  616. wmi_buf = wmi_buf_alloc(wmi, sizeof(*cmd));
  617. if (!wmi_buf) {
  618. return QDF_STATUS_E_NOMEM;
  619. }
  620. cmd = (wmi_hw_data_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
  621. WMITLV_SET_HDR(&cmd->tlv_header,
  622. WMITLV_TAG_STRUC_wmi_hw_data_filter_cmd_fixed_param,
  623. WMITLV_GET_STRUCT_TLVLEN(wmi_hw_data_filter_cmd_fixed_param));
  624. cmd->vdev_id = req->vdev_id;
  625. cmd->enable = req->enable;
  626. /* Set all modes in case of disable */
  627. if (!cmd->enable)
  628. cmd->hw_filter_bitmap = ((uint32_t)~0U);
  629. else
  630. cmd->hw_filter_bitmap = req->mode_bitmap;
  631. wmi_debug("Send %s hw filter mode: 0x%X for vdev id %d",
  632. req->enable ? "enable" : "disable", req->mode_bitmap,
  633. req->vdev_id);
  634. wmi_mtrace(WMI_HW_DATA_FILTER_CMDID, cmd->vdev_id, 0);
  635. status = wmi_unified_cmd_send(wmi, wmi_buf, sizeof(*cmd),
  636. WMI_HW_DATA_FILTER_CMDID);
  637. if (QDF_IS_STATUS_ERROR(status)) {
  638. wmi_err("Failed to configure hw filter");
  639. wmi_buf_free(wmi_buf);
  640. }
  641. return status;
  642. }
  643. static void
  644. fill_fils_tlv_params(WMI_GTK_OFFLOAD_CMD_fixed_param *cmd,
  645. uint8_t vdev_id,
  646. struct pmo_gtk_req *params)
  647. {
  648. uint8_t *buf_ptr;
  649. wmi_gtk_offload_fils_tlv_param *ext_param;
  650. buf_ptr = (uint8_t *) cmd + sizeof(*cmd);
  651. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  652. sizeof(*ext_param));
  653. buf_ptr += WMI_TLV_HDR_SIZE;
  654. ext_param = (wmi_gtk_offload_fils_tlv_param *)buf_ptr;
  655. WMITLV_SET_HDR(&ext_param->tlv_header,
  656. WMITLV_TAG_STRUC_wmi_gtk_offload_extended_tlv_param,
  657. WMITLV_GET_STRUCT_TLVLEN(
  658. wmi_gtk_offload_fils_tlv_param));
  659. ext_param->vdev_id = vdev_id;
  660. ext_param->flags = cmd->flags;
  661. ext_param->kek_len = params->kek_len;
  662. qdf_mem_copy(ext_param->KEK, params->kek, params->kek_len);
  663. qdf_mem_copy(ext_param->KCK, params->kck,
  664. WMI_GTK_OFFLOAD_KCK_BYTES);
  665. qdf_mem_copy(ext_param->replay_counter, &params->replay_counter,
  666. GTK_REPLAY_COUNTER_BYTES);
  667. }
  668. #ifdef WLAN_FEATURE_IGMP_OFFLOAD
  669. /**
  670. * send_igmp_offload_cmd_tlv() - send IGMP offload command to fw
  671. * @wmi_handle: wmi handle
  672. * @params: IGMP offload parameters
  673. *
  674. * Return: QDF status
  675. */
  676. static
  677. QDF_STATUS send_igmp_offload_cmd_tlv(wmi_unified_t wmi_handle,
  678. struct pmo_igmp_offload_req *pmo_igmp_req)
  679. {
  680. wmi_buf_t buf;
  681. uint8_t *buf_ptr;
  682. int len;
  683. int i = 0;
  684. WMI_IPV4_ADDR *ipv4_list;
  685. wmi_igmp_offload_fixed_param *cmd;
  686. QDF_STATUS status = QDF_STATUS_SUCCESS;
  687. len = sizeof(wmi_igmp_offload_fixed_param) + WMI_TLV_HDR_SIZE +
  688. (pmo_igmp_req->num_grp_ip_address) * sizeof(WMI_IPV4_ADDR);
  689. /* alloc wmi buffer */
  690. buf = wmi_buf_alloc(wmi_handle, len);
  691. if (!buf) {
  692. status = QDF_STATUS_E_NOMEM;
  693. goto out;
  694. }
  695. buf_ptr = (uint8_t *)wmi_buf_data(buf);
  696. cmd = (wmi_igmp_offload_fixed_param *)wmi_buf_data(buf);
  697. WMITLV_SET_HDR(&cmd->tlv_header,
  698. WMITLV_TAG_STRUC_wmi_igmp_offload_fixed_param,
  699. WMITLV_GET_STRUCT_TLVLEN(wmi_igmp_offload_fixed_param));
  700. cmd->vdev_id = pmo_igmp_req->vdev_id;
  701. cmd->enable = pmo_igmp_req->enable;
  702. cmd->version_support_bitmask =
  703. pmo_igmp_req->version_support;
  704. buf_ptr += sizeof(*cmd);
  705. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
  706. sizeof(WMI_IPV4_ADDR) *
  707. pmo_igmp_req->num_grp_ip_address);
  708. ipv4_list = (WMI_IPV4_ADDR *)(buf_ptr + WMI_TLV_HDR_SIZE);
  709. while (i < pmo_igmp_req->num_grp_ip_address) {
  710. qdf_mem_copy((void *)((*(ipv4_list + i)).address),
  711. (void *)&(pmo_igmp_req->grp_ip_address[i]),
  712. WMI_IPV4_ADDR_LEN);
  713. wmi_debug("piv4[%d]:%x", i, *(uint32_t *)(ipv4_list + i));
  714. i++;
  715. }
  716. wmi_debug("VDEVID:%d, FLAG:x%x version support:%d",
  717. cmd->vdev_id, cmd->enable,
  718. cmd->version_support_bitmask);
  719. /* send the wmi command */
  720. wmi_mtrace(WMI_VDEV_IGMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
  721. if (wmi_unified_cmd_send(wmi_handle, buf, len,
  722. WMI_VDEV_IGMP_OFFLOAD_CMDID)) {
  723. wmi_err("Failed to send WMI_VDEV_IGMP_OFFLOAD_CMDID");
  724. wmi_buf_free(buf);
  725. status = QDF_STATUS_E_FAILURE;
  726. }
  727. out:
  728. return status;
  729. }
  730. #endif
  731. /**
  732. * send_gtk_offload_cmd_tlv() - send GTK offload command to fw
  733. * @wmi_handle: wmi handle
  734. * @vdev_id: vdev id
  735. * @params: GTK offload parameters
  736. *
  737. * Return: CDF status
  738. */
  739. static
  740. QDF_STATUS send_gtk_offload_cmd_tlv(wmi_unified_t wmi_handle, uint8_t vdev_id,
  741. struct pmo_gtk_req *params,
  742. bool enable_offload,
  743. uint32_t gtk_offload_opcode)
  744. {
  745. int len;
  746. wmi_buf_t buf;
  747. WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
  748. QDF_STATUS status = QDF_STATUS_SUCCESS;
  749. len = sizeof(*cmd);
  750. if (params->is_fils_connection)
  751. len += WMI_TLV_HDR_SIZE +
  752. sizeof(wmi_gtk_offload_fils_tlv_param);
  753. /* alloc wmi buffer */
  754. buf = wmi_buf_alloc(wmi_handle, len);
  755. if (!buf) {
  756. status = QDF_STATUS_E_NOMEM;
  757. goto out;
  758. }
  759. cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
  760. WMITLV_SET_HDR(&cmd->tlv_header,
  761. WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
  762. WMITLV_GET_STRUCT_TLVLEN
  763. (WMI_GTK_OFFLOAD_CMD_fixed_param));
  764. cmd->vdev_id = vdev_id;
  765. /* Request target to enable GTK offload */
  766. if (enable_offload == PMO_GTK_OFFLOAD_ENABLE) {
  767. cmd->flags = gtk_offload_opcode;
  768. /* Copy the keys and replay counter */
  769. qdf_mem_copy(cmd->KCK, params->kck, sizeof(cmd->KCK));
  770. qdf_mem_copy(cmd->KEK, params->kek, sizeof(cmd->KEK));
  771. qdf_mem_copy(cmd->replay_counter, &params->replay_counter,
  772. GTK_REPLAY_COUNTER_BYTES);
  773. } else {
  774. cmd->flags = gtk_offload_opcode;
  775. }
  776. if (params->is_fils_connection)
  777. fill_fils_tlv_params(cmd, vdev_id, params);
  778. wmi_debug("VDEVID: %d, GTK_FLAGS: x%x kek len %d",
  779. vdev_id, cmd->flags, params->kek_len);
  780. /* send the wmi command */
  781. wmi_mtrace(WMI_GTK_OFFLOAD_CMDID, cmd->vdev_id, 0);
  782. if (wmi_unified_cmd_send(wmi_handle, buf, len,
  783. WMI_GTK_OFFLOAD_CMDID)) {
  784. wmi_err("Failed to send WMI_GTK_OFFLOAD_CMDID");
  785. wmi_buf_free(buf);
  786. status = QDF_STATUS_E_FAILURE;
  787. }
  788. out:
  789. return status;
  790. }
  791. /**
  792. * send_process_gtk_offload_getinfo_cmd_tlv() - send GTK offload cmd to fw
  793. * @wmi_handle: wmi handle
  794. * @params: GTK offload params
  795. *
  796. * Return: CDF status
  797. */
  798. static QDF_STATUS send_process_gtk_offload_getinfo_cmd_tlv(
  799. wmi_unified_t wmi_handle,
  800. uint8_t vdev_id,
  801. uint64_t offload_req_opcode)
  802. {
  803. int len;
  804. wmi_buf_t buf;
  805. WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
  806. QDF_STATUS status = QDF_STATUS_SUCCESS;
  807. len = sizeof(*cmd);
  808. /* alloc wmi buffer */
  809. buf = wmi_buf_alloc(wmi_handle, len);
  810. if (!buf) {
  811. status = QDF_STATUS_E_NOMEM;
  812. goto out;
  813. }
  814. cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
  815. WMITLV_SET_HDR(&cmd->tlv_header,
  816. WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
  817. WMITLV_GET_STRUCT_TLVLEN
  818. (WMI_GTK_OFFLOAD_CMD_fixed_param));
  819. /* Request for GTK offload status */
  820. cmd->flags = offload_req_opcode;
  821. cmd->vdev_id = vdev_id;
  822. /* send the wmi command */
  823. wmi_mtrace(WMI_GTK_OFFLOAD_CMDID, cmd->vdev_id, 0);
  824. if (wmi_unified_cmd_send(wmi_handle, buf, len,
  825. WMI_GTK_OFFLOAD_CMDID)) {
  826. wmi_err("Failed to send WMI_GTK_OFFLOAD_CMDID for req info");
  827. wmi_buf_free(buf);
  828. status = QDF_STATUS_E_FAILURE;
  829. }
  830. out:
  831. return status;
  832. }
  833. /**
  834. * send_enable_enhance_multicast_offload_tlv() - send enhance multicast offload
  835. * @wmi_handle: wmi handle
  836. * @vdev_id: vdev id
  837. * @action: true for enable else false
  838. *
  839. * To enable enhance multicast offload to firmware
  840. * when target goes to wow mode.
  841. *
  842. * Return: QDF Status
  843. */
  844. static
  845. QDF_STATUS send_enable_enhance_multicast_offload_tlv(
  846. wmi_unified_t wmi_handle,
  847. uint8_t vdev_id, bool action)
  848. {
  849. QDF_STATUS status;
  850. wmi_buf_t buf;
  851. wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
  852. buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
  853. if (!buf) {
  854. return QDF_STATUS_E_NOMEM;
  855. }
  856. cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
  857. wmi_buf_data(buf);
  858. WMITLV_SET_HDR(&cmd->tlv_header,
  859. WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
  860. WMITLV_GET_STRUCT_TLVLEN(
  861. wmi_config_enhanced_mcast_filter_cmd_fixed_param));
  862. cmd->vdev_id = vdev_id;
  863. cmd->enable = ((action == 0) ? ENHANCED_MCAST_FILTER_DISABLED :
  864. ENHANCED_MCAST_FILTER_ENABLED);
  865. wmi_debug("config enhance multicast offload action %d for vdev %d",
  866. action, vdev_id);
  867. wmi_mtrace(WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID, cmd->vdev_id, 0);
  868. status = wmi_unified_cmd_send(wmi_handle, buf,
  869. sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
  870. if (status != QDF_STATUS_SUCCESS) {
  871. wmi_buf_free(buf);
  872. wmi_err("Failed to send ENHANCED_MCAST_FILTER_CMDID");
  873. }
  874. return status;
  875. }
  876. /**
  877. * extract_gtk_rsp_event_tlv() - extract gtk rsp params from event
  878. * @wmi_handle: wmi handle
  879. * @param evt_buf: pointer to event buffer
  880. * @param hdr: Pointer to hold header
  881. * @param bufp: Pointer to hold pointer to rx param buffer
  882. *
  883. * Return: QDF_STATUS_SUCCESS for success or error code
  884. */
  885. static QDF_STATUS extract_gtk_rsp_event_tlv(wmi_unified_t wmi_handle,
  886. void *evt_buf, struct pmo_gtk_rsp_params *gtk_rsp_param, uint32_t len)
  887. {
  888. WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *fixed_param;
  889. WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
  890. param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *)evt_buf;
  891. if (!param_buf) {
  892. wmi_err("gtk param_buf is NULL");
  893. return QDF_STATUS_E_INVAL;
  894. }
  895. if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
  896. wmi_err("Invalid length for GTK status");
  897. return QDF_STATUS_E_INVAL;
  898. }
  899. fixed_param = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *)
  900. param_buf->fixed_param;
  901. if (fixed_param->vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) {
  902. wmi_err_rl("Invalid vdev_id %u", fixed_param->vdev_id);
  903. return QDF_STATUS_E_INVAL;
  904. }
  905. gtk_rsp_param->vdev_id = fixed_param->vdev_id;
  906. gtk_rsp_param->status_flag = QDF_STATUS_SUCCESS;
  907. gtk_rsp_param->refresh_cnt = fixed_param->refresh_cnt;
  908. qdf_mem_copy(&gtk_rsp_param->replay_counter,
  909. &fixed_param->replay_counter,
  910. GTK_REPLAY_COUNTER_BYTES);
  911. return QDF_STATUS_SUCCESS;
  912. }
  913. #ifdef FEATURE_WLAN_RA_FILTERING
  914. /**
  915. * send_wow_sta_ra_filter_cmd_tlv() - set RA filter pattern in fw
  916. * @wmi_handle: wmi handle
  917. * @vdev_id: vdev id
  918. *
  919. * Return: CDF status
  920. */
  921. static QDF_STATUS send_wow_sta_ra_filter_cmd_tlv(wmi_unified_t wmi_handle,
  922. uint8_t vdev_id,
  923. uint8_t default_pattern,
  924. uint16_t rate_limit_interval)
  925. {
  926. WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
  927. wmi_buf_t buf;
  928. uint8_t *buf_ptr;
  929. int32_t len;
  930. int ret;
  931. len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
  932. WMI_TLV_HDR_SIZE +
  933. 0 * sizeof(WOW_BITMAP_PATTERN_T) +
  934. WMI_TLV_HDR_SIZE +
  935. 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
  936. WMI_TLV_HDR_SIZE +
  937. 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
  938. WMI_TLV_HDR_SIZE +
  939. 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
  940. WMI_TLV_HDR_SIZE +
  941. 0 * sizeof(uint32_t) + WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t);
  942. buf = wmi_buf_alloc(wmi_handle, len);
  943. if (!buf) {
  944. return QDF_STATUS_E_NOMEM;
  945. }
  946. cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
  947. buf_ptr = (uint8_t *) cmd;
  948. WMITLV_SET_HDR(&cmd->tlv_header,
  949. WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
  950. WMITLV_GET_STRUCT_TLVLEN
  951. (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
  952. cmd->vdev_id = vdev_id;
  953. cmd->pattern_id = default_pattern,
  954. cmd->pattern_type = WOW_IPV6_RA_PATTERN;
  955. buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
  956. /* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */
  957. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  958. buf_ptr += WMI_TLV_HDR_SIZE;
  959. /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
  960. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  961. buf_ptr += WMI_TLV_HDR_SIZE;
  962. /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
  963. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  964. buf_ptr += WMI_TLV_HDR_SIZE;
  965. /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
  966. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  967. buf_ptr += WMI_TLV_HDR_SIZE;
  968. /* Fill TLV for pattern_info_timeout but no data. */
  969. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
  970. buf_ptr += WMI_TLV_HDR_SIZE;
  971. /* Fill TLV for ra_ratelimit_interval. */
  972. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
  973. buf_ptr += WMI_TLV_HDR_SIZE;
  974. *((uint32_t *) buf_ptr) = rate_limit_interval;
  975. wmi_debug("send RA rate limit [%d] to fw vdev = %d",
  976. rate_limit_interval, vdev_id);
  977. wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
  978. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  979. WMI_WOW_ADD_WAKE_PATTERN_CMDID);
  980. if (ret) {
  981. wmi_err("Failed to send RA rate limit to fw");
  982. wmi_buf_free(buf);
  983. return QDF_STATUS_E_FAILURE;
  984. }
  985. return QDF_STATUS_SUCCESS;
  986. }
  987. void wmi_ra_filtering_attach_tlv(struct wmi_unified *wmi_handle)
  988. {
  989. struct wmi_ops *ops = wmi_handle->ops;
  990. ops->send_wow_sta_ra_filter_cmd = send_wow_sta_ra_filter_cmd_tlv;
  991. }
  992. #endif /* FEATURE_WLAN_RA_FILTERING */
  993. /**
  994. * send_action_frame_patterns_cmd_tlv() - send wmi cmd of action filter params
  995. * @wmi_handle: wmi handler
  996. * @action_params: pointer to action_params
  997. *
  998. * Return: 0 for success, otherwise appropriate error code
  999. */
  1000. static QDF_STATUS send_action_frame_patterns_cmd_tlv(wmi_unified_t wmi_handle,
  1001. struct pmo_action_wakeup_set_params *action_params)
  1002. {
  1003. WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param *cmd;
  1004. wmi_buf_t buf;
  1005. int i;
  1006. int32_t err;
  1007. uint32_t len = 0, *cmd_args;
  1008. uint8_t *buf_ptr;
  1009. len = (PMO_SUPPORTED_ACTION_CATE * sizeof(uint32_t))
  1010. + WMI_TLV_HDR_SIZE + sizeof(*cmd);
  1011. buf = wmi_buf_alloc(wmi_handle, len);
  1012. if (!buf) {
  1013. return QDF_STATUS_E_NOMEM;
  1014. }
  1015. cmd = (WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param *) wmi_buf_data(buf);
  1016. buf_ptr = (uint8_t *)cmd;
  1017. WMITLV_SET_HDR(&cmd->tlv_header,
  1018. WMITLV_TAG_STRUC_wmi_wow_set_action_wake_up_cmd_fixed_param,
  1019. WMITLV_GET_STRUCT_TLVLEN(
  1020. WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param));
  1021. cmd->vdev_id = action_params->vdev_id;
  1022. cmd->operation = action_params->operation;
  1023. for (i = 0; i < MAX_SUPPORTED_ACTION_CATEGORY_ELE_LIST; i++)
  1024. cmd->action_category_map[i] =
  1025. action_params->action_category_map[i];
  1026. buf_ptr += sizeof(WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param);
  1027. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
  1028. (PMO_SUPPORTED_ACTION_CATE * sizeof(uint32_t)));
  1029. buf_ptr += WMI_TLV_HDR_SIZE;
  1030. cmd_args = (uint32_t *) buf_ptr;
  1031. for (i = 0; i < PMO_SUPPORTED_ACTION_CATE; i++)
  1032. cmd_args[i] = action_params->action_per_category[i];
  1033. wmi_mtrace(WMI_WOW_SET_ACTION_WAKE_UP_CMDID, cmd->vdev_id, 0);
  1034. err = wmi_unified_cmd_send(wmi_handle, buf,
  1035. len, WMI_WOW_SET_ACTION_WAKE_UP_CMDID);
  1036. if (err) {
  1037. wmi_err("Failed to send ap_ps_egap cmd");
  1038. wmi_buf_free(buf);
  1039. return QDF_STATUS_E_FAILURE;
  1040. }
  1041. return QDF_STATUS_SUCCESS;
  1042. }
  1043. #ifdef FEATURE_WLAN_LPHB
  1044. /**
  1045. * send_lphb_config_hbenable_cmd_tlv() - enable command of LPHB configuration
  1046. * @wmi_handle: wmi handle
  1047. * @lphb_conf_req: configuration info
  1048. *
  1049. * Return: CDF status
  1050. */
  1051. static QDF_STATUS send_lphb_config_hbenable_cmd_tlv(wmi_unified_t wmi_handle,
  1052. wmi_hb_set_enable_cmd_fixed_param *params)
  1053. {
  1054. QDF_STATUS status;
  1055. wmi_buf_t buf = NULL;
  1056. uint8_t *buf_ptr;
  1057. wmi_hb_set_enable_cmd_fixed_param *hb_enable_fp;
  1058. int len = sizeof(wmi_hb_set_enable_cmd_fixed_param);
  1059. buf = wmi_buf_alloc(wmi_handle, len);
  1060. if (!buf) {
  1061. return QDF_STATUS_E_NOMEM;
  1062. }
  1063. buf_ptr = (uint8_t *) wmi_buf_data(buf);
  1064. hb_enable_fp = (wmi_hb_set_enable_cmd_fixed_param *) buf_ptr;
  1065. WMITLV_SET_HDR(&hb_enable_fp->tlv_header,
  1066. WMITLV_TAG_STRUC_wmi_hb_set_enable_cmd_fixed_param,
  1067. WMITLV_GET_STRUCT_TLVLEN
  1068. (wmi_hb_set_enable_cmd_fixed_param));
  1069. /* fill in values */
  1070. hb_enable_fp->vdev_id = params->session;
  1071. hb_enable_fp->enable = params->enable;
  1072. hb_enable_fp->item = params->item;
  1073. hb_enable_fp->session = params->session;
  1074. wmi_mtrace(WMI_HB_SET_ENABLE_CMDID, NO_SESSION, 0);
  1075. status = wmi_unified_cmd_send(wmi_handle, buf,
  1076. len, WMI_HB_SET_ENABLE_CMDID);
  1077. if (QDF_IS_STATUS_ERROR(status)) {
  1078. wmi_err("cmd_send WMI_HB_SET_ENABLE returned Error %d",
  1079. status);
  1080. wmi_buf_free(buf);
  1081. }
  1082. return status;
  1083. }
  1084. /**
  1085. * send_lphb_config_tcp_params_cmd_tlv() - set tcp params of LPHB configuration
  1086. * @wmi_handle: wmi handle
  1087. * @lphb_conf_req: lphb config request
  1088. *
  1089. * Return: CDF status
  1090. */
  1091. static QDF_STATUS send_lphb_config_tcp_params_cmd_tlv(wmi_unified_t wmi_handle,
  1092. wmi_hb_set_tcp_params_cmd_fixed_param *lphb_conf_req)
  1093. {
  1094. QDF_STATUS status;
  1095. wmi_buf_t buf = NULL;
  1096. uint8_t *buf_ptr;
  1097. wmi_hb_set_tcp_params_cmd_fixed_param *hb_tcp_params_fp;
  1098. int len = sizeof(wmi_hb_set_tcp_params_cmd_fixed_param);
  1099. buf = wmi_buf_alloc(wmi_handle, len);
  1100. if (!buf) {
  1101. return QDF_STATUS_E_NOMEM;
  1102. }
  1103. buf_ptr = (uint8_t *) wmi_buf_data(buf);
  1104. hb_tcp_params_fp = (wmi_hb_set_tcp_params_cmd_fixed_param *) buf_ptr;
  1105. WMITLV_SET_HDR(&hb_tcp_params_fp->tlv_header,
  1106. WMITLV_TAG_STRUC_wmi_hb_set_tcp_params_cmd_fixed_param,
  1107. WMITLV_GET_STRUCT_TLVLEN
  1108. (wmi_hb_set_tcp_params_cmd_fixed_param));
  1109. /* fill in values */
  1110. hb_tcp_params_fp->vdev_id = lphb_conf_req->vdev_id;
  1111. hb_tcp_params_fp->srv_ip = lphb_conf_req->srv_ip;
  1112. hb_tcp_params_fp->dev_ip = lphb_conf_req->dev_ip;
  1113. hb_tcp_params_fp->seq = lphb_conf_req->seq;
  1114. hb_tcp_params_fp->src_port = lphb_conf_req->src_port;
  1115. hb_tcp_params_fp->dst_port = lphb_conf_req->dst_port;
  1116. hb_tcp_params_fp->interval = lphb_conf_req->interval;
  1117. hb_tcp_params_fp->timeout = lphb_conf_req->timeout;
  1118. hb_tcp_params_fp->session = lphb_conf_req->session;
  1119. qdf_mem_copy(&hb_tcp_params_fp->gateway_mac,
  1120. &lphb_conf_req->gateway_mac,
  1121. sizeof(hb_tcp_params_fp->gateway_mac));
  1122. wmi_mtrace(WMI_HB_SET_TCP_PARAMS_CMDID, NO_SESSION, 0);
  1123. status = wmi_unified_cmd_send(wmi_handle, buf,
  1124. len, WMI_HB_SET_TCP_PARAMS_CMDID);
  1125. if (QDF_IS_STATUS_ERROR(status)) {
  1126. wmi_err("cmd_send WMI_HB_SET_TCP_PARAMS returned Error %d",
  1127. status);
  1128. wmi_buf_free(buf);
  1129. }
  1130. return status;
  1131. }
  1132. /**
  1133. * send_lphb_config_tcp_pkt_filter_cmd_tlv() - configure tcp packet filter cmd
  1134. * @wmi_handle: wmi handle
  1135. * @lphb_conf_req: lphb config request
  1136. *
  1137. * Return: CDF status
  1138. */
  1139. static
  1140. QDF_STATUS send_lphb_config_tcp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle,
  1141. wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *g_hb_tcp_filter_fp)
  1142. {
  1143. QDF_STATUS status;
  1144. wmi_buf_t buf = NULL;
  1145. uint8_t *buf_ptr;
  1146. wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *hb_tcp_filter_fp;
  1147. int len = sizeof(wmi_hb_set_tcp_pkt_filter_cmd_fixed_param);
  1148. buf = wmi_buf_alloc(wmi_handle, len);
  1149. if (!buf) {
  1150. return QDF_STATUS_E_NOMEM;
  1151. }
  1152. buf_ptr = (uint8_t *) wmi_buf_data(buf);
  1153. hb_tcp_filter_fp =
  1154. (wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *) buf_ptr;
  1155. WMITLV_SET_HDR(&hb_tcp_filter_fp->tlv_header,
  1156. WMITLV_TAG_STRUC_wmi_hb_set_tcp_pkt_filter_cmd_fixed_param,
  1157. WMITLV_GET_STRUCT_TLVLEN
  1158. (wmi_hb_set_tcp_pkt_filter_cmd_fixed_param));
  1159. /* fill in values */
  1160. hb_tcp_filter_fp->vdev_id = g_hb_tcp_filter_fp->vdev_id;
  1161. hb_tcp_filter_fp->length = g_hb_tcp_filter_fp->length;
  1162. hb_tcp_filter_fp->offset = g_hb_tcp_filter_fp->offset;
  1163. hb_tcp_filter_fp->session = g_hb_tcp_filter_fp->session;
  1164. memcpy((void *)&hb_tcp_filter_fp->filter,
  1165. (void *)&g_hb_tcp_filter_fp->filter,
  1166. WMI_WLAN_HB_MAX_FILTER_SIZE);
  1167. wmi_mtrace(WMI_HB_SET_TCP_PKT_FILTER_CMDID, NO_SESSION, 0);
  1168. status = wmi_unified_cmd_send(wmi_handle, buf,
  1169. len, WMI_HB_SET_TCP_PKT_FILTER_CMDID);
  1170. if (QDF_IS_STATUS_ERROR(status)) {
  1171. wmi_err("cmd_send WMI_HB_SET_TCP_PKT_FILTER returned Error %d",
  1172. status);
  1173. wmi_buf_free(buf);
  1174. }
  1175. return status;
  1176. }
  1177. /**
  1178. * send_lphb_config_udp_params_cmd_tlv() - configure udp param command of LPHB
  1179. * @wmi_handle: wmi handle
  1180. * @lphb_conf_req: lphb config request
  1181. *
  1182. * Return: CDF status
  1183. */
  1184. static QDF_STATUS send_lphb_config_udp_params_cmd_tlv(wmi_unified_t wmi_handle,
  1185. wmi_hb_set_udp_params_cmd_fixed_param *lphb_conf_req)
  1186. {
  1187. QDF_STATUS status;
  1188. wmi_buf_t buf = NULL;
  1189. uint8_t *buf_ptr;
  1190. wmi_hb_set_udp_params_cmd_fixed_param *hb_udp_params_fp;
  1191. int len = sizeof(wmi_hb_set_udp_params_cmd_fixed_param);
  1192. buf = wmi_buf_alloc(wmi_handle, len);
  1193. if (!buf) {
  1194. return QDF_STATUS_E_NOMEM;
  1195. }
  1196. buf_ptr = (uint8_t *) wmi_buf_data(buf);
  1197. hb_udp_params_fp = (wmi_hb_set_udp_params_cmd_fixed_param *) buf_ptr;
  1198. WMITLV_SET_HDR(&hb_udp_params_fp->tlv_header,
  1199. WMITLV_TAG_STRUC_wmi_hb_set_udp_params_cmd_fixed_param,
  1200. WMITLV_GET_STRUCT_TLVLEN
  1201. (wmi_hb_set_udp_params_cmd_fixed_param));
  1202. /* fill in values */
  1203. hb_udp_params_fp->vdev_id = lphb_conf_req->vdev_id;
  1204. hb_udp_params_fp->srv_ip = lphb_conf_req->srv_ip;
  1205. hb_udp_params_fp->dev_ip = lphb_conf_req->dev_ip;
  1206. hb_udp_params_fp->src_port = lphb_conf_req->src_port;
  1207. hb_udp_params_fp->dst_port = lphb_conf_req->dst_port;
  1208. hb_udp_params_fp->interval = lphb_conf_req->interval;
  1209. hb_udp_params_fp->timeout = lphb_conf_req->timeout;
  1210. hb_udp_params_fp->session = lphb_conf_req->session;
  1211. qdf_mem_copy(&hb_udp_params_fp->gateway_mac,
  1212. &lphb_conf_req->gateway_mac,
  1213. sizeof(lphb_conf_req->gateway_mac));
  1214. wmi_mtrace(WMI_HB_SET_UDP_PARAMS_CMDID, NO_SESSION, 0);
  1215. status = wmi_unified_cmd_send(wmi_handle, buf,
  1216. len, WMI_HB_SET_UDP_PARAMS_CMDID);
  1217. if (QDF_IS_STATUS_ERROR(status)) {
  1218. wmi_err("cmd_send WMI_HB_SET_UDP_PARAMS returned Error %d",
  1219. status);
  1220. wmi_buf_free(buf);
  1221. }
  1222. return status;
  1223. }
  1224. /**
  1225. * send_lphb_config_udp_pkt_filter_cmd_tlv() - configure udp pkt filter command
  1226. * @wmi_handle: wmi handle
  1227. * @lphb_conf_req: lphb config request
  1228. *
  1229. * Return: CDF status
  1230. */
  1231. static
  1232. QDF_STATUS send_lphb_config_udp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle,
  1233. wmi_hb_set_udp_pkt_filter_cmd_fixed_param *lphb_conf_req)
  1234. {
  1235. QDF_STATUS status;
  1236. wmi_buf_t buf = NULL;
  1237. uint8_t *buf_ptr;
  1238. wmi_hb_set_udp_pkt_filter_cmd_fixed_param *hb_udp_filter_fp;
  1239. int len = sizeof(wmi_hb_set_udp_pkt_filter_cmd_fixed_param);
  1240. buf = wmi_buf_alloc(wmi_handle, len);
  1241. if (!buf) {
  1242. return QDF_STATUS_E_NOMEM;
  1243. }
  1244. buf_ptr = (uint8_t *) wmi_buf_data(buf);
  1245. hb_udp_filter_fp =
  1246. (wmi_hb_set_udp_pkt_filter_cmd_fixed_param *) buf_ptr;
  1247. WMITLV_SET_HDR(&hb_udp_filter_fp->tlv_header,
  1248. WMITLV_TAG_STRUC_wmi_hb_set_udp_pkt_filter_cmd_fixed_param,
  1249. WMITLV_GET_STRUCT_TLVLEN
  1250. (wmi_hb_set_udp_pkt_filter_cmd_fixed_param));
  1251. /* fill in values */
  1252. hb_udp_filter_fp->vdev_id = lphb_conf_req->vdev_id;
  1253. hb_udp_filter_fp->length = lphb_conf_req->length;
  1254. hb_udp_filter_fp->offset = lphb_conf_req->offset;
  1255. hb_udp_filter_fp->session = lphb_conf_req->session;
  1256. memcpy((void *)&hb_udp_filter_fp->filter,
  1257. (void *)&lphb_conf_req->filter,
  1258. WMI_WLAN_HB_MAX_FILTER_SIZE);
  1259. wmi_mtrace(WMI_HB_SET_UDP_PKT_FILTER_CMDID, NO_SESSION, 0);
  1260. status = wmi_unified_cmd_send(wmi_handle, buf,
  1261. len, WMI_HB_SET_UDP_PKT_FILTER_CMDID);
  1262. if (QDF_IS_STATUS_ERROR(status)) {
  1263. wmi_err("cmd_send WMI_HB_SET_UDP_PKT_FILTER returned Error %d",
  1264. status);
  1265. wmi_buf_free(buf);
  1266. }
  1267. return status;
  1268. }
  1269. void wmi_lphb_attach_tlv(struct wmi_unified *wmi_handle)
  1270. {
  1271. struct wmi_ops *ops = wmi_handle->ops;
  1272. ops->send_lphb_config_hbenable_cmd =
  1273. send_lphb_config_hbenable_cmd_tlv;
  1274. ops->send_lphb_config_tcp_params_cmd =
  1275. send_lphb_config_tcp_params_cmd_tlv;
  1276. ops->send_lphb_config_tcp_pkt_filter_cmd =
  1277. send_lphb_config_tcp_pkt_filter_cmd_tlv;
  1278. ops->send_lphb_config_udp_params_cmd =
  1279. send_lphb_config_udp_params_cmd_tlv;
  1280. ops->send_lphb_config_udp_pkt_filter_cmd =
  1281. send_lphb_config_udp_pkt_filter_cmd_tlv;
  1282. }
  1283. #endif /* FEATURE_WLAN_LPHB */
  1284. #ifdef WLAN_FEATURE_PACKET_FILTERING
  1285. /**
  1286. * send_enable_disable_packet_filter_cmd_tlv() - enable/disable packet filter
  1287. * @wmi_handle: wmi handle
  1288. * @vdev_id: vdev id
  1289. * @enable: Flag to enable/disable packet filter
  1290. *
  1291. * Return: QDF_STATUS_SUCCESS for success or error code
  1292. */
  1293. static QDF_STATUS send_enable_disable_packet_filter_cmd_tlv(
  1294. wmi_unified_t wmi_handle, uint8_t vdev_id, bool enable)
  1295. {
  1296. int32_t len;
  1297. int ret = 0;
  1298. wmi_buf_t buf;
  1299. WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *cmd;
  1300. len = sizeof(WMI_PACKET_FILTER_ENABLE_CMD_fixed_param);
  1301. buf = wmi_buf_alloc(wmi_handle, len);
  1302. if (!buf) {
  1303. return QDF_STATUS_E_NOMEM;
  1304. }
  1305. cmd = (WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *) wmi_buf_data(buf);
  1306. WMITLV_SET_HDR(&cmd->tlv_header,
  1307. WMITLV_TAG_STRUC_wmi_packet_filter_enable_fixed_param,
  1308. WMITLV_GET_STRUCT_TLVLEN(
  1309. WMI_PACKET_FILTER_ENABLE_CMD_fixed_param));
  1310. cmd->vdev_id = vdev_id;
  1311. if (enable)
  1312. cmd->enable = PACKET_FILTER_SET_ENABLE;
  1313. else
  1314. cmd->enable = PACKET_FILTER_SET_DISABLE;
  1315. wmi_err("Packet filter enable %d for vdev_id %d", cmd->enable, vdev_id);
  1316. wmi_mtrace(WMI_PACKET_FILTER_ENABLE_CMDID, cmd->vdev_id, 0);
  1317. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  1318. WMI_PACKET_FILTER_ENABLE_CMDID);
  1319. if (ret) {
  1320. wmi_err("Failed to send packet filter wmi cmd to fw");
  1321. wmi_buf_free(buf);
  1322. }
  1323. return ret;
  1324. }
  1325. /**
  1326. * send_config_packet_filter_cmd_tlv() - configure packet filter in target
  1327. * @wmi_handle: wmi handle
  1328. * @vdev_id: vdev id
  1329. * @rcv_filter_param: Packet filter parameters
  1330. * @filter_id: Filter id
  1331. * @enable: Flag to add/delete packet filter configuration
  1332. *
  1333. * Return: QDF_STATUS_SUCCESS for success or error code
  1334. */
  1335. static QDF_STATUS send_config_packet_filter_cmd_tlv(wmi_unified_t wmi_handle,
  1336. uint8_t vdev_id, struct pmo_rcv_pkt_fltr_cfg *rcv_filter_param,
  1337. uint8_t filter_id, bool enable)
  1338. {
  1339. int len, i;
  1340. int err = 0;
  1341. wmi_buf_t buf;
  1342. WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *cmd;
  1343. /* allocate the memory */
  1344. len = sizeof(*cmd);
  1345. buf = wmi_buf_alloc(wmi_handle, len);
  1346. if (!buf) {
  1347. return QDF_STATUS_E_NOMEM;
  1348. }
  1349. cmd = (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *)wmi_buf_data(buf);
  1350. WMITLV_SET_HDR(&cmd->tlv_header,
  1351. WMITLV_TAG_STRUC_wmi_packet_filter_config_fixed_param,
  1352. WMITLV_GET_STRUCT_TLVLEN
  1353. (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param));
  1354. cmd->vdev_id = vdev_id;
  1355. cmd->filter_id = filter_id;
  1356. if (enable)
  1357. cmd->filter_action = PACKET_FILTER_SET_ACTIVE;
  1358. else
  1359. cmd->filter_action = PACKET_FILTER_SET_INACTIVE;
  1360. if (enable) {
  1361. cmd->num_params = QDF_MIN(
  1362. WMI_PACKET_FILTER_MAX_CMP_PER_PACKET_FILTER,
  1363. rcv_filter_param->num_params);
  1364. cmd->filter_type = rcv_filter_param->filter_type;
  1365. cmd->coalesce_time = rcv_filter_param->coalesce_time;
  1366. for (i = 0; i < cmd->num_params; i++) {
  1367. cmd->paramsData[i].proto_type =
  1368. rcv_filter_param->params_data[i].protocol_layer;
  1369. cmd->paramsData[i].cmp_type =
  1370. rcv_filter_param->params_data[i].compare_flag;
  1371. cmd->paramsData[i].data_length =
  1372. rcv_filter_param->params_data[i].data_length;
  1373. cmd->paramsData[i].data_offset =
  1374. rcv_filter_param->params_data[i].data_offset;
  1375. memcpy(&cmd->paramsData[i].compareData,
  1376. rcv_filter_param->params_data[i].compare_data,
  1377. sizeof(cmd->paramsData[i].compareData));
  1378. memcpy(&cmd->paramsData[i].dataMask,
  1379. rcv_filter_param->params_data[i].data_mask,
  1380. sizeof(cmd->paramsData[i].dataMask));
  1381. }
  1382. }
  1383. wmi_err("Packet filter action %d filter with id: %d, num_params=%d",
  1384. cmd->filter_action, cmd->filter_id, cmd->num_params);
  1385. /* send the command along with data */
  1386. wmi_mtrace(WMI_PACKET_FILTER_CONFIG_CMDID, cmd->vdev_id, 0);
  1387. err = wmi_unified_cmd_send(wmi_handle, buf, len,
  1388. WMI_PACKET_FILTER_CONFIG_CMDID);
  1389. if (err) {
  1390. wmi_err("Failed to send pkt_filter cmd");
  1391. wmi_buf_free(buf);
  1392. return QDF_STATUS_E_FAILURE;
  1393. }
  1394. return QDF_STATUS_SUCCESS;
  1395. }
  1396. void wmi_packet_filtering_attach_tlv(struct wmi_unified *wmi_handle)
  1397. {
  1398. struct wmi_ops *ops = wmi_handle->ops;
  1399. ops->send_enable_disable_packet_filter_cmd =
  1400. send_enable_disable_packet_filter_cmd_tlv;
  1401. ops->send_config_packet_filter_cmd =
  1402. send_config_packet_filter_cmd_tlv;
  1403. }
  1404. #endif /* WLAN_FEATURE_PACKET_FILTERING */
  1405. /**
  1406. * send_wow_delete_pattern_cmd_tlv() - delete wow pattern in target
  1407. * @wmi_handle: wmi handle
  1408. * @ptrn_id: pattern id
  1409. * @vdev_id: vdev id
  1410. *
  1411. * Return: CDF status
  1412. */
  1413. static QDF_STATUS send_wow_delete_pattern_cmd_tlv(wmi_unified_t wmi_handle,
  1414. uint8_t ptrn_id,
  1415. uint8_t vdev_id)
  1416. {
  1417. WMI_WOW_DEL_PATTERN_CMD_fixed_param *cmd;
  1418. wmi_buf_t buf;
  1419. int32_t len;
  1420. int ret;
  1421. len = sizeof(WMI_WOW_DEL_PATTERN_CMD_fixed_param);
  1422. buf = wmi_buf_alloc(wmi_handle, len);
  1423. if (!buf) {
  1424. return QDF_STATUS_E_NOMEM;
  1425. }
  1426. cmd = (WMI_WOW_DEL_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
  1427. WMITLV_SET_HDR(&cmd->tlv_header,
  1428. WMITLV_TAG_STRUC_WMI_WOW_DEL_PATTERN_CMD_fixed_param,
  1429. WMITLV_GET_STRUCT_TLVLEN(
  1430. WMI_WOW_DEL_PATTERN_CMD_fixed_param));
  1431. cmd->vdev_id = vdev_id;
  1432. cmd->pattern_id = ptrn_id;
  1433. cmd->pattern_type = WOW_BITMAP_PATTERN;
  1434. wmi_mtrace(WMI_WOW_DEL_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
  1435. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  1436. WMI_WOW_DEL_WAKE_PATTERN_CMDID);
  1437. if (ret) {
  1438. wmi_err("Failed to delete wow ptrn from fw");
  1439. wmi_buf_free(buf);
  1440. return QDF_STATUS_E_FAILURE;
  1441. }
  1442. return QDF_STATUS_SUCCESS;
  1443. }
  1444. #ifdef WMI_HOST_WAKEUP_OVER_QMI
  1445. static inline
  1446. QDF_STATUS wmi_unified_cmd_send_chk(struct wmi_unified *wmi_handle,
  1447. wmi_buf_t buf,
  1448. uint32_t buflen, uint32_t cmd_id)
  1449. {
  1450. wmi_debug("Send WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID over QMI");
  1451. return wmi_unified_cmd_send_over_qmi(wmi_handle, buf,
  1452. buflen, cmd_id);
  1453. }
  1454. #else
  1455. static inline
  1456. QDF_STATUS wmi_unified_cmd_send_chk(struct wmi_unified *wmi_handle,
  1457. wmi_buf_t buf,
  1458. uint32_t buflen, uint32_t cmd_id)
  1459. {
  1460. return wmi_unified_cmd_send(wmi_handle, buf,
  1461. buflen, cmd_id);
  1462. }
  1463. #endif
  1464. #define WMI_WAKEUP_TX_PEDNING_IND 1
  1465. /**
  1466. * send_host_wakeup_ind_to_fw_cmd_tlv() - send wakeup ind to fw
  1467. * @wmi_handle: wmi handle
  1468. * @tx_pending_ind: flag of TX has pending frames
  1469. *
  1470. * Sends host wakeup indication to FW. On receiving this indication,
  1471. * FW will come out of WOW.
  1472. *
  1473. * Return: CDF status
  1474. */
  1475. static QDF_STATUS send_host_wakeup_ind_to_fw_cmd_tlv(wmi_unified_t wmi_handle,
  1476. bool tx_pending_ind)
  1477. {
  1478. wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *cmd;
  1479. wmi_buf_t buf;
  1480. QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
  1481. int32_t len;
  1482. int ret;
  1483. len = sizeof(wmi_wow_hostwakeup_from_sleep_cmd_fixed_param);
  1484. buf = wmi_buf_alloc(wmi_handle, len);
  1485. if (!buf) {
  1486. return QDF_STATUS_E_NOMEM;
  1487. }
  1488. cmd = (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *)
  1489. wmi_buf_data(buf);
  1490. if (tx_pending_ind) {
  1491. wmi_debug("TX pending before WoW wake, indicate FW");
  1492. cmd->reserved0 |= WMI_WAKEUP_TX_PEDNING_IND;
  1493. }
  1494. WMITLV_SET_HDR(&cmd->tlv_header,
  1495. WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param,
  1496. WMITLV_GET_STRUCT_TLVLEN
  1497. (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param));
  1498. wmi_mtrace(WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, NO_SESSION, 0);
  1499. ret = wmi_unified_cmd_send_chk(wmi_handle, buf, len,
  1500. WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
  1501. if (ret) {
  1502. wmi_err("Failed to send host wakeup indication to fw");
  1503. wmi_buf_free(buf);
  1504. return QDF_STATUS_E_FAILURE;
  1505. }
  1506. return qdf_status;
  1507. }
  1508. /**
  1509. * send_wow_timer_pattern_cmd_tlv() - set timer pattern tlv, so that firmware
  1510. * will wake up host after specified time is elapsed
  1511. * @wmi_handle: wmi handle
  1512. * @vdev_id: vdev id
  1513. * @cookie: value to identify reason why host set up wake call.
  1514. * @time: time in ms
  1515. *
  1516. * Return: QDF status
  1517. */
  1518. static QDF_STATUS send_wow_timer_pattern_cmd_tlv(wmi_unified_t wmi_handle,
  1519. uint8_t vdev_id, uint32_t cookie, uint32_t time)
  1520. {
  1521. WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
  1522. wmi_buf_t buf;
  1523. uint8_t *buf_ptr;
  1524. int32_t len;
  1525. int ret;
  1526. len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
  1527. WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_BITMAP_PATTERN_T) +
  1528. WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
  1529. WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
  1530. WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
  1531. WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t) +
  1532. WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t);
  1533. buf = wmi_buf_alloc(wmi_handle, len);
  1534. if (!buf) {
  1535. return QDF_STATUS_E_NOMEM;
  1536. }
  1537. cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
  1538. buf_ptr = (uint8_t *) cmd;
  1539. WMITLV_SET_HDR(&cmd->tlv_header,
  1540. WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
  1541. WMITLV_GET_STRUCT_TLVLEN
  1542. (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
  1543. cmd->vdev_id = vdev_id;
  1544. cmd->pattern_id = cookie,
  1545. cmd->pattern_type = WOW_TIMER_PATTERN;
  1546. buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
  1547. /* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */
  1548. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  1549. buf_ptr += WMI_TLV_HDR_SIZE;
  1550. /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
  1551. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  1552. buf_ptr += WMI_TLV_HDR_SIZE;
  1553. /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
  1554. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  1555. buf_ptr += WMI_TLV_HDR_SIZE;
  1556. /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
  1557. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  1558. buf_ptr += WMI_TLV_HDR_SIZE;
  1559. /* Fill TLV for pattern_info_timeout, and time value */
  1560. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
  1561. buf_ptr += WMI_TLV_HDR_SIZE;
  1562. *((uint32_t *) buf_ptr) = time;
  1563. buf_ptr += sizeof(uint32_t);
  1564. /* Fill TLV for ra_ratelimit_interval. with dummy 0 value */
  1565. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
  1566. buf_ptr += WMI_TLV_HDR_SIZE;
  1567. *((uint32_t *) buf_ptr) = 0;
  1568. wmi_debug("send wake timer pattern with time[%d] to fw vdev = %d",
  1569. time, vdev_id);
  1570. wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
  1571. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  1572. WMI_WOW_ADD_WAKE_PATTERN_CMDID);
  1573. if (ret) {
  1574. wmi_err("Failed to send wake timer pattern to fw");
  1575. wmi_buf_free(buf);
  1576. return QDF_STATUS_E_FAILURE;
  1577. }
  1578. return QDF_STATUS_SUCCESS;
  1579. }
  1580. #ifdef WLAN_FEATURE_EXTWOW_SUPPORT
  1581. /**
  1582. * send_enable_ext_wow_cmd_tlv() - enable ext wow in fw
  1583. * @wmi_handle: wmi handle
  1584. * @params: ext wow params
  1585. *
  1586. * Return:0 for success or error code
  1587. */
  1588. static QDF_STATUS send_enable_ext_wow_cmd_tlv(wmi_unified_t wmi_handle,
  1589. struct ext_wow_params *params)
  1590. {
  1591. wmi_extwow_enable_cmd_fixed_param *cmd;
  1592. wmi_buf_t buf;
  1593. int32_t len;
  1594. int ret;
  1595. len = sizeof(wmi_extwow_enable_cmd_fixed_param);
  1596. buf = wmi_buf_alloc(wmi_handle, len);
  1597. if (!buf) {
  1598. return QDF_STATUS_E_NOMEM;
  1599. }
  1600. cmd = (wmi_extwow_enable_cmd_fixed_param *) wmi_buf_data(buf);
  1601. WMITLV_SET_HDR(&cmd->tlv_header,
  1602. WMITLV_TAG_STRUC_wmi_extwow_enable_cmd_fixed_param,
  1603. WMITLV_GET_STRUCT_TLVLEN
  1604. (wmi_extwow_enable_cmd_fixed_param));
  1605. cmd->vdev_id = params->vdev_id;
  1606. cmd->type = params->type;
  1607. cmd->wakeup_pin_num = params->wakeup_pin_num;
  1608. wmi_debug("vdev_id %d type %d Wakeup_pin_num %x",
  1609. cmd->vdev_id, cmd->type, cmd->wakeup_pin_num);
  1610. wmi_mtrace(WMI_EXTWOW_ENABLE_CMDID, cmd->vdev_id, 0);
  1611. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  1612. WMI_EXTWOW_ENABLE_CMDID);
  1613. if (ret) {
  1614. wmi_err("Failed to set EXTWOW Enable");
  1615. wmi_buf_free(buf);
  1616. return QDF_STATUS_E_FAILURE;
  1617. }
  1618. return QDF_STATUS_SUCCESS;
  1619. }
  1620. /**
  1621. * send_set_app_type2_params_in_fw_cmd_tlv() - set app type2 params in fw
  1622. * @wmi_handle: wmi handle
  1623. * @appType2Params: app type2 params
  1624. *
  1625. * Return: CDF status
  1626. */
  1627. static QDF_STATUS send_set_app_type2_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle,
  1628. struct app_type2_params *appType2Params)
  1629. {
  1630. wmi_extwow_set_app_type2_params_cmd_fixed_param *cmd;
  1631. wmi_buf_t buf;
  1632. int32_t len;
  1633. int ret;
  1634. len = sizeof(wmi_extwow_set_app_type2_params_cmd_fixed_param);
  1635. buf = wmi_buf_alloc(wmi_handle, len);
  1636. if (!buf) {
  1637. return QDF_STATUS_E_NOMEM;
  1638. }
  1639. cmd = (wmi_extwow_set_app_type2_params_cmd_fixed_param *)
  1640. wmi_buf_data(buf);
  1641. WMITLV_SET_HDR(&cmd->tlv_header,
  1642. WMITLV_TAG_STRUC_wmi_extwow_set_app_type2_params_cmd_fixed_param,
  1643. WMITLV_GET_STRUCT_TLVLEN
  1644. (wmi_extwow_set_app_type2_params_cmd_fixed_param));
  1645. cmd->vdev_id = appType2Params->vdev_id;
  1646. qdf_mem_copy(cmd->rc4_key, appType2Params->rc4_key, 16);
  1647. cmd->rc4_key_len = appType2Params->rc4_key_len;
  1648. cmd->ip_id = appType2Params->ip_id;
  1649. cmd->ip_device_ip = appType2Params->ip_device_ip;
  1650. cmd->ip_server_ip = appType2Params->ip_server_ip;
  1651. cmd->tcp_src_port = appType2Params->tcp_src_port;
  1652. cmd->tcp_dst_port = appType2Params->tcp_dst_port;
  1653. cmd->tcp_seq = appType2Params->tcp_seq;
  1654. cmd->tcp_ack_seq = appType2Params->tcp_ack_seq;
  1655. cmd->keepalive_init = appType2Params->keepalive_init;
  1656. cmd->keepalive_min = appType2Params->keepalive_min;
  1657. cmd->keepalive_max = appType2Params->keepalive_max;
  1658. cmd->keepalive_inc = appType2Params->keepalive_inc;
  1659. WMI_CHAR_ARRAY_TO_MAC_ADDR(appType2Params->gateway_mac.bytes,
  1660. &cmd->gateway_mac);
  1661. cmd->tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
  1662. cmd->tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
  1663. wmi_debug("vdev_id %d gateway_mac "QDF_MAC_ADDR_FMT" "
  1664. "rc4_key %.16s rc4_key_len %u "
  1665. "ip_id %x ip_device_ip %x ip_server_ip %x "
  1666. "tcp_src_port %u tcp_dst_port %u tcp_seq %u "
  1667. "tcp_ack_seq %u keepalive_init %u keepalive_min %u "
  1668. "keepalive_max %u keepalive_inc %u "
  1669. "tcp_tx_timeout_val %u tcp_rx_timeout_val %u",
  1670. cmd->vdev_id,
  1671. QDF_MAC_ADDR_REF(appType2Params->gateway_mac.bytes),
  1672. cmd->rc4_key, cmd->rc4_key_len,
  1673. cmd->ip_id, cmd->ip_device_ip, cmd->ip_server_ip,
  1674. cmd->tcp_src_port, cmd->tcp_dst_port, cmd->tcp_seq,
  1675. cmd->tcp_ack_seq, cmd->keepalive_init, cmd->keepalive_min,
  1676. cmd->keepalive_max, cmd->keepalive_inc,
  1677. cmd->tcp_tx_timeout_val, cmd->tcp_rx_timeout_val);
  1678. wmi_mtrace(WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID, cmd->vdev_id, 0);
  1679. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  1680. WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID);
  1681. if (ret) {
  1682. wmi_err("Failed to set APP TYPE2 PARAMS");
  1683. wmi_buf_free(buf);
  1684. return QDF_STATUS_E_FAILURE;
  1685. }
  1686. return QDF_STATUS_SUCCESS;
  1687. }
  1688. /**
  1689. * send_app_type1_params_in_fw_cmd_tlv() - set app type1 params in fw
  1690. * @wmi_handle: wmi handle
  1691. * @app_type1_params: app type1 params
  1692. *
  1693. * Return: CDF status
  1694. */
  1695. static QDF_STATUS send_app_type1_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle,
  1696. struct app_type1_params *app_type1_params)
  1697. {
  1698. wmi_extwow_set_app_type1_params_cmd_fixed_param *cmd;
  1699. wmi_buf_t buf;
  1700. int32_t len;
  1701. int ret;
  1702. len = sizeof(wmi_extwow_set_app_type1_params_cmd_fixed_param);
  1703. buf = wmi_buf_alloc(wmi_handle, len);
  1704. if (!buf) {
  1705. return QDF_STATUS_E_NOMEM;
  1706. }
  1707. cmd = (wmi_extwow_set_app_type1_params_cmd_fixed_param *)
  1708. wmi_buf_data(buf);
  1709. WMITLV_SET_HDR(&cmd->tlv_header,
  1710. WMITLV_TAG_STRUC_wmi_extwow_set_app_type1_params_cmd_fixed_param,
  1711. WMITLV_GET_STRUCT_TLVLEN
  1712. (wmi_extwow_set_app_type1_params_cmd_fixed_param));
  1713. cmd->vdev_id = app_type1_params->vdev_id;
  1714. WMI_CHAR_ARRAY_TO_MAC_ADDR(app_type1_params->wakee_mac_addr.bytes,
  1715. &cmd->wakee_mac);
  1716. qdf_mem_copy(cmd->ident, app_type1_params->identification_id, 8);
  1717. cmd->ident_len = app_type1_params->id_length;
  1718. qdf_mem_copy(cmd->passwd, app_type1_params->password, 16);
  1719. cmd->passwd_len = app_type1_params->pass_length;
  1720. wmi_debug("vdev_id %d wakee_mac_addr "QDF_MAC_ADDR_FMT" "
  1721. "identification_id %.8s id_length %u "
  1722. "password %.16s pass_length %u",
  1723. cmd->vdev_id,
  1724. QDF_MAC_ADDR_REF(app_type1_params->wakee_mac_addr.bytes),
  1725. cmd->ident, cmd->ident_len, cmd->passwd, cmd->passwd_len);
  1726. wmi_mtrace(WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID, cmd->vdev_id, 0);
  1727. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  1728. WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID);
  1729. if (ret) {
  1730. wmi_err("Failed to set APP TYPE1 PARAMS");
  1731. wmi_buf_free(buf);
  1732. return QDF_STATUS_E_FAILURE;
  1733. }
  1734. return QDF_STATUS_SUCCESS;
  1735. }
  1736. void wmi_extwow_attach_tlv(struct wmi_unified *wmi_handle)
  1737. {
  1738. struct wmi_ops *ops = wmi_handle->ops;
  1739. ops->send_enable_ext_wow_cmd = send_enable_ext_wow_cmd_tlv;
  1740. ops->send_set_app_type2_params_in_fw_cmd =
  1741. send_set_app_type2_params_in_fw_cmd_tlv;
  1742. ops->send_app_type1_params_in_fw_cmd =
  1743. send_app_type1_params_in_fw_cmd_tlv;
  1744. }
  1745. #endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
  1746. #ifdef WLAN_FEATURE_ICMP_OFFLOAD
  1747. /**
  1748. * send_icmp_ipv4_config_cmd_tlv() - send ICMP IPV4 offload command to fw
  1749. * @wmi_handle: wmi handle
  1750. * @pmo_icmp_req: ICMP offload parameters
  1751. *
  1752. * Return: QDF status
  1753. */
  1754. static QDF_STATUS
  1755. send_icmp_ipv4_config_cmd_tlv(wmi_unified_t wmi_handle,
  1756. struct pmo_icmp_offload *pmo_icmp_req)
  1757. {
  1758. wmi_buf_t buf;
  1759. wmi_icmp_offload_fixed_param *cmd;
  1760. uint16_t len = sizeof(*cmd);
  1761. QDF_STATUS status;
  1762. buf = wmi_buf_alloc(wmi_handle, len);
  1763. if (!buf) {
  1764. wmi_err_rl("Failed to allocate wmi buffer");
  1765. status = QDF_STATUS_E_NOMEM;
  1766. return status;
  1767. }
  1768. cmd = (wmi_icmp_offload_fixed_param *)wmi_buf_data(buf);
  1769. WMITLV_SET_HDR(&cmd->tlv_header,
  1770. WMITLV_TAG_STRUC_wmi_icmp_offload_fixed_param,
  1771. WMITLV_GET_STRUCT_TLVLEN(wmi_icmp_offload_fixed_param));
  1772. cmd->vdev_id = pmo_icmp_req->vdev_id;
  1773. cmd->enable = pmo_icmp_req->enable;
  1774. cmd->valid_bitmask = 0;
  1775. WMI_SET_ICMP_OFFLOAD_IPV4_ENABLED_BIT(cmd->valid_bitmask);
  1776. qdf_mem_copy(&cmd->ipv4_addr, pmo_icmp_req->ipv4_addr,
  1777. QDF_IPV4_ADDR_SIZE);
  1778. wmi_debug("ipv4:%pI4", &cmd->ipv4_addr);
  1779. wmi_mtrace(WMI_VDEV_ICMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
  1780. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  1781. WMI_VDEV_ICMP_OFFLOAD_CMDID);
  1782. if (QDF_IS_STATUS_ERROR(status))
  1783. wmi_buf_free(buf);
  1784. return status;
  1785. }
  1786. /**
  1787. * send_icmp_ipv6_config_cmd_tlv() - send ICMP IPV6 offload command to fw
  1788. * @wmi_handle: wmi handle
  1789. * @pmo_icmp_req: ICMP offload parameters
  1790. *
  1791. * Return: QDF status
  1792. */
  1793. static QDF_STATUS
  1794. send_icmp_ipv6_config_cmd_tlv(wmi_unified_t wmi_handle,
  1795. struct pmo_icmp_offload *pmo_icmp_req)
  1796. {
  1797. wmi_buf_t buf;
  1798. uint8_t *buf_ptr;
  1799. uint16_t len;
  1800. int i;
  1801. WMI_IPV6_ADDR *ipv6_list;
  1802. wmi_icmp_offload_fixed_param *cmd;
  1803. QDF_STATUS status;
  1804. len = sizeof(wmi_icmp_offload_fixed_param) + WMI_TLV_HDR_SIZE +
  1805. (pmo_icmp_req->ipv6_count) * sizeof(WMI_IPV6_ADDR);
  1806. buf = wmi_buf_alloc(wmi_handle, len);
  1807. if (!buf) {
  1808. wmi_err_rl("Failed to allocate wmi buffer");
  1809. status = QDF_STATUS_E_NOMEM;
  1810. return status;
  1811. }
  1812. buf_ptr = (uint8_t *)wmi_buf_data(buf);
  1813. cmd = (wmi_icmp_offload_fixed_param *)wmi_buf_data(buf);
  1814. WMITLV_SET_HDR(&cmd->tlv_header,
  1815. WMITLV_TAG_STRUC_wmi_icmp_offload_fixed_param,
  1816. WMITLV_GET_STRUCT_TLVLEN(wmi_icmp_offload_fixed_param));
  1817. cmd->vdev_id = pmo_icmp_req->vdev_id;
  1818. cmd->enable = pmo_icmp_req->enable;
  1819. cmd->valid_bitmask = 0;
  1820. WMI_SET_ICMP_OFFLOAD_IPV6_ENABLED_BIT(cmd->valid_bitmask);
  1821. buf_ptr += sizeof(*cmd);
  1822. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
  1823. sizeof(WMI_IPV6_ADDR) * pmo_icmp_req->ipv6_count);
  1824. ipv6_list = (WMI_IPV6_ADDR *)(buf_ptr + WMI_TLV_HDR_SIZE);
  1825. for (i = 0; i < pmo_icmp_req->ipv6_count; i++) {
  1826. qdf_mem_copy(((*(ipv6_list + i)).address),
  1827. &pmo_icmp_req->ipv6_addr[i],
  1828. sizeof(WMI_IPV6_ADDR));
  1829. wmi_debug("ipv6_list[%d]:%pI6", i, (ipv6_list + i));
  1830. }
  1831. /* send the wmi command */
  1832. wmi_mtrace(WMI_VDEV_ICMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
  1833. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  1834. WMI_VDEV_ICMP_OFFLOAD_CMDID);
  1835. if (QDF_IS_STATUS_ERROR(status))
  1836. wmi_buf_free(buf);
  1837. return status;
  1838. }
  1839. /**
  1840. * send_icmp_offload_config_cmd_tlv() - send ICMP offload command to fw
  1841. * @wmi_handle: wmi handle
  1842. * @pmo_icmp_req: ICMP offload parameters
  1843. *
  1844. * Return: QDF status
  1845. */
  1846. static QDF_STATUS
  1847. send_icmp_offload_config_cmd_tlv(wmi_unified_t wmi_handle,
  1848. struct pmo_icmp_offload *pmo_icmp_req)
  1849. {
  1850. QDF_STATUS status;
  1851. switch (pmo_icmp_req->trigger) {
  1852. case pmo_ipv4_change_notify:
  1853. status = send_icmp_ipv4_config_cmd_tlv(wmi_handle,
  1854. pmo_icmp_req);
  1855. break;
  1856. case pmo_ipv6_change_notify:
  1857. status = send_icmp_ipv6_config_cmd_tlv(wmi_handle,
  1858. pmo_icmp_req);
  1859. break;
  1860. default:
  1861. QDF_DEBUG_PANIC("Invalid ICMP trigger %d",
  1862. pmo_icmp_req->trigger);
  1863. status = QDF_STATUS_E_FAILURE;
  1864. }
  1865. return status;
  1866. }
  1867. static void wmi_icmp_offload_config_tlv(struct wmi_unified *wmi_handle)
  1868. {
  1869. struct wmi_ops *ops = wmi_handle->ops;
  1870. ops->send_icmp_offload_config_cmd = send_icmp_offload_config_cmd_tlv;
  1871. }
  1872. #else
  1873. static inline void wmi_icmp_offload_config_tlv(struct wmi_unified *wmi_handle)
  1874. {}
  1875. #endif /* WLAN_FEATURE_ICMP_OFFLOAD */
  1876. void wmi_pmo_attach_tlv(wmi_unified_t wmi_handle)
  1877. {
  1878. struct wmi_ops *ops = wmi_handle->ops;
  1879. ops->send_add_wow_wakeup_event_cmd =
  1880. send_add_wow_wakeup_event_cmd_tlv;
  1881. ops->send_wow_patterns_to_fw_cmd = send_wow_patterns_to_fw_cmd_tlv;
  1882. ops->send_enable_arp_ns_offload_cmd =
  1883. send_enable_arp_ns_offload_cmd_tlv;
  1884. ops->send_add_clear_mcbc_filter_cmd =
  1885. send_add_clear_mcbc_filter_cmd_tlv;
  1886. ops->send_multiple_add_clear_mcbc_filter_cmd =
  1887. send_multiple_add_clear_mcbc_filter_cmd_tlv;
  1888. ops->send_conf_hw_filter_cmd = send_conf_hw_filter_cmd_tlv;
  1889. ops->send_gtk_offload_cmd = send_gtk_offload_cmd_tlv;
  1890. #ifdef WLAN_FEATURE_IGMP_OFFLOAD
  1891. ops->send_igmp_offload_cmd = send_igmp_offload_cmd_tlv;
  1892. #endif
  1893. ops->send_process_gtk_offload_getinfo_cmd =
  1894. send_process_gtk_offload_getinfo_cmd_tlv;
  1895. ops->send_enable_enhance_multicast_offload_cmd =
  1896. send_enable_enhance_multicast_offload_tlv;
  1897. ops->extract_gtk_rsp_event = extract_gtk_rsp_event_tlv;
  1898. ops->send_action_frame_patterns_cmd =
  1899. send_action_frame_patterns_cmd_tlv;
  1900. ops->send_wow_delete_pattern_cmd = send_wow_delete_pattern_cmd_tlv;
  1901. ops->send_host_wakeup_ind_to_fw_cmd =
  1902. send_host_wakeup_ind_to_fw_cmd_tlv;
  1903. ops->send_wow_timer_pattern_cmd = send_wow_timer_pattern_cmd_tlv;
  1904. wmi_d0wow_attach_tlv(wmi_handle);
  1905. wmi_ra_filtering_attach_tlv(wmi_handle);
  1906. wmi_lphb_attach_tlv(wmi_handle);
  1907. wmi_packet_filtering_attach_tlv(wmi_handle);
  1908. wmi_extwow_attach_tlv(wmi_handle);
  1909. wmi_icmp_offload_config_tlv(wmi_handle);
  1910. }