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