1 /******************************************************************************
2 *
3 * Copyright(c) 2019 - 2020 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #include "phl_headers.h"
16
17 static const char *
_phl_pkt_ofld_get_txt(u8 type)18 _phl_pkt_ofld_get_txt(u8 type)
19 {
20 switch (type)
21 {
22 case PKT_TYPE_PROBE_RSP:
23 return "PROBE RSP";
24 case PKT_TYPE_PS_POLL:
25 return "PS POLL";
26 case PKT_TYPE_NULL_DATA:
27 return "NULL DATA";
28 case PKT_TYPE_QOS_NULL:
29 return "QOS NULL";
30 case PKT_TYPE_CTS2SELF:
31 return "CTS2SELF";
32 case PKT_TYPE_ARP_RSP:
33 return "ARP Response";
34 case PKT_TYPE_NDP:
35 return "Neighbor Discovery Protocol";
36 case PKT_TYPE_EAPOL_KEY:
37 return "EAPOL-KEY";
38 case PKT_TYPE_SA_QUERY:
39 return "SA QUERY";
40 case PKT_TYPE_PROBE_REQ:
41 return "PROBE REQ";
42 default:
43 return "Unknown?!";
44 }
45 }
46
47 static u8
_phl_pkt_ofld_is_pkt_ofld(struct pkt_ofld_info * pkt_info)48 _phl_pkt_ofld_is_pkt_ofld(struct pkt_ofld_info *pkt_info)
49 {
50 if(pkt_info->id != NOT_USED)
51 return true;
52 else
53 return false;
54 }
55
56 static void
_phl_pkt_ofld_dbg_dump_pkt_info(struct pkt_ofld_obj * ofld_obj,struct pkt_ofld_info * pkt_info)57 _phl_pkt_ofld_dbg_dump_pkt_info(struct pkt_ofld_obj *ofld_obj,
58 struct pkt_ofld_info *pkt_info)
59 {
60 struct pkt_ofld_req *pos = NULL;
61
62 phl_list_for_loop(pos, struct pkt_ofld_req, &pkt_info->req_q, list) {
63
64 PHL_TRACE(COMP_PHL_PKTOFLD, _PHL_INFO_,
65 "[PKT] ## token %d, req name unknown\n",
66 pos->token);
67 }
68
69 if(_phl_pkt_ofld_is_pkt_ofld(pkt_info)) {
70 HAL_PKT_OFLD_READ(ofld_obj, &pkt_info->id);
71 }
72
73 }
74
75 static void
_phl_pkt_ofld_dbg_dump(struct pkt_ofld_obj * ofld_obj)76 _phl_pkt_ofld_dbg_dump(struct pkt_ofld_obj *ofld_obj)
77 {
78 u8 idx;
79 struct pkt_ofld_entry *pos = NULL;
80
81 phl_list_for_loop(pos, struct pkt_ofld_entry, &ofld_obj->entry_q, list) {
82
83 PHL_TRACE(COMP_PHL_PKTOFLD, _PHL_INFO_,
84 "[PKT] => mac id = %d\n", pos->macid);
85
86 for(idx = 0; idx < PKT_OFLD_TYPE_MAX; idx++) {
87
88 PHL_TRACE(COMP_PHL_PKTOFLD, _PHL_INFO_,
89 "[PKT] type %-10s:id = %d, req cnt = %d.\n",
90 _phl_pkt_ofld_get_txt(idx),
91 pos->pkt_info[idx].id,
92 pos->pkt_info[idx].req_cnt);
93
94 _phl_pkt_ofld_dbg_dump_pkt_info(ofld_obj,
95 &pos->pkt_info[idx]);
96
97 }
98 }
99 }
100
101 static struct pkt_ofld_req *
_phl_pkt_ofld_gen_req(struct pkt_ofld_obj * ofld_obj,const char * req_name)102 _phl_pkt_ofld_gen_req(struct pkt_ofld_obj *ofld_obj, const char *req_name)
103 {
104 struct pkt_ofld_req *req;
105 void *d = phl_to_drvpriv(ofld_obj->phl_info);
106
107 req = _os_mem_alloc(d, sizeof(struct pkt_ofld_req));
108 if (req == NULL) {
109 PHL_ERR("[PKT] %s: alloc memory req failed.\n", __func__);
110 return NULL;
111 }
112
113 INIT_LIST_HEAD(&req->list);
114 req->token = ofld_obj->cur_seq++;
115 req->req_name_len = _os_strlen((u8 *)req_name) +1;
116
117 req->req_name = _os_mem_alloc(d, sizeof(u8)*req->req_name_len);
118 if (req->req_name == NULL) {
119 PHL_ERR("[PKT] %s: alloc memory req name failed.\n", __func__);
120 _os_mem_free(d, req, sizeof(struct pkt_ofld_req));
121 return NULL;
122 }
123 _os_mem_set(d, req->req_name, 0, req->req_name_len);
124 _os_mem_cpy(d, req->req_name, (char *)req_name, req->req_name_len);
125
126 PHL_TRACE(COMP_PHL_PKTOFLD, _PHL_INFO_,
127 "[PKT] New request %p, token = %d, name = unknown.\n",
128 req, req->token);
129
130 return req;
131 }
132
133 static void
_phl_pkt_ofld_del_req(struct pkt_ofld_obj * ofld_obj,struct pkt_ofld_info * pkt_info,struct pkt_ofld_req * req)134 _phl_pkt_ofld_del_req(struct pkt_ofld_obj *ofld_obj, struct pkt_ofld_info *pkt_info,
135 struct pkt_ofld_req *req)
136 {
137 void *d = phl_to_drvpriv(ofld_obj->phl_info);
138
139 list_del(&req->list);
140 pkt_info->req_cnt--;
141 _os_mem_free(d, req->req_name, sizeof(u8)*req->req_name_len);
142 _os_mem_free(d, req, sizeof(*req));
143 }
144
145 static struct pkt_ofld_req *
_phl_pkt_ofld_get_req(struct pkt_ofld_obj * ofld_obj,struct pkt_ofld_info * pkt_info,u32 token)146 _phl_pkt_ofld_get_req(struct pkt_ofld_obj *ofld_obj, struct pkt_ofld_info *pkt_info,
147 u32 token)
148 {
149 struct pkt_ofld_req *pos = NULL;
150 u8 find = false;
151
152 phl_list_for_loop(pos, struct pkt_ofld_req,
153 &pkt_info->req_q, list) {
154 if (pos->token == token) {
155 find = true;
156 break;
157 }
158 }
159
160 if (find) {
161 return pos;
162 } else {
163 return NULL;
164 }
165 }
166
167 static void
_phl_pkt_ofld_add_req(struct pkt_ofld_obj * ofld_obj,struct pkt_ofld_info * pkt_info,struct pkt_ofld_req * req)168 _phl_pkt_ofld_add_req(struct pkt_ofld_obj *ofld_obj, struct pkt_ofld_info *pkt_info,
169 struct pkt_ofld_req *req)
170 {
171 list_add(&req->list, &pkt_info->req_q);
172 pkt_info->req_cnt++;
173 }
174
175
176 static enum rtw_phl_status
_phl_pkt_ofld_construct_null_data(struct pkt_ofld_obj * ofld_obj,u8 ** pkt_buf,u16 * len,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_null_info * null_info)177 _phl_pkt_ofld_construct_null_data(struct pkt_ofld_obj *ofld_obj, u8 **pkt_buf,
178 u16 *len, struct rtw_phl_stainfo_t *phl_sta,
179 struct rtw_pkt_ofld_null_info *null_info)
180 {
181 void *d = phl_to_drvpriv(ofld_obj->phl_info);
182 struct rtw_wifi_role_t *wrole = phl_sta->wrole;
183 *len = NULL_PACKET_LEN;
184
185 *pkt_buf = _os_mem_alloc(d, NULL_PACKET_LEN);
186 if (*pkt_buf == NULL) {
187 return RTW_PHL_STATUS_RESOURCE;
188 }
189
190 _os_mem_set(d, *pkt_buf, 0, NULL_PACKET_LEN);
191
192 SET_80211_PKT_HDR_FRAME_CONTROL(*pkt_buf, 0);
193 SET_80211_PKT_HDR_TYPE_AND_SUBTYPE(*pkt_buf, TYPE_NULL_FRAME);
194 SET_80211_PKT_HDR_PWR_MGNT(*pkt_buf, 0);
195
196 switch(wrole->type)
197 {
198 case PHL_RTYPE_STATION:
199 SET_80211_PKT_HDR_TO_DS(*pkt_buf, 1);
200 SET_80211_PKT_HDR_ADDRESS1(d, *pkt_buf, null_info->a1);
201 SET_80211_PKT_HDR_ADDRESS2(d, *pkt_buf, null_info->a2);
202 SET_80211_PKT_HDR_ADDRESS3(d, *pkt_buf, null_info->a3);
203 break;
204 case PHL_RTYPE_AP:
205 case PHL_RTYPE_ADHOC:
206 default:
207 break;
208 }
209 SET_80211_PKT_HDR_DURATION(*pkt_buf, 0);
210 SET_80211_PKT_HDR_FRAGMENT_SEQUENCE(*pkt_buf, 0);
211
212 return RTW_PHL_STATUS_SUCCESS;
213 }
214
215 static enum rtw_phl_status
_phl_pkt_ofld_construct_na(struct pkt_ofld_obj * pkt,u8 ** pkt_buf,u16 * len,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_na_info * na_info)216 _phl_pkt_ofld_construct_na(struct pkt_ofld_obj *pkt, u8 **pkt_buf,
217 u16 *len, struct rtw_phl_stainfo_t *phl_sta,
218 struct rtw_pkt_ofld_na_info *na_info)
219 {
220 void *d = phl_to_drvpriv(pkt->phl_info);
221 u8* p_na_body;
222 u8 NSLLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x86, 0xDD};
223 u8 IPv6HeadInfo[4] = {0x60, 0x00, 0x00, 0x00};
224 u8 IPv6HeadContx[4] = {0x00, 0x20, 0x3a, 0xff};
225 u8 ICMPv6Head[8] = {0x88, 0x00, 0x00, 0x00 , 0x60 , 0x00 , 0x00 , 0x00};
226 u8 sec_hdr = na_info->sec_hdr;
227
228 /* size estimation */
229 /* sMacHdrLng + LLC header(8) + na element(28) */
230 *len = MAC_HDR_LEN + sec_hdr + 8 + 72;
231
232 *pkt_buf = _os_mem_alloc(d, *len);
233
234 if (*pkt_buf == NULL)
235 return RTW_PHL_STATUS_RESOURCE;
236
237
238 _os_mem_set(d, *pkt_buf, 0, *len);
239
240 SET_80211_PKT_HDR_FRAME_CONTROL(*pkt_buf, 0);
241 SET_80211_PKT_HDR_TYPE_AND_SUBTYPE(*pkt_buf, TYPE_DATA_FRAME);
242 SET_80211_PKT_HDR_TO_DS(*pkt_buf, 1);
243
244 if (sec_hdr != 0)
245 SET_80211_PKT_HDR_PROTECT(*pkt_buf, 1);
246
247 SET_80211_PKT_HDR_ADDRESS1(d, *pkt_buf, na_info->a1);
248 SET_80211_PKT_HDR_ADDRESS2(d, *pkt_buf, na_info->a2);
249 SET_80211_PKT_HDR_ADDRESS3(d, *pkt_buf, na_info->a3);
250
251 SET_80211_PKT_HDR_DURATION(*pkt_buf, 0);
252 SET_80211_PKT_HDR_FRAGMENT_SEQUENCE(*pkt_buf, 0);
253
254 /* Frame Body */
255 p_na_body = (u8*)(*pkt_buf + MAC_HDR_LEN);
256
257 /* offset for security iv */
258 p_na_body += sec_hdr;
259
260 /* LLC heade*/
261 _os_mem_cpy(d, p_na_body, NSLLCHeader, 8);
262
263
264 /* IPv6 Heard */
265
266
267 /* 1 . Information (4 bytes): 0x60 0x00 0x00 0x00 */
268 _os_mem_cpy(d, p_na_body+8, IPv6HeadInfo, 4);
269
270 /* 2 . playload : 0x00 0x20 , NextProt : 0x3a (ICMPv6) HopLim : 0xff */
271 _os_mem_cpy(d, p_na_body+12, IPv6HeadContx, 4);
272
273 /* 3 . SA : 16 bytes , DA : 16 bytes ( Fw will fill) */
274 _os_mem_set(d, p_na_body+16, 0, 32);
275
276
277 /* ICMPv6 */
278
279 /* 1. Type : 0x88 (NA) , Code : 0x00 , ChechSum : 0x00 0x00 (RSvd) NAFlag: 0x60 0x00 0x00 0x00 ( Solicited , Override) */
280 _os_mem_cpy(d, p_na_body+48, ICMPv6Head, 8);
281
282 /* 2. TA : 16 bytes */
283 _os_mem_set(d, p_na_body+56, 0, 16);
284
285 /* ICMPv6 Target Link Layer address */
286
287 WriteLE1Byte(p_na_body+72, 0x02); /* type */
288 WriteLE1Byte(p_na_body+73, 0x01); /* Len 1 unit of 8 octes */
289 _os_mem_set(d, p_na_body+74, 0, 6); /* Target Link Address */
290
291 return RTW_PHL_STATUS_SUCCESS;
292 }
293
294 static enum rtw_phl_status
_phl_pkt_ofld_construct_arp_rsp(struct pkt_ofld_obj * pkt,u8 ** pkt_buf,u16 * len,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_arp_rsp_info * arp_rsp_info)295 _phl_pkt_ofld_construct_arp_rsp(struct pkt_ofld_obj *pkt, u8 **pkt_buf,
296 u16 *len, struct rtw_phl_stainfo_t *phl_sta,
297 struct rtw_pkt_ofld_arp_rsp_info *arp_rsp_info)
298 {
299 void *d = phl_to_drvpriv(pkt->phl_info);
300 u8* p_arp_rsp_body;
301 u8 ARPLLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06};
302 u8 sec_hdr = arp_rsp_info->sec_hdr;
303
304
305 /* size estimation */
306 /* sMacHdrLng + LLC header(8) + arp element(28) */
307 *len = MAC_HDR_LEN + sec_hdr + 8 + 28;
308
309 *pkt_buf = _os_mem_alloc(d, *len);
310
311 if (*pkt_buf == NULL)
312 return RTW_PHL_STATUS_RESOURCE;
313
314
315 _os_mem_set(d, *pkt_buf, 0, *len);
316
317 SET_80211_PKT_HDR_FRAME_CONTROL(*pkt_buf, 0);
318 SET_80211_PKT_HDR_TYPE_AND_SUBTYPE(*pkt_buf, TYPE_DATA_FRAME);
319 SET_80211_PKT_HDR_TO_DS(*pkt_buf, 1);
320
321 if (sec_hdr != 0)
322 SET_80211_PKT_HDR_PROTECT(*pkt_buf, 1);
323
324 SET_80211_PKT_HDR_ADDRESS1(d, *pkt_buf, arp_rsp_info->a1);
325 SET_80211_PKT_HDR_ADDRESS2(d, *pkt_buf, arp_rsp_info->a2);
326 SET_80211_PKT_HDR_ADDRESS3(d, *pkt_buf, arp_rsp_info->a3);
327
328 SET_80211_PKT_HDR_DURATION(*pkt_buf, 0);
329 SET_80211_PKT_HDR_FRAGMENT_SEQUENCE(*pkt_buf, 0);
330
331 /* Frame bod*/
332 p_arp_rsp_body = (u8*)(*pkt_buf + MAC_HDR_LEN);
333
334 /* offset for security iv */
335 p_arp_rsp_body += sec_hdr;
336
337 /* LLC header */
338 _os_mem_cpy(d, p_arp_rsp_body, ARPLLCHeader, 8);
339
340 /* ARP element */
341 p_arp_rsp_body += 8;
342
343 /* hardware type = 0x10 Ethernet */
344 WriteLE2Byte(p_arp_rsp_body, 0x0100);
345 /* Protcol type = 0800 IP */
346 WriteLE2Byte(p_arp_rsp_body+2, 0x0008);
347 /* Hardware address length = 6 */
348 WriteLE1Byte(p_arp_rsp_body+4, 6);
349 /* Protocol address length = 4 */
350 WriteLE1Byte(p_arp_rsp_body+5, 4);
351 /* Operation = 0x0002 arp response */
352 WriteLE2Byte(p_arp_rsp_body+6, 0x0200);
353 /* Sender Mac Address */
354 _os_mem_cpy(d, p_arp_rsp_body+8, arp_rsp_info->a2, 6);
355 /* Sender IPv4 Address */
356 _os_mem_cpy(d, p_arp_rsp_body+14,
357 &(arp_rsp_info->host_ipv4_addr[0]), 4);
358 /* Target Mac Address */
359 _os_mem_cpy(d, p_arp_rsp_body+18, arp_rsp_info->a1, 6);
360 /* Target IPv4 Address */
361 _os_mem_cpy(d, p_arp_rsp_body+24,
362 &(arp_rsp_info->remote_ipv4_addr[0]), 4);
363
364 return RTW_PHL_STATUS_SUCCESS;
365 }
366
367 static enum rtw_phl_status
_phl_pkt_ofld_construct_eapol_key_data(struct pkt_ofld_obj * ofld_obj,u8 ** pkt_buf,u16 * len,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_eapol_key_info * eapol_key_info)368 _phl_pkt_ofld_construct_eapol_key_data(struct pkt_ofld_obj *ofld_obj, u8 **pkt_buf,
369 u16 *len, struct rtw_phl_stainfo_t *phl_sta,
370 struct rtw_pkt_ofld_eapol_key_info *eapol_key_info)
371 {
372 void *d = phl_to_drvpriv(ofld_obj->phl_info);
373 u8 *pkt = NULL;
374 u8 llc_hdr[] = {0xAA, 0xAA, 0x03};
375 u8 llc_oui[] = {0x00, 0x00, 0x00};
376 u8 llc_proto_id[] = {0x88, 0x8E};
377 u8 sec_hdr = eapol_key_info->sec_hdr;
378 u8 key_desc_ver = eapol_key_info->key_desc_ver;
379
380 *len = MAC_HDR_LEN+sec_hdr+LLC_LEN+AUTH_1X_HDR_LEN+EAPOLMSG_HDR_LEN;
381
382 *pkt_buf = _os_mem_alloc(d, *len);
383
384 if (*pkt_buf == NULL)
385 return RTW_PHL_STATUS_RESOURCE;
386
387 pkt = *pkt_buf;
388
389 _os_mem_set(d, pkt, 0, *len);
390
391 SET_80211_PKT_HDR_FRAME_CONTROL(pkt, 0);
392 SET_80211_PKT_HDR_TYPE_AND_SUBTYPE(pkt, TYPE_DATA_FRAME);
393 SET_80211_PKT_HDR_TO_DS(pkt, 1);
394
395 if (sec_hdr != 0)
396 SET_80211_PKT_HDR_PROTECT(*pkt_buf, 1);
397
398 SET_80211_PKT_HDR_ADDRESS1(d, pkt, eapol_key_info->a1); /* BSSID */
399 SET_80211_PKT_HDR_ADDRESS2(d, pkt, eapol_key_info->a2); /* SA */
400 SET_80211_PKT_HDR_ADDRESS3(d, pkt, eapol_key_info->a3); /* DA */
401
402 SET_80211_PKT_HDR_DURATION(pkt, 0);
403 SET_80211_PKT_HDR_FRAGMENT_SEQUENCE(pkt, 0);
404 pkt += MAC_HDR_LEN;
405
406 /* offset for security iv */
407 pkt += sec_hdr;
408
409 /* LLC */
410 SET_LLC_HDR(d, pkt, llc_hdr);
411 SET_LLC_OUI(d, pkt, llc_oui);
412 SET_LLC_PROTO_ID(d, pkt, llc_proto_id);
413 pkt += LLC_LEN;
414
415 /* 802.1x Auth hdr */
416 SET_AUTH_1X_PROTO_VER(pkt, LIB1X_EAPOL_VER);
417 SET_AUTH_1X_PKT_TYPE(pkt, LIB1X_TYPE_EAPOL_KEY);
418 SET_AUTH_1X_LENGTH(pkt, EAPOLMSG_HDR_LEN);
419 pkt += AUTH_1X_HDR_LEN;
420
421 /* EAPOL-KEY */
422 SET_EAPOLKEY_KEYDESC_TYPE(pkt, EAPOLKEY_KEYDESC_TYPE_RSN);
423 SET_EAPOLKEY_KEY_INFO(pkt, EAPOLKEY_SECURE|EAPOLKEY_KEYMIC|key_desc_ver);
424
425 /* SET_EAPOLKEY_REPLAY_CNT(d, pkt, eapol_key_info->replay_cnt); */
426
427 return RTW_PHL_STATUS_SUCCESS;
428 }
429
430 static enum rtw_phl_status
_phl_pkt_ofld_construct_sa_query_pkt(struct pkt_ofld_obj * ofld_obj,u8 ** pkt_buf,u16 * len,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_sa_query_info * sa_query_info)431 _phl_pkt_ofld_construct_sa_query_pkt(struct pkt_ofld_obj *ofld_obj, u8 **pkt_buf,
432 u16 *len, struct rtw_phl_stainfo_t *phl_sta,
433 struct rtw_pkt_ofld_sa_query_info *sa_query_info)
434 {
435 void *d = phl_to_drvpriv(ofld_obj->phl_info);
436 u8 *pkt = NULL;
437 u8 sec_hdr = sa_query_info->sec_hdr;
438
439 *len = MAC_HDR_LEN+sec_hdr+SAQ_ACTION_LEN;
440
441 *pkt_buf = _os_mem_alloc(d, *len);
442
443 if (*pkt_buf == NULL)
444 return RTW_PHL_STATUS_RESOURCE;
445
446 pkt = *pkt_buf;
447
448 _os_mem_set(d, pkt, 0, *len);
449
450 SET_80211_PKT_HDR_FRAME_CONTROL(pkt, 0);
451 SET_80211_PKT_HDR_TYPE_AND_SUBTYPE(pkt, TYPE_ACTION_FRAME);
452 SET_80211_PKT_HDR_DURATION(pkt, 0);
453
454 if (sec_hdr != 0)
455 SET_80211_PKT_HDR_PROTECT(pkt, 1);
456
457 SET_80211_PKT_HDR_ADDRESS1(d, pkt, sa_query_info->a1); /* bssid */
458 SET_80211_PKT_HDR_ADDRESS2(d, pkt, sa_query_info->a2); /* sa */
459 SET_80211_PKT_HDR_ADDRESS3(d, pkt, sa_query_info->a3); /* da */
460
461 SET_80211_PKT_HDR_FRAGMENT_SEQUENCE(pkt, 0);
462 pkt += MAC_HDR_LEN;
463
464 /* offset for security iv */
465 pkt += sec_hdr;
466
467 SET_ACTION_FRAME_CATEGORY(pkt, ACT_TYPE_SA_QUERY);
468 SET_SAQ_ACTION_FIELD(pkt, 1);
469
470 return RTW_PHL_STATUS_SUCCESS;
471 }
472
473 static enum rtw_phl_status
_phl_pkt_ofld_construct_realwow_kapkt(struct pkt_ofld_obj * ofld_obj,u8 ** pkt_buf,u16 * len,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_realwow_kapkt_info * kapkt_info)474 _phl_pkt_ofld_construct_realwow_kapkt(struct pkt_ofld_obj *ofld_obj, u8 **pkt_buf,
475 u16 *len, struct rtw_phl_stainfo_t *phl_sta,
476 struct rtw_pkt_ofld_realwow_kapkt_info *kapkt_info)
477 {
478 void *d = phl_to_drvpriv(ofld_obj->phl_info);
479
480 *len = kapkt_info->keep_alive_pkt_size;
481
482 *pkt_buf = _os_mem_alloc(d, *len);
483 if (*pkt_buf == NULL)
484 return RTW_PHL_STATUS_RESOURCE;
485
486 _os_mem_set(d, *pkt_buf, 0, *len);
487
488 _os_mem_cpy(d, *pkt_buf, kapkt_info, *len);
489
490 return RTW_PHL_STATUS_SUCCESS;
491 }
492
493 static enum rtw_phl_status
_phl_pkt_ofld_construct_realwow_ack(struct pkt_ofld_obj * ofld_obj,u8 ** pkt_buf,u16 * len,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_realwow_ack_info * ack_info)494 _phl_pkt_ofld_construct_realwow_ack(struct pkt_ofld_obj *ofld_obj, u8 **pkt_buf,
495 u16 *len, struct rtw_phl_stainfo_t *phl_sta,
496 struct rtw_pkt_ofld_realwow_ack_info *ack_info)
497 {
498 void *d = phl_to_drvpriv(ofld_obj->phl_info);
499
500 *len = ack_info->ack_ptrn_size;
501
502 *pkt_buf = _os_mem_alloc(d, *len);
503 if (*pkt_buf == NULL)
504 return RTW_PHL_STATUS_RESOURCE;
505
506 _os_mem_set(d, *pkt_buf, 0, *len);
507
508 _os_mem_cpy(d, *pkt_buf, ack_info, *len);
509
510 return RTW_PHL_STATUS_SUCCESS;
511 }
512
513 static enum rtw_phl_status
_phl_pkt_ofld_construct_realwow_wp(struct pkt_ofld_obj * ofld_obj,u8 ** pkt_buf,u16 * len,struct rtw_phl_stainfo_t * phl_sta,struct rtw_pkt_ofld_realwow_wp_info * wake_info)514 _phl_pkt_ofld_construct_realwow_wp(struct pkt_ofld_obj *ofld_obj, u8 **pkt_buf,
515 u16 *len, struct rtw_phl_stainfo_t *phl_sta,
516 struct rtw_pkt_ofld_realwow_wp_info *wake_info)
517 {
518 void *d = phl_to_drvpriv(ofld_obj->phl_info);
519
520 *len = wake_info->wakeup_ptrn_size;
521
522 *pkt_buf = _os_mem_alloc(d, *len);
523 if (*pkt_buf == NULL)
524 return RTW_PHL_STATUS_RESOURCE;
525
526 _os_mem_set(d, *pkt_buf, 0, *len);
527
528 _os_mem_cpy(d, *pkt_buf, wake_info, *len);
529
530 return RTW_PHL_STATUS_SUCCESS;
531 }
532
533 static enum rtw_phl_status
_phl_pkt_ofld_construct_probe_req(struct pkt_ofld_obj * ofld_obj,u8 ** pkt_buf,u16 * len,struct rtw_pkt_ofld_probe_req_info * probe_req_info)534 _phl_pkt_ofld_construct_probe_req(struct pkt_ofld_obj *ofld_obj, u8 **pkt_buf,
535 u16 *len, struct rtw_pkt_ofld_probe_req_info *probe_req_info)
536 {
537 void *d = phl_to_drvpriv(ofld_obj->phl_info);
538 u8 wild_card[MAC_ADDRESS_LENGTH] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
539 u8 *tmp_buf = NULL;
540
541 if (probe_req_info->construct_pbreq == NULL) {
542
543 *len = MAC_HDR_LEN;
544 *pkt_buf = _os_mem_alloc(d, MAC_HDR_LEN);
545 if (*pkt_buf == NULL) {
546 return RTW_PHL_STATUS_RESOURCE;
547 }
548
549 _os_mem_set(d, *pkt_buf, 0, MAC_HDR_LEN);
550
551 SET_80211_PKT_HDR_FRAME_CONTROL(*pkt_buf, 0);
552 SET_80211_PKT_HDR_TYPE_AND_SUBTYPE(*pkt_buf, TYPE_PROBE_REQ_FRAME);
553 SET_80211_PKT_HDR_ADDRESS1(d, *pkt_buf, &wild_card);
554 SET_80211_PKT_HDR_ADDRESS2(d, *pkt_buf, probe_req_info->a2);
555 SET_80211_PKT_HDR_ADDRESS3(d, *pkt_buf, &wild_card);
556 SET_80211_PKT_HDR_DURATION(*pkt_buf, 0);
557 SET_80211_PKT_HDR_FRAGMENT_SEQUENCE(*pkt_buf, 0);
558
559 } else {
560
561 tmp_buf = _os_mem_alloc(d, MAX_MSDU_LEN + MAC_HDR_LEN + FCS_LEN);
562
563 if (tmp_buf == NULL)
564 return RTW_PHL_STATUS_RESOURCE;
565
566 probe_req_info->construct_pbreq(d, tmp_buf, len);
567
568 *pkt_buf = _os_mem_alloc(d, *len);
569 if (*pkt_buf == NULL) {
570 _os_mem_free(d, tmp_buf, MAX_MSDU_LEN + MAC_HDR_LEN + FCS_LEN);
571 return RTW_PHL_STATUS_RESOURCE;
572 }
573
574 _os_mem_set(d, *pkt_buf, 0, *len);
575 _os_mem_cpy(d, *pkt_buf, tmp_buf, *len);
576
577 _os_mem_free(d, tmp_buf, MAX_MSDU_LEN + MAC_HDR_LEN + FCS_LEN);
578 }
579
580 return RTW_PHL_STATUS_SUCCESS;
581 }
582
583 static enum rtw_phl_status
_phl_pkt_ofld_construct_packet(struct pkt_ofld_obj * ofld_obj,u16 macid,u8 type,u8 ** pkt_buf,u16 * len,void * buf)584 _phl_pkt_ofld_construct_packet(struct pkt_ofld_obj *ofld_obj, u16 macid,
585 u8 type, u8 **pkt_buf, u16 *len, void *buf)
586 {
587 struct rtw_phl_stainfo_t *phl_sta = rtw_phl_get_stainfo_by_macid(
588 ofld_obj->phl_info, macid);
589 enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
590
591 switch(type) {
592 case PKT_TYPE_NULL_DATA:
593 status = _phl_pkt_ofld_construct_null_data(ofld_obj, pkt_buf,
594 len, phl_sta, (struct rtw_pkt_ofld_null_info *) buf);
595 break;
596 case PKT_TYPE_ARP_RSP:
597 status = _phl_pkt_ofld_construct_arp_rsp(ofld_obj, pkt_buf,
598 len, phl_sta, (struct rtw_pkt_ofld_arp_rsp_info *) buf);
599 break;
600 case PKT_TYPE_NDP:
601 status = _phl_pkt_ofld_construct_na(ofld_obj, pkt_buf,
602 len, phl_sta, (struct rtw_pkt_ofld_na_info *) buf);
603 break;
604 case PKT_TYPE_EAPOL_KEY:
605 status = _phl_pkt_ofld_construct_eapol_key_data(ofld_obj, pkt_buf,
606 len, phl_sta, (struct rtw_pkt_ofld_eapol_key_info *) buf);
607 break;
608 case PKT_TYPE_SA_QUERY:
609 status = _phl_pkt_ofld_construct_sa_query_pkt(ofld_obj, pkt_buf,
610 len, phl_sta, (struct rtw_pkt_ofld_sa_query_info *) buf);
611 break;
612 case PKT_TYPE_REALWOW_KAPKT:
613 status = _phl_pkt_ofld_construct_realwow_kapkt(ofld_obj, pkt_buf,
614 len, phl_sta, (struct rtw_pkt_ofld_realwow_kapkt_info *) buf);
615 break;
616 case PKT_TYPE_REALWOW_ACK:
617 status = _phl_pkt_ofld_construct_realwow_ack(ofld_obj, pkt_buf,
618 len, phl_sta, (struct rtw_pkt_ofld_realwow_ack_info *) buf);
619 break;
620 case PKT_TYPE_REALWOW_WP:
621 status = _phl_pkt_ofld_construct_realwow_wp(ofld_obj, pkt_buf,
622 len, phl_sta, (struct rtw_pkt_ofld_realwow_wp_info *) buf);
623 break;
624 case PKT_TYPE_PROBE_REQ:
625 status = _phl_pkt_ofld_construct_probe_req(ofld_obj, pkt_buf,
626 len, (struct rtw_pkt_ofld_probe_req_info *) buf);
627 break;
628 case PKT_TYPE_PROBE_RSP:
629 case PKT_TYPE_PS_POLL:
630 case PKT_TYPE_QOS_NULL:
631 case PKT_TYPE_CTS2SELF:
632 default:
633 PHL_ERR("[PKT] packet type %s is not implemented.\n",
634 _phl_pkt_ofld_get_txt(type));
635 status = RTW_PHL_STATUS_FAILURE;
636 break;
637 }
638
639 if(status == RTW_PHL_STATUS_SUCCESS) {
640 PHL_TRACE(COMP_PHL_PKTOFLD, _PHL_INFO_,"%s:\n", _phl_pkt_ofld_get_txt(type));
641 debug_dump_data((u8 *)*pkt_buf, *len, "construct packet");
642 } else if(status == RTW_PHL_STATUS_RESOURCE) {
643 PHL_ERR("[PKT] %s: alloc memory failed.\n", __func__);
644 } else {
645 PHL_ERR("[PKT] %s: failed.\n", __func__);
646 }
647
648 return status;
649 }
650
651 static void
_phl_pkt_ofld_init_entry(struct pkt_ofld_entry * entry,u16 macid)652 _phl_pkt_ofld_init_entry(struct pkt_ofld_entry *entry, u16 macid)
653 {
654 u8 idx;
655
656 INIT_LIST_HEAD(&entry->list);
657 entry->macid = macid;
658
659 for(idx = 0; idx < PKT_OFLD_TYPE_MAX; idx++) {
660 INIT_LIST_HEAD(&entry->pkt_info[idx].req_q);
661 entry->pkt_info[idx].id = NOT_USED;
662 entry->pkt_info[idx].req_cnt = 0;
663 }
664 }
665
666 static u8
_phl_pkt_ofld_is_entry_exist(struct pkt_ofld_obj * ofld_obj,u16 macid)667 _phl_pkt_ofld_is_entry_exist(struct pkt_ofld_obj *ofld_obj, u16 macid)
668 {
669 struct pkt_ofld_entry *pos = NULL;
670
671 phl_list_for_loop(pos, struct pkt_ofld_entry, &ofld_obj->entry_q, list) {
672 if (pos->macid == macid) {
673
674 PHL_ERR("[PKT] %s, mac id(%d) already in entry queue.\n",
675 __func__, macid);
676 return true;
677 }
678 }
679
680 return false;
681 }
682
683 static void
_phl_pkt_ofld_del_all_req(struct pkt_ofld_obj * ofld_obj,struct pkt_ofld_info * pkt_info)684 _phl_pkt_ofld_del_all_req(struct pkt_ofld_obj *ofld_obj,
685 struct pkt_ofld_info *pkt_info)
686 {
687 struct pkt_ofld_req *pos = NULL;
688 struct pkt_ofld_req *n = NULL;
689
690 phl_list_for_loop_safe(pos, n, struct pkt_ofld_req,
691 &pkt_info->req_q, list) {
692
693 _phl_pkt_ofld_del_req(ofld_obj, pkt_info, pos);
694 }
695 }
696
697 static void
_phl_pkt_ofld_del_ofld_type(struct pkt_ofld_obj * ofld_obj,struct pkt_ofld_entry * entry)698 _phl_pkt_ofld_del_ofld_type(struct pkt_ofld_obj *ofld_obj,
699 struct pkt_ofld_entry *entry)
700 {
701 u8 idx;
702 u8 id;
703
704 for(idx = 0; idx < PKT_OFLD_TYPE_MAX; idx++) {
705 if(_phl_pkt_ofld_is_pkt_ofld(&entry->pkt_info[idx])) {
706
707 id = entry->pkt_info[idx].id;
708 if(HAL_PKT_OFLD_DEL(ofld_obj, &id) !=
709 RTW_HAL_STATUS_SUCCESS) {
710
711 PHL_ERR("[PKT] %s: delete pkt(%d) failed, id(%d).\n",
712 __func__, idx, id);
713 }
714 }
715 }
716 }
717
718 static void
_phl_pkt_ofld_reset_entry(struct pkt_ofld_obj * ofld_obj,struct pkt_ofld_entry * entry)719 _phl_pkt_ofld_reset_entry(struct pkt_ofld_obj *ofld_obj,
720 struct pkt_ofld_entry *entry)
721 {
722 u8 idx;
723
724 for(idx = 0; idx < PKT_OFLD_TYPE_MAX; idx++) {
725 entry->pkt_info[idx].id = NOT_USED;
726 _phl_pkt_ofld_del_all_req(ofld_obj, &entry->pkt_info[idx]);
727 }
728 }
729
730 static void
_phl_pkt_ofld_add_entry(struct pkt_ofld_obj * ofld_obj,struct pkt_ofld_entry * entry,u16 macid)731 _phl_pkt_ofld_add_entry(struct pkt_ofld_obj *ofld_obj,
732 struct pkt_ofld_entry *entry, u16 macid)
733 {
734 PHL_TRACE(COMP_PHL_PKTOFLD, _PHL_INFO_,
735 "[PKT] New entry %p, mac id = %d\n", entry, macid);
736
737 _phl_pkt_ofld_init_entry(entry, macid);
738 list_add(&entry->list, &ofld_obj->entry_q);
739 ofld_obj->entry_cnt++;
740
741 if(rtw_hal_pkt_update_ids(ofld_obj->phl_info->hal, entry)
742 != RTW_HAL_STATUS_SUCCESS) {
743 PHL_WARN("%s: init general id failed.\n", __func__);
744 }
745 }
746
747 static void
_phl_pkt_ofld_del_entry(struct pkt_ofld_obj * ofld_obj,struct pkt_ofld_entry * entry)748 _phl_pkt_ofld_del_entry(struct pkt_ofld_obj *ofld_obj, struct pkt_ofld_entry *entry)
749 {
750 void *d = phl_to_drvpriv(ofld_obj->phl_info);
751
752 list_del(&entry->list);
753 ofld_obj->entry_cnt--;
754 _os_mem_free(d, entry, sizeof(*entry));
755 }
756
757 static struct pkt_ofld_entry *
_phl_pkt_ofld_get_entry(struct pkt_ofld_obj * ofld_obj,u16 macid)758 _phl_pkt_ofld_get_entry(struct pkt_ofld_obj *ofld_obj, u16 macid)
759 {
760 struct pkt_ofld_entry *pos = NULL;
761 u8 find = false;
762
763 phl_list_for_loop(pos, struct pkt_ofld_entry, &ofld_obj->entry_q, list) {
764 if (pos->macid == macid) {
765 find = true;
766 break;
767 }
768 }
769
770 if (find) {
771 return pos;
772 } else {
773 return NULL;
774 }
775 }
776
777 static enum rtw_phl_status
_phl_pkt_ofld_req_type(struct pkt_ofld_obj * ofld_obj,struct pkt_ofld_entry * entry,u8 type,void * buf)778 _phl_pkt_ofld_req_type(struct pkt_ofld_obj *ofld_obj,
779 struct pkt_ofld_entry *entry, u8 type, void *buf)
780 {
781 enum rtw_phl_status phl_status;
782 enum rtw_hal_status hal_status;
783 struct pkt_ofld_info *pkt_info = &entry->pkt_info[type];
784 void *d = phl_to_drvpriv(ofld_obj->phl_info);
785 u8 *pkt_buf = NULL;
786 u16 len = 0;
787
788 if(_phl_pkt_ofld_is_pkt_ofld(pkt_info)) {
789 PHL_TRACE(COMP_PHL_PKTOFLD, _PHL_INFO_,
790 "[PKT] %s: type %s is already download to FW.\n",
791 __func__, _phl_pkt_ofld_get_txt(type));
792 return RTW_PHL_STATUS_SUCCESS;
793 }
794
795 phl_status = _phl_pkt_ofld_construct_packet(ofld_obj, entry->macid, type,
796 &pkt_buf, &len, buf);
797 if(phl_status != RTW_PHL_STATUS_SUCCESS) {
798 PHL_ERR("[PKT] %s: construct packet type(%d) failed.\n",
799 __func__, type);
800 return RTW_PHL_STATUS_FAILURE;
801 }
802
803 hal_status = HAL_PKT_OFLD_ADD(ofld_obj, &pkt_info->id, pkt_buf, &len);
804
805 _os_mem_free(d, pkt_buf, len);
806
807 if(hal_status != RTW_HAL_STATUS_SUCCESS) {
808 pkt_info->id = NOT_USED;
809 PHL_ERR("[PKT] %s: add packet offload(%d) failed.\n", __func__,
810 pkt_info->id);
811 return RTW_PHL_STATUS_FAILURE;
812 }
813
814 hal_status = rtw_hal_pkt_update_ids(ofld_obj->phl_info->hal, entry);
815 if(hal_status != RTW_HAL_STATUS_SUCCESS) {
816 pkt_info->id = NOT_USED;
817 PHL_ERR("[PKT] %s: update id failed.\n", __func__);
818 return RTW_PHL_STATUS_FAILURE;
819 }
820
821 return RTW_PHL_STATUS_SUCCESS;
822 }
823
824 static enum rtw_phl_status
_phl_pkt_ofld_cancel_type(struct pkt_ofld_obj * ofld_obj,struct pkt_ofld_entry * entry,u8 type)825 _phl_pkt_ofld_cancel_type(struct pkt_ofld_obj *ofld_obj,
826 struct pkt_ofld_entry *entry, u8 type)
827 {
828 struct pkt_ofld_info *pkt_info = &entry->pkt_info[type];
829
830 if(_phl_pkt_ofld_is_pkt_ofld(pkt_info) == false) {
831 PHL_ERR("[PKT] %s, type not offload to FW.\n", __func__);
832 return RTW_PHL_STATUS_FAILURE;
833 }
834
835 if((entry->pkt_info[type].req_cnt-1) != 0) {
836 return RTW_PHL_STATUS_SUCCESS;
837 }
838
839 if(HAL_PKT_OFLD_DEL(ofld_obj, &entry->pkt_info[type].id)
840 != RTW_HAL_STATUS_SUCCESS) {
841
842 PHL_ERR("[PKT] %s: delete id(%d) failed.\n", __func__,
843 entry->pkt_info[type].id);
844 return RTW_PHL_STATUS_FAILURE;
845 }
846 entry->pkt_info[type].id = NOT_USED;
847
848 return RTW_PHL_STATUS_SUCCESS;
849 }
850
851 /* For EXTERNAL application to create packet offload object */
phl_pkt_ofld_init(struct phl_info_t * phl_info)852 enum rtw_phl_status phl_pkt_ofld_init(struct phl_info_t *phl_info)
853 {
854 void *d = phl_to_drvpriv(phl_info);
855 struct pkt_ofld_obj *ofld_obj;
856
857 ofld_obj = (struct pkt_ofld_obj *)_os_mem_alloc(d, sizeof(*ofld_obj));
858 if (ofld_obj == NULL)
859 return RTW_PHL_STATUS_RESOURCE;
860
861 phl_info->pkt_ofld = ofld_obj;
862
863 ofld_obj->phl_info = phl_info;
864 INIT_LIST_HEAD(&ofld_obj->entry_q);
865 ofld_obj->entry_cnt = 0;
866 ofld_obj->cur_seq = 0;
867 _os_mutex_init(d, &ofld_obj->mux);
868
869 return RTW_PHL_STATUS_SUCCESS;
870 }
871
872 /* For EXTERNAL application to free packet offload object */
phl_pkt_ofld_deinit(struct phl_info_t * phl_info)873 void phl_pkt_ofld_deinit(struct phl_info_t *phl_info)
874 {
875 struct pkt_ofld_obj *ofld_obj = phl_info->pkt_ofld;
876 struct pkt_ofld_entry *pos = NULL;
877 struct pkt_ofld_entry *n = NULL;
878 void *d = phl_to_drvpriv(phl_info);
879
880 _os_mutex_lock(d, &ofld_obj->mux);
881
882 phl_list_for_loop_safe(pos, n, struct pkt_ofld_entry,
883 &ofld_obj->entry_q, list) {
884
885 _phl_pkt_ofld_reset_entry(ofld_obj, pos);
886 _phl_pkt_ofld_del_entry(ofld_obj, pos);
887 }
888
889 _os_mutex_unlock(d, &ofld_obj->mux);
890 _os_mutex_deinit(d, &ofld_obj->mux);
891
892 _os_mem_free(d, ofld_obj, sizeof(*ofld_obj));
893 }
894
895 /* For EXTERNAL application to reset all entry */
phl_pkt_ofld_reset_all_entry(struct phl_info_t * phl_info)896 void phl_pkt_ofld_reset_all_entry(struct phl_info_t *phl_info)
897 {
898 struct pkt_ofld_obj *ofld_obj = phl_info->pkt_ofld;
899 struct pkt_ofld_entry *pos = NULL;
900 void *d = phl_to_drvpriv(phl_info);
901
902 _os_mutex_lock(d, &ofld_obj->mux);
903
904 phl_list_for_loop(pos, struct pkt_ofld_entry,
905 &ofld_obj->entry_q, list) {
906
907 _phl_pkt_ofld_reset_entry(ofld_obj, pos);
908 }
909
910 _os_mutex_unlock(d, &ofld_obj->mux);
911 }
912
913 /* For EXTERNAL application to add entry to do packet offload (expose)
914 * @phl: refer to rtw_phl_com_t
915 * @macid: the mac id of STA
916 */
phl_pkt_ofld_add_entry(struct phl_info_t * phl_info,u16 macid)917 enum rtw_phl_status phl_pkt_ofld_add_entry(struct phl_info_t *phl_info, u16 macid)
918 {
919 struct pkt_ofld_obj *ofld_obj = phl_info->pkt_ofld;
920 void *d = phl_to_drvpriv(ofld_obj->phl_info);
921 struct pkt_ofld_entry *entry = NULL;
922
923 if (ofld_obj == NULL) {
924 PHL_ERR("[PKT] %s: pkt_ofld_obj is NULL.\n", __func__);
925 return RTW_PHL_STATUS_FAILURE;
926 }
927
928 _os_mutex_lock(d, &ofld_obj->mux);
929
930 if (_phl_pkt_ofld_is_entry_exist(ofld_obj, macid)) {
931 _os_mutex_unlock(d, &ofld_obj->mux);
932 return RTW_PHL_STATUS_FAILURE;
933 }
934
935 entry = _os_mem_alloc(d, sizeof(*entry));
936 if (entry == NULL) {
937 PHL_ERR("[PKT] %s: alloc memory failed.\n", __func__);
938 _os_mutex_unlock(d, &ofld_obj->mux);
939 return RTW_PHL_STATUS_RESOURCE;
940 }
941
942 _phl_pkt_ofld_add_entry(ofld_obj, entry, macid);
943
944 _os_mutex_unlock(d, &ofld_obj->mux);
945
946 return RTW_PHL_STATUS_SUCCESS;
947 }
948
949 /* For EXTERNAL application to remove entry (expose)
950 * @phl: refer to rtw_phl_com_t
951 * @macid: the mac id of STA
952 */
phl_pkt_ofld_del_entry(struct phl_info_t * phl_info,u16 macid)953 enum rtw_phl_status phl_pkt_ofld_del_entry(struct phl_info_t *phl_info, u16 macid)
954 {
955 struct pkt_ofld_obj *ofld_obj = phl_info->pkt_ofld;
956 void *d = phl_to_drvpriv(ofld_obj->phl_info);
957 struct pkt_ofld_entry *entry = NULL;
958
959 if (ofld_obj == NULL) {
960 PHL_ERR("[PKT] %s: pkt_ofld_obj is NULL.\n", __func__);
961 return RTW_PHL_STATUS_FAILURE;
962 }
963
964 _os_mutex_lock(d, &ofld_obj->mux);
965
966 entry = _phl_pkt_ofld_get_entry(ofld_obj, macid);
967 if(entry == NULL) {
968 _os_mutex_unlock(d, &ofld_obj->mux);
969 PHL_ERR("[PKT] %s, mac id(%d) not found.\n", __func__, macid);
970 return RTW_PHL_STATUS_FAILURE;
971 }
972
973 PHL_TRACE(COMP_PHL_PKTOFLD, _PHL_INFO_,
974 "[PKT] Remove entry %p, mac id = %d\n", entry, macid);
975
976 _phl_pkt_ofld_del_ofld_type(ofld_obj, entry);
977 _phl_pkt_ofld_reset_entry(ofld_obj, entry);
978 _phl_pkt_ofld_del_entry(ofld_obj, entry);
979
980 _os_mutex_unlock(d, &ofld_obj->mux);
981
982 return RTW_PHL_STATUS_SUCCESS;
983 }
984
985 /* For EXTERNAL application to request packet offload to FW (expose)
986 * @phl: refer to rtw_phl_com_t
987 * @macid: the mac id of STA
988 * @type: The type of packet
989 * @token: The identifier (return to caller)
990 * @req_name: The function name of caller
991 */
992 enum rtw_phl_status
phl_pkt_ofld_request(struct phl_info_t * phl_info,u16 macid,u8 type,u32 * token,const char * req_name,void * buf)993 phl_pkt_ofld_request(struct phl_info_t *phl_info, u16 macid, u8 type,
994 u32 *token, const char *req_name, void *buf)
995 {
996 struct pkt_ofld_obj *ofld_obj = phl_info->pkt_ofld;
997 void *d = phl_to_drvpriv(ofld_obj->phl_info);
998 struct pkt_ofld_entry *entry = NULL;
999 struct pkt_ofld_req *req = NULL;
1000
1001 if (ofld_obj == NULL) {
1002 PHL_ERR("[PKT] %s: pkt_ofld_obj is NULL.\n", __func__);
1003 return RTW_PHL_STATUS_FAILURE;
1004 }
1005
1006 _os_mutex_lock(d, &ofld_obj->mux);
1007
1008 entry = _phl_pkt_ofld_get_entry(ofld_obj, macid);
1009 if(entry == NULL) {
1010 _os_mutex_unlock(d, &ofld_obj->mux);
1011 PHL_ERR("[PKT] %s, mac id(%d) not found.\n", __func__, macid);
1012 return RTW_PHL_STATUS_FAILURE;
1013 }
1014
1015 req = _phl_pkt_ofld_gen_req(ofld_obj, req_name);
1016 if (req == NULL) {
1017 _os_mutex_unlock(d, &ofld_obj->mux);
1018 return RTW_PHL_STATUS_RESOURCE;
1019 }
1020 _phl_pkt_ofld_add_req(ofld_obj, &entry->pkt_info[type], req);
1021
1022 if(_phl_pkt_ofld_req_type(ofld_obj, entry, type, buf) !=
1023 RTW_PHL_STATUS_SUCCESS) {
1024
1025 _phl_pkt_ofld_del_req(ofld_obj, &entry->pkt_info[type], req);
1026 _os_mutex_unlock(d, &ofld_obj->mux);
1027 return RTW_PHL_STATUS_FAILURE;
1028 }
1029
1030 *token = req->token;
1031
1032 _os_mutex_unlock(d, &ofld_obj->mux);
1033
1034 PHL_TRACE(COMP_PHL_PKTOFLD, _PHL_INFO_,
1035 "[PKT] Request: macid %d, pkt type %s, token %d.\n",
1036 entry->macid, _phl_pkt_ofld_get_txt(type), *token);
1037
1038 return RTW_PHL_STATUS_SUCCESS;
1039 }
1040
1041 /* For EXTERNAL application to cancel request (expose)
1042 * @phl: refer to rtw_phl_com_t
1043 * @macid: the mac id of STA
1044 * @type: The type of packet
1045 * @token: The identifier to get the request to be canceled
1046 */
phl_pkt_ofld_cancel(struct phl_info_t * phl_info,u16 macid,u8 type,u32 * token)1047 enum rtw_phl_status phl_pkt_ofld_cancel(struct phl_info_t *phl_info,
1048 u16 macid, u8 type, u32 *token)
1049 {
1050 struct pkt_ofld_obj *ofld_obj = phl_info->pkt_ofld;
1051 void *d = phl_to_drvpriv(ofld_obj->phl_info);
1052 struct pkt_ofld_entry *entry = NULL;
1053 struct pkt_ofld_req *req = NULL;
1054 struct pkt_ofld_info *pkt_info = NULL;
1055
1056 if (ofld_obj == NULL) {
1057 PHL_ERR("[PKT] %s: pkt_ofld_obj is NULL.\n", __func__);
1058 return RTW_PHL_STATUS_FAILURE;
1059 }
1060
1061 _os_mutex_lock(d, &ofld_obj->mux);
1062
1063 entry = _phl_pkt_ofld_get_entry(ofld_obj, macid);
1064 if(entry == NULL) {
1065 _os_mutex_unlock(d, &ofld_obj->mux);
1066 PHL_ERR("[PKT] %s, macid(%d) not found.\n", __func__, macid);
1067 return RTW_PHL_STATUS_FAILURE;
1068 }
1069 pkt_info = &entry->pkt_info[type];
1070
1071 req = _phl_pkt_ofld_get_req(ofld_obj, pkt_info, *token);
1072 if(req == NULL) {
1073 _os_mutex_unlock(d, &ofld_obj->mux);
1074 PHL_ERR("[PKT] %s, token(%d) not found.\n", __func__, *token);
1075 return RTW_PHL_STATUS_FAILURE;
1076 }
1077
1078 PHL_TRACE(COMP_PHL_PKTOFLD, _PHL_INFO_,
1079 "[PKT] Cancel: macid %d, type %s, token %d.\n",
1080 entry->macid, _phl_pkt_ofld_get_txt(type), *token);
1081
1082 if(_phl_pkt_ofld_cancel_type(ofld_obj, entry, type)
1083 != RTW_PHL_STATUS_SUCCESS) {
1084 _os_mutex_unlock(d, &ofld_obj->mux);
1085 return RTW_PHL_STATUS_FAILURE;
1086 }
1087 _phl_pkt_ofld_del_req(ofld_obj, pkt_info, req);
1088
1089 _os_mutex_unlock(d, &ofld_obj->mux);
1090
1091 return RTW_PHL_STATUS_SUCCESS;
1092 }
1093
1094 /* For EXTERNAL application to show current info (expose)
1095 * @phl: refer to rtw_phl_com_t
1096 */
phl_pkt_ofld_show_info(struct phl_info_t * phl_info)1097 void phl_pkt_ofld_show_info(struct phl_info_t *phl_info)
1098 {
1099 struct pkt_ofld_obj *ofld_obj = phl_info->pkt_ofld;
1100 void *d = phl_to_drvpriv(ofld_obj->phl_info);
1101
1102 _os_mutex_lock(d, &ofld_obj->mux);
1103
1104 _phl_pkt_ofld_dbg_dump(ofld_obj);
1105
1106 _os_mutex_unlock(d, &ofld_obj->mux);
1107 }
1108
1109 /* For EXTERNAL application to get id (expose)
1110 * @phl: refer to rtw_phl_com_t
1111 * @macid: the mac id of STA
1112 * @type: The type of packet
1113 */
phl_pkt_ofld_get_id(struct phl_info_t * phl_info,u16 macid,u8 type)1114 u8 phl_pkt_ofld_get_id(struct phl_info_t *phl_info, u16 macid, u8 type)
1115 {
1116 struct pkt_ofld_obj *ofld_obj = phl_info->pkt_ofld;
1117 void *d = phl_to_drvpriv(ofld_obj->phl_info);
1118 struct pkt_ofld_entry *entry = NULL;
1119 struct pkt_ofld_info *pkt_info = NULL;
1120
1121 if (ofld_obj == NULL) {
1122 PHL_ERR("[PKT] %s: pkt_ofld_obj is NULL.\n", __func__);
1123 return RTW_PHL_STATUS_FAILURE;
1124 }
1125
1126 _os_mutex_lock(d, &ofld_obj->mux);
1127
1128 entry = _phl_pkt_ofld_get_entry(ofld_obj, macid);
1129 if(entry == NULL) {
1130 _os_mutex_unlock(d, &ofld_obj->mux);
1131 PHL_ERR("[PKT] %s, macid(%d) not found.\n", __func__, macid);
1132 return RTW_PHL_STATUS_FAILURE;
1133 }
1134 pkt_info = &entry->pkt_info[type];
1135
1136 PHL_TRACE(COMP_PHL_PKTOFLD, _PHL_INFO_,
1137 "[PKT] Get id: macid %d, pkt type %s, id %d.\n",
1138 entry->macid, _phl_pkt_ofld_get_txt(type),
1139 pkt_info->id);
1140
1141 _os_mutex_unlock(d, &ofld_obj->mux);
1142
1143 return pkt_info->id;
1144 }
1145
phl_get_pkt_ofld_str(enum pkt_ofld_type type)1146 const char *phl_get_pkt_ofld_str(enum pkt_ofld_type type)
1147 {
1148 switch(type) {
1149 case PKT_TYPE_NULL_DATA:
1150 return "PKT_TYPE_NULL_DATA";
1151 case PKT_TYPE_ARP_RSP:
1152 return "PKT_TYPE_ARP_RSP";
1153 case PKT_TYPE_NDP:
1154 return "PKT_TYPE_NDP";
1155 case PKT_TYPE_EAPOL_KEY:
1156 return "PKT_TYPE_EAPOL_KEY";
1157 case PKT_TYPE_SA_QUERY:
1158 return "PKT_TYPE_SA_QUERY";
1159 case PKT_TYPE_PROBE_REQ:
1160 return "PKT_TYPE_PROBE_REQ";
1161 default:
1162 return "UNKNOWN_PKT_TYPE";
1163 }
1164 }