diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index 3fc8d89427dc..620513343129 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -2730,4 +2730,33 @@ cdp_drain_txrx(ol_txrx_soc_handle soc) return soc->ops->cmn_drv_ops->txrx_drain(soc); } + +#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 +/** + * cdp_set_pkt_capture_mode() - set pkt capture mode in dp ctx + * @soc: opaque soc handle + * @val: value to be set + */ +static inline void +cdp_set_pkt_capture_mode(ol_txrx_soc_handle soc, bool val) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->set_pkt_capture_mode) + return; + + soc->ops->cmn_drv_ops->set_pkt_capture_mode(soc, val); +} +#else +static inline void +cdp_set_pkt_capture_mode(ol_txrx_soc_handle soc, bool val) +{ +} +#endif #endif /* _CDP_TXRX_CMN_H_ */ diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 93789956bb51..921876d0a690 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -578,6 +578,9 @@ struct cdp_cmn_ops { ol_osif_peer_handle osif_peer); #endif /* QCA_SUPPORT_WDS_EXTENDED */ void (*txrx_drain)(ol_txrx_soc_handle soc); +#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 + void (*set_pkt_capture_mode)(struct cdp_soc_t *soc, bool val); +#endif }; struct cdp_ctrl_ops { diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index 11c5ec3aa0ba..de4ed05f0882 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/dp/inc/cdp_txrx_stats_struct.h @@ -1024,6 +1024,8 @@ struct cdp_tx_stats { uint32_t num_ppdu_cookie_valid; uint32_t no_ack_count[QDF_PROTO_SUBTYPE_MAX]; struct cdp_pkt_info tx_success_twt; + /* mpdu retry count in case of successful transmission */ + uint32_t mpdu_success_with_retries; }; /* struct cdp_rx_stats - rx Level Stats diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 22da8713a5cf..13e4a851611c 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -871,6 +871,8 @@ static inline void dp_update_vdev_stats(struct dp_soc *soc, tgtobj->tx.dropped.fw_reason3 += srcobj->stats.tx.dropped.fw_reason3; tgtobj->tx.dropped.age_out += srcobj->stats.tx.dropped.age_out; + tgtobj->tx.mpdu_success_with_retries += + srcobj->stats.tx.mpdu_success_with_retries; tgtobj->rx.err.mic_err += srcobj->stats.rx.err.mic_err; if (srcobj->stats.rx.rssi != 0) tgtobj->rx.rssi = srcobj->stats.rx.rssi; diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index c1615ed0da86..b9f1537f81dc 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -10495,27 +10495,27 @@ static void dp_display_srng_info(struct cdp_soc_t *soc_hdl) dp_info("SRNG HP-TP data:"); for (i = 0; i < soc->num_tcl_data_rings; i++) { hal_get_sw_hptp(hal_soc, soc->tcl_data_ring[i].hal_srng, - &hp, &tp); + &tp, &hp); dp_info("TCL DATA ring[%d]: hp=0x%x, tp=0x%x", i, hp, tp); hal_get_sw_hptp(hal_soc, soc->tx_comp_ring[i].hal_srng, - &hp, &tp); + &tp, &hp); dp_info("TX comp ring[%d]: hp=0x%x, tp=0x%x", i, hp, tp); } for (i = 0; i < soc->num_reo_dest_rings; i++) { hal_get_sw_hptp(hal_soc, soc->reo_dest_ring[i].hal_srng, - &hp, &tp); + &tp, &hp); dp_info("REO DST ring[%d]: hp=0x%x, tp=0x%x", i, hp, tp); } - hal_get_sw_hptp(hal_soc, soc->reo_exception_ring.hal_srng, &hp, &tp); + hal_get_sw_hptp(hal_soc, soc->reo_exception_ring.hal_srng, &tp, &hp); dp_info("REO exception ring: hp=0x%x, tp=0x%x", hp, tp); - hal_get_sw_hptp(hal_soc, soc->rx_rel_ring.hal_srng, &hp, &tp); + hal_get_sw_hptp(hal_soc, soc->rx_rel_ring.hal_srng, &tp, &hp); dp_info("WBM RX release ring: hp=0x%x, tp=0x%x", hp, tp); - hal_get_sw_hptp(hal_soc, soc->wbm_desc_rel_ring.hal_srng, &hp, &tp); + hal_get_sw_hptp(hal_soc, soc->wbm_desc_rel_ring.hal_srng, &tp, &hp); dp_info("WBM desc release ring: hp=0x%x, tp=0x%x", hp, tp); } @@ -11294,6 +11294,16 @@ static void dp_drain_txrx(struct cdp_soc_t *soc_handle) } #endif +#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 +static void +dp_set_pkt_capture_mode(struct cdp_soc_t *soc_handle, bool val) +{ + struct dp_soc *soc = (struct dp_soc *)soc_handle; + + soc->wlan_cfg_ctx->pkt_capture_mode = val; +} +#endif + static struct cdp_cmn_ops dp_ops_cmn = { .txrx_soc_attach_target = dp_soc_attach_target_wifi3, .txrx_vdev_attach = dp_vdev_attach_wifi3, @@ -11396,6 +11406,9 @@ static struct cdp_cmn_ops dp_ops_cmn = { #if defined(FEATURE_RUNTIME_PM) || defined(DP_POWER_SAVE) .txrx_drain = dp_drain_txrx, #endif +#ifdef WLAN_FEATURE_PKT_CAPTURE_V2 + .set_pkt_capture_mode = dp_set_pkt_capture_mode, +#endif }; static struct cdp_ctrl_ops dp_ops_ctrl = { diff --git a/dp/wifi3.0/dp_rx_mon_dest.c b/dp/wifi3.0/dp_rx_mon_dest.c index 7e0eea1062cc..2816a59fbb1d 100644 --- a/dp/wifi3.0/dp_rx_mon_dest.c +++ b/dp/wifi3.0/dp_rx_mon_dest.c @@ -1411,27 +1411,6 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu(struct dp_soc *soc, uint32_t mac_id, } #endif -#ifdef DP_MON_RSSI_IN_DBM -/* - * dp_rx_mon_rssi_convert(): convert rssi_comb from unit dBm to dB - * to match with radiotap further conversion requirement - * @rx_status: monitor mode rx status pointer - * - * Return: none - */ -static inline -void dp_rx_mon_rssi_convert(struct mon_rx_status *rx_status) -{ - rx_status->rssi_comb = rx_status->rssi_comb - - rx_status->chan_noise_floor; -} -#else -static inline -void dp_rx_mon_rssi_convert(struct mon_rx_status *rx_status) -{ -} -#endif - /* * dp_rx_mon_deliver(): function to deliver packets to stack * @soc: DP soc @@ -1469,8 +1448,6 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, pdev->ppdu_info.rx_status.device_id = soc->device_id; pdev->ppdu_info.rx_status.chan_noise_floor = pdev->chan_noise_floor; - /* convert rssi_comb from dBm to positive dB value */ - dp_rx_mon_rssi_convert(&pdev->ppdu_info.rx_status); dp_handle_tx_capture(soc, pdev, mon_mpdu); diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index e54928cb66ca..1848fa50f48d 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -58,6 +58,8 @@ /* invalid peer id for reinject*/ #define DP_INVALID_PEER 0XFFFE +#define DP_RETRY_COUNT 7 + /*mapping between hal encrypt type and cdp_sec_type*/ #define MAX_CDP_SEC_TYPE 12 static const uint8_t sec_type_map[MAX_CDP_SEC_TYPE] = { @@ -4113,12 +4115,15 @@ dp_tx_update_peer_stats(struct dp_tx_desc_s *tx_desc, DP_STATS_INCC(peer, tx.stbc, 1, ts->stbc); DP_STATS_INCC(peer, tx.ldpc, 1, ts->ldpc); DP_STATS_INCC(peer, tx.retries, 1, ts->transmit_cnt > 1); - #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, pdev->soc, &peer->stats, ts->peer_id, UPDATE_PEER_STATS, pdev->pdev_id); #endif + if (ts->first_msdu) + DP_STATS_INCC(peer, tx.mpdu_success_with_retries, + qdf_do_div(ts->transmit_cnt, DP_RETRY_COUNT), + ts->transmit_cnt > DP_RETRY_COUNT); } #ifdef QCA_LL_TX_FLOW_CONTROL_V2 diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 5910bd795b12..a07ffc269803 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -455,8 +455,7 @@ static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc, { qdf_iowrite32(addr, value); } -#elif defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#elif defined(FEATURE_HAL_DELAYED_REG_WRITE) static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc, struct hal_srng *srng, void __iomem *addr, @@ -778,8 +777,7 @@ static inline void hal_write32_mb_confirm_retry(struct hal_soc *hal_soc, } #endif /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */ -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * hal_dump_reg_write_srng_stats() - dump SRNG reg write stats * @hal_soc: HAL soc handle diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index a8857c89c96e..e1aec3aa0d18 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -25,8 +25,7 @@ #include "qdf_mem.h" #include "qdf_nbuf.h" #include "pld_common.h" -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) #include "qdf_defer.h" #include "qdf_timer.h" #endif @@ -259,8 +258,7 @@ typedef struct hal_ring_handle *hal_ring_handle_t; */ #define HAL_SRNG_FLUSH_EVENT BIT(0) -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * struct hal_reg_write_q_elem - delayed register write queue element @@ -339,21 +337,6 @@ struct hal_reg_write_soc_stats { uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX]; uint32_t dequeue_delay; }; - -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -struct hal_reg_write_tcl_stats { - uint32_t wq_delayed; - uint32_t wq_direct; - uint32_t timer_enq; - uint32_t timer_direct; - uint32_t enq_timer_set; - uint32_t direct_timer_set; - uint32_t timer_reset; - qdf_time_t enq_time; - qdf_time_t deq_time; - uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX]; -}; -#endif #endif /* Common SRNG ring structure for source and destination rings */ @@ -476,10 +459,7 @@ struct hal_srng { /* last ring desc entry cleared */ uint32_t last_desc_cleared; #endif -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) - /* Previous hp/tp (based on ring dir) value written to the reg */ - uint32_t last_reg_wr_val; +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /* flag to indicate whether srng is already queued for delayed write */ uint8_t reg_write_in_progress; /* last dequeue elem time stamp */ @@ -718,8 +698,7 @@ struct hal_hw_txrx_ops { */ struct hal_soc_stats { uint32_t reg_write_fail; -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) struct hal_reg_write_soc_stats wstats; #endif #ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE @@ -835,20 +814,6 @@ struct hal_soc { /* read index used by worker thread to dequeue/write registers */ uint32_t read_idx; #endif /*FEATURE_HAL_DELAYED_REG_WRITE */ -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 - /* delayed work for TCL reg write to be queued into workqueue */ - qdf_work_t tcl_reg_write_work; - /* workqueue for TCL delayed register writes */ - qdf_workqueue_t *tcl_reg_write_wq; - /* flag denotes whether TCL delayed write work is active */ - qdf_atomic_t tcl_work_active; - /* flag indiactes TCL write happening from direct context */ - bool tcl_direct; - /* timer to handle the pending TCL reg writes */ - qdf_timer_t tcl_reg_write_timer; - /* stats related to TCL reg write */ - struct hal_reg_write_tcl_stats tcl_stats; -#endif /* FEATURE_HAL_DELAYED_REG_WRITE_V2 */ qdf_atomic_t active_work_cnt; #ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE struct shadow_reg_config @@ -857,8 +822,7 @@ struct hal_soc { #endif }; -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * hal_delayed_reg_write() - delayed regiter write * @hal_soc: HAL soc handle diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index 0f76e4a5ff7e..4a55cbb70cb8 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -446,8 +446,7 @@ uint32_t hal_get_target_type(hal_soc_handle_t hal_soc_hdl) qdf_export_symbol(hal_get_target_type); -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) || \ - defined(FEATURE_HAL_DELAYED_REG_WRITE_V2) +#if defined(FEATURE_HAL_DELAYED_REG_WRITE) /** * hal_is_reg_write_tput_level_high() - throughput level for delayed reg writes * @hal: hal_soc pointer @@ -501,41 +500,6 @@ void hal_dump_reg_write_srng_stats(hal_soc_handle_t hal_soc_hdl) hal_fill_reg_write_srng_stats(srng, buf, sizeof(buf))); } -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -/** - * hal_dump_tcl_stats() - dump the TCL reg write stats - * @hal: hal_soc pointer - * - * Return: None - */ -static inline void hal_dump_tcl_stats(struct hal_soc *hal) -{ - struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1); - uint32_t *hist = hal->tcl_stats.sched_delay; - char buf[HAL_REG_WRITE_SRNG_STATS_LEN]; - - hal_debug("TCL: %s sched-delay hist %u %u %u %u", - hal_fill_reg_write_srng_stats(srng, buf, sizeof(buf)), - hist[REG_WRITE_SCHED_DELAY_SUB_100us], - hist[REG_WRITE_SCHED_DELAY_SUB_1000us], - hist[REG_WRITE_SCHED_DELAY_SUB_5000us], - hist[REG_WRITE_SCHED_DELAY_GT_5000us]); - hal_debug("wq_dly %u wq_dir %u tim_enq %u tim_dir %u enq_tim_cnt %u dir_tim_cnt %u rst_tim_cnt %u", - hal->tcl_stats.wq_delayed, - hal->tcl_stats.wq_direct, - hal->tcl_stats.timer_enq, - hal->tcl_stats.timer_direct, - hal->tcl_stats.enq_timer_set, - hal->tcl_stats.direct_timer_set, - hal->tcl_stats.timer_reset); -} - -#else -static inline void hal_dump_tcl_stats(struct hal_soc *hal) -{ -} -#endif - void hal_dump_reg_write_stats(hal_soc_handle_t hal_soc_hdl) { uint32_t *hist; @@ -553,8 +517,6 @@ void hal_dump_reg_write_stats(hal_soc_handle_t hal_soc_hdl) hist[REG_WRITE_SCHED_DELAY_SUB_1000us], hist[REG_WRITE_SCHED_DELAY_SUB_5000us], hist[REG_WRITE_SCHED_DELAY_GT_5000us]); - - hal_dump_tcl_stats(hal); } int hal_get_reg_write_pending_work(void *hal_soc) @@ -577,46 +539,6 @@ int hal_get_reg_write_pending_work(void *hal_soc) #define HAL_REG_WRITE_QUEUE_LEN 32 #endif -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -/** - * hal_process_reg_write_q_elem() - process a regiter write queue element - * @hal: hal_soc pointer - * @q_elem: pointer to hal regiter write queue element - * - * Return: The value which was written to the address - */ -static uint32_t -hal_process_reg_write_q_elem(struct hal_soc *hal, - struct hal_reg_write_q_elem *q_elem) -{ - struct hal_srng *srng = q_elem->srng; - uint32_t write_val; - - SRNG_LOCK(&srng->lock); - srng->reg_write_in_progress = false; - srng->wstats.dequeues++; - - if (srng->ring_dir == HAL_SRNG_SRC_RING) { - write_val = srng->u.src_ring.hp; - q_elem->dequeue_val = write_val; - q_elem->valid = 0; - SRNG_UNLOCK(&srng->lock); - hal_write_address_32_mb(hal, - srng->u.src_ring.hp_addr, - write_val, false); - } else { - write_val = srng->u.dst_ring.tp; - q_elem->dequeue_val = write_val; - q_elem->valid = 0; - SRNG_UNLOCK(&srng->lock); - hal_write_address_32_mb(hal, - srng->u.dst_ring.tp_addr, - write_val, false); - } - - return write_val; -} -#else /** * hal_process_reg_write_q_elem() - process a regiter write queue element * @hal: hal_soc pointer @@ -656,7 +578,6 @@ hal_process_reg_write_q_elem(struct hal_soc *hal, return write_val; } -#endif /** * hal_reg_write_fill_sched_delay_hist() - fill reg write delay histogram in hal @@ -818,8 +739,8 @@ static void hal_reg_write_work(void *arg) static void __hal_flush_reg_write_work(struct hal_soc *hal) { - qdf_cancel_work(&hal->reg_write_work); - + qdf_flush_work(&hal->reg_write_work); + qdf_disable_work(&hal->reg_write_work); } void hal_flush_reg_write_work(hal_soc_handle_t hal_handle) @@ -962,383 +883,6 @@ static inline void hal_delayed_reg_write_deinit(struct hal_soc *hal) } #endif -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -#ifdef MEMORY_DEBUG -/** - * hal_reg_write_get_timestamp() - Function to get the timestamp - * - * Return: return present simestamp - */ -static inline qdf_time_t hal_del_reg_write_get_ts(void) -{ - return qdf_get_log_timestamp(); -} - -/** - * hal_del_reg_write_ts_usecs() - Convert the timestamp to micro secs - * @ts: timestamp value to be converted - * - * Return: return the timestamp in micro secs - */ -static inline qdf_time_t hal_del_reg_write_ts_usecs(qdf_time_t ts) -{ - return qdf_log_timestamp_to_usecs(ts); -} - -/** - * hal_tcl_write_fill_sched_delay_hist() - fill TCL reg write delay histogram - * @hal: hal_soc pointer - * @delay: delay in us - * - * Return: None - */ -static inline void hal_tcl_write_fill_sched_delay_hist(struct hal_soc *hal) -{ - uint32_t *hist; - uint32_t delay_us; - - hal->tcl_stats.deq_time = hal_del_reg_write_get_ts(); - delay_us = hal_del_reg_write_ts_usecs(hal->tcl_stats.deq_time - - hal->tcl_stats.enq_time); - - hist = hal->tcl_stats.sched_delay; - if (delay_us < 100) - hist[REG_WRITE_SCHED_DELAY_SUB_100us]++; - else if (delay_us < 1000) - hist[REG_WRITE_SCHED_DELAY_SUB_1000us]++; - else if (delay_us < 5000) - hist[REG_WRITE_SCHED_DELAY_SUB_5000us]++; - else - hist[REG_WRITE_SCHED_DELAY_GT_5000us]++; -} - -#else -static inline qdf_time_t hal_del_reg_write_get_ts(void) -{ - return 0; -} - -static inline qdf_time_t hal_del_reg_write_ts_usecs(qdf_time_t ts) -{ - return 0; -} - -static inline void hal_tcl_write_fill_sched_delay_hist(struct hal_soc *hal) -{ -} -#endif - -/** - * hal_tcl_reg_write_work() - Worker to process delayed SW2TCL1 writes - * @arg: hal_soc pointer - * - * Return: None - */ -static void hal_tcl_reg_write_work(void *arg) -{ - struct hal_soc *hal = arg; - struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1); - - SRNG_LOCK(&srng->lock); - srng->wstats.dequeues++; - hal_tcl_write_fill_sched_delay_hist(hal); - - /* - * During the tranition of low to high tput scenario, reg write moves - * from delayed to direct write context, there is a little chance that - * worker thread gets scheduled later than direct context write which - * already wrote the latest HP value. This check can catch that case - * and avoid the repetitive writing of the same HP value. - */ - if (srng->last_reg_wr_val != srng->u.src_ring.hp) { - srng->last_reg_wr_val = srng->u.src_ring.hp; - if (hal->tcl_direct) { - /* - * TCL reg writes have been moved to direct context and - * the assumption is that PCIe bus stays in Active state - * during high tput, hence its fine to write the HP - * while the SRNG_LOCK is being held. - */ - hal->tcl_stats.wq_direct++; - hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr, - srng->last_reg_wr_val, false); - srng->reg_write_in_progress = false; - SRNG_UNLOCK(&srng->lock); - } else { - /* - * TCL reg write to happen in delayed context, - * write operation might take time due to possibility of - * PCIe bus stays in low power state during low tput, - * Hence release the SRNG_LOCK before writing. - */ - hal->tcl_stats.wq_delayed++; - srng->reg_write_in_progress = false; - SRNG_UNLOCK(&srng->lock); - hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr, - srng->last_reg_wr_val, false); - } - } else { - srng->reg_write_in_progress = false; - SRNG_UNLOCK(&srng->lock); - } - - /* - * Decrement active_work_cnt to make sure that hif_try_complete_tasks - * will wait. This will avoid race condition between delayed register - * worker and bus suspend (system suspend or runtime suspend). - * - * The following decrement should be done at the end! - */ - qdf_atomic_dec(&hal->active_work_cnt); - qdf_atomic_set(&hal->tcl_work_active, false); -} - -static void __hal_flush_tcl_reg_write_work(struct hal_soc *hal) -{ - qdf_cancel_work(&hal->tcl_reg_write_work); -} - -/** - * hal_tcl_reg_write_enqueue() - enqueue TCL register writes into kworker - * @hal_soc: hal_soc pointer - * @srng: srng pointer - * @addr: iomem address of regiter - * @value: value to be written to iomem address - * - * This function executes from within the SRNG LOCK - * - * Return: None - */ -static void hal_tcl_reg_write_enqueue(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - hal_soc->tcl_stats.enq_time = hal_del_reg_write_get_ts(); - - if (qdf_queue_work(hal_soc->qdf_dev, hal_soc->tcl_reg_write_wq, - &hal_soc->tcl_reg_write_work)) { - srng->reg_write_in_progress = true; - qdf_atomic_inc(&hal_soc->active_work_cnt); - qdf_atomic_set(&hal_soc->tcl_work_active, true); - srng->wstats.enqueues++; - } else { - hal_soc->tcl_stats.enq_timer_set++; - qdf_timer_mod(&hal_soc->tcl_reg_write_timer, 1); - } -} - -/** - * hal_tcl_reg_write_timer() - timer handler to take care of pending TCL writes - * @arg: srng handle - * - * This function handles the pending TCL reg writes missed due to the previous - * scheduled worker running. - * - * Return: None - */ -static void hal_tcl_reg_write_timer(void *arg) -{ - hal_ring_handle_t srng_hdl = arg; - struct hal_srng *srng; - struct hal_soc *hal; - - srng = (struct hal_srng *)srng_hdl; - hal = srng->hal_soc; - - if (hif_pm_runtime_get(hal->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE, - true)) { - hal_srng_set_event(srng_hdl, HAL_SRNG_FLUSH_EVENT); - hal_srng_inc_flush_cnt(srng_hdl); - goto fail; - } - - SRNG_LOCK(&srng->lock); - if (hal->tcl_direct) { - /* - * Due to the previous scheduled worker still running, - * direct reg write cannot be performed, so posted the - * pending writes to timer context. - */ - if (srng->last_reg_wr_val != srng->u.src_ring.hp) { - srng->last_reg_wr_val = srng->u.src_ring.hp; - srng->wstats.direct++; - hal->tcl_stats.timer_direct++; - hal_write_address_32_mb(hal, srng->u.src_ring.hp_addr, - srng->last_reg_wr_val, false); - } - } else { - /* - * Due to the previous scheduled worker still running, - * queue_work from delayed context would fail, - * so retry from timer context. - */ - if (qdf_queue_work(hal->qdf_dev, hal->tcl_reg_write_wq, - &hal->tcl_reg_write_work)) { - srng->reg_write_in_progress = true; - qdf_atomic_inc(&hal->active_work_cnt); - qdf_atomic_set(&hal->tcl_work_active, true); - srng->wstats.enqueues++; - hal->tcl_stats.timer_enq++; - } else { - if (srng->last_reg_wr_val != srng->u.src_ring.hp) { - hal->tcl_stats.timer_reset++; - qdf_timer_mod(&hal->tcl_reg_write_timer, 1); - } - } - } - SRNG_UNLOCK(&srng->lock); - hif_pm_runtime_put(hal->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE); - -fail: - return; -} - -/** - * hal_delayed_tcl_reg_write_init() - Initialization for delayed TCL reg writes - * @hal_soc: hal_soc pointer - * - * Initialize main data structures to process TCL register writes in a delayed - * workqueue. - * - * Return: QDF_STATUS_SUCCESS on success else a QDF error. - */ -static QDF_STATUS hal_delayed_tcl_reg_write_init(struct hal_soc *hal) -{ - struct hal_srng *srng = hal_get_srng(hal, HAL_SRNG_SW2TCL1); - QDF_STATUS status; - - hal->tcl_reg_write_wq = - qdf_alloc_high_prior_ordered_workqueue("hal_tcl_reg_write_wq"); - if (!hal->tcl_reg_write_wq) { - hal_err("hal_tcl_reg_write_wq alloc failed"); - return QDF_STATUS_E_NOMEM; - } - - status = qdf_create_work(0, &hal->tcl_reg_write_work, - hal_tcl_reg_write_work, hal); - if (status != QDF_STATUS_SUCCESS) { - hal_err("tcl_reg_write_work create failed"); - goto fail; - } - - status = qdf_timer_init(hal->qdf_dev, &hal->tcl_reg_write_timer, - hal_tcl_reg_write_timer, (void *)srng, - QDF_TIMER_TYPE_WAKE_APPS); - if (status != QDF_STATUS_SUCCESS) { - hal_err("tcl_reg_write_timer init failed"); - goto fail; - } - - qdf_atomic_init(&hal->tcl_work_active); - - return QDF_STATUS_SUCCESS; - -fail: - qdf_destroy_workqueue(0, hal->tcl_reg_write_wq); - return status; -} - -/** - * hal_delayed_tcl_reg_write_deinit() - De-Initialize delayed TCL reg writes - * @hal_soc: hal_soc pointer - * - * De-initialize main data structures to process TCL register writes in a - * delayed workqueue. - * - * Return: None - */ -static void hal_delayed_tcl_reg_write_deinit(struct hal_soc *hal) -{ - qdf_timer_stop(&hal->tcl_reg_write_timer); - qdf_timer_free(&hal->tcl_reg_write_timer); - - __hal_flush_tcl_reg_write_work(hal); - qdf_flush_workqueue(0, hal->tcl_reg_write_wq); - qdf_destroy_workqueue(0, hal->tcl_reg_write_wq); -} - -#else -static inline QDF_STATUS hal_delayed_tcl_reg_write_init(struct hal_soc *hal) -{ - return QDF_STATUS_SUCCESS; -} - -static inline void hal_delayed_tcl_reg_write_deinit(struct hal_soc *hal) -{ -} -#endif - -#ifdef FEATURE_HAL_DELAYED_REG_WRITE_V2 -#ifdef FEATURE_HAL_DELAYED_REG_WRITE -static inline void hal_reg_write_enqueue_v2(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - hal_reg_write_enqueue(hal_soc, srng, addr, value); -} -#else -static inline void hal_reg_write_enqueue_v2(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - qdf_atomic_inc(&hal_soc->stats.wstats.direct); - srng->wstats.direct++; - hal_write_address_32_mb(hal_soc, addr, value, false); -} -#endif -void hal_delayed_reg_write(struct hal_soc *hal_soc, - struct hal_srng *srng, - void __iomem *addr, - uint32_t value) -{ - switch (srng->ring_type) { - case TCL_DATA: - if (hal_is_reg_write_tput_level_high(hal_soc)) { - hal_soc->tcl_direct = true; - if (srng->reg_write_in_progress || - !qdf_atomic_read(&hal_soc->tcl_work_active)) { - /* - * Now the delayed work have either completed - * the writing or not even scheduled and would - * be blocked by SRNG_LOCK, hence it is fine to - * do direct write here. - */ - srng->last_reg_wr_val = srng->u.src_ring.hp; - srng->wstats.direct++; - hal_write_address_32_mb(hal_soc, addr, - srng->last_reg_wr_val, - false); - } else { - hal_soc->tcl_stats.direct_timer_set++; - qdf_timer_mod(&hal_soc->tcl_reg_write_timer, 1); - } - } else { - hal_soc->tcl_direct = false; - if (srng->reg_write_in_progress) { - srng->wstats.coalesces++; - } else { - hal_tcl_reg_write_enqueue(hal_soc, srng, - addr, value); - } - } - break; - case CE_SRC: - case CE_DST: - case CE_DST_STATUS: - hal_reg_write_enqueue_v2(hal_soc, srng, addr, value); - break; - default: - qdf_atomic_inc(&hal_soc->stats.wstats.direct); - srng->wstats.direct++; - hal_write_address_32_mb(hal_soc, addr, value, false); - break; - } -} - -#else #ifdef FEATURE_HAL_DELAYED_REG_WRITE #ifdef QCA_WIFI_QCA6750 void hal_delayed_reg_write(struct hal_soc *hal_soc, @@ -1398,7 +942,6 @@ void hal_delayed_reg_write(struct hal_soc *hal_soc, } #endif #endif -#endif /** * hal_attach - Initialize HAL layer @@ -1470,7 +1013,6 @@ void *hal_attach(struct hif_opaque_softc *hif_handle, qdf_device_t qdf_dev) qdf_atomic_init(&hal->active_work_cnt); hal_delayed_reg_write_init(hal); - hal_delayed_tcl_reg_write_init(hal); return (void *)hal; @@ -1521,7 +1063,6 @@ extern void hal_detach(void *hal_soc) struct hal_soc *hal = (struct hal_soc *)hal_soc; hal_delayed_reg_write_deinit(hal); - hal_delayed_tcl_reg_write_deinit(hal); qdf_mem_free_consistent(hal->qdf_dev, hal->qdf_dev->dev, sizeof(*(hal->shadow_rdptr_mem_vaddr)) * HAL_SRNG_ID_MAX, diff --git a/hal/wifi3.0/qca6490/hal_6490.c b/hal/wifi3.0/qca6490/hal_6490.c index b8f9766ddef5..00d2a7a2f34b 100644 --- a/hal/wifi3.0/qca6490/hal_6490.c +++ b/hal/wifi3.0/qca6490/hal_6490.c @@ -2073,7 +2073,11 @@ struct hal_hw_srng_config hw_srng_table_6490[] = { }, { /* WBM2SW_RELEASE */ .start_ring_id = HAL_SRNG_WBM2SW0_RELEASE, +#ifdef CONFIG_PLD_PCIE_FW_SIM + .max_rings = 5, +#else .max_rings = 4, +#endif .entry_size = sizeof(struct wbm_release_ring) >> 2, .lmac_ring = FALSE, .ring_dir = HAL_SRNG_DST_RING, diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 3ffa9a28f0b1..9786f4aa6d4e 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -327,6 +327,8 @@ struct hif_opaque_softc { * @HIF_EVENT_BH_SCHED: NAPI POLL scheduled event * @HIF_EVENT_SRNG_ACCESS_START: hal ring access start event * @HIF_EVENT_SRNG_ACCESS_END: hal ring access end event + * @HIF_EVENT_BH_COMPLETE: NAPI POLL completion event + * @HIF_EVENT_BH_FORCE_BREAK: NAPI POLL force break event */ enum hif_event_type { HIF_EVENT_IRQ_TRIGGER, @@ -335,6 +337,8 @@ enum hif_event_type { HIF_EVENT_BH_SCHED, HIF_EVENT_SRNG_ACCESS_START, HIF_EVENT_SRNG_ACCESS_END, + HIF_EVENT_BH_COMPLETE, + HIF_EVENT_BH_FORCE_BREAK, /* Do check hif_hist_skip_event_record when adding new events */ }; @@ -360,7 +364,7 @@ enum hif_system_pm_state { /* HIF_EVENT_HIST_MAX should always be power of 2 */ #define HIF_EVENT_HIST_MAX 512 #define HIF_NUM_INT_CONTEXTS HIF_MAX_GROUP -#define HIF_EVENT_HIST_ENABLE_MASK 0x3F +#define HIF_EVENT_HIST_ENABLE_MASK 0xFF static inline uint64_t hif_get_log_timestamp(void) { diff --git a/hif/src/hif_exec.c b/hif/src/hif_exec.c index 62a44bc7958a..76a4e0a9382e 100644 --- a/hif/src/hif_exec.c +++ b/hif/src/hif_exec.c @@ -96,7 +96,7 @@ hif_hist_skip_event_record(struct hif_event_history *hist_ev, HIF_EVENT_HIST_MAX)) { last_irq_rec = &hist_ev->event[hist_ev->misc.last_irq_index]; - last_irq_rec->timestamp = qdf_get_log_timestamp(); + last_irq_rec->timestamp = hif_get_log_timestamp(); last_irq_rec->cpu_id = qdf_get_cpu(); last_irq_rec->hp++; last_irq_rec->tp = last_irq_rec->timestamp - @@ -106,7 +106,7 @@ hif_hist_skip_event_record(struct hif_event_history *hist_ev, break; case HIF_EVENT_BH_SCHED: if (rec->type == HIF_EVENT_BH_SCHED) { - rec->timestamp = qdf_get_log_timestamp(); + rec->timestamp = hif_get_log_timestamp(); rec->cpu_id = qdf_get_cpu(); return true; } @@ -119,6 +119,11 @@ hif_hist_skip_event_record(struct hif_event_history *hist_ev, if (rec->type != HIF_EVENT_SRNG_ACCESS_START) return true; break; + case HIF_EVENT_BH_COMPLETE: + case HIF_EVENT_BH_FORCE_BREAK: + if (rec->type != HIF_EVENT_SRNG_ACCESS_END) + return true; + break; default: break; } @@ -623,6 +628,8 @@ static int hif_exec_poll(struct napi_struct *napi, int budget) actual_dones = work_done; if (!hif_ext_group->force_break && work_done < normalized_budget) { + hif_record_event(hif_ext_group->hif, hif_ext_group->grp_id, + 0, 0, 0, HIF_EVENT_BH_COMPLETE); napi_complete(napi); qdf_atomic_dec(&scn->active_grp_tasklet_cnt); hif_ext_group->irq_enable(hif_ext_group); @@ -630,6 +637,8 @@ static int hif_exec_poll(struct napi_struct *napi, int budget) } else { /* if the ext_group supports time based yield, claim full work * done anyways */ + hif_record_event(hif_ext_group->hif, hif_ext_group->grp_id, + 0, 0, 0, HIF_EVENT_BH_FORCE_BREAK); work_done = normalized_budget; } diff --git a/os_if/linux/qca_vendor.h b/os_if/linux/qca_vendor.h index d3b91124e082..97309a331915 100644 --- a/os_if/linux/qca_vendor.h +++ b/os_if/linux/qca_vendor.h @@ -475,6 +475,36 @@ * configurations, concurrency combinations, etc. The attributes used * with this command are defined in * enum qca_wlan_vendor_attr_usable_channels. + * + * @QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE: This vendor subcommand is used + * to set packet monitor mode that aims to send the specified set of TX and + * RX frames on the current client interface to an active monitor interface. + * If this Monitor mode is set, the driver will send the configured frames, + * from the interface on which the command is issued, to an active monitor + * interface. The attributes used with this command are defined in + * enum qca_wlan_vendor_attr_set_monitor_mode. + * + * Though the monitor mode is configured for the respective data/mgmt/ctrl + * frames, it is up to the respective WLAN driver/firmware/hardware designs + * to consider the possibility of sending these frames over the monitor + * interface. For example, the control frames are handled with in the + * hardware and thus passing such frames over the monitor interface is left + * to the respective designs. + * + * Also, this monitor mode is governed to behave accordingly in + * suspend/resume states. If the firmware handles any of such frames + * in suspend state without waking up the host and if the monitor mode + * is configured to notify all such frames, then the firmware is expected + * to resume the host and forward the respective frames to the monitor + * interface. Please note that such a request to get the frames over the + * monitor interface will have a definite power implications. + * + * @QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS: This vendor subcommand is used both + * as a request to set the driver/firmware with the parameters to trigger + * the roaming events, and also used by the driver/firmware to pass on the + * various roam events to userspace. + * Applicable only for the STA mode. The attributes used with this command + * are defined in enum qca_wlan_vendor_attr_roam_events. */ enum qca_nl80211_vendor_subcmds { @@ -708,6 +738,8 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS = 196, QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY = 197, QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS = 198, + QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE = 202, + QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS = 203, }; enum qca_wlan_vendor_tos { @@ -11014,4 +11046,270 @@ enum qca_wlan_vendor_attr_usable_channels { QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST - 1, }; +/** + * qca_wlan_vendor_monitor_data_frame_type - Represent the various + * data types to be sent over the monitor interface. + */ +enum qca_wlan_vendor_monitor_data_frame_type { + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL = BIT(0), + + /* valid only if QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL is + not set */ + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ARP = BIT(1), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV4 = BIT(2), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV6 = BIT(3), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_EAPOL = BIT(4), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV4 = BIT(5), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV6 = BIT(6), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYN = BIT(7), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYNACK = BIT(8), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FIN = BIT(9), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FINACK = BIT(10), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_ACK = BIT(11), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_RST = BIT(12), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV4 = BIT(13), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV6 = BIT(14), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_RTP = BIT(15), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_SIP = BIT(16), + QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_QOS_NULL = BIT(17), +}; + +/** + * qca_wlan_vendor_monitor_mgmt_frame_type - Represent the various + * mgmt types to be sent over the monitor interface. + * @QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL: All the MGMT Frames. + * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_NO_BEACON: All the MGMT Frames + * except the Beacons. Valid only in the Connect state. + * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON: Only the connected + * BSSID Beacons. Valid only in the Connect state. + * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON: Represents + * the Beacons obtained during the scan (off channel and connected channel) + * when in connected state. + */ + +enum qca_wlan_vendor_monitor_mgmt_frame_type { + QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL = BIT(0), + /* valid only if QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL is not set */ + QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_NO_BEACON = BIT(1), + QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON = BIT(2), + QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON = BIT(3), +}; + +/** + * qca_wlan_vendor_monitor_ctrl_frame_type - Represent the various + * ctrl types to be sent over the monitor interface. + * @QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL: All the ctrl Frames. + * @QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME: Trigger Frame. + */ +enum qca_wlan_vendor_monitor_ctrl_frame_type { + QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL = BIT(0), + /* valid only if QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL is not set */ + QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME = BIT(1), +}; + +/** + * enum qca_wlan_vendor_attr_set_monitor_mode - Used by the + * vendor command QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE to set the + * monitor mode. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These data packets + * are represented by enum qca_wlan_vendor_monitor_data_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These data packets + * are represented by enum qca_wlan_vendor_monitor_data_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These mgmt packets + * are represented by enum qca_wlan_vendor_monitor_mgmt_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These mgmt packets + * are represented by enum qca_wlan_vendor_monitor_mgmt_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These ctrl packets + * are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE: u32 attribute, + * Represents the tx data packet type to be monitored (u32). These ctrl packets + * are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type. + * + * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL: + * u32 attribute, An interval only for the connected beacon interval, which + * expects that the connected BSSID's beacons shall be sent on the monitor + * interface only on this specific interval. + */ +enum qca_wlan_vendor_attr_set_monitor_mode { + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE = 1, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE = 2, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE = 3, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE = 4, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE = 5, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE = 6, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL = 7, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX = + QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST - 1, + +}; + +/** + * enum qca_wlan_vendor_roam_scan_state - Roam scan state flags. + * Bits will be set to 1 if the corresponding state is enabled. + * + * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_START: Scan Start. + * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_END: Scan end. + */ +enum qca_wlan_vendor_roam_scan_state { + QCA_WLAN_VENDOR_ROAM_SCAN_STATE_START = BIT(0), + QCA_WLAN_VENDOR_ROAM_SCAN_STATE_END = BIT(1), +}; + +/** + * enum qca_wlan_vendor_roam_event_type - Roam event type flags. + * Bits will be set to 1 if the corresponding event is notified. + * + * @QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON: Represents that the roam event + * carries the trigger reason. When set, it is expected that the roam event + * carries the respective reason via the attribute + * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON. This event also carries + * the BSSID, RSSI, frequency info of the AP to which the roam is attempted. + * + * @QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON: Represents that the roam event + * carries the roam fail reason. When set, it is expected that the roam event + * carries the respective reason via the attribute + * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_FAIL_REASON. This event also carries the + * BSSID, RSSI, frequency info of the AP to which the roam was attempted. + * + * @QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON: Represents that the roam + * event carries the roam invoke fail reason. When set, it is expected that + * the roam event carries the respective reason via the attribute + * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON. + * + * @QCA_WLAN_VENDOR_ROAM_EVENT_SCAN_STATE: Represents that the roam event + * carries the roam scan state. When set, it is expected that the roam event + * carries the respective scan state via the attribute + * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE and the corresponding + * frequency info via QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST. + */ +enum qca_wlan_vendor_roam_event_type { + QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON = BIT(0), + QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON = BIT(1), + QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON = BIT(2), + QCA_WLAN_VENDOR_ROAM_EVENT_ROAM_SCAN_STATE = BIT(3), +}; + +/** + * enum qca_wlan_vendor_attr_roam_events_candidate_info: Roam candidate info. + * Referred by QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID: 6-byte MAC address + * representing the BSSID of the AP to which the Roam is attempted. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI: Signed 32-bit value + * in dBm, signifying the RSSI of the candidate BSSID to which the Roaming is + * attempted. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ: u32, Frequency in MHz + * on which the roam is attempted. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON: u32, used in + * STA mode only. This represents the roam fail reason for the last failed + * roaming attempt by the firmware for the specific BSSID. Different roam + * failure reason codes are specified in enum qca_vendor_roam_fail_reasons. + */ +enum qca_wlan_vendor_attr_roam_events_candidate_info { + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID = 1, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI = 2, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ = 3, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON = 4, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_MAX = + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_roam_events - Used by the + * vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS to either configure the + * roam events to the driver or notify these events from the driver. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE: u8 attribute. Configures the + * driver/firmware to enable/disable the notification of roam events. It's a + * mandatory attribute and used only in the request from the userspace to the + * host driver. 1-Enable, 0-Disable. + * If the roaming is totally offloaded to the firmware, this request when + * enabled shall mandate the firmware to notify all the relevant roam events + * represented by the below attributes. If the host is in the suspend mode, + * the behavior of the firmware to notify these events is guided by + * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_DEVICE_STATE, and if the request is to get + * these events in the suspend state, the firmware is expected to wake up the + * host before the respective events are notified. Please note that such a + * request to get the events in the suspend state will have a definite power + * implication. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE: flag attribute. Represents + * that the roam events need to be notified in the suspend state too. By + * default, these roam events are notified in the resume state. With this flag, + * the roam events are notified in both resume and suspend states. + * This attribute is used in the request from the userspace to the host driver. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE: u32, used in STA mode only. + * Represents the different roam event types, signified by the enum + * qca_wlan_vendor_roam_event_type. + * Each bit of this attribute represents the different roam even types reported + * through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON: u32, used in STA + * mode only. This represents the roam trigger reason for the last roaming + * attempted by the firmware. Each bit of this attribute represents the + * different roam trigger reason code which are defined in enum + * qca_vendor_roam_triggers. + * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON: u32, used in + * STA mode only. This represents the roam invoke fail reason for the last + * failed roam invoke. Different roam invoke failure reason codes + * are specified in enum qca_vendor_roam_invoke_fail_reasons. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO: Array of candidates info + * for which the roam is attempted. Each entry is a nested attribute defined + * by enum qca_wlan_vendor_attr_roam_events_candidate_info. + * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE: u8 attribute. Represents + * the scan state on which the roam events need to be notified. The values for + * this attribute are referred from enum qca_wlan_vendor_roam_scan_state. + * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + * + * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST: Nested attribute of + * u32 values. List of frequencies in MHz considered for a roam scan. + * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. + */ + +enum qca_wlan_vendor_attr_roam_events { + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE = 1, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE = 2, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE = 3, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON = 4, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON = 5, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO = 6, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE = 7, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST = 8, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX = + QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST - 1, +}; + #endif diff --git a/os_if/linux/wlan_cfg80211.h b/os_if/linux/wlan_cfg80211.h index 2769d7288650..ea022611eb04 100644 --- a/os_if/linux/wlan_cfg80211.h +++ b/os_if/linux/wlan_cfg80211.h @@ -238,6 +238,9 @@ enum qca_nl80211_vendor_subcmds_index { #ifdef WLAN_CFR_ENABLE QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG_INDEX, #endif +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS_INDEX, +#endif }; #if !defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC) && \ diff --git a/qdf/inc/qdf_event.h b/qdf/inc/qdf_event.h index 27de4c79369c..04e09434f243 100644 --- a/qdf/inc/qdf_event.h +++ b/qdf/inc/qdf_event.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2018, 2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -41,8 +41,36 @@ typedef __qdf_event_t qdf_event_t; QDF_STATUS qdf_event_create(qdf_event_t *event); +/** + * qdf_event_set() - sets a QDF event for single waiting threads + * @event: The event to set to the signalled state + * + * The state of the specified event is set to signalled by calling + * qdf_event_set(). + * + * Single thread waiting on the event as a result of a qdf_event_wait() will + * be unblocked and available to be scheduled for execution when the event + * is signaled by a call to qdf_event_set(). + * + * Return: QDF status + */ QDF_STATUS qdf_event_set(qdf_event_t *event); +/** + * qdf_event_set_all() - sets a QDF event for all waiting threads + * @event: The event to set to the signalled state + * + * The state of the specified event is set to signalled by calling + * qdf_event_set_all(). + * + * Any threads waiting on the event as a result of a qdf_event_wait() will + * be unblocked and available to be scheduled for execution when the event + * is signaled by a call to qdf_event_set(). + * + * Return: QDF status + */ +QDF_STATUS qdf_event_set_all(qdf_event_t *event); + QDF_STATUS qdf_event_reset(qdf_event_t *event); QDF_STATUS qdf_event_destroy(qdf_event_t *event); diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index 05a67bb7b67e..9f2c7871bcf6 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/qdf/inc/qdf_nbuf.h @@ -2952,6 +2952,32 @@ bool qdf_nbuf_data_is_dns_response(qdf_nbuf_t buf) return __qdf_nbuf_data_is_dns_response(qdf_nbuf_data(buf)); } +/** + * qdf_nbuf_data_is_tcp_fin() - check if skb data is a tcp fin + * @buf: buffer + * + * Return: true if packet is tcp fin packet. + * false otherwise. + */ +static inline +bool qdf_nbuf_data_is_tcp_fin(qdf_nbuf_t buf) +{ + return __qdf_nbuf_data_is_tcp_fin(qdf_nbuf_data(buf)); +} + +/** + * qdf_nbuf_data_is_tcp_fin_ack() - check if skb data is a tcp fin ack + * @buf: buffer + * + * Return: true if packet is tcp fin ack packet. + * false otherwise. + */ +static inline +bool qdf_nbuf_data_is_tcp_fin_ack(qdf_nbuf_t buf) +{ + return __qdf_nbuf_data_is_tcp_fin_ack(qdf_nbuf_data(buf)); +} + /** * qdf_nbuf_data_is_tcp_syn() - check if skb data is a tcp syn * @buf: buffer @@ -2978,6 +3004,19 @@ bool qdf_nbuf_data_is_tcp_syn_ack(qdf_nbuf_t buf) return __qdf_nbuf_data_is_tcp_syn_ack(qdf_nbuf_data(buf)); } +/** + * qdf_nbuf_data_is_tcp_rst() - check if skb data is a tcp rst + * @buf: buffer + * + * Return: true if packet is tcp rst packet. + * false otherwise. + */ +static inline +bool qdf_nbuf_data_is_tcp_rst(qdf_nbuf_t buf) +{ + return __qdf_nbuf_data_is_tcp_rst(qdf_nbuf_data(buf)); +} + /** * qdf_nbuf_data_is_tcp_ack() - check if skb data is a tcp ack * @buf: buffer diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index cc049e2a8690..0471fcc41ce9 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/qdf/linux/src/i_qdf_nbuf.h @@ -73,6 +73,11 @@ typedef struct sk_buff_head __qdf_nbuf_queue_head_t; /* mark the first packet after wow wakeup */ #define QDF_MARK_FIRST_WAKEUP_PACKET 0x80000000 +/* TCP Related MASK */ +#define QDF_NBUF_PKT_TCPOP_FIN 0x01 +#define QDF_NBUF_PKT_TCPOP_FIN_ACK 0x11 +#define QDF_NBUF_PKT_TCPOP_RST 0x04 + /* * Make sure that qdf_dma_addr_t in the cb block is always 64 bit aligned */ @@ -836,8 +841,11 @@ uint32_t __qdf_nbuf_get_arp_tgt_ip(uint8_t *data); uint8_t *__qdf_nbuf_get_dns_domain_name(uint8_t *data, uint32_t len); bool __qdf_nbuf_data_is_dns_query(uint8_t *data); bool __qdf_nbuf_data_is_dns_response(uint8_t *data); +bool __qdf_nbuf_data_is_tcp_fin(uint8_t *data); +bool __qdf_nbuf_data_is_tcp_fin_ack(uint8_t *data); bool __qdf_nbuf_data_is_tcp_syn(uint8_t *data); bool __qdf_nbuf_data_is_tcp_syn_ack(uint8_t *data); +bool __qdf_nbuf_data_is_tcp_rst(uint8_t *data); bool __qdf_nbuf_data_is_tcp_ack(uint8_t *data); uint16_t __qdf_nbuf_data_get_tcp_src_port(uint8_t *data); uint16_t __qdf_nbuf_data_get_tcp_dst_port(uint8_t *data); diff --git a/qdf/linux/src/qdf_event.c b/qdf/linux/src/qdf_event.c index 3fcaae820464..b77556ddf74c 100644 --- a/qdf/linux/src/qdf_event.c +++ b/qdf/linux/src/qdf_event.c @@ -77,19 +77,6 @@ QDF_STATUS qdf_event_create(qdf_event_t *event) } qdf_export_symbol(qdf_event_create); -/** - * qdf_event_set() - sets a QDF event - * @event: The event to set to the signalled state - * - * The state of the specified event is set to signalled by calling - * qdf_event_set(). - * - * Any threads waiting on the event as a result of a qdf_event_wait() will - * be unblocked and available to be scheduled for execution when the event - * is signaled by a call to qdf_event_set(). - * - * Return: QDF status - */ QDF_STATUS qdf_event_set(qdf_event_t *event) { QDF_BUG(event); @@ -106,8 +93,28 @@ QDF_STATUS qdf_event_set(qdf_event_t *event) return QDF_STATUS_SUCCESS; } + qdf_export_symbol(qdf_event_set); +QDF_STATUS qdf_event_set_all(qdf_event_t *event) +{ + QDF_BUG(event); + if (!event) + return QDF_STATUS_E_FAULT; + + /* ensure event is initialized */ + QDF_BUG(event->cookie == LINUX_EVENT_COOKIE); + if (event->cookie != LINUX_EVENT_COOKIE) + return QDF_STATUS_E_INVAL; + + event->done = true; + complete_all(&event->complete); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(qdf_event_set_all); + /** * qdf_event_reset() - resets a QDF event * @event: The event to set to the NOT signalled state diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index f7963e010eb7..9340d33d774c 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/qdf/linux/src/qdf_nbuf.c @@ -1725,6 +1725,50 @@ bool __qdf_nbuf_data_is_dns_response(uint8_t *data) return false; } +/** + * __qdf_nbuf_data_is_tcp_fin() - check if skb data is a tcp fin + * @data: Pointer to network data buffer + * + * This api is to check if the packet is tcp fin. + * + * Return: true if packet is tcp fin packet. + * false otherwise. + */ +bool __qdf_nbuf_data_is_tcp_fin(uint8_t *data) +{ + uint8_t op_code; + + op_code = (uint8_t)(*(uint8_t *)(data + + QDF_NBUF_PKT_TCP_OPCODE_OFFSET)); + + if (op_code == QDF_NBUF_PKT_TCPOP_FIN) + return true; + + return false; +} + +/** + * __qdf_nbuf_data_is_tcp_fin_ack() - check if skb data is a tcp fin ack + * @data: Pointer to network data buffer + * + * This api is to check if the tcp packet is fin ack. + * + * Return: true if packet is tcp fin ack packet. + * false otherwise. + */ +bool __qdf_nbuf_data_is_tcp_fin_ack(uint8_t *data) +{ + uint8_t op_code; + + op_code = (uint8_t)(*(uint8_t *)(data + + QDF_NBUF_PKT_TCP_OPCODE_OFFSET)); + + if (op_code == QDF_NBUF_PKT_TCPOP_FIN_ACK) + return true; + + return false; +} + /** * __qdf_nbuf_data_is_tcp_syn() - check if skb data is a tcp syn * @data: Pointer to network data buffer @@ -1767,6 +1811,28 @@ bool __qdf_nbuf_data_is_tcp_syn_ack(uint8_t *data) return false; } +/** + * __qdf_nbuf_data_is_tcp_rst() - check if skb data is a tcp rst + * @data: Pointer to network data buffer + * + * This api is to check if the tcp packet is rst. + * + * Return: true if packet is tcp rst packet. + * false otherwise. + */ +bool __qdf_nbuf_data_is_tcp_rst(uint8_t *data) +{ + uint8_t op_code; + + op_code = (uint8_t)(*(uint8_t *)(data + + QDF_NBUF_PKT_TCP_OPCODE_OFFSET)); + + if (op_code == QDF_NBUF_PKT_TCPOP_RST) + return true; + + return false; +} + /** * __qdf_nbuf_data_is_tcp_ack() - check if skb data is a tcp ack * @data: Pointer to network data buffer @@ -4438,6 +4504,14 @@ static unsigned int qdf_nbuf_update_radiotap_ampdu_flags( return rtap_len; } +#ifdef DP_MON_RSSI_IN_DBM +#define QDF_MON_STATUS_GET_RSSI_IN_DBM(rx_status) \ +(rx_status->rssi_comb) +#else +#define QDF_MON_STATUS_GET_RSSI_IN_DBM(rx_status) \ +(rx_status->rssi_comb + rx_status->chan_noise_floor) +#endif + /** * qdf_nbuf_update_radiotap() - Update radiotap header from rx_status * @rx_status: Pointer to rx_status. @@ -4513,7 +4587,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status, * rssi_comb is int dB, need to convert it to dBm. * normalize value to noise floor of -96 dBm */ - rtap_buf[rtap_len] = rx_status->rssi_comb + rx_status->chan_noise_floor; + rtap_buf[rtap_len] = QDF_MON_STATUS_GET_RSSI_IN_DBM(rx_status); rtap_len += 1; /* RX signal noise floor */ diff --git a/target_if/spectral/target_if_spectral.h b/target_if/spectral/target_if_spectral.h index 1ff8609ee436..3add3240564c 100644 --- a/target_if/spectral/target_if_spectral.h +++ b/target_if/spectral/target_if_spectral.h @@ -1732,6 +1732,10 @@ void target_if_spectral_process_phyerr( } p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + if (!p_sops->spectral_process_phyerr) { + spectral_err("null spectral_process_phyerr"); + return; + } p_sops->spectral_process_phyerr(spectral, data, datalen, p_rfqual, p_chaninfo, tsf64, acs_stats); diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c index fd847dbe18b9..72649ff046a2 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -370,7 +370,8 @@ QDF_STATUS wlan_crypto_set_pmksa(struct wlan_crypto_params *crypto_params, return QDF_STATUS_E_INVAL; } crypto_params->pmksa[first_available_slot] = pmksa; - crypto_debug("PMKSA: Added the PMKSA entry at index=%d", i); + crypto_debug("PMKSA: Added the PMKSA entry at index=%d", + first_available_slot); return QDF_STATUS_SUCCESS; } @@ -379,7 +380,7 @@ static QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params, struct wlan_crypto_pmksa *pmksa) { - uint8_t i, j; + uint8_t i, j, valid_entries_in_table = 0; bool match_found = false; u8 del_pmk[MAX_PMK_LEN] = {0}; @@ -387,7 +388,12 @@ QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params, for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) { if (!crypto_params->pmksa[i]) continue; - if (qdf_is_macaddr_equal(&pmksa->bssid, + + valid_entries_in_table++; + + if (!pmksa->ssid_len && + !qdf_is_macaddr_zero(&pmksa->bssid) && + qdf_is_macaddr_equal(&pmksa->bssid, &crypto_params->pmksa[i]->bssid)) { match_found = true; } else if (pmksa->ssid_len && @@ -435,7 +441,8 @@ QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params, } if (i == WLAN_CRYPTO_MAX_PMKID && !match_found) - crypto_debug("No such pmksa entry exists"); + crypto_debug("No such pmksa entry exists: valid entries:%d", + valid_entries_in_table); return QDF_STATUS_SUCCESS; } @@ -453,6 +460,8 @@ QDF_STATUS wlan_crypto_pmksa_flush(struct wlan_crypto_params *crypto_params) crypto_params->pmksa[i] = NULL; } + crypto_debug("Flushed the pmksa table"); + return QDF_STATUS_SUCCESS; } @@ -607,16 +616,19 @@ wlan_crypto_get_peer_pmksa(struct wlan_objmgr_vdev *vdev, for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) { if (!crypto_params->pmksa[i]) continue; - if (qdf_is_macaddr_equal(&pmksa->bssid, - &crypto_params->pmksa[i]->bssid)) { + + if (pmksa->ssid_len && + !qdf_mem_cmp(pmksa->ssid, + crypto_params->pmksa[i]->ssid, + pmksa->ssid_len) && + !qdf_mem_cmp(pmksa->cache_id, + crypto_params->pmksa[i]->cache_id, + WLAN_CACHE_ID_LEN)) { return crypto_params->pmksa[i]; - } else if (pmksa->ssid_len && - !qdf_mem_cmp(pmksa->ssid, - crypto_params->pmksa[i]->ssid, - pmksa->ssid_len) && - !qdf_mem_cmp(pmksa->cache_id, - crypto_params->pmksa[i]->cache_id, - WLAN_CACHE_ID_LEN)){ + } else if (!pmksa->ssid_len && + !qdf_is_macaddr_zero(&pmksa->bssid) && + qdf_is_macaddr_equal(&pmksa->bssid, + &crypto_params->pmksa[i]->bssid)) { return crypto_params->pmksa[i]; } } diff --git a/umac/regulatory/core/src/reg_callbacks.c b/umac/regulatory/core/src/reg_callbacks.c index ed253021d077..62b0a069024e 100644 --- a/umac/regulatory/core/src/reg_callbacks.c +++ b/umac/regulatory/core/src/reg_callbacks.c @@ -37,9 +37,13 @@ * change. * @psoc: Pointer to global psoc structure. * @pdev: Pointer to global pdev structure. + * @ch_avoid_ind: if chan avoid indicated + * @avoid_info: chan avoid info if @ch_avoid_ind is true */ static void reg_call_chan_change_cbks(struct wlan_objmgr_psoc *psoc, - struct wlan_objmgr_pdev *pdev) + struct wlan_objmgr_pdev *pdev, + bool ch_avoid_ind, + struct avoid_freq_ind_data *avoid_info) { struct chan_change_cbk_entry *cbk_list; struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; @@ -70,21 +74,9 @@ static void reg_call_chan_change_cbks(struct wlan_objmgr_psoc *psoc, NUM_CHANNELS * sizeof(struct regulatory_channel)); - if (psoc_priv_obj->ch_avoid_ind) { - avoid_freq_ind = qdf_mem_malloc(sizeof(*avoid_freq_ind)); - if (!avoid_freq_ind) - goto skip_ch_avoid_ind; + if (ch_avoid_ind) + avoid_freq_ind = avoid_info; - qdf_mem_copy(&avoid_freq_ind->freq_list, - &psoc_priv_obj->avoid_freq_list, - sizeof(struct ch_avoid_ind_type)); - qdf_mem_copy(&avoid_freq_ind->chan_list, - &psoc_priv_obj->unsafe_chan_list, - sizeof(struct unsafe_ch_list)); - psoc_priv_obj->ch_avoid_ind = false; - } - -skip_ch_avoid_ind: cbk_list = psoc_priv_obj->cbk_list; for (ctr = 0; ctr < REG_MAX_CHAN_CHANGE_CBKS; ctr++) { @@ -98,8 +90,6 @@ skip_ch_avoid_ind: cbk_list[ctr].arg); } qdf_mem_free(cur_chan_list); - if (avoid_freq_ind) - qdf_mem_free(avoid_freq_ind); } /** @@ -111,10 +101,28 @@ static void reg_alloc_and_fill_payload(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev, struct reg_sched_payload **payload) { + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + psoc_priv_obj = reg_get_psoc_obj(psoc); + if (!psoc_priv_obj) { + reg_err("reg psoc private obj is NULL"); + *payload = NULL; + return; + } + *payload = qdf_mem_malloc(sizeof(**payload)); if (*payload) { (*payload)->psoc = psoc; (*payload)->pdev = pdev; + (*payload)->ch_avoid_ind = !!psoc_priv_obj->ch_avoid_ind; + qdf_mem_copy(&(*payload)->avoid_info.freq_list, + &psoc_priv_obj->avoid_freq_list, + sizeof(psoc_priv_obj->avoid_freq_list)); + qdf_mem_copy(&(*payload)->avoid_info.chan_list, + &psoc_priv_obj->unsafe_chan_list, + sizeof(psoc_priv_obj->unsafe_chan_list)); + + psoc_priv_obj->ch_avoid_ind = false; } } @@ -146,7 +154,8 @@ static QDF_STATUS reg_sched_chan_change_cbks_sb(struct scheduler_msg *msg) struct wlan_objmgr_psoc *psoc = load->psoc; struct wlan_objmgr_pdev *pdev = load->pdev; - reg_call_chan_change_cbks(psoc, pdev); + reg_call_chan_change_cbks(psoc, pdev, load->ch_avoid_ind, + &load->avoid_info); wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_SB_ID); wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID); @@ -183,7 +192,8 @@ static QDF_STATUS reg_sched_chan_change_cbks_nb(struct scheduler_msg *msg) struct wlan_objmgr_psoc *psoc = load->psoc; struct wlan_objmgr_pdev *pdev = load->pdev; - reg_call_chan_change_cbks(psoc, pdev); + reg_call_chan_change_cbks(psoc, pdev, load->ch_avoid_ind, + &load->avoid_info); wlan_objmgr_pdev_release_ref(pdev, WLAN_REGULATORY_NB_ID); wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_NB_ID); diff --git a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h index 8887cdad7540..46b1e668709b 100644 --- a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h +++ b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h @@ -1203,16 +1203,6 @@ struct reg_freq_range { uint32_t high_freq; }; -/** - * struct reg_sched_payload - * @psoc: psoc ptr - * @pdev: pdev ptr - */ -struct reg_sched_payload { - struct wlan_objmgr_psoc *psoc; - struct wlan_objmgr_pdev *pdev; -}; - /** * enum direction * @NORTHBOUND: northbound @@ -1359,6 +1349,20 @@ struct avoid_freq_ind_data { struct unsafe_ch_list chan_list; }; +/** + * struct reg_sched_payload + * @psoc: psoc ptr + * @pdev: pdev ptr + * @ch_avoid_ind: if avoidance event indicated + * @avoid_info: chan avoid info if @ch_avoid_ind is true + */ +struct reg_sched_payload { + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + bool ch_avoid_ind; + struct avoid_freq_ind_data avoid_info; +}; + #define FIVEG_STARTING_FREQ 5000 #define TWOG_STARTING_FREQ 2407 #define TWOG_CHAN_14_IN_MHZ 2484 diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 6956d03061fb..cfc2e5ec3ba3 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -859,6 +859,26 @@ QDF_STATUS wmi_unified_vdev_set_param_send(wmi_unified_t wmi_handle, struct vdev_set_params *param); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * wmi_unified_roam_set_param_send() - WMI roam set parameter function + * @wmi_handle: handle to WMI. + * @roam_param: pointer to hold roam set parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_roam_set_param_send(wmi_unified_t wmi_handle, + struct vdev_set_params *roam_param); +#else +static inline QDF_STATUS +wmi_unified_roam_set_param_send(wmi_unified_t wmi_handle, + struct vdev_set_params *roam_param) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * wmi_unified_sifs_trigger_send() - WMI vdev sifs trigger parameter function * @wmi_handle: handle to WMI. diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 85fbd47c86de..0e224b67b650 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -7887,12 +7887,14 @@ struct wmi_roam_scan_data { * @status: 0 - Roaming is success ; 1 - Roaming failed ; * 2 - No roam * @fail_reason: One of WMI_ROAM_FAIL_REASON_ID + * @fail_bssid: BSSID of the last attempted roam failed AP */ struct wmi_roam_result { bool present; uint32_t timestamp; uint32_t status; uint32_t fail_reason; + struct qdf_mac_addr fail_bssid; }; /** diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 6ed14454981a..ba47388218c6 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -1015,6 +1015,9 @@ QDF_STATUS (*send_pdev_set_pcl_cmd)(wmi_unified_t wmi_handle, #ifdef WLAN_FEATURE_ROAM_OFFLOAD QDF_STATUS (*send_vdev_set_pcl_cmd)(wmi_unified_t wmi_handle, struct set_pcl_cmd_params *params); + +QDF_STATUS (*send_roam_set_param_cmd)(wmi_unified_t wmi_handle, + struct vdev_set_params *roam_param); #endif #ifdef WLAN_POLICY_MGR_ENABLE diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index 71733a726529..5ecf442f8c42 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -399,6 +399,19 @@ wmi_unified_vdev_set_param_send(wmi_unified_t wmi_handle, return QDF_STATUS_E_FAILURE; } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +QDF_STATUS +wmi_unified_roam_set_param_send(wmi_unified_t wmi_handle, + struct vdev_set_params *roam_param) +{ + if (wmi_handle->ops->send_roam_set_param_cmd) + return wmi_handle->ops->send_roam_set_param_cmd(wmi_handle, + roam_param); + + return QDF_STATUS_E_FAILURE; +} +#endif + QDF_STATUS wmi_unified_sifs_trigger_send(wmi_unified_t wmi_handle, struct sifs_trigger_param *param) { diff --git a/wmi/src/wmi_unified_nan_tlv.c b/wmi/src/wmi_unified_nan_tlv.c index 42acfd137778..de5706c8f514 100644 --- a/wmi/src/wmi_unified_nan_tlv.c +++ b/wmi/src/wmi_unified_nan_tlv.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -693,7 +693,7 @@ static QDF_STATUS extract_ndp_initiator_rsp_tlv(wmi_unified_t wmi_handle, return QDF_STATUS_SUCCESS; } -#define MAX_NAN_MSG_LEN 200 +#define MAX_NAN_MSG_LEN 400 static QDF_STATUS extract_nan_msg_tlv(uint8_t *data, struct nan_dump_msg *msg) diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 76da4ea51604..b004aaef6df6 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -14263,6 +14263,7 @@ extract_roam_result_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, dst->status = src_data->roam_status; dst->timestamp = src_data->timestamp; dst->fail_reason = src_data->roam_fail_reason; + WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_data->bssid, dst->fail_bssid.bytes); return QDF_STATUS_SUCCESS; } @@ -14328,6 +14329,47 @@ extract_roam_11kv_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, return QDF_STATUS_SUCCESS; } + +/** + * send_roam_set_param_cmd_tlv() - WMI roam set parameter function + * @wmi_handle : handle to WMI. + * @roam_param : pointer to hold roam set parameter + * + * Return: 0 on success and -ve on failure. + */ +static QDF_STATUS +send_roam_set_param_cmd_tlv(wmi_unified_t wmi_handle, + struct vdev_set_params *roam_param) +{ + QDF_STATUS ret; + wmi_roam_set_param_cmd_fixed_param *cmd; + wmi_buf_t buf; + uint16_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) + return QDF_STATUS_E_NOMEM; + + cmd = (wmi_roam_set_param_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_set_param_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_set_param_cmd_fixed_param)); + cmd->vdev_id = roam_param->vdev_id; + cmd->param_id = roam_param->param_id; + cmd->param_value = roam_param->param_value; + wmi_debug("Setting vdev %d roam_param = %x, value = %u", + cmd->vdev_id, cmd->param_id, cmd->param_value); + wmi_mtrace(WMI_ROAM_SET_PARAM_CMDID, cmd->vdev_id, 0); + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_ROAM_SET_PARAM_CMDID); + if (QDF_IS_STATUS_ERROR(ret)) { + wmi_err("Failed to send roam set param command, ret = %d", ret); + wmi_buf_free(buf); + } + + return ret; +} #else static inline QDF_STATUS extract_roam_trigger_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, @@ -15039,6 +15081,9 @@ struct wmi_ops tlv_ops = { .extract_pdev_csa_switch_count_status = extract_pdev_csa_switch_count_status_tlv, .send_set_tpc_power_cmd = send_set_tpc_power_cmd_tlv, +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + .send_roam_set_param_cmd = send_roam_set_param_cmd_tlv, +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ }; /**