diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index 8987785234..07545ffe63 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -1959,16 +1959,16 @@ void cdp_set_nac(ol_txrx_soc_handle soc, * @pdev: data path pdev handle * @val: value of pdev_tx_capture * - * Return: void + * Return: status: 0 - Success, non-zero: Failure */ static inline -void cdp_set_pdev_tx_capture(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, int val) +QDF_STATUS cdp_set_pdev_tx_capture(ol_txrx_soc_handle soc, + struct cdp_pdev *pdev, int val) { if (soc->ops->cmn_drv_ops->txrx_set_pdev_tx_capture) return soc->ops->cmn_drv_ops->txrx_set_pdev_tx_capture(pdev, val); - + return QDF_STATUS_SUCCESS; } /** diff --git a/dp/inc/cdp_txrx_ctrl.h b/dp/inc/cdp_txrx_ctrl.h index c1d53e8c2a..f2bade06b8 100644 --- a/dp/inc/cdp_txrx_ctrl.h +++ b/dp/inc/cdp_txrx_ctrl.h @@ -466,22 +466,32 @@ cdp_peer_set_nawds(ol_txrx_soc_handle soc, (peer, value); } -static inline void cdp_txrx_set_pdev_param(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, enum cdp_pdev_param_type type, - uint8_t val) +/** + * cdp_txrx_set_pdev_param() - set pdev parameter + * @soc: opaque soc handle + * @pdev: data path pdev handle + * @type: param type + * @val: value of pdev_tx_capture + * + * Return: status: 0 - Success, non-zero: Failure + */ +static inline QDF_STATUS cdp_txrx_set_pdev_param(ol_txrx_soc_handle soc, + struct cdp_pdev *pdev, + enum cdp_pdev_param_type type, + uint8_t val) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return; + return QDF_STATUS_SUCCESS; } if (!soc->ops->ctrl_ops || !soc->ops->ctrl_ops->txrx_set_pdev_param) - return; + return QDF_STATUS_SUCCESS; - soc->ops->ctrl_ops->txrx_set_pdev_param + return soc->ops->ctrl_ops->txrx_set_pdev_param (pdev, type, val); } diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 63e728299d..7da20eadc6 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -172,7 +172,15 @@ struct cdp_cmn_ops { void (*txrx_set_nac)(struct cdp_peer *peer); - void (*txrx_set_pdev_tx_capture)(struct cdp_pdev *pdev, int val); + /** + * txrx_set_pdev_tx_capture() - callback to set pdev tx_capture + * @soc: opaque soc handle + * @pdev: data path pdev handle + * @val: value of pdev_tx_capture + * + * Return: status: 0 - Success, non-zero: Failure + */ + QDF_STATUS (*txrx_set_pdev_tx_capture)(struct cdp_pdev *pdev, int val); void (*txrx_get_peer_mac_from_peer_id) (struct cdp_pdev *pdev_handle, @@ -601,8 +609,17 @@ struct cdp_ctrl_ops { void (*txrx_update_mgmt_txpow_vdev)(struct cdp_vdev *vdev, uint8_t subtype, uint8_t tx_power); - void (*txrx_set_pdev_param)(struct cdp_pdev *pdev, - enum cdp_pdev_param_type type, uint8_t val); + /** + * txrx_set_pdev_param() - callback to set pdev parameter + * @soc: opaque soc handle + * @pdev: data path pdev handle + * @val: value of pdev_tx_capture + * + * Return: status: 0 - Success, non-zero: Failure + */ + QDF_STATUS (*txrx_set_pdev_param)(struct cdp_pdev *pdev, + enum cdp_pdev_param_type type, + uint8_t val); void * (*txrx_get_pldev)(struct cdp_pdev *pdev); #ifdef ATH_SUPPORT_NAC_RSSI diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 4d6aeb2431..2eaec2811c 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -5380,6 +5380,7 @@ static QDF_STATUS dp_reset_monitor_mode(struct cdp_pdev *pdev_handle) } pdev->monitor_vdev = NULL; + pdev->mcopy_mode = 0; qdf_spin_unlock_bh(&pdev->mon_lock); @@ -5437,47 +5438,21 @@ static void dp_get_peer_mac_from_peer_id(struct cdp_pdev *pdev_handle, } /** - * dp_vdev_set_monitor_mode() - Set DP VDEV to monitor mode + * dp_pdev_configure_monitor_rings() - configure monitor rings * @vdev_handle: Datapath VDEV handle - * @smart_monitor: Flag to denote if its smart monitor mode * - * Return: 0 on success, not 0 on failure + * Return: void */ -static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_vdev *vdev_handle, - uint8_t smart_monitor) +static QDF_STATUS dp_pdev_configure_monitor_rings(struct dp_pdev *pdev) { - /* Many monitor VAPs can exists in a system but only one can be up at - * anytime - */ - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - struct dp_pdev *pdev; struct htt_rx_ring_tlv_filter htt_tlv_filter; struct dp_soc *soc; uint8_t pdev_id; int mac_id; QDF_STATUS status = QDF_STATUS_SUCCESS; - qdf_assert(vdev); - - pdev = vdev->pdev; pdev_id = pdev->pdev_id; soc = pdev->soc; - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, - "pdev=%pK, pdev_id=%d, soc=%pK vdev=%pK", - pdev, pdev_id, soc, vdev); - - /*Check if current pdev's monitor_vdev exists */ - if (pdev->monitor_vdev) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "vdev=%pK", vdev); - qdf_assert(vdev); - } - - pdev->monitor_vdev = vdev; - - /* If smart monitor mode, do not configure monitor ring */ - if (smart_monitor) - return QDF_STATUS_SUCCESS; QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, "MODE[%x] FP[%02x|%02x|%02x] MO[%02x|%02x|%02x]", @@ -5508,7 +5483,10 @@ static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_vdev *vdev_handle, (pdev->mon_filter_mode & MON_FILTER_OTHER) ? 1 : 0; htt_tlv_filter.fp_mgmt_filter = pdev->fp_mgmt_filter; htt_tlv_filter.fp_ctrl_filter = pdev->fp_ctrl_filter; - htt_tlv_filter.fp_data_filter = pdev->fp_data_filter; + if (pdev->mcopy_mode) + htt_tlv_filter.fp_data_filter = 0; + else + htt_tlv_filter.fp_data_filter = pdev->fp_data_filter; htt_tlv_filter.mo_mgmt_filter = pdev->mo_mgmt_filter; htt_tlv_filter.mo_ctrl_filter = pdev->mo_ctrl_filter; htt_tlv_filter.mo_data_filter = pdev->mo_data_filter; @@ -5561,7 +5539,44 @@ static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_vdev *vdev_handle, RXDMA_MONITOR_STATUS, RX_BUFFER_SIZE, &htt_tlv_filter); } - return QDF_STATUS_SUCCESS; + return status; +} + +/** + * dp_vdev_set_monitor_mode() - Set DP VDEV to monitor mode + * @vdev_handle: Datapath VDEV handle + * @smart_monitor: Flag to denote if its smart monitor mode + * + * Return: 0 on success, not 0 on failure + */ +static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_vdev *vdev_handle, + uint8_t smart_monitor) +{ + struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; + struct dp_pdev *pdev; + + qdf_assert(vdev); + + pdev = vdev->pdev; + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, + "pdev=%pK, pdev_id=%d, soc=%pK vdev=%pK\n", + pdev, pdev->pdev_id, pdev->soc, vdev); + + /*Check if current pdev's monitor_vdev exists */ + if (pdev->monitor_vdev || pdev->mcopy_mode) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "monitor vap already created vdev=%pK\n", vdev); + qdf_assert(vdev); + return QDF_STATUS_E_RESOURCES; + } + + pdev->monitor_vdev = vdev; + + /* If smart monitor mode, do not configure monitor ring */ + if (smart_monitor) + return QDF_STATUS_SUCCESS; + + return dp_pdev_configure_monitor_rings(pdev); } /** @@ -5654,7 +5669,10 @@ dp_pdev_set_advance_monitor_filter(struct cdp_pdev *pdev_handle, (pdev->mon_filter_mode & MON_FILTER_OTHER) ? 1 : 0; htt_tlv_filter.fp_mgmt_filter = pdev->fp_mgmt_filter; htt_tlv_filter.fp_ctrl_filter = pdev->fp_ctrl_filter; - htt_tlv_filter.fp_data_filter = pdev->fp_data_filter; + if (pdev->mcopy_mode) + htt_tlv_filter.fp_data_filter = 0; + else + htt_tlv_filter.fp_data_filter = pdev->fp_data_filter; htt_tlv_filter.mo_mgmt_filter = pdev->mo_mgmt_filter; htt_tlv_filter.mo_ctrl_filter = pdev->mo_ctrl_filter; htt_tlv_filter.mo_data_filter = pdev->mo_data_filter; @@ -7464,9 +7482,9 @@ static inline bool is_ppdu_txrx_capture_enabled(struct dp_pdev *pdev) *@pdev_handle: DP_PDEV handle. *@val: Provided value. * - *Return: void + *Return: 0 for success. nonzero for failure. */ -static void +static QDF_STATUS dp_set_bpr_enable(struct cdp_pdev *pdev_handle, int val) { struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; @@ -7507,6 +7525,8 @@ dp_set_bpr_enable(struct cdp_pdev *pdev_handle, int val) default: break; } + + return QDF_STATUS_SUCCESS; } /* @@ -7514,12 +7534,16 @@ dp_set_bpr_enable(struct cdp_pdev *pdev_handle, int val) * @pdev_handle: DP_PDEV handle * @val: user provided value * - * Return: void + * Return: 0 for success. nonzero for failure. */ -static void +static QDF_STATUS dp_config_debug_sniffer(struct cdp_pdev *pdev_handle, int val) { struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (pdev->mcopy_mode) + dp_reset_monitor_mode(pdev_handle); switch (val) { case 0: @@ -7553,9 +7577,14 @@ dp_config_debug_sniffer(struct cdp_pdev *pdev_handle, int val) DP_PPDU_STATS_CFG_SNIFFER, pdev->pdev_id); break; case 2: + if (pdev->monitor_vdev) { + status = QDF_STATUS_E_RESOURCES; + break; + } + pdev->mcopy_mode = 1; + dp_pdev_configure_monitor_rings(pdev); pdev->tx_sniffer_enable = 0; - dp_ppdu_ring_cfg(pdev); if (!pdev->pktlog_ppdu_stats) dp_h2t_cfg_stats_msg_send(pdev, @@ -7566,6 +7595,7 @@ dp_config_debug_sniffer(struct cdp_pdev *pdev_handle, int val) "Invalid value"); break; } + return status; } /* @@ -7709,25 +7739,25 @@ dp_get_htt_stats(struct cdp_pdev *pdev_handle, void *data, uint32_t data_len) * @param: parameter type to be set * @val: value of parameter to be set * - * return: void + * Return: 0 for success. nonzero for failure. */ -static void dp_set_pdev_param(struct cdp_pdev *pdev_handle, - enum cdp_pdev_param_type param, uint8_t val) +static QDF_STATUS dp_set_pdev_param(struct cdp_pdev *pdev_handle, + enum cdp_pdev_param_type param, + uint8_t val) { struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; switch (param) { case CDP_CONFIG_DEBUG_SNIFFER: - dp_config_debug_sniffer(pdev_handle, val); - break; + return dp_config_debug_sniffer(pdev_handle, val); case CDP_CONFIG_BPR_ENABLE: - dp_set_bpr_enable(pdev_handle, val); - break; + return dp_set_bpr_enable(pdev_handle, val); case CDP_CONFIG_PRIMARY_RADIO: pdev->is_primary = val; break; default: - break; + return QDF_STATUS_E_INVAL; } + return QDF_STATUS_SUCCESS; } /* diff --git a/dp/wifi3.0/dp_rx_mon_dest.c b/dp/wifi3.0/dp_rx_mon_dest.c index 028f892261..44d2b868aa 100644 --- a/dp/wifi3.0/dp_rx_mon_dest.c +++ b/dp/wifi3.0/dp_rx_mon_dest.c @@ -440,7 +440,6 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, + frag_len; qdf_nbuf_set_pktlen(msdu, rx_buf_size); - #if 0 /* Disble it.see packet on msdu done set to 0 */ /* @@ -814,6 +813,60 @@ mpdu_stitch_fail: return NULL; } +/** + * dp_send_mgmt_packet_to_stack(): send indicataion to upper layers + * + * @soc: soc handle + * @nbuf: Mgmt packet + * @pdev: pdev handle + * + * Return: QDF_STATUS_SUCCESS on success + * QDF_STATUS_E_INVAL in error + */ +#ifdef FEATURE_PERPKT_INFO +static inline QDF_STATUS dp_send_mgmt_packet_to_stack(struct dp_soc *soc, + qdf_nbuf_t nbuf, + struct dp_pdev *pdev) +{ + uint32_t *nbuf_data; + struct ieee80211_frame *wh; + + if (!nbuf) + return QDF_STATUS_E_INVAL; + + /*check if this is not a mgmt packet*/ + wh = (struct ieee80211_frame *)qdf_nbuf_data(nbuf); + if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != + IEEE80211_FC0_TYPE_MGT) && + ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != + IEEE80211_FC0_TYPE_CTL)) { + qdf_nbuf_free(nbuf); + return QDF_STATUS_E_INVAL; + } + nbuf_data = (uint32_t *)qdf_nbuf_push_head(nbuf, 4); + if (!nbuf_data) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("No headroom")); + qdf_nbuf_free(nbuf); + return QDF_STATUS_E_INVAL; + } + *nbuf_data = pdev->ppdu_info.com_info.ppdu_id; + + dp_wdi_event_handler(WDI_EVENT_RX_MGMT_CTRL, soc, nbuf, + HTT_INVALID_PEER, + WDI_NO_VAL, pdev->pdev_id); + return QDF_STATUS_SUCCESS; +} +#else +static inline QDF_STATUS dp_send_mgmt_packet_to_stack(struct dp_soc *soc, + qdf_nbuf_t nbuf, + struct dp_pdev *pdev) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * dp_rx_extract_radiotap_info(): Extract and populate information in * struct mon_rx_status type @@ -842,6 +895,15 @@ void dp_rx_extract_radiotap_info(struct cdp_mon_status *rx_status, /* TODO: rx_mon_status->vht_flag_values1 */ } +/* + * dp_rx_mon_deliver(): function to deliver packets to stack + * @soc: DP soc + * @mac_id: MAC ID + * @head_msdu: head of msdu list + * @tail_msdu: tail of msdu list + * + * Return: status: 0 - Success, non-zero: Failure + */ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, qdf_nbuf_t head_msdu, qdf_nbuf_t tail_msdu) { @@ -850,16 +912,21 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, qdf_nbuf_t mon_skb, skb_next; qdf_nbuf_t mon_mpdu = NULL; - if ((pdev->monitor_vdev == NULL) || - (pdev->monitor_vdev->osif_rx_mon == NULL)) { + if (!pdev->monitor_vdev && !pdev->mcopy_mode) goto mon_deliver_fail; - } /* restitch mon MPDU for delivery via monitor interface */ mon_mpdu = dp_rx_mon_restitch_mpdu_from_msdus(soc, mac_id, head_msdu, tail_msdu, rs); - if (mon_mpdu && pdev->monitor_vdev && pdev->monitor_vdev->osif_vdev) { + /* monitor vap cannot be present when mcopy is enabled + * hence same skb can be consumed + */ + if (pdev->mcopy_mode) + return dp_send_mgmt_packet_to_stack(soc, mon_mpdu, pdev); + + if (mon_mpdu && pdev->monitor_vdev && pdev->monitor_vdev->osif_vdev && + pdev->monitor_vdev->osif_rx_mon) { pdev->ppdu_info.rx_status.ppdu_id = pdev->ppdu_info.com_info.ppdu_id; pdev->ppdu_info.rx_status.device_id = soc->device_id; @@ -872,9 +939,10 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, pdev->monitor_vdev->osif_vdev, mon_mpdu, NULL); } else { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "[%s][%d] mon_mpdu=%pK pdev->monitor_vdev %pK osif_vdev %pK", - __func__, __LINE__, mon_mpdu, pdev->monitor_vdev, - pdev->monitor_vdev->osif_vdev); + "[%s][%d] mon_mpdu=%pK monitor_vdev %pK osif_vdev %pK" + , __func__, __LINE__, mon_mpdu, pdev->monitor_vdev, + (pdev->monitor_vdev ? pdev->monitor_vdev->osif_vdev + : NULL)); goto mon_deliver_fail; } diff --git a/dp/wifi3.0/dp_rx_mon_status.c b/dp/wifi3.0/dp_rx_mon_status.c index 10d1bfc39d..680d55f568 100644 --- a/dp/wifi3.0/dp_rx_mon_status.c +++ b/dp/wifi3.0/dp_rx_mon_status.c @@ -271,6 +271,8 @@ dp_rx_handle_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, struct hal_rx_ppdu_info *ppdu_info, qdf_nbuf_t nbuf) { uint8_t size = 0; + struct ieee80211_frame *wh; + uint32_t *nbuf_data; if (ppdu_info->msdu_info.first_msdu_payload == NULL) return QDF_STATUS_SUCCESS; @@ -280,14 +282,24 @@ dp_rx_handle_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, pdev->m_copy_id.rx_ppdu_id = ppdu_info->com_info.ppdu_id; - /* Include 2 bytes of reserved space appended to the msdu payload */ + wh = (struct ieee80211_frame *)(ppdu_info->msdu_info.first_msdu_payload + + 4); size = (ppdu_info->msdu_info.first_msdu_payload - - qdf_nbuf_data(nbuf)) + 2; + qdf_nbuf_data(nbuf)); ppdu_info->msdu_info.first_msdu_payload = NULL; if (qdf_nbuf_pull_head(nbuf, size) == NULL) return QDF_STATUS_SUCCESS; + if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == + IEEE80211_FC0_TYPE_MGT) || + ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == + IEEE80211_FC0_TYPE_CTL)) { + return QDF_STATUS_SUCCESS; + } + + nbuf_data = (uint32_t *)qdf_nbuf_data(nbuf); + *nbuf_data = pdev->ppdu_info.com_info.ppdu_id; /* only retain RX MSDU payload in the skb */ qdf_nbuf_trim_tail(nbuf, qdf_nbuf_len(nbuf) - ppdu_info->msdu_info.payload_len);