diff --git a/components/dp/core/inc/wlan_dp_main.h b/components/dp/core/inc/wlan_dp_main.h index 64bdae1942..9a50f021c9 100644 --- a/components/dp/core/inc/wlan_dp_main.h +++ b/components/dp/core/inc/wlan_dp_main.h @@ -390,4 +390,33 @@ void dp_try_set_rps_cpu_mask(struct wlan_objmgr_psoc *psoc); */ void dp_clear_rps_cpu_mask(struct wlan_dp_psoc_context *dp_ctx); +/** + * dp_mic_init_work() - init mic error work + * @dp_intf: Pointer to dp interface + * + * Return: None + */ +void dp_mic_init_work(struct wlan_dp_intf *dp_intf); + +/** + * dp_mic_deinit_work() - deinitialize mic error work + * @dp_intf: Pointer to dp interface + * + * Return: None + */ +void dp_mic_deinit_work(struct wlan_dp_intf *dp_intf); + +/** + * dp_rx_mic_error_ind() - MIC error indication handler + * @psoc: opaque handle for UMAC psoc object + * @pdev_id: physical device instance id + * @mic_failure_info: mic failure information + * + * This function indicates the Mic failure to the supplicant + * + * Return: None + */ +void +dp_rx_mic_error_ind(struct cdp_ctrl_objmgr_psoc *psoc, uint8_t pdev_id, + struct cdp_rx_mic_err_info *mic_failure_info); #endif diff --git a/components/dp/core/inc/wlan_dp_priv.h b/components/dp/core/inc/wlan_dp_priv.h index 5dbe1eda71..8371115dcf 100644 --- a/components/dp/core/inc/wlan_dp_priv.h +++ b/components/dp/core/inc/wlan_dp_priv.h @@ -258,6 +258,7 @@ struct dp_stats { * @vdev: object manager vdev context * @dev: netdev reference * @stats: Netdev stats + * @mic_work: Work to handle MIC error */ struct wlan_dp_intf { struct wlan_dp_psoc_context *dp_ctx; @@ -294,7 +295,7 @@ struct wlan_dp_intf { unsigned long mscs_prev_tx_vo_pkts; uint32_t mscs_counter; #endif /* WLAN_FEATURE_MSCS */ - + struct dp_mic_work mic_work; }; /** @@ -368,6 +369,10 @@ struct wlan_dp_psoc_context { struct dp_rtpm_tput_policy_context rtpm_tput_policy_ctx; #endif #endif /*WLAN_FEATURE_DP_BUS_BANDWIDTH*/ + /* disable RX offload (GRO/LRO) in concurrency scenarios */ + qdf_atomic_t disable_rx_ol_in_concurrency; + /* disable RX offload (GRO/LRO) in low throughput scenarios */ + qdf_atomic_t disable_rx_ol_in_low_tput; #ifdef WLAN_NS_OFFLOAD /* IPv6 notifier callback for handling NS offload on change in IP */ struct notifier_block ipv6_notifier; diff --git a/components/dp/core/src/wlan_dp_bus_bandwidth.c b/components/dp/core/src/wlan_dp_bus_bandwidth.c index 57dab52e5b..9e41d21c66 100644 --- a/components/dp/core/src/wlan_dp_bus_bandwidth.c +++ b/components/dp/core/src/wlan_dp_bus_bandwidth.c @@ -36,6 +36,7 @@ #include #include #include "wlan_dp_periodic_sta_stats.h" +#include "wlan_mlme_ucfg_api.h" #include #ifdef FEATURE_BUS_BANDWIDTH_MGR @@ -1018,6 +1019,149 @@ static void wlan_dp_deinit_tx_rx_histogram(struct wlan_dp_psoc_context *dp_ctx) dp_ctx->txrx_hist = NULL; } +/** + * wlan_dp_display_txrx_stats() - Display tx/rx histogram stats + * @dp_ctx: dp context + * + * Return: none + */ +static void wlan_dp_display_txrx_stats(struct wlan_dp_psoc_context *dp_ctx) +{ + struct wlan_dp_intf *dp_intf = NULL, *next_dp_intf = NULL; + struct dp_tx_rx_stats *stats; + hdd_cb_handle ctx = dp_ctx->dp_ops.callback_ctx; + int i = 0; + uint32_t total_rx_pkt, total_rx_dropped, + total_rx_delv, total_rx_refused; + uint32_t total_tx_pkt; + uint32_t total_tx_dropped; + uint32_t total_tx_orphaned; + + dp_for_each_intf_held_safe(dp_ctx, dp_intf, next_dp_intf) { + total_rx_pkt = 0; + total_rx_dropped = 0; + total_rx_delv = 0; + total_rx_refused = 0; + total_tx_pkt = 0; + total_tx_dropped = 0; + total_tx_orphaned = 0; + stats = &dp_intf->dp_stats.tx_rx_stats; + + if (dp_intf->intf_id == WLAN_INVALID_VDEV_ID) + continue; + + dp_info("dp_intf: %u", dp_intf->intf_id); + for (i = 0; i < NUM_CPUS; i++) { + total_rx_pkt += stats->per_cpu[i].rx_packets; + total_rx_dropped += stats->per_cpu[i].rx_dropped; + total_rx_delv += stats->per_cpu[i].rx_delivered; + total_rx_refused += stats->per_cpu[i].rx_refused; + total_tx_pkt += stats->per_cpu[i].tx_called; + total_tx_dropped += stats->per_cpu[i].tx_dropped; + total_tx_orphaned += stats->per_cpu[i].tx_orphaned; + } + + for (i = 0; i < NUM_CPUS; i++) { + if (!stats->per_cpu[i].tx_called) + continue; + + dp_info("Tx CPU[%d]: called %u, dropped %u, orphaned %u", + i, stats->per_cpu[i].tx_called, + stats->per_cpu[i].tx_dropped, + stats->per_cpu[i].tx_orphaned); + } + + dp_info("TX - called %u, dropped %u orphan %u", + total_tx_pkt, total_tx_dropped, + total_tx_orphaned); + + dp_ctx->dp_ops.wlan_dp_display_tx_multiq_stats(ctx, dp_intf->intf_id); + + for (i = 0; i < NUM_CPUS; i++) { + if (stats->per_cpu[i].rx_packets == 0) + continue; + dp_info("Rx CPU[%d]: packets %u, dropped %u, delivered %u, refused %u", + i, stats->per_cpu[i].rx_packets, + stats->per_cpu[i].rx_dropped, + stats->per_cpu[i].rx_delivered, + stats->per_cpu[i].rx_refused); + } + + dp_info("RX - packets %u, dropped %u, unsol_arp_mcast_drp %u, delivered %u, refused %u GRO - agg %u drop %u non-agg %u flush_skip %u low_tput_flush %u disabled(conc %u low-tput %u)", + total_rx_pkt, total_rx_dropped, + qdf_atomic_read(&stats->rx_usolict_arp_n_mcast_drp), + total_rx_delv, + total_rx_refused, stats->rx_aggregated, + stats->rx_gro_dropped, stats->rx_non_aggregated, + stats->rx_gro_flush_skip, + stats->rx_gro_low_tput_flush, + qdf_atomic_read(&dp_ctx->disable_rx_ol_in_concurrency), + qdf_atomic_read(&dp_ctx->disable_rx_ol_in_low_tput)); + } +} + +/** + * dp_display_periodic_stats() - Function to display periodic stats + * @dp_ctx - handle to dp context + * @bool data_in_interval - true, if data detected in bw time interval + * + * The periodicity is determined by dp_ctx->dp_cfg->periodic_stats_disp_time. + * Stats show up in wlan driver logs. + * + * Returns: None + */ +static void dp_display_periodic_stats(struct wlan_dp_psoc_context *dp_ctx, + bool data_in_interval) +{ + static uint32_t counter; + static bool data_in_time_period; + ol_txrx_soc_handle soc; + uint32_t periodic_stats_disp_time = 0; + hdd_cb_handle ctx = dp_ctx->dp_ops.callback_ctx; + + ucfg_mlme_stats_get_periodic_display_time(dp_ctx->psoc, + &periodic_stats_disp_time); + if (!periodic_stats_disp_time) + return; + + soc = cds_get_context(QDF_MODULE_ID_SOC); + if (!soc) + return; + + counter++; + if (data_in_interval) + data_in_time_period = data_in_interval; + + if (counter * dp_ctx->dp_cfg.bus_bw_compute_interval >= + periodic_stats_disp_time * 1000) { + if (data_in_time_period) { + wlan_dp_display_txrx_stats(dp_ctx); + dp_txrx_ext_dump_stats(soc, CDP_DP_RX_THREAD_STATS); + cdp_display_stats(soc, + CDP_RX_RING_STATS, + QDF_STATS_VERBOSITY_LEVEL_LOW); + cdp_display_stats(soc, + CDP_DP_NAPI_STATS, + QDF_STATS_VERBOSITY_LEVEL_LOW); + cdp_display_stats(soc, + CDP_TXRX_PATH_STATS, + QDF_STATS_VERBOSITY_LEVEL_LOW); + cdp_display_stats(soc, + CDP_DUMP_TX_FLOW_POOL_INFO, + QDF_STATS_VERBOSITY_LEVEL_LOW); + cdp_display_stats(soc, + CDP_DP_SWLM_STATS, + QDF_STATS_VERBOSITY_LEVEL_LOW); + dp_ctx->dp_ops.wlan_dp_display_netif_queue_history + (ctx, QDF_STATS_VERBOSITY_LEVEL_LOW); + cdp_display_txrx_hw_info(soc); + qdf_dp_trace_dump_stats(); + } + counter = 0; + data_in_time_period = false; + } +} + /** * dp_pm_qos_update_cpu_mask() - Prepare CPU mask for PM_qos voting * @mask: return variable of cpumask for the TPUT @@ -1470,9 +1614,8 @@ static void dp_pld_request_bus_bandwidth(struct wlan_dp_psoc_context *dp_ctx, * scheduler thread can utilize CPU. */ if (!dp_ops->dp_is_roaming_in_progress(ctx)) { - dp_ops->dp_display_periodic_stats(ctx, - (total_pkts > 0) ? - true : false); + dp_display_periodic_stats(dp_ctx, (total_pkts > 0) ? + true : false); dp_periodic_sta_stats_display(dp_ctx); } } diff --git a/components/dp/core/src/wlan_dp_main.c b/components/dp/core/src/wlan_dp_main.c index 23c8ec489a..dc734c1401 100644 --- a/components/dp/core/src/wlan_dp_main.c +++ b/components/dp/core/src/wlan_dp_main.c @@ -28,6 +28,7 @@ #include #include #include "wlan_objmgr_vdev_obj.h" +#include /* Global DP context */ static struct wlan_dp_psoc_context *gp_dp_ctx; @@ -123,10 +124,228 @@ dp_get_intf_by_macaddr(struct wlan_dp_psoc_context *dp_ctx, return NULL; } +/** + * validate_interface_id() - Check if interface ID is valid + * @intf_id: interface ID + * + * Return: 0 on success, error code on failure + */ +static int validate_interface_id(uint8_t intf_id) +{ + if (intf_id == WLAN_UMAC_VDEV_ID_MAX) { + dp_err("Interface is not up"); + return -EINVAL; + } + if (intf_id >= WLAN_MAX_VDEVS) { + dp_err("Bad interface id:%u", intf_id); + return -EINVAL; + } + return 0; +} + +/** + * is_dp_intf_valid() - Check if interface is valid + * @dp_intf: interface context + * + * Return: 0 on success, error code on failure + */ +static int is_dp_intf_valid(struct wlan_dp_intf *dp_intf) +{ + if (!dp_intf) { + dp_err("Interface is NULL"); + return -EINVAL; + } + return validate_interface_id(dp_intf->intf_id); +} + static void dp_cfg_init(struct wlan_dp_psoc_context *ctx) { } +/** + * __dp_process_mic_error() - Indicate mic error to supplicant + * @dp_intf: Pointer to dp interface + * + * Return: None + */ +static void +__dp_process_mic_error(struct wlan_dp_intf *dp_intf) +{ + struct wlan_dp_psoc_callbacks *ops = &dp_intf->dp_ctx->dp_ops; + struct wlan_objmgr_vdev *vdev = dp_intf->vdev; + + if (!vdev) { + dp_err("vdev is NULL"); + return; + } + + if (dp_comp_vdev_get_ref(vdev)) { + dp_err("vdev ref get error"); + return; + } + + if ((dp_intf->device_mode == QDF_STA_MODE || + dp_intf->device_mode == QDF_P2P_CLIENT_MODE) && + ucfg_cm_is_vdev_active(vdev)) + ops->osif_dp_process_sta_mic_error(dp_intf->mic_work.info, + vdev); + else if (dp_intf->device_mode == QDF_SAP_MODE || + dp_intf->device_mode == QDF_P2P_GO_MODE) + ops->osif_dp_process_sap_mic_error(dp_intf->mic_work.info, + vdev); + else + dp_err("Invalid interface type:%d", dp_intf->device_mode); + + dp_comp_vdev_put_ref(vdev); +} + +/** + * dp_process_mic_error() - process mic error work + * @data: void pointer to dp interface + * + * Return: None + */ +static void +dp_process_mic_error(void *data) +{ + struct wlan_dp_intf *dp_intf = data; + + if (is_dp_intf_valid(dp_intf)) + goto exit; + + __dp_process_mic_error(dp_intf); + +exit: + qdf_spin_lock_bh(&dp_intf->mic_work.lock); + if (dp_intf->mic_work.info) { + qdf_mem_free(dp_intf->mic_work.info); + dp_intf->mic_work.info = NULL; + } + if (dp_intf->mic_work.status == DP_MIC_SCHEDULED) + dp_intf->mic_work.status = DP_MIC_INITIALIZED; + qdf_spin_unlock_bh(&dp_intf->mic_work.lock); +} + +void +dp_rx_mic_error_ind(struct cdp_ctrl_objmgr_psoc *psoc, uint8_t pdev_id, + struct cdp_rx_mic_err_info *mic_failure_info) +{ + struct dp_mic_error_info *dp_mic_info; + struct wlan_objmgr_vdev *vdev; + struct wlan_dp_intf *dp_intf; + + if (!psoc) + return; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc((struct wlan_objmgr_psoc *)psoc, + mic_failure_info->vdev_id, + WLAN_DP_ID); + if (!vdev) + return; + dp_intf = dp_get_vdev_priv_obj(vdev); + if (!dp_intf) { + dp_comp_vdev_put_ref(vdev); + return; + } + + dp_mic_info = qdf_mem_malloc(sizeof(*dp_mic_info)); + if (!dp_mic_info) { + dp_comp_vdev_put_ref(vdev); + return; + } + + qdf_copy_macaddr(&dp_mic_info->ta_mac_addr, + &mic_failure_info->ta_mac_addr); + dp_mic_info->multicast = mic_failure_info->multicast; + dp_mic_info->key_id = mic_failure_info->key_id; + qdf_mem_copy(&dp_mic_info->tsc, &mic_failure_info->tsc, + SIR_CIPHER_SEQ_CTR_SIZE); + dp_mic_info->vdev_id = mic_failure_info->vdev_id; + + qdf_spin_lock_bh(&dp_intf->mic_work.lock); + if (dp_intf->mic_work.status != DP_MIC_INITIALIZED) { + qdf_spin_unlock_bh(&dp_intf->mic_work.lock); + qdf_mem_free(dp_mic_info); + dp_comp_vdev_put_ref(vdev); + return; + } + /* + * Store mic error info pointer in dp_intf + * for freeing up the alocated memory in case + * the work scheduled below is flushed or deinitialized. + */ + dp_intf->mic_work.status = DP_MIC_SCHEDULED; + dp_intf->mic_work.info = dp_mic_info; + qdf_sched_work(0, &dp_intf->mic_work.work); + qdf_spin_unlock_bh(&dp_intf->mic_work.lock); + dp_comp_vdev_put_ref(vdev); +} + +/** + * dp_mic_flush_work() - disable and flush pending mic work + * @dp_intf: Pointer to dp interface + * + * Return: None + */ +static void +dp_mic_flush_work(struct wlan_dp_intf *dp_intf) +{ + dp_info("Flush the MIC error work"); + + qdf_spin_lock_bh(&dp_intf->mic_work.lock); + if (dp_intf->mic_work.status != DP_MIC_SCHEDULED) { + qdf_spin_unlock_bh(&dp_intf->mic_work.lock); + return; + } + dp_intf->mic_work.status = DP_MIC_DISABLED; + qdf_spin_unlock_bh(&dp_intf->mic_work.lock); + + qdf_flush_work(&dp_intf->mic_work.work); +} + +/** + * dp_mic_enable_work() - enable mic error work + * @dp_intf: Pointer to dp interface + * + * Return: None + */ +static void dp_mic_enable_work(struct wlan_dp_intf *dp_intf) +{ + dp_info("Enable the MIC error work"); + + qdf_spin_lock_bh(&dp_intf->mic_work.lock); + if (dp_intf->mic_work.status == DP_MIC_DISABLED) + dp_intf->mic_work.status = DP_MIC_INITIALIZED; + qdf_spin_unlock_bh(&dp_intf->mic_work.lock); +} + +void dp_mic_deinit_work(struct wlan_dp_intf *dp_intf) +{ + dp_info("DeInitialize the MIC error work"); + + if (dp_intf->mic_work.status != DP_MIC_UNINITIALIZED) { + qdf_destroy_work(NULL, &dp_intf->mic_work.work); + + qdf_spin_lock_bh(&dp_intf->mic_work.lock); + dp_intf->mic_work.status = DP_MIC_UNINITIALIZED; + if (dp_intf->mic_work.info) { + qdf_mem_free(dp_intf->mic_work.info); + dp_intf->mic_work.info = NULL; + } + qdf_spin_unlock_bh(&dp_intf->mic_work.lock); + qdf_spinlock_destroy(&dp_intf->mic_work.lock); + } +} + +void dp_mic_init_work(struct wlan_dp_intf *dp_intf) +{ + qdf_spinlock_create(&dp_intf->mic_work.lock); + qdf_create_work(0, &dp_intf->mic_work.work, + dp_process_mic_error, dp_intf); + dp_intf->mic_work.status = DP_MIC_INITIALIZED; + dp_intf->mic_work.info = NULL; +} + QDF_STATUS dp_vdev_obj_create_notification(struct wlan_objmgr_vdev *vdev, void *arg) { @@ -167,6 +386,8 @@ dp_vdev_obj_create_notification(struct wlan_objmgr_vdev *vdev, void *arg) return status; } + dp_mic_enable_work(dp_intf); + return status; } @@ -185,6 +406,8 @@ dp_vdev_obj_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg) return QDF_STATUS_E_INVAL; } + dp_mic_flush_work(dp_intf); + status = wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_COMP_DP, (void *)dp_intf); diff --git a/components/dp/dispatcher/inc/wlan_dp_public_struct.h b/components/dp/dispatcher/inc/wlan_dp_public_struct.h index 41978a48ab..8eb9bdb266 100644 --- a/components/dp/dispatcher/inc/wlan_dp_public_struct.h +++ b/components/dp/dispatcher/inc/wlan_dp_public_struct.h @@ -29,6 +29,47 @@ #include "qdf_status.h" #include #include +#include +#include + +/** + * struct dp_mic_info - mic error info in dp + * @ta_mac_addr: transmitter mac address + * @multicast: Flag for multicast + * @key_id: Key ID + * @tsc: Sequence number + * @vdev_id: vdev id + * + */ +struct dp_mic_error_info { + struct qdf_mac_addr ta_mac_addr; + bool multicast; + uint8_t key_id; + uint8_t tsc[SIR_CIPHER_SEQ_CTR_SIZE]; + uint16_t vdev_id; +}; + +enum dp_mic_work_status { + DP_MIC_UNINITIALIZED, + DP_MIC_INITIALIZED, + DP_MIC_SCHEDULED, + DP_MIC_DISABLED +}; + +/** + * struct dp_mic_work - mic work info in dp + * @mic_error_work: mic error work + * @status: sattus of mic error work + * @info: Pointer to mic error information + * @lock: lock to synchronixe mic error work + * + */ +struct dp_mic_work { + qdf_work_t work; + enum dp_mic_work_status status; + struct dp_mic_error_info *info; + qdf_spinlock_t lock; +}; /** * typedef hdd_cb_handle - HDD Handle @@ -208,6 +249,10 @@ union wlan_tp_data { * @dp_is_roaming_in_progress:Callback to check if roaming is in progress * @dp_is_ap_active:Callback to check if AP is active * @dp_napi_apply_throughput_policy:Callback to apply NAPI throughput policy + * @wlan_dp_display_tx_multiq_stats: Callback to display Tx Mulit queue stats + * @wlan_dp_display_netif_queue_history: Callback to display Netif queue history + * @osif_dp_process_sta_mic_error: osif callback to process STA MIC error + * @osif_dp_process_sap_mic_error: osif callback to process SAP MIC error */ struct wlan_dp_psoc_callbacks { void (*os_if_dp_gro_rx)(struct sk_buff *skb, uint8_t napi_to_use, @@ -242,12 +287,19 @@ struct wlan_dp_psoc_callbacks { uint8_t user_triggered, int size); bool (*dp_is_roaming_in_progress)(hdd_cb_handle context); bool (*dp_is_ap_active)(hdd_cb_handle context, uint8_t vdev_id); - void (*dp_display_periodic_stats)(hdd_cb_handle context, bool interval); void (*dp_disable_rx_ol_for_low_tput)(hdd_cb_handle context, bool disable); int (*dp_napi_apply_throughput_policy)(hdd_cb_handle context, uint64_t tx_packets, uint64_t rx_packets); + void (*wlan_dp_display_tx_multiq_stats)(hdd_cb_handle context, + uint8_t vdev_id); + void (*wlan_dp_display_netif_queue_history)(hdd_cb_handle context, + enum qdf_stats_verbosity_level verb_lvl); + void (*osif_dp_process_sta_mic_error)(struct dp_mic_error_info *info, + struct wlan_objmgr_vdev *vdev); + void (*osif_dp_process_sap_mic_error)(struct dp_mic_error_info *info, + struct wlan_objmgr_vdev *vdev); }; /** diff --git a/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h b/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h index d3cedca1c2..dc6d48d6e4 100644 --- a/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h +++ b/components/dp/dispatcher/inc/wlan_dp_ucfg_api.h @@ -32,6 +32,7 @@ #include #include "pld_common.h" #include +#include /** * ucfg_dp_create_intf() - update DP interface MAC address @@ -130,6 +131,12 @@ ucfg_dp_update_config(struct wlan_objmgr_psoc *psoc, uint64_t ucfg_dp_get_rx_softirq_yield_duration(struct wlan_objmgr_psoc *psoc); +/** + * ucfg_dp_register_rx_mic_error_ind_handler : register mic error handler. + * @soc: soc handle + */ +void ucfg_dp_register_rx_mic_error_ind_handler(void *soc); + /** * ucfg_dp_bbm_context_init() - Initialize BBM context * @psoc: psoc handle diff --git a/components/dp/dispatcher/src/wlan_dp_ucfg_api.c b/components/dp/dispatcher/src/wlan_dp_ucfg_api.c index a8c126f461..03f3cfb375 100644 --- a/components/dp/dispatcher/src/wlan_dp_ucfg_api.c +++ b/components/dp/dispatcher/src/wlan_dp_ucfg_api.c @@ -82,6 +82,7 @@ ucfg_dp_create_intf(struct wlan_objmgr_psoc *psoc, dp_periodic_sta_stats_init(dp_intf); dp_periodic_sta_stats_mutex_create(dp_intf); + dp_mic_init_work(dp_intf); return QDF_STATUS_SUCCESS; } @@ -106,6 +107,8 @@ ucfg_dp_destroy_intf(struct wlan_objmgr_psoc *psoc, } dp_periodic_sta_stats_mutex_destroy(dp_intf); + dp_mic_deinit_work(dp_intf); + qdf_spin_lock_bh(&dp_ctx->intf_list_lock); qdf_list_remove_node(&dp_ctx->intf_list, &dp_intf->node); qdf_spin_unlock_bh(&dp_ctx->intf_list_lock); @@ -478,6 +481,11 @@ ucfg_dp_get_rx_softirq_yield_duration(struct wlan_objmgr_psoc *psoc) return dp_ctx->dp_cfg.rx_softirq_max_yield_duration_ns; } +void ucfg_dp_register_rx_mic_error_ind_handler(void *soc) +{ + cdp_register_rx_mic_error_ind_handler(soc, dp_rx_mic_error_ind); +} + int ucfg_dp_bbm_context_init(struct wlan_objmgr_psoc *psoc) { return dp_bbm_context_init(psoc); @@ -623,6 +631,10 @@ void ucfg_dp_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc, dp_ctx->dp_ops.dp_pm_qos_add_request = cb_obj->dp_pm_qos_add_request; dp_ctx->dp_ops.dp_pm_qos_remove_request = cb_obj->dp_pm_qos_remove_request; + dp_ctx->dp_ops.wlan_dp_display_tx_multiq_stats = + cb_obj->wlan_dp_display_tx_multiq_stats; + dp_ctx->dp_ops.wlan_dp_display_netif_queue_history = + cb_obj->wlan_dp_display_netif_queue_history; dp_ctx->dp_ops.dp_send_mscs_action_frame = cb_obj->dp_send_mscs_action_frame; dp_ctx->dp_ops.dp_pktlog_enable_disable = @@ -630,8 +642,6 @@ void ucfg_dp_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc, dp_ctx->dp_ops.dp_is_roaming_in_progress = cb_obj->dp_is_roaming_in_progress; dp_ctx->dp_ops.dp_is_ap_active = cb_obj->dp_is_ap_active; - dp_ctx->dp_ops.dp_display_periodic_stats = - cb_obj->dp_display_periodic_stats; dp_ctx->dp_ops.dp_disable_rx_ol_for_low_tput = cb_obj->dp_disable_rx_ol_for_low_tput; dp_ctx->dp_ops.dp_napi_apply_throughput_policy = diff --git a/os_if/dp/src/os_if_dp.c b/os_if/dp/src/os_if_dp.c index 54af33c24c..6ca8b50796 100644 --- a/os_if/dp/src/os_if_dp.c +++ b/os_if/dp/src/os_if_dp.c @@ -27,6 +27,7 @@ #include #include "qca_vendor.h" #include "wlan_dp_ucfg_api.h" +#include "osif_vdev_sync.h" #ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH /** @@ -157,11 +158,105 @@ void osif_dp_send_tcp_param_update_event(struct wlan_objmgr_psoc *psoc, } #endif /*WLAN_FEATURE_DP_BUS_BANDWIDTH*/ +/** + * osif_dp_get_net_dev_from_vdev() - Get netdev object from vdev + * @vdev: Pointer to vdev manager + * @out_net_dev: Pointer to output netdev + * + * Return: 0 on success, error code on failure + */ +static int osif_dp_get_net_dev_from_vdev(struct wlan_objmgr_vdev *vdev, + struct net_device **out_net_dev) +{ + struct vdev_osif_priv *priv; + + if (!vdev) + return -EINVAL; + + priv = wlan_vdev_get_ospriv(vdev); + if (!priv || !priv->wdev || !priv->wdev->netdev) + return -EINVAL; + + *out_net_dev = priv->wdev->netdev; + + return 0; +} + +/** + * osif_dp_process_sta_mic_error() - Indicate STA mic error to supplicant + * @info: MIC error information + * @vdev: vdev handle + * + * Return: None + */ +static void +osif_dp_process_sta_mic_error(struct dp_mic_error_info *info, + struct wlan_objmgr_vdev *vdev) +{ + struct net_device *dev; + struct osif_vdev_sync *vdev_sync; + int errno; + + errno = osif_dp_get_net_dev_from_vdev(vdev, &dev); + if (errno) { + dp_err("failed to get netdev"); + return; + } + if (osif_vdev_sync_op_start(dev, &vdev_sync)) + return; + + /* inform mic failure to nl80211 */ + cfg80211_michael_mic_failure(dev, + (uint8_t *)&info->ta_mac_addr, + info->multicast ? + NL80211_KEYTYPE_GROUP : + NL80211_KEYTYPE_PAIRWISE, + info->key_id, + info->tsc, + GFP_KERNEL); +} + +/** + * osif_dp_process_sap_mic_error() - Indicate SAP mic error to supplicant + * @info: MIC error information + * @vdev: vdev handle + * + * Return: None + */ +static void +osif_dp_process_sap_mic_error(struct dp_mic_error_info *info, + struct wlan_objmgr_vdev *vdev) +{ + struct net_device *dev; + int errno; + struct osif_vdev_sync *vdev_sync; + + errno = osif_dp_get_net_dev_from_vdev(vdev, &dev); + if (errno) { + dp_err("failed to get netdev"); + return; + } + if (osif_vdev_sync_op_start(dev, &vdev_sync)) + return; + + /* inform mic failure to nl80211 */ + cfg80211_michael_mic_failure(dev, + (uint8_t *)&info->ta_mac_addr, + info->multicast ? + NL80211_KEYTYPE_GROUP : + NL80211_KEYTYPE_PAIRWISE, + info->key_id, + info->tsc, + GFP_KERNEL); +} + void os_if_dp_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc, struct wlan_dp_psoc_callbacks *cb_obj) { cb_obj->osif_dp_send_tcp_param_update_event = osif_dp_send_tcp_param_update_event; + cb_obj->osif_dp_process_sta_mic_error = osif_dp_process_sta_mic_error; + cb_obj->osif_dp_process_sap_mic_error = osif_dp_process_sap_mic_error; ucfg_dp_register_hdd_callbacks(psoc, cb_obj); }