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