xref: /wlan-dirver/qca-wifi-host-cmn/hal/wifi3.0/hal_api_mon.h (revision ef615e7655641c631b491672197920d85ac046d8)
1 /*
2  * Copyright (c) 2017 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #ifndef _HAL_API_MON_H_
20 #define _HAL_API_MON_H_
21 
22 #include "qdf_types.h"
23 #include "hal_internal.h"
24 
25 #define HAL_RX_OFFSET(block, field) block##_##field##_OFFSET
26 #define HAL_RX_LSB(block, field) block##_##field##_LSB
27 #define HAL_RX_MASk(block, field) block##_##field##_MASK
28 
29 #define HAL_RX_GET(_ptr, block, field) \
30 	(((*((volatile uint32_t *)_ptr + (HAL_RX_OFFSET(block, field)>>2))) & \
31 	HAL_RX_MASk(block, field)) >> \
32 	HAL_RX_LSB(block, field))
33 
34 #define HAL_RX_PHY_DATA_RADAR 0x01
35 #define HAL_SU_MU_CODING_LDPC 0x01
36 
37 #define HAL_RX_FCS_LEN (4)
38 #define KEY_EXTIV 0x20
39 
40 #define HAL_RX_USER_TLV32_TYPE_OFFSET		0x00000000
41 #define HAL_RX_USER_TLV32_TYPE_LSB		1
42 #define HAL_RX_USER_TLV32_TYPE_MASK		0x000003FE
43 
44 #define HAL_RX_USER_TLV32_LEN_OFFSET		0x00000000
45 #define HAL_RX_USER_TLV32_LEN_LSB		10
46 #define HAL_RX_USER_TLV32_LEN_MASK		0x003FFC00
47 
48 #define HAL_RX_USER_TLV32_USERID_OFFSET		0x00000000
49 #define HAL_RX_USER_TLV32_USERID_LSB		26
50 #define HAL_RX_USER_TLV32_USERID_MASK		0xFC000000
51 
52 #define HAL_ALIGN(x, a)				HAL_ALIGN_MASK(x, (a)-1)
53 #define HAL_ALIGN_MASK(x, mask)	(typeof(x))(((uint32)(x) + (mask)) & ~(mask))
54 
55 #define HAL_RX_TLV32_HDR_SIZE			4
56 
57 #define HAL_RX_GET_USER_TLV32_TYPE(rx_status_tlv_ptr) \
58 		((*((uint32_t *)(rx_status_tlv_ptr)) & \
59 		HAL_RX_USER_TLV32_TYPE_MASK) >> \
60 		HAL_RX_USER_TLV32_TYPE_LSB)
61 
62 #define HAL_RX_GET_USER_TLV32_LEN(rx_status_tlv_ptr) \
63 		((*((uint32_t *)(rx_status_tlv_ptr)) & \
64 		HAL_RX_USER_TLV32_LEN_MASK) >> \
65 		HAL_RX_USER_TLV32_LEN_LSB)
66 
67 #define HAL_RX_GET_USER_TLV32_USERID(rx_status_tlv_ptr) \
68 		((*((uint32_t *)(rx_status_tlv_ptr)) & \
69 		HAL_RX_USER_TLV32_USERID_MASK) >> \
70 		HAL_RX_USER_TLV32_USERID_LSB)
71 
72 #define HAL_TLV_STATUS_PPDU_NOT_DONE		0
73 #define HAL_TLV_STATUS_PPDU_DONE		1
74 #define HAL_TLV_STATUS_BUF_DONE			2
75 
76 #define HAL_MAX_UL_MU_USERS			8
77 
78 #define HAL_RX_PKT_TYPE_11A	0
79 #define HAL_RX_PKT_TYPE_11B	1
80 #define HAL_RX_PKT_TYPE_11N	2
81 #define HAL_RX_PKT_TYPE_11AC	3
82 #define HAL_RX_PKT_TYPE_11AX	4
83 
84 #define HAL_RX_RECEPTION_TYPE_SU	0
85 #define HAL_RX_RECEPTION_TYPE_MU_MIMO	1
86 #define HAL_RX_RECEPTION_TYPE_OFDMA	2
87 #define HAL_RX_RECEPTION_TYPE_MU_OFDMA	3
88 
89 #define HAL_11B_RATE_0MCS	11
90 #define HAL_11B_RATE_1MCS	5.5
91 #define HAL_11B_RATE_2MCS	2
92 #define HAL_11B_RATE_3MCS	1
93 #define HAL_11B_RATE_4MCS	11
94 #define HAL_11B_RATE_5MCS	5.5
95 #define HAL_11B_RATE_6MCS	2
96 
97 #define HAL_11A_RATE_0MCS	48
98 #define HAL_11A_RATE_1MCS	24
99 #define HAL_11A_RATE_2MCS	12
100 #define HAL_11A_RATE_3MCS	6
101 #define HAL_11A_RATE_4MCS	54
102 #define HAL_11A_RATE_5MCS	36
103 #define HAL_11A_RATE_6MCS	18
104 #define HAL_11A_RATE_7MCS	9
105 
106 enum {
107 	HAL_HW_RX_DECAP_FORMAT_RAW = 0,
108 	HAL_HW_RX_DECAP_FORMAT_NWIFI,
109 	HAL_HW_RX_DECAP_FORMAT_ETH2,
110 	HAL_HW_RX_DECAP_FORMAT_8023,
111 };
112 
113 enum {
114 	DP_PPDU_STATUS_START,
115 	DP_PPDU_STATUS_DONE,
116 };
117 
118 static inline
119 uint32_t HAL_RX_MON_HW_RX_DESC_SIZE(void)
120 {
121 	/* return the HW_RX_DESC size */
122 	return sizeof(struct rx_pkt_tlvs);
123 }
124 
125 static inline
126 uint8_t *HAL_RX_MON_DEST_GET_DESC(uint8_t *data)
127 {
128 	return data;
129 }
130 
131 static inline
132 uint32_t HAL_RX_DESC_GET_MPDU_LENGTH_ERR(void *hw_desc_addr)
133 {
134 	struct rx_attention *rx_attn;
135 	struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr;
136 
137 	rx_attn = &rx_desc->attn_tlv.rx_attn;
138 
139 	return HAL_RX_GET(rx_attn, RX_ATTENTION_1, MPDU_LENGTH_ERR);
140 }
141 
142 static inline
143 uint32_t HAL_RX_DESC_GET_MPDU_FCS_ERR(void *hw_desc_addr)
144 {
145 	struct rx_attention *rx_attn;
146 	struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr;
147 
148 	rx_attn = &rx_desc->attn_tlv.rx_attn;
149 
150 	return HAL_RX_GET(rx_attn, RX_ATTENTION_1, FCS_ERR);
151 }
152 
153 static inline
154 uint32_t
155 HAL_RX_DESC_GET_DECAP_FORMAT(void *hw_desc_addr) {
156 	struct rx_msdu_start *rx_msdu_start;
157 	struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr;
158 
159 	rx_msdu_start = &rx_desc->msdu_start_tlv.rx_msdu_start;
160 
161 	return HAL_RX_GET(rx_msdu_start, RX_MSDU_START_2, DECAP_FORMAT);
162 }
163 
164 static inline
165 uint8_t *
166 HAL_RX_DESC_GET_80211_HDR(void *hw_desc_addr) {
167 	uint8_t *rx_pkt_hdr;
168 	struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr;
169 
170 	rx_pkt_hdr = &rx_desc->pkt_hdr_tlv.rx_pkt_hdr[0];
171 
172 	return rx_pkt_hdr;
173 }
174 
175 static inline
176 uint32_t HAL_RX_MON_HW_DESC_GET_PPDUID_GET(void *hw_desc_addr)
177 {
178 	struct rx_mpdu_info *rx_mpdu_info;
179 	struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr;
180 
181 	rx_mpdu_info =
182 		&rx_desc->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details;
183 
184 	return HAL_RX_GET(rx_mpdu_info, RX_MPDU_INFO_0, PHY_PPDU_ID);
185 }
186 
187 /* TODO: Move all Rx descriptor functions to hal_rx.h to avoid duplication */
188 static inline
189 uint32_t hal_rx_desc_is_first_msdu(void *hw_desc_addr)
190 {
191 	struct rx_pkt_tlvs *rx_tlvs = (struct rx_pkt_tlvs *)hw_desc_addr;
192 	struct rx_msdu_end *msdu_end = &rx_tlvs->msdu_end_tlv.rx_msdu_end;
193 
194 	return HAL_RX_GET(msdu_end, RX_MSDU_END_5, FIRST_MSDU);
195 }
196 
197 #define HAL_RX_BUFFER_ADDR_31_0_GET(buff_addr_info)		\
198 	(_HAL_MS((*_OFFSET_TO_WORD_PTR(buff_addr_info,		\
199 		BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_OFFSET)),	\
200 		BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_MASK,	\
201 		BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_LSB))
202 
203 #define HAL_RX_REO_ENT_BUFFER_ADDR_39_32_GET(reo_ent_desc)	\
204 	(HAL_RX_BUFFER_ADDR_39_32_GET(&				\
205 		(((struct reo_entrance_ring *)reo_ent_desc)	\
206 			->reo_level_mpdu_frame_info.msdu_link_desc_addr_info)))
207 
208 #define HAL_RX_REO_ENT_BUFFER_ADDR_31_0_GET(reo_ent_desc)	\
209 	(HAL_RX_BUFFER_ADDR_31_0_GET(&				\
210 		(((struct reo_entrance_ring *)reo_ent_desc)	\
211 			->reo_level_mpdu_frame_info.msdu_link_desc_addr_info)))
212 
213 #define HAL_RX_REO_ENT_BUF_COOKIE_GET(reo_ent_desc)		\
214 	(HAL_RX_BUF_COOKIE_GET(&					\
215 		(((struct reo_entrance_ring *)reo_ent_desc)	\
216 			->reo_level_mpdu_frame_info.msdu_link_desc_addr_info)))
217 
218 /**
219  * hal_rx_reo_ent_buf_paddr_get: Gets the physical address and
220  * cookie from the REO entrance ring element
221  *
222  * @ hal_rx_desc_cookie: Opaque cookie pointer used by HAL to get to
223  * the current descriptor
224  * @ buf_info: structure to return the buffer information
225  * @ msdu_cnt: pointer to msdu count in MPDU
226  * Return: void
227  */
228 static inline
229 void hal_rx_reo_ent_buf_paddr_get(void *rx_desc,
230 	struct hal_buf_info *buf_info,
231 	void **pp_buf_addr_info,
232 	uint32_t *msdu_cnt
233 )
234 {
235 	struct reo_entrance_ring *reo_ent_ring =
236 		(struct reo_entrance_ring *)rx_desc;
237 	struct buffer_addr_info *buf_addr_info;
238 	struct rx_mpdu_desc_info *rx_mpdu_desc_info_details;
239 	uint32_t loop_cnt;
240 
241 	rx_mpdu_desc_info_details =
242 	&reo_ent_ring->reo_level_mpdu_frame_info.rx_mpdu_desc_info_details;
243 
244 	*msdu_cnt = HAL_RX_GET(rx_mpdu_desc_info_details,
245 				RX_MPDU_DESC_INFO_0, MSDU_COUNT);
246 
247 	loop_cnt = HAL_RX_GET(reo_ent_ring, REO_ENTRANCE_RING_7, LOOPING_COUNT);
248 
249 	buf_addr_info =
250 	&reo_ent_ring->reo_level_mpdu_frame_info.msdu_link_desc_addr_info;
251 
252 	buf_info->paddr =
253 		(HAL_RX_BUFFER_ADDR_31_0_GET(buf_addr_info) |
254 		((uint64_t)
255 		(HAL_RX_BUFFER_ADDR_39_32_GET(buf_addr_info)) << 32));
256 
257 	buf_info->sw_cookie = HAL_RX_BUF_COOKIE_GET(buf_addr_info);
258 
259 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
260 		"[%s][%d] ReoAddr=%pK, addrInfo=%pK, paddr=0x%llx, loopcnt=%d\n",
261 		__func__, __LINE__, reo_ent_ring, buf_addr_info,
262 	(unsigned long long)buf_info->paddr, loop_cnt);
263 
264 	*pp_buf_addr_info = (void *)buf_addr_info;
265 }
266 
267 static inline
268 void hal_rx_mon_next_link_desc_get(void *rx_msdu_link_desc,
269 	struct hal_buf_info *buf_info, void **pp_buf_addr_info)
270 {
271 	struct rx_msdu_link *msdu_link =
272 		(struct rx_msdu_link *)rx_msdu_link_desc;
273 	struct buffer_addr_info *buf_addr_info;
274 
275 	buf_addr_info = &msdu_link->next_msdu_link_desc_addr_info;
276 
277 	buf_info->paddr =
278 		(HAL_RX_BUFFER_ADDR_31_0_GET(buf_addr_info) |
279 		((uint64_t)
280 		(HAL_RX_BUFFER_ADDR_39_32_GET(buf_addr_info)) << 32));
281 
282 	buf_info->sw_cookie = HAL_RX_BUF_COOKIE_GET(buf_addr_info);
283 
284 	*pp_buf_addr_info = (void *)buf_addr_info;
285 }
286 
287 /**
288  * hal_rx_msdu_link_desc_set: Retrieves MSDU Link Descriptor to WBM
289  *
290  * @ soc		: HAL version of the SOC pointer
291  * @ src_srng_desc	: void pointer to the WBM Release Ring descriptor
292  * @ buf_addr_info	: void pointer to the buffer_addr_info
293  *
294  * Return: void
295  */
296 
297 static inline void hal_rx_mon_msdu_link_desc_set(struct hal_soc *soc,
298 			void *src_srng_desc, void *buf_addr_info)
299 {
300 	struct buffer_addr_info *wbm_srng_buffer_addr_info =
301 			(struct buffer_addr_info *)src_srng_desc;
302 	uint64_t paddr;
303 	struct buffer_addr_info *p_buffer_addr_info =
304 			(struct buffer_addr_info *)buf_addr_info;
305 
306 	paddr =
307 		(HAL_RX_BUFFER_ADDR_31_0_GET(buf_addr_info) |
308 		((uint64_t)
309 		(HAL_RX_BUFFER_ADDR_39_32_GET(buf_addr_info)) << 32));
310 
311 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
312 		"[%s][%d] src_srng_desc=%pK, buf_addr=0x%llx, cookie=0x%llx\n",
313 		__func__, __LINE__, src_srng_desc, (unsigned long long)paddr,
314 		(unsigned long long)p_buffer_addr_info->sw_buffer_cookie);
315 
316 	/* Structure copy !!! */
317 	*wbm_srng_buffer_addr_info =
318 		*((struct buffer_addr_info *)buf_addr_info);
319 }
320 
321 static inline
322 uint32 hal_get_rx_msdu_link_desc_size(void)
323 {
324 	return sizeof(struct rx_msdu_link);
325 }
326 
327 enum {
328 	HAL_PKT_TYPE_OFDM = 0,
329 	HAL_PKT_TYPE_CCK,
330 	HAL_PKT_TYPE_HT,
331 	HAL_PKT_TYPE_VHT,
332 	HAL_PKT_TYPE_HE,
333 };
334 
335 enum {
336 	HAL_SGI_0_8_US,
337 	HAL_SGI_0_4_US,
338 	HAL_SGI_1_6_US,
339 	HAL_SGI_3_2_US,
340 };
341 
342 enum {
343 	HAL_FULL_RX_BW_20,
344 	HAL_FULL_RX_BW_40,
345 	HAL_FULL_RX_BW_80,
346 	HAL_FULL_RX_BW_160,
347 };
348 
349 enum {
350 	HAL_RX_TYPE_SU,
351 	HAL_RX_TYPE_MU_MIMO,
352 	HAL_RX_TYPE_MU_OFDMA,
353 	HAL_RX_TYPE_MU_OFDMA_MIMO,
354 };
355 
356 /**
357  * hal_rx_mon_hw_desc_get_mpdu_status: Retrieve MPDU status
358  *
359  * @ hw_desc_addr: Start address of Rx HW TLVs
360  * @ rs: Status for monitor mode
361  *
362  * Return: void
363  */
364 static inline
365 void hal_rx_mon_hw_desc_get_mpdu_status(void *hw_desc_addr,
366 		struct mon_rx_status *rs)
367 {
368 	struct rx_msdu_start *rx_msdu_start;
369 	struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr;
370 	uint32_t reg_value;
371 	uint8_t nss = 0;
372 	static uint32_t sgi_hw_to_cdp[] = {
373 		CDP_SGI_0_8_US,
374 		CDP_SGI_0_4_US,
375 		CDP_SGI_1_6_US,
376 		CDP_SGI_3_2_US,
377 	};
378 
379 	rx_msdu_start = &rx_desc->msdu_start_tlv.rx_msdu_start;
380 
381 	rs->ant_signal_db = HAL_RX_GET(rx_msdu_start,
382 					RX_MSDU_START_5, USER_RSSI);
383 	rs->mcs = HAL_RX_GET(rx_msdu_start,
384 					RX_MSDU_START_5, RATE_MCS);
385 	rs->is_stbc = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, STBC);
386 
387 	reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, SGI);
388 	rs->sgi = sgi_hw_to_cdp[reg_value];
389 	rs->nr_ant = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, NSS);
390 
391 	reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, PKT_TYPE);
392 	switch (reg_value) {
393 	case HAL_RX_PKT_TYPE_11N:
394 		rs->ht_flags = 1;
395 		rs->bw = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5,
396 			RECEIVE_BANDWIDTH);
397 		break;
398 	case HAL_RX_PKT_TYPE_11AC:
399 		rs->vht_flags = 1;
400 		reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5,
401 			RECEIVE_BANDWIDTH);
402 		rs->vht_flag_values2 = reg_value;
403 		nss = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, NSS);
404 		nss = nss + 1;
405 		rs->vht_flag_values3[0] = (rs->mcs << 4) | nss ;
406 		break;
407 	case HAL_RX_PKT_TYPE_11AX:
408 		rs->he_flags = 1;
409 		break;
410 	default:
411 		break;
412 	}
413 	reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEPTION_TYPE);
414 	rs->beamformed = (reg_value == HAL_RX_RECEPTION_TYPE_MU_MIMO) ? 1 : 0;
415 	/* TODO: rs->beamformed should be set for SU beamforming also */
416 }
417 
418 struct hal_rx_ppdu_user_info {
419 
420 };
421 
422 struct hal_rx_ppdu_common_info {
423 	uint32_t ppdu_id;
424 	uint32_t ppdu_timestamp;
425 };
426 
427 struct hal_rx_ppdu_info {
428 	struct hal_rx_ppdu_common_info com_info;
429 	struct hal_rx_ppdu_user_info user_info[HAL_MAX_UL_MU_USERS];
430 	struct mon_rx_status rx_status;
431 };
432 
433 static inline uint32_t
434 hal_get_rx_status_buf_size(void) {
435 	/* RX status buffer size is hard coded for now */
436 	return 2048;
437 }
438 
439 static inline uint8_t*
440 hal_rx_status_get_next_tlv(uint8_t *rx_tlv) {
441 	uint32_t tlv_len, tlv_tag;
442 
443 	tlv_len = HAL_RX_GET_USER_TLV32_LEN(rx_tlv);
444 	tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv);
445 
446 	/* The actual length of PPDU_END is the combined lenght of many PHY
447 	 * TLVs that follow. Skip the TLV header and
448 	 * rx_rxpcu_classification_overview that follows the header to get to
449 	 * next TLV.
450 	 */
451 	if (tlv_tag == WIFIRX_PPDU_END_E)
452 		tlv_len = sizeof(struct rx_rxpcu_classification_overview);
453 
454 	return (uint8_t *)(((unsigned long)(rx_tlv + tlv_len +
455 			HAL_RX_TLV32_HDR_SIZE + 3)) & (~((unsigned long)3)));
456 }
457 
458 static inline uint32_t
459 hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info)
460 {
461 	uint32_t tlv_tag, user_id, tlv_len, value;
462 	uint8_t group_id = 0;
463 
464 	tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv);
465 	user_id = HAL_RX_GET_USER_TLV32_USERID(rx_tlv);
466 	tlv_len = HAL_RX_GET_USER_TLV32_LEN(rx_tlv);
467 
468 	rx_tlv = (uint8_t *) rx_tlv + HAL_RX_TLV32_HDR_SIZE;
469 
470 	switch (tlv_tag) {
471 
472 	case WIFIRX_PPDU_START_E:
473 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
474 			"[%s][%d] ppdu_start_e len=%d\n",
475 					__func__, __LINE__, tlv_len);
476 		ppdu_info->com_info.ppdu_id =
477 			HAL_RX_GET(rx_tlv, RX_PPDU_START_0,
478 				PHY_PPDU_ID);
479 		/* TODO: Ensure channel number is set in PHY meta data */
480 		ppdu_info->rx_status.chan_freq =
481 			HAL_RX_GET(rx_tlv, RX_PPDU_START_1,
482 				SW_PHY_META_DATA);
483 		ppdu_info->com_info.ppdu_timestamp =
484 			HAL_RX_GET(rx_tlv, RX_PPDU_START_2,
485 				PPDU_START_TIMESTAMP);
486 		break;
487 
488 	case WIFIRX_PPDU_START_USER_INFO_E:
489 		break;
490 
491 	case WIFIRX_PPDU_END_E:
492 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
493 			"[%s][%d] ppdu_end_e len=%d\n",
494 				__func__, __LINE__, tlv_len);
495 		/* This is followed by sub-TLVs of PPDU_END */
496 
497 		ppdu_info->rx_status.duration =
498 			HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_8,
499 					RX_PPDU_DURATION);
500 		break;
501 
502 	case WIFIRXPCU_PPDU_END_INFO_E:
503 		ppdu_info->rx_status.tsft =
504 			HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_1,
505 				WB_TIMESTAMP_UPPER_32);
506 		ppdu_info->rx_status.tsft = (ppdu_info->rx_status.tsft << 32) |
507 			HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_0,
508 				WB_TIMESTAMP_LOWER_32);
509 		break;
510 
511 	case WIFIRX_PPDU_END_USER_STATS_E:
512 	{
513 		unsigned long tid = 0;
514 
515 		ppdu_info->rx_status.ast_index =
516 				HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_4,
517 						AST_INDEX);
518 		tid = HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_12,
519 				RECEIVED_QOS_DATA_TID_BITMAP);
520 		ppdu_info->rx_status.tid = qdf_find_first_bit(&tid, sizeof(tid)*8);
521 		ppdu_info->rx_status.mcs =
522 			HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_1,
523 						MCS);
524 		ppdu_info->rx_status.nss =
525 			HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_1,
526 						NSS);
527 		ppdu_info->rx_status.first_data_seq_ctrl =
528 			HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_3,
529 						DATA_SEQUENCE_CONTROL_INFO_VALID);
530 		break;
531 	}
532 
533 	case WIFIRX_PPDU_END_USER_STATS_EXT_E:
534 		break;
535 
536 	case WIFIRX_PPDU_END_STATUS_DONE_E:
537 		return HAL_TLV_STATUS_PPDU_DONE;
538 
539 	case WIFIDUMMY_E:
540 		return HAL_TLV_STATUS_BUF_DONE;
541 
542 	case WIFIPHYRX_HT_SIG_E:
543 	{
544 		uint8_t *ht_sig_info = (uint8_t *)rx_tlv +
545 				HAL_RX_OFFSET(PHYRX_HT_SIG_0,
546 				HT_SIG_INFO_PHYRX_HT_SIG_INFO_DETAILS);
547 		value = HAL_RX_GET(ht_sig_info, HT_SIG_INFO_1,
548 				FEC_CODING);
549 		ppdu_info->rx_status.ldpc = (value == HAL_SU_MU_CODING_LDPC) ?
550 			1 : 0;
551 		break;
552 	}
553 
554 	case WIFIPHYRX_L_SIG_B_E:
555 	{
556 		uint8_t *l_sig_b_info = (uint8_t *)rx_tlv +
557 				HAL_RX_OFFSET(PHYRX_L_SIG_B_0,
558 				L_SIG_B_INFO_PHYRX_L_SIG_B_INFO_DETAILS);
559 
560 		value = HAL_RX_GET(l_sig_b_info, L_SIG_B_INFO_0, RATE);
561 		switch (value) {
562 		case 1:
563 			ppdu_info->rx_status.rate = HAL_11B_RATE_3MCS;
564 			break;
565 		case 2:
566 			ppdu_info->rx_status.rate = HAL_11B_RATE_2MCS;
567 			break;
568 		case 3:
569 			ppdu_info->rx_status.rate = HAL_11B_RATE_1MCS;
570 			break;
571 		case 4:
572 			ppdu_info->rx_status.rate = HAL_11B_RATE_0MCS;
573 			break;
574 		case 5:
575 			ppdu_info->rx_status.rate = HAL_11B_RATE_6MCS;
576 			break;
577 		case 6:
578 			ppdu_info->rx_status.rate = HAL_11B_RATE_5MCS;
579 			break;
580 		case 7:
581 			ppdu_info->rx_status.rate = HAL_11B_RATE_4MCS;
582 			break;
583 		default:
584 			break;
585 		}
586 	break;
587 	}
588 
589 	case WIFIPHYRX_L_SIG_A_E:
590 	{
591 		uint8_t *l_sig_a_info = (uint8_t *)rx_tlv +
592 				HAL_RX_OFFSET(PHYRX_L_SIG_A_0,
593 				L_SIG_A_INFO_PHYRX_L_SIG_A_INFO_DETAILS);
594 
595 		value = HAL_RX_GET(l_sig_a_info, L_SIG_A_INFO_0, RATE);
596 		switch (value) {
597 		case 8:
598 			ppdu_info->rx_status.rate = HAL_11A_RATE_0MCS;
599 			break;
600 		case 9:
601 			ppdu_info->rx_status.rate = HAL_11A_RATE_1MCS;
602 			break;
603 		case 10:
604 			ppdu_info->rx_status.rate = HAL_11A_RATE_2MCS;
605 			break;
606 		case 11:
607 			ppdu_info->rx_status.rate = HAL_11A_RATE_3MCS;
608 			break;
609 		case 12:
610 			ppdu_info->rx_status.rate = HAL_11A_RATE_4MCS;
611 			break;
612 		case 13:
613 			ppdu_info->rx_status.rate = HAL_11A_RATE_5MCS;
614 			break;
615 		case 14:
616 			ppdu_info->rx_status.rate = HAL_11A_RATE_6MCS;
617 			break;
618 		case 15:
619 			ppdu_info->rx_status.rate = HAL_11A_RATE_7MCS;
620 			break;
621 		default:
622 			break;
623 		}
624 	break;
625 	}
626 
627 	case WIFIPHYRX_VHT_SIG_A_E:
628 	{
629 		uint8_t *vht_sig_a_info = (uint8_t *)rx_tlv +
630 				HAL_RX_OFFSET(PHYRX_VHT_SIG_A_0,
631 				VHT_SIG_A_INFO_PHYRX_VHT_SIG_A_INFO_DETAILS);
632 
633 		value = HAL_RX_GET(vht_sig_a_info, VHT_SIG_A_INFO_1,
634 				SU_MU_CODING);
635 		ppdu_info->rx_status.ldpc = (value == HAL_SU_MU_CODING_LDPC) ?
636 			1 : 0;
637 		group_id = HAL_RX_GET(vht_sig_a_info, VHT_SIG_A_INFO_0, GROUP_ID);
638 		ppdu_info->rx_status.vht_flag_values5 = group_id;
639 		break;
640 	}
641 	case WIFIPHYRX_HE_SIG_A_SU_E:
642 		ppdu_info->rx_status.he_sig_A1 =
643 			*((uint32_t *)((uint8_t *)rx_tlv +
644 			HAL_RX_OFFSET(PHYRX_HE_SIG_A_SU_0,
645 			HE_SIG_A_SU_INFO_PHYRX_HE_SIG_A_SU_INFO_DETAILS)));
646 		ppdu_info->rx_status.he_sig_A1 |=
647 			QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_SU;
648 		/* TODO: Enabling all known bits. Check if this should be
649 		 * enabled selectively
650 		 */
651 		ppdu_info->rx_status.he_sig_A1_known =
652 			QDF_MON_STATUS_HE_SIG_A1_SU_KNOWN_ALL;
653 		ppdu_info->rx_status.he_sig_A2 =
654 			*((uint32_t *)((uint8_t *)rx_tlv +
655 			HAL_RX_OFFSET(PHYRX_HE_SIG_A_SU_1,
656 			HE_SIG_A_SU_INFO_PHYRX_HE_SIG_A_SU_INFO_DETAILS)));
657 		ppdu_info->rx_status.he_sig_A2_known =
658 			QDF_MON_STATUS_HE_SIG_A2_SU_KNOWN_ALL;
659 		break;
660 	case WIFIPHYRX_HE_SIG_A_MU_DL_E:
661 		ppdu_info->rx_status.he_sig_A1 =
662 			*((uint32_t *)((uint8_t *)rx_tlv +
663 			HAL_RX_OFFSET(PHYRX_HE_SIG_A_MU_DL_0,
664 			HE_SIG_A_MU_DL_INFO_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS)));
665 		ppdu_info->rx_status.he_sig_A1 |=
666 			QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_MU;
667 		ppdu_info->rx_status.he_sig_A1_known =
668 			QDF_MON_STATUS_HE_SIG_A1_MU_KNOWN_ALL;
669 
670 		ppdu_info->rx_status.he_sig_A2 =
671 			*((uint32_t *)((uint8_t *)rx_tlv +
672 			HAL_RX_OFFSET(PHYRX_HE_SIG_A_MU_DL_1,
673 			HE_SIG_A_MU_DL_INFO_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS)));
674 		ppdu_info->rx_status.he_sig_A2_known =
675 			QDF_MON_STATUS_HE_SIG_A2_MU_KNOWN_ALL;
676 		break;
677 	case WIFIPHYRX_HE_SIG_B1_MU_E:
678 	{
679 		uint8_t *he_sig_b1_mu_info = (uint8_t *)rx_tlv +
680 			*((uint32_t *)((uint8_t *)rx_tlv +
681 			HAL_RX_OFFSET(PHYRX_HE_SIG_B1_MU_0,
682 			HE_SIG_B1_MU_INFO_PHYRX_HE_SIG_B1_MU_INFO_DETAILS)));
683 
684 		ppdu_info->rx_status.he_sig_b_common_RU[0] =
685 			HAL_RX_GET(he_sig_b1_mu_info, HE_SIG_B1_MU_INFO_0,
686 				RU_ALLOCATION);
687 
688 		ppdu_info->rx_status.he_sig_b_common_known =
689 			QDF_MON_STATUS_HE_SIG_B_COMMON_KNOWN_RU0;
690 		/* TODO: Check on the availability of other fields in
691 		 * sig_b_common
692 		 */
693 		break;
694 	}
695 	case WIFIPHYRX_HE_SIG_B2_MU_E:
696 		ppdu_info->rx_status.he_sig_b_user =
697 			*((uint32_t *)((uint8_t *)rx_tlv +
698 			HAL_RX_OFFSET(PHYRX_HE_SIG_B2_MU_0,
699 			HE_SIG_B2_MU_INFO_PHYRX_HE_SIG_B2_MU_INFO_DETAILS)));
700 		ppdu_info->rx_status.he_sig_b_user_known =
701 			QDF_MON_STATUS_HE_SIG_B_USER_KNOWN_SIG_B_ALL;
702 		break;
703 	case WIFIPHYRX_HE_SIG_B2_OFDMA_E:
704 		ppdu_info->rx_status.he_sig_b_user =
705 			*((uint32_t *)((uint8_t *)rx_tlv +
706 			HAL_RX_OFFSET(PHYRX_HE_SIG_B2_OFDMA_0,
707 			HE_SIG_B2_OFDMA_INFO_PHYRX_HE_SIG_B2_OFDMA_INFO_DETAILS)));
708 		ppdu_info->rx_status.he_sig_b_user_known =
709 			QDF_MON_STATUS_HE_SIG_B_USER_KNOWN_SIG_B_ALL;
710 		break;
711 	case WIFIPHYRX_RSSI_LEGACY_E:
712 	{
713 		uint8_t *rssi_info_tlv = (uint8_t *)rx_tlv +
714 			HAL_RX_OFFSET(PHYRX_RSSI_LEGACY_3,
715 			RECEIVE_RSSI_INFO_PRE_RSSI_INFO_DETAILS);
716 
717 		ppdu_info->rx_status.rssi_comb = HAL_RX_GET(rssi_info_tlv,
718 			PHYRX_RSSI_LEGACY_35, RSSI_COMB);
719 		ppdu_info->rx_status.bw = HAL_RX_GET(rssi_info_tlv,
720 			PHYRX_RSSI_LEGACY_35, RECEIVE_BANDWIDTH);
721 		ppdu_info->rx_status.preamble_type = HAL_RX_GET(rssi_info_tlv,
722 			PHYRX_RSSI_LEGACY_0, RECEPTION_TYPE);
723 		ppdu_info->rx_status.he_re = 0;
724 
725 		value = HAL_RX_GET(rssi_info_tlv,
726 			RECEIVE_RSSI_INFO_0, RSSI_PRI20_CHAIN0);
727 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
728 			"RSSI_PRI20_CHAIN0: %d\n", value);
729 
730 		value = HAL_RX_GET(rssi_info_tlv,
731 			RECEIVE_RSSI_INFO_0, RSSI_EXT20_CHAIN0);
732 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
733 			"RSSI_EXT20_CHAIN0: %d\n", value);
734 
735 		value = HAL_RX_GET(rssi_info_tlv,
736 			RECEIVE_RSSI_INFO_0, RSSI_EXT40_LOW20_CHAIN0);
737 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
738 			"RSSI_EXT40_LOW20_CHAIN0: %d\n", value);
739 
740 		value = HAL_RX_GET(rssi_info_tlv,
741 			RECEIVE_RSSI_INFO_0, RSSI_EXT40_HIGH20_CHAIN0);
742 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
743 			"RSSI_EXT40_HIGH20_CHAIN0: %d\n", value);
744 
745 		value = HAL_RX_GET(rssi_info_tlv,
746 			RECEIVE_RSSI_INFO_1, RSSI_EXT80_LOW20_CHAIN0);
747 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
748 			"RSSI_EXT80_LOW20_CHAIN0: %d\n", value);
749 
750 		value = HAL_RX_GET(rssi_info_tlv,
751 			RECEIVE_RSSI_INFO_1, RSSI_EXT80_LOW_HIGH20_CHAIN0);
752 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
753 			"RSSI_EXT80_LOW_HIGH20_CHAIN0: %d\n", value);
754 
755 		value = HAL_RX_GET(rssi_info_tlv,
756 			RECEIVE_RSSI_INFO_1, RSSI_EXT80_HIGH_LOW20_CHAIN0);
757 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
758 			"RSSI_EXT80_HIGH_LOW20_CHAIN0: %d\n", value);
759 
760 		value = HAL_RX_GET(rssi_info_tlv,
761 			RECEIVE_RSSI_INFO_1, RSSI_EXT80_HIGH20_CHAIN0);
762 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
763 			"RSSI_EXT80_HIGH20_CHAIN0: %d\n", value);
764 		break;
765 	}
766 	case 0:
767 		return HAL_TLV_STATUS_PPDU_DONE;
768 
769 	default:
770 		break;
771 	}
772 
773 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
774 		"%s TLV type: %d, TLV len:%d\n",
775 		__func__, tlv_tag, tlv_len);
776 
777 	return HAL_TLV_STATUS_PPDU_NOT_DONE;
778 }
779 
780 static inline
781 uint32_t hal_get_rx_status_done_tlv_size(void *hal_soc)
782 {
783 	return HAL_RX_TLV32_HDR_SIZE;
784 }
785 
786 static inline QDF_STATUS
787 hal_get_rx_status_done(uint8_t *rx_tlv)
788 {
789 	uint32_t tlv_tag;
790 
791 	tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv);
792 
793 	if (tlv_tag == WIFIRX_STATUS_BUFFER_DONE_E)
794 		return QDF_STATUS_SUCCESS;
795 	else
796 		return QDF_STATUS_E_EMPTY;
797 }
798 
799 static inline QDF_STATUS
800 hal_clear_rx_status_done(uint8_t *rx_tlv)
801 {
802 	*(uint32_t *)rx_tlv = 0;
803 	return QDF_STATUS_SUCCESS;
804 }
805 
806 #endif
807