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:
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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 = {
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user