xref: /wlan-driver/qcacld-3.0/core/dp/htt/htt_rx_hl.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name #include <qdf_mem.h>         /* qdf_mem_malloc,free, etc. */
21*5113495bSYour Name #include <qdf_types.h>          /* qdf_print, bool */
22*5113495bSYour Name #include <qdf_nbuf.h>           /* qdf_nbuf_t, etc. */
23*5113495bSYour Name #include <qdf_timer.h>		/* qdf_timer_free */
24*5113495bSYour Name 
25*5113495bSYour Name #include <htt.h>                /* HTT_HL_RX_DESC_SIZE */
26*5113495bSYour Name #include <ol_cfg.h>
27*5113495bSYour Name #include <ol_rx.h>
28*5113495bSYour Name #include <ol_htt_rx_api.h>
29*5113495bSYour Name #include <htt_internal.h>       /* HTT_ASSERT, htt_pdev_t, HTT_RX_BUF_SIZE */
30*5113495bSYour Name #include "regtable.h"
31*5113495bSYour Name 
32*5113495bSYour Name #include <cds_ieee80211_common.h>   /* ieee80211_frame, ieee80211_qoscntl */
33*5113495bSYour Name #include <cds_utils.h>
34*5113495bSYour Name #include <wlan_policy_mgr_api.h>
35*5113495bSYour Name #include "ol_txrx_types.h"
36*5113495bSYour Name 
37*5113495bSYour Name /*
38*5113495bSYour Name  * This function is used both below within this file (which the compiler
39*5113495bSYour Name  * will hopefully inline), and out-line from other files via the
40*5113495bSYour Name  * htt_rx_msdu_first_msdu_flag function pointer.
41*5113495bSYour Name  */
42*5113495bSYour Name static inline bool
htt_rx_msdu_first_msdu_flag_hl(htt_pdev_handle pdev,void * msdu_desc)43*5113495bSYour Name htt_rx_msdu_first_msdu_flag_hl(htt_pdev_handle pdev, void *msdu_desc)
44*5113495bSYour Name {
45*5113495bSYour Name 	return ((u_int8_t *)msdu_desc - sizeof(struct hl_htt_rx_ind_base))
46*5113495bSYour Name 		[HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_IND_HL_FLAG_OFFSET)] &
47*5113495bSYour Name 		HTT_RX_IND_HL_FLAG_FIRST_MSDU ? true : false;
48*5113495bSYour Name }
49*5113495bSYour Name 
50*5113495bSYour Name u_int16_t
htt_rx_msdu_rx_desc_size_hl(htt_pdev_handle pdev,void * msdu_desc)51*5113495bSYour Name htt_rx_msdu_rx_desc_size_hl(
52*5113495bSYour Name 	htt_pdev_handle pdev,
53*5113495bSYour Name 	void *msdu_desc
54*5113495bSYour Name 		)
55*5113495bSYour Name {
56*5113495bSYour Name 	return ((u_int8_t *)(msdu_desc) - HTT_RX_IND_HL_BYTES)
57*5113495bSYour Name 		[HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_IND_HL_RX_DESC_LEN_OFFSET)];
58*5113495bSYour Name }
59*5113495bSYour Name 
60*5113495bSYour Name #ifdef CHECKSUM_OFFLOAD
61*5113495bSYour Name static void
htt_set_checksum_result_hl(qdf_nbuf_t msdu,struct htt_host_rx_desc_base * rx_desc)62*5113495bSYour Name htt_set_checksum_result_hl(qdf_nbuf_t msdu,
63*5113495bSYour Name 			   struct htt_host_rx_desc_base *rx_desc)
64*5113495bSYour Name {
65*5113495bSYour Name 	u_int8_t flag = ((u_int8_t *)rx_desc -
66*5113495bSYour Name 				sizeof(struct hl_htt_rx_ind_base))[
67*5113495bSYour Name 					HTT_ENDIAN_BYTE_IDX_SWAP(
68*5113495bSYour Name 						HTT_RX_IND_HL_FLAG_OFFSET)];
69*5113495bSYour Name 
70*5113495bSYour Name 	int is_ipv6 = flag & HTT_RX_IND_HL_FLAG_IPV6 ? 1 : 0;
71*5113495bSYour Name 	int is_tcp = flag & HTT_RX_IND_HL_FLAG_TCP ? 1 : 0;
72*5113495bSYour Name 	int is_udp = flag & HTT_RX_IND_HL_FLAG_UDP ? 1 : 0;
73*5113495bSYour Name 
74*5113495bSYour Name 	qdf_nbuf_rx_cksum_t cksum = {
75*5113495bSYour Name 		QDF_NBUF_RX_CKSUM_NONE,
76*5113495bSYour Name 		QDF_NBUF_RX_CKSUM_NONE,
77*5113495bSYour Name 		0
78*5113495bSYour Name 	};
79*5113495bSYour Name 
80*5113495bSYour Name 	switch ((is_udp << 2) | (is_tcp << 1) | (is_ipv6 << 0)) {
81*5113495bSYour Name 	case 0x4:
82*5113495bSYour Name 		cksum.l4_type = QDF_NBUF_RX_CKSUM_UDP;
83*5113495bSYour Name 		break;
84*5113495bSYour Name 	case 0x2:
85*5113495bSYour Name 		cksum.l4_type = QDF_NBUF_RX_CKSUM_TCP;
86*5113495bSYour Name 		break;
87*5113495bSYour Name 	case 0x5:
88*5113495bSYour Name 		cksum.l4_type = QDF_NBUF_RX_CKSUM_UDPIPV6;
89*5113495bSYour Name 		break;
90*5113495bSYour Name 	case 0x3:
91*5113495bSYour Name 		cksum.l4_type = QDF_NBUF_RX_CKSUM_TCPIPV6;
92*5113495bSYour Name 		break;
93*5113495bSYour Name 	default:
94*5113495bSYour Name 		cksum.l4_type = QDF_NBUF_RX_CKSUM_NONE;
95*5113495bSYour Name 		break;
96*5113495bSYour Name 	}
97*5113495bSYour Name 	if (cksum.l4_type != (qdf_nbuf_l4_rx_cksum_type_t)
98*5113495bSYour Name 				QDF_NBUF_RX_CKSUM_NONE) {
99*5113495bSYour Name 		cksum.l4_result = flag & HTT_RX_IND_HL_FLAG_C4_FAILED ?
100*5113495bSYour Name 			QDF_NBUF_RX_CKSUM_NONE :
101*5113495bSYour Name 				QDF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY;
102*5113495bSYour Name 	}
103*5113495bSYour Name 	qdf_nbuf_set_rx_cksum(msdu, &cksum);
104*5113495bSYour Name }
105*5113495bSYour Name #else
106*5113495bSYour Name static inline
htt_set_checksum_result_hl(qdf_nbuf_t msdu,struct htt_host_rx_desc_base * rx_desc)107*5113495bSYour Name void htt_set_checksum_result_hl(qdf_nbuf_t msdu,
108*5113495bSYour Name 				struct htt_host_rx_desc_base *rx_desc)
109*5113495bSYour Name {
110*5113495bSYour Name }
111*5113495bSYour Name #endif
112*5113495bSYour Name 
113*5113495bSYour Name /**
114*5113495bSYour Name  * htt_rx_fill_ring_count() - replenish rx msdu buffer
115*5113495bSYour Name  * @pdev: Handle (pointer) to HTT pdev.
116*5113495bSYour Name  *
117*5113495bSYour Name  * This function will replenish the rx buffer to the max number
118*5113495bSYour Name  * that can be kept in the ring
119*5113495bSYour Name  *
120*5113495bSYour Name  * Return: None
121*5113495bSYour Name  */
htt_rx_fill_ring_count(htt_pdev_handle pdev)122*5113495bSYour Name void htt_rx_fill_ring_count(htt_pdev_handle pdev)
123*5113495bSYour Name {
124*5113495bSYour Name }
125*5113495bSYour Name 
126*5113495bSYour Name /**
127*5113495bSYour Name  * htt_rx_mpdu_desc_list_next_hl() - provides an abstract way to obtain
128*5113495bSYour Name  *				     the next MPDU descriptor
129*5113495bSYour Name  * @pdev: the HTT instance the rx data was received on
130*5113495bSYour Name  * @rx_ind_msg: the netbuf containing the rx indication message
131*5113495bSYour Name  *
132*5113495bSYour Name  * for HL, the returned value is not mpdu_desc,
133*5113495bSYour Name  * it's translated hl_rx_desc just after the hl_ind_msg
134*5113495bSYour Name  * for HL AMSDU, we can't point to payload now, because
135*5113495bSYour Name  * hl rx desc is not fixed, we can't retrieve the desc
136*5113495bSYour Name  * by minus rx_desc_size when release. keep point to hl rx desc
137*5113495bSYour Name  * now
138*5113495bSYour Name  *
139*5113495bSYour Name  * Return: next abstract rx descriptor from the series of MPDUs
140*5113495bSYour Name  *		   referenced by an rx ind msg
141*5113495bSYour Name  */
142*5113495bSYour Name static inline void *
htt_rx_mpdu_desc_list_next_hl(htt_pdev_handle pdev,qdf_nbuf_t rx_ind_msg)143*5113495bSYour Name htt_rx_mpdu_desc_list_next_hl(htt_pdev_handle pdev, qdf_nbuf_t rx_ind_msg)
144*5113495bSYour Name {
145*5113495bSYour Name 	void *mpdu_desc = (void *)qdf_nbuf_data(rx_ind_msg);
146*5113495bSYour Name 	return mpdu_desc;
147*5113495bSYour Name }
148*5113495bSYour Name 
149*5113495bSYour Name /**
150*5113495bSYour Name  * htt_rx_msdu_desc_retrieve_hl() - Retrieve a previously-stored rx descriptor
151*5113495bSYour Name  *				    from a MSDU buffer
152*5113495bSYour Name  * @pdev: the HTT instance the rx data was received on
153*5113495bSYour Name  * @msdu - the buffer containing the MSDU payload
154*5113495bSYour Name  *
155*5113495bSYour Name  * currently for HL AMSDU, we don't point to payload.
156*5113495bSYour Name  * we shift to payload in ol_rx_deliver later
157*5113495bSYour Name  *
158*5113495bSYour Name  * Return: the corresponding abstract rx MSDU descriptor
159*5113495bSYour Name  */
160*5113495bSYour Name static inline void *
htt_rx_msdu_desc_retrieve_hl(htt_pdev_handle pdev,qdf_nbuf_t msdu)161*5113495bSYour Name htt_rx_msdu_desc_retrieve_hl(htt_pdev_handle pdev, qdf_nbuf_t msdu)
162*5113495bSYour Name {
163*5113495bSYour Name 	return qdf_nbuf_data(msdu);
164*5113495bSYour Name }
165*5113495bSYour Name 
166*5113495bSYour Name static
htt_rx_mpdu_is_encrypted_hl(htt_pdev_handle pdev,void * mpdu_desc)167*5113495bSYour Name bool htt_rx_mpdu_is_encrypted_hl(htt_pdev_handle pdev, void *mpdu_desc)
168*5113495bSYour Name {
169*5113495bSYour Name 	if (htt_rx_msdu_first_msdu_flag_hl(pdev, mpdu_desc) == true) {
170*5113495bSYour Name 		/* Fix Me: only for little endian */
171*5113495bSYour Name 		struct hl_htt_rx_desc_base *rx_desc =
172*5113495bSYour Name 			(struct hl_htt_rx_desc_base *)mpdu_desc;
173*5113495bSYour Name 
174*5113495bSYour Name 		return HTT_WORD_GET(*(u_int32_t *)rx_desc,
175*5113495bSYour Name 					HTT_HL_RX_DESC_MPDU_ENC);
176*5113495bSYour Name 	} else {
177*5113495bSYour Name 		/* not first msdu, no encrypt info for hl */
178*5113495bSYour Name 		qdf_print(
179*5113495bSYour Name 			"Error: get encrypted from a not-first msdu.\n");
180*5113495bSYour Name 		qdf_assert(0);
181*5113495bSYour Name 		return false;
182*5113495bSYour Name 	}
183*5113495bSYour Name }
184*5113495bSYour Name 
185*5113495bSYour Name static inline bool
htt_rx_msdu_chan_info_present_hl(htt_pdev_handle pdev,void * mpdu_desc)186*5113495bSYour Name htt_rx_msdu_chan_info_present_hl(htt_pdev_handle pdev, void *mpdu_desc)
187*5113495bSYour Name {
188*5113495bSYour Name 	if (htt_rx_msdu_first_msdu_flag_hl(pdev, mpdu_desc) == true &&
189*5113495bSYour Name 	    HTT_WORD_GET(*(u_int32_t *)mpdu_desc,
190*5113495bSYour Name 			 HTT_HL_RX_DESC_CHAN_INFO_PRESENT))
191*5113495bSYour Name 		return true;
192*5113495bSYour Name 
193*5113495bSYour Name 	return false;
194*5113495bSYour Name }
195*5113495bSYour Name 
196*5113495bSYour Name static bool
htt_rx_msdu_center_freq_hl(htt_pdev_handle pdev,struct ol_txrx_peer_t * peer,void * mpdu_desc,uint16_t * primary_chan_center_freq_mhz,uint16_t * contig_chan1_center_freq_mhz,uint16_t * contig_chan2_center_freq_mhz,uint8_t * phy_mode)197*5113495bSYour Name htt_rx_msdu_center_freq_hl(htt_pdev_handle pdev,
198*5113495bSYour Name 			   struct ol_txrx_peer_t *peer,
199*5113495bSYour Name 			   void *mpdu_desc,
200*5113495bSYour Name 			   uint16_t *primary_chan_center_freq_mhz,
201*5113495bSYour Name 			   uint16_t *contig_chan1_center_freq_mhz,
202*5113495bSYour Name 			   uint16_t *contig_chan2_center_freq_mhz,
203*5113495bSYour Name 			   uint8_t *phy_mode)
204*5113495bSYour Name {
205*5113495bSYour Name 	int pn_len, index;
206*5113495bSYour Name 	uint32_t *chan_info;
207*5113495bSYour Name 
208*5113495bSYour Name 	index = htt_rx_msdu_is_wlan_mcast(pdev, mpdu_desc) ?
209*5113495bSYour Name 		txrx_sec_mcast : txrx_sec_ucast;
210*5113495bSYour Name 
211*5113495bSYour Name 	pn_len = (peer ?
212*5113495bSYour Name 			pdev->txrx_pdev->rx_pn[peer->security[index].sec_type].
213*5113495bSYour Name 								len : 0);
214*5113495bSYour Name 	chan_info = (uint32_t *)((uint8_t *)mpdu_desc +
215*5113495bSYour Name 			HTT_HL_RX_DESC_PN_OFFSET + pn_len);
216*5113495bSYour Name 
217*5113495bSYour Name 	if (htt_rx_msdu_chan_info_present_hl(pdev, mpdu_desc)) {
218*5113495bSYour Name 		if (primary_chan_center_freq_mhz)
219*5113495bSYour Name 			*primary_chan_center_freq_mhz =
220*5113495bSYour Name 				HTT_WORD_GET(
221*5113495bSYour Name 					*chan_info,
222*5113495bSYour Name 					HTT_CHAN_INFO_PRIMARY_CHAN_CENTER_FREQ);
223*5113495bSYour Name 		if (contig_chan1_center_freq_mhz)
224*5113495bSYour Name 			*contig_chan1_center_freq_mhz =
225*5113495bSYour Name 				HTT_WORD_GET(
226*5113495bSYour Name 					*chan_info,
227*5113495bSYour Name 					HTT_CHAN_INFO_CONTIG_CHAN1_CENTER_FREQ);
228*5113495bSYour Name 		chan_info++;
229*5113495bSYour Name 		if (contig_chan2_center_freq_mhz)
230*5113495bSYour Name 			*contig_chan2_center_freq_mhz =
231*5113495bSYour Name 				HTT_WORD_GET(
232*5113495bSYour Name 					*chan_info,
233*5113495bSYour Name 					HTT_CHAN_INFO_CONTIG_CHAN2_CENTER_FREQ);
234*5113495bSYour Name 		if (phy_mode)
235*5113495bSYour Name 			*phy_mode =
236*5113495bSYour Name 				HTT_WORD_GET(*chan_info,
237*5113495bSYour Name 					     HTT_CHAN_INFO_PHY_MODE);
238*5113495bSYour Name 		return true;
239*5113495bSYour Name 	}
240*5113495bSYour Name 
241*5113495bSYour Name 	if (primary_chan_center_freq_mhz)
242*5113495bSYour Name 		*primary_chan_center_freq_mhz = 0;
243*5113495bSYour Name 	if (contig_chan1_center_freq_mhz)
244*5113495bSYour Name 		*contig_chan1_center_freq_mhz = 0;
245*5113495bSYour Name 	if (contig_chan2_center_freq_mhz)
246*5113495bSYour Name 		*contig_chan2_center_freq_mhz = 0;
247*5113495bSYour Name 	if (phy_mode)
248*5113495bSYour Name 		*phy_mode = 0;
249*5113495bSYour Name 	return false;
250*5113495bSYour Name }
251*5113495bSYour Name 
252*5113495bSYour Name static bool
htt_rx_msdu_desc_key_id_hl(htt_pdev_handle htt_pdev,void * mpdu_desc,u_int8_t * key_id)253*5113495bSYour Name htt_rx_msdu_desc_key_id_hl(htt_pdev_handle htt_pdev,
254*5113495bSYour Name 			   void *mpdu_desc, u_int8_t *key_id)
255*5113495bSYour Name {
256*5113495bSYour Name 	if (htt_rx_msdu_first_msdu_flag_hl(htt_pdev, mpdu_desc) == true) {
257*5113495bSYour Name 		/* Fix Me: only for little endian */
258*5113495bSYour Name 		struct hl_htt_rx_desc_base *rx_desc =
259*5113495bSYour Name 			(struct hl_htt_rx_desc_base *)mpdu_desc;
260*5113495bSYour Name 
261*5113495bSYour Name 		*key_id = rx_desc->key_id_oct;
262*5113495bSYour Name 		return true;
263*5113495bSYour Name 	}
264*5113495bSYour Name 
265*5113495bSYour Name 	return false;
266*5113495bSYour Name }
267*5113495bSYour Name 
268*5113495bSYour Name /**
269*5113495bSYour Name  * htt_rx_mpdu_desc_retry_hl() - Returns the retry bit from the Rx descriptor
270*5113495bSYour Name  *                               for the High Latency driver
271*5113495bSYour Name  * @pdev: Handle (pointer) to HTT pdev.
272*5113495bSYour Name  * @mpdu_desc: Void pointer to the Rx descriptor for MPDU
273*5113495bSYour Name  *             before the beginning of the payload.
274*5113495bSYour Name  *
275*5113495bSYour Name  *  This function returns the retry bit of the 802.11 header for the
276*5113495bSYour Name  *  provided rx MPDU descriptor. For the high latency driver, this function
277*5113495bSYour Name  *  pretends as if the retry bit is never set so that the mcast duplicate
278*5113495bSYour Name  *  detection never fails.
279*5113495bSYour Name  *
280*5113495bSYour Name  * Return:        boolean -- false always for HL
281*5113495bSYour Name  */
282*5113495bSYour Name static inline bool
htt_rx_mpdu_desc_retry_hl(htt_pdev_handle pdev,void * mpdu_desc)283*5113495bSYour Name htt_rx_mpdu_desc_retry_hl(htt_pdev_handle pdev, void *mpdu_desc)
284*5113495bSYour Name {
285*5113495bSYour Name 	return false;
286*5113495bSYour Name }
287*5113495bSYour Name 
288*5113495bSYour Name static int
htt_rx_amsdu_pop_hl(htt_pdev_handle pdev,qdf_nbuf_t rx_ind_msg,qdf_nbuf_t * head_msdu,qdf_nbuf_t * tail_msdu,uint32_t * msdu_count)289*5113495bSYour Name htt_rx_amsdu_pop_hl(
290*5113495bSYour Name 	htt_pdev_handle pdev,
291*5113495bSYour Name 	qdf_nbuf_t rx_ind_msg,
292*5113495bSYour Name 	qdf_nbuf_t *head_msdu,
293*5113495bSYour Name 	qdf_nbuf_t *tail_msdu,
294*5113495bSYour Name 	uint32_t *msdu_count)
295*5113495bSYour Name {
296*5113495bSYour Name 	pdev->rx_desc_size_hl =
297*5113495bSYour Name 		(qdf_nbuf_data(rx_ind_msg))
298*5113495bSYour Name 		[HTT_ENDIAN_BYTE_IDX_SWAP(
299*5113495bSYour Name 				HTT_RX_IND_HL_RX_DESC_LEN_OFFSET)];
300*5113495bSYour Name 
301*5113495bSYour Name 	/* point to the rx desc */
302*5113495bSYour Name 	qdf_nbuf_pull_head(rx_ind_msg,
303*5113495bSYour Name 			   sizeof(struct hl_htt_rx_ind_base));
304*5113495bSYour Name 	*head_msdu = *tail_msdu = rx_ind_msg;
305*5113495bSYour Name 
306*5113495bSYour Name 	htt_set_checksum_result_hl(rx_ind_msg,
307*5113495bSYour Name 				   (struct htt_host_rx_desc_base *)
308*5113495bSYour Name 				   (qdf_nbuf_data(rx_ind_msg)));
309*5113495bSYour Name 
310*5113495bSYour Name 	qdf_nbuf_set_next(*tail_msdu, NULL);
311*5113495bSYour Name 	return 0;
312*5113495bSYour Name }
313*5113495bSYour Name 
314*5113495bSYour Name static int
htt_rx_frag_pop_hl(htt_pdev_handle pdev,qdf_nbuf_t frag_msg,qdf_nbuf_t * head_msdu,qdf_nbuf_t * tail_msdu,uint32_t * msdu_count)315*5113495bSYour Name htt_rx_frag_pop_hl(
316*5113495bSYour Name 	htt_pdev_handle pdev,
317*5113495bSYour Name 	qdf_nbuf_t frag_msg,
318*5113495bSYour Name 	qdf_nbuf_t *head_msdu,
319*5113495bSYour Name 	qdf_nbuf_t *tail_msdu,
320*5113495bSYour Name 	uint32_t *msdu_count)
321*5113495bSYour Name {
322*5113495bSYour Name 	qdf_nbuf_pull_head(frag_msg, HTT_RX_FRAG_IND_BYTES);
323*5113495bSYour Name 	pdev->rx_desc_size_hl =
324*5113495bSYour Name 		(qdf_nbuf_data(frag_msg))
325*5113495bSYour Name 		[HTT_ENDIAN_BYTE_IDX_SWAP(
326*5113495bSYour Name 				HTT_RX_IND_HL_RX_DESC_LEN_OFFSET)];
327*5113495bSYour Name 
328*5113495bSYour Name 	/* point to the rx desc */
329*5113495bSYour Name 	qdf_nbuf_pull_head(frag_msg,
330*5113495bSYour Name 			   sizeof(struct hl_htt_rx_ind_base));
331*5113495bSYour Name 	*head_msdu = *tail_msdu = frag_msg;
332*5113495bSYour Name 
333*5113495bSYour Name 	qdf_nbuf_set_next(*tail_msdu, NULL);
334*5113495bSYour Name 	return 1;
335*5113495bSYour Name }
336*5113495bSYour Name 
337*5113495bSYour Name static inline int
htt_rx_offload_msdu_cnt_hl(htt_pdev_handle pdev)338*5113495bSYour Name htt_rx_offload_msdu_cnt_hl(htt_pdev_handle pdev)
339*5113495bSYour Name {
340*5113495bSYour Name 	return 1;
341*5113495bSYour Name }
342*5113495bSYour Name 
343*5113495bSYour Name static inline int
htt_rx_offload_msdu_pop_hl(htt_pdev_handle pdev,qdf_nbuf_t offload_deliver_msg,int * vdev_id,int * peer_id,int * tid,u_int8_t * fw_desc,qdf_nbuf_t * head_buf,qdf_nbuf_t * tail_buf)344*5113495bSYour Name htt_rx_offload_msdu_pop_hl(htt_pdev_handle pdev,
345*5113495bSYour Name 			   qdf_nbuf_t offload_deliver_msg,
346*5113495bSYour Name 			   int *vdev_id,
347*5113495bSYour Name 			   int *peer_id,
348*5113495bSYour Name 			   int *tid,
349*5113495bSYour Name 			   u_int8_t *fw_desc,
350*5113495bSYour Name 			   qdf_nbuf_t *head_buf,
351*5113495bSYour Name 			   qdf_nbuf_t *tail_buf)
352*5113495bSYour Name {
353*5113495bSYour Name 	qdf_nbuf_t buf;
354*5113495bSYour Name 	u_int32_t *msdu_hdr, msdu_len;
355*5113495bSYour Name 	int ret = 0;
356*5113495bSYour Name 
357*5113495bSYour Name 	*head_buf = *tail_buf = buf = offload_deliver_msg;
358*5113495bSYour Name 	msdu_hdr = (u_int32_t *)qdf_nbuf_data(buf);
359*5113495bSYour Name 	/* First dword */
360*5113495bSYour Name 
361*5113495bSYour Name 	/* Second dword */
362*5113495bSYour Name 	msdu_hdr++;
363*5113495bSYour Name 	msdu_len = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_LEN_GET(*msdu_hdr);
364*5113495bSYour Name 	*peer_id = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_PEER_ID_GET(*msdu_hdr);
365*5113495bSYour Name 
366*5113495bSYour Name 	/* Third dword */
367*5113495bSYour Name 	msdu_hdr++;
368*5113495bSYour Name 	*vdev_id = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_VDEV_ID_GET(*msdu_hdr);
369*5113495bSYour Name 	*tid = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_TID_GET(*msdu_hdr);
370*5113495bSYour Name 	*fw_desc = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_DESC_GET(*msdu_hdr);
371*5113495bSYour Name 
372*5113495bSYour Name 	qdf_nbuf_pull_head(buf, HTT_RX_OFFLOAD_DELIVER_IND_MSDU_HDR_BYTES
373*5113495bSYour Name 			+ HTT_RX_OFFLOAD_DELIVER_IND_HDR_BYTES);
374*5113495bSYour Name 
375*5113495bSYour Name 	if (msdu_len <= qdf_nbuf_len(buf)) {
376*5113495bSYour Name 		qdf_nbuf_set_pktlen(buf, msdu_len);
377*5113495bSYour Name 	} else {
378*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HTT, QDF_TRACE_LEVEL_ERROR,
379*5113495bSYour Name 			  "%s: drop frame with invalid msdu len %d %d",
380*5113495bSYour Name 			  __func__, msdu_len, (int)qdf_nbuf_len(buf));
381*5113495bSYour Name 		qdf_nbuf_free(offload_deliver_msg);
382*5113495bSYour Name 		ret = -1;
383*5113495bSYour Name 	}
384*5113495bSYour Name 
385*5113495bSYour Name 	return ret;
386*5113495bSYour Name }
387*5113495bSYour Name 
388*5113495bSYour Name static uint16_t
htt_rx_mpdu_desc_seq_num_hl(htt_pdev_handle pdev,void * mpdu_desc,bool update_seq_num)389*5113495bSYour Name htt_rx_mpdu_desc_seq_num_hl(htt_pdev_handle pdev, void *mpdu_desc,
390*5113495bSYour Name 			    bool update_seq_num)
391*5113495bSYour Name {
392*5113495bSYour Name 	if (pdev->rx_desc_size_hl) {
393*5113495bSYour Name 		if (update_seq_num)
394*5113495bSYour Name 			return pdev->cur_seq_num_hl =
395*5113495bSYour Name 			       (u_int16_t)(HTT_WORD_GET(*(u_int32_t *)mpdu_desc,
396*5113495bSYour Name 					   HTT_HL_RX_DESC_MPDU_SEQ_NUM));
397*5113495bSYour Name 		else
398*5113495bSYour Name 			return (u_int16_t)(HTT_WORD_GET(*(u_int32_t *)mpdu_desc,
399*5113495bSYour Name 					   HTT_HL_RX_DESC_MPDU_SEQ_NUM));
400*5113495bSYour Name 	} else {
401*5113495bSYour Name 		return (u_int16_t)(pdev->cur_seq_num_hl);
402*5113495bSYour Name 	}
403*5113495bSYour Name }
404*5113495bSYour Name 
405*5113495bSYour Name static void
htt_rx_mpdu_desc_pn_hl(htt_pdev_handle pdev,void * mpdu_desc,union htt_rx_pn_t * pn,int pn_len_bits)406*5113495bSYour Name htt_rx_mpdu_desc_pn_hl(
407*5113495bSYour Name 	htt_pdev_handle pdev,
408*5113495bSYour Name 	void *mpdu_desc,
409*5113495bSYour Name 	union htt_rx_pn_t *pn,
410*5113495bSYour Name 	int pn_len_bits)
411*5113495bSYour Name {
412*5113495bSYour Name 	if (htt_rx_msdu_first_msdu_flag_hl(pdev, mpdu_desc) == true) {
413*5113495bSYour Name 		/* Fix Me: only for little endian */
414*5113495bSYour Name 		struct hl_htt_rx_desc_base *rx_desc =
415*5113495bSYour Name 			(struct hl_htt_rx_desc_base *)mpdu_desc;
416*5113495bSYour Name 		u_int32_t *word_ptr = (u_int32_t *)pn->pn128;
417*5113495bSYour Name 
418*5113495bSYour Name 		/* TODO: for Host of big endian */
419*5113495bSYour Name 		switch (pn_len_bits) {
420*5113495bSYour Name 		case 128:
421*5113495bSYour Name 			/* bits 128:64 */
422*5113495bSYour Name 			*(word_ptr + 3) = rx_desc->pn_127_96;
423*5113495bSYour Name 			/* bits 63:0 */
424*5113495bSYour Name 			*(word_ptr + 2) = rx_desc->pn_95_64;
425*5113495bSYour Name 		case 48:
426*5113495bSYour Name 			/* bits 48:0
427*5113495bSYour Name 			 * copy 64 bits
428*5113495bSYour Name 			 */
429*5113495bSYour Name 			*(word_ptr + 1) = rx_desc->u0.pn_63_32;
430*5113495bSYour Name 		case 24:
431*5113495bSYour Name 			/* bits 23:0
432*5113495bSYour Name 			 * copy 32 bits
433*5113495bSYour Name 			 */
434*5113495bSYour Name 			*(word_ptr + 0) = rx_desc->pn_31_0;
435*5113495bSYour Name 			break;
436*5113495bSYour Name 		default:
437*5113495bSYour Name 			QDF_TRACE(QDF_MODULE_ID_HTT, QDF_TRACE_LEVEL_ERROR,
438*5113495bSYour Name 				  "Error: invalid length spec (%d bits) for PN",
439*5113495bSYour Name 				  pn_len_bits);
440*5113495bSYour Name 			qdf_assert(0);
441*5113495bSYour Name 			break;
442*5113495bSYour Name 		};
443*5113495bSYour Name 	} else {
444*5113495bSYour Name 		/* not first msdu, no pn info */
445*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HTT, QDF_TRACE_LEVEL_ERROR,
446*5113495bSYour Name 			  "Error: get pn from a not-first msdu.");
447*5113495bSYour Name 		qdf_assert(0);
448*5113495bSYour Name 	}
449*5113495bSYour Name }
450*5113495bSYour Name 
451*5113495bSYour Name /**
452*5113495bSYour Name  * htt_rx_mpdu_desc_tid_hl() - Returns the TID value from the Rx descriptor
453*5113495bSYour Name  *                             for High Latency driver
454*5113495bSYour Name  * @pdev:                        Handle (pointer) to HTT pdev.
455*5113495bSYour Name  * @mpdu_desc:                   Void pointer to the Rx descriptor for the MPDU
456*5113495bSYour Name  *                               before the beginning of the payload.
457*5113495bSYour Name  *
458*5113495bSYour Name  * This function returns the TID set in the 802.11 QoS Control for the MPDU
459*5113495bSYour Name  * in the packet header, by looking at the mpdu_start of the Rx descriptor.
460*5113495bSYour Name  * Rx descriptor gets a copy of the TID from the MAC.
461*5113495bSYour Name  * For the HL driver, this is currently uimplemented and always returns
462*5113495bSYour Name  * an invalid tid. It is the responsibility of the caller to make
463*5113495bSYour Name  * sure that return value is checked for valid range.
464*5113495bSYour Name  *
465*5113495bSYour Name  * Return:        Invalid TID value (0xff) for HL driver.
466*5113495bSYour Name  */
467*5113495bSYour Name static inline uint8_t
htt_rx_mpdu_desc_tid_hl(htt_pdev_handle pdev,void * mpdu_desc)468*5113495bSYour Name htt_rx_mpdu_desc_tid_hl(htt_pdev_handle pdev, void *mpdu_desc)
469*5113495bSYour Name {
470*5113495bSYour Name 	return 0xff;  /* Invalid TID */
471*5113495bSYour Name }
472*5113495bSYour Name 
473*5113495bSYour Name static inline bool
htt_rx_msdu_desc_completes_mpdu_hl(htt_pdev_handle pdev,void * msdu_desc)474*5113495bSYour Name htt_rx_msdu_desc_completes_mpdu_hl(htt_pdev_handle pdev, void *msdu_desc)
475*5113495bSYour Name {
476*5113495bSYour Name 	return (
477*5113495bSYour Name 		((u_int8_t *)(msdu_desc) - sizeof(struct hl_htt_rx_ind_base))
478*5113495bSYour Name 		[HTT_ENDIAN_BYTE_IDX_SWAP(HTT_RX_IND_HL_FLAG_OFFSET)]
479*5113495bSYour Name 		& HTT_RX_IND_HL_FLAG_LAST_MSDU)
480*5113495bSYour Name 		? true : false;
481*5113495bSYour Name }
482*5113495bSYour Name 
483*5113495bSYour Name static inline int
htt_rx_msdu_has_wlan_mcast_flag_hl(htt_pdev_handle pdev,void * msdu_desc)484*5113495bSYour Name htt_rx_msdu_has_wlan_mcast_flag_hl(htt_pdev_handle pdev, void *msdu_desc)
485*5113495bSYour Name {
486*5113495bSYour Name 	/* currently, only first msdu has hl rx_desc */
487*5113495bSYour Name 	return htt_rx_msdu_first_msdu_flag_hl(pdev, msdu_desc) == true;
488*5113495bSYour Name }
489*5113495bSYour Name 
490*5113495bSYour Name static inline bool
htt_rx_msdu_is_wlan_mcast_hl(htt_pdev_handle pdev,void * msdu_desc)491*5113495bSYour Name htt_rx_msdu_is_wlan_mcast_hl(htt_pdev_handle pdev, void *msdu_desc)
492*5113495bSYour Name {
493*5113495bSYour Name 	struct hl_htt_rx_desc_base *rx_desc =
494*5113495bSYour Name 		(struct hl_htt_rx_desc_base *)msdu_desc;
495*5113495bSYour Name 
496*5113495bSYour Name 	return
497*5113495bSYour Name 		HTT_WORD_GET(*(u_int32_t *)rx_desc, HTT_HL_RX_DESC_MCAST_BCAST);
498*5113495bSYour Name }
499*5113495bSYour Name 
500*5113495bSYour Name static inline int
htt_rx_msdu_is_frag_hl(htt_pdev_handle pdev,void * msdu_desc)501*5113495bSYour Name htt_rx_msdu_is_frag_hl(htt_pdev_handle pdev, void *msdu_desc)
502*5113495bSYour Name {
503*5113495bSYour Name 	struct hl_htt_rx_desc_base *rx_desc =
504*5113495bSYour Name 		(struct hl_htt_rx_desc_base *)msdu_desc;
505*5113495bSYour Name 
506*5113495bSYour Name 	return
507*5113495bSYour Name 		HTT_WORD_GET(*(u_int32_t *)rx_desc, HTT_HL_RX_DESC_MCAST_BCAST);
508*5113495bSYour Name }
509*5113495bSYour Name 
htt_rx_attach(struct htt_pdev_t * pdev)510*5113495bSYour Name int htt_rx_attach(struct htt_pdev_t *pdev)
511*5113495bSYour Name {
512*5113495bSYour Name 	pdev->rx_ring.size = HTT_RX_RING_SIZE_MIN;
513*5113495bSYour Name 	HTT_ASSERT2(IS_PWR2(pdev->rx_ring.size));
514*5113495bSYour Name 	pdev->rx_ring.size_mask = pdev->rx_ring.size - 1;
515*5113495bSYour Name 	/* host can force ring base address if it wish to do so */
516*5113495bSYour Name 	pdev->rx_ring.base_paddr = 0;
517*5113495bSYour Name 	htt_rx_amsdu_pop = htt_rx_amsdu_pop_hl;
518*5113495bSYour Name 	htt_rx_frag_pop = htt_rx_frag_pop_hl;
519*5113495bSYour Name 	htt_rx_offload_msdu_cnt = htt_rx_offload_msdu_cnt_hl;
520*5113495bSYour Name 	htt_rx_offload_msdu_pop = htt_rx_offload_msdu_pop_hl;
521*5113495bSYour Name 	htt_rx_mpdu_desc_list_next = htt_rx_mpdu_desc_list_next_hl;
522*5113495bSYour Name 	htt_rx_mpdu_desc_retry = htt_rx_mpdu_desc_retry_hl;
523*5113495bSYour Name 	htt_rx_mpdu_desc_seq_num = htt_rx_mpdu_desc_seq_num_hl;
524*5113495bSYour Name 	htt_rx_mpdu_desc_pn = htt_rx_mpdu_desc_pn_hl;
525*5113495bSYour Name 	htt_rx_mpdu_desc_tid = htt_rx_mpdu_desc_tid_hl;
526*5113495bSYour Name 	htt_rx_msdu_desc_completes_mpdu = htt_rx_msdu_desc_completes_mpdu_hl;
527*5113495bSYour Name 	htt_rx_msdu_first_msdu_flag = htt_rx_msdu_first_msdu_flag_hl;
528*5113495bSYour Name 	htt_rx_msdu_has_wlan_mcast_flag = htt_rx_msdu_has_wlan_mcast_flag_hl;
529*5113495bSYour Name 	htt_rx_msdu_is_wlan_mcast = htt_rx_msdu_is_wlan_mcast_hl;
530*5113495bSYour Name 	htt_rx_msdu_is_frag = htt_rx_msdu_is_frag_hl;
531*5113495bSYour Name 	htt_rx_msdu_desc_retrieve = htt_rx_msdu_desc_retrieve_hl;
532*5113495bSYour Name 	htt_rx_mpdu_is_encrypted = htt_rx_mpdu_is_encrypted_hl;
533*5113495bSYour Name 	htt_rx_msdu_desc_key_id = htt_rx_msdu_desc_key_id_hl;
534*5113495bSYour Name 	htt_rx_msdu_chan_info_present = htt_rx_msdu_chan_info_present_hl;
535*5113495bSYour Name 	htt_rx_msdu_center_freq = htt_rx_msdu_center_freq_hl;
536*5113495bSYour Name 
537*5113495bSYour Name 	/*
538*5113495bSYour Name 	 * HL case, the rx descriptor can be different sizes for
539*5113495bSYour Name 	 * different sub-types of RX_IND messages, e.g. for the
540*5113495bSYour Name 	 * initial vs. interior vs. final MSDUs within a PPDU.
541*5113495bSYour Name 	 * The size of each RX_IND message's rx desc is read from
542*5113495bSYour Name 	 * a field within the RX_IND message itself.
543*5113495bSYour Name 	 * In the meantime, until the rx_desc_size_hl variable is
544*5113495bSYour Name 	 * set to its real value based on the RX_IND message,
545*5113495bSYour Name 	 * initialize it to a reasonable value (zero).
546*5113495bSYour Name 	 */
547*5113495bSYour Name 	pdev->rx_desc_size_hl = 0;
548*5113495bSYour Name 	return 0;	/* success */
549*5113495bSYour Name }
550