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