qca-wifi: Fix mgmt/ctrl retries frames in tx capture
Fix tx capture retries mgmt/ctrl frames Change-Id: I6060a48368f609522a326b5801d82e9899403e77
This commit is contained in:
@@ -58,6 +58,15 @@
|
||||
#define SEQ_BIT(_seqarr, _seqno) \
|
||||
SEQ_SEG_BIT(SEQ_SEG(_seqarr, (_seqno)), (_seqno))
|
||||
|
||||
/* Lower 32 mask for timestamp us as completion path has 32 bits timestamp */
|
||||
#define LOWER_32_MASK 0xFFFFFFFF
|
||||
|
||||
/* Maximum time taken to enqueue next mgmt pkt */
|
||||
#define MAX_MGMT_ENQ_DELAY 10000
|
||||
|
||||
/* Schedule id counter mask in ppdu_id */
|
||||
#define SCH_ID_MASK 0xFF
|
||||
|
||||
#ifdef WLAN_TX_PKT_CAPTURE_ENH
|
||||
|
||||
/*
|
||||
@@ -210,8 +219,6 @@ void dp_peer_update_80211_hdr(struct dp_vdev *vdev, struct dp_peer *peer)
|
||||
*/
|
||||
void dp_deliver_mgmt_frm(struct dp_pdev *pdev, qdf_nbuf_t nbuf)
|
||||
{
|
||||
uint32_t ppdu_id;
|
||||
|
||||
if (pdev->tx_sniffer_enable || pdev->mcopy_mode) {
|
||||
dp_wdi_event_handler(WDI_EVENT_TX_MGMT_CTRL, pdev->soc,
|
||||
nbuf, HTT_INVALID_PEER,
|
||||
@@ -223,14 +230,28 @@ void dp_deliver_mgmt_frm(struct dp_pdev *pdev, qdf_nbuf_t nbuf)
|
||||
/* invoke WDI event handler here send mgmt pkt here */
|
||||
struct ieee80211_frame *wh;
|
||||
uint8_t type, subtype;
|
||||
struct cdp_tx_mgmt_comp_info *ptr_mgmt_hdr;
|
||||
|
||||
ppdu_id = *(uint32_t *)qdf_nbuf_data(nbuf);
|
||||
ptr_mgmt_hdr = (struct cdp_tx_mgmt_comp_info *)
|
||||
qdf_nbuf_data(nbuf);
|
||||
wh = (struct ieee80211_frame *)(qdf_nbuf_data(nbuf) +
|
||||
sizeof(uint32_t));
|
||||
sizeof(struct cdp_tx_mgmt_comp_info));
|
||||
type = (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) >>
|
||||
IEEE80211_FC0_TYPE_SHIFT;
|
||||
subtype = (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
|
||||
IEEE80211_FC0_SUBTYPE_SHIFT;
|
||||
|
||||
if (!ptr_mgmt_hdr->ppdu_id || !ptr_mgmt_hdr->tx_tsf) {
|
||||
/*
|
||||
* if either ppdu_id and tx_tsf are zero then
|
||||
* storing the payload won't be useful
|
||||
* in constructing the packet
|
||||
* Hence freeing the packet
|
||||
*/
|
||||
qdf_nbuf_free(nbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
qdf_spin_lock_bh(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[type][subtype]);
|
||||
qdf_nbuf_queue_add(&pdev->tx_capture.ctl_mgmt_q[type][subtype],
|
||||
@@ -239,7 +260,7 @@ void dp_deliver_mgmt_frm(struct dp_pdev *pdev, qdf_nbuf_t nbuf)
|
||||
&pdev->tx_capture.ctl_mgmt_lock[type][subtype]);
|
||||
QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE, QDF_TRACE_LEVEL_DEBUG,
|
||||
"dlvr mgmt frm(0x%08x): fc 0x%x %x, dur 0x%x%x\n",
|
||||
ppdu_id, wh->i_fc[1], wh->i_fc[0],
|
||||
ptr_mgmt_hdr->ppdu_id, wh->i_fc[1], wh->i_fc[0],
|
||||
wh->i_dur[1], wh->i_dur[0]);
|
||||
}
|
||||
}
|
||||
@@ -1353,6 +1374,7 @@ QDF_STATUS dp_send_dummy_mpdu_info_to_stack(struct dp_pdev *pdev,
|
||||
dp_tx_update_user_mpdu_info(ppdu_desc->bar_ppdu_id,
|
||||
&tx_capture_info.mpdu_info,
|
||||
&ppdu_desc->user[0]);
|
||||
tx_capture_info.ppdu_desc = ppdu_desc;
|
||||
|
||||
mpdu_info->ppdu_id = ppdu_desc->ppdu_id;
|
||||
mpdu_info->channel_num = pdev->operating_channel;
|
||||
@@ -1434,7 +1456,7 @@ QDF_STATUS dp_send_dummy_mpdu_info_to_stack(struct dp_pdev *pdev,
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_send_mpdu_info_to_stack(): Function to deliver mpdu info to stack
|
||||
* dp_send_data_to_stack(): Function to deliver mpdu info to stack
|
||||
* to upper layer
|
||||
* @pdev: DP pdev handle
|
||||
* @nbuf_ppdu_desc_list: ppdu_desc_list per sched cmd id
|
||||
@@ -1443,9 +1465,8 @@ QDF_STATUS dp_send_dummy_mpdu_info_to_stack(struct dp_pdev *pdev,
|
||||
* return: status
|
||||
*/
|
||||
static
|
||||
void dp_send_mpdu_info_to_stack(struct dp_pdev *pdev,
|
||||
struct cdp_tx_completion_ppdu
|
||||
*ppdu_desc)
|
||||
void dp_send_data_to_stack(struct dp_pdev *pdev,
|
||||
struct cdp_tx_completion_ppdu *ppdu_desc)
|
||||
{
|
||||
struct cdp_tx_indication_info tx_capture_info;
|
||||
struct cdp_tx_indication_mpdu_info *mpdu_info;
|
||||
@@ -1594,7 +1615,7 @@ dp_tx_mon_proc_xretries(struct dp_pdev *pdev, struct dp_peer *peer,
|
||||
qdf_nbuf_queue_first(&tx_tid->pending_ppdu_q))) {
|
||||
qdf_nbuf_queue_remove(&tx_tid->pending_ppdu_q);
|
||||
/* Deliver PPDU */
|
||||
dp_send_mpdu_info_to_stack(pdev, ppdu_desc);
|
||||
dp_send_data_to_stack(pdev, ppdu_desc);
|
||||
qdf_nbuf_queue_free(&ppdu_desc->mpdu_q);
|
||||
qdf_mem_free(ppdu_desc->mpdus);
|
||||
ppdu_desc->mpdus = NULL;
|
||||
@@ -1640,7 +1661,7 @@ dp_tx_mon_proc_pending_ppdus(struct dp_pdev *pdev, struct dp_tx_tid *tx_tid,
|
||||
if ((ppdu_desc->pending_retries == 0) &&
|
||||
qdf_nbuf_is_queue_empty(&tx_tid->pending_ppdu_q) &&
|
||||
qdf_nbuf_is_queue_empty(head_ppdu)) {
|
||||
dp_send_mpdu_info_to_stack(pdev, ppdu_desc);
|
||||
dp_send_data_to_stack(pdev, ppdu_desc);
|
||||
qdf_nbuf_queue_free(&ppdu_desc->mpdu_q);
|
||||
qdf_mem_free(ppdu_desc->mpdus);
|
||||
ppdu_desc->mpdus = NULL;
|
||||
@@ -1785,7 +1806,7 @@ dp_tx_mon_proc_pending_ppdus(struct dp_pdev *pdev, struct dp_tx_tid *tx_tid,
|
||||
qdf_nbuf_queue_first(&tx_tid->pending_ppdu_q)) &&
|
||||
(ppdu_desc->pending_retries == 0)) {
|
||||
qdf_nbuf_queue_remove(&tx_tid->pending_ppdu_q);
|
||||
dp_send_mpdu_info_to_stack(pdev, ppdu_desc);
|
||||
dp_send_data_to_stack(pdev, ppdu_desc);
|
||||
qdf_nbuf_queue_free(&ppdu_desc->mpdu_q);
|
||||
qdf_mem_free(ppdu_desc->mpdus);
|
||||
ppdu_desc->mpdus = NULL;
|
||||
@@ -1798,6 +1819,370 @@ dp_tx_mon_proc_pending_ppdus(struct dp_pdev *pdev, struct dp_tx_tid *tx_tid,
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
dp_send_mgmt_ctrl_to_stack(struct dp_pdev *pdev,
|
||||
qdf_nbuf_t nbuf_ppdu_desc,
|
||||
struct cdp_tx_indication_info *ptr_tx_cap_info,
|
||||
qdf_nbuf_t mgmt_ctl_nbuf,
|
||||
bool is_payload)
|
||||
{
|
||||
struct cdp_tx_completion_ppdu *ppdu_desc;
|
||||
struct cdp_tx_indication_mpdu_info *mpdu_info;
|
||||
struct ieee80211_frame *wh;
|
||||
uint16_t duration_le, seq_le;
|
||||
struct ieee80211_frame_min_one *wh_min;
|
||||
uint16_t frame_ctrl_le;
|
||||
uint8_t type, subtype;
|
||||
|
||||
mpdu_info = &ptr_tx_cap_info->mpdu_info;
|
||||
ppdu_desc = (struct cdp_tx_completion_ppdu *)
|
||||
qdf_nbuf_data(nbuf_ppdu_desc);
|
||||
|
||||
type = (ppdu_desc->frame_ctrl &
|
||||
IEEE80211_FC0_TYPE_MASK) >>
|
||||
IEEE80211_FC0_TYPE_SHIFT;
|
||||
subtype = (ppdu_desc->frame_ctrl &
|
||||
IEEE80211_FC0_SUBTYPE_MASK) >>
|
||||
IEEE80211_FC0_SUBTYPE_SHIFT;
|
||||
|
||||
if (is_payload) {
|
||||
wh = (struct ieee80211_frame *)qdf_nbuf_data(mgmt_ctl_nbuf);
|
||||
|
||||
if (subtype != IEEE80211_FC0_SUBTYPE_BEACON) {
|
||||
duration_le = qdf_cpu_to_le16(ppdu_desc->tx_duration);
|
||||
wh->i_dur[1] = (duration_le & 0xFF00) >> 8;
|
||||
wh->i_dur[0] = duration_le & 0xFF;
|
||||
seq_le = qdf_cpu_to_le16(ppdu_desc->user[0].start_seq <<
|
||||
IEEE80211_SEQ_SEQ_SHIFT);
|
||||
wh->i_seq[1] = (seq_le & 0xFF00) >> 8;
|
||||
wh->i_seq[0] = seq_le & 0xFF;
|
||||
}
|
||||
QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE,
|
||||
QDF_TRACE_LEVEL_DEBUG,
|
||||
"ctrl/mgmt frm(0x%08x): fc 0x%x 0x%x\n",
|
||||
ptr_tx_cap_info->mpdu_info.ppdu_id,
|
||||
wh->i_fc[1], wh->i_fc[0]);
|
||||
QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE,
|
||||
QDF_TRACE_LEVEL_DEBUG,
|
||||
"desc->ppdu_id 0x%08x\n", ppdu_desc->ppdu_id);
|
||||
|
||||
/* append ext list */
|
||||
qdf_nbuf_append_ext_list(ptr_tx_cap_info->mpdu_nbuf,
|
||||
mgmt_ctl_nbuf,
|
||||
qdf_nbuf_len(mgmt_ctl_nbuf));
|
||||
} else {
|
||||
wh_min = (struct ieee80211_frame_min_one *)
|
||||
qdf_nbuf_data(ptr_tx_cap_info->mpdu_nbuf);
|
||||
qdf_mem_zero(wh_min, MAX_DUMMY_FRM_BODY);
|
||||
frame_ctrl_le = qdf_cpu_to_le16(ppdu_desc->frame_ctrl);
|
||||
duration_le = qdf_cpu_to_le16(ppdu_desc->tx_duration);
|
||||
wh_min->i_fc[1] = (frame_ctrl_le & 0xFF00) >> 8;
|
||||
wh_min->i_fc[0] = (frame_ctrl_le & 0xFF);
|
||||
wh_min->i_dur[1] = (duration_le & 0xFF00) >> 8;
|
||||
wh_min->i_dur[0] = (duration_le & 0xFF);
|
||||
qdf_mem_copy(wh_min->i_addr1, mpdu_info->mac_address,
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
qdf_nbuf_set_pktlen(ptr_tx_cap_info->mpdu_nbuf,
|
||||
sizeof(*wh_min));
|
||||
QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE,
|
||||
QDF_TRACE_LEVEL_DEBUG,
|
||||
"frm(0x%08x): fc %x %x, dur 0x%x%x\n",
|
||||
ptr_tx_cap_info->mpdu_info.ppdu_id,
|
||||
wh_min->i_fc[1], wh_min->i_fc[0],
|
||||
wh_min->i_dur[1], wh_min->i_dur[0]);
|
||||
}
|
||||
|
||||
|
||||
dp_wdi_event_handler(WDI_EVENT_TX_DATA, pdev->soc,
|
||||
ptr_tx_cap_info, HTT_INVALID_PEER,
|
||||
WDI_NO_VAL, pdev->pdev_id);
|
||||
|
||||
if (ptr_tx_cap_info->mpdu_nbuf)
|
||||
qdf_nbuf_free(ptr_tx_cap_info->mpdu_nbuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
dp_update_tx_cap_info(struct dp_pdev *pdev,
|
||||
qdf_nbuf_t nbuf_ppdu_desc,
|
||||
void *tx_info, bool is_payload)
|
||||
{
|
||||
struct cdp_tx_completion_ppdu *ppdu_desc;
|
||||
struct cdp_tx_indication_info *tx_capture_info =
|
||||
(struct cdp_tx_indication_info *)tx_info;
|
||||
struct cdp_tx_indication_mpdu_info *mpdu_info;
|
||||
|
||||
ppdu_desc = (struct cdp_tx_completion_ppdu *)
|
||||
qdf_nbuf_data(nbuf_ppdu_desc);
|
||||
|
||||
qdf_mem_set(tx_capture_info, sizeof(struct cdp_tx_indication_info), 0);
|
||||
mpdu_info = &tx_capture_info->mpdu_info;
|
||||
|
||||
mpdu_info->channel = ppdu_desc->channel;
|
||||
mpdu_info->frame_type = ppdu_desc->frame_type;
|
||||
mpdu_info->ppdu_start_timestamp = ppdu_desc->ppdu_start_timestamp;
|
||||
mpdu_info->ppdu_end_timestamp = ppdu_desc->ppdu_end_timestamp;
|
||||
mpdu_info->tx_duration = ppdu_desc->tx_duration;
|
||||
mpdu_info->seq_no = ppdu_desc->user[0].start_seq;
|
||||
mpdu_info->num_msdu = ppdu_desc->num_msdu;
|
||||
|
||||
/* update cdp_tx_indication_mpdu_info */
|
||||
dp_tx_update_user_mpdu_info(ppdu_desc->ppdu_id,
|
||||
&tx_capture_info->mpdu_info,
|
||||
&ppdu_desc->user[0]);
|
||||
tx_capture_info->ppdu_desc = ppdu_desc;
|
||||
|
||||
tx_capture_info->mpdu_info.channel_num = pdev->operating_channel;
|
||||
tx_capture_info->mpdu_info.ppdu_id = ppdu_desc->ppdu_id;
|
||||
if (is_payload)
|
||||
tx_capture_info->mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
|
||||
MAX_MONITOR_HEADER,
|
||||
MAX_MONITOR_HEADER,
|
||||
4, FALSE);
|
||||
else
|
||||
tx_capture_info->mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
|
||||
MAX_MONITOR_HEADER +
|
||||
MAX_DUMMY_FRM_BODY,
|
||||
MAX_MONITOR_HEADER,
|
||||
4, FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
dp_check_mgmt_ctrl_ppdu(struct dp_pdev *pdev,
|
||||
qdf_nbuf_t nbuf_ppdu_desc)
|
||||
{
|
||||
struct cdp_tx_indication_info tx_capture_info;
|
||||
qdf_nbuf_t mgmt_ctl_nbuf;
|
||||
uint8_t type, subtype;
|
||||
bool is_sgen_pkt;
|
||||
struct cdp_tx_mgmt_comp_info *ptr_comp_info;
|
||||
qdf_nbuf_queue_t *retries_q;
|
||||
struct cdp_tx_completion_ppdu *ppdu_desc;
|
||||
uint32_t ppdu_id;
|
||||
size_t head_size;
|
||||
uint32_t status = 1;
|
||||
|
||||
ppdu_desc = (struct cdp_tx_completion_ppdu *)
|
||||
qdf_nbuf_data(nbuf_ppdu_desc);
|
||||
/*
|
||||
* only for host generated frame we do have
|
||||
* timestamp and retries count.
|
||||
*/
|
||||
head_size = sizeof(struct cdp_tx_mgmt_comp_info);
|
||||
|
||||
type = (ppdu_desc->frame_ctrl &
|
||||
IEEE80211_FC0_TYPE_MASK) >>
|
||||
IEEE80211_FC0_TYPE_SHIFT;
|
||||
subtype = (ppdu_desc->frame_ctrl &
|
||||
IEEE80211_FC0_SUBTYPE_MASK) >>
|
||||
IEEE80211_FC0_SUBTYPE_SHIFT;
|
||||
|
||||
if (ppdu_desc->htt_frame_type == HTT_STATS_FTYPE_SGEN_NDP) {
|
||||
dp_update_frame_ctrl_from_frame_type(ppdu_desc);
|
||||
type = 0;
|
||||
subtype = 0;
|
||||
}
|
||||
|
||||
retries_q = &pdev->tx_capture.retries_ctl_mgmt_q[type][subtype];
|
||||
get_mgmt_pkt_from_queue:
|
||||
qdf_spin_lock_bh(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[type][subtype]);
|
||||
mgmt_ctl_nbuf = qdf_nbuf_queue_remove(
|
||||
&pdev->tx_capture.ctl_mgmt_q[type][subtype]);
|
||||
qdf_spin_unlock_bh(&pdev->tx_capture.ctl_mgmt_lock[type][subtype]);
|
||||
|
||||
if (mgmt_ctl_nbuf) {
|
||||
qdf_nbuf_t tmp_mgmt_ctl_nbuf;
|
||||
uint32_t start_tsf;
|
||||
|
||||
ptr_comp_info = (struct cdp_tx_mgmt_comp_info *)
|
||||
qdf_nbuf_data(mgmt_ctl_nbuf);
|
||||
is_sgen_pkt = ptr_comp_info->is_sgen_pkt;
|
||||
ppdu_id = ptr_comp_info->ppdu_id;
|
||||
|
||||
if (!is_sgen_pkt && ptr_comp_info->tx_tsf <
|
||||
ppdu_desc->ppdu_start_timestamp) {
|
||||
/*
|
||||
* free the older mgmt buffer from
|
||||
* the queue and get new mgmt buffer
|
||||
*/
|
||||
qdf_nbuf_free(mgmt_ctl_nbuf);
|
||||
goto get_mgmt_pkt_from_queue;
|
||||
}
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE,
|
||||
QDF_TRACE_LEVEL_INFO_HIGH,
|
||||
"ppdu_id [%d 0x%x] type_subtype[%d %d] is_sgen[%d] h_sz[%d]",
|
||||
ppdu_id, ppdu_id, type, subtype,
|
||||
is_sgen_pkt, head_size);
|
||||
|
||||
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_TX_CAPTURE,
|
||||
QDF_TRACE_LEVEL_INFO_HIGH,
|
||||
qdf_nbuf_data(mgmt_ctl_nbuf), 32);
|
||||
|
||||
/*
|
||||
* for sgen frame we won't have, retries count
|
||||
* and 64 bits tsf in the head.
|
||||
*/
|
||||
if (ppdu_id != ppdu_desc->ppdu_id) {
|
||||
if (is_sgen_pkt) {
|
||||
start_tsf = (ppdu_desc->ppdu_start_timestamp &
|
||||
LOWER_32_MASK);
|
||||
if ((ptr_comp_info->tx_tsf <
|
||||
(start_tsf + MAX_MGMT_ENQ_DELAY)) &&
|
||||
((ppdu_id & SCH_ID_MASK) <
|
||||
(ppdu_desc->ppdu_id & SCH_ID_MASK))) {
|
||||
/*
|
||||
* free the older mgmt buffer from
|
||||
* the queue and get new mgmt buffer
|
||||
*/
|
||||
qdf_nbuf_free(mgmt_ctl_nbuf);
|
||||
goto get_mgmt_pkt_from_queue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ppdu_desc->user[0].completion_status ==
|
||||
HTT_PPDU_STATS_USER_STATUS_FILTERED) {
|
||||
qdf_nbuf_free(nbuf_ppdu_desc);
|
||||
status = 0;
|
||||
goto free_ppdu_desc;
|
||||
}
|
||||
|
||||
/*
|
||||
* add the ppdu_desc into retry queue
|
||||
*/
|
||||
qdf_nbuf_queue_add(retries_q, nbuf_ppdu_desc);
|
||||
status = 0;
|
||||
|
||||
/*
|
||||
* insert the mgmt_ctl buffer back to
|
||||
* the queue
|
||||
*/
|
||||
qdf_spin_lock_bh(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[type][subtype]);
|
||||
qdf_nbuf_queue_insert_head(
|
||||
&pdev->tx_capture.ctl_mgmt_q[type][subtype],
|
||||
mgmt_ctl_nbuf);
|
||||
qdf_spin_unlock_bh(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[type][subtype]);
|
||||
} else {
|
||||
qdf_nbuf_t nbuf_retry_ppdu;
|
||||
struct cdp_tx_completion_ppdu *tmp_ppdu_desc;
|
||||
uint16_t frame_ctrl_le;
|
||||
struct ieee80211_frame *wh;
|
||||
|
||||
if (ppdu_desc->user[0].completion_status ==
|
||||
HTT_PPDU_STATS_USER_STATUS_FILTERED) {
|
||||
qdf_nbuf_free(nbuf_ppdu_desc);
|
||||
qdf_nbuf_free(mgmt_ctl_nbuf);
|
||||
status = 0;
|
||||
goto free_ppdu_desc;
|
||||
}
|
||||
|
||||
while (!!qdf_nbuf_queue_len(retries_q)) {
|
||||
/*
|
||||
* send retried packet stored
|
||||
* in queue
|
||||
*/
|
||||
nbuf_retry_ppdu =
|
||||
qdf_nbuf_queue_remove(retries_q);
|
||||
tmp_ppdu_desc =
|
||||
(struct cdp_tx_completion_ppdu *)
|
||||
qdf_nbuf_data(nbuf_retry_ppdu);
|
||||
tmp_mgmt_ctl_nbuf =
|
||||
skb_copy_expand(mgmt_ctl_nbuf,
|
||||
0, 0, GFP_ATOMIC);
|
||||
|
||||
dp_update_tx_cap_info(pdev, nbuf_retry_ppdu,
|
||||
&tx_capture_info, true);
|
||||
if (!tx_capture_info.mpdu_nbuf) {
|
||||
qdf_nbuf_free(nbuf_retry_ppdu);
|
||||
qdf_nbuf_free(tmp_mgmt_ctl_nbuf);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* pull head based on sgen pkt or mgmt pkt */
|
||||
qdf_nbuf_pull_head(tmp_mgmt_ctl_nbuf,
|
||||
head_size);
|
||||
|
||||
/*
|
||||
* frame control from ppdu_desc has
|
||||
* retry flag set
|
||||
*/
|
||||
frame_ctrl_le =
|
||||
qdf_cpu_to_le16(tmp_ppdu_desc->frame_ctrl);
|
||||
wh = (struct ieee80211_frame *)
|
||||
(qdf_nbuf_data(tmp_mgmt_ctl_nbuf));
|
||||
wh->i_fc[1] = (frame_ctrl_le & 0xFF00) >> 8;
|
||||
wh->i_fc[0] = (frame_ctrl_le & 0xFF);
|
||||
|
||||
/*
|
||||
* send MPDU to osif layer
|
||||
*/
|
||||
dp_send_mgmt_ctrl_to_stack(pdev,
|
||||
nbuf_retry_ppdu,
|
||||
&tx_capture_info,
|
||||
tmp_mgmt_ctl_nbuf,
|
||||
true);
|
||||
|
||||
/* free retried queue nbuf ppdu_desc */
|
||||
qdf_nbuf_free(nbuf_retry_ppdu);
|
||||
}
|
||||
|
||||
dp_update_tx_cap_info(pdev, nbuf_ppdu_desc,
|
||||
&tx_capture_info, true);
|
||||
if (!tx_capture_info.mpdu_nbuf) {
|
||||
qdf_nbuf_free(mgmt_ctl_nbuf);
|
||||
goto free_ppdu_desc;
|
||||
}
|
||||
|
||||
tx_capture_info.mpdu_info.ppdu_id =
|
||||
*(uint32_t *)qdf_nbuf_data(mgmt_ctl_nbuf);
|
||||
/* pull head based on sgen pkt or mgmt pkt */
|
||||
qdf_nbuf_pull_head(mgmt_ctl_nbuf, head_size);
|
||||
|
||||
/* frame control from ppdu_desc has retry flag set */
|
||||
frame_ctrl_le = qdf_cpu_to_le16(ppdu_desc->frame_ctrl);
|
||||
wh = (struct ieee80211_frame *)
|
||||
(qdf_nbuf_data(mgmt_ctl_nbuf));
|
||||
wh->i_fc[1] = (frame_ctrl_le & 0xFF00) >> 8;
|
||||
wh->i_fc[0] = (frame_ctrl_le & 0xFF);
|
||||
|
||||
/*
|
||||
* send MPDU to osif layer
|
||||
*/
|
||||
dp_send_mgmt_ctrl_to_stack(pdev, nbuf_ppdu_desc,
|
||||
&tx_capture_info,
|
||||
mgmt_ctl_nbuf, true);
|
||||
}
|
||||
} else if ((ppdu_desc->frame_ctrl &
|
||||
IEEE80211_FC0_TYPE_MASK) ==
|
||||
IEEE80211_FC0_TYPE_CTL) {
|
||||
|
||||
if (ppdu_desc->user[0].completion_status ==
|
||||
HTT_PPDU_STATS_USER_STATUS_FILTERED) {
|
||||
qdf_nbuf_free(nbuf_ppdu_desc);
|
||||
status = 0;
|
||||
goto free_ppdu_desc;
|
||||
}
|
||||
|
||||
dp_update_tx_cap_info(pdev, nbuf_ppdu_desc,
|
||||
&tx_capture_info, false);
|
||||
if (!tx_capture_info.mpdu_nbuf)
|
||||
goto free_ppdu_desc;
|
||||
/*
|
||||
* send MPDU to osif layer
|
||||
*/
|
||||
dp_send_mgmt_ctrl_to_stack(pdev, nbuf_ppdu_desc,
|
||||
&tx_capture_info, NULL, false);
|
||||
}
|
||||
|
||||
free_ppdu_desc:
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_tx_ppdu_stats_flush(): Function to flush pending retried ppdu desc
|
||||
* @pdev: DP pdev handle
|
||||
@@ -1855,6 +2240,7 @@ dp_check_ppdu_and_deliver(struct dp_pdev *pdev,
|
||||
uint32_t len;
|
||||
qdf_nbuf_t mpdu_nbuf;
|
||||
struct dp_peer *peer;
|
||||
uint8_t type;
|
||||
|
||||
if (!nbuf_ppdu_desc_list[desc_cnt])
|
||||
continue;
|
||||
@@ -1863,6 +2249,8 @@ dp_check_ppdu_and_deliver(struct dp_pdev *pdev,
|
||||
qdf_nbuf_data(nbuf_ppdu_desc_list[desc_cnt]);
|
||||
|
||||
ppdu_id = ppdu_desc->ppdu_id;
|
||||
type = (ppdu_desc->frame_ctrl & IEEE80211_FC0_TYPE_MASK) >>
|
||||
IEEE80211_FC0_TYPE_SHIFT;
|
||||
|
||||
if (ppdu_desc->is_flush) {
|
||||
dp_tx_ppdu_stats_flush(pdev, ppdu_desc);
|
||||
@@ -1874,128 +2262,17 @@ dp_check_ppdu_and_deliver(struct dp_pdev *pdev,
|
||||
|
||||
if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_CTRL ||
|
||||
ppdu_desc->htt_frame_type ==
|
||||
HTT_STATS_FTYPE_SGEN_QOS_NULL) {
|
||||
struct cdp_tx_indication_info tx_capture_info;
|
||||
struct cdp_tx_indication_mpdu_info *mpdu_info;
|
||||
qdf_nbuf_t mgmt_ctl_nbuf;
|
||||
uint8_t type, subtype;
|
||||
HTT_STATS_FTYPE_SGEN_QOS_NULL ||
|
||||
type != FRAME_CTRL_TYPE_DATA) {
|
||||
qdf_nbuf_t nbuf_ppdu = nbuf_ppdu_desc_list[desc_cnt];
|
||||
|
||||
qdf_mem_set(&tx_capture_info,
|
||||
sizeof(struct cdp_tx_indication_info),
|
||||
0);
|
||||
mpdu_info = &tx_capture_info.mpdu_info;
|
||||
|
||||
mpdu_info->channel = ppdu_desc->channel;
|
||||
mpdu_info->frame_type = ppdu_desc->frame_type;
|
||||
mpdu_info->ppdu_start_timestamp =
|
||||
ppdu_desc->ppdu_start_timestamp;
|
||||
mpdu_info->ppdu_end_timestamp =
|
||||
ppdu_desc->ppdu_end_timestamp;
|
||||
mpdu_info->tx_duration = ppdu_desc->tx_duration;
|
||||
mpdu_info->seq_no = seq_no;
|
||||
mpdu_info->num_msdu = ppdu_desc->num_msdu;
|
||||
|
||||
mpdu_info->resp_type = ppdu_desc->resp_type;
|
||||
mpdu_info->mprot_type = ppdu_desc->mprot_type;
|
||||
mpdu_info->rts_success = ppdu_desc->rts_success;
|
||||
mpdu_info->rts_failure = ppdu_desc->rts_failure;
|
||||
|
||||
/* update cdp_tx_indication_mpdu_info */
|
||||
dp_tx_update_user_mpdu_info(ppdu_id,
|
||||
&tx_capture_info.mpdu_info,
|
||||
&ppdu_desc->user[0]);
|
||||
tx_capture_info.ppdu_desc = ppdu_desc;
|
||||
|
||||
tx_capture_info.mpdu_info.channel_num =
|
||||
pdev->operating_channel;
|
||||
|
||||
if (!ppdu_desc->frame_ctrl)
|
||||
dp_update_frame_ctrl_from_frame_type(ppdu_desc);
|
||||
|
||||
type = (ppdu_desc->frame_ctrl &
|
||||
IEEE80211_FC0_TYPE_MASK) >>
|
||||
IEEE80211_FC0_TYPE_SHIFT;
|
||||
subtype = (ppdu_desc->frame_ctrl &
|
||||
IEEE80211_FC0_SUBTYPE_MASK) >>
|
||||
IEEE80211_FC0_SUBTYPE_SHIFT;
|
||||
qdf_spin_lock_bh(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[type][subtype]);
|
||||
mgmt_ctl_nbuf = qdf_nbuf_queue_remove(
|
||||
&pdev->tx_capture.ctl_mgmt_q[type][subtype]);
|
||||
qdf_spin_unlock_bh(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[type][subtype]);
|
||||
if (mgmt_ctl_nbuf) {
|
||||
struct ieee80211_frame *wh;
|
||||
uint16_t duration_le, seq_le;
|
||||
|
||||
tx_capture_info.mpdu_nbuf =
|
||||
qdf_nbuf_alloc(pdev->soc->osdev,
|
||||
MAX_MONITOR_HEADER, MAX_MONITOR_HEADER,
|
||||
4, FALSE);
|
||||
if (!tx_capture_info.mpdu_nbuf) {
|
||||
qdf_nbuf_free(mgmt_ctl_nbuf);
|
||||
goto free_ppdu_desc;
|
||||
}
|
||||
/* pull ppdu_id from the packet */
|
||||
tx_capture_info.mpdu_info.ppdu_id =
|
||||
*(uint32_t *)qdf_nbuf_data(mgmt_ctl_nbuf);
|
||||
qdf_nbuf_pull_head(mgmt_ctl_nbuf, sizeof(uint32_t));
|
||||
wh = (struct ieee80211_frame *)qdf_nbuf_data(mgmt_ctl_nbuf);
|
||||
|
||||
if (subtype != IEEE80211_FC0_SUBTYPE_BEACON) {
|
||||
duration_le = qdf_cpu_to_le16(
|
||||
ppdu_desc->tx_duration);
|
||||
wh->i_dur[1] =
|
||||
(duration_le & 0xFF00) >> 8;
|
||||
wh->i_dur[0] = duration_le & 0xFF;
|
||||
seq_le = qdf_cpu_to_le16(
|
||||
ppdu_desc->user[0].start_seq <<
|
||||
IEEE80211_SEQ_SEQ_SHIFT);
|
||||
wh->i_seq[1] = (seq_le & 0xFF00) >> 8;
|
||||
wh->i_seq[0] = seq_le & 0xFF;
|
||||
}
|
||||
qdf_nbuf_append_ext_list(
|
||||
tx_capture_info.mpdu_nbuf,
|
||||
mgmt_ctl_nbuf,
|
||||
qdf_nbuf_len(mgmt_ctl_nbuf));
|
||||
QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE,
|
||||
QDF_TRACE_LEVEL_DEBUG,
|
||||
"ctrl/mgmt frm(0x%08x): fc 0x%x 0x%x\n",
|
||||
tx_capture_info.mpdu_info.ppdu_id,
|
||||
wh->i_fc[1], wh->i_fc[0]);
|
||||
QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE,
|
||||
QDF_TRACE_LEVEL_DEBUG,
|
||||
"desc->ppdu_id 0x%08x\n", ppdu_id);
|
||||
} else {
|
||||
dp_send_dummy_mpdu_info_to_stack(pdev,
|
||||
ppdu_desc);
|
||||
goto free_ppdu_desc;
|
||||
if (dp_check_mgmt_ctrl_ppdu(pdev, nbuf_ppdu)) {
|
||||
tmp_nbuf = nbuf_ppdu_desc_list[desc_cnt];
|
||||
nbuf_ppdu_desc_list[desc_cnt] = NULL;
|
||||
qdf_nbuf_free(tmp_nbuf);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* send MPDU to osif layer
|
||||
*/
|
||||
dp_wdi_event_handler(WDI_EVENT_TX_DATA, pdev->soc,
|
||||
&tx_capture_info, HTT_INVALID_PEER,
|
||||
WDI_NO_VAL, pdev->pdev_id);
|
||||
|
||||
if (tx_capture_info.mpdu_nbuf)
|
||||
qdf_nbuf_free(tx_capture_info.mpdu_nbuf);
|
||||
|
||||
free_ppdu_desc:
|
||||
tmp_nbuf = nbuf_ppdu_desc_list[desc_cnt];
|
||||
nbuf_ppdu_desc_list[desc_cnt] = NULL;
|
||||
qdf_nbuf_free(tmp_nbuf);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (qdf_nbuf_is_queue_empty(&ppdu_desc->mpdu_q)) {
|
||||
if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR)
|
||||
dp_send_dummy_mpdu_info_to_stack(pdev,
|
||||
ppdu_desc);
|
||||
|
||||
tmp_nbuf = nbuf_ppdu_desc_list[desc_cnt];
|
||||
nbuf_ppdu_desc_list[desc_cnt] = NULL;
|
||||
qdf_nbuf_free(tmp_nbuf);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2029,6 +2306,9 @@ free_ppdu_desc:
|
||||
ppdu_desc->user[0].start_seq;
|
||||
}
|
||||
|
||||
if (ppdu_desc->user[0].ba_size == 0)
|
||||
ppdu_desc->user[0].ba_size = 1;
|
||||
|
||||
/* find list of missing sequence */
|
||||
ppdu_desc->mpdus = qdf_mem_malloc(sizeof(qdf_nbuf_t) *
|
||||
ppdu_desc->user[0].ba_size);
|
||||
@@ -2109,7 +2389,7 @@ free_ppdu_desc:
|
||||
|
||||
if ((ppdu_desc->pending_retries == 0) &&
|
||||
qdf_nbuf_is_queue_empty(&tx_tid->pending_ppdu_q)) {
|
||||
dp_send_mpdu_info_to_stack(pdev, ppdu_desc);
|
||||
dp_send_data_to_stack(pdev, ppdu_desc);
|
||||
qdf_nbuf_queue_free(&ppdu_desc->mpdu_q);
|
||||
qdf_mem_free(ppdu_desc->mpdus);
|
||||
ppdu_desc->mpdus = NULL;
|
||||
@@ -2155,7 +2435,7 @@ free_ppdu_desc:
|
||||
qdf_nbuf_data(tmp_nbuf);
|
||||
if (cur_ppdu_desc->pending_retries)
|
||||
break;
|
||||
dp_send_mpdu_info_to_stack(pdev, cur_ppdu_desc);
|
||||
dp_send_data_to_stack(pdev, cur_ppdu_desc);
|
||||
qdf_nbuf_queue_free(&cur_ppdu_desc->mpdu_q);
|
||||
qdf_mem_free(cur_ppdu_desc->mpdus);
|
||||
cur_ppdu_desc->mpdus = NULL;
|
||||
|
Reference in New Issue
Block a user