xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/phl/phl_pkt_ofld.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 }