qcacmn: Add MPDU restitch logic For Waikiki RxMON

a. For decapped frames, convert frames from 802.3 t 802.11
b. for non-decapped frames no conversion is needed
c. Apply radiotap header and deliver MPDU to osif layer

CRs-Fixed: 3074441
Change-Id: Ia03b4bad35d69aa292958782cd424f3df56dabbc
This commit is contained in:
Amir Patel
2021-12-15 11:55:15 +05:30
committed by Madan Koyyalamudi
parent 6b69543b79
commit 19970ea217
8 changed files with 733 additions and 82 deletions

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2021, The Linux Foundation. All rights reserved. * Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@@ -32,30 +32,6 @@
*/ */
#define MON_DROP_REAP_LIMIT 64 #define MON_DROP_REAP_LIMIT 64
/*
* The maximum headroom reserved for monitor destination buffer to
* accomodate radiotap header and protocol flow tag
*/
#ifdef DP_RX_MON_MEM_FRAG
/*
* -------------------------------------------------
* | Protocol & Flow TAG | Radiotap header|
* | | Length(128 B) |
* | ((4* QDF_NBUF_MAX_FRAGS) * 2) | |
* -------------------------------------------------
*/
#define DP_RX_MON_MAX_RADIO_TAP_HDR (128)
#define DP_RX_MON_PF_TAG_LEN_PER_FRAG (4)
#define DP_RX_MON_TOT_PF_TAG_LEN \
((DP_RX_MON_PF_TAG_LEN_PER_FRAG) * (QDF_NBUF_MAX_FRAGS))
#define DP_RX_MON_MAX_MONITOR_HEADER \
((DP_RX_MON_TOT_PF_TAG_LEN * 2) + (DP_RX_MON_MAX_RADIO_TAP_HDR))
#endif
/* l2 header pad byte in case of Raw frame is Zero and 2 in non raw */
#define DP_RX_MON_RAW_L2_HDR_PAD_BYTE (0)
#define DP_RX_MON_NONRAW_L2_HDR_PAD_BYTE (2)
QDF_STATUS dp_rx_pdev_mon_status_buffers_alloc(struct dp_pdev *pdev, QDF_STATUS dp_rx_pdev_mon_status_buffers_alloc(struct dp_pdev *pdev,
uint32_t mac_id); uint32_t mac_id);
QDF_STATUS dp_rx_pdev_mon_status_desc_pool_alloc(struct dp_pdev *pdev, QDF_STATUS dp_rx_pdev_mon_status_desc_pool_alloc(struct dp_pdev *pdev,

View File

@@ -49,6 +49,8 @@ QDF_STATUS dp_mon_pdev_ext_init_2_0(struct dp_pdev *pdev)
struct dp_mon_pdev_be *mon_pdev_be = struct dp_mon_pdev_be *mon_pdev_be =
dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
qdf_create_work(0, &mon_pdev_be->rx_mon_work,
dp_rx_mon_process_ppdu, pdev);
mon_pdev_be->rx_mon_workqueue = mon_pdev_be->rx_mon_workqueue =
qdf_alloc_unbound_workqueue("rx_mon_work_queue"); qdf_alloc_unbound_workqueue("rx_mon_work_queue");
@@ -58,8 +60,6 @@ QDF_STATUS dp_mon_pdev_ext_init_2_0(struct dp_pdev *pdev)
} }
TAILQ_INIT(&mon_pdev_be->rx_mon_queue); TAILQ_INIT(&mon_pdev_be->rx_mon_queue);
qdf_create_work(0, &mon_pdev_be->rx_mon_work,
dp_rx_mon_process_ppdu, pdev);
qdf_spinlock_create(&mon_pdev_be->rx_mon_wq_lock); qdf_spinlock_create(&mon_pdev_be->rx_mon_wq_lock);
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;

View File

@@ -1194,6 +1194,43 @@ void dp_mon_filter_reset_tx_mon_mode_2_0(struct dp_pdev *pdev)
mon_pdev_be->filter_be[mode][srng_type] = filter; mon_pdev_be->filter_be[mode][srng_type] = filter;
} }
static void dp_mon_filter_set_mon_2_0(struct dp_mon_pdev *mon_pdev,
struct dp_mon_filter *filter)
{
filter->tlv_filter.mpdu_start = 1;
filter->tlv_filter.msdu_start = 1;
filter->tlv_filter.packet = 1;
filter->tlv_filter.packet_header = 1;
filter->tlv_filter.header_per_msdu = 1;
filter->tlv_filter.msdu_end = 1;
filter->tlv_filter.mpdu_end = 1;
filter->tlv_filter.attention = 0;
filter->tlv_filter.ppdu_start = 1;
filter->tlv_filter.ppdu_end = 1;
filter->tlv_filter.ppdu_end_user_stats = 1;
filter->tlv_filter.ppdu_end_user_stats_ext = 1;
filter->tlv_filter.ppdu_end_status_done = 1;
filter->tlv_filter.enable_fp = 1;
filter->tlv_filter.enable_md = 0;
filter->tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL;
filter->tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL;
filter->tlv_filter.fp_data_filter = FILTER_DATA_ALL;
filter->tlv_filter.offset_valid = false;
filter->tlv_filter.rx_packet_offset = 8;
filter->tlv_filter.mgmt_dma_length = 3;
filter->tlv_filter.data_dma_length = 3;
filter->tlv_filter.ctrl_dma_length = 3;
if (mon_pdev->mon_filter_mode & MON_FILTER_OTHER) {
filter->tlv_filter.enable_mo = 1;
filter->tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL;
filter->tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL;
filter->tlv_filter.mo_data_filter = FILTER_DATA_ALL;
} else {
filter->tlv_filter.enable_mo = 0;
}
}
void dp_mon_filter_setup_rx_mon_mode_2_0(struct dp_pdev *pdev) void dp_mon_filter_setup_rx_mon_mode_2_0(struct dp_pdev *pdev)
{ {
struct dp_mon_filter_be filter = {0}; struct dp_mon_filter_be filter = {0};
@@ -1226,7 +1263,7 @@ void dp_mon_filter_setup_rx_mon_mode_2_0(struct dp_pdev *pdev)
rx_tlv_filter = &filter.rx_tlv_filter; rx_tlv_filter = &filter.rx_tlv_filter;
rx_tlv_filter->valid = false; rx_tlv_filter->valid = false;
dp_mon_filter_set_status_cmn(mon_pdev, rx_tlv_filter); dp_mon_filter_set_mon_2_0(mon_pdev, rx_tlv_filter);
dp_mon_filter_show_filter(mon_pdev, mode, rx_tlv_filter); dp_mon_filter_show_filter(mon_pdev, mode, rx_tlv_filter);
mon_pdev->current_filter_mode = mode; mon_pdev->current_filter_mode = mode;

View File

@@ -26,19 +26,162 @@
#include "dp_mon.h" #include "dp_mon.h"
#include <dp_rx_mon.h> #include <dp_rx_mon.h>
#include <dp_mon_2.0.h> #include <dp_mon_2.0.h>
#include <dp_rx_mon.h>
#include <dp_rx_mon_2.0.h> #include <dp_rx_mon_2.0.h>
#include <dp_rx.h> #include <dp_rx.h>
#include <dp_be.h> #include <dp_be.h>
#include <hal_be_api_mon.h> #include <hal_be_api_mon.h>
void dp_rx_mon_process_ppdu(void *context) /**
* dp_rx_mon_deliver_mpdu() - Deliver MPDU to osif layer
*
* @mon_pdev: monitor pdev
* @mpdu: MPDU nbuf
* @status: monitor status
*
* Return: QDF_STATUS
*/
static QDF_STATUS
dp_rx_mon_deliver_mpdu(struct dp_mon_pdev *mon_pdev,
qdf_nbuf_t mpdu,
struct mon_rx_status *rx_status)
{ {
if (mon_pdev->mvdev && mon_pdev->mvdev->monitor_vdev->osif_rx_mon) {
mon_pdev->mvdev->monitor_vdev->osif_rx_mon(mon_pdev->mvdev->osif_vdev,
mpdu,
rx_status);
} else {
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
} }
void dp_rx_mon_add_ppdu_info_to_wq(struct dp_mon_pdev_be *mon_pdev_be, /**
struct hal_rx_ppdu_info *ppdu_info) * dp_rx_mon_process_ppdu_info () - Process PPDU info
* @pdev: DP pdev
* @ppdu_info: PPDU info
*
* Return: Void
*/
static void
dp_rx_mon_process_ppdu_info(struct dp_pdev *pdev,
struct hal_rx_ppdu_info *ppdu_info)
{ {
if (ppdu_info) { struct dp_mon_pdev *mon_pdev = (struct dp_mon_pdev *)pdev->monitor_pdev;
uint8_t user;
for (user = 0; user < ppdu_info->com_info.num_users; user++) {
uint16_t mpdu_count = ppdu_info->mpdu_count[user];
uint16_t mpdu_idx;
qdf_nbuf_t mpdu;
struct hal_rx_mon_mpdu_info *mpdu_meta;
QDF_STATUS status;
for (mpdu_idx = 0; mpdu_idx < mpdu_count; mpdu_idx++) {
mpdu = (qdf_nbuf_t)ppdu_info->mpdu_q[user][mpdu_idx];
if (!mpdu)
continue;
mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(mpdu);
if (mpdu_meta->full_pkt) {
dp_rx_mon_handle_full_mon(pdev, ppdu_info, mpdu);
} else {
qdf_nbuf_free(mpdu);
continue;
}
/* reset mpdu metadata and apply radiotap header over MPDU */
qdf_mem_zero(mpdu_meta, sizeof(struct hal_rx_mon_mpdu_info));
if (!qdf_nbuf_update_radiotap(&ppdu_info->rx_status,
mpdu,
qdf_nbuf_headroom(mpdu))) {
dp_mon_err("failed to update radiotap pdev: %pK",
pdev);
}
/* Deliver MPDU to osif layer */
status = dp_rx_mon_deliver_mpdu(mon_pdev,
mpdu,
&ppdu_info->rx_status);
if (status != QDF_STATUS_SUCCESS)
qdf_nbuf_free(mpdu);
}
}
}
/**
* dp_rx_mon_process_ppdu ()- Deferred monitor processing
* This workqueue API handles:
* a. Full monitor
* b. Lite monitor
*
* @context: Opaque work context
*
* Return: none
*/
void dp_rx_mon_process_ppdu(void *context)
{
struct dp_pdev *pdev = (struct dp_pdev *)context;
struct dp_mon_pdev *mon_pdev;
struct hal_rx_ppdu_info *ppdu_info = NULL;
struct hal_rx_ppdu_info *temp_ppdu_info = NULL;
struct dp_mon_pdev_be *mon_pdev_be;
if (qdf_unlikely(!pdev)) {
dp_mon_debug("Pdev is NULL");
return;
}
mon_pdev = (struct dp_mon_pdev *)pdev->monitor_pdev;
if (qdf_unlikely(!mon_pdev)) {
dp_mon_debug("monitor pdev is NULL");
return;
}
mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
qdf_spin_lock_bh(&mon_pdev_be->rx_mon_wq_lock);
if (!TAILQ_EMPTY(&mon_pdev_be->rx_mon_queue)) {
TAILQ_FOREACH_SAFE(ppdu_info,
&mon_pdev_be->rx_mon_queue,
ppdu_list_elem,
temp_ppdu_info) {
TAILQ_REMOVE(&mon_pdev_be->rx_mon_queue,
ppdu_info, ppdu_list_elem);
mon_pdev_be->rx_mon_queue_depth--;
dp_rx_mon_process_ppdu_info(pdev, ppdu_info);
qdf_mem_free(ppdu_info);
}
}
qdf_spin_unlock_bh(&mon_pdev_be->rx_mon_wq_lock);
}
/**
* dp_rx_mon_add_ppdu_info_to_wq () - Add PPDU info to workqueue
*
* @mon_pdev: monitor pdev
* @ppdu_info: ppdu info to be added to workqueue
*
* Return: SUCCESS or FAILIRE
*/
static QDF_STATUS
dp_rx_mon_add_ppdu_info_to_wq(struct dp_mon_pdev *mon_pdev,
struct hal_rx_ppdu_info *ppdu_info)
{
struct dp_mon_pdev_be *mon_pdev_be =
dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
/* Full monitor or lite monitor mode is not enabled, return */
if (!mon_pdev->monitor_configured)
return QDF_STATUS_E_FAILURE;
if (qdf_likely(ppdu_info)) {
qdf_spin_lock_bh(&mon_pdev_be->rx_mon_wq_lock); qdf_spin_lock_bh(&mon_pdev_be->rx_mon_wq_lock);
TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_queue, TAILQ_INSERT_TAIL(&mon_pdev_be->rx_mon_queue,
ppdu_info, ppdu_list_elem); ppdu_info, ppdu_list_elem);
@@ -50,8 +193,308 @@ void dp_rx_mon_add_ppdu_info_to_wq(struct dp_mon_pdev_be *mon_pdev_be,
&mon_pdev_be->rx_mon_work); &mon_pdev_be->rx_mon_work);
} }
} }
return QDF_STATUS_SUCCESS;
} }
void
dp_rx_mon_handle_full_mon(struct dp_pdev *pdev,
struct hal_rx_ppdu_info *ppdu_info,
qdf_nbuf_t mpdu)
{
uint32_t wifi_hdr_len, sec_hdr_len, msdu_llc_len,
mpdu_buf_len, decap_hdr_pull_bytes, dir,
is_amsdu, amsdu_pad, frag_size, tot_msdu_len;
struct hal_rx_mon_mpdu_info *mpdu_meta;
struct hal_rx_mon_msdu_info *msdu_meta;
char *hdr_desc;
uint8_t num_frags, frag_iter, l2_hdr_offset;
struct ieee80211_frame *wh;
struct ieee80211_qoscntl *qos;
void *hdr_frag_addr;
uint32_t hdr_frag_size, frag_page_offset, pad_byte_pholder,
total_msdu_len, msdu_len;
qdf_nbuf_t head_msdu, msdu_cur;
void *frag_addr;
bool prev_msdu_end_received = false;
/***************************************************************************
*********************** Non-raw packet ************************************
---------------------------------------------------------------------------
| | frag-0 | frag-1 | frag - 2 | frag - 3 | frag - 4 | frag - 5 |
| skb | rx_hdr-1 | rx_msdu-1 | rx_hdr-2 | rx_msdu-2 | rx_hdr-3 | rx-msdu-3 |
---------------------------------------------------------------------------
**************************************************************************/
if (!mpdu) {
dp_mon_debug("nbuf is NULL, return");
return;
}
head_msdu = mpdu;
mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(mpdu);
if (mpdu_meta->decap_type == HAL_HW_RX_DECAP_FORMAT_RAW) {
qdf_nbuf_trim_add_frag_size(mpdu,
qdf_nbuf_get_nr_frags(mpdu) - 1,
-HAL_RX_FCS_LEN, 0);
return;
}
l2_hdr_offset = DP_RX_MON_NONRAW_L2_HDR_PAD_BYTE;
/* hdr_desc points to 80211 hdr */
hdr_desc = qdf_nbuf_get_frag_addr(mpdu, 0);
/* Calculate Base header size */
wifi_hdr_len = sizeof(struct ieee80211_frame);
wh = (struct ieee80211_frame *)hdr_desc;
dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
if (dir == IEEE80211_FC1_DIR_DSTODS)
wifi_hdr_len += 6;
is_amsdu = 0;
if (wh->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_QOS) {
qos = (struct ieee80211_qoscntl *)
(hdr_desc + wifi_hdr_len);
wifi_hdr_len += 2;
is_amsdu = (qos->i_qos[0] & IEEE80211_QOS_AMSDU);
}
/*Calculate security header length based on 'Protected'
* and 'EXT_IV' flag
*/
if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
char *iv = (char *)wh + wifi_hdr_len;
if (iv[3] & KEY_EXTIV)
sec_hdr_len = 8;
else
sec_hdr_len = 4;
} else {
sec_hdr_len = 0;
}
wifi_hdr_len += sec_hdr_len;
/* MSDU related stuff LLC - AMSDU subframe header etc */
msdu_llc_len = is_amsdu ? (DP_RX_MON_DECAP_HDR_SIZE +
DP_RX_MON_LLC_SIZE +
DP_RX_MON_SNAP_SIZE) :
(DP_RX_MON_LLC_SIZE + DP_RX_MON_SNAP_SIZE);
mpdu_buf_len = wifi_hdr_len + msdu_llc_len;
/* "Decap" header to remove from MSDU buffer */
decap_hdr_pull_bytes = DP_RX_MON_DECAP_HDR_SIZE;
amsdu_pad = 0;
total_msdu_len = 0;
tot_msdu_len = 0;
/*
* Update protocol and flow tag for MSDU
* update frag index in ctx_idx field.
* Reset head pointer data of nbuf before updating.
*/
QDF_NBUF_CB_RX_CTX_ID(mpdu) = 0;
/* Construct destination address */
hdr_frag_addr = qdf_nbuf_get_frag_addr(mpdu, 0);
hdr_frag_size = qdf_nbuf_get_frag_size_by_idx(mpdu, 0);
/* Adjust page frag offset to point to 802.11 header */
qdf_nbuf_trim_add_frag_size(head_msdu, 0, -(hdr_frag_size - mpdu_buf_len), 0);
msdu_meta = (struct hal_rx_mon_msdu_info *)(qdf_nbuf_get_frag_addr(mpdu, 1) - DP_RX_MON_PACKET_OFFSET + 2);
msdu_len = msdu_meta->msdu_len;
/* Adjust page frag offset to appropriate after decap header */
frag_page_offset =
decap_hdr_pull_bytes;
qdf_nbuf_move_frag_page_offset(head_msdu, 1, frag_page_offset);
frag_size = qdf_nbuf_get_frag_size_by_idx(head_msdu, 1);
pad_byte_pholder =
RX_MONITOR_BUFFER_SIZE - frag_size;
if (msdu_meta->first_buffer && msdu_meta->last_buffer) {
/* MSDU with single bufffer */
amsdu_pad = frag_size & 0x3;
amsdu_pad = amsdu_pad ? (4 - amsdu_pad) : 0;
if (amsdu_pad && (amsdu_pad <= pad_byte_pholder)) {
char *frag_addr_temp;
qdf_nbuf_trim_add_frag_size(mpdu, 1, amsdu_pad, 0);
frag_addr_temp =
(char *)qdf_nbuf_get_frag_addr(mpdu, 1);
frag_addr_temp = (frag_addr_temp +
qdf_nbuf_get_frag_size_by_idx(mpdu, 1)) -
amsdu_pad;
qdf_mem_zero(frag_addr_temp, amsdu_pad);
amsdu_pad = 0;
}
} else {
total_msdu_len = msdu_len;
amsdu_pad = 0;
}
for (msdu_cur = mpdu; msdu_cur;) {
/* frag_iter will start from 0 for second skb onwards */
if (msdu_cur == mpdu)
frag_iter = 2;
else
frag_iter = 0;
num_frags = qdf_nbuf_get_nr_frags(msdu_cur);
for (; frag_iter < num_frags; frag_iter++) {
/* Construct destination address
* ----------------------------------------------------------
* | | L2_HDR_PAD | Decap HDR | Payload | Pad |
* | | (First buffer) | | |
* | | / / |
* | >Frag address points here / / |
* | \ / / |
* | \ This bytes needs to / / |
* | \ removed to frame pkt/ / |
* | ---------------------- / |
* | | / Add |
* | | / amsdu pad |
* | LLC HDR will be added here <-| | Byte for |
* | | | | last frame |
* | >Dest addr will point | | if space |
* | somewhere in this area | | available |
* | And amsdu_pad will be created if | | |
* | dint get added in last buffer | | |
* | (First Buffer) | | |
* ----------------------------------------------------------
*/
/* If previous msdu end has received, modify next frag's offset to point to LLC */
if (prev_msdu_end_received) {
hdr_frag_size = qdf_nbuf_get_frag_size_by_idx(msdu_cur, frag_iter);
/* Adjust page frag offset to point to llc/snap header */
qdf_nbuf_trim_add_frag_size(msdu_cur, frag_iter, -(hdr_frag_size - msdu_llc_len), 0);
continue;
}
frag_addr =
qdf_nbuf_get_frag_addr(msdu_cur, frag_iter) - 8;
msdu_meta = (struct hal_rx_mon_msdu_info *)frag_addr;
/*
* Update protocol and flow tag for MSDU
* update frag index in ctx_idx field
*/
QDF_NBUF_CB_RX_CTX_ID(msdu_cur) = frag_iter;
frag_size = qdf_nbuf_get_frag_size_by_idx(msdu_cur,
frag_iter);
/* If Middle buffer, dont add any header */
if ((!msdu_meta->first_buffer) &&
(!msdu_meta->last_buffer)) {
tot_msdu_len += frag_size;
amsdu_pad = 0;
pad_byte_pholder = 0;
continue;
}
/* Calculate if current buffer has placeholder
* to accommodate amsdu pad byte
*/
pad_byte_pholder =
RX_MONITOR_BUFFER_SIZE - frag_size;
/*
* We will come here only only three condition:
* 1. Msdu with single Buffer
* 2. First buffer in case MSDU is spread in multiple
* buffer
* 3. Last buffer in case MSDU is spread in multiple
* buffer
*
* First buffER | Last buffer
* Case 1: 1 | 1
* Case 2: 1 | 0
* Case 3: 0 | 1
*
* In 3rd case only l2_hdr_padding byte will be Zero and
* in other case, It will be 2 Bytes.
*/
if (msdu_meta->first_buffer)
l2_hdr_offset =
DP_RX_MON_NONRAW_L2_HDR_PAD_BYTE;
else
l2_hdr_offset = DP_RX_MON_RAW_L2_HDR_PAD_BYTE;
if (msdu_meta->first_buffer) {
/* Adjust page frag offset to point to 802.11 header */
hdr_frag_size = qdf_nbuf_get_frag_size_by_idx(msdu_cur, frag_iter - 1);
qdf_nbuf_trim_add_frag_size(msdu_cur, frag_iter - 1, -(hdr_frag_size - msdu_llc_len), 0);
/* Adjust page frag offset to appropriate after decap header */
frag_page_offset =
(decap_hdr_pull_bytes);
qdf_nbuf_move_frag_page_offset(msdu_cur, frag_iter, frag_page_offset);
/*
* Calculate new page offset and create hole
* if amsdu_pad required.
*/
tot_msdu_len = frag_size;
/*
* No amsdu padding required for first frame of
* continuation buffer
*/
if (!msdu_meta->last_buffer) {
amsdu_pad = 0;
continue;
}
} else {
tot_msdu_len += frag_size;
}
/* Will reach to this place in only two case:
* 1. Single buffer MSDU
* 2. Last buffer of MSDU in case of multiple buf MSDU
*/
/* This flag is used to identify msdu boundry */
prev_msdu_end_received = true;
/* Check size of buffer if amsdu padding required */
amsdu_pad = tot_msdu_len & 0x3;
amsdu_pad = amsdu_pad ? (4 - amsdu_pad) : 0;
/* Create placeholder if current bufer can
* accommodate padding.
*/
if (amsdu_pad && (amsdu_pad <= pad_byte_pholder)) {
char *frag_addr_temp;
qdf_nbuf_trim_add_frag_size(msdu_cur,
frag_iter,
amsdu_pad, 0);
frag_addr_temp = (char *)qdf_nbuf_get_frag_addr(msdu_cur,
frag_iter);
frag_addr_temp = (frag_addr_temp +
qdf_nbuf_get_frag_size_by_idx(msdu_cur, frag_iter)) -
amsdu_pad;
qdf_mem_zero(frag_addr_temp, amsdu_pad);
amsdu_pad = 0;
}
/* reset tot_msdu_len */
tot_msdu_len = 0;
}
msdu_cur = NULL;
}
}
/** /**
* dp_rx_mon_flush_status_buf_queue () - Flush status buffer queue * dp_rx_mon_flush_status_buf_queue () - Flush status buffer queue
* *
@@ -143,86 +586,168 @@ dp_rx_mon_handle_flush_n_trucated_ppdu(struct dp_soc *soc,
&desc_list, &tail); &desc_list, &tail);
} }
void dp_rx_mon_process_tlv_status(struct dp_pdev *pdev, uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
struct hal_rx_ppdu_info *ppdu_info, struct hal_rx_ppdu_info *ppdu_info,
void *status_frag, void *status_frag,
uint16_t tlv_status) uint16_t tlv_status,
union dp_mon_desc_list_elem_t **desc_list,
union dp_mon_desc_list_elem_t **tail)
{ {
struct dp_soc *soc = pdev->soc; struct dp_soc *soc = pdev->soc;
struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
qdf_nbuf_t nbuf; qdf_nbuf_t nbuf;
qdf_frag_t addr; qdf_frag_t addr;
uint8_t user_id = ppdu_info->user_id; uint8_t user_id = ppdu_info->user_id;
uint8_t mpdu_idx = ppdu_info->mpdu_count[user_id]; uint8_t mpdu_idx = ppdu_info->mpdu_count[user_id];
uint16_t num_frags; uint16_t num_frags;
uint16_t frag_len = RX_MONITOR_BUFFER_SIZE; uint8_t *data;
struct ieee80211_frame *qwh;
uint8_t num_buf_reaped = 0;
if (!mon_pdev->monitor_configured) {
return num_buf_reaped;
}
switch (tlv_status) { switch (tlv_status) {
case HAL_TLV_STATUS_HEADER: { case HAL_TLV_STATUS_HEADER: {
/* If this is first RX_HEADER for MPDU, allocate skb /* If this is first RX_HEADER for MPDU, allocate skb
* else add frag to already allocated skb * else add frag to already allocated skb
*/ */
if (!ppdu_info->mpdu_info[user_id].mpdu_start_received) {
nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
DP_MON_DATA_BUFFER_SIZE,
MAX_MONITOR_HEADER,
0, FALSE);
if (!ppdu_info->mpdu_info[user_id].mpdu_start_received) {
nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
DP_RX_MON_MAX_MONITOR_HEADER,
DP_RX_MON_MAX_MONITOR_HEADER,
4, FALSE);
/* Set *head_msdu->next as NULL as all msdus are
* * mapped via nr frags
* */
if (!nbuf) { if (!nbuf) {
dp_mon_err("malloc failed pdev: %pK ", pdev); dp_mon_err("malloc failed pdev: %pK ", pdev);
return; return num_buf_reaped;
} }
qdf_nbuf_set_next(nbuf, NULL);
ppdu_info->mpdu_q[user_id][mpdu_idx] = nbuf; ppdu_info->mpdu_q[user_id][mpdu_idx] = nbuf;
dp_rx_mon_add_frag_to_skb(ppdu_info, nbuf, status_frag);
num_frags = qdf_nbuf_get_nr_frags(nbuf);
if (num_frags < QDF_NBUF_MAX_FRAGS) {
qdf_nbuf_add_rx_frag(status_frag, nbuf,
ppdu_info->data - (unsigned char *)status_frag + 4,
ppdu_info->hdr_len - DP_RX_MON_RX_HDR_OFFSET,
DP_MON_DATA_BUFFER_SIZE,
true);
data = (uint8_t *)qdf_nbuf_get_frag_addr(nbuf, 0);
qwh = (struct ieee80211_frame *)data;
} else {
dp_mon_err("num_frags exceeding MAX frags");
qdf_assert_always(0);
}
ppdu_info->mpdu_info[ppdu_info->user_id].mpdu_start_received = true;
ppdu_info->mpdu_info[user_id].first_rx_hdr_rcvd = true;
} else { } else {
if (ppdu_info->mpdu_info[user_id].decap_type ==
HAL_HW_RX_DECAP_FORMAT_RAW) {
return num_buf_reaped;
}
nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx];
dp_rx_mon_add_frag_to_skb(ppdu_info, nbuf, status_frag); num_frags = qdf_nbuf_get_nr_frags(nbuf);
if (num_frags < QDF_NBUF_MAX_FRAGS) {
qdf_nbuf_add_rx_frag(status_frag,
nbuf,
ppdu_info->data - (unsigned char *)status_frag + 4,
ppdu_info->hdr_len - DP_RX_MON_RX_HDR_OFFSET,
DP_MON_DATA_BUFFER_SIZE,
true);
} else {
dp_mon_err("num_frags exceeding MAX frags");
qdf_assert_always(0);
}
} }
} }
break; break;
case HAL_TLV_STATUS_MON_BUF_ADDR: case HAL_TLV_STATUS_MON_BUF_ADDR:
{ {
struct hal_mon_packet_info *packet_info = &ppdu_info->packet_info;
struct dp_mon_desc *mon_desc = dp_mon_desc_get(&packet_info->sw_cookie);
struct hal_rx_mon_msdu_info *buf_info; struct hal_rx_mon_msdu_info *buf_info;
struct hal_mon_packet_info *packet_info = &ppdu_info->packet_info;
struct dp_mon_desc *mon_desc = (struct dp_mon_desc *)(uintptr_t)ppdu_info->packet_info.sw_cookie;
struct hal_rx_mon_mpdu_info *mpdu_info;
uint16_t frag_idx = 0;
qdf_assert_always(mon_desc); qdf_assert_always(mon_desc);
if (mon_desc->magic != DP_MON_DESC_MAGIC)
qdf_assert_always(0);
addr = mon_desc->buf_addr; addr = mon_desc->buf_addr;
qdf_assert_always(addr); qdf_assert_always(addr);
mpdu_info = &ppdu_info->mpdu_info[user_id];
if (!mon_desc->unmapped) { if (!mon_desc->unmapped) {
qdf_mem_unmap_page(soc->osdev, qdf_mem_unmap_page(soc->osdev,
(qdf_dma_addr_t)mon_desc->paddr, (qdf_dma_addr_t)mon_desc->paddr,
QDF_DMA_FROM_DEVICE, DP_MON_DATA_BUFFER_SIZE,
DP_MON_DATA_BUFFER_SIZE); QDF_DMA_FROM_DEVICE);
mon_desc->unmapped = 1; mon_desc->unmapped = 1;
} }
dp_mon_add_to_free_desc_list(desc_list, tail, mon_desc);
num_buf_reaped++;
nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx];
num_frags = qdf_nbuf_get_nr_frags(nbuf);
if (num_frags < QDF_NBUF_MAX_FRAGS) {
qdf_nbuf_add_rx_frag(addr, nbuf,
packet_info->dma_length,
frag_len,
RX_MONITOR_BUFFER_SIZE,
false);
}
buf_info = addr; mpdu_info->full_pkt = true;
if (ppdu_info->msdu[user_id].first_buffer) { if (mpdu_info->decap_type == HAL_HW_RX_DECAP_FORMAT_RAW) {
buf_info->first_buffer = true; if (mpdu_info->first_rx_hdr_rcvd) {
ppdu_info->msdu[user_id].first_buffer = false; qdf_nbuf_remove_frag(nbuf, frag_idx, DP_MON_DATA_BUFFER_SIZE);
qdf_nbuf_add_rx_frag(addr, nbuf,
DP_RX_MON_PACKET_OFFSET,
packet_info->dma_length,
DP_MON_DATA_BUFFER_SIZE,
false);
mpdu_info->first_rx_hdr_rcvd = false;
} else {
num_frags = qdf_nbuf_get_nr_frags(nbuf);
if (num_frags < QDF_NBUF_MAX_FRAGS) {
qdf_nbuf_add_rx_frag(addr, nbuf,
DP_RX_MON_PACKET_OFFSET,
packet_info->dma_length,
RX_MONITOR_BUFFER_SIZE,
false);
}
}
} else { } else {
buf_info->first_buffer = false; num_frags = qdf_nbuf_get_nr_frags(nbuf);
if (num_frags < QDF_NBUF_MAX_FRAGS) {
qdf_nbuf_add_rx_frag(addr, nbuf,
DP_RX_MON_NONRAW_L2_HDR_PAD_BYTE +
DP_RX_MON_PACKET_OFFSET,
packet_info->dma_length,
RX_MONITOR_BUFFER_SIZE,
false);
}
buf_info = addr;
if (!ppdu_info->msdu[user_id].first_buffer) {
buf_info->first_buffer = true;
ppdu_info->msdu[user_id].first_buffer = true;
} else {
buf_info->first_buffer = false;
}
if (packet_info->msdu_continuation)
buf_info->last_buffer = false;
else
buf_info->last_buffer = true;
buf_info->frag_len = packet_info->dma_length;
} }
if (packet_info->msdu_continuation)
buf_info->last_buffer = false;
else
buf_info->last_buffer = true;
buf_info->frag_len = packet_info->dma_length;
} }
break; break;
case HAL_TLV_STATUS_MSDU_END: case HAL_TLV_STATUS_MSDU_END:
@@ -231,10 +756,19 @@ void dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
struct hal_rx_mon_msdu_info *last_buf_info; struct hal_rx_mon_msdu_info *last_buf_info;
/* update msdu metadata at last buffer of msdu in MPDU */ /* update msdu metadata at last buffer of msdu in MPDU */
nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx];
if (!nbuf) {
dp_mon_err(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d", __LINE__, user_id, mpdu_idx);
break;
}
num_frags = qdf_nbuf_get_nr_frags(nbuf); num_frags = qdf_nbuf_get_nr_frags(nbuf);
if (ppdu_info->mpdu_info[user_id].decap_type ==
HAL_HW_RX_DECAP_FORMAT_RAW) {
break;
}
/* This points to last buffer of MSDU . update metadata here */ /* This points to last buffer of MSDU . update metadata here */
addr = qdf_nbuf_get_frag_addr(nbuf, num_frags - 1); addr = qdf_nbuf_get_frag_addr(nbuf, num_frags - 1) -
(DP_RX_MON_PACKET_OFFSET +
DP_RX_MON_NONRAW_L2_HDR_PAD_BYTE);
last_buf_info = addr; last_buf_info = addr;
last_buf_info->first_msdu = msdu_info->first_msdu; last_buf_info->first_msdu = msdu_info->first_msdu;
@@ -242,10 +776,8 @@ void dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
last_buf_info->decap_type = msdu_info->decap_type; last_buf_info->decap_type = msdu_info->decap_type;
last_buf_info->msdu_index = msdu_info->msdu_index; last_buf_info->msdu_index = msdu_info->msdu_index;
last_buf_info->user_rssi = msdu_info->user_rssi; last_buf_info->user_rssi = msdu_info->user_rssi;
last_buf_info->l3_header_padding = msdu_info->l3_header_padding;
last_buf_info->stbc = msdu_info->stbc;
last_buf_info->sgi = msdu_info->sgi;
last_buf_info->reception_type = msdu_info->reception_type; last_buf_info->reception_type = msdu_info->reception_type;
last_buf_info->msdu_len = msdu_info->msdu_len;
/* reset msdu info for next msdu for same user */ /* reset msdu info for next msdu for same user */
qdf_mem_zero(msdu_info, sizeof(msdu_info)); qdf_mem_zero(msdu_info, sizeof(msdu_info));
@@ -260,28 +792,44 @@ void dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
struct hal_rx_mon_mpdu_info *mpdu_info, *mpdu_meta; struct hal_rx_mon_mpdu_info *mpdu_info, *mpdu_meta;
nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx];
if (!nbuf) {
dp_mon_err(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d", __LINE__, user_id, mpdu_idx);
break;
}
mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf); mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf);
mpdu_info = &ppdu_info->mpdu_info[user_id]; mpdu_info = &ppdu_info->mpdu_info[user_id];
mpdu_meta->decap_type = mpdu_info->decap_type; mpdu_meta->decap_type = mpdu_info->decap_type;
} ppdu_info->mpdu_info[ppdu_info->user_id].mpdu_start_received = true;
break; break;
}
case HAL_TLV_STATUS_MPDU_END: case HAL_TLV_STATUS_MPDU_END:
{ {
struct hal_rx_mon_mpdu_info *mpdu_info, *mpdu_meta; struct hal_rx_mon_mpdu_info *mpdu_info, *mpdu_meta;
mpdu_info = &ppdu_info->mpdu_info[user_id]; mpdu_info = &ppdu_info->mpdu_info[user_id];
nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx]; nbuf = ppdu_info->mpdu_q[user_id][mpdu_idx];
if (!nbuf) {
dp_mon_err(" <%d> nbuf is NULL, return user: %d mpdu_idx: %d", __LINE__, user_id, mpdu_idx);
break;
}
mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf); mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf);
mpdu_meta->mpdu_length_err = mpdu_info->mpdu_length_err; mpdu_meta->mpdu_length_err = mpdu_info->mpdu_length_err;
mpdu_meta->fcs_err = mpdu_info->fcs_err; mpdu_meta->fcs_err = mpdu_info->fcs_err;
ppdu_info->rx_status.rs_fcs_err = mpdu_info->fcs_err;
mpdu_meta->overflow_err = mpdu_info->overflow_err; mpdu_meta->overflow_err = mpdu_info->overflow_err;
mpdu_meta->decrypt_err = mpdu_info->decrypt_err; mpdu_meta->decrypt_err = mpdu_info->decrypt_err;
mpdu_meta->full_pkt = mpdu_info->full_pkt;
num_frags = qdf_nbuf_get_nr_frags(nbuf);
num_frags = qdf_nbuf_get_nr_frags(nbuf);
ppdu_info->mpdu_q[user_id][mpdu_idx] = nbuf;
/* reset msdu info for next msdu for same user */ /* reset msdu info for next msdu for same user */
qdf_mem_zero(mpdu_info, sizeof(mpdu_info)); qdf_mem_zero(mpdu_info, sizeof(mpdu_info));
ppdu_info->mpdu_info[ppdu_info->user_id].mpdu_start_received = false;
ppdu_info->mpdu_count[user_id]++;
} }
break; break;
} }
return num_buf_reaped;
} }
/** /**
@@ -349,6 +897,12 @@ dp_rx_mon_process_status_tlv(struct dp_pdev *pdev)
pdev->soc->hal_soc, pdev->soc->hal_soc,
buf); buf);
work_done += dp_rx_mon_process_tlv_status(pdev,
ppdu_info,
buf,
tlv_status,
&desc_list,
&tail);
rx_tlv = hal_rx_status_get_next_tlv(rx_tlv, 1); rx_tlv = hal_rx_status_get_next_tlv(rx_tlv, 1);
/* HW provides end_offset (how many bytes HW DMA'ed) /* HW provides end_offset (how many bytes HW DMA'ed)
@@ -361,7 +915,9 @@ dp_rx_mon_process_status_tlv(struct dp_pdev *pdev)
} while ((tlv_status == HAL_TLV_STATUS_PPDU_NOT_DONE) || } while ((tlv_status == HAL_TLV_STATUS_PPDU_NOT_DONE) ||
(tlv_status == HAL_TLV_STATUS_HEADER) || (tlv_status == HAL_TLV_STATUS_HEADER) ||
(tlv_status == HAL_TLV_STATUS_MPDU_END) || (tlv_status == HAL_TLV_STATUS_MPDU_END) ||
(tlv_status == HAL_TLV_STATUS_MSDU_END)); (tlv_status == HAL_TLV_STATUS_MSDU_END) ||
(tlv_status == HAL_TLV_STATUS_MON_BUF_ADDR) ||
(tlv_status == HAL_TLV_STATUS_MPDU_START));
/* set status buffer pointer to NULL */ /* set status buffer pointer to NULL */
mon_pdev_be->status[idx] = NULL; mon_pdev_be->status[idx] = NULL;
@@ -504,9 +1060,12 @@ dp_rx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
dp_rx_handle_ppdu_stats(soc, pdev, ppdu_info); dp_rx_handle_ppdu_stats(soc, pdev, ppdu_info);
/* Call API to add PPDU info workqueue */ /* Call API to add PPDU info workqueue */
status = dp_rx_mon_add_ppdu_info_to_wq(mon_pdev, ppdu_info);
if (ppdu_info) if (status != QDF_STATUS_SUCCESS) {
qdf_mem_free(ppdu_info); if (ppdu_info)
qdf_mem_free(ppdu_info);
}
work_done++; work_done++;

View File

@@ -21,6 +21,8 @@
#include <qdf_nbuf_frag.h> #include <qdf_nbuf_frag.h>
#include <hal_be_api_mon.h> #include <hal_be_api_mon.h>
#define DP_RX_MON_PACKET_OFFSET 8
#define DP_RX_MON_RX_HDR_OFFSET 8
/* /*
* dp_rx_mon_buffers_alloc() - allocate rx monitor buffers * dp_rx_mon_buffers_alloc() - allocate rx monitor buffers
* @soc: DP soc handle * @soc: DP soc handle
@@ -156,4 +158,16 @@ static inline void dp_rx_mon_process_ppdu(void *context)
{ {
} }
#endif /* DISABLE_MON_CONFIG */ #endif /* DISABLE_MON_CONFIG */
/**
* dp_rx_mon_handle_full_mon() - Handle full monitor MPDU restitch
*
* @pdev: DP pdev
* @ppdu_info: PPDU info
* @mpdu: mpdu buf
*/
void
dp_rx_mon_handle_full_mon(struct dp_pdev *pdev,
struct hal_rx_ppdu_info *ppdu_info,
qdf_nbuf_t mpdu);
#endif /* _DP_RX_MON_2_0_H_ */ #endif /* _DP_RX_MON_2_0_H_ */

View File

@@ -37,6 +37,35 @@
/* The maximum buffer length allocated for radiotap for monitor status buffer */ /* The maximum buffer length allocated for radiotap for monitor status buffer */
#define MAX_MONITOR_HEADER (512) #define MAX_MONITOR_HEADER (512)
/* l2 header pad byte in case of Raw frame is Zero and 2 in non raw */
#define DP_RX_MON_RAW_L2_HDR_PAD_BYTE (0)
#define DP_RX_MON_NONRAW_L2_HDR_PAD_BYTE (2)
/*
* The maximum headroom reserved for monitor destination buffer to
* accomodate radiotap header and protocol flow tag
*/
#ifdef DP_RX_MON_MEM_FRAG
/*
* -------------------------------------------------
* | Protocol & Flow TAG | Radiotap header|
* | | Length(128 B) |
* | ((4* QDF_NBUF_MAX_FRAGS) * 2) | |
* -------------------------------------------------
*/
#define DP_RX_MON_MAX_RADIO_TAP_HDR (128)
#define DP_RX_MON_PF_TAG_LEN_PER_FRAG (4)
#define DP_RX_MON_TOT_PF_TAG_LEN \
((DP_RX_MON_PF_TAG_LEN_PER_FRAG) * (QDF_NBUF_MAX_FRAGS))
#define DP_RX_MON_MAX_MONITOR_HEADER \
((DP_RX_MON_TOT_PF_TAG_LEN * 2) + (DP_RX_MON_MAX_RADIO_TAP_HDR))
#endif
#define DP_RX_MON_LLC_SIZE 4
#define DP_RX_MON_SNAP_SIZE 4
#define DP_RX_MON_DECAP_HDR_SIZE 14
/** /**
* enum dp_mon_reap_status - monitor status ring ppdu status * enum dp_mon_reap_status - monitor status ring ppdu status
* *

View File

@@ -1652,6 +1652,19 @@ hal_rx_status_get_mpdu_retry_cnt(struct hal_rx_ppdu_info *ppdu_info,
HAL_RX_GET_64(rx_tlv, RX_PPDU_END_USER_STATS, HAL_RX_GET_64(rx_tlv, RX_PPDU_END_USER_STATS,
RETRIED_MPDU_COUNT); RETRIED_MPDU_COUNT);
} }
static inline void
hal_rx_status_get_mon_buf_addr(uint8_t *rx_tlv,
struct hal_rx_ppdu_info *ppdu_info)
{
struct mon_buffer_addr *addr = (struct mon_buffer_addr *)rx_tlv;
ppdu_info->packet_info.sw_cookie = (((uint64_t)addr->buffer_virt_addr_63_32 << 32) |
(addr->buffer_virt_addr_31_0));
ppdu_info->packet_info.dma_length = addr->dma_length;
ppdu_info->packet_info.msdu_continuation = addr->msdu_continuation;
}
#else #else
static inline void static inline void
hal_rx_status_get_mpdu_retry_cnt(struct hal_rx_ppdu_info *ppdu_info, hal_rx_status_get_mpdu_retry_cnt(struct hal_rx_ppdu_info *ppdu_info,
@@ -1659,6 +1672,11 @@ hal_rx_status_get_mpdu_retry_cnt(struct hal_rx_ppdu_info *ppdu_info,
{ {
ppdu_info->rx_status.mpdu_retry_cnt = 0; ppdu_info->rx_status.mpdu_retry_cnt = 0;
} }
static inline void
hal_rx_status_get_mon_buf_addr(uint8_t *rx_tlv,
struct hal_rx_ppdu_info *ppdu_info)
{
}
#endif #endif
/** /**
@@ -1694,6 +1712,7 @@ hal_rx_status_get_tlv_info_generic_be(void *rx_tlv_hdr, void *ppduinfo,
qdf_trace_hex_dump(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, qdf_trace_hex_dump(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
rx_tlv, tlv_len); rx_tlv, tlv_len);
ppdu_info->user_id = user_id;
switch (tlv_tag) { switch (tlv_tag) {
case WIFIRX_PPDU_START_E: case WIFIRX_PPDU_START_E:
{ {
@@ -2755,7 +2774,10 @@ hal_rx_status_get_tlv_info_generic_be(void *rx_tlv_hdr, void *ppduinfo,
ppdu_info->nac_info.mcast_bcast = ppdu_info->nac_info.mcast_bcast =
rx_mpdu_start->rx_mpdu_info_details.mcast_bcast; rx_mpdu_start->rx_mpdu_info_details.mcast_bcast;
break; ppdu_info->mpdu_info[user_id].decap_type =
rx_mpdu_start->rx_mpdu_info_details.decap_type;
return HAL_TLV_STATUS_MPDU_START;
} }
case WIFIRX_MPDU_END_E: case WIFIRX_MPDU_END_E:
ppdu_info->user_id = user_id; ppdu_info->user_id = user_id;
@@ -2777,13 +2799,23 @@ hal_rx_status_get_tlv_info_generic_be(void *rx_tlv_hdr, void *ppduinfo,
rx_msdu_end->flow_idx_invalid; rx_msdu_end->flow_idx_invalid;
ppdu_info->rx_msdu_info[user_id].flow_idx = ppdu_info->rx_msdu_info[user_id].flow_idx =
rx_msdu_end->flow_idx; rx_msdu_end->flow_idx;
ppdu_info->msdu[user_id].first_msdu =
rx_msdu_end->first_msdu;
ppdu_info->msdu[user_id].last_msdu =
rx_msdu_end->last_msdu;
ppdu_info->msdu[user_id].msdu_len =
rx_msdu_end->msdu_length;
ppdu_info->msdu[user_id].user_rssi =
rx_msdu_end->user_rssi;
ppdu_info->msdu[user_id].reception_type =
rx_msdu_end->reception_type;
} }
return HAL_TLV_STATUS_MSDU_END; return HAL_TLV_STATUS_MSDU_END;
} }
case WIFIMON_BUFFER_ADDR_E: case WIFIMON_BUFFER_ADDR_E:
{ hal_rx_status_get_mon_buf_addr(rx_tlv, ppdu_info);
return HAL_TLV_STATUS_MON_BUF_ADDR; return HAL_TLV_STATUS_MON_BUF_ADDR;
}
case 0: case 0:
return HAL_TLV_STATUS_PPDU_DONE; return HAL_TLV_STATUS_PPDU_DONE;

View File

@@ -277,6 +277,8 @@ struct hal_rx_mon_msdu_info {
* @overflow_err: overflow error * @overflow_err: overflow error
* @decrypt_err: decrypt error * @decrypt_err: decrypt error
* @mpdu_start_received: MPDU start received * @mpdu_start_received: MPDU start received
* @full_pkt: Full MPDU received
* @first_rx_hdr_rcvd: First rx_hdr received
*/ */
struct hal_rx_mon_mpdu_info { struct hal_rx_mon_mpdu_info {
uint8_t decap_type; uint8_t decap_type;
@@ -285,6 +287,8 @@ struct hal_rx_mon_mpdu_info {
bool overflow_err; bool overflow_err;
bool decrypt_err; bool decrypt_err;
bool mpdu_start_received; bool mpdu_start_received;
bool full_pkt;
bool first_rx_hdr_rcvd;
}; };
/** /**