qca-wifi: Fix mgmt/ctrl frames in tx capture
Include host generated management and also update phy information for control and mgmt indications from FW when Tx capture is enabled. Change-Id: Icbc0b175c73b6eab0bb6e35fa157bfce92927d24
This commit is contained in:
@@ -31,6 +31,9 @@
|
||||
|
||||
#include "dp_tx_capture.h"
|
||||
|
||||
#define MAX_MONITOR_HEADER (512)
|
||||
#define MAX_DUMMY_FRM_BODY (128)
|
||||
|
||||
#ifdef WLAN_TX_PKT_CAPTURE_ENH
|
||||
/**
|
||||
* dp_peer_or_pdev_tx_cap_enabled - Returns status of tx_cap_enabled
|
||||
@@ -135,7 +138,7 @@ 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)
|
||||
{
|
||||
struct cdp_tx_indication_info tx_capture_info;
|
||||
uint32_t ppdu_id;
|
||||
|
||||
if (pdev->tx_sniffer_enable || pdev->mcopy_mode) {
|
||||
dp_wdi_event_handler(WDI_EVENT_TX_MGMT_CTRL, pdev->soc,
|
||||
@@ -146,24 +149,26 @@ void dp_deliver_mgmt_frm(struct dp_pdev *pdev, qdf_nbuf_t nbuf)
|
||||
if (pdev->tx_capture_enabled == CDP_TX_ENH_CAPTURE_ENABLE_ALL_PEERS ||
|
||||
pdev->tx_capture_enabled == CDP_TX_ENH_CAPTURE_ENDIS_PER_PEER) {
|
||||
/* invoke WDI event handler here send mgmt pkt here */
|
||||
struct ieee80211_frame *wh;
|
||||
uint8_t type, subtype;
|
||||
|
||||
/* pull ppdu_id from the packet */
|
||||
qdf_nbuf_pull_head(nbuf, sizeof(uint32_t));
|
||||
tx_capture_info.frame_payload = 1;
|
||||
tx_capture_info.mpdu_nbuf = nbuf;
|
||||
|
||||
/*
|
||||
* send MPDU to osif layer
|
||||
* do we need to update mpdu_info before tranmit
|
||||
* get current mpdu_nbuf
|
||||
*/
|
||||
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);
|
||||
|
||||
ppdu_id = *(uint32_t *)qdf_nbuf_data(nbuf);
|
||||
wh = (struct ieee80211_frame *)(qdf_nbuf_data(nbuf) +
|
||||
sizeof(uint32_t));
|
||||
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;
|
||||
qdf_spin_lock_bh(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[type][subtype]);
|
||||
qdf_nbuf_queue_add(&pdev->tx_capture.ctl_mgmt_q[type][subtype],
|
||||
nbuf);
|
||||
qdf_spin_unlock_bh(
|
||||
&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],
|
||||
wh->i_dur[1], wh->i_dur[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +180,7 @@ void dp_deliver_mgmt_frm(struct dp_pdev *pdev, qdf_nbuf_t nbuf)
|
||||
*/
|
||||
void dp_tx_ppdu_stats_attach(struct dp_pdev *pdev)
|
||||
{
|
||||
int i, j;
|
||||
/* Work queue setup for HTT stats and tx capture handling */
|
||||
qdf_create_work(0, &pdev->tx_capture.ppdu_stats_work,
|
||||
dp_tx_ppdu_stats_process,
|
||||
@@ -188,6 +194,14 @@ void dp_tx_ppdu_stats_attach(struct dp_pdev *pdev)
|
||||
pdev->tx_capture.ppdu_stats_next_sched = 0;
|
||||
pdev->tx_capture.ppdu_stats_defer_queue_depth = 0;
|
||||
pdev->tx_capture.ppdu_dropped = 0;
|
||||
for (i = 0; i < TXCAP_MAX_TYPE; i++) {
|
||||
for (j = 0; j < TXCAP_MAX_SUBTYPE; j++) {
|
||||
qdf_nbuf_queue_init(
|
||||
&pdev->tx_capture.ctl_mgmt_q[i][j]);
|
||||
qdf_spinlock_create(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,6 +213,7 @@ void dp_tx_ppdu_stats_attach(struct dp_pdev *pdev)
|
||||
void dp_tx_ppdu_stats_detach(struct dp_pdev *pdev)
|
||||
{
|
||||
struct ppdu_info *ppdu_info, *tmp_ppdu_info = NULL;
|
||||
int i, j;
|
||||
|
||||
if (!pdev || !pdev->tx_capture.ppdu_stats_workqueue)
|
||||
return;
|
||||
@@ -225,6 +240,18 @@ void dp_tx_ppdu_stats_detach(struct dp_pdev *pdev)
|
||||
qdf_nbuf_free(ppdu_info->nbuf);
|
||||
qdf_mem_free(ppdu_info);
|
||||
}
|
||||
for (i = 0; i < TXCAP_MAX_TYPE; i++) {
|
||||
for (j = 0; j < TXCAP_MAX_SUBTYPE; j++) {
|
||||
qdf_spin_lock_bh(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[i][j]);
|
||||
qdf_nbuf_queue_free(
|
||||
&pdev->tx_capture.ctl_mgmt_q[i][j]);
|
||||
qdf_spin_unlock_bh(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[i][j]);
|
||||
qdf_spinlock_destroy(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,6 +505,7 @@ QDF_STATUS
|
||||
dp_config_enh_tx_capture(struct cdp_pdev *pdev_handle, uint8_t val)
|
||||
{
|
||||
struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
|
||||
int i, j;
|
||||
|
||||
pdev->tx_capture_enabled = val;
|
||||
|
||||
@@ -494,6 +522,16 @@ dp_config_enh_tx_capture(struct cdp_pdev *pdev_handle, uint8_t val)
|
||||
DP_PPDU_STATS_CFG_ENH_STATS,
|
||||
pdev->pdev_id);
|
||||
dp_iterate_free_peer_msdu_q(pdev);
|
||||
for (i = 0; i < TXCAP_MAX_TYPE; i++) {
|
||||
for (j = 0; j < TXCAP_MAX_SUBTYPE; j++) {
|
||||
qdf_spin_lock_bh(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[i][j]);
|
||||
qdf_nbuf_queue_free(
|
||||
&pdev->tx_capture.ctl_mgmt_q[i][j]);
|
||||
qdf_spin_unlock_bh(
|
||||
&pdev->tx_capture.ctl_mgmt_lock[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
@@ -665,8 +703,6 @@ static uint32_t dp_tx_update_80211_hdr(struct dp_pdev *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_MONITOR_HEADER (512)
|
||||
|
||||
/**
|
||||
* dp_tx_mon_restitch_mpdu_from_msdus(): Function to restitch msdu to mpdu
|
||||
* @pdev: dp_pdev
|
||||
@@ -1136,18 +1172,13 @@ QDF_STATUS dp_send_mpdu_info_to_stack(struct dp_pdev *pdev,
|
||||
if (!ppdu_desc)
|
||||
continue;
|
||||
|
||||
if (qdf_nbuf_is_queue_empty(&ppdu_desc->mpdu_q)) {
|
||||
tmp_nbuf = nbuf_ppdu_desc_list[desc_cnt];
|
||||
nbuf_ppdu_desc_list[desc_cnt] = NULL;
|
||||
qdf_nbuf_free(tmp_nbuf);
|
||||
continue;
|
||||
}
|
||||
|
||||
ppdu_id = ppdu_desc->ppdu_id;
|
||||
|
||||
if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_CTRL) {
|
||||
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;
|
||||
|
||||
qdf_mem_set(&tx_capture_info,
|
||||
sizeof(struct cdp_tx_indication_info),
|
||||
@@ -1165,20 +1196,105 @@ QDF_STATUS dp_send_mpdu_info_to_stack(struct dp_pdev *pdev,
|
||||
mpdu_info->num_msdu = ppdu_desc->num_msdu;
|
||||
|
||||
/* update cdp_tx_indication_mpdu_info */
|
||||
dp_tx_update_user_mpdu_info(ppdu_desc->ppdu_id,
|
||||
dp_tx_update_user_mpdu_info(ppdu_id,
|
||||
&tx_capture_info.mpdu_info,
|
||||
&ppdu_desc->user[0]);
|
||||
|
||||
tx_capture_info.mpdu_info.channel_num =
|
||||
pdev->operating_channel;
|
||||
|
||||
tx_capture_info.mpdu_nbuf =
|
||||
qdf_nbuf_queue_remove(&ppdu_desc->mpdu_q);
|
||||
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 if ((ppdu_desc->frame_ctrl &
|
||||
IEEE80211_FC0_TYPE_MASK) ==
|
||||
IEEE80211_FC0_TYPE_CTL) {
|
||||
struct ieee80211_frame_min_one *wh_min;
|
||||
uint16_t frame_ctrl_le, duration_le;
|
||||
|
||||
tx_capture_info.mpdu_nbuf =
|
||||
qdf_nbuf_alloc(pdev->soc->osdev,
|
||||
MAX_MONITOR_HEADER + MAX_DUMMY_FRM_BODY,
|
||||
MAX_MONITOR_HEADER,
|
||||
4, FALSE);
|
||||
if (!tx_capture_info.mpdu_nbuf)
|
||||
goto free_ppdu_desc;
|
||||
wh_min = (struct ieee80211_frame_min_one *)
|
||||
qdf_nbuf_data(
|
||||
tx_capture_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(tx_capture_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",
|
||||
ppdu_id, wh_min->i_fc[1], wh_min->i_fc[0],
|
||||
wh_min->i_dur[1], wh_min->i_dur[0]);
|
||||
}
|
||||
/*
|
||||
* send MPDU to osif layer
|
||||
* do we need to update mpdu_info before tranmit
|
||||
* get current mpdu_nbuf
|
||||
*/
|
||||
dp_wdi_event_handler(WDI_EVENT_TX_DATA, pdev->soc,
|
||||
&tx_capture_info, HTT_INVALID_PEER,
|
||||
@@ -1187,13 +1303,20 @@ QDF_STATUS dp_send_mpdu_info_to_stack(struct dp_pdev *pdev,
|
||||
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)) {
|
||||
tmp_nbuf = nbuf_ppdu_desc_list[desc_cnt];
|
||||
nbuf_ppdu_desc_list[desc_cnt] = NULL;
|
||||
qdf_nbuf_free(tmp_nbuf);
|
||||
continue;
|
||||
}
|
||||
|
||||
ppdu_id = ppdu_desc->ppdu_id;
|
||||
/* find mpdu tried is same as success mpdu */
|
||||
|
||||
mpdu_tried = ppdu_desc->user[0].mpdu_tried_ucast +
|
||||
@@ -1228,7 +1351,7 @@ QDF_STATUS dp_send_mpdu_info_to_stack(struct dp_pdev *pdev,
|
||||
nbuf_ppdu_desc_list + desc_cnt,
|
||||
ppdu_desc_cnt - desc_cnt,
|
||||
seq_no,
|
||||
ppdu_desc->ppdu_id);
|
||||
ppdu_id);
|
||||
|
||||
/* check mpdu_nbuf NULL */
|
||||
if (!mpdu_nbuf)
|
||||
@@ -1464,28 +1587,22 @@ void dp_tx_ppdu_stats_process(void *context)
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether it is bss peer,
|
||||
* if bss_peer no need to process further
|
||||
*/
|
||||
if (peer->bss_peer) {
|
||||
dp_peer_unref_del_find_by_id(peer);
|
||||
qdf_nbuf_free(nbuf);
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether tx_capture feature is enabled
|
||||
* for this peer or globally for all peers
|
||||
*/
|
||||
if (!dp_peer_or_pdev_tx_cap_enabled(pdev, peer)) {
|
||||
dp_peer_unref_del_find_by_id(peer);
|
||||
qdf_nbuf_free(nbuf);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((ppdu_desc->frame_type == CDP_PPDU_FTYPE_DATA) &&
|
||||
(!ppdu_desc->user[0].completion_status)) {
|
||||
/**
|
||||
* check whether it is bss peer,
|
||||
* if bss_peer no need to process further
|
||||
* check whether tx_capture feature is enabled
|
||||
* for this peer or globally for all peers
|
||||
*/
|
||||
if (peer->bss_peer ||
|
||||
!dp_peer_or_pdev_tx_cap_enabled(pdev,
|
||||
peer)) {
|
||||
dp_peer_unref_del_find_by_id(peer);
|
||||
qdf_nbuf_free(nbuf);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* print the bit map */
|
||||
dp_tx_print_bitmap(pdev, ppdu_desc,
|
||||
0, ppdu_desc->ppdu_id);
|
||||
|
Reference in New Issue
Block a user