diff --git a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c index 47391608ff..bf28992bdd 100644 --- a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c @@ -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_add_to_comp_queue = NULL; mon_ops->mon_print_pdev_tx_capture_stats = - dp_print_pdev_tx_capture_stats_2_0; - mon_ops->mon_config_enh_tx_capture = dp_config_enh_tx_capture_2_0; + dp_print_pdev_tx_monitor_stats_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; #endif #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_add_to_comp_queue = 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; #endif #ifdef WLAN_RX_PKT_CAPTURE_ENH diff --git a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h index b6e30c9d9c..ee4e3c1540 100644 --- a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h +++ b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.h @@ -136,7 +136,7 @@ struct dp_mon_desc_pool { * @filter_be: filters sent to fw * @tx_mon_mode: tx monitor mode * @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 * @rx_mon_wq_lock: Rx mon workqueue lock * @rx_mon_workqueue: Rx mon workqueue @@ -151,7 +151,7 @@ struct dp_mon_pdev_be { struct dp_mon_filter_be **filter_be; uint8_t tx_mon_mode; 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; qdf_spinlock_t rx_mon_wq_lock; qdf_workqueue_t *rx_mon_workqueue; diff --git a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c index 8ad00ea62f..1ad5171c55 100644 --- a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.c @@ -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; 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); - union dp_mon_desc_list_elem_t *desc_list = NULL; - union dp_mon_desc_list_elem_t *tail = NULL; + struct dp_pdev_tx_monitor_be *tx_mon_be = NULL; 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) { 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)) return work_done; + tx_mon_be = &mon_pdev_be->tx_monitor_be; hal_soc = soc->hal_soc; qdf_assert((hal_soc && pdev)); 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))) { 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--)) { struct hal_mon_desc hal_mon_tx_desc = {0}; 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, 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); } - 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) || - (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); + status_frag = (qdf_frag_t)(mon_desc->buf_addr); + mon_desc->buf_addr = NULL; + /* increment reap count */ + ++mon_desc_list.tx_mon_reap_cnt; - qdf_frag_free(mon_desc->buf_addr); - mon_desc->buf_addr = NULL; - ++tx_monitor_reap_cnt; - dp_mon_add_to_free_desc_list(&desc_list, - &tail, mon_desc); + /* add the mon_desc to free list */ + dp_mon_add_to_free_desc_list(&mon_desc_list.desc_list, + &mon_desc_list.tail, mon_desc); - work_done++; - hal_srng_dst_get_next(hal_soc, mon_dst_srng); - continue; - } - 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", hal_mon_tx_desc.ppdu_id, 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_reason); - ++tx_monitor_reap_cnt; - dp_mon_add_to_free_desc_list(&desc_list, - &tail, mon_desc); + work_done++; + hal_srng_dst_get_next(hal_soc, mon_dst_srng); + 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++; 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, &hal_mon_tx_desc, - mon_desc->buf_addr, end_offset); - - mon_desc->buf_addr = NULL; - ++tx_monitor_reap_cnt; - dp_mon_add_to_free_desc_list(&desc_list, &tail, mon_desc); + status_frag, + end_offset, + &mon_desc_list); work_done++; hal_srng_dst_get_next(hal_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, tx_mon_desc_pool, - tx_monitor_reap_cnt, - &desc_list, &tail); + mon_desc_list.tx_mon_reap_cnt, + &mon_desc_list.desc_list, + &mon_desc_list.tail); } qdf_spin_unlock_bh(&mon_pdev->mon_lock); 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; } @@ -304,15 +313,18 @@ dp_tx_mon_buffers_alloc(struct dp_soc *soc, uint32_t size) } #ifdef WLAN_TX_PKT_CAPTURE_ENH_BE + /* * dp_tx_mon_free_usr_mpduq() - API to free user mpduq * @tx_ppdu_info - pointer to tx_ppdu_info * @usr_idx - user index + * @tx_mon_be - pointer to tx capture be * * Return: void */ 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; @@ -320,16 +332,18 @@ void dp_tx_mon_free_usr_mpduq(struct dp_tx_ppdu_info *tx_ppdu_info, return; 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 * @tx_ppdu_info - pointer to tx_ppdu_info + * @tx_mon_be - pointer to tx capture be * * 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; @@ -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_be *mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); - struct dp_pdev_tx_capture_be *tx_cap_be = - &mon_pdev_be->tx_capture_be; + struct dp_pdev_tx_monitor_be *tx_mon_be = + &mon_pdev_be->tx_monitor_be; struct dp_tx_ppdu_info *tx_ppdu_info; size_t sz_ppdu_info = 0; 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 */ sz_ppdu_info = (sizeof(struct dp_tx_ppdu_info) + (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, num_users) = num_user; TXMON_PPDU_HAL(tx_ppdu_info, ppdu_id) = ppdu_id; + tx_ppdu_info->ppdu_id = ppdu_id; for (i = 0; i < num_user; i++) { qdf_nbuf_queue_t *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); } /* assign tx_ppdu_info to monitor pdev for reference */ 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; } 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; } @@ -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 * * 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 */ } /* - * 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 * @val: user provided value * * Return: 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_be *mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); - struct dp_pdev_tx_capture_be *tx_cap_be = - &mon_pdev_be->tx_capture_be; + struct dp_pdev_tx_monitor_be *tx_mon_be = + &mon_pdev_be->tx_monitor_be; switch (val) { case TX_MON_BE_DISABLE: { /* 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_filter_length = DMA_LENGTH_64B; 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: { /* 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_filter_length = DMA_LENGTH_256B; + mon_pdev_be->tx_mon_filter_length = DEFAULT_DMA_LENGTH; break; } case TX_MON_BE_PEER_FILTER: { /* 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_filter_length = DMA_LENGTH_256B; 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", - 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); 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 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.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, pdev->soc, &tx_capture_info, @@ -568,6 +555,8 @@ dp_tx_mon_send_to_stack(struct dp_pdev *pdev, qdf_nbuf_t mpdu) WDI_NO_VAL, pdev->pdev_id); } + if (tx_capture_info.mpdu_nbuf) + qdf_nbuf_free(tx_capture_info.mpdu_nbuf); } /** @@ -575,75 +564,30 @@ dp_tx_mon_send_to_stack(struct dp_pdev *pdev, qdf_nbuf_t mpdu) * @pdev: pdev Handle * @ppdu_info: pointer to dp_tx_ppdu_info * @user_id: current user index - * @radiota_hdr_ref: pointer to radiotap ref * * Return: void */ static void dp_tx_mon_send_per_usr_mpdu(struct dp_pdev *pdev, struct dp_tx_ppdu_info *ppdu_info, - uint8_t user_id, - qdf_nbuf_t *radiotap_hdr_ref) + uint8_t user_idx) { - uint32_t mpdu_queue_len = 0; qdf_nbuf_queue_t *usr_mpdu_q = NULL; qdf_nbuf_t buf = NULL; - qdf_nbuf_t radiotap_copy = NULL; - usr_mpdu_q = &TXMON_PPDU_USR(ppdu_info, user_id, mpdu_q); - - if (!usr_mpdu_q) { - qdf_nbuf_free(*radiotap_hdr_ref); - *radiotap_hdr_ref = NULL; - /* free radiotap hdr */ - return; - } + usr_mpdu_q = &TXMON_PPDU_USR(ppdu_info, user_idx, mpdu_q); while ((buf = qdf_nbuf_queue_remove(usr_mpdu_q)) != NULL) { - mpdu_queue_len = qdf_nbuf_queue_len(usr_mpdu_q); - /* - * In an aggregated frame, each mpdu is send individualy to - * stack. caller of the function already allocate - * and update radiotap header information. We copy the - * same radiotap header until we reach the end of mpdu. - * Once we reached end of mpdu we use the buffer allocated - * 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; - } + ppdu_info->hal_txmon.rx_status.rx_user_status = + &ppdu_info->hal_txmon.rx_user_status[user_idx]; - /* 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); + qdf_nbuf_update_radiotap(&ppdu_info->hal_txmon.rx_status, + buf, qdf_nbuf_headroom(buf)); + + dp_tx_mon_send_to_stack(pdev, buf); } } -/** - * 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; -} - /** * dp_tx_mon_update_radiotap() - API to update radiotap information * @pdev: pdev Handle @@ -655,13 +599,8 @@ static void dp_tx_mon_update_radiotap(struct dp_pdev *pdev, struct dp_tx_ppdu_info *ppdu_info) { - uint32_t i = 0; + uint32_t usr_idx = 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); @@ -673,13 +612,15 @@ dp_tx_mon_update_radiotap(struct dp_pdev *pdev, TXMON_PPDU_COM(ppdu_info, chan_freq) = pdev->operating_channel.freq; - for (i = 0; i < num_users; i++) { - /* allocate radiotap_hdr */ - status = dp_tx_mon_alloc_radiotap_hdr(pdev, &radiotap_hdr); - if (status != QDF_STATUS_SUCCESS) { - /* free ppdu_info per user */ - dp_tx_mon_free_usr_mpduq(ppdu_info, i); - continue; + for (usr_idx = 0; usr_idx < num_users; usr_idx++) { + qdf_nbuf_queue_t *mpdu_q = NULL; + + /* set AMPDU flag if number mpdu is more than 1 */ + mpdu_q = &TXMON_PPDU_USR(ppdu_info, usr_idx, mpdu_q); + if (mpdu_q && (qdf_nbuf_queue_len(mpdu_q) > 1)) { + 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))) { @@ -689,7 +630,7 @@ dp_tx_mon_update_radiotap(struct dp_pdev *pdev, rate = dp_getrateindex(TXMON_PPDU_COM(ppdu_info, sgi), TXMON_PPDU_USR(ppdu_info, - i, mcs), + usr_idx, mcs), TXMON_PPDU_COM(ppdu_info, nss), TXMON_PPDU_COM(ppdu_info, preamble_type), @@ -701,21 +642,7 @@ dp_tx_mon_update_radiotap(struct dp_pdev *pdev, TXMON_PPDU_COM(ppdu_info, rate) = rate; } - /* copy rx_status to rx_status and invoke update radiotap */ - 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); + dp_tx_mon_send_per_usr_mpdu(pdev, ppdu_info, usr_idx); } } @@ -732,7 +659,7 @@ void dp_tx_mon_ppdu_process(void *context) 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_next = NULL; - struct dp_pdev_tx_capture_be *tx_cap_be; + struct dp_pdev_tx_monitor_be *tx_mon_be; /* sanity check */ if (qdf_unlikely(!pdev)) @@ -747,34 +674,34 @@ void dp_tx_mon_ppdu_process(void *context) if (qdf_unlikely(!mon_pdev_be)) return; - tx_cap_be = &mon_pdev_be->tx_capture_be; - if (qdf_unlikely(TX_MON_BE_DISABLE == tx_cap_be->mode && + tx_mon_be = &mon_pdev_be->tx_monitor_be; + if (qdf_unlikely(TX_MON_BE_DISABLE == tx_mon_be->mode && !dp_lite_mon_is_tx_enabled(mon_pdev))) return; /* take lock here */ - qdf_spin_lock_bh(&tx_cap_be->tx_mon_list_lock); - STAILQ_CONCAT(&tx_cap_be->defer_tx_ppdu_info_queue, - &tx_cap_be->tx_ppdu_info_queue); - tx_cap_be->defer_ppdu_info_list_depth += - tx_cap_be->tx_ppdu_info_list_depth; - tx_cap_be->tx_ppdu_info_list_depth = 0; - qdf_spin_unlock_bh(&tx_cap_be->tx_mon_list_lock); + qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock); + STAILQ_CONCAT(&tx_mon_be->defer_tx_ppdu_info_queue, + &tx_mon_be->tx_ppdu_info_queue); + tx_mon_be->defer_ppdu_info_list_depth += + tx_mon_be->tx_ppdu_info_list_depth; + tx_mon_be->tx_ppdu_info_list_depth = 0; + qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock); 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) { /* 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, dp_tx_ppdu_info, 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); /* 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; } } @@ -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_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)) return; @@ -803,20 +730,20 @@ void dp_tx_ppdu_stats_attach_2_0(struct dp_pdev *pdev) if (qdf_unlikely(!mon_pdev_be)) 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); - tx_cap_be->tx_ppdu_info_list_depth = 0; + STAILQ_INIT(&tx_mon_be->tx_ppdu_info_queue); + tx_mon_be->tx_ppdu_info_list_depth = 0; - STAILQ_INIT(&tx_cap_be->defer_tx_ppdu_info_queue); - tx_cap_be->defer_ppdu_info_list_depth = 0; + STAILQ_INIT(&tx_mon_be->defer_tx_ppdu_info_queue); + 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 */ - 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); - tx_cap_be->post_ppdu_workqueue = + tx_mon_be->post_ppdu_workqueue = 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_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_next = NULL; @@ -846,86 +773,86 @@ void dp_tx_ppdu_stats_detach_2_0(struct dp_pdev *pdev) if (qdf_unlikely(!mon_pdev_be)) 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 */ dp_monitor_config_enh_tx_capture(pdev, TX_MON_BE_DISABLE); /* flush workqueue */ - qdf_flush_workqueue(0, tx_cap_be->post_ppdu_workqueue); - qdf_destroy_workqueue(0, tx_cap_be->post_ppdu_workqueue); + qdf_flush_workqueue(0, tx_mon_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 * 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, - &tx_cap_be->tx_ppdu_info_queue, + &tx_mon_be->tx_ppdu_info_queue, tx_ppdu_info_queue_elem, tx_ppdu_info_next) { /* 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); /* decrement list length */ - tx_cap_be->tx_ppdu_info_list_depth--; + tx_mon_be->tx_ppdu_info_list_depth--; /* 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, - &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) { /* 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, dp_tx_ppdu_info, tx_ppdu_info_queue_elem); /* decrement list length */ - tx_cap_be->defer_ppdu_info_list_depth--; + tx_mon_be->defer_ppdu_info_list_depth--; /* 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 */ #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 * @val: user provided value * * Return: 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_be *mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev); - struct dp_pdev_tx_capture_be *tx_cap_be = - &mon_pdev_be->tx_capture_be; + struct dp_pdev_tx_monitor_be *tx_mon_be = + &mon_pdev_be->tx_monitor_be; switch (val) { 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_filter_length = DMA_LENGTH_64B; break; } 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_filter_length = DEFAULT_DMA_LENGTH; break; } 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_filter_length = DMA_LENGTH_128B; 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", - 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); /* send HTT msg to configure TLV based on mode */ diff --git a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h index 57f7dde248..5739d69241 100644 --- a/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h +++ b/dp/wifi3.0/monitor/2.0/dp_tx_mon_2.0.h @@ -22,6 +22,19 @@ #include 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 * @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, 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 * 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 * @addr - status buffer frag address * @end_offset - end offset of buffer that has valid buffer + * @mon_desc_list_ref: tx monitor descriptor list reference * * Return: QDF_STATUS */ -QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, - struct dp_pdev *pdev, - struct hal_mon_desc *mon_ring_desc, - qdf_frag_t status_frag, - uint32_t end_offset); +QDF_STATUS +dp_tx_mon_process_status_tlv(struct dp_soc *soc, + struct dp_pdev *pdev, + struct hal_mon_desc *mon_ring_desc, + qdf_frag_t status_frag, + uint32_t end_offset, + struct dp_tx_mon_desc_list *mon_desc_list_ref); /* * 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 /** - * 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 - * - * This is a dummy structure + * @tx_stats: tx monitor drop stats for that mac */ -struct dp_pdev_tx_capture_be { +struct dp_pdev_tx_monitor_be { + uint32_t be_ppdu_id; 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_end_reason_bitmap: current end reason bitmap * @mode: tx monitor current mode @@ -436,7 +469,7 @@ struct dp_txmon_frag_vec { * @cur_frag_q_idx: current index of frag 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_end_reason_bitmap; 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 * @tx_ppdu_info - pointer to tx_ppdu_info * @usr_idx - user index + * @tx_cap_be - pointer to tx capture be * * Return: void */ 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 * @tx_ppdu_info - pointer to tx_ppdu_info + * @tx_cap_be - pointer to tx capture be * * 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 @@ -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); /* - * 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 * * 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 * @val: user provided value * * 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 @@ -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)) /* - * 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 * @val: user provided value * * 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 /* _DP_TX_MON_2_0_H_ */ diff --git a/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c b/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c index 211ae02140..3f02f26e12 100644 --- a/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_tx_mon_status_2.0.c @@ -26,38 +26,126 @@ #include #include +/** + * 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) /** * dp_tx_mon_status_queue_free() - API to free status buffer * @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 */ static void 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; - 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; 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)) continue; - end_offset = tx_cap_be->frag_q_vec[i].end_offset; - hal_txmon_status_free_buffer(pdev->soc->hal_soc, status_frag, - end_offset); + end_offset = tx_mon_be->frag_q_vec[i].end_offset; + dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset, + mon_desc_list_ref); qdf_frag_free(status_frag); - tx_cap_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].frag_buf = NULL; + tx_mon_be->frag_q_vec[i].end_offset = 0; } - tx_cap_be->last_frag_q_idx = 0; - tx_cap_be->cur_frag_q_idx = 0; + tx_mon_be->last_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 */ 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) { + qdf_nbuf_t radiotap = NULL; /* enqueue mpdu_nbuf to the per user mpdu_q */ 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); - 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 */ struct dp_mon_pdev *mon_pdev; 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; uint16_t duration_le = 0; 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)) return; - tx_cap_be = &mon_pdev_be->tx_capture_be; - tx_status_info = &tx_cap_be->prot_status_info; + tx_mon_be = &mon_pdev_be->tx_monitor_be; + tx_status_info = &tx_mon_be->prot_status_info; /* * 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_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; } @@ -270,7 +366,7 @@ dp_tx_mon_generate_rts_frm(struct dp_pdev *pdev, /* enqueue 802.11 payload to per user mpdu_q */ struct dp_mon_pdev *mon_pdev; 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; uint16_t duration_le = 0; 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)) return; - tx_cap_be = &mon_pdev_be->tx_capture_be; - tx_status_info = &tx_cap_be->prot_status_info; + tx_mon_be = &mon_pdev_be->tx_monitor_be; + tx_status_info = &tx_mon_be->prot_status_info; /* * for radiotap we allocate new skb, * 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); 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, TXMON_STATUS_INFO(tx_status_info, addr1), QDF_MAC_ADDR_SIZE); @@ -319,7 +415,7 @@ dp_tx_mon_generate_rts_frm(struct dp_pdev *pdev, QDF_MAC_ADDR_SIZE); 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; } @@ -338,7 +434,7 @@ dp_tx_mon_generate_ack_frm(struct dp_pdev *pdev, /* enqueue 802.11 payload to per user mpdu_q */ struct dp_mon_pdev *mon_pdev; 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 ieee80211_frame_min_one *wh_addr1 = 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)) return; - tx_cap_be = &mon_pdev_be->tx_capture_be; - tx_status_info = &tx_cap_be->data_status_info; + tx_mon_be = &mon_pdev_be->tx_monitor_be; + tx_status_info = &tx_mon_be->data_status_info; /* * for radiotap we allocate new skb, * 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)); - 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; } @@ -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 */ struct dp_mon_pdev *mon_pdev; 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 ieee80211_qosframe *wh_addr3 = 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)) return; - tx_cap_be = &mon_pdev_be->tx_capture_be; - tx_status_info = &tx_cap_be->data_status_info; + tx_mon_be = &mon_pdev_be->tx_monitor_be; + tx_status_info = &tx_mon_be->data_status_info; /* * for radiotap we allocate new skb, * 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_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; } @@ -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 */ struct dp_mon_pdev *mon_pdev; 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 ieee80211_qosframe_addr4 *wh_addr4 = 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)) return; - tx_cap_be = &mon_pdev_be->tx_capture_be; - tx_status_info = &tx_cap_be->data_status_info; + tx_mon_be = &mon_pdev_be->tx_monitor_be; + tx_status_info = &tx_mon_be->data_status_info; /* * for radiotap we allocate new skb, * 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_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; } @@ -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 */ struct dp_mon_pdev *mon_pdev; 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 ieee80211_ctlframe_addr2 *wh_addr2 = 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)) return; - tx_cap_be = &mon_pdev_be->tx_capture_be; - tx_status_info = &tx_cap_be->data_status_info; + tx_mon_be = &mon_pdev_be->tx_monitor_be; + tx_status_info = &tx_mon_be->data_status_info; for (i = 0; i < num_users; i++) ba_sz += (4 << TXMON_BA_INFO_SZ(TXMON_PPDU_USR(tx_ppdu_info, 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))); /* 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; } @@ -666,7 +762,7 @@ dp_tx_mon_generate_block_ack_frm(struct dp_pdev *pdev, /* enqueue 802.11 payload to per user mpdu_q */ struct dp_mon_pdev *mon_pdev; 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 ieee80211_ctlframe_addr2 *wh_addr2 = 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)) return; - tx_cap_be = &mon_pdev_be->tx_capture_be; - tx_status_info = &tx_cap_be->data_status_info; + tx_mon_be = &mon_pdev_be->tx_monitor_be; + tx_status_info = &tx_mon_be->data_status_info; /* * for multi sta block ack, do we need to increase the size * 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, (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; } @@ -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 */ mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev, - TXMON_NO_BUFFER_SZ, - TXMON_NO_BUFFER_SZ, + MAX_MONITOR_HEADER, MAX_MONITOR_HEADER, 4, FALSE); if (!mpdu_nbuf) { 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 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_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; qdf_nbuf_t mpdu_nbuf = 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)) 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_mpdu_q = &TXMON_PPDU_USR(tx_ppdu_info, usr_idx, 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, TXMON_STATUS_INFO(tx_status_info, offset), TXMON_STATUS_INFO(tx_status_info, length), - TX_MON_STATUS_BUF_SIZE, - true, TXMON_NO_BUFFER_SZ); + DP_MON_DATA_BUFFER_SIZE, + 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_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; /* sanity check */ @@ -888,12 +984,12 @@ dp_tx_mon_generate_prot_frm(struct dp_pdev *pdev, if (qdf_unlikely(!mon_pdev_be)) return; - tx_cap_be = &mon_pdev_be->tx_capture_be; - tx_status_info = &tx_cap_be->prot_status_info; + tx_mon_be = &mon_pdev_be->tx_monitor_be; + tx_status_info = &tx_mon_be->prot_status_info; /* update medium prot type from data */ 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)) { 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_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; QDF_STATUS status = QDF_STATUS_SUCCESS; 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)) 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); 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 * @status_frag: pointer to fragment * @tlv_status: tlv status return from hal api + * @mon_desc_list_ref: tx monitor descriptor list reference * * 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, void *tx_tlv_hdr, 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_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; 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)) 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) { 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) * 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) == TXMON_RESP_CTS) 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 * multiple BlockAck info */ - tx_status_info = &tx_cap_be->data_status_info; - if (TXMON_STATUS_INFO(tx_status_info, transmission_type) == - TXMON_SU_TRANSMISSION) + tx_status_info = &tx_mon_be->data_status_info; + + if (TXMON_PPDU_HAL(tx_data_ppdu_info, num_users)) dp_tx_mon_generate_block_ack_frm(pdev, tx_data_ppdu_info); else @@ -1199,10 +1297,56 @@ dp_tx_mon_update_ppdu_info_status(struct dp_pdev *pdev, break; } case HAL_MON_TX_DATA: - case HAL_MON_TX_BUFFER_ADDR: { 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; } 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 * @pdev_handle: DP_PDEV handle + * @mon_desc_list_ref: tx monitor descriptor list reference * * 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_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_data_ppdu_info = NULL; struct hal_tx_status_info *tx_status_prot; struct hal_tx_status_info *tx_status_data; qdf_frag_t status_frag = NULL; + uint32_t end_offset = 0; uint8_t *tx_tlv; uint8_t *tx_tlv_start; uint32_t tlv_status; uint32_t status = QDF_STATUS_SUCCESS; uint8_t num_users = 0; uint8_t cur_frag_q_idx; - uint32_t end_offset = 0; + bool schedule_wrq = false; /* sanity check */ 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)) return QDF_STATUS_E_NOMEM; - tx_cap_be = &mon_pdev_be->tx_capture_be; - cur_frag_q_idx = tx_cap_be->cur_frag_q_idx; + tx_mon_be = &mon_pdev_be->tx_monitor_be; + cur_frag_q_idx = tx_mon_be->cur_frag_q_idx; - tx_status_prot = &tx_cap_be->prot_status_info; - tx_status_data = &tx_cap_be->data_status_info; + tx_status_prot = &tx_mon_be->prot_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, - 1, tx_cap_be->be_ppdu_id); + 1, tx_mon_be->be_ppdu_id); if (!tx_prot_ppdu_info) { dp_mon_info("tx prot ppdu info alloc got failed!!"); return QDF_STATUS_E_NOMEM; } - status_frag = tx_cap_be->frag_q_vec[cur_frag_q_idx].frag_buf; - end_offset = tx_cap_be->frag_q_vec[cur_frag_q_idx].end_offset; + status_frag = tx_mon_be->frag_q_vec[cur_frag_q_idx].frag_buf; + end_offset = tx_mon_be->frag_q_vec[cur_frag_q_idx].end_offset; tx_tlv = status_frag; 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 */ 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 */ tx_data_ppdu_info = dp_tx_mon_get_ppdu_info(pdev, TX_DATA_PPDU_INFO, num_users, - tx_cap_be->be_ppdu_id); + tx_mon_be->be_ppdu_id); if (!tx_data_ppdu_info) { dp_mon_info("tx prot ppdu info alloc got failed!!"); return QDF_STATUS_E_NOMEM; } /* 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) { /* get status buffer from frag_q_vec */ - status_frag = tx_cap_be->frag_q_vec[cur_frag_q_idx].frag_buf; - end_offset = tx_cap_be->frag_q_vec[cur_frag_q_idx].end_offset; + status_frag = tx_mon_be->frag_q_vec[cur_frag_q_idx].frag_buf; + end_offset = tx_mon_be->frag_q_vec[cur_frag_q_idx].end_offset; if (qdf_unlikely(!status_frag)) { dp_mon_err("status frag is NULL\n"); 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_tlv, status_frag, - tlv_status); + tlv_status, + mon_desc_list_ref); if (status != QDF_STATUS_SUCCESS) { dp_tx_mon_status_free_packet_buf(pdev, - status_frag, - end_offset); + status_frag, + end_offset, + mon_desc_list_ref); 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 */ qdf_frag_free(status_frag); - tx_cap_be->frag_q_vec[cur_frag_q_idx].frag_buf = NULL; - tx_cap_be->frag_q_vec[cur_frag_q_idx].end_offset = 0; - cur_frag_q_idx = ++tx_cap_be->cur_frag_q_idx; + tx_mon_be->frag_q_vec[cur_frag_q_idx].frag_buf = NULL; + tx_mon_be->frag_q_vec[cur_frag_q_idx].end_offset = 0; + cur_frag_q_idx = ++tx_mon_be->cur_frag_q_idx; } /* 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 (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 */ - qdf_spin_lock_bh(&tx_cap_be->tx_mon_list_lock); - tx_cap_be->last_prot_ppdu_info = - tx_cap_be->tx_prot_ppdu_info; - STAILQ_INSERT_TAIL(&tx_cap_be->tx_ppdu_info_queue, + qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock); + tx_mon_be->last_prot_ppdu_info = + tx_mon_be->tx_prot_ppdu_info; + STAILQ_INSERT_TAIL(&tx_mon_be->tx_ppdu_info_queue, tx_prot_ppdu_info, 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; - qdf_spin_unlock_bh(&tx_cap_be->tx_mon_list_lock); + tx_mon_be->tx_prot_ppdu_info = NULL; + qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock); + schedule_wrq = true; } else { - /* - * TODO : we can also save - * allocated buffer for future use - */ + dp_tx_mon_free_ppdu_info(tx_prot_ppdu_info, tx_mon_be); + tx_mon_be->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 */ - qdf_spin_lock_bh(&tx_cap_be->tx_mon_list_lock); - tx_cap_be->last_data_ppdu_info = - tx_cap_be->tx_data_ppdu_info; - STAILQ_INSERT_TAIL(&tx_cap_be->tx_ppdu_info_queue, + qdf_spin_lock_bh(&tx_mon_be->tx_mon_list_lock); + tx_mon_be->last_data_ppdu_info = + tx_mon_be->tx_data_ppdu_info; + STAILQ_INSERT_TAIL(&tx_mon_be->tx_ppdu_info_queue, tx_data_ppdu_info, 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; - qdf_spin_unlock_bh(&tx_cap_be->tx_mon_list_lock); + tx_mon_be->tx_data_ppdu_info = NULL; + qdf_spin_unlock_bh(&tx_mon_be->tx_mon_list_lock); + schedule_wrq = true; } else { - /* - * TODO : we can also save - * allocated buffer for future use - */ + dp_tx_mon_free_ppdu_info(tx_data_ppdu_info, tx_mon_be); + tx_mon_be->tx_data_ppdu_info = NULL; tx_data_ppdu_info = NULL; } - /* - * TODO: iterate status buffer queue and free - * need a wrapper function to free the status buffer - */ - qdf_queue_work(0, tx_cap_be->post_ppdu_workqueue, - &tx_cap_be->post_ppdu_work); + if (schedule_wrq) + qdf_queue_work(NULL, tx_mon_be->post_ppdu_workqueue, + &tx_mon_be->post_ppdu_work); 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) { 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); if (qdf_unlikely(!mon_pdev_be)) 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) - return; - - tx_cap_be->be_end_reason_bitmap |= (1 << end_reason); + tx_mon_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 * @addr - status buffer frag address * @end_offset - end offset of buffer that has valid buffer + * @mon_desc_list_ref: tx monitor descriptor list reference * * Return: QDF_STATUS */ -QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, - struct dp_pdev *pdev, - struct hal_mon_desc *mon_ring_desc, - qdf_frag_t status_frag, - uint32_t end_offset) +QDF_STATUS +dp_tx_mon_process_status_tlv(struct dp_soc *soc, + struct dp_pdev *pdev, + struct hal_mon_desc *mon_ring_desc, + 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_capture_be *tx_cap_be; + struct dp_pdev_tx_monitor_be *tx_mon_be; uint8_t last_frag_q_idx = 0; /* sanity check */ @@ -1522,63 +1667,72 @@ QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, if (qdf_unlikely(!mon_pdev_be)) 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)) { 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); - 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; } - if (tx_cap_be->mode == TX_MON_BE_DISABLE && - !dp_lite_mon_is_tx_enabled(mon_pdev)) + if (tx_mon_be->mode == TX_MON_BE_DISABLE && + !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; + } - if (tx_cap_be->be_ppdu_id != mon_ring_desc->ppdu_id && - tx_cap_be->last_frag_q_idx) { - if (tx_cap_be->be_end_reason_bitmap & + if (tx_mon_be->be_ppdu_id != mon_ring_desc->ppdu_id && + tx_mon_be->last_frag_q_idx) { + if (tx_mon_be->be_end_reason_bitmap & (1 << HAL_MON_FLUSH_DETECTED)) { - dp_tx_mon_status_queue_free(pdev, tx_cap_be); - } else if (tx_cap_be->be_end_reason_bitmap & + dp_tx_mon_status_queue_free(pdev, tx_mon_be, + mon_desc_list_ref); + } else if (tx_mon_be->be_end_reason_bitmap & (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 { 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, - tx_cap_be->last_frag_q_idx); + tx_mon_be->last_frag_q_idx); /* 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 */ - tx_cap_be->be_end_reason_bitmap = 0; - tx_cap_be->last_frag_q_idx = 0; - tx_cap_be->cur_frag_q_idx = 0; + tx_mon_be->be_end_reason_bitmap = 0; + tx_mon_be->last_frag_q_idx = 0; + tx_mon_be->cur_frag_q_idx = 0; } - tx_cap_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_ppdu_id = mon_ring_desc->ppdu_id; + 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_cap_be->frag_q_vec[last_frag_q_idx].end_offset = end_offset; - tx_cap_be->last_frag_q_idx++; + tx_mon_be->frag_q_vec[last_frag_q_idx].frag_buf = status_frag; + tx_mon_be->frag_q_vec[last_frag_q_idx].end_offset = end_offset; + tx_mon_be->last_frag_q_idx++; if (mon_ring_desc->end_reason == HAL_MON_END_OF_PPDU) { - if (dp_tx_mon_process_tlv_2_0(pdev) != QDF_STATUS_SUCCESS) - dp_tx_mon_status_queue_free(pdev, tx_cap_be); + if (dp_tx_mon_process_tlv_2_0(pdev, + 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; free_status_buffer: - hal_txmon_status_free_buffer(pdev->soc->hal_soc, - status_frag, end_offset); + dp_tx_mon_status_free_packet_buf(pdev, status_frag, end_offset, + mon_desc_list_ref); qdf_frag_free(status_frag); return QDF_STATUS_E_NOMEM; @@ -1595,17 +1749,38 @@ free_status_buffer: * @mon_ring_desc - descriptor status info * @addr - status buffer frag address * @end_offset - end offset of buffer that has valid buffer + * @mon_desc_list_ref: tx monitor descriptor list reference * * Return: QDF_STATUS */ -QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc, - struct dp_pdev *pdev, - struct hal_mon_desc *mon_ring_desc, - qdf_frag_t status_frag, - uint32_t end_offset) +QDF_STATUS +dp_tx_mon_process_status_tlv(struct dp_soc *soc, + struct dp_pdev *pdev, + struct hal_mon_desc *mon_ring_desc, + qdf_frag_t status_frag, + uint32_t end_offset, + struct dp_tx_mon_desc_list *mon_desc_list_ref) { - hal_txmon_status_free_buffer(pdev->soc->hal_soc, - status_frag, end_offset); + struct dp_mon_pdev *mon_pdev; + 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); return QDF_STATUS_E_INVAL; diff --git a/dp/wifi3.0/monitor/dp_mon.h b/dp/wifi3.0/monitor/dp_mon.h index 72049f3935..436c250528 100644 --- a/dp/wifi3.0/monitor/dp_mon.h +++ b/dp/wifi3.0/monitor/dp_mon.h @@ -57,6 +57,10 @@ #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_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 typedef struct dp_peer_extd_tx_stats dp_mon_peer_tx_stats; typedef struct dp_peer_extd_rx_stats dp_mon_peer_rx_stats; diff --git a/hal/wifi3.0/be/hal_be_api_mon.h b/hal/wifi3.0/be/hal_be_api_mon.h index f9f19076f7..5a657648ab 100644 --- a/hal/wifi3.0/be/hal_be_api_mon.h +++ b/hal/wifi3.0/be/hal_be_api_mon.h @@ -866,6 +866,7 @@ struct hal_tx_status_info { * @cur_usr_idx: Current user index of the PPDU * @reserved: for furture purpose * @prot_tlv_status: protection tlv status + * @packet_info: packet information * @rx_status: monitor mode rx 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; + /* placeholder to hold packet buffer info */ + struct hal_mon_packet_info packet_info; struct mon_rx_status rx_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); } -/** - * 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 * @tx_tlv_hdr: pointer to TLV header @@ -986,6 +970,45 @@ hal_tx_status_get_tlv_tag(void *tx_tlv_hdr) } #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 hal_rx_parse_u_sig_cmn(struct hal_soc *hal_soc, void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info) diff --git a/hal/wifi3.0/be/hal_be_generic_api.h b/hal/wifi3.0/be/hal_be_generic_api.h index 7bee6fd845..4c4fabf394 100644 --- a/hal/wifi3.0/be/hal_be_generic_api.h +++ b/hal/wifi3.0/be/hal_be_generic_api.h @@ -326,34 +326,43 @@ hal_rx_fst_get_fse_size_be(void) #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 - * @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 -hal_txmon_get_buffer_addr_generic_be(void *tx_tlv, - struct hal_mon_buf_addr_status *status) +static inline bool +hal_txmon_is_mon_buf_addr_tlv_generic_be(void *tx_tlv_hdr) { - struct mon_buffer_addr *hal_buffer_addr = - (struct mon_buffer_addr *)((uint8_t *)tx_tlv + - HAL_RX_TLV64_HDR_SIZE); - qdf_frag_t buf_addr = NULL; + uint32_t tlv_tag; - buf_addr = (qdf_frag_t)(uintptr_t)((hal_buffer_addr->buffer_virt_addr_31_0 | - ((unsigned long long)hal_buffer_addr->buffer_virt_addr_63_32 << - 32))); + tlv_tag = HAL_RX_GET_USER_TLV64_TYPE(tx_tlv_hdr); - /* qdf_frag_t is derived from buffer address tlv */ - if (qdf_unlikely(status)) { - 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 */ - } + if (WIFIMON_BUFFER_ADDR_E == tlv_tag) + return true; - 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) @@ -657,60 +666,6 @@ hal_txmon_status_get_num_users_generic_be(void *tx_tlv_hdr, uint8_t *num_users) 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 * @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_status_info *tx_status_info; + struct hal_mon_packet_info *packet_info = NULL; uint32_t tlv_tag, user_id, tlv_len; - qdf_frag_t frag_buf = NULL; uint32_t status = HAL_MON_TX_STATUS_PPDU_NOT_DONE; void *tx_tlv; @@ -1043,21 +998,15 @@ hal_txmon_status_parse_tlv_generic_be(void *data_ppdu_info, } 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; /* * TODO: do we need a conversion api to convert * user_id from hw to get host user_index */ TXMON_HAL(ppdu_info, cur_usr_idx) = user_id; - frag_buf = hal_txmon_get_buffer_addr_generic_be(tx_tlv, - &buf_status); - 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; + + hal_txmon_populate_packet_info_generic_be(tx_tlv, packet_info); SHOW_DEFINED(WIFIMON_BUFFER_ADDR_E); break; @@ -1591,10 +1540,9 @@ hal_txmon_status_parse_tlv_generic_be(void *data_ppdu_info, BA_TS_CTRL); /* memcpy ba bitmap */ qdf_mem_copy(TXMON_HAL_USER(ppdu_info, user_id, ba_bitmap), - tx_tlv + - HAL_TX_DESC_OFFSET_GET_64(tx_tlv, - RX_FRAME_1K_BITMAP_ACK, - BA_TS_BITMAP_31_0, 0), + &HAL_SET_FLD_OFFSET_64(tx_tlv, + RX_FRAME_1K_BITMAP_ACK, + BA_TS_BITMAP_31_0, 0), 4 << TXMON_HAL_USER(ppdu_info, user_id, ba_bitmap_sz)); diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 759e4bd60b..ee1846ae6b 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -1139,6 +1139,9 @@ struct hal_hw_txrx_ops { uint8_t (*hal_get_tlv_hdr_size)(void); 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 */ #ifdef QCA_MONITOR_2_0_SUPPORT 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); uint32_t (*hal_txmon_status_get_num_users)(void *tx_tlv_hdr, 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 */ 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); diff --git a/hal/wifi3.0/qcn9224/hal_9224.c b/hal/wifi3.0/qcn9224/hal_9224.c index d5b27a51b3..1c33d1130e 100644 --- a/hal/wifi3.0/qcn9224/hal_9224.c +++ b/hal/wifi3.0/qcn9224/hal_9224.c @@ -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; /* TX MONITOR */ #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_txmon_status_parse_tlv_generic_be; hal_soc->ops->hal_txmon_status_get_num_users = 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 */ hal_soc->ops->hal_compute_reo_remap_ix0 = NULL; hal_soc->ops->hal_tx_vdev_mismatch_routing_set =