qcacmn: Tx packet capture

Add support to send MSDU, mgmt. and ctrl payload along with metadata
to upper layer callback

FR 42132

Change-Id: Ie751322c7c15419ea908538e9e8687b64693fcfa
CRs-Fixed:2068486
This commit is contained in:
Soumya Bhat
2017-10-03 15:04:09 +05:30
committed by snandini
parent f6cb4b8576
commit cfbb8952ff
7 changed files with 173 additions and 1 deletions

View File

@@ -531,6 +531,15 @@ struct cdp_soc_t {
struct ol_if_ops *ol_ops; struct ol_if_ops *ol_ops;
}; };
/*
* cdp_pdev_param_type: different types of parameters
* to set values in pdev
* @CDP_ENABLE_TX_CAPTURE: Enable Tx capture feature
*/
enum cdp_pdev_param_type {
CDP_CONFIG_TX_CAPTURE,
};
/* /*
* cdp_vdev_param_type: different types of parameters * cdp_vdev_param_type: different types of parameters
* to set values in vdev * to set values in vdev

View File

@@ -389,6 +389,16 @@ cdp_peer_set_nawds(ol_txrx_soc_handle soc,
return; return;
} }
static inline void cdp_txrx_set_pdev_param(ol_txrx_soc_handle soc,
struct cdp_pdev *pdev, enum cdp_pdev_param_type type,
uint8_t val)
{
if (soc->ops->ctrl_ops->txrx_set_pdev_param)
return soc->ops->ctrl_ops->txrx_set_pdev_param
(pdev, type, val);
}
/** /**
* @brief Subscribe to a specified WDI event. * @brief Subscribe to a specified WDI event.
* @details * @details

View File

@@ -415,6 +415,9 @@ struct cdp_ctrl_ops {
void (*txrx_update_mgmt_txpow_vdev)(struct cdp_vdev *vdev, void (*txrx_update_mgmt_txpow_vdev)(struct cdp_vdev *vdev,
uint8_t subtype, uint8_t tx_power); uint8_t subtype, uint8_t tx_power);
void (*txrx_set_pdev_param)(struct cdp_pdev *pdev,
enum cdp_pdev_param_type type, uint8_t val);
}; };
struct cdp_me_ops { struct cdp_me_ops {

View File

@@ -44,6 +44,8 @@ do { \
htt_htc_misc_pkt_list_add(soc, pkt); \ htt_htc_misc_pkt_list_add(soc, pkt); \
} while (0) } while (0)
#define HTT_MGMT_CTRL_TLV_RESERVERD_LEN 12
/* /*
* dp_tx_stats_update() - Update per-peer statistics * dp_tx_stats_update() - Update per-peer statistics
* @soc: Datapath soc handle * @soc: Datapath soc handle
@@ -1789,6 +1791,42 @@ static void dp_process_ppdu_stats_user_common_array_tlv(struct dp_pdev *pdev,
HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_DUR_GET(*tag_buf); HTT_PPDU_STATS_ARRAY_ITEM_TLV_TX_DUR_GET(*tag_buf);
} }
/*
* dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv: Process
* htt_ppdu_stats_tx_mgmtctrl_payload_tlv
* @pdev: DP PDEV handle
* @tag_buf: buffer containing the htt_ppdu_stats_tx_mgmtctrl_payload_tlv
* @length: tlv_length
*
* return:void
*/
static void dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv(
struct dp_pdev *pdev, uint32_t *tag_buf, uint32_t length)
{
htt_ppdu_stats_tx_mgmtctrl_payload_tlv *dp_stats_buf =
(htt_ppdu_stats_tx_mgmtctrl_payload_tlv *)tag_buf;
qdf_nbuf_t nbuf = NULL;
uint32_t payload_size = length - HTT_MGMT_CTRL_TLV_RESERVERD_LEN;
nbuf = qdf_nbuf_alloc(pdev->soc->osdev, payload_size, 0, 4, true);
if (!nbuf) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"Nbuf Allocation failed for Mgmt. payload");
qdf_assert(0);
return;
}
qdf_nbuf_put_tail(nbuf, payload_size);
qdf_mem_copy(qdf_nbuf_data(nbuf), dp_stats_buf->payload, payload_size);
dp_wdi_event_handler(WDI_EVENT_TX_MGMT_CTRL, pdev->soc,
nbuf, HTT_INVALID_PEER,
WDI_NO_VAL, pdev->pdev_id);
}
/** /**
* dp_process_ppdu_tag(): Function to process the PPDU TLVs * dp_process_ppdu_tag(): Function to process the PPDU TLVs
* @soc: DP Physical device (radio) handle * @soc: DP Physical device (radio) handle
@@ -1838,6 +1876,10 @@ static void dp_process_ppdu_tag(struct dp_pdev *pdev, uint32_t *tag_buf,
dp_process_ppdu_stats_user_common_array_tlv(pdev, dp_process_ppdu_stats_user_common_array_tlv(pdev,
tag_buf); tag_buf);
break; break;
case HTT_PPDU_STATS_TX_MGMTCTRL_PAYLOAD_TLV:
dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv(pdev,
tag_buf, tlv_len);
break;
default: default:
break; break;
} }
@@ -1908,7 +1950,7 @@ static void dp_txrx_ppdu_stats_handler(struct dp_soc *soc,
int status; int status;
int i; int i;
if (!pdev->enhanced_stats_en) if (!pdev->enhanced_stats_en && !pdev->tx_sniffer_enable)
return; return;
if (!pdev->tx_ppdu_info.buf) { if (!pdev->tx_ppdu_info.buf) {

View File

@@ -4795,6 +4795,30 @@ dp_ppdu_ring_cfg(struct dp_pdev *pdev)
RX_BUFFER_SIZE, &htt_tlv_filter); RX_BUFFER_SIZE, &htt_tlv_filter);
} }
/*
* dp_config_tx_capture()- API to enable/disable tx capture
* @pdev_handle: DP_PDEV handle
* @val: user provided value
*
* Return: void
*/
static void
dp_config_tx_capture(struct cdp_pdev *pdev_handle, int val)
{
struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
if (val) {
pdev->tx_sniffer_enable = 1;
dp_h2t_cfg_stats_msg_send(pdev, 0xffff);
} else {
pdev->tx_sniffer_enable = 0;
if (!pdev->enhanced_stats_en)
dp_h2t_cfg_stats_msg_send(pdev, 0);
}
}
/* /*
* dp_enable_enhanced_stats()- API to enable enhanced statistcs * dp_enable_enhanced_stats()- API to enable enhanced statistcs
* @pdev_handle: DP_PDEV handle * @pdev_handle: DP_PDEV handle
@@ -4821,7 +4845,11 @@ static void
dp_disable_enhanced_stats(struct cdp_pdev *pdev_handle) dp_disable_enhanced_stats(struct cdp_pdev *pdev_handle)
{ {
struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
pdev->enhanced_stats_en = 0; pdev->enhanced_stats_en = 0;
if (!pdev->tx_sniffer_enable)
dp_h2t_cfg_stats_msg_send(pdev, 0);
} }
/* /*
@@ -4866,6 +4894,26 @@ dp_get_fw_peer_stats(struct cdp_pdev *pdev_handle, uint8_t *mac_addr,
} }
/*
* dp_set_pdev_param: function to set parameters in pdev
* @pdev_handle: DP pdev handle
* @param: parameter type to be set
* @val: value of parameter to be set
*
* return: void
*/
static void dp_set_pdev_param(struct cdp_pdev *pdev_handle,
enum cdp_pdev_param_type param, uint8_t val)
{
switch (param) {
case CDP_CONFIG_TX_CAPTURE:
dp_config_tx_capture(pdev_handle, val);
break;
default:
break;
}
}
/* /*
* dp_set_vdev_param: function to set parameters in vdev * dp_set_vdev_param: function to set parameters in vdev
* @param: parameter type to be set * @param: parameter type to be set
@@ -5374,6 +5422,7 @@ static struct cdp_ctrl_ops dp_ops_ctrl = {
/* TODO: Add other functions */ /* TODO: Add other functions */
.txrx_wdi_event_sub = dp_wdi_event_sub, .txrx_wdi_event_sub = dp_wdi_event_sub,
.txrx_wdi_event_unsub = dp_wdi_event_unsub, .txrx_wdi_event_unsub = dp_wdi_event_unsub,
.txrx_set_pdev_param = dp_set_pdev_param,
}; };
static struct cdp_me_ops dp_ops_me = { static struct cdp_me_ops dp_ops_me = {

View File

@@ -1731,6 +1731,56 @@ static void dp_tx_inspect_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status)
dp_tx_desc_release(tx_desc, tx_desc->pool_id); dp_tx_desc_release(tx_desc, tx_desc->pool_id);
} }
#ifdef FEATURE_PERPKT_INFO
static QDF_STATUS
dp_send_compl_to_stack(struct dp_soc *soc, struct dp_tx_desc_s *desc,
uint16_t peer_id, uint16_t ppdu_id)
{
struct tx_capture_hdr *ppdu_hdr;
struct ethhdr *eh;
struct dp_peer *peer = NULL;
qdf_nbuf_t netbuf = desc->nbuf;
if (!desc->pdev->tx_sniffer_enable)
return QDF_STATUS_E_NOSUPPORT;
eh = (struct ethhdr *)(netbuf->data);
peer = (peer_id == HTT_INVALID_PEER) ? NULL :
dp_peer_find_by_id(soc, peer_id);
if (!peer) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("Peer Invalid"));
return QDF_STATUS_E_INVAL;
}
if (!qdf_nbuf_push_head(netbuf, sizeof(struct tx_capture_hdr))) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("No headroom"));
return QDF_STATUS_E_NOMEM;
}
ppdu_hdr = (struct tx_capture_hdr *)qdf_nbuf_data(netbuf);
qdf_mem_copy(ppdu_hdr->ta, (eh->h_dest), IEEE80211_ADDR_LEN);
ppdu_hdr->ppdu_id = ppdu_id;
qdf_mem_copy(ppdu_hdr->ra, peer->mac_addr.raw,
IEEE80211_ADDR_LEN);
dp_wdi_event_handler(WDI_EVENT_TX_DATA, soc,
netbuf, peer_id,
WDI_NO_VAL, desc->pdev->pdev_id);
return QDF_STATUS_SUCCESS;
}
#else
static QDF_STATUS
dp_send_compl_to_stack(struct dp_soc *soc, struct dp_tx_desc_s *desc,
uint16_t peer_id, uint16_t ppdu_id)
{
return QDF_STATUS_E_NOSUPPORT;
}
#endif
/** /**
* dp_tx_comp_free_buf() - Free nbuf associated with the Tx Descriptor * dp_tx_comp_free_buf() - Free nbuf associated with the Tx Descriptor
* @soc: Soc handle * @soc: Soc handle
@@ -1743,6 +1793,10 @@ static inline void dp_tx_comp_free_buf(struct dp_soc *soc,
{ {
struct dp_vdev *vdev = desc->vdev; struct dp_vdev *vdev = desc->vdev;
qdf_nbuf_t nbuf = desc->nbuf; qdf_nbuf_t nbuf = desc->nbuf;
struct hal_tx_completion_status ts = {0};
if (desc)
hal_tx_comp_get_status(&desc->comp, &ts);
/* If it is TDLS mgmt, don't unmap or free the frame */ /* If it is TDLS mgmt, don't unmap or free the frame */
if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME) if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME)
@@ -1769,6 +1823,9 @@ static inline void dp_tx_comp_free_buf(struct dp_soc *soc,
qdf_nbuf_unmap(soc->osdev, nbuf, QDF_DMA_TO_DEVICE); qdf_nbuf_unmap(soc->osdev, nbuf, QDF_DMA_TO_DEVICE);
if (dp_send_compl_to_stack(soc, desc, ts.peer_id, ts.ppdu_id))
return;
if (!vdev->mesh_vdev) { if (!vdev->mesh_vdev) {
qdf_nbuf_free(nbuf); qdf_nbuf_free(nbuf);
} else { } else {

View File

@@ -1046,6 +1046,8 @@ struct dp_pdev {
uint8_t last_user; uint8_t last_user;
qdf_nbuf_t buf; qdf_nbuf_t buf;
} tx_ppdu_info; } tx_ppdu_info;
bool tx_sniffer_enable;
}; };
struct dp_peer; struct dp_peer;