qcacmn: Add support for tx monitor full buffer and minor fix

Add support and handle tx monitor full buffer payload and
other minior fix include change of name for uniformity.

Change-Id: If401ecd5e1c6263584fa7013df672459c883ca8b
CRs-Fixed: 3215244
This commit is contained in:
nobelj
2022-06-07 12:50:30 -07:00
committed by Madan Koyyalamudi
parent af37507eba
commit 09bc440ca9
10 changed files with 631 additions and 514 deletions

View File

@@ -1287,8 +1287,8 @@ dp_mon_register_feature_ops_2_0(struct dp_soc *soc)
mon_ops->mon_tx_capture_debugfs_init = NULL; mon_ops->mon_tx_capture_debugfs_init = NULL;
mon_ops->mon_tx_add_to_comp_queue = NULL; mon_ops->mon_tx_add_to_comp_queue = NULL;
mon_ops->mon_print_pdev_tx_capture_stats = mon_ops->mon_print_pdev_tx_capture_stats =
dp_print_pdev_tx_capture_stats_2_0; dp_print_pdev_tx_monitor_stats_2_0;
mon_ops->mon_config_enh_tx_capture = dp_config_enh_tx_capture_2_0; mon_ops->mon_config_enh_tx_capture = dp_config_enh_tx_monitor_2_0;
mon_ops->mon_tx_peer_filter = dp_peer_set_tx_capture_enabled_2_0; mon_ops->mon_tx_peer_filter = dp_peer_set_tx_capture_enabled_2_0;
#endif #endif
#if (defined(WIFI_MONITOR_SUPPORT) && !defined(WLAN_TX_PKT_CAPTURE_ENH_BE)) #if (defined(WIFI_MONITOR_SUPPORT) && !defined(WLAN_TX_PKT_CAPTURE_ENH_BE))
@@ -1296,7 +1296,7 @@ dp_mon_register_feature_ops_2_0(struct dp_soc *soc)
mon_ops->mon_tx_capture_debugfs_init = NULL; mon_ops->mon_tx_capture_debugfs_init = NULL;
mon_ops->mon_tx_add_to_comp_queue = NULL; mon_ops->mon_tx_add_to_comp_queue = NULL;
mon_ops->mon_print_pdev_tx_capture_stats = NULL; mon_ops->mon_print_pdev_tx_capture_stats = NULL;
mon_ops->mon_config_enh_tx_capture = dp_config_enh_tx_core_capture_2_0; mon_ops->mon_config_enh_tx_capture = dp_config_enh_tx_core_monitor_2_0;
mon_ops->mon_tx_peer_filter = NULL; mon_ops->mon_tx_peer_filter = NULL;
#endif #endif
#ifdef WLAN_RX_PKT_CAPTURE_ENH #ifdef WLAN_RX_PKT_CAPTURE_ENH

View File

@@ -136,7 +136,7 @@ struct dp_mon_desc_pool {
* @filter_be: filters sent to fw * @filter_be: filters sent to fw
* @tx_mon_mode: tx monitor mode * @tx_mon_mode: tx monitor mode
* @tx_mon_filter_length: tx monitor filter length * @tx_mon_filter_length: tx monitor filter length
* @tx_capture: pointer to tx capture function * @tx_monitor_be: pointer to tx monitor be structure
* @tx_stats: tx monitor drop stats * @tx_stats: tx monitor drop stats
* @rx_mon_wq_lock: Rx mon workqueue lock * @rx_mon_wq_lock: Rx mon workqueue lock
* @rx_mon_workqueue: Rx mon workqueue * @rx_mon_workqueue: Rx mon workqueue
@@ -151,7 +151,7 @@ struct dp_mon_pdev_be {
struct dp_mon_filter_be **filter_be; struct dp_mon_filter_be **filter_be;
uint8_t tx_mon_mode; uint8_t tx_mon_mode;
uint8_t tx_mon_filter_length; uint8_t tx_mon_filter_length;
struct dp_pdev_tx_capture_be tx_capture_be; struct dp_pdev_tx_monitor_be tx_monitor_be;
struct dp_tx_monitor_drop_stats tx_stats; struct dp_tx_monitor_drop_stats tx_stats;
qdf_spinlock_t rx_mon_wq_lock; qdf_spinlock_t rx_mon_wq_lock;
qdf_workqueue_t *rx_mon_workqueue; qdf_workqueue_t *rx_mon_workqueue;

View File

@@ -46,10 +46,9 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
uint32_t work_done = 0; uint32_t work_done = 0;
struct dp_mon_soc *mon_soc = soc->monitor_soc; struct dp_mon_soc *mon_soc = soc->monitor_soc;
struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc); struct dp_mon_soc_be *mon_soc_be = dp_get_be_mon_soc_from_dp_mon_soc(mon_soc);
union dp_mon_desc_list_elem_t *desc_list = NULL; struct dp_pdev_tx_monitor_be *tx_mon_be = NULL;
union dp_mon_desc_list_elem_t *tail = NULL;
struct dp_mon_desc_pool *tx_mon_desc_pool = &mon_soc_be->tx_desc_mon; struct dp_mon_desc_pool *tx_mon_desc_pool = &mon_soc_be->tx_desc_mon;
uint32_t tx_monitor_reap_cnt = 0; struct dp_tx_mon_desc_list mon_desc_list;
if (!pdev) { if (!pdev) {
dp_mon_err("%pK: pdev is null for mac_id = %d", soc, mac_id); dp_mon_err("%pK: pdev is null for mac_id = %d", soc, mac_id);
@@ -69,11 +68,15 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return work_done; return work_done;
tx_mon_be = &mon_pdev_be->tx_monitor_be;
hal_soc = soc->hal_soc; hal_soc = soc->hal_soc;
qdf_assert((hal_soc && pdev)); qdf_assert((hal_soc && pdev));
qdf_spin_lock_bh(&mon_pdev->mon_lock); qdf_spin_lock_bh(&mon_pdev->mon_lock);
mon_desc_list.desc_list = NULL;
mon_desc_list.tail = NULL;
mon_desc_list.tx_mon_reap_cnt = 0;
if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, mon_dst_srng))) { if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, mon_dst_srng))) {
dp_mon_err("%s %d : HAL Mon Dest Ring access Failed -- %pK", dp_mon_err("%s %d : HAL Mon Dest Ring access Failed -- %pK",
@@ -87,7 +90,8 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
&& quota--)) { && quota--)) {
struct hal_mon_desc hal_mon_tx_desc = {0}; struct hal_mon_desc hal_mon_tx_desc = {0};
struct dp_mon_desc *mon_desc = NULL; struct dp_mon_desc *mon_desc = NULL;
uint32_t end_offset = DP_MON_DATA_BUFFER_SIZE; qdf_frag_t status_frag = NULL;
uint32_t end_offset = 0;
hal_be_get_mon_dest_status(soc->hal_soc, hal_be_get_mon_dest_status(soc->hal_soc,
tx_mon_dst_ring_desc, tx_mon_dst_ring_desc,
@@ -136,27 +140,19 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
qdf_assert_always(0); qdf_assert_always(0);
} }
if (qdf_likely(hal_mon_tx_desc.end_offset))
end_offset = hal_mon_tx_desc.end_offset; end_offset = hal_mon_tx_desc.end_offset;
if ((hal_mon_tx_desc.end_reason == HAL_MON_FLUSH_DETECTED) || status_frag = (qdf_frag_t)(mon_desc->buf_addr);
(hal_mon_tx_desc.end_reason == HAL_MON_PPDU_TRUNCATED)) {
dp_tx_mon_update_end_reason(mon_pdev,
hal_mon_tx_desc.ppdu_id,
hal_mon_tx_desc.end_reason);
qdf_frag_free(mon_desc->buf_addr);
mon_desc->buf_addr = NULL; mon_desc->buf_addr = NULL;
++tx_monitor_reap_cnt; /* increment reap count */
dp_mon_add_to_free_desc_list(&desc_list, ++mon_desc_list.tx_mon_reap_cnt;
&tail, mon_desc);
work_done++; /* add the mon_desc to free list */
hal_srng_dst_get_next(hal_soc, mon_dst_srng); dp_mon_add_to_free_desc_list(&mon_desc_list.desc_list,
continue; &mon_desc_list.tail, mon_desc);
}
if (qdf_unlikely(!mon_desc->buf_addr)) {
if (qdf_unlikely(!status_frag)) {
dp_mon_debug("P_ID:%d INIT:%d E_DESC:%d R_ID:%d L_CNT:%d BUF_ADDR: 0x%llx E_OFF: %d E_REA: %d", dp_mon_debug("P_ID:%d INIT:%d E_DESC:%d R_ID:%d L_CNT:%d BUF_ADDR: 0x%llx E_OFF: %d E_REA: %d",
hal_mon_tx_desc.ppdu_id, hal_mon_tx_desc.ppdu_id,
hal_mon_tx_desc.initiator, hal_mon_tx_desc.initiator,
@@ -167,9 +163,22 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
hal_mon_tx_desc.end_offset, hal_mon_tx_desc.end_offset,
hal_mon_tx_desc.end_reason); hal_mon_tx_desc.end_reason);
++tx_monitor_reap_cnt; work_done++;
dp_mon_add_to_free_desc_list(&desc_list, hal_srng_dst_get_next(hal_soc, mon_dst_srng);
&tail, mon_desc); continue;
}
if ((hal_mon_tx_desc.end_reason == HAL_MON_FLUSH_DETECTED) ||
(hal_mon_tx_desc.end_reason == HAL_MON_PPDU_TRUNCATED)) {
tx_mon_be->be_ppdu_id = hal_mon_tx_desc.ppdu_id;
dp_tx_mon_update_end_reason(mon_pdev,
hal_mon_tx_desc.ppdu_id,
hal_mon_tx_desc.end_reason);
/* check and free packet buffer from status buffer */
dp_tx_mon_status_free_packet_buf(pdev, status_frag,
end_offset,
&mon_desc_list);
qdf_frag_free(status_frag);
work_done++; work_done++;
hal_srng_dst_get_next(hal_soc, mon_dst_srng); hal_srng_dst_get_next(hal_soc, mon_dst_srng);
@@ -178,26 +187,26 @@ dp_tx_mon_srng_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
dp_tx_mon_process_status_tlv(soc, pdev, dp_tx_mon_process_status_tlv(soc, pdev,
&hal_mon_tx_desc, &hal_mon_tx_desc,
mon_desc->buf_addr, end_offset); status_frag,
end_offset,
mon_desc->buf_addr = NULL; &mon_desc_list);
++tx_monitor_reap_cnt;
dp_mon_add_to_free_desc_list(&desc_list, &tail, mon_desc);
work_done++; work_done++;
hal_srng_dst_get_next(hal_soc, mon_dst_srng); hal_srng_dst_get_next(hal_soc, mon_dst_srng);
} }
dp_srng_access_end(int_ctx, soc, mon_dst_srng); dp_srng_access_end(int_ctx, soc, mon_dst_srng);
if (tx_monitor_reap_cnt) { if (mon_desc_list.tx_mon_reap_cnt) {
dp_mon_buffers_replenish(soc, &mon_soc_be->tx_mon_buf_ring, dp_mon_buffers_replenish(soc, &mon_soc_be->tx_mon_buf_ring,
tx_mon_desc_pool, tx_mon_desc_pool,
tx_monitor_reap_cnt, mon_desc_list.tx_mon_reap_cnt,
&desc_list, &tail); &mon_desc_list.desc_list,
&mon_desc_list.tail);
} }
qdf_spin_unlock_bh(&mon_pdev->mon_lock); qdf_spin_unlock_bh(&mon_pdev->mon_lock);
dp_mon_debug("mac_id: %d, work_done:%d tx_monitor_reap_cnt:%d", dp_mon_debug("mac_id: %d, work_done:%d tx_monitor_reap_cnt:%d",
mac_id, work_done, tx_monitor_reap_cnt); mac_id, work_done, mon_desc_list.tx_mon_reap_cnt);
return work_done; return work_done;
} }
@@ -304,15 +313,18 @@ dp_tx_mon_buffers_alloc(struct dp_soc *soc, uint32_t size)
} }
#ifdef WLAN_TX_PKT_CAPTURE_ENH_BE #ifdef WLAN_TX_PKT_CAPTURE_ENH_BE
/* /*
* dp_tx_mon_free_usr_mpduq() - API to free user mpduq * dp_tx_mon_free_usr_mpduq() - API to free user mpduq
* @tx_ppdu_info - pointer to tx_ppdu_info * @tx_ppdu_info - pointer to tx_ppdu_info
* @usr_idx - user index * @usr_idx - user index
* @tx_mon_be - pointer to tx capture be
* *
* Return: void * Return: void
*/ */
void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info, void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info,
uint8_t usr_idx) uint8_t usr_idx,
struct dp_pdev_tx_monitor_be *tx_mon_be)
{ {
qdf_nbuf_queue_t *mpdu_q; qdf_nbuf_queue_t *mpdu_q;
@@ -320,16 +332,18 @@ void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info,
return; return;
mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, usr_idx, mpdu_q); mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, usr_idx, mpdu_q);
qdf_nbuf_queue_remove(mpdu_q); qdf_nbuf_queue_free(mpdu_q);
} }
/* /*
* dp_tx_mon_free_ppdu_info() - API to free dp_tx_ppdu_info * dp_tx_mon_free_ppdu_info() - API to free dp_tx_ppdu_info
* @tx_ppdu_info - pointer to tx_ppdu_info * @tx_ppdu_info - pointer to tx_ppdu_info
* @tx_mon_be - pointer to tx capture be
* *
* Return: void * Return: void
*/ */
void dp_tx_mon_free_ppdu_info(struct dp_tx_ppdu_info *tx_ppdu_info) void dp_tx_mon_free_ppdu_info(struct dp_tx_ppdu_info *tx_ppdu_info,
struct dp_pdev_tx_monitor_be *tx_mon_be)
{ {
uint32_t user = 0; uint32_t user = 0;
@@ -361,37 +375,12 @@ struct dp_tx_ppdu_info *dp_tx_mon_get_ppdu_info(struct dp_pdev *pdev,
struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; struct dp_mon_pdev *mon_pdev = pdev->monitor_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);
struct dp_pdev_tx_capture_be *tx_cap_be = struct dp_pdev_tx_monitor_be *tx_mon_be =
&mon_pdev_be->tx_capture_be; &mon_pdev_be->tx_monitor_be;
struct dp_tx_ppdu_info *tx_ppdu_info; struct dp_tx_ppdu_info *tx_ppdu_info;
size_t sz_ppdu_info = 0; size_t sz_ppdu_info = 0;
uint8_t i; uint8_t i;
if (type == TX_PROT_PPDU_INFO) {
tx_ppdu_info = tx_cap_be->tx_prot_ppdu_info;
if (tx_ppdu_info &&
TXMON_PPDU_HAL(tx_ppdu_info, is_used) != 1) {
return tx_ppdu_info;
} else if (tx_ppdu_info) {
dp_tx_mon_free_ppdu_info(tx_ppdu_info);
tx_ppdu_info = NULL;
}
/* for protection frame num_user is always 1 */
num_user = 1;
} else {
tx_ppdu_info = tx_cap_be->tx_data_ppdu_info;
if (tx_ppdu_info &&
TXMON_PPDU_HAL(tx_ppdu_info, is_used) != 1 &&
num_user == TXMON_PPDU_HAL(tx_ppdu_info, num_users)) {
/* number of user matched */
return tx_ppdu_info;
} else if (tx_ppdu_info) {
dp_tx_mon_free_ppdu_info(tx_ppdu_info);
tx_ppdu_info = NULL;
}
}
/* allocate new tx_ppdu_info */ /* allocate new tx_ppdu_info */
sz_ppdu_info = (sizeof(struct dp_tx_ppdu_info) + sz_ppdu_info = (sizeof(struct dp_tx_ppdu_info) +
(sizeof(struct mon_rx_user_status) * num_user)); (sizeof(struct mon_rx_user_status) * num_user));
@@ -406,23 +395,21 @@ struct dp_tx_ppdu_info *dp_tx_mon_get_ppdu_info(struct dp_pdev *pdev,
TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 0; TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 0;
TXMON_PPDU_HAL(tx_ppdu_info, num_users) = num_user; TXMON_PPDU_HAL(tx_ppdu_info, num_users) = num_user;
TXMON_PPDU_HAL(tx_ppdu_info, ppdu_id) = ppdu_id; TXMON_PPDU_HAL(tx_ppdu_info, ppdu_id) = ppdu_id;
tx_ppdu_info->ppdu_id = ppdu_id;
for (i = 0; i < num_user; i++) { for (i = 0; i < num_user; i++) {
qdf_nbuf_queue_t *mpdu_q; qdf_nbuf_queue_t *mpdu_q;
mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, i, mpdu_q); mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, i, mpdu_q);
if (qdf_unlikely(qdf_nbuf_queue_len(mpdu_q)))
qdf_nbuf_queue_free(mpdu_q);
qdf_nbuf_queue_init(mpdu_q); qdf_nbuf_queue_init(mpdu_q);
} }
/* assign tx_ppdu_info to monitor pdev for reference */ /* assign tx_ppdu_info to monitor pdev for reference */
if (type == TX_PROT_PPDU_INFO) { if (type == TX_PROT_PPDU_INFO) {
tx_cap_be->tx_prot_ppdu_info = tx_ppdu_info; tx_mon_be->tx_prot_ppdu_info = tx_ppdu_info;
TXMON_PPDU_HAL(tx_ppdu_info, is_data) = 0; TXMON_PPDU_HAL(tx_ppdu_info, is_data) = 0;
} else { } else {
tx_cap_be->tx_data_ppdu_info = tx_ppdu_info; tx_mon_be->tx_data_ppdu_info = tx_ppdu_info;
TXMON_PPDU_HAL(tx_ppdu_info, is_data) = 1; TXMON_PPDU_HAL(tx_ppdu_info, is_data) = 1;
} }
@@ -430,37 +417,37 @@ struct dp_tx_ppdu_info *dp_tx_mon_get_ppdu_info(struct dp_pdev *pdev,
} }
/* /*
* dp_print_pdev_tx_capture_stats_2_0: print tx capture stats * dp_print_pdev_tx_monitor_stats_2_0: print tx capture stats
* @pdev: DP PDEV handle * @pdev: DP PDEV handle
* *
* return: void * return: void
*/ */
void dp_print_pdev_tx_capture_stats_2_0(struct dp_pdev *pdev) void dp_print_pdev_tx_monitor_stats_2_0(struct dp_pdev *pdev)
{ {
/* TX monitor stats needed for beryllium */ /* TX monitor stats needed for beryllium */
} }
/* /*
* dp_config_enh_tx_capture_be()- API to enable/disable enhanced tx capture * dp_config_enh_tx_monitor_2_0()- API to enable/disable enhanced tx capture
* @pdev_handle: DP_PDEV handle * @pdev_handle: DP_PDEV handle
* @val: user provided value * @val: user provided value
* *
* Return: QDF_STATUS * Return: QDF_STATUS
*/ */
QDF_STATUS QDF_STATUS
dp_config_enh_tx_capture_2_0(struct dp_pdev *pdev, uint8_t val) dp_config_enh_tx_monitor_2_0(struct dp_pdev *pdev, uint8_t val)
{ {
struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; struct dp_mon_pdev *mon_pdev = pdev->monitor_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);
struct dp_pdev_tx_capture_be *tx_cap_be = struct dp_pdev_tx_monitor_be *tx_mon_be =
&mon_pdev_be->tx_capture_be; &mon_pdev_be->tx_monitor_be;
switch (val) { switch (val) {
case TX_MON_BE_DISABLE: case TX_MON_BE_DISABLE:
{ {
/* TODO: send HTT msg to configure TLV based on mode */ /* TODO: send HTT msg to configure TLV based on mode */
tx_cap_be->mode = TX_MON_BE_DISABLE; tx_mon_be->mode = TX_MON_BE_DISABLE;
mon_pdev_be->tx_mon_mode = 0; mon_pdev_be->tx_mon_mode = 0;
mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_64B; mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_64B;
break; break;
@@ -468,15 +455,15 @@ dp_config_enh_tx_capture_2_0(struct dp_pdev *pdev, uint8_t val)
case TX_MON_BE_FULL_CAPTURE: case TX_MON_BE_FULL_CAPTURE:
{ {
/* TODO: send HTT msg to configure TLV based on mode */ /* TODO: send HTT msg to configure TLV based on mode */
tx_cap_be->mode = TX_MON_BE_FULL_CAPTURE; tx_mon_be->mode = TX_MON_BE_FULL_CAPTURE;
mon_pdev_be->tx_mon_mode = 1; mon_pdev_be->tx_mon_mode = 1;
mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_256B; mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH;
break; break;
} }
case TX_MON_BE_PEER_FILTER: case TX_MON_BE_PEER_FILTER:
{ {
/* TODO: send HTT msg to configure TLV based on mode */ /* TODO: send HTT msg to configure TLV based on mode */
tx_cap_be->mode = TX_MON_BE_PEER_FILTER; tx_mon_be->mode = TX_MON_BE_PEER_FILTER;
mon_pdev_be->tx_mon_mode = 1; mon_pdev_be->tx_mon_mode = 1;
mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_256B; mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_256B;
break; break;
@@ -489,7 +476,7 @@ dp_config_enh_tx_capture_2_0(struct dp_pdev *pdev, uint8_t val)
} }
dp_mon_info("Tx monitor mode:%d mon_mode_flag:%d config_length:%d", dp_mon_info("Tx monitor mode:%d mon_mode_flag:%d config_length:%d",
tx_cap_be->mode, mon_pdev_be->tx_mon_mode, tx_mon_be->mode, mon_pdev_be->tx_mon_mode,
mon_pdev_be->tx_mon_filter_length); mon_pdev_be->tx_mon_filter_length);
dp_mon_filter_setup_tx_mon_mode(pdev); dp_mon_filter_setup_tx_mon_mode(pdev);
@@ -545,14 +532,14 @@ static void dp_fill_lite_mon_vdev(struct cdp_tx_indication_info *tx_cap_info,
static void static void
dp_tx_mon_send_to_stack(struct dp_pdev *pdev, qdf_nbuf_t mpdu) dp_tx_mon_send_to_stack(struct dp_pdev *pdev, qdf_nbuf_t mpdu)
{ {
struct cdp_tx_indication_info tx_capture_info; struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev;
struct dp_mon_pdev_be *mon_pdev_be =
dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
struct cdp_tx_indication_info tx_capture_info = {0};
qdf_mem_set(&tx_capture_info,
sizeof(struct cdp_tx_indication_info),
0);
tx_capture_info.radiotap_done = 1; tx_capture_info.radiotap_done = 1;
tx_capture_info.mpdu_nbuf = mpdu; tx_capture_info.mpdu_nbuf = mpdu;
if (!dp_lite_mon_is_tx_enabled(pdev->monitor_pdev)) { if (!dp_lite_mon_is_tx_enabled(mon_pdev)) {
dp_wdi_event_handler(WDI_EVENT_TX_PKT_CAPTURE, dp_wdi_event_handler(WDI_EVENT_TX_PKT_CAPTURE,
pdev->soc, pdev->soc,
&tx_capture_info, &tx_capture_info,
@@ -568,6 +555,8 @@ dp_tx_mon_send_to_stack(struct dp_pdev *pdev, qdf_nbuf_t mpdu)
WDI_NO_VAL, WDI_NO_VAL,
pdev->pdev_id); pdev->pdev_id);
} }
if (tx_capture_info.mpdu_nbuf)
qdf_nbuf_free(tx_capture_info.mpdu_nbuf);
} }
/** /**
@@ -575,73 +564,28 @@ dp_tx_mon_send_to_stack(struct dp_pdev *pdev, qdf_nbuf_t mpdu)
* @pdev: pdev Handle * @pdev: pdev Handle
* @ppdu_info: pointer to dp_tx_ppdu_info * @ppdu_info: pointer to dp_tx_ppdu_info
* @user_id: current user index * @user_id: current user index
* @radiota_hdr_ref: pointer to radiotap ref
* *
* Return: void * Return: void
*/ */
static void static void
dp_tx_mon_send_per_usr_mpdu(struct dp_pdev *pdev, dp_tx_mon_send_per_usr_mpdu(struct dp_pdev *pdev,
struct dp_tx_ppdu_info *ppdu_info, struct dp_tx_ppdu_info *ppdu_info,
uint8_t user_id, uint8_t user_idx)
qdf_nbuf_t *radiotap_hdr_ref)
{ {
uint32_t mpdu_queue_len = 0;
qdf_nbuf_queue_t *usr_mpdu_q = NULL; qdf_nbuf_queue_t *usr_mpdu_q = NULL;
qdf_nbuf_t buf = NULL; qdf_nbuf_t buf = NULL;
qdf_nbuf_t radiotap_copy = NULL;
usr_mpdu_q = &TXMON_PPDU_USR(ppdu_info, user_id, mpdu_q); usr_mpdu_q = &TXMON_PPDU_USR(ppdu_info, user_idx, mpdu_q);
if (!usr_mpdu_q) {
qdf_nbuf_free(*radiotap_hdr_ref);
*radiotap_hdr_ref = NULL;
/* free radiotap hdr */
return;
}
while ((buf = qdf_nbuf_queue_remove(usr_mpdu_q)) != NULL) { while ((buf = qdf_nbuf_queue_remove(usr_mpdu_q)) != NULL) {
mpdu_queue_len = qdf_nbuf_queue_len(usr_mpdu_q); ppdu_info->hal_txmon.rx_status.rx_user_status =
/* &ppdu_info->hal_txmon.rx_user_status[user_idx];
* In an aggregated frame, each mpdu is send individualy to
* stack. caller of the function already allocate qdf_nbuf_update_radiotap(&ppdu_info->hal_txmon.rx_status,
* and update radiotap header information. We copy the buf, qdf_nbuf_headroom(buf));
* same radiotap header until we reach the end of mpdu.
* Once we reached end of mpdu we use the buffer allocated dp_tx_mon_send_to_stack(pdev, buf);
* for radiotap hdr.
*/
if (mpdu_queue_len) {
radiotap_copy = qdf_nbuf_copy_expand(*radiotap_hdr_ref,
0, 0);
} else {
radiotap_copy = *radiotap_hdr_ref;
*radiotap_hdr_ref = NULL;
} }
/* add msdu as a fraglist of mpdu */
qdf_nbuf_append_ext_list(radiotap_copy,
buf, qdf_nbuf_len(buf));
dp_tx_mon_send_to_stack(pdev, radiotap_copy);
}
}
/**
* dp_tx_mon_alloc_radiotap_hdr() - API to allocate radiotap header
* @pdev: pdev Handle
* @nbuf_ref: reference to nbuf
*
* Return: QDF_STATUS
*/
static QDF_STATUS
dp_tx_mon_alloc_radiotap_hdr(struct dp_pdev *pdev, qdf_nbuf_t *nbuf_ref)
{
*nbuf_ref = qdf_nbuf_alloc(pdev->soc->osdev,
MAX_MONITOR_HEADER,
MAX_MONITOR_HEADER,
4, FALSE);
if (!*nbuf_ref)
return QDF_STATUS_E_NOMEM;
return QDF_STATUS_SUCCESS;
} }
/** /**
@@ -655,13 +599,8 @@ static void
dp_tx_mon_update_radiotap(struct dp_pdev *pdev, dp_tx_mon_update_radiotap(struct dp_pdev *pdev,
struct dp_tx_ppdu_info *ppdu_info) struct dp_tx_ppdu_info *ppdu_info)
{ {
uint32_t i = 0; uint32_t usr_idx = 0;
uint32_t num_users = 0; uint32_t num_users = 0;
qdf_nbuf_t radiotap_hdr = NULL;
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct dp_mon_pdev *mon_pdev;
mon_pdev = pdev->monitor_pdev;
num_users = TXMON_PPDU_HAL(ppdu_info, num_users); num_users = TXMON_PPDU_HAL(ppdu_info, num_users);
@@ -673,13 +612,15 @@ dp_tx_mon_update_radiotap(struct dp_pdev *pdev,
TXMON_PPDU_COM(ppdu_info, chan_freq) = TXMON_PPDU_COM(ppdu_info, chan_freq) =
pdev->operating_channel.freq; pdev->operating_channel.freq;
for (i = 0; i < num_users; i++) { for (usr_idx = 0; usr_idx < num_users; usr_idx++) {
/* allocate radiotap_hdr */ qdf_nbuf_queue_t *mpdu_q = NULL;
status = dp_tx_mon_alloc_radiotap_hdr(pdev, &radiotap_hdr);
if (status != QDF_STATUS_SUCCESS) { /* set AMPDU flag if number mpdu is more than 1 */
/* free ppdu_info per user */ mpdu_q = &TXMON_PPDU_USR(ppdu_info, usr_idx, mpdu_q);
dp_tx_mon_free_usr_mpduq(ppdu_info, i); if (mpdu_q && (qdf_nbuf_queue_len(mpdu_q) > 1)) {
continue; TXMON_PPDU_COM(ppdu_info,
rs_flags) |= IEEE80211_AMPDU_FLAG;
TXMON_PPDU_USR(ppdu_info, usr_idx, is_ampdu) = 1;
} }
if (qdf_unlikely(!TXMON_PPDU_COM(ppdu_info, rate))) { if (qdf_unlikely(!TXMON_PPDU_COM(ppdu_info, rate))) {
@@ -689,7 +630,7 @@ dp_tx_mon_update_radiotap(struct dp_pdev *pdev,
rate = dp_getrateindex(TXMON_PPDU_COM(ppdu_info, sgi), rate = dp_getrateindex(TXMON_PPDU_COM(ppdu_info, sgi),
TXMON_PPDU_USR(ppdu_info, TXMON_PPDU_USR(ppdu_info,
i, mcs), usr_idx, mcs),
TXMON_PPDU_COM(ppdu_info, nss), TXMON_PPDU_COM(ppdu_info, nss),
TXMON_PPDU_COM(ppdu_info, TXMON_PPDU_COM(ppdu_info,
preamble_type), preamble_type),
@@ -701,21 +642,7 @@ dp_tx_mon_update_radiotap(struct dp_pdev *pdev,
TXMON_PPDU_COM(ppdu_info, rate) = rate; TXMON_PPDU_COM(ppdu_info, rate) = rate;
} }
/* copy rx_status to rx_status and invoke update radiotap */ dp_tx_mon_send_per_usr_mpdu(pdev, ppdu_info, usr_idx);
ppdu_info->hal_txmon.rx_status.rx_user_status =
&ppdu_info->hal_txmon.rx_user_status[i];
qdf_nbuf_update_radiotap(&ppdu_info->hal_txmon.rx_status,
radiotap_hdr, MAX_MONITOR_HEADER);
/* radiotap header will be free in below function */
dp_tx_mon_send_per_usr_mpdu(pdev, ppdu_info, i, &radiotap_hdr);
/*
* radiotap_hdr will be free in above function
* if not free here
*/
if (!!radiotap_hdr)
qdf_nbuf_free(radiotap_hdr);
} }
} }
@@ -732,7 +659,7 @@ void dp_tx_mon_ppdu_process(void *context)
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_tx_ppdu_info *defer_ppdu_info = NULL; struct dp_tx_ppdu_info *defer_ppdu_info = NULL;
struct dp_tx_ppdu_info *defer_ppdu_info_next = NULL; struct dp_tx_ppdu_info *defer_ppdu_info_next = NULL;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
/* sanity check */ /* sanity check */
if (qdf_unlikely(!pdev)) if (qdf_unlikely(!pdev))
@@ -747,34 +674,34 @@ void dp_tx_mon_ppdu_process(void *context)
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
if (qdf_unlikely(TX_MON_BE_DISABLE == tx_cap_be->mode && if (qdf_unlikely(TX_MON_BE_DISABLE == tx_mon_be->mode &&
!dp_lite_mon_is_tx_enabled(mon_pdev))) !dp_lite_mon_is_tx_enabled(mon_pdev)))
return; return;
/* take lock here */ /* take lock here */
qdf_spin_lock_bh(&tx_cap_be->tx_mon_list_lock); qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock);
STAILQ_CONCAT(&tx_cap_be->defer_tx_ppdu_info_queue, STAILQ_CONCAT(&tx_mon_be->defer_tx_ppdu_info_queue,
&tx_cap_be->tx_ppdu_info_queue); &tx_mon_be->tx_ppdu_info_queue);
tx_cap_be->defer_ppdu_info_list_depth += tx_mon_be->defer_ppdu_info_list_depth +=
tx_cap_be->tx_ppdu_info_list_depth; tx_mon_be->tx_ppdu_info_list_depth;
tx_cap_be->tx_ppdu_info_list_depth = 0; tx_mon_be->tx_ppdu_info_list_depth = 0;
qdf_spin_unlock_bh(&tx_cap_be->tx_mon_list_lock); qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock);
STAILQ_FOREACH_SAFE(defer_ppdu_info, STAILQ_FOREACH_SAFE(defer_ppdu_info,
&tx_cap_be->defer_tx_ppdu_info_queue, &tx_mon_be->defer_tx_ppdu_info_queue,
tx_ppdu_info_queue_elem, defer_ppdu_info_next) { tx_ppdu_info_queue_elem, defer_ppdu_info_next) {
/* remove dp_tx_ppdu_info from the list */ /* remove dp_tx_ppdu_info from the list */
STAILQ_REMOVE(&tx_cap_be->defer_tx_ppdu_info_queue, STAILQ_REMOVE(&tx_mon_be->defer_tx_ppdu_info_queue,
defer_ppdu_info, defer_ppdu_info,
dp_tx_ppdu_info, dp_tx_ppdu_info,
tx_ppdu_info_queue_elem); tx_ppdu_info_queue_elem);
tx_cap_be->defer_ppdu_info_list_depth--; tx_mon_be->defer_ppdu_info_list_depth--;
dp_tx_mon_update_radiotap(pdev, defer_ppdu_info); dp_tx_mon_update_radiotap(pdev, defer_ppdu_info);
/* free the ppdu_info */ /* free the ppdu_info */
dp_tx_mon_free_ppdu_info(defer_ppdu_info); dp_tx_mon_free_ppdu_info(defer_ppdu_info, tx_mon_be);
defer_ppdu_info = NULL; defer_ppdu_info = NULL;
} }
} }
@@ -789,7 +716,7 @@ void dp_tx_ppdu_stats_attach_2_0(struct dp_pdev *pdev)
{ {
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
if (qdf_unlikely(!pdev)) if (qdf_unlikely(!pdev))
return; return;
@@ -803,20 +730,20 @@ void dp_tx_ppdu_stats_attach_2_0(struct dp_pdev *pdev)
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
STAILQ_INIT(&tx_cap_be->tx_ppdu_info_queue); STAILQ_INIT(&tx_mon_be->tx_ppdu_info_queue);
tx_cap_be->tx_ppdu_info_list_depth = 0; tx_mon_be->tx_ppdu_info_list_depth = 0;
STAILQ_INIT(&tx_cap_be->defer_tx_ppdu_info_queue); STAILQ_INIT(&tx_mon_be->defer_tx_ppdu_info_queue);
tx_cap_be->defer_ppdu_info_list_depth = 0; tx_mon_be->defer_ppdu_info_list_depth = 0;
qdf_spinlock_create(&tx_cap_be->tx_mon_list_lock); qdf_spinlock_create(&tx_mon_be->tx_mon_list_lock);
/* Work queue setup for TX MONITOR post handling */ /* Work queue setup for TX MONITOR post handling */
qdf_create_work(0, &tx_cap_be->post_ppdu_work, qdf_create_work(0, &tx_mon_be->post_ppdu_work,
dp_tx_mon_ppdu_process, pdev); dp_tx_mon_ppdu_process, pdev);
tx_cap_be->post_ppdu_workqueue = tx_mon_be->post_ppdu_workqueue =
qdf_alloc_unbound_workqueue("tx_mon_ppdu_work_queue"); qdf_alloc_unbound_workqueue("tx_mon_ppdu_work_queue");
} }
@@ -830,7 +757,7 @@ void dp_tx_ppdu_stats_detach_2_0(struct dp_pdev *pdev)
{ {
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct dp_tx_ppdu_info *tx_ppdu_info = NULL; struct dp_tx_ppdu_info *tx_ppdu_info = NULL;
struct dp_tx_ppdu_info *tx_ppdu_info_next = NULL; struct dp_tx_ppdu_info *tx_ppdu_info_next = NULL;
@@ -846,86 +773,86 @@ void dp_tx_ppdu_stats_detach_2_0(struct dp_pdev *pdev)
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
/* TODO: disable tx_monitor, to avoid further packet from HW */ /* TODO: disable tx_monitor, to avoid further packet from HW */
dp_monitor_config_enh_tx_capture(pdev, TX_MON_BE_DISABLE); dp_monitor_config_enh_tx_capture(pdev, TX_MON_BE_DISABLE);
/* flush workqueue */ /* flush workqueue */
qdf_flush_workqueue(0, tx_cap_be->post_ppdu_workqueue); qdf_flush_workqueue(0, tx_mon_be->post_ppdu_workqueue);
qdf_destroy_workqueue(0, tx_cap_be->post_ppdu_workqueue); qdf_destroy_workqueue(0, tx_mon_be->post_ppdu_workqueue);
/* /*
* TODO: iterate both tx_ppdu_info and defer_ppdu_info_list * TODO: iterate both tx_ppdu_info and defer_ppdu_info_list
* free the tx_ppdu_info and decrement depth * free the tx_ppdu_info and decrement depth
*/ */
qdf_spin_lock_bh(&tx_cap_be->tx_mon_list_lock); qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock);
STAILQ_FOREACH_SAFE(tx_ppdu_info, STAILQ_FOREACH_SAFE(tx_ppdu_info,
&tx_cap_be->tx_ppdu_info_queue, &tx_mon_be->tx_ppdu_info_queue,
tx_ppdu_info_queue_elem, tx_ppdu_info_next) { tx_ppdu_info_queue_elem, tx_ppdu_info_next) {
/* remove dp_tx_ppdu_info from the list */ /* remove dp_tx_ppdu_info from the list */
STAILQ_REMOVE(&tx_cap_be->tx_ppdu_info_queue, tx_ppdu_info, STAILQ_REMOVE(&tx_mon_be->tx_ppdu_info_queue, tx_ppdu_info,
dp_tx_ppdu_info, tx_ppdu_info_queue_elem); dp_tx_ppdu_info, tx_ppdu_info_queue_elem);
/* decrement list length */ /* decrement list length */
tx_cap_be->tx_ppdu_info_list_depth--; tx_mon_be->tx_ppdu_info_list_depth--;
/* free tx_ppdu_info */ /* free tx_ppdu_info */
dp_tx_mon_free_ppdu_info(tx_ppdu_info); dp_tx_mon_free_ppdu_info(tx_ppdu_info, tx_mon_be);
} }
qdf_spin_unlock_bh(&tx_cap_be->tx_mon_list_lock); qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock);
qdf_spin_lock_bh(&tx_cap_be->tx_mon_list_lock); qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock);
STAILQ_FOREACH_SAFE(tx_ppdu_info, STAILQ_FOREACH_SAFE(tx_ppdu_info,
&tx_cap_be->defer_tx_ppdu_info_queue, &tx_mon_be->defer_tx_ppdu_info_queue,
tx_ppdu_info_queue_elem, tx_ppdu_info_next) { tx_ppdu_info_queue_elem, tx_ppdu_info_next) {
/* remove dp_tx_ppdu_info from the list */ /* remove dp_tx_ppdu_info from the list */
STAILQ_REMOVE(&tx_cap_be->defer_tx_ppdu_info_queue, STAILQ_REMOVE(&tx_mon_be->defer_tx_ppdu_info_queue,
tx_ppdu_info, tx_ppdu_info,
dp_tx_ppdu_info, tx_ppdu_info_queue_elem); dp_tx_ppdu_info, tx_ppdu_info_queue_elem);
/* decrement list length */ /* decrement list length */
tx_cap_be->defer_ppdu_info_list_depth--; tx_mon_be->defer_ppdu_info_list_depth--;
/* free tx_ppdu_info */ /* free tx_ppdu_info */
dp_tx_mon_free_ppdu_info(tx_ppdu_info); dp_tx_mon_free_ppdu_info(tx_ppdu_info, tx_mon_be);
} }
qdf_spin_unlock_bh(&tx_cap_be->tx_mon_list_lock); qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock);
qdf_spinlock_destroy(&tx_cap_be->tx_mon_list_lock); qdf_spinlock_destroy(&tx_mon_be->tx_mon_list_lock);
} }
#endif /* WLAN_TX_PKT_CAPTURE_ENH_BE */ #endif /* WLAN_TX_PKT_CAPTURE_ENH_BE */
#if (defined(WIFI_MONITOR_SUPPORT) && !defined(WLAN_TX_PKT_CAPTURE_ENH_BE)) #if (defined(WIFI_MONITOR_SUPPORT) && !defined(WLAN_TX_PKT_CAPTURE_ENH_BE))
/* /*
* dp_config_enh_tx_core_capture_2_0()- API to validate core framework * dp_config_enh_tx_core_monitor_2_0()- API to validate core framework
* @pdev_handle: DP_PDEV handle * @pdev_handle: DP_PDEV handle
* @val: user provided value * @val: user provided value
* *
* Return: QDF_STATUS * Return: QDF_STATUS
*/ */
QDF_STATUS QDF_STATUS
dp_config_enh_tx_core_capture_2_0(struct dp_pdev *pdev, uint8_t val) dp_config_enh_tx_core_monitor_2_0(struct dp_pdev *pdev, uint8_t val)
{ {
struct dp_mon_pdev *mon_pdev = pdev->monitor_pdev; struct dp_mon_pdev *mon_pdev = pdev->monitor_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);
struct dp_pdev_tx_capture_be *tx_cap_be = struct dp_pdev_tx_monitor_be *tx_mon_be =
&mon_pdev_be->tx_capture_be; &mon_pdev_be->tx_monitor_be;
switch (val) { switch (val) {
case TX_MON_BE_FRM_WRK_DISABLE: case TX_MON_BE_FRM_WRK_DISABLE:
{ {
tx_cap_be->mode = val; tx_mon_be->mode = val;
mon_pdev_be->tx_mon_mode = 0; mon_pdev_be->tx_mon_mode = 0;
mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_64B; mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_64B;
break; break;
} }
case TX_MON_BE_FRM_WRK_FULL_CAPTURE: case TX_MON_BE_FRM_WRK_FULL_CAPTURE:
{ {
tx_cap_be->mode = val; tx_mon_be->mode = val;
mon_pdev_be->tx_mon_mode = 1; mon_pdev_be->tx_mon_mode = 1;
mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH; mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH;
break; break;
} }
case TX_MON_BE_FRM_WRK_128B_CAPTURE: case TX_MON_BE_FRM_WRK_128B_CAPTURE:
{ {
tx_cap_be->mode = val; tx_mon_be->mode = val;
mon_pdev_be->tx_mon_mode = 1; mon_pdev_be->tx_mon_mode = 1;
mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_128B; mon_pdev_be->tx_mon_filter_length = DMA_LENGTH_128B;
break; break;
@@ -937,7 +864,7 @@ dp_config_enh_tx_core_capture_2_0(struct dp_pdev *pdev, uint8_t val)
} }
dp_mon_debug("Tx monitor mode:%d mon_mode_flag:%d config_length:%d", dp_mon_debug("Tx monitor mode:%d mon_mode_flag:%d config_length:%d",
tx_cap_be->mode, mon_pdev_be->tx_mon_mode, tx_mon_be->mode, mon_pdev_be->tx_mon_mode,
mon_pdev_be->tx_mon_filter_length); mon_pdev_be->tx_mon_filter_length);
/* send HTT msg to configure TLV based on mode */ /* send HTT msg to configure TLV based on mode */

View File

@@ -22,6 +22,19 @@
#include <hal_be_api_mon.h> #include <hal_be_api_mon.h>
struct dp_mon_desc; struct dp_mon_desc;
/**
* dp_tx_mon_desc_list - structure to store double linked liskt
* @tx_ppdu_info_dlist_elem: support adding to double linked list
* @tx_ppdu_info_slist_elem: support adding to single linked list
* @tx_mon_reap_cnt: tx monitor reap count
*/
struct dp_tx_mon_desc_list {
union dp_mon_desc_list_elem_t *desc_list;
union dp_mon_desc_list_elem_t *tail;
uint32_t tx_mon_reap_cnt;
};
/* /*
* dp_tx_mon_buffers_alloc() - allocate tx monitor buffers * dp_tx_mon_buffers_alloc() - allocate tx monitor buffers
* @soc: DP soc handle * @soc: DP soc handle
@@ -87,6 +100,21 @@ dp_tx_mon_buf_desc_pool_alloc(struct dp_soc *soc);
void dp_tx_mon_update_end_reason(struct dp_mon_pdev *mon_pdev, void dp_tx_mon_update_end_reason(struct dp_mon_pdev *mon_pdev,
int ppdu_id, int end_reason); int ppdu_id, int end_reason);
/**
* dp_tx_mon_status_free_packet_buf() - API to free packet buffer
* @pdev: pdev Handle
* @status_frag: status frag
* @end_offset: status fragment end offset
* @mon_desc_list_ref: tx monitor descriptor list reference
*
* Return: void
*/
void
dp_tx_mon_status_free_packet_buf(struct dp_pdev *pdev,
qdf_frag_t status_frag,
uint32_t end_offset,
struct dp_tx_mon_desc_list *mon_desc_list_ref);
/* /*
* dp_tx_mon_process_status_tlv() - API to processed TLV * dp_tx_mon_process_status_tlv() - API to processed TLV
* invoked from interrupt handler * invoked from interrupt handler
@@ -96,14 +124,17 @@ void dp_tx_mon_update_end_reason(struct dp_mon_pdev *mon_pdev,
* @mon_ring_desc - descriptor status info * @mon_ring_desc - descriptor status info
* @addr - status buffer frag address * @addr - status buffer frag address
* @end_offset - end offset of buffer that has valid buffer * @end_offset - end offset of buffer that has valid buffer
* @mon_desc_list_ref: tx monitor descriptor list reference
* *
* Return: QDF_STATUS * Return: QDF_STATUS
*/ */
QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, QDF_STATUS
dp_tx_mon_process_status_tlv(struct dp_soc *soc,
struct dp_pdev *pdev, struct dp_pdev *pdev,
struct hal_mon_desc *mon_ring_desc, struct hal_mon_desc *mon_ring_desc,
qdf_frag_t status_frag, qdf_frag_t status_frag,
uint32_t end_offset); uint32_t end_offset,
struct dp_tx_mon_desc_list *mon_desc_list_ref);
/* /*
* dp_tx_mon_process_2_0() - tx monitor interrupt process * dp_tx_mon_process_2_0() - tx monitor interrupt process
@@ -385,13 +416,15 @@ enum dp_tx_monitor_framework_mode {
#ifndef WLAN_TX_PKT_CAPTURE_ENH_BE #ifndef WLAN_TX_PKT_CAPTURE_ENH_BE
/** /**
* dp_pdev_tx_capture_be - info to store tx capture information in pdev * dp_pdev_tx_monitor_be - info to store tx capture information in pdev
* @be_ppdu_id: current ppdu id
* @mode: tx monitor core framework current mode * @mode: tx monitor core framework current mode
* * @tx_stats: tx monitor drop stats for that mac
* This is a dummy structure
*/ */
struct dp_pdev_tx_capture_be { struct dp_pdev_tx_monitor_be {
uint32_t be_ppdu_id;
uint32_t mode; uint32_t mode;
struct dp_tx_monitor_drop_stats tx_stats;
}; };
/** /**
@@ -414,7 +447,7 @@ struct dp_txmon_frag_vec {
}; };
/** /**
* dp_pdev_tx_capture_be - info to store tx capture information in pdev * dp_pdev_tx_monitor_be - info to store tx capture information in pdev
* @be_ppdu_id: current ppdu id * @be_ppdu_id: current ppdu id
* @be_end_reason_bitmap: current end reason bitmap * @be_end_reason_bitmap: current end reason bitmap
* @mode: tx monitor current mode * @mode: tx monitor current mode
@@ -436,7 +469,7 @@ struct dp_txmon_frag_vec {
* @cur_frag_q_idx: current index of frag buffer * @cur_frag_q_idx: current index of frag buffer
* @status_frag_queue: array of status frag queue to hold 64 status buffer * @status_frag_queue: array of status frag queue to hold 64 status buffer
*/ */
struct dp_pdev_tx_capture_be { struct dp_pdev_tx_monitor_be {
uint32_t be_ppdu_id; uint32_t be_ppdu_id;
uint32_t be_end_reason_bitmap; uint32_t be_end_reason_bitmap;
uint32_t mode; uint32_t mode;
@@ -491,19 +524,23 @@ void dp_tx_mon_ppdu_info_free(struct dp_tx_ppdu_info *tx_ppdu_info);
* dp_tx_mon_free_usr_mpduq() - API to free user mpduq * dp_tx_mon_free_usr_mpduq() - API to free user mpduq
* @tx_ppdu_info - pointer to tx_ppdu_info * @tx_ppdu_info - pointer to tx_ppdu_info
* @usr_idx - user index * @usr_idx - user index
* @tx_cap_be - pointer to tx capture be
* *
* Return: void * Return: void
*/ */
void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info, void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info,
uint8_t usr_idx); uint8_t usr_idx,
struct dp_pdev_tx_monitor_be *tx_cap_be);
/* /*
* dp_tx_mon_free_ppdu_info() - API to free dp_tx_ppdu_info * dp_tx_mon_free_ppdu_info() - API to free dp_tx_ppdu_info
* @tx_ppdu_info - pointer to tx_ppdu_info * @tx_ppdu_info - pointer to tx_ppdu_info
* @tx_cap_be - pointer to tx capture be
* *
* Return: void * Return: void
*/ */
void dp_tx_mon_free_ppdu_info(struct dp_tx_ppdu_info *tx_ppdu_info); void dp_tx_mon_free_ppdu_info(struct dp_tx_ppdu_info *tx_ppdu_info,
struct dp_pdev_tx_monitor_be *tx_cap_be);
/* /*
* dp_tx_mon_get_ppdu_info() - API to allocate dp_tx_ppdu_info * dp_tx_mon_get_ppdu_info() - API to allocate dp_tx_ppdu_info
@@ -537,21 +574,21 @@ void dp_tx_ppdu_stats_attach_2_0(struct dp_pdev *pdev);
void dp_tx_ppdu_stats_detach_2_0(struct dp_pdev *pdev); void dp_tx_ppdu_stats_detach_2_0(struct dp_pdev *pdev);
/* /*
* dp_print_pdev_tx_capture_stats_2_0: print tx capture stats * dp_print_pdev_tx_monitor_stats_2_0: print tx capture stats
* @pdev: DP PDEV handle * @pdev: DP PDEV handle
* *
* return: void * return: void
*/ */
void dp_print_pdev_tx_capture_stats_2_0(struct dp_pdev *pdev); void dp_print_pdev_tx_monitor_stats_2_0(struct dp_pdev *pdev);
/* /*
* dp_config_enh_tx_capture_be()- API to enable/disable enhanced tx capture * dp_config_enh_tx_monitor_2_0()- API to enable/disable enhanced tx capture
* @pdev_handle: DP_PDEV handle * @pdev_handle: DP_PDEV handle
* @val: user provided value * @val: user provided value
* *
* Return: QDF_STATUS * Return: QDF_STATUS
*/ */
QDF_STATUS dp_config_enh_tx_capture_2_0(struct dp_pdev *pdev, uint8_t val); QDF_STATUS dp_config_enh_tx_monitor_2_0(struct dp_pdev *pdev, uint8_t val);
/* /*
* dp_peer_set_tx_capture_enabled_2_0() - add tx monitor peer filter * dp_peer_set_tx_capture_enabled_2_0() - add tx monitor peer filter
@@ -570,13 +607,13 @@ QDF_STATUS dp_peer_set_tx_capture_enabled_2_0(struct dp_pdev *pdev_handle,
#if (defined(WIFI_MONITOR_SUPPORT) && !defined(WLAN_TX_PKT_CAPTURE_ENH_BE)) #if (defined(WIFI_MONITOR_SUPPORT) && !defined(WLAN_TX_PKT_CAPTURE_ENH_BE))
/* /*
* dp_config_enh_tx_core_capture_2_0()- API to validate core framework * dp_config_enh_tx_core_monitor_2_0()- API to validate core framework
* @pdev_handle: DP_PDEV handle * @pdev_handle: DP_PDEV handle
* @val: user provided value * @val: user provided value
* *
* Return: QDF_STATUS * Return: QDF_STATUS
*/ */
QDF_STATUS dp_config_enh_tx_core_capture_2_0(struct dp_pdev *pdev, uint8_t val); QDF_STATUS dp_config_enh_tx_core_monitor_2_0(struct dp_pdev *pdev, uint8_t val);
#endif #endif
#endif /* _DP_TX_MON_2_0_H_ */ #endif /* _DP_TX_MON_2_0_H_ */

View File

@@ -26,38 +26,126 @@
#include <dp_mon_2.0.h> #include <dp_mon_2.0.h>
#include <dp_lite_mon.h> #include <dp_lite_mon.h>
/**
* dp_tx_mon_status_free_packet_buf() - API to free packet buffer
* @pdev: pdev Handle
* @status_frag: status frag
* @end_offset: status fragment end offset
* @mon_desc_list_ref: tx monitor descriptor list reference
*
* Return: void
*/
void
dp_tx_mon_status_free_packet_buf(struct dp_pdev *pdev,
qdf_frag_t status_frag, uint32_t end_offset,
struct dp_tx_mon_desc_list *mon_desc_list_ref)
{
struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_mon_packet_info packet_info = {0};
uint8_t *tx_tlv;
uint8_t *mon_buf_tx_tlv;
uint8_t *tx_tlv_start;
if (qdf_unlikely(!pdev))
return;
mon_pdev = pdev->monitor_pdev;
if (qdf_unlikely(!mon_pdev))
return;
mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
if (qdf_unlikely(!mon_pdev_be))
return;
tx_mon_be = &mon_pdev_be->tx_monitor_be;
tx_tlv = status_frag;
tx_tlv_start = tx_tlv;
/*
* parse each status buffer and find packet buffer in it
*/
do {
if (hal_txmon_is_mon_buf_addr_tlv(pdev->soc->hal_soc, tx_tlv)) {
struct dp_mon_desc *mon_desc = NULL;
qdf_frag_t packet_buffer = NULL;
mon_buf_tx_tlv = ((uint8_t *)tx_tlv +
HAL_RX_TLV64_HDR_SIZE);
hal_txmon_populate_packet_info(pdev->soc->hal_soc,
mon_buf_tx_tlv,
&packet_info);
mon_desc = (struct dp_mon_desc *)(uintptr_t)packet_info.sw_cookie;
qdf_assert_always(mon_desc);
if (mon_desc->magic != DP_MON_DESC_MAGIC)
qdf_assert_always(0);
if (!mon_desc->unmapped) {
qdf_mem_unmap_page(pdev->soc->osdev,
(qdf_dma_addr_t)mon_desc->paddr,
DP_MON_DATA_BUFFER_SIZE,
QDF_DMA_FROM_DEVICE);
mon_desc->unmapped = 1;
}
packet_buffer = (qdf_frag_t)(mon_desc->buf_addr);
mon_desc->buf_addr = NULL;
qdf_assert_always(packet_buffer);
/* increment reap count */
mon_desc_list_ref->tx_mon_reap_cnt++;
/* add the mon_desc to free list */
dp_mon_add_to_free_desc_list(&mon_desc_list_ref->desc_list,
&mon_desc_list_ref->tail,
mon_desc);
/* free buffer, mapped to descriptor */
qdf_frag_free(packet_buffer);
}
/* need api definition for hal_tx_status_get_next_tlv */
tx_tlv = hal_tx_status_get_next_tlv(tx_tlv);
} while ((tx_tlv - tx_tlv_start) < end_offset);
}
#if defined(WLAN_TX_PKT_CAPTURE_ENH_BE) && defined(QCA_MONITOR_2_0_SUPPORT) #if defined(WLAN_TX_PKT_CAPTURE_ENH_BE) && defined(QCA_MONITOR_2_0_SUPPORT)
/** /**
* dp_tx_mon_status_queue_free() - API to free status buffer * dp_tx_mon_status_queue_free() - API to free status buffer
* @pdev: pdev Handle * @pdev: pdev Handle
* @tx_cap_be: pointer to tx_capture * @tx_mon_be: pointer to tx_monitor_be
* @mon_desc_list_ref: tx monitor descriptor list reference
* *
* Return: void * Return: void
*/ */
static void static void
dp_tx_mon_status_queue_free(struct dp_pdev *pdev, dp_tx_mon_status_queue_free(struct dp_pdev *pdev,
struct dp_pdev_tx_capture_be *tx_cap_be) struct dp_pdev_tx_monitor_be *tx_mon_be,
struct dp_tx_mon_desc_list *mon_desc_list_ref)
{ {
uint8_t last_frag_q_idx = tx_cap_be->last_frag_q_idx; uint8_t last_frag_q_idx = tx_mon_be->last_frag_q_idx;
qdf_frag_t status_frag = NULL; qdf_frag_t status_frag = NULL;
uint8_t i = tx_cap_be->cur_frag_q_idx; uint8_t i = tx_mon_be->cur_frag_q_idx;
uint32_t end_offset = 0; uint32_t end_offset = 0;
for (; i < last_frag_q_idx; i++) { for (; i < last_frag_q_idx; i++) {
status_frag = tx_cap_be->frag_q_vec[i].frag_buf; status_frag = tx_mon_be->frag_q_vec[i].frag_buf;
if (qdf_unlikely(!status_frag)) if (qdf_unlikely(!status_frag))
continue; continue;
end_offset = tx_cap_be->frag_q_vec[i].end_offset; end_offset = tx_mon_be->frag_q_vec[i].end_offset;
hal_txmon_status_free_buffer(pdev->soc->hal_soc, status_frag, dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset,
end_offset); mon_desc_list_ref);
qdf_frag_free(status_frag); qdf_frag_free(status_frag);
tx_cap_be->frag_q_vec[i].frag_buf = NULL; tx_mon_be->frag_q_vec[i].frag_buf = NULL;
tx_cap_be->frag_q_vec[i].end_offset = 0; tx_mon_be->frag_q_vec[i].end_offset = 0;
} }
tx_cap_be->last_frag_q_idx = 0; tx_mon_be->last_frag_q_idx = 0;
tx_cap_be->cur_frag_q_idx = 0; tx_mon_be->cur_frag_q_idx = 0;
} }
/** /**
@@ -69,9 +157,11 @@ dp_tx_mon_status_queue_free(struct dp_pdev *pdev,
* Return: void * Return: void
*/ */
static void static void
dp_tx_mon_enqueue_mpdu_nbuf(struct dp_tx_ppdu_info *tx_ppdu_info, dp_tx_mon_enqueue_mpdu_nbuf(struct dp_pdev *pdev,
struct dp_tx_ppdu_info *tx_ppdu_info,
uint8_t user_id, qdf_nbuf_t mpdu_nbuf) uint8_t user_id, qdf_nbuf_t mpdu_nbuf)
{ {
qdf_nbuf_t radiotap = NULL;
/* enqueue mpdu_nbuf to the per user mpdu_q */ /* enqueue mpdu_nbuf to the per user mpdu_q */
qdf_nbuf_queue_t *usr_mpdu_q = NULL; qdf_nbuf_queue_t *usr_mpdu_q = NULL;
@@ -81,7 +171,13 @@ dp_tx_mon_enqueue_mpdu_nbuf(struct dp_tx_ppdu_info *tx_ppdu_info,
usr_mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, user_id, mpdu_q); usr_mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, user_id, mpdu_q);
qdf_nbuf_queue_add(usr_mpdu_q, mpdu_nbuf); radiotap = qdf_nbuf_alloc(pdev->soc->osdev, MAX_MONITOR_HEADER,
MAX_MONITOR_HEADER,
4, FALSE);
/* append ext list */
qdf_nbuf_append_ext_list(radiotap, mpdu_nbuf, qdf_nbuf_len(mpdu_nbuf));
qdf_nbuf_queue_add(usr_mpdu_q, radiotap);
} }
/* /*
@@ -206,7 +302,7 @@ dp_tx_mon_generate_cts2self_frm(struct dp_pdev *pdev,
/* enqueue 802.11 payload to per user mpdu_q */ /* enqueue 802.11 payload to per user mpdu_q */
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
uint16_t duration_le = 0; uint16_t duration_le = 0;
struct ieee80211_frame_min_one *wh_min = NULL; struct ieee80211_frame_min_one *wh_min = NULL;
@@ -224,8 +320,8 @@ dp_tx_mon_generate_cts2self_frm(struct dp_pdev *pdev,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
tx_status_info = &tx_cap_be->prot_status_info; tx_status_info = &tx_mon_be->prot_status_info;
/* /*
* for radiotap we allocate new skb, * for radiotap we allocate new skb,
@@ -251,7 +347,7 @@ dp_tx_mon_generate_cts2self_frm(struct dp_pdev *pdev,
QDF_MAC_ADDR_SIZE); QDF_MAC_ADDR_SIZE);
qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_min)); qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_min));
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, 0, mpdu_nbuf); dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, 0, mpdu_nbuf);
TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1; TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
} }
@@ -270,7 +366,7 @@ dp_tx_mon_generate_rts_frm(struct dp_pdev *pdev,
/* enqueue 802.11 payload to per user mpdu_q */ /* enqueue 802.11 payload to per user mpdu_q */
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
uint16_t duration_le = 0; uint16_t duration_le = 0;
struct ieee80211_ctlframe_addr2 *wh_min = NULL; struct ieee80211_ctlframe_addr2 *wh_min = NULL;
@@ -288,8 +384,8 @@ dp_tx_mon_generate_rts_frm(struct dp_pdev *pdev,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
tx_status_info = &tx_cap_be->prot_status_info; tx_status_info = &tx_mon_be->prot_status_info;
/* /*
* for radiotap we allocate new skb, * for radiotap we allocate new skb,
* so we don't need reserver skb header * so we don't need reserver skb header
@@ -310,7 +406,7 @@ dp_tx_mon_generate_rts_frm(struct dp_pdev *pdev,
wh_min->i_aidordur[0] = (duration_le & 0xFF); wh_min->i_aidordur[0] = (duration_le & 0xFF);
if (!tx_status_info->protection_addr) if (!tx_status_info->protection_addr)
tx_status_info = &tx_cap_be->data_status_info; tx_status_info = &tx_mon_be->data_status_info;
qdf_mem_copy(wh_min->i_addr1, qdf_mem_copy(wh_min->i_addr1,
TXMON_STATUS_INFO(tx_status_info, addr1), TXMON_STATUS_INFO(tx_status_info, addr1),
QDF_MAC_ADDR_SIZE); QDF_MAC_ADDR_SIZE);
@@ -319,7 +415,7 @@ dp_tx_mon_generate_rts_frm(struct dp_pdev *pdev,
QDF_MAC_ADDR_SIZE); QDF_MAC_ADDR_SIZE);
qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_min)); qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_min));
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, 0, mpdu_nbuf); dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, 0, mpdu_nbuf);
TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1; TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
} }
@@ -338,7 +434,7 @@ dp_tx_mon_generate_ack_frm(struct dp_pdev *pdev,
/* enqueue 802.11 payload to per user mpdu_q */ /* enqueue 802.11 payload to per user mpdu_q */
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
struct ieee80211_frame_min_one *wh_addr1 = NULL; struct ieee80211_frame_min_one *wh_addr1 = NULL;
qdf_nbuf_t mpdu_nbuf = NULL; qdf_nbuf_t mpdu_nbuf = NULL;
@@ -356,8 +452,8 @@ dp_tx_mon_generate_ack_frm(struct dp_pdev *pdev,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
tx_status_info = &tx_cap_be->data_status_info; tx_status_info = &tx_mon_be->data_status_info;
/* /*
* for radiotap we allocate new skb, * for radiotap we allocate new skb,
* so we don't need reserver skb header * so we don't need reserver skb header
@@ -379,7 +475,7 @@ dp_tx_mon_generate_ack_frm(struct dp_pdev *pdev,
qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr1)); qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr1));
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, user_id, mpdu_nbuf); dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, user_id, mpdu_nbuf);
TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1; TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
} }
@@ -400,7 +496,7 @@ dp_tx_mon_generate_3addr_qos_null_frm(struct dp_pdev *pdev,
/* enqueue 802.11 payload to per user mpdu_q */ /* enqueue 802.11 payload to per user mpdu_q */
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
struct ieee80211_qosframe *wh_addr3 = NULL; struct ieee80211_qosframe *wh_addr3 = NULL;
qdf_nbuf_t mpdu_nbuf = NULL; qdf_nbuf_t mpdu_nbuf = NULL;
@@ -419,8 +515,8 @@ dp_tx_mon_generate_3addr_qos_null_frm(struct dp_pdev *pdev,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
tx_status_info = &tx_cap_be->data_status_info; tx_status_info = &tx_mon_be->data_status_info;
/* /*
* for radiotap we allocate new skb, * for radiotap we allocate new skb,
* so we don't need reserver skb header * so we don't need reserver skb header
@@ -453,7 +549,7 @@ dp_tx_mon_generate_3addr_qos_null_frm(struct dp_pdev *pdev,
QDF_MAC_ADDR_SIZE); QDF_MAC_ADDR_SIZE);
qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr3)); qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr3));
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, num_users, mpdu_nbuf); dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, num_users, mpdu_nbuf);
TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1; TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
} }
@@ -474,7 +570,7 @@ dp_tx_mon_generate_4addr_qos_null_frm(struct dp_pdev *pdev,
/* enqueue 802.11 payload to per user mpdu_q */ /* enqueue 802.11 payload to per user mpdu_q */
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
struct ieee80211_qosframe_addr4 *wh_addr4 = NULL; struct ieee80211_qosframe_addr4 *wh_addr4 = NULL;
qdf_nbuf_t mpdu_nbuf = NULL; qdf_nbuf_t mpdu_nbuf = NULL;
@@ -493,8 +589,8 @@ dp_tx_mon_generate_4addr_qos_null_frm(struct dp_pdev *pdev,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
tx_status_info = &tx_cap_be->data_status_info; tx_status_info = &tx_mon_be->data_status_info;
/* /*
* for radiotap we allocate new skb, * for radiotap we allocate new skb,
* so we don't need reserver skb header * so we don't need reserver skb header
@@ -529,7 +625,7 @@ dp_tx_mon_generate_4addr_qos_null_frm(struct dp_pdev *pdev,
QDF_MAC_ADDR_SIZE); QDF_MAC_ADDR_SIZE);
qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr4)); qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr4));
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, num_users, mpdu_nbuf); dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, num_users, mpdu_nbuf);
TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1; TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
} }
@@ -558,7 +654,7 @@ dp_tx_mon_generate_mu_block_ack_frm(struct dp_pdev *pdev,
/* enqueue 802.11 payload to per user mpdu_q */ /* enqueue 802.11 payload to per user mpdu_q */
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
struct ieee80211_ctlframe_addr2 *wh_addr2 = NULL; struct ieee80211_ctlframe_addr2 *wh_addr2 = NULL;
qdf_nbuf_t mpdu_nbuf = NULL; qdf_nbuf_t mpdu_nbuf = NULL;
@@ -579,8 +675,8 @@ dp_tx_mon_generate_mu_block_ack_frm(struct dp_pdev *pdev,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
tx_status_info = &tx_cap_be->data_status_info; tx_status_info = &tx_mon_be->data_status_info;
for (i = 0; i < num_users; i++) for (i = 0; i < num_users; i++)
ba_sz += (4 << TXMON_BA_INFO_SZ(TXMON_PPDU_USR(tx_ppdu_info, ba_sz += (4 << TXMON_BA_INFO_SZ(TXMON_PPDU_USR(tx_ppdu_info,
i, i,
@@ -647,7 +743,7 @@ dp_tx_mon_generate_mu_block_ack_frm(struct dp_pdev *pdev,
(frm - (uint8_t *)qdf_nbuf_data(mpdu_nbuf))); (frm - (uint8_t *)qdf_nbuf_data(mpdu_nbuf)));
/* always enqueue to first active user */ /* always enqueue to first active user */
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, 0, mpdu_nbuf); dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, 0, mpdu_nbuf);
TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1; TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
} }
@@ -666,7 +762,7 @@ dp_tx_mon_generate_block_ack_frm(struct dp_pdev *pdev,
/* enqueue 802.11 payload to per user mpdu_q */ /* enqueue 802.11 payload to per user mpdu_q */
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
struct ieee80211_ctlframe_addr2 *wh_addr2 = NULL; struct ieee80211_ctlframe_addr2 *wh_addr2 = NULL;
qdf_nbuf_t mpdu_nbuf = NULL; qdf_nbuf_t mpdu_nbuf = NULL;
@@ -687,8 +783,8 @@ dp_tx_mon_generate_block_ack_frm(struct dp_pdev *pdev,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
tx_status_info = &tx_cap_be->data_status_info; tx_status_info = &tx_mon_be->data_status_info;
/* /*
* for multi sta block ack, do we need to increase the size * for multi sta block ack, do we need to increase the size
* or copy info on subsequent frame offset * or copy info on subsequent frame offset
@@ -768,7 +864,7 @@ dp_tx_mon_generate_block_ack_frm(struct dp_pdev *pdev,
qdf_nbuf_set_pktlen(mpdu_nbuf, qdf_nbuf_set_pktlen(mpdu_nbuf,
(frm - (uint8_t *)qdf_nbuf_data(mpdu_nbuf))); (frm - (uint8_t *)qdf_nbuf_data(mpdu_nbuf)));
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, 0, mpdu_nbuf); dp_tx_mon_enqueue_mpdu_nbuf(pdev, tx_ppdu_info, 0, mpdu_nbuf);
TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1; TXMON_PPDU_HAL(tx_ppdu_info, is_used) = 1;
} }
@@ -795,8 +891,7 @@ dp_tx_mon_alloc_mpdu(struct dp_pdev *pdev, struct dp_tx_ppdu_info *tx_ppdu_info)
* we allocate a dummy bufffer size * we allocate a dummy bufffer size
*/ */
mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev, mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
TXMON_NO_BUFFER_SZ, MAX_MONITOR_HEADER, MAX_MONITOR_HEADER,
TXMON_NO_BUFFER_SZ,
4, FALSE); 4, FALSE);
if (!mpdu_nbuf) { if (!mpdu_nbuf) {
qdf_err("%s: %d No memory to allocate mpdu_nbuf!!!!!\n", qdf_err("%s: %d No memory to allocate mpdu_nbuf!!!!!\n",
@@ -818,11 +913,12 @@ dp_tx_mon_alloc_mpdu(struct dp_pdev *pdev, struct dp_tx_ppdu_info *tx_ppdu_info)
*/ */
static void static void
dp_tx_mon_generate_data_frm(struct dp_pdev *pdev, dp_tx_mon_generate_data_frm(struct dp_pdev *pdev,
struct dp_tx_ppdu_info *tx_ppdu_info) struct dp_tx_ppdu_info *tx_ppdu_info,
bool take_ref)
{ {
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
qdf_nbuf_t mpdu_nbuf = NULL; qdf_nbuf_t mpdu_nbuf = NULL;
qdf_nbuf_queue_t *usr_mpdu_q = NULL; qdf_nbuf_queue_t *usr_mpdu_q = NULL;
@@ -840,9 +936,9 @@ dp_tx_mon_generate_data_frm(struct dp_pdev *pdev,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
tx_status_info = &tx_cap_be->data_status_info; tx_status_info = &tx_mon_be->data_status_info;
usr_idx = TXMON_PPDU(tx_ppdu_info, cur_usr_idx); usr_idx = TXMON_PPDU(tx_ppdu_info, cur_usr_idx);
usr_mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, usr_idx, mpdu_q); usr_mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, usr_idx, mpdu_q);
mpdu_nbuf = qdf_nbuf_queue_last(usr_mpdu_q); mpdu_nbuf = qdf_nbuf_queue_last(usr_mpdu_q);
@@ -856,8 +952,8 @@ dp_tx_mon_generate_data_frm(struct dp_pdev *pdev,
mpdu_nbuf, mpdu_nbuf,
TXMON_STATUS_INFO(tx_status_info, offset), TXMON_STATUS_INFO(tx_status_info, offset),
TXMON_STATUS_INFO(tx_status_info, length), TXMON_STATUS_INFO(tx_status_info, length),
TX_MON_STATUS_BUF_SIZE, DP_MON_DATA_BUFFER_SIZE,
true, TXMON_NO_BUFFER_SZ); take_ref, TXMON_NO_BUFFER_SZ);
} }
/** /**
@@ -873,7 +969,7 @@ dp_tx_mon_generate_prot_frm(struct dp_pdev *pdev,
{ {
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
/* sanity check */ /* sanity check */
@@ -888,12 +984,12 @@ dp_tx_mon_generate_prot_frm(struct dp_pdev *pdev,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
tx_status_info = &tx_cap_be->prot_status_info; tx_status_info = &tx_mon_be->prot_status_info;
/* update medium prot type from data */ /* update medium prot type from data */
TXMON_STATUS_INFO(tx_status_info, medium_prot_type) = TXMON_STATUS_INFO(tx_status_info, medium_prot_type) =
tx_cap_be->data_status_info.medium_prot_type; tx_mon_be->data_status_info.medium_prot_type;
switch (TXMON_STATUS_INFO(tx_status_info, medium_prot_type)) { switch (TXMON_STATUS_INFO(tx_status_info, medium_prot_type)) {
case TXMON_MEDIUM_NO_PROTECTION: case TXMON_MEDIUM_NO_PROTECTION:
@@ -996,7 +1092,7 @@ dp_tx_mon_generated_response_frm(struct dp_pdev *pdev,
{ {
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
QDF_STATUS status = QDF_STATUS_SUCCESS; QDF_STATUS status = QDF_STATUS_SUCCESS;
uint8_t gen_response = 0; uint8_t gen_response = 0;
@@ -1013,9 +1109,9 @@ dp_tx_mon_generated_response_frm(struct dp_pdev *pdev,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return QDF_STATUS_E_NOMEM; return QDF_STATUS_E_NOMEM;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
tx_status_info = &tx_cap_be->data_status_info; tx_status_info = &tx_mon_be->data_status_info;
gen_response = TXMON_STATUS_INFO(tx_status_info, generated_response); gen_response = TXMON_STATUS_INFO(tx_status_info, generated_response);
switch (gen_response) { switch (gen_response) {
@@ -1086,6 +1182,7 @@ dp_tx_mon_generated_response_frm(struct dp_pdev *pdev,
* @tx_tlv_hdr: pointer to tx_tlv_hdr * @tx_tlv_hdr: pointer to tx_tlv_hdr
* @status_frag: pointer to fragment * @status_frag: pointer to fragment
* @tlv_status: tlv status return from hal api * @tlv_status: tlv status return from hal api
* @mon_desc_list_ref: tx monitor descriptor list reference
* *
* Return: QDF_STATUS * Return: QDF_STATUS
*/ */
@@ -1095,11 +1192,12 @@ dp_tx_mon_update_ppdu_info_status(struct dp_pdev *pdev,
struct dp_tx_ppdu_info *tx_prot_ppdu_info, struct dp_tx_ppdu_info *tx_prot_ppdu_info,
void *tx_tlv_hdr, void *tx_tlv_hdr,
qdf_frag_t status_frag, qdf_frag_t status_frag,
uint32_t tlv_status) uint32_t tlv_status,
struct dp_tx_mon_desc_list *mon_desc_list_ref)
{ {
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
QDF_STATUS status = QDF_STATUS_SUCCESS; QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -1115,7 +1213,7 @@ dp_tx_mon_update_ppdu_info_status(struct dp_pdev *pdev,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return QDF_STATUS_E_NOMEM; return QDF_STATUS_E_NOMEM;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
switch (tlv_status) { switch (tlv_status) {
case HAL_MON_TX_FES_SETUP: case HAL_MON_TX_FES_SETUP:
@@ -1136,7 +1234,7 @@ dp_tx_mon_update_ppdu_info_status(struct dp_pdev *pdev,
* RTS(sta) - cts(AP) * RTS(sta) - cts(AP)
* BlockAckReq(sta) - BlockAck(AP) * BlockAckReq(sta) - BlockAck(AP)
*/ */
tx_status_info = &tx_cap_be->data_status_info; tx_status_info = &tx_mon_be->data_status_info;
if (TXMON_STATUS_INFO(tx_status_info, reception_type) == if (TXMON_STATUS_INFO(tx_status_info, reception_type) ==
TXMON_RESP_CTS) TXMON_RESP_CTS)
dp_tx_mon_generate_cts2self_frm(pdev, dp_tx_mon_generate_cts2self_frm(pdev,
@@ -1177,9 +1275,9 @@ dp_tx_mon_update_ppdu_info_status(struct dp_pdev *pdev,
* BlockAck is not same as ACK, single frame can hold * BlockAck is not same as ACK, single frame can hold
* multiple BlockAck info * multiple BlockAck info
*/ */
tx_status_info = &tx_cap_be->data_status_info; tx_status_info = &tx_mon_be->data_status_info;
if (TXMON_STATUS_INFO(tx_status_info, transmission_type) ==
TXMON_SU_TRANSMISSION) if (TXMON_PPDU_HAL(tx_data_ppdu_info, num_users))
dp_tx_mon_generate_block_ack_frm(pdev, dp_tx_mon_generate_block_ack_frm(pdev,
tx_data_ppdu_info); tx_data_ppdu_info);
else else
@@ -1199,10 +1297,56 @@ dp_tx_mon_update_ppdu_info_status(struct dp_pdev *pdev,
break; break;
} }
case HAL_MON_TX_DATA: case HAL_MON_TX_DATA:
case HAL_MON_TX_BUFFER_ADDR:
{ {
TXMON_PPDU_HAL(tx_data_ppdu_info, is_used) = 1; TXMON_PPDU_HAL(tx_data_ppdu_info, is_used) = 1;
dp_tx_mon_generate_data_frm(pdev, tx_data_ppdu_info); dp_tx_mon_generate_data_frm(pdev, tx_data_ppdu_info, true);
break;
}
case HAL_MON_TX_BUFFER_ADDR:
{
struct hal_mon_packet_info *packet_info = NULL;
struct dp_mon_desc *mon_desc = NULL;
qdf_frag_t packet_buffer = NULL;
uint32_t end_offset = 0;
tx_status_info = &tx_mon_be->data_status_info;
/* update buffer from packet info */
packet_info = &TXMON_PPDU_HAL(tx_data_ppdu_info, packet_info);
mon_desc = (struct dp_mon_desc *)(uintptr_t)packet_info->sw_cookie;
qdf_assert_always(mon_desc);
if (mon_desc->magic != DP_MON_DESC_MAGIC)
qdf_assert_always(0);
qdf_assert_always(mon_desc->buf_addr);
if (!mon_desc->unmapped) {
qdf_mem_unmap_page(pdev->soc->osdev,
(qdf_dma_addr_t)mon_desc->paddr,
DP_MON_DATA_BUFFER_SIZE,
QDF_DMA_FROM_DEVICE);
mon_desc->unmapped = 1;
}
packet_buffer = mon_desc->buf_addr;
mon_desc->buf_addr = NULL;
/* increment reap count */
mon_desc_list_ref->tx_mon_reap_cnt++;
/* add the mon_desc to free list */
dp_mon_add_to_free_desc_list(&mon_desc_list_ref->desc_list,
&mon_desc_list_ref->tail,
mon_desc);
TXMON_STATUS_INFO(tx_status_info, buffer) = packet_buffer;
TXMON_STATUS_INFO(tx_status_info, offset) = end_offset;
TXMON_STATUS_INFO(tx_status_info,
length) = packet_info->dma_length;
TXMON_PPDU_HAL(tx_data_ppdu_info, is_used) = 1;
dp_tx_mon_generate_data_frm(pdev, tx_data_ppdu_info, false);
break; break;
} }
case HAL_MON_TX_FES_STATUS_END: case HAL_MON_TX_FES_STATUS_END:
@@ -1240,26 +1384,30 @@ dp_tx_mon_update_ppdu_info_status(struct dp_pdev *pdev,
/* /*
* dp_tx_mon_process_tlv_2_0() - API to parse PPDU worth information * dp_tx_mon_process_tlv_2_0() - API to parse PPDU worth information
* @pdev_handle: DP_PDEV handle * @pdev_handle: DP_PDEV handle
* @mon_desc_list_ref: tx monitor descriptor list reference
* *
* Return: status * Return: status
*/ */
QDF_STATUS dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev) QDF_STATUS
dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev,
struct dp_tx_mon_desc_list *mon_desc_list_ref)
{ {
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
struct dp_tx_ppdu_info *tx_prot_ppdu_info = NULL; struct dp_tx_ppdu_info *tx_prot_ppdu_info = NULL;
struct dp_tx_ppdu_info *tx_data_ppdu_info = NULL; struct dp_tx_ppdu_info *tx_data_ppdu_info = NULL;
struct hal_tx_status_info *tx_status_prot; struct hal_tx_status_info *tx_status_prot;
struct hal_tx_status_info *tx_status_data; struct hal_tx_status_info *tx_status_data;
qdf_frag_t status_frag = NULL; qdf_frag_t status_frag = NULL;
uint32_t end_offset = 0;
uint8_t *tx_tlv; uint8_t *tx_tlv;
uint8_t *tx_tlv_start; uint8_t *tx_tlv_start;
uint32_t tlv_status; uint32_t tlv_status;
uint32_t status = QDF_STATUS_SUCCESS; uint32_t status = QDF_STATUS_SUCCESS;
uint8_t num_users = 0; uint8_t num_users = 0;
uint8_t cur_frag_q_idx; uint8_t cur_frag_q_idx;
uint32_t end_offset = 0; bool schedule_wrq = false;
/* sanity check */ /* sanity check */
if (qdf_unlikely(!pdev)) if (qdf_unlikely(!pdev))
@@ -1273,25 +1421,25 @@ QDF_STATUS dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev)
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return QDF_STATUS_E_NOMEM; return QDF_STATUS_E_NOMEM;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
cur_frag_q_idx = tx_cap_be->cur_frag_q_idx; cur_frag_q_idx = tx_mon_be->cur_frag_q_idx;
tx_status_prot = &tx_cap_be->prot_status_info; tx_status_prot = &tx_mon_be->prot_status_info;
tx_status_data = &tx_cap_be->data_status_info; tx_status_data = &tx_mon_be->data_status_info;
tx_prot_ppdu_info = dp_tx_mon_get_ppdu_info(pdev, TX_PROT_PPDU_INFO, tx_prot_ppdu_info = dp_tx_mon_get_ppdu_info(pdev, TX_PROT_PPDU_INFO,
1, tx_cap_be->be_ppdu_id); 1, tx_mon_be->be_ppdu_id);
if (!tx_prot_ppdu_info) { if (!tx_prot_ppdu_info) {
dp_mon_info("tx prot ppdu info alloc got failed!!"); dp_mon_info("tx prot ppdu info alloc got failed!!");
return QDF_STATUS_E_NOMEM; return QDF_STATUS_E_NOMEM;
} }
status_frag = tx_cap_be->frag_q_vec[cur_frag_q_idx].frag_buf; status_frag = tx_mon_be->frag_q_vec[cur_frag_q_idx].frag_buf;
end_offset = tx_cap_be->frag_q_vec[cur_frag_q_idx].end_offset; end_offset = tx_mon_be->frag_q_vec[cur_frag_q_idx].end_offset;
tx_tlv = status_frag; tx_tlv = status_frag;
dp_mon_debug("last_frag_q_idx: %d status_frag:%pK", dp_mon_debug("last_frag_q_idx: %d status_frag:%pK",
tx_cap_be->last_frag_q_idx, status_frag); tx_mon_be->last_frag_q_idx, status_frag);
/* get number of user from tlv window */ /* get number of user from tlv window */
tlv_status = hal_txmon_status_get_num_users(pdev->soc->hal_soc, tlv_status = hal_txmon_status_get_num_users(pdev->soc->hal_soc,
@@ -1305,18 +1453,18 @@ QDF_STATUS dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev)
/* allocate tx_data_ppdu_info based on num_users */ /* allocate tx_data_ppdu_info based on num_users */
tx_data_ppdu_info = dp_tx_mon_get_ppdu_info(pdev, TX_DATA_PPDU_INFO, tx_data_ppdu_info = dp_tx_mon_get_ppdu_info(pdev, TX_DATA_PPDU_INFO,
num_users, num_users,
tx_cap_be->be_ppdu_id); tx_mon_be->be_ppdu_id);
if (!tx_data_ppdu_info) { if (!tx_data_ppdu_info) {
dp_mon_info("tx prot ppdu info alloc got failed!!"); dp_mon_info("tx prot ppdu info alloc got failed!!");
return QDF_STATUS_E_NOMEM; return QDF_STATUS_E_NOMEM;
} }
/* iterate status buffer queue */ /* iterate status buffer queue */
while (tx_cap_be->cur_frag_q_idx < tx_cap_be->last_frag_q_idx && while (tx_mon_be->cur_frag_q_idx < tx_mon_be->last_frag_q_idx &&
status == QDF_STATUS_SUCCESS) { status == QDF_STATUS_SUCCESS) {
/* get status buffer from frag_q_vec */ /* get status buffer from frag_q_vec */
status_frag = tx_cap_be->frag_q_vec[cur_frag_q_idx].frag_buf; status_frag = tx_mon_be->frag_q_vec[cur_frag_q_idx].frag_buf;
end_offset = tx_cap_be->frag_q_vec[cur_frag_q_idx].end_offset; end_offset = tx_mon_be->frag_q_vec[cur_frag_q_idx].end_offset;
if (qdf_unlikely(!status_frag)) { if (qdf_unlikely(!status_frag)) {
dp_mon_err("status frag is NULL\n"); dp_mon_err("status frag is NULL\n");
QDF_BUG(0); QDF_BUG(0);
@@ -1344,12 +1492,14 @@ QDF_STATUS dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev)
tx_prot_ppdu_info, tx_prot_ppdu_info,
tx_tlv, tx_tlv,
status_frag, status_frag,
tlv_status); tlv_status,
mon_desc_list_ref);
if (status != QDF_STATUS_SUCCESS) { if (status != QDF_STATUS_SUCCESS) {
dp_tx_mon_status_free_packet_buf(pdev, dp_tx_mon_status_free_packet_buf(pdev,
status_frag, status_frag,
end_offset); end_offset,
mon_desc_list_ref);
break; break;
} }
@@ -1364,13 +1514,13 @@ QDF_STATUS dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev)
* is status_frag mapped to mpdu if so make sure * is status_frag mapped to mpdu if so make sure
*/ */
qdf_frag_free(status_frag); qdf_frag_free(status_frag);
tx_cap_be->frag_q_vec[cur_frag_q_idx].frag_buf = NULL; tx_mon_be->frag_q_vec[cur_frag_q_idx].frag_buf = NULL;
tx_cap_be->frag_q_vec[cur_frag_q_idx].end_offset = 0; tx_mon_be->frag_q_vec[cur_frag_q_idx].end_offset = 0;
cur_frag_q_idx = ++tx_cap_be->cur_frag_q_idx; cur_frag_q_idx = ++tx_mon_be->cur_frag_q_idx;
} }
/* clear the unreleased frag array */ /* clear the unreleased frag array */
dp_tx_mon_status_queue_free(pdev, tx_cap_be); dp_tx_mon_status_queue_free(pdev, tx_mon_be, mon_desc_list_ref);
if (TXMON_PPDU_HAL(tx_prot_ppdu_info, is_used)) { if (TXMON_PPDU_HAL(tx_prot_ppdu_info, is_used)) {
if (qdf_unlikely(!TXMON_PPDU_COM(tx_prot_ppdu_info, if (qdf_unlikely(!TXMON_PPDU_COM(tx_prot_ppdu_info,
@@ -1393,21 +1543,20 @@ QDF_STATUS dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev)
* *
* TODO: add a threshold check and drop the ppdu info * TODO: add a threshold check and drop the ppdu info
*/ */
qdf_spin_lock_bh(&tx_cap_be->tx_mon_list_lock); qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock);
tx_cap_be->last_prot_ppdu_info = tx_mon_be->last_prot_ppdu_info =
tx_cap_be->tx_prot_ppdu_info; tx_mon_be->tx_prot_ppdu_info;
STAILQ_INSERT_TAIL(&tx_cap_be->tx_ppdu_info_queue, STAILQ_INSERT_TAIL(&tx_mon_be->tx_ppdu_info_queue,
tx_prot_ppdu_info, tx_prot_ppdu_info,
tx_ppdu_info_queue_elem); tx_ppdu_info_queue_elem);
tx_cap_be->tx_ppdu_info_list_depth++; tx_mon_be->tx_ppdu_info_list_depth++;
tx_cap_be->tx_prot_ppdu_info = NULL; tx_mon_be->tx_prot_ppdu_info = NULL;
qdf_spin_unlock_bh(&tx_cap_be->tx_mon_list_lock); qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock);
schedule_wrq = true;
} else { } else {
/* dp_tx_mon_free_ppdu_info(tx_prot_ppdu_info, tx_mon_be);
* TODO : we can also save tx_mon_be->tx_prot_ppdu_info = NULL;
* allocated buffer for future use
*/
tx_prot_ppdu_info = NULL; tx_prot_ppdu_info = NULL;
} }
@@ -1432,30 +1581,26 @@ QDF_STATUS dp_tx_mon_process_tlv_2_0(struct dp_pdev *pdev)
* *
* TODO: add a threshold check and drop the ppdu info * TODO: add a threshold check and drop the ppdu info
*/ */
qdf_spin_lock_bh(&tx_cap_be->tx_mon_list_lock); qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock);
tx_cap_be->last_data_ppdu_info = tx_mon_be->last_data_ppdu_info =
tx_cap_be->tx_data_ppdu_info; tx_mon_be->tx_data_ppdu_info;
STAILQ_INSERT_TAIL(&tx_cap_be->tx_ppdu_info_queue, STAILQ_INSERT_TAIL(&tx_mon_be->tx_ppdu_info_queue,
tx_data_ppdu_info, tx_data_ppdu_info,
tx_ppdu_info_queue_elem); tx_ppdu_info_queue_elem);
tx_cap_be->tx_ppdu_info_list_depth++; tx_mon_be->tx_ppdu_info_list_depth++;
tx_cap_be->tx_data_ppdu_info = NULL; tx_mon_be->tx_data_ppdu_info = NULL;
qdf_spin_unlock_bh(&tx_cap_be->tx_mon_list_lock); qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock);
schedule_wrq = true;
} else { } else {
/* dp_tx_mon_free_ppdu_info(tx_data_ppdu_info, tx_mon_be);
* TODO : we can also save tx_mon_be->tx_data_ppdu_info = NULL;
* allocated buffer for future use
*/
tx_data_ppdu_info = NULL; tx_data_ppdu_info = NULL;
} }
/* if (schedule_wrq)
* TODO: iterate status buffer queue and free qdf_queue_work(NULL, tx_mon_be->post_ppdu_workqueue,
* need a wrapper function to free the status buffer &tx_mon_be->post_ppdu_work);
*/
qdf_queue_work(0, tx_cap_be->post_ppdu_workqueue,
&tx_cap_be->post_ppdu_work);
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
@@ -1473,18 +1618,15 @@ void dp_tx_mon_update_end_reason(struct dp_mon_pdev *mon_pdev,
int ppdu_id, int end_reason) int ppdu_id, int end_reason)
{ {
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
return; return;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
if (tx_cap_be->be_ppdu_id != ppdu_id) tx_mon_be->be_end_reason_bitmap |= (1 << end_reason);
return;
tx_cap_be->be_end_reason_bitmap |= (1 << end_reason);
} }
/* /*
@@ -1496,18 +1638,21 @@ void dp_tx_mon_update_end_reason(struct dp_mon_pdev *mon_pdev,
* @mon_ring_desc - descriptor status info * @mon_ring_desc - descriptor status info
* @addr - status buffer frag address * @addr - status buffer frag address
* @end_offset - end offset of buffer that has valid buffer * @end_offset - end offset of buffer that has valid buffer
* @mon_desc_list_ref: tx monitor descriptor list reference
* *
* Return: QDF_STATUS * Return: QDF_STATUS
*/ */
QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, QDF_STATUS
dp_tx_mon_process_status_tlv(struct dp_soc *soc,
struct dp_pdev *pdev, struct dp_pdev *pdev,
struct hal_mon_desc *mon_ring_desc, struct hal_mon_desc *mon_ring_desc,
qdf_frag_t status_frag, qdf_frag_t status_frag,
uint32_t end_offset) uint32_t end_offset,
struct dp_tx_mon_desc_list *mon_desc_list_ref)
{ {
struct dp_mon_pdev *mon_pdev; struct dp_mon_pdev *mon_pdev;
struct dp_mon_pdev_be *mon_pdev_be; struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_capture_be *tx_cap_be; struct dp_pdev_tx_monitor_be *tx_mon_be;
uint8_t last_frag_q_idx = 0; uint8_t last_frag_q_idx = 0;
/* sanity check */ /* sanity check */
@@ -1522,63 +1667,72 @@ QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc,
if (qdf_unlikely(!mon_pdev_be)) if (qdf_unlikely(!mon_pdev_be))
goto free_status_buffer; goto free_status_buffer;
tx_cap_be = &mon_pdev_be->tx_capture_be; tx_mon_be = &mon_pdev_be->tx_monitor_be;
if (qdf_unlikely(tx_cap_be->last_frag_q_idx > if (qdf_unlikely(tx_mon_be->last_frag_q_idx >
MAX_STATUS_BUFFER_IN_PPDU)) { MAX_STATUS_BUFFER_IN_PPDU)) {
dp_mon_err("status frag queue for a ppdu[%d] exceed %d\n", dp_mon_err("status frag queue for a ppdu[%d] exceed %d\n",
tx_cap_be->be_ppdu_id, tx_mon_be->be_ppdu_id,
MAX_STATUS_BUFFER_IN_PPDU); MAX_STATUS_BUFFER_IN_PPDU);
dp_tx_mon_status_queue_free(pdev, tx_cap_be); dp_tx_mon_status_queue_free(pdev, tx_mon_be, mon_desc_list_ref);
goto free_status_buffer; goto free_status_buffer;
} }
if (tx_cap_be->mode == TX_MON_BE_DISABLE && if (tx_mon_be->mode == TX_MON_BE_DISABLE &&
!dp_lite_mon_is_tx_enabled(mon_pdev)) !dp_lite_mon_is_tx_enabled(mon_pdev)) {
dp_tx_mon_status_queue_free(pdev, tx_mon_be,
mon_desc_list_ref);
goto free_status_buffer; goto free_status_buffer;
}
if (tx_cap_be->be_ppdu_id != mon_ring_desc->ppdu_id && if (tx_mon_be->be_ppdu_id != mon_ring_desc->ppdu_id &&
tx_cap_be->last_frag_q_idx) { tx_mon_be->last_frag_q_idx) {
if (tx_cap_be->be_end_reason_bitmap & if (tx_mon_be->be_end_reason_bitmap &
(1 << HAL_MON_FLUSH_DETECTED)) { (1 << HAL_MON_FLUSH_DETECTED)) {
dp_tx_mon_status_queue_free(pdev, tx_cap_be); dp_tx_mon_status_queue_free(pdev, tx_mon_be,
} else if (tx_cap_be->be_end_reason_bitmap & mon_desc_list_ref);
} else if (tx_mon_be->be_end_reason_bitmap &
(1 << HAL_MON_PPDU_TRUNCATED)) { (1 << HAL_MON_PPDU_TRUNCATED)) {
dp_tx_mon_status_queue_free(pdev, tx_cap_be); dp_tx_mon_status_queue_free(pdev, tx_mon_be,
mon_desc_list_ref);
} else { } else {
dp_mon_err("End of ppdu not seen PID:%d cur_pid:%d idx:%d", dp_mon_err("End of ppdu not seen PID:%d cur_pid:%d idx:%d",
tx_cap_be->be_ppdu_id, tx_mon_be->be_ppdu_id,
mon_ring_desc->ppdu_id, mon_ring_desc->ppdu_id,
tx_cap_be->last_frag_q_idx); tx_mon_be->last_frag_q_idx);
/* schedule ppdu worth information */ /* schedule ppdu worth information */
dp_tx_mon_status_queue_free(pdev, tx_cap_be); dp_tx_mon_status_queue_free(pdev, tx_mon_be,
mon_desc_list_ref);
} }
/* reset end reason bitmap */ /* reset end reason bitmap */
tx_cap_be->be_end_reason_bitmap = 0; tx_mon_be->be_end_reason_bitmap = 0;
tx_cap_be->last_frag_q_idx = 0; tx_mon_be->last_frag_q_idx = 0;
tx_cap_be->cur_frag_q_idx = 0; tx_mon_be->cur_frag_q_idx = 0;
} }
tx_cap_be->be_ppdu_id = mon_ring_desc->ppdu_id; tx_mon_be->be_ppdu_id = mon_ring_desc->ppdu_id;
tx_cap_be->be_end_reason_bitmap |= (1 << mon_ring_desc->end_reason); tx_mon_be->be_end_reason_bitmap |= (1 << mon_ring_desc->end_reason);
last_frag_q_idx = tx_cap_be->last_frag_q_idx; last_frag_q_idx = tx_mon_be->last_frag_q_idx;
tx_cap_be->frag_q_vec[last_frag_q_idx].frag_buf = status_frag; tx_mon_be->frag_q_vec[last_frag_q_idx].frag_buf = status_frag;
tx_cap_be->frag_q_vec[last_frag_q_idx].end_offset = end_offset; tx_mon_be->frag_q_vec[last_frag_q_idx].end_offset = end_offset;
tx_cap_be->last_frag_q_idx++; tx_mon_be->last_frag_q_idx++;
if (mon_ring_desc->end_reason == HAL_MON_END_OF_PPDU) { if (mon_ring_desc->end_reason == HAL_MON_END_OF_PPDU) {
if (dp_tx_mon_process_tlv_2_0(pdev) != QDF_STATUS_SUCCESS) if (dp_tx_mon_process_tlv_2_0(pdev,
dp_tx_mon_status_queue_free(pdev, tx_cap_be); mon_desc_list_ref) !=
QDF_STATUS_SUCCESS)
dp_tx_mon_status_queue_free(pdev, tx_mon_be,
mon_desc_list_ref);
} }
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
free_status_buffer: free_status_buffer:
hal_txmon_status_free_buffer(pdev->soc->hal_soc, dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset,
status_frag, end_offset); mon_desc_list_ref);
qdf_frag_free(status_frag); qdf_frag_free(status_frag);
return QDF_STATUS_E_NOMEM; return QDF_STATUS_E_NOMEM;
@@ -1595,17 +1749,38 @@ free_status_buffer:
* @mon_ring_desc - descriptor status info * @mon_ring_desc - descriptor status info
* @addr - status buffer frag address * @addr - status buffer frag address
* @end_offset - end offset of buffer that has valid buffer * @end_offset - end offset of buffer that has valid buffer
* @mon_desc_list_ref: tx monitor descriptor list reference
* *
* Return: QDF_STATUS * Return: QDF_STATUS
*/ */
QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, QDF_STATUS
dp_tx_mon_process_status_tlv(struct dp_soc *soc,
struct dp_pdev *pdev, struct dp_pdev *pdev,
struct hal_mon_desc *mon_ring_desc, struct hal_mon_desc *mon_ring_desc,
qdf_frag_t status_frag, qdf_frag_t status_frag,
uint32_t end_offset) uint32_t end_offset,
struct dp_tx_mon_desc_list *mon_desc_list_ref)
{ {
hal_txmon_status_free_buffer(pdev->soc->hal_soc, struct dp_mon_pdev *mon_pdev;
status_frag, end_offset); struct dp_mon_pdev_be *mon_pdev_be;
struct dp_pdev_tx_monitor_be *tx_mon_be;
/* sanity check */
if (qdf_unlikely(!pdev))
return QDF_STATUS_E_INVAL;
mon_pdev = pdev->monitor_pdev;
if (qdf_unlikely(!mon_pdev))
return QDF_STATUS_E_INVAL;
mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
if (qdf_unlikely(!mon_pdev_be))
return QDF_STATUS_E_INVAL;
tx_mon_be = &mon_pdev_be->tx_monitor_be;
dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset,
mon_desc_list_ref);
qdf_frag_free(status_frag); qdf_frag_free(status_frag);
return QDF_STATUS_E_INVAL; return QDF_STATUS_E_INVAL;

View File

@@ -57,6 +57,10 @@
#define dp_mon_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_MON, params) #define dp_mon_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_MON, params)
#define dp_mon_warn(params...) QDF_TRACE_WARN(QDF_MODULE_ID_MON, params) #define dp_mon_warn(params...) QDF_TRACE_WARN(QDF_MODULE_ID_MON, params)
#define dp_mon_debug_rl(params...) QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_MON, params)
#define dp_mon_info_rl(params...) \
__QDF_TRACE_RL(QDF_TRACE_LEVEL_INFO_HIGH, QDF_MODULE_ID_MON, ## params)
#ifdef QCA_ENHANCED_STATS_SUPPORT #ifdef QCA_ENHANCED_STATS_SUPPORT
typedef struct dp_peer_extd_tx_stats dp_mon_peer_tx_stats; typedef struct dp_peer_extd_tx_stats dp_mon_peer_tx_stats;
typedef struct dp_peer_extd_rx_stats dp_mon_peer_rx_stats; typedef struct dp_peer_extd_rx_stats dp_mon_peer_rx_stats;

View File

@@ -866,6 +866,7 @@ struct hal_tx_status_info {
* @cur_usr_idx: Current user index of the PPDU * @cur_usr_idx: Current user index of the PPDU
* @reserved: for furture purpose * @reserved: for furture purpose
* @prot_tlv_status: protection tlv status * @prot_tlv_status: protection tlv status
* @packet_info: packet information
* @rx_status: monitor mode rx status information * @rx_status: monitor mode rx status information
* @rx_user_status: monitor mode rx user status information * @rx_user_status: monitor mode rx user status information
*/ */
@@ -879,6 +880,8 @@ struct hal_tx_ppdu_info {
uint32_t prot_tlv_status; uint32_t prot_tlv_status;
/* placeholder to hold packet buffer info */
struct hal_mon_packet_info packet_info;
struct mon_rx_status rx_status; struct mon_rx_status rx_status;
struct mon_rx_user_status rx_user_status[]; struct mon_rx_user_status rx_user_status[];
}; };
@@ -950,25 +953,6 @@ hal_txmon_status_get_num_users(hal_soc_handle_t hal_soc_hdl,
num_users); num_users);
} }
/**
* hal_txmon_status_free_buffer() - api to free status buffer
* @hal_soc: HAL soc handle
* @status_frag: qdf_frag_t buffer
* @end_offset: end offset within buffer that has valid data
*
* Return status
*/
static inline QDF_STATUS
hal_txmon_status_free_buffer(hal_soc_handle_t hal_soc_hdl,
qdf_frag_t status_frag,
uint32_t end_offset)
{
struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl;
return hal_soc->ops->hal_txmon_status_free_buffer(status_frag,
end_offset);
}
/** /**
* hal_tx_status_get_tlv_tag() - api to get tlv tag * hal_tx_status_get_tlv_tag() - api to get tlv tag
* @tx_tlv_hdr: pointer to TLV header * @tx_tlv_hdr: pointer to TLV header
@@ -986,6 +970,45 @@ hal_tx_status_get_tlv_tag(void *tx_tlv_hdr)
} }
#endif #endif
/**
* hal_txmon_is_mon_buf_addr_tlv() - api to find packet buffer addr tlv
* @hal_soc: HAL soc handle
* @tx_tlv_hdr: pointer to TLV header
*
* Return: bool
*/
static inline bool
hal_txmon_is_mon_buf_addr_tlv(hal_soc_handle_t hal_soc_hdl, void *tx_tlv_hdr)
{
struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl;
if (qdf_unlikely(!hal_soc->ops->hal_txmon_is_mon_buf_addr_tlv))
return false;
return hal_soc->ops->hal_txmon_is_mon_buf_addr_tlv(tx_tlv_hdr);
}
/**
* hal_txmon_populate_packet_info() - api to populate packet info
* @hal_soc: HAL soc handle
* @tx_tlv_hdr: pointer to TLV header
* @packet_info: pointer to placeholder for packet info
*
* Return void
*/
static inline void
hal_txmon_populate_packet_info(hal_soc_handle_t hal_soc_hdl,
void *tx_tlv_hdr,
void *packet_info)
{
struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl;
if (qdf_unlikely(!hal_soc->ops->hal_txmon_populate_packet_info))
return;
hal_soc->ops->hal_txmon_populate_packet_info(tx_tlv_hdr, packet_info);
}
static inline uint32_t static inline uint32_t
hal_rx_parse_u_sig_cmn(struct hal_soc *hal_soc, void *rx_tlv, hal_rx_parse_u_sig_cmn(struct hal_soc *hal_soc, void *rx_tlv,
struct hal_rx_ppdu_info *ppdu_info) struct hal_rx_ppdu_info *ppdu_info)

View File

@@ -326,34 +326,43 @@ hal_rx_fst_get_fse_size_be(void)
#ifdef QCA_MONITOR_2_0_SUPPORT #ifdef QCA_MONITOR_2_0_SUPPORT
/** /**
* hal_txmon_get_buffer_addr_generic_be() - api to get buffer address * hal_txmon_is_mon_buf_addr_tlv_generic_be() - api to find mon buffer tlv
* @tx_tlv: pointer to TLV header * @tx_tlv: pointer to TLV header
* @status: hal mon buffer address status
* *
* Return: Address to qdf_frag_t * Return: bool based on tlv tag matches monitor buffer address tlv
*/ */
static inline qdf_frag_t static inline bool
hal_txmon_get_buffer_addr_generic_be(void *tx_tlv, hal_txmon_is_mon_buf_addr_tlv_generic_be(void *tx_tlv_hdr)
struct hal_mon_buf_addr_status *status)
{ {
struct mon_buffer_addr *hal_buffer_addr = uint32_t tlv_tag;
(struct mon_buffer_addr *)((uint8_t *)tx_tlv +
HAL_RX_TLV64_HDR_SIZE);
qdf_frag_t buf_addr = NULL;
buf_addr = (qdf_frag_t)(uintptr_t)((hal_buffer_addr->buffer_virt_addr_31_0 | tlv_tag = HAL_RX_GET_USER_TLV64_TYPE(tx_tlv_hdr);
((unsigned long long)hal_buffer_addr->buffer_virt_addr_63_32 <<
32)));
/* qdf_frag_t is derived from buffer address tlv */ if (WIFIMON_BUFFER_ADDR_E == tlv_tag)
if (qdf_unlikely(status)) { return true;
qdf_mem_copy(status,
(uint8_t *)tx_tlv + HAL_RX_TLV64_HDR_SIZE,
sizeof(struct hal_mon_buf_addr_status));
/* update hal_mon_buf_addr_status */
}
return buf_addr; return false;
}
/**
* hal_txmon_populate_packet_info_generic_be() - api to populate packet info
* @tx_tlv: pointer to TLV header
* @packet_info: place holder for packet info
*
* Return: Address to void
*/
static inline void
hal_txmon_populate_packet_info_generic_be(void *tx_tlv, void *packet_info)
{
struct hal_mon_packet_info *pkt_info;
struct mon_buffer_addr *addr = (struct mon_buffer_addr *)tx_tlv;
pkt_info = (struct hal_mon_packet_info *)packet_info;
pkt_info->sw_cookie = (((uint64_t)addr->buffer_virt_addr_63_32 << 32) |
(addr->buffer_virt_addr_31_0));
pkt_info->dma_length = addr->dma_length + 1;
pkt_info->msdu_continuation = addr->msdu_continuation;
pkt_info->truncated = addr->truncated;
} }
#if defined(TX_MONITOR_WORD_MASK) #if defined(TX_MONITOR_WORD_MASK)
@@ -657,60 +666,6 @@ hal_txmon_status_get_num_users_generic_be(void *tx_tlv_hdr, uint8_t *num_users)
return tlv_status; return tlv_status;
} }
/**
* hal_txmon_free_status_buffer() - api to free status buffer
* @pdev_handle: DP_PDEV handle
* @status_frag: qdf_frag_t buffer
* @end_offset: end offset within buffer that has valid data
*
* Return status
*/
static inline QDF_STATUS
hal_txmon_status_free_buffer_generic_be(qdf_frag_t status_frag,
uint32_t end_offset)
{
uint32_t tlv_tag, tlv_len;
uint32_t tlv_status = HAL_MON_TX_STATUS_PPDU_NOT_DONE;
uint8_t *tx_tlv;
uint8_t *tx_tlv_start;
qdf_frag_t frag_buf = NULL;
QDF_STATUS status = QDF_STATUS_E_ABORTED;
tx_tlv = (uint8_t *)status_frag;
tx_tlv_start = tx_tlv;
/* parse tlv and populate tx_ppdu_info */
do {
tlv_tag = HAL_RX_GET_USER_TLV64_TYPE(tx_tlv);
tlv_len = HAL_RX_GET_USER_TLV64_LEN(tx_tlv);
if (((tx_tlv - tx_tlv_start) + tlv_len) > end_offset)
return QDF_STATUS_E_ABORTED;
if (tlv_tag == WIFIMON_BUFFER_ADDR_E) {
frag_buf = hal_txmon_get_buffer_addr_generic_be(tx_tlv,
NULL);
if (frag_buf)
qdf_frag_free(frag_buf);
frag_buf = NULL;
}
if (WIFITX_FES_STATUS_END_E == tlv_tag ||
WIFIRESPONSE_END_STATUS_E == tlv_tag ||
WIFIDUMMY_E == tlv_tag) {
status = QDF_STATUS_SUCCESS;
break;
}
/* need api definition for hal_tx_status_get_next_tlv */
tx_tlv = hal_tx_status_get_next_tlv(tx_tlv);
if ((tx_tlv - tx_tlv_start) >= end_offset)
break;
} while (tlv_status == HAL_MON_TX_STATUS_PPDU_NOT_DONE);
return status;
}
/** /**
* hal_tx_get_ppdu_info() - api to get tx ppdu info * hal_tx_get_ppdu_info() - api to get tx ppdu info
* @pdev_handle: DP_PDEV handle * @pdev_handle: DP_PDEV handle
@@ -794,8 +749,8 @@ hal_txmon_status_parse_tlv_generic_be(void *data_ppdu_info,
{ {
struct hal_tx_ppdu_info *ppdu_info; struct hal_tx_ppdu_info *ppdu_info;
struct hal_tx_status_info *tx_status_info; struct hal_tx_status_info *tx_status_info;
struct hal_mon_packet_info *packet_info = NULL;
uint32_t tlv_tag, user_id, tlv_len; uint32_t tlv_tag, user_id, tlv_len;
qdf_frag_t frag_buf = NULL;
uint32_t status = HAL_MON_TX_STATUS_PPDU_NOT_DONE; uint32_t status = HAL_MON_TX_STATUS_PPDU_NOT_DONE;
void *tx_tlv; void *tx_tlv;
@@ -1043,21 +998,15 @@ hal_txmon_status_parse_tlv_generic_be(void *data_ppdu_info,
} }
case WIFIMON_BUFFER_ADDR_E:/* DOWNSTREAM */ case WIFIMON_BUFFER_ADDR_E:/* DOWNSTREAM */
{ {
struct hal_mon_buf_addr_status buf_status = {0}; packet_info = &ppdu_info->packet_info;
status = HAL_MON_TX_BUFFER_ADDR; status = HAL_MON_TX_BUFFER_ADDR;
/* /*
* TODO: do we need a conversion api to convert * TODO: do we need a conversion api to convert
* user_id from hw to get host user_index * user_id from hw to get host user_index
*/ */
TXMON_HAL(ppdu_info, cur_usr_idx) = user_id; TXMON_HAL(ppdu_info, cur_usr_idx) = user_id;
frag_buf = hal_txmon_get_buffer_addr_generic_be(tx_tlv,
&buf_status); hal_txmon_populate_packet_info_generic_be(tx_tlv, packet_info);
TXMON_STATUS_INFO(tx_status_info,
buffer) = (void *)frag_buf;
TXMON_STATUS_INFO(tx_status_info, offset) = 0;
TXMON_STATUS_INFO(tx_status_info,
length) = buf_status.dma_length;
SHOW_DEFINED(WIFIMON_BUFFER_ADDR_E); SHOW_DEFINED(WIFIMON_BUFFER_ADDR_E);
break; break;
@@ -1591,8 +1540,7 @@ hal_txmon_status_parse_tlv_generic_be(void *data_ppdu_info,
BA_TS_CTRL); BA_TS_CTRL);
/* memcpy ba bitmap */ /* memcpy ba bitmap */
qdf_mem_copy(TXMON_HAL_USER(ppdu_info, user_id, ba_bitmap), qdf_mem_copy(TXMON_HAL_USER(ppdu_info, user_id, ba_bitmap),
tx_tlv + &HAL_SET_FLD_OFFSET_64(tx_tlv,
HAL_TX_DESC_OFFSET_GET_64(tx_tlv,
RX_FRAME_1K_BITMAP_ACK, RX_FRAME_1K_BITMAP_ACK,
BA_TS_BITMAP_31_0, 0), BA_TS_BITMAP_31_0, 0),
4 << TXMON_HAL_USER(ppdu_info, 4 << TXMON_HAL_USER(ppdu_info,

View File

@@ -1139,6 +1139,9 @@ struct hal_hw_txrx_ops {
uint8_t (*hal_get_tlv_hdr_size)(void); uint8_t (*hal_get_tlv_hdr_size)(void);
uint8_t (*hal_get_idle_link_bm_id)(uint8_t chip_id); uint8_t (*hal_get_idle_link_bm_id)(uint8_t chip_id);
bool (*hal_txmon_is_mon_buf_addr_tlv)(void *tx_tlv_hdr);
void (*hal_txmon_populate_packet_info)(void *tx_tlv_hdr,
void *pkt_info);
/* TX MONITOR */ /* TX MONITOR */
#ifdef QCA_MONITOR_2_0_SUPPORT #ifdef QCA_MONITOR_2_0_SUPPORT
uint32_t (*hal_txmon_status_parse_tlv)(void *data_ppdu_info, uint32_t (*hal_txmon_status_parse_tlv)(void *data_ppdu_info,
@@ -1149,8 +1152,6 @@ struct hal_hw_txrx_ops {
qdf_frag_t status_frag); qdf_frag_t status_frag);
uint32_t (*hal_txmon_status_get_num_users)(void *tx_tlv_hdr, uint32_t (*hal_txmon_status_get_num_users)(void *tx_tlv_hdr,
uint8_t *num_users); uint8_t *num_users);
QDF_STATUS (*hal_txmon_status_free_buffer)(qdf_frag_t status_frag,
uint32_t end_offset);
#endif /* QCA_MONITOR_2_0_SUPPORT */ #endif /* QCA_MONITOR_2_0_SUPPORT */
void (*hal_reo_shared_qaddr_setup)(hal_soc_handle_t hal_soc_hdl); void (*hal_reo_shared_qaddr_setup)(hal_soc_handle_t hal_soc_hdl);
void (*hal_reo_shared_qaddr_init)(hal_soc_handle_t hal_soc_hdl); void (*hal_reo_shared_qaddr_init)(hal_soc_handle_t hal_soc_hdl);

View File

@@ -1959,12 +1959,14 @@ static void hal_hw_txrx_ops_attach_qcn9224(struct hal_soc *hal_soc)
hal_soc->ops->hal_get_reo_qdesc_size = hal_qcn9224_get_reo_qdesc_size; hal_soc->ops->hal_get_reo_qdesc_size = hal_qcn9224_get_reo_qdesc_size;
/* TX MONITOR */ /* TX MONITOR */
#ifdef QCA_MONITOR_2_0_SUPPORT #ifdef QCA_MONITOR_2_0_SUPPORT
hal_soc->ops->hal_txmon_is_mon_buf_addr_tlv =
hal_txmon_is_mon_buf_addr_tlv_generic_be;
hal_soc->ops->hal_txmon_populate_packet_info =
hal_txmon_populate_packet_info_generic_be;
hal_soc->ops->hal_txmon_status_parse_tlv = hal_soc->ops->hal_txmon_status_parse_tlv =
hal_txmon_status_parse_tlv_generic_be; hal_txmon_status_parse_tlv_generic_be;
hal_soc->ops->hal_txmon_status_get_num_users = hal_soc->ops->hal_txmon_status_get_num_users =
hal_txmon_status_get_num_users_generic_be; hal_txmon_status_get_num_users_generic_be;
hal_soc->ops->hal_txmon_status_free_buffer =
hal_txmon_status_free_buffer_generic_be;
#endif /* QCA_MONITOR_2_0_SUPPORT */ #endif /* QCA_MONITOR_2_0_SUPPORT */
hal_soc->ops->hal_compute_reo_remap_ix0 = NULL; hal_soc->ops->hal_compute_reo_remap_ix0 = NULL;
hal_soc->ops->hal_tx_vdev_mismatch_routing_set = hal_soc->ops->hal_tx_vdev_mismatch_routing_set =