diff --git a/drivers/staging/qca-wifi-host-cmn/cfg/inc/cfg_converged.h b/drivers/staging/qca-wifi-host-cmn/cfg/inc/cfg_converged.h index a26ac6d1db6e5ac8c0bc608fb4b5f21f77d4ebcd..87eecad0f2854a7b74f47ec5059efd2c9813dd2e 100644 --- a/drivers/staging/qca-wifi-host-cmn/cfg/inc/cfg_converged.h +++ b/drivers/staging/qca-wifi-host-cmn/cfg/inc/cfg_converged.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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,6 +25,7 @@ #include #include "cfg_dp.h" +#include "cfg_hif.h" #include #ifdef WLAN_SUPPORT_GREEN_AP #include "cfg_green_ap_params.h" @@ -38,7 +39,8 @@ CFG_DP \ CFG_EXTSCAN_ALL \ CFG_GREEN_AP_ALL \ - CFG_SPECTRAL_ALL + CFG_SPECTRAL_ALL \ + CFG_HIF #endif /* __CFG_CONVERGED_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/cfg/inc/cfg_define.h b/drivers/staging/qca-wifi-host-cmn/cfg/inc/cfg_define.h index 59423bd48362cb7b08dbff93a816cd0c7e42f852..375bce92154bc10b02ea8ecec5f2189068aff1b3 100644 --- a/drivers/staging/qca-wifi-host-cmn/cfg/inc/cfg_define.h +++ b/drivers/staging/qca-wifi-host-cmn/cfg/inc/cfg_define.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 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 @@ -85,10 +85,10 @@ enum cfg_fallback_behavior { (NON_INI, IPV6, struct qdf_ipv6_addr, name, -1, -1, -1, desc, def) /* utility macros/functions */ -#ifdef CONFIG_MCL -#define MCL_OR_WIN_VALUE(mcl_value, win_value) mcl_value +#ifdef CONFIG_AP_PLATFORM +#define PLATFORM_VALUE(non_ap_value, ap_value) ap_value #else -#define MCL_OR_WIN_VALUE(mcl_value, win_value) win_value +#define PLATFORM_VALUE(non_ap_value, ap_value) non_ap_value #endif #endif /* __CFG_DEFINE_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/cfg/inc/i_cfg.h b/drivers/staging/qca-wifi-host-cmn/cfg/inc/i_cfg.h index afc240b808e3bd071ee35bac6e727c9fb11dd2c9..986ba246be297d2da901e784de1666d813f0d169 100644 --- a/drivers/staging/qca-wifi-host-cmn/cfg/inc/i_cfg.h +++ b/drivers/staging/qca-wifi-host-cmn/cfg/inc/i_cfg.h @@ -70,7 +70,8 @@ struct cfg_values { struct cfg_values *cfg_psoc_get_values(struct wlan_objmgr_psoc *psoc); -#define __cfg_get(psoc, id) (cfg_psoc_get_values(psoc)->id##_internal) +#define __cfg_get(psoc, id) (cfg_psoc_get_values( \ + (struct wlan_objmgr_psoc *)psoc)->id##_internal) #endif /* __I_CFG_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/cfg/src/cfg.c b/drivers/staging/qca-wifi-host-cmn/cfg/src/cfg.c index a923ed04e893449f6941c1e615361143707151fd..297c3706a8228a6ed69bce8b649dcb8935b6e389 100644 --- a/drivers/staging/qca-wifi-host-cmn/cfg/src/cfg.c +++ b/drivers/staging/qca-wifi-host-cmn/cfg/src/cfg.c @@ -234,8 +234,8 @@ cfg_mac_item_handler(struct cfg_value_store *store, return; cfg_err("%s=%s - Invalid format (status %d); Using default " - QDF_MAC_ADDR_STR, meta->name, str_value, status, - QDF_MAC_ADDR_ARRAY(store_value->bytes)); + QDF_MAC_ADDR_FMT, meta->name, str_value, status, + QDF_MAC_ADDR_REF(store_value->bytes)); } static __attribute__((unused)) void @@ -539,7 +539,8 @@ cfg_store_print(struct wlan_objmgr_psoc *psoc) #undef __CFG_INI_MAC #define __CFG_INI_MAC(id, mtype, ctype, name, desc, def...) \ - cfg_nofl_debug("%s %pM", name, (&store->values.id##_internal)->bytes); + cfg_nofl_debug("%s "QDF_MAC_ADDR_FMT, name, \ + QDF_MAC_ADDR_REF((&store->values.id##_internal)->bytes)); #undef __CFG_INI_IPV4 #define __CFG_INI_IPV4(id, mtype, ctype, name, desc, def...) \ @@ -591,8 +592,8 @@ cfg_ini_config_print(struct wlan_objmgr_psoc *psoc, uint8_t *buf, #undef __CFG_INI_MAC #define __CFG_INI_MAC(id, mtype, ctype, name, desc, def...) \ do { \ - len = qdf_scnprintf(buf, buflen, "%s %pM\n", name, \ - (&store->values.id##_internal)->bytes); \ + len = qdf_scnprintf(buf, buflen, "%s "QDF_MAC_ADDR_FMT"\n", name, \ + QDF_MAC_ADDR_REF((&store->values.id##_internal)->bytes)); \ buf += len; \ buflen -= len; \ } while (0); diff --git a/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_cal_client_api.c b/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_cal_client_api.c index 37217434ac6f66fd325b51443df345c5cb9e42f0..08c8e55f42e2dee8b21d1d605b5e02c35e5b9eb8 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_cal_client_api.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_cal_client_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 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 @@ -27,9 +27,10 @@ * * return: void */ -void dp_cal_client_attach(void **cal_client_ctx, void *pdev, +void dp_cal_client_attach(struct cdp_cal_client **cal_client_ctx, + struct cdp_pdev *pdev, qdf_device_t osdev, - void (*dp_iterate_peer_list)(void *)) + void (*dp_iterate_peer_list)(struct cdp_pdev *)) { struct cal_client *cal_cl; @@ -54,7 +55,7 @@ qdf_export_symbol(dp_cal_client_attach); * * return: void */ -void dp_cal_client_detach(void **cal_client_ctx) +void dp_cal_client_detach(struct cdp_cal_client **cal_client_ctx) { struct cal_client *cal_cl; @@ -147,6 +148,14 @@ void dp_cal_client_update_peer_stats(struct cdp_peer_stats *peer_stats) peer_stats->tx.tx_data_ucast_rate = temp_tx_ucast_pkts - peer_stats->tx.tx_data_ucast_last; + /* Check tx and rx packets in last one second, and increment + * inactive time for peer + */ + if (peer_stats->tx.tx_data_rate || peer_stats->rx.rx_data_rate) + peer_stats->tx.inactive_time = 0; + else + peer_stats->tx.inactive_time++; + peer_stats->rx.rx_bytes_success_last = temp_rx_bytes; peer_stats->rx.rx_data_success_last = temp_rx_data; peer_stats->tx.tx_bytes_success_last = temp_tx_bytes; diff --git a/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_ratetable.c b/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_ratetable.c index a11cbfe6f42d58251788fed43bad3671d8db63e1..78bc187a1b6d2aeff924329e9987b9fe6a52f6f1 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_ratetable.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_ratetable.c @@ -3209,17 +3209,20 @@ enum DP_CMN_MODULATION_TYPE dp_getmodulation( * preamble - preamble * @bw - Transmission Bandwidth * @rix: rate index to be populated + * @ratecode: ratecode * * return - rate in kbps */ uint32_t dp_getrateindex(uint32_t gi, uint16_t mcs, uint8_t nss, uint8_t preamble, - uint8_t bw, uint32_t *rix) + uint8_t bw, uint32_t *rix, uint16_t *ratecode) { uint32_t ratekbps = 0, res = RT_INVALID_INDEX; /* represents failure */ uint16_t rc; enum DP_CMN_MODULATION_TYPE mod; + /* For error case, where idx exceeds bountry limit */ + *ratecode = 0; mod = dp_getmodulation(preamble, bw); rc = mcs; @@ -3269,6 +3272,7 @@ dp_getrateindex(uint32_t gi, uint16_t mcs, uint8_t nss, uint8_t preamble, break; } } + *ratecode = dp_11abgnratetable.info[res].ratecode; done: *rix = res; diff --git a/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_ratetable.h b/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_ratetable.h index 8809515d7bb4876027d08261b5c1064d1583468d..b22527a48590d14a58762d8299ed431a6a7b488e 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_ratetable.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/cmn_dp_api/dp_ratetable.h @@ -166,7 +166,7 @@ enum DP_CMN_MODULATION_TYPE dp_getmodulation( uint32_t dp_getrateindex(uint32_t gi, uint16_t mcs, uint8_t nss, uint8_t preamble, - uint8_t bw, uint32_t *rix); + uint8_t bw, uint32_t *rix, uint16_t *ratecode); int dp_rate_idx_to_kbps(uint8_t rate_idx, uint8_t gintval); diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_bus.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_bus.h index 28834cab8529abf56600c4ac7d971564cd648e15..99ad08adba05585639b168261518958f649e3b22 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_bus.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_bus.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, 2019-2020 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,15 +25,15 @@ /** * cdp_bus_suspend() - suspend bus - * @soc - data path soc handle - * @ppdev: data path pdev handle + * @soc: data path soc handle + * @pdev_id: id of dp pdev handle * * suspend bus * * return QDF_STATUS_SUCCESS suspend is not implemented or suspend done */ static inline QDF_STATUS cdp_bus_suspend(ol_txrx_soc_handle soc, - struct cdp_pdev *ppdev) + uint8_t pdev_id) { if (!soc || !soc->ops || !soc->ops->bus_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -42,21 +42,21 @@ static inline QDF_STATUS cdp_bus_suspend(ol_txrx_soc_handle soc, } if (soc->ops->bus_ops->bus_suspend) - return soc->ops->bus_ops->bus_suspend(ppdev); + return soc->ops->bus_ops->bus_suspend(soc, pdev_id); return QDF_STATUS_E_NOSUPPORT; } /** * cdp_bus_resume() - resume bus - * @soc - data path soc handle - * @ppdev: data path pdev handle + * @soc: data path soc handle + * @pdev_id: id of dp pdev handle * * resume bus * * return QDF_STATUS_SUCCESS resume is not implemented or suspend done */ static inline QDF_STATUS cdp_bus_resume(ol_txrx_soc_handle soc, - struct cdp_pdev *ppdev) + uint8_t pdev_id) { if (!soc || !soc->ops || !soc->ops->bus_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -65,14 +65,14 @@ static inline QDF_STATUS cdp_bus_resume(ol_txrx_soc_handle soc, } if (soc->ops->bus_ops->bus_resume) - return soc->ops->bus_ops->bus_resume(ppdev); + return soc->ops->bus_ops->bus_resume(soc, pdev_id); return QDF_STATUS_E_NOSUPPORT; } /** * cdp_process_wow_ack() - Process wow ack response * @soc: data path soc handle - * @ppdev: data path pdev handle + * @pdev_id: id of dp pdev handle * * Do any required data path operations for target wow ack * suspend response. @@ -80,7 +80,7 @@ static inline QDF_STATUS cdp_bus_resume(ol_txrx_soc_handle soc, * Return: None */ static inline void cdp_process_wow_ack_rsp(ol_txrx_soc_handle soc, - struct cdp_pdev *ppdev) + uint8_t pdev_id) { if (!soc || !soc->ops || !soc->ops->bus_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -89,7 +89,7 @@ static inline void cdp_process_wow_ack_rsp(ol_txrx_soc_handle soc, } if (soc->ops->bus_ops->process_wow_ack_rsp) - return soc->ops->bus_ops->process_wow_ack_rsp(soc, ppdev); + return soc->ops->bus_ops->process_wow_ack_rsp(soc, pdev_id); } /** @@ -102,7 +102,7 @@ static inline void cdp_process_wow_ack_rsp(ol_txrx_soc_handle soc, * Return: None */ static inline void cdp_process_target_suspend_req(ol_txrx_soc_handle soc, - struct cdp_pdev *ppdev) + uint8_t pdev_id) { if (!soc || !soc->ops || !soc->ops->bus_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -112,6 +112,6 @@ static inline void cdp_process_target_suspend_req(ol_txrx_soc_handle soc, if (soc->ops->bus_ops->process_target_suspend_req) return soc->ops->bus_ops->process_target_suspend_req(soc, - ppdev); + pdev_id); } #endif /* _CDP_TXRX_BUS_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cfg.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cfg.h index e3a624c5624ecae6e5b90b3551715c94a5806307..4c88b815d30fd12aaf97043943db00c987d9627e 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cfg.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cfg.h @@ -112,7 +112,7 @@ static inline struct cdp_cfg /** * cdp_cfg_vdev_rx_set_intrabss_fwd() - enable/disable intra bass forwarding * @soc - data path soc handle - * @vdev - virtual interface instance + * @vdev_id - virtual interface id * @val - enable or disable intra bss forwarding * * ap isolate, do not forward intra bss traffic @@ -121,7 +121,7 @@ static inline struct cdp_cfg */ static inline void cdp_cfg_vdev_rx_set_intrabss_fwd(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, bool val) + uint8_t vdev_id, bool val) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, @@ -134,7 +134,7 @@ cdp_cfg_vdev_rx_set_intrabss_fwd(ol_txrx_soc_handle soc, !soc->ops->cfg_ops->vdev_rx_set_intrabss_fwd) return; - soc->ops->cfg_ops->vdev_rx_set_intrabss_fwd(vdev, val); + soc->ops->cfg_ops->vdev_rx_set_intrabss_fwd(soc, vdev_id, val); } /** diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn.h index 4bd8046b0a132b7d283103d37518e05d7e60bfc8..f9b1f601edb0f72f20e59b2b89b919e55d0be581 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 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 @@ -81,6 +81,17 @@ enum verbose_debug_module { #define dp_verbose_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_DP, params) #endif +#define dp_nofl_alert(params...) \ + QDF_TRACE_FATAL_NO_FL(QDF_MODULE_ID_DP, params) +#define dp_nofl_err(params...) \ + QDF_TRACE_ERROR_NO_FL(QDF_MODULE_ID_DP, params) +#define dp_nofl_warn(params...) \ + QDF_TRACE_WARN_NO_FL(QDF_MODULE_ID_DP, params) +#define dp_nofl_info(params...) \ + QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_DP, params) +#define dp_nofl_debug(params...) \ + QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_DP, params) + #define dp_alert_rl(params...) QDF_TRACE_FATAL_RL(QDF_MODULE_ID_DP, params) #define dp_err_rl(params...) QDF_TRACE_ERROR_RL(QDF_MODULE_ID_DP, params) #define dp_warn_rl(params...) QDF_TRACE_WARN_RL(QDF_MODULE_ID_DP, params) @@ -116,42 +127,8 @@ cdp_soc_attach_target(ol_txrx_soc_handle soc) } -static inline int -cdp_soc_get_nss_cfg(ol_txrx_soc_handle soc) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); - QDF_BUG(0); - return 0; - } - - if (!soc->ops->cmn_drv_ops || - !soc->ops->cmn_drv_ops->txrx_soc_get_nss_cfg) - return 0; - - return soc->ops->cmn_drv_ops->txrx_soc_get_nss_cfg(soc); -} - -static inline void -cdp_soc_set_nss_cfg(ol_txrx_soc_handle soc, uint32_t config) -{ - 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->txrx_soc_set_nss_cfg) - return; - - soc->ops->cmn_drv_ops->txrx_soc_set_nss_cfg(soc, config); -} - -static inline struct cdp_vdev * -cdp_vdev_attach(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, +static inline QDF_STATUS +cdp_vdev_attach(ol_txrx_soc_handle soc, uint8_t pdev_id, uint8_t *vdev_mac_addr, uint8_t vdev_id, enum wlan_op_mode op_mode, enum wlan_op_subtype subtype) { @@ -159,30 +136,31 @@ cdp_vdev_attach(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return NULL; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_vdev_attach) - return NULL; + return QDF_STATUS_E_FAILURE; - return soc->ops->cmn_drv_ops->txrx_vdev_attach(pdev, - vdev_mac_addr, vdev_id, op_mode, subtype); + return soc->ops->cmn_drv_ops->txrx_vdev_attach(soc, pdev_id, + vdev_mac_addr, vdev_id, + op_mode, subtype); } -#ifdef CONFIG_MCL +#ifdef DP_FLOW_CTL /** * cdp_flow_pool_map() - Create flow pool for vdev - * @soc - data path soc handle - * @pdev - * @vdev_id - vdev_id corresponding to vdev start + * @soc: data path soc handle + * @pdev_id: id of dp pdev handle + * @vdev_id: vdev_id corresponding to vdev start * * Create per vdev flow pool. * * return none */ static inline QDF_STATUS cdp_flow_pool_map(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, uint8_t vdev_id) + uint8_t pdev_id, uint8_t vdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -195,21 +173,22 @@ static inline QDF_STATUS cdp_flow_pool_map(ol_txrx_soc_handle soc, !soc->ops->flowctl_ops->flow_pool_map_handler) return QDF_STATUS_E_INVAL; - return soc->ops->flowctl_ops->flow_pool_map_handler(soc, pdev, vdev_id); + return soc->ops->flowctl_ops->flow_pool_map_handler(soc, pdev_id, + vdev_id); } /** * cdp_flow_pool_unmap() - Delete flow pool - * @soc - data path soc handle - * @pdev - * @vdev_id - vdev_id corresponding to vdev start + * @soc: data path soc handle + * @pdev_id: id of dp pdev handle + * @vdev_id: vdev_id corresponding to vdev start * * Delete flow pool * * return none */ static inline void cdp_flow_pool_unmap(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, uint8_t vdev_id) + uint8_t pdev_id, uint8_t vdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -222,32 +201,32 @@ static inline void cdp_flow_pool_unmap(ol_txrx_soc_handle soc, !soc->ops->flowctl_ops->flow_pool_unmap_handler) return; - return soc->ops->flowctl_ops->flow_pool_unmap_handler(soc, pdev, + return soc->ops->flowctl_ops->flow_pool_unmap_handler(soc, pdev_id, vdev_id); } #endif -static inline void -cdp_vdev_detach(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - ol_txrx_vdev_delete_cb callback, void *cb_context) +static inline QDF_STATUS +cdp_vdev_detach(ol_txrx_soc_handle soc, uint8_t vdev_id, + ol_txrx_vdev_delete_cb callback, void *cb_context) { 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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_vdev_detach) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->txrx_vdev_detach(vdev, - callback, cb_context); + return soc->ops->cmn_drv_ops->txrx_vdev_detach(soc, vdev_id, + callback, cb_context); } static inline int -cdp_pdev_attach_target(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +cdp_pdev_attach_target(ol_txrx_soc_handle soc, uint8_t pdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -260,30 +239,39 @@ cdp_pdev_attach_target(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) !soc->ops->cmn_drv_ops->txrx_pdev_attach_target) return 0; - return soc->ops->cmn_drv_ops->txrx_pdev_attach_target(pdev); + return soc->ops->cmn_drv_ops->txrx_pdev_attach_target(soc, pdev_id); } -static inline struct cdp_pdev *cdp_pdev_attach - (ol_txrx_soc_handle soc, struct cdp_ctrl_objmgr_pdev *ctrl_pdev, - HTC_HANDLE htc_pdev, qdf_device_t osdev, uint8_t pdev_id) +static inline QDF_STATUS cdp_pdev_attach + (ol_txrx_soc_handle soc, HTC_HANDLE htc_pdev, qdf_device_t osdev, + uint8_t pdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return NULL; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_pdev_attach) - return NULL; + return QDF_STATUS_E_FAILURE; - return soc->ops->cmn_drv_ops->txrx_pdev_attach(soc, ctrl_pdev, - htc_pdev, osdev, pdev_id); + return soc->ops->cmn_drv_ops->txrx_pdev_attach(soc, htc_pdev, osdev, + pdev_id); } -static inline int cdp_pdev_post_attach(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev) +/** + * cdp_pdev_post_attach() - attach the data SW state + * @soc: datapath soc handle + * @pdev_id: the data physical device id being removed + * + * This function is used when the WLAN driver is being loaded to + * attach the host data component within the driver. + * + * Return: 0 for success or error code + */ +static inline int cdp_pdev_post_attach(ol_txrx_soc_handle soc, uint8_t pdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -296,11 +284,24 @@ static inline int cdp_pdev_post_attach(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->txrx_pdev_post_attach) return 0; - return soc->ops->cmn_drv_ops->txrx_pdev_post_attach(pdev); + return soc->ops->cmn_drv_ops->txrx_pdev_post_attach(soc, pdev_id); } +/** + * cdp_pdev_pre_detach() - detach the data SW state + * @soc: datapath soc handle + * @pdev_id: the data physical device id being removed + * @force: delete the pdev (and its vdevs and peers) even if + * there are outstanding references by the target to the vdevs + * and peers within the pdev + * + * This function is used when the WLAN driver is being removed to + * detach the host data component within the driver. + * + * Return: None + */ static inline void -cdp_pdev_pre_detach(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, int force) +cdp_pdev_pre_detach(ol_txrx_soc_handle soc, uint8_t pdev_id, int force) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -313,28 +314,28 @@ cdp_pdev_pre_detach(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, int force) !soc->ops->cmn_drv_ops->txrx_pdev_pre_detach) return; - soc->ops->cmn_drv_ops->txrx_pdev_pre_detach(pdev, force); + soc->ops->cmn_drv_ops->txrx_pdev_pre_detach(soc, pdev_id, force); } -static inline void -cdp_pdev_detach(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, int force) +static inline QDF_STATUS +cdp_pdev_detach(ol_txrx_soc_handle soc, uint8_t pdev_id, int force) { 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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_pdev_detach) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->txrx_pdev_detach(pdev, force); + return soc->ops->cmn_drv_ops->txrx_pdev_detach(soc, pdev_id, force); } static inline void -cdp_pdev_deinit(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, int force) +cdp_pdev_deinit(ol_txrx_soc_handle soc, uint8_t pdev_id, int force) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -347,30 +348,30 @@ cdp_pdev_deinit(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, int force) !soc->ops->cmn_drv_ops->txrx_pdev_deinit) return; - soc->ops->cmn_drv_ops->txrx_pdev_deinit(pdev, force); + soc->ops->cmn_drv_ops->txrx_pdev_deinit(soc, pdev_id, force); } -static inline void *cdp_peer_create - (ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - uint8_t *peer_mac_addr, struct cdp_ctrl_objmgr_peer *ctrl_peer) +static inline QDF_STATUS cdp_peer_create + (ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac_addr) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return NULL; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_peer_create) - return NULL; + return QDF_STATUS_E_FAILURE; - return soc->ops->cmn_drv_ops->txrx_peer_create(vdev, - peer_mac_addr, ctrl_peer); + return soc->ops->cmn_drv_ops->txrx_peer_create(soc, vdev_id, + peer_mac_addr); } static inline void cdp_peer_setup - (ol_txrx_soc_handle soc, struct cdp_vdev *vdev, void *peer) + (ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -383,36 +384,36 @@ static inline void cdp_peer_setup !soc->ops->cmn_drv_ops->txrx_peer_setup) return; - soc->ops->cmn_drv_ops->txrx_peer_setup(vdev, - peer); + soc->ops->cmn_drv_ops->txrx_peer_setup(soc, vdev_id, + peer_mac); } /* * cdp_cp_peer_del_response - Call the peer delete response handler * @soc: Datapath SOC handle - * @vdev_hdl: virtual device object + * @vdev_id: id of virtual device object * @peer_mac_addr: Mac address of the peer * * Return: void */ -static inline void cdp_cp_peer_del_response +static inline QDF_STATUS cdp_cp_peer_del_response (ol_txrx_soc_handle soc, - struct cdp_vdev *vdev_hdl, + uint8_t vdev_id, uint8_t *peer_mac_addr) { 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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_cp_peer_del_response) - return; + return QDF_STATUS_E_FAILURE; return soc->ops->cmn_drv_ops->txrx_cp_peer_del_response(soc, - vdev_hdl, + vdev_id, peer_mac_addr); } /** @@ -559,8 +560,9 @@ static inline QDF_STATUS cdp_peer_ast_delete_by_pdev } static inline int cdp_peer_add_ast - (ol_txrx_soc_handle soc, struct cdp_peer *peer_handle, - uint8_t *mac_addr, enum cdp_txrx_ast_entry_type type, uint32_t flags) + (ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac, + uint8_t *mac_addr, + enum cdp_txrx_ast_entry_type type, uint32_t flags) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -574,46 +576,47 @@ static inline int cdp_peer_add_ast return 0; return soc->ops->cmn_drv_ops->txrx_peer_add_ast(soc, - peer_handle, + vdev_id, + peer_mac, mac_addr, type, flags); } -static inline void cdp_peer_reset_ast +static inline QDF_STATUS cdp_peer_reset_ast (ol_txrx_soc_handle soc, uint8_t *wds_macaddr, uint8_t *peer_macaddr, - void *vdev_hdl) + uint8_t vdev_id) { 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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_peer_reset_ast) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->txrx_peer_reset_ast(soc, wds_macaddr, - peer_macaddr, vdev_hdl); + return soc->ops->cmn_drv_ops->txrx_peer_reset_ast(soc, wds_macaddr, + peer_macaddr, vdev_id); } -static inline void cdp_peer_reset_ast_table - (ol_txrx_soc_handle soc, void *vdev_hdl) +static inline QDF_STATUS cdp_peer_reset_ast_table + (ol_txrx_soc_handle soc, uint8_t vdev_id) { 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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_peer_reset_ast_table) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->txrx_peer_reset_ast_table(soc, vdev_hdl); + return soc->ops->cmn_drv_ops->txrx_peer_reset_ast_table(soc, vdev_id); } static inline void cdp_peer_flush_ast_table @@ -634,8 +637,8 @@ static inline void cdp_peer_flush_ast_table } static inline int cdp_peer_update_ast - (ol_txrx_soc_handle soc, uint8_t *wds_macaddr, - struct cdp_peer *peer_handle, uint32_t flags) + (ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac, + uint8_t *wds_macaddr, uint32_t flags) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -650,13 +653,14 @@ static inline int cdp_peer_update_ast return soc->ops->cmn_drv_ops->txrx_peer_update_ast(soc, - peer_handle, + vdev_id, + peer_mac, wds_macaddr, flags); } static inline void cdp_peer_teardown - (ol_txrx_soc_handle soc, struct cdp_vdev *vdev, void *peer) + (ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -669,29 +673,12 @@ static inline void cdp_peer_teardown !soc->ops->cmn_drv_ops->txrx_peer_teardown) return; - soc->ops->cmn_drv_ops->txrx_peer_teardown(vdev, peer); -} - -static inline void -cdp_vdev_flush_peers(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - bool unmap_only) -{ - 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->txrx_vdev_flush_peers) - return; - - soc->ops->cmn_drv_ops->txrx_vdev_flush_peers(vdev, unmap_only); + soc->ops->cmn_drv_ops->txrx_peer_teardown(soc, vdev_id, peer_mac); } static inline void -cdp_peer_delete(ol_txrx_soc_handle soc, void *peer, uint32_t bitmap) +cdp_peer_delete(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac, uint32_t bitmap) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -704,11 +691,21 @@ cdp_peer_delete(ol_txrx_soc_handle soc, void *peer, uint32_t bitmap) !soc->ops->cmn_drv_ops->txrx_peer_delete) return; - soc->ops->cmn_drv_ops->txrx_peer_delete(peer, bitmap); + soc->ops->cmn_drv_ops->txrx_peer_delete(soc, vdev_id, peer_mac, bitmap); } +/** + * cdp_peer_detach_sync() - peer detach sync callback + * @soc: datapath soc handle + * @vdev_id: virtual device/interface id + * @peer_mac: peer mac address + * @peer_unmap_sync: peer unmap sync cb. + * @bitmap: bitmap indicating special handling of request. + * + * Return: None + */ static inline void -cdp_peer_delete_sync(ol_txrx_soc_handle soc, void *peer, +cdp_peer_delete_sync(ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac, QDF_STATUS(*delete_cb)( uint8_t vdev_id, uint32_t peerid_cnt, @@ -726,14 +723,14 @@ cdp_peer_delete_sync(ol_txrx_soc_handle soc, void *peer, !soc->ops->cmn_drv_ops->txrx_peer_delete_sync) return; - soc->ops->cmn_drv_ops->txrx_peer_delete_sync(peer, + soc->ops->cmn_drv_ops->txrx_peer_delete_sync(soc, vdev_id, peer_mac, delete_cb, bitmap); } static inline int -cdp_set_monitor_mode(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - uint8_t smart_monitor) +cdp_set_monitor_mode(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t smart_monitor) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -746,55 +743,56 @@ cdp_set_monitor_mode(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, !soc->ops->cmn_drv_ops->txrx_set_monitor_mode) return 0; - return soc->ops->cmn_drv_ops->txrx_set_monitor_mode(vdev, + return soc->ops->cmn_drv_ops->txrx_set_monitor_mode(soc, vdev_id, smart_monitor); } -static inline void +static inline QDF_STATUS cdp_set_curchan(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, + uint8_t pdev_id, uint32_t chan_mhz) { 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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_set_curchan) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->txrx_set_curchan(pdev, chan_mhz); + return soc->ops->cmn_drv_ops->txrx_set_curchan(soc, pdev_id, chan_mhz); } -static inline void -cdp_set_privacy_filters(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - void *filter, uint32_t num) +static inline QDF_STATUS +cdp_set_privacy_filters(ol_txrx_soc_handle soc, uint8_t vdev_id, + void *filter, uint32_t num) { 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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_set_privacy_filters) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->txrx_set_privacy_filters(vdev, + return soc->ops->cmn_drv_ops->txrx_set_privacy_filters(soc, vdev_id, filter, num); } static inline int -cdp_set_monitor_filter(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - struct cdp_monitor_filter *filter_val) +cdp_set_monitor_filter(ol_txrx_soc_handle soc, uint8_t pdev_id, + struct cdp_monitor_filter *filter_val) { if (soc->ops->mon_ops->txrx_set_advance_monitor_filter) - return soc->ops->mon_ops->txrx_set_advance_monitor_filter(pdev, - filter_val); + return soc->ops->mon_ops->txrx_set_advance_monitor_filter(soc, + pdev_id, + filter_val); return 0; } @@ -803,9 +801,9 @@ cdp_set_monitor_filter(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, * Data Interface (B Interface) *****************************************************************************/ static inline void -cdp_vdev_register(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - void *osif_vdev, struct cdp_ctrl_objmgr_vdev *ctrl_vdev, - struct ol_txrx_ops *txrx_ops) +cdp_vdev_register(ol_txrx_soc_handle soc, uint8_t vdev_id, + ol_osif_vdev_handle osif_vdev, + struct ol_txrx_ops *txrx_ops) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -818,13 +816,13 @@ cdp_vdev_register(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, !soc->ops->cmn_drv_ops->txrx_vdev_register) return; - soc->ops->cmn_drv_ops->txrx_vdev_register(vdev, - osif_vdev, ctrl_vdev, txrx_ops); + soc->ops->cmn_drv_ops->txrx_vdev_register(soc, vdev_id, + osif_vdev, txrx_ops); } static inline int -cdp_mgmt_send(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - qdf_nbuf_t tx_mgmt_frm, uint8_t type) +cdp_mgmt_send(ol_txrx_soc_handle soc, uint8_t vdev_id, + qdf_nbuf_t tx_mgmt_frm, uint8_t type) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -837,14 +835,14 @@ cdp_mgmt_send(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, !soc->ops->cmn_drv_ops->txrx_mgmt_send) return 0; - return soc->ops->cmn_drv_ops->txrx_mgmt_send(vdev, + return soc->ops->cmn_drv_ops->txrx_mgmt_send(soc, vdev_id, tx_mgmt_frm, type); } static inline int -cdp_mgmt_send_ext(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - qdf_nbuf_t tx_mgmt_frm, uint8_t type, - uint8_t use_6mbps, uint16_t chanfreq) +cdp_mgmt_send_ext(ol_txrx_soc_handle soc, uint8_t vdev_id, + qdf_nbuf_t tx_mgmt_frm, uint8_t type, + uint8_t use_6mbps, uint16_t chanfreq) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -858,12 +856,12 @@ cdp_mgmt_send_ext(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, return 0; return soc->ops->cmn_drv_ops->txrx_mgmt_send_ext - (vdev, tx_mgmt_frm, type, use_6mbps, chanfreq); + (soc, vdev_id, tx_mgmt_frm, type, use_6mbps, chanfreq); } -static inline void -cdp_mgmt_tx_cb_set(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, +static inline QDF_STATUS +cdp_mgmt_tx_cb_set(ol_txrx_soc_handle soc, uint8_t pdev_id, uint8_t type, ol_txrx_mgmt_tx_cb download_cb, ol_txrx_mgmt_tx_cb ota_ack_cb, void *ctxt) { @@ -871,20 +869,28 @@ cdp_mgmt_tx_cb_set(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_mgmt_tx_cb_set) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->txrx_mgmt_tx_cb_set - (pdev, type, download_cb, ota_ack_cb, ctxt); + return soc->ops->cmn_drv_ops->txrx_mgmt_tx_cb_set + (soc, pdev_id, type, download_cb, ota_ack_cb, ctxt); } +/** + * cdp_peer_unmap_sync_cb_set() - set peer unmap sync callback + * @soc: datapath soc handle + * @pdev_id: physical device instance id + * @peer_unmap_sync: peer unmap sync callback + * + * Return: None + */ static inline void cdp_peer_unmap_sync_cb_set(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, + uint8_t pdev_id, QDF_STATUS(*unmap_resp_cb)( uint8_t vdev_id, uint32_t peerid_cnt, @@ -901,30 +907,21 @@ cdp_peer_unmap_sync_cb_set(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->txrx_peer_unmap_sync_cb_set) return; - soc->ops->cmn_drv_ops->txrx_peer_unmap_sync_cb_set(pdev, unmap_resp_cb); -} - -static inline int cdp_get_tx_pending(ol_txrx_soc_handle soc, -struct cdp_pdev *pdev) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); - QDF_BUG(0); - return 0; - } - - if (!soc->ops->cmn_drv_ops || - !soc->ops->cmn_drv_ops->txrx_get_tx_pending) - return 0; - - - return soc->ops->cmn_drv_ops->txrx_get_tx_pending(pdev); + soc->ops->cmn_drv_ops->txrx_peer_unmap_sync_cb_set(soc, pdev_id, + unmap_resp_cb); } +/* + * cdp_data_tx_cb_set(): set the callback for non standard tx + * @soc - datapath soc handle + * @vdev_id - virtual device/interface id + * @callback - callback function + * @ctxt: callback context + * + */ static inline void -cdp_data_tx_cb_set(ol_txrx_soc_handle soc, struct cdp_vdev *data_vdev, - ol_txrx_data_tx_cb callback, void *ctxt) +cdp_data_tx_cb_set(ol_txrx_soc_handle soc, uint8_t vdev_id, + ol_txrx_data_tx_cb callback, void *ctxt) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -937,8 +934,8 @@ cdp_data_tx_cb_set(ol_txrx_soc_handle soc, struct cdp_vdev *data_vdev, !soc->ops->cmn_drv_ops->txrx_data_tx_cb_set) return; - soc->ops->cmn_drv_ops->txrx_data_tx_cb_set(data_vdev, - callback, ctxt); + soc->ops->cmn_drv_ops->txrx_data_tx_cb_set(soc, vdev_id, + callback, ctxt); } /****************************************************************************** @@ -963,9 +960,9 @@ typedef uint32_t target_paddr_t; #endif /*HTT_PADDR64 */ static inline int -cdp_aggr_cfg(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - int max_subfrms_ampdu, - int max_subfrms_amsdu) +cdp_aggr_cfg(ol_txrx_soc_handle soc, uint8_t vdev_id, + int max_subfrms_ampdu, + int max_subfrms_amsdu) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -978,14 +975,14 @@ cdp_aggr_cfg(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, !soc->ops->cmn_drv_ops->txrx_aggr_cfg) return 0; - return soc->ops->cmn_drv_ops->txrx_aggr_cfg(vdev, + return soc->ops->cmn_drv_ops->txrx_aggr_cfg(soc, vdev_id, max_subfrms_ampdu, max_subfrms_amsdu); } static inline int -cdp_fw_stats_get(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - struct ol_txrx_stats_req *req, bool per_vdev, - bool response_expected) +cdp_fw_stats_get(ol_txrx_soc_handle soc, uint8_t vdev_id, + struct ol_txrx_stats_req *req, bool per_vdev, + bool response_expected) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -998,12 +995,12 @@ cdp_fw_stats_get(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, !soc->ops->cmn_drv_ops->txrx_fw_stats_get) return 0; - return soc->ops->cmn_drv_ops->txrx_fw_stats_get(vdev, req, + return soc->ops->cmn_drv_ops->txrx_fw_stats_get(soc, vdev_id, req, per_vdev, response_expected); } static inline int -cdp_debug(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, int debug_specs) +cdp_debug(ol_txrx_soc_handle soc, uint8_t vdev_id, int debug_specs) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -1016,25 +1013,26 @@ cdp_debug(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, int debug_specs) !soc->ops->cmn_drv_ops->txrx_debug) return 0; - return soc->ops->cmn_drv_ops->txrx_debug(vdev, debug_specs); + return soc->ops->cmn_drv_ops->txrx_debug(soc, vdev_id, debug_specs); } -static inline void cdp_fw_stats_cfg(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, uint8_t cfg_stats_type, uint32_t cfg_val) +static inline QDF_STATUS +cdp_fw_stats_cfg(ol_txrx_soc_handle soc, + uint8_t vdev_id, uint8_t cfg_stats_type, uint32_t cfg_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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_fw_stats_cfg) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->txrx_fw_stats_cfg(vdev, - cfg_stats_type, cfg_val); + return soc->ops->cmn_drv_ops->txrx_fw_stats_cfg(soc, vdev_id, + cfg_stats_type, cfg_val); } static inline void cdp_print_level_set(ol_txrx_soc_handle soc, unsigned level) @@ -1053,58 +1051,16 @@ static inline void cdp_print_level_set(ol_txrx_soc_handle soc, unsigned level) soc->ops->cmn_drv_ops->txrx_print_level_set(level); } -static inline uint8_t * -cdp_get_vdev_mac_addr(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); - QDF_BUG(0); - return NULL; - } - - if (!soc->ops->cmn_drv_ops || - !soc->ops->cmn_drv_ops->txrx_get_vdev_mac_addr) - return NULL; - - return soc->ops->cmn_drv_ops->txrx_get_vdev_mac_addr(vdev); - -} - -/** - * cdp_get_vdev_struct_mac_addr() - Return handle to struct qdf_mac_addr of - * vdev - * @vdev: vdev handle +/* + * cdp_get_vdev_mac_addr() – Detach txrx peer + * @soc_hdl: Datapath soc handle + * @vdev_id: virtual device/interface id * - * Return: Handle to struct qdf_mac_addr - */ -static inline struct qdf_mac_addr *cdp_get_vdev_struct_mac_addr - (ol_txrx_soc_handle soc, struct cdp_vdev *vdev) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); - QDF_BUG(0); - return NULL; - } - - if (!soc->ops->cmn_drv_ops || - !soc->ops->cmn_drv_ops->txrx_get_vdev_struct_mac_addr) - return NULL; - - return soc->ops->cmn_drv_ops->txrx_get_vdev_struct_mac_addr - (vdev); - -} - -/** - * cdp_get_pdev_from_vdev() - Return handle to pdev of vdev - * @vdev: vdev handle + * Return: MAC address on success, NULL on failure. * - * Return: Handle to pdev */ -static inline struct cdp_pdev *cdp_get_pdev_from_vdev - (ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +static inline uint8_t * +cdp_get_vdev_mac_addr(ol_txrx_soc_handle soc, uint8_t vdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -1114,16 +1070,17 @@ static inline struct cdp_pdev *cdp_get_pdev_from_vdev } if (!soc->ops->cmn_drv_ops || - !soc->ops->cmn_drv_ops->txrx_get_pdev_from_vdev) + !soc->ops->cmn_drv_ops->txrx_get_vdev_mac_addr) return NULL; - return soc->ops->cmn_drv_ops->txrx_get_pdev_from_vdev(vdev); + return soc->ops->cmn_drv_ops->txrx_get_vdev_mac_addr(soc, vdev_id); + } /** * cdp_get_os_rx_handles_from_vdev() - Return os rx handles for a vdev * @soc: ol_txrx_soc_handle handle - * @vdev: vdev for which os rx handles are needed + * @vdev_id: vdev id for which os rx handles are needed * @stack_fn_p: pointer to stack function pointer * @osif_handle_p: pointer to ol_osif_vdev_handle * @@ -1131,7 +1088,7 @@ static inline struct cdp_pdev *cdp_get_pdev_from_vdev */ static inline void cdp_get_os_rx_handles_from_vdev(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, + uint8_t vdev_id, ol_txrx_rx_fp *stack_fn_p, ol_osif_vdev_handle *osif_handle_p) { @@ -1146,19 +1103,20 @@ void cdp_get_os_rx_handles_from_vdev(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->txrx_get_os_rx_handles_from_vdev) return; - soc->ops->cmn_drv_ops->txrx_get_os_rx_handles_from_vdev(vdev, + soc->ops->cmn_drv_ops->txrx_get_os_rx_handles_from_vdev(soc, vdev_id, stack_fn_p, osif_handle_p); } /** * cdp_get_ctrl_pdev_from_vdev() - Return control pdev of vdev - * @vdev: vdev handle + * @soc: datapath soc handle + * @vdev_id: virtual device/interface id * * Return: Handle to control pdev */ static inline struct cdp_cfg * -cdp_get_ctrl_pdev_from_vdev(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +cdp_get_ctrl_pdev_from_vdev(ol_txrx_soc_handle soc, uint8_t vdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -1171,45 +1129,32 @@ cdp_get_ctrl_pdev_from_vdev(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) !soc->ops->cmn_drv_ops->txrx_get_ctrl_pdev_from_vdev) return NULL; - return soc->ops->cmn_drv_ops->txrx_get_ctrl_pdev_from_vdev - (vdev); -} - -static inline struct cdp_vdev * -cdp_get_vdev_from_vdev_id(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint8_t vdev_id) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); - QDF_BUG(0); - return NULL; - } - - if (!soc->ops->cmn_drv_ops || - !soc->ops->cmn_drv_ops->txrx_get_vdev_from_vdev_id) - return NULL; - - return soc->ops->cmn_drv_ops->txrx_get_vdev_from_vdev_id - (pdev, vdev_id); + return soc->ops->cmn_drv_ops->txrx_get_ctrl_pdev_from_vdev(soc, + vdev_id); } -static inline struct cdp_vdev * -cdp_get_mon_vdev_from_pdev(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +/* + * cdp_get_mon_vdev_from_pdev() - Get vdev handle of monitor mode + * @soc: datapath soc handle + * @pdev_id: physical device instance id + * + * Return: virtual interface id + */ +static inline uint8_t +cdp_get_mon_vdev_from_pdev(ol_txrx_soc_handle soc, uint8_t pdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return NULL; + return -EINVAL; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_get_mon_vdev_from_pdev) - return NULL; + return -EINVAL; - return soc->ops->cmn_drv_ops->txrx_get_mon_vdev_from_pdev - (pdev); + return soc->ops->cmn_drv_ops->txrx_get_mon_vdev_from_pdev(soc, pdev_id); } static inline void @@ -1226,7 +1171,7 @@ cdp_soc_detach(ol_txrx_soc_handle soc) !soc->ops->cmn_drv_ops->txrx_soc_detach) return; - soc->ops->cmn_drv_ops->txrx_soc_detach((void *)soc); + soc->ops->cmn_drv_ops->txrx_soc_detach(soc); } /** @@ -1242,8 +1187,10 @@ cdp_soc_detach(ol_txrx_soc_handle soc) * Return: DP SOC handle on success, NULL on failure */ static inline ol_txrx_soc_handle -cdp_soc_init(ol_txrx_soc_handle soc, u_int16_t devid, void *hif_handle, - void *psoc, void *htc_handle, qdf_device_t qdf_dev, +cdp_soc_init(ol_txrx_soc_handle soc, u_int16_t devid, + void *hif_handle, + struct cdp_ctrl_objmgr_psoc *psoc, + HTC_HANDLE htc_handle, qdf_device_t qdf_dev, struct ol_if_ops *dp_ol_if_ops) { if (!soc || !soc->ops) { @@ -1283,7 +1230,7 @@ cdp_soc_deinit(ol_txrx_soc_handle soc) !soc->ops->cmn_drv_ops->txrx_soc_deinit) return; - soc->ops->cmn_drv_ops->txrx_soc_deinit((void *)soc); + soc->ops->cmn_drv_ops->txrx_soc_deinit(soc); } /** @@ -1309,7 +1256,7 @@ cdp_tso_soc_attach(ol_txrx_soc_handle soc) !soc->ops->cmn_drv_ops->txrx_tso_soc_attach) return 0; - return soc->ops->cmn_drv_ops->txrx_tso_soc_attach((void *)soc); + return soc->ops->cmn_drv_ops->txrx_tso_soc_attach(soc); } /** @@ -1335,21 +1282,23 @@ cdp_tso_soc_detach(ol_txrx_soc_handle soc) !soc->ops->cmn_drv_ops->txrx_tso_soc_detach) return 0; - return soc->ops->cmn_drv_ops->txrx_tso_soc_detach((void *)soc); + return soc->ops->cmn_drv_ops->txrx_tso_soc_detach(soc); } /** * cdp_addba_resp_tx_completion() - Indicate addba response tx * completion to dp to change tid state. * @soc: soc handle - * @peer_handle: peer handle + * @peer_mac: mac address of peer handle + * @vdev_id: id of vdev handle * @tid: tid * @status: Tx completion status * * Return: success/failure of tid update */ static inline int cdp_addba_resp_tx_completion(ol_txrx_soc_handle soc, - void *peer_handle, + uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, int status) { if (!soc || !soc->ops) { @@ -1363,12 +1312,12 @@ static inline int cdp_addba_resp_tx_completion(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->addba_resp_tx_completion) return 0; - return soc->ops->cmn_drv_ops->addba_resp_tx_completion(peer_handle, tid, - status); + return soc->ops->cmn_drv_ops->addba_resp_tx_completion(soc, peer_mac, + vdev_id, tid, status); } static inline int cdp_addba_requestprocess(ol_txrx_soc_handle soc, - void *peer_handle, uint8_t dialogtoken, uint16_t tid, + uint8_t *peer_mac, uint16_t vdev_id, uint8_t dialogtoken, uint16_t tid, uint16_t batimeout, uint16_t buffersize, uint16_t startseqnum) { if (!soc || !soc->ops) { @@ -1382,31 +1331,37 @@ static inline int cdp_addba_requestprocess(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->addba_requestprocess) return 0; - return soc->ops->cmn_drv_ops->addba_requestprocess(peer_handle, - dialogtoken, tid, batimeout, buffersize, startseqnum); + return soc->ops->cmn_drv_ops->addba_requestprocess(soc, peer_mac, + vdev_id, dialogtoken, tid, batimeout, buffersize, + startseqnum); } -static inline void cdp_addba_responsesetup(ol_txrx_soc_handle soc, - void *peer_handle, uint8_t tid, uint8_t *dialogtoken, - uint16_t *statuscode, uint16_t *buffersize, uint16_t *batimeout) +static inline QDF_STATUS +cdp_addba_responsesetup(ol_txrx_soc_handle soc, + uint8_t *peer_mac, uint16_t vdev_id, + uint8_t tid, uint8_t *dialogtoken, + uint16_t *statuscode, uint16_t *buffersize, + uint16_t *batimeout) { 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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->addba_responsesetup) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->addba_responsesetup(peer_handle, tid, - dialogtoken, statuscode, buffersize, batimeout); + return soc->ops->cmn_drv_ops->addba_responsesetup(soc, peer_mac, + vdev_id, tid, dialogtoken, statuscode, buffersize, + batimeout); } -static inline int cdp_delba_process(ol_txrx_soc_handle soc, - void *peer_handle, int tid, uint16_t reasoncode) +static inline int cdp_delba_process(ol_txrx_soc_handle soc, uint8_t *peer_mac, + uint16_t vdev_id, int tid, + uint16_t reasoncode) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -1419,15 +1374,16 @@ static inline int cdp_delba_process(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->delba_process) return 0; - return soc->ops->cmn_drv_ops->delba_process(peer_handle, - tid, reasoncode); + return soc->ops->cmn_drv_ops->delba_process(soc, peer_mac, + vdev_id, tid, reasoncode); } /** * cdp_delba_tx_completion() - Handle delba tx completion * to update stats and retry transmission if failed. * @soc: soc handle - * @peer_handle: peer handle + * @peer_mac: peer mac address + * @vdev_id: id of vdev handle * @tid: Tid number * @status: Tx completion status * @@ -1435,7 +1391,8 @@ static inline int cdp_delba_process(ol_txrx_soc_handle soc, */ static inline int cdp_delba_tx_completion(ol_txrx_soc_handle soc, - void *peer_handle, + uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, int status) { if (!soc || !soc->ops) { @@ -1449,90 +1406,97 @@ static inline int cdp_delba_tx_completion(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->delba_tx_completion) return 0; - return soc->ops->cmn_drv_ops->delba_tx_completion(peer_handle, + return soc->ops->cmn_drv_ops->delba_tx_completion(soc, peer_mac, + vdev_id, tid, status); } -static inline void cdp_set_addbaresponse(ol_txrx_soc_handle soc, - void *peer_handle, int tid, uint16_t statuscode) +static inline QDF_STATUS +cdp_set_addbaresponse(ol_txrx_soc_handle soc, + uint8_t *peer_mac, uint16_t vdev_id, int tid, + uint16_t statuscode) { 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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->set_addba_response) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->set_addba_response(peer_handle, tid, statuscode); + return soc->ops->cmn_drv_ops->set_addba_response(soc, peer_mac, vdev_id, + tid, statuscode); } /** - * cdp_get_peer_mac_addr_frm_id: function to return vdev id and and peer - * mac address - * @soc: SOC handle - * @peer_id: peer id of the peer for which mac_address is required - * @mac_addr: reference to mac address + * cdp_set_vdev_dscp_tid_map(): function to set DSCP-tid map in the vap + * @soc : soc handle + * @vdev_id: id of vdev handle + * @map_id: id of the tid map * - * reutm: vdev_id of the vap + * Return: QDF_STATUS */ -static inline uint8_t -cdp_get_peer_mac_addr_frm_id(ol_txrx_soc_handle soc, uint16_t peer_id, - uint8_t *mac_addr) +static inline QDF_STATUS +cdp_set_vdev_dscp_tid_map(ol_txrx_soc_handle soc, + uint8_t vdev_id, uint8_t map_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return CDP_INVALID_VDEV_ID; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->cmn_drv_ops || - !soc->ops->cmn_drv_ops->get_peer_mac_addr_frm_id) - return CDP_INVALID_VDEV_ID; + !soc->ops->cmn_drv_ops->set_vdev_dscp_tid_map) + return QDF_STATUS_E_FAILURE; - return soc->ops->cmn_drv_ops->get_peer_mac_addr_frm_id(soc, - peer_id, mac_addr); + return soc->ops->cmn_drv_ops->set_vdev_dscp_tid_map(soc, vdev_id, + map_id); } +#ifdef QCA_MULTIPASS_SUPPORT /** - * cdp_set_vdev_dscp_tid_map(): function to set DSCP-tid map in the vap - * @vdev: vdev handle - * @map_id: id of the tid map + * cdp_set_vlan_groupkey(): function to set vlan ID - group key map in the vap + * @soc : soc handle + * @vdev_id: id of vdev handle + * @vlan_id: vlan id + * @group_key: corresponding group key to vlan ID * * Return: void */ -static inline void cdp_set_vdev_dscp_tid_map(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, uint8_t map_id) +static inline +QDF_STATUS cdp_set_vlan_groupkey(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint16_t vlan_id, uint16_t group_key) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); + "%s: Invalid Instance:", __func__); QDF_BUG(0); - return; + return 0; } if (!soc->ops->cmn_drv_ops || - !soc->ops->cmn_drv_ops->set_vdev_dscp_tid_map) - return; + !soc->ops->cmn_drv_ops->set_vlan_groupkey) + return 0; - soc->ops->cmn_drv_ops->set_vdev_dscp_tid_map(vdev, - map_id); + return soc->ops->cmn_drv_ops->set_vlan_groupkey(soc, vdev_id, vlan_id, + group_key); } +#endif /** * cdp_ath_get_total_per(): function to get hw retries * @soc : soc handle - * @pdev: pdev handle + * @pdev_id: id of pdev handle * * Return: get hw retries */ static inline -int cdp_ath_get_total_per(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev) +int cdp_ath_get_total_per(ol_txrx_soc_handle soc, uint8_t pdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -1545,12 +1509,12 @@ int cdp_ath_get_total_per(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->txrx_get_total_per) return 0; - return soc->ops->cmn_drv_ops->txrx_get_total_per(pdev); + return soc->ops->cmn_drv_ops->txrx_get_total_per(soc, pdev_id); } /** * cdp_set_pdev_dscp_tid_map(): function to change tid values in DSCP-tid map - * @pdev: pdev handle + * @pdev_id: id of pdev handle * @map_id: id of the tid map * @tos: index value in map that needs to be changed * @tid: tid value passed by user @@ -1558,7 +1522,7 @@ int cdp_ath_get_total_per(ol_txrx_soc_handle soc, * Return: void */ static inline void cdp_set_pdev_dscp_tid_map(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, uint8_t map_id, uint8_t tos, uint8_t tid) + uint8_t pdev_id, uint8_t map_id, uint8_t tos, uint8_t tid) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -1571,60 +1535,10 @@ static inline void cdp_set_pdev_dscp_tid_map(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->set_pdev_dscp_tid_map) return; - soc->ops->cmn_drv_ops->set_pdev_dscp_tid_map(pdev, + soc->ops->cmn_drv_ops->set_pdev_dscp_tid_map(soc, pdev_id, map_id, tos, tid); } -/** - * cdp_hmmc_tid_override_en(): Function to enable hmmc tid override. - * @soc : soc handle - * @pdev: pdev handle - * @val: hmmc-dscp flag value - * - * Return: void - */ -static inline void cdp_hmmc_tid_override_en(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, 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->hmmc_tid_override_en) - return; - - soc->ops->cmn_drv_ops->hmmc_tid_override_en(pdev, val); -} - -/** - * cdp_set_hmmc_tid_val(): Function to set hmmc tid value. - * @soc : soc handle - * @pdev: pdev handle - * @tid: tid value - * - * Return: void - */ -static inline void cdp_set_hmmc_tid_val(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, uint8_t tid) -{ - 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_hmmc_tid_val) - return; - - soc->ops->cmn_drv_ops->set_hmmc_tid_val(pdev, tid); -} - /** * cdp_flush_cache_rx_queue() - flush cache rx queue frame * @@ -1648,14 +1562,14 @@ static inline void cdp_flush_cache_rx_queue(ol_txrx_soc_handle soc) /** * cdp_txrx_stats_request(): function to map to host and firmware statistics * @soc: soc handle - * @vdev: virtual device + * @vdev_id: virtual device ID * @req: stats request container * * return: status */ static inline -int cdp_txrx_stats_request(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - struct cdp_txrx_stats_req *req) +int cdp_txrx_stats_request(ol_txrx_soc_handle soc, uint8_t vdev_id, + struct cdp_txrx_stats_req *req) { if (!soc || !soc->ops || !soc->ops->cmn_drv_ops || !req) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -1665,7 +1579,8 @@ int cdp_txrx_stats_request(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, } if (soc->ops->cmn_drv_ops->txrx_stats_request) - return soc->ops->cmn_drv_ops->txrx_stats_request(vdev, req); + return soc->ops->cmn_drv_ops->txrx_stats_request(soc, vdev_id, + req); return 0; } @@ -1737,11 +1652,14 @@ cdp_display_stats(ol_txrx_soc_handle soc, uint16_t value, /** * cdp_set_pn_check(): function to set pn check * @soc: soc handle + * @vdev_id: id of virtual device + * @peer_mac: mac address of peer * @sec_type: security type - * #rx_pn: receive pn + * @rx_pn: receive pn */ static inline int cdp_set_pn_check(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, struct cdp_peer *peer_handle, enum cdp_sec_type sec_type, uint32_t *rx_pn) + uint8_t vdev_id, uint8_t *peer_mac, + enum cdp_sec_type sec_type, uint32_t *rx_pn) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -1754,26 +1672,28 @@ static inline int cdp_set_pn_check(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->set_pn_check) return 0; - soc->ops->cmn_drv_ops->set_pn_check(vdev, peer_handle, + soc->ops->cmn_drv_ops->set_pn_check(soc, vdev_id, peer_mac, sec_type, rx_pn); return 0; } /** - * cdp_set_key_sec_type(): function to set pn check + * cdp_set_key_sec_type(): function to set sec mode of key * @soc: soc handle + * @vdev_id: id of virtual device + * @peer_mac: mac address of peer * @sec_type: security type * #is_unicast: ucast or mcast */ static inline int cdp_set_key_sec_type(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, - struct cdp_peer *peer_handle, + uint8_t vdev_id, + uint8_t *peer_mac, enum cdp_sec_type sec_type, bool is_unicast) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); + "%s: Invalid Instance:", __func__); QDF_BUG(0); return 0; } @@ -1782,29 +1702,30 @@ static inline int cdp_set_key_sec_type(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->set_key_sec_type) return 0; - soc->ops->cmn_drv_ops->set_key_sec_type(vdev, peer_handle, - sec_type, is_unicast); + soc->ops->cmn_drv_ops->set_key_sec_type(soc, vdev_id, + peer_mac, sec_type, is_unicast); return 0; } -static inline int cdp_set_key(ol_txrx_soc_handle soc, - struct cdp_peer *peer_handle, - bool is_unicast, uint32_t *key) +static inline QDF_STATUS +cdp_set_key(ol_txrx_soc_handle soc, + uint8_t vdev_id, + uint8_t *mac, + bool is_unicast, uint32_t *key) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return 0; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->ctrl_ops || !soc->ops->ctrl_ops->set_key) - return 0; + return QDF_STATUS_E_FAILURE; - soc->ops->ctrl_ops->set_key(peer_handle, + return soc->ops->ctrl_ops->set_key(soc, vdev_id, mac, is_unicast, key); - return 0; } /** @@ -1839,12 +1760,12 @@ QDF_STATUS cdp_update_config_parameters(ol_txrx_soc_handle soc, /** * cdp_pdev_get_dp_txrx_handle() - get advanced dp handle from pdev * @soc: opaque soc handle - * @pdev: data path pdev handle + * @pdev_id: id of data path pdev handle * * Return: opaque dp handle */ static inline void * -cdp_pdev_get_dp_txrx_handle(ol_txrx_soc_handle soc, void *pdev) +cdp_pdev_get_dp_txrx_handle(ol_txrx_soc_handle soc, uint8_t pdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -1854,7 +1775,7 @@ cdp_pdev_get_dp_txrx_handle(ol_txrx_soc_handle soc, void *pdev) } if (soc->ops->cmn_drv_ops->get_dp_txrx_handle) - return soc->ops->cmn_drv_ops->get_dp_txrx_handle(pdev); + return soc->ops->cmn_drv_ops->get_dp_txrx_handle(soc, pdev_id); return 0; } @@ -1862,13 +1783,14 @@ cdp_pdev_get_dp_txrx_handle(ol_txrx_soc_handle soc, void *pdev) /** * cdp_pdev_set_dp_txrx_handle() - set advanced dp handle in pdev * @soc: opaque soc handle - * @pdev: data path pdev handle + * @pdev_id: id of data path pdev handle * @dp_hdl: opaque pointer for dp_txrx_handle * * Return: void */ static inline void -cdp_pdev_set_dp_txrx_handle(ol_txrx_soc_handle soc, void *pdev, void *dp_hdl) +cdp_pdev_set_dp_txrx_handle(ol_txrx_soc_handle soc, uint8_t pdev_id, + void *dp_hdl) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -1881,7 +1803,59 @@ cdp_pdev_set_dp_txrx_handle(ol_txrx_soc_handle soc, void *pdev, void *dp_hdl) !soc->ops->cmn_drv_ops->set_dp_txrx_handle) return; - soc->ops->cmn_drv_ops->set_dp_txrx_handle(pdev, dp_hdl); + soc->ops->cmn_drv_ops->set_dp_txrx_handle(soc, pdev_id, dp_hdl); +} + +/** + * cdp_vdev_get_dp_ext_txrx_handle() - get extended dp handle from vdev + * @soc: opaque soc handle + * @vdev_id: vdev id + * + * Return: opaque dp handle + */ +static inline void * +cdp_vdev_get_dp_ext_txrx_handle(ol_txrx_soc_handle soc, uint8_t vdev_id) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return 0; + } + + if (soc->ops->cmn_drv_ops->get_vdev_dp_ext_txrx_handle) + return soc->ops->cmn_drv_ops->get_vdev_dp_ext_txrx_handle( + soc, vdev_id); + + return 0; +} + +/** + * cdp_vdev_set_dp_ext_txrx_handle() - set extended dp handle in vdev + * @soc: opaque soc handle + * @vdev_id: vdev id + * @size: size of the advance dp handle + * + * Return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_vdev_set_dp_ext_txrx_handle(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint16_t size) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->set_vdev_dp_ext_txrx_handle) + return QDF_STATUS_E_FAILURE; + + return soc->ops->cmn_drv_ops->set_vdev_dp_ext_txrx_handle(soc, + vdev_id, + size); } /* @@ -1932,37 +1906,90 @@ cdp_soc_set_dp_txrx_handle(ol_txrx_soc_handle soc, void *dp_handle) dp_handle); } +/** + * cdp_soc_handle_mode_change() - Update pdev_id to lmac_id mapping + * @soc: opaque soc handle + * @pdev_id: id of data path pdev handle + * @lmac_id: lmac id + * Return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_soc_handle_mode_change(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint32_t lmac_id) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->map_pdev_to_lmac) + return QDF_STATUS_E_FAILURE; + + return soc->ops->cmn_drv_ops->handle_mode_change(soc, pdev_id, + lmac_id); +} + /** * cdp_soc_map_pdev_to_lmac() - Save pdev_id to lmac_id mapping * @soc: opaque soc handle - * @pdev_handle: data path pdev handle + * @pdev_id: id of data path pdev handle * @lmac_id: lmac id - * - * Return: void + * Return: QDF_STATUS */ -static inline void -cdp_soc_map_pdev_to_lmac(ol_txrx_soc_handle soc, void *pdev_handle, +static inline QDF_STATUS +cdp_soc_map_pdev_to_lmac(ol_txrx_soc_handle soc, uint8_t pdev_id, uint32_t lmac_id) { 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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->map_pdev_to_lmac) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->map_pdev_to_lmac((struct cdp_pdev *)pdev_handle, + return soc->ops->cmn_drv_ops->map_pdev_to_lmac(soc, pdev_id, lmac_id); } +/** + * cdp_txrx_set_pdev_status_down() - set pdev down/up status + * @soc: soc opaque handle + * @pdev_id: id of data path pdev handle + * @is_pdev_down: pdev down/up status + * + * return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_txrx_set_pdev_status_down(ol_txrx_soc_handle soc, + uint8_t pdev_id, + bool is_pdev_down) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->cmn_drv_ops || + !soc->ops->cmn_drv_ops->set_pdev_status_down) + return QDF_STATUS_E_FAILURE; + + return soc->ops->cmn_drv_ops->set_pdev_status_down(soc, pdev_id, + is_pdev_down); +} + /** * cdp_tx_send() - enqueue frame for transmission * @soc: soc opaque handle - * @vdev: VAP device + * @vdev_id: id of VAP device * @nbuf: nbuf to be enqueued * * This API is used by Extended Datapath modules to enqueue frame for @@ -1971,7 +1998,7 @@ cdp_soc_map_pdev_to_lmac(ol_txrx_soc_handle soc, void *pdev_handle, * Return: void */ static inline void -cdp_tx_send(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, qdf_nbuf_t nbuf) +cdp_tx_send(ol_txrx_soc_handle soc, uint8_t vdev_id, qdf_nbuf_t nbuf) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -1984,96 +2011,13 @@ cdp_tx_send(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, qdf_nbuf_t nbuf) !soc->ops->cmn_drv_ops->tx_send) return; - soc->ops->cmn_drv_ops->tx_send(vdev, nbuf); -} - -/* - * cdp_get_pdev_id_frm_pdev() - return pdev_id from pdev - * @soc: opaque soc handle - * @pdev: data path pdev handle - * - * Return: pdev_id - */ -static inline -uint8_t cdp_get_pdev_id_frm_pdev(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev) -{ - if (soc->ops->cmn_drv_ops->txrx_get_pdev_id_frm_pdev) - return soc->ops->cmn_drv_ops->txrx_get_pdev_id_frm_pdev(pdev); - return 0; -} - -/* - * cdp_get_vow_config_frm_pdev() - return carrier_vow_config from pdev - * @soc: opaque soc handle - * @pdev: data path pdev handle - * - * Return: carrier_vow_config - */ -static inline -bool cdp_get_vow_config_frm_pdev(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev) -{ - if (soc->ops->cmn_drv_ops->txrx_get_vow_config_frm_pdev) - return soc->ops->cmn_drv_ops->txrx_get_vow_config_frm_pdev( - pdev); - return 0; -} - -/** - * cdp_pdev_set_chan_noise_floor() - Set channel noise floor to DP layer - * @soc: opaque soc handle - * @pdev: data path pdev handle - * @chan_noise_floor: Channel Noise Floor (in dbM) obtained from control path - * - * Return: None - */ -static inline -void cdp_pdev_set_chan_noise_floor(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, - int16_t chan_noise_floor) -{ - if (soc->ops->cmn_drv_ops->txrx_pdev_set_chan_noise_floor) - return soc->ops->cmn_drv_ops->txrx_pdev_set_chan_noise_floor( - pdev, chan_noise_floor); -} - -/** - * cdp_set_nac() - set nac - * @soc: opaque soc handle - * @peer: data path peer handle - * - */ -static inline -void cdp_set_nac(ol_txrx_soc_handle soc, - struct cdp_peer *peer) -{ - if (soc->ops->cmn_drv_ops->txrx_set_nac) - soc->ops->cmn_drv_ops->txrx_set_nac(peer); -} - -/** - * cdp_set_pdev_tx_capture() - 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 - */ -static inline -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; + soc->ops->cmn_drv_ops->tx_send(soc, vdev_id, nbuf); } /** * cdp_set_pdev_pcp_tid_map() - set pdev pcp-tid-map * @soc: opaque soc handle - * @pdev: data path pdev handle + * @pdev_id: id of data path pdev handle * @pcp: pcp value * @tid: tid value * @@ -2084,7 +2028,7 @@ QDF_STATUS cdp_set_pdev_tx_capture(ol_txrx_soc_handle soc, */ static inline QDF_STATUS cdp_set_pdev_pcp_tid_map(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, + uint8_t pdev_id, uint32_t pcp, uint32_t tid) { if (!soc || !soc->ops) { @@ -2097,57 +2041,28 @@ QDF_STATUS cdp_set_pdev_pcp_tid_map(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->set_pdev_pcp_tid_map) return QDF_STATUS_E_INVAL; - return soc->ops->cmn_drv_ops->set_pdev_pcp_tid_map(pdev, pcp, tid); -} - -/** - * cdp_set_pdev_pcp_tidmap_prty() - set pdev tidmap priority - * @soc: opaque soc handle - * @pdev: data path pdev handle - * @val: priority value - * - * This API is used to configure the tidmap priority for a pdev. - * The tidmap priority decides which mapping, namely DSCP-TID, SVLAN_PCP-TID, - * CVLAN_PCP-TID will be used. - * - * Return: QDF_STATUS_SUCCESS if value set successfully - * QDF_STATUS_E_INVAL false if error - */ -static inline -QDF_STATUS cdp_set_pdev_tidmap_prty(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev_handle, - uint32_t val) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); - return QDF_STATUS_E_INVAL; - } - - if (!soc->ops->cmn_drv_ops || - !soc->ops->cmn_drv_ops->set_pdev_tidmap_prty) - return QDF_STATUS_E_INVAL; - - return soc->ops->cmn_drv_ops->set_pdev_tidmap_prty(pdev_handle, val); + return soc->ops->cmn_drv_ops->set_pdev_pcp_tid_map(soc, pdev_id, + pcp, tid); } /** * cdp_get_peer_mac_from_peer_id() - get peer mac addr from peer id * @soc: opaque soc handle - * @pdev: data path pdev handle + * @pdev_id: id of data path pdev handle * @peer_id: data path peer id * @peer_mac: peer_mac * - * Return: void + * Return: QDF_STATUS */ static inline -void cdp_get_peer_mac_from_peer_id(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev_handle, - uint32_t peer_id, uint8_t *peer_mac) +QDF_STATUS cdp_get_peer_mac_from_peer_id(ol_txrx_soc_handle soc, + uint32_t peer_id, uint8_t *peer_mac) { if (soc->ops->cmn_drv_ops->txrx_get_peer_mac_from_peer_id) - soc->ops->cmn_drv_ops->txrx_get_peer_mac_from_peer_id( - pdev_handle, peer_id, peer_mac); + return soc->ops->cmn_drv_ops->txrx_get_peer_mac_from_peer_id( + soc, peer_id, peer_mac); + + return QDF_STATUS_E_INVAL; } /** @@ -2159,90 +2074,97 @@ void cdp_get_peer_mac_from_peer_id(ol_txrx_soc_handle soc, */ static inline void cdp_vdev_tx_lock(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev) + uint8_t vdev_id) { if (soc->ops->cmn_drv_ops->txrx_vdev_tx_lock) - soc->ops->cmn_drv_ops->txrx_vdev_tx_lock(vdev); + soc->ops->cmn_drv_ops->txrx_vdev_tx_lock(soc, vdev_id); } /** * cdp_vdev_tx_unlock() - release lock * @soc: opaque soc handle - * @vdev: data path vdev handle + * @vdev_id: id of data path vdev handle * * Return: void */ static inline void cdp_vdev_tx_unlock(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev) + uint8_t vdev_id) { if (soc->ops->cmn_drv_ops->txrx_vdev_tx_unlock) - soc->ops->cmn_drv_ops->txrx_vdev_tx_unlock(vdev); + soc->ops->cmn_drv_ops->txrx_vdev_tx_unlock(soc, vdev_id); } /** * cdp_ath_getstats() - get updated athstats * @soc: opaque soc handle - * @dev: dp interface handle + * @id: vdev_id/pdev_id based on type * @stats: cdp network device stats structure * @type: device type pdev/vdev * - * Return: void + * Return: QDF_STATUS */ -static inline void cdp_ath_getstats(ol_txrx_soc_handle soc, - void *dev, struct cdp_dev_stats *stats, - uint8_t type) +static inline QDF_STATUS +cdp_ath_getstats(ol_txrx_soc_handle soc, + uint8_t id, struct cdp_dev_stats *stats, + uint8_t type) { if (soc && soc->ops && soc->ops->cmn_drv_ops->txrx_ath_getstats) - soc->ops->cmn_drv_ops->txrx_ath_getstats(dev, stats, type); + return soc->ops->cmn_drv_ops->txrx_ath_getstats(soc, id, + stats, type); + + return QDF_STATUS_E_FAILURE; } /** * cdp_set_gid_flag() - set groupid flag * @soc: opaque soc handle - * @pdev: data path pdev handle + * @pdev_id: id of data path pdev handle * @mem_status: member status from grp management frame * @user_position: user position from grp management frame * - * Return: void + * Return: QDF_STATUS */ -static inline -void cdp_set_gid_flag(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, u_int8_t *mem_status, - u_int8_t *user_position) +static inline QDF_STATUS +cdp_set_gid_flag(ol_txrx_soc_handle soc, + uint8_t pdev_id, u_int8_t *mem_status, + u_int8_t *user_position) { if (soc->ops->cmn_drv_ops->txrx_set_gid_flag) - soc->ops->cmn_drv_ops->txrx_set_gid_flag(pdev, mem_status, user_position); + return soc->ops->cmn_drv_ops->txrx_set_gid_flag(soc, pdev_id, + mem_status, + user_position); + return QDF_STATUS_E_FAILURE; } /** * cdp_fw_supported_enh_stats_version() - returns the fw enhanced stats version * @soc: opaque soc handle - * @pdev: data path pdev handle + * @pdev_id: id of data path pdev handle * */ static inline uint32_t cdp_fw_supported_enh_stats_version(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev) + uint8_t pdev_id) { if (soc->ops->cmn_drv_ops->txrx_fw_supported_enh_stats_version) - return soc->ops->cmn_drv_ops->txrx_fw_supported_enh_stats_version(pdev); + return soc->ops->cmn_drv_ops->txrx_fw_supported_enh_stats_version(soc, pdev_id); return 0; } /** * cdp_get_pdev_id_frm_pdev() - return pdev_id from pdev * @soc: opaque soc handle - * @ni: associated node + * @vdev_id: id of vdev device * @force: number of frame in SW queue * Return: void */ static inline void cdp_if_mgmt_drain(ol_txrx_soc_handle soc, - void *ni, int force) + uint8_t vdev_id, int force) { if (soc->ops->cmn_drv_ops->txrx_if_mgmt_drain) - soc->ops->cmn_drv_ops->txrx_if_mgmt_drain(ni, force); + soc->ops->cmn_drv_ops->txrx_if_mgmt_drain(soc, vdev_id, force); } /* cdp_peer_map_attach() - CDP API to allocate PEER map memory @@ -2268,25 +2190,6 @@ cdp_peer_map_attach(ol_txrx_soc_handle soc, uint32_t max_peers, return QDF_STATUS_SUCCESS; } -/** - - * cdp_pdev_set_ctrl_pdev() - set UMAC ctrl pdev to dp pdev - * @soc: opaque soc handle - * @pdev: opaque dp pdev handle - * @ctrl_pdev: opaque ctrl pdev handle - * - * Return: void - */ -static inline void -cdp_pdev_set_ctrl_pdev(ol_txrx_soc_handle soc, struct cdp_pdev *dp_pdev, - struct cdp_ctrl_objmgr_pdev *ctrl_pdev) -{ - if (soc && soc->ops && soc->ops->cmn_drv_ops && - soc->ops->cmn_drv_ops->txrx_pdev_set_ctrl_pdev) - soc->ops->cmn_drv_ops->txrx_pdev_set_ctrl_pdev(dp_pdev, - ctrl_pdev); -} - /* cdp_txrx_classify_and_update() - To classify the packet and update stats * @soc: opaque soc handle * @vdev: opaque dp vdev handle @@ -2298,7 +2201,7 @@ cdp_pdev_set_ctrl_pdev(ol_txrx_soc_handle soc, struct cdp_pdev *dp_pdev, */ static inline int cdp_txrx_classify_and_update(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, qdf_nbuf_t skb, + uint8_t vdev_id, qdf_nbuf_t skb, enum txrx_direction dir, struct ol_txrx_nbuf_classify *nbuf_class) { @@ -2313,7 +2216,7 @@ cdp_txrx_classify_and_update(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->txrx_classify_update) return 0; - return soc->ops->cmn_drv_ops->txrx_classify_update(vdev, + return soc->ops->cmn_drv_ops->txrx_classify_update(soc, vdev_id, skb, dir, nbuf_class); } @@ -2461,7 +2364,8 @@ static inline uint32_t cdp_cfg_get(ol_txrx_soc_handle soc, enum cdp_dp_cfg cfg) * Return: void */ static inline void -cdp_soc_set_rate_stats_ctx(ol_txrx_soc_handle soc, void *ctx) +cdp_soc_set_rate_stats_ctx(ol_txrx_soc_handle soc, + void *ctx) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -2504,11 +2408,11 @@ cdp_soc_get_rate_stats_ctx(ol_txrx_soc_handle soc) /** * cdp_peer_flush_rate_stats() - flush peer rate statistics * @soc: opaque soc handle - * @pdev: pdev handle + * @pdev_id: id of pdev handle * @buf: stats buffer */ static inline void -cdp_peer_flush_rate_stats(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, +cdp_peer_flush_rate_stats(ol_txrx_soc_handle soc, uint8_t pdev_id, void *buf) { if (!soc || !soc->ops) { @@ -2522,35 +2426,36 @@ cdp_peer_flush_rate_stats(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, !soc->ops->cmn_drv_ops->txrx_peer_flush_rate_stats) return; - soc->ops->cmn_drv_ops->txrx_peer_flush_rate_stats(soc, pdev, buf); + soc->ops->cmn_drv_ops->txrx_peer_flush_rate_stats(soc, pdev_id, buf); } /** * cdp_flush_rate_stats_request() - request flush rate statistics * @soc: opaque soc handle - * @pdev: pdev handle + * @pdev_id: id of pdev handle */ -static inline void -cdp_flush_rate_stats_request(struct cdp_soc_t *soc, struct cdp_pdev *pdev) +static inline QDF_STATUS +cdp_flush_rate_stats_request(struct cdp_soc_t *soc, uint8_t pdev_id) { 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_E_FAILURE; } if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_flush_rate_stats_request) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->cmn_drv_ops->txrx_flush_rate_stats_request(soc, pdev); + return soc->ops->cmn_drv_ops->txrx_flush_rate_stats_request(soc, + pdev_id); } /** * cdp_set_vdev_pcp_tid_map() - set vdev pcp-tid-map * @soc: opaque soc handle - * @vdev: data path vdev handle + * @vdev: id of data path vdev handle * @pcp: pcp value * @tid: tid value * @@ -2561,7 +2466,7 @@ cdp_flush_rate_stats_request(struct cdp_soc_t *soc, struct cdp_pdev *pdev) */ static inline QDF_STATUS cdp_set_vdev_pcp_tid_map(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev_handle, + uint8_t vdev_id, uint8_t pcp, uint8_t tid) { if (!soc || !soc->ops) { @@ -2574,71 +2479,87 @@ QDF_STATUS cdp_set_vdev_pcp_tid_map(ol_txrx_soc_handle soc, !soc->ops->cmn_drv_ops->set_vdev_pcp_tid_map) return QDF_STATUS_E_INVAL; - return soc->ops->cmn_drv_ops->set_vdev_pcp_tid_map(vdev_handle, + return soc->ops->cmn_drv_ops->set_vdev_pcp_tid_map(soc, vdev_id, pcp, tid); } /** - * cdp_set_vdev_tidmap_tbl_id() - set vdev tidmap table id + * cdp_tx_send_exc() - Transmit a frame on a given vdev in exception path * * @soc: opaque soc handle - * @vdev: data path vdev handle - * @mapid: value of mapid + * @vdev_id: vdev id + * @nbuf: skb + * @tx_exc_metadata: Handle that holds exception path meta data * - * This API is used to configure the table-id of the tid-mapping for a vdev. - * Table '0' is for using the pdev's pcp-tid mapping and '1' is for using - * the vdev's pcp-tid mapping. - * - * Return: QDF_STATUS_SUCCESS if value set successfully - * QDF_STATUS_E_INVAL false if error + * Return: NULL on success + * nbuf when it fails to send */ -static inline -QDF_STATUS cdp_set_vdev_tidmap_tbl_id(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev_handle, - uint8_t mapid) +static inline qdf_nbuf_t +cdp_tx_send_exc(ol_txrx_soc_handle soc, + uint8_t vdev_id, + qdf_nbuf_t nbuf, + struct cdp_tx_exception_metadata *tx_exc_metadata) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance", __func__); - return QDF_STATUS_E_INVAL; + QDF_BUG(0); + return 0; } if (!soc->ops->cmn_drv_ops || - !soc->ops->cmn_drv_ops->set_vdev_tidmap_tbl_id) - return QDF_STATUS_E_INVAL; + !soc->ops->cmn_drv_ops->tx_send_exc) + return 0; - return soc->ops->cmn_drv_ops->set_vdev_tidmap_tbl_id(vdev_handle, - mapid); + return soc->ops->cmn_drv_ops->tx_send_exc + (soc, vdev_id, nbuf, tx_exc_metadata); } /** - * cdp_set_vdev_tidmap_prty() - set vdev tidmap priority - * @soc: opaque soc handle - * @vdev: data path vdev handle - * @prio: tidmap priority value - * - * This API is used to configure the tidmap priority for a vdev. - * The tidmap priority decides which mapping, namely DSCP-TID, SVLAN_PCP-TID, - * CVLAN_PCP-TID will be used. - * The vdev tidmap priority will be used only when the tidmap_tbl_id is '1'. + * cdp_vdev_get_peer_mac_list(): function to get peer mac list of vdev + * @soc: Datapath soc handle + * @vdev_id: vdev id + * @newmac: Table of the clients mac + * @mac_cnt: No. of MACs required * - * Return: QDF_STATUS_SUCCESS if value set successfully - * QDF_STATUS_E_INVAL false if error + * return: no of clients */ -static inline -QDF_STATUS cdp_set_vdev_tidmap_prty(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev_handle, uint8_t prio) +static inline uint16_t +cdp_vdev_get_peer_mac_list(ol_txrx_soc_handle soc, + uint8_t vdev_id, + uint8_t newmac[][QDF_MAC_ADDR_SIZE], + uint16_t mac_cnt) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance", __func__); - return QDF_STATUS_E_INVAL; + QDF_BUG(0); + return 0; } if (!soc->ops->cmn_drv_ops || - !soc->ops->cmn_drv_ops->set_vdev_tidmap_prty) - return QDF_STATUS_E_INVAL; + !soc->ops->cmn_drv_ops->get_peer_mac_list) + return 0; - return soc->ops->cmn_drv_ops->set_vdev_tidmap_prty(vdev_handle, prio); + return soc->ops->cmn_drv_ops->get_peer_mac_list + (soc, vdev_id, newmac, mac_cnt); +} + +/** + * cdp_rx_get_pending() - Get number of pending frames of RX threads + * @soc: opaque soc handle + * Return: number of pending frames + */ +static inline int +cdp_rx_get_pending(ol_txrx_soc_handle soc) +{ + if (!soc || !soc->ol_ops || + !soc->ol_ops->dp_rx_get_pending) + return 0; + + if (cdp_cfg_get(soc, cfg_dp_wow_check_rx_pending)) + return soc->ol_ops->dp_rx_get_pending(soc); + else + return 0; } #endif /* _CDP_TXRX_CMN_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn_reg.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn_reg.h index 0200794d3fb53b0b742af88cc1506c1e190363c3..f99fd6b5c37e7f6ac8bff6e56da0e7f813cb3298 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn_reg.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn_reg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 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 @@ -30,7 +30,16 @@ #define LITHIUM_DP 0xfffd/*FIXME Add Litium device ID */ /* Use these device IDs for attach in future */ -ol_txrx_soc_handle ol_txrx_soc_attach(void *scn_handle, struct ol_if_ops *dp_ol_if_ops); +#if defined(DP_TXRX_SOC_ATTACH) +static inline ol_txrx_soc_handle +ol_txrx_soc_attach(void *scn_handle, struct ol_if_ops *dp_ol_if_ops) +{ + return NULL; +} +#else +ol_txrx_soc_handle +ol_txrx_soc_attach(void *scn_handle, struct ol_if_ops *dp_ol_if_ops); +#endif /** * dp_soc_attach_wifi3() - Attach txrx SOC @@ -57,24 +66,32 @@ ol_txrx_soc_handle ol_txrx_soc_attach(void *scn_handle, struct ol_if_ops *dp_ol_ * Return: DP SOC handle on success, NULL on failure */ #if defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) -void *dp_soc_attach_wifi3(void *ctrl_psoc, void *hif_handle, - HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, - struct ol_if_ops *ol_ops, uint16_t device_id); -void *dp_soc_init_wifi3(void *soc, void *ctrl_psoc, void *hif_handle, +struct cdp_soc_t * +dp_soc_attach_wifi3(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + struct hif_opaque_softc *hif_handle, + HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, + struct ol_if_ops *ol_ops, uint16_t device_id); +void *dp_soc_init_wifi3(struct cdp_soc_t *soc, + struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + struct hif_opaque_softc *hif_handle, HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, struct ol_if_ops *ol_ops, uint16_t device_id); #else -static inline void *dp_soc_attach_wifi3(void *ctrl_psoc, void *hif_handle, - HTC_HANDLE htc_handle, - qdf_device_t qdf_osdev, - struct ol_if_ops *ol_ops, - uint16_t device_id) +static inline struct cdp_soc_t * +dp_soc_attach_wifi3(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + struct hif_opaque_softc *hif_handle, + HTC_HANDLE htc_handle, + qdf_device_t qdf_osdev, + struct ol_if_ops *ol_ops, + uint16_t device_id) { return NULL; } static inline -void *dp_soc_init_wifi3(void *soc, void *ctrl_psoc, void *hif_handle, +void *dp_soc_init_wifi3(struct cdp_soc_t *soc, + struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + struct hif_opaque_softc *hif_handle, HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, struct ol_if_ops *ol_ops, uint16_t device_id) { @@ -82,16 +99,23 @@ void *dp_soc_init_wifi3(void *soc, void *ctrl_psoc, void *hif_handle, } #endif /* QCA_WIFI_QCA8074 */ -static inline ol_txrx_soc_handle cdp_soc_attach(u_int16_t devid, - void *hif_handle, void *psoc, void *htc_handle, - qdf_device_t qdf_dev, struct ol_if_ops *dp_ol_if_ops) +static inline +ol_txrx_soc_handle cdp_soc_attach(u_int16_t devid, + struct hif_opaque_softc *hif_handle, + struct cdp_ctrl_objmgr_psoc *psoc, + HTC_HANDLE htc_handle, + qdf_device_t qdf_dev, + struct ol_if_ops *dp_ol_if_ops) { switch (devid) { case LITHIUM_DP: /*FIXME Add lithium devide IDs */ case QCA8074_DEVICE_ID: /* Hawekeye */ case QCA8074V2_DEVICE_ID: /* Hawekeye V2*/ case QCA6290_DEVICE_ID: + case QCN9000_DEVICE_ID: case QCA6390_DEVICE_ID: + case QCA6490_DEVICE_ID: + case QCA6750_DEVICE_ID: case QCA6390_EMULATION_DEVICE_ID: case RUMIM2M_DEVICE_ID_NODE0: /*lithium emulation */ case RUMIM2M_DEVICE_ID_NODE1: /*lithium emulation */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn_struct.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn_struct.h index d2127c695ea0836d475550d9831d6b6134e33772..33916952c6aa4aeba98821120034186ec1e99d6f 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn_struct.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_cmn_struct.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -34,7 +35,7 @@ #include "qdf_types.h" #include "qdf_nbuf.h" #include "qdf_atomic.h" -#ifdef CONFIG_MCL +#ifdef DP_MOB_DEFS #include #endif #include @@ -56,6 +57,7 @@ #define CDP_BA_64_BIT_MAP_SIZE_DWORDS 2 #define CDP_RSSI_CHAIN_LEN 8 +#define OL_TXRX_INVALID_PDEV_ID 0xff #define OL_TXRX_INVALID_LOCAL_PEER_ID 0xffff #define CDP_INVALID_VDEV_ID 0xff /* Options for Dump Statistics */ @@ -78,6 +80,7 @@ #define CDP_BUNDLE_STATS 23 #define CDP_CREDIT_STATS 24 #define CDP_DISCONNECT_STATS 25 +#define CDP_DP_RX_FISA_STATS 26 #define WME_AC_TO_TID(_ac) ( \ ((_ac) == WME_AC_VO) ? 6 : \ @@ -100,6 +103,10 @@ #define CDP_DATA_TID_MAX 8 #define CDP_DATA_NON_QOS_TID 16 + +#define CDP_NUM_SA_BW 4 +#define CDP_PERCENT_MACRO 100 +#define CDP_NUM_KB_IN_MB 1000 /* * advance rx monitor filter * */ @@ -149,6 +156,36 @@ #define FILTER_DATA_DATA 0x0001 #define FILTER_DATA_NULL 0x0008 +/* + * Multiply rate by 2 to avoid float point + * and get rate in units of 500kbps + */ +#define CDP_11B_RATE_0MCS (11 * 2) +#define CDP_11B_RATE_1MCS (5.5 * 2) +#define CDP_11B_RATE_2MCS (2 * 2) +#define CDP_11B_RATE_3MCS (1 * 2) +#define CDP_11B_RATE_4MCS (11 * 2) +#define CDP_11B_RATE_5MCS (5.5 * 2) +#define CDP_11B_RATE_6MCS (2 * 2) + +#define CDP_11A_RATE_0MCS (48 * 2) +#define CDP_11A_RATE_1MCS (24 * 2) +#define CDP_11A_RATE_2MCS (12 * 2) +#define CDP_11A_RATE_3MCS (6 * 2) +#define CDP_11A_RATE_4MCS (54 * 2) +#define CDP_11A_RATE_5MCS (36 * 2) +#define CDP_11A_RATE_6MCS (18 * 2) +#define CDP_11A_RATE_7MCS (9 * 2) + +#define CDP_LEGACY_MCS0 0 +#define CDP_LEGACY_MCS1 1 +#define CDP_LEGACY_MCS2 2 +#define CDP_LEGACY_MCS3 3 +#define CDP_LEGACY_MCS4 4 +#define CDP_LEGACY_MCS5 5 +#define CDP_LEGACY_MCS6 6 +#define CDP_LEGACY_MCS7 7 + QDF_DECLARE_EWMA(tx_lag, 1024, 8) struct cdp_stats_cookie; @@ -161,6 +198,32 @@ enum cdp_cfg_param_type { CDP_CFG_NUM_PARAMS }; +/* + * PPDU TYPE from FW - + * @CDP_PPDU_STATS_PPDU_TYPE_SU: single user type + * @CDP_PPDU_STATS_PPDU_TYPE_MU_MIMO: multi user mu-mimo + * @CDP_PPDU_STATS_PPDU_TYPE_MU_OFDMA: multi user ofdma + * @CDP_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA: multi user mu-mimo ofdma + * @CDP_PPDU_STATS_PPDU_TYPE_UL_TRIG: ul trigger ppdu + * @CDP_PPDU_STATS_PPDU_TYPE_BURST_BCN: burst beacon + * @CDP_PPDU_STATS_PPDU_TYPE_UL_BSR_RESP: bsr respond + * @CDP_PPDU_STATS_PPDU_TYPE_UL_BSR_TRIG: bsr trigger + * @CDP_PPDU_STATS_PPDU_TYPE_UL_RESP: ul response + * @CDP_PPDU_STATS_PPDU_TYPE_UNKNOWN + */ +enum CDP_PPDU_STATS_PPDU_TYPE { + CDP_PPDU_STATS_PPDU_TYPE_SU = 0, + CDP_PPDU_STATS_PPDU_TYPE_MU_MIMO = 1, + CDP_PPDU_STATS_PPDU_TYPE_MU_OFDMA = 2, + CDP_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA = 4, + CDP_PPDU_STATS_PPDU_TYPE_UL_TRIG = 5, + CDP_PPDU_STATS_PPDU_TYPE_BURST_BCN = 6, + CDP_PPDU_STATS_PPDU_TYPE_UL_BSR_RESP = 7, + CDP_PPDU_STATS_PPDU_TYPE_UL_BSR_TRIG = 8, + CDP_PPDU_STATS_PPDU_TYPE_UL_RESP = 9, + CDP_PPDU_STATS_PPDU_TYPE_UNKNOWN = 0x1F, +}; + /* * htt_dbg_stats_type - * bit positions for each stats type within a stats type bitmask @@ -224,7 +287,9 @@ enum cdp_host_txrx_stats { TXRX_PDEV_CFG_PARAMS = 10, TXRX_NAPI_STATS = 11, TXRX_SOC_INTERRUPT_STATS = 12, + TXRX_SOC_FSE_STATS = 13, TXRX_HAL_REG_WRITE_STATS = 14, + TXRX_SOC_REO_HW_DESC_DUMP = 15, TXRX_HOST_STATS_MAX, }; @@ -360,8 +425,8 @@ enum cdp_ast_free_status { * @cookie: cookie * @cdp_ast_free_status: ast free status */ -typedef void (*txrx_ast_free_cb)(void *ctrl_soc, - void *cdp_soc, +typedef void (*txrx_ast_free_cb)(struct cdp_ctrl_objmgr_psoc *ctrl_soc, + struct cdp_soc *cdp_soc, void *cookie, enum cdp_ast_free_status); @@ -384,6 +449,39 @@ struct cdp_ast_entry_info { uint16_t peer_id; }; +#define MIC_SEQ_CTR_SIZE 6 + +enum cdp_rx_frame_type { + cdp_rx_frame_type_802_11, + cdp_rx_frame_type_802_3, +}; + +/** + * struct cdp_rx_mic_err_info - rx mic error information + * @frame_type: frame type - 0 - 802.11 frame + * - 1 - 802.3 frame + * @data: 802.11 frame + * @ta_mac_addr: transmitter mac address + * @da_mac_addr: destination mac address + * @tsc: sequence number + * @key_id: Key ID + * @multicast: flag for multicast + * @vdev_id: vdev ID + * + * This structure holds rx mic error information + * + */ +struct cdp_rx_mic_err_info { + uint8_t frame_type; + uint8_t *data; + struct qdf_mac_addr ta_mac_addr; + struct qdf_mac_addr da_mac_addr; + uint8_t tsc[MIC_SEQ_CTR_SIZE]; + uint8_t key_id; + bool multicast; + uint16_t vdev_id; +}; + /** * struct cdp_sec_type - security type information */ @@ -515,7 +613,6 @@ typedef struct ol_osif_vdev_t *ol_osif_vdev_handle; * @wlan_op_mode_sta: STA (client) mode * @wlan_op_mode_monitor: Monitor mode * @wlan_op_mode_ocb: OCB mode - * @wlan_op_mode_nan: NAN mode */ enum wlan_op_mode { wlan_op_mode_unknown, @@ -525,7 +622,6 @@ enum wlan_op_mode { wlan_op_mode_monitor, wlan_op_mode_ocb, wlan_op_mode_ndi, - wlan_op_mode_nan, }; /** @@ -586,19 +682,21 @@ typedef void /** * ol_txrx_tx_fp - top-level transmit function - * @data_vdev - handle to the virtual device object + * @soc - dp soc handle + * @vdev_id - handle to the virtual device object * @msdu_list - list of network buffers */ -typedef qdf_nbuf_t (*ol_txrx_tx_fp)(void *data_vdev, +typedef qdf_nbuf_t (*ol_txrx_tx_fp)(struct cdp_soc_t *soc, uint8_t vdev_id, qdf_nbuf_t msdu_list); /** * ol_txrx_tx_exc_fp - top-level transmit function on exception path - * @data_vdev - handle to the virtual device object + * @soc - dp soc handle + * @vdev_id - handle to the virtual device object * @msdu_list - list of network buffers * @tx_exc_metadata - structure that holds parameters to exception path */ -typedef qdf_nbuf_t (*ol_txrx_tx_exc_fp)(void *data_vdev, +typedef qdf_nbuf_t (*ol_txrx_tx_exc_fp)(struct cdp_soc_t *soc, uint8_t vdev_id, qdf_nbuf_t msdu_list, struct cdp_tx_exception_metadata *tx_exc_metadata); @@ -637,6 +735,11 @@ typedef bool (*ol_txrx_tx_flow_control_is_pause_fp)(void *osif_dev); */ typedef QDF_STATUS(*ol_txrx_rx_fp)(void *osif_dev, qdf_nbuf_t msdu_list); +typedef QDF_STATUS(*ol_txrx_fisa_rx_fp)(void *soc, + void *dp_vdev, + qdf_nbuf_t msdu_list); + +typedef QDF_STATUS(*ol_txrx_fisa_flush_fp)(void *soc, int ring_num); /** * ol_txrx_rx_flush_fp - receive function to hand batches of data * frames from txrx to OS shim @@ -682,12 +785,12 @@ typedef QDF_STATUS(*ol_txrx_get_key_fp)(void *osif_dev, uint8_t *key_buf, uint8_ * @osif_dev - the virtual device's OS shim object * @list_head - poniter to head of receive packet queue to decap * @list_tail - poniter to tail of receive packet queue to decap - * @peer - Peer handler + * @peer_mac - mac address of peer handler */ typedef QDF_STATUS(*ol_txrx_rsim_rx_decap_fp)(void *osif_dev, qdf_nbuf_t *list_head, qdf_nbuf_t *list_tail, - struct cdp_peer *peer); + uint8_t *peer_mac); /* ol_txrx_rx_fp - external tx free function to read per packet stats and * free tx buffer externally @@ -732,10 +835,11 @@ typedef void (*ol_txrx_stats_callback)(void *ctxt, * ol_txrx_pktdump_cb - callback for packet dump feature */ typedef void (*ol_txrx_pktdump_cb)(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, - qdf_nbuf_t netbuf, - uint8_t status, - uint8_t type); + uint8_t pdev_id, + uint8_t vdev_id, + qdf_nbuf_t netbuf, + uint8_t status, + uint8_t type); /** * ol_txrx_ops - (pointers to) the functions used for tx and rx @@ -812,6 +916,8 @@ struct ol_txrx_ops { ol_txrx_rx_mon_fp mon; ol_txrx_stats_rx_fp stats_rx; ol_txrx_rsim_rx_decap_fp rsim_rx_decap; + ol_txrx_fisa_rx_fp osif_fisa_rx; + ol_txrx_fisa_flush_fp osif_fisa_flush; } rx; /* proxy arp function pointer - specified by OS shim, stored by txrx */ ol_txrx_proxy_arp_fp proxy_arp; @@ -865,6 +971,17 @@ struct cdp_soc_t { struct ol_if_ops *ol_ops; }; +/* + * cdp_peer_param_type: different types of parameters + * to set values in peer + * @CDP_CONFIG_NAWDS: Enable nawds mode + * @CDP_CONFIG_NAC: Enable nac + */ +enum cdp_peer_param_type { + CDP_CONFIG_NAWDS, + CDP_CONFIG_NAC, +}; + /* * cdp_pdev_param_type: different types of parameters * to set values in pdev @@ -879,6 +996,22 @@ struct cdp_soc_t { * @CDP_INGRESS_STATS: Accumulate ingress statistics * @CDP_OSIF_DROP: Accumulate drops in OSIF layer * @CDP_CONFIG_ENH_RX_CAPTURE: Enable enhanced RX capture + * @CDP_CONFIG_ENH_TX_CAPTURE: Enable enhanced TX capture + * @CDP_CONFIG_HMMC_TID_OVERRIDE: Enable hmmc tid override + * @CDP_CONFIG_HMMC_TID_VALUE: set hmmc tid value + * @CDP_CONFIG_TX_CAPTURE: set tx capture + * @CDP_CHAN_NOISE_FLOOR: set channel noise floor + * @CDP_CONFIG_VOW: set/get vow config + * @CDP_TIDQ_OVERRIDE: set/get tid queue override + * @CDP_TIDMAP_PRTY: set/get tid map prty + * @CDP_TX_PENDING: get tx pending + * @CDP_FILTER_NEIGH_PEERS: filter neighbour peers + * @CDP_FILTER_UCAST_DATA: filter unicast data + * @CDP_FILTER_MCAST_DATA: filter multicast data + * @CDP_FILTER_NO_DATA: filter no data + * @CDP_MONITOR_CHANNEL: monitor channel + * @CDP_MONITOR_FREQUENCY: monitor frequency + * @CDP_CONFIG_BSS_COLOR: configure bss color */ enum cdp_pdev_param_type { CDP_CONFIG_DEBUG_SNIFFER, @@ -892,9 +1025,145 @@ enum cdp_pdev_param_type { CDP_INGRESS_STATS, CDP_OSIF_DROP, CDP_CONFIG_ENH_RX_CAPTURE, + CDP_CONFIG_ENH_TX_CAPTURE, + CDP_CONFIG_HMMC_TID_OVERRIDE, + CDP_CONFIG_HMMC_TID_VALUE, CDP_CONFIG_TX_CAPTURE, + CDP_CHAN_NOISE_FLOOR, + CDP_CONFIG_VOW, + CDP_TIDQ_OVERRIDE, + CDP_TIDMAP_PRTY, + CDP_TX_PENDING, + CDP_FILTER_NEIGH_PEERS, + CDP_FILTER_UCAST_DATA, + CDP_FILTER_MCAST_DATA, + CDP_FILTER_NO_DATA, + CDP_MONITOR_CHANNEL, + CDP_MONITOR_FREQUENCY, + CDP_CONFIG_BSS_COLOR, }; +/* + * cdp_config_param_type: union of different types of parameters + * to set values into dp handles. + * + * @cdp_peer_param_nawds: Enable nawds mode + * @cdp_peer_param_nac: Enable nac + * + * @cdp_vdev_param_nawds: set nawds enable/disable + * @cdp_vdev_param_mcast_en: enable/disable multicast enhancement + * @cdp_vdev_param_wds: wds sta + * @cdp_vdev_param_mec: MEC enable flags + * @cdp_vdev_param_proxysta: proxy sta + * @cdp_vdev_param_tdls_flags: tdls link flags + * @cdp_vdev_param_ap_brdg_en: set ap_bridging enable/disable + * @cdp_vdev_param_cipher_en: set cipher type based on security + * @cdp_vdev_param_qwrap_isolation: qwrap isolation mode + * @cdp_vdev_param_tx_encap: tx encap type + * @cdp_vdev_param_rx_decap: rx decap type + * @cdp_vdev_param_mesh_rx_filter: set mesh rx filter + * @cdp_vdev_param_tidmap_prty: set tid vdev prty + * @cdp_vdev_param_tidmap_tbl_id: set tidmap table id + * @cdp_vdev_param_mesh_mode: set mesh mode + * @cdp_vdev_param_safe_mode: set safe mode + * @cdp_vdev_param_drop_unenc: set drop unencrypted flag + * + * @cdp_pdev_param_dbg_snf: Enable debug sniffer feature + * @cdp_pdev_param_bpr_enable: Enable bcast probe feature + * @cdp_pdev_param_primary_radio: Configure radio as primary + * @cdp_pdev_param_en_perpkt_txstats: Enable per packet statistics + * @cdp_pdev_param_igmpmld_override: Override IGMP/MLD + * @cdp_pdev_param_igmpmld_tid: TID value when igmmld_override is set + * @cdp_pdev_param_arp_dbg_conf: Enable ARP debug + * @cdp_pdev_param_cptr_latcy: Capture time latency + * @cdp_pdev_param_ingrs_stats: Accumulate ingress statistics + * @cdp_pdev_param_osif_drop: Accumulate drops in OSIF layer + * @cdp_pdev_param_en_rx_cap: Enable enhanced RX capture + * @cdp_pdev_param_en_tx_cap: Enable enhanced TX capture + * @cdp_pdev_param_hmmc_tid_ovrd: Enable hmmc tid override + * @cdp_pdev_param_hmmc_tid: set hmmc tid value + * @cdp_pdev_param_tx_capture: set tx capture + * @cdp_pdev_param_chn_noise_flr: set channel noise floor + * @cdp_pdev_param_cfg_vow: set/get vow config + * @cdp_pdev_param_tidq_override: set/get tid queue override + * @cdp_pdev_param_mon_freq: set monitor frequency + * @cdp_pdev_param_bss_color: configure bss color + * @cdp_pdev_param_tidmap_prty: set/get tid map prty + * @cdp_pdev_param_tx_pending: get tx pending + * @cdp_pdev_param_fltr_neigh_peers: filter neighbour peers + * @cdp_pdev_param_fltr_ucast: filter unicast data + * @cdp_pdev_param_fltr_mcast: filter multicast data + * @cdp_pdev_param_fltr_none: filter no data + * @cdp_pdev_param_monitor_chan: monitor channel + * + * @cdp_psoc_param_en_rate_stats: set rate stats enable/disable + * @cdp_psoc_param_en_nss_cfg: set nss cfg + * + * @cdp_enable_tx_checksum: Flag to specify if HW Tx checksum enabled + */ +typedef union cdp_config_param_t { + /* peer params */ + bool cdp_peer_param_nawds; + uint8_t cdp_peer_param_nac; + + /* vdev params */ + bool cdp_vdev_param_wds; + bool cdp_vdev_param_mec; + bool cdp_vdev_param_nawds; + bool cdp_vdev_param_proxysta; + bool cdp_vdev_param_tdls_flags; + bool cdp_vdev_param_ap_brdg_en; + bool cdp_vdev_param_qwrap_isolation; + bool cdp_vdev_param_update_multipass; + uint8_t cdp_vdev_param_da_war; + uint8_t cdp_vdev_param_mcast_en; + uint8_t cdp_vdev_param_tidmap_prty; + uint8_t cdp_vdev_param_tidmap_tbl_id; + uint32_t cdp_vdev_param_aging_tmr; + uint32_t cdp_vdev_param_cipher_en; + uint32_t cdp_vdev_param_tx_encap; + uint32_t cdp_vdev_param_rx_decap; + uint32_t cdp_vdev_param_mesh_rx_filter; + uint32_t cdp_vdev_param_mesh_mode; + uint32_t cdp_vdev_param_safe_mode; + uint32_t cdp_vdev_param_drop_unenc; + + /* pdev params */ + bool cdp_pdev_param_cptr_latcy; + bool cdp_pdev_param_hmmc_tid_ovrd; + bool cdp_pdev_param_fltr_neigh_peers; + bool cdp_pdev_param_cfg_vow; + bool cdp_pdev_param_fltr_mcast; + bool cdp_pdev_param_fltr_none; + bool cdp_pdev_param_fltr_ucast; + uint8_t cdp_pdev_param_primary_radio; + uint8_t cdp_pdev_param_en_rx_cap; + uint8_t cdp_pdev_param_en_tx_cap; + uint8_t cdp_pdev_param_tx_capture; + uint8_t cdp_pdev_param_hmmc_tid; + uint8_t cdp_pdev_param_tidmap_prty; + uint8_t cdp_pdev_param_igmpmld_override; + uint8_t cdp_pdev_param_igmpmld_tid; + uint8_t cdp_pdev_param_arp_dbg_conf; + uint8_t cdp_pdev_param_tidq_override; + uint8_t cdp_pdev_param_bss_color; + uint16_t cdp_pdev_param_chn_noise_flr; + qdf_freq_t cdp_pdev_param_mon_freq; + int cdp_pdev_param_dbg_snf; + int cdp_pdev_param_bpr_enable; + int cdp_pdev_param_monitor_chan; + uint32_t cdp_pdev_param_ingrs_stats; + uint32_t cdp_pdev_param_osif_drop; + uint32_t cdp_pdev_param_en_perpkt_txstats; + uint32_t cdp_pdev_param_tx_pending; + + /* psoc params */ + bool cdp_psoc_param_en_rate_stats; + int cdp_psoc_param_en_nss_cfg; + + bool cdp_enable_tx_checksum; +} cdp_config_param_type; + /** * cdp_rx_enh_capture_mode - Rx enhanced capture modes * @CDP_RX_ENH_CAPTURE_DISABLED: Disable Rx enhance capture @@ -907,6 +1176,28 @@ enum cdp_rx_enh_capture_mode { CDP_RX_ENH_CAPTURE_MPDU_MSDU, }; +/** + * cdp_rx_enh_capture_peer - Rx enhanced capture peer filtering + * @CDP_RX_ENH_CAPTURE_PEER_DISABLED: Disable Rx ENH capture peer filtering + * @CDP_RX_ENH_CAPTURE_PEER_ENABLED: Enable Rx ENH capture peer filtering + */ +enum cdp_rx_enh_capture_peer { + CDP_RX_ENH_CAPTURE_PEER_DISABLED = 0, + CDP_RX_ENH_CAPTURE_PEER_ENABLED, +}; + +/** + * cdp_tx_enh_capture_mode - Tx enhanced capture modes + * @CDP_TX_ENH_CAPTURE_DISABLED: Disable Tx enhance capture for all peers + * @CDP_TX_ENH_CAPTURE_ENABLE_ALL_PEERS: Enable tx capture for all peers + * @CDP_TX_ENH_CAPTURE_ENDIS_PER_PEER: Enable/disable per peer as necessary + */ +enum cdp_tx_enh_capture_mode { + CDP_TX_ENH_CAPTURE_DISABLED = 0, + CDP_TX_ENH_CAPTURE_ENABLE_ALL_PEERS, + CDP_TX_ENH_CAPTURE_ENDIS_PER_PEER, +}; + /* * enum cdp_pdev_bpr_param - different types of parameters * to set value in pdev @@ -932,6 +1223,14 @@ enum cdp_pdev_bpr_param { * @CDP_ENABLE_AP_BRIDGE: set ap_bridging enable/disable * @CDP_ENABLE_CIPHER : set cipher type based on security * @CDP_ENABLE_QWRAP_ISOLATION: qwrap isolation mode + * @CDP_TX_ENCAP_TYPE: tx encap type + * @CDP_RX_DECAP_TYPE: rx decap type + * @CDP_MESH_RX_FILTER: set mesh rx filter + * @CDP_TID_VDEV_PRTY: set tid vdev prty + * @CDP_TIDMAP_TBL_ID: set tidmap table id + * @CDP_MESH_MODE: set mesh mode + * @CDP_SAFEMODE: set safe mode + * @CDP_DROP_UNENC: set drop unencrypted flag */ enum cdp_vdev_param_type { CDP_ENABLE_NAWDS, @@ -944,7 +1243,30 @@ enum cdp_vdev_param_type { CDP_CFG_WDS_AGING_TIMER, CDP_ENABLE_AP_BRIDGE, CDP_ENABLE_CIPHER, - CDP_ENABLE_QWRAP_ISOLATION + CDP_ENABLE_QWRAP_ISOLATION, + CDP_UPDATE_MULTIPASS, + CDP_TX_ENCAP_TYPE, + CDP_RX_DECAP_TYPE, + CDP_MESH_RX_FILTER, + CDP_TID_VDEV_PRTY, + CDP_TIDMAP_TBL_ID, +#ifdef MESH_MODE_SUPPORT + CDP_MESH_MODE, +#endif + CDP_SAFEMODE, + CDP_DROP_UNENC, + CDP_ENABLE_CSUM, +}; + +/* + * cdp_psoc_param_type: different types of parameters + * to set values in psoc + * @CDP_ENABLE_RATE_STATS: set rate stats enable/disable + * @CDP_SET_NSS_CFG: set nss cfg + */ +enum cdp_psoc_param_type { + CDP_ENABLE_RATE_STATS, + CDP_SET_NSS_CFG, }; #define TXRX_FW_STATS_TXSTATS 1 @@ -1158,11 +1480,63 @@ struct cdp_tx_sojourn_stats { struct cdp_stats_cookie *cookie; }; +/** + * struct cdp_delayed_tx_completion_ppdu_user - Delayed Tx PPDU completion + * per-user information + * @frame_ctrl: frame control field in 802.11 header + * @qos_ctrl: QoS control field in 802.11 header + * @mpdu_tried: number of mpdus tried + * @ltf_size: ltf_size + * @stbc: stbc + * @he_re: he_re (range extension) + * @txbf: txbf + * @bw: Transmission bandwidth + * + * + * + * + * @nss: NSS 1,2, ...8 + * @mcs: MCS index + * @preamble: preamble + * @gi: guard interval 800/400/1600/3200 ns + * @dcm: dcm + * @ldpc: ldpc + * @ru_start: RU start index + * @ru_tones: RU tones length + * @is_mcast: MCAST or UCAST + * @user_pos: user position + * @mu_group_id: mu group id + */ +struct cdp_delayed_tx_completion_ppdu_user { + uint32_t frame_ctrl:16, + qos_ctrl:16; + uint32_t mpdu_tried_ucast:16, + mpdu_tried_mcast:16; + uint32_t ltf_size:2, + stbc:1, + he_re:1, + txbf:4, + bw:4, + nss:4, + mcs:4, + preamble:4, + gi:4, + dcm:1, + ldpc:1, + delayed_ba:1; + uint16_t ru_start; + uint16_t ru_tones; + bool is_mcast; + uint32_t user_pos; + uint32_t mu_group_id; +}; + /** * struct cdp_tx_completion_ppdu_user - Tx PPDU completion per-user information * @completion_status: completion status - OK/Filter/Abort/Timeout * @tid: TID number * @peer_id: Peer ID + * @ba_size: Block-Ack size * @frame_ctrl: frame control field in 802.11 header * @qos_ctrl: QoS control field in 802.11 header * @mpdu_tried: number of mpdus tried @@ -1206,12 +1580,20 @@ struct cdp_tx_sojourn_stats { * @cookie: cookie to used by upper layer * @is_ppdu_cookie_valid : Indicates that ppdu_cookie is valid * @ppdu_cookie: 16-bit ppdu_cookie + * @sa_is_training: smart antenna training packets indication + * @rssi_chain: rssi chain per bandwidth + * @sa_tx_antenna: antenna in which packet is transmitted + * @sa_max_rates: smart antenna tx feedback info max rates + * @sa_goodput: smart antenna tx feedback info goodput + * @current_rate_per: Moving average per + * @last_enq_seq: last equeue sequence number */ struct cdp_tx_completion_ppdu_user { uint32_t completion_status:8, tid:8, peer_id:16; uint8_t mac_addr[6]; + uint16_t ba_size; uint32_t frame_ctrl:16, qos_ctrl:16; uint32_t mpdu_tried_ucast:16, @@ -1220,7 +1602,7 @@ struct cdp_tx_completion_ppdu_user { uint16_t mpdu_failed:16; uint32_t long_retries:4, short_retries:4, - tx_ratecode:8, + tx_ratecode:16, is_ampdu:1, ppdu_type:5; uint32_t success_bytes; @@ -1264,6 +1646,32 @@ struct cdp_tx_completion_ppdu_user { struct cdp_stats_cookie *cookie; uint8_t is_ppdu_cookie_valid; uint16_t ppdu_cookie; + uint8_t sa_is_training; + uint32_t rssi_chain[CDP_RSSI_CHAIN_LEN]; + uint32_t sa_tx_antenna; + /*Max rates for BW: 20MHZ, 40MHZ and 80MHZ and 160MHZ + * |---------------------------------------| + * | 16 bits | 16 bits | 16 bits | 16 bits | + * | BW-1 | BW-2 | BW-3 | BW-4 | + * | /\ \ | + * | / \ \ | + * | / \ \ | + * | / \ \ | + * | / \ \ | + * | / \ \ | + * |/ \ \ | + * |[11|8] [5|8] \ | + * | BW1 PADDED \ | + * |---------------------------------------| + */ + uint16_t sa_max_rates[CDP_NUM_SA_BW]; + uint32_t sa_goodput; + /* below field is used to calculate goodput in non-training period + * Note: As host is exposing goodput and hence current_rate_per is + * of no use. It is just for Host computation. + */ + uint32_t current_rate_per; + uint32_t last_enq_seq; }; /** @@ -1289,6 +1697,10 @@ struct cdp_tx_completion_ppdu_user { * @mcs: MCS index * @preamble: preamble * @gi: guard interval 800/400/1600/3200 ns + * @resp_type: response type + * @mprot_type: medium protection type + * @rts_success: rts success + * @rts failure: rts failure * @channel: frequency * @channel_num: channel number * @ack_rssi: ack rssi @@ -1301,6 +1713,9 @@ struct cdp_tx_completion_ppdu_user { * @ba_start_seq: Block Ack sequence number * @ba_bitmap: Block Ack bitmap * @ppdu_cookie: 16-bit ppdu_cookie + * @long_retries: long retries + * @short_retries: short retries + * @completion_status: completion status - OK/Filter/Abort/Timeout */ struct cdp_tx_indication_mpdu_info { uint32_t ppdu_id; @@ -1326,21 +1741,44 @@ struct cdp_tx_indication_mpdu_info { uint32_t tx_rate; uint8_t mac_address[QDF_MAC_ADDR_SIZE]; uint8_t bss_mac_address[QDF_MAC_ADDR_SIZE]; - uint32_t ppdu_start_timestamp; - uint32_t ppdu_end_timestamp; + uint64_t ppdu_start_timestamp; + uint64_t ppdu_end_timestamp; uint32_t ba_start_seq; uint32_t ba_bitmap[CDP_BA_256_BIT_MAP_SIZE_DWORDS]; uint16_t ppdu_cookie; + uint16_t long_retries:4, + short_retries:4, + completion_status:8; + uint16_t resp_type:4, + mprot_type:3, + rts_success:1, + rts_failure:1; }; /** * struct cdp_tx_indication_info - Tx capture information * @mpdu_info: Tx MPDU completion information * @mpdu_nbuf: reconstructed mpdu packet + * @ppdu_desc: tx completion ppdu */ struct cdp_tx_indication_info { struct cdp_tx_indication_mpdu_info mpdu_info; qdf_nbuf_t mpdu_nbuf; + struct cdp_tx_completion_ppdu *ppdu_desc; +}; + +/** + * struct cdp_tx_mgmt_comp_info - Tx mgmt comp info + * @ppdu_id: ppdu_id + * @is_sgen_pkt: payload recevied from wmi or htt path + * @retries_count: retries count + * @tx_tsf: 64 bit timestamp + */ +struct cdp_tx_mgmt_comp_info { + uint32_t ppdu_id; + bool is_sgen_pkt; + uint16_t retries_count; + uint64_t tx_tsf; }; /** @@ -1349,39 +1787,78 @@ struct cdp_tx_indication_info { * @ppdu_id: PPDU Id * @ppdu_seq_id: ppdu sequence id for sojourn stats * @vdev_id: VAP Id + * @bar_num_users: BA response user count, based on completion common TLV * @num_users: Number of users + * @pending_retries: pending MPDUs (retries) + * @drop_reason: drop reason from flush status + * @is_flush: is_flush is set based on flush tlv + * @flow_type: tx flow type from flush status + * @queue_type: queue type from flush status * @num_mpdu: Number of MPDUs in PPDU * @num_msdu: Number of MSDUs in PPDU * @frame_type: frame SU or MU + * @htt_frame_type: frame type from htt * @frame_ctrl: frame control of 80211 header * @channel: Channel informartion + * @resp_type: response type + * @mprot_type: medium protection type + * @rts_success: rts success + * @rts failure: rts failure + * @phymode: phy mode * @ack_rssi: RSSI value of last ack packet (units=dB above noise floor) * @tx_duration: PPDU airtime * @ppdu_start_timestamp: TSF at PPDU start * @ppdu_end_timestamp: TSF at PPDU end * @ack_timestamp: TSF at the reception of ACK + * @delayed_ba: Delayed ba flag + * @beam_change: beam change bit in ppdu for he-information + * @bss_color: 6 bit value for full bss color * @user: per-User stats (array of per-user structures) * @mpdu_q: queue of mpdu in a ppdu + * @mpdus: MPDU list based on enqueue sequence bitmap + * @bar_ppdu_id: BAR ppdu_id + * @bar_tx_duration: BAR tx duration + * @bar_ppdu_start_timestamp: BAR start timestamp + * @bar_ppdu_end_timestamp: BAR end timestamp */ struct cdp_tx_completion_ppdu { uint32_t ppdu_id; uint32_t ppdu_seq_id; uint16_t vdev_id; + uint16_t bar_num_users; uint32_t num_users; uint8_t last_usr_index; + uint32_t pending_retries; + uint32_t drop_reason; + uint32_t is_flush:1, + flow_type:8, + queue_type:8; uint32_t num_mpdu:9, num_msdu:16; uint16_t frame_type; + uint16_t htt_frame_type; uint16_t frame_ctrl; uint16_t channel; + uint16_t resp_type:4, + mprot_type:3, + rts_success:1, + rts_failure:1; uint16_t phy_mode; uint32_t ack_rssi; uint32_t tx_duration; - uint32_t ppdu_start_timestamp; - uint32_t ppdu_end_timestamp; - uint32_t ack_timestamp; + uint64_t ppdu_start_timestamp; + uint64_t ppdu_end_timestamp; + uint64_t ack_timestamp; + bool delayed_ba; + uint8_t beam_change; + uint8_t bss_color; struct cdp_tx_completion_ppdu_user user[CDP_MU_MAX_USERS]; qdf_nbuf_queue_t mpdu_q; + qdf_nbuf_t *mpdus; + uint32_t bar_ppdu_id; + uint32_t bar_tx_duration; + uint32_t bar_ppdu_start_timestamp; + uint32_t bar_ppdu_end_timestamp; }; /** @@ -1392,6 +1869,8 @@ struct cdp_tx_completion_ppdu { * @tx_dropped: Tx dropped is same as tx errors as above * @rx_packets: Rx total packets transmitted * @rx_bytes : Rx total bytes transmitted + * @rx_errors : Rx erros + * @rx_dropped: Rx dropped stats */ struct cdp_dev_stats { uint32_t tx_packets; @@ -1400,6 +1879,8 @@ struct cdp_dev_stats { uint32_t tx_dropped; uint32_t rx_packets; uint32_t rx_bytes; + uint32_t rx_errors; + uint32_t rx_dropped; }; /** @@ -1461,6 +1942,71 @@ struct cdp_tx_completion_msdu { struct cdp_rate_stats extd; }; +/** + * struct cdp_rx_stats_ppdu_user -- per user RX stats + * @peer_id: Peer ID + * @vdev_id: VAP ID + * @is_ampdu: mpdu aggregate or non-aggregate? + * @mu_ul_info_valid: MU UL info valid + * @ofdma_ru_start_index: RU index number(0-73) + * @ofdma_ru_width: size of RU in units of 1(26tone)RU + * @nss: NSS 1,2, ...8 + * @mcs: MCS index + * @user_index: user ID in multi-user case + * @ast_index: ast index in multi-user case + * @tid: TID number + * @num_msdu: Number of MSDUs in PPDU + * @udp_msdu_count: Number of UDP MSDUs in PPDU + * @tcp_msdu_count: Number of TCP MSDUs in PPDU + * @other_msdu_count: Number of MSDUs other than UDP and TCP MSDUs in PPDU + * @frame_control: frame control field + * @frame_control_info_valid: frame_control valid + * @data_sequence_control_info_valid: data_sequence_control_info valid + * @first_data_seq_ctrl: Sequence control field of first data frame + * @preamble: preamble + * @ht_flag: ht flag + * @vht_flag: vht flag + * @he_re: he_re (range extension) + * @mpdu_cnt_fcs_ok: Number of MPDUs in PPDU with fcs ok + * @mpdu_cnt_fcs_err: Number of MPDUs in PPDU with fcs err + * @mpdu_fcs_ok_bitmap - MPDU with fcs ok bitmap + * @retried - number of retries + * @mac_addr: Peer MAC Address + */ +struct cdp_rx_stats_ppdu_user { + uint16_t peer_id; + uint8_t vdev_id; + bool is_ampdu; + uint32_t mu_ul_info_valid:1, + ofdma_ru_start_index:7, + ofdma_ru_width:7, + nss:4, + mcs:4; + /* user id */ + uint8_t user_index; + uint32_t ast_index; + uint32_t tid; + uint32_t num_msdu; + uint16_t tcp_msdu_count; + uint16_t udp_msdu_count; + uint16_t other_msdu_count; + uint16_t frame_control; + uint8_t frame_control_info_valid; + uint8_t data_sequence_control_info_valid; + uint16_t first_data_seq_ctrl; + uint32_t preamble_type; + uint16_t ht_flags; + uint16_t vht_flags; + uint16_t he_flags; + uint32_t mpdu_cnt_fcs_ok; + uint32_t mpdu_cnt_fcs_err; + uint32_t mpdu_fcs_ok_bitmap[QDF_MON_STATUS_MPDU_FCS_BMAP_NWORDS]; + uint32_t mpdu_ok_byte_count; + uint32_t mpdu_err_byte_count; + uint32_t retries; + uint8_t mac_addr[QDF_MAC_ADDR_SIZE]; +}; + /** * struct cdp_rx_indication_ppdu - Rx PPDU indication structure * @ppdu_id: PPDU Id @@ -1505,6 +2051,9 @@ struct cdp_tx_completion_msdu { * @rix: rate index * @rssi_chain: rssi chain per nss per bw * @cookie: cookie to used by upper layer + * @user: per user stats in MU-user case + * @nf: noise floor + * @per_chain_rssi: rssi per antenna */ struct cdp_rx_indication_ppdu { uint32_t ppdu_id; @@ -1551,11 +2100,21 @@ struct cdp_rx_indication_ppdu { uint32_t retries; uint32_t rx_byte_count; - uint8_t rx_ratecode; + uint16_t rx_ratecode; uint8_t fcs_error_mpdus; uint16_t frame_ctrl; - uint32_t rssi_chain[SS_COUNT][MAX_BW]; + int8_t rssi_chain[SS_COUNT][MAX_BW]; struct cdp_stats_cookie *cookie; + struct cdp_rx_su_evm_info evm_info; + uint32_t rx_antenna; + uint8_t num_users; + struct cdp_rx_stats_ppdu_user user[CDP_MU_MAX_USERS]; + uint32_t nf; + uint8_t per_chain_rssi[MAX_CHAIN]; + uint8_t is_mcast_bcast; +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) + struct cdp_rx_ppdu_cfr_info cfr_info; +#endif }; /** @@ -1587,7 +2146,11 @@ struct cdp_rx_indication_msdu { * @lro_enable: Enable/Disable LRO * @gro_enable: Enable/Disable GRO * @flow_steering_enable: Enable/Disable Rx Hash based flow steering - * @tcp_Udp_ChecksumOffload: Enable/Disable tcp-Udp checksum Offload + * @p2p_tcp_udp_checksumoffload: Enable/Disable TCP/UDP Checksum Offload for P2P + * @nan_tcp_udp_checksumoffload: Enable/Disable TCP/UDP Checksum Offload for NAN + * @tcp_udp_checksumoffload: Enable/Disable TCP/UDP Checksum Offload + * @legacy_mode_checksumoffload_disable: Disable TCP/UDP Checksum Offload for + * legacy modes. * @napi_enable: Enable/Disable Napi * @ipa_enable: Flag indicating if IPA is enabled or not * @tx_flow_stop_queue_threshold: Value to Pause tx queues @@ -1602,7 +2165,10 @@ struct cdp_config_params { unsigned int lro_enable:1; unsigned int gro_enable:1; unsigned int flow_steering_enable:1; + unsigned int p2p_tcp_udp_checksumoffload:1; + unsigned int nan_tcp_udp_checksumoffload:1; unsigned int tcp_udp_checksumoffload:1; + unsigned int legacy_mode_checksumoffload_disable:1; unsigned int napi_enable:1; unsigned int ipa_enable:1; /* Set when QCA_LL_TX_FLOW_CONTROL_V2 is enabled */ @@ -1657,14 +2223,41 @@ struct cdp_monitor_filter { }; /** - * cdp_dp_cfg - dp ini config enum + * enum cdp_dp_cfg - CDP ENUMs to get to DP configation + * @cfg_dp_enable_data_stall: context passed to be used by consumer + * @cfg_dp_enable_p2p_ip_tcp_udp_checksum_offload: get P2P checksum config + * @cfg_dp_enable_nan_ip_tcp_udp_checksum_offload: get NAN TX checksum config + * @cfg_dp_enable_ip_tcp_udp_checksum_offload: get TX checksum config for others + * @cfg_dp_tso_enable: get TSO enable config + * @cfg_dp_lro_enable: get LRO enable config + * @cfg_dp_gro_enable: get GRP enable config + * @cfg_dp_tc_based_dyn_gro_enable: get TC based dynamic gro enable config + * @cfg_dp_tc_ingress_prio: priority value to be checked for tc filters + * @cfg_dp_tx_flow_start_queue_offset: get DP TX flow start queue offset + * @cfg_dp_tx_flow_stop_queue_threshold: get DP TX flow stop queue threshold + * @cfg_dp_ipa_uc_tx_buf_size: get IPA TX buf size config + * @cfg_dp_ipa_uc_tx_partition_base: get IPA UC TX partition base config + * @cfg_dp_ipa_uc_rx_ind_ring_count: get IPA rx indication ring count config + * @cfg_dp_enable_flow_steering: get flow steerint enable config + * @cfg_dp_reorder_offload_supported: get reorder offload support config + * @cfg_dp_ce_classify_enable: get CE classify enable config + * @cfg_dp_disable_intra_bss_fwd: get intra bss fwd config + * @cfg_dp_pktlog_buffer_size: get packet log buffer size config + * @cfg_dp_wow_check_rx_pending: get wow rx pending frame check config */ enum cdp_dp_cfg { cfg_dp_enable_data_stall, + cfg_dp_enable_p2p_ip_tcp_udp_checksum_offload, + cfg_dp_enable_nan_ip_tcp_udp_checksum_offload, cfg_dp_enable_ip_tcp_udp_checksum_offload, + /* Disable checksum offload for legacy modes */ + cfg_dp_disable_legacy_mode_csum_offload, cfg_dp_tso_enable, cfg_dp_lro_enable, cfg_dp_gro_enable, + cfg_dp_sg_enable, + cfg_dp_tc_based_dyn_gro_enable, + cfg_dp_tc_ingress_prio, cfg_dp_tx_flow_start_queue_offset, cfg_dp_tx_flow_stop_queue_threshold, cfg_dp_ipa_uc_tx_buf_size, @@ -1675,19 +2268,105 @@ enum cdp_dp_cfg { cfg_dp_ce_classify_enable, cfg_dp_disable_intra_bss_fwd, cfg_dp_pktlog_buffer_size, + cfg_dp_wow_check_rx_pending, }; /** * struct cdp_peer_cookie - cookie used when creating peer - * @peer_id: peer id + * @ctx: context passed to be used by consumer * @mac_addr: MAC address of peer + * @peer_id: peer id + * @pdev_id: pdev_id * @cookie: cookie to be used by consumer - * @ctx: context passed to be used by consumer */ struct cdp_peer_cookie { - uint8_t peer_id; + struct cdp_stats_cookie *ctx; uint8_t mac_addr[QDF_MAC_ADDR_SIZE]; + uint8_t peer_id; + uint8_t pdev_id; uint8_t cookie; - struct cdp_stats_cookie *ctx; +}; + +#ifdef WLAN_SUPPORT_RX_FISA +struct cdp_flow_stats { + uint32_t aggr_count; + uint32_t curr_aggr_count; + uint32_t flush_count; + uint32_t bytes_aggregated; +}; +#else +/** + * cdp_flow_stats - Per-Flow (5-tuple) statistics + * @msdu_count: number of rx msdus matching this flow + * + * HW also includes msdu_byte_count and timestamp, which + * are not currently tracked in SW. + */ +struct cdp_flow_stats { + uint32_t msdu_count; +}; +#endif + +/** + * cdp_flow_fst_operation - RX FST operations allowed + */ +enum cdp_flow_fst_operation { + CDP_FLOW_FST_ENTRY_ADD, + CDP_FLOW_FST_ENTRY_DEL, + CDP_FLOW_FST_RX_BYPASS_ENABLE, + CDP_FLOW_FST_RX_BYPASS_DISABLE +}; + +/** + * cdp_flow_protocol_type - RX FST supported protocol types, mapped to HW spec + */ +enum cdp_flow_protocol_type { + CDP_FLOW_PROTOCOL_TYPE_TCP = 6, + CDP_FLOW_PROTOCOL_TYPE_UDP = 17, +}; + +/** + * cdp_rx_flow_tuple_info - RX flow tuple info used for addition/deletion + * @dest_ip_127_96: destination IP address bit fields 96-127 + * @dest_ip_95_64: destination IP address bit fields 64-95 + * @dest_ip_63_32: destination IP address bit fields 32-63 + * @dest_ip_31_0: destination IP address bit fields 0-31 + * @src_ip_127_96: source IP address bit fields 96-127 + * @src_ip_95_64: source IP address bit fields 64-95 + * @src_ip_63_32: source IP address bit fields 32-63 + * @src_ip_31_0: source IP address bit fields 0-31 + * @dest_port: destination port of flow + * @src_port: source port of flow + * @l4_protocol: protocol type in flow (TCP/UDP) + */ +struct cdp_rx_flow_tuple_info { +#ifdef WLAN_SUPPORT_RX_FISA + uint8_t tuple_populated; +#endif + uint32_t dest_ip_127_96; + uint32_t dest_ip_95_64; + uint32_t dest_ip_63_32; + uint32_t dest_ip_31_0; + uint32_t src_ip_127_96; + uint32_t src_ip_95_64; + uint32_t src_ip_63_32; + uint32_t src_ip_31_0; + uint16_t dest_port; + uint16_t src_port; + uint16_t l4_protocol; +}; + +/** + * cdp_rx_flow_info - RX flow info used for addition/deletion + * @is_addr_ipv4: indicates whether given IP address is IPv4/IPv6 + * @op_code: add/delete/enable/disable operation requested + * @flow_tupe_info: structure containing tuple info + * @fse_metadata: metadata to be set in RX flow + */ +struct cdp_rx_flow_info { + bool is_addr_ipv4; + enum cdp_flow_fst_operation op_code; + struct cdp_rx_flow_tuple_info flow_tuple_info; + uint16_t fse_metadata; }; #endif diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ctrl.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ctrl.h index 187ab87daf68cebfb1c605399c97cae550ab816f..82f7ce6c943950d0f0ae9fdaf7d30443a919aa7b 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ctrl.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ctrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -30,7 +30,7 @@ #include "cdp_txrx_ops.h" static inline int cdp_is_target_ar900b - (ol_txrx_soc_handle soc, struct cdp_vdev *vdev) + (ol_txrx_soc_handle soc) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -43,13 +43,13 @@ static inline int cdp_is_target_ar900b !soc->ops->ctrl_ops->txrx_is_target_ar900b) return 0; - return soc->ops->ctrl_ops->txrx_is_target_ar900b(vdev); + return soc->ops->ctrl_ops->txrx_is_target_ar900b(soc); } /* WIN */ static inline int -cdp_mempools_attach(ol_txrx_soc_handle soc, void *ctrl_pdev) +cdp_mempools_attach(ol_txrx_soc_handle soc) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -62,22 +62,26 @@ cdp_mempools_attach(ol_txrx_soc_handle soc, void *ctrl_pdev) !soc->ops->ctrl_ops->txrx_mempools_attach) return 0; - return soc->ops->ctrl_ops->txrx_mempools_attach(ctrl_pdev); + return soc->ops->ctrl_ops->txrx_mempools_attach(soc); } + +#if defined(ATH_SUPPORT_NAC) || defined(ATH_SUPPORT_NAC_RSSI) /** - * @brief set filter neighbour peers + * @brief update the neighbour peer addresses * @details - * This defines interface function to set neighbour peer filtering. + * This defines interface function to update neighbour peers addresses + * which needs to be filtered * * @param soc - the pointer to soc object - * @param pdev - the pointer physical device object - * @param val - the enable/disable value + * @param vdev_id - id of the pointer to vdev + * @param cmd - add/del entry into peer table + * @param macaddr - the address of neighbour peer * @return - int */ static inline int -cdp_set_filter_neighbour_peers(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, u_int32_t val) +cdp_update_filter_neighbour_peers(ol_txrx_soc_handle soc, + uint8_t vdev_id, uint32_t cmd, uint8_t *macaddr) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -87,114 +91,103 @@ cdp_set_filter_neighbour_peers(ol_txrx_soc_handle soc, } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_set_filter_neighbour_peers) + !soc->ops->ctrl_ops->txrx_update_filter_neighbour_peers) return 0; - return soc->ops->ctrl_ops->txrx_set_filter_neighbour_peers - (pdev, val); + return soc->ops->ctrl_ops->txrx_update_filter_neighbour_peers + (soc, vdev_id, cmd, macaddr); } +#endif /* ATH_SUPPORT_NAC || ATH_SUPPORT_NAC_RSSI*/ /** - * @brief update the neighbour peer addresses + * @brief set the Reo Destination ring for the pdev * @details - * This defines interface function to update neighbour peers addresses - * which needs to be filtered + * This will be used to configure the Reo Destination ring for this pdev. * - * @param soc - the pointer to soc object - * @param vdev - the pointer to vdev - * @param cmd - add/del entry into peer table - * @param macaddr - the address of neighbour peer - * @return - int + * @param soc - pointer to the soc + * @param pdev_id - id of the data physical device object + * @param val - the Reo destination ring index (1 to 4) + * @return - QDF_STATUS */ -static inline int -cdp_update_filter_neighbour_peers(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, uint32_t cmd, uint8_t *macaddr) +static inline QDF_STATUS +cdp_set_pdev_reo_dest(ol_txrx_soc_handle soc, + uint8_t pdev_id, enum cdp_host_reo_dest_ring val) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return 0; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_update_filter_neighbour_peers) - return 0; + !soc->ops->ctrl_ops->txrx_set_pdev_reo_dest) + return QDF_STATUS_E_FAILURE; - return soc->ops->ctrl_ops->txrx_update_filter_neighbour_peers - (vdev, cmd, macaddr); + return soc->ops->ctrl_ops->txrx_set_pdev_reo_dest + (soc, pdev_id, val); } /** - * @brief set the safemode of the device - * @details - * This flag is used to bypass the encrypt and decrypt processes when send and - * receive packets. It works like open AUTH mode, HW will treate all packets - * as non-encrypt frames because no key installed. For rx fragmented frames, - * it bypasses all the rx defragmentaion. + * @brief get the Reo Destination ring for the pdev * - * @param vdev - the data virtual device object - * @param val - the safemode state - * @return - void + * @param soc - pointer to the soc + * @param pdev_id - id of physical device object + * @return - the Reo destination ring index (1 to 4), 0 if not supported. */ -static inline void -cdp_set_safemode(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, u_int32_t val) +static inline enum cdp_host_reo_dest_ring +cdp_get_pdev_reo_dest(ol_txrx_soc_handle soc, uint8_t pdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return; + return cdp_host_reo_dest_ring_unknown; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_set_safemode) - return; + !soc->ops->ctrl_ops->txrx_get_pdev_reo_dest) + return cdp_host_reo_dest_ring_unknown; - soc->ops->ctrl_ops->txrx_set_safemode(vdev, val); + return soc->ops->ctrl_ops->txrx_get_pdev_reo_dest(soc, pdev_id); } + +/* Is this similar to ol_txrx_peer_state_update() in MCL */ /** - * @brief configure the drop unencrypted frame flag + * @brief Update the authorize peer object at association time * @details - * Rx related. When set this flag, all the unencrypted frames - * received over a secure connection will be discarded + * For the host-based implementation of rate-control, it + * updates the peer/node-related parameters within rate-control + * context of the peer at association. + * + * @param soc - pointer to the soc + * @param vdev_id - id of the pointer to vdev + * @param peer_mac - mac address of the node's object + * @authorize - either to authorize or unauthorize peer * - * @param vdev - the data virtual device object - * @param val - flag - * @return - void + * @return QDF_STATUS */ -static inline void -cdp_set_drop_unenc(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, u_int32_t val) +static inline QDF_STATUS +cdp_peer_authorize(ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac, + u_int32_t authorize) { 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_E_FAILURE; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_set_drop_unenc) - return; + !soc->ops->ctrl_ops->txrx_peer_authorize) + return QDF_STATUS_E_FAILURE; - soc->ops->ctrl_ops->txrx_set_drop_unenc(vdev, val); + return soc->ops->ctrl_ops->txrx_peer_authorize + (soc, vdev_id, peer_mac, authorize); } - -/** - * @brief set the Tx encapsulation type of the VDEV - * @details - * This will be used to populate the HTT desc packet type field during Tx - * - * @param vdev - the data virtual device object - * @param val - the Tx encap type (htt_cmn_pkt_type) - * @return - void - */ -static inline void -cdp_set_tx_encap_type(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, enum htt_cmn_pkt_type val) +static inline void cdp_tx_flush_buffers +(ol_txrx_soc_handle soc, uint8_t vdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -204,303 +197,416 @@ cdp_set_tx_encap_type(ol_txrx_soc_handle soc, } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_set_tx_encap_type) + !soc->ops->ctrl_ops->tx_flush_buffers) return; - soc->ops->ctrl_ops->txrx_set_tx_encap_type(vdev, val); + soc->ops->ctrl_ops->tx_flush_buffers(soc, vdev_id); } -/** - * @brief set the Rx decapsulation type of the VDEV - * @details - * This will be used to configure into firmware and hardware which format to - * decap all Rx packets into, for all peers under the VDEV. - * - * @param vdev - the data virtual device object - * @param val - the Rx decap mode (htt_cmn_pkt_type) - * @return - void - */ -static inline void -cdp_set_vdev_rx_decap_type(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, enum htt_cmn_pkt_type val) +static inline QDF_STATUS cdp_txrx_get_vdev_param(ol_txrx_soc_handle soc, + uint8_t vdev_id, + enum cdp_vdev_param_type type, + cdp_config_param_type *val) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); + "%s: Invalid Instance:", __func__); QDF_BUG(0); - return; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_set_vdev_rx_decap_type) - return; + !soc->ops->ctrl_ops->txrx_get_vdev_param) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: callback not registered:", __func__); + return QDF_STATUS_E_FAILURE; + } - soc->ops->ctrl_ops->txrx_set_vdev_rx_decap_type - (vdev, val); + return soc->ops->ctrl_ops->txrx_get_vdev_param(soc, vdev_id, + type, val); } -/** - * @brief get the Rx decapsulation type of the VDEV - * - * @param vdev - the data virtual device object - * @return - the Rx decap type (htt_cmn_pkt_type) - */ -static inline enum htt_cmn_pkt_type -cdp_get_vdev_rx_decap_type(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +static inline QDF_STATUS +cdp_txrx_set_vdev_param(ol_txrx_soc_handle soc, + uint8_t vdev_id, enum cdp_vdev_param_type type, + cdp_config_param_type val) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return 0; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_get_vdev_rx_decap_type) - return 0; + !soc->ops->ctrl_ops->txrx_set_vdev_param) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "NULL vdev params callback"); + return QDF_STATUS_E_FAILURE; + } - return soc->ops->ctrl_ops->txrx_get_vdev_rx_decap_type(vdev); + return soc->ops->ctrl_ops->txrx_set_vdev_param(soc, vdev_id, + type, val); } -/** - * @brief set the Reo Destination ring for the pdev - * @details - * This will be used to configure the Reo Destination ring for this pdev. - * - * @param soc - pointer to the soc - * @param pdev - the data physical device object - * @param val - the Reo destination ring index (1 to 4) - * @return - void - */ -static inline void -cdp_set_pdev_reo_dest(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, enum cdp_host_reo_dest_ring val) +static inline QDF_STATUS +cdp_txrx_set_psoc_param(ol_txrx_soc_handle soc, + enum cdp_psoc_param_type type, + cdp_config_param_type 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_E_FAILURE; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_set_pdev_reo_dest) - return; + !soc->ops->ctrl_ops->txrx_set_psoc_param) + return QDF_STATUS_E_FAILURE; - soc->ops->ctrl_ops->txrx_set_pdev_reo_dest - (pdev, val); + return soc->ops->ctrl_ops->txrx_set_psoc_param(soc, type, val); } -/** - * @brief get the Reo Destination ring for the pdev - * - * @param soc - pointer to the soc - * @param pdev - the data physical device object - * @return - the Reo destination ring index (1 to 4), 0 if not supported. - */ -static inline enum cdp_host_reo_dest_ring -cdp_get_pdev_reo_dest(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +static inline QDF_STATUS +cdp_txrx_get_psoc_param(ol_txrx_soc_handle soc, + enum cdp_psoc_param_type type, + cdp_config_param_type *val) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return cdp_host_reo_dest_ring_unknown; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_get_pdev_reo_dest) - return cdp_host_reo_dest_ring_unknown; + !soc->ops->ctrl_ops->txrx_get_psoc_param) + return QDF_STATUS_E_FAILURE; - return soc->ops->ctrl_ops->txrx_get_pdev_reo_dest(pdev); + return soc->ops->ctrl_ops->txrx_get_psoc_param(soc, type, val); } -/* Is this similar to ol_txrx_peer_state_update() in MCL */ +#ifdef VDEV_PEER_PROTOCOL_COUNT /** - * @brief Update the authorize peer object at association time - * @details - * For the host-based implementation of rate-control, it - * updates the peer/node-related parameters within rate-control - * context of the peer at association. + * cdp_set_vdev_peer_protocol_count() - set per-peer protocol count tracking * - * @param peer - pointer to the node's object - * @authorize - either to authorize or unauthorize peer + * @soc - pointer to the soc + * @vdev - the data virtual device object + * @enable - enable per-peer protocol count + * + * Set per-peer protocol count feature enable * - * @return none + * Return: void */ -static inline void -cdp_peer_authorize(ol_txrx_soc_handle soc, - struct cdp_peer *peer, u_int32_t authorize) +static inline +void cdp_set_vdev_peer_protocol_count(ol_txrx_soc_handle soc, int8_t vdev_id, + bool enable) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); + "%s: Invalid Instance:", __func__); QDF_BUG(0); return; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_peer_authorize) + !soc->ops->ctrl_ops->txrx_enable_peer_protocol_count) return; - soc->ops->ctrl_ops->txrx_peer_authorize - (peer, authorize); + soc->ops->ctrl_ops->txrx_enable_peer_protocol_count(soc, vdev_id, + enable); } -/* Should be ol_txrx_ctrl_api.h */ -static inline void cdp_set_mesh_mode -(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, u_int32_t val) +/** + * cdp_set_vdev_peer_protocol_drop_mask() - set per-peer protocol drop mask + * + * @soc - pointer to the soc + * @vdev - the data virtual device object + * @drop_mask - drop_mask + * + * Set per-peer protocol drop_mask + * + * Return - void + */ +static inline +void cdp_set_vdev_peer_protocol_drop_mask(ol_txrx_soc_handle soc, + int8_t vdev_id, int drop_mask) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); + "%s: Invalid Instance:", __func__); QDF_BUG(0); return; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_set_mesh_mode) + !soc->ops->ctrl_ops->txrx_set_peer_protocol_drop_mask) return; - soc->ops->ctrl_ops->txrx_set_mesh_mode(vdev, val); + soc->ops->ctrl_ops->txrx_set_peer_protocol_drop_mask(soc, vdev_id, + drop_mask); } /** - * @brief set mesh rx filter - * @details based on the bits enabled in the filter packets has to be dropped. + * cdp_is_vdev_peer_protocol_count_enabled() - whether peer-protocol tracking + * enabled * - * @param soc - pointer to the soc - * @param vdev - the data virtual device object - * @param val - value to be set - * @return - void + * @soc - pointer to the soc + * @vdev - the data virtual device object + * + * Get whether peer protocol count feature enabled or not + * + * Return: whether feature enabled or not */ static inline -void cdp_set_mesh_rx_filter(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, uint32_t val) +int cdp_is_vdev_peer_protocol_count_enabled(ol_txrx_soc_handle soc, + int8_t vdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); + "%s: Invalid Instance:", __func__); QDF_BUG(0); - return; + return 0; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_set_mesh_rx_filter) - return; + !soc->ops->ctrl_ops->txrx_is_peer_protocol_count_enabled) + return 0; - soc->ops->ctrl_ops->txrx_set_mesh_rx_filter(vdev, val); + return soc->ops->ctrl_ops->txrx_is_peer_protocol_count_enabled(soc, + vdev_id); } -static inline void cdp_tx_flush_buffers -(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +/** + * cdp_get_peer_protocol_drop_mask() - get per-peer protocol count drop-mask + * + * @soc - pointer to the soc + * @vdev - the data virtual device object + * + * Get peer-protocol-count drop-mask + * + * Return: peer-protocol-count drop-mask + */ +static inline +int cdp_get_peer_protocol_drop_mask(ol_txrx_soc_handle soc, int8_t vdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); + "%s: Invalid Instance:", __func__); QDF_BUG(0); - return; + return 0; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->tx_flush_buffers) - return; + !soc->ops->ctrl_ops->txrx_get_peer_protocol_drop_mask) + return 0; - soc->ops->ctrl_ops->tx_flush_buffers(vdev); + return soc->ops->ctrl_ops->txrx_get_peer_protocol_drop_mask(soc, + vdev_id); } -static inline uint32_t cdp_txrx_get_vdev_param(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, - enum cdp_vdev_param_type type) +/* + * Rx-Ingress and Tx-Egress are in the lower level DP layer + * Rx-Egress and Tx-ingress are handled in osif layer for DP + * So + * Rx-Ingress and Tx-Egress definitions are in DP layer + * Rx-Egress and Tx-ingress mask definitions are here below + */ +#define VDEV_PEER_PROTOCOL_RX_INGRESS_MASK 1 +#define VDEV_PEER_PROTOCOL_TX_INGRESS_MASK 2 +#define VDEV_PEER_PROTOCOL_RX_EGRESS_MASK 4 +#define VDEV_PEER_PROTOCOL_TX_EGRESS_MASK 8 + +#else +#define cdp_set_vdev_peer_protocol_count(soc, vdev_id, enable) +#define cdp_set_vdev_peer_protocol_drop_mask(soc, vdev_id, drop_mask) +#define cdp_is_vdev_peer_protocol_count_enabled(soc, vdev_id) 0 +#define cdp_get_peer_protocol_drop_mask(soc, vdev_id) 0 +#endif + +/** + * cdp_txrx_set_pdev_param() - set pdev parameter + * @soc: opaque soc handle + * @pdev_id: id of data path pdev handle + * @type: param type + * @val: value + * + * Return: status: 0 - Success, non-zero: Failure + */ +static inline QDF_STATUS cdp_txrx_set_pdev_param(ol_txrx_soc_handle soc, + uint8_t pdev_id, + enum cdp_pdev_param_type type, + cdp_config_param_type val) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); + "%s: Invalid Instance:", __func__); QDF_BUG(0); - return -1; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_get_vdev_param) { + !soc->ops->ctrl_ops->txrx_set_pdev_param) + return QDF_STATUS_E_FAILURE; + + return soc->ops->ctrl_ops->txrx_set_pdev_param + (soc, pdev_id, type, val); +} + +/** + * cdp_txrx_set_peer_param() - set pdev parameter + * @soc: opaque soc handle + * @vdev_id: id of data path vdev handle + * @peer_mac: peer mac address + * @type: param type + * @val: value + * + * Return: status: 0 - Success, non-zero: Failure + */ +static inline QDF_STATUS cdp_txrx_set_peer_param(ol_txrx_soc_handle soc, + uint8_t vdev_id, + uint8_t *peer_mac, + enum cdp_peer_param_type type, + cdp_config_param_type val) +{ + if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: callback not registered:", __func__); - return -1; + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; } - return soc->ops->ctrl_ops->txrx_get_vdev_param(vdev, type); + if (!soc->ops->ctrl_ops || + !soc->ops->ctrl_ops->txrx_set_peer_param) + return QDF_STATUS_E_FAILURE; + + return soc->ops->ctrl_ops->txrx_set_peer_param + (soc, vdev_id, peer_mac, type, val); } -static inline void cdp_txrx_set_vdev_param(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, enum cdp_vdev_param_type type, - uint32_t val) +/** + * cdp_txrx_get_peer_param() - set pdev parameter + * @soc: opaque soc handle + * @vdev_id: id of data path vdev handle + * @peer_mac: peer mac address + * @type: param type + * @val: address of buffer + * + * Return: status + */ +static inline QDF_STATUS cdp_txrx_get_peer_param(ol_txrx_soc_handle soc, + uint8_t vdev_id, + uint8_t *peer_mac, + enum cdp_peer_param_type type, + cdp_config_param_type *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_E_FAILURE; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_set_vdev_param) - return; + !soc->ops->ctrl_ops->txrx_get_peer_param) + return QDF_STATUS_E_FAILURE; - soc->ops->ctrl_ops->txrx_set_vdev_param(vdev, type, val); + return soc->ops->ctrl_ops->txrx_get_peer_param + (soc, vdev_id, peer_mac, type, val); } +#ifdef QCA_MULTIPASS_SUPPORT static inline void -cdp_peer_set_nawds(ol_txrx_soc_handle soc, - struct cdp_peer *peer, uint8_t value) +cdp_peer_set_vlan_id(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac, uint8_t vlan_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance:", __func__); + "%s: Invalid Instance:", __func__); QDF_BUG(0); return; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_peer_set_nawds) + !soc->ops->ctrl_ops->txrx_peer_set_vlan_id) return; - soc->ops->ctrl_ops->txrx_peer_set_nawds - (peer, value); + soc->ops->ctrl_ops->txrx_peer_set_vlan_id(soc, vdev_id, peer_mac, + vlan_id); } +#endif /** - * cdp_txrx_set_pdev_param() - set pdev parameter + * cdp_txrx_get_pdev_param() - get pdev parameter * @soc: opaque soc handle - * @pdev: data path pdev handle + * @pdev_id: id of data path pdev handle * @type: param type - * @val: value of pdev_tx_capture + * @value: address of value buffer * - * Return: status: 0 - Success, non-zero: Failure + * Return: status */ -static inline QDF_STATUS cdp_txrx_set_pdev_param(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, +static inline QDF_STATUS cdp_txrx_get_pdev_param(ol_txrx_soc_handle soc, + uint8_t pdev_id, enum cdp_pdev_param_type type, - uint8_t val) + cdp_config_param_type *value) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return QDF_STATUS_SUCCESS; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->ctrl_ops || - !soc->ops->ctrl_ops->txrx_set_pdev_param) - return QDF_STATUS_SUCCESS; + !soc->ops->ctrl_ops->txrx_get_pdev_param) + return QDF_STATUS_E_FAILURE; - return soc->ops->ctrl_ops->txrx_set_pdev_param - (pdev, type, val); + return soc->ops->ctrl_ops->txrx_get_pdev_param + (soc, pdev_id, type, value); +} + +/** + * cdp_txrx_peer_protocol_cnt() - set peer protocol count + * @soc: opaque soc handle + * @vdev: opaque vdev handle + * @nbuf: data packet + * @is_egress: whether egress or ingress + * @is_rx: whether tx or rx + * + * Return: void + */ +#ifdef VDEV_PEER_PROTOCOL_COUNT +static inline void +cdp_txrx_peer_protocol_cnt(ol_txrx_soc_handle soc, + int8_t vdev_id, + qdf_nbuf_t nbuf, + enum vdev_peer_protocol_enter_exit is_egress, + enum vdev_peer_protocol_tx_rx is_rx) +{ + 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->ctrl_ops || + !soc->ops->ctrl_ops->txrx_peer_protocol_cnt) + return; + + soc->ops->ctrl_ops->txrx_peer_protocol_cnt(soc, vdev_id, nbuf, + is_egress, is_rx); } +#else +#define cdp_txrx_peer_protocol_cnt(soc, vdev_id, nbuf, is_egress, is_rx) +#endif /** * cdp_enable_peer_based_pktlog()- Set flag in peer structure * * @soc: pointer to the soc - * @pdev: the data physical device object + * @pdev_id: id of the data physical device object * @enable: enable or disable peer based filter based pktlog * @peer_macaddr: Mac address of peer which needs to be * filtered @@ -511,8 +617,8 @@ static inline QDF_STATUS cdp_txrx_set_pdev_param(ol_txrx_soc_handle soc, * Return: int */ static inline int -cdp_enable_peer_based_pktlog(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, char *peer_macaddr, +cdp_enable_peer_based_pktlog(ol_txrx_soc_handle soc, uint8_t pdev_id, + char *peer_macaddr, uint8_t enable) { if (!soc || !soc->ops) { @@ -527,37 +633,37 @@ cdp_enable_peer_based_pktlog(ol_txrx_soc_handle soc, return 0; return soc->ops->ctrl_ops->enable_peer_based_pktlog - (pdev, peer_macaddr, enable); + (soc, pdev_id, peer_macaddr, enable); } /** * cdp_calculate_delay_stats()- get rx delay stats * * @soc: pointer to the soc - * @vdev: vdev handle + * @vdev_id: id of vdev handle * @nbuf: nbuf which is passed * * This function will calculate rx delay statistics. */ -static inline void -cdp_calculate_delay_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, +static inline QDF_STATUS +cdp_calculate_delay_stats(ol_txrx_soc_handle soc, uint8_t vdev_id, qdf_nbuf_t nbuf) { 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_E_FAILURE; } if (!soc->ops->ctrl_ops || !soc->ops->ctrl_ops->calculate_delay_stats) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: callback not registered:", __func__); - return; + return QDF_STATUS_E_FAILURE; } - return soc->ops->ctrl_ops->calculate_delay_stats(vdev, nbuf); + return soc->ops->ctrl_ops->calculate_delay_stats(soc, vdev_id, nbuf); } /** @@ -571,19 +677,19 @@ cdp_calculate_delay_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, * invoked is unspecified. * * @param soc - pointer to the soc - * @param pdev - the data physical device object + * @param pdev_id - id of the data physical device object * @param event_cb_sub - the callback and context for the event subscriber * @param event - which event's notifications are being subscribed to * @return - int */ static inline int -cdp_wdi_event_sub(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, void *event_cb_sub, uint32_t event) +cdp_wdi_event_sub(ol_txrx_soc_handle soc, uint8_t pdev_id, + wdi_event_subscribe *event_cb_sub, uint32_t event) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s invalid instance", __func__); + "%s invalid instance", __func__); QDF_BUG(0); return 0; } @@ -593,7 +699,7 @@ cdp_wdi_event_sub(ol_txrx_soc_handle soc, return 0; return soc->ops->ctrl_ops->txrx_wdi_event_sub - (pdev, event_cb_sub, event); + (soc, pdev_id, event_cb_sub, event); } /** @@ -605,14 +711,15 @@ cdp_wdi_event_sub(ol_txrx_soc_handle soc, * to event_sub() on the same wdi_event_subscribe object. * * @param soc - pointer to the soc - * @param pdev - the data physical device object + * @param pdev_id - id of the data physical device object * @param event_cb_sub - the callback and context for the event subscriber * @param event - which event's notifications are being subscribed to * @return - int */ static inline int cdp_wdi_event_unsub(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, void *event_cb_sub, uint32_t event) + uint8_t pdev_id, wdi_event_subscribe *event_cb_sub, + uint32_t event) { if (!soc || !soc->ops) { @@ -627,7 +734,7 @@ cdp_wdi_event_unsub(ol_txrx_soc_handle soc, return 0; return soc->ops->ctrl_ops->txrx_wdi_event_unsub - (pdev, event_cb_sub, event); + (soc, pdev_id, event_cb_sub, event); } /** @@ -638,16 +745,18 @@ cdp_wdi_event_unsub(ol_txrx_soc_handle soc, * to the peer handler. * * @param soc - pointer to the soc - * @param peer - peer handler + * @param vdev_id - id of vdev handle + * @param peer mac - peer mac address * @param sec_idx - mcast or ucast frame type. * @return - int */ static inline int -cdp_get_sec_type(ol_txrx_soc_handle soc, struct cdp_peer *peer, uint8_t sec_idx) +cdp_get_sec_type(ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac, + uint8_t sec_idx) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s invalid instance", __func__); + "%s invalid instance", __func__); QDF_BUG(0); return A_ERROR; } @@ -657,38 +766,45 @@ cdp_get_sec_type(ol_txrx_soc_handle soc, struct cdp_peer *peer, uint8_t sec_idx) return A_ERROR; return soc->ops->ctrl_ops->txrx_get_sec_type - (peer, sec_idx); + (soc, vdev_id, peer_mac, sec_idx); } /** * cdp_set_mgmt_tx_power(): function to set tx power for mgmt frames - * @vdev_handle: vdev handle + * @param soc - pointer to the soc + * @vdev_id : id of vdev handle * @subtype_index: subtype * @tx_power: Tx power - * Return: None + * Return: QDF_STATUS */ -static inline int cdp_set_mgmt_tx_power(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, uint8_t subtype, uint8_t tx_power) +static inline QDF_STATUS +cdp_set_mgmt_tx_power(ol_txrx_soc_handle soc, + uint8_t vdev_id, uint8_t subtype, uint8_t tx_power) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance:", __func__); QDF_BUG(0); - return 0; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->ctrl_ops || !soc->ops->ctrl_ops->txrx_update_mgmt_txpow_vdev) - return 0; + return QDF_STATUS_E_FAILURE; - soc->ops->ctrl_ops->txrx_update_mgmt_txpow_vdev(vdev, + return soc->ops->ctrl_ops->txrx_update_mgmt_txpow_vdev(soc, vdev_id, subtype, tx_power); - return 0; } +/** + * cdp_get_pldev() - function to get pktlog device handle + * @soc: datapath soc handle + * @pdev_id: physical device id + * + * Return: pktlog device handle or NULL + */ static inline void * -cdp_get_pldev(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev) +cdp_get_pldev(ol_txrx_soc_handle soc, uint8_t pdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -700,15 +816,200 @@ cdp_get_pldev(ol_txrx_soc_handle soc, if (!soc->ops->ctrl_ops || !soc->ops->ctrl_ops->txrx_get_pldev) return NULL; - return soc->ops->ctrl_ops->txrx_get_pldev(pdev); + return soc->ops->ctrl_ops->txrx_get_pldev(soc, pdev_id); +} + +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) +/** + * cdp_cfr_filter() - Configure Host RX monitor status ring for CFR + * @soc: SOC TXRX handle + * @pdev_id: ID of the physical device object + * @enable: Enable or disable CFR + * @filter_val: Flag to select filter for monitor mode + */ +static inline void +cdp_cfr_filter(ol_txrx_soc_handle soc, + uint8_t pdev_id, + bool enable, + struct cdp_monitor_filter *filter_val) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cfr_ops || !soc->ops->cfr_ops->txrx_cfr_filter) + return; + + soc->ops->cfr_ops->txrx_cfr_filter(soc, pdev_id, enable, filter_val); } +/** + * cdp_get_cfr_rcc() - get cfr rcc config + * @soc: Datapath soc handle + * @pdev_id: id of objmgr pdev + * + * Return: true/false based on cfr mode setting + */ +static inline +bool cdp_get_cfr_rcc(ol_txrx_soc_handle soc, uint8_t pdev_id) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + QDF_BUG(0); + return 0; + } + + if (!soc->ops->cfr_ops || !soc->ops->cfr_ops->txrx_get_cfr_rcc) + return 0; + + return soc->ops->cfr_ops->txrx_get_cfr_rcc(soc, pdev_id); +} + +/** + * cdp_set_cfr_rcc() - enable/disable cfr rcc config + * @soc: Datapath soc handle + * @pdev_id: id of objmgr pdev + * @enable: Enable/Disable cfr rcc mode + * + * Return: none + */ +static inline +void cdp_set_cfr_rcc(ol_txrx_soc_handle soc, uint8_t pdev_id, bool enable) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cfr_ops || !soc->ops->cfr_ops->txrx_set_cfr_rcc) + return; + + return soc->ops->cfr_ops->txrx_set_cfr_rcc(soc, pdev_id, enable); +} + +/** + * cdp_get_cfr_dbg_stats() - Get debug statistics for CFR + * + * @soc: SOC TXRX handle + * @pdev_id: ID of the physical device object + * @buf: CFR RCC debug statistics buffer + * + * Return: None + */ +static inline void +cdp_get_cfr_dbg_stats(ol_txrx_soc_handle soc, uint8_t pdev_id, + struct cdp_cfr_rcc_stats *buf) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cfr_ops || !soc->ops->cfr_ops->txrx_get_cfr_dbg_stats) + return; + + soc->ops->cfr_ops->txrx_get_cfr_dbg_stats(soc, pdev_id, buf); +} + +/** + * cdp_cfr_clr_dbg_stats() - Clear debug statistics for CFR + * + * @soc: SOC TXRX handle + * @pdev_id: ID of the physical device object + */ +static inline void +cdp_cfr_clr_dbg_stats(ol_txrx_soc_handle soc, uint8_t pdev_id) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cfr_ops || !soc->ops->cfr_ops->txrx_clear_cfr_dbg_stats) + return; + + soc->ops->cfr_ops->txrx_clear_cfr_dbg_stats(soc, pdev_id); +} + +/** + * cdp_enable_mon_reap_timer() - enable/disable reap timer + * @soc: Datapath soc handle + * @pdev_id: id of objmgr pdev + * @enable: enable/disable reap timer of monitor status ring + * + * Return: none + */ +static inline void +cdp_enable_mon_reap_timer(ol_txrx_soc_handle soc, uint8_t pdev_id, + bool enable) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->cfr_ops || + !soc->ops->cfr_ops->txrx_enable_mon_reap_timer) + return; + + return soc->ops->cfr_ops->txrx_enable_mon_reap_timer(soc, pdev_id, + enable); +} +#endif + +#if defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(WLAN_RX_PKT_CAPTURE_ENH) +/** + * cdp_update_peer_pkt_capture_params() - Sets Rx & Tx Capture params for a peer + * @soc: SOC TXRX handle + * @pdev_id: id of CDP pdev pointer + * @is_rx_pkt_cap_enable: enable/disable rx pkt capture for this peer + * @is_tx_pkt_cap_enable: enable/disable tx pkt capture for this peer + * @peer_mac: MAC address of peer for which pkt_cap is to be enabled/disabled + * + * Return: Success when matching peer is found & flags are set, error otherwise + */ +static inline QDF_STATUS +cdp_update_peer_pkt_capture_params(ol_txrx_soc_handle soc, + uint8_t pdev_id, + bool is_rx_pkt_cap_enable, + bool is_tx_pkt_cap_enable, + uint8_t *peer_mac) +{ + if (!soc || !soc->ops) { + dp_err("Invalid SOC instance"); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->ctrl_ops || + !soc->ops->ctrl_ops->txrx_update_peer_pkt_capture_params) + return QDF_STATUS_E_FAILURE; + + return soc->ops->ctrl_ops->txrx_update_peer_pkt_capture_params + (soc, pdev_id, is_rx_pkt_cap_enable, + is_tx_pkt_cap_enable, + peer_mac); +} +#endif /* WLAN_TX_PKT_CAPTURE_ENH || WLAN_RX_PKT_CAPTURE_ENH */ + #ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG /** * cdp_update_pdev_rx_protocol_tag() - wrapper function to set the protocol * tag in CDP layer from cfg layer * @soc: SOC TXRX handle - * @pdev: CDP pdev pointer + * @pdev_id: id of CDP pdev pointer * @protocol_mask: Bitmap for protocol for which tagging is enabled * @protocol_type: Protocol type for which the tag should be update * @tag: Actual tag value for the given prototype @@ -716,7 +1017,7 @@ cdp_get_pldev(ol_txrx_soc_handle soc, */ static inline QDF_STATUS cdp_update_pdev_rx_protocol_tag(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, uint32_t protocol_mask, + uint8_t pdev_id, uint32_t protocol_mask, uint16_t protocol_type, uint16_t tag) { if (!soc || !soc->ops) { @@ -730,7 +1031,7 @@ cdp_update_pdev_rx_protocol_tag(ol_txrx_soc_handle soc, return QDF_STATUS_E_FAILURE; return soc->ops->ctrl_ops->txrx_update_pdev_rx_protocol_tag - (pdev, protocol_mask, protocol_type, tag); + (soc, pdev_id, protocol_mask, protocol_type, tag); } #ifdef WLAN_SUPPORT_RX_TAG_STATISTICS @@ -738,13 +1039,13 @@ cdp_update_pdev_rx_protocol_tag(ol_txrx_soc_handle soc, * cdp_dump_pdev_rx_protocol_tag_stats() - wrapper function to dump the protocol tag statistics for given or all protocols * @soc: SOC TXRX handle - * @pdev: CDP pdev pointer + * @pdev_id: id of CDP pdev pointer * @protocol_type: Protocol type for which the tag should be update * Return: Returns QDF_STATUS_SUCCESS/FAILURE */ static inline QDF_STATUS cdp_dump_pdev_rx_protocol_tag_stats(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, + uint8_t pdev_id, uint16_t protocol_type) { if (!soc || !soc->ops) { @@ -757,7 +1058,7 @@ cdp_dump_pdev_rx_protocol_tag_stats(ol_txrx_soc_handle soc, !soc->ops->ctrl_ops->txrx_dump_pdev_rx_protocol_tag_stats) return QDF_STATUS_E_FAILURE; - soc->ops->ctrl_ops->txrx_dump_pdev_rx_protocol_tag_stats(pdev, + soc->ops->ctrl_ops->txrx_dump_pdev_rx_protocol_tag_stats(soc, pdev_id, protocol_type); return QDF_STATUS_SUCCESS; } @@ -768,7 +1069,7 @@ cdp_dump_pdev_rx_protocol_tag_stats(ol_txrx_soc_handle soc, /** * cdp_vdev_config_for_nac_rssi(): To invoke dp callback for nac rssi config * @soc: soc pointer - * @vdev: vdev pointer + * @vdev_id: id of vdev * @nac_cmd: specfies nac_rss config action add, del, list * @bssid: Neighbour bssid * @client_macaddr: Non-Associated client MAC @@ -777,7 +1078,7 @@ cdp_dump_pdev_rx_protocol_tag_stats(ol_txrx_soc_handle soc, * Return: QDF_STATUS */ static inline QDF_STATUS cdp_vdev_config_for_nac_rssi(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, enum cdp_nac_param_cmd nac_cmd, + uint8_t vdev_id, enum cdp_nac_param_cmd nac_cmd, char *bssid, char *client_macaddr, uint8_t chan_num) { if (!soc || !soc->ops) { @@ -791,21 +1092,21 @@ static inline QDF_STATUS cdp_vdev_config_for_nac_rssi(ol_txrx_soc_handle soc, !soc->ops->ctrl_ops->txrx_vdev_config_for_nac_rssi) return QDF_STATUS_E_FAILURE; - return soc->ops->ctrl_ops->txrx_vdev_config_for_nac_rssi(vdev, + return soc->ops->ctrl_ops->txrx_vdev_config_for_nac_rssi(soc, vdev_id, nac_cmd, bssid, client_macaddr, chan_num); } /* * cdp_vdev_get_neighbour_rssi(): To invoke dp callback to get rssi value of nac * @soc: soc pointer - * @vdev: vdev pointer + * @vdev_id: id of vdev * @macaddr: Non-Associated client MAC * @rssi: rssi * * Return: QDF_STATUS */ static inline QDF_STATUS cdp_vdev_get_neighbour_rssi(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, + uint8_t vdev_id, char *macaddr, uint8_t *rssi) { @@ -820,8 +1121,66 @@ static inline QDF_STATUS cdp_vdev_get_neighbour_rssi(ol_txrx_soc_handle soc, !soc->ops->ctrl_ops->txrx_vdev_get_neighbour_rssi) return QDF_STATUS_E_FAILURE; - return soc->ops->ctrl_ops->txrx_vdev_get_neighbour_rssi(vdev, macaddr, + return soc->ops->ctrl_ops->txrx_vdev_get_neighbour_rssi(soc, vdev_id, + macaddr, rssi); } #endif -#endif + +#ifdef WLAN_SUPPORT_RX_FLOW_TAG +/** + * cdp_set_rx_flow_tag() - wrapper function to set the flow + * tag in CDP layer from cfg layer + * @soc: SOC TXRX handle + * @pdev_id: id of CDP pdev pointer + * @flow_info: Flow 5-tuple, along with tag, if any, that needs to added/deleted + * + * Return: Success when add/del operation is successful, error otherwise + */ +static inline QDF_STATUS +cdp_set_rx_flow_tag(ol_txrx_soc_handle soc, uint8_t pdev_id, + struct cdp_rx_flow_info *flow_info) +{ + if (!soc || !soc->ops) { + dp_err("Invalid SOC instance"); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->ctrl_ops || + !soc->ops->ctrl_ops->txrx_set_rx_flow_tag) + return QDF_STATUS_E_FAILURE; + + return soc->ops->ctrl_ops->txrx_set_rx_flow_tag(soc, pdev_id, + flow_info); +} + +/** + * cdp_dump_rx_flow_tag_stats() - wrapper function to dump the flow + * tag statistics for given flow + * @soc: SOC TXRX handle + * @pdev_id: id of CDP pdev + * @flow_info: Flow tuple for which we want to print the statistics + * + * Return: Success when flow is found and stats are printed, error otherwise + */ +static inline QDF_STATUS +cdp_dump_rx_flow_tag_stats(ol_txrx_soc_handle soc, uint8_t pdev_id, + struct cdp_rx_flow_info *flow_info) +{ + if (!soc || !soc->ops) { + dp_err("Invalid SOC instance"); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->ctrl_ops || + !soc->ops->ctrl_ops->txrx_dump_rx_flow_tag_stats) + return QDF_STATUS_E_FAILURE; + + return soc->ops->ctrl_ops->txrx_dump_rx_flow_tag_stats(soc, + pdev_id, + flow_info); +} +#endif /* WLAN_SUPPORT_RX_FLOW_TAG */ +#endif /* _CDP_TXRX_CTRL_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ctrl_def.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ctrl_def.h index a0811af57a457811900b5cf8a7ab523351c29f43..1a922f6b7e6ed5dc51f9b7cf844ce93b0c13b09b 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ctrl_def.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ctrl_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016,2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016,2018-2019 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 @@ -73,9 +73,9 @@ void ol_ll_pdev_tx_unlock(void *); #else #define OSIF_VAP_TX_LOCK(_y, _x) cdp_vdev_tx_lock( \ - _y, wlan_vdev_get_dp_handle((_x)->ctrl_vdev)) + _y, wlan_vdev_get_id((_x)->ctrl_vdev)) #define OSIF_VAP_TX_UNLOCK(_y, _x) cdp_vdev_tx_unlock( \ - _y, wlan_vdev_get_dp_handle((_x)->ctrl_vdev)) + _y, wlan_vdev_get_id((_x)->ctrl_vdev)) #define OL_TX_FLOW_CTRL_LOCK(_x) #define OL_TX_FLOW_CTRL_UNLOCK(_x) diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_flow_ctrl_legacy.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_flow_ctrl_legacy.h index d0ac40cb0b9ce3ce7b22f95134155e6e1e9b8a45..b00b905d3a9f7d8f1a9258f76f65b79bc410b463 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_flow_ctrl_legacy.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_flow_ctrl_legacy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 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 @@ -30,13 +30,17 @@ /** * cdp_hl_fc_register() - Register HL flow control callback. - * @soc - data path soc handle - * @flowcontrol - callback function pointer to stop/start OS netdev queues + * @soc: data path soc handle + * @pdev_id: datapath pdev identifier + * @flowcontrol: callback function pointer to stop/start OS netdev queues + * * Register flow control callback. - * return 0 success + * + * Returns: 0 for success */ static inline int -cdp_hl_fc_register(ol_txrx_soc_handle soc, tx_pause_callback flowcontrol) +cdp_hl_fc_register(ol_txrx_soc_handle soc, uint8_t pdev_id, + tx_pause_callback flowcontrol) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, @@ -49,17 +53,18 @@ cdp_hl_fc_register(ol_txrx_soc_handle soc, tx_pause_callback flowcontrol) !soc->ops->l_flowctl_ops->register_tx_flow_control) return -EINVAL; - return soc->ops->l_flowctl_ops->register_tx_flow_control(soc, + return soc->ops->l_flowctl_ops->register_tx_flow_control(soc, pdev_id, flowcontrol); } static inline int cdp_hl_fc_set_td_limit(ol_txrx_soc_handle soc, - uint8_t vdev_id, uint8_t chan) + uint8_t vdev_id, uint32_t chan_freq) { if (!soc->ops->l_flowctl_ops->set_vdev_tx_desc_limit) return 0; - return soc->ops->l_flowctl_ops->set_vdev_tx_desc_limit(vdev_id, chan); + return soc->ops->l_flowctl_ops->set_vdev_tx_desc_limit(soc, vdev_id, + chan_freq); } static inline int cdp_hl_fc_set_os_queue_status(ol_txrx_soc_handle soc, @@ -69,18 +74,20 @@ static inline int cdp_hl_fc_set_os_queue_status(ol_txrx_soc_handle soc, if (!soc->ops->l_flowctl_ops->set_vdev_os_queue_status) return -EINVAL; - return soc->ops->l_flowctl_ops->set_vdev_os_queue_status(vdev_id, + return soc->ops->l_flowctl_ops->set_vdev_os_queue_status(soc, + vdev_id, action); } #else static inline int -cdp_hl_fc_register(ol_txrx_soc_handle soc, tx_pause_callback flowcontrol) +cdp_hl_fc_register(ol_txrx_soc_handle soc, uint8_t pdev_id, + tx_pause_callback flowcontrol) { return 0; } static inline int cdp_hl_fc_set_td_limit(ol_txrx_soc_handle soc, - uint8_t vdev_id, uint8_t chan) + uint8_t vdev_id, uint32_t chan_freq) { return 0; } @@ -109,7 +116,7 @@ static inline int cdp_hl_fc_set_os_queue_status(ol_txrx_soc_handle soc, */ static inline int cdp_fc_register(ol_txrx_soc_handle soc, uint8_t vdev_id, - ol_txrx_tx_flow_control_fp flowControl, void *osif_fc_ctx, + ol_txrx_tx_flow_control_fp flowcontrol, void *osif_fc_ctx, ol_txrx_tx_flow_control_is_pause_fp flow_control_is_pause) { if (!soc || !soc->ops) { @@ -124,7 +131,7 @@ cdp_fc_register(ol_txrx_soc_handle soc, uint8_t vdev_id, return 0; return soc->ops->l_flowctl_ops->register_tx_flow_control( - vdev_id, flowControl, osif_fc_ctx, + soc, vdev_id, flowcontrol, osif_fc_ctx, flow_control_is_pause); } #else @@ -160,15 +167,16 @@ cdp_fc_deregister(ol_txrx_soc_handle soc, uint8_t vdev_id) return 0; return soc->ops->l_flowctl_ops->deregister_tx_flow_control_cb( - vdev_id); + soc, vdev_id); } /** * cdp_fc_get_tx_resource() - get data path resource count - * @soc - data path soc handle - * @sta_id - local peer id - * @low_watermark - low resource threshold - * @high_watermark_offset - high resource threshold + * @soc: data path soc handle + * @pdev_id: datapath pdev ID + * @peer_addr: peer mac address + * @low_watermark: low resource threshold + * @high_watermark_offset: high resource threshold * * get data path resource count * @@ -176,8 +184,10 @@ cdp_fc_deregister(ol_txrx_soc_handle soc, uint8_t vdev_id) * false resource is not avaialbe */ static inline bool -cdp_fc_get_tx_resource(ol_txrx_soc_handle soc, uint8_t sta_id, - unsigned int low_watermark, unsigned int high_watermark_offset) +cdp_fc_get_tx_resource(ol_txrx_soc_handle soc, uint8_t pdev_id, + struct qdf_mac_addr peer_addr, + unsigned int low_watermark, + unsigned int high_watermark_offset) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, @@ -190,8 +200,9 @@ cdp_fc_get_tx_resource(ol_txrx_soc_handle soc, uint8_t sta_id, !soc->ops->l_flowctl_ops->get_tx_resource) return false; - return soc->ops->l_flowctl_ops->get_tx_resource(sta_id, - low_watermark, high_watermark_offset); + return soc->ops->l_flowctl_ops->get_tx_resource(soc, pdev_id, peer_addr, + low_watermark, + high_watermark_offset); } /** @@ -220,21 +231,21 @@ cdp_fc_ll_set_tx_pause_q_depth(ol_txrx_soc_handle soc, return 0; return soc->ops->l_flowctl_ops->ll_set_tx_pause_q_depth( - vdev_id, pause_q_depth); + soc, vdev_id, pause_q_depth); } /** * cdp_fc_vdev_flush() - flush tx queue - * @soc - data path soc handle - * @vdev - virtual interface context pointer + * @soc: data path soc handle + * @vdev_id: id of vdev * * flush tx queue * * return None */ static inline void -cdp_fc_vdev_flush(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +cdp_fc_vdev_flush(ol_txrx_soc_handle soc, uint8_t vdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, @@ -247,22 +258,23 @@ cdp_fc_vdev_flush(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) !soc->ops->l_flowctl_ops->vdev_flush) return; - soc->ops->l_flowctl_ops->vdev_flush(vdev); + soc->ops->l_flowctl_ops->vdev_flush(soc, vdev_id); } /** * cdp_fc_vdev_pause() - pause tx scheduler on vdev - * @soc - data path soc handle - * @vdev - virtual interface context pointer - * @reason - pause reason + * @soc: data path soc handle + * @vdev_id: id of vdev + * @reason: pause reason + * @pause_type: type of pause * * pause tx scheduler on vdev * * return None */ static inline void -cdp_fc_vdev_pause(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - uint32_t reason) +cdp_fc_vdev_pause(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint32_t reason, uint32_t pause_type) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, @@ -275,22 +287,23 @@ cdp_fc_vdev_pause(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, !soc->ops->l_flowctl_ops->vdev_pause) return; - soc->ops->l_flowctl_ops->vdev_pause(vdev, reason); + soc->ops->l_flowctl_ops->vdev_pause(soc, vdev_id, reason, pause_type); } /** * cdp_fc_vdev_unpause() - resume tx scheduler on vdev - * @soc - data path soc handle - * @vdev - virtual interface context pointer - * @reason - pause reason + * @soc: data path soc handle + * @vdev_id: id of vdev + * @reason: pause reason + * @pause_type: type of pause * * resume tx scheduler on vdev * * return None */ static inline void -cdp_fc_vdev_unpause(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - uint32_t reason) +cdp_fc_vdev_unpause(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint32_t reason, uint32_t pause_type) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, @@ -302,6 +315,7 @@ cdp_fc_vdev_unpause(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, !soc->ops->l_flowctl_ops->vdev_unpause) return; - soc->ops->l_flowctl_ops->vdev_unpause(vdev, reason); + soc->ops->l_flowctl_ops->vdev_unpause(soc, vdev_id, reason, + pause_type); } #endif /* _CDP_TXRX_FC_LEG_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_flow_ctrl_v2.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_flow_ctrl_v2.h index 9ef5cb5685d7a48a158be4ac7ff01497ca5593fe..630b8b9060116a08e9ab8d449eef8cb933fd17eb 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_flow_ctrl_v2.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_flow_ctrl_v2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 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 @@ -92,8 +92,6 @@ cdp_set_desc_global_pool_size(ol_txrx_soc_handle soc, static inline void cdp_dump_flow_pool_info(struct cdp_soc_t *soc) { - void *dp_soc = (void *)soc; - if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "%s invalid instance", __func__); @@ -105,18 +103,18 @@ cdp_dump_flow_pool_info(struct cdp_soc_t *soc) !soc->ops->flowctl_ops->dump_flow_pool_info) return; - soc->ops->flowctl_ops->dump_flow_pool_info(dp_soc); + soc->ops->flowctl_ops->dump_flow_pool_info(soc); } /** * cdp_tx_desc_thresh_reached() - Check if avail tx desc meet threshold - * @soc - data path soc handle - * @vdev - dp vdev handle + * @soc: data path soc handle + * @vdev_id: vdev_id corresponding to vdev start * * Return: true if threshold is met, false if not */ static inline bool -cdp_tx_desc_thresh_reached(struct cdp_soc_t *soc, struct cdp_vdev *vdev) +cdp_tx_desc_thresh_reached(struct cdp_soc_t *soc, uint8_t vdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, @@ -129,6 +127,6 @@ cdp_tx_desc_thresh_reached(struct cdp_soc_t *soc, struct cdp_vdev *vdev) !soc->ops->flowctl_ops->tx_desc_thresh_reached) return false; - return soc->ops->flowctl_ops->tx_desc_thresh_reached(vdev); + return soc->ops->flowctl_ops->tx_desc_thresh_reached(soc, vdev_id); } #endif /* _CDP_TXRX_FC_V2_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_handle.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_handle.h index 8b59efc18b2ea9235a086ef6c20f931917522672..a3e448eb3e1bea4ddc8138aaca29c0a0eedd62a6 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_handle.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_handle.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -33,6 +33,11 @@ struct cdp_peer; struct cdp_raw_ast; struct cdp_soc; +/** + * cdp_ctrl_objmgr_psoc - opaque handle for UMAC psoc object + */ +struct cdp_ctrl_objmgr_psoc; + /** * cdp_ctrl_objmgr_pdev - opaque handle for UMAC pdev object */ @@ -48,4 +53,13 @@ struct cdp_ctrl_objmgr_vdev; */ struct cdp_ctrl_objmgr_peer; +/** + * cdp_cal_client - opaque handle for cal client object + */ +struct cdp_cal_client; + +/** + * cdp_ext_vdev - opaque handle for extended vdev data path handle + */ +struct cdp_ext_vdev; #endif diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_host_stats.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_host_stats.h index 9a18113a63122a6814a1aa87028c383174dcdb2b..5db10b26e10e58ff608978dd1f8653a8ab40f90f 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_host_stats.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_host_stats.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -24,15 +24,17 @@ #ifndef _CDP_TXRX_HOST_STATS_H_ #define _CDP_TXRX_HOST_STATS_H_ #include "cdp_txrx_handle.h" +#include /** * cdp_host_stats_get: cdp call to get host stats * @soc: SOC handle + * @vdev_id: vdev id of vdev * @req: Requirement type * * return: 0 for Success, Failure returns error message */ static inline int cdp_host_stats_get(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, + uint8_t vdev_id, struct ol_txrx_stats_req *req) { if (!soc || !soc->ops) { @@ -46,7 +48,7 @@ static inline int cdp_host_stats_get(ol_txrx_soc_handle soc, !soc->ops->host_stats_ops->txrx_host_stats_get) return 0; - return soc->ops->host_stats_ops->txrx_host_stats_get(vdev, req); + return soc->ops->host_stats_ops->txrx_host_stats_get(soc, vdev_id, req); } /** @@ -81,46 +83,47 @@ static inline int cdp_host_stats_get_ratekbps(ol_txrx_soc_handle soc, /** * cdp_host_stats_clr: cdp call to clear host stats - * @vdev: vdev handle + * @soc: soc handle + * @vdev_id: vdev handle id * - * return: void + * return: QDF_STATUS */ -static inline void -cdp_host_stats_clr(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +static inline QDF_STATUS +cdp_host_stats_clr(ol_txrx_soc_handle soc, uint8_t vdev_id) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->txrx_host_stats_clr) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->txrx_host_stats_clr(vdev); + return soc->ops->host_stats_ops->txrx_host_stats_clr(soc, vdev_id); } -static inline void -cdp_host_ce_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +static inline QDF_STATUS +cdp_host_ce_stats(ol_txrx_soc_handle soc, uint8_t vdev_id) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->txrx_host_ce_stats) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->txrx_host_ce_stats(vdev); + return soc->ops->host_stats_ops->txrx_host_ce_stats(soc, vdev_id); } static inline int cdp_stats_publish - (ol_txrx_soc_handle soc, struct cdp_pdev *pdev, + (ol_txrx_soc_handle soc, uint8_t pdev_id, struct cdp_stats_extd *buf) { if (!soc || !soc->ops) { @@ -134,204 +137,176 @@ static inline int cdp_stats_publish !soc->ops->host_stats_ops->txrx_stats_publish) return 0; - return soc->ops->host_stats_ops->txrx_stats_publish(pdev, buf); + return soc->ops->host_stats_ops->txrx_stats_publish(soc, pdev_id, buf); } /** * @brief Enable enhanced stats functionality. * - * @param pdev - the physical device object - * @return - void + * @param soc - the soc object + * @param pdev_id - id of the physical device object + * @return - QDF_STATUS */ -static inline void -cdp_enable_enhanced_stats(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +static inline QDF_STATUS +cdp_enable_enhanced_stats(ol_txrx_soc_handle soc, uint8_t pdev_id) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->txrx_enable_enhanced_stats) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->txrx_enable_enhanced_stats - (pdev); + return soc->ops->host_stats_ops->txrx_enable_enhanced_stats + (soc, pdev_id); } /** * @brief Disable enhanced stats functionality. * - * @param pdev - the physical device object - * @return - void + * @param soc - the soc object + * @param pdev_id - id of the physical device object + * @return - QDF_STATUS */ -static inline void -cdp_disable_enhanced_stats(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +static inline QDF_STATUS +cdp_disable_enhanced_stats(ol_txrx_soc_handle soc, uint8_t pdev_id) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->txrx_disable_enhanced_stats) - return; - - soc->ops->host_stats_ops->txrx_disable_enhanced_stats - (pdev); -} - -/** - * @brief Get the desired stats from the message. - * - * @param pdev - the physical device object - * @param stats_base - stats buffer received from FW - * @param type - stats type. - * @return - pointer to requested stat identified by type - */ -static inline uint32_t *cdp_get_stats_base - (ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint32_t *stats_base, uint32_t msg_len, uint8_t type) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); - QDF_BUG(0); - return 0; - } - - if (!soc->ops->host_stats_ops || - !soc->ops->host_stats_ops->txrx_get_stats_base) - return 0; + return QDF_STATUS_E_FAILURE; - return (uint32_t *)soc->ops->host_stats_ops->txrx_get_stats_base - (pdev, stats_base, msg_len, type); + return soc->ops->host_stats_ops->txrx_disable_enhanced_stats + (soc, pdev_id); } -static inline void -cdp_tx_print_tso_stats(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev) +static inline QDF_STATUS +cdp_tx_print_tso_stats(ol_txrx_soc_handle soc, uint8_t vdev_id) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->tx_print_tso_stats) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->tx_print_tso_stats(vdev); + return soc->ops->host_stats_ops->tx_print_tso_stats(soc, vdev_id); } -static inline void -cdp_tx_rst_tso_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +static inline QDF_STATUS +cdp_tx_rst_tso_stats(ol_txrx_soc_handle soc, uint8_t vdev_id) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->tx_rst_tso_stats) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->tx_rst_tso_stats(vdev); + return soc->ops->host_stats_ops->tx_rst_tso_stats(soc, vdev_id); } -static inline void -cdp_tx_print_sg_stats(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev) +static inline QDF_STATUS +cdp_tx_print_sg_stats(ol_txrx_soc_handle soc, uint8_t vdev_id) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->tx_print_sg_stats) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->tx_print_sg_stats(vdev); + return soc->ops->host_stats_ops->tx_print_sg_stats(soc, vdev_id); } -static inline void -cdp_tx_rst_sg_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +static inline QDF_STATUS +cdp_tx_rst_sg_stats(ol_txrx_soc_handle soc, uint8_t vdev_id) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->tx_rst_sg_stats) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->tx_rst_sg_stats(vdev); + return soc->ops->host_stats_ops->tx_rst_sg_stats(soc, vdev_id); } -static inline void -cdp_print_rx_cksum_stats(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev) +static inline QDF_STATUS +cdp_print_rx_cksum_stats(ol_txrx_soc_handle soc, uint8_t vdev_id) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->print_rx_cksum_stats) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->print_rx_cksum_stats(vdev); + return soc->ops->host_stats_ops->print_rx_cksum_stats(soc, vdev_id); } -static inline void -cdp_rst_rx_cksum_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +static inline QDF_STATUS +cdp_rst_rx_cksum_stats(ol_txrx_soc_handle soc, uint8_t vdev_id) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->rst_rx_cksum_stats) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->rst_rx_cksum_stats(vdev); + return soc->ops->host_stats_ops->rst_rx_cksum_stats(soc, vdev_id); } -static inline A_STATUS -cdp_host_me_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +static inline QDF_STATUS +cdp_host_me_stats(ol_txrx_soc_handle soc, uint8_t vdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance", __func__); QDF_BUG(0); - return 0; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->txrx_host_me_stats) - return 0; + return QDF_STATUS_E_FAILURE; - return soc->ops->host_stats_ops->txrx_host_me_stats(vdev); + return soc->ops->host_stats_ops->txrx_host_me_stats(soc, vdev_id); } /** @@ -342,25 +317,25 @@ cdp_host_me_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) * * return: status */ -static inline void cdp_per_peer_stats(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, char *addr) +static inline QDF_STATUS cdp_per_peer_stats(ol_txrx_soc_handle soc, + uint8_t *addr) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->txrx_per_peer_stats) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->txrx_per_peer_stats(pdev, addr); + return soc->ops->host_stats_ops->txrx_per_peer_stats(soc, addr); } static inline int cdp_host_msdu_ttl_stats(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, + uint8_t vdev_id, struct ol_txrx_stats_req *req) { if (!soc || !soc->ops) { @@ -375,106 +350,113 @@ static inline int cdp_host_msdu_ttl_stats(ol_txrx_soc_handle soc, return 0; return soc->ops->host_stats_ops->txrx_host_msdu_ttl_stats - (vdev, req); + (soc, vdev_id, req); } -static inline void -cdp_print_lro_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +static inline QDF_STATUS cdp_update_peer_stats(ol_txrx_soc_handle soc, + uint8_t vdev_id, uint8_t *mac, + void *stats, + uint32_t last_tx_rate_mcs, + uint32_t stats_id) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || - !soc->ops->host_stats_ops->print_lro_stats) - return; + !soc->ops->host_stats_ops->txrx_update_peer_stats) + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->print_lro_stats(vdev); + return soc->ops->host_stats_ops->txrx_update_peer_stats + (soc, vdev_id, mac, stats, last_tx_rate_mcs, stats_id); } -static inline void -cdp_reset_lro_stats(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +static inline QDF_STATUS cdp_get_dp_fw_peer_stats(ol_txrx_soc_handle soc, + uint8_t pdev_id, + uint8_t *mac, uint32_t caps, + uint32_t copy_stats) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || - !soc->ops->host_stats_ops->reset_lro_stats) - return; + !soc->ops->host_stats_ops->get_fw_peer_stats) + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->reset_lro_stats(vdev); + return soc->ops->host_stats_ops->get_fw_peer_stats + (soc, pdev_id, mac, caps, copy_stats); } -static inline void cdp_get_dp_fw_peer_stats(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, uint8_t *mac, uint32_t caps, - uint32_t copy_stats) +static inline QDF_STATUS cdp_get_dp_htt_stats(ol_txrx_soc_handle soc, + uint8_t pdev_id, + void *data, uint32_t data_len) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); + "%s: Invalid Instance", __func__); QDF_BUG(0); - return; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->host_stats_ops || - !soc->ops->host_stats_ops->get_fw_peer_stats) - return; + !soc->ops->host_stats_ops->get_htt_stats) + return QDF_STATUS_E_FAILURE; - soc->ops->host_stats_ops->get_fw_peer_stats - (pdev, mac, caps, copy_stats); -} - -static inline void cdp_get_dp_htt_stats(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, - void *data, uint32_t data_len) -{ - if (soc && soc->ops && soc->ops->host_stats_ops && - soc->ops->host_stats_ops->get_htt_stats) - return soc->ops->host_stats_ops->get_htt_stats - (pdev, data, data_len); - return; + return soc->ops->host_stats_ops->get_htt_stats(soc, pdev_id, data, + data_len); } /** * @brief Update pdev host stats received from firmware * (wmi_host_pdev_stats and wmi_host_pdev_ext_stats) into dp * - * @param pdev - the physical device object + * @param soc - soc handle + * @param pdev_id - id of the physical device object * @param data - pdev stats - * @return - void + * @return - QDF_STATUS */ -static inline void +static inline QDF_STATUS cdp_update_pdev_host_stats(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, + uint8_t pdev_id, void *data, uint16_t stats_id) { - if (soc && soc->ops && soc->ops->host_stats_ops && - soc->ops->host_stats_ops->txrx_update_pdev_stats) - return soc->ops->host_stats_ops->txrx_update_pdev_stats - (pdev, data, stats_id); + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance", __func__); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->host_stats_ops || + !soc->ops->host_stats_ops->txrx_update_pdev_stats) + return QDF_STATUS_E_FAILURE; + + return soc->ops->host_stats_ops->txrx_update_pdev_stats(soc, pdev_id, + data, + stats_id); } /** * @brief Update vdev host stats * - * @param soc - soc handle - * @param vdev - the physical device object - * @param data - pdev stats - * @param stats_id - type of stats + * @soc: soc handle + * @vdev_id: id of the virtual device object + * @data: pdev stats + * @stats_id: type of stats * - * @return - void + * Return: QDF_STATUS */ -static inline void +static inline QDF_STATUS cdp_update_vdev_host_stats(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, + uint8_t vdev_id, void *data, uint16_t stats_id) { @@ -482,98 +464,148 @@ cdp_update_vdev_host_stats(ol_txrx_soc_handle soc, QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance", __func__); QDF_BUG(0); - return; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->txrx_update_vdev_stats) - return; + return QDF_STATUS_E_FAILURE; - return soc->ops->host_stats_ops->txrx_update_vdev_stats(vdev, data, + return soc->ops->host_stats_ops->txrx_update_vdev_stats(soc, vdev_id, + data, stats_id); } +/** + * @brief Call to get specified peer stats + * + * @param soc - soc handle + * @param vdev_id - vdev_id of vdev object + * @param peer_mac - mac address of the peer + * @param type - enum of required stats + * @param buf - buffer to hold the value + * @return - QDF_STATUS + */ +static inline QDF_STATUS +cdp_txrx_get_peer_stats_param(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac, + enum cdp_peer_stats_type type, + cdp_peer_stats_param_t *buf) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance", __func__); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->host_stats_ops || + !soc->ops->host_stats_ops->txrx_get_peer_stats_param) + return QDF_STATUS_E_FAILURE; + + return soc->ops->host_stats_ops->txrx_get_peer_stats_param(soc, + vdev_id, + peer_mac, + type, + buf); +} + /** * @brief Call to get peer stats * - * @param peer - dp peer object + * @param soc - soc handle + * @param vdev_id - vdev_id of vdev object + * @param peer_mac - mac address of the peer * @return - struct cdp_peer_stats */ -static inline struct cdp_peer_stats * -cdp_host_get_peer_stats(ol_txrx_soc_handle soc, struct cdp_peer *peer) +static inline QDF_STATUS +cdp_host_get_peer_stats(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac, + struct cdp_peer_stats *peer_stats) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance", __func__); QDF_BUG(0); - return NULL; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->txrx_get_peer_stats) - return NULL; + return QDF_STATUS_E_FAILURE; - return soc->ops->host_stats_ops->txrx_get_peer_stats(peer); + return soc->ops->host_stats_ops->txrx_get_peer_stats(soc, vdev_id, + peer_mac, + peer_stats); } /** * @brief Call to reset ald stats * - * @param peer - dp peer object + * @param soc - soc handle + * @param vdev_id - vdev_id of vdev object + * @param peer_mac - mac address of the peer * @return - void */ -static inline void -cdp_host_reset_peer_ald_stats(ol_txrx_soc_handle soc, - struct cdp_peer *peer) +static inline QDF_STATUS +cdp_host_reset_peer_ald_stats(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->txrx_reset_peer_ald_stats) - return; + return QDF_STATUS_E_FAILURE; - return soc->ops->host_stats_ops->txrx_reset_peer_ald_stats(peer); + return soc->ops->host_stats_ops->txrx_reset_peer_ald_stats(soc, + vdev_id, + peer_mac); } /** * @brief Call to reset peer stats * - * @param peer - dp peer object - * @return - void + * @param soc - soc handle + * @param vdev_id - vdev_id of vdev object + * @param peer_mac - mac address of the peer + * @return - QDF_STATUS */ -static inline void +static inline QDF_STATUS cdp_host_reset_peer_stats(ol_txrx_soc_handle soc, - struct cdp_peer *peer) + uint8_t vdev_id, uint8_t *peer_mac) { 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_E_FAILURE; } if (!soc->ops->host_stats_ops || !soc->ops->host_stats_ops->txrx_reset_peer_stats) - return; + return QDF_STATUS_E_FAILURE; - return soc->ops->host_stats_ops->txrx_reset_peer_stats(peer); + return soc->ops->host_stats_ops->txrx_reset_peer_stats(soc, + vdev_id, + peer_mac); } /** * @brief Call to get vdev stats * - * @param vdev - dp vdev object + * @param soc - dp soc object + * @param vdev_id - id of dp vdev object * @param buf - buffer * @return - int */ static inline int cdp_host_get_vdev_stats(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, + uint8_t vdev_id, struct cdp_vdev_stats *buf, bool is_aggregate) { @@ -588,7 +620,7 @@ cdp_host_get_vdev_stats(ol_txrx_soc_handle soc, !soc->ops->host_stats_ops->txrx_get_vdev_stats) return 0; - return soc->ops->host_stats_ops->txrx_get_vdev_stats(vdev, + return soc->ops->host_stats_ops->txrx_get_vdev_stats(soc, vdev_id, buf, is_aggregate); } @@ -629,14 +661,15 @@ cdp_update_host_vdev_stats(ol_txrx_soc_handle soc, /** * @brief Call to get vdev extd stats * - * @param vdev - dp vdev object + * @param soc - soc handle + * @param vdev_id - id of dp vdev object * @param buf - buffer * @return - int */ static inline int cdp_get_vdev_extd_stats(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, - void *buf) + uint8_t vdev_id, + wmi_host_vdev_extd_stats *buf) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -649,18 +682,21 @@ cdp_get_vdev_extd_stats(ol_txrx_soc_handle soc, !soc->ops->host_stats_ops->txrx_get_vdev_extd_stats) return 0; - return soc->ops->host_stats_ops->txrx_get_vdev_extd_stats(vdev, buf); + return soc->ops->host_stats_ops->txrx_get_vdev_extd_stats(soc, vdev_id, + buf); } /** * @brief Call to get cdp_pdev_stats * - * @param pdev - dp pdev object - * @return - cdp_pdev_stats + * @param soc - soc handle + * @param pdev_id - id of dp pdev object + * @param buf - buffer to hold cdp_pdev_stats + * @return - success/failure */ -static inline struct cdp_pdev_stats* +static inline int cdp_host_get_pdev_stats(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev) + uint8_t pdev_id, struct cdp_pdev_stats *buf) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -673,19 +709,20 @@ cdp_host_get_pdev_stats(ol_txrx_soc_handle soc, !soc->ops->host_stats_ops->txrx_get_pdev_stats) return 0; - return soc->ops->host_stats_ops->txrx_get_pdev_stats(pdev); + return soc->ops->host_stats_ops->txrx_get_pdev_stats(soc, pdev_id, buf); } /** * @brief Call to get radio stats * - * @param pdev - dp pdev object + * @param soc - soc handle + * @param pdev_id - id of dp pdev object * @param scn_stats_user - stats buffer * @return - int */ static inline int cdp_host_get_radio_stats(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, + uint8_t pdev_id, void *buf) { if (!soc || !soc->ops) { @@ -699,47 +736,7 @@ cdp_host_get_radio_stats(ol_txrx_soc_handle soc, !soc->ops->host_stats_ops->txrx_get_radio_stats) return 0; - return soc->ops->host_stats_ops->txrx_get_radio_stats(pdev, + return soc->ops->host_stats_ops->txrx_get_radio_stats(soc, pdev_id, buf); } - -/** - * @brief confgure rate stats at soc - * - * @param soc - opaque soc handle - * @param vap - capabilities - * @return - void - */ -static inline void -cdp_soc_configure_rate_stats(ol_txrx_soc_handle soc, 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; - } - - if (!soc->ops->host_stats_ops || - !soc->ops->host_stats_ops->configure_rate_stats) - return; - - return soc->ops->host_stats_ops->configure_rate_stats(soc, val); -} - -/** - * @brief Parse the stats header and get the payload from the message. - * - * @param pdev - the physical device object - * @param msg_word - stats buffer received from FW - * @param msg_len - length of the message - * @param type - place holder for parsed message type - * @param status - place holder for parsed message status - * @return - pointer to received stat payload - */ - -#if defined(QCA_SUPPORT_SON) || defined(ENHANCED_STATS) -uint32_t *ol_txrx_get_en_stats_base(struct cdp_pdev *pdev, uint32_t *msg_word, - uint32_t msg_len, enum htt_cmn_t2h_en_stats_type *type, enum htt_cmn_t2h_en_stats_status *status); -#endif #endif /* _CDP_TXRX_HOST_STATS_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ipa.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ipa.h index e989df69f036b5bc0e24b0bb68c87ef00c6a4198..9073aa90466692d24d04f5a243c967b3e9b095f2 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ipa.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ipa.h @@ -35,23 +35,23 @@ /** * cdp_ipa_get_resource() - Get allocated WLAN resources for IPA data path * @soc - data path soc handle - * @pdev - device instance pointer + * @pdev_id - device instance id * * Get allocated WLAN resources for IPA data path * * return QDF_STATUS_SUCCESS */ static inline QDF_STATUS -cdp_ipa_get_resource(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +cdp_ipa_get_resource(ol_txrx_soc_handle soc, uint8_t pdev_id) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_get_resource) - return soc->ops->ipa_ops->ipa_get_resource(pdev); + return soc->ops->ipa_ops->ipa_get_resource(soc, pdev_id); return QDF_STATUS_SUCCESS; } @@ -59,23 +59,23 @@ cdp_ipa_get_resource(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) /** * cdp_ipa_set_doorbell_paddr() - give IPA db paddr to FW * @soc - data path soc handle - * @pdev - device instance pointer + * @pdev_id - device instance id * * give IPA db paddr to FW * * return QDF_STATUS_SUCCESS */ static inline QDF_STATUS -cdp_ipa_set_doorbell_paddr(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +cdp_ipa_set_doorbell_paddr(ol_txrx_soc_handle soc, uint8_t pdev_id) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_set_doorbell_paddr) - return soc->ops->ipa_ops->ipa_set_doorbell_paddr(pdev); + return soc->ops->ipa_ops->ipa_set_doorbell_paddr(soc, pdev_id); return QDF_STATUS_SUCCESS; } @@ -83,7 +83,7 @@ cdp_ipa_set_doorbell_paddr(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) /** * cdp_ipa_set_active() - activate/de-ctivate IPA offload path * @soc - data path soc handle - * @pdev - device instance pointer + * @pdev_id - device instance id * @uc_active - activate or de-activate * @is_tx - toggle tx or rx data path * @@ -92,18 +92,18 @@ cdp_ipa_set_doorbell_paddr(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) * return QDF_STATUS_SUCCESS */ static inline QDF_STATUS -cdp_ipa_set_active(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - bool uc_active, bool is_tx) +cdp_ipa_set_active(ol_txrx_soc_handle soc, uint8_t pdev_id, bool uc_active, + bool is_tx) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_set_active) - return soc->ops->ipa_ops->ipa_set_active(pdev, uc_active, - is_tx); + return soc->ops->ipa_ops->ipa_set_active(soc, pdev_id, + uc_active, is_tx); return QDF_STATUS_SUCCESS; } @@ -111,7 +111,7 @@ cdp_ipa_set_active(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, /** * cdp_ipa_op_response() - event handler from FW * @soc - data path soc handle - * @pdev - device instance pointer + * @pdev_id - device instance id * @op_msg - event contents from firmware * * event handler from FW @@ -119,17 +119,16 @@ cdp_ipa_set_active(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, * return QDF_STATUS_SUCCESS */ static inline QDF_STATUS -cdp_ipa_op_response(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint8_t *op_msg) +cdp_ipa_op_response(ol_txrx_soc_handle soc, uint8_t pdev_id, uint8_t *op_msg) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_op_response) - return soc->ops->ipa_ops->ipa_op_response(pdev, op_msg); + return soc->ops->ipa_ops->ipa_op_response(soc, pdev_id, op_msg); return QDF_STATUS_SUCCESS; } @@ -137,7 +136,7 @@ cdp_ipa_op_response(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, /** * cdp_ipa_register_op_cb() - register event handler function pointer * @soc - data path soc handle - * @pdev - device instance pointer + * @pdev_id - device instance id * @op_cb - event handler callback function pointer * @usr_ctxt - user context to registered * @@ -146,18 +145,18 @@ cdp_ipa_op_response(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, * return QDF_STATUS_SUCCESS */ static inline QDF_STATUS -cdp_ipa_register_op_cb(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - ipa_uc_op_cb_type op_cb, void *usr_ctxt) +cdp_ipa_register_op_cb(ol_txrx_soc_handle soc, uint8_t pdev_id, + ipa_uc_op_cb_type op_cb, void *usr_ctxt) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_register_op_cb) - return soc->ops->ipa_ops->ipa_register_op_cb(pdev, op_cb, - usr_ctxt); + return soc->ops->ipa_ops->ipa_register_op_cb(soc, pdev_id, + op_cb, usr_ctxt); return QDF_STATUS_SUCCESS; } @@ -165,52 +164,55 @@ cdp_ipa_register_op_cb(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, /** * cdp_ipa_get_stat() - get IPA data path stats from FW * @soc - data path soc handle - * @pdev - device instance pointer + * @pdev_id - device instance id * * get IPA data path stats from FW async * * return QDF_STATUS_SUCCESS */ static inline QDF_STATUS -cdp_ipa_get_stat(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +cdp_ipa_get_stat(ol_txrx_soc_handle soc, uint8_t pdev_id) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_get_stat) - return soc->ops->ipa_ops->ipa_get_stat(pdev); + return soc->ops->ipa_ops->ipa_get_stat(soc, pdev_id); return QDF_STATUS_SUCCESS; } /** * cdp_tx_send_ipa_data_frame() - send IPA data frame - * @vdev: vdev + * @soc - data path soc handle + * @vdev_id: vdev id * @skb: skb * * Return: skb/ NULL is for success */ static inline qdf_nbuf_t cdp_ipa_tx_send_data_frame(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, qdf_nbuf_t skb) + uint8_t vdev_id, + qdf_nbuf_t skb) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !vdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return skb; } if (soc->ops->ipa_ops->ipa_tx_data_frame) - return soc->ops->ipa_ops->ipa_tx_data_frame(vdev, skb); + return soc->ops->ipa_ops->ipa_tx_data_frame(soc, vdev_id, skb); return skb; } /** * cdp_ipa_set_uc_tx_partition_base() - set tx packet partition base - * @pdev: physical device instance + * @soc - data path soc handle + * @cfg_pdev: physical device instance config * @value: partition base value * * Return: QDF_STATUS @@ -235,23 +237,24 @@ cdp_ipa_set_uc_tx_partition_base(ol_txrx_soc_handle soc, #ifdef FEATURE_METERING /** * cdp_ipa_uc_get_share_stats() - get Tx/Rx byte stats from FW - * @pdev: physical device instance + * @soc - data path soc handle + * @pdev_id: physical device instance number * @value: reset stats * * Return: QDF_STATUS */ static inline QDF_STATUS -cdp_ipa_uc_get_share_stats(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, uint8_t value) +cdp_ipa_uc_get_share_stats(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint8_t value) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_uc_get_share_stats) - return soc->ops->ipa_ops->ipa_uc_get_share_stats(pdev, + return soc->ops->ipa_ops->ipa_uc_get_share_stats(soc, pdev_id, value); return QDF_STATUS_SUCCESS; @@ -259,24 +262,23 @@ cdp_ipa_uc_get_share_stats(ol_txrx_soc_handle soc, /** * cdp_ipa_uc_set_quota() - set quota limit to FW - * @pdev: physical device instance + * @soc - data path soc handle + * @pdev_id: physical device instance number * @value: quota limit bytes * * Return: QDF_STATUS */ static inline QDF_STATUS -cdp_ipa_uc_set_quota(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, uint64_t value) +cdp_ipa_uc_set_quota(ol_txrx_soc_handle soc, uint8_t pdev_id, uint64_t value) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_uc_set_quota) - return soc->ops->ipa_ops->ipa_uc_set_quota(pdev, - value); + return soc->ops->ipa_ops->ipa_uc_set_quota(soc, pdev_id, value); return QDF_STATUS_SUCCESS; } @@ -285,7 +287,7 @@ cdp_ipa_uc_set_quota(ol_txrx_soc_handle soc, /** * cdp_ipa_enable_autonomy() - Enable autonomy RX data path * @soc: data path soc handle - * @pdev: handle to the device instance + * @pdev_id: physical device instance number * * IPA Data path is enabled and resumed. * All autonomy data path elements are ready to deliver packet @@ -295,16 +297,16 @@ cdp_ipa_uc_set_quota(ol_txrx_soc_handle soc, * Return: QDF_STATUS */ static inline QDF_STATUS -cdp_ipa_enable_autonomy(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +cdp_ipa_enable_autonomy(ol_txrx_soc_handle soc, uint8_t pdev_id) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_enable_autonomy) - return soc->ops->ipa_ops->ipa_enable_autonomy(pdev); + return soc->ops->ipa_ops->ipa_enable_autonomy(soc, pdev_id); return QDF_STATUS_SUCCESS; } @@ -312,7 +314,7 @@ cdp_ipa_enable_autonomy(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) /** * cdp_ipa_disable_autonomy() - Disable autonomy RX data path * @soc: data path soc handle - * @pdev: handle to the device instance + * @pdev_id: physical device instance number * * IPA Data path is enabled and resumed. * All autonomy datapath elements are ready to deliver packet @@ -322,15 +324,15 @@ cdp_ipa_enable_autonomy(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) * Return: QDF_STATUS */ static inline QDF_STATUS -cdp_ipa_disable_autonomy(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +cdp_ipa_disable_autonomy(ol_txrx_soc_handle soc, uint8_t pdev_id) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } - if (soc->ops->ipa_ops->ipa_enable_autonomy) - return soc->ops->ipa_ops->ipa_disable_autonomy(pdev); + if (soc->ops->ipa_ops->ipa_disable_autonomy) + return soc->ops->ipa_ops->ipa_disable_autonomy(soc, pdev_id); return QDF_STATUS_SUCCESS; } @@ -339,7 +341,7 @@ cdp_ipa_disable_autonomy(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) /** * cdp_ipa_setup() - Setup and connect IPA pipes * @soc: data path soc handle - * @pdev: handle to the device instance + * @pdev_id: handle to the device instance number * @ipa_i2w_cb: IPA to WLAN callback * @ipa_w2i_cb: WLAN to IPA callback * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback @@ -355,21 +357,21 @@ cdp_ipa_disable_autonomy(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) * Return: QDF_STATUS */ static inline QDF_STATUS -cdp_ipa_setup(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, void *ipa_i2w_cb, +cdp_ipa_setup(ol_txrx_soc_handle soc, uint8_t pdev_id, void *ipa_i2w_cb, void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled, uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle, bool is_smmu_enabled, qdf_ipa_sys_connect_params_t *sys_in, bool over_gsi) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_setup) - return soc->ops->ipa_ops->ipa_setup(pdev, ipa_i2w_cb, + return soc->ops->ipa_ops->ipa_setup(soc, pdev_id, ipa_i2w_cb, ipa_w2i_cb, ipa_wdi_meter_notifier_cb, ipa_desc_size, ipa_priv, @@ -385,7 +387,7 @@ cdp_ipa_setup(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, void *ipa_i2w_cb, /** * cdp_ipa_setup() - Setup and connect IPA pipes * @soc: data path soc handle - * @pdev: handle to the device instance + * @pdev_id: handle to the device instance number * @ipa_i2w_cb: IPA to WLAN callback * @ipa_w2i_cb: WLAN to IPA callback * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback @@ -398,19 +400,19 @@ cdp_ipa_setup(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, void *ipa_i2w_cb, * Return: QDF_STATUS */ static inline QDF_STATUS -cdp_ipa_setup(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, void *ipa_i2w_cb, +cdp_ipa_setup(ol_txrx_soc_handle soc, uint8_t pdev_id, void *ipa_i2w_cb, void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled, uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_setup) - return soc->ops->ipa_ops->ipa_setup(pdev, ipa_i2w_cb, + return soc->ops->ipa_ops->ipa_setup(soc, pdev_id, ipa_i2w_cb, ipa_w2i_cb, ipa_wdi_meter_notifier_cb, ipa_desc_size, ipa_priv, @@ -425,14 +427,15 @@ cdp_ipa_setup(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, void *ipa_i2w_cb, /** * cdp_ipa_cleanup() - Disconnect IPA pipes * @soc: data path soc handle + * @pdev_id: handle to the device instance number * @tx_pipe_handle: Tx pipe handle * @rx_pipe_handle: Rx pipe handle * * Return: QDF_STATUS */ static inline QDF_STATUS -cdp_ipa_cleanup(ol_txrx_soc_handle soc, uint32_t tx_pipe_handle, - uint32_t rx_pipe_handle) +cdp_ipa_cleanup(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint32_t tx_pipe_handle, uint32_t rx_pipe_handle) { if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -441,7 +444,8 @@ cdp_ipa_cleanup(ol_txrx_soc_handle soc, uint32_t tx_pipe_handle, } if (soc->ops->ipa_ops->ipa_cleanup) - return soc->ops->ipa_ops->ipa_cleanup(tx_pipe_handle, + return soc->ops->ipa_ops->ipa_cleanup(soc, pdev_id, + tx_pipe_handle, rx_pipe_handle); return QDF_STATUS_SUCCESS; @@ -508,22 +512,22 @@ cdp_ipa_cleanup_iface(ol_txrx_soc_handle soc, char *ifname, /** * cdp_ipa_uc_enable_pipes() - Enable and resume traffic on Tx/Rx pipes - * @soc: data path soc handle - * @pdev: handle to the device instance + * @soc - data path soc handle + * @pdev_id - device instance id * * Return: QDF_STATUS */ static inline QDF_STATUS -cdp_ipa_enable_pipes(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +cdp_ipa_enable_pipes(ol_txrx_soc_handle soc, uint8_t pdev_id) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_enable_pipes) - return soc->ops->ipa_ops->ipa_enable_pipes(pdev); + return soc->ops->ipa_ops->ipa_enable_pipes(soc, pdev_id); return QDF_STATUS_SUCCESS; } @@ -531,21 +535,21 @@ cdp_ipa_enable_pipes(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) /** * cdp_ipa_uc_disable_pipes() - Suspend traffic and disable Tx/Rx pipes * @soc: data path soc handle - * @pdev: handle to the device instance + * @pdev_id - device instance id * * Return: QDF_STATUS */ static inline QDF_STATUS -cdp_ipa_disable_pipes(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +cdp_ipa_disable_pipes(ol_txrx_soc_handle soc, uint8_t pdev_id) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !pdev) { + if (!soc || !soc->ops || !soc->ops->ipa_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_disable_pipes) - return soc->ops->ipa_ops->ipa_disable_pipes(pdev); + return soc->ops->ipa_ops->ipa_disable_pipes(soc, pdev_id); return QDF_STATUS_SUCCESS; } @@ -579,7 +583,7 @@ cdp_ipa_set_perf_level(ol_txrx_soc_handle soc, int client, * cdp_ipa_rx_intrabss_fwd() - Perform intra-bss fwd for IPA RX path * * @soc: data path soc handle - * @vdev: vdev handle + * @vdev_id: vdev id * @nbuf: pointer to skb of ethernet packet received from IPA RX path * @fwd_success: pointer to indicate if skb succeeded in intra-bss TX * @@ -589,17 +593,18 @@ cdp_ipa_set_perf_level(ol_txrx_soc_handle soc, int client, * network stack. false if packet needs to be passed to network stack. */ static inline bool -cdp_ipa_rx_intrabss_fwd(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, +cdp_ipa_rx_intrabss_fwd(ol_txrx_soc_handle soc, uint8_t vdev_id, qdf_nbuf_t nbuf, bool *fwd_success) { - if (!soc || !soc->ops || !soc->ops->ipa_ops || !vdev || !fwd_success) { + if (!soc || !soc->ops || !soc->ops->ipa_ops || !fwd_success) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); return QDF_STATUS_E_FAILURE; } if (soc->ops->ipa_ops->ipa_rx_intrabss_fwd) - return soc->ops->ipa_ops->ipa_rx_intrabss_fwd(vdev, nbuf, + return soc->ops->ipa_ops->ipa_rx_intrabss_fwd(soc, vdev_id, + nbuf, fwd_success); /* Fall back to pass up to stack */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_me.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_me.h index f897febe745ee82b71643846f06355d8ec3e058e..010b4c383a8a4714b12560d7c2c22467ac52430e 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_me.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_me.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -28,67 +28,8 @@ /* TODO: adf need to be replaced with qdf */ #include "cdp_txrx_handle.h" -static inline u_int16_t -cdp_tx_desc_alloc_and_mark_for_mcast_clone(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, u_int16_t buf_count) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); - QDF_BUG(0); - return 0; - } - - if (!soc->ops->me_ops || - !soc->ops->me_ops->tx_desc_alloc_and_mark_for_mcast_clone) - return 0; - - return soc->ops->me_ops-> - tx_desc_alloc_and_mark_for_mcast_clone - (pdev, buf_count); -} - -static inline u_int16_t -cdp_tx_desc_free_and_unmark_for_mcast_clone(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, u_int16_t buf_count) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); - QDF_BUG(0); - return 0; - } - - if (!soc->ops->me_ops || - !soc->ops->me_ops->tx_desc_free_and_unmark_for_mcast_clone) - return 0; - - return soc->ops->me_ops-> - tx_desc_free_and_unmark_for_mcast_clone - (pdev, buf_count); -} - -static inline u_int16_t -cdp_tx_get_mcast_buf_allocated_marked(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); - QDF_BUG(0); - return 0; - } - - if (!soc->ops->me_ops || - !soc->ops->me_ops->tx_get_mcast_buf_allocated_marked) - return 0; - - return soc->ops->me_ops->tx_get_mcast_buf_allocated_marked - (pdev); -} - static inline void -cdp_tx_me_alloc_descriptor(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +cdp_tx_me_alloc_descriptor(ol_txrx_soc_handle soc, uint8_t pdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -101,11 +42,11 @@ cdp_tx_me_alloc_descriptor(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) !soc->ops->me_ops->tx_me_alloc_descriptor) return; - soc->ops->me_ops->tx_me_alloc_descriptor(pdev); + soc->ops->me_ops->tx_me_alloc_descriptor(soc, pdev_id); } static inline void -cdp_tx_me_free_descriptor(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +cdp_tx_me_free_descriptor(ol_txrx_soc_handle soc, uint8_t pdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -118,12 +59,13 @@ cdp_tx_me_free_descriptor(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) !soc->ops->me_ops->tx_me_free_descriptor) return; - soc->ops->me_ops->tx_me_free_descriptor(pdev); + soc->ops->me_ops->tx_me_free_descriptor(soc, pdev_id); } static inline uint16_t -cdp_tx_me_convert_ucast(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - qdf_nbuf_t wbuf, u_int8_t newmac[][6], uint8_t newmaccnt) +cdp_tx_me_convert_ucast(ol_txrx_soc_handle soc, uint8_t vdev_id, + qdf_nbuf_t wbuf, u_int8_t newmac[][6], + uint8_t newmaccnt) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -137,35 +79,7 @@ cdp_tx_me_convert_ucast(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, return 0; return soc->ops->me_ops->tx_me_convert_ucast - (vdev, wbuf, newmac, newmaccnt); + (soc, vdev_id, wbuf, newmac, newmaccnt); } -/* Should be a function pointer in ol_txrx_osif_ops{} */ -/** - * @brief notify mcast frame indication from FW. - * @details - * This notification will be used to convert - * multicast frame to unicast. - * - * @param pdev - handle to the ctrl SW's physical device object - * @param vdev_id - ID of the virtual device received the special data - * @param msdu - the multicast msdu returned by FW for host inspect - */ - -static inline int cdp_mcast_notify(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, u_int8_t vdev_id, qdf_nbuf_t msdu) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); - QDF_BUG(0); - return 0; - } - - if (!soc->ops->me_ops || - !soc->ops->me_ops->mcast_notify) - return 0; - - return soc->ops->me_ops->mcast_notify(pdev, vdev_id, msdu); -} #endif diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_misc.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_misc.h index f5a97956340813211fb9a66b717b2d66d4dece75..1db265f6ffe06860fc5b0e703104fbcdf5b83f47 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_misc.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_misc.h @@ -27,11 +27,10 @@ #include "cdp_txrx_handle.h" /** * cdp_tx_non_std() - Allow the control-path SW to send data frames - * - * @soc - data path soc handle - * @data_vdev - which vdev should transmit the tx data frames - * @tx_spec - what non-standard handling to apply to the tx data frames - * @msdu_list - NULL-terminated list of tx MSDUs + * @soc: data path soc handle + * @vdev_id: id of vdev + * @tx_spec: what non-standard handling to apply to the tx data frames + * @msdu_list: NULL-terminated list of tx MSDUs * * Generally, all tx data frames come from the OS shim into the txrx layer. * However, there are rare cases such as TDLS messaging where the UMAC @@ -49,8 +48,8 @@ * Return: null - success, skb - failure */ static inline qdf_nbuf_t -cdp_tx_non_std(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list) +cdp_tx_non_std(ol_txrx_soc_handle soc, uint8_t vdev_id, + enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, @@ -59,23 +58,23 @@ cdp_tx_non_std(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, } if (soc->ops->misc_ops->tx_non_std) - return soc->ops->misc_ops->tx_non_std( - vdev, tx_spec, msdu_list); + return soc->ops->misc_ops->tx_non_std(soc, vdev_id, tx_spec, + msdu_list); return NULL; } /** * cdp_set_ibss_vdev_heart_beat_timer() - Update ibss vdev heart * beat timer - * @soc - data path soc handle - * @vdev - vdev handle - * @timer_value_sec - new heart beat timer value + * @soc: data path soc handle + * @vdev_id: id of vdev + * @timer_value_sec: new heart beat timer value * * Return: Old timer value set in vdev. */ static inline uint16_t cdp_set_ibss_vdev_heart_beat_timer(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, uint16_t timer_value_sec) + uint8_t vdev_id, uint16_t timer_value_sec) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -85,21 +84,21 @@ cdp_set_ibss_vdev_heart_beat_timer(ol_txrx_soc_handle soc, if (soc->ops->misc_ops->set_ibss_vdev_heart_beat_timer) return soc->ops->misc_ops->set_ibss_vdev_heart_beat_timer( - vdev, timer_value_sec); + soc, vdev_id, timer_value_sec); return 0; } /** * cdp_set_wisa_mode() - set wisa mode - * @soc - data path soc handle - * @vdev - vdev handle - * @enable - enable or disable + * @soc: data path soc handle + * @vdev_id: vdev_id + * @enable: enable or disable * * Return: QDF_STATUS_SUCCESS mode enable success */ static inline QDF_STATUS -cdp_set_wisa_mode(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, bool enable) +cdp_set_wisa_mode(ol_txrx_soc_handle soc, uint8_t vdev_id, bool enable) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -108,20 +107,20 @@ cdp_set_wisa_mode(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, bool enable) } if (soc->ops->misc_ops->set_wisa_mode) - return soc->ops->misc_ops->set_wisa_mode(vdev, enable); + return soc->ops->misc_ops->set_wisa_mode(soc, vdev_id, enable); return QDF_STATUS_SUCCESS; } /** * cdp_data_stall_cb_register() - register data stall callback - * @soc - data path soc handle - * @pdev - device instance pointer - * @cb - callback function + * @soc: data path soc handle + * @pdev_id: id of data path pdev handle + * @cb: callback function * * Return: QDF_STATUS_SUCCESS register success */ static inline QDF_STATUS cdp_data_stall_cb_register(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, + uint8_t pdev_id, data_stall_detect_cb cb) { if (!soc || !soc->ops || !soc->ops->misc_ops) { @@ -132,21 +131,20 @@ static inline QDF_STATUS cdp_data_stall_cb_register(ol_txrx_soc_handle soc, if (soc->ops->misc_ops->txrx_data_stall_cb_register) return soc->ops->misc_ops->txrx_data_stall_cb_register( - pdev, - cb); + soc, pdev_id, cb); return QDF_STATUS_SUCCESS; } /** * cdp_data_stall_cb_deregister() - de-register data stall callback - * @soc - data path soc handle - * @pdev - device instance pointer + * @soc: data path soc handle + * @pdev_id: id of data path pdev handle * @cb - callback function * * Return: QDF_STATUS_SUCCESS de-register success */ static inline QDF_STATUS cdp_data_stall_cb_deregister(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, + uint8_t pdev_id, data_stall_detect_cb cb) { if (!soc || !soc->ops || !soc->ops->misc_ops) { @@ -157,15 +155,13 @@ static inline QDF_STATUS cdp_data_stall_cb_deregister(ol_txrx_soc_handle soc, if (soc->ops->misc_ops->txrx_data_stall_cb_deregister) return soc->ops->misc_ops->txrx_data_stall_cb_deregister( - pdev, - cb); + soc, pdev_id, cb); return QDF_STATUS_SUCCESS; } /** * cdp_post_data_stall_event() - post data stall event - * @soc - data path soc handle - * @pdev - device instance pointer + * @soc: data path soc handle * @indicator: Module triggering data stall * @data_stall_type: data stall event type * @pdev_id: pdev id @@ -176,7 +172,6 @@ static inline QDF_STATUS cdp_data_stall_cb_deregister(ol_txrx_soc_handle soc, */ static inline void cdp_post_data_stall_event(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, enum data_stall_log_event_indicator indicator, enum data_stall_log_event_type data_stall_type, uint32_t pdev_id, uint32_t vdev_id_bitmap, @@ -194,22 +189,21 @@ cdp_post_data_stall_event(ol_txrx_soc_handle soc, return; soc->ops->misc_ops->txrx_post_data_stall_event( - pdev, - indicator, data_stall_type, pdev_id, + soc, indicator, data_stall_type, pdev_id, vdev_id_bitmap, recovery_type); } /** * cdp_set_wmm_param() - set wmm parameter - * @soc - data path soc handle - * @pdev - device instance pointer - * @wmm_param - wmm parameter + * @soc: data path soc handle + * @pdev_id: id of data path pdev handle + * @wmm_param: wmm parameter * * Return: none */ static inline void -cdp_set_wmm_param(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - struct ol_tx_wmm_param_t wmm_param) +cdp_set_wmm_param(ol_txrx_soc_handle soc, uint8_t pdev_id, + struct ol_tx_wmm_param_t wmm_param) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -218,21 +212,21 @@ cdp_set_wmm_param(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->misc_ops->set_wmm_param) - return soc->ops->misc_ops->set_wmm_param( - pdev, wmm_param); + return soc->ops->misc_ops->set_wmm_param(soc, pdev_id, + wmm_param); return; } /** * cdp_runtime_suspend() - suspend - * @soc - data path soc handle - * @pdev - device instance pointer + * @soc: data path soc handle + * @pdev_id: id of data path pdev handle * * Return: QDF_STATUS_SUCCESS suspend success */ static inline QDF_STATUS cdp_runtime_suspend(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev) + uint8_t pdev_id) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -241,20 +235,20 @@ static inline QDF_STATUS cdp_runtime_suspend(ol_txrx_soc_handle soc, } if (soc->ops->misc_ops->runtime_suspend) - return soc->ops->misc_ops->runtime_suspend(pdev); + return soc->ops->misc_ops->runtime_suspend(soc, pdev_id); return QDF_STATUS_SUCCESS; } /** * cdp_runtime_resume() - resume - * @soc - data path soc handle - * @pdev - device instance pointer + * @soc: data path soc handle + * @pdev_id: id of data path pdev handle * * Return: QDF_STATUS_SUCCESS suspend success */ static inline QDF_STATUS cdp_runtime_resume(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev) + uint8_t pdev_id) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -263,21 +257,21 @@ static inline QDF_STATUS cdp_runtime_resume(ol_txrx_soc_handle soc, } if (soc->ops->misc_ops->runtime_resume) - return soc->ops->misc_ops->runtime_resume(pdev); + return soc->ops->misc_ops->runtime_resume(soc, pdev_id); return QDF_STATUS_SUCCESS; } /** * cdp_hl_tdls_flag_reset() - tdls flag reset - * @soc - data path soc handle - * @vdev - virtual interface handle pointer - * @flag + * @soc: data path soc handle + * @vdev_id: id of vdev + * @flag: flag indicating to set/reset tdls * * Return: none */ static inline void -cdp_hl_tdls_flag_reset(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, bool flag) +cdp_hl_tdls_flag_reset(ol_txrx_soc_handle soc, uint8_t vdev_id, bool flag) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -286,15 +280,16 @@ cdp_hl_tdls_flag_reset(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, bool flag) } if (soc->ops->misc_ops->hl_tdls_flag_reset) - return soc->ops->misc_ops->hl_tdls_flag_reset(vdev, flag); + return soc->ops->misc_ops->hl_tdls_flag_reset(soc, vdev_id, + flag); return; } /** * cdp_get_opmode() - get vdev operation mode - * @soc - data path soc handle - * @vdev - virtual interface instance + * @soc: data path soc handle + * @vdev_id: id of vdev * * Return virtual device operational mode * op_mode_ap, @@ -307,7 +302,7 @@ cdp_hl_tdls_flag_reset(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, bool flag) * 0 unknown interface */ static inline int -cdp_get_opmode(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +cdp_get_opmode(ol_txrx_soc_handle soc, uint8_t vdev_id) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -316,7 +311,8 @@ cdp_get_opmode(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) } if (soc->ops->misc_ops->get_opmode) - return soc->ops->misc_ops->get_opmode(vdev); + return soc->ops->misc_ops->get_opmode(soc, vdev_id); + return 0; } @@ -347,15 +343,13 @@ cdp_get_vdev_id(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) /** * cdp_get_tx_ack_stats() - get tx ack count for vdev * @soc - data path soc handle - * @pdev - data path device instance * @vdev_id - vdev id * * return tx ack count * 0 invalid count */ static inline uint32_t -cdp_get_tx_ack_stats(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint8_t vdev_id) +cdp_get_tx_ack_stats(ol_txrx_soc_handle soc, uint8_t vdev_id) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -364,26 +358,24 @@ cdp_get_tx_ack_stats(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->misc_ops->get_tx_ack_stats) - return soc->ops->misc_ops->get_tx_ack_stats(pdev, vdev_id); + return soc->ops->misc_ops->get_tx_ack_stats(soc, vdev_id); return 0; } /** - * cdp_bad_peer_txctl_set_setting() - TBD - * @soc - data path soc handle - * @pdev - data path device instance - * @enable - - * @period - - * @txq_limit - - * - * TBD + * cdp_bad_peer_txctl_set_setting() - Set peer timer balance parameters + * @soc: data path soc handle + * @pdev_id: id of datapath pdev handle + * @enable: enable/disable peer balance state + * @period: balance timer period for peer + * @txq_limit: txp limit for peer * * Return: none */ static inline void -cdp_bad_peer_txctl_set_setting(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - int enable, int period, int txq_limit) +cdp_bad_peer_txctl_set_setting(ol_txrx_soc_handle soc, uint8_t pdev_id, + int enable, int period, int txq_limit) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -392,18 +384,19 @@ cdp_bad_peer_txctl_set_setting(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->misc_ops->bad_peer_txctl_set_setting) - return soc->ops->misc_ops->bad_peer_txctl_set_setting(pdev, - enable, period, txq_limit); + return soc->ops->misc_ops->bad_peer_txctl_set_setting( + soc, pdev_id, enable, period, + txq_limit); return; } /** * cdp_bad_peer_txctl_update_threshold() - TBD - * @soc - data path soc handle - * @pdev - data path device instance - * @level - - * @tput_thresh - - * @tx_limit - + * @soc: data path soc handle + * @pdev_id: id of data path pdev handle + * @level: index of the threshold configuration + * @tput_thresh: peer balance throughput threshold + * @tx_limit: peer balance tx limit threshold * * TBD * @@ -411,8 +404,8 @@ cdp_bad_peer_txctl_set_setting(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, */ static inline void cdp_bad_peer_txctl_update_threshold(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, - int level, int tput_thresh, int tx_limit) + uint8_t pdev_id, int level, + int tput_thresh, int tx_limit) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -422,20 +415,21 @@ cdp_bad_peer_txctl_update_threshold(ol_txrx_soc_handle soc, if (soc->ops->misc_ops->bad_peer_txctl_update_threshold) return soc->ops->misc_ops->bad_peer_txctl_update_threshold( - pdev, level, tput_thresh, tx_limit); + soc, pdev_id, level, tput_thresh, tx_limit); return; } /** * cdp_mark_first_wakeup_packet() - set flag to indicate that * fw is compatible for marking first packet after wow wakeup - * @soc - data path soc handle + * @soc: data path soc handle + * @pdev_id: id of data path pdev handle * @value: 1 for enabled/ 0 for disabled * * Return: None */ static inline void cdp_mark_first_wakeup_packet(ol_txrx_soc_handle soc, - uint8_t value) + uint8_t pdev_id, uint8_t value) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -444,21 +438,22 @@ static inline void cdp_mark_first_wakeup_packet(ol_txrx_soc_handle soc, } if (soc->ops->misc_ops->mark_first_wakeup_packet) - return soc->ops->misc_ops->mark_first_wakeup_packet(value); + return soc->ops->misc_ops->mark_first_wakeup_packet( + soc, pdev_id, value); return; } /** * cds_update_mac_id() - update mac_id for vdev - * @soc - data path soc handle + * @psoc: data path soc handle * @vdev_id: vdev id * @mac_id: mac id * * Return: none */ static inline void cdp_update_mac_id(void *psoc, uint8_t vdev_id, - uint8_t mac_id) + uint8_t mac_id) { ol_txrx_soc_handle soc = psoc; @@ -469,20 +464,21 @@ static inline void cdp_update_mac_id(void *psoc, uint8_t vdev_id, } if (soc->ops->misc_ops->update_mac_id) - return soc->ops->misc_ops->update_mac_id(vdev_id, mac_id); + return soc->ops->misc_ops->update_mac_id(soc, vdev_id, mac_id); return; } /** * cdp_flush_rx_frames() - flush cached rx frames - * @soc - data path soc handle - * @peer: peer + * @soc: data path soc handle + * @pdev_id: datapath pdev identifier + * @peer_mac: peer mac address * @drop: set flag to drop frames * * Return: None */ -static inline void cdp_flush_rx_frames(ol_txrx_soc_handle soc, void *peer, - bool drop) +static inline void cdp_flush_rx_frames(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint8_t *peer_mac, bool drop) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -491,13 +487,15 @@ static inline void cdp_flush_rx_frames(ol_txrx_soc_handle soc, void *peer, } if (soc->ops->misc_ops->flush_rx_frames) - return soc->ops->misc_ops->flush_rx_frames(peer, drop); + return soc->ops->misc_ops->flush_rx_frames(soc, pdev_id, + peer_mac, drop); return; } /* * cdp_get_intra_bss_fwd_pkts_count() - to get the total tx and rx packets * that has been forwarded from txrx layer without going to upper layers. + * @soc: Datapath soc handle * @vdev_id: vdev id * @fwd_tx_packets: pointer to forwarded tx packets count parameter * @fwd_rx_packets: pointer to forwarded rx packets count parameter @@ -516,20 +514,21 @@ static inline A_STATUS cdp_get_intra_bss_fwd_pkts_count( if (soc->ops->misc_ops->get_intra_bss_fwd_pkts_count) return soc->ops->misc_ops->get_intra_bss_fwd_pkts_count( - vdev_id, fwd_tx_packets, fwd_rx_packets); + soc, vdev_id, fwd_tx_packets, fwd_rx_packets); return 0; } /** * cdp_pkt_log_init() - API to initialize packet log - * @handle: pdev handle + * @soc: data path soc handle + * @pdev_id: id of data path pdev handle * @scn: HIF context * * Return: void */ static inline void cdp_pkt_log_init(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, void *scn) + uint8_t pdev_id, void *scn) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -538,20 +537,21 @@ static inline void cdp_pkt_log_init(ol_txrx_soc_handle soc, } if (soc->ops->misc_ops->pkt_log_init) - return soc->ops->misc_ops->pkt_log_init(pdev, scn); + return soc->ops->misc_ops->pkt_log_init(soc, pdev_id, scn); return; } /** * cdp_pkt_log_con_service() - API to connect packet log service - * @handle: pdev handle + * @soc: data path soc handle + * @pdev_id: id of data path pdev handle * @scn: HIF context * * Return: void */ static inline void cdp_pkt_log_con_service(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, void *scn) + uint8_t pdev_id, void *scn) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -560,7 +560,8 @@ static inline void cdp_pkt_log_con_service(ol_txrx_soc_handle soc, } if (soc->ops->misc_ops->pkt_log_con_service) - return soc->ops->misc_ops->pkt_log_con_service(pdev, scn); + return soc->ops->misc_ops->pkt_log_con_service( + soc, pdev_id, scn); return; } @@ -592,12 +593,14 @@ static inline int cdp_get_num_rx_contexts(ol_txrx_soc_handle soc) * stats will be passed to user-space by @tx_cb/@rx_cb. * * @soc: soc handle + * @pdev_id: id of data path pdev handle * @tx_cb: tx packet callback * @rx_cb: rx packet callback * * Return: void */ static inline void cdp_register_packetdump_cb(ol_txrx_soc_handle soc, + uint8_t pdev_id, ol_txrx_pktdump_cb tx_cb, ol_txrx_pktdump_cb rx_cb) { @@ -608,7 +611,8 @@ static inline void cdp_register_packetdump_cb(ol_txrx_soc_handle soc, } if (soc->ops->misc_ops->register_pktdump_cb) - return soc->ops->misc_ops->register_pktdump_cb(tx_cb, rx_cb); + return soc->ops->misc_ops->register_pktdump_cb( + soc, pdev_id, tx_cb, rx_cb); } /** @@ -617,10 +621,12 @@ static inline void cdp_register_packetdump_cb(ol_txrx_soc_handle soc, * Deregister callback for TX/RX data packets. * * @soc: soc handle + * @pdev_id: id of data path pdev handle * * Return: void */ -static inline void cdp_deregister_packetdump_cb(ol_txrx_soc_handle soc) +static inline void cdp_deregister_packetdump_cb(ol_txrx_soc_handle soc, + uint8_t pdev_id) { if (!soc || !soc->ops || !soc->ops->misc_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -629,18 +635,44 @@ static inline void cdp_deregister_packetdump_cb(ol_txrx_soc_handle soc) } if (soc->ops->misc_ops->unregister_pktdump_cb) - return soc->ops->misc_ops->unregister_pktdump_cb(); + return soc->ops->misc_ops->unregister_pktdump_cb(soc, pdev_id); +} + +typedef void (*rx_mic_error_callback)(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, + struct cdp_rx_mic_err_info *info); + +/** + * cdp_register_rx_mic_error_ind_handler() - API to register mic error + * indication handler + * + * @soc: soc handle + * @rx_mic_cb: rx mic error indication callback + * + * Return: void + */ +static inline void +cdp_register_rx_mic_error_ind_handler(ol_txrx_soc_handle soc, + rx_mic_error_callback rx_mic_cb) +{ + if (!soc || !soc->ol_ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return; + } + + soc->ol_ops->rx_mic_error = rx_mic_cb; } /** * cdp_pdev_reset_driver_del_ack() - reset driver TCP delayed ack flag - * @soc - data path soc handle - * @pdev - data path device instance + * @soc: data path soc handle + * @pdev_id: pdev id * * Return: none */ static inline void cdp_pdev_reset_driver_del_ack(void *psoc, - struct cdp_pdev *pdev) + uint8_t pdev_id) { ol_txrx_soc_handle soc = psoc; @@ -651,12 +683,13 @@ static inline void cdp_pdev_reset_driver_del_ack(void *psoc, } if (soc->ops->misc_ops->pdev_reset_driver_del_ack) - return soc->ops->misc_ops->pdev_reset_driver_del_ack(pdev); + return soc->ops->misc_ops->pdev_reset_driver_del_ack(soc, + pdev_id); } /* * cdp_vdev_set_driver_del_ack_enable() - set driver delayed ack enabled flag - * @soc - data path soc handle + * @soc: data path soc handle * @vdev_id: vdev id * @rx_packets: number of rx packets * @time_in_ms: time in ms @@ -680,19 +713,51 @@ static inline void cdp_vdev_set_driver_del_ack_enable(ol_txrx_soc_handle soc, if (soc->ops->misc_ops->vdev_set_driver_del_ack_enable) return soc->ops->misc_ops->vdev_set_driver_del_ack_enable( - vdev_id, rx_packets, time_in_ms, high_th, low_th); + soc, vdev_id, rx_packets, time_in_ms, high_th, low_th); +} + +static inline void cdp_vdev_set_bundle_require_flag(ol_txrx_soc_handle soc, + uint8_t vdev_id, + unsigned long tx_bytes, + uint32_t time_in_ms, + uint32_t high_th, + uint32_t low_th) +{ + if (!soc || !soc->ops || !soc->ops->misc_ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return; + } + + if (soc->ops->misc_ops->vdev_set_bundle_require_flag) + return soc->ops->misc_ops->vdev_set_bundle_require_flag( + vdev_id, tx_bytes, time_in_ms, high_th, low_th); +} + +static inline void cdp_pdev_reset_bundle_require_flag(ol_txrx_soc_handle soc, + uint8_t pdev_id) +{ + if (!soc || !soc->ops || !soc->ops->misc_ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return; + } + + if (soc->ops->misc_ops->pdev_reset_bundle_require_flag) + return soc->ops->misc_ops->pdev_reset_bundle_require_flag( + soc, pdev_id); } /** * cdp_txrx_ext_stats_request(): request dp tx and rx extended stats * @soc: soc handle - * @pdev: pdev handle + * @pdev_id: pdev id * @req: stats request structure to fill * * return: status */ static inline QDF_STATUS -cdp_txrx_ext_stats_request(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, +cdp_txrx_ext_stats_request(ol_txrx_soc_handle soc, uint8_t pdev_id, struct cdp_txrx_ext_stats *req) { if (!soc || !soc->ops || !soc->ops->misc_ops || !req) { @@ -702,7 +767,8 @@ cdp_txrx_ext_stats_request(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->misc_ops->txrx_ext_stats_request) - return soc->ops->misc_ops->txrx_ext_stats_request(pdev, req); + return soc->ops->misc_ops->txrx_ext_stats_request(soc, pdev_id, + req); return QDF_STATUS_SUCCESS; } @@ -710,7 +776,7 @@ cdp_txrx_ext_stats_request(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, /** * cdp_request_rx_hw_stats(): request rx hw stats * @soc: soc handle - * @vdev: vdev handle + * @vdev_id: vdev id * * return: none */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mob_def.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mob_def.h index c706d6d2acfda169c6080dd94206898bb32ca4a9..96638a716f26275b5c0cc912090a999dcbbf29f3 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mob_def.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mob_def.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -232,14 +233,14 @@ enum peer_debug_id_type { /** * struct ol_txrx_desc_type - txrx descriptor type - * @sta_id: sta id * @is_qos_enabled: is station qos enabled * @is_wapi_supported: is station wapi supported + * @peer_addr: peer mac address */ struct ol_txrx_desc_type { - uint8_t sta_id; uint8_t is_qos_enabled; uint8_t is_wapi_supported; + struct qdf_mac_addr peer_addr; }; /** @@ -284,14 +285,22 @@ struct txrx_pdev_cfg_param_t { uint32_t uc_tx_partition_base; /* IP, TCP and UDP checksum offload */ bool ip_tcp_udp_checksum_offload; + /* IP, TCP and UDP checksum offload for NAN Mode */ + bool nan_ip_tcp_udp_checksum_offload; + /* IP, TCP and UDP checksum offload for P2P Mode*/ + bool p2p_ip_tcp_udp_checksum_offload; + /* Checksum offload override flag for Legcay modes */ + bool legacy_mode_csum_disable; /* Rx processing in thread from TXRX */ bool enable_rxthread; /* CE classification enabled through INI */ bool ce_classify_enabled; +#if defined(QCA_LL_TX_FLOW_CONTROL_V2) || defined(QCA_LL_PDEV_TX_FLOW_CONTROL) /* Threshold to stop queue in percentage */ uint32_t tx_flow_stop_queue_th; /* Start queue offset in percentage */ uint32_t tx_flow_start_queue_offset; +#endif #ifdef QCA_SUPPORT_TXRX_DRIVER_TCP_DEL_ACK /* enable the tcp delay ack feature in the driver */ @@ -304,11 +313,19 @@ struct txrx_pdev_cfg_param_t { struct ol_tx_sched_wrr_ac_specs_t ac_specs[TX_WMM_AC_NUM]; bool gro_enable; + bool tc_based_dyn_gro; + uint32_t tc_ingress_prio; bool tso_enable; bool lro_enable; + bool sg_enable; bool enable_data_stall_detection; bool enable_flow_steering; bool disable_intra_bss_fwd; + +#ifdef WLAN_SUPPORT_TXRX_HL_BUNDLE + uint16_t bundle_timer_value; + uint16_t bundle_size; +#endif uint8_t pktlog_buffer_size; }; diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mon.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mon.h index 5cefc1d4a34bfe89090f23e8bf6ae02d9e62ea19..a11bb95846bfb2eacebc7601d7b52800909dd6ae 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mon.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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,168 +25,187 @@ #ifndef _CDP_TXRX_MON_H_ #define _CDP_TXRX_MON_H_ #include "cdp_txrx_handle.h" -static inline void cdp_monitor_set_filter_ucast_data - (ol_txrx_soc_handle soc, struct cdp_pdev *pdev, u_int8_t val) + +static inline QDF_STATUS cdp_reset_monitor_mode(ol_txrx_soc_handle soc, + uint8_t pdev_id, + u_int8_t smart_monitor) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance", __func__); QDF_BUG(0); - return; + return 0; } if (!soc->ops->mon_ops || - !soc->ops->mon_ops->txrx_monitor_set_filter_ucast_data) - return; + !soc->ops->mon_ops->txrx_reset_monitor_mode) + return 0; - soc->ops->mon_ops->txrx_monitor_set_filter_ucast_data - (pdev, val); + return soc->ops->mon_ops->txrx_reset_monitor_mode(soc, pdev_id, + smart_monitor); } -static inline void cdp_monitor_set_filter_mcast_data - (ol_txrx_soc_handle soc, struct cdp_pdev *pdev, u_int8_t val) +/** + * cdp_deliver_tx_mgmt() - Deliver mgmt frame for tx capture + * @soc: Datapath SOC handle + * @pdev_id: id of datapath PDEV handle + * @nbuf: Management frame buffer + */ +static inline QDF_STATUS +cdp_deliver_tx_mgmt(ol_txrx_soc_handle soc, uint8_t pdev_id, + qdf_nbuf_t nbuf) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); + "%s: Invalid Instance", __func__); QDF_BUG(0); - return; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->mon_ops || - !soc->ops->mon_ops->txrx_monitor_set_filter_mcast_data) - return; + !soc->ops->mon_ops->txrx_deliver_tx_mgmt) + return QDF_STATUS_E_FAILURE; - soc->ops->mon_ops->txrx_monitor_set_filter_mcast_data - (pdev, val); + return soc->ops->mon_ops->txrx_deliver_tx_mgmt(soc, pdev_id, nbuf); } -static inline void cdp_monitor_set_filter_non_data - (ol_txrx_soc_handle soc, struct cdp_pdev *pdev, u_int8_t val) +#ifdef WLAN_FEATURE_PKT_CAPTURE +static inline void +cdp_pktcapture_record_channel( + ol_txrx_soc_handle soc, + uint8_t pdev_id, + int chan_num) { if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s invalid instance", __func__); QDF_BUG(0); return; } - if (!soc->ops->mon_ops || - !soc->ops->mon_ops->txrx_monitor_set_filter_non_data) + if (!soc->ops->pktcapture_ops || + !soc->ops->pktcapture_ops->txrx_pktcapture_record_channel) return; - soc->ops->mon_ops->txrx_monitor_set_filter_non_data - (pdev, val); + soc->ops->pktcapture_ops->txrx_pktcapture_record_channel(soc, + pdev_id, + chan_num); } -static inline bool cdp_monitor_get_filter_ucast_data -(ol_txrx_soc_handle soc, struct cdp_vdev *vdev_txrx_handle) +static inline void +cdp_set_packet_capture_mode(ol_txrx_soc_handle soc, + uint8_t pdev_id, + uint8_t val) { if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s invalid instance", __func__); QDF_BUG(0); - return 0; + return; } - if (!soc->ops->mon_ops || - !soc->ops->mon_ops->txrx_monitor_get_filter_ucast_data) - return 0; + if (!soc->ops->pktcapture_ops || + !soc->ops->pktcapture_ops->txrx_pktcapture_set_mode) + return; - return soc->ops->mon_ops->txrx_monitor_get_filter_ucast_data - (vdev_txrx_handle); + soc->ops->pktcapture_ops->txrx_pktcapture_set_mode(soc, pdev_id, val); } -static inline bool cdp_monitor_get_filter_mcast_data -(ol_txrx_soc_handle soc, struct cdp_vdev *vdev_txrx_handle) +static inline uint8_t +cdp_get_packet_capture_mode(ol_txrx_soc_handle soc, uint8_t pdev_id) { if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s invalid instance", __func__); QDF_BUG(0); return 0; } - if (!soc->ops->mon_ops || - !soc->ops->mon_ops->txrx_monitor_get_filter_mcast_data) + if (!soc->ops->pktcapture_ops || + !soc->ops->pktcapture_ops->txrx_pktcapture_get_mode) return 0; - return soc->ops->mon_ops->txrx_monitor_get_filter_mcast_data - (vdev_txrx_handle); + return soc->ops->pktcapture_ops->txrx_pktcapture_get_mode(soc, + pdev_id); } -static inline bool cdp_monitor_get_filter_non_data -(ol_txrx_soc_handle soc, struct cdp_vdev *vdev_txrx_handle) +static inline QDF_STATUS +cdp_register_pktcapture_cb( + ol_txrx_soc_handle soc, uint8_t pdev_id, void *ctx, + QDF_STATUS(txrx_pktcapture_cb)(void *, qdf_nbuf_t)) { if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); - QDF_BUG(0); - return 0; + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return QDF_STATUS_E_INVAL; } - if (!soc->ops->mon_ops || - !soc->ops->mon_ops->txrx_monitor_get_filter_non_data) - return 0; - - return soc->ops->mon_ops->txrx_monitor_get_filter_non_data - (vdev_txrx_handle); + if (!soc->ops->pktcapture_ops || + !soc->ops->pktcapture_ops->txrx_pktcapture_cb_register) + return QDF_STATUS_E_INVAL; + + return soc->ops->pktcapture_ops->txrx_pktcapture_cb_register( + soc, + pdev_id, + ctx, + txrx_pktcapture_cb); } -static inline QDF_STATUS cdp_reset_monitor_mode -(ol_txrx_soc_handle soc, struct cdp_pdev *pdev) +static inline QDF_STATUS +cdp_deregister_pktcapture_cb(ol_txrx_soc_handle soc, uint8_t pdev_id) { if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, - "%s: Invalid Instance", __func__); - QDF_BUG(0); - return 0; + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return QDF_STATUS_E_INVAL; } - if (!soc->ops->mon_ops || - !soc->ops->mon_ops->txrx_reset_monitor_mode) - return 0; + if (!soc->ops->pktcapture_ops || + !soc->ops->pktcapture_ops->txrx_pktcapture_cb_deregister) + return QDF_STATUS_E_INVAL; - return soc->ops->mon_ops->txrx_reset_monitor_mode(pdev); + return soc->ops->pktcapture_ops->txrx_pktcapture_cb_deregister(soc, + pdev_id); } -static inline void cdp_record_monitor_chan_num -(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, int chan_num) +static inline QDF_STATUS +cdp_pktcapture_mgmtpkt_process( + ol_txrx_soc_handle soc, + uint8_t pdev_id, + struct mon_rx_status *txrx_status, + qdf_nbuf_t nbuf, + uint8_t status) { 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->mon_ops || - !soc->ops->mon_ops->txrx_monitor_record_channel) - return; - - soc->ops->mon_ops->txrx_monitor_record_channel(pdev, chan_num); -} -#ifdef WLAN_FEATURE_PKT_CAPTURE -static inline void -cdp_pktcapture_record_channel( - ol_txrx_soc_handle soc, - uint8_t pdev_id, - int chan_num) -{ - if (!soc || !soc->ops) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - QDF_BUG(0); - return; + return QDF_STATUS_E_INVAL; } if (!soc->ops->pktcapture_ops || - !soc->ops->pktcapture_ops->txrx_pktcapture_record_channel) - return; + !soc->ops->pktcapture_ops->txrx_pktcapture_mgmtpkt_process) + return QDF_STATUS_E_INVAL; + + return soc->ops->pktcapture_ops->txrx_pktcapture_mgmtpkt_process( + soc, + pdev_id, + txrx_status, + nbuf, + status); +} +#else +static inline uint8_t +cdp_get_packet_capture_mode(ol_txrx_soc_handle soc, uint8_t pdev_id) +{ + return 0; +} - soc->ops->pktcapture_ops->txrx_pktcapture_record_channel(soc, - pdev_id, - chan_num); +static inline void +cdp_pktcapture_record_channel(ol_txrx_soc_handle soc, + uint8_t pdev_id, + int chan_num) +{ } -#endif +#endif /* WLAN_FEATURE_PKT_CAPTURE */ + #endif diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mon_struct.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mon_struct.h index 189c0e47519ddf3d723235e6ea81114f3beba9de..edb12c95eda99f0ee16572541f92f32ae13be2aa 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mon_struct.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_mon_struct.h @@ -102,6 +102,8 @@ enum { }; struct cdp_mon_status { + /* bss color value 1-63 used for update on ppdu_desc bsscolor */ + uint8_t bsscolor; int rs_numchains; int rs_flags; #define IEEE80211_RX_FCS_ERROR 0x01 @@ -236,7 +238,7 @@ struct cdp_pdev_mon_stats { uint32_t stat_ring_ppdu_id_hist[MAX_PPDU_ID_HIST]; uint32_t dest_ring_ppdu_id_hist[MAX_PPDU_ID_HIST]; uint32_t ppdu_id_hist_idx; - uint32_t tlv_tag_status_err; uint32_t mon_rx_dest_stuck; + uint32_t tlv_tag_status_err; }; #endif diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ocb.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ocb.h index 5fd6d682f0cac3bcc511f8f54ba7d0cef51ffe6f..abab53af194eea28df204fd2c65d589d4e173008 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ocb.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ocb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, 2019 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 @@ -23,14 +23,14 @@ /** * cdp_set_ocb_chan_info() - set OCB channel info to vdev. * @soc - data path soc handle - * @vdev: vdev handle + * @vdev_id: vdev_id corresponding to vdev start * @ocb_set_chan: OCB channel information to be set in vdev. * * Return: NONE */ static inline void -cdp_set_ocb_chan_info(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, - struct ol_txrx_ocb_set_chan ocb_set_chan) +cdp_set_ocb_chan_info(ol_txrx_soc_handle soc, uint8_t vdev_id, + struct ol_txrx_ocb_set_chan ocb_set_chan) { if (!soc || !soc->ops || !soc->ops->ocb_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -39,19 +39,19 @@ cdp_set_ocb_chan_info(ol_txrx_soc_handle soc, struct cdp_vdev *vdev, } if (soc->ops->ocb_ops->set_ocb_chan_info) - soc->ops->ocb_ops->set_ocb_chan_info(vdev, + soc->ops->ocb_ops->set_ocb_chan_info(soc, vdev_id, ocb_set_chan); } /** * cdp_get_ocb_chan_info() - return handle to vdev ocb_channel_info * @soc - data path soc handle - * @vdev: vdev handle + * @vdev_id: vdev_id corresponding to vdev start * * Return: handle to struct ol_txrx_ocb_chan_info */ static inline struct ol_txrx_ocb_chan_info * -cdp_get_ocb_chan_info(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) +cdp_get_ocb_chan_info(ol_txrx_soc_handle soc, uint8_t vdev_id) { if (!soc || !soc->ops || !soc->ops->ocb_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -60,7 +60,7 @@ cdp_get_ocb_chan_info(ol_txrx_soc_handle soc, struct cdp_vdev *vdev) } if (soc->ops->ocb_ops->get_ocb_chan_info) - return soc->ops->ocb_ops->get_ocb_chan_info(vdev); + return soc->ops->ocb_ops->get_ocb_chan_info(soc, vdev_id); return NULL; } diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ops.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ops.h index 1b080200452500b3ddb6fde4dc0f0a994869162b..243f1a87d503f67d664a120b7bad045878825412 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ops.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_ops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -29,6 +29,8 @@ #include "cdp_txrx_handle.h" #include #include "wlan_objmgr_psoc_obj.h" +#include +#include #ifdef IPA_OFFLOAD #ifdef CONFIG_IPA_WDI_UNIFIED_API @@ -44,6 +46,8 @@ #define CDP_PEER_DELETE_NO_SPECIAL 0 #define CDP_PEER_DO_NOT_START_UNMAP_TIMER 1 +struct hif_opaque_softc; + /* same as ieee80211_nac_param */ enum cdp_nac_param_cmd { /* IEEE80211_NAC_PARAM_ADD */ @@ -53,6 +57,31 @@ enum cdp_nac_param_cmd { /* IEEE80211_NAC_PARAM_LIST */ CDP_NAC_PARAM_LIST, }; + +/** + * enum vdev_peer_protocol_enter_exit - whether ingress or egress + * @CDP_VDEV_PEER_PROTOCOL_IS_INGRESS: ingress + * @CDP_VDEV_PEER_PROTOCOL_IS_EGRESS: egress + * + * whether ingress or egress + */ +enum vdev_peer_protocol_enter_exit { + CDP_VDEV_PEER_PROTOCOL_IS_INGRESS, + CDP_VDEV_PEER_PROTOCOL_IS_EGRESS +}; + +/** + * enum vdev_peer_protocol_tx_rx - whether tx or rx + * @CDP_VDEV_PEER_PROTOCOL_IS_TX: tx + * @CDP_VDEV_PEER_PROTOCOL_IS_RX: rx + * + * whether tx or rx + */ +enum vdev_peer_protocol_tx_rx { + CDP_VDEV_PEER_PROTOCOL_IS_TX, + CDP_VDEV_PEER_PROTOCOL_IS_RX +}; + /****************************************************************************** * * Control Interface (A Interface) @@ -63,57 +92,69 @@ struct cdp_cmn_ops { QDF_STATUS (*txrx_soc_attach_target)(ol_txrx_soc_handle soc); - int (*txrx_pdev_attach_target)(struct cdp_pdev *pdev); + int (*txrx_pdev_attach_target)(ol_txrx_soc_handle soc, uint8_t pdev_id); - struct cdp_vdev *(*txrx_vdev_attach) - (struct cdp_pdev *pdev, uint8_t *vdev_mac_addr, + QDF_STATUS (*txrx_vdev_attach) + (struct cdp_soc_t *soc, uint8_t pdev_id, uint8_t *mac, uint8_t vdev_id, enum wlan_op_mode op_mode, enum wlan_op_subtype subtype); - void (*txrx_vdev_detach) - (struct cdp_vdev *vdev, ol_txrx_vdev_delete_cb callback, - void *cb_context); + QDF_STATUS + (*txrx_vdev_detach)(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, + ol_txrx_vdev_delete_cb callback, + void *cb_context); - struct cdp_pdev *(*txrx_pdev_attach) - (ol_txrx_soc_handle soc, struct cdp_ctrl_objmgr_pdev *ctrl_pdev, - HTC_HANDLE htc_pdev, qdf_device_t osdev, uint8_t pdev_id); + QDF_STATUS (*txrx_pdev_attach) + (ol_txrx_soc_handle soc, HTC_HANDLE htc_pdev, + qdf_device_t osdev, uint8_t pdev_id); - int (*txrx_pdev_post_attach)(struct cdp_pdev *pdev); + int (*txrx_pdev_post_attach)(struct cdp_soc_t *soc, uint8_t pdev_id); - void (*txrx_pdev_pre_detach)(struct cdp_pdev *pdev, int force); + void + (*txrx_pdev_pre_detach)(struct cdp_soc_t *soc, uint8_t pdev_id, + int force); - void (*txrx_pdev_detach)(struct cdp_pdev *pdev, int force); + QDF_STATUS + (*txrx_pdev_detach)(struct cdp_soc_t *psoc, uint8_t pdev_id, + int force); /** * txrx_pdev_deinit() - Deinitialize pdev and dp ring memory - * @pdev: Dp pdev handle + * @soc: soc dp handle + * @pdev_id: id of Dp pdev handle * @force: Force deinit or not * - * Return: None + * Return: QDF_STATUS */ - void (*txrx_pdev_deinit)(struct cdp_pdev *pdev, int force); + QDF_STATUS + (*txrx_pdev_deinit)(struct cdp_soc_t *soc, uint8_t pdev_id, + int force); - void *(*txrx_peer_create) - (struct cdp_vdev *vdev, uint8_t *peer_mac_addr, - struct cdp_ctrl_objmgr_peer *ctrl_peer); + QDF_STATUS + (*txrx_peer_create) + (ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac_addr); - void (*txrx_peer_setup) - (struct cdp_vdev *vdev_hdl, void *peer_hdl); + QDF_STATUS + (*txrx_peer_setup)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_mac); - void (*txrx_cp_peer_del_response) - (ol_txrx_soc_handle soc, struct cdp_vdev *vdev_hdl, + QDF_STATUS + (*txrx_cp_peer_del_response) + (ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac_addr); - void (*txrx_peer_teardown) - (struct cdp_vdev *vdev_hdl, void *peer_hdl); + QDF_STATUS + (*txrx_peer_teardown) + (struct cdp_soc_t *soc, uint8_t vdev_id, uint8_t *peer_mac); int (*txrx_peer_add_ast) - (ol_txrx_soc_handle soc, struct cdp_peer *peer_hdl, + (ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac, uint8_t *mac_addr, enum cdp_txrx_ast_entry_type type, uint32_t flags); int (*txrx_peer_update_ast) - (ol_txrx_soc_handle soc, struct cdp_peer *peer_hdl, + (ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac, uint8_t *mac_addr, uint32_t flags); bool (*txrx_peer_get_ast_info_by_soc) @@ -136,94 +177,91 @@ struct cdp_cmn_ops { txrx_ast_free_cb callback, void *cookie); - void (*txrx_peer_delete)(void *peer, uint32_t bitmap); - - void (*txrx_vdev_flush_peers)(struct cdp_vdev *vdev, bool unmap_only); + QDF_STATUS + (*txrx_peer_delete)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, uint32_t bitmap); - QDF_STATUS (*txrx_set_monitor_mode)(struct cdp_vdev *vdev, + QDF_STATUS (*txrx_set_monitor_mode)(struct cdp_soc_t *soc, + uint8_t vdev_id, uint8_t smart_monitor); - void (*txrx_peer_delete_sync)(void *peer, + void (*txrx_peer_delete_sync)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, QDF_STATUS(*delete_cb)( uint8_t vdev_id, uint32_t peerid_cnt, uint16_t *peerid_list), uint32_t bitmap); - void (*txrx_peer_unmap_sync_cb_set)(struct cdp_pdev *pdev, - QDF_STATUS(*unmap_resp_cb)( - uint8_t vdev_id, - uint32_t peerid_cnt, - uint16_t *peerid_list)); - - uint8_t (*txrx_get_pdev_id_frm_pdev)(struct cdp_pdev *pdev); - bool (*txrx_get_vow_config_frm_pdev)(struct cdp_pdev *pdev); - - void (*txrx_pdev_set_chan_noise_floor)(struct cdp_pdev *pdev, - int16_t chan_noise_floor); + void (*txrx_peer_unmap_sync_cb_set)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + ol_txrx_peer_unmap_sync_cb + peer_unmap_sync); - void (*txrx_set_nac)(struct cdp_peer *peer); - - /** - * 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, + QDF_STATUS + (*txrx_get_peer_mac_from_peer_id) + (struct cdp_soc_t *cdp_soc, uint32_t peer_id, uint8_t *peer_mac); - void (*txrx_vdev_tx_lock)(struct cdp_vdev *vdev); + void + (*txrx_vdev_tx_lock)(struct cdp_soc_t *soc, uint8_t vdev_id); - void (*txrx_vdev_tx_unlock)(struct cdp_vdev *vdev); + void + (*txrx_vdev_tx_unlock)(struct cdp_soc_t *soc, uint8_t vdev_id); - void (*txrx_ath_getstats)(void *pdev, - struct cdp_dev_stats *stats, uint8_t type); + QDF_STATUS + (*txrx_ath_getstats)(struct cdp_soc_t *soc, uint8_t id, + struct cdp_dev_stats *stats, uint8_t type); - void (*txrx_set_gid_flag)(struct cdp_pdev *pdev, u_int8_t *mem_status, - u_int8_t *user_position); + QDF_STATUS + (*txrx_set_gid_flag)(struct cdp_soc_t *soc, uint8_t pdev_id, + u_int8_t *mem_status, + u_int8_t *user_position); - uint32_t (*txrx_fw_supported_enh_stats_version)(struct cdp_pdev *pdev); + uint32_t (*txrx_fw_supported_enh_stats_version)(struct cdp_soc_t *soc, + uint8_t pdev_id); - void (*txrx_if_mgmt_drain)(void *ni, int force); + QDF_STATUS + (*txrx_if_mgmt_drain)(struct cdp_soc_t *soc, uint8_t pdev_id, + int force); - void (*txrx_set_curchan)(struct cdp_pdev *pdev, uint32_t chan_mhz); + QDF_STATUS + (*txrx_set_curchan)(struct cdp_soc_t *soc, uint8_t pdev_id, + uint32_t chan_mhz); - void (*txrx_set_privacy_filters) - (struct cdp_vdev *vdev, void *filter, uint32_t num); + QDF_STATUS + (*txrx_set_privacy_filters) + (struct cdp_soc_t *soc, uint8_t vdev_id, void *filter, + uint32_t num); - uint32_t (*txrx_get_cfg)(void *soc, enum cdp_dp_cfg cfg); + uint32_t (*txrx_get_cfg)(struct cdp_soc_t *soc, enum cdp_dp_cfg cfg); /******************************************************************** * Data Interface (B Interface) ********************************************************************/ - void (*txrx_vdev_register)(struct cdp_vdev *vdev, - void *osif_vdev, struct cdp_ctrl_objmgr_vdev *ctrl_vdev, - struct ol_txrx_ops *txrx_ops); + QDF_STATUS + (*txrx_vdev_register)(struct cdp_soc_t *soc, uint8_t vdev_id, + ol_osif_vdev_handle osif_vdev, + struct ol_txrx_ops *txrx_ops); - int (*txrx_mgmt_send)(struct cdp_vdev *vdev, - qdf_nbuf_t tx_mgmt_frm, uint8_t type); + int (*txrx_mgmt_send)(struct cdp_soc_t *soc, uint8_t vdev_id, + qdf_nbuf_t tx_mgmt_frm, uint8_t type); - int (*txrx_mgmt_send_ext)(struct cdp_vdev *vdev, - qdf_nbuf_t tx_mgmt_frm, uint8_t type, uint8_t use_6mbps, - uint16_t chanfreq); + int (*txrx_mgmt_send_ext)(struct cdp_soc_t *soc, uint8_t vdev_id, + qdf_nbuf_t tx_mgmt_frm, uint8_t type, + uint8_t use_6mbps, uint16_t chanfreq); /** * ol_txrx_mgmt_tx_cb - tx management delivery notification * callback function */ - void (*txrx_mgmt_tx_cb_set)(struct cdp_pdev *pdev, uint8_t type, - ol_txrx_mgmt_tx_cb download_cb, - ol_txrx_mgmt_tx_cb ota_ack_cb, - void *ctxt); - - int (*txrx_get_tx_pending)(struct cdp_pdev *pdev); + QDF_STATUS + (*txrx_mgmt_tx_cb_set)(struct cdp_soc_t *soc, uint8_t pdev_id, + uint8_t type, + ol_txrx_mgmt_tx_cb download_cb, + ol_txrx_mgmt_tx_cb ota_ack_cb, + void *ctxt); /** * ol_txrx_data_tx_cb - Function registered with the data path @@ -231,95 +269,87 @@ struct cdp_cmn_ops { * done being transmitted */ - void (*txrx_data_tx_cb_set)(struct cdp_vdev *data_vdev, - ol_txrx_data_tx_cb callback, void *ctxt); + void (*txrx_data_tx_cb_set)(struct cdp_soc_t *soc, uint8_t vdev_id, + ol_txrx_data_tx_cb callback, void *ctxt); + + qdf_nbuf_t (*tx_send_exc) + (ol_txrx_soc_handle soc, uint8_t vdev_id, qdf_nbuf_t msdu_list, + struct cdp_tx_exception_metadata *tx_exc_metadata); /******************************************************************* * Statistics and Debugging Interface (C Interface) ********************************************************************/ - int (*txrx_aggr_cfg)(struct cdp_vdev *vdev, int max_subfrms_ampdu, - int max_subfrms_amsdu); + int (*txrx_aggr_cfg)(struct cdp_soc_t *soc, uint8_t vdev_id, + int max_subfrms_ampdu, + int max_subfrms_amsdu); - A_STATUS (*txrx_fw_stats_get)(struct cdp_vdev *vdev, - struct ol_txrx_stats_req *req, - bool per_vdev, bool response_expected); + A_STATUS + (*txrx_fw_stats_get)(struct cdp_soc_t *soc, uint8_t vdev_id, + struct ol_txrx_stats_req *req, + bool per_vdev, bool response_expected); - int (*txrx_debug)(struct cdp_vdev *vdev, int debug_specs); + int (*txrx_debug)(struct cdp_soc_t *soc, uint8_t vdev_id, + int debug_specs); - void (*txrx_fw_stats_cfg)(struct cdp_vdev *vdev, - uint8_t cfg_stats_type, uint32_t cfg_val); + QDF_STATUS + (*txrx_fw_stats_cfg)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t cfg_stats_type, uint32_t cfg_val); void (*txrx_print_level_set)(unsigned level); /** * ol_txrx_get_vdev_mac_addr() - Return mac addr of vdev - * @vdev: vdev handle + * @soc: datapath soc handle + * @vdev_id: vdev id * * Return: vdev mac address */ - uint8_t * (*txrx_get_vdev_mac_addr)(struct cdp_vdev *vdev); - - /** - * ol_txrx_get_vdev_struct_mac_addr() - Return handle to struct qdf_mac_addr of - * vdev - * @vdev: vdev handle - * - * Return: Handle to struct qdf_mac_addr - */ - struct qdf_mac_addr * - (*txrx_get_vdev_struct_mac_addr)(struct cdp_vdev *vdev); - - /** - * ol_txrx_get_pdev_from_vdev() - Return handle to pdev of vdev - * @vdev: vdev handle - * - * Return: Handle to pdev - */ - struct cdp_pdev *(*txrx_get_pdev_from_vdev) - (struct cdp_vdev *vdev); + uint8_t * (*txrx_get_vdev_mac_addr)(struct cdp_soc_t *soc, + uint8_t vdev_id); /** * ol_txrx_get_ctrl_pdev_from_vdev() - Return control pdev of vdev - * @vdev: vdev handle + * @soc: datapath soc handle + * @vdev_id: vdev id * * Return: Handle to control pdev */ - struct cdp_cfg * - (*txrx_get_ctrl_pdev_from_vdev)(struct cdp_vdev *vdev); + struct cdp_cfg *(*txrx_get_ctrl_pdev_from_vdev)(struct cdp_soc_t *soc, + uint8_t vdev_id); /** * txrx_get_mon_vdev_from_pdev() - Return monitor mode vdev - * @pdev: pdev handle + * @soc: datapath soc handle + * @pdev: pdev id * - * Return: Handle to vdev + * Return: vdev_id */ - struct cdp_vdev * - (*txrx_get_mon_vdev_from_pdev)(struct cdp_pdev *pdev); + uint8_t (*txrx_get_mon_vdev_from_pdev)(struct cdp_soc_t *soc, + uint8_t pdev_id); - struct cdp_vdev * - (*txrx_get_vdev_from_vdev_id)(struct cdp_pdev *pdev, - uint8_t vdev_id); - - void (*txrx_soc_detach)(void *soc); + void (*txrx_soc_detach)(struct cdp_soc_t *soc); /** * txrx_soc_deinit() - Deinitialize dp soc and dp ring memory * @soc: Opaque Dp handle * - * Return: None + * Return None */ - void (*txrx_soc_deinit)(void *soc); + void (*txrx_soc_deinit)(struct cdp_soc_t *soc); /** * txrx_soc_init() - Initialize dp soc and dp ring memory * @soc: Opaque Dp handle + * @ctrl_psoc: Opaque Cp handle * @htchdl: Opaque htc handle * @hifhdl: Opaque hif handle * * Return: None */ - void *(*txrx_soc_init)(void *soc, void *ctrl_psoc, void *hif_handle, + void *(*txrx_soc_init)(struct cdp_soc_t *soc, + struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + struct hif_opaque_softc *hif_handle, HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, struct ol_if_ops *ol_ops, uint16_t device_id); @@ -330,7 +360,7 @@ struct cdp_cmn_ops { * * Return: QDF status */ - QDF_STATUS (*txrx_tso_soc_attach)(void *soc); + QDF_STATUS (*txrx_tso_soc_attach)(struct cdp_soc_t *soc); /** * txrx_tso_soc_detach() - TSO detach handler triggered during @@ -339,87 +369,112 @@ struct cdp_cmn_ops { * * Return: QDF status */ - QDF_STATUS (*txrx_tso_soc_detach)(void *soc); - int (*addba_resp_tx_completion)(void *peer_handle, uint8_t tid, + QDF_STATUS (*txrx_tso_soc_detach)(struct cdp_soc_t *soc); + int (*addba_resp_tx_completion)(struct cdp_soc_t *cdp_soc, + uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, int status); - int (*addba_requestprocess)(void *peer_handle, uint8_t dialogtoken, - uint16_t tid, uint16_t batimeout, - uint16_t buffersize, - uint16_t startseqnum); + int (*addba_requestprocess)(struct cdp_soc_t *cdp_soc, + uint8_t *peer_mac, + uint16_t vdev_id, + uint8_t dialogtoken, + uint16_t tid, uint16_t batimeout, + uint16_t buffersize, + uint16_t startseqnum); - void (*addba_responsesetup)(void *peer_handle, uint8_t tid, - uint8_t *dialogtoken, uint16_t *statuscode, - uint16_t *buffersize, uint16_t *batimeout); + QDF_STATUS + (*addba_responsesetup)(struct cdp_soc_t *cdp_soc, + uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, + uint8_t *dialogtoken, uint16_t *statuscode, + uint16_t *buffersize, uint16_t *batimeout); - int (*delba_process)(void *peer_handle, - int tid, uint16_t reasoncode); + int (*delba_process)(struct cdp_soc_t *cdp_soc, uint8_t *peer_mac, + uint16_t vdev_id, int tid, uint16_t reasoncode); /** * delba_tx_completion() - Indicate delba tx status - * @peer_handle: Peer handle + * @cdp_soc: soc handle + * @peer_mac: Peer mac address + * @vdev_id: vdev id * @tid: Tid number * @status: Tx completion status * * Return: 0 on Success, 1 on failure */ - int (*delba_tx_completion)(void *peer_handle, + int (*delba_tx_completion)(struct cdp_soc_t *cdp_soc, uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, int status); - void (*set_addba_response)(void *peer_handle, - uint8_t tid, uint16_t statuscode); - - uint8_t (*get_peer_mac_addr_frm_id)(struct cdp_soc_t *soc_handle, - uint16_t peer_id, uint8_t *mac_addr); + QDF_STATUS + (*set_addba_response)(struct cdp_soc_t *cdp_soc, uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, + uint16_t statuscode); - void (*set_vdev_dscp_tid_map)(struct cdp_vdev *vdev_handle, - uint8_t map_id); - int (*txrx_get_total_per)(struct cdp_pdev *pdev_handle); + QDF_STATUS + (*set_vdev_dscp_tid_map)(struct cdp_soc_t *soc_handle, + uint8_t vdev_id, uint8_t map_id); + int (*txrx_get_total_per)(struct cdp_soc_t *soc, uint8_t pdev_id); void (*flush_cache_rx_queue)(void); - void (*set_pdev_dscp_tid_map)(struct cdp_pdev *pdev, uint8_t map_id, - uint8_t tos, uint8_t tid); - void (*hmmc_tid_override_en)(struct cdp_pdev *pdev, bool val); - void (*set_hmmc_tid_val)(struct cdp_pdev *pdev, uint8_t tid); - QDF_STATUS (*txrx_stats_request)(struct cdp_vdev *vdev, + QDF_STATUS (*set_pdev_dscp_tid_map)(struct cdp_soc_t *soc_handle, + uint8_t pdev_id, + uint8_t map_id, + uint8_t tos, uint8_t tid); + + QDF_STATUS (*txrx_stats_request)(struct cdp_soc_t *soc_handle, + uint8_t vdev_id, struct cdp_txrx_stats_req *req); - QDF_STATUS (*display_stats)(void *psoc, uint16_t value, + QDF_STATUS (*display_stats)(struct cdp_soc_t *psoc, uint16_t value, enum qdf_stats_verbosity_level level); - void (*txrx_soc_set_nss_cfg)(ol_txrx_soc_handle soc, int config); - - int(*txrx_soc_get_nss_cfg)(ol_txrx_soc_handle soc); - QDF_STATUS (*txrx_intr_attach)(void *soc); - void (*txrx_intr_detach)(void *soc); - void (*set_pn_check)(struct cdp_vdev *vdev, - struct cdp_peer *peer_handle, enum cdp_sec_type sec_type, - uint32_t *rx_pn); - void (*set_key_sec_type)(struct cdp_vdev *vdev, - struct cdp_peer *peer_handle, - enum cdp_sec_type sec_type, - bool is_unicast); + + QDF_STATUS (*txrx_intr_attach)(struct cdp_soc_t *soc_handle); + void (*txrx_intr_detach)(struct cdp_soc_t *soc_handle); + QDF_STATUS (*set_pn_check)(struct cdp_soc_t *soc_handle, + uint8_t vdev_id, uint8_t *peermac, + enum cdp_sec_type sec_type, + uint32_t *rx_pn); + + QDF_STATUS(*set_key_sec_type)(struct cdp_soc_t *soc_handle, + uint8_t vdev_id, uint8_t *peermac, + enum cdp_sec_type sec_type, + bool is_unicast); QDF_STATUS (*update_config_parameters)(struct cdp_soc *psoc, struct cdp_config_params *params); - void *(*get_dp_txrx_handle)(struct cdp_pdev *pdev_hdl); - void (*set_dp_txrx_handle)(struct cdp_pdev *pdev_hdl, - void *dp_txrx_hdl); + void *(*get_dp_txrx_handle)(ol_txrx_soc_handle soc, uint8_t pdev_id); + void (*set_dp_txrx_handle)(ol_txrx_soc_handle soc, uint8_t pdev_id, + void *dp_hdl); + + void *(*get_vdev_dp_ext_txrx_handle)(struct cdp_soc_t *soc, + uint8_t vdev_id); + QDF_STATUS (*set_vdev_dp_ext_txrx_handle)(struct cdp_soc_t *soc, + uint8_t vdev_id, + uint16_t size); void *(*get_soc_dp_txrx_handle)(struct cdp_soc *soc_handle); void (*set_soc_dp_txrx_handle)(struct cdp_soc *soc_handle, void *dp_txrx_handle); - void (*map_pdev_to_lmac)(struct cdp_pdev *pdev_hdl, - uint32_t lmac_id); + QDF_STATUS (*map_pdev_to_lmac)(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint32_t lmac_id); - void (*txrx_peer_reset_ast) + QDF_STATUS (*handle_mode_change)(ol_txrx_soc_handle soc, + uint8_t pdev_id, uint32_t lmac_id); + + QDF_STATUS (*set_pdev_status_down)(struct cdp_soc_t *soc_handle, + uint8_t pdev_id, bool is_pdev_down); + + QDF_STATUS (*txrx_peer_reset_ast) (ol_txrx_soc_handle soc, uint8_t *ast_macaddr, - uint8_t *peer_macaddr, void *vdev_hdl); + uint8_t *peer_macaddr, uint8_t vdev_id); - void (*txrx_peer_reset_ast_table)(ol_txrx_soc_handle soc, - void *vdev_hdl); + QDF_STATUS (*txrx_peer_reset_ast_table)(ol_txrx_soc_handle soc, + uint8_t vdev_id); void (*txrx_peer_flush_ast_table)(ol_txrx_soc_handle soc); void (*txrx_set_ba_aging_timeout)(struct cdp_soc_t *soc_handle, @@ -432,125 +487,61 @@ struct cdp_cmn_ops { uint32_t max_ast_index, bool peer_map_unmap_v2); - void (*txrx_pdev_set_ctrl_pdev)(struct cdp_pdev *pdev_hdl, - struct cdp_ctrl_objmgr_pdev *ctrl_pdev); - ol_txrx_tx_fp tx_send; /** * txrx_get_os_rx_handles_from_vdev() - Return function, osif vdev * to deliver pkt to stack. - * @vdev: vdev handle + * @soc: datapath soc handle + * @vdev: vdev id * @stack_fn: pointer to - function pointer to deliver RX pkt to stack * @osif_vdev: pointer to - osif vdev to deliver RX packet to. */ void (*txrx_get_os_rx_handles_from_vdev) - (struct cdp_vdev *vdev, + (ol_txrx_soc_handle soc, + uint8_t vdev_id, ol_txrx_rx_fp *stack_fn, ol_osif_vdev_handle *osif_vdev); + + void (*set_rate_stats_ctx)(struct cdp_soc_t *soc, + void *ctx); + int (*txrx_classify_update) - (struct cdp_vdev *vdev, qdf_nbuf_t skb, + (struct cdp_soc_t *soc, uint8_t vdev_id, qdf_nbuf_t skb, enum txrx_direction, struct ol_txrx_nbuf_classify *nbuf_class); bool (*get_dp_capabilities)(struct cdp_soc_t *soc, enum cdp_capabilities dp_caps); - void (*set_rate_stats_ctx)(struct cdp_soc_t *soc, void *ctx); void* (*get_rate_stats_ctx)(struct cdp_soc_t *soc); - void (*txrx_peer_flush_rate_stats)(struct cdp_soc_t *soc, - struct cdp_pdev *pdev, - void *buf); - void (*txrx_flush_rate_stats_request)(struct cdp_soc_t *soc, - struct cdp_pdev *pdev); - QDF_STATUS (*set_pdev_pcp_tid_map)(struct cdp_pdev *pdev, + QDF_STATUS (*txrx_peer_flush_rate_stats)(struct cdp_soc_t *soc, + uint8_t pdev_id, + void *buf); + + QDF_STATUS (*txrx_flush_rate_stats_request)(struct cdp_soc_t *soc, + uint8_t pdev_id); + QDF_STATUS (*set_pdev_pcp_tid_map)(struct cdp_soc_t *soc, + uint8_t pdev_id, uint8_t pcp, uint8_t tid); - QDF_STATUS (*set_pdev_tidmap_prty)(struct cdp_pdev *pdev, uint8_t prty); - QDF_STATUS (*set_vdev_pcp_tid_map)(struct cdp_vdev *vdev, + QDF_STATUS (*set_vdev_pcp_tid_map)(struct cdp_soc_t *soc, + uint8_t vdev_id, uint8_t pcp, uint8_t tid); - QDF_STATUS (*set_vdev_tidmap_prty)(struct cdp_vdev *vdev, uint8_t prty); - QDF_STATUS (*set_vdev_tidmap_tbl_id)(struct cdp_vdev *vdev, - uint8_t mapid); +#ifdef QCA_MULTIPASS_SUPPORT + QDF_STATUS (*set_vlan_groupkey)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint16_t vlan_id, uint16_t group_key); +#endif + + uint16_t (*get_peer_mac_list) + (ol_txrx_soc_handle soc, uint8_t vdev_id, + u_int8_t newmac[][QDF_MAC_ADDR_SIZE], uint16_t mac_cnt); }; struct cdp_ctrl_ops { int - (*txrx_mempools_attach)(void *ctrl_pdev); - int - (*txrx_set_filter_neighbour_peers)( - struct cdp_pdev *pdev, - uint32_t val); + (*txrx_mempools_attach)(ol_txrx_soc_handle dp_soc); int (*txrx_update_filter_neighbour_peers)( - struct cdp_vdev *vdev, + struct cdp_soc_t *soc, uint8_t vdev_id, uint32_t cmd, uint8_t *macaddr); - /** - * @brief set the safemode of the device - * @details - * This flag is used to bypass the encrypt and decrypt processes when - * send and receive packets. It works like open AUTH mode, HW will - * ctreate all packets as non-encrypt frames because no key installed. - * For rx fragmented frames,it bypasses all the rx defragmentaion. - * - * @param vdev - the data virtual device object - * @param val - the safemode state - * @return - void - */ - - void - (*txrx_set_safemode)( - struct cdp_vdev *vdev, - u_int32_t val); - /** - * @brief configure the drop unencrypted frame flag - * @details - * Rx related. When set this flag, all the unencrypted frames - * received over a secure connection will be discarded - * - * @param vdev - the data virtual device object - * @param val - flag - * @return - void - */ - void - (*txrx_set_drop_unenc)( - struct cdp_vdev *vdev, - u_int32_t val); - - - /** - * @brief set the Tx encapsulation type of the VDEV - * @details - * This will be used to populate the HTT desc packet type field - * during Tx - * @param vdev - the data virtual device object - * @param val - the Tx encap type - * @return - void - */ - void - (*txrx_set_tx_encap_type)( - struct cdp_vdev *vdev, - enum htt_cmn_pkt_type val); - /** - * @brief set the Rx decapsulation type of the VDEV - * @details - * This will be used to configure into firmware and hardware - * which format to decap all Rx packets into, for all peers under - * the VDEV. - * @param vdev - the data virtual device object - * @param val - the Rx decap mode - * @return - void - */ - void - (*txrx_set_vdev_rx_decap_type)( - struct cdp_vdev *vdev, - enum htt_cmn_pkt_type val); - - /** - * @brief get the Rx decapsulation type of the VDEV - * - * @param vdev - the data virtual device object - * @return - the Rx decap type - */ - enum htt_cmn_pkt_type - (*txrx_get_vdev_rx_decap_type)(struct cdp_vdev *vdev); /* Is this similar to ol_txrx_peer_state_update() in MCL */ /** @@ -560,47 +551,42 @@ struct cdp_ctrl_ops { * updates the peer/node-related parameters within rate-control * context of the peer at association. * - * @param peer - pointer to the node's object + * @param soc_hdl - pointer to the soc object + * @param vdev_id - id of the virtual object + * @param peer_mac - mac address of the node's object * @authorize - either to authorize or unauthorize peer * - * @return none - */ - void - (*txrx_peer_authorize)(struct cdp_peer *peer, - u_int32_t authorize); - - /* Should be ol_txrx_ctrl_api.h */ - void (*txrx_set_mesh_mode)(struct cdp_vdev *vdev, u_int32_t val); - - /** - * @brief setting mesh rx filter - * @details - * based on the bits enabled in the filter packets has to be dropped. - * - * @param vdev - the data virtual device object - * @param val - value to set + * @return QDF_STATUS */ - void (*txrx_set_mesh_rx_filter)(struct cdp_vdev *vdev, uint32_t val); + QDF_STATUS + (*txrx_peer_authorize)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, + uint8_t *peer_mac, + u_int32_t authorize); - void (*tx_flush_buffers)(struct cdp_vdev *vdev); + void (*tx_flush_buffers)(struct cdp_soc_t *soc, uint8_t vdev_id); - int (*txrx_is_target_ar900b)(struct cdp_vdev *vdev); + int (*txrx_is_target_ar900b)(struct cdp_soc_t *soc_hdl); - void (*txrx_set_vdev_param)(struct cdp_vdev *vdev, - enum cdp_vdev_param_type param, uint32_t val); + QDF_STATUS + (*txrx_set_vdev_param)(struct cdp_soc_t *soc, uint8_t vdev_id, + enum cdp_vdev_param_type param, + cdp_config_param_type val); - void (*txrx_peer_set_nawds)(struct cdp_peer *peer, uint8_t value); /** * @brief Set the reo dest ring num of the radio * @details * Set the reo destination ring no on which we will receive * pkts for this radio. * - * @param pdev - the data physical device object + * @txrx_soc - soc handle + * @param pdev_id - id of physical device + * @return the reo destination ring number * @param reo_dest_ring_num - value ranges between 1 - 4 */ - void (*txrx_set_pdev_reo_dest)( - struct cdp_pdev *pdev, + QDF_STATUS (*txrx_set_pdev_reo_dest)( + struct cdp_soc_t *txrx_soc, + uint8_t pdev_id, enum cdp_host_reo_dest_ring reo_dest_ring_num); /** @@ -609,274 +595,361 @@ struct cdp_ctrl_ops { * Get the reo destination ring no on which we will receive * pkts for this radio. * - * @param pdev - the data physical device object + * @txrx_soc - soc handle + * @param pdev_id - id of physical device * @return the reo destination ring number */ enum cdp_host_reo_dest_ring (*txrx_get_pdev_reo_dest)( - struct cdp_pdev *pdev); + struct cdp_soc_t *txrx_soc, + uint8_t pdev_id); + + int (*txrx_wdi_event_sub)(struct cdp_soc_t *soc, uint8_t pdev_id, + wdi_event_subscribe *event_cb_sub, + uint32_t event); - int (*txrx_wdi_event_sub)(struct cdp_pdev *pdev, void *event_cb_sub, - uint32_t event); + int (*txrx_wdi_event_unsub)(struct cdp_soc_t *soc, uint8_t pdev_id, + wdi_event_subscribe *event_cb_sub, + uint32_t event); - int (*txrx_wdi_event_unsub)(struct cdp_pdev *pdev, void *event_cb_sub, - uint32_t event); - int (*txrx_get_sec_type)(struct cdp_peer *peer, uint8_t sec_idx); + int (*txrx_get_sec_type)(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac, uint8_t sec_idx); - void (*txrx_update_mgmt_txpow_vdev)(struct cdp_vdev *vdev, - uint8_t subtype, uint8_t tx_power); + QDF_STATUS + (*txrx_update_mgmt_txpow_vdev)(struct cdp_soc_t *soc, + uint8_t vdev_id, + uint8_t subtype, uint8_t tx_power); /** * txrx_set_pdev_param() - callback to set pdev parameter * @soc: opaque soc handle - * @pdev: data path pdev handle + * @pdev_id:id of 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, + QDF_STATUS (*txrx_set_pdev_param)(struct cdp_soc_t *soc, + uint8_t pdev_id, enum cdp_pdev_param_type type, - uint8_t val); - void * (*txrx_get_pldev)(struct cdp_pdev *pdev); + cdp_config_param_type val); + QDF_STATUS (*txrx_get_pdev_param)(struct cdp_soc_t *soc, + uint8_t pdev_id, + enum cdp_pdev_param_type type, + cdp_config_param_type *val); + + QDF_STATUS (*txrx_set_peer_param)(struct cdp_soc_t *soc, + uint8_t vdev_id, uint8_t *peer_mac, + enum cdp_peer_param_type param, + cdp_config_param_type val); + + QDF_STATUS (*txrx_get_peer_param)(struct cdp_soc_t *soc, + uint8_t vdev_id, uint8_t *peer_mac, + enum cdp_peer_param_type param, + cdp_config_param_type *val); + + void * (*txrx_get_pldev)(struct cdp_soc_t *soc, uint8_t pdev_id); +#ifdef VDEV_PEER_PROTOCOL_COUNT + void (*txrx_peer_protocol_cnt)(struct cdp_soc_t *soc, + int8_t vdev_id, + qdf_nbuf_t nbuf, + bool is_egress, + bool is_rx); +#endif #ifdef ATH_SUPPORT_NAC_RSSI - QDF_STATUS (*txrx_vdev_config_for_nac_rssi)(struct cdp_vdev *vdev, - enum cdp_nac_param_cmd cmd, char *bssid, char *client_macaddr, - uint8_t chan_num); - QDF_STATUS (*txrx_vdev_get_neighbour_rssi)(struct cdp_vdev *vdev, + QDF_STATUS (*txrx_vdev_config_for_nac_rssi)(struct cdp_soc_t *cdp_soc, + uint8_t vdev_id, + enum cdp_nac_param_cmd cmd, + char *bssid, + char *client_macaddr, + uint8_t chan_num); + + QDF_STATUS (*txrx_vdev_get_neighbour_rssi)(struct cdp_soc_t *cdp_soc, + uint8_t vdev_id, char *macaddr, uint8_t *rssi); #endif - void (*set_key)(struct cdp_peer *peer_handle, - bool is_unicast, uint32_t *key); + QDF_STATUS + (*set_key)(struct cdp_soc_t *soc, uint8_t vdev_id, uint8_t *mac, + bool is_unicast, uint32_t *key); - uint32_t (*txrx_get_vdev_param)(struct cdp_vdev *vdev, - enum cdp_vdev_param_type param); - int (*enable_peer_based_pktlog)(struct cdp_pdev - *txrx_pdev_handle, char *macaddr, uint8_t enb_dsb); + QDF_STATUS (*txrx_get_vdev_param)(struct cdp_soc_t *soc, + uint8_t vdev_id, + enum cdp_vdev_param_type param, + cdp_config_param_type *val); + int (*enable_peer_based_pktlog)(struct cdp_soc_t *cdp_soc, + uint8_t pdev_id, + uint8_t *macaddr, uint8_t enb_dsb); - void (*calculate_delay_stats)(struct cdp_vdev *vdev, qdf_nbuf_t nbuf); + QDF_STATUS + (*calculate_delay_stats)(struct cdp_soc_t *cdp_soc, + uint8_t vdev_id, qdf_nbuf_t nbuf); #ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG QDF_STATUS (*txrx_update_pdev_rx_protocol_tag)( - struct cdp_pdev *txrx_pdev_handle, + struct cdp_soc_t *soc, uint8_t pdev_id, uint32_t protocol_mask, uint16_t protocol_type, uint16_t tag); #ifdef WLAN_SUPPORT_RX_TAG_STATISTICS void (*txrx_dump_pdev_rx_protocol_tag_stats)( - struct cdp_pdev *txrx_pdev_handle, + struct cdp_soc_t *soc, uint8_t pdev_id, uint16_t protocol_type); #endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */ #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ +#ifdef WLAN_SUPPORT_RX_FLOW_TAG + QDF_STATUS (*txrx_set_rx_flow_tag)( + struct cdp_soc_t *cdp_soc, uint8_t pdev_id, + struct cdp_rx_flow_info *flow_info); + QDF_STATUS (*txrx_dump_rx_flow_tag_stats)( + struct cdp_soc_t *cdp_soc, uint8_t pdev_id, + struct cdp_rx_flow_info *flow_info); +#endif /* WLAN_SUPPORT_RX_FLOW_TAG */ +#ifdef QCA_MULTIPASS_SUPPORT + void (*txrx_peer_set_vlan_id)(struct cdp_soc_t *cdp_soc, + uint8_t vdev_id, uint8_t *peer_mac, + uint16_t vlan_id); +#endif +#if defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(WLAN_RX_PKT_CAPTURE_ENH) + QDF_STATUS (*txrx_update_peer_pkt_capture_params)( + ol_txrx_soc_handle soc, uint8_t pdev_id, + bool is_rx_pkt_cap_enable, bool is_tx_pkt_cap_enable, + uint8_t *peer_mac); +#endif /* WLAN_TX_PKT_CAPTURE_ENH || WLAN_RX_PKT_CAPTURE_ENH */ + QDF_STATUS + (*txrx_set_psoc_param)(struct cdp_soc_t *soc, + enum cdp_psoc_param_type param, + cdp_config_param_type val); + + QDF_STATUS (*txrx_get_psoc_param)(ol_txrx_soc_handle soc, + enum cdp_psoc_param_type type, + cdp_config_param_type *val); +#ifdef VDEV_PEER_PROTOCOL_COUNT + /* + * Enable per-peer protocol counters + */ + void (*txrx_enable_peer_protocol_count)(struct cdp_soc_t *soc, + int8_t vdev_id, bool enable); + void (*txrx_set_peer_protocol_drop_mask)(struct cdp_soc_t *soc, + int8_t vdev_id, int mask); + int (*txrx_is_peer_protocol_count_enabled)(struct cdp_soc_t *soc, + int8_t vdev_id); + int (*txrx_get_peer_protocol_drop_mask)(struct cdp_soc_t *soc, + int8_t vdev_id); + +#endif }; struct cdp_me_ops { - u_int16_t (*tx_desc_alloc_and_mark_for_mcast_clone) - (struct cdp_pdev *pdev, u_int16_t buf_count); - - u_int16_t (*tx_desc_free_and_unmark_for_mcast_clone)( - struct cdp_pdev *pdev, - u_int16_t buf_count); - - u_int16_t - (*tx_get_mcast_buf_allocated_marked) - (struct cdp_pdev *pdev); - void - (*tx_me_alloc_descriptor)(struct cdp_pdev *pdev); - - void - (*tx_me_free_descriptor)(struct cdp_pdev *pdev); + void (*tx_me_alloc_descriptor)(struct cdp_soc_t *soc, + uint8_t pdev_id); - uint16_t - (*tx_me_convert_ucast)(struct cdp_vdev *vdev, - qdf_nbuf_t wbuf, u_int8_t newmac[][6], - uint8_t newmaccnt); - /* Should be a function pointer in ol_txrx_osif_ops{} */ - /** - * @brief notify mcast frame indication from FW. - * @details - * This notification will be used to convert - * multicast frame to unicast. - * - * @param pdev - handle to the ctrl SW's physical device object - * @param vdev_id - ID of the virtual device received the special data - * @param msdu - the multicast msdu returned by FW for host inspect - */ + void (*tx_me_free_descriptor)(struct cdp_soc_t *soc, uint8_t pdev_id); - int (*mcast_notify)(struct cdp_pdev *pdev, - u_int8_t vdev_id, qdf_nbuf_t msdu); + uint16_t (*tx_me_convert_ucast)(struct cdp_soc_t *soc, uint8_t vdev_id, + qdf_nbuf_t wbuf, u_int8_t newmac[][6], + uint8_t newmaccnt); }; struct cdp_mon_ops { - void (*txrx_monitor_set_filter_ucast_data) - (struct cdp_pdev *, u_int8_t val); - void (*txrx_monitor_set_filter_mcast_data) - (struct cdp_pdev *, u_int8_t val); - void (*txrx_monitor_set_filter_non_data) - (struct cdp_pdev *, u_int8_t val); - - bool (*txrx_monitor_get_filter_ucast_data) - (struct cdp_vdev *vdev_txrx_handle); - bool (*txrx_monitor_get_filter_mcast_data) - (struct cdp_vdev *vdev_txrx_handle); - bool (*txrx_monitor_get_filter_non_data) - (struct cdp_vdev *vdev_txrx_handle); - QDF_STATUS (*txrx_reset_monitor_mode)(struct cdp_pdev *pdev); + QDF_STATUS (*txrx_reset_monitor_mode) + (ol_txrx_soc_handle soc, uint8_t pdev_id, u_int8_t smart_monitor); + + QDF_STATUS (*txrx_deliver_tx_mgmt) + (struct cdp_soc_t *cdp_soc, uint8_t pdev_id, qdf_nbuf_t nbuf); /* HK advance monitor filter support */ QDF_STATUS (*txrx_set_advance_monitor_filter) - (struct cdp_pdev *pdev, struct cdp_monitor_filter *filter_val); - - void (*txrx_monitor_record_channel) - (struct cdp_pdev *, int val); + (struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct cdp_monitor_filter *filter_val); }; #ifdef WLAN_FEATURE_PKT_CAPTURE -/* - * struct cdp_pktcapture_ops - packet capture ops - * @txrx_pktcapture_record_channel: update channel information for packet - * capture mode - */ struct cdp_pktcapture_ops { + void (*txrx_pktcapture_set_mode) + (struct cdp_soc_t *soc, + uint8_t pdev_id, + uint8_t mode); + + uint8_t (*txrx_pktcapture_get_mode) + (struct cdp_soc_t *soc, + uint8_t pdev_id); + + QDF_STATUS (*txrx_pktcapture_cb_register) + (struct cdp_soc_t *soc, + uint8_t pdev_id, + void *context, + QDF_STATUS(cb)(void *, qdf_nbuf_t)); + + QDF_STATUS (*txrx_pktcapture_cb_deregister) + (struct cdp_soc_t *soc, + uint8_t pdev_id); + + QDF_STATUS (*txrx_pktcapture_mgmtpkt_process) + (struct cdp_soc_t *soc, + uint8_t pdev_id, + struct mon_rx_status *txrx_status, + qdf_nbuf_t nbuf, uint8_t status); + void (*txrx_pktcapture_record_channel) (struct cdp_soc_t *soc, - uint8_t pdev_id, - int chan_no); + uint8_t pdev_id, + int chan_no); }; #endif /* #ifdef WLAN_FEATURE_PKT_CAPTURE */ struct cdp_host_stats_ops { - int (*txrx_host_stats_get)(struct cdp_vdev *vdev, - struct ol_txrx_stats_req *req); + int (*txrx_host_stats_get)(struct cdp_soc_t *soc, uint8_t vdev_id, + struct ol_txrx_stats_req *req); - void (*txrx_host_stats_clr)(struct cdp_vdev *vdev); + QDF_STATUS (*txrx_host_stats_clr)(struct cdp_soc_t *soc, + uint8_t vdev_id); - void (*txrx_host_ce_stats)(struct cdp_vdev *vdev); + QDF_STATUS + (*txrx_host_ce_stats)(struct cdp_soc_t *soc, uint8_t vdev_id); - int (*txrx_stats_publish)(struct cdp_pdev *pdev, - struct cdp_stats_extd *buf); + int (*txrx_stats_publish)(struct cdp_soc_t *soc, uint8_t pdev_id, + struct cdp_stats_extd *buf); /** * @brief Enable enhanced stats functionality. * - * @param pdev - the physical device object - * @return - void + * @param soc - the soc handle + * @param pdev_id - pdev_id of pdev + * @return - QDF_STATUS */ - void (*txrx_enable_enhanced_stats)(struct cdp_pdev *pdev); + QDF_STATUS (*txrx_enable_enhanced_stats)(struct cdp_soc_t *soc, + uint8_t pdev_id); /** * @brief Disable enhanced stats functionality. * - * @param pdev - the physical device object - * @return - void + * @param soc - the soc handle + * @param pdev_id - pdev_id of pdev + * @return - QDF_STATUS */ - void (*txrx_disable_enhanced_stats)(struct cdp_pdev *pdev); + QDF_STATUS (*txrx_disable_enhanced_stats)(struct cdp_soc_t *soc, + uint8_t pdev_id); - /** - * @brief Get the desired stats from the message. - * - * @param pdev - the physical device object - * @param stats_base - stats buffer received from FW - * @param type - stats type. - * @return - pointer to requested stat identified by type - */ - uint32_t * (*txrx_get_stats_base)(struct cdp_pdev *pdev, - uint32_t *stats_base, uint32_t msg_len, uint8_t type); - void - (*tx_print_tso_stats)(struct cdp_vdev *vdev); + QDF_STATUS + (*tx_print_tso_stats)(struct cdp_soc_t *soc, uint8_t vdev_id); - void - (*tx_rst_tso_stats)(struct cdp_vdev *vdev); + QDF_STATUS + (*tx_rst_tso_stats)(struct cdp_soc_t *soc, uint8_t vdev_id); - void - (*tx_print_sg_stats)(struct cdp_vdev *vdev); + QDF_STATUS + (*tx_print_sg_stats)(struct cdp_soc_t *soc, uint8_t vdev_id); - void - (*tx_rst_sg_stats)(struct cdp_vdev *vdev); + QDF_STATUS + (*tx_rst_sg_stats)(struct cdp_soc_t *soc, uint8_t vdev_id); - void - (*print_rx_cksum_stats)(struct cdp_vdev *vdev); + QDF_STATUS + (*print_rx_cksum_stats)(struct cdp_soc_t *soc, uint8_t vdev_id); - void - (*rst_rx_cksum_stats)(struct cdp_vdev *vdev); + QDF_STATUS + (*rst_rx_cksum_stats)(struct cdp_soc_t *soc, uint8_t vdev_id); - A_STATUS - (*txrx_host_me_stats)(struct cdp_vdev *vdev); + QDF_STATUS + (*txrx_host_me_stats)(struct cdp_soc_t *soc, uint8_t vdev_id); - void - (*txrx_per_peer_stats)(struct cdp_pdev *pdev, char *addr); + QDF_STATUS + (*txrx_per_peer_stats)(struct cdp_soc_t *soc, uint8_t *addr); - int (*txrx_host_msdu_ttl_stats)(struct cdp_vdev *vdev, - struct ol_txrx_stats_req *req); + int (*txrx_host_msdu_ttl_stats)(struct cdp_soc_t *soc, uint8_t vdev_id, + struct ol_txrx_stats_req *req); - void - (*print_lro_stats)(struct cdp_vdev *vdev); + int (*ol_txrx_update_peer_stats)(struct cdp_soc_t *soc, + uint8_t pdev_id, + uint8_t *addr, void *stats, + uint32_t last_tx_rate_mcs, + uint32_t stats_id); - void - (*reset_lro_stats)(struct cdp_vdev *vdev); + QDF_STATUS + (*get_fw_peer_stats)(struct cdp_soc_t *soc, uint8_t pdev_id, + uint8_t *addr, + uint32_t cap, uint32_t copy_stats); - void - (*get_fw_peer_stats)(struct cdp_pdev *pdev, uint8_t *addr, - uint32_t cap, uint32_t copy_stats); - void - (*get_htt_stats)(struct cdp_pdev *pdev, void *data, - uint32_t data_len); - void - (*txrx_update_pdev_stats)(struct cdp_pdev *pdev, void *data, + QDF_STATUS + (*get_htt_stats)(struct cdp_soc_t *soc, uint8_t pdev_id, + void *data, + uint32_t data_len); + QDF_STATUS + (*txrx_update_pdev_stats)(struct cdp_soc_t *soc, + uint8_t pdev_id, void *data, uint16_t stats_id); - struct cdp_peer_stats* - (*txrx_get_peer_stats)(struct cdp_peer *peer); - void - (*txrx_reset_peer_ald_stats)(struct cdp_peer *peer); - void - (*txrx_reset_peer_stats)(struct cdp_peer *peer); + QDF_STATUS + (*txrx_get_peer_stats_param)(struct cdp_soc_t *soc, + uint8_t vdev_id, + uint8_t *peer_mac, + enum cdp_peer_stats_type type, + cdp_peer_stats_param_t *buf); + QDF_STATUS + (*txrx_get_peer_stats)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, + struct cdp_peer_stats *peer_stats); + QDF_STATUS + (*txrx_reset_peer_ald_stats)(struct cdp_soc_t *soc, + uint8_t vdev_id, + uint8_t *peer_mac); + QDF_STATUS + (*txrx_reset_peer_stats)(struct cdp_soc_t *soc, + uint8_t vdev_id, uint8_t *peer_mac); int - (*txrx_get_vdev_stats)(struct cdp_vdev *vdev, void *buf, - bool is_aggregate); + (*txrx_get_vdev_stats)(struct cdp_soc_t *soc, uint8_t vdev_id, + void *buf, bool is_aggregate); int (*txrx_process_wmi_host_vdev_stats)(ol_txrx_soc_handle soc, void *data, uint32_t len, uint32_t stats_id); int - (*txrx_get_vdev_extd_stats)(struct cdp_vdev *vdev_handle, - void *buffer); - void - (*txrx_update_vdev_stats)(struct cdp_vdev *vdev, void *buf, + (*txrx_get_vdev_extd_stats)(struct cdp_soc_t *soc, + uint8_t vdev_id, + wmi_host_vdev_extd_stats *buffer); + QDF_STATUS + (*txrx_update_vdev_stats)(struct cdp_soc_t *soc, + uint8_t vdev_id, void *buf, uint16_t stats_id); int - (*txrx_get_radio_stats)(struct cdp_pdev *pdev, + (*txrx_get_radio_stats)(struct cdp_soc_t *soc, uint8_t pdev_id, void *buf); - struct cdp_pdev_stats* - (*txrx_get_pdev_stats)(struct cdp_pdev *pdev); + QDF_STATUS + (*txrx_get_pdev_stats)(struct cdp_soc_t *soc, uint8_t pdev_id, + struct cdp_pdev_stats *buf); int (*txrx_get_ratekbps)(int preamb, int mcs, int htflag, int gintval); - void - (*configure_rate_stats)(struct cdp_soc_t *soc, - uint8_t val); + + QDF_STATUS + (*txrx_update_peer_stats)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, void *stats, + uint32_t last_tx_rate_mcs, + uint32_t stats_id); }; struct cdp_wds_ops { - void - (*txrx_set_wds_rx_policy)(struct cdp_vdev *vdev, - u_int32_t val); - void - (*txrx_wds_peer_tx_policy_update)(struct cdp_peer *peer, - int wds_tx_ucast, int wds_tx_mcast); - int (*vdev_set_wds)(void *vdev, uint32_t val); + QDF_STATUS + (*txrx_set_wds_rx_policy)(struct cdp_soc_t *soc, uint8_t vdev_id, + u_int32_t val); + QDF_STATUS + (*txrx_wds_peer_tx_policy_update)(struct cdp_soc_t *soc, + uint8_t vdev_id, uint8_t *peer_mac, + int wds_tx_ucast, int wds_tx_mcast); + int (*vdev_set_wds)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint32_t val); }; struct cdp_raw_ops { - int (*txrx_get_nwifi_mode)(struct cdp_vdev *vdev); + int (*txrx_get_nwifi_mode)(struct cdp_soc_t *soc, uint8_t vdev_id); - void (*rsim_get_astentry)(struct cdp_vdev *vdev, - qdf_nbuf_t *pnbuf, - struct cdp_raw_ast *raw_ast); + QDF_STATUS + (*rsim_get_astentry)(struct cdp_soc_t *soc, uint8_t vdev_id, + qdf_nbuf_t *pnbuf, struct cdp_raw_ast *raw_ast); }; #ifdef PEER_FLOW_CONTROL struct cdp_pflow_ops { - uint32_t(*pflow_update_pdev_params)(void *, - enum _ol_ath_param_t, uint32_t, void *); + uint32_t (*pflow_update_pdev_params)(struct cdp_soc_t *soc, + uint8_t pdev_id, + enum _ol_ath_param_t, + uint32_t, void *); }; #endif /* PEER_FLOW_CONTROL */ @@ -906,196 +979,380 @@ struct cdp_lro_hash_config { struct ol_if_ops { void - (*peer_set_default_routing)(struct cdp_ctrl_objmgr_pdev *ctrl_pdev, - uint8_t *peer_macaddr, uint8_t vdev_id, + (*peer_set_default_routing)(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + uint8_t pdev_id, uint8_t *peer_macaddr, + uint8_t vdev_id, bool hash_based, uint8_t ring_num); QDF_STATUS - (*peer_rx_reorder_queue_setup)(struct cdp_ctrl_objmgr_pdev *ctrl_pdev, + (*peer_rx_reorder_queue_setup)(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + uint8_t pdev_id, uint8_t vdev_id, uint8_t *peer_mac, qdf_dma_addr_t hw_qdesc, int tid, uint16_t queue_num, uint8_t ba_window_size_valid, uint16_t ba_window_size); QDF_STATUS - (*peer_rx_reorder_queue_remove)(struct cdp_ctrl_objmgr_pdev *ctrl_pdev, + (*peer_rx_reorder_queue_remove)(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + uint8_t pdev_id, uint8_t vdev_id, uint8_t *peer_macaddr, uint32_t tid_mask); - int (*peer_unref_delete)(void *scn_handle, uint8_t *peer_mac, - uint8_t *vdev_mac, enum wlan_op_mode opmode, - void *old_peer, void *new_peer); + int (*peer_unref_delete)(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, + uint8_t *peer_mac, + uint8_t *vdev_mac, enum wlan_op_mode opmode); bool (*is_hw_dbs_2x2_capable)(struct wlan_objmgr_psoc *psoc); - int (*peer_add_wds_entry)(void *vdev_handle, - struct cdp_peer *peer_handle, + int (*peer_add_wds_entry)(struct cdp_ctrl_objmgr_psoc *soc, + uint8_t vdev_id, + uint8_t *peer_macaddr, const uint8_t *dest_macaddr, uint8_t *next_node_mac, - uint32_t flags); - int (*peer_update_wds_entry)(void *ol_soc_handle, - uint8_t *dest_macaddr, uint8_t *peer_macaddr, - uint32_t flags); - void (*peer_del_wds_entry)(void *ol_soc_handle, + uint32_t flags, + uint8_t type); + int (*peer_update_wds_entry)(struct cdp_ctrl_objmgr_psoc *soc, + uint8_t vdev_id, + uint8_t *dest_macaddr, + uint8_t *peer_macaddr, + uint32_t flags); + void (*peer_del_wds_entry)(struct cdp_ctrl_objmgr_psoc *soc, + uint8_t vdev_id, uint8_t *wds_macaddr, uint8_t type); QDF_STATUS - (*lro_hash_config)(struct cdp_ctrl_objmgr_pdev *ctrl_pdev, + (*lro_hash_config)(struct cdp_ctrl_objmgr_psoc *psoc, uint8_t pdev_id, struct cdp_lro_hash_config *rx_offld_hash); + void (*update_dp_stats)(void *soc, void *stats, uint16_t id, uint8_t type); -#ifdef CONFIG_MCL - uint8_t (*rx_invalid_peer)(uint8_t vdev_id, void *wh); +#ifdef FEATURE_NAC_RSSI + uint8_t (*rx_invalid_peer)(struct cdp_ctrl_objmgr_psoc *soc, + uint8_t pdev_id, void *msg); #else - uint8_t (*rx_invalid_peer)(void *ctrl_pdev, void *msg); + uint8_t (*rx_invalid_peer)(uint8_t vdev_id, void *wh); #endif - int (*peer_map_event)(void *ol_soc_handle, uint16_t peer_id, uint16_t hw_peer_id, - uint8_t vdev_id, uint8_t *peer_mac_addr, - enum cdp_txrx_ast_entry_type peer_type, - uint32_t tx_ast_hashidx); - int (*peer_unmap_event)(void *ol_soc_handle, uint16_t peer_id, + + int (*peer_map_event)(struct cdp_ctrl_objmgr_psoc *psoc, + uint16_t peer_id, uint16_t hw_peer_id, + uint8_t vdev_id, uint8_t *peer_mac_addr, + enum cdp_txrx_ast_entry_type peer_type, + uint32_t tx_ast_hashidx); + int (*peer_unmap_event)(struct cdp_ctrl_objmgr_psoc *psoc, + uint16_t peer_id, uint8_t vdev_id); - int (*get_dp_cfg_param)(void *ol_soc_handle, enum cdp_cfg_param_type param_num); + int (*get_dp_cfg_param)(struct cdp_ctrl_objmgr_psoc *psoc, + enum cdp_cfg_param_type param_num); + + void (*rx_mic_error)(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, + struct cdp_rx_mic_err_info *info); - void (*rx_mic_error)(void *ol_soc_handle, - uint16_t vdev_id, void *wh); - bool (*rx_frag_tkip_demic)(struct wlan_objmgr_peer *ctrl_peer, + bool (*rx_frag_tkip_demic)(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t vdev_id, uint8_t *peer_mac_addr, qdf_nbuf_t nbuf, uint16_t hdr_space); - uint8_t (*freq_to_channel)(void *ol_soc_handle, uint16_t vdev_id); - void (*record_act_change)(struct wlan_objmgr_pdev *pdev, - u_int8_t *dstmac, bool active); + uint8_t (*freq_to_channel)(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t vdev_id, uint16_t freq); + #ifdef ATH_SUPPORT_NAC_RSSI - int (*config_fw_for_nac_rssi)(struct wlan_objmgr_pdev *pdev, - u_int8_t vdev_id, enum cdp_nac_param_cmd cmd, char *bssid, - char *client_macaddr, uint8_t chan_num); - int (*config_bssid_in_fw_for_nac_rssi)(struct wlan_objmgr_pdev *pdev, - u_int8_t vdev_id, enum cdp_nac_param_cmd cmd, char *bssid); + int (*config_fw_for_nac_rssi)(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, + u_int8_t vdev_id, + enum cdp_nac_param_cmd cmd, char *bssid, + char *client_macaddr, uint8_t chan_num); + + int + (*config_bssid_in_fw_for_nac_rssi)(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, u_int8_t vdev_id, + enum cdp_nac_param_cmd cmd, + char *bssid, char *client_mac); #endif - int (*peer_sta_kickout)(void *ctrl_pdev, uint8_t *peer_macaddr); + int (*peer_sta_kickout)(struct cdp_ctrl_objmgr_psoc *psoc, + uint16_t pdev_id, uint8_t *peer_macaddr); /** * send_delba() - Send delba to peer - * @pdev_handle: Dp pdev handle - * @ctrl_peer: Peer handle + * @psoc: Objmgr soc handle + * @vdev_id: dp vdev id * @peer_macaddr: Peer mac addr * @tid: Tid number * * Return: 0 for success, non-zero for failure */ - int (*send_delba)(void *pdev_handle, void *ctrl_peer, - uint8_t *peer_macaddr, uint8_t tid, void *vdev_handle, + int (*send_delba)(struct cdp_ctrl_objmgr_psoc *psoc, uint8_t vdev_id, + uint8_t *peer_macaddr, uint8_t tid, uint8_t reason_code); - int (*peer_delete_multiple_wds_entries)(void *vdev_handle, - uint8_t *dest_macaddr, - uint8_t *peer_macaddr, - uint32_t flags); + int + (*peer_delete_multiple_wds_entries)(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t vdev_id, + uint8_t *dest_macaddr, + uint8_t *peer_macaddr, + uint32_t flags); + int + (*pdev_update_lmac_n_target_pdev_id)(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t *pdev_id, + uint8_t *lmac_id, + uint8_t *target_pdev_id); bool (*is_roam_inprogress)(uint32_t vdev_id); enum QDF_GLOBAL_MODE (*get_con_mode)(void); +#ifdef QCA_PEER_MULTIQ_SUPPORT + int (*peer_ast_flowid_map)(struct cdp_ctrl_objmgr_psoc *ol_soc_handle, + uint16_t peer_id, uint8_t vdev_id, + uint8_t *peer_mac_addr); +#endif +#ifdef DP_MEM_PRE_ALLOC + void *(*dp_prealloc_get_context)(uint32_t ctxt_type); + + QDF_STATUS(*dp_prealloc_put_context)(uint32_t ctxt_type, void *vaddr); + void *(*dp_prealloc_get_consistent)(uint32_t *size, + void **base_vaddr_unaligned, + qdf_dma_addr_t *paddr_unaligned, + qdf_dma_addr_t *paddr_aligned, + uint32_t align, + uint32_t ring_type); + void (*dp_prealloc_put_consistent)(qdf_size_t size, + void *vaddr_unligned, + qdf_dma_addr_t paddr); + void (*dp_get_multi_pages)(uint32_t desc_type, + size_t element_size, + uint16_t element_num, + struct qdf_mem_multi_page_t *pages, + bool cacheable); + void (*dp_put_multi_pages)(uint32_t desc_type, + struct qdf_mem_multi_page_t *pages); +#endif + int (*dp_rx_get_pending)(ol_txrx_soc_handle soc); /* TODO: Add any other control path calls required to OL_IF/WMA layer */ }; -#ifdef CONFIG_MCL -/* From here MCL specific OPs */ + +#ifdef DP_PEER_EXTENDED_API /** * struct cdp_misc_ops - mcl ops not classified - * @set_ibss_vdev_heart_beat_timer: - * @bad_peer_txctl_set_setting: - * @bad_peer_txctl_update_threshold: - * @hl_tdls_flag_reset: - * @tx_non_std: - * @get_vdev_id: - * @set_wisa_mode: - * @txrx_data_stall_cb_register: - * @txrx_data_stall_cb_deregister: - * @txrx_post_data_stall_event - * @runtime_suspend: - * @runtime_resume: - * @register_packetdump_cb: - * @unregister_packetdump_cb: - * @pdev_reset_driver_del_ack: - * @vdev_set_driver_del_ack_enable: + * @set_ibss_vdev_heart_beat_timer: Update ibss vdev heart beat timer + * @set_wmm_param: set wmm parameters + * @bad_peer_txctl_set_setting: configure bad peer tx limit setting + * @bad_peer_txctl_update_threshold: configure bad peer tx threshold limit + * @hl_tdls_flag_reset: reset tdls flag for vdev + * @tx_non_std: Allow the control-path SW to send data frames + * @get_vdev_id: get vdev id + * @set_wisa_mode: set wisa mode for a vdev + * @txrx_data_stall_cb_register: register data stall callback + * @txrx_data_stall_cb_deregister: deregister data stall callback + * @txrx_post_data_stall_event: post data stall event + * @runtime_suspend: ensure TXRX is ready to runtime suspend + * @runtime_resume: ensure TXRX is ready to runtime resume + * @get_opmode: get operation mode of vdev + * @mark_first_wakeup_packet: set flag to indicate that fw is compatible for + marking first packet after wow wakeup + * @update_mac_id: update mac_id for vdev + * @flush_rx_frames: flush rx frames on the queue + * @get_intra_bss_fwd_pkts_count: to get the total tx and rx packets that + has been forwarded from txrx layer + without going to upper layers + * @pkt_log_init: handler to initialize packet log + * @pkt_log_con_service: handler to connect packet log service + * @get_num_rx_contexts: handler to get number of RX contexts + * @register_packetdump_cb: register callback for different pktlog + * @unregister_packetdump_cb: unregister callback for different pktlog + * @pdev_reset_driver_del_ack: reset driver delayed ack enabled flag + * @vdev_set_driver_del_ack_enable: set driver delayed ack enabled flag + * + * Function pointers for miscellaneous soc/pdev/vdev related operations. */ struct cdp_misc_ops { - uint16_t (*set_ibss_vdev_heart_beat_timer)(struct cdp_vdev *vdev, - uint16_t timer_value_sec); - void (*set_wmm_param)(struct cdp_pdev *cfg_pdev, - struct ol_tx_wmm_param_t wmm_param); - void (*bad_peer_txctl_set_setting)(struct cdp_pdev *pdev, int enable, - int period, int txq_limit); - void (*bad_peer_txctl_update_threshold)(struct cdp_pdev *pdev, - int level, int tput_thresh, int tx_limit); - void (*hl_tdls_flag_reset)(struct cdp_vdev *vdev, bool flag); - qdf_nbuf_t (*tx_non_std)(struct cdp_vdev *vdev, - enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list); + uint16_t (*set_ibss_vdev_heart_beat_timer)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, + uint16_t timer_value_sec); + void (*set_wmm_param)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct ol_tx_wmm_param_t wmm_param); + void (*bad_peer_txctl_set_setting)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, int enable, + int period, int txq_limit); + void (*bad_peer_txctl_update_threshold)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + int level, int tput_thresh, + int tx_limit); + void (*hl_tdls_flag_reset)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, bool flag); + qdf_nbuf_t (*tx_non_std)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list); uint16_t (*get_vdev_id)(struct cdp_vdev *vdev); - uint32_t (*get_tx_ack_stats)(struct cdp_pdev *pdev, uint8_t vdev_id); - QDF_STATUS (*set_wisa_mode)(struct cdp_vdev *vdev, bool enable); - QDF_STATUS (*txrx_data_stall_cb_register)( - struct cdp_pdev *pdev, - data_stall_detect_cb cb); - QDF_STATUS (*txrx_data_stall_cb_deregister)( - struct cdp_pdev *pdev, - data_stall_detect_cb cb); + uint32_t (*get_tx_ack_stats)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id); + QDF_STATUS (*set_wisa_mode)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, bool enable); + QDF_STATUS (*txrx_data_stall_cb_register)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + data_stall_detect_cb cb); + QDF_STATUS (*txrx_data_stall_cb_deregister)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + data_stall_detect_cb cb); void (*txrx_post_data_stall_event)( - struct cdp_pdev *pdev, + struct cdp_soc_t *soc_hdl, enum data_stall_log_event_indicator indicator, enum data_stall_log_event_type data_stall_type, uint32_t pdev_id, uint32_t vdev_id_bitmap, enum data_stall_log_recovery_type recovery_type); - QDF_STATUS (*runtime_suspend)(struct cdp_pdev *pdev); - QDF_STATUS (*runtime_resume)(struct cdp_pdev *pdev); - int (*get_opmode)(struct cdp_vdev *vdev); - void (*mark_first_wakeup_packet)(uint8_t value); - void (*update_mac_id)(uint8_t vdev_id, uint8_t mac_id); - void (*flush_rx_frames)(void *peer, bool drop); - A_STATUS (*get_intra_bss_fwd_pkts_count)(uint8_t vdev_id, - uint64_t *fwd_tx_packets, uint64_t *fwd_rx_packets); - void (*pkt_log_init)(struct cdp_pdev *handle, void *scn); - void (*pkt_log_con_service)(struct cdp_pdev *pdev, void *scn); - int (*get_num_rx_contexts)(struct cdp_soc_t *soc); - void (*register_pktdump_cb)(ol_txrx_pktdump_cb tx_cb, + QDF_STATUS (*runtime_suspend)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); + QDF_STATUS (*runtime_resume)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); + int (*get_opmode)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id); + void (*mark_first_wakeup_packet)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, uint8_t value); + void (*update_mac_id)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t mac_id); + void (*flush_rx_frames)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + void *peer, bool drop); + A_STATUS(*get_intra_bss_fwd_pkts_count)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, + uint64_t *fwd_tx_packets, + uint64_t *fwd_rx_packets); + void (*pkt_log_init)(struct cdp_soc_t *soc_hdl, uint8_t pdev, + void *scn); + void (*pkt_log_con_service)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, void *scn); + int (*get_num_rx_contexts)(struct cdp_soc_t *soc_hdl); + void (*register_pktdump_cb)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + ol_txrx_pktdump_cb tx_cb, ol_txrx_pktdump_cb rx_cb); - void (*unregister_pktdump_cb)(void); - void (*pdev_reset_driver_del_ack)(struct cdp_pdev *ppdev); - void (*vdev_set_driver_del_ack_enable)(uint8_t vdev_id, + void (*unregister_pktdump_cb)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); + void (*pdev_reset_driver_del_ack)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); + void (*vdev_set_driver_del_ack_enable)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, unsigned long rx_packets, uint32_t time_in_ms, uint32_t high_th, uint32_t low_th); - QDF_STATUS (*txrx_ext_stats_request)(struct cdp_pdev *pdev, + void (*vdev_set_bundle_require_flag)(uint8_t vdev_id, + unsigned long tx_bytes, + uint32_t time_in_ms, + uint32_t high_th, + uint32_t low_th); + void (*pdev_reset_bundle_require_flag)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); + QDF_STATUS (*txrx_ext_stats_request)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, struct cdp_txrx_ext_stats *req); QDF_STATUS (*request_rx_hw_stats)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id); }; /** - * struct cdp_tx_delay_ops - mcl tx delay ops - * @tx_delay: - * @tx_delay_hist: - * @tx_packet_count: - * @tx_set_compute_interval: + * struct cdp_ocb_ops - mcl ocb ops + * @set_ocb_chan_info: set OCB channel info + * @get_ocb_chan_info: get OCB channel info + * + * Function pointers for operations related to OCB. */ -struct cdp_tx_delay_ops { - void (*tx_delay)(struct cdp_pdev *pdev, uint32_t *queue_delay_microsec, - uint32_t *tx_delay_microsec, int category); - void (*tx_delay_hist)(struct cdp_pdev *pdev, - uint16_t *bin_values, int category); - void (*tx_packet_count)(struct cdp_pdev *pdev, - uint16_t *out_packet_count, - uint16_t *out_packet_loss_count, int category); - void (*tx_set_compute_interval)(struct cdp_pdev *pdev, - uint32_t interval); +struct cdp_ocb_ops { + void (*set_ocb_chan_info)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + struct ol_txrx_ocb_set_chan ocb_set_chan); + struct ol_txrx_ocb_chan_info *(*get_ocb_chan_info)( + struct cdp_soc_t *soc_hdl, uint8_t vdev_id); +}; + +/** + * struct cdp_peer_ops - mcl peer related ops + * @register_peer: + * @clear_peer: + * @find_peer_exist + * @find_peer_exist_on_vdev + * @find_peer_exist_on_other_vdev + * @peer_state_update: + * @get_vdevid: + * @register_ocb_peer: + * @peer_get_peer_mac_addr: + * @get_peer_state: + * @update_ibss_add_peer_num_of_vdev: + * @copy_mac_addr_raw: + * @add_last_real_peer: + * @is_vdev_restore_last_peer: + * @update_last_real_peer: + */ +struct cdp_peer_ops { + QDF_STATUS (*register_peer)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct ol_txrx_desc_type *sta_desc); + QDF_STATUS (*clear_peer)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct qdf_mac_addr peer_addr); + bool (*find_peer_exist)(struct cdp_soc_t *soc, uint8_t pdev_id, + uint8_t *peer_addr); + bool (*find_peer_exist_on_vdev)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_addr); + bool (*find_peer_exist_on_other_vdev)(struct cdp_soc_t *soc, + uint8_t vdev_id, + uint8_t *peer_addr, + uint16_t max_bssid); + QDF_STATUS (*peer_state_update)(struct cdp_soc_t *soc, + uint8_t *peer_addr, + enum ol_txrx_peer_state state); + QDF_STATUS (*get_vdevid)(struct cdp_soc_t *soc_hdl, uint8_t *peer_mac, + uint8_t *vdev_id); + struct cdp_vdev * (*get_vdev_by_peer_addr)(struct cdp_pdev *pdev, + struct qdf_mac_addr peer_addr); + QDF_STATUS (*register_ocb_peer)(uint8_t *mac_addr); + uint8_t * (*peer_get_peer_mac_addr)(void *peer); + int (*get_peer_state)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac); + struct cdp_vdev * (*get_vdev_for_peer)(void *peer); + int16_t (*update_ibss_add_peer_num_of_vdev)(struct cdp_soc_t *soc, + uint8_t vdev_id, + int16_t peer_num_delta); + void (*remove_peers_for_vdev)(struct cdp_vdev *vdev, + ol_txrx_vdev_peer_remove_cb callback, + void *callback_context, bool remove_last_peer); + void (*remove_peers_for_vdev_no_lock)(struct cdp_vdev *vdev, + ol_txrx_vdev_peer_remove_cb callback, + void *callback_context); + void (*copy_mac_addr_raw)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *bss_addr); + void (*add_last_real_peer)(struct cdp_soc_t *soc, uint8_t pdev_id, + uint8_t vdev_id); + bool (*is_vdev_restore_last_peer)(struct cdp_soc_t *soc, + uint8_t vdev_id, + uint8_t *peer_mac); + void (*update_last_real_peer)(struct cdp_soc_t *soc, uint8_t pdev_id, + uint8_t vdev_id, bool restore_last_peer); + void (*peer_detach_force_delete)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, uint8_t *peer_addr); + void (*set_tdls_offchan_enabled)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, bool val); + void (*set_peer_as_tdls_peer)(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, bool val); + void (*peer_flush_frags)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, uint8_t *peer_mac); +}; + +/** + * struct cdp_mob_stats_ops - mcl mob stats ops + * @clear_stats: handler to clear ol txrx stats + * @stats: handler to update ol txrx stats + */ +struct cdp_mob_stats_ops { + QDF_STATUS(*clear_stats)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, uint8_t bitmap); + int (*stats)(uint8_t vdev_id, char *buffer, unsigned buf_len); }; /** * struct cdp_pmf_ops - mcl protected management frame ops - * @get_pn_info: + * @get_pn_info: handler to get pn info from peer + * + * Function pointers for pmf related operations. */ struct cdp_pmf_ops { - void (*get_pn_info)(void *peer, uint8_t **last_pn_valid, - uint64_t **last_pn, uint32_t **rmf_pn_replays); + void (*get_pn_info)(struct cdp_soc_t *soc, uint8_t *peer_mac, + uint8_t vdev_id, uint8_t **last_pn_valid, + uint64_t **last_pn, uint32_t **rmf_pn_replays); }; +#endif + +#ifdef DP_FLOW_CTL /** * struct cdp_cfg_ops - mcl configuration ops * @set_cfg_rx_fwd_disabled: set rx_fwd_disabled flag @@ -1127,7 +1384,8 @@ struct cdp_cfg_ops { void (*set_cfg_packet_log_enabled)(struct cdp_cfg *cfg_pdev, uint8_t val); struct cdp_cfg * (*cfg_attach)(qdf_device_t osdev, void *cfg_param); - void (*vdev_rx_set_intrabss_fwd)(struct cdp_vdev *vdev, bool val); + void (*vdev_rx_set_intrabss_fwd)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, bool val); uint8_t (*is_rx_fwd_disabled)(struct cdp_vdev *vdev); void (*tx_set_is_mgmt_over_wmi_enabled)(uint8_t value); int (*is_high_latency)(struct cdp_cfg *cfg_pdev); @@ -1144,59 +1402,94 @@ struct cdp_cfg_ops { /** * struct cdp_flowctl_ops - mcl flow control - * @register_pause_cb: - * @set_desc_global_pool_size: - * @dump_flow_pool_info: + * @flow_pool_map_handler: handler to map flow_id and pool descriptors + * @flow_pool_unmap_handler: handler to unmap flow_id and pool descriptors + * @register_pause_cb: handler to register tx pause callback + * @set_desc_global_pool_size: handler to set global pool size + * @dump_flow_pool_info: handler to dump global and flow pool info + * @tx_desc_thresh_reached: handler to set tx desc threshold + * + * Function pointers for operations related to flow control */ struct cdp_flowctl_ops { QDF_STATUS (*flow_pool_map_handler)(struct cdp_soc_t *soc, - struct cdp_pdev *pdev, + uint8_t pdev_id, uint8_t vdev_id); void (*flow_pool_unmap_handler)(struct cdp_soc_t *soc, - struct cdp_pdev *pdev, + uint8_t pdev_id, uint8_t vdev_id); QDF_STATUS (*register_pause_cb)(struct cdp_soc_t *soc, tx_pause_callback); void (*set_desc_global_pool_size)(uint32_t num_msdu_desc); - void (*dump_flow_pool_info)(void *); + void (*dump_flow_pool_info)(struct cdp_soc_t *soc_hdl); - bool (*tx_desc_thresh_reached)(struct cdp_vdev *vdev); + bool (*tx_desc_thresh_reached)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id); }; /** * struct cdp_lflowctl_ops - mcl legacy flow control ops - * @register_tx_flow_control: - * @deregister_tx_flow_control_cb: - * @flow_control_cb: - * @get_tx_resource: - * @ll_set_tx_pause_q_depth: - * @vdev_flush: - * @vdev_pause: - * @vdev_unpause: + * @register_tx_flow_control: Register tx flow control callback + * @set_vdev_tx_desc_limit: Set tx descriptor limit for a vdev + * @set_vdev_os_queue_status: Set vdev queue status + * @deregister_tx_flow_control_cb: Deregister tx flow control callback + * @flow_control_cb: Call osif flow control callback + * @get_tx_resource: Get tx resources and comapre with watermark + * @ll_set_tx_pause_q_depth: set pause queue depth + * @vdev_flush: Flush all packets on a particular vdev + * @vdev_pause: Pause a particular vdev + * @vdev_unpause: Unpause a particular vdev + * + * Function pointers for operations related to flow control */ struct cdp_lflowctl_ops { #ifdef QCA_HL_NETDEV_FLOW_CONTROL - int (*register_tx_flow_control)(struct cdp_soc_t *soc, + int (*register_tx_flow_control)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, tx_pause_callback flowcontrol); - int (*set_vdev_tx_desc_limit)(uint8_t vdev_id, uint8_t chan); - int (*set_vdev_os_queue_status)(uint8_t vdev_id, + int (*set_vdev_tx_desc_limit)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, uint32_t chan_freq); + int (*set_vdev_os_queue_status)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, enum netif_action_type action); #else - int (*register_tx_flow_control)(uint8_t vdev_id, + int (*register_tx_flow_control)( + struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, ol_txrx_tx_flow_control_fp flowControl, void *osif_fc_ctx, ol_txrx_tx_flow_control_is_pause_fp flow_control_is_pause); #endif /* QCA_HL_NETDEV_FLOW_CONTROL */ - int (*deregister_tx_flow_control_cb)(uint8_t vdev_id); - void (*flow_control_cb)(struct cdp_vdev *vdev, bool tx_resume); - bool (*get_tx_resource)(uint8_t sta_id, - unsigned int low_watermark, - unsigned int high_watermark_offset); - int (*ll_set_tx_pause_q_depth)(uint8_t vdev_id, int pause_q_depth); - void (*vdev_flush)(struct cdp_vdev *vdev); - void (*vdev_pause)(struct cdp_vdev *vdev, uint32_t reason); - void (*vdev_unpause)(struct cdp_vdev *vdev, uint32_t reason); + int (*deregister_tx_flow_control_cb)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id); + void (*flow_control_cb)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + bool tx_resume); + bool (*get_tx_resource)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct qdf_mac_addr peer_addr, + unsigned int low_watermark, + unsigned int high_watermark_offset); + int (*ll_set_tx_pause_q_depth)(struct cdp_soc_t *soc, uint8_t vdev_id, + int pause_q_depth); + void (*vdev_flush)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id); + void (*vdev_pause)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint32_t reason, uint32_t pause_type); + void (*vdev_unpause)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint32_t reason, uint32_t pause_type); +}; + +/** + * struct cdp_throttle_ops - mcl throttle ops + * @throttle_init_period: handler to initialize tx throttle time + * @throttle_set_level: handler to set tx throttle level + */ +struct cdp_throttle_ops { + void (*throttle_init_period)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, int period, + uint8_t *dutycycle_level); + void (*throttle_set_level)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, int level); }; +#endif #ifdef IPA_OFFLOAD /** @@ -1210,176 +1503,109 @@ struct cdp_lflowctl_ops { * @ipa_tx_data_frame: */ struct cdp_ipa_ops { - QDF_STATUS (*ipa_get_resource)(struct cdp_pdev *pdev); - QDF_STATUS (*ipa_set_doorbell_paddr)(struct cdp_pdev *pdev); - QDF_STATUS (*ipa_set_active)(struct cdp_pdev *pdev, bool uc_active, - bool is_tx); - QDF_STATUS (*ipa_op_response)(struct cdp_pdev *pdev, uint8_t *op_msg); - QDF_STATUS (*ipa_register_op_cb)(struct cdp_pdev *pdev, - void (*ipa_uc_op_cb_type)(uint8_t *op_msg, void *osif_ctxt), - void *usr_ctxt); - QDF_STATUS (*ipa_get_stat)(struct cdp_pdev *pdev); - qdf_nbuf_t (*ipa_tx_data_frame)(struct cdp_vdev *vdev, qdf_nbuf_t skb); + QDF_STATUS (*ipa_get_resource)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); + QDF_STATUS (*ipa_set_doorbell_paddr)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); + QDF_STATUS (*ipa_set_active)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + bool uc_active, bool is_tx); + QDF_STATUS (*ipa_op_response)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, uint8_t *op_msg); + QDF_STATUS (*ipa_register_op_cb)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + void (*ipa_uc_op_cb_type) + (uint8_t *op_msg, void *osif_ctxt), + void *usr_ctxt); + QDF_STATUS (*ipa_get_stat)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); + qdf_nbuf_t (*ipa_tx_data_frame)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, qdf_nbuf_t skb); void (*ipa_set_uc_tx_partition_base)(struct cdp_cfg *pdev, uint32_t value); #ifdef FEATURE_METERING - QDF_STATUS (*ipa_uc_get_share_stats)(struct cdp_pdev *pdev, - uint8_t reset_stats); - QDF_STATUS (*ipa_uc_set_quota)(struct cdp_pdev *pdev, - uint64_t quota_bytes); + QDF_STATUS (*ipa_uc_get_share_stats)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + uint8_t reset_stats); + QDF_STATUS (*ipa_uc_set_quota)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, uint64_t quota_bytes); #endif - QDF_STATUS (*ipa_enable_autonomy)(struct cdp_pdev *pdev); - QDF_STATUS (*ipa_disable_autonomy)(struct cdp_pdev *pdev); + QDF_STATUS (*ipa_enable_autonomy)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); + QDF_STATUS (*ipa_disable_autonomy)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); #ifdef CONFIG_IPA_WDI_UNIFIED_API - QDF_STATUS (*ipa_setup)(struct cdp_pdev *pdev, void *ipa_i2w_cb, - void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, - uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled, - uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle, - bool is_smmu_enabled, qdf_ipa_sys_connect_params_t *sys_in, - bool over_gsi); + QDF_STATUS (*ipa_setup)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + void *ipa_i2w_cb, void *ipa_w2i_cb, + void *ipa_wdi_meter_notifier_cb, + uint32_t ipa_desc_size, void *ipa_priv, + bool is_rm_enabled, uint32_t *tx_pipe_handle, + uint32_t *rx_pipe_handle, bool is_smmu_enabled, + qdf_ipa_sys_connect_params_t *sys_in, + bool over_gsi); #else /* CONFIG_IPA_WDI_UNIFIED_API */ - QDF_STATUS (*ipa_setup)(struct cdp_pdev *pdev, void *ipa_i2w_cb, - void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, - uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled, - uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle); + QDF_STATUS (*ipa_setup)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + void *ipa_i2w_cb, void *ipa_w2i_cb, + void *ipa_wdi_meter_notifier_cb, + uint32_t ipa_desc_size, void *ipa_priv, + bool is_rm_enabled, uint32_t *tx_pipe_handle, + uint32_t *rx_pipe_handle); #endif /* CONFIG_IPA_WDI_UNIFIED_API */ - QDF_STATUS (*ipa_cleanup)(uint32_t tx_pipe_handle, - uint32_t rx_pipe_handle); + QDF_STATUS (*ipa_cleanup)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint32_t tx_pipe_handle, + uint32_t rx_pipe_handle); QDF_STATUS (*ipa_setup_iface)(char *ifname, uint8_t *mac_addr, qdf_ipa_client_type_t prod_client, qdf_ipa_client_type_t cons_client, uint8_t session_id, bool is_ipv6_enabled); QDF_STATUS (*ipa_cleanup_iface)(char *ifname, bool is_ipv6_enabled); - QDF_STATUS (*ipa_enable_pipes)(struct cdp_pdev *pdev); - QDF_STATUS (*ipa_disable_pipes)(struct cdp_pdev *pdev); + QDF_STATUS (*ipa_enable_pipes)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); + QDF_STATUS (*ipa_disable_pipes)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); QDF_STATUS (*ipa_set_perf_level)(int client, uint32_t max_supported_bw_mbps); - bool (*ipa_rx_intrabss_fwd)(struct cdp_vdev *vdev, qdf_nbuf_t nbuf, - bool *fwd_success); + bool (*ipa_rx_intrabss_fwd)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + qdf_nbuf_t nbuf, bool *fwd_success); }; #endif +#ifdef DP_POWER_SAVE +/** + * struct cdp_tx_delay_ops - mcl tx delay ops + * @tx_delay: handler to get tx packet delay + * @tx_delay_hist: handler to get tx packet delay histogram + * @tx_packet_count: handler to get tx packet count + * @tx_set_compute_interval: update compute interval period for TSM stats + * + * Function pointer for operations related to tx delay. + */ +struct cdp_tx_delay_ops { + void (*tx_delay)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint32_t *queue_delay_microsec, + uint32_t *tx_delay_microsec, int category); + void (*tx_delay_hist)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint16_t *bin_values, int category); + void (*tx_packet_count)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint16_t *out_packet_count, + uint16_t *out_packet_loss_count, int category); + void (*tx_set_compute_interval)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, uint32_t interval); +}; + /** * struct cdp_bus_ops - mcl bus suspend/resume ops - * @bus_suspend: - * @bus_resume: + * @bus_suspend: handler for bus suspend + * @bus_resume: handler for bus resume * @process_wow_ack_rsp: handler for wow ack response * @process_target_suspend_req: handler for target suspend request */ struct cdp_bus_ops { - QDF_STATUS (*bus_suspend)(struct cdp_pdev *opaque_pdev); - QDF_STATUS (*bus_resume)(struct cdp_pdev *opaque_pdev); - void (*process_wow_ack_rsp)(struct cdp_soc_t *soc_hdl, - struct cdp_pdev *opaque_pdev); + QDF_STATUS (*bus_suspend)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); + QDF_STATUS (*bus_resume)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); + void (*process_wow_ack_rsp)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); void (*process_target_suspend_req)(struct cdp_soc_t *soc_hdl, - struct cdp_pdev *opaque_pdev); -}; - -/** - * struct cdp_ocb_ops - mcl ocb ops - * @set_ocb_chan_info: - * @get_ocb_chan_info: - */ -struct cdp_ocb_ops { - void (*set_ocb_chan_info)(struct cdp_vdev *vdev, - struct ol_txrx_ocb_set_chan ocb_set_chan); - struct ol_txrx_ocb_chan_info * - (*get_ocb_chan_info)(struct cdp_vdev *vdev); -}; - -/** - * struct cdp_peer_ops - mcl peer related ops - * @register_peer: - * @clear_peer: - * @cfg_attach: - * @find_peer_by_addr: - * @find_peer_by_addr_and_vdev: - * @local_peer_id: - * @peer_find_by_local_id: - * @peer_state_update: - * @get_vdevid: - * @get_vdev_by_sta_id: - * @register_ocb_peer: - * @peer_get_peer_mac_addr: - * @get_peer_state: - * @get_vdev_for_peer: - * @update_ibss_add_peer_num_of_vdev: - * @remove_peers_for_vdev: - * @remove_peers_for_vdev_no_lock: - * @copy_mac_addr_raw: - * @add_last_real_peer: - * @is_vdev_restore_last_peer: - * @update_last_real_peer: - */ -struct cdp_peer_ops { - QDF_STATUS (*register_peer)(struct cdp_pdev *pdev, - struct ol_txrx_desc_type *sta_desc); - QDF_STATUS (*clear_peer)(struct cdp_pdev *pdev, uint8_t sta_id); - QDF_STATUS (*change_peer_state)(uint8_t sta_id, - enum ol_txrx_peer_state sta_state, - bool roam_synch_in_progress); - void * (*peer_get_ref_by_addr)(struct cdp_pdev *pdev, - uint8_t *peer_addr, uint8_t *peer_id, - enum peer_debug_id_type debug_id); - void (*peer_release_ref)(void *peer, enum peer_debug_id_type debug_id); - void * (*find_peer_by_addr)(struct cdp_pdev *pdev, - uint8_t *peer_addr, uint8_t *peer_id); - void * (*find_peer_by_addr_and_vdev)(struct cdp_pdev *pdev, - struct cdp_vdev *vdev, - uint8_t *peer_addr, uint8_t *peer_id); - uint16_t (*local_peer_id)(void *peer); - void * (*peer_find_by_local_id)(struct cdp_pdev *pdev, - uint8_t local_peer_id); - QDF_STATUS (*peer_state_update)(struct cdp_pdev *pdev, - uint8_t *peer_addr, - enum ol_txrx_peer_state state); - QDF_STATUS (*get_vdevid)(void *peer, uint8_t *vdev_id); - struct cdp_vdev * (*get_vdev_by_sta_id)(struct cdp_pdev *pdev, - uint8_t sta_id); - QDF_STATUS (*register_ocb_peer)(uint8_t *mac_addr, uint8_t *peer_id); - uint8_t * (*peer_get_peer_mac_addr)(void *peer); - int (*get_peer_state)(void *peer); - struct cdp_vdev * (*get_vdev_for_peer)(void *peer); - int16_t (*update_ibss_add_peer_num_of_vdev)(struct cdp_vdev *vdev, - int16_t peer_num_delta); - void (*remove_peers_for_vdev)(struct cdp_vdev *vdev, - ol_txrx_vdev_peer_remove_cb callback, - void *callback_context, bool remove_last_peer); - void (*remove_peers_for_vdev_no_lock)(struct cdp_vdev *vdev, - ol_txrx_vdev_peer_remove_cb callback, - void *callback_context); - void (*copy_mac_addr_raw)(struct cdp_vdev *vdev, uint8_t *bss_addr); - void (*add_last_real_peer)(struct cdp_pdev *pdev, - struct cdp_vdev *vdev, uint8_t *peer_id); - bool (*is_vdev_restore_last_peer)(void *peer); - void (*update_last_real_peer)(struct cdp_pdev *pdev, void *vdev, - uint8_t *peer_id, bool restore_last_peer); - void (*peer_detach_force_delete)(void *peer); - void (*peer_flush_frags)(struct cdp_pdev *pdev, - uint8_t vdev_id, uint8_t *peer_mac); + uint8_t pdev_id); }; - -/** - * struct cdp_ocb_ops - mcl ocb ops - * @throttle_init_period: - * @throttle_set_level: - */ -struct cdp_throttle_ops { - void (*throttle_init_period)(struct cdp_pdev *pdev, int period, - uint8_t *dutycycle_level); - void (*throttle_set_level)(struct cdp_pdev *pdev, int level); -}; - -/** - * struct cdp_ocb_ops - mcl ocb ops - * @clear_stats: - * @stats: - */ -struct cdp_mob_stats_ops { - void (*clear_stats)(uint16_t bitmap); - int (*stats)(uint8_t vdev_id, char *buffer, unsigned buf_len); -}; -#endif /* CONFIG_MCL */ +#endif #ifdef RECEIVE_OFFLOAD /** @@ -1393,6 +1619,37 @@ struct cdp_rx_offld_ops { }; #endif +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) +/** + * struct cdp_cfr_ops - host cfr ops + * @txrx_cfr_filter: Handler to configure host rx monitor status ring + * @txrx_get_cfr_rcc: Handler to get CFR mode + * @txrx_set_cfr_rcc: Handler to enable/disable CFR mode + * @txrx_get_cfr_dbg_stats: Handler to get debug statistics for CFR mode + * @txrx_clear_cfr_dbg_stats: Handler to clear debug statistics for CFR mode + * @txrx_enable_mon_reap_timer: Enable/Disable reap timer of monitor status ring + */ +struct cdp_cfr_ops { + void (*txrx_cfr_filter)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + bool enable, + struct cdp_monitor_filter *filter_val); + bool (*txrx_get_cfr_rcc)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); + void (*txrx_set_cfr_rcc)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + bool enable); + void (*txrx_get_cfr_dbg_stats)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + struct cdp_cfr_rcc_stats *buf); + void (*txrx_clear_cfr_dbg_stats)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); + void (*txrx_enable_mon_reap_timer)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + bool enable); +}; +#endif + struct cdp_ops { struct cdp_cmn_ops *cmn_drv_ops; struct cdp_ctrl_ops *ctrl_ops; @@ -1402,27 +1659,35 @@ struct cdp_ops { struct cdp_wds_ops *wds_ops; struct cdp_raw_ops *raw_ops; struct cdp_pflow_ops *pflow_ops; -#ifdef CONFIG_MCL +#ifdef DP_PEER_EXTENDED_API struct cdp_misc_ops *misc_ops; + struct cdp_peer_ops *peer_ops; + struct cdp_ocb_ops *ocb_ops; + struct cdp_mob_stats_ops *mob_stats_ops; + struct cdp_pmf_ops *pmf_ops; +#endif +#ifdef DP_FLOW_CTL struct cdp_cfg_ops *cfg_ops; struct cdp_flowctl_ops *flowctl_ops; struct cdp_lflowctl_ops *l_flowctl_ops; + struct cdp_throttle_ops *throttle_ops; +#endif +#ifdef DP_POWER_SAVE + struct cdp_bus_ops *bus_ops; + struct cdp_tx_delay_ops *delay_ops; +#endif #ifdef IPA_OFFLOAD struct cdp_ipa_ops *ipa_ops; #endif #ifdef RECEIVE_OFFLOAD struct cdp_rx_offld_ops *rx_offld_ops; -#endif - struct cdp_bus_ops *bus_ops; - struct cdp_ocb_ops *ocb_ops; - struct cdp_peer_ops *peer_ops; - struct cdp_throttle_ops *throttle_ops; - struct cdp_mob_stats_ops *mob_stats_ops; - struct cdp_tx_delay_ops *delay_ops; - struct cdp_pmf_ops *pmf_ops; #endif #ifdef WLAN_FEATURE_PKT_CAPTURE struct cdp_pktcapture_ops *pktcapture_ops; #endif +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) + struct cdp_cfr_ops *cfr_ops; +#endif + }; #endif diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_peer_ops.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_peer_ops.h index 19604ab93af6c3907b73d2fa85f18024838dcbba..2a394392029b78ca56f297e18268c655337c29ea 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_peer_ops.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_peer_ops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019, 2021 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 @@ -29,7 +29,7 @@ /** * cdp_peer_register() - Register peer into physical device * @soc - data path soc handle - * @pdev - data path device instance + * @pdev_id - data path device instance id * @sta_desc - peer description * * Register peer into physical device @@ -38,8 +38,8 @@ * QDF_STATUS_E_NOSUPPORT not support this feature */ static inline QDF_STATUS -cdp_peer_register(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - struct ol_txrx_desc_type *sta_desc) +cdp_peer_register(ol_txrx_soc_handle soc, uint8_t pdev_id, + struct ol_txrx_desc_type *sta_desc) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -48,7 +48,8 @@ cdp_peer_register(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->peer_ops->register_peer) - return soc->ops->peer_ops->register_peer(pdev, sta_desc); + return soc->ops->peer_ops->register_peer(soc, pdev_id, + sta_desc); return QDF_STATUS_E_NOSUPPORT; } @@ -56,8 +57,8 @@ cdp_peer_register(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, /** * cdp_clear_peer() - remove peer from physical device * @soc - data path soc handle - * @pdev - data path device instance - * @sta_id - local peer id + * @pdev_id - data path device instance id + * @peer_addr - peer mac address * * remove peer from physical device * @@ -65,7 +66,8 @@ cdp_peer_register(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, * QDF_STATUS_E_NOSUPPORT not support this feature */ static inline QDF_STATUS -cdp_clear_peer(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, uint8_t sta_id) +cdp_clear_peer(ol_txrx_soc_handle soc, uint8_t pdev_id, + struct qdf_mac_addr peer_addr) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -74,7 +76,7 @@ cdp_clear_peer(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, uint8_t sta_id) } if (soc->ops->peer_ops->clear_peer) - return soc->ops->peer_ops->clear_peer(pdev, sta_id); + return soc->ops->peer_ops->clear_peer(soc, pdev_id, peer_addr); return QDF_STATUS_E_NOSUPPORT; } @@ -84,7 +86,6 @@ cdp_clear_peer(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, uint8_t sta_id) * @soc - data path soc handle * @cds_ctx - cds void context * @mac_addr - mac address for ocb self peer - * @peer_id - local peer id * * register ocb peer from physical device * @@ -93,7 +94,7 @@ cdp_clear_peer(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, uint8_t sta_id) */ static inline QDF_STATUS cdp_peer_register_ocb_peer(ol_txrx_soc_handle soc, - uint8_t *mac_addr, uint8_t *peer_id) + uint8_t *mac_addr) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -102,213 +103,94 @@ cdp_peer_register_ocb_peer(ol_txrx_soc_handle soc, } if (soc->ops->peer_ops->register_ocb_peer) - return soc->ops->peer_ops->register_ocb_peer(mac_addr, peer_id); + return soc->ops->peer_ops->register_ocb_peer(mac_addr); return QDF_STATUS_E_NOSUPPORT; } /** - * cdp_peer_remove_for_vdev() - remove peer instance from virtual interface - * @soc - data path soc handle - * @vdev - virtual interface instance - * @callback - remove done notification callback function pointer - * @callback_context - callback caller context - * @remove_last_peer - removed peer is last peer or not - * - * remove peer instance from virtual interface - * - * Return: NONE - */ -static inline void -cdp_peer_remove_for_vdev(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, ol_txrx_vdev_peer_remove_cb callback, - void *callback_context, bool remove_last_peer) -{ - if (!soc || !soc->ops || !soc->ops->peer_ops) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, - "%s invalid instance", __func__); - return; - } - - if (soc->ops->peer_ops->remove_peers_for_vdev) - return soc->ops->peer_ops->remove_peers_for_vdev( - vdev, callback, callback_context, remove_last_peer); - - return; -} - -/** - * cdp_peer_remove_for_vdev_no_lock() - remove peer instance from vdev - * @soc - data path soc handle - * @vdev - virtual interface instance - * @callback - remove done notification callback function pointer - * @callback_context - callback caller context - * - * remove peer instance from virtual interface without lock - * - * Return: NONE - */ -static inline void -cdp_peer_remove_for_vdev_no_lock(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, - ol_txrx_vdev_peer_remove_cb callback, - void *callback_context) -{ - if (!soc || !soc->ops || !soc->ops->peer_ops) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, - "%s invalid instance", __func__); - return; - } - - if (soc->ops->peer_ops->remove_peers_for_vdev_no_lock) - return soc->ops->peer_ops->remove_peers_for_vdev_no_lock( - vdev, callback, callback_context); -} - -/** - * cdp_peer_get_ref_by_addr() - Find peer by peer mac address and inc peer ref - * @soc - data path soc handle - * @pdev - data path device instance - * @peer_addr - peer mac address - * @peer_id - local peer id with target mac address - * @debug_id - debug_id to track caller - * - * To release the peer ref, cdp_peer_release_ref needs to be called. - * - * Return: peer instance void pointer - * NULL cannot find target peer - */ -static inline void -*cdp_peer_get_ref_by_addr(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint8_t *peer_addr, uint8_t *peer_id, - enum peer_debug_id_type debug_id) -{ - if (!soc || !soc->ops || !soc->ops->peer_ops) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, - "%s invalid instance", __func__); - return NULL; - } - - if (soc->ops->peer_ops->peer_get_ref_by_addr) - return soc->ops->peer_ops->peer_get_ref_by_addr( - pdev, peer_addr, peer_id, debug_id); - - return NULL; -} - -/** - * cdp_peer_release_ref() - Release peer reference - * @soc - data path soc handle - * @peer - peer pointer - * @debug_id - debug_id to track caller - * - * Return:void - */ -static inline void -cdp_peer_release_ref(ol_txrx_soc_handle soc, void *peer, - enum peer_debug_id_type debug_id) -{ - if (!soc || !soc->ops || !soc->ops->peer_ops) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, - "%s invalid instance", __func__); - return; - } - - if (soc->ops->peer_ops->peer_release_ref) - soc->ops->peer_ops->peer_release_ref(peer, debug_id); -} - -/** - * cdp_peer_find_by_addr() - Find peer by peer mac address + * cdp_find_peer_exist - Find if peer already exists * @soc - data path soc handle - * @pdev - data path device instance + * @pdev_id - data path device instance id * @peer_addr - peer mac address - * @peer_id - local peer id with target mac address * - * Find peer and local peer id by peer mac address - * - * Return: peer instance void pointer - * NULL cannot find target peer + * Return: true or false */ -static inline void -*cdp_peer_find_by_addr(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint8_t *peer_addr, uint8_t *peer_id) +static inline bool +cdp_find_peer_exist(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint8_t *peer_addr) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return NULL; + return false; } - if (soc->ops->peer_ops->find_peer_by_addr) - return soc->ops->peer_ops->find_peer_by_addr( - pdev, peer_addr, peer_id); + if (soc->ops->peer_ops->find_peer_exist) + return soc->ops->peer_ops->find_peer_exist(soc, pdev_id, + peer_addr); - return NULL; + return false; } /** - * cdp_peer_find_by_addr_and_vdev() - Find peer by peer mac address within vdev + * cdp_find_peer_exist_on_vdev - Find if duplicate peer exists + * on the given vdev * @soc - data path soc handle - * @pdev - data path device instance - * @vdev - virtual interface instance + * @vdev_id - data path virtual interface id * @peer_addr - peer mac address - * @peer_id - local peer id with target mac address * - * Find peer by peer mac address within vdev - * - * Return: peer instance void pointer - * NULL cannot find target peer + * Return: true or false */ -static inline void -*cdp_peer_find_by_addr_and_vdev(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - struct cdp_vdev *vdev, uint8_t *peer_addr, uint8_t *peer_id) +static inline bool +cdp_find_peer_exist_on_vdev(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_addr) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return NULL; + return false; } - if (soc->ops->peer_ops->find_peer_by_addr_and_vdev) - return soc->ops->peer_ops->find_peer_by_addr_and_vdev( - pdev, vdev, peer_addr, peer_id); + if (soc->ops->peer_ops->find_peer_exist_on_vdev) + return soc->ops->peer_ops->find_peer_exist_on_vdev(soc, vdev_id, + peer_addr); - return NULL; + return false; } /** - * cdp_peer_find_by_local_id() - Find peer by local peer id + * cdp_find_peer_exist_on_other_vdev - Find if duplicate peer exists + * on other than the given vdev * @soc - data path soc handle - * @pdev - data path device instance - * @local_peer_id - local peer id want to find - * - * Find peer by local peer id within physical device + * @vdev_id - data path virtual interface id + * @peer_addr - peer mac address + * @max_bssid - max number of bssids * - * Return: peer instance void pointer - * NULL cannot find target peer + * Return: true or false */ -static inline void -*cdp_peer_find_by_local_id(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint8_t local_peer_id) +static inline bool +cdp_find_peer_exist_on_other_vdev(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_addr, uint16_t max_bssid) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return NULL; + return false; } - if (soc->ops->peer_ops->peer_find_by_local_id) - return soc->ops->peer_ops->peer_find_by_local_id( - pdev, local_peer_id); + if (soc->ops->peer_ops->find_peer_exist_on_other_vdev) + return soc->ops->peer_ops->find_peer_exist_on_other_vdev( + soc, vdev_id, + peer_addr, + max_bssid); - return NULL; + return false; } /** * cdp_peer_state_update() - update peer local state * @soc - data path soc handle - * @pdev - data path device instance * @peer_addr - peer mac address * @state - new peer local state * @@ -318,8 +200,8 @@ static inline void * QDF_STATUS_E_NOSUPPORT not support this feature */ static inline QDF_STATUS -cdp_peer_state_update(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint8_t *peer_addr, enum ol_txrx_peer_state state) +cdp_peer_state_update(ol_txrx_soc_handle soc, uint8_t *peer_addr, + enum ol_txrx_peer_state state) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -328,8 +210,8 @@ cdp_peer_state_update(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->peer_ops->peer_state_update) - return soc->ops->peer_ops->peer_state_update( - pdev, peer_addr, state); + return soc->ops->peer_ops->peer_state_update(soc, peer_addr, + state); return QDF_STATUS_E_NOSUPPORT; } @@ -337,14 +219,15 @@ cdp_peer_state_update(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, /** * cdp_peer_state_get() - Get local peer state * @soc - data path soc handle - * @peer - peer instance + * @vdev_id - virtual interface id + * @peer_mac - peer mac addr * * Get local peer state * * Return: peer status */ static inline int -cdp_peer_state_get(ol_txrx_soc_handle soc, void *peer) +cdp_peer_state_get(ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -353,40 +236,16 @@ cdp_peer_state_get(ol_txrx_soc_handle soc, void *peer) } if (soc->ops->peer_ops->get_peer_state) - return soc->ops->peer_ops->get_peer_state(peer); + return soc->ops->peer_ops->get_peer_state(soc, vdev_id, + peer_mac); return 0; } -/** - * cdp_peer_get_local_peer_id() - Find local peer id within peer instance - * @soc - data path soc handle - * @peer - peer instance - * - * Find local peer id within peer instance - * - * Return: local peer id - * HTT_INVALID_PEER Invalid peer - */ -static inline uint16_t -cdp_peer_get_local_peer_id(ol_txrx_soc_handle soc, void *peer) -{ - if (!soc || !soc->ops || !soc->ops->peer_ops) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, - "%s invalid instance", __func__); - return HTT_INVALID_PEER; - } - - if (soc->ops->peer_ops->local_peer_id) - return soc->ops->peer_ops->local_peer_id(peer); - - return HTT_INVALID_PEER; -} - /** * cdp_peer_get_vdevid() - Get virtual interface id which peer registered * @soc - data path soc handle - * @peer - peer instance + * @peer_mac - peer mac address * @vdev_id - virtual interface id which peer registered * * Get virtual interface id which peer registered @@ -395,7 +254,8 @@ cdp_peer_get_local_peer_id(ol_txrx_soc_handle soc, void *peer) * QDF_STATUS_E_NOSUPPORT not support this feature */ static inline QDF_STATUS -cdp_peer_get_vdevid(ol_txrx_soc_handle soc, void *peer, uint8_t *vdev_id) +cdp_peer_get_vdevid(ol_txrx_soc_handle soc, + uint8_t *peer_mac, uint8_t *vdev_id) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -404,7 +264,7 @@ cdp_peer_get_vdevid(ol_txrx_soc_handle soc, void *peer, uint8_t *vdev_id) } if (soc->ops->peer_ops->get_vdevid) - return soc->ops->peer_ops->get_vdevid(peer, vdev_id); + return soc->ops->peer_ops->get_vdevid(soc, peer_mac, vdev_id); return QDF_STATUS_E_NOSUPPORT; } @@ -413,7 +273,7 @@ cdp_peer_get_vdevid(ol_txrx_soc_handle soc, void *peer, uint8_t *vdev_id) * cdp_peer_get_vdev_by_sta_id() - Get vdev instance by local peer id * @soc - data path soc handle * @pdev - data path device instance - * @sta_id - local peer id + * @peer_addr - peer mac address * * Get virtual interface id by local peer id * @@ -421,8 +281,8 @@ cdp_peer_get_vdevid(ol_txrx_soc_handle soc, void *peer, uint8_t *vdev_id) * NULL in case cannot find */ static inline struct cdp_vdev -*cdp_peer_get_vdev_by_sta_id(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint8_t sta_id) +*cdp_peer_get_vdev_by_peer_addr(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, + struct qdf_mac_addr peer_addr) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -430,8 +290,9 @@ static inline struct cdp_vdev return NULL; } - if (soc->ops->peer_ops->get_vdev_by_sta_id) - return soc->ops->peer_ops->get_vdev_by_sta_id(pdev, sta_id); + if (soc->ops->peer_ops->get_vdev_by_peer_addr) + return soc->ops->peer_ops->get_vdev_by_peer_addr(pdev, + peer_addr); return NULL; } @@ -461,35 +322,10 @@ static inline uint8_t return NULL; } -/** - * cdp_peer_get_vdev() - Get virtual interface instance which peer belongs - * @soc - data path soc handle - * @peer - peer instance - * - * Get virtual interface instance which peer belongs - * - * Return: virtual interface instance pointer - * NULL in case cannot find - */ -static inline struct cdp_vdev -*cdp_peer_get_vdev(ol_txrx_soc_handle soc, void *peer) -{ - if (!soc || !soc->ops || !soc->ops->peer_ops) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, - "%s invalid instance", __func__); - return NULL; - } - - if (soc->ops->peer_ops->get_vdev_for_peer) - return soc->ops->peer_ops->get_vdev_for_peer(peer); - - return NULL; -} - /** * cdp_peer_update_ibss_add_peer_num_of_vdev() - update number of peer * @soc - data path soc handle - * @vdev - virtual interface instance + * @vdev_id - virtual interface instance id * @peer_num_delta - number of peer should be updated * * update number of peer @@ -499,7 +335,8 @@ static inline struct cdp_vdev */ static inline int16_t cdp_peer_update_ibss_add_peer_num_of_vdev(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, int16_t peer_num_delta) + uint8_t vdev_id, + int16_t peer_num_delta) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -509,7 +346,8 @@ cdp_peer_update_ibss_add_peer_num_of_vdev(ol_txrx_soc_handle soc, if (soc->ops->peer_ops->update_ibss_add_peer_num_of_vdev) return soc->ops->peer_ops->update_ibss_add_peer_num_of_vdev( - vdev, peer_num_delta); + soc, vdev_id, + peer_num_delta); return 0; } @@ -517,7 +355,7 @@ cdp_peer_update_ibss_add_peer_num_of_vdev(ol_txrx_soc_handle soc, /** * cdp_peer_copy_mac_addr_raw() - copy peer mac address * @soc - data path soc handle - * @vdev - virtual interface instance + * @vdev_id - virtual interface instance id * @bss_addr - mac address should be copied * * copy peer mac address @@ -526,7 +364,7 @@ cdp_peer_update_ibss_add_peer_num_of_vdev(ol_txrx_soc_handle soc, */ static inline void cdp_peer_copy_mac_addr_raw(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, uint8_t *bss_addr) + uint8_t vdev_id, uint8_t *bss_addr) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -535,7 +373,8 @@ cdp_peer_copy_mac_addr_raw(ol_txrx_soc_handle soc, } if (soc->ops->peer_ops->copy_mac_addr_raw) - return soc->ops->peer_ops->copy_mac_addr_raw(vdev, bss_addr); + return soc->ops->peer_ops->copy_mac_addr_raw(soc, vdev_id, + bss_addr); return; } @@ -543,17 +382,16 @@ cdp_peer_copy_mac_addr_raw(ol_txrx_soc_handle soc, /** * cdp_peer_add_last_real_peer() - Add peer with last peer marking * @soc - data path soc handle - * @pdev - data path device instance - * @vdev - virtual interface instance - * @peer_id - local peer id + * @pdev_id - data path device instance id + * @vdev_id - virtual interface instance id * * copy peer mac address * * Return: none */ static inline void -cdp_peer_add_last_real_peer(ol_txrx_soc_handle soc, - struct cdp_pdev *pdev, struct cdp_vdev *vdev, uint8_t *peer_id) +cdp_peer_add_last_real_peer(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint8_t vdev_id) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -562,15 +400,16 @@ cdp_peer_add_last_real_peer(ol_txrx_soc_handle soc, } if (soc->ops->peer_ops->add_last_real_peer) - return soc->ops->peer_ops->add_last_real_peer( - pdev, vdev, peer_id); + return soc->ops->peer_ops->add_last_real_peer(soc, pdev_id, + vdev_id); return; } /** * cdp_peer_is_vdev_restore_last_peer() - restore last peer * @soc - data path soc handle - * @peer - peer instance pointer + * @vdev_id - virtual interface id + * @peer_mac - peer mac address * * restore last peer * @@ -578,7 +417,8 @@ cdp_peer_add_last_real_peer(ol_txrx_soc_handle soc, * fasle, restore fail */ static inline bool -cdp_peer_is_vdev_restore_last_peer(ol_txrx_soc_handle soc, void *peer) +cdp_peer_is_vdev_restore_last_peer(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -587,7 +427,9 @@ cdp_peer_is_vdev_restore_last_peer(ol_txrx_soc_handle soc, void *peer) } if (soc->ops->peer_ops->is_vdev_restore_last_peer) - return soc->ops->peer_ops->is_vdev_restore_last_peer(peer); + return soc->ops->peer_ops->is_vdev_restore_last_peer(soc, + vdev_id, + peer_mac); return false; } @@ -595,9 +437,8 @@ cdp_peer_is_vdev_restore_last_peer(ol_txrx_soc_handle soc, void *peer) /** * cdp_peer_update_last_real_peer() - update last real peer * @soc - data path soc handle - * @pdev - data path device instance - * @peer - peer instance pointer - * @peer_id - local peer id + * @pdev_id - data path device instance id + * @vdev_id - virtual interface id * @restore_last_peer - restore last peer or not * * update last real peer @@ -605,8 +446,8 @@ cdp_peer_is_vdev_restore_last_peer(ol_txrx_soc_handle soc, void *peer) * Return: none */ static inline void -cdp_peer_update_last_real_peer(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - void *vdev, uint8_t *peer_id, bool restore_last_peer) +cdp_peer_update_last_real_peer(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint8_t vdev_id, bool restore_last_peer) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -615,8 +456,9 @@ cdp_peer_update_last_real_peer(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->peer_ops->update_last_real_peer) - return soc->ops->peer_ops->update_last_real_peer(pdev, vdev, - peer_id, restore_last_peer); + return soc->ops->peer_ops->update_last_real_peer( + soc, pdev_id, vdev_id, + restore_last_peer); return; } @@ -633,7 +475,8 @@ cdp_peer_update_last_real_peer(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, * Return: None */ static inline void cdp_peer_detach_force_delete(ol_txrx_soc_handle soc, - void *peer) + uint8_t vdev_id, + uint8_t *peer_mac) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -642,7 +485,9 @@ static inline void cdp_peer_detach_force_delete(ol_txrx_soc_handle soc, } if (soc->ops->peer_ops->peer_detach_force_delete) - return soc->ops->peer_ops->peer_detach_force_delete(peer); + return soc->ops->peer_ops->peer_detach_force_delete(soc, + vdev_id, + peer_mac); return; } @@ -674,18 +519,66 @@ is_cdp_peer_detach_force_delete_supported(ol_txrx_soc_handle soc) return false; } +/* + * cdp_peer_set_peer_as_tdls() - To set peer as tdls peer + * @soc: pointer to SOC handle + * @vdev_id: virtual interface id + * @peer_mac: peer mac address + * @var: true or false + * + * Return: void + */ +static inline void +cdp_peer_set_peer_as_tdls(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac, bool val) +{ + if (!soc || !soc->ops || !soc->ops->peer_ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return; + } + + if (soc->ops->peer_ops->set_peer_as_tdls_peer) + soc->ops->peer_ops->set_peer_as_tdls_peer(soc, vdev_id, + peer_mac, val); +} + +/** + * cdp_peer_set_tdls_offchan_enabled() - Set tdls offchan operation as enabled + * @soc: pointer to SOC handle + * @vdev_id: virtual interface id + * @peer_mac: peer mac address + * @val: true or false + * + * update tdls_offchan_enabled + * + * Return: none + */ +static inline void +cdp_peer_set_tdls_offchan_enabled(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint8_t *peer_mac, bool val) +{ + if (!soc || !soc->ops || !soc->ops->peer_ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return; + } + + if (soc->ops->peer_ops->set_tdls_offchan_enabled) + soc->ops->peer_ops->set_tdls_offchan_enabled(soc, vdev_id, + peer_mac, val); +} + /** * cdp_peer_flush_frags() - Flush frags on peer * @soc - data path soc handle - * @pdev - data path device instance * @vdev_id - virtual interface id * @peer_mac - peer mac addr * * Return: None */ static inline void -cdp_peer_flush_frags(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint8_t vdev_id, uint8_t *peer_mac) +cdp_peer_flush_frags(ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac) { if (!soc || !soc->ops || !soc->ops->peer_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -694,6 +587,6 @@ cdp_peer_flush_frags(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->peer_ops->peer_flush_frags) - soc->ops->peer_ops->peer_flush_frags(pdev, vdev_id, peer_mac); + soc->ops->peer_ops->peer_flush_frags(soc, vdev_id, peer_mac); } #endif /* _CDP_TXRX_PEER_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_pflow.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_pflow.h index 1a7ea9038aa702cb7e3008f1b34dd21e623f2bb2..ecb2bddc91d8ae195a40f8a9f7ecb134e04f26df 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_pflow.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_pflow.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, 2019 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 @@ -29,7 +29,7 @@ #include "cdp_txrx_handle.h" static inline uint32_t cdp_pflow_update_pdev_params - (ol_txrx_soc_handle soc, struct cdp_pdev *pdev, + (ol_txrx_soc_handle soc, uint8_t pdev_id, enum _ol_ath_param_t param, uint32_t val, void *ctx) { if (!soc || !soc->ops) { @@ -44,6 +44,6 @@ static inline uint32_t cdp_pflow_update_pdev_params return 0; return soc->ops->pflow_ops->pflow_update_pdev_params - (pdev, param, val, ctx); + (soc, pdev_id, param, val, ctx); } #endif diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_pmf.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_pmf.h index 48f644bbd0fc640e41a96385a3d1897cd1a6b2e9..c869eac2b70cc445d703cc5eb03aa2242e6257cc 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_pmf.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_pmf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016, 2019 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 @@ -22,7 +22,8 @@ /** * cdp_get_pn_info() - Returns pn info from peer * @soc - data path soc handle - * @peer: handle to peer + * @peer_mac: peer mac address + * @vdev_id: virtual device/interface id * @last_pn_valid: return last_rmf_pn_valid value from peer. * @last_pn: return last_rmf_pn value from peer. * @rmf_pn_replays: return rmf_pn_replays value from peer. @@ -30,8 +31,9 @@ * Return: NONE */ static inline void -cdp_get_pn_info(ol_txrx_soc_handle soc, void *peer, uint8_t **last_pn_valid, - uint64_t **last_pn, uint32_t **rmf_pn_replays) +cdp_get_pn_info(ol_txrx_soc_handle soc, uint8_t *peer_mac, uint8_t vdev_id, + uint8_t **last_pn_valid, uint64_t **last_pn, + uint32_t **rmf_pn_replays) { if (!soc || !soc->ops || !soc->ops->pmf_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -40,8 +42,9 @@ cdp_get_pn_info(ol_txrx_soc_handle soc, void *peer, uint8_t **last_pn_valid, } if (soc->ops->pmf_ops->get_pn_info) - return soc->ops->pmf_ops->get_pn_info( - peer, last_pn_valid, last_pn, rmf_pn_replays); + return soc->ops->pmf_ops->get_pn_info(soc, peer_mac, vdev_id, + last_pn_valid, + last_pn, rmf_pn_replays); return; } diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_raw.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_raw.h index a15e37a3713ea144cf87a2ab8593aa82a546ea9c..0eb40e6a0efc3640f44519299271a9a9b557e3c6 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_raw.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_raw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, 2019 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 @@ -28,7 +28,7 @@ #include "cdp_txrx_ops.h" /* TODO: adf need to be replaced with qdf */ static inline int cdp_get_nwifi_mode(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev) + uint8_t vdev_id) { if (!soc || !soc->ops) { QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, @@ -41,7 +41,7 @@ static inline int cdp_get_nwifi_mode(ol_txrx_soc_handle soc, !soc->ops->raw_ops->txrx_get_nwifi_mode) return 0; - return soc->ops->raw_ops->txrx_get_nwifi_mode(vdev); + return soc->ops->raw_ops->txrx_get_nwifi_mode(soc, vdev_id); } /** @@ -49,15 +49,16 @@ static inline int cdp_get_nwifi_mode(ol_txrx_soc_handle soc, * @details: Finds the ast entry i.e 4th address for the packet based on the * details in the netbuf. * - * @param vdev - the data virtual device object + * @param soc - soc handle + * @param vdev_id - id of the data virtual device object * @param pnbuf - pointer to nbuf * @param raw_ast - pointer to fill ast information * * @return - 0 on success, -1 on error, 1 if more nbufs need to be consumed. */ -static inline void -cdp_rawsim_get_astentry (ol_txrx_soc_handle soc, struct cdp_vdev *vdev, +static inline QDF_STATUS +cdp_rawsim_get_astentry(ol_txrx_soc_handle soc, uint8_t vdev_id, qdf_nbuf_t *pnbuf, struct cdp_raw_ast *raw_ast) { @@ -65,14 +66,15 @@ cdp_rawsim_get_astentry (ol_txrx_soc_handle soc, struct cdp_vdev *vdev, QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, "%s: Invalid Instance", __func__); QDF_BUG(0); - return; + return QDF_STATUS_E_FAILURE; } if (!soc->ops->raw_ops || !soc->ops->raw_ops->rsim_get_astentry) - return; + return QDF_STATUS_E_FAILURE; - soc->ops->raw_ops->rsim_get_astentry(vdev, pnbuf, raw_ast); + return soc->ops->raw_ops->rsim_get_astentry(soc, vdev_id, + pnbuf, raw_ast); } #endif diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_stats.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_stats.h index 69814a071e22dd0a16d25dca813065b2132388d8..c912591248ba4b336523918ea5fe74599e6bfd31 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_stats.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_stats.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017,2019 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,22 +25,22 @@ #define _CDP_TXRX_STATS_H_ #include -static inline void -cdp_clear_stats(ol_txrx_soc_handle soc, uint16_t bitmap) +static inline QDF_STATUS +cdp_clear_stats(ol_txrx_soc_handle soc, uint8_t pdev_id, uint8_t bitmap) { 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_E_INVAL; } if (!soc->ops->mob_stats_ops || !soc->ops->mob_stats_ops->clear_stats) - return; + return QDF_STATUS_E_INVAL; - soc->ops->mob_stats_ops->clear_stats(bitmap); + return soc->ops->mob_stats_ops->clear_stats(soc, pdev_id, bitmap); } static inline int diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_stats_struct.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_stats_struct.h index 2036ad14bbfeccd53c1f5a7bd3f238d9b1553411..1612a3513687cc7369a3c25e903306e54315fc0a 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_stats_struct.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_stats_struct.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -23,9 +23,9 @@ */ #ifndef _CDP_TXRX_STATS_STRUCT_H_ #define _CDP_TXRX_STATS_STRUCT_H_ -#ifdef CONFIG_MCL -#include -#endif + +#include + #define TXRX_STATS_LEVEL_OFF 0 #define TXRX_STATS_LEVEL_BASIC 1 #define TXRX_STATS_LEVEL_FULL 2 @@ -73,6 +73,8 @@ #define CDP_MAX_RX_RINGS 4 /* max rx rings */ #define CDP_MAX_TX_COMP_RINGS 3 /* max tx completion rings */ +#define CDP_MAX_TX_TQM_STATUS 9 /* max tx tqm completion status */ +#define CDP_MAX_TX_HTT_STATUS 7 /* max tx htt completion status */ /* TID level VoW stats macros * to add and get stats @@ -114,7 +116,84 @@ #define INVALID_RSSI 255 +#define CDP_RSSI_MULTIPLIER BIT(8) +#define CDP_RSSI_MUL(x, mul) ((x) * (mul)) +#define CDP_RSSI_RND(x, mul) ((((x) % (mul)) >= ((mul) / 2)) ?\ + ((x) + ((mul) - 1)) / (mul) : (x) / (mul)) + +#define CDP_RSSI_OUT(x) (CDP_RSSI_RND((x), CDP_RSSI_MULTIPLIER)) +#define CDP_RSSI_IN(x) (CDP_RSSI_MUL((x), CDP_RSSI_MULTIPLIER)) +#define CDP_RSSI_AVG(x, y) ((((x) << 2) + (y) - (x)) >> 2) + +#define CDP_RSSI_UPDATE_AVG(x, y) x = CDP_RSSI_AVG((x), CDP_RSSI_IN((y))) + +/*Max SU EVM count */ +#define DP_RX_MAX_SU_EVM_COUNT 32 + #define WDI_EVENT_BASE 0x100 + +#define CDP_TXRX_RATECODE_MCS_MASK 0xF +#define CDP_TXRX_RATECODE_NSS_MASK 0x3 +#define CDP_TXRX_RATECODE_NSS_LSB 4 +#define CDP_TXRX_RATECODE_PREM_MASK 0x3 +#define CDP_TXRX_RATECODE_PREM_LSB 6 + +/* Below BW_GAIN should be added to the SNR value of every ppdu based on the + * bandwidth. This table is obtained from HALPHY. + * BW BW_Gain + * 20 0 + * 40 3dBm + * 80 6dBm + * 160/80P80 9dBm + */ + +#define PKT_BW_GAIN_20MHZ 0 +#define PKT_BW_GAIN_40MHZ 3 +#define PKT_BW_GAIN_80MHZ 6 +#define PKT_BW_GAIN_160MHZ 9 + +/* + * cdp_tx_transmit_type: Transmit type index + * SU: SU Transmit type index + * MU_MIMO: MU_MIMO Transmit type index + * MU_OFDMA: MU_OFDMA Transmit type index + * MU_MIMO_OFDMA: MU MIMO OFDMA Transmit type index + */ +enum cdp_tx_transmit_type { + SU = 0, + MU_MIMO, + MU_OFDMA, + MU_MIMO_OFDMA, +}; + +/* + * cdp_ru_index: Different RU index + * + * RU_26_INDEX : 26-tone Resource Unit index + * RU_52_INDEX : 52-tone Resource Unit index + * RU_106_INDEX: 106-tone Resource Unit index + * RU_242_INDEX: 242-tone Resource Unit index + * RU_484_INDEX: 484-tone Resource Unit index + * RU_996_INDEX: 996-tone Resource Unit index + */ +enum cdp_ru_index { + RU_26_INDEX = 0, + RU_52_INDEX, + RU_106_INDEX, + RU_242_INDEX, + RU_484_INDEX, + RU_996_INDEX, +}; + +#ifdef FEATURE_TSO_STATS +/* Number of TSO Packet Statistics captured */ +#define CDP_MAX_TSO_PACKETS 5 +/* Information for Number of Segments for a TSO Packet captured */ +#define CDP_MAX_TSO_SEGMENTS 2 +/* Information for Number of Fragments for a TSO Segment captured */ +#define CDP_MAX_TSO_FRAGMENTS 6 +#endif /* FEATURE_TSO_STATS */ + /* Different Packet Types */ enum cdp_packet_type { DOT11_A = 0, @@ -125,6 +204,18 @@ enum cdp_packet_type { DOT11_MAX = 5, }; +/* + * cdp_mu_packet_type: MU Rx type index + * RX_TYPE_MU_MIMO: MU MIMO Rx type index + * RX_TYPE_MU_OFDMA: MU OFDMA Rx type index + * MU_MIMO_OFDMA: MU Rx MAX type index + */ +enum cdp_mu_packet_type { + RX_TYPE_MU_MIMO = 0, + RX_TYPE_MU_OFDMA = 1, + RX_TYPE_MU_MAX = 2, +}; + enum WDI_EVENT { WDI_EVENT_TX_STATUS = WDI_EVENT_BASE, WDI_EVENT_OFFLOAD_ALL, @@ -205,6 +296,78 @@ struct cdp_tidq_stats { uint32_t stats[TIDQ_STATS_MAX]; }; +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) +/** + * struct cdp_rx_ppdu_cfr_info - struct for storing ppdu info extracted from HW + * TLVs, this will be used for CFR correlation + * + * @bb_captured_channel : Set by RXPCU when MACRX_FREEZE_CAPTURE_CHANNEL TLV is + * sent to PHY, SW checks it to correlate current PPDU TLVs with uploaded + * channel information. + * + * @bb_captured_timeout : Set by RxPCU to indicate channel capture condition is + * met, but MACRX_FREEZE_CAPTURE_CHANNEL is not sent to PHY due to AST delay, + * which means the rx_frame_falling edge to FREEZE TLV ready time exceeds + * the threshold time defined by RXPCU register FREEZE_TLV_DELAY_CNT_THRESH. + * Bb_captured_reason is still valid in this case. + * + * @bb_captured_reason : Copy capture_reason of MACRX_FREEZE_CAPTURE_CHANNEL + * TLV to here for FW usage. Valid when bb_captured_channel or + * bb_captured_timeout is set. + * + * + * + * + * + * + * + * + * @rx_location_info_valid: Indicates whether CFR DMA address in the PPDU TLV + * is valid + * + * + * + * + * @chan_capture_status : capture status reported by ucode + * a. CAPTURE_IDLE: FW has disabled "REPETITIVE_CHE_CAPTURE_CTRL" + * b. CAPTURE_BUSY: previous PPDU’s channel capture upload DMA ongoing. (Note + * that this upload is triggered after receiving freeze_channel_capture TLV + * after last PPDU is rx) + * c. CAPTURE_ACTIVE: channel capture is enabled and no previous channel + * capture ongoing + * d. CAPTURE_NO_BUFFER: next buffer in IPC ring not available + * + * @rtt_che_buffer_pointer_high8 : The high 8 bits of the 40 bits pointer to + * external RTT channel information buffer + * + * @rtt_che_buffer_pointer_low32 : The low 32 bits of the 40 bits pointer to + * external RTT channel information buffer + * + */ + +struct cdp_rx_ppdu_cfr_info { + bool bb_captured_channel; + bool bb_captured_timeout; + uint8_t bb_captured_reason; + bool rx_location_info_valid; + uint8_t chan_capture_status; + uint8_t rtt_che_buffer_pointer_high8; + uint32_t rtt_che_buffer_pointer_low32; +}; +#endif +/* + * struct cdp_rx_su_evm_info: Rx evm info + * @number_of_symbols: number of symbols + * @nss_count: number of spatial streams + * @pilot_count: number of pilot count + */ +struct cdp_rx_su_evm_info { + uint16_t number_of_symbols; + uint8_t nss_count; + uint8_t pilot_count; + uint32_t pilot_evm[DP_RX_MAX_SU_EVM_COUNT]; +}; + /* * cdp_delay_stats_mode: Different types of delay statistics * @@ -294,6 +457,8 @@ struct cdp_delay_stats { * @success_cnt: total successful transmit count * @comp_fail_cnt: firmware drop found in tx completion path * @swdrop_cnt: software drop in tx path + * @tqm_status_cnt: TQM completion status count + * @htt_status_cnt: HTT completion status count */ struct cdp_tid_tx_stats { struct cdp_delay_stats swq_delay; @@ -302,6 +467,8 @@ struct cdp_tid_tx_stats { uint64_t success_cnt; uint64_t comp_fail_cnt; uint64_t swdrop_cnt[TX_MAX_DROP]; + uint64_t tqm_status_cnt[CDP_MAX_TX_TQM_STATUS]; + uint64_t htt_status_cnt[CDP_MAX_TX_HTT_STATUS]; }; /* @@ -358,14 +525,183 @@ struct cdp_pkt_type { uint32_t mcs_count[MAX_MCS]; }; +/* + * struct cdp_rx_mu - Rx MU Stats + * @ppdu_nss[SS_COUNT]: Packet Count in spatial streams + * @mpdu_cnt_fcs_ok: Rx success mpdu count + * @mpdu_cnt_fcs_err: Rx fail mpdu count + * @cdp_pkt_type: counter array for each MCS index + */ +struct cdp_rx_mu { + uint32_t ppdu_nss[SS_COUNT]; + uint32_t mpdu_cnt_fcs_ok; + uint32_t mpdu_cnt_fcs_err; + struct cdp_pkt_type ppdu; +}; + +/* struct cdp_tx_pkt_info - tx packet info + * num_msdu - successful msdu + * num_mpdu - successful mpdu from compltn common + * mpdu_tried - mpdu tried + * + * tx packet info counter field for mpdu success/tried and msdu + */ +struct cdp_tx_pkt_info { + uint32_t num_msdu; + uint32_t num_mpdu; + uint32_t mpdu_tried; +}; + +#ifdef FEATURE_TSO_STATS +/** + * struct cdp_tso_seg_histogram - Segment histogram for TCP Packets + * @segs_1: packets with single segments + * @segs_2_5: packets with 2-5 segments + * @segs_6_10: packets with 6-10 segments + * @segs_11_15: packets with 11-15 segments + * @segs_16_20: packets with 16-20 segments + * @segs_20_plus: packets with 20 plus segments + */ +struct cdp_tso_seg_histogram { + uint64_t segs_1; + uint64_t segs_2_5; + uint64_t segs_6_10; + uint64_t segs_11_15; + uint64_t segs_16_20; + uint64_t segs_20_plus; +}; + +/** + * struct cdp_tso_packet_info - Stats for TSO segments within a TSO packet + * @tso_seg: TSO Segment information + * @num_seg: Number of segments + * @tso_packet_len: Size of the tso packet + * @tso_seg_idx: segment number + */ +struct cdp_tso_packet_info { + struct qdf_tso_seg_t tso_seg[CDP_MAX_TSO_SEGMENTS]; + uint8_t num_seg; + size_t tso_packet_len; + uint32_t tso_seg_idx; +}; + +/** + * struct cdp_tso_info - stats for tso packets + * @tso_packet_info: TSO packet information + */ +struct cdp_tso_info { + struct cdp_tso_packet_info tso_packet_info[CDP_MAX_TSO_PACKETS]; +}; +#endif /* FEATURE_TSO_STATS */ + +/** + * struct cdp_tso_stats - TSO stats information + * @num_tso_pkts: Total number of TSO Packets + * @tso_comp: Total tso packet completions + * @dropped_host: TSO packets dropped by host + * @tso_no_mem_dropped: TSO packets dropped by host due to descriptor + unavailablity + * @dropped_target: TSO packets_dropped by target + * @tso_info: Per TSO packet counters + * @seg_histogram: TSO histogram stats + */ +struct cdp_tso_stats { + struct cdp_pkt_info num_tso_pkts; + uint32_t tso_comp; + struct cdp_pkt_info dropped_host; + struct cdp_pkt_info tso_no_mem_dropped; + uint32_t dropped_target; +#ifdef FEATURE_TSO_STATS + struct cdp_tso_info tso_info; + struct cdp_tso_seg_histogram seg_histogram; +#endif /* FEATURE_TSO_STATS */ +}; + +#define CDP_PEER_STATS_START 0 + +enum cdp_peer_stats_type { + cdp_peer_stats_min = CDP_PEER_STATS_START, + + /* Tx types */ + cdp_peer_tx_ucast = cdp_peer_stats_min, + cdp_peer_tx_mcast, + cdp_peer_tx_rate, + cdp_peer_tx_last_tx_rate, + cdp_peer_tx_inactive_time, + cdp_peer_tx_ratecode, + cdp_peer_tx_flags, + cdp_peer_tx_power, + + /* Rx types */ + cdp_peer_rx_rate, + cdp_peer_rx_last_rx_rate, + cdp_peer_rx_ratecode, + cdp_peer_rx_ucast, + cdp_peer_rx_flags, + cdp_peer_rx_avg_rssi, + cdp_peer_stats_max, +}; + +/* + * The max size of cdp_peer_stats_param_t is limited to 16 bytes. + * If the buffer size is exceeding this size limit, + * dp_txrx_get_peer_stats is to be used instead. + */ +typedef union cdp_peer_stats_buf { + /* Tx types */ + struct cdp_pkt_info tx_ucast; + struct cdp_pkt_info tx_mcast; + uint32_t tx_rate; + uint32_t last_tx_rate; + uint32_t tx_inactive_time; + uint32_t tx_flags; + uint32_t tx_power; + uint16_t tx_ratecode; + + /* Rx types */ + struct cdp_pkt_info rx_ucast; + uint32_t rx_rate; + uint32_t last_rx_rate; + uint32_t rx_ratecode; + uint32_t rx_flags; + uint32_t rx_avg_rssi; +} cdp_peer_stats_param_t; /* Max union size 16 bytes */ + +/** + * enum cdp_protocol_trace - Protocols supported by per-peer protocol trace + * @CDP_TRACE_ICMP: ICMP packets + * @CDP_TRACE_EAP: EAPOL packets + * @CDP_TRACE_ARP: ARP packets + * + * Enumeration of all protocols supported by per-peer protocol trace feature + */ +enum cdp_protocol_trace { + CDP_TRACE_ICMP, + CDP_TRACE_EAP, + CDP_TRACE_ARP, + CDP_TRACE_MAX +}; + +/** + * struct protocol_trace_count - type of count on per-peer protocol trace + * @egress_cnt: how many packets go out of host driver + * @ingress_cnt: how many packets come into the host driver + * + * Type of count on per-peer protocol trace + */ +struct protocol_trace_count { + uint16_t egress_cnt; + uint16_t ingress_cnt; +}; /* struct cdp_tx_stats - tx stats * @cdp_pkt_info comp_pkt: Pkt Info for which completions were received * @cdp_pkt_info ucast: Unicast Packet Count * @cdp_pkt_info mcast: Multicast Packet Count * @cdp_pkt_info bcast: Broadcast Packet Count * @cdp_pkt_info nawds_mcast: NAWDS Multicast Packet Count - * @nawds_mcast_drop: NAWDS Multicast Drop Count * @cdp_pkt_info tx_success: Successful Tx Packets + * @nawds_mcast_drop: NAWDS Multicast Drop Count + * @protocol_trace_cnt: per-peer protocol counter * @tx_failed: Total Tx failure * @ofdma: Total Packets as ofdma * @stbc: Packets in STBC @@ -391,6 +727,7 @@ struct cdp_pkt_type { * @bw[MAX_BW]: Packet Count for different bandwidths * @wme_ac_type[WME_AC_MAX]: Wireless Multimedia type Count * @excess_retries_per_ac[WME_AC_MAX]: Wireless Multimedia type Count + * @dot11_tx_pkts: dot11 tx packets * @fw_rem: Discarded by firmware * @fw_rem_notx: firmware_discard_untransmitted * @fw_rem_tx: firmware_discard_transmitted @@ -399,7 +736,6 @@ struct cdp_pkt_type { * @fw_reason2: discarded by firmware reason 2 * @fw_reason3: discarded by firmware reason 3 * @mcs_count: MCS Count - * @dot11_tx_pkts: dot11 tx packets * @an_tx_cnt: ald tx count * @an_tx_rates_used: ald rx rate used * @an_tx_bytes: ald tx bytes @@ -412,10 +748,10 @@ struct cdp_pkt_type { * @ald_ac_excretries: #pkts dropped after excessive retries per node per AC * @rssi_chain: rssi chain * @inactive_time: inactive time in secs - * @tx_ratecode: Tx rate code of last frame * @tx_flags: tx flags * @tx_power: Tx power latest * @is_tx_no_ack: no ack received + * @tx_ratecode: Tx rate code of last frame * @is_tx_nodefkey: tx failed 'cuz no defkey * @is_tx_noheadroom: tx failed 'cuz no space * @is_crypto_enmicfail: @@ -427,11 +763,11 @@ struct cdp_pkt_type { * @failed_retry_count: packets failed due to retry above 802.11 retry limit * @retry_count: packets successfully send after one or more retry * @multiple_retry_count: packets successfully sent after more than one retry - * @transmit_type: tx transmit type + * @transmit_type: pkt info for tx transmit type * @mu_group_id: mumimo mu group id * @ru_start: RU start index * @ru_tones: RU tones size - * @ru_loc: RU location 26/ 52/ 106/ 242/ 484 counter + * @ru_loc: pkt info for RU location 26/ 52/ 106/ 242/ 484 counter * @num_ppdu_cookie_valid : Number of comp received with valid ppdu cookie */ struct cdp_tx_stats { @@ -440,8 +776,11 @@ struct cdp_tx_stats { struct cdp_pkt_info mcast; struct cdp_pkt_info bcast; struct cdp_pkt_info nawds_mcast; - uint32_t nawds_mcast_drop; +#ifdef VDEV_PEER_PROTOCOL_COUNT + struct protocol_trace_count protocol_trace_cnt[CDP_TRACE_MAX]; +#endif struct cdp_pkt_info tx_success; + uint32_t nawds_mcast_drop; uint32_t tx_failed; uint32_t ofdma; uint32_t stbc; @@ -474,6 +813,7 @@ struct cdp_tx_stats { uint32_t wme_ac_type[WME_AC_MAX]; uint32_t excess_retries_per_ac[WME_AC_MAX]; + struct cdp_pkt_info dot11_tx_pkts; struct { struct cdp_pkt_info fw_rem; @@ -485,10 +825,8 @@ struct cdp_tx_stats { uint32_t fw_reason3; } dropped; - struct cdp_pkt_info dot11_tx_pkts; uint32_t fw_tx_cnt; - uint32_t fw_tx_rates_used; uint32_t fw_tx_bytes; uint32_t fw_txcount; uint32_t fw_max4msframelen; @@ -498,12 +836,12 @@ struct cdp_tx_stats { uint32_t rssi_chain[WME_AC_MAX]; uint32_t inactive_time; - uint32_t tx_ratecode; uint32_t tx_flags; uint32_t tx_power; /* MSDUs which the target sent but couldn't get an ack for */ struct cdp_pkt_info is_tx_no_ack; + uint16_t tx_ratecode; /*add for peer and upadted from ppdu*/ uint32_t ampdu_cnt; @@ -513,11 +851,12 @@ struct cdp_tx_stats { uint32_t multiple_retry_count; uint32_t last_tx_rate_used; - uint32_t transmit_type[MAX_TRANSMIT_TYPES]; + struct cdp_tx_pkt_info transmit_type[MAX_TRANSMIT_TYPES]; uint32_t mu_group_id[MAX_MU_GROUP_ID]; uint32_t ru_start; uint32_t ru_tones; - uint32_t ru_loc[MAX_RU_LOCATIONS]; + struct cdp_tx_pkt_info ru_loc[MAX_RU_LOCATIONS]; + uint32_t num_ppdu_cookie_valid; uint32_t no_ack_count[QDF_PROTO_SUBTYPE_MAX]; }; @@ -534,6 +873,7 @@ struct cdp_tx_stats { * @pkts: Intra BSS packets received * @fail: Intra BSS packets failed * @mdns_no_fwd: Intra BSS MDNS packets not forwarded + * @protocol_trace_cnt: per-peer protocol counters * @mic_err: Rx MIC errors CCMP * @decrypt_err: Rx Decryption Errors CRC * @fcserr: rx MIC check failed (CCMP) @@ -541,15 +881,19 @@ struct cdp_tx_stats { * @reception_type[MAX_RECEPTION_TYPES]: Reception type os packets * @mcs_count[MAX_MCS]: mcs count * @sgi_count[MAX_GI]: sgi count - * @nss[SS_COUNT]: Packet count in spatiel Streams + * @nss[SS_COUNT]: packet count in spatiel Streams + * @ppdu_nss[SS_COUNT]: PPDU packet count in spatial streams + * @mpdu_cnt_fcs_ok: SU Rx success mpdu count + * @mpdu_cnt_fcs_err: SU Rx fail mpdu count + * @su_ax_ppdu_cnt: SU Rx packet count + * @ppdu_cnt[MAX_RECEPTION_TYPES]: PPDU packet count in reception type + * @rx_mu[RX_TYPE_MU_MAX]: Rx MU stats * @bw[MAX_BW]: Packet Count in different bandwidths * @non_ampdu_cnt: Number of MSDUs with no MPDU level aggregation * @ampdu_cnt: Number of MSDUs part of AMSPU * @non_amsdu_cnt: Number of MSDUs with no MSDU level aggregation * @amsdu_cnt: Number of MSDUs part of AMSDU * @bar_recv_cnt: Number of bar received - * @rssi: RSSI of received signal - * @last_rssi: Previous rssi * @avg_rssi: Average rssi * @rx_rate: Rx rate * @last_rx_rate: Previous rx rate @@ -575,6 +919,9 @@ struct cdp_tx_stats { * @rx_ratecode: Rx rate code of last frame * @rx_flags: rx flags * @rx_rssi_measured_time: Time at which rssi is measured + * @rssi: RSSI of received signal + * @last_rssi: Previous rssi + * @multipass_rx_pkt_drop: Dropped multipass rx pkt * @rx_mpdu_cnt: rx mpdu count per MCS rate */ struct cdp_rx_stats { @@ -591,6 +938,9 @@ struct cdp_rx_stats { struct cdp_pkt_info fail; uint32_t mdns_no_fwd; } intra_bss; +#ifdef VDEV_PEER_PROTOCOL_COUNT + struct protocol_trace_count protocol_trace_cnt[CDP_TRACE_MAX]; +#endif struct { uint32_t mic_err; @@ -603,14 +953,18 @@ struct cdp_rx_stats { struct cdp_pkt_type pkt_type[DOT11_MAX]; uint32_t sgi_count[MAX_GI]; uint32_t nss[SS_COUNT]; + uint32_t ppdu_nss[SS_COUNT]; + uint32_t mpdu_cnt_fcs_ok; + uint32_t mpdu_cnt_fcs_err; + struct cdp_pkt_type su_ax_ppdu_cnt; + uint32_t ppdu_cnt[MAX_RECEPTION_TYPES]; + struct cdp_rx_mu rx_mu[RX_TYPE_MU_MAX]; uint32_t bw[MAX_BW]; uint32_t non_ampdu_cnt; uint32_t ampdu_cnt; uint32_t non_amsdu_cnt; uint32_t amsdu_cnt; uint32_t bar_recv_cnt; - uint32_t rssi; - uint32_t last_rssi; uint32_t avg_rssi; uint32_t rx_rate; uint32_t last_rx_rate; @@ -633,6 +987,9 @@ struct cdp_rx_stats { uint32_t rx_ratecode; uint32_t rx_flags; uint32_t rx_rssi_measured_time; + uint8_t rssi; + uint8_t last_rssi; + uint32_t multipass_rx_pkt_drop; uint32_t rx_mpdu_cnt[MAX_MCS]; }; @@ -648,8 +1005,6 @@ struct cdp_rx_stats { * @tso_pkt:total no of TSO packets * @non_tso_pkts: non - TSO packets * @dropped_host: TSO packets dropped by host - * @tso_no_mem_dropped: TSO packets dropped by host due to descriptor - unavailability * @dropped_target:TSO packets dropped by target * @sg_pkt: Total scatter gather packets * @non_sg_pkts: non SG packets @@ -689,16 +1044,6 @@ struct cdp_tx_ingress_stats { uint32_t invalid_raw_pkt_datatype; } raw; - /* TSO packets info */ - struct { - uint32_t num_seg; - struct cdp_pkt_info tso_pkt; - struct cdp_pkt_info non_tso_pkts; - struct cdp_pkt_info dropped_host; - struct cdp_pkt_info tso_no_mem_dropped; - uint32_t dropped_target; - } tso; - /* Scatter Gather packet info */ struct { struct cdp_pkt_info sg_pkt; @@ -740,17 +1085,20 @@ struct cdp_tx_ingress_stats { uint32_t cce_classified; uint32_t cce_classified_raw; struct cdp_pkt_info sniffer_rcvd; + struct cdp_tso_stats tso_stats; }; /* struct cdp_vdev_stats - vdev stats structure * @tx_i: ingress tx stats * @tx: cdp tx stats * @rx: cdp rx stats + * @tso_stats: tso stats */ struct cdp_vdev_stats { struct cdp_tx_ingress_stats tx_i; struct cdp_tx_stats tx; struct cdp_rx_stats rx; + struct cdp_tso_stats tso_stats; }; /* struct cdp_peer_stats - peer stats structure @@ -765,7 +1113,8 @@ struct cdp_peer_stats { }; /* struct cdp_interface_peer_stats - interface structure for txrx peer stats - * @peer_hdl: control path peer handle + * @peer_mac: peer mac address + * @vdev_id : vdev_id for the peer * @last_peer_tx_rate: peer tx rate for last transmission * @peer_tx_rate: tx rate for current transmission * @peer_rssi: current rssi value of peer @@ -778,17 +1127,18 @@ struct cdp_peer_stats { * @rssi_changed: denotes rssi is changed */ struct cdp_interface_peer_stats { - void *peer_hdl; + uint8_t peer_mac[QDF_MAC_ADDR_SIZE]; + uint8_t vdev_id; + uint8_t rssi_changed; uint32_t last_peer_tx_rate; uint32_t peer_tx_rate; - uint32_t peer_rssi; + uint32_t peer_rssi; uint32_t tx_packet_count; uint32_t rx_packet_count; uint32_t tx_byte_count; uint32_t rx_byte_count; uint32_t per; uint32_t ack_rssi; - uint8_t rssi_changed; }; /* Tx completions per interrupt */ @@ -1203,12 +1553,92 @@ struct cdp_htt_rx_pdev_stats { #define RX_PROTOCOL_TAG_ALL 0xff #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ +#define OFDMA_NUM_RU_SIZE 7 + +#define OFDMA_NUM_USERS 37 + +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) +/* + * mac_freeze_capture_reason - capture reason counters + * @FREEZE_REASON_TM: When m_directed_ftm is enabled, this CFR data is + * captured for a Timing Measurement (TM) frame. + * @FREEZE_REASON_FTM: When m_directed_ftm is enabled, this CFR data is + * captured for a Fine Timing Measurement (FTM) frame. + * @FREEZE_REASON_ACK_RESP_TO_TM_FTM: When m_all_ftm_ack is enabled, this CFR + * data is captured for an ACK received for the FTM/TM frame sent to a station. + * @FREEZE_REASON_TA_RA_TYPE_FILTER: When m_ta_ra_filter is enabled, this CFR + * data is captured for a PPDU received,since the CFR TA_RA filter is met. + * @FREEZE_REASON_NDPA_NDP: When m_ndpa_ndp_directed(or)m_ndpa_ndp_all is + * enabled, this CFR data is captured for an NDP frame received. + * @FREEZE_REASON_ALL_PACKET: When m_all_packet is enabled, this CFR data is + * captured for an incoming PPDU. + */ +enum mac_freeze_capture_reason { + FREEZE_REASON_TM = 0, + FREEZE_REASON_FTM, + FREEZE_REASON_ACK_RESP_TO_TM_FTM, + FREEZE_REASON_TA_RA_TYPE_FILTER, + FREEZE_REASON_NDPA_NDP, + FREEZE_REASON_ALL_PACKET, + FREEZE_REASON_MAX, +}; + +/* + * chan_capture_status: capture status counters + * @CAPTURE_IDLE: CFR data is not captured, since VCSR setting for CFR/RCC is + * not enabled. + * @CAPTURE_BUSY: CFR data is not available, since previous channel + * upload is in progress + * @CAPTURE_ACTIVE: CFR data is captured in HW registers + * @CAPTURE_NO_BUFFER: CFR data is not captured, since no buffer is available + * in IPC ring to DMA CFR data + */ +enum chan_capture_status { + CAPTURE_IDLE = 0, + CAPTURE_BUSY, + CAPTURE_ACTIVE, + CAPTURE_NO_BUFFER, + CAPTURE_MAX, +}; + +/* struct cdp_cfr_rcc_stats - CFR RCC debug statistics + * @bb_captured_channel_cnt: No. of PPDUs for which MAC sent Freeze TLV to PHY + * @bb_captured_timeout_cnt: No. of PPDUs for which CFR filter criteria matched + * but MAC did not send Freeze TLV to PHY as time exceeded freeze tlv delay + * count threshold + * @rx_loc_info_valid_cnt: No. of PPDUs for which PHY could find a valid buffer + * in ucode IPC ring + * @chan_capture_status[]: capture status counters + * [0] - No. of PPDUs with capture status CAPTURE_IDLE + * [1] - No. of PPDUs with capture status CAPTURE_BUSY + * [2] - No. of PPDUs with capture status CAPTURE_ACTIVE + * [3] - No. of PPDUs with capture status CAPTURE_NO_BUFFER + * @reason_cnt[]: capture reason counters + * [0] - No. PPDUs filtered due to freeze_reason_TM + * [1] - No. PPDUs filtered due to freeze_reason_FTM + * [2] - No. PPDUs filtered due to freeze_reason_ACK_resp_to_TM_FTM + * [3] - No. PPDUs filtered due to freeze_reason_TA_RA_TYPE_FILTER + * [4] - No. PPDUs filtered due to freeze_reason_NDPA_NDP + * [5] - No. PPDUs filtered due to freeze_reason_ALL_PACKET + */ +struct cdp_cfr_rcc_stats { + uint64_t bb_captured_channel_cnt; + uint64_t bb_captured_timeout_cnt; + uint64_t rx_loc_info_valid_cnt; + uint64_t chan_capture_status[CAPTURE_MAX]; + uint64_t reason_cnt[FREEZE_REASON_MAX]; +}; +#else +struct cdp_cfr_rcc_stats { +}; +#endif /* struct cdp_pdev_stats - pdev stats * @msdu_not_done: packets dropped because msdu done bit not set * @mec:Multicast Echo check * @mesh_filter: Mesh Filtered packets * @mon_rx_drop: packets dropped on monitor vap * @wifi_parse: rxdma errors due to wifi parse error + * @mon_radiotap_update_err: not enough space to update radiotap * @pkts: total packets replenished * @rxdma_err: rxdma errors for replenished * @nbuf_alloc_fail: nbuf alloc failed @@ -1230,16 +1660,23 @@ struct cdp_htt_rx_pdev_stats { * @tx_comp_histogram: Number of Tx completions per interrupt * @rx_ind_histogram: Number of Rx ring descriptors reaped per interrupt * @ppdu_stats_counter: ppdu stats counter + * @cdp_delayed_ba_not_recev: counter for delayed ba not received * @htt_tx_pdev_stats: htt pdev stats for tx * @htt_rx_pdev_stats: htt pdev stats for rx + * @data_rx_ru_size: UL ofdma data ru size counter array + * @nondata_rx_ru_size: UL ofdma non data ru size counter array + * @data_rx_ppdu: data rx ppdu counter + * @data_user: data user counter array */ struct cdp_pdev_stats { struct { uint32_t msdu_not_done; uint32_t mec; uint32_t mesh_filter; - uint32_t mon_rx_drop; uint32_t wifi_parse; + /* Monitor mode related */ + uint32_t mon_rx_drop; + uint32_t mon_radiotap_update_err; } dropped; struct { @@ -1262,6 +1699,8 @@ struct cdp_pdev_stats { uint32_t desc_alloc_fail; uint32_t ip_csum_err; uint32_t tcp_udp_csum_err; + uint32_t rxdma_error; + uint32_t reo_error; } err; uint32_t buf_freelist; @@ -1271,6 +1710,7 @@ struct cdp_pdev_stats { struct cdp_hist_tx_comp tx_comp_histogram; struct cdp_hist_rx_ind rx_ind_histogram; uint64_t ppdu_stats_counter[CDP_PPDU_STATS_MAX_TAG]; + uint32_t cdp_delayed_ba_not_recev; struct cdp_htt_tx_pdev_stats htt_tx_pdev_stats; struct cdp_htt_rx_pdev_stats htt_rx_pdev_stats; @@ -1278,9 +1718,20 @@ struct cdp_pdev_stats { /* Received wdi messages from fw */ uint32_t wdi_event[CDP_WDI_NUM_EVENTS]; struct cdp_tid_stats tid_stats; + + /* numbers of data/nondata per RU sizes */ + struct { + uint32_t data_rx_ru_size[OFDMA_NUM_RU_SIZE]; + uint32_t nondata_rx_ru_size[OFDMA_NUM_RU_SIZE]; + uint32_t data_rx_ppdu; + uint32_t data_users[OFDMA_NUM_USERS]; + } ul_ofdma; + + struct cdp_tso_stats tso_stats; + struct cdp_cfr_rcc_stats rcc; }; -#ifndef CONFIG_MCL +#ifdef QCA_ENH_V3_STATS_SUPPORT /* * Enumeration of PDEV Configuration parameter */ @@ -1615,6 +2066,8 @@ enum _ol_ath_param_t { OL_ATH_PARAM_ACS_NEAR_RANGE_WEIGHTAGE = 413, OL_ATH_PARAM_ACS_MID_RANGE_WEIGHTAGE = 414, OL_ATH_PARAM_ACS_FAR_RANGE_WEIGHTAGE = 415, + /* Set SELF AP OBSS_PD_THRESHOLD value */ + OL_ATH_PARAM_SET_CMD_OBSS_PD_THRESHOLD = 416, /* Enable/Disable/Set MGMT_TTL in milliseconds. */ OL_ATH_PARAM_MGMT_TTL = 417, /* Enable/Disable/Set PROBE_RESP_TTL in milliseconds */ @@ -1623,6 +2076,44 @@ enum _ol_ath_param_t { OL_ATH_PARAM_MU_PPDU_DURATION = 419, /* Set TBTT_CTRL_CFG */ OL_ATH_PARAM_TBTT_CTRL = 420, + /* Enable/disable AP OBSS_PD_THRESHOLD */ + OL_ATH_PARAM_SET_CMD_OBSS_PD_THRESHOLD_ENABLE = 421, + /* Get baseline radio level channel width */ + OL_ATH_PARAM_RCHWIDTH = 422, + /* Whether external ACS request is in progress */ + OL_ATH_EXT_ACS_REQUEST_IN_PROGRESS = 423, + /* set/get hw mode */ + OL_ATH_PARAM_HW_MODE = 424, +#if DBDC_REPEATER_SUPPORT + /* same ssid feature global disable */ + OL_ATH_PARAM_SAME_SSID_DISABLE = 425, +#endif + /* get MBSS enable flag */ + OL_ATH_PARAM_MBSS_EN = 426, + /* UNII-1 and UNII-2A channel coexistance */ + OL_ATH_PARAM_CHAN_COEX = 427, + /* Out of Band Advertisement feature */ + OL_ATH_PARAM_OOB_ENABLE = 428, + /* set/get opmode-notification timer for hw-mode switch */ + OL_ATH_PARAM_HW_MODE_SWITCH_OMN_TIMER = 429, + /* enable opmode-notification when doing hw-mode switch */ + OL_ATH_PARAM_HW_MODE_SWITCH_OMN_ENABLE = 430, + /* set primary interface for hw-mode switch */ + OL_ATH_PARAM_HW_MODE_SWITCH_PRIMARY_IF = 431, + /* Number of vdevs configured per PSOC */ + OL_ATH_PARAM_GET_PSOC_NUM_VDEVS = 432, + /* Number of peers configured per PSOC */ + OL_ATH_PARAM_GET_PSOC_NUM_PEERS = 433, + /* Number of vdevs configured per PDEV */ + OL_ATH_PARAM_GET_PDEV_NUM_VDEVS = 434, + /* Number of peers configured per PDEV */ + OL_ATH_PARAM_GET_PDEV_NUM_PEERS = 435, + /* Number of monitor vdevs configured per PDEV */ + OL_ATH_PARAM_GET_PDEV_NUM_MONITOR_VDEVS = 436, +#ifdef CE_TASKLET_DEBUG_ENABLE + /* Enable/disable CE stats print */ + OL_ATH_PARAM_ENABLE_CE_LATENCY_STATS = 437, +#endif }; #endif /* Bitmasks for stats that can block */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_tx_delay.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_tx_delay.h index 34e3cbe9355b7bd867bd4cc4796c1ad2d45d6c4c..044052dd7d14ad3471991b5d69b754a2c271c3ae 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_tx_delay.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_tx_delay.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 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 @@ -27,7 +27,7 @@ /** * cdp_tx_delay() - get tx packet delay * @soc: data path soc handle - * @pdev: physical device instance + * @pdev_id: id of data path pdev handle * @queue_delay_microsec: tx packet delay within queue, usec * @tx_delay_microsec: tx packet delay, usec * @category: packet category @@ -35,9 +35,9 @@ * Return: NONE */ static inline void -cdp_tx_delay(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint32_t *queue_delay_microsec, uint32_t *tx_delay_microsec, - int category) +cdp_tx_delay(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint32_t *queue_delay_microsec, uint32_t *tx_delay_microsec, + int category) { if (!soc || !soc->ops || !soc->ops->delay_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -46,7 +46,7 @@ cdp_tx_delay(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->delay_ops->tx_delay) - return soc->ops->delay_ops->tx_delay(pdev, + return soc->ops->delay_ops->tx_delay(soc, pdev_id, queue_delay_microsec, tx_delay_microsec, category); return; } @@ -54,15 +54,15 @@ cdp_tx_delay(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, /** * cdp_tx_delay_hist() - get tx packet delay histogram * @soc: data path soc handle - * @pdev: physical device instance + * @pdev_id: id of data path pdev handle * @bin_values: bin * @category: packet category * * Return: NONE */ static inline void -cdp_tx_delay_hist(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint16_t *bin_values, int category) +cdp_tx_delay_hist(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint16_t *bin_values, int category) { if (!soc || !soc->ops || !soc->ops->delay_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -71,7 +71,7 @@ cdp_tx_delay_hist(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->delay_ops->tx_delay_hist) - return soc->ops->delay_ops->tx_delay_hist(pdev, + return soc->ops->delay_ops->tx_delay_hist(soc, pdev_id, bin_values, category); return; } @@ -79,16 +79,16 @@ cdp_tx_delay_hist(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, /** * cdp_tx_packet_count() - get tx packet count * @soc: data path soc handle - * @pdev: physical device instance + * @pdev_id: id of data path pdev handle * @out_packet_loss_count: packet loss count * @category: packet category * * Return: NONE */ static inline void -cdp_tx_packet_count(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint16_t *out_packet_count, uint16_t *out_packet_loss_count, - int category) +cdp_tx_packet_count(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint16_t *out_packet_count, uint16_t *out_packet_loss_count, + int category) { if (!soc || !soc->ops || !soc->ops->delay_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -97,7 +97,7 @@ cdp_tx_packet_count(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->delay_ops->tx_packet_count) - return soc->ops->delay_ops->tx_packet_count(pdev, + return soc->ops->delay_ops->tx_packet_count(soc, pdev_id, out_packet_count, out_packet_loss_count, category); return; } @@ -105,14 +105,14 @@ cdp_tx_packet_count(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, /** * cdp_tx_set_compute_interval() - set tx packet stat compute interval * @soc: data path soc handle - * @pdev: physical device instance + * @pdev_id: id of data path pdev handle * @interval: compute interval * * Return: NONE */ static inline void -cdp_tx_set_compute_interval(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - uint32_t interval) +cdp_tx_set_compute_interval(ol_txrx_soc_handle soc, uint8_t pdev_id, + uint32_t interval) { if (!soc || !soc->ops || !soc->ops->delay_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -121,8 +121,9 @@ cdp_tx_set_compute_interval(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->delay_ops->tx_set_compute_interval) - return soc->ops->delay_ops->tx_set_compute_interval(pdev, - interval); + return soc->ops->delay_ops->tx_set_compute_interval(soc, + pdev_id, + interval); return; } #endif /* _CDP_TXRX_COMPUTE_TX_DELAY_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_tx_throttle.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_tx_throttle.h index 9716f27c4bd017ba648b81c995631b1566565a06..a17d1237bc06b23043e4c004096959c40b7138e9 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_tx_throttle.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_tx_throttle.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, 2019 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 @@ -29,15 +29,15 @@ /** * cdp_throttle_init_period() - init tx throttle period * @soc: data path soc handle - * @pdev: physical device instance + * @pdev_id: id of data path pdev handle * @period: throttle period * @dutycycle_level: duty cycle level * * Return: NONE */ static inline void -cdp_throttle_init_period(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, - int period, uint8_t *dutycycle_level) +cdp_throttle_init_period(ol_txrx_soc_handle soc, uint8_t pdev_id, + int period, uint8_t *dutycycle_level) { if (!soc || !soc->ops || !soc->ops->throttle_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -46,21 +46,21 @@ cdp_throttle_init_period(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, } if (soc->ops->throttle_ops->throttle_init_period) - return soc->ops->throttle_ops->throttle_init_period(pdev, - period, dutycycle_level); + return soc->ops->throttle_ops->throttle_init_period( + soc, pdev_id, period, dutycycle_level); return; } /** * cdp_throttle_init_period() - init tx throttle period * @soc: data path soc handle - * @pdev: physical device instance + * @pdev_id: id of data path pdev handle * @level: throttle level * * Return: NONE */ static inline void -cdp_throttle_set_level(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, int level) +cdp_throttle_set_level(ol_txrx_soc_handle soc, uint8_t pdev_id, int level) { if (!soc || !soc->ops || !soc->ops->throttle_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, @@ -69,7 +69,8 @@ cdp_throttle_set_level(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, int level) } if (soc->ops->throttle_ops->throttle_set_level) - return soc->ops->throttle_ops->throttle_set_level(pdev, level); + return soc->ops->throttle_ops->throttle_set_level(soc, pdev_id, + level); return; } diff --git a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_wds.h b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_wds.h index db28e80bed9a07ebea9d8ed1783718d83b6e03db..24c253f03540c6eb82dfdfecdd789dd438c2f325 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_wds.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/inc/cdp_txrx_wds.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, 2019 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 @@ -30,24 +30,24 @@ * This flag sets the wds rx policy on the vdev. Rx frames not compliant * with the policy will be dropped. * - * @param vdev - the data virtual device object + * @param vdev_id - id of the data virtual device object * @param val - the wds rx policy bitmask - * @return - void + * @return - QDF_STATUS */ -static inline void +static inline QDF_STATUS cdp_set_wds_rx_policy(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, + uint8_t vdev_id, u_int32_t val) { if (!soc || !soc->ops || !soc->ops->wds_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return; + return QDF_STATUS_E_FAILURE; } if (soc->ops->wds_ops->txrx_set_wds_rx_policy) - return soc->ops->wds_ops->txrx_set_wds_rx_policy(vdev, val); - return; + soc->ops->wds_ops->txrx_set_wds_rx_policy(soc, vdev_id, val); + return QDF_STATUS_SUCCESS; } /** @@ -56,31 +56,34 @@ cdp_set_wds_rx_policy(ol_txrx_soc_handle soc, * This flag sets the wds rx policy on the vdev. Rx frames not compliant * with the policy will be dropped. * - * @param vdev - the data virtual device object + * @param psoc - psoc object + * @param vdev_id - id of the data virtual device object + * @param peer_mac - peer mac address * @param val - the wds rx policy bitmask - * @return - void + * @return - QDF_STATUS */ -static inline void +static inline QDF_STATUS cdp_set_wds_tx_policy_update(ol_txrx_soc_handle soc, - struct cdp_peer *peer, + uint8_t vdev_id, uint8_t *peer_mac, int wds_tx_ucast, int wds_tx_mcast) { if (!soc || !soc->ops || !soc->ops->wds_ops) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, "%s invalid instance", __func__); - return; + return QDF_STATUS_E_FAILURE; } if (soc->ops->wds_ops->txrx_wds_peer_tx_policy_update) - return soc->ops->wds_ops->txrx_wds_peer_tx_policy_update( - peer, wds_tx_ucast, wds_tx_mcast); - return; + soc->ops->wds_ops->txrx_wds_peer_tx_policy_update( + soc, vdev_id, peer_mac, wds_tx_ucast, + wds_tx_mcast); + return QDF_STATUS_SUCCESS; } /** * cdp_vdev_set_wds() - Set/unset wds_enable flag in vdev * @soc - data path soc handle - * @vdev - data path vap handle + * @vdev_id - id of data path vap handle * @val - value to be set in wds_en flag * * This flag enables WDS source port learning feature on a vdev @@ -88,10 +91,10 @@ cdp_set_wds_tx_policy_update(ol_txrx_soc_handle soc, * return 1 on success */ static inline int -cdp_vdev_set_wds(ol_txrx_soc_handle soc, void *vdev, uint32_t val) +cdp_vdev_set_wds(ol_txrx_soc_handle soc, uint8_t vdev_id, uint32_t val) { if (soc->ops->wds_ops->vdev_set_wds) - return soc->ops->wds_ops->vdev_set_wds(vdev, val); + return soc->ops->wds_ops->vdev_set_wds(soc, vdev_id, val); return 0; } #endif diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_cal_client_api.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_cal_client_api.h index 7bf9ec43b39fdb825702180469e8c9a97449c52b..d7c8815bff8f647472996f550f715c2daf04b2be 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_cal_client_api.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_cal_client_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 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 @@ -26,31 +26,34 @@ #include #include #include +#include /*timer will run every 1 sec*/ #define DP_CAL_CLIENT_TIME 1000 struct cal_client { qdf_timer_t cal_client_timer; - void (*iterate_update_peer_list)(void *ctx); - void *pdev_hdl; + void (*iterate_update_peer_list)(struct cdp_pdev *ctx); + struct cdp_pdev *pdev_hdl; }; -void dp_cal_client_attach(void **cal_client_ctx, void *pdev, qdf_device_t osdev, - void (*iterate_peer_list)(void *)); -void dp_cal_client_detach(void **cal_client_ctx); +void dp_cal_client_attach(struct cdp_cal_client **cal_client_ctx, + struct cdp_pdev *pdev, qdf_device_t osdev, + void (*iterate_peer_list)(struct cdp_pdev *)); +void dp_cal_client_detach(struct cdp_cal_client **cal_client_ctx); void dp_cal_client_timer_start(void *ctx); void dp_cal_client_timer_stop(void *ctx); void dp_cal_client_stats_timer_fn(void *pdev_hdl); void dp_cal_client_update_peer_stats(struct cdp_peer_stats *peer_stats); #ifndef ATH_SUPPORT_EXT_STAT -void dp_cal_client_attach(void **cal_client_ctx, void *pdev, qdf_device_t osdev, - void (*iterate_peer_list)(void *)) +void dp_cal_client_attach(struct cdp_cal_client **cal_client_ctx, + struct cdp_pdev *pdev, qdf_device_t osdev, + void (*iterate_peer_list)(struct cdp_pdev *)) { } -void dp_cal_client_detach(void **cal_client_ctx) +void dp_cal_client_detach(struct cdp_cal_client **cal_client_ctx) { } diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_htt.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_htt.c index 71a7c7326c24c6eb7c916520cd7eb43c7fd0d20a..55cd09fa630c6ea7529cbac8421f85d41035f128 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_htt.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_htt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -26,6 +26,7 @@ #include "htt_stats.h" #include "htt_ppdu_stats.h" #include "dp_htt.h" +#include "dp_rx.h" #include "qdf_mem.h" /* qdf_mem_malloc,free */ #include "cdp_txrx_cmn_struct.h" @@ -43,20 +44,16 @@ #define HTT_PID_BIT_MASK 0x3 #define DP_EXT_MSG_LENGTH 2048 -#define DP_HTT_SEND_HTC_PKT(soc, pkt) \ -do { \ - if (htc_send_pkt(soc->htc_soc, &pkt->htc_pkt) == \ - QDF_STATUS_SUCCESS) { \ - htt_htc_misc_pkt_list_add(soc, pkt); \ - } else { \ - dp_err("htc_send_pkt failure!!"); \ - qdf_nbuf_free((qdf_nbuf_t)(pkt->htc_pkt.pNetBufContext)); \ - htt_htc_pkt_free(soc, pkt); \ - } \ -} while (0) #define HTT_MGMT_CTRL_TLV_HDR_RESERVERD_LEN 16 +#define HTT_SHIFT_UPPER_TIMESTAMP 32 +#define HTT_MASK_UPPER_TIMESTAMP 0xFFFFFFFF00000000 + +#define HTT_HTC_PKT_STATUS_SUCCESS \ + ((pkt->htc_pkt.Status != QDF_STATUS_E_CANCELED) && \ + (pkt->htc_pkt.Status != QDF_STATUS_E_RESOURCES)) + /* * dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap() - Get ppdu stats tlv * bitmap for sniffer mode @@ -77,6 +74,108 @@ dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap(uint32_t bitmap) } #ifdef FEATURE_PERPKT_INFO +/* + * dp_peer_copy_delay_stats() - copy ppdu stats to peer delayed stats. + * @peer: Datapath peer handle + * @ppdu: PPDU Descriptor + * + * Return: None + * + * on Tx data frame, we may get delayed ba set + * in htt_ppdu_stats_user_common_tlv. which mean we get Block Ack(BA) after we + * request Block Ack Request(BAR). Successful msdu is received only after Block + * Ack. To populate peer stats we need successful msdu(data frame). + * So we hold the Tx data stats on delayed_ba for stats update. + */ +static inline void +dp_peer_copy_delay_stats(struct dp_peer *peer, + struct cdp_tx_completion_ppdu_user *ppdu) +{ + struct dp_pdev *pdev; + struct dp_vdev *vdev; + + if (peer->last_delayed_ba) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "BA not yet recv for prev delayed ppdu[%d]\n", + peer->last_delayed_ba_ppduid); + vdev = peer->vdev; + if (vdev) { + pdev = vdev->pdev; + pdev->stats.cdp_delayed_ba_not_recev++; + } + } + + peer->delayed_ba_ppdu_stats.ltf_size = ppdu->ltf_size; + peer->delayed_ba_ppdu_stats.stbc = ppdu->stbc; + peer->delayed_ba_ppdu_stats.he_re = ppdu->he_re; + peer->delayed_ba_ppdu_stats.txbf = ppdu->txbf; + peer->delayed_ba_ppdu_stats.bw = ppdu->bw; + peer->delayed_ba_ppdu_stats.nss = ppdu->nss; + peer->delayed_ba_ppdu_stats.preamble = ppdu->preamble; + peer->delayed_ba_ppdu_stats.gi = ppdu->gi; + peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; + peer->delayed_ba_ppdu_stats.ldpc = ppdu->ldpc; + peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; + peer->delayed_ba_ppdu_stats.mpdu_tried_ucast = ppdu->mpdu_tried_ucast; + peer->delayed_ba_ppdu_stats.mpdu_tried_mcast = ppdu->mpdu_tried_mcast; + peer->delayed_ba_ppdu_stats.frame_ctrl = ppdu->frame_ctrl; + peer->delayed_ba_ppdu_stats.qos_ctrl = ppdu->qos_ctrl; + peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; + + peer->delayed_ba_ppdu_stats.ru_start = ppdu->ru_start; + peer->delayed_ba_ppdu_stats.ru_tones = ppdu->ru_tones; + peer->delayed_ba_ppdu_stats.is_mcast = ppdu->is_mcast; + + peer->delayed_ba_ppdu_stats.user_pos = ppdu->user_pos; + peer->delayed_ba_ppdu_stats.mu_group_id = ppdu->mu_group_id; + + peer->last_delayed_ba = true; +} + +/* + * dp_peer_copy_stats_to_bar() - copy delayed stats to ppdu stats. + * @peer: Datapath peer handle + * @ppdu: PPDU Descriptor + * + * Return: None + * + * For Tx BAR, PPDU stats TLV include Block Ack info. PPDU info + * from Tx BAR frame not required to populate peer stats. + * But we need successful MPDU and MSDU to update previous + * transmitted Tx data frame. Overwrite ppdu stats with the previous + * stored ppdu stats. + */ +static void +dp_peer_copy_stats_to_bar(struct dp_peer *peer, + struct cdp_tx_completion_ppdu_user *ppdu) +{ + ppdu->ltf_size = peer->delayed_ba_ppdu_stats.ltf_size; + ppdu->stbc = peer->delayed_ba_ppdu_stats.stbc; + ppdu->he_re = peer->delayed_ba_ppdu_stats.he_re; + ppdu->txbf = peer->delayed_ba_ppdu_stats.txbf; + ppdu->bw = peer->delayed_ba_ppdu_stats.bw; + ppdu->nss = peer->delayed_ba_ppdu_stats.nss; + ppdu->preamble = peer->delayed_ba_ppdu_stats.preamble; + ppdu->gi = peer->delayed_ba_ppdu_stats.gi; + ppdu->dcm = peer->delayed_ba_ppdu_stats.dcm; + ppdu->ldpc = peer->delayed_ba_ppdu_stats.ldpc; + ppdu->dcm = peer->delayed_ba_ppdu_stats.dcm; + ppdu->mpdu_tried_ucast = peer->delayed_ba_ppdu_stats.mpdu_tried_ucast; + ppdu->mpdu_tried_mcast = peer->delayed_ba_ppdu_stats.mpdu_tried_mcast; + ppdu->frame_ctrl = peer->delayed_ba_ppdu_stats.frame_ctrl; + ppdu->qos_ctrl = peer->delayed_ba_ppdu_stats.qos_ctrl; + ppdu->dcm = peer->delayed_ba_ppdu_stats.dcm; + + ppdu->ru_start = peer->delayed_ba_ppdu_stats.ru_start; + ppdu->ru_tones = peer->delayed_ba_ppdu_stats.ru_tones; + ppdu->is_mcast = peer->delayed_ba_ppdu_stats.is_mcast; + + ppdu->user_pos = peer->delayed_ba_ppdu_stats.user_pos; + ppdu->mu_group_id = peer->delayed_ba_ppdu_stats.mu_group_id; + + peer->last_delayed_ba = false; +} + /* * dp_tx_rate_stats_update() - Update rate per-peer statistics * @peer: Datapath peer handle @@ -91,6 +190,7 @@ dp_tx_rate_stats_update(struct dp_peer *peer, uint32_t ratekbps = 0; uint64_t ppdu_tx_rate = 0; uint32_t rix; + uint16_t ratecode = 0; if (!peer || !ppdu) return; @@ -100,15 +200,25 @@ dp_tx_rate_stats_update(struct dp_peer *peer, ppdu->nss, ppdu->preamble, ppdu->bw, - &rix); + &rix, + &ratecode); DP_STATS_UPD(peer, tx.last_tx_rate, ratekbps); if (!ratekbps) return; + /* Calculate goodput in non-training period + * In training period, don't do anything as + * pending pkt is send as goodput. + */ + if ((!peer->bss_peer) && (!ppdu->sa_is_training)) { + ppdu->sa_goodput = ((ratekbps / CDP_NUM_KB_IN_MB) * + (CDP_PERCENT_MACRO - ppdu->current_rate_per)); + } ppdu->rix = rix; ppdu->tx_ratekbps = ratekbps; + ppdu->tx_ratecode = ratecode; peer->stats.tx.avg_tx_rate = dp_ath_rate_lpf(peer->stats.tx.avg_tx_rate, ratekbps); ppdu_tx_rate = dp_ath_rate_out(peer->stats.tx.avg_tx_rate); @@ -135,7 +245,7 @@ dp_tx_rate_stats_update(struct dp_peer *peer, /* * dp_tx_stats_update() - Update per-peer statistics - * @soc: Datapath soc handle + * @pdev: Datapath pdev handle * @peer: Datapath peer handle * @ppdu: PPDU Descriptor * @ack_rssi: RSSI of last ack received @@ -143,27 +253,37 @@ dp_tx_rate_stats_update(struct dp_peer *peer, * Return: None */ static void -dp_tx_stats_update(struct dp_soc *soc, struct dp_peer *peer, +dp_tx_stats_update(struct dp_pdev *pdev, struct dp_peer *peer, struct cdp_tx_completion_ppdu_user *ppdu, uint32_t ack_rssi) { - struct dp_pdev *pdev = peer->vdev->pdev; uint8_t preamble, mcs; uint16_t num_msdu; + uint16_t num_mpdu; + uint16_t mpdu_tried; + uint16_t mpdu_failed; preamble = ppdu->preamble; mcs = ppdu->mcs; num_msdu = ppdu->num_msdu; + num_mpdu = ppdu->mpdu_success; + mpdu_tried = ppdu->mpdu_tried_ucast + ppdu->mpdu_tried_mcast; + mpdu_failed = mpdu_tried - num_mpdu; /* If the peer statistics are already processed as part of * per-MSDU completion handler, do not process these again in per-PPDU * indications */ - if (soc->process_tx_status) + if (pdev->soc->process_tx_status) return; if (ppdu->completion_status != HTT_PPDU_STATS_USER_STATUS_OK) { - DP_STATS_INC(peer, tx.retries, - (ppdu->long_retries + ppdu->short_retries)); + /* + * All failed mpdu will be retried, so incrementing + * retries mpdu based on mpdu failed. Even for + * ack failure i.e for long retries we get + * mpdu failed equal mpdu tried. + */ + DP_STATS_INC(peer, tx.retries, mpdu_failed); DP_STATS_INC(peer, tx.tx_failed, ppdu->failed_msdus); return; } @@ -187,27 +307,72 @@ dp_tx_stats_update(struct dp_soc *soc, struct dp_peer *peer, DP_STATS_UPD(peer, tx.ru_start, ppdu->ru_start); switch (ppdu->ru_tones) { case RU_26: - DP_STATS_INC(peer, tx.ru_loc[0], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_26_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_26_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_26_INDEX].mpdu_tried, + mpdu_tried); break; case RU_52: - DP_STATS_INC(peer, tx.ru_loc[1], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_52_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_52_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_52_INDEX].mpdu_tried, + mpdu_tried); break; case RU_106: - DP_STATS_INC(peer, tx.ru_loc[2], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_106_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_106_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_106_INDEX].mpdu_tried, + mpdu_tried); break; case RU_242: - DP_STATS_INC(peer, tx.ru_loc[3], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_242_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_242_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_242_INDEX].mpdu_tried, + mpdu_tried); break; case RU_484: - DP_STATS_INC(peer, tx.ru_loc[4], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_484_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_484_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_484_INDEX].mpdu_tried, + mpdu_tried); break; case RU_996: - DP_STATS_INC(peer, tx.ru_loc[5], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_996_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_996_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_996_INDEX].mpdu_tried, + mpdu_tried); break; } } - DP_STATS_INC(peer, tx.transmit_type[ppdu->ppdu_type], num_msdu); + /* + * All failed mpdu will be retried, so incrementing + * retries mpdu based on mpdu failed. Even for + * ack failure i.e for long retries we get + * mpdu failed equal mpdu tried. + */ + DP_STATS_INC(peer, tx.retries, mpdu_failed); + DP_STATS_INC(peer, tx.tx_failed, ppdu->failed_msdus); + + DP_STATS_INC(peer, tx.transmit_type[ppdu->ppdu_type].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.transmit_type[ppdu->ppdu_type].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.transmit_type[ppdu->ppdu_type].mpdu_tried, + mpdu_tried); + DP_STATS_INC_PKT(peer, tx.comp_pkt, num_msdu, (ppdu->success_bytes + ppdu->retry_bytes + ppdu->failed_bytes)); @@ -215,7 +380,9 @@ dp_tx_stats_update(struct dp_soc *soc, struct dp_peer *peer, DP_STATS_INC(peer, tx.sgi_count[ppdu->gi], num_msdu); DP_STATS_INC(peer, tx.bw[ppdu->bw], num_msdu); DP_STATS_INC(peer, tx.nss[ppdu->nss], num_msdu); - DP_STATS_INC(peer, tx.wme_ac_type[TID_TO_WME_AC(ppdu->tid)], num_msdu); + if (ppdu->tid < CDP_DATA_TID_MAX) + DP_STATS_INC(peer, tx.wme_ac_type[TID_TO_WME_AC(ppdu->tid)], + num_msdu); DP_STATS_INCC(peer, tx.stbc, num_msdu, ppdu->stbc); DP_STATS_INCC(peer, tx.ldpc, num_msdu, ppdu->ldpc); if (!(ppdu->is_mcast) && ppdu->ack_rssi_valid) @@ -254,7 +421,7 @@ dp_tx_stats_update(struct dp_soc *soc, struct dp_peer *peer, DP_STATS_INCC(peer, tx.ampdu_cnt, num_msdu, ppdu->is_ampdu); DP_STATS_INCC(peer, tx.non_ampdu_cnt, num_msdu, !(ppdu->is_ampdu)); - dp_peer_stats_notify(peer); + dp_peer_stats_notify(pdev, peer); #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, pdev->soc, @@ -394,6 +561,30 @@ htt_htc_misc_pkt_list_add(struct htt_soc *soc, struct dp_htt_htc_pkt *pkt) htt_htc_misc_pkt_list_trim(soc, misclist_trim_level); } +/** + * DP_HTT_SEND_HTC_PKT() - Send htt packet from host + * @soc : HTT SOC handle + * @pkt: pkt to be send + * @cmd : command to be recorded in dp htt logger + * @buf : Pointer to buffer needs to be recored for above cmd + * + * Return: None + */ +static inline QDF_STATUS DP_HTT_SEND_HTC_PKT(struct htt_soc *soc, + struct dp_htt_htc_pkt *pkt, + uint8_t cmd, uint8_t *buf) +{ + QDF_STATUS status; + + htt_command_record(soc->htt_logger_handle, cmd, buf); + + status = htc_send_pkt(soc->htc_soc, &pkt->htc_pkt); + if (status == QDF_STATUS_SUCCESS && HTT_HTC_PKT_STATUS_SUCCESS) + htt_htc_misc_pkt_list_add(soc, pkt); + + return status; +} + /* * htt_htc_misc_pkt_pool_free() - free pkts in misc list * @htt_soc: HTT SOC handle @@ -404,6 +595,7 @@ htt_htc_misc_pkt_pool_free(struct htt_soc *soc) struct dp_htt_htc_pkt_union *pkt, *next; qdf_nbuf_t netbuf; + HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex); pkt = soc->htt_htc_pkt_misclist; while (pkt) { @@ -421,6 +613,7 @@ htt_htc_misc_pkt_pool_free(struct htt_soc *soc) pkt = next; } soc->htt_htc_pkt_misclist = NULL; + HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex); } /* @@ -513,6 +706,7 @@ static int htt_h2t_ver_req_msg(struct htt_soc *soc) struct dp_htt_htc_pkt *pkt; qdf_nbuf_t msg; uint32_t *msg_word; + QDF_STATUS status; msg = qdf_nbuf_alloc( soc->osdev, @@ -554,11 +748,18 @@ static int htt_h2t_ver_req_msg(struct htt_soc *soc) SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, dp_htt_h2t_send_complete_free_netbuf, qdf_nbuf_data(msg), qdf_nbuf_len(msg), soc->htc_endpoint, - 1); /* tag - not relevant here */ + HTC_TX_PACKET_TAG_RTPM_PUT_RC); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); - DP_HTT_SEND_HTC_PKT(soc, pkt); - return 0; + status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_VERSION_REQ, + NULL); + + if (status != QDF_STATUS_SUCCESS) { + qdf_nbuf_free(msg); + htt_htc_pkt_free(soc, pkt); + } + + return status; } /* @@ -570,10 +771,10 @@ static int htt_h2t_ver_req_msg(struct htt_soc *soc) * * Return: 0 on success; error code on failure */ -int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng, - int hal_ring_type) +int htt_srng_setup(struct htt_soc *soc, int mac_id, + hal_ring_handle_t hal_ring_hdl, + int hal_ring_type) { - struct htt_soc *soc = (struct htt_soc *)htt_soc; struct dp_htt_htc_pkt *pkt; qdf_nbuf_t htt_msg; uint32_t *msg_word; @@ -582,6 +783,10 @@ int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng, uint32_t ring_entry_size = hal_srng_get_entrysize(soc->hal_soc, hal_ring_type); int htt_ring_type, htt_ring_id; + uint8_t *htt_logger_bufp; + int target_pdev_id; + int lmac_id = dp_get_lmac_id_for_pdev_id(soc->dp_soc, 0, mac_id); + QDF_STATUS status; /* Sizes should be set in 4-byte words */ ring_entry_size = ring_entry_size >> 2; @@ -593,9 +798,9 @@ int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng, if (!htt_msg) goto fail0; - hal_get_srng_params(soc->hal_soc, hal_srng, &srng_params); - hp_addr = hal_srng_get_hp_addr(soc->hal_soc, hal_srng); - tp_addr = hal_srng_get_tp_addr(soc->hal_soc, hal_srng); + hal_get_srng_params(soc->hal_soc, hal_ring_hdl, &srng_params); + hp_addr = hal_srng_get_hp_addr(soc->hal_soc, hal_ring_hdl); + tp_addr = hal_srng_get_tp_addr(soc->hal_soc, hal_ring_hdl); switch (hal_ring_type) { case RXDMA_BUF: @@ -613,7 +818,7 @@ int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng, #else if (srng_params.ring_id == (HAL_SRNG_WMAC1_SW2RXDMA0_BUF0 + - (mac_id * HAL_MAX_RINGS_PER_LMAC))) { + (lmac_id * HAL_MAX_RINGS_PER_LMAC))) { htt_ring_id = HTT_RXDMA_HOST_BUF_RING; htt_ring_type = HTT_SW_TO_HW_RING; #endif @@ -623,7 +828,7 @@ int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng, #else (HAL_SRNG_WMAC1_SW2RXDMA1_BUF + #endif - (mac_id * HAL_MAX_RINGS_PER_LMAC))) { + (lmac_id * HAL_MAX_RINGS_PER_LMAC))) { htt_ring_id = HTT_RXDMA_HOST_BUF_RING; htt_ring_type = HTT_SW_TO_HW_RING; } else { @@ -685,12 +890,14 @@ int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng, /* word 0 */ *msg_word = 0; + htt_logger_bufp = (uint8_t *)msg_word; HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_SRING_SETUP); + target_pdev_id = + dp_get_target_pdev_id_for_host_pdev_id(soc->dp_soc, mac_id); if ((htt_ring_type == HTT_SW_TO_HW_RING) || (htt_ring_type == HTT_HW_TO_SW_RING)) - HTT_SRING_SETUP_PDEV_ID_SET(*msg_word, - DP_SW2HW_MACID(mac_id)); + HTT_SRING_SETUP_PDEV_ID_SET(*msg_word, target_pdev_id); else HTT_SRING_SETUP_PDEV_ID_SET(*msg_word, mac_id); @@ -812,9 +1019,15 @@ int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng, HTC_TX_PACKET_TAG_RUNTIME_PUT); /* tag for no FW response msg */ SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg); - DP_HTT_SEND_HTC_PKT(soc, pkt); + status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_SRING_SETUP, + htt_logger_bufp); - return QDF_STATUS_SUCCESS; + if (status != QDF_STATUS_SUCCESS) { + qdf_nbuf_free(htt_msg); + htt_htc_pkt_free(soc, pkt); + } + + return status; fail1: qdf_nbuf_free(htt_msg); @@ -826,16 +1039,17 @@ int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng, * htt_h2t_rx_ring_cfg() - Send SRNG packet and TLV filter * config message to target * @htt_soc: HTT SOC handle - * @pdev_id: PDEV Id + * @pdev_id: WIN- PDEV Id, MCL- mac id * @hal_srng: Opaque HAL SRNG pointer * @hal_ring_type: SRNG ring type * @ring_buf_size: SRNG buffer size * @htt_tlv_filter: Rx SRNG TLV and filter setting * Return: 0 on success; error code on failure */ -int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, - int hal_ring_type, int ring_buf_size, - struct htt_rx_ring_tlv_filter *htt_tlv_filter) +int htt_h2t_rx_ring_cfg(struct htt_soc *htt_soc, int pdev_id, + hal_ring_handle_t hal_ring_hdl, + int hal_ring_type, int ring_buf_size, + struct htt_rx_ring_tlv_filter *htt_tlv_filter) { struct htt_soc *soc = (struct htt_soc *)htt_soc; struct dp_htt_htc_pkt *pkt; @@ -844,6 +1058,11 @@ int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, struct hal_srng_params srng_params; uint32_t htt_ring_type, htt_ring_id; uint32_t tlv_filter; + uint8_t *htt_logger_bufp; + struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx = soc->dp_soc->wlan_cfg_ctx; + uint32_t mon_drop_th = wlan_cfg_get_mon_drop_thresh(wlan_cfg_ctx); + int target_pdev_id; + QDF_STATUS status; htt_msg = qdf_nbuf_alloc(soc->osdev, HTT_MSG_BUF_SIZE(HTT_RX_RING_SELECTION_CFG_SZ), @@ -852,7 +1071,7 @@ int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, if (!htt_msg) goto fail0; - hal_get_srng_params(soc->hal_soc, hal_srng, &srng_params); + hal_get_srng_params(soc->hal_soc, hal_ring_hdl, &srng_params); switch (hal_ring_type) { case RXDMA_BUF: @@ -905,6 +1124,7 @@ int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, qdf_nbuf_push_head(htt_msg, HTC_HDR_ALIGNMENT_PADDING); /* word 0 */ + htt_logger_bufp = (uint8_t *)msg_word; *msg_word = 0; HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG); @@ -912,10 +1132,13 @@ int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, * pdev_id is indexed from 0 whereas mac_id is indexed from 1 * SW_TO_SW and SW_TO_HW rings are unaffected by this */ + target_pdev_id = + dp_get_target_pdev_id_for_host_pdev_id(soc->dp_soc, pdev_id); + if (htt_ring_type == HTT_SW_TO_SW_RING || htt_ring_type == HTT_SW_TO_HW_RING) HTT_RX_RING_SELECTION_CFG_PDEV_ID_SET(*msg_word, - DP_SW2HW_MACID(pdev_id)); + target_pdev_id); /* TODO: Discuss with FW on changing this to unique ID and using * htt_ring_type to send the type of ring @@ -931,6 +1154,13 @@ int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, HTT_RX_RING_SELECTION_CFG_RX_OFFSETS_VALID_SET(*msg_word, htt_tlv_filter->offset_valid); + if (mon_drop_th > 0) + HTT_RX_RING_SELECTION_CFG_DROP_THRESHOLD_VALID_SET(*msg_word, + 1); + else + HTT_RX_RING_SELECTION_CFG_DROP_THRESHOLD_VALID_SET(*msg_word, + 0); + /* word 1 */ msg_word++; *msg_word = 0; @@ -1494,8 +1724,17 @@ int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, *msg_word = 0; HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET_SET(*msg_word, htt_tlv_filter->rx_attn_offset); + msg_word++; + *msg_word = 0; + } else { + msg_word += 4; + *msg_word = 0; } + if (mon_drop_th > 0) + HTT_RX_RING_SELECTION_CFG_RX_DROP_THRESHOLD_SET(*msg_word, + mon_drop_th); + /* "response_required" field should be set if a HTT response message is * required after setting up the ring. */ @@ -1511,11 +1750,19 @@ int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, qdf_nbuf_data(htt_msg), qdf_nbuf_len(htt_msg), soc->htc_endpoint, - 1); /* tag - not relevant here */ + HTC_TX_PACKET_TAG_RUNTIME_PUT); /* tag for no FW response msg */ SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg); - DP_HTT_SEND_HTC_PKT(soc, pkt); - return QDF_STATUS_SUCCESS; + status = DP_HTT_SEND_HTC_PKT(soc, pkt, + HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG, + htt_logger_bufp); + + if (status != QDF_STATUS_SUCCESS) { + qdf_nbuf_free(htt_msg); + htt_htc_pkt_free(soc, pkt); + } + + return status; fail1: qdf_nbuf_free(htt_msg); @@ -1668,9 +1915,13 @@ static inline void dp_process_htt_stat_msg(struct htt_stats_context *htt_stats, } if (copy_stats) - dp_htt_stats_copy_tag(pdev, tlv_type, tlv_start); + dp_htt_stats_copy_tag(pdev, + tlv_type, + tlv_start); else - dp_htt_stats_print_tag(tlv_type, tlv_start); + dp_htt_stats_print_tag(pdev, + tlv_type, + tlv_start); if (tlv_type == HTT_STATS_PEER_DETAILS_TAG || tlv_type == HTT_STATS_PEER_STATS_CMN_TAG) @@ -1737,12 +1988,18 @@ void htt_t2h_stats_handler(void *context) uint32_t *msg_word; qdf_nbuf_t htt_msg = NULL; uint8_t done; - uint8_t rem_stats; + uint32_t rem_stats; + + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "soc is NULL"); + return; + } - if (!soc || !qdf_atomic_read(&soc->cmn_init_done)) { + if (!qdf_atomic_read(&soc->cmn_init_done)) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "soc: 0x%pK, init_done: %d", soc, - qdf_atomic_read(&soc->cmn_init_done)); + "soc: 0x%pK, init_done: %d", soc, + qdf_atomic_read(&soc->cmn_init_done)); return; } @@ -1770,10 +2027,14 @@ void htt_t2h_stats_handler(void *context) rem_stats = --soc->htt_stats.num_stats; qdf_spin_unlock_bh(&soc->htt_stats.lock); - dp_process_htt_stat_msg(&htt_stats, soc); - /* If there are more stats to process, schedule stats work again */ + /* If there are more stats to process, schedule stats work again. + * Scheduling prior to processing ht_stats to queue with early + * index + */ if (rem_stats) qdf_sched_work(0, &soc->htt_stats.work); + + dp_process_htt_stat_msg(&htt_stats, soc); } /* @@ -1828,28 +2089,37 @@ static void dp_process_ppdu_stats_common_tlv(struct dp_pdev *pdev, uint32_t *tag_buf, struct ppdu_info *ppdu_info) { uint16_t frame_type; + uint16_t frame_ctrl; uint16_t freq; struct dp_soc *soc = NULL; struct cdp_tx_completion_ppdu *ppdu_desc = NULL; + uint64_t ppdu_start_timestamp; + uint32_t *start_tag_buf; + start_tag_buf = tag_buf; ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); - tag_buf += 2; + tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(RING_ID_SCH_CMD_ID); ppdu_info->sched_cmdid = HTT_PPDU_STATS_COMMON_TLV_SCH_CMDID_GET(*tag_buf); ppdu_desc->num_users = HTT_PPDU_STATS_COMMON_TLV_NUM_USERS_GET(*tag_buf); - tag_buf++; + + tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(QTYPE_FRM_TYPE); frame_type = HTT_PPDU_STATS_COMMON_TLV_FRM_TYPE_GET(*tag_buf); + ppdu_desc->htt_frame_type = frame_type; + + frame_ctrl = ppdu_desc->frame_ctrl; switch (frame_type) { case HTT_STATS_FTYPE_TIDQ_DATA_SU: case HTT_STATS_FTYPE_TIDQ_DATA_MU: + case HTT_STATS_FTYPE_SGEN_QOS_NULL: /* * for management packet, frame type come as DATA_SU * need to check frame_ctrl before setting frame_type */ - if (HTT_GET_FRAME_CTRL_TYPE(frame_type) <= FRAME_CTRL_TYPE_CTRL) + if (HTT_GET_FRAME_CTRL_TYPE(frame_ctrl) <= FRAME_CTRL_TYPE_CTRL) ppdu_desc->frame_type = CDP_PPDU_FTYPE_CTRL; else ppdu_desc->frame_type = CDP_PPDU_FTYPE_DATA; @@ -1857,34 +2127,58 @@ static void dp_process_ppdu_stats_common_tlv(struct dp_pdev *pdev, case HTT_STATS_FTYPE_SGEN_MU_BAR: case HTT_STATS_FTYPE_SGEN_BAR: ppdu_desc->frame_type = CDP_PPDU_FTYPE_BAR; + ppdu_desc->bar_ppdu_id = ppdu_info->ppdu_id; break; default: ppdu_desc->frame_type = CDP_PPDU_FTYPE_CTRL; break; } - tag_buf += 2; + tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(FES_DUR_US); ppdu_desc->tx_duration = *tag_buf; - tag_buf += 3; - ppdu_desc->ppdu_start_timestamp = *tag_buf; - - ppdu_desc->ppdu_end_timestamp = ppdu_desc->ppdu_start_timestamp + - ppdu_desc->tx_duration; - /* Ack time stamp is same as end time stamp*/ - ppdu_desc->ack_timestamp = ppdu_desc->ppdu_end_timestamp; - tag_buf++; + tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(START_TSTMP_L32_US); + ppdu_desc->ppdu_start_timestamp = *tag_buf; + tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(CHAN_MHZ_PHY_MODE); freq = HTT_PPDU_STATS_COMMON_TLV_CHAN_MHZ_GET(*tag_buf); if (freq != ppdu_desc->channel) { soc = pdev->soc; ppdu_desc->channel = freq; if (soc && soc->cdp_soc.ol_ops->freq_to_channel) pdev->operating_channel = - soc->cdp_soc.ol_ops->freq_to_channel(pdev->ctrl_pdev, freq); + soc->cdp_soc.ol_ops->freq_to_channel(soc->ctrl_psoc, + pdev->pdev_id, freq); } ppdu_desc->phy_mode = HTT_PPDU_STATS_COMMON_TLV_PHY_MODE_GET(*tag_buf); + + tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(RESV_NUM_UL_BEAM); + ppdu_desc->beam_change = + HTT_PPDU_STATS_COMMON_TLV_BEAM_CHANGE_GET(*tag_buf); + + dp_tx_capture_htt_frame_counter(pdev, frame_type); + + tag_buf = start_tag_buf + HTT_GET_STATS_CMN_INDEX(START_TSTMP_U32_US); + ppdu_start_timestamp = *tag_buf; + ppdu_desc->ppdu_start_timestamp |= ((ppdu_start_timestamp << + HTT_SHIFT_UPPER_TIMESTAMP) & + HTT_MASK_UPPER_TIMESTAMP); + + ppdu_desc->ppdu_end_timestamp = ppdu_desc->ppdu_start_timestamp + + ppdu_desc->tx_duration; + /* Ack time stamp is same as end time stamp*/ + ppdu_desc->ack_timestamp = ppdu_desc->ppdu_end_timestamp; + + ppdu_desc->ppdu_end_timestamp = ppdu_desc->ppdu_start_timestamp + + ppdu_desc->tx_duration; + + ppdu_desc->bar_ppdu_start_timestamp = ppdu_desc->ppdu_start_timestamp; + ppdu_desc->bar_ppdu_end_timestamp = ppdu_desc->ppdu_end_timestamp; + ppdu_desc->bar_tx_duration = ppdu_desc->tx_duration; + + /* Ack time stamp is same as end time stamp*/ + ppdu_desc->ack_timestamp = ppdu_desc->ppdu_end_timestamp; } /* @@ -1902,6 +2196,8 @@ static void dp_process_ppdu_stats_user_common_tlv( struct cdp_tx_completion_ppdu *ppdu_desc; struct cdp_tx_completion_ppdu_user *ppdu_user_desc; uint8_t curr_user_index = 0; + struct dp_peer *peer; + struct dp_vdev *vdev; ppdu_desc = (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(ppdu_info->nbuf); @@ -1917,9 +2213,20 @@ static void dp_process_ppdu_stats_user_common_tlv( if (peer_id == DP_SCAN_PEER_ID) { ppdu_desc->vdev_id = HTT_PPDU_STATS_USER_COMMON_TLV_VAP_ID_GET(*tag_buf); + vdev = + dp_get_vdev_from_soc_vdev_id_wifi3(pdev->soc, + ppdu_desc->vdev_id); + if (!vdev) + return; + qdf_mem_copy(ppdu_user_desc->mac_addr, vdev->mac_addr.raw, + QDF_MAC_ADDR_SIZE); } else { - if (!dp_peer_find_by_id_valid(pdev->soc, peer_id)) + peer = dp_peer_find_by_id(pdev->soc, peer_id); + if (!peer) return; + qdf_mem_copy(ppdu_user_desc->mac_addr, + peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); + dp_peer_unref_del_find_by_id(peer); } ppdu_user_desc->peer_id = peer_id; @@ -1928,6 +2235,7 @@ static void dp_process_ppdu_stats_user_common_tlv( if (HTT_PPDU_STATS_USER_COMMON_TLV_DELAYED_BA_GET(*tag_buf)) { ppdu_user_desc->delayed_ba = 1; + ppdu_desc->delayed_ba = 1; } if (HTT_PPDU_STATS_USER_COMMON_TLV_MCAST_GET(*tag_buf)) { @@ -1948,11 +2256,8 @@ static void dp_process_ppdu_stats_user_common_tlv( HTT_PPDU_STATS_USER_COMMON_TLV_FRAME_CTRL_GET(*tag_buf); ppdu_desc->frame_ctrl = ppdu_user_desc->frame_ctrl; - if (ppdu_user_desc->delayed_ba) { + if (ppdu_user_desc->delayed_ba) ppdu_user_desc->mpdu_success = 0; - ppdu_user_desc->mpdu_tried_mcast = 0; - ppdu_user_desc->mpdu_tried_ucast = 0; - } tag_buf += 3; @@ -1998,14 +2303,10 @@ static void dp_process_ppdu_stats_user_rate_tlv(struct dp_pdev *pdev, ppdu_desc->vdev_id); if (!vdev) return; - qdf_mem_copy(ppdu_user_desc->mac_addr, vdev->mac_addr.raw, - QDF_MAC_ADDR_SIZE); } else { peer = dp_peer_find_by_id(pdev->soc, peer_id); if (!peer) return; - qdf_mem_copy(ppdu_user_desc->mac_addr, - peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); dp_peer_unref_del_find_by_id(peer); } @@ -2167,6 +2468,7 @@ static void dp_process_ppdu_stats_user_cmpltn_common_tlv( struct cdp_tx_completion_ppdu *ppdu_desc; struct cdp_tx_completion_ppdu_user *ppdu_user_desc; uint8_t curr_user_index = 0; + uint8_t bw_iter; htt_ppdu_stats_user_cmpltn_common_tlv *dp_stats_buf = (htt_ppdu_stats_user_cmpltn_common_tlv *)tag_buf; @@ -2206,6 +2508,10 @@ static void dp_process_ppdu_stats_user_cmpltn_common_tlv( ppdu_user_desc->mpdu_success = HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MPDU_SUCCESS_GET(*tag_buf); + ppdu_user_desc->mpdu_failed = + HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MPDU_TRIED_GET(*tag_buf) - + ppdu_user_desc->mpdu_success; + tag_buf++; ppdu_user_desc->long_retries = @@ -2220,6 +2526,56 @@ static void dp_process_ppdu_stats_user_cmpltn_common_tlv( HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_IS_AMPDU_GET(*tag_buf); ppdu_info->is_ampdu = ppdu_user_desc->is_ampdu; + ppdu_desc->resp_type = + HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_RESP_TYPE_GET(*tag_buf); + ppdu_desc->mprot_type = + HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MPROT_TYPE_GET(*tag_buf); + ppdu_desc->rts_success = + HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_RTS_SUCCESS_GET(*tag_buf); + ppdu_desc->rts_failure = + HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_RTS_FAILURE_GET(*tag_buf); + + /* + * increase successful mpdu counter from + * htt_ppdu_stats_user_cmpltn_common_tlv + */ + ppdu_info->mpdu_compltn_common_tlv += ppdu_user_desc->mpdu_success; + + /* + * MU BAR may send request to n users but we may received ack only from + * m users. To have count of number of users respond back, we have a + * separate counter bar_num_users per PPDU that get increment for every + * htt_ppdu_stats_user_cmpltn_common_tlv + */ + ppdu_desc->bar_num_users++; + + tag_buf++; + for (bw_iter = 0; bw_iter < CDP_RSSI_CHAIN_LEN; bw_iter++) { + ppdu_user_desc->rssi_chain[bw_iter] = + HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_CHAIN_RSSI_GET(*tag_buf); + tag_buf++; + } + + ppdu_user_desc->sa_tx_antenna = + HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_TX_ANTENNA_MASK_GET(*tag_buf); + + tag_buf++; + ppdu_user_desc->sa_is_training = + HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_IS_TRAINING_GET(*tag_buf); + if (ppdu_user_desc->sa_is_training) { + ppdu_user_desc->sa_goodput = + HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_PENDING_TRAINING_PKTS_GET(*tag_buf); + } + + tag_buf++; + for (bw_iter = 0; bw_iter < CDP_NUM_SA_BW; bw_iter++) { + ppdu_user_desc->sa_max_rates[bw_iter] = + HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MAX_RATES_GET(tag_buf[bw_iter]); + } + + tag_buf += CDP_NUM_SA_BW; + ppdu_user_desc->current_rate_per = + HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_CURRENT_RATE_PER_GET(*tag_buf); } /* @@ -2260,6 +2616,7 @@ static void dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv( ppdu_user_desc->ba_seq_no = dp_stats_buf->ba_seq_no; qdf_mem_copy(&ppdu_user_desc->ba_bitmap, &dp_stats_buf->ba_bitmap, sizeof(uint32_t) * CDP_BA_64_BIT_MAP_SIZE_DWORDS); + ppdu_user_desc->ba_size = CDP_BA_64_BIT_MAP_SIZE_DWORDS * 32; } /* @@ -2300,6 +2657,7 @@ static void dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv( ppdu_user_desc->ba_seq_no = dp_stats_buf->ba_seq_no; qdf_mem_copy(&ppdu_user_desc->ba_bitmap, &dp_stats_buf->ba_bitmap, sizeof(uint32_t) * CDP_BA_256_BIT_MAP_SIZE_DWORDS); + ppdu_user_desc->ba_size = CDP_BA_256_BIT_MAP_SIZE_DWORDS * 32; } /* @@ -2335,8 +2693,7 @@ static void dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv( ppdu_user_desc->peer_id = peer_id; tag_buf++; - ppdu_user_desc->tid = - HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_TID_NUM_GET(*tag_buf); + /* not to update ppdu_desc->tid from this TLV */ ppdu_user_desc->num_mpdu = HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_NUM_MPDU_GET(*tag_buf); @@ -2345,9 +2702,16 @@ static void dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv( ppdu_user_desc->success_msdus = ppdu_user_desc->num_msdu; - tag_buf += 2; + tag_buf++; + ppdu_user_desc->start_seq = + HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_START_SEQ_GET( + *tag_buf); + + tag_buf++; ppdu_user_desc->success_bytes = *tag_buf; + /* increase successful mpdu counter */ + ppdu_info->mpdu_ack_ba_tlv += ppdu_user_desc->num_mpdu; } /* @@ -2406,37 +2770,50 @@ static void dp_process_ppdu_stats_user_common_array_tlv( * htt_ppdu_stats_flush_tlv * @pdev: DP PDEV handle * @tag_buf: buffer containing the htt_ppdu_stats_flush_tlv + * @ppdu_info: per ppdu tlv structure * * return:void */ -static void dp_process_ppdu_stats_user_compltn_flush_tlv(struct dp_pdev *pdev, - uint32_t *tag_buf) +static void +dp_process_ppdu_stats_user_compltn_flush_tlv(struct dp_pdev *pdev, + uint32_t *tag_buf, + struct ppdu_info *ppdu_info) { + struct cdp_tx_completion_ppdu *ppdu_desc; uint32_t peer_id; - uint32_t drop_reason; uint8_t tid; - uint32_t num_msdu; struct dp_peer *peer; + ppdu_desc = (struct cdp_tx_completion_ppdu *) + qdf_nbuf_data(ppdu_info->nbuf); + ppdu_desc->is_flush = 1; + tag_buf++; - drop_reason = *tag_buf; + ppdu_desc->drop_reason = *tag_buf; tag_buf++; - num_msdu = HTT_PPDU_STATS_FLUSH_TLV_NUM_MSDU_GET(*tag_buf); + ppdu_desc->num_msdu = HTT_PPDU_STATS_FLUSH_TLV_NUM_MSDU_GET(*tag_buf); + ppdu_desc->num_mpdu = HTT_PPDU_STATS_FLUSH_TLV_NUM_MPDU_GET(*tag_buf); + ppdu_desc->flow_type = HTT_PPDU_STATS_FLUSH_TLV_FLOW_TYPE_GET(*tag_buf); tag_buf++; - peer_id = - HTT_PPDU_STATS_FLUSH_TLV_SW_PEER_ID_GET(*tag_buf); + peer_id = HTT_PPDU_STATS_FLUSH_TLV_SW_PEER_ID_GET(*tag_buf); + tid = HTT_PPDU_STATS_FLUSH_TLV_TID_NUM_GET(*tag_buf); + + ppdu_desc->user[0].peer_id = peer_id; + ppdu_desc->user[0].tid = tid; + + ppdu_desc->queue_type = + HTT_PPDU_STATS_FLUSH_TLV_QUEUE_TYPE_GET(*tag_buf); peer = dp_peer_find_by_id(pdev->soc, peer_id); if (!peer) return; - tid = HTT_PPDU_STATS_FLUSH_TLV_TID_NUM_GET(*tag_buf); - - if (drop_reason == HTT_FLUSH_EXCESS_RETRIES) { - DP_STATS_INC(peer, tx.excess_retries_per_ac[TID_TO_WME_AC(tid)], - num_msdu); + if (ppdu_desc->drop_reason == HTT_FLUSH_EXCESS_RETRIES) { + DP_STATS_INC(peer, + tx.excess_retries_per_ac[TID_TO_WME_AC(tid)], + ppdu_desc->num_msdu); } dp_peer_unref_del_find_by_id(peer); @@ -2450,7 +2827,7 @@ static void dp_process_ppdu_stats_user_compltn_flush_tlv(struct dp_pdev *pdev, * * return: void */ -static void dp_deliver_mgmt_frm(struct dp_pdev *pdev, qdf_nbuf_t nbuf) +void dp_deliver_mgmt_frm(struct dp_pdev *pdev, qdf_nbuf_t nbuf) { if (pdev->tx_sniffer_enable || pdev->mcopy_mode) { dp_wdi_event_handler(WDI_EVENT_TX_MGMT_CTRL, pdev->soc, @@ -2476,11 +2853,22 @@ dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv(struct dp_pdev *pdev, { uint32_t *nbuf_ptr; uint8_t trim_size; + size_t head_size; + struct cdp_tx_mgmt_comp_info *ptr_mgmt_comp_info; + uint32_t *msg_word; + uint32_t tsf_hdr; if ((!pdev->tx_sniffer_enable) && (!pdev->mcopy_mode) && (!pdev->bpr_enable) && (!pdev->tx_capture_enabled)) return QDF_STATUS_SUCCESS; + /* + * get timestamp from htt_t2h_ppdu_stats_ind_hdr_t + */ + msg_word = (uint32_t *)qdf_nbuf_data(tag_buf); + msg_word = msg_word + 2; + tsf_hdr = *msg_word; + trim_size = ((pdev->mgmtctrl_frm_info.mgmt_buf + HTT_MGMT_CTRL_TLV_HDR_RESERVERD_LEN) - qdf_nbuf_data(tag_buf)); @@ -2491,9 +2879,25 @@ dp_process_ppdu_stats_tx_mgmtctrl_payload_tlv(struct dp_pdev *pdev, qdf_nbuf_trim_tail(tag_buf, qdf_nbuf_len(tag_buf) - pdev->mgmtctrl_frm_info.mgmt_buf_len); - nbuf_ptr = (uint32_t *)qdf_nbuf_push_head( - tag_buf, sizeof(ppdu_id)); - *nbuf_ptr = ppdu_id; + if (pdev->tx_capture_enabled) { + head_size = sizeof(struct cdp_tx_mgmt_comp_info); + if (qdf_unlikely(qdf_nbuf_headroom(tag_buf) < head_size)) { + qdf_err("Fail to get headroom h_sz %d h_avail %d\n", + head_size, qdf_nbuf_headroom(tag_buf)); + qdf_assert_always(0); + return QDF_STATUS_E_NOMEM; + } + ptr_mgmt_comp_info = (struct cdp_tx_mgmt_comp_info *) + qdf_nbuf_push_head(tag_buf, head_size); + qdf_assert_always(ptr_mgmt_comp_info); + ptr_mgmt_comp_info->ppdu_id = ppdu_id; + ptr_mgmt_comp_info->is_sgen_pkt = true; + ptr_mgmt_comp_info->tx_tsf = tsf_hdr; + } else { + head_size = sizeof(ppdu_id); + nbuf_ptr = (uint32_t *)qdf_nbuf_push_head(tag_buf, head_size); + *nbuf_ptr = ppdu_id; + } if (pdev->bpr_enable) { dp_wdi_event_handler(WDI_EVENT_TX_BEACON, pdev->soc, @@ -2635,8 +3039,8 @@ static void dp_process_ppdu_tag(struct dp_pdev *pdev, uint32_t *tag_buf, tlv_expected_size = sizeof(htt_ppdu_stats_flush_tlv); tlv_desc = dp_validate_fix_ppdu_tlv(pdev, tag_buf, tlv_expected_size, tlv_len); - dp_process_ppdu_stats_user_compltn_flush_tlv( - pdev, tlv_desc); + dp_process_ppdu_stats_user_compltn_flush_tlv(pdev, tlv_desc, + ppdu_info); break; default: break; @@ -2659,6 +3063,7 @@ dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, uint32_t tlv_bitmap_expected; uint32_t tlv_bitmap_default; uint16_t i; + uint32_t num_users; ppdu_desc = (struct cdp_tx_completion_ppdu *) qdf_nbuf_data(ppdu_info->nbuf); @@ -2667,7 +3072,8 @@ dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, ppdu_desc->ppdu_id = ppdu_info->ppdu_id; tlv_bitmap_expected = HTT_PPDU_DEFAULT_TLV_BITMAP; - if (pdev->tx_sniffer_enable || pdev->mcopy_mode) { + if (pdev->tx_sniffer_enable || pdev->mcopy_mode || + pdev->tx_capture_enabled) { if (ppdu_info->is_ampdu) tlv_bitmap_expected = dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap( @@ -2675,7 +3081,15 @@ dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, } tlv_bitmap_default = tlv_bitmap_expected; - for (i = 0; i < ppdu_desc->num_users; i++) { + + if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR) { + num_users = ppdu_desc->bar_num_users; + ppdu_desc->num_users = ppdu_desc->bar_num_users; + } else { + num_users = ppdu_desc->num_users; + } + + for (i = 0; i < num_users; i++) { ppdu_desc->num_mpdu += ppdu_desc->user[i].num_mpdu; ppdu_desc->num_msdu += ppdu_desc->user[i].num_msdu; @@ -2689,23 +3103,40 @@ dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, continue; ppdu_desc->user[i].cookie = (void *)peer->wlanstats_ctx; - if (ppdu_desc->user[i].completion_status != - HTT_PPDU_STATS_USER_STATUS_OK) - tlv_bitmap_expected = tlv_bitmap_expected & 0xFF; - if (ppdu_info->tlv_bitmap != tlv_bitmap_expected) { + /* + * different frame like DATA, BAR or CTRL has different + * tlv bitmap expected. Apart from ACK_BA_STATUS TLV, we + * receive other tlv in-order/sequential from fw. + * Since ACK_BA_STATUS TLV come from Hardware it is + * asynchronous So we need to depend on some tlv to confirm + * all tlv is received for a ppdu. + * So we depend on both HTT_PPDU_STATS_COMMON_TLV and + * ACK_BA_STATUS_TLV. for failure packet we won't get + * ACK_BA_STATUS_TLV. + */ + if (!(ppdu_info->tlv_bitmap & + (1 << HTT_PPDU_STATS_COMMON_TLV)) || + (!(ppdu_info->tlv_bitmap & + (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV)) && + (ppdu_desc->user[i].completion_status == + HTT_PPDU_STATS_USER_STATUS_OK))) { dp_peer_unref_del_find_by_id(peer); continue; } + /** * Update tx stats for data frames having Qos as well as * non-Qos data tid */ + if ((ppdu_desc->user[i].tid < CDP_DATA_TID_MAX || - (ppdu_desc->user[i].tid == CDP_DATA_NON_QOS_TID)) && - (ppdu_desc->frame_type == CDP_PPDU_FTYPE_DATA)) { + (ppdu_desc->user[i].tid == CDP_DATA_NON_QOS_TID) || + (ppdu_desc->htt_frame_type == + HTT_STATS_FTYPE_SGEN_QOS_NULL)) && + (ppdu_desc->frame_type != CDP_PPDU_FTYPE_CTRL)) { - dp_tx_stats_update(pdev->soc, peer, + dp_tx_stats_update(pdev, peer, &ppdu_desc->user[i], ppdu_desc->ack_rssi); dp_tx_rate_stats_update(peer, &ppdu_desc->user[i]); @@ -2815,6 +3246,15 @@ struct ppdu_info *dp_get_ppdu_desc(struct dp_pdev *pdev, uint32_t ppdu_id, (1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV))) return ppdu_info; + /** + * apart from ACK BA STATUS TLV rest all comes in order + * so if tlv type not ACK BA STATUS TLV we can deliver + * ppdu_info + */ + if (tlv_type == + HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) + return ppdu_info; + dp_ppdu_desc_deliver(pdev, ppdu_info); } else { return ppdu_info; @@ -2889,6 +3329,8 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev, uint8_t *tlv_buf; struct ppdu_info *ppdu_info = NULL; struct cdp_tx_completion_ppdu *ppdu_desc = NULL; + struct dp_peer *peer; + uint32_t i = 0; uint32_t *msg_word = (uint32_t *) qdf_nbuf_data(htt_t2h_msg); @@ -2918,8 +3360,10 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev, */ if (tlv_type == HTT_PPDU_STATS_TX_MGMTCTRL_PAYLOAD_TLV) { pdev->mgmtctrl_frm_info.mgmt_buf = tlv_buf; - pdev->mgmtctrl_frm_info.mgmt_buf_len = tlv_length; pdev->mgmtctrl_frm_info.ppdu_id = ppdu_id; + pdev->mgmtctrl_frm_info.mgmt_buf_len = + HTT_PPDU_STATS_TX_MGMTCTRL_TLV_FRAME_LENGTH_GET + (*(msg_word + 1)); msg_word = (uint32_t *)((uint8_t *)tlv_buf + tlv_length); length -= (tlv_length); @@ -2929,6 +3373,9 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev, ppdu_info = dp_get_ppdu_desc(pdev, ppdu_id, tlv_type); if (!ppdu_info) return NULL; + ppdu_info->ppdu_desc->bss_color = + pdev->rx_mon_recv_status.bsscolor; + ppdu_info->ppdu_id = ppdu_id; ppdu_info->tlv_bitmap |= (1 << tlv_type); @@ -2951,26 +3398,111 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev, tlv_bitmap_expected = HTT_PPDU_DEFAULT_TLV_BITMAP; + if (pdev->tx_sniffer_enable || pdev->mcopy_mode || + pdev->tx_capture_enabled) { + if (ppdu_info->is_ampdu) + tlv_bitmap_expected = + dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap( + ppdu_info->tlv_bitmap); + } + ppdu_desc = ppdu_info->ppdu_desc; - if (ppdu_desc && - ppdu_desc->user[ppdu_desc->last_usr_index].completion_status != + + if (!ppdu_desc) + return NULL; + + if (ppdu_desc->user[ppdu_desc->last_usr_index].completion_status != HTT_PPDU_STATS_USER_STATUS_OK) { tlv_bitmap_expected = tlv_bitmap_expected & 0xFF; } - if (pdev->tx_sniffer_enable || pdev->mcopy_mode) { - if (ppdu_info->is_ampdu) - tlv_bitmap_expected = - dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap( - ppdu_info->tlv_bitmap); + if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_DATA && + (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_COMMON_TLV)) && + ppdu_desc->delayed_ba) { + for (i = 0; i < ppdu_desc->num_users; i++) { + uint32_t ppdu_id; + + ppdu_id = ppdu_desc->ppdu_id; + peer = dp_peer_find_by_id(pdev->soc, + ppdu_desc->user[i].peer_id); + /** + * This check is to make sure peer is not deleted + * after processing the TLVs. + */ + if (!peer) + continue; + + /** + * save delayed ba user info + */ + if (ppdu_desc->user[i].delayed_ba) { + dp_peer_copy_delay_stats(peer, + &ppdu_desc->user[i]); + peer->last_delayed_ba_ppduid = ppdu_id; + } + dp_peer_unref_del_find_by_id(peer); + } + } + + /* + * when frame type is BAR and STATS_COMMON_TLV is set + * copy the store peer delayed info to BAR status + */ + if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR && + (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_COMMON_TLV))) { + for (i = 0; i < ppdu_desc->bar_num_users; i++) { + peer = dp_peer_find_by_id(pdev->soc, + ppdu_desc->user[i].peer_id); + /** + * This check is to make sure peer is not deleted + * after processing the TLVs. + */ + if (!peer) + continue; + + if (peer->last_delayed_ba) { + dp_peer_copy_stats_to_bar(peer, + &ppdu_desc->user[i]); + ppdu_desc->bar_ppdu_id = ppdu_desc->ppdu_id; + ppdu_desc->ppdu_id = + peer->last_delayed_ba_ppduid; + } + dp_peer_unref_del_find_by_id(peer); + } + } + + /* + * for frame type DATA and BAR, we update stats based on MSDU, + * successful msdu and mpdu are populate from ACK BA STATUS TLV + * which comes out of order. successful mpdu also populated from + * COMPLTN COMMON TLV which comes in order. for every ppdu_info + * we store successful mpdu from both tlv and compare before delivering + * to make sure we received ACK BA STATUS TLV. For some self generated + * frame we won't get ack ba status tlv so no need to wait for + * ack ba status tlv. + */ + if (ppdu_desc->frame_type != CDP_PPDU_FTYPE_CTRL && + ppdu_desc->htt_frame_type != HTT_STATS_FTYPE_SGEN_QOS_NULL) { + /* + * successful mpdu count should match with both tlv + */ + if (ppdu_info->mpdu_compltn_common_tlv != + ppdu_info->mpdu_ack_ba_tlv) + return NULL; } /** * Once all the TLVs for a given PPDU has been processed, - * return PPDU status to be delivered to higher layer + * return PPDU status to be delivered to higher layer. + * tlv_bitmap_expected can't be available for different frame type. + * But STATS COMMON TLV is the last TLV from the FW for a ppdu. + * apart from ACK BA TLV, FW sends other TLV in sequential order. + * flush tlv comes separate. */ - if (ppdu_info->tlv_bitmap != 0 && - ppdu_info->tlv_bitmap == tlv_bitmap_expected) + if ((ppdu_info->tlv_bitmap != 0 && + (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_COMMON_TLV))) || + (ppdu_info->tlv_bitmap & + (1 << HTT_PPDU_STATS_USR_COMPLTN_FLUSH_TLV))) return ppdu_info; return NULL; @@ -3008,17 +3540,15 @@ static bool dp_txrx_ppdu_stats_handler(struct dp_soc *soc, (pdev, htt_t2h_msg, pdev->mgmtctrl_frm_info.ppdu_id) != QDF_STATUS_SUCCESS) free_buf = false; - - if (free_buf) { - pdev->mgmtctrl_frm_info.mgmt_buf = NULL; - pdev->mgmtctrl_frm_info.mgmt_buf_len = 0; - pdev->mgmtctrl_frm_info.ppdu_id = 0; - } } if (ppdu_info) dp_ppdu_desc_deliver(pdev, ppdu_info); + pdev->mgmtctrl_frm_info.mgmt_buf = NULL; + pdev->mgmtctrl_frm_info.mgmt_buf_len = 0; + pdev->mgmtctrl_frm_info.ppdu_id = 0; + return free_buf; } #else @@ -3100,34 +3630,85 @@ static inline void dp_txrx_fw_stats_handler(struct dp_soc *soc, * * Return: 0 on success; error code on failure */ -int htt_soc_attach_target(void *htt_soc) +int htt_soc_attach_target(struct htt_soc *htt_soc) { struct htt_soc *soc = (struct htt_soc *)htt_soc; return htt_h2t_ver_req_msg(soc); } +void htt_set_htc_handle(struct htt_soc *htt_soc, HTC_HANDLE htc_soc) +{ + htt_soc->htc_soc = htc_soc; +} -#if defined(WDI_EVENT_ENABLE) && !defined(REMOVE_PKT_LOG) -/* - * dp_ppdu_stats_ind_handler() - PPDU stats msg handler - * @htt_soc: HTT SOC handle - * @msg_word: Pointer to payload - * @htt_t2h_msg: HTT msg nbuf - * - * Return: True if buffer should be freed by caller. - */ -static bool -dp_ppdu_stats_ind_handler(struct htt_soc *soc, - uint32_t *msg_word, - qdf_nbuf_t htt_t2h_msg) +HTC_HANDLE htt_get_htc_handle(struct htt_soc *htt_soc) { - u_int8_t pdev_id; - bool free_buf; - qdf_nbuf_set_pktlen(htt_t2h_msg, HTT_T2H_MAX_MSG_SIZE); - pdev_id = HTT_T2H_PPDU_STATS_PDEV_ID_GET(*msg_word); - pdev_id = DP_HW2SW_MACID(pdev_id); - free_buf = dp_txrx_ppdu_stats_handler(soc->dp_soc, pdev_id, + return htt_soc->htc_soc; +} + +struct htt_soc *htt_soc_attach(struct dp_soc *soc, HTC_HANDLE htc_handle) +{ + int i; + int j; + int alloc_size = HTT_SW_UMAC_RING_IDX_MAX * sizeof(unsigned long); + struct htt_soc *htt_soc = NULL; + + htt_soc = qdf_mem_malloc(sizeof(*htt_soc)); + if (!htt_soc) { + dp_err("HTT attach failed"); + return NULL; + } + + for (i = 0; i < MAX_PDEV_CNT; i++) { + htt_soc->pdevid_tt[i].umac_ttt = qdf_mem_malloc(alloc_size); + if (!htt_soc->pdevid_tt[i].umac_ttt) + break; + qdf_mem_set(htt_soc->pdevid_tt[i].umac_ttt, alloc_size, -1); + htt_soc->pdevid_tt[i].lmac_ttt = qdf_mem_malloc(alloc_size); + if (!htt_soc->pdevid_tt[i].lmac_ttt) { + qdf_mem_free(htt_soc->pdevid_tt[i].umac_ttt); + break; + } + qdf_mem_set(htt_soc->pdevid_tt[i].lmac_ttt, alloc_size, -1); + } + if (i != MAX_PDEV_CNT) { + for (j = 0; j < i; j++) { + qdf_mem_free(htt_soc->pdevid_tt[i].umac_ttt); + qdf_mem_free(htt_soc->pdevid_tt[i].lmac_ttt); + } + return NULL; + } + + htt_soc->dp_soc = soc; + htt_soc->htc_soc = htc_handle; + HTT_TX_MUTEX_INIT(&htt_soc->htt_tx_mutex); + + return htt_soc; +} + +#if defined(WDI_EVENT_ENABLE) && !defined(REMOVE_PKT_LOG) +/* + * dp_ppdu_stats_ind_handler() - PPDU stats msg handler + * @htt_soc: HTT SOC handle + * @msg_word: Pointer to payload + * @htt_t2h_msg: HTT msg nbuf + * + * Return: True if buffer should be freed by caller. + */ +static bool +dp_ppdu_stats_ind_handler(struct htt_soc *soc, + uint32_t *msg_word, + qdf_nbuf_t htt_t2h_msg) +{ + u_int8_t pdev_id; + u_int8_t target_pdev_id; + bool free_buf; + qdf_nbuf_set_pktlen(htt_t2h_msg, HTT_T2H_MAX_MSG_SIZE); + target_pdev_id = HTT_T2H_PPDU_STATS_PDEV_ID_GET(*msg_word); + pdev_id = dp_get_host_pdev_id_for_target_pdev_id(soc->dp_soc, + target_pdev_id); + free_buf = dp_txrx_ppdu_stats_handler(soc->dp_soc, pdev_id, htt_t2h_msg); dp_wdi_event_handler(WDI_EVENT_LITE_T2H, soc->dp_soc, htt_t2h_msg, HTT_INVALID_PEER, WDI_NO_VAL, @@ -3158,10 +3739,12 @@ dp_pktlog_msg_handler(struct htt_soc *soc, uint32_t *msg_word) { uint8_t pdev_id; + uint8_t target_pdev_id; uint32_t *pl_hdr; - pdev_id = HTT_T2H_PKTLOG_PDEV_ID_GET(*msg_word); - pdev_id = DP_HW2SW_MACID(pdev_id); + target_pdev_id = HTT_T2H_PKTLOG_PDEV_ID_GET(*msg_word); + pdev_id = dp_get_host_pdev_id_for_target_pdev_id(soc->dp_soc, + target_pdev_id); pl_hdr = (msg_word + 1); dp_wdi_event_handler(WDI_EVENT_OFFLOAD_ALL, soc->dp_soc, pl_hdr, HTT_INVALID_PEER, WDI_NO_VAL, @@ -3174,6 +3757,109 @@ dp_pktlog_msg_handler(struct htt_soc *soc, { } #endif + +/* + * time_allow_print() - time allow print + * @htt_ring_tt: ringi_id array of timestamps + * @ring_id: ring_id (index) + * + * Return: 1 for successfully saving timestamp in array + * and 0 for timestamp falling within 2 seconds after last one + */ +static bool time_allow_print(unsigned long *htt_ring_tt, u_int8_t ring_id) +{ + unsigned long tstamp; + unsigned long delta; + + tstamp = qdf_get_system_timestamp(); + + if (!htt_ring_tt) + return 0; //unable to print backpressure messages + + if (htt_ring_tt[ring_id] == -1) { + htt_ring_tt[ring_id] = tstamp; + return 1; + } + delta = tstamp - htt_ring_tt[ring_id]; + if (delta >= 2000) { + htt_ring_tt[ring_id] = tstamp; + return 1; + } + + return 0; +} + +static void dp_htt_alert_print(enum htt_t2h_msg_type msg_type, + u_int8_t pdev_id, u_int8_t ring_id, + u_int16_t hp_idx, u_int16_t tp_idx, + u_int32_t bkp_time, char *ring_stype) +{ + dp_alert("msg_type: %d pdev_id: %d ring_type: %s ", + msg_type, pdev_id, ring_stype); + dp_alert("ring_id: %d hp_idx: %d tp_idx: %d bkpressure_time_ms: %d ", + ring_id, hp_idx, tp_idx, bkp_time); +} + +/* + * dp_htt_bkp_event_alert() - htt backpressure event alert + * @msg_word: htt packet context + * @htt_soc: HTT SOC handle + * + * Return: after attempting to print stats + */ +static void dp_htt_bkp_event_alert(u_int32_t *msg_word, struct htt_soc *soc) +{ + u_int8_t ring_type; + u_int8_t pdev_id; + uint8_t target_pdev_id; + u_int8_t ring_id; + u_int16_t hp_idx; + u_int16_t tp_idx; + u_int32_t bkp_time; + enum htt_t2h_msg_type msg_type; + struct dp_soc *dpsoc; + struct dp_pdev *pdev; + struct dp_htt_timestamp *radio_tt; + + if (!soc) + return; + + dpsoc = (struct dp_soc *)soc->dp_soc; + msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); + ring_type = HTT_T2H_RX_BKPRESSURE_RING_TYPE_GET(*msg_word); + target_pdev_id = HTT_T2H_RX_BKPRESSURE_PDEV_ID_GET(*msg_word); + pdev_id = dp_get_host_pdev_id_for_target_pdev_id(soc->dp_soc, + target_pdev_id); + pdev = (struct dp_pdev *)dpsoc->pdev_list[pdev_id]; + ring_id = HTT_T2H_RX_BKPRESSURE_RINGID_GET(*msg_word); + hp_idx = HTT_T2H_RX_BKPRESSURE_HEAD_IDX_GET(*(msg_word + 1)); + tp_idx = HTT_T2H_RX_BKPRESSURE_TAIL_IDX_GET(*(msg_word + 1)); + bkp_time = HTT_T2H_RX_BKPRESSURE_TIME_MS_GET(*(msg_word + 2)); + radio_tt = &soc->pdevid_tt[pdev_id]; + + switch (ring_type) { + case HTT_SW_RING_TYPE_UMAC: + if (!time_allow_print(radio_tt->umac_ttt, ring_id)) + return; + dp_htt_alert_print(msg_type, pdev_id, ring_id, hp_idx, tp_idx, + bkp_time, "HTT_SW_RING_TYPE_UMAC"); + break; + case HTT_SW_RING_TYPE_LMAC: + if (!time_allow_print(radio_tt->lmac_ttt, ring_id)) + return; + dp_htt_alert_print(msg_type, pdev_id, ring_id, hp_idx, tp_idx, + bkp_time, "HTT_SW_RING_TYPE_LMAC"); + break; + default: + dp_htt_alert_print(msg_type, pdev_id, ring_id, hp_idx, tp_idx, + bkp_time, "UNKNOWN"); + break; + } + + dp_print_ring_stats(pdev); + dp_print_napi_stats(pdev->soc); +} + /* * dp_htt_t2h_msg_handler() - Generic Target to host Msg/event handler * @context: Opaque context (HTT SOC handle) @@ -3200,7 +3886,14 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) msg_word = (u_int32_t *) qdf_nbuf_data(htt_t2h_msg); msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); + htt_event_record(soc->htt_logger_handle, + msg_type, (uint8_t *)msg_word); switch (msg_type) { + case HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND: + { + dp_htt_bkp_event_alert(msg_word, soc); + break; + } case HTT_T2H_MSG_TYPE_PEER_MAP: { u_int8_t mac_addr_deswizzle_buf[QDF_MAC_ADDR_SIZE]; @@ -3280,17 +3973,27 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) case HTT_T2H_MSG_TYPE_VERSION_CONF: { - htc_pm_runtime_put(soc->htc_soc); + /* + * HTC maintains runtime pm count for H2T messages that + * have a response msg from FW. This count ensures that + * in the case FW does not sent out the response or host + * did not process this indication runtime_put happens + * properly in the cleanup path. + */ + if (htc_dec_return_runtime_cnt(soc->htc_soc) >= 0) + htc_pm_runtime_put(soc->htc_soc); + else + soc->stats.htt_ver_req_put_skip++; soc->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word); soc->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word); - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_LOW, "target uses HTT version %d.%d; host uses %d.%d", soc->tgt_ver.major, soc->tgt_ver.minor, HTT_CURRENT_VERSION_MAJOR, HTT_CURRENT_VERSION_MINOR); if (soc->tgt_ver.major != HTT_CURRENT_VERSION_MAJOR) { QDF_TRACE(QDF_MODULE_ID_TXRX, - QDF_TRACE_LEVEL_ERROR, + QDF_TRACE_LEVEL_WARN, "*** Incompatible host/target HTT versions!"); } /* abort if the target is incompatible with the host */ @@ -3298,7 +4001,7 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) HTT_CURRENT_VERSION_MAJOR); if (soc->tgt_ver.minor != HTT_CURRENT_VERSION_MINOR) { QDF_TRACE(QDF_MODULE_ID_TXRX, - QDF_TRACE_LEVEL_WARN, + QDF_TRACE_LEVEL_INFO_LOW, "*** Warning: host/target HTT versions" " are different, though compatible!"); } @@ -3326,8 +4029,10 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) * using just 8 bits */ if (peer) { - status = dp_addba_requestprocess_wifi3(peer, - 0, tid, 0, win_sz + 1, 0xffff); + status = dp_addba_requestprocess_wifi3( + (struct cdp_soc_t *)soc->dp_soc, + peer->mac_addr.raw, peer->vdev->vdev_id, + 0, tid, 0, win_sz + 1, 0xffff); /* * If PEER_LOCK_REF_PROTECT enbled dec ref @@ -3362,6 +4067,10 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) u_int8_t vdev_id; bool is_wds; u_int16_t ast_hash; + struct dp_ast_flow_override_info ast_flow_info; + + qdf_mem_set(&ast_flow_info, 0, + sizeof(struct dp_ast_flow_override_info)); peer_id = HTT_RX_PEER_MAP_V2_SW_PEER_ID_GET(*msg_word); hw_peer_id = @@ -3374,6 +4083,40 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) HTT_RX_PEER_MAP_V2_NEXT_HOP_GET(*(msg_word + 3)); ast_hash = HTT_RX_PEER_MAP_V2_AST_HASH_VALUE_GET(*(msg_word + 3)); + /* + * Update 4 ast_index per peer, ast valid mask + * and TID flow valid mask. + * AST valid mask is 3 bit field corresponds to + * ast_index[3:1]. ast_index 0 is always valid. + */ + ast_flow_info.ast_valid_mask = + HTT_RX_PEER_MAP_V2_AST_VALID_MASK_GET(*(msg_word + 3)); + ast_flow_info.ast_idx[0] = hw_peer_id; + ast_flow_info.ast_flow_mask[0] = + HTT_RX_PEER_MAP_V2_AST_0_FLOW_MASK_GET(*(msg_word + 4)); + ast_flow_info.ast_idx[1] = + HTT_RX_PEER_MAP_V2_AST_INDEX_1_GET(*(msg_word + 4)); + ast_flow_info.ast_flow_mask[1] = + HTT_RX_PEER_MAP_V2_AST_1_FLOW_MASK_GET(*(msg_word + 4)); + ast_flow_info.ast_idx[2] = + HTT_RX_PEER_MAP_V2_AST_INDEX_2_GET(*(msg_word + 5)); + ast_flow_info.ast_flow_mask[2] = + HTT_RX_PEER_MAP_V2_AST_2_FLOW_MASK_GET(*(msg_word + 4)); + ast_flow_info.ast_idx[3] = + HTT_RX_PEER_MAP_V2_AST_INDEX_3_GET(*(msg_word + 6)); + ast_flow_info.ast_flow_mask[3] = + HTT_RX_PEER_MAP_V2_AST_3_FLOW_MASK_GET(*(msg_word + 4)); + /* + * TID valid mask is applicable only + * for HI and LOW priority flows. + * tid_valid_mas is 8 bit field corresponds + * to TID[7:0] + */ + ast_flow_info.tid_valid_low_pri_mask = + HTT_RX_PEER_MAP_V2_TID_VALID_LOW_PRI_GET(*(msg_word + 5)); + ast_flow_info.tid_valid_hi_pri_mask = + HTT_RX_PEER_MAP_V2_TID_VALID_HI_PRI_GET(*(msg_word + 5)); + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, "HTT_T2H_MSG_TYPE_PEER_MAP msg for peer id %d vdev id %d n", @@ -3383,6 +4126,16 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) hw_peer_id, vdev_id, peer_mac_addr, ast_hash, is_wds); + + /* + * Update ast indexes for flow override support + * Applicable only for non wds peers + */ + dp_peer_ast_index_flow_queue_map_create( + soc->dp_soc, is_wds, + peer_id, peer_mac_addr, + &ast_flow_info); + break; } case HTT_T2H_MSG_TYPE_PEER_UNMAP_V2: @@ -3532,6 +4285,8 @@ htt_htc_soc_attach(struct htt_soc *soc) soc->htc_endpoint = response.Endpoint; hif_save_htc_htt_config_endpoint(dpsoc->hif_handle, soc->htc_endpoint); + + htt_interface_logging_init(&soc->htt_logger_handle); dp_hif_update_pipe_callback(soc->dp_soc, (void *)soc, dp_htt_hif_t2h_hp_callback, DP_HTT_T2H_HP_PIPE); @@ -3549,15 +4304,17 @@ htt_htc_soc_attach(struct htt_soc *soc) * Return: HTT handle on success; NULL on failure */ void * -htt_soc_initialize(void *htt_soc, void *ctrl_psoc, HTC_HANDLE htc_soc, - void *hal_soc, qdf_device_t osdev) +htt_soc_initialize(struct htt_soc *htt_soc, + struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + HTC_HANDLE htc_soc, + hal_soc_handle_t hal_soc_hdl, qdf_device_t osdev) { struct htt_soc *soc = (struct htt_soc *)htt_soc; soc->osdev = osdev; soc->ctrl_psoc = ctrl_psoc; soc->htc_soc = htc_soc; - soc->hal_soc = hal_soc; + soc->hal_soc = hal_soc_hdl; if (htt_htc_soc_attach(soc)) goto fail2; @@ -3570,6 +4327,7 @@ htt_soc_initialize(void *htt_soc, void *ctrl_psoc, HTC_HANDLE htc_soc, void htt_soc_htc_dealloc(struct htt_soc *htt_handle) { + htt_interface_logging_deinit(htt_handle->htt_logger_handle); htt_htc_misc_pkt_pool_free(htt_handle); htt_htc_pkt_pool_free(htt_handle); } @@ -3585,8 +4343,6 @@ QDF_STATUS htt_soc_htc_prealloc(struct htt_soc *soc) { int i; - HTT_TX_MUTEX_INIT(&soc->htt_tx_mutex); - soc->htt_htc_pkt_freelist = NULL; /* pre-allocate some HTC_PACKET objects */ for (i = 0; i < HTT_HTC_PKT_POOL_INIT_SIZE; i++) { @@ -3604,12 +4360,19 @@ QDF_STATUS htt_soc_htc_prealloc(struct htt_soc *soc) * htt_soc_detach() - Free SOC level HTT handle * @htt_hdl: HTT SOC handle */ -void htt_soc_detach(void *htt_hdl) +void htt_soc_detach(struct htt_soc *htt_hdl) { + int i; struct htt_soc *htt_handle = (struct htt_soc *)htt_hdl; + for (i = 0; i < MAX_PDEV_CNT; i++) { + qdf_mem_free(htt_handle->pdevid_tt[i].umac_ttt); + qdf_mem_free(htt_handle->pdevid_tt[i].lmac_ttt); + } + HTT_TX_MUTEX_DESTROY(&htt_handle->htt_tx_mutex); qdf_mem_free(htt_handle); + } /** @@ -3635,6 +4398,10 @@ QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev, qdf_nbuf_t msg; uint32_t *msg_word; uint8_t pdev_mask = 0; + uint8_t *htt_logger_bufp; + int mac_for_pdev; + int target_pdev_id; + QDF_STATUS status; msg = qdf_nbuf_alloc( soc->osdev, @@ -3650,9 +4417,11 @@ QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev, * Bit 2: Pdev stats for pdev id 1 * Bit 3: Pdev stats for pdev id 2 */ - mac_id = dp_get_mac_id_for_pdev(mac_id, pdev->pdev_id); + mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev->pdev_id); + target_pdev_id = + dp_get_target_pdev_id_for_host_pdev_id(pdev->soc, mac_for_pdev); - pdev_mask = 1 << DP_SW2HW_MACID(mac_id); + pdev_mask = 1 << target_pdev_id; /* * Set the length of the message. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added @@ -3676,6 +4445,7 @@ QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev, msg_word = (uint32_t *) qdf_nbuf_data(msg); qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + htt_logger_bufp = (uint8_t *)msg_word; *msg_word = 0; HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_EXT_STATS_REQ); HTT_H2T_EXT_STATS_REQ_PDEV_MASK_SET(*msg_word, pdev_mask); @@ -3734,8 +4504,15 @@ QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev, HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); - DP_HTT_SEND_HTC_PKT(soc, pkt); - return 0; + status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_EXT_STATS_REQ, + htt_logger_bufp); + + if (status != QDF_STATUS_SUCCESS) { + qdf_nbuf_free(msg); + htt_htc_pkt_free(soc, pkt); + } + + return status; } /* This macro will revert once proper HTT header will define for @@ -3758,6 +4535,7 @@ QDF_STATUS dp_h2t_cfg_stats_msg_send(struct dp_pdev *pdev, qdf_nbuf_t msg; uint32_t *msg_word; uint8_t pdev_mask; + QDF_STATUS status; msg = qdf_nbuf_alloc( soc->osdev, @@ -3777,7 +4555,8 @@ QDF_STATUS dp_h2t_cfg_stats_msg_send(struct dp_pdev *pdev, * Bit 2: Pdev stats for pdev id 1 * Bit 3: Pdev stats for pdev id 2 */ - pdev_mask = 1 << DP_SW2HW_MACID(mac_id); + pdev_mask = 1 << dp_get_target_pdev_id_for_host_pdev_id(pdev->soc, + mac_id); /* * Set the length of the message. @@ -3816,11 +4595,19 @@ QDF_STATUS dp_h2t_cfg_stats_msg_send(struct dp_pdev *pdev, dp_htt_h2t_send_complete_free_netbuf, qdf_nbuf_data(msg), qdf_nbuf_len(msg), soc->htc_endpoint, - 1); /* tag - not relevant here */ + /* tag for no FW response msg */ + HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); - DP_HTT_SEND_HTC_PKT(soc, pkt); - return 0; + status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_PPDU_STATS_CFG, + (uint8_t *)msg_word); + + if (status != QDF_STATUS_SUCCESS) { + qdf_nbuf_free(msg); + htt_htc_pkt_free(soc, pkt); + } + + return status; } #endif @@ -3858,3 +4645,404 @@ dp_peer_update_inactive_time(struct dp_pdev *pdev, uint32_t tag_type, qdf_err("Invalid tag_type"); } } + +/** + * dp_htt_rx_flow_fst_setup(): Send HTT Rx FST setup message to FW + * @pdev: DP pdev handle + * @fse_setup_info: FST setup parameters + * + * Return: Success when HTT message is sent, error on failure + */ +QDF_STATUS +dp_htt_rx_flow_fst_setup(struct dp_pdev *pdev, + struct dp_htt_rx_flow_fst_setup *fse_setup_info) +{ + struct htt_soc *soc = pdev->soc->htt_handle; + struct dp_htt_htc_pkt *pkt; + qdf_nbuf_t msg; + u_int32_t *msg_word; + struct htt_h2t_msg_rx_fse_setup_t *fse_setup; + uint8_t *htt_logger_bufp; + u_int32_t *key; + QDF_STATUS status; + + msg = qdf_nbuf_alloc( + soc->osdev, + HTT_MSG_BUF_SIZE(sizeof(struct htt_h2t_msg_rx_fse_setup_t)), + /* reserve room for the HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); + + if (!msg) + return QDF_STATUS_E_NOMEM; + + /* + * Set the length of the message. + * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added + * separately during the below call to qdf_nbuf_push_head. + * The contribution from the HTC header is added separately inside HTC. + */ + if (!qdf_nbuf_put_tail(msg, + sizeof(struct htt_h2t_msg_rx_fse_setup_t))) { + qdf_err("Failed to expand head for HTT RX_FSE_SETUP msg"); + return QDF_STATUS_E_FAILURE; + } + + /* fill in the message contents */ + msg_word = (u_int32_t *)qdf_nbuf_data(msg); + + memset(msg_word, 0, sizeof(struct htt_h2t_msg_rx_fse_setup_t)); + /* rewind beyond alignment pad to get to the HTC header reserved area */ + qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + htt_logger_bufp = (uint8_t *)msg_word; + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_FSE_SETUP_CFG); + + fse_setup = (struct htt_h2t_msg_rx_fse_setup_t *)msg_word; + + HTT_RX_FSE_SETUP_PDEV_ID_SET(*msg_word, fse_setup_info->pdev_id); + + msg_word++; + HTT_RX_FSE_SETUP_NUM_REC_SET(*msg_word, fse_setup_info->max_entries); + HTT_RX_FSE_SETUP_MAX_SEARCH_SET(*msg_word, fse_setup_info->max_search); + HTT_RX_FSE_SETUP_IP_DA_SA_PREFIX_SET(*msg_word, + fse_setup_info->ip_da_sa_prefix); + + msg_word++; + HTT_RX_FSE_SETUP_BASE_ADDR_LO_SET(*msg_word, + fse_setup_info->base_addr_lo); + msg_word++; + HTT_RX_FSE_SETUP_BASE_ADDR_HI_SET(*msg_word, + fse_setup_info->base_addr_hi); + + key = (u_int32_t *)fse_setup_info->hash_key; + fse_setup->toeplitz31_0 = *key++; + fse_setup->toeplitz63_32 = *key++; + fse_setup->toeplitz95_64 = *key++; + fse_setup->toeplitz127_96 = *key++; + fse_setup->toeplitz159_128 = *key++; + fse_setup->toeplitz191_160 = *key++; + fse_setup->toeplitz223_192 = *key++; + fse_setup->toeplitz255_224 = *key++; + fse_setup->toeplitz287_256 = *key++; + fse_setup->toeplitz314_288 = *key; + + msg_word++; + HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz31_0); + msg_word++; + HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz63_32); + msg_word++; + HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz95_64); + msg_word++; + HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz127_96); + msg_word++; + HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz159_128); + msg_word++; + HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz191_160); + msg_word++; + HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz223_192); + msg_word++; + HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz255_224); + msg_word++; + HTT_RX_FSE_SETUP_HASH_VALUE_SET(*msg_word, fse_setup->toeplitz287_256); + msg_word++; + HTT_RX_FSE_SETUP_HASH_314_288_SET(*msg_word, + fse_setup->toeplitz314_288); + + pkt = htt_htc_pkt_alloc(soc); + if (!pkt) { + qdf_err("Fail to allocate dp_htt_htc_pkt buffer"); + qdf_assert(0); + qdf_nbuf_free(msg); + return QDF_STATUS_E_RESOURCES; /* failure */ + } + + pkt->soc_ctxt = NULL; /* not used during send-done callback */ + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + dp_htt_h2t_send_complete_free_netbuf, + qdf_nbuf_data(msg), + qdf_nbuf_len(msg), + soc->htc_endpoint, + HTC_TX_PACKET_TAG_RUNTIME_PUT); + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + + status = DP_HTT_SEND_HTC_PKT(soc, pkt, + HTT_H2T_MSG_TYPE_RX_FSE_SETUP_CFG, + htt_logger_bufp); + + if (status == QDF_STATUS_SUCCESS) { + dp_info("HTT_H2T RX_FSE_SETUP sent to FW for pdev = %u", + fse_setup_info->pdev_id); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_DEBUG, + (void *)fse_setup_info->hash_key, + fse_setup_info->hash_key_len); + } else { + qdf_nbuf_free(msg); + htt_htc_pkt_free(soc, pkt); + } + + return status; +} + +/** + * dp_htt_rx_flow_fse_operation(): Send HTT Flow Search Entry msg to + * add/del a flow in HW + * @pdev: DP pdev handle + * @fse_op_info: Flow entry parameters + * + * Return: Success when HTT message is sent, error on failure + */ +QDF_STATUS +dp_htt_rx_flow_fse_operation(struct dp_pdev *pdev, + struct dp_htt_rx_flow_fst_operation *fse_op_info) +{ + struct htt_soc *soc = pdev->soc->htt_handle; + struct dp_htt_htc_pkt *pkt; + qdf_nbuf_t msg; + u_int32_t *msg_word; + struct htt_h2t_msg_rx_fse_operation_t *fse_operation; + uint8_t *htt_logger_bufp; + QDF_STATUS status; + + msg = qdf_nbuf_alloc( + soc->osdev, + HTT_MSG_BUF_SIZE(sizeof(struct htt_h2t_msg_rx_fse_operation_t)), + /* reserve room for the HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); + if (!msg) + return QDF_STATUS_E_NOMEM; + + /* + * Set the length of the message. + * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added + * separately during the below call to qdf_nbuf_push_head. + * The contribution from the HTC header is added separately inside HTC. + */ + if (!qdf_nbuf_put_tail(msg, + sizeof(struct htt_h2t_msg_rx_fse_operation_t))) { + qdf_err("Failed to expand head for HTT_RX_FSE_OPERATION msg"); + qdf_nbuf_free(msg); + return QDF_STATUS_E_FAILURE; + } + + /* fill in the message contents */ + msg_word = (u_int32_t *)qdf_nbuf_data(msg); + + memset(msg_word, 0, sizeof(struct htt_h2t_msg_rx_fse_operation_t)); + /* rewind beyond alignment pad to get to the HTC header reserved area */ + qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + htt_logger_bufp = (uint8_t *)msg_word; + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_FSE_OPERATION_CFG); + + fse_operation = (struct htt_h2t_msg_rx_fse_operation_t *)msg_word; + + HTT_RX_FSE_OPERATION_PDEV_ID_SET(*msg_word, fse_op_info->pdev_id); + msg_word++; + HTT_RX_FSE_IPSEC_VALID_SET(*msg_word, false); + if (fse_op_info->op_code == DP_HTT_FST_CACHE_INVALIDATE_ENTRY) { + HTT_RX_FSE_OPERATION_SET(*msg_word, + HTT_RX_FSE_CACHE_INVALIDATE_ENTRY); + msg_word++; + HTT_RX_FSE_OPERATION_IP_ADDR_SET( + *msg_word, + qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.src_ip_31_0)); + msg_word++; + HTT_RX_FSE_OPERATION_IP_ADDR_SET( + *msg_word, + qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.src_ip_63_32)); + msg_word++; + HTT_RX_FSE_OPERATION_IP_ADDR_SET( + *msg_word, + qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.src_ip_95_64)); + msg_word++; + HTT_RX_FSE_OPERATION_IP_ADDR_SET( + *msg_word, + qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.src_ip_127_96)); + msg_word++; + HTT_RX_FSE_OPERATION_IP_ADDR_SET( + *msg_word, + qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.dest_ip_31_0)); + msg_word++; + HTT_RX_FSE_OPERATION_IP_ADDR_SET( + *msg_word, + qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.dest_ip_63_32)); + msg_word++; + HTT_RX_FSE_OPERATION_IP_ADDR_SET( + *msg_word, + qdf_htonl(fse_op_info->rx_flow->flow_tuple_info.dest_ip_95_64)); + msg_word++; + HTT_RX_FSE_OPERATION_IP_ADDR_SET( + *msg_word, + qdf_htonl( + fse_op_info->rx_flow->flow_tuple_info.dest_ip_127_96)); + msg_word++; + HTT_RX_FSE_SOURCEPORT_SET( + *msg_word, + fse_op_info->rx_flow->flow_tuple_info.src_port); + HTT_RX_FSE_DESTPORT_SET( + *msg_word, + fse_op_info->rx_flow->flow_tuple_info.dest_port); + msg_word++; + HTT_RX_FSE_L4_PROTO_SET( + *msg_word, + fse_op_info->rx_flow->flow_tuple_info.l4_protocol); + } else if (fse_op_info->op_code == DP_HTT_FST_CACHE_INVALIDATE_FULL) { + HTT_RX_FSE_OPERATION_SET(*msg_word, + HTT_RX_FSE_CACHE_INVALIDATE_FULL); + } else if (fse_op_info->op_code == DP_HTT_FST_DISABLE) { + HTT_RX_FSE_OPERATION_SET(*msg_word, HTT_RX_FSE_DISABLE); + } else if (fse_op_info->op_code == DP_HTT_FST_ENABLE) { + HTT_RX_FSE_OPERATION_SET(*msg_word, HTT_RX_FSE_ENABLE); + } + + pkt = htt_htc_pkt_alloc(soc); + if (!pkt) { + qdf_err("Fail to allocate dp_htt_htc_pkt buffer"); + qdf_assert(0); + qdf_nbuf_free(msg); + return QDF_STATUS_E_RESOURCES; /* failure */ + } + + pkt->soc_ctxt = NULL; /* not used during send-done callback */ + + SET_HTC_PACKET_INFO_TX( + &pkt->htc_pkt, + dp_htt_h2t_send_complete_free_netbuf, + qdf_nbuf_data(msg), + qdf_nbuf_len(msg), + soc->htc_endpoint, + HTC_TX_PACKET_TAG_RUNTIME_PUT); + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + + status = DP_HTT_SEND_HTC_PKT(soc, pkt, + HTT_H2T_MSG_TYPE_RX_FSE_OPERATION_CFG, + htt_logger_bufp); + + if (status == QDF_STATUS_SUCCESS) { + dp_info("HTT_H2T RX_FSE_OPERATION_CFG sent to FW for pdev = %u", + fse_op_info->pdev_id); + } else { + qdf_nbuf_free(msg); + htt_htc_pkt_free(soc, pkt); + } + + return status; +} + +/** + * dp_htt_rx_fisa_config(): Send HTT msg to configure FISA + * @pdev: DP pdev handle + * @fse_op_info: Flow entry parameters + * + * Return: Success when HTT message is sent, error on failure + */ +QDF_STATUS +dp_htt_rx_fisa_config(struct dp_pdev *pdev, + struct dp_htt_rx_fisa_cfg *fisa_config) +{ + struct htt_soc *soc = pdev->soc->htt_handle; + struct dp_htt_htc_pkt *pkt; + qdf_nbuf_t msg; + u_int32_t *msg_word; + struct htt_h2t_msg_type_fisa_config_t *htt_fisa_config; + uint8_t *htt_logger_bufp; + uint32_t len; + QDF_STATUS status; + + len = HTT_MSG_BUF_SIZE(sizeof(struct htt_h2t_msg_type_fisa_config_t)); + + msg = qdf_nbuf_alloc(soc->osdev, + len, + /* reserve room for the HTC header */ + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, + 4, + TRUE); + if (!msg) + return QDF_STATUS_E_NOMEM; + + /* + * Set the length of the message. + * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added + * separately during the below call to qdf_nbuf_push_head. + * The contribution from the HTC header is added separately inside HTC. + */ + if (!qdf_nbuf_put_tail(msg, + sizeof(struct htt_h2t_msg_type_fisa_config_t))) { + qdf_err("Failed to expand head for HTT_RX_FSE_OPERATION msg"); + qdf_nbuf_free(msg); + return QDF_STATUS_E_FAILURE; + } + + /* fill in the message contents */ + msg_word = (u_int32_t *)qdf_nbuf_data(msg); + + memset(msg_word, 0, sizeof(struct htt_h2t_msg_type_fisa_config_t)); + /* rewind beyond alignment pad to get to the HTC header reserved area */ + qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); + htt_logger_bufp = (uint8_t *)msg_word; + + *msg_word = 0; + HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_FISA_CFG); + + htt_fisa_config = (struct htt_h2t_msg_type_fisa_config_t *)msg_word; + + HTT_RX_FSE_OPERATION_PDEV_ID_SET(*msg_word, htt_fisa_config->pdev_id); + + msg_word++; + HTT_RX_FISA_CONFIG_FISA_ENABLE_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_IPSEC_SKIP_SEARCH_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_NON_TCP_SKIP_SEARCH_SET(*msg_word, 0); + HTT_RX_FISA_CONFIG_ADD_IPV4_FIXED_HDR_LEN_SET(*msg_word, 0); + HTT_RX_FISA_CONFIG_ADD_IPV6_FIXED_HDR_LEN_SET(*msg_word, 0); + HTT_RX_FISA_CONFIG_ADD_TCP_FIXED_HDR_LEN_SET(*msg_word, 0); + HTT_RX_FISA_CONFIG_ADD_UDP_HDR_LEN_SET(*msg_word, 0); + HTT_RX_FISA_CONFIG_CHKSUM_CUM_IP_LEN_EN_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_TID_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_TA_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_QOS_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_RAW_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_DECRYPT_ERR_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_DISABLE_MSDU_DROP_CHECK_SET(*msg_word, 1); + HTT_RX_FISA_CONFIG_FISA_AGGR_LIMIT_SET(*msg_word, 0xf); + + msg_word++; + htt_fisa_config->fisa_timeout_threshold = fisa_config->fisa_timeout; + + pkt = htt_htc_pkt_alloc(soc); + if (!pkt) { + qdf_err("Fail to allocate dp_htt_htc_pkt buffer"); + qdf_assert(0); + qdf_nbuf_free(msg); + return QDF_STATUS_E_RESOURCES; /* failure */ + } + + pkt->soc_ctxt = NULL; /* not used during send-done callback */ + + SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt, + dp_htt_h2t_send_complete_free_netbuf, + qdf_nbuf_data(msg), + qdf_nbuf_len(msg), + soc->htc_endpoint, + HTC_TX_PACKET_TAG_RUNTIME_PUT); + + SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); + + status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_RX_FISA_CFG, + htt_logger_bufp); + + if (status == QDF_STATUS_SUCCESS) { + dp_info("HTT_H2T_MSG_TYPE_RX_FISA_CFG sent to FW for pdev = %u", + fisa_config->pdev_id); + } else { + qdf_nbuf_free(msg); + htt_htc_pkt_free(soc, pkt); + } + + return status; +} diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_htt.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_htt.h index 09d7d7c71e6447a9be487431da695c1df4cbbae9..6843904df22655e9a5e9c72e3a7991dd6e8f2754 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_htt.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_htt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -26,6 +26,42 @@ #include "cdp_txrx_cmn_struct.h" #include "dp_types.h" +#ifdef HTT_LOGGER +#include "dp_htt_logger.h" +#else +struct htt_logger; +static inline +void htt_interface_logging_init(struct htt_logger **htt_logger_handle) +{ +} + +static inline +void htt_interface_logging_deinit(struct htt_logger *htt_logger_handle) +{ +} + +static inline +int htt_command_record(struct htt_logger *h, uint8_t msg_type, + uint8_t *msg_data) +{ + return 0; +} + +static inline +int htt_event_record(struct htt_logger *h, uint8_t msg_type, + uint8_t *msg_data) +{ + return 0; +} + +static inline +int htt_wbm_event_record(struct htt_logger *h, uint8_t tx_status, + uint8_t *msg_data) +{ + return 0; +} + +#endif #define HTT_TX_MUTEX_TYPE qdf_spinlock_t @@ -62,7 +98,7 @@ #define HTT_RX_DELBA_WIN_SIZE_M 0x0000FC00 #define HTT_RX_DELBA_WIN_SIZE_S 10 -#define HTT_RX_DELBA_WIN_SIZE_GET(word) \ +#define HTT_RX_DELBA_WIN_SIZE_GET(word) \ (((word) & HTT_RX_DELBA_WIN_SIZE_M) >> HTT_RX_DELBA_WIN_SIZE_S) /* @@ -75,6 +111,30 @@ #define HTT_T2H_EXT_STATS_TLV_START_OFFSET 3 +/* + * Below offset are based on htt_ppdu_stats_common_tlv + * defined in htt_ppdu_stats.h + */ +#define HTT_PPDU_STATS_COMMON_TLV_TLV_HDR_OFFSET 0 +#define HTT_PPDU_STATS_COMMON_TLV_PPDU_ID_OFFSET 1 +#define HTT_PPDU_STATS_COMMON_TLV_RING_ID_SCH_CMD_ID_OFFSET 2 +#define HTT_PPDU_STATS_COMMON_TLV_QTYPE_FRM_TYPE_OFFSET 3 +#define HTT_PPDU_STATS_COMMON_TLV_CHAIN_MASK_OFFSET 4 +#define HTT_PPDU_STATS_COMMON_TLV_FES_DUR_US_OFFSET 5 +#define HTT_PPDU_STATS_COMMON_TLV_SCH_EVAL_START_TSTMP_L32_US_OFFSET 6 +#define HTT_PPDU_STATS_COMMON_TLV_SCH_END_TSTMP_US_OFFSET 7 +#define HTT_PPDU_STATS_COMMON_TLV_START_TSTMP_L32_US_OFFSET 8 +#define HTT_PPDU_STATS_COMMON_TLV_CHAN_MHZ_PHY_MODE_OFFSET 9 +#define HTT_PPDU_STATS_COMMON_TLV_CCA_DELTA_TIME_US_OFFSET 10 +#define HTT_PPDU_STATS_COMMON_TLV_RXFRM_DELTA_TIME_US_OFFSET 11 +#define HTT_PPDU_STATS_COMMON_TLV_TXFRM_DELTA_TIME_US_OFFSET 12 +#define HTT_PPDU_STATS_COMMON_TLV_RESV_NUM_UL_BEAM_OFFSET 13 +#define HTT_PPDU_STATS_COMMON_TLV_START_TSTMP_U32_US_OFFSET 14 + +/* get index for field in htt_ppdu_stats_common_tlv */ +#define HTT_GET_STATS_CMN_INDEX(index) \ + HTT_PPDU_STATS_COMMON_TLV_##index##_OFFSET + struct dp_htt_htc_pkt { void *soc_ctxt; qdf_dma_addr_t nbuf_paddr; @@ -88,10 +148,18 @@ struct dp_htt_htc_pkt_union { } u; }; +struct dp_htt_timestamp { + long *umac_ttt; + long *lmac_ttt; +}; + struct htt_soc { - void *ctrl_psoc; - void *dp_soc; - void *hal_soc; + struct cdp_ctrl_objmgr_psoc *ctrl_psoc; + struct dp_soc *dp_soc; + hal_soc_handle_t hal_soc; + struct dp_htt_timestamp pdevid_tt[MAX_PDEV_CNT]; + /* htt_logger handle */ + struct htt_logger *htt_logger_handle; HTC_HANDLE htc_soc; qdf_device_t osdev; HTC_ENDPOINT_ID htc_endpoint; @@ -109,6 +177,8 @@ struct htt_soc { struct { int htc_err_cnt; int htc_pkt_free; + /* rtpm put skip count for ver req msg */ + int htt_ver_req_put_skip; } stats; HTT_TX_MUTEX_TYPE htt_tx_mutex; @@ -143,6 +213,8 @@ struct htt_soc { * @rx_msdu_end_offset: Offset of rx_msdu_end tlv * @rx_msdu_start_offset: Offset of rx_msdu_start tlv * @rx_attn_offset: Offset of rx_attention tlv + * + * NOTE: Do not change the layout of this structure */ struct htt_rx_ring_tlv_filter { u_int32_t mpdu_start:1, @@ -180,6 +252,69 @@ struct htt_rx_ring_tlv_filter { uint16_t rx_attn_offset; }; +/** + * struct dp_htt_rx_flow_fst_setup - Rx FST setup message + * @pdev_id: DP Pdev identifier + * @max_entries: Size of Rx FST in number of entries + * @max_search: Number of collisions allowed + * @base_addr_lo: lower 32-bit physical address + * @base_addr_hi: upper 32-bit physical address + * @ip_da_sa_prefix: IPv4 prefix to map to IPv6 address scheme + * @hash_key_len: Rx FST hash key size + * @hash_key: Rx FST Toeplitz hash key + */ +struct dp_htt_rx_flow_fst_setup { + uint8_t pdev_id; + uint32_t max_entries; + uint32_t max_search; + uint32_t base_addr_lo; + uint32_t base_addr_hi; + uint32_t ip_da_sa_prefix; + uint32_t hash_key_len; + uint8_t *hash_key; +}; + +/** + * enum dp_htt_flow_fst_operation - FST related operations allowed + * @DP_HTT_FST_CACHE_OP_NONE: Cache no-op + * @DP_HTT_FST_CACHE_INVALIDATE_ENTRY: Invalidate single cache entry + * @DP_HTT_FST_CACHE_INVALIDATE_FULL: Invalidate entire cache + * @DP_HTT_FST_ENABLE: Bypass FST is enabled + * @DP_HTT_FST_DISABLE: Disable bypass FST + */ +enum dp_htt_flow_fst_operation { + DP_HTT_FST_CACHE_OP_NONE, + DP_HTT_FST_CACHE_INVALIDATE_ENTRY, + DP_HTT_FST_CACHE_INVALIDATE_FULL, + DP_HTT_FST_ENABLE, + DP_HTT_FST_DISABLE +}; + +/** + * struct dp_htt_rx_flow_fst_setup - Rx FST setup message + * @pdev_id: DP Pdev identifier + * @op_code: FST operation to be performed by FW/HW + * @rx_flow: Rx Flow information on which operation is to be performed + */ +struct dp_htt_rx_flow_fst_operation { + uint8_t pdev_id; + enum dp_htt_flow_fst_operation op_code; + struct cdp_rx_flow_info *rx_flow; +}; + +/** + * struct dp_htt_rx_fisa_config - Rx fisa config + * @pdev_id: DP Pdev identifier + * @fisa_timeout: fisa aggregation timeout + */ +struct dp_htt_rx_fisa_cfg { + uint8_t pdev_id; + uint32_t fisa_timeout; +}; + +QDF_STATUS dp_htt_rx_fisa_config(struct dp_pdev *pdev, + struct dp_htt_rx_fisa_cfg *fisa_config); + /* * htt_soc_initialize() - SOC level HTT initialization * @htt_soc: Opaque htt SOC handle @@ -191,8 +326,36 @@ struct htt_rx_ring_tlv_filter { * Return: HTT handle on success; NULL on failure */ void * -htt_soc_initialize(void *htt_soc, void *ctrl_psoc, HTC_HANDLE htc_soc, - void *hal_soc, qdf_device_t osdev); +htt_soc_initialize(struct htt_soc *htt_soc, + struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + HTC_HANDLE htc_soc, + hal_soc_handle_t hal_soc_hdl, qdf_device_t osdev); + +/* + * htt_soc_attach() - attach DP and HTT SOC + * @soc: DP SOC handle + * @htc_hdl: HTC handle + * + * Return: htt_soc handle on Success, NULL on Failure + */ +struct htt_soc *htt_soc_attach(struct dp_soc *soc, HTC_HANDLE htc_hdl); + +/* + * htt_set_htc_handle_() - set HTC handle + * @htt_hdl: HTT handle/SOC + * @htc_soc: HTC handle + * + * Return: None + */ +void htt_set_htc_handle(struct htt_soc *htt_hdl, HTC_HANDLE htc_soc); + +/* + * htt_get_htc_handle_() - set HTC handle + * @htt_hdl: HTT handle/SOC + * + * Return: HTC_HANDLE + */ +HTC_HANDLE htt_get_htc_handle(struct htt_soc *htt_hdl); /* * htt_soc_htc_dealloc() - HTC memory de-alloc @@ -211,12 +374,13 @@ void htt_soc_htc_dealloc(struct htt_soc *htt_handle); */ QDF_STATUS htt_soc_htc_prealloc(struct htt_soc *htt_soc); -void htt_soc_detach(void *soc); +void htt_soc_detach(struct htt_soc *soc); -int htt_srng_setup(void *htt_soc, int pdev_id, void *hal_srng, - int hal_ring_type); +int htt_srng_setup(struct htt_soc *htt_soc, int pdev_id, + hal_ring_handle_t hal_ring_hdl, + int hal_ring_type); -int htt_soc_attach_target(void *htt_soc); +int htt_soc_attach_target(struct htt_soc *htt_soc); /* * htt_h2t_rx_ring_cfg() - Send SRNG packet and TLV filter @@ -230,9 +394,10 @@ int htt_soc_attach_target(void *htt_soc); * * Return: 0 on success; error code on failure */ -int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, - int hal_ring_type, int ring_buf_size, - struct htt_rx_ring_tlv_filter *htt_tlv_filter); +int htt_h2t_rx_ring_cfg(struct htt_soc *htt_soc, int pdev_id, + hal_ring_handle_t hal_ring_hdl, + int hal_ring_type, int ring_buf_size, + struct htt_rx_ring_tlv_filter *htt_tlv_filter); /* * htt_t2h_stats_handler() - target to host stats work handler @@ -268,4 +433,26 @@ void dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, struct ppdu_info *ppdu_info); +/** + * dp_htt_rx_flow_fst_setup(): Send HTT Rx FST setup message to FW + * @pdev: DP pdev handle + * @fse_setup_info: FST setup parameters + * + * Return: Success when HTT message is sent, error on failure + */ +QDF_STATUS +dp_htt_rx_flow_fst_setup(struct dp_pdev *pdev, + struct dp_htt_rx_flow_fst_setup *setup_info); + +/** + * dp_htt_rx_flow_fse_operation(): Send HTT Flow Search Entry msg to + * add/del a flow in HW + * @pdev: DP pdev handle + * @fse_op_info: Flow entry parameters + * + * Return: Success when HTT message is sent, error on failure + */ +QDF_STATUS +dp_htt_rx_flow_fse_operation(struct dp_pdev *pdev, + struct dp_htt_rx_flow_fst_operation *op_info); #endif /* _DP_HTT_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_internal.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_internal.h index 495fb647e87726abda99bf3ff93a31aa0b17aea6..69e821a5e4b658095752e3426248bbeee186d2be 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_internal.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -22,8 +22,11 @@ #include "dp_types.h" #define RX_BUFFER_SIZE_PKTLOG_LITE 1024 +/* Alignment for consistent memory for DP rings*/ +#define DP_RING_BASE_ALIGN 8 +#define DP_RSSI_INVAL 0x80 #define DP_RSSI_AVG_WEIGHT 2 /* * Formula to derive avg_rssi is taken from wifi2.o firmware @@ -62,6 +65,21 @@ (1 << HTT_PPDU_STATS_USR_COMPLTN_COMMON_TLV) | \ (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) +/** + * Bitmap of HTT PPDU delayed ba TLV types for Default mode + */ +#define HTT_PPDU_DELAYED_BA_TLV_BITMAP \ + (1 << HTT_PPDU_STATS_COMMON_TLV) | \ + (1 << HTT_PPDU_STATS_USR_COMMON_TLV) | \ + (1 << HTT_PPDU_STATS_USR_RATE_TLV) + +/** + * Bitmap of HTT PPDU TLV types for Delayed BA + */ +#define HTT_PPDU_STATUS_TLV_BITMAP \ + (1 << HTT_PPDU_STATS_COMMON_TLV) | \ + (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) + /** * Bitmap of HTT PPDU TLV types for Sniffer mode bitmap 64 */ @@ -90,7 +108,7 @@ #ifdef WLAN_TX_PKT_CAPTURE_ENH extern uint8_t -dp_cpu_ring_map[DP_NSS_CPU_RING_MAP_MAX][WLAN_CFG_INT_NUM_CONTEXTS]; +dp_cpu_ring_map[DP_NSS_CPU_RING_MAP_MAX][WLAN_CFG_INT_NUM_CONTEXTS_MAX]; #endif #define DP_MAX_TIMER_EXEC_TIME_TICKS \ @@ -147,7 +165,7 @@ while (0) QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_##LVL, \ fmt, ## args) -#ifdef CONFIG_MCL +#ifdef DP_PRINT_NO_CONSOLE /* Stat prints should not go to console or kernel logs.*/ #define DP_PRINT_STATS(fmt, args ...)\ QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, \ @@ -315,7 +333,6 @@ while (0) } \ } while (0) - #else #define DP_HIST_INIT() #define DP_HIST_PACKET_COUNT_INC(_pdev_id) @@ -323,7 +340,134 @@ while (0) #define DP_RX_HISTOGRAM_UPDATE(_pdev, _p_cntrs) #define DP_RX_HIST_STATS_PER_PDEV() #define DP_TX_HIST_STATS_PER_PDEV() -#endif +#endif /* DISABLE_DP_STATS */ + +#ifdef FEATURE_TSO_STATS +/** + * dp_init_tso_stats() - Clear tso stats + * @pdev: pdev handle + * + * Return: None + */ +static inline +void dp_init_tso_stats(struct dp_pdev *pdev) +{ + if (pdev) { + qdf_mem_zero(&((pdev)->stats.tso_stats), + sizeof((pdev)->stats.tso_stats)); + qdf_atomic_init(&pdev->tso_idx); + } +} + +/** + * dp_stats_tso_segment_histogram_update() - TSO Segment Histogram + * @pdev: pdev handle + * @_p_cntrs: number of tso segments for a tso packet + * + * Return: None + */ +void dp_stats_tso_segment_histogram_update(struct dp_pdev *pdev, + uint8_t _p_cntrs); + +/** + * dp_tso_segment_update() - Collect tso segment information + * @pdev: pdev handle + * @stats_idx: tso packet number + * @idx: tso segment number + * @seg: tso segment + * + * Return: None + */ +void dp_tso_segment_update(struct dp_pdev *pdev, + uint32_t stats_idx, + uint8_t idx, + struct qdf_tso_seg_t seg); + +/** + * dp_tso_packet_update() - TSO Packet information + * @pdev: pdev handle + * @stats_idx: tso packet number + * @msdu: nbuf handle + * @num_segs: tso segments + * + * Return: None + */ +void dp_tso_packet_update(struct dp_pdev *pdev, uint32_t stats_idx, + qdf_nbuf_t msdu, uint16_t num_segs); + +/** + * dp_tso_segment_stats_update() - TSO Segment stats + * @pdev: pdev handle + * @stats_seg: tso segment list + * @stats_idx: tso packet number + * + * Return: None + */ +void dp_tso_segment_stats_update(struct dp_pdev *pdev, + struct qdf_tso_seg_elem_t *stats_seg, + uint32_t stats_idx); + +/** + * dp_print_tso_stats() - dump tso statistics + * @soc:soc handle + * @level: verbosity level + * + * Return: None + */ +void dp_print_tso_stats(struct dp_soc *soc, + enum qdf_stats_verbosity_level level); + +/** + * dp_txrx_clear_tso_stats() - clear tso stats + * @soc: soc handle + * + * Return: None + */ +void dp_txrx_clear_tso_stats(struct dp_soc *soc); +#else +static inline +void dp_init_tso_stats(struct dp_pdev *pdev) +{ +} + +static inline +void dp_stats_tso_segment_histogram_update(struct dp_pdev *pdev, + uint8_t _p_cntrs) +{ +} + +static inline +void dp_tso_segment_update(struct dp_pdev *pdev, + uint32_t stats_idx, + uint32_t idx, + struct qdf_tso_seg_t seg) +{ +} + +static inline +void dp_tso_packet_update(struct dp_pdev *pdev, uint32_t stats_idx, + qdf_nbuf_t msdu, uint16_t num_segs) +{ +} + +static inline +void dp_tso_segment_stats_update(struct dp_pdev *pdev, + struct qdf_tso_seg_elem_t *stats_seg, + uint32_t stats_idx) +{ +} + +static inline +void dp_print_tso_stats(struct dp_soc *soc, + enum qdf_stats_verbosity_level level) +{ +} + +static inline +void dp_txrx_clear_tso_stats(struct dp_soc *soc) +{ +} +#endif /* FEATURE_TSO_STATS */ #define DP_HTT_T2H_HP_PIPE 5 static inline void dp_update_pdev_stats(struct dp_pdev *tgtobj, @@ -465,6 +609,8 @@ static inline void dp_update_pdev_stats(struct dp_pdev *tgtobj, srcobj->tx.last_ack_rssi; tgtobj->stats.rx.mec_drop.num += srcobj->rx.mec_drop.num; tgtobj->stats.rx.mec_drop.bytes += srcobj->rx.mec_drop.bytes; + tgtobj->stats.rx.multipass_rx_pkt_drop += + srcobj->rx.multipass_rx_pkt_drop; } static inline void dp_update_pdev_ingress_stats(struct dp_pdev *tgtobj, @@ -478,10 +624,6 @@ static inline void dp_update_pdev_ingress_stats(struct dp_pdev *tgtobj, DP_STATS_AGGR_PKT(tgtobj, srcobj, tx_i.inspect_pkts); DP_STATS_AGGR_PKT(tgtobj, srcobj, tx_i.raw.raw_pkt); DP_STATS_AGGR(tgtobj, srcobj, tx_i.raw.dma_map_error); - DP_STATS_AGGR_PKT(tgtobj, srcobj, tx_i.tso.tso_pkt); - DP_STATS_AGGR(tgtobj, srcobj, tx_i.tso.dropped_host.num); - DP_STATS_AGGR(tgtobj, srcobj, tx_i.tso.tso_no_mem_dropped.num); - DP_STATS_AGGR(tgtobj, srcobj, tx_i.tso.dropped_target); DP_STATS_AGGR(tgtobj, srcobj, tx_i.sg.dropped_host.num); DP_STATS_AGGR(tgtobj, srcobj, tx_i.sg.dropped_target); DP_STATS_AGGR_PKT(tgtobj, srcobj, tx_i.sg.sg_pkt); @@ -512,8 +654,6 @@ static inline void dp_update_pdev_ingress_stats(struct dp_pdev *tgtobj, tgtobj->stats.tx_i.dropped.desc_na.num + tgtobj->stats.tx_i.dropped.res_full; - tgtobj->stats.tx_i.tso.num_seg = - srcobj->stats.tx_i.tso.num_seg; } static inline void dp_update_vdev_stats(struct cdp_vdev_stats *tgtobj, @@ -654,6 +794,8 @@ static inline void dp_update_vdev_stats(struct cdp_vdev_stats *tgtobj, srcobj->stats.tx.last_ack_rssi; tgtobj->rx.mec_drop.num += srcobj->stats.rx.mec_drop.num; tgtobj->rx.mec_drop.bytes += srcobj->stats.rx.mec_drop.bytes; + tgtobj->rx.multipass_rx_pkt_drop += + srcobj->stats.rx.multipass_rx_pkt_drop; } #define DP_UPDATE_STATS(_tgtobj, _srcobj) \ @@ -748,6 +890,7 @@ static inline void dp_update_vdev_stats(struct cdp_vdev_stats *tgtobj, \ _tgtobj->stats.tx.last_ack_rssi = \ _srcobj->stats.tx.last_ack_rssi; \ + DP_STATS_AGGR(_tgtobj, _srcobj, rx.multipass_rx_pkt_drop); \ } while (0) extern int dp_peer_find_attach(struct dp_soc *soc); @@ -755,43 +898,163 @@ extern void dp_peer_find_detach(struct dp_soc *soc); extern void dp_peer_find_hash_add(struct dp_soc *soc, struct dp_peer *peer); extern void dp_peer_find_hash_remove(struct dp_soc *soc, struct dp_peer *peer); extern void dp_peer_find_hash_erase(struct dp_soc *soc); + +/* + * dp_peer_ppdu_delayed_ba_init() Initialize ppdu in peer + * @peer: Datapath peer + * + * return: void + */ +void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer); + +/* + * dp_peer_ppdu_delayed_ba_cleanup() free ppdu allocated in peer + * @peer: Datapath peer + * + * return: void + */ +void dp_peer_ppdu_delayed_ba_cleanup(struct dp_peer *peer); + extern void dp_peer_rx_init(struct dp_pdev *pdev, struct dp_peer *peer); void dp_peer_tx_init(struct dp_pdev *pdev, struct dp_peer *peer); void dp_peer_cleanup(struct dp_vdev *vdev, struct dp_peer *peer, bool reuse); void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer, bool reuse); -extern void dp_peer_unref_delete(void *peer_handle); -extern void dp_rx_discard(struct dp_vdev *vdev, struct dp_peer *peer, - unsigned tid, qdf_nbuf_t msdu_list); +void dp_peer_unref_delete(struct dp_peer *peer); extern void *dp_find_peer_by_addr(struct cdp_pdev *dev, - uint8_t *peer_mac_addr, uint8_t *peer_id); + uint8_t *peer_mac_addr); extern struct dp_peer *dp_peer_find_hash_find(struct dp_soc *soc, uint8_t *peer_mac_addr, int mac_addr_is_aligned, uint8_t vdev_id); -#ifndef CONFIG_WIN -QDF_STATUS dp_register_peer(struct cdp_pdev *pdev_handle, - struct ol_txrx_desc_type *sta_desc); -QDF_STATUS dp_clear_peer(struct cdp_pdev *pdev_handle, uint8_t local_id); +#ifdef DP_PEER_EXTENDED_API +/** + * dp_register_peer() - Register peer into physical device + * @soc_hdl - data path soc handle + * @pdev_id - device instance id + * @sta_desc - peer description + * + * Register peer into physical device + * + * Return: QDF_STATUS_SUCCESS registration success + * QDF_STATUS_E_FAULT peer not found + */ +QDF_STATUS dp_register_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct ol_txrx_desc_type *sta_desc); + +/** + * dp_clear_peer() - remove peer from physical device + * @soc_hdl - data path soc handle + * @pdev_id - device instance id + * @peer_addr - peer mac address + * + * remove peer from physical device + * + * Return: QDF_STATUS_SUCCESS registration success + * QDF_STATUS_E_FAULT peer not found + */ +QDF_STATUS dp_clear_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct qdf_mac_addr peer_addr); + +/* + * dp_find_peer_exist - find peer if already exists + * @soc: datapath soc handle + * @pdev_id: physical device instance id + * @peer_mac_addr: peer mac address + * + * Return: true or false + */ +bool dp_find_peer_exist(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint8_t *peer_addr); + +/* + * dp_find_peer_exist_on_vdev - find if peer exists on the given vdev + * @soc: datapath soc handle + * @vdev_id: vdev instance id + * @peer_mac_addr: peer mac address + * + * Return: true or false + */ +bool dp_find_peer_exist_on_vdev(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_addr); + +/* + * dp_find_peer_exist_on_other_vdev - find if peer exists + * on other than the given vdev + * @soc: datapath soc handle + * @vdev_id: vdev instance id + * @peer_mac_addr: peer mac address + * @max_bssid: max number of bssids + * + * Return: true or false + */ +bool dp_find_peer_exist_on_other_vdev(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, uint8_t *peer_addr, + uint16_t max_bssid); + void *dp_find_peer_by_addr_and_vdev(struct cdp_pdev *pdev_handle, struct cdp_vdev *vdev, - uint8_t *peer_addr, uint8_t *local_id); -uint16_t dp_local_peer_id(void *peer); -void *dp_peer_find_by_local_id(struct cdp_pdev *pdev_handle, uint8_t local_id); -QDF_STATUS dp_peer_state_update(struct cdp_pdev *pdev_handle, uint8_t *peer_mac, - enum ol_txrx_peer_state state); -QDF_STATUS dp_get_vdevid(void *peer_handle, uint8_t *vdev_id); -struct cdp_vdev *dp_get_vdev_by_sta_id(struct cdp_pdev *pdev_handle, - uint8_t sta_id); + uint8_t *peer_addr); + +/** + * dp_peer_state_update() - update peer local state + * @pdev - data path device instance + * @peer_addr - peer mac address + * @state - new peer local state + * + * update peer local state + * + * Return: QDF_STATUS_SUCCESS registration success + */ +QDF_STATUS dp_peer_state_update(struct cdp_soc_t *soc, uint8_t *peer_mac, + enum ol_txrx_peer_state state); + +/** + * dp_get_vdevid() - Get virtual interface id which peer registered + * @soc - datapath soc handle + * @peer_mac - peer mac address + * @vdev_id - virtual interface id which peer registered + * + * Get virtual interface id which peer registered + * + * Return: QDF_STATUS_SUCCESS registration success + */ +QDF_STATUS dp_get_vdevid(struct cdp_soc_t *soc_hdl, uint8_t *peer_mac, + uint8_t *vdev_id); +struct cdp_vdev *dp_get_vdev_by_peer_addr(struct cdp_pdev *pdev_handle, + struct qdf_mac_addr peer_addr); struct cdp_vdev *dp_get_vdev_for_peer(void *peer); uint8_t *dp_peer_get_peer_mac_addr(void *peer); -int dp_get_peer_state(void *peer_handle); + +/** + * dp_get_peer_state() - Get local peer state + * @soc - datapath soc handle + * @vdev_id - vdev id + * @peer_mac - peer mac addr + * + * Get local peer state + * + * Return: peer status + */ +int dp_get_peer_state(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac); void dp_local_peer_id_pool_init(struct dp_pdev *pdev); void dp_local_peer_id_alloc(struct dp_pdev *pdev, struct dp_peer *peer); void dp_local_peer_id_free(struct dp_pdev *pdev, struct dp_peer *peer); #else +/** + * dp_get_vdevid() - Get virtual interface id which peer registered + * @soc - datapath soc handle + * @peer_mac - peer mac address + * @vdev_id - virtual interface id which peer registered + * + * Get virtual interface id which peer registered + * + * Return: QDF_STATUS_SUCCESS registration success + */ static inline -QDF_STATUS dp_get_vdevid(void *peer_handle, uint8_t *vdev_id) +QDF_STATUS dp_get_vdevid(struct cdp_soc_t *soc_hdl, uint8_t *peer_mac, + uint8_t *vdev_id) { return QDF_STATUS_E_NOSUPPORT; } @@ -810,30 +1073,44 @@ void dp_local_peer_id_free(struct dp_pdev *pdev, struct dp_peer *peer) { } #endif -int dp_addba_resp_tx_completion_wifi3(void *peer_handle, uint8_t tid, - int status); -extern int dp_addba_requestprocess_wifi3(void *peer_handle, - uint8_t dialogtoken, uint16_t tid, uint16_t batimeout, - uint16_t buffersize, uint16_t startseqnum); -extern void dp_addba_responsesetup_wifi3(void *peer_handle, uint8_t tid, - uint8_t *dialogtoken, uint16_t *statuscode, - uint16_t *buffersize, uint16_t *batimeout); -extern void dp_set_addba_response(void *peer_handle, uint8_t tid, - uint16_t statuscode); -extern int dp_delba_process_wifi3(void *peer_handle, - int tid, uint16_t reasoncode); +int dp_addba_resp_tx_completion_wifi3(struct cdp_soc_t *cdp_soc, + uint8_t *peer_mac, uint16_t vdev_id, + uint8_t tid, + int status); +int dp_addba_requestprocess_wifi3(struct cdp_soc_t *cdp_soc, + uint8_t *peer_mac, uint16_t vdev_id, + uint8_t dialogtoken, uint16_t tid, + uint16_t batimeout, + uint16_t buffersize, + uint16_t startseqnum); +QDF_STATUS dp_addba_responsesetup_wifi3(struct cdp_soc_t *cdp_soc, + uint8_t *peer_mac, uint16_t vdev_id, + uint8_t tid, uint8_t *dialogtoken, + uint16_t *statuscode, + uint16_t *buffersize, + uint16_t *batimeout); +QDF_STATUS dp_set_addba_response(struct cdp_soc_t *cdp_soc, + uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, + uint16_t statuscode); +int dp_delba_process_wifi3(struct cdp_soc_t *cdp_soc, uint8_t *peer_mac, + uint16_t vdev_id, int tid, + uint16_t reasoncode); /* * dp_delba_tx_completion_wifi3() - Handle delba tx completion * - * @peer_handle: Peer handle + * @cdp_soc: soc handle + * @vdev_id: id of the vdev handle + * @peer_mac: peer mac address * @tid: Tid number * @status: Tx completion status * Indicate status of delba Tx to DP for stats update and retry * delba if tx failed. * */ -int dp_delba_tx_completion_wifi3(void *peer_handle, uint8_t tid, - int status); +int dp_delba_tx_completion_wifi3(struct cdp_soc_t *cdp_soc, uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, + int status); extern QDF_STATUS dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid, uint32_t ba_window_size, uint32_t start_seq); @@ -859,37 +1136,46 @@ void dp_rx_tid_stats_cb(struct dp_soc *soc, void *cb_ctxt, union hal_reo_status *reo_status); void dp_rx_bar_stats_cb(struct dp_soc *soc, void *cb_ctxt, union hal_reo_status *reo_status); -uint16_t dp_tx_me_send_convert_ucast(struct cdp_vdev *vdev_handle, - qdf_nbuf_t nbuf, uint8_t newmac[][QDF_MAC_ADDR_SIZE], - uint8_t new_mac_cnt); -void dp_tx_me_alloc_descriptor(struct cdp_pdev *pdev); +uint16_t dp_tx_me_send_convert_ucast(struct cdp_soc_t *soc, uint8_t vdev_id, + qdf_nbuf_t nbuf, + uint8_t newmac[][QDF_MAC_ADDR_SIZE], + uint8_t new_mac_cnt); +void dp_tx_me_alloc_descriptor(struct cdp_soc_t *soc, uint8_t pdev_id); -void dp_tx_me_free_descriptor(struct cdp_pdev *pdev); +void dp_tx_me_free_descriptor(struct cdp_soc_t *soc, uint8_t pdev_id); QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev, uint32_t stats_type_upload_mask, uint32_t config_param_0, uint32_t config_param_1, uint32_t config_param_2, uint32_t config_param_3, int cookie, int cookie_msb, uint8_t mac_id); -void dp_htt_stats_print_tag(uint8_t tag_type, uint32_t *tag_buf); +void dp_htt_stats_print_tag(struct dp_pdev *pdev, + uint8_t tag_type, uint32_t *tag_buf); void dp_htt_stats_copy_tag(struct dp_pdev *pdev, uint8_t tag_type, uint32_t *tag_buf); -int dp_peer_rxtid_stats(struct dp_peer *peer, void (*callback_fn), +/** + * dp_rxtid_stats_cmd_cb - function pointer for peer + * rx tid stats cmd call_back + */ +typedef void (*dp_rxtid_stats_cmd_cb)(struct dp_soc *soc, void *cb_ctxt, + union hal_reo_status *reo_status); +int dp_peer_rxtid_stats(struct dp_peer *peer, + dp_rxtid_stats_cmd_cb dp_stats_cmd_cb, void *cb_ctxt); -void dp_set_pn_check_wifi3(struct cdp_vdev *vdev_handle, - struct cdp_peer *peer_handle, enum cdp_sec_type sec_type, - uint32_t *rx_pn); +QDF_STATUS +dp_set_pn_check_wifi3(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, enum cdp_sec_type sec_type, + uint32_t *rx_pn); -void dp_set_key_sec_type_wifi3(struct cdp_vdev *vdev_handle, - struct cdp_peer *peer_handle, - enum cdp_sec_type sec_type, - bool is_unicast); +QDF_STATUS +dp_set_key_sec_type_wifi3(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, enum cdp_sec_type sec_type, + bool is_unicast); void *dp_get_pdev_for_mac_id(struct dp_soc *soc, uint32_t mac_id); -void dp_set_michael_key(struct cdp_peer *peer_handle, - bool is_unicast, uint32_t *key); -#ifdef CONFIG_WIN -uint32_t dp_pdev_tid_stats_display(void *pdev_handle, - enum _ol_ath_param_t param, uint32_t value, void *buff); -#endif + +QDF_STATUS +dp_set_michael_key(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, + bool is_unicast, uint32_t *key); /** * dp_check_pdev_exists() - Validate pdev before use @@ -1067,6 +1353,121 @@ static inline int dp_get_mac_id_for_pdev(uint32_t mac_id, uint32_t pdev_id) return (mac_id + pdev_id); } +/** + * dp_get_lmac_id_for_pdev_id() - Return lmac id corresponding to host pdev id + * @soc: soc pointer + * @mac_id: MAC id + * @pdev_id: pdev_id corresponding to pdev, 0 for MCL + * + * For MCL, Single pdev using both MACs will operate on both MAC rings. + * + * For WIN, each PDEV will operate one ring. + * + */ +static inline int +dp_get_lmac_id_for_pdev_id + (struct dp_soc *soc, uint32_t mac_id, uint32_t pdev_id) +{ + if (!wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) { + if (mac_id && pdev_id) { + qdf_print("Both mac_id and pdev_id cannot be non zero"); + QDF_BUG(0); + return 0; + } + return (mac_id + pdev_id); + } + + return soc->pdev_list[pdev_id]->lmac_id; +} + +/** + * dp_get_pdev_for_lmac_id() - Return pdev pointer corresponding to lmac id + * @soc: soc pointer + * @lmac_id: LMAC id + * + * For MCL, Single pdev exists + * + * For WIN, each PDEV will operate one ring. + * + */ +static inline struct dp_pdev * + dp_get_pdev_for_lmac_id(struct dp_soc *soc, uint32_t lmac_id) +{ + int i = 0; + + if (wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) { + i = wlan_cfg_get_pdev_idx(soc->wlan_cfg_ctx, lmac_id); + qdf_assert_always(i < MAX_PDEV_CNT); + + return soc->pdev_list[i]; + } + + /* Typically for MCL as there only 1 PDEV*/ + return soc->pdev_list[0]; +} + +/** + * dp_get_target_pdev_id_for_host_pdev_id() - Return target pdev corresponding + * to host pdev id + * @soc: soc pointer + * @mac_for_pdev: pdev_id corresponding to host pdev for WIN, mac id for MCL + * + * returns target pdev_id for host pdev id. For WIN, this is derived through + * a two step process: + * 1. Get lmac_id corresponding to host pdev_id (lmac_id can change + * during mode switch) + * 2. Get target pdev_id (set up during WMI ready) from lmac_id + * + * For MCL, return the offset-1 translated mac_id + */ +static inline int +dp_get_target_pdev_id_for_host_pdev_id + (struct dp_soc *soc, uint32_t mac_for_pdev) +{ + struct dp_pdev *pdev; + + if (!wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) + return DP_SW2HW_MACID(mac_for_pdev); + + pdev = soc->pdev_list[mac_for_pdev]; + + /*non-MCL case, get original target_pdev mapping*/ + return wlan_cfg_get_target_pdev_id(soc->wlan_cfg_ctx, pdev->lmac_id); +} + +/** + * dp_get_host_pdev_id_for_target_pdev_id() - Return host pdev corresponding + * to target pdev id + * @soc: soc pointer + * @pdev_id: pdev_id corresponding to target pdev + * + * returns host pdev_id for target pdev id. For WIN, this is derived through + * a two step process: + * 1. Get lmac_id corresponding to target pdev_id + * 2. Get host pdev_id (set up during WMI ready) from lmac_id + * + * For MCL, return the 0-offset pdev_id + */ +static inline int +dp_get_host_pdev_id_for_target_pdev_id + (struct dp_soc *soc, uint32_t pdev_id) +{ + struct dp_pdev *pdev; + int lmac_id; + + if (!wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) + return DP_HW2SW_MACID(pdev_id); + + /*non-MCL case, get original target_lmac mapping from target pdev*/ + lmac_id = wlan_cfg_get_hw_mac_idx(soc->wlan_cfg_ctx, + DP_HW2SW_MACID(pdev_id)); + + /*Get host pdev from lmac*/ + pdev = dp_get_pdev_for_lmac_id(soc, lmac_id); + + return pdev->pdev_id; +} + /* * dp_get_mac_id_for_mac() - Return mac corresponding WIN and MCL mac_ids * @@ -1122,30 +1523,40 @@ QDF_STATUS dp_h2t_cfg_stats_msg_send(struct dp_pdev *pdev, uint32_t stats_type_upload_mask, uint8_t mac_id); -int dp_wdi_event_unsub(struct cdp_pdev *txrx_pdev_handle, - void *event_cb_sub_handle, - uint32_t event); +int dp_wdi_event_unsub(struct cdp_soc_t *soc, uint8_t pdev_id, + wdi_event_subscribe *event_cb_sub_handle, + uint32_t event); -int dp_wdi_event_sub(struct cdp_pdev *txrx_pdev_handle, - void *event_cb_sub_handle, - uint32_t event); +int dp_wdi_event_sub(struct cdp_soc_t *soc, uint8_t pdev_id, + wdi_event_subscribe *event_cb_sub_handle, + uint32_t event); -void dp_wdi_event_handler(enum WDI_EVENT event, void *soc, - void *data, u_int16_t peer_id, - int status, u_int8_t pdev_id); +void dp_wdi_event_handler(enum WDI_EVENT event, struct dp_soc *soc, + void *data, u_int16_t peer_id, + int status, u_int8_t pdev_id); int dp_wdi_event_attach(struct dp_pdev *txrx_pdev); int dp_wdi_event_detach(struct dp_pdev *txrx_pdev); int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, bool enable); -void *dp_get_pldev(struct cdp_pdev *txrx_pdev); -void dp_pkt_log_init(struct cdp_pdev *ppdev, void *scn); -static inline void dp_hif_update_pipe_callback(void *soc, void *cb_context, - QDF_STATUS (*callback)(void *, qdf_nbuf_t, uint8_t), uint8_t pipe_id) +/** + * dp_get_pldev() - function to get pktlog device handle + * @soc_hdl: datapath soc handle + * @pdev_id: physical device id + * + * Return: pktlog device handle or NULL + */ +void *dp_get_pldev(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); +void dp_pkt_log_init(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, void *scn); + +static inline void +dp_hif_update_pipe_callback(struct dp_soc *dp_soc, + void *cb_context, + QDF_STATUS (*callback)(void *, qdf_nbuf_t, uint8_t), + uint8_t pipe_id) { struct hif_msg_callbacks hif_pipe_callbacks; - struct dp_soc *dp_soc = (struct dp_soc *)soc; /* TODO: Temporary change to bypass HTC connection for this new * HIF pipe, which will be used for packet log and other high- @@ -1158,26 +1569,28 @@ static inline void dp_hif_update_pipe_callback(void *soc, void *cb_context, DP_HTT_T2H_HP_PIPE, &hif_pipe_callbacks); } -QDF_STATUS dp_peer_stats_notify(struct dp_peer *peer); +QDF_STATUS dp_peer_stats_notify(struct dp_pdev *pdev, struct dp_peer *peer); #else -static inline int dp_wdi_event_unsub(struct cdp_pdev *txrx_pdev_handle, - void *event_cb_sub_handle, - uint32_t event) +static inline int dp_wdi_event_unsub(struct cdp_soc_t *soc, uint8_t pdev_id, + wdi_event_subscribe *event_cb_sub_handle, + uint32_t event) { return 0; } -static inline int dp_wdi_event_sub(struct cdp_pdev *txrx_pdev_handle, - void *event_cb_sub_handle, - uint32_t event) +static inline int dp_wdi_event_sub(struct cdp_soc_t *soc, uint8_t pdev_id, + wdi_event_subscribe *event_cb_sub_handle, + uint32_t event) { return 0; } -static inline void dp_wdi_event_handler(enum WDI_EVENT event, void *soc, - void *data, u_int16_t peer_id, - int status, u_int8_t pdev_id) +static inline +void dp_wdi_event_handler(enum WDI_EVENT event, + struct dp_soc *soc, + void *data, u_int16_t peer_id, + int status, u_int8_t pdev_id) { } @@ -1201,19 +1614,70 @@ static inline QDF_STATUS dp_h2t_cfg_stats_msg_send(struct dp_pdev *pdev, { return 0; } -static inline void dp_hif_update_pipe_callback(void *soc, void *cb_context, - QDF_STATUS (*callback)(void *, qdf_nbuf_t, uint8_t), uint8_t pipe_id) + +static inline void +dp_pkt_log_init(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, void *scn) +{ +} + +static inline void +dp_hif_update_pipe_callback(struct dp_soc *dp_soc, void *cb_context, + QDF_STATUS (*callback)(void *, qdf_nbuf_t, uint8_t), + uint8_t pipe_id) { } -static inline QDF_STATUS dp_peer_stats_notify(struct dp_peer *peer) +static inline QDF_STATUS dp_peer_stats_notify(struct dp_pdev *pdev, + struct dp_peer *peer) { return QDF_STATUS_SUCCESS; } #endif /* CONFIG_WIN */ + +#ifdef VDEV_PEER_PROTOCOL_COUNT +/** + * dp_vdev_peer_stats_update_protocol_cnt() - update per-peer protocol counters + * @vdev: VDEV DP object + * @nbuf: data packet + * @peer: Peer DP object + * @is_egress: whether egress or ingress + * @is_rx: whether rx or tx + * + * This function updates the per-peer protocol counters + * Return: void + */ +void dp_vdev_peer_stats_update_protocol_cnt(struct dp_vdev *vdev, + qdf_nbuf_t nbuf, + struct dp_peer *peer, + bool is_egress, + bool is_rx); + +/** + * dp_vdev_peer_stats_update_protocol_cnt() - update per-peer protocol counters + * @soc: SOC DP object + * @vdev_id: vdev_id + * @nbuf: data packet + * @is_egress: whether egress or ingress + * @is_rx: whether rx or tx + * + * This function updates the per-peer protocol counters + * Return: void + */ + +void dp_peer_stats_update_protocol_cnt(struct cdp_soc_t *soc, + int8_t vdev_id, + qdf_nbuf_t nbuf, + bool is_egress, + bool is_rx); + +#else +#define dp_vdev_peer_stats_update_protocol_cnt(vdev, nbuf, peer, \ + is_egress, is_rx) +#endif + #ifdef QCA_LL_TX_FLOW_CONTROL_V2 -void dp_tx_dump_flow_pool_info(void *soc); +void dp_tx_dump_flow_pool_info(struct cdp_soc_t *soc_hdl); int dp_tx_delete_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *pool, bool force); #endif /* QCA_LL_TX_FLOW_CONTROL_V2 */ @@ -1246,7 +1710,7 @@ static inline void dp_peer_unref_del_find_by_id(struct dp_peer *peer) * Return: 0 on success; error on failure */ int dp_srng_access_start(struct dp_intr *int_ctx, struct dp_soc *dp_soc, - void *hal_ring); + hal_ring_handle_t hal_ring_hdl); /** * dp_srng_access_end() - Wrapper function to log access end of a hal ring @@ -1257,28 +1721,30 @@ int dp_srng_access_start(struct dp_intr *int_ctx, struct dp_soc *dp_soc, * Return: void */ void dp_srng_access_end(struct dp_intr *int_ctx, struct dp_soc *dp_soc, - void *hal_ring); + hal_ring_handle_t hal_ring_hdl); #else static inline int dp_srng_access_start(struct dp_intr *int_ctx, - struct dp_soc *dp_soc, void *hal_ring) + struct dp_soc *dp_soc, + hal_ring_handle_t hal_ring_hdl) { - void *hal_soc = dp_soc->hal_soc; + hal_soc_handle_t hal_soc = dp_soc->hal_soc; - return hal_srng_access_start(hal_soc, hal_ring); + return hal_srng_access_start(hal_soc, hal_ring_hdl); } static inline void dp_srng_access_end(struct dp_intr *int_ctx, - struct dp_soc *dp_soc, void *hal_ring) + struct dp_soc *dp_soc, + hal_ring_handle_t hal_ring_hdl) { - void *hal_soc = dp_soc->hal_soc; + hal_soc_handle_t hal_soc = dp_soc->hal_soc; - return hal_srng_access_end(hal_soc, hal_ring); + return hal_srng_access_end(hal_soc, hal_ring_hdl); } #endif /* WLAN_FEATURE_DP_EVENT_HISTORY */ -#ifdef CONFIG_WIN +#ifdef QCA_ENH_V3_STATS_SUPPORT /** * dp_pdev_print_delay_stats(): Print pdev level delay stats * @pdev: DP_PDEV handle @@ -1346,8 +1812,225 @@ QDF_STATUS dp_tx_add_to_comp_queue(struct dp_soc *soc, { return QDF_STATUS_E_FAILURE; } + +/* + * dp_tx_capture_htt_frame_counter: increment counter for htt_frame_type + * pdev: DP pdev handle + * htt_frame_type: htt frame type received from fw + * + * return: void + */ +static inline +void dp_tx_capture_htt_frame_counter(struct dp_pdev *pdev, + uint32_t htt_frame_type) +{ +} + +/* + * dp_tx_cature_stats: print tx capture stats + * @pdev: DP PDEV handle + * + * return: void + */ +static inline +void dp_print_pdev_tx_capture_stats(struct dp_pdev *pdev) +{ +} + #endif +#ifdef FEATURE_PERPKT_INFO +void dp_deliver_mgmt_frm(struct dp_pdev *pdev, qdf_nbuf_t nbuf); +#else +static inline +void dp_deliver_mgmt_frm(struct dp_pdev *pdev, qdf_nbuf_t nbuf) +{ +} +#endif + +/** + * dp_vdev_to_cdp_vdev() - typecast dp vdev to cdp vdev + * @vdev: DP vdev handle + * + * Return: struct cdp_vdev pointer + */ +static inline +struct cdp_vdev *dp_vdev_to_cdp_vdev(struct dp_vdev *vdev) +{ + return (struct cdp_vdev *)vdev; +} + +/** + * dp_pdev_to_cdp_pdev() - typecast dp pdev to cdp pdev + * @pdev: DP pdev handle + * + * Return: struct cdp_pdev pointer + */ +static inline +struct cdp_pdev *dp_pdev_to_cdp_pdev(struct dp_pdev *pdev) +{ + return (struct cdp_pdev *)pdev; +} + +/** + * dp_soc_to_cdp_soc() - typecast dp psoc to cdp psoc + * @psoc: DP psoc handle + * + * Return: struct cdp_soc pointer + */ +static inline +struct cdp_soc *dp_soc_to_cdp_soc(struct dp_soc *psoc) +{ + return (struct cdp_soc *)psoc; +} + +/** + * dp_soc_to_cdp_soc_t() - typecast dp psoc to + * ol txrx soc handle + * @psoc: DP psoc handle + * + * Return: struct cdp_soc_t pointer + */ +static inline +struct cdp_soc_t *dp_soc_to_cdp_soc_t(struct dp_soc *psoc) +{ + return (struct cdp_soc_t *)psoc; +} + +/** + * cdp_soc_t_to_dp_soc() - typecast cdp_soc_t to + * dp soc handle + * @psoc: CDP psoc handle + * + * Return: struct dp_soc pointer + */ +static inline +struct dp_soc *cdp_soc_t_to_dp_soc(struct cdp_soc_t *psoc) +{ + return (struct dp_soc *)psoc; +} + +#if defined(WLAN_SUPPORT_RX_FLOW_TAG) || defined(WLAN_SUPPORT_RX_FISA) +/** + * dp_rx_flow_update_fse_stats() - Update a flow's statistics + * @pdev: pdev handle + * @flow_id: flow index (truncated hash) in the Rx FST + * + * Return: Success when flow statistcs is updated, error on failure + */ +QDF_STATUS dp_rx_flow_get_fse_stats(struct dp_pdev *pdev, + struct cdp_rx_flow_info *rx_flow_info, + struct cdp_flow_stats *stats); + +/** + * dp_rx_flow_delete_entry() - Delete a flow entry from flow search table + * @pdev: pdev handle + * @rx_flow_info: DP flow parameters + * + * Return: Success when flow is deleted, error on failure + */ +QDF_STATUS dp_rx_flow_delete_entry(struct dp_pdev *pdev, + struct cdp_rx_flow_info *rx_flow_info); + +/** + * dp_rx_flow_add_entry() - Add a flow entry to flow search table + * @pdev: DP pdev instance + * @rx_flow_info: DP flow paramaters + * + * Return: Success when flow is added, no-memory or already exists on error + */ +QDF_STATUS dp_rx_flow_add_entry(struct dp_pdev *pdev, + struct cdp_rx_flow_info *rx_flow_info); + +/** + * dp_rx_fst_attach() - Initialize Rx FST and setup necessary parameters + * @soc: SoC handle + * @pdev: Pdev handle + * + * Return: Handle to flow search table entry + */ +QDF_STATUS dp_rx_fst_attach(struct dp_soc *soc, struct dp_pdev *pdev); + +/** + * dp_rx_fst_detach() - De-initialize Rx FST + * @soc: SoC handle + * @pdev: Pdev handle + * + * Return: None + */ +void dp_rx_fst_detach(struct dp_soc *soc, struct dp_pdev *pdev); + +/** + * dp_rx_flow_send_fst_fw_setup() - Program FST parameters in FW/HW post-attach + * @soc: SoC handle + * @pdev: Pdev handle + * + * Return: Success when fst parameters are programmed in FW, error otherwise + */ +QDF_STATUS dp_rx_flow_send_fst_fw_setup(struct dp_soc *soc, + struct dp_pdev *pdev); +#else /* !((WLAN_SUPPORT_RX_FLOW_TAG) || defined(WLAN_SUPPORT_RX_FISA)) */ + +/** + * dp_rx_fst_attach() - Initialize Rx FST and setup necessary parameters + * @soc: SoC handle + * @pdev: Pdev handle + * + * Return: Handle to flow search table entry + */ +static inline +QDF_STATUS dp_rx_fst_attach(struct dp_soc *soc, struct dp_pdev *pdev) +{ + return QDF_STATUS_SUCCESS; +} + +/** + * dp_rx_fst_detach() - De-initialize Rx FST + * @soc: SoC handle + * @pdev: Pdev handle + * + * Return: None + */ +static inline +void dp_rx_fst_detach(struct dp_soc *soc, struct dp_pdev *pdev) +{ +} +#endif + +/** + * dp_get_vdev_from_soc_vdev_id_wifi3() - Returns vdev object given the vdev id + * @soc: core DP soc context + * @vdev_id: vdev id from vdev object can be retrieved + * + * Return: struct dp_vdev*: Pointer to DP vdev object + */ +static inline struct dp_vdev * +dp_get_vdev_from_soc_vdev_id_wifi3(struct dp_soc *soc, + uint8_t vdev_id) +{ + if (qdf_unlikely(vdev_id >= MAX_VDEV_CNT)) + return NULL; + + return soc->vdev_id_map[vdev_id]; +} + +/** + * dp_get_pdev_from_soc_pdev_id_wifi3() - Returns pdev object given the pdev id + * @soc: core DP soc context + * @pdev_id: pdev id from pdev object can be retrieved + * + * Return: struct dp_pdev*: Pointer to DP pdev object + */ +static inline struct dp_pdev * +dp_get_pdev_from_soc_pdev_id_wifi3(struct dp_soc *soc, + uint8_t pdev_id) +{ + if (qdf_unlikely(pdev_id >= MAX_PDEV_CNT)) + return NULL; + + return soc->pdev_list[pdev_id]; +} + /* * dp_rx_tid_update_wifi3() – Update receive TID state * @peer: Datapath peer handle @@ -1360,39 +2043,275 @@ QDF_STATUS dp_tx_add_to_comp_queue(struct dp_soc *soc, QDF_STATUS dp_rx_tid_update_wifi3(struct dp_peer *peer, int tid, uint32_t ba_window_size, uint32_t start_seq); +/** + * dp_get_peer_mac_list(): function to get peer mac list of vdev + * @soc: Datapath soc handle + * @vdev_id: vdev id + * @newmac: Table of the clients mac + * @mac_cnt: No. of MACs required + * + * return: no of clients + */ +uint16_t dp_get_peer_mac_list(ol_txrx_soc_handle soc, uint8_t vdev_id, + u_int8_t newmac[][QDF_MAC_ADDR_SIZE], + u_int16_t mac_cnt); /* - * dp_get_vdev_from_soc_vdev_id_wifi3() - - * Returns vdev object given the vdev id - * vdev id is unique across pdev's + * dp_is_hw_dbs_enable() - Procedure to check if DBS is supported + * @soc: DP SoC context + * @max_mac_rings: No of MAC rings * - * @soc : core DP soc context - * @vdev_id : vdev id from vdev object can be retrieved + * Return: None + */ +void dp_is_hw_dbs_enable(struct dp_soc *soc, + int *max_mac_rings); + + +#if defined(WLAN_SUPPORT_RX_FISA) +void dp_rx_dump_fisa_table(struct dp_soc *soc); +#endif /* WLAN_SUPPORT_RX_FISA */ + +/** + * dp_rx_skip_tlvs() - Skip TLVs len + L2 hdr_offset, save in nbuf->cb + * @nbuf: nbuf cb to be updated + * @l2_hdr_offset: l2_hdr_offset * - * Return: struct dp_vdev*: Pointer to DP vdev object + * Return: None */ -static inline struct dp_vdev * -dp_get_vdev_from_soc_vdev_id_wifi3(struct dp_soc *soc, - uint8_t vdev_id) -{ - struct dp_pdev *pdev = NULL; - struct dp_vdev *vdev = NULL; - int i; - - for (i = 0; i < MAX_PDEV_CNT && soc->pdev_list[i]; i++) { - pdev = soc->pdev_list[i]; - qdf_spin_lock_bh(&pdev->vdev_list_lock); - TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { - if (vdev->vdev_id == vdev_id) { - qdf_spin_unlock_bh(&pdev->vdev_list_lock); - return vdev; - } - } - qdf_spin_unlock_bh(&pdev->vdev_list_lock); - } - dp_err("Failed to find vdev for vdev_id %d", vdev_id); +void dp_rx_skip_tlvs(qdf_nbuf_t nbuf, uint32_t l3_padding); + +#ifdef MAX_ALLOC_PAGE_SIZE +/** + * dp_set_page_size() - Set the max page size for hw link desc. + * For MCL the page size is set to OS defined value and for WIN + * the page size is set to the max_alloc_size cfg ini + * param. + * This is to ensure that WIN gets contiguous memory allocations + * as per requirement. + * @pages: link desc page handle + * @max_alloc_size: max_alloc_size + * + * Return: None + */ +static inline +void dp_set_max_page_size(struct qdf_mem_multi_page_t *pages, + uint32_t max_alloc_size) +{ + pages->page_size = qdf_page_size; +} + +#else +static inline +void dp_set_max_page_size(struct qdf_mem_multi_page_t *pages, + uint32_t max_alloc_size) +{ + pages->page_size = max_alloc_size; +} +#endif /* MAX_ALLOC_PAGE_SIZE */ + +/** + * dp_history_get_next_index() - get the next entry to record an entry + * in the history. + * @curr_idx: Current index where the last entry is written. + * @max_entries: Max number of entries in the history + * + * This function assumes that the max number os entries is a power of 2. + * + * Returns: The index where the next entry is to be written. + */ +static inline uint32_t dp_history_get_next_index(qdf_atomic_t *curr_idx, + uint32_t max_entries) +{ + uint32_t idx = qdf_atomic_inc_return(curr_idx); + + return idx & (max_entries - 1); +} + +#ifdef DP_MEM_PRE_ALLOC +/** + * dp_context_alloc_mem() - allocate memory for DP context + * @soc: datapath soc handle + * @ctxt_type: DP context type + * @ctxt_size: DP context size + * + * Return: DP context address + */ +void *dp_context_alloc_mem(struct dp_soc *soc, enum dp_ctxt_type ctxt_type, + size_t ctxt_size); + +/** + * dp_context_free_mem() - Free memory of DP context + * @soc: datapath soc handle + * @ctxt_type: DP context type + * @vaddr: Address of context memory + * + * Return: None + */ +void dp_context_free_mem(struct dp_soc *soc, enum dp_ctxt_type ctxt_type, + void *vaddr); + +/** + * dp_desc_multi_pages_mem_alloc() - alloc memory over multiple pages + * @soc: datapath soc handle + * @desc_type: memory request source type + * @pages: multi page information storage + * @element_size: each element size + * @element_num: total number of elements should be allocated + * @memctxt: memory context + * @cacheable: coherent memory or cacheable memory + * + * This function is a wrapper for memory allocation over multiple + * pages, if dp prealloc method is registered, then will try prealloc + * firstly. if prealloc failed, fall back to regular way over + * qdf_mem_multi_pages_alloc(). + * + * Return: None + */ +void dp_desc_multi_pages_mem_alloc(struct dp_soc *soc, + enum dp_desc_type desc_type, + struct qdf_mem_multi_page_t *pages, + size_t element_size, + uint16_t element_num, + qdf_dma_context_t memctxt, + bool cacheable); + +/** + * dp_desc_multi_pages_mem_free() - free multiple pages memory + * @soc: datapath soc handle + * @desc_type: memory request source type + * @pages: multi page information storage + * @memctxt: memory context + * @cacheable: coherent memory or cacheable memory + * + * This function is a wrapper for multiple pages memory free, + * if memory is got from prealloc pool, put it back to pool. + * otherwise free by qdf_mem_multi_pages_free(). + * + * Return: None + */ +void dp_desc_multi_pages_mem_free(struct dp_soc *soc, + enum dp_desc_type desc_type, + struct qdf_mem_multi_page_t *pages, + qdf_dma_context_t memctxt, + bool cacheable); + +#else +static inline +void *dp_context_alloc_mem(struct dp_soc *soc, enum dp_ctxt_type ctxt_type, + size_t ctxt_size) +{ + return qdf_mem_malloc(ctxt_size); +} + +static inline +void dp_context_free_mem(struct dp_soc *soc, enum dp_ctxt_type ctxt_type, + void *vaddr) +{ + qdf_mem_free(vaddr); +} + +static inline +void dp_desc_multi_pages_mem_alloc(struct dp_soc *soc, + enum dp_desc_type desc_type, + struct qdf_mem_multi_page_t *pages, + size_t element_size, + uint16_t element_num, + qdf_dma_context_t memctxt, + bool cacheable) +{ + qdf_mem_multi_pages_alloc(soc->osdev, pages, element_size, + element_num, memctxt, cacheable); +} + +static inline +void dp_desc_multi_pages_mem_free(struct dp_soc *soc, + enum dp_desc_type desc_type, + struct qdf_mem_multi_page_t *pages, + qdf_dma_context_t memctxt, + bool cacheable) +{ + qdf_mem_multi_pages_free(soc->osdev, pages, + memctxt, cacheable); +} + +#endif +#ifdef FEATURE_RUNTIME_PM +/** + * dp_runtime_get() - Get dp runtime refcount + * @soc: Datapath soc handle + * + * Get dp runtime refcount by increment of an atomic variable, which can block + * dp runtime resume to wait to flush pending tx by runtime suspend. + * + * Return: Current refcount + */ +static inline int32_t dp_runtime_get(struct dp_soc *soc) +{ + return qdf_atomic_inc_return(&soc->dp_runtime_refcount); +} + +/** + * dp_runtime_put() - Return dp runtime refcount + * @soc: Datapath soc handle + * + * Return dp runtime refcount by decrement of an atomic variable, allow dp + * runtime resume finish. + * + * Return: Current refcount + */ +static inline int32_t dp_runtime_put(struct dp_soc *soc) +{ + return qdf_atomic_dec_return(&soc->dp_runtime_refcount); +} + +/** + * dp_runtime_get_refcount() - Get dp runtime refcount + * @soc: Datapath soc handle + * + * Get dp runtime refcount by returning an atomic variable + * + * Return: Current refcount + */ +static inline int32_t dp_runtime_get_refcount(struct dp_soc *soc) +{ + return qdf_atomic_read(&soc->dp_runtime_refcount); +} + +/** + * dp_runtime_init() - Init dp runtime refcount when dp soc init + * @soc: Datapath soc handle + * + * Return: QDF_STATUS + */ +static inline QDF_STATUS dp_runtime_init(struct dp_soc *soc) +{ + return qdf_atomic_init(&soc->dp_runtime_refcount); +} +#else +static inline int32_t dp_runtime_get(struct dp_soc *soc) +{ + return 0; +} - return NULL; +static inline int32_t dp_runtime_put(struct dp_soc *soc) +{ + return 0; +} +static inline QDF_STATUS dp_runtime_init(struct dp_soc *soc) +{ + return QDF_STATUS_SUCCESS; } +#endif +/** + * dp_peer_flush_frags() - Flush all fragments for a particular + * peer + * @soc_hdl - data path soc handle + * @vdev_id - vdev id + * @peer_addr - peer mac address + * + * Return: None + */ +void dp_peer_flush_frags(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_mac); #endif /* #ifndef _DP_INTERNAL_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_ipa.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_ipa.c index 6a9d28259cafc9dbb9a7b605affd7427b1ab5054..2f6ecb3510760081fe47b4691c98c73091d34b3c 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_ipa.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_ipa.c @@ -31,6 +31,9 @@ #include "dp_rx.h" #include "dp_ipa.h" +/* Ring index for WBM2SW2 release ring */ +#define IPA_TX_COMP_RING_IDX HAL_IPA_TX_COMP_RING_IDX + /* Hard coded config parameters until dp_ops_cfg.cfg_attach implemented */ #define CFG_IPA_UC_TX_BUF_SIZE_DEFAULT (2048) @@ -290,7 +293,7 @@ static int dp_tx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev) uint32_t tx_buffer_count; uint32_t ring_base_align = 8; qdf_dma_addr_t buffer_paddr; - struct hal_srng *wbm_srng = + struct hal_srng *wbm_srng = (struct hal_srng *) soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng; struct hal_srng_params srng_params; uint32_t paddr_lo; @@ -309,7 +312,8 @@ static int dp_tx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev) unsigned int uc_tx_buf_sz = CFG_IPA_UC_TX_BUF_SIZE_DEFAULT; unsigned int alloc_size = uc_tx_buf_sz + ring_base_align - 1; - hal_get_srng_params(soc->hal_soc, (void *)wbm_srng, &srng_params); + hal_get_srng_params(soc->hal_soc, hal_srng_to_hal_ring_handle(wbm_srng), + &srng_params); num_entries = srng_params.num_entries; max_alloc_count = @@ -330,7 +334,8 @@ static int dp_tx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev) return -ENOMEM; } - hal_srng_access_start_unlocked(soc->hal_soc, (void *)wbm_srng); + hal_srng_access_start_unlocked(soc->hal_soc, + hal_srng_to_hal_ring_handle(wbm_srng)); /* * Allocate Tx buffers as many as possible. @@ -346,7 +351,7 @@ static int dp_tx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev) break; ring_entry = hal_srng_dst_get_next_hp(soc->hal_soc, - (void *)wbm_srng); + hal_srng_to_hal_ring_handle(wbm_srng)); if (!ring_entry) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, "%s: Failed to get WBM ring entry", @@ -373,7 +378,8 @@ static int dp_tx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev) __dp_ipa_handle_buf_smmu_mapping(soc, nbuf, true); } - hal_srng_access_end_unlocked(soc->hal_soc, wbm_srng); + hal_srng_access_end_unlocked(soc->hal_soc, + hal_srng_to_hal_ring_handle(wbm_srng)); soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt = tx_buffer_count; @@ -454,8 +460,11 @@ int dp_ipa_ring_resource_setup(struct dp_soc *soc, return QDF_STATUS_SUCCESS; /* IPA TCL_DATA Ring - HAL_SRNG_SW2TCL3 */ - hal_srng = soc->tcl_data_ring[IPA_TCL_DATA_RING_IDX].hal_srng; - hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params); + hal_srng = (struct hal_srng *) + soc->tcl_data_ring[IPA_TCL_DATA_RING_IDX].hal_srng; + hal_get_srng_params(hal_soc_to_hal_soc_handle(hal_soc), + hal_srng_to_hal_ring_handle(hal_srng), + &srng_params); soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr = srng_params.ring_base_paddr; @@ -485,8 +494,11 @@ int dp_ipa_ring_resource_setup(struct dp_soc *soc, soc->ipa_uc_tx_rsc.ipa_tcl_ring_size); /* IPA TX COMP Ring - HAL_SRNG_WBM2SW2_RELEASE */ - hal_srng = soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng; - hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params); + hal_srng = (struct hal_srng *) + soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng; + hal_get_srng_params(hal_soc_to_hal_soc_handle(hal_soc), + hal_srng_to_hal_ring_handle(hal_srng), + &srng_params); soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr = srng_params.ring_base_paddr; @@ -494,6 +506,9 @@ int dp_ipa_ring_resource_setup(struct dp_soc *soc, srng_params.ring_base_vaddr; soc->ipa_uc_tx_rsc.ipa_wbm_ring_size = (srng_params.num_entries * srng_params.entry_size) << 2; + soc->ipa_uc_tx_rsc.ipa_wbm_hp_shadow_paddr = + hal_srng_get_hp_addr(hal_soc_to_hal_soc_handle(hal_soc), + hal_srng_to_hal_ring_handle(hal_srng)); addr_offset = (unsigned long)(hal_srng->u.dst_ring.tp_addr) - (unsigned long)(hal_soc->dev_base_addr); soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr = @@ -509,8 +524,11 @@ int dp_ipa_ring_resource_setup(struct dp_soc *soc, soc->ipa_uc_tx_rsc.ipa_wbm_ring_size); /* IPA REO_DEST Ring - HAL_SRNG_REO2SW4 */ - hal_srng = soc->reo_dest_ring[IPA_REO_DEST_RING_IDX].hal_srng; - hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params); + hal_srng = (struct hal_srng *) + soc->reo_dest_ring[IPA_REO_DEST_RING_IDX].hal_srng; + hal_get_srng_params(hal_soc_to_hal_soc_handle(hal_soc), + hal_srng_to_hal_ring_handle(hal_srng), + &srng_params); soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr = srng_params.ring_base_paddr; @@ -532,15 +550,19 @@ int dp_ipa_ring_resource_setup(struct dp_soc *soc, srng_params.num_entries, soc->ipa_uc_rx_rsc.ipa_reo_ring_size); - hal_srng = pdev->rx_refill_buf_ring2.hal_srng; - hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params); + hal_srng = (struct hal_srng *) + pdev->rx_refill_buf_ring2.hal_srng; + hal_get_srng_params(hal_soc_to_hal_soc_handle(hal_soc), + hal_srng_to_hal_ring_handle(hal_srng), + &srng_params); soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr = srng_params.ring_base_paddr; soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_vaddr = srng_params.ring_base_vaddr; soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size = (srng_params.num_entries * srng_params.entry_size) << 2; - hp_addr = hal_srng_get_hp_addr(hal_soc, (void *)hal_srng); + hp_addr = hal_srng_get_hp_addr(hal_soc_to_hal_soc_handle(hal_soc), + hal_srng_to_hal_ring_handle(hal_srng)); soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr = qdf_mem_paddr_from_dmaaddr(soc->osdev, hp_addr); @@ -555,14 +577,14 @@ int dp_ipa_ring_resource_setup(struct dp_soc *soc, * Set DEST_RING_MAPPING_4 to SW2 as default value for * DESTINATION_RING_CTRL_IX_0. */ - ix0 = HAL_REO_REMAP_VAL(REO_REMAP_TCL, REO_REMAP_TCL) | - HAL_REO_REMAP_VAL(REO_REMAP_SW1, REO_REMAP_SW1) | - HAL_REO_REMAP_VAL(REO_REMAP_SW2, REO_REMAP_SW2) | - HAL_REO_REMAP_VAL(REO_REMAP_SW3, REO_REMAP_SW3) | - HAL_REO_REMAP_VAL(REO_REMAP_SW4, REO_REMAP_SW2) | - HAL_REO_REMAP_VAL(REO_REMAP_RELEASE, REO_REMAP_RELEASE) | - HAL_REO_REMAP_VAL(REO_REMAP_FW, REO_REMAP_FW) | - HAL_REO_REMAP_VAL(REO_REMAP_UNUSED, REO_REMAP_FW); + ix0 = HAL_REO_REMAP_IX0(REO_REMAP_TCL, 0) | + HAL_REO_REMAP_IX0(REO_REMAP_SW1, 1) | + HAL_REO_REMAP_IX0(REO_REMAP_SW2, 2) | + HAL_REO_REMAP_IX0(REO_REMAP_SW3, 3) | + HAL_REO_REMAP_IX0(REO_REMAP_SW2, 4) | + HAL_REO_REMAP_IX0(REO_REMAP_RELEASE, 5) | + HAL_REO_REMAP_IX0(REO_REMAP_FW, 6) | + HAL_REO_REMAP_IX0(REO_REMAP_FW, 7); hal_reo_read_write_ctrl_ix(soc->hal_soc, false, &ix0, NULL, NULL, NULL); @@ -597,22 +619,19 @@ static QDF_STATUS dp_ipa_get_shared_mem_info(qdf_device_t osdev, return QDF_STATUS_SUCCESS; } -/** - * dp_ipa_uc_get_resource() - Client request resource information - * @ppdev - handle to the device instance - * - * IPA client will request IPA UC related resource information - * Resource information will be distributed to IPA module - * All of the required resources should be pre-allocated - * - * Return: QDF_STATUS - */ -QDF_STATUS dp_ipa_get_resource(struct cdp_pdev *ppdev) +QDF_STATUS dp_ipa_get_resource(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; - struct dp_soc *soc = pdev->soc; - struct dp_ipa_resources *ipa_res = &pdev->ipa_resource; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + struct dp_ipa_resources *ipa_res; + + if (!pdev) { + dp_err("%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + ipa_res = &pdev->ipa_resource; if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx)) return QDF_STATUS_SUCCESS; @@ -648,27 +667,45 @@ QDF_STATUS dp_ipa_get_resource(struct cdp_pdev *ppdev) return QDF_STATUS_SUCCESS; } -/** - * dp_ipa_set_doorbell_paddr () - Set doorbell register physical address to SRNG - * @ppdev - handle to the device instance - * - * Set TX_COMP_DOORBELL register physical address to WBM Head_Ptr_MemAddr_LSB - * Set RX_READ_DOORBELL register physical address to REO Head_Ptr_MemAddr_LSB - * - * Return: none - */ -QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_pdev *ppdev) +static void dp_ipa_set_tx_doorbell_paddr(struct dp_soc *soc, + struct dp_ipa_resources *ipa_res) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; - struct dp_soc *soc = pdev->soc; - struct dp_ipa_resources *ipa_res = &pdev->ipa_resource; - struct hal_srng *wbm_srng = + struct hal_srng *wbm_srng = (struct hal_srng *) soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng; - struct hal_srng *reo_srng = + + hal_srng_dst_set_hp_paddr_confirm(wbm_srng, + ipa_res->tx_comp_doorbell_paddr); + + dp_info("paddr %pK vaddr %pK", + (void *)ipa_res->tx_comp_doorbell_paddr, + (void *)ipa_res->tx_comp_doorbell_vaddr); +} + +#ifdef IPA_SET_RESET_TX_DB_PA +#define DP_IPA_SET_TX_DB_PADDR(soc, ipa_res) +#else +#define DP_IPA_SET_TX_DB_PADDR(soc, ipa_res) \ + dp_ipa_set_tx_doorbell_paddr(soc, ipa_res) +#endif + +QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + struct dp_ipa_resources *ipa_res; + struct hal_srng *reo_srng = (struct hal_srng *) soc->reo_dest_ring[IPA_REO_DEST_RING_IDX].hal_srng; uint32_t tx_comp_doorbell_dmaaddr; uint32_t rx_ready_doorbell_dmaaddr; + int ret = 0; + + if (!pdev) { + dp_err("%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + ipa_res = &pdev->ipa_resource; if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx)) return QDF_STATUS_SUCCESS; @@ -676,20 +713,22 @@ QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_pdev *ppdev) ioremap(ipa_res->tx_comp_doorbell_paddr, 4); if (qdf_mem_smmu_s1_enabled(soc->osdev)) { - pld_smmu_map(soc->osdev->dev, ipa_res->tx_comp_doorbell_paddr, - &tx_comp_doorbell_dmaaddr, sizeof(uint32_t)); + ret = pld_smmu_map(soc->osdev->dev, + ipa_res->tx_comp_doorbell_paddr, + &tx_comp_doorbell_dmaaddr, + sizeof(uint32_t)); ipa_res->tx_comp_doorbell_paddr = tx_comp_doorbell_dmaaddr; + qdf_assert_always(!ret); - pld_smmu_map(soc->osdev->dev, ipa_res->rx_ready_doorbell_paddr, - &rx_ready_doorbell_dmaaddr, sizeof(uint32_t)); + ret = pld_smmu_map(soc->osdev->dev, + ipa_res->rx_ready_doorbell_paddr, + &rx_ready_doorbell_dmaaddr, + sizeof(uint32_t)); ipa_res->rx_ready_doorbell_paddr = rx_ready_doorbell_dmaaddr; + qdf_assert_always(!ret); } - hal_srng_dst_set_hp_paddr(wbm_srng, ipa_res->tx_comp_doorbell_paddr); - - dp_info("paddr %pK vaddr %pK", - (void *)ipa_res->tx_comp_doorbell_paddr, - (void *)ipa_res->tx_comp_doorbell_vaddr); + DP_IPA_SET_TX_DB_PADDR(soc, ipa_res); /* * For RX, REO module on Napier/Hastings does reordering on incoming @@ -698,20 +737,22 @@ QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_pdev *ppdev) * to IPA. * Set the doorbell addr for the REO ring. */ - hal_srng_dst_set_hp_paddr(reo_srng, ipa_res->rx_ready_doorbell_paddr); + hal_srng_dst_set_hp_paddr_confirm(reo_srng, + ipa_res->rx_ready_doorbell_paddr); return QDF_STATUS_SUCCESS; } -/** - * dp_ipa_op_response() - Handle OP command response from firmware - * @ppdev - handle to the device instance - * @op_msg: op response message from firmware - * - * Return: none - */ -QDF_STATUS dp_ipa_op_response(struct cdp_pdev *ppdev, uint8_t *op_msg) +QDF_STATUS dp_ipa_op_response(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint8_t *op_msg) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (!pdev) { + dp_err("%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } if (!wlan_cfg_is_ipa_enabled(pdev->soc->wlan_cfg_ctx)) return QDF_STATUS_SUCCESS; @@ -728,18 +769,18 @@ QDF_STATUS dp_ipa_op_response(struct cdp_pdev *ppdev, uint8_t *op_msg) return QDF_STATUS_SUCCESS; } -/** - * dp_ipa_register_op_cb() - Register OP handler function - * @ppdev - handle to the device instance - * @op_cb: handler function pointer - * - * Return: none - */ -QDF_STATUS dp_ipa_register_op_cb(struct cdp_pdev *ppdev, +QDF_STATUS dp_ipa_register_op_cb(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, ipa_uc_op_cb_type op_cb, void *usr_ctxt) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (!pdev) { + dp_err("%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } if (!wlan_cfg_is_ipa_enabled(pdev->soc->wlan_cfg_ctx)) return QDF_STATUS_SUCCESS; @@ -750,13 +791,7 @@ QDF_STATUS dp_ipa_register_op_cb(struct cdp_pdev *ppdev, return QDF_STATUS_SUCCESS; } -/** - * dp_ipa_get_stat() - Get firmware wdi status - * @ppdev - handle to the device instance - * - * Return: none - */ -QDF_STATUS dp_ipa_get_stat(struct cdp_pdev *ppdev) +QDF_STATUS dp_ipa_get_stat(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) { /* TBD */ return QDF_STATUS_SUCCESS; @@ -764,18 +799,20 @@ QDF_STATUS dp_ipa_get_stat(struct cdp_pdev *ppdev) /** * dp_tx_send_ipa_data_frame() - send IPA data frame - * @vdev: vdev - * @skb: skb + * @soc_hdl: datapath soc handle + * @vdev_id: id of the virtual device + * @skb: skb to transmit * * Return: skb/ NULL is for success */ -qdf_nbuf_t dp_tx_send_ipa_data_frame(struct cdp_vdev *vdev, qdf_nbuf_t skb) +qdf_nbuf_t dp_tx_send_ipa_data_frame(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + qdf_nbuf_t skb) { qdf_nbuf_t ret; /* Terminate the (single-element) list of tx frames */ qdf_nbuf_set_next(skb, NULL); - ret = dp_tx_send((struct dp_vdev_t *)vdev, skb); + ret = dp_tx_send(soc_hdl, vdev_id, skb); if (ret) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: Failed to tx", __func__); @@ -785,23 +822,19 @@ qdf_nbuf_t dp_tx_send_ipa_data_frame(struct cdp_vdev *vdev, qdf_nbuf_t skb) return NULL; } -/** - * dp_ipa_enable_autonomy() – Enable autonomy RX path - * @pdev - handle to the device instance - * - * Set all RX packet route to IPA REO ring - * Program Destination_Ring_Ctrl_IX_0 REO register to point IPA REO ring - * - * Return: QDF_STATUS_SUCCESS in case of success - * QDF error code in failure cases - */ -QDF_STATUS dp_ipa_enable_autonomy(struct cdp_pdev *ppdev) +QDF_STATUS dp_ipa_enable_autonomy(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); uint32_t ix0; uint32_t ix2; + if (!pdev) { + dp_err("%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx)) return QDF_STATUS_SUCCESS; @@ -809,20 +842,24 @@ QDF_STATUS dp_ipa_enable_autonomy(struct cdp_pdev *ppdev) return QDF_STATUS_E_AGAIN; /* Call HAL API to remap REO rings to REO2IPA ring */ - ix0 = HAL_REO_REMAP_VAL(REO_REMAP_TCL, REO_REMAP_TCL) | - HAL_REO_REMAP_VAL(REO_REMAP_SW1, REO_REMAP_SW4) | - HAL_REO_REMAP_VAL(REO_REMAP_SW2, REO_REMAP_SW4) | - HAL_REO_REMAP_VAL(REO_REMAP_SW3, REO_REMAP_SW4) | - HAL_REO_REMAP_VAL(REO_REMAP_SW4, REO_REMAP_SW4) | - HAL_REO_REMAP_VAL(REO_REMAP_RELEASE, REO_REMAP_RELEASE) | - HAL_REO_REMAP_VAL(REO_REMAP_FW, REO_REMAP_FW) | - HAL_REO_REMAP_VAL(REO_REMAP_UNUSED, REO_REMAP_FW); + ix0 = HAL_REO_REMAP_IX0(REO_REMAP_TCL, 0) | + HAL_REO_REMAP_IX0(REO_REMAP_SW4, 1) | + HAL_REO_REMAP_IX0(REO_REMAP_SW1, 2) | + HAL_REO_REMAP_IX0(REO_REMAP_SW4, 3) | + HAL_REO_REMAP_IX0(REO_REMAP_SW4, 4) | + HAL_REO_REMAP_IX0(REO_REMAP_RELEASE, 5) | + HAL_REO_REMAP_IX0(REO_REMAP_FW, 6) | + HAL_REO_REMAP_IX0(REO_REMAP_FW, 7); if (wlan_cfg_is_rx_hash_enabled(soc->wlan_cfg_ctx)) { - ix2 = ((REO_REMAP_SW4 << 0) | (REO_REMAP_SW4 << 3) | - (REO_REMAP_SW4 << 6) | (REO_REMAP_SW4 << 9) | - (REO_REMAP_SW4 << 12) | (REO_REMAP_SW4 << 15) | - (REO_REMAP_SW4 << 18) | (REO_REMAP_SW4 << 21)) << 8; + ix2 = HAL_REO_REMAP_IX2(REO_REMAP_SW4, 16) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 17) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 18) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 19) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 20) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 21) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 22) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 23); hal_reo_read_write_ctrl_ix(soc->hal_soc, false, &ix0, NULL, &ix2, &ix2); @@ -836,24 +873,20 @@ QDF_STATUS dp_ipa_enable_autonomy(struct cdp_pdev *ppdev) return QDF_STATUS_SUCCESS; } -/** - * dp_ipa_disable_autonomy() – Disable autonomy RX path - * @ppdev - handle to the device instance - * - * Disable RX packet routing to IPA REO - * Program Destination_Ring_Ctrl_IX_0 REO register to disable - * - * Return: QDF_STATUS_SUCCESS in case of success - * QDF error code in failure cases - */ -QDF_STATUS dp_ipa_disable_autonomy(struct cdp_pdev *ppdev) +QDF_STATUS dp_ipa_disable_autonomy(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); uint32_t ix0; uint32_t ix2; uint32_t ix3; + if (!pdev) { + dp_err("%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx)) return QDF_STATUS_SUCCESS; @@ -861,14 +894,14 @@ QDF_STATUS dp_ipa_disable_autonomy(struct cdp_pdev *ppdev) return QDF_STATUS_E_AGAIN; /* Call HAL API to remap REO rings to REO2IPA ring */ - ix0 = HAL_REO_REMAP_VAL(REO_REMAP_TCL, REO_REMAP_TCL) | - HAL_REO_REMAP_VAL(REO_REMAP_SW1, REO_REMAP_SW1) | - HAL_REO_REMAP_VAL(REO_REMAP_SW2, REO_REMAP_SW2) | - HAL_REO_REMAP_VAL(REO_REMAP_SW3, REO_REMAP_SW3) | - HAL_REO_REMAP_VAL(REO_REMAP_SW4, REO_REMAP_SW2) | - HAL_REO_REMAP_VAL(REO_REMAP_RELEASE, REO_REMAP_RELEASE) | - HAL_REO_REMAP_VAL(REO_REMAP_FW, REO_REMAP_FW) | - HAL_REO_REMAP_VAL(REO_REMAP_UNUSED, REO_REMAP_FW); + ix0 = HAL_REO_REMAP_IX0(REO_REMAP_TCL, 0) | + HAL_REO_REMAP_IX0(REO_REMAP_SW1, 1) | + HAL_REO_REMAP_IX0(REO_REMAP_SW2, 2) | + HAL_REO_REMAP_IX0(REO_REMAP_SW3, 3) | + HAL_REO_REMAP_IX0(REO_REMAP_SW2, 4) | + HAL_REO_REMAP_IX0(REO_REMAP_RELEASE, 5) | + HAL_REO_REMAP_IX0(REO_REMAP_FW, 6) | + HAL_REO_REMAP_IX0(REO_REMAP_FW, 7); if (wlan_cfg_is_rx_hash_enabled(soc->wlan_cfg_ctx)) { dp_reo_remap_config(soc, &ix2, &ix3); @@ -1105,32 +1138,18 @@ dp_ipa_wdi_rx_smmu_params(struct dp_soc *soc, RX_PKT_TLVS_LEN + L3_HEADER_PADDING; } -/** - * dp_ipa_setup() - Setup and connect IPA pipes - * @ppdev - handle to the device instance - * @ipa_i2w_cb: IPA to WLAN callback - * @ipa_w2i_cb: WLAN to IPA callback - * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback - * @ipa_desc_size: IPA descriptor size - * @ipa_priv: handle to the HTT instance - * @is_rm_enabled: Is IPA RM enabled or not - * @tx_pipe_handle: pointer to Tx pipe handle - * @rx_pipe_handle: pointer to Rx pipe handle - * @is_smmu_enabled: Is SMMU enabled or not - * @sys_in: parameters to setup sys pipe in mcc mode - * - * Return: QDF_STATUS - */ -QDF_STATUS dp_ipa_setup(struct cdp_pdev *ppdev, void *ipa_i2w_cb, - void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, +QDF_STATUS dp_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + void *ipa_i2w_cb, void *ipa_w2i_cb, + void *ipa_wdi_meter_notifier_cb, uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled, uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle, bool is_smmu_enabled, qdf_ipa_sys_connect_params_t *sys_in, bool over_gsi) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; - struct dp_soc *soc = pdev->soc; - struct dp_ipa_resources *ipa_res = &pdev->ipa_resource; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + struct dp_ipa_resources *ipa_res; qdf_ipa_ep_cfg_t *tx_cfg; qdf_ipa_ep_cfg_t *rx_cfg; qdf_ipa_wdi_pipe_setup_info_t *tx = NULL; @@ -1141,6 +1160,12 @@ QDF_STATUS dp_ipa_setup(struct cdp_pdev *ppdev, void *ipa_i2w_cb, qdf_ipa_wdi_conn_out_params_t pipe_out; int ret; + if (!pdev) { + dp_err("%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + + ipa_res = &pdev->ipa_resource; if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx)) return QDF_STATUS_SUCCESS; @@ -1262,7 +1287,9 @@ QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr, struct dp_ipa_uc_tx_hdr uc_tx_hdr_v6; int ret = -EINVAL; - dp_debug("Add Partial hdr: %s, %pM", ifname, mac_addr); + dp_debug("Add Partial hdr: %s, "QDF_MAC_ADDR_FMT, ifname, + QDF_MAC_ADDR_REF(mac_addr)); + qdf_mem_zero(&in, sizeof(qdf_ipa_wdi_reg_intf_in_params_t)); qdf_mem_zero(&hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t)); qdf_ether_addr_copy(uc_tx_hdr.eth.h_source, mac_addr); @@ -1309,30 +1336,17 @@ QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr, } #else /* CONFIG_IPA_WDI_UNIFIED_API */ - -/** - * dp_ipa_setup() - Setup and connect IPA pipes - * @ppdev - handle to the device instance - * @ipa_i2w_cb: IPA to WLAN callback - * @ipa_w2i_cb: WLAN to IPA callback - * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback - * @ipa_desc_size: IPA descriptor size - * @ipa_priv: handle to the HTT instance - * @is_rm_enabled: Is IPA RM enabled or not - * @tx_pipe_handle: pointer to Tx pipe handle - * @rx_pipe_handle: pointer to Rx pipe handle - * - * Return: QDF_STATUS - */ -QDF_STATUS dp_ipa_setup(struct cdp_pdev *ppdev, void *ipa_i2w_cb, - void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, +QDF_STATUS dp_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + void *ipa_i2w_cb, void *ipa_w2i_cb, + void *ipa_wdi_meter_notifier_cb, uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled, uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; - struct dp_soc *soc = pdev->soc; - struct dp_ipa_resources *ipa_res = &pdev->ipa_resource; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + struct dp_ipa_resources *ipa_res; qdf_ipa_wdi_pipe_setup_info_t *tx; qdf_ipa_wdi_pipe_setup_info_t *rx; qdf_ipa_wdi_conn_in_params_t pipe_in; @@ -1342,6 +1356,12 @@ QDF_STATUS dp_ipa_setup(struct cdp_pdev *ppdev, void *ipa_i2w_cb, uint32_t desc_size; int ret; + if (!pdev) { + dp_err("%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + + ipa_res = &pdev->ipa_resource; if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx)) return QDF_STATUS_SUCCESS; @@ -1524,9 +1544,10 @@ QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr, int ret = -EINVAL; QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, - "%s: Add Partial hdr: %s, %pM", - __func__, ifname, mac_addr); + "%s: Add Partial hdr: %s, "QDF_MAC_ADDR_FMT, + __func__, ifname, QDF_MAC_ADDR_REF(mac_addr)); + qdf_mem_zero(&in, sizeof(qdf_ipa_wdi_reg_intf_in_params_t)); qdf_mem_zero(&hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t)); qdf_ether_addr_copy(uc_tx_hdr.eth.h_source, mac_addr); @@ -1571,23 +1592,53 @@ QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr, /** * dp_ipa_cleanup() - Disconnect IPA pipes + * @soc_hdl: dp soc handle + * @pdev_id: dp pdev id * @tx_pipe_handle: Tx pipe handle * @rx_pipe_handle: Rx pipe handle * * Return: QDF_STATUS */ -QDF_STATUS dp_ipa_cleanup(uint32_t tx_pipe_handle, uint32_t rx_pipe_handle) +QDF_STATUS dp_ipa_cleanup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint32_t tx_pipe_handle, uint32_t rx_pipe_handle) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_ipa_resources *ipa_res; + struct dp_pdev *pdev; int ret; ret = qdf_ipa_wdi_disconn_pipes(); if (ret) { dp_err("ipa_wdi_disconn_pipes: IPA pipe cleanup failed: ret=%d", ret); - return QDF_STATUS_E_FAILURE; + status = QDF_STATUS_E_FAILURE; } - return QDF_STATUS_SUCCESS; + pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + if (qdf_unlikely(!pdev)) { + dp_err_rl("Invalid pdev for pdev_id %d", pdev_id); + status = QDF_STATUS_E_FAILURE; + goto exit; + } + + if (qdf_mem_smmu_s1_enabled(soc->osdev)) { + ipa_res = &pdev->ipa_resource; + + /* unmap has to be the reverse order of smmu map */ + ret = pld_smmu_unmap(soc->osdev->dev, + ipa_res->rx_ready_doorbell_paddr, + sizeof(uint32_t)); + qdf_assert_always(!ret); + + ret = pld_smmu_unmap(soc->osdev->dev, + ipa_res->tx_comp_doorbell_paddr, + sizeof(uint32_t)); + qdf_assert_always(!ret); + } + +exit: + return status; } /** @@ -1612,24 +1663,55 @@ QDF_STATUS dp_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled) return QDF_STATUS_SUCCESS; } -/** - * dp_ipa_uc_enable_pipes() - Enable and resume traffic on Tx/Rx pipes - * @ppdev - handle to the device instance - * - * Return: QDF_STATUS - */ -QDF_STATUS dp_ipa_enable_pipes(struct cdp_pdev *ppdev) +#ifdef IPA_SET_RESET_TX_DB_PA +static +QDF_STATUS dp_ipa_reset_tx_doorbell_pa(struct dp_soc *soc, + struct dp_ipa_resources *ipa_res) +{ + hal_ring_handle_t wbm_srng = + soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng; + qdf_dma_addr_t hp_addr; + + if (!wbm_srng) + return QDF_STATUS_E_FAILURE; + + hp_addr = soc->ipa_uc_tx_rsc.ipa_wbm_hp_shadow_paddr; + + hal_srng_dst_set_hp_paddr_confirm((struct hal_srng *)wbm_srng, hp_addr); + + dp_info("Reset WBM HP addr paddr: %pK", (void *)hp_addr); + + return QDF_STATUS_SUCCESS; +} + +#define DP_IPA_EP_SET_TX_DB_PA(soc, ipa_res) \ + dp_ipa_set_tx_doorbell_paddr((soc), (ipa_res)) +#define DP_IPA_RESET_TX_DB_PA(soc, ipa_res) \ + dp_ipa_reset_tx_doorbell_pa((soc), (ipa_res)) +#else +#define DP_IPA_EP_SET_TX_DB_PA(soc, ipa_res) +#define DP_IPA_RESET_TX_DB_PA(soc, ipa_res) +#endif + +QDF_STATUS dp_ipa_enable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); struct hal_srng *wbm_srng = (struct hal_srng *) soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng; struct dp_ipa_resources *ipa_res; QDF_STATUS result; + if (!pdev) { + dp_err("%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + ipa_res = &pdev->ipa_resource; qdf_atomic_set(&soc->ipa_pipes_enabled, 1); + DP_IPA_EP_SET_TX_DB_PA(soc, ipa_res); dp_ipa_handle_rx_buf_pool_smmu_mapping(soc, pdev, true); result = qdf_ipa_wdi_enable_pipes(); @@ -1638,29 +1720,43 @@ QDF_STATUS dp_ipa_enable_pipes(struct cdp_pdev *ppdev) "%s: Enable WDI PIPE fail, code %d", __func__, result); qdf_atomic_set(&soc->ipa_pipes_enabled, 0); + DP_IPA_RESET_TX_DB_PA(soc, ipa_res); dp_ipa_handle_rx_buf_pool_smmu_mapping(soc, pdev, false); return QDF_STATUS_E_FAILURE; } if (soc->ipa_first_tx_db_access) { - hal_srng_dst_init_hp(wbm_srng, ipa_res->tx_comp_doorbell_vaddr); + hal_srng_dst_init_hp( + soc->hal_soc, wbm_srng, + ipa_res->tx_comp_doorbell_vaddr); soc->ipa_first_tx_db_access = false; } return QDF_STATUS_SUCCESS; } -/** - * dp_ipa_uc_disable_pipes() – Suspend traffic and disable Tx/Rx pipes - * @ppdev - handle to the device instance - * - * Return: QDF_STATUS - */ -QDF_STATUS dp_ipa_disable_pipes(struct cdp_pdev *ppdev) +QDF_STATUS dp_ipa_disable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); QDF_STATUS result; + struct dp_ipa_resources *ipa_res; + + if (!pdev) { + dp_err("%s invalid instance", __func__); + return QDF_STATUS_E_FAILURE; + } + + ipa_res = &pdev->ipa_resource; + + qdf_sleep(TX_COMP_DRAIN_WAIT_TIMEOUT_MS); + /* + * Reset the tx completion doorbell address before invoking IPA disable + * pipes API to ensure that there is no access to IPA tx doorbell + * address post disable pipes. + */ + DP_IPA_RESET_TX_DB_PA(soc, ipa_res); result = qdf_ipa_wdi_disable_pipes(); if (result) { @@ -1725,7 +1821,7 @@ static qdf_nbuf_t dp_ipa_intrabss_send(struct dp_pdev *pdev, qdf_mem_zero(nbuf->cb, sizeof(nbuf->cb)); len = qdf_nbuf_len(nbuf); - if (dp_tx_send(vdev, nbuf)) { + if (dp_tx_send((struct cdp_soc_t *)pdev->soc, vdev->vdev_id, nbuf)) { DP_STATS_INC_PKT(vdev_peer, rx.intra_bss.fail, 1, len); return nbuf; } @@ -1734,17 +1830,18 @@ static qdf_nbuf_t dp_ipa_intrabss_send(struct dp_pdev *pdev, return NULL; } -bool dp_ipa_rx_intrabss_fwd(struct cdp_vdev *pvdev, qdf_nbuf_t nbuf, - bool *fwd_success) +bool dp_ipa_rx_intrabss_fwd(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + qdf_nbuf_t nbuf, bool *fwd_success) { - struct dp_vdev *vdev = (struct dp_vdev *)pvdev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); struct dp_pdev *pdev; struct dp_peer *da_peer; struct dp_peer *sa_peer; qdf_nbuf_t nbuf_copy; uint8_t da_is_bcmc; struct ethhdr *eh; - uint8_t local_id; *fwd_success = false; /* set default as failure */ @@ -1785,22 +1882,20 @@ bool dp_ipa_rx_intrabss_fwd(struct cdp_vdev *pvdev, qdf_nbuf_t nbuf, if (!qdf_mem_cmp(eh->h_dest, vdev->mac_addr.raw, QDF_MAC_ADDR_SIZE)) return false; - da_peer = dp_find_peer_by_addr((struct cdp_pdev *)pdev, eh->h_dest, - &local_id); + da_peer = dp_find_peer_by_addr_and_vdev(dp_pdev_to_cdp_pdev(pdev), + dp_vdev_to_cdp_vdev(vdev), + eh->h_dest); + if (!da_peer) return false; - if (da_peer->vdev != vdev) - return false; + sa_peer = dp_find_peer_by_addr_and_vdev(dp_pdev_to_cdp_pdev(pdev), + dp_vdev_to_cdp_vdev(vdev), + eh->h_source); - sa_peer = dp_find_peer_by_addr((struct cdp_pdev *)pdev, eh->h_source, - &local_id); if (!sa_peer) return false; - if (sa_peer->vdev != vdev) - return false; - /* * In intra-bss forwarding scenario, skb is allocated by IPA driver. * Need to add skb to internal tracking table to avoid nbuf memory @@ -1846,16 +1941,16 @@ static qdf_nbuf_t dp_ipa_frag_nbuf_linearize(struct dp_soc *soc, bool is_nbuf_head = true; uint32_t copy_len = 0; - dst_nbuf = qdf_nbuf_alloc(soc->osdev, RX_BUFFER_SIZE, - RX_BUFFER_RESERVATION, RX_BUFFER_ALIGNMENT, - FALSE); + dst_nbuf = qdf_nbuf_alloc(soc->osdev, RX_DATA_BUFFER_SIZE, + RX_BUFFER_RESERVATION, + RX_DATA_BUFFER_ALIGNMENT, FALSE); if (!dst_nbuf) { dp_err_rl("nbuf allocate fail"); return NULL; } - if ((nbuf_len + L3_HEADER_PADDING) > RX_BUFFER_SIZE) { + if ((nbuf_len + L3_HEADER_PADDING) > RX_DATA_BUFFER_SIZE) { qdf_nbuf_free(dst_nbuf); dp_err_rl("nbuf is jumbo data"); return NULL; diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_ipa.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_ipa.h index 48b071a8c9857490fc899132194453de0b3128be..0ec21d3ce1892e432a44b9baf2f48376267d5f6c 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_ipa.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_ipa.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, 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 above @@ -21,10 +21,13 @@ #define DP_IPA_MAX_IFACE 3 #define IPA_TCL_DATA_RING_IDX 2 -#define IPA_TX_COMP_RING_IDX 2 #define IPA_REO_DEST_RING_IDX 3 #define IPA_RX_REFILL_BUF_RING_IDX 2 +/* Adding delay before disabling ipa pipes if any Tx Completions are pending */ +#define TX_COMP_DRAIN_WAIT_MS 50 +#define TX_COMP_DRAIN_WAIT_TIMEOUT_MS 200 + /** * struct dp_ipa_uc_tx_hdr - full tx header registered to IPA hardware * @eth: ether II header @@ -45,34 +48,150 @@ struct dp_ipa_uc_rx_hdr { #define DP_IPA_UC_WLAN_RX_HDR_LEN sizeof(struct dp_ipa_uc_rx_hdr) #define DP_IPA_UC_WLAN_HDR_DES_MAC_OFFSET 0 -QDF_STATUS dp_ipa_get_resource(struct cdp_pdev *pdev); -QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_pdev *pdev); -QDF_STATUS dp_ipa_uc_set_active(struct cdp_pdev *pdev, bool uc_active, - bool is_tx); -QDF_STATUS dp_ipa_op_response(struct cdp_pdev *pdev, uint8_t *op_msg); -QDF_STATUS dp_ipa_register_op_cb(struct cdp_pdev *pdev, ipa_uc_op_cb_type op_cb, - void *usr_ctxt); -QDF_STATUS dp_ipa_get_stat(struct cdp_pdev *pdev); -qdf_nbuf_t dp_tx_send_ipa_data_frame(struct cdp_vdev *vdev, qdf_nbuf_t skb); -QDF_STATUS dp_ipa_enable_autonomy(struct cdp_pdev *pdev); -QDF_STATUS dp_ipa_disable_autonomy(struct cdp_pdev *pdev); +/** + * dp_ipa_get_resource() - Client request resource information + * @soc_hdl - data path soc handle + * @pdev_id - device instance id + * + * IPA client will request IPA UC related resource information + * Resource information will be distributed to IPA module + * All of the required resources should be pre-allocated + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_get_resource(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); + +/** + * dp_ipa_set_doorbell_paddr () - Set doorbell register physical address to SRNG + * @soc_hdl - data path soc handle + * @pdev_id - device instance id + * + * Set TX_COMP_DOORBELL register physical address to WBM Head_Ptr_MemAddr_LSB + * Set RX_READ_DOORBELL register physical address to REO Head_Ptr_MemAddr_LSB + * + * Return: none + */ +QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id); +QDF_STATUS dp_ipa_uc_set_active(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + bool uc_active, bool is_tx); + +/** + * dp_ipa_op_response() - Handle OP command response from firmware + * @soc_hdl - data path soc handle + * @pdev_id - device instance id + * @op_msg: op response message from firmware + * + * Return: none + */ +QDF_STATUS dp_ipa_op_response(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint8_t *op_msg); + +/** + * dp_ipa_register_op_cb() - Register OP handler function + * @soc_hdl - data path soc handle + * @pdev_id - device instance id + * @op_cb: handler function pointer + * + * Return: none + */ +QDF_STATUS dp_ipa_register_op_cb(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + ipa_uc_op_cb_type op_cb, void *usr_ctxt); + +/** + * dp_ipa_get_stat() - Get firmware wdi status + * @soc_hdl - data path soc handle + * @pdev_id - device instance id + * + * Return: none + */ +QDF_STATUS dp_ipa_get_stat(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); + +/** + * dp_tx_send_ipa_data_frame() - send IPA data frame + * @soc_hdl: datapath soc handle + * @vdev_id: virtual device/interface id + * @skb: skb + * + * Return: skb/ NULL is for success + */ +qdf_nbuf_t dp_tx_send_ipa_data_frame(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + qdf_nbuf_t skb); + +/** + * dp_ipa_enable_autonomy() – Enable autonomy RX path + * @soc_hdl - data path soc handle + * @pdev_id - device instance id + * + * Set all RX packet route to IPA REO ring + * Program Destination_Ring_Ctrl_IX_0 REO register to point IPA REO ring + * Return: none + */ +QDF_STATUS dp_ipa_enable_autonomy(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); + +/** + * dp_ipa_disable_autonomy() – Disable autonomy RX path + * @soc_hdl - data path soc handle + * @pdev_id - device instance id + * + * Disable RX packet routing to IPA REO + * Program Destination_Ring_Ctrl_IX_0 REO register to disable + * Return: none + */ +QDF_STATUS dp_ipa_disable_autonomy(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); + #ifdef CONFIG_IPA_WDI_UNIFIED_API -QDF_STATUS dp_ipa_setup(struct cdp_pdev *pdev, void *ipa_i2w_cb, - void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, +/** + * dp_ipa_setup() - Setup and connect IPA pipes + * @soc_hdl - data path soc handle + * @pdev_id - device instance id + * @ipa_i2w_cb: IPA to WLAN callback + * @ipa_w2i_cb: WLAN to IPA callback + * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback + * @ipa_desc_size: IPA descriptor size + * @ipa_priv: handle to the HTT instance + * @is_rm_enabled: Is IPA RM enabled or not + * @tx_pipe_handle: pointer to Tx pipe handle + * @rx_pipe_handle: pointer to Rx pipe handle + * @is_smmu_enabled: Is SMMU enabled or not + * @sys_in: parameters to setup sys pipe in mcc mode + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + void *ipa_i2w_cb, void *ipa_w2i_cb, + void *ipa_wdi_meter_notifier_cb, uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled, uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle, bool is_smmu_enabled, qdf_ipa_sys_connect_params_t *sys_in, bool over_gsi); #else /* CONFIG_IPA_WDI_UNIFIED_API */ -QDF_STATUS dp_ipa_setup(struct cdp_pdev *pdev, void *ipa_i2w_cb, - void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb, +/** + * dp_ipa_setup() - Setup and connect IPA pipes + * @soc_hdl - data path soc handle + * @pdev_id - device instance id + * @ipa_i2w_cb: IPA to WLAN callback + * @ipa_w2i_cb: WLAN to IPA callback + * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback + * @ipa_desc_size: IPA descriptor size + * @ipa_priv: handle to the HTT instance + * @is_rm_enabled: Is IPA RM enabled or not + * @tx_pipe_handle: pointer to Tx pipe handle + * @rx_pipe_handle: pointer to Rx pipe handle + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + void *ipa_i2w_cb, void *ipa_w2i_cb, + void *ipa_wdi_meter_notifier_cb, uint32_t ipa_desc_size, void *ipa_priv, bool is_rm_enabled, uint32_t *tx_pipe_handle, uint32_t *rx_pipe_handle); #endif /* CONFIG_IPA_WDI_UNIFIED_API */ -QDF_STATUS dp_ipa_cleanup(uint32_t tx_pipe_handle, - uint32_t rx_pipe_handle); +QDF_STATUS dp_ipa_cleanup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint32_t tx_pipe_handle, + uint32_t rx_pipe_handle); QDF_STATUS dp_ipa_remove_header(char *name); int dp_ipa_add_header_info(char *ifname, uint8_t *mac_addr, uint8_t session_id, bool is_ipv6_enabled); @@ -82,15 +201,32 @@ QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr, qdf_ipa_client_type_t cons_client, uint8_t session_id, bool is_ipv6_enabled); QDF_STATUS dp_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled); -QDF_STATUS dp_ipa_enable_pipes(struct cdp_pdev *pdev); -QDF_STATUS dp_ipa_disable_pipes(struct cdp_pdev *pdev); + +/** + * dp_ipa_uc_enable_pipes() - Enable and resume traffic on Tx/Rx pipes + * @soc_hdl - handle to the soc + * @pdev_id - pdev id number, to get the handle + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_enable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); + +/** + * dp_ipa_disable_pipes() – Suspend traffic and disable Tx/Rx pipes + * @soc_hdl - handle to the soc + * @pdev_id - pdev id number, to get the handle + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_ipa_disable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); QDF_STATUS dp_ipa_set_perf_level(int client, uint32_t max_supported_bw_mbps); /** * dp_ipa_rx_intrabss_fwd() - Perform intra-bss fwd for IPA RX path * - * @pvdev: pointer to dp_vdev structure + * @soc_hdl: data path soc handle + * @vdev_id: virtual device/interface id * @nbuf: pointer to skb of ethernet packet received from IPA RX path * @fwd_success: pointer to indicate if skb succeeded in intra-bss TX * @@ -99,8 +235,8 @@ QDF_STATUS dp_ipa_set_perf_level(int client, * Return: true if packet is intra-bss fwd-ed and no need to pass to * network stack. false if packet needs to be passed to network stack. */ -bool dp_ipa_rx_intrabss_fwd(struct cdp_vdev *pvdev, qdf_nbuf_t nbuf, - bool *fwd_success); +bool dp_ipa_rx_intrabss_fwd(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + qdf_nbuf_t nbuf, bool *fwd_success); int dp_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev); int dp_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev); int dp_ipa_ring_resource_setup(struct dp_soc *soc, diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_main.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_main.c index 12041016ad1791d9e7d1da28484b3def678f07e7..926543b156e86d426de96e2450a562fa665d1c8a 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_main.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_main.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -45,10 +46,14 @@ #include "dp_peer.h" #include "dp_rx_mon.h" #include "htt_stats.h" -#include "htt_ppdu_stats.h" #include "dp_htt.h" +#ifdef WLAN_SUPPORT_RX_FISA +#include +#endif +#include "htt_ppdu_stats.h" #include "qdf_mem.h" /* qdf_mem_malloc,free */ #include "cfg_ucfg_api.h" +#include "dp_mon_filter.h" #ifdef QCA_LL_TX_FLOW_CONTROL_V2 #include "cdp_txrx_flow_ctrl_v2.h" #else @@ -63,7 +68,10 @@ cdp_dump_flow_pool_info(struct cdp_soc_t *soc) #ifdef FEATURE_WDS #include "dp_txrx_wds.h" #endif -#ifdef CONFIG_MCL +#ifdef ATH_SUPPORT_IQUE +#include "dp_txrx_me.h" +#endif +#if defined(DP_CON_MON) #ifndef REMOVE_PKT_LOG #include #include @@ -87,6 +95,14 @@ cdp_dump_flow_pool_info(struct cdp_soc_t *soc) #define SET_PEER_REF_CNT_ONE(_peer) #endif +/* + * The max size of cdp_peer_stats_param_t is limited to 16 bytes. + * If the buffer size is exceeding this size limit, + * dp_txrx_get_peer_stats is to be used instead. + */ +QDF_COMPILE_TIME_ASSERT(cdp_peer_stats_param_t_max_size, + (sizeof(cdp_peer_stats_param_t) <= 16)); + #ifdef WLAN_FEATURE_DP_EVENT_HISTORY /* * If WLAN_CFG_INT_NUM_CONTEXTS is changed, HIF_NUM_INT_CONTEXTS @@ -102,6 +118,14 @@ QDF_COMPILE_TIME_ASSERT(hif_event_history_size, (HIF_EVENT_HIST_MAX & (HIF_EVENT_HIST_MAX - 1)) == 0); #endif /* WLAN_FEATURE_DP_EVENT_HISTORY */ +/* + * If WLAN_CFG_INT_NUM_CONTEXTS is changed, + * WLAN_CFG_INT_NUM_CONTEXTS_MAX should also be updated + */ +QDF_COMPILE_TIME_ASSERT(wlan_cfg_num_int_ctxs, + WLAN_CFG_INT_NUM_CONTEXTS_MAX >= + WLAN_CFG_INT_NUM_CONTEXTS); + #ifdef WLAN_RX_PKT_CAPTURE_ENH #include "dp_rx_mon_feature.h" #else @@ -113,7 +137,7 @@ QDF_COMPILE_TIME_ASSERT(hif_event_history_size, * Return: QDF_STATUS */ static QDF_STATUS -dp_config_enh_rx_capture(struct cdp_pdev *pdev_handle, uint8_t val) +dp_config_enh_rx_capture(struct dp_pdev *pdev_handle, uint8_t val) { return QDF_STATUS_E_INVAL; } @@ -130,30 +154,51 @@ dp_config_enh_rx_capture(struct cdp_pdev *pdev_handle, uint8_t val) * Return: QDF_STATUS */ static QDF_STATUS -dp_config_enh_tx_capture(struct cdp_pdev *pdev_handle, int val) +dp_config_enh_tx_capture(struct dp_pdev *pdev_handle, uint8_t val) { return QDF_STATUS_E_INVAL; } #endif -void *dp_soc_init(void *dpsoc, HTC_HANDLE htc_handle, void *hif_handle); +void *dp_soc_init(struct dp_soc *soc, HTC_HANDLE htc_handle, + struct hif_opaque_softc *hif_handle); static void dp_pdev_detach(struct cdp_pdev *txrx_pdev, int force); static struct dp_soc * -dp_soc_attach(void *ctrl_psoc, HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, +dp_soc_attach(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, HTC_HANDLE htc_handle, + qdf_device_t qdf_osdev, struct ol_if_ops *ol_ops, uint16_t device_id); static void dp_pktlogmod_exit(struct dp_pdev *handle); -static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, - uint8_t *peer_mac_addr, - struct cdp_ctrl_objmgr_peer *ctrl_peer); -static void dp_peer_delete_wifi3(void *peer_handle, uint32_t bitmap); -static void dp_ppdu_ring_reset(struct dp_pdev *pdev); -static void dp_ppdu_ring_cfg(struct dp_pdev *pdev); +static inline QDF_STATUS dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, + uint8_t *peer_mac_addr); +static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, + uint8_t *peer_mac, uint32_t bitmap); static void dp_vdev_flush_peers(struct cdp_vdev *vdev_handle, bool unmap_only); #ifdef ENABLE_VERBOSE_DEBUG bool is_dp_verbose_debug_enabled; #endif +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) +static void dp_cfr_filter(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + bool enable, + struct cdp_monitor_filter *filter_val); +static bool dp_get_cfr_rcc(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); +static void dp_set_cfr_rcc(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + bool enable); +static inline void +dp_get_cfr_dbg_stats(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct cdp_cfr_rcc_stats *cfr_rcc_stats); +static inline void +dp_clear_cfr_dbg_stats(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); +static inline void +dp_enable_mon_reap_timer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + bool enable); +#endif +static inline bool +dp_is_enable_reap_timer_non_pkt(struct dp_pdev *pdev); static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc, enum hal_ring_type ring_type, int ring_num); @@ -234,37 +279,17 @@ static uint8_t default_pcp_tid_map[PCP_TID_MAP_MAX] = { /** * @brief Cpu to tx ring map */ -#ifdef CONFIG_WIN -#ifdef WLAN_TX_PKT_CAPTURE_ENH uint8_t -dp_cpu_ring_map[DP_NSS_CPU_RING_MAP_MAX][WLAN_CFG_INT_NUM_CONTEXTS] = { +dp_cpu_ring_map[DP_NSS_CPU_RING_MAP_MAX][WLAN_CFG_INT_NUM_CONTEXTS_MAX] = { {0x0, 0x1, 0x2, 0x0, 0x0, 0x1, 0x2, 0x0, 0x0, 0x1, 0x2}, {0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1}, {0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0}, {0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2}, {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3}, +#ifdef WLAN_TX_PKT_CAPTURE_ENH {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1} -}; -#else -static uint8_t -dp_cpu_ring_map[DP_NSS_CPU_RING_MAP_MAX][WLAN_CFG_INT_NUM_CONTEXTS] = { - {0x0, 0x1, 0x2, 0x0, 0x0, 0x1, 0x2, 0x0, 0x0, 0x1, 0x2}, - {0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1}, - {0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0}, - {0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2}, - {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} -}; #endif -#else -static uint8_t -dp_cpu_ring_map[DP_NSS_CPU_RING_MAP_MAX][WLAN_CFG_INT_NUM_CONTEXTS] = { - {0x0, 0x1, 0x2, 0x0, 0x0, 0x1, 0x2}, - {0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1}, - {0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0}, - {0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2}, - {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3} }; -#endif /** * @brief Select the type of statistics @@ -321,11 +346,13 @@ const int dp_stats_mapping_table[][STATS_TYPE_MAX] = { {TXRX_FW_STATS_INVALID, TXRX_SOC_CFG_PARAMS}, {TXRX_FW_STATS_INVALID, TXRX_PDEV_CFG_PARAMS}, {TXRX_FW_STATS_INVALID, TXRX_SOC_INTERRUPT_STATS}, + {TXRX_FW_STATS_INVALID, TXRX_SOC_FSE_STATS}, {TXRX_FW_STATS_INVALID, TXRX_HAL_REG_WRITE_STATS}, + {TXRX_FW_STATS_INVALID, TXRX_SOC_REO_HW_DESC_DUMP}, }; /* MCL specific functions */ -#ifdef CONFIG_MCL +#if defined(DP_CON_MON) /** * dp_soc_get_mon_mask_for_interrupt_mode() - get mon mode mask for intr mode * @soc: pointer to dp_soc handle @@ -357,23 +384,18 @@ uint32_t dp_soc_get_mon_mask_for_interrupt_mode(struct dp_soc *soc, int intr_ctx */ static void dp_service_mon_rings(struct dp_soc *soc, uint32_t quota) { - int ring = 0, work_done, mac_id; + int ring = 0, work_done; struct dp_pdev *pdev = NULL; - for (ring = 0 ; ring < MAX_PDEV_CNT; ring++) { - pdev = soc->pdev_list[ring]; + for (ring = 0 ; ring < MAX_NUM_LMAC_HW; ring++) { + pdev = dp_get_pdev_for_lmac_id(soc, ring); if (!pdev) continue; - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); - work_done = dp_mon_process(soc, mac_for_pdev, - QCA_NAPI_BUDGET); + work_done = dp_mon_process(soc, ring, quota); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - FL("Reaped %d descs from Monitor rings"), - work_done); - } + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + FL("Reaped %d descs from Monitor rings"), + work_done); } } @@ -397,14 +419,22 @@ static void dp_mon_reap_timer_handler(void *arg) #ifndef REMOVE_PKT_LOG /** * dp_pkt_log_init() - API to initialize packet log - * @ppdev: physical device handle + * @soc_hdl: Datapath soc handle + * @pdev_id: id of data path pdev handle * @scn: HIF context * * Return: none */ -void dp_pkt_log_init(struct cdp_pdev *ppdev, void *scn) +void dp_pkt_log_init(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, void *scn) { - struct dp_pdev *handle = (struct dp_pdev *)ppdev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *handle = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (!handle) { + dp_err("pdev handle is NULL"); + return; + } if (handle->pkt_log_init) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -413,6 +443,7 @@ void dp_pkt_log_init(struct cdp_pdev *ppdev, void *scn) } pktlog_sethandle(&handle->pl_dev, scn); + pktlog_set_pdev_id(handle->pl_dev, pdev_id); pktlog_set_callback_regtype(PKTLOG_DEFAULT_CALLBACK_REGISTRATION); if (pktlogmod_init(scn)) { @@ -426,39 +457,19 @@ void dp_pkt_log_init(struct cdp_pdev *ppdev, void *scn) /** * dp_pkt_log_con_service() - connect packet log service - * @ppdev: physical device handle + * @soc_hdl: Datapath soc handle + * @pdev_id: id of data path pdev handle * @scn: device context * * Return: none */ -static void dp_pkt_log_con_service(struct cdp_pdev *ppdev, void *scn) +static void dp_pkt_log_con_service(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, void *scn) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; - - dp_pkt_log_init((struct cdp_pdev *)pdev, scn); + dp_pkt_log_init(soc_hdl, pdev_id, scn); pktlog_htc_attach(); } -/** - * dp_get_num_rx_contexts() - get number of RX contexts - * @soc_hdl: cdp opaque soc handle - * - * Return: number of RX contexts - */ -static int dp_get_num_rx_contexts(struct cdp_soc_t *soc_hdl) -{ - int i; - int num_rx_contexts = 0; - - struct dp_soc *soc = (struct dp_soc *)soc_hdl; - - for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) - if (wlan_cfg_get_rx_ring_mask(soc->wlan_cfg_ctx, i)) - num_rx_contexts++; - - return num_rx_contexts; -} - /** * dp_pktlogmod_exit() - API to cleanup pktlog info * @pdev: Pdev handle @@ -477,13 +488,40 @@ static void dp_pktlogmod_exit(struct dp_pdev *pdev) /* stop mon_reap_timer if it has been started */ if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED && - soc->reap_timer_init) + soc->reap_timer_init && (!dp_is_enable_reap_timer_non_pkt(pdev))) qdf_timer_sync_cancel(&soc->mon_reap_timer); pktlogmod_exit(scn); pdev->pkt_log_init = false; } +#else +static void dp_pkt_log_con_service(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, void *scn) +{ +} + +static void dp_pktlogmod_exit(struct dp_pdev *handle) { } #endif +/** + * dp_get_num_rx_contexts() - get number of RX contexts + * @soc_hdl: cdp opaque soc handle + * + * Return: number of RX contexts + */ +static int dp_get_num_rx_contexts(struct cdp_soc_t *soc_hdl) +{ + int i; + int num_rx_contexts = 0; + + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + + for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) + if (wlan_cfg_get_rx_ring_mask(soc->wlan_cfg_ctx, i)) + num_rx_contexts++; + + return num_rx_contexts; +} + #else static void dp_pktlogmod_exit(struct dp_pdev *handle) { } @@ -499,43 +537,101 @@ uint32_t dp_soc_get_mon_mask_for_interrupt_mode(struct dp_soc *soc, int intr_ctx { return wlan_cfg_get_rx_mon_ring_mask(soc->wlan_cfg_ctx, intr_ctx_num); } -#endif -/** - * dp_get_dp_vdev_from_cdp_vdev() - get dp_vdev from cdp_vdev by type-casting - * @cdp_opaque_vdev: pointer to cdp_vdev +/* + * dp_service_lmac_rings()- timer to reap lmac rings + * @arg: SoC Handle + * + * Return: * - * Return: pointer to dp_vdev */ -static -struct dp_vdev *dp_get_dp_vdev_from_cdp_vdev(struct cdp_vdev *cdp_opaque_vdev) +static void dp_service_lmac_rings(void *arg) { - return (struct dp_vdev *)cdp_opaque_vdev; + struct dp_soc *soc = (struct dp_soc *)arg; + int ring = 0, i; + struct dp_pdev *pdev = NULL; + union dp_rx_desc_list_elem_t *desc_list = NULL; + union dp_rx_desc_list_elem_t *tail = NULL; + + /* Process LMAC interrupts */ + for (ring = 0 ; ring < MAX_NUM_LMAC_HW; ring++) { + int mac_for_pdev = ring; + struct dp_srng *rx_refill_buf_ring; + + pdev = dp_get_pdev_for_lmac_id(soc, mac_for_pdev); + if (!pdev) + continue; + + rx_refill_buf_ring = &soc->rx_refill_buf_ring[mac_for_pdev]; + + dp_mon_process(soc, mac_for_pdev, + QCA_NAPI_BUDGET); + + for (i = 0; + i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) + dp_rxdma_err_process(&soc->intr_ctx[i], soc, + mac_for_pdev, + QCA_NAPI_BUDGET); + + if (!dp_soc_ring_if_nss_offloaded(soc, RXDMA_BUF, + mac_for_pdev)) + dp_rx_buffers_replenish(soc, mac_for_pdev, + rx_refill_buf_ring, + &soc->rx_desc_buf[mac_for_pdev], + 0, &desc_list, &tail); + } + + qdf_timer_mod(&soc->lmac_reap_timer, DP_INTR_POLL_TIMER_MS); } +#endif static int dp_peer_add_ast_wifi3(struct cdp_soc_t *soc_hdl, - struct cdp_peer *peer_hdl, - uint8_t *mac_addr, - enum cdp_txrx_ast_entry_type type, - uint32_t flags) + uint8_t vdev_id, + uint8_t *peer_mac, + uint8_t *mac_addr, + enum cdp_txrx_ast_entry_type type, + uint32_t flags) { - return dp_peer_add_ast((struct dp_soc *)soc_hdl, - (struct dp_peer *)peer_hdl, - mac_addr, - type, - flags); + int ret = -1; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc_hdl, + peer_mac, 0, vdev_id); + + if (!peer || peer->delete_in_progress) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s: Peer is NULL!\n", __func__); + goto fail; + } + + ret = dp_peer_add_ast((struct dp_soc *)soc_hdl, + peer, + mac_addr, + type, + flags); +fail: + if (peer) + dp_peer_unref_delete(peer); + + return ret; } static int dp_peer_update_ast_wifi3(struct cdp_soc_t *soc_hdl, - struct cdp_peer *peer_hdl, + uint8_t vdev_id, + uint8_t *peer_mac, uint8_t *wds_macaddr, uint32_t flags) { int status = -1; struct dp_soc *soc = (struct dp_soc *)soc_hdl; struct dp_ast_entry *ast_entry = NULL; - struct dp_peer *peer = (struct dp_peer *)peer_hdl; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc_hdl, + peer_mac, 0, vdev_id); + + if (!peer || peer->delete_in_progress) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s: Peer is NULL!\n", __func__); + goto fail; + } qdf_spin_lock_bh(&soc->ast_lock); ast_entry = dp_peer_ast_hash_find_by_pdevid(soc, wds_macaddr, @@ -546,9 +642,12 @@ static int dp_peer_update_ast_wifi3(struct cdp_soc_t *soc_hdl, peer, ast_entry, flags); } - qdf_spin_unlock_bh(&soc->ast_lock); +fail: + if (peer) + dp_peer_unref_delete(peer); + return status; } @@ -556,30 +655,39 @@ static int dp_peer_update_ast_wifi3(struct cdp_soc_t *soc_hdl, * dp_wds_reset_ast_wifi3() - Reset the is_active param for ast entry * @soc_handle: Datapath SOC handle * @wds_macaddr: WDS entry MAC Address - * Return: None + * @peer_macaddr: WDS entry MAC Address + * @vdev_id: id of vdev handle + * Return: QDF_STATUS */ -static void dp_wds_reset_ast_wifi3(struct cdp_soc_t *soc_hdl, - uint8_t *wds_macaddr, - uint8_t *peer_mac_addr, - void *vdev_handle) +static QDF_STATUS dp_wds_reset_ast_wifi3(struct cdp_soc_t *soc_hdl, + uint8_t *wds_macaddr, + uint8_t *peer_mac_addr, + uint8_t vdev_id) { struct dp_soc *soc = (struct dp_soc *)soc_hdl; struct dp_ast_entry *ast_entry = NULL; struct dp_ast_entry *tmp_ast_entry; struct dp_peer *peer; - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; struct dp_pdev *pdev; + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); if (!vdev) - return; + return QDF_STATUS_E_FAILURE; pdev = vdev->pdev; if (peer_mac_addr) { peer = dp_peer_find_hash_find(soc, peer_mac_addr, 0, vdev->vdev_id); - if (!peer) - return; + if (!peer) { + return QDF_STATUS_E_FAILURE; + } + + if (peer->delete_in_progress) { + dp_peer_unref_delete(peer); + return QDF_STATUS_E_FAILURE; + } + qdf_spin_lock_bh(&soc->ast_lock); DP_PEER_ITERATE_ASE_LIST(peer, ast_entry, tmp_ast_entry) { if ((ast_entry->type == CDP_TXRX_AST_TYPE_WDS_HM) || @@ -589,6 +697,7 @@ static void dp_wds_reset_ast_wifi3(struct cdp_soc_t *soc_hdl, qdf_spin_unlock_bh(&soc->ast_lock); dp_peer_unref_delete(peer); + return QDF_STATUS_SUCCESS; } else if (wds_macaddr) { qdf_spin_lock_bh(&soc->ast_lock); ast_entry = dp_peer_ast_hash_find_by_pdevid(soc, wds_macaddr, @@ -601,16 +710,19 @@ static void dp_wds_reset_ast_wifi3(struct cdp_soc_t *soc_hdl, } qdf_spin_unlock_bh(&soc->ast_lock); } + + return QDF_STATUS_SUCCESS; } /* * dp_wds_reset_ast_table_wifi3() - Reset the is_active param for all ast entry * @soc: Datapath SOC handle * - * Return: None + * Return: QDF_STATUS */ -static void dp_wds_reset_ast_table_wifi3(struct cdp_soc_t *soc_hdl, - void *vdev_hdl) +static QDF_STATUS +dp_wds_reset_ast_table_wifi3(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id) { struct dp_soc *soc = (struct dp_soc *) soc_hdl; struct dp_pdev *pdev; @@ -639,6 +751,8 @@ static void dp_wds_reset_ast_table_wifi3(struct cdp_soc_t *soc_hdl, } qdf_spin_unlock_bh(&soc->ast_lock); + + return QDF_STATUS_SUCCESS; } /* @@ -715,7 +829,7 @@ static bool dp_peer_get_ast_info_by_soc_wifi3 } ast_entry_info->type = ast_entry->type; ast_entry_info->pdev_id = ast_entry->pdev_id; - ast_entry_info->vdev_id = ast_entry->vdev_id; + ast_entry_info->vdev_id = ast_entry->peer->vdev->vdev_id; ast_entry_info->peer_id = ast_entry->peer->peer_ids[0]; qdf_mem_copy(&ast_entry_info->peer_mac_addr[0], &ast_entry->peer->mac_addr.raw[0], @@ -760,7 +874,7 @@ static bool dp_peer_get_ast_info_by_pdevid_wifi3 } ast_entry_info->type = ast_entry->type; ast_entry_info->pdev_id = ast_entry->pdev_id; - ast_entry_info->vdev_id = ast_entry->vdev_id; + ast_entry_info->vdev_id = ast_entry->peer->vdev->vdev_id; ast_entry_info->peer_id = ast_entry->peer->peer_ids[0]; qdf_mem_copy(&ast_entry_info->peer_mac_addr[0], &ast_entry->peer->mac_addr.raw[0], @@ -819,7 +933,7 @@ static QDF_STATUS dp_peer_ast_entry_del_by_soc(struct cdp_soc_t *soc_handle, qdf_spin_unlock_bh(&soc->ast_lock); if (cb) { cb(soc->ctrl_psoc, - soc, + dp_soc_to_cdp_soc(soc), arg, CDP_TXRX_AST_DELETE_IN_PROGRESS); } @@ -881,7 +995,7 @@ static QDF_STATUS dp_peer_ast_entry_del_by_pdev(struct cdp_soc_t *soc_handle, if (cb) { cb(soc->ctrl_psoc, - soc, + dp_soc_to_cdp_soc(soc), arg, CDP_TXRX_AST_DELETE_IN_PROGRESS); } @@ -1066,6 +1180,8 @@ void dp_print_ast_stats(struct dp_soc *soc) DP_PRINT_STATS(" Entries Added = %d", soc->stats.ast.added); DP_PRINT_STATS(" Entries Deleted = %d", soc->stats.ast.deleted); DP_PRINT_STATS(" Entries Agedout = %d", soc->stats.ast.aged_out); + DP_PRINT_STATS(" Entries MAP ERR = %d", soc->stats.ast.map_err); + DP_PRINT_STATS("AST Table:"); qdf_spin_lock_bh(&soc->ast_lock); @@ -1075,29 +1191,29 @@ void dp_print_ast_stats(struct dp_soc *soc) DP_PDEV_ITERATE_VDEV_LIST(pdev, vdev) { DP_VDEV_ITERATE_PEER_LIST(vdev, peer) { DP_PEER_ITERATE_ASE_LIST(peer, ase, tmp_ase) { - DP_PRINT_STATS("%6d mac_addr = %pM" - " peer_mac_addr = %pM" - " peer_id = %u" - " type = %s" - " next_hop = %d" - " is_active = %d" - " ast_idx = %d" - " ast_hash = %d" - " delete_in_progress = %d" - " pdev_id = %d" - " vdev_id = %d", - ++num_entries, - ase->mac_addr.raw, - ase->peer->mac_addr.raw, - ase->peer->peer_ids[0], - type[ase->type], - ase->next_hop, - ase->is_active, - ase->ast_idx, - ase->ast_hash_value, - ase->delete_in_progress, - ase->pdev_id, - vdev->vdev_id); + DP_PRINT_STATS("%6d mac_addr = "QDF_MAC_ADDR_FMT + " peer_mac_addr = "QDF_MAC_ADDR_FMT + " peer_id = %u" + " type = %s" + " next_hop = %d" + " is_active = %d" + " ast_idx = %d" + " ast_hash = %d" + " delete_in_progress = %d" + " pdev_id = %d" + " vdev_id = %d", + ++num_entries, + QDF_MAC_ADDR_REF(ase->mac_addr.raw), + QDF_MAC_ADDR_REF(ase->peer->mac_addr.raw), + ase->peer->peer_ids[0], + type[ase->type], + ase->next_hop, + ase->is_active, + ase->ast_idx, + ase->ast_hash_value, + ase->delete_in_progress, + ase->pdev_id, + vdev->vdev_id); } } } @@ -1129,101 +1245,25 @@ static void dp_print_peer_table(struct dp_vdev *vdev) DP_PRINT_STATS("Invalid Peer"); return; } - DP_PRINT_STATS(" peer_mac_addr = %pM" + DP_PRINT_STATS(" peer_mac_addr = "QDF_MAC_ADDR_FMT " nawds_enabled = %d" " bss_peer = %d" - " wapi = %d" " wds_enabled = %d" + " tx_cap_enabled = %d" + " rx_cap_enabled = %d" " delete in progress = %d" " peer id = %d", - peer->mac_addr.raw, + QDF_MAC_ADDR_REF(peer->mac_addr.raw), peer->nawds_enabled, peer->bss_peer, - peer->wapi, peer->wds_enabled, + peer->tx_cap_enabled, + peer->rx_cap_enabled, peer->delete_in_progress, peer->peer_ids[0]); } } -/* - * dp_srng_mem_alloc() - Allocate memory for SRNG - * @soc : Data path soc handle - * @srng : SRNG pointer - * @align : Align size - * - * return: QDF_STATUS_SUCCESS on successful allocation - * QDF_STATUS_E_NOMEM on failure - */ -static QDF_STATUS -dp_srng_mem_alloc(struct dp_soc *soc, struct dp_srng *srng, uint32_t align, - bool cached) -{ - uint32_t align_alloc_size; - - if (!cached) { - srng->base_vaddr_unaligned = - qdf_mem_alloc_consistent(soc->osdev, - soc->osdev->dev, - srng->alloc_size, - &srng->base_paddr_unaligned); - } else { - srng->base_vaddr_unaligned = qdf_mem_malloc(srng->alloc_size); - srng->base_paddr_unaligned = - qdf_mem_virt_to_phys(srng->base_vaddr_unaligned); - } - - if (!srng->base_vaddr_unaligned) { - return QDF_STATUS_E_NOMEM; - } - - /* Re-allocate additional bytes to align base address only if - * above allocation returns unaligned address. Reason for - * trying exact size allocation above is, OS tries to allocate - * blocks of size power-of-2 pages and then free extra pages. - * e.g., of a ring size of 1MB, the allocation below will - * request 1MB plus 7 bytes for alignment, which will cause a - * 2MB block allocation,and that is failing sometimes due to - * memory fragmentation. - * dp_srng_mem_alloc should be replaced with - * qdf_aligned_mem_alloc_consistent after fixing some known - * shortcomings with this QDF function - */ - if ((unsigned long)(srng->base_paddr_unaligned) & - (align - 1)) { - align_alloc_size = srng->alloc_size + align - 1; - - if (!cached) { - qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, - srng->alloc_size, - srng->base_vaddr_unaligned, - srng->base_paddr_unaligned, 0); - - srng->base_vaddr_unaligned = - qdf_mem_alloc_consistent(soc->osdev, - soc->osdev->dev, - align_alloc_size, - &srng->base_paddr_unaligned); - - } else { - qdf_mem_free(srng->base_vaddr_unaligned); - srng->base_vaddr_unaligned = - qdf_mem_malloc(align_alloc_size); - - srng->base_paddr_unaligned = - qdf_mem_virt_to_phys(srng->base_vaddr_unaligned); - } - - srng->alloc_size = align_alloc_size; - - if (!srng->base_vaddr_unaligned) { - return QDF_STATUS_E_NOMEM; - } - } - - return QDF_STATUS_SUCCESS; -} - #ifdef WLAN_DP_PER_RING_TYPE_CONFIG /** * dp_srng_configure_interrupt_thresholds() - Retrieve interrupt @@ -1304,6 +1344,191 @@ dp_srng_configure_interrupt_thresholds(struct dp_soc *soc, } #endif + +#ifdef DP_MEM_PRE_ALLOC +void *dp_context_alloc_mem(struct dp_soc *soc, enum dp_ctxt_type ctxt_type, + size_t ctxt_size) +{ + void *ctxt_mem; + + if (!soc->cdp_soc.ol_ops->dp_prealloc_get_context) { + dp_warn("dp_prealloc_get_context null!"); + goto dynamic_alloc; + } + + ctxt_mem = soc->cdp_soc.ol_ops->dp_prealloc_get_context(ctxt_type); + + if (ctxt_mem) + goto end; + +dynamic_alloc: + dp_info("Pre-alloc of ctxt failed. Dynamic allocation"); + ctxt_mem = qdf_mem_malloc(ctxt_size); +end: + return ctxt_mem; +} + +void dp_context_free_mem(struct dp_soc *soc, enum dp_ctxt_type ctxt_type, + void *vaddr) +{ + QDF_STATUS status; + + if (soc->cdp_soc.ol_ops->dp_prealloc_put_context) { + status = soc->cdp_soc.ol_ops->dp_prealloc_put_context( + ctxt_type, + vaddr); + } else { + dp_warn("dp_prealloc_get_context null!"); + status = QDF_STATUS_E_NOSUPPORT; + } + + if (QDF_IS_STATUS_ERROR(status)) { + dp_info("Context not pre-allocated"); + qdf_mem_free(vaddr); + } +} + +static inline +void *dp_srng_aligned_mem_alloc_consistent(struct dp_soc *soc, + struct dp_srng *srng, + struct hal_srng_params *ring_params, + uint32_t ring_type) +{ + void *mem; + + qdf_assert(!srng->is_mem_prealloc); + + if (!soc->cdp_soc.ol_ops->dp_prealloc_get_consistent) { + dp_warn("dp_prealloc_get_consistent is null!"); + goto qdf; + } + + mem = + soc->cdp_soc.ol_ops->dp_prealloc_get_consistent + (&srng->alloc_size, + &srng->base_vaddr_unaligned, + &srng->base_paddr_unaligned, + &ring_params->ring_base_paddr, + DP_RING_BASE_ALIGN, ring_type); + + if (mem) { + srng->is_mem_prealloc = true; + goto end; + } +qdf: + mem = qdf_aligned_mem_alloc_consistent(soc->osdev, &srng->alloc_size, + &srng->base_vaddr_unaligned, + &srng->base_paddr_unaligned, + &ring_params->ring_base_paddr, + DP_RING_BASE_ALIGN); +end: + dp_info("%s memory %pK dp_srng %pK alloc_size %d num_entries %d", + srng->is_mem_prealloc ? "pre-alloc" : "dynamic-alloc", mem, + srng, srng->alloc_size, srng->num_entries); + return mem; +} + +static inline void dp_srng_mem_free_consistent(struct dp_soc *soc, + struct dp_srng *srng) +{ + if (srng->is_mem_prealloc) { + if (!soc->cdp_soc.ol_ops->dp_prealloc_put_consistent) { + dp_warn("dp_prealloc_put_consistent is null!"); + QDF_BUG(0); + return; + } + soc->cdp_soc.ol_ops->dp_prealloc_put_consistent + (srng->alloc_size, + srng->base_vaddr_unaligned, + srng->base_paddr_unaligned); + + } else { + qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, + srng->alloc_size, + srng->base_vaddr_unaligned, + srng->base_paddr_unaligned, 0); + } +} + +void dp_desc_multi_pages_mem_alloc(struct dp_soc *soc, + enum dp_desc_type desc_type, + struct qdf_mem_multi_page_t *pages, + size_t element_size, + uint16_t element_num, + qdf_dma_context_t memctxt, + bool cacheable) +{ + if (!soc->cdp_soc.ol_ops->dp_get_multi_pages) { + dp_warn("dp_get_multi_pages is null!"); + goto qdf; + } + + pages->num_pages = 0; + pages->is_mem_prealloc = 0; + soc->cdp_soc.ol_ops->dp_get_multi_pages(desc_type, + element_size, + element_num, + pages, + cacheable); + if (pages->num_pages) + goto end; + +qdf: + qdf_mem_multi_pages_alloc(soc->osdev, pages, element_size, + element_num, memctxt, cacheable); +end: + dp_info("%s desc_type %d element_size %d element_num %d cacheable %d", + pages->is_mem_prealloc ? "pre-alloc" : "dynamic-alloc", + desc_type, (int)element_size, element_num, cacheable); +} + +void dp_desc_multi_pages_mem_free(struct dp_soc *soc, + enum dp_desc_type desc_type, + struct qdf_mem_multi_page_t *pages, + qdf_dma_context_t memctxt, + bool cacheable) +{ + if (pages->is_mem_prealloc) { + if (!soc->cdp_soc.ol_ops->dp_put_multi_pages) { + dp_warn("dp_put_multi_pages is null!"); + QDF_BUG(0); + return; + } + + soc->cdp_soc.ol_ops->dp_put_multi_pages(desc_type, pages); + qdf_mem_zero(pages, sizeof(*pages)); + } else { + qdf_mem_multi_pages_free(soc->osdev, pages, + memctxt, cacheable); + } +} + +#else + +static inline +void *dp_srng_aligned_mem_alloc_consistent(struct dp_soc *soc, + struct dp_srng *srng, + struct hal_srng_params *ring_params, + uint32_t ring_type) + +{ + return qdf_aligned_mem_alloc_consistent(soc->osdev, &srng->alloc_size, + &srng->base_vaddr_unaligned, + &srng->base_paddr_unaligned, + &ring_params->ring_base_paddr, + DP_RING_BASE_ALIGN); +} + +static inline void dp_srng_mem_free_consistent(struct dp_soc *soc, + struct dp_srng *srng) +{ + qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, + srng->alloc_size, + srng->base_vaddr_unaligned, + srng->base_paddr_unaligned, 0); +} + +#endif /* DP_MEM_PRE_ALLOC */ /** * dp_srng_setup() - Internal function to setup SRNG rings used by data path * @soc: datapath soc handle @@ -1318,17 +1543,15 @@ static int dp_srng_setup(struct dp_soc *soc, struct dp_srng *srng, int ring_type, int ring_num, int mac_id, uint32_t num_entries, bool cached) { - void *hal_soc = soc->hal_soc; + hal_soc_handle_t hal_soc = soc->hal_soc; uint32_t entry_size = hal_srng_get_entrysize(hal_soc, ring_type); - /* TODO: See if we should get align size from hal */ - uint32_t ring_base_align = 8; struct hal_srng_params ring_params; uint32_t max_entries = hal_srng_max_entries(hal_soc, ring_type); /* TODO: Currently hal layer takes care of endianness related settings. * See if these settings need to passed from DP layer */ - ring_params.flags = 0; + qdf_mem_zero(&ring_params, sizeof(struct hal_srng_params)); num_entries = (num_entries > max_entries) ? max_entries : num_entries; srng->hal_srng = NULL; @@ -1336,32 +1559,45 @@ static int dp_srng_setup(struct dp_soc *soc, struct dp_srng *srng, srng->num_entries = num_entries; if (!dp_is_soc_reinit(soc)) { - if (dp_srng_mem_alloc(soc, srng, ring_base_align, cached) != - QDF_STATUS_SUCCESS) { + if (!cached) { + ring_params.ring_base_vaddr = + dp_srng_aligned_mem_alloc_consistent(soc, srng, + &ring_params, + ring_type); + } else { + ring_params.ring_base_vaddr = qdf_aligned_malloc( + &srng->alloc_size, + &srng->base_vaddr_unaligned, + &srng->base_paddr_unaligned, + &ring_params.ring_base_paddr, + DP_RING_BASE_ALIGN); + } + + if (!ring_params.ring_base_vaddr) { dp_err("alloc failed - ring_type: %d, ring_num %d", - ring_type, ring_num); + ring_type, ring_num); return QDF_STATUS_E_NOMEM; } - } - ring_params.ring_base_paddr = - (qdf_dma_addr_t)qdf_align( + ring_params.ring_base_paddr = (qdf_dma_addr_t)qdf_align( (unsigned long)(srng->base_paddr_unaligned), - ring_base_align); + DP_RING_BASE_ALIGN); - ring_params.ring_base_vaddr = - (void *)((unsigned long)(srng->base_vaddr_unaligned) + + ring_params.ring_base_vaddr = (void *)( + (unsigned long)(srng->base_vaddr_unaligned) + ((unsigned long)(ring_params.ring_base_paddr) - - (unsigned long)(srng->base_paddr_unaligned))); + (unsigned long)(srng->base_paddr_unaligned))); + + qdf_assert_always(ring_params.ring_base_vaddr); ring_params.num_entries = num_entries; - dp_verbose_debug("Ring type: %d, num:%d vaddr %pK paddr %pK entries %u", - ring_type, ring_num, - (void *)ring_params.ring_base_vaddr, - (void *)ring_params.ring_base_paddr, - ring_params.num_entries); + dp_info("Ring type: %d, num:%d vaddr %pK paddr %pK entries %u", + ring_type, ring_num, + (void *)ring_params.ring_base_vaddr, + (void *)ring_params.ring_base_paddr, + ring_params.num_entries); if (soc->intr_mode == DP_INTR_MSI) { dp_srng_msi_setup(soc, &ring_params, ring_type, ring_num); @@ -1391,10 +1627,7 @@ static int dp_srng_setup(struct dp_soc *soc, struct dp_srng *srng, if (cached) { qdf_mem_free(srng->base_vaddr_unaligned); } else { - qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, - srng->alloc_size, - srng->base_vaddr_unaligned, - srng->base_paddr_unaligned, 0); + dp_srng_mem_free_consistent(soc, srng); } } @@ -1448,10 +1681,7 @@ static void dp_srng_cleanup(struct dp_soc *soc, struct dp_srng *srng, if (srng->alloc_size && srng->base_vaddr_unaligned) { if (!srng->cached) { - qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, - srng->alloc_size, - srng->base_vaddr_unaligned, - srng->base_paddr_unaligned, 0); + dp_srng_mem_free_consistent(soc, srng); } else { qdf_mem_free(srng->base_vaddr_unaligned); } @@ -1462,39 +1692,39 @@ static void dp_srng_cleanup(struct dp_soc *soc, struct dp_srng *srng, } /* TODO: Need this interface from HIF */ -void *hif_get_hal_handle(void *hif_handle); +void *hif_get_hal_handle(struct hif_opaque_softc *hif_handle); #ifdef WLAN_FEATURE_DP_EVENT_HISTORY int dp_srng_access_start(struct dp_intr *int_ctx, struct dp_soc *dp_soc, - void *hal_ring) + hal_ring_handle_t hal_ring_hdl) { - void *hal_soc = dp_soc->hal_soc; + hal_soc_handle_t hal_soc = dp_soc->hal_soc; uint32_t hp, tp; uint8_t ring_id; - hal_get_sw_hptp(hal_soc, hal_ring, &tp, &hp); - ring_id = hal_srng_ring_id_get(hal_ring); + hal_get_sw_hptp(hal_soc, hal_ring_hdl, &tp, &hp); + ring_id = hal_srng_ring_id_get(hal_ring_hdl); hif_record_event(dp_soc->hif_handle, int_ctx->dp_intr_id, ring_id, hp, tp, HIF_EVENT_SRNG_ACCESS_START); - return hal_srng_access_start(hal_soc, hal_ring); + return hal_srng_access_start(hal_soc, hal_ring_hdl); } void dp_srng_access_end(struct dp_intr *int_ctx, struct dp_soc *dp_soc, - void *hal_ring) + hal_ring_handle_t hal_ring_hdl) { - void *hal_soc = dp_soc->hal_soc; + hal_soc_handle_t hal_soc = dp_soc->hal_soc; uint32_t hp, tp; uint8_t ring_id; - hal_get_sw_hptp(hal_soc, hal_ring, &tp, &hp); - ring_id = hal_srng_ring_id_get(hal_ring); + hal_get_sw_hptp(hal_soc, hal_ring_hdl, &tp, &hp); + ring_id = hal_srng_ring_id_get(hal_ring_hdl); hif_record_event(dp_soc->hif_handle, int_ctx->dp_intr_id, ring_id, hp, tp, HIF_EVENT_SRNG_ACCESS_END); - return hal_srng_access_end(hal_soc, hal_ring); + return hal_srng_access_end(hal_soc, hal_ring_hdl); } #endif /* WLAN_FEATURE_DP_EVENT_HISTORY */ @@ -1537,59 +1767,61 @@ static int dp_process_lmac_rings(struct dp_intr *int_ctx, int total_budget) uint32_t work_done = 0; int budget = total_budget; int ring = 0; - int mac_id; /* Process LMAC interrupts */ - for (ring = 0 ; ring < MAX_PDEV_CNT; ring++) { - pdev = soc->pdev_list[ring]; + for (ring = 0 ; ring < MAX_NUM_LMAC_HW; ring++) { + int mac_for_pdev = ring; + + pdev = dp_get_pdev_for_lmac_id(soc, mac_for_pdev); if (!pdev) continue; - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); - if (int_ctx->rx_mon_ring_mask & (1 << mac_for_pdev)) { - work_done = dp_mon_process(soc, mac_for_pdev, - remaining_quota); - if (work_done) - intr_stats->num_rx_mon_ring_masks++; - budget -= work_done; - if (budget <= 0) - goto budget_done; - remaining_quota = budget; - } + if (int_ctx->rx_mon_ring_mask & (1 << mac_for_pdev)) { + work_done = dp_mon_process(soc, mac_for_pdev, + remaining_quota); + if (work_done) + intr_stats->num_rx_mon_ring_masks++; + budget -= work_done; + if (budget <= 0) + goto budget_done; + remaining_quota = budget; + } - if (int_ctx->rxdma2host_ring_mask & - (1 << mac_for_pdev)) { - work_done = dp_rxdma_err_process(int_ctx, soc, - mac_for_pdev, - remaining_quota); - if (work_done) - intr_stats->num_rxdma2host_ring_masks++; - budget -= work_done; - if (budget <= 0) - goto budget_done; - remaining_quota = budget; - } + if (int_ctx->rxdma2host_ring_mask & + (1 << mac_for_pdev)) { + work_done = dp_rxdma_err_process(int_ctx, soc, + mac_for_pdev, + remaining_quota); + if (work_done) + intr_stats->num_rxdma2host_ring_masks++; + budget -= work_done; + if (budget <= 0) + goto budget_done; + remaining_quota = budget; + } - if (int_ctx->host2rxdma_ring_mask & - (1 << mac_for_pdev)) { - union dp_rx_desc_list_elem_t *desc_list = NULL; - union dp_rx_desc_list_elem_t *tail = NULL; - struct dp_srng *rx_refill_buf_ring = - &pdev->rx_refill_buf_ring; - - intr_stats->num_host2rxdma_ring_masks++; - DP_STATS_INC(pdev, replenish.low_thresh_intrs, - 1); - dp_rx_buffers_replenish(soc, mac_for_pdev, - rx_refill_buf_ring, - &soc->rx_desc_buf[mac_for_pdev], - 0, &desc_list, &tail); - } + if (int_ctx->host2rxdma_ring_mask & + (1 << mac_for_pdev)) { + union dp_rx_desc_list_elem_t *desc_list = NULL; + union dp_rx_desc_list_elem_t *tail = NULL; + struct dp_srng *rx_refill_buf_ring; + + if (wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) + rx_refill_buf_ring = + &soc->rx_refill_buf_ring[mac_for_pdev]; + else + rx_refill_buf_ring = + &soc->rx_refill_buf_ring[pdev->lmac_id]; + + intr_stats->num_host2rxdma_ring_masks++; + DP_STATS_INC(pdev, replenish.low_thresh_intrs, + 1); + dp_rx_buffers_replenish(soc, mac_for_pdev, + rx_refill_buf_ring, + &soc->rx_desc_buf[mac_for_pdev], + 0, &desc_list, &tail); } } - budget_done: return total_budget - budget; } @@ -1792,7 +2024,7 @@ static void dp_interrupt_timer(void *arg) * * Return: 0 for success, nonzero for failure. */ -static QDF_STATUS dp_soc_attach_poll(void *txrx_soc) +static QDF_STATUS dp_soc_attach_poll(struct cdp_soc_t *txrx_soc) { struct dp_soc *soc = (struct dp_soc *)txrx_soc; int i; @@ -1837,7 +2069,7 @@ static void dp_soc_set_interrupt_mode(struct dp_soc *soc) uint32_t msi_base_data, msi_vector_start; int msi_vector_count, ret; - soc->intr_mode = DP_INTR_LEGACY; + soc->intr_mode = DP_INTR_INTEGRATED; if (!(soc->wlan_cfg_ctx->napi_enabled) || (soc->cdp_soc.ol_ops->get_con_mode && @@ -1855,8 +2087,8 @@ static void dp_soc_set_interrupt_mode(struct dp_soc *soc) } } -static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc); -#if defined(CONFIG_MCL) +static QDF_STATUS dp_soc_interrupt_attach(struct cdp_soc_t *txrx_soc); +#if defined(DP_INTR_POLL_BOTH) /* * dp_soc_interrupt_attach_wrapper() - Register handlers for DP interrupts * @txrx_soc: DP SOC handle @@ -1866,7 +2098,7 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc); * * Return: 0 for success. nonzero for failure. */ -static QDF_STATUS dp_soc_interrupt_attach_wrapper(void *txrx_soc) +static QDF_STATUS dp_soc_interrupt_attach_wrapper(struct cdp_soc_t *txrx_soc) { struct dp_soc *soc = (struct dp_soc *)txrx_soc; @@ -1874,24 +2106,21 @@ static QDF_STATUS dp_soc_interrupt_attach_wrapper(void *txrx_soc) (soc->cdp_soc.ol_ops->get_con_mode && soc->cdp_soc.ol_ops->get_con_mode() == QDF_GLOBAL_MONITOR_MODE)) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "%s: Poll mode", __func__); + dp_info("Poll mode"); return dp_soc_attach_poll(txrx_soc); } else { - - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "%s: Interrupt mode", __func__); + dp_info("Interrupt mode"); return dp_soc_interrupt_attach(txrx_soc); } } #else #if defined(DP_INTR_POLL_BASED) && DP_INTR_POLL_BASED -static QDF_STATUS dp_soc_interrupt_attach_wrapper(void *txrx_soc) +static QDF_STATUS dp_soc_interrupt_attach_wrapper(struct cdp_soc_t *txrx_soc) { return dp_soc_attach_poll(txrx_soc); } #else -static QDF_STATUS dp_soc_interrupt_attach_wrapper(void *txrx_soc) +static QDF_STATUS dp_soc_interrupt_attach_wrapper(struct cdp_soc_t *txrx_soc) { struct dp_soc *soc = (struct dp_soc *)txrx_soc; @@ -1928,7 +2157,7 @@ static void dp_soc_interrupt_map_calculate_integrated(struct dp_soc *soc, int host2rxdma_mon_ring_mask = wlan_cfg_get_host2rxdma_mon_ring_mask( soc->wlan_cfg_ctx, intr_ctx_num); - soc->intr_mode = DP_INTR_LEGACY; + soc->intr_mode = DP_INTR_INTEGRATED; for (j = 0; j < HIF_MAX_GRP_IRQ; j++) { @@ -1944,29 +2173,24 @@ static void dp_soc_interrupt_map_calculate_integrated(struct dp_soc *soc, if (rxdma2host_ring_mask & (1 << j)) { irq_id_map[num_irq++] = - rxdma2host_destination_ring_mac1 - - wlan_cfg_get_hw_mac_idx(soc->wlan_cfg_ctx, j); + rxdma2host_destination_ring_mac1 - j; } if (host2rxdma_ring_mask & (1 << j)) { irq_id_map[num_irq++] = - host2rxdma_host_buf_ring_mac1 - - wlan_cfg_get_hw_mac_idx(soc->wlan_cfg_ctx, j); + host2rxdma_host_buf_ring_mac1 - j; } if (host2rxdma_mon_ring_mask & (1 << j)) { irq_id_map[num_irq++] = - host2rxdma_monitor_ring1 - - wlan_cfg_get_hw_mac_idx(soc->wlan_cfg_ctx, j); + host2rxdma_monitor_ring1 - j; } if (rx_mon_mask & (1 << j)) { irq_id_map[num_irq++] = - ppdu_end_interrupts_mac1 - - wlan_cfg_get_hw_mac_idx(soc->wlan_cfg_ctx, j); + ppdu_end_interrupts_mac1 - j; irq_id_map[num_irq++] = - rxdma2host_monitor_status_ring_mac1 - - wlan_cfg_get_hw_mac_idx(soc->wlan_cfg_ctx, j); + rxdma2host_monitor_status_ring_mac1 - j; } if (rx_wbm_rel_ring_mask & (1 << j)) @@ -2045,7 +2269,7 @@ static void dp_soc_interrupt_map_calculate(struct dp_soc *soc, int intr_ctx_num, * * Return: 0 for success. nonzero for failure. */ -static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc) +static QDF_STATUS dp_soc_interrupt_attach(struct cdp_soc_t *txrx_soc) { struct dp_soc *soc = (struct dp_soc *)txrx_soc; @@ -2112,7 +2336,6 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc) } hif_configure_ext_group_interrupts(soc->hif_handle); - hif_config_irq_set_perf_affinity_hint(soc->hif_handle); return QDF_STATUS_SUCCESS; } @@ -2121,9 +2344,9 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc) * dp_soc_interrupt_detach() - Deregister any allocations done for interrupts * @txrx_soc: DP SOC handle * - * Return: void + * Return: none */ -static void dp_soc_interrupt_detach(void *txrx_soc) +static void dp_soc_interrupt_detach(struct cdp_soc_t *txrx_soc) { struct dp_soc *soc = (struct dp_soc *)txrx_soc; int i; @@ -2131,6 +2354,7 @@ static void dp_soc_interrupt_detach(void *txrx_soc) if (soc->intr_mode == DP_INTR_POLL) { qdf_timer_free(&soc->int_timer); } else { + hif_deconfigure_ext_group_interrupts(soc->hif_handle); hif_deregister_exec_group(soc->hif_handle, "dp_intr"); } @@ -2174,12 +2398,16 @@ static int dp_hw_link_desc_pool_setup(struct dp_soc *soc) uint32_t total_link_descs, total_mem_size; uint32_t num_mpdu_link_descs, num_mpdu_queue_descs; uint32_t num_tx_msdu_link_descs, num_rx_msdu_link_descs; - uint32_t num_link_desc_banks; - uint32_t last_bank_size = 0; uint32_t entry_size, num_entries; int i; - uint32_t desc_id = 0; + uint32_t cookie = 0; qdf_dma_addr_t *baseaddr = NULL; + uint32_t page_idx = 0; + struct qdf_mem_multi_page_t *pages; + struct qdf_mem_dma_page_t *dma_pages; + uint32_t offset = 0; + uint32_t count = 0; + uint32_t num_descs_per_page; /* Only Tx queue descriptors are allocated from common link descriptor * pool Rx queue descriptors are not included in this because (REO queue @@ -2214,86 +2442,28 @@ static int dp_hw_link_desc_pool_setup(struct dp_soc *soc) total_mem_size += link_desc_align; - if (total_mem_size <= max_alloc_size) { - num_link_desc_banks = 0; - last_bank_size = total_mem_size; - } else { - num_link_desc_banks = (total_mem_size) / - (max_alloc_size - link_desc_align); - last_bank_size = total_mem_size % - (max_alloc_size - link_desc_align); - } - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, - FL("total_mem_size: %d, num_link_desc_banks: %u"), - total_mem_size, num_link_desc_banks); - - for (i = 0; i < num_link_desc_banks; i++) { - if (!dp_is_soc_reinit(soc)) { - baseaddr = &soc->link_desc_banks[i]. - base_paddr_unaligned; - soc->link_desc_banks[i].base_vaddr_unaligned = - qdf_mem_alloc_consistent(soc->osdev, - soc->osdev->dev, - max_alloc_size, - baseaddr); - } - soc->link_desc_banks[i].size = max_alloc_size; - - soc->link_desc_banks[i].base_vaddr = (void *)((unsigned long)( - soc->link_desc_banks[i].base_vaddr_unaligned) + - ((unsigned long)( - soc->link_desc_banks[i].base_vaddr_unaligned) % - link_desc_align)); - - soc->link_desc_banks[i].base_paddr = (unsigned long)( - soc->link_desc_banks[i].base_paddr_unaligned) + - ((unsigned long)(soc->link_desc_banks[i].base_vaddr) - - (unsigned long)( - soc->link_desc_banks[i].base_vaddr_unaligned)); - - if (!soc->link_desc_banks[i].base_vaddr_unaligned) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - FL("Link descriptor memory alloc failed")); - goto fail; - } - qdf_minidump_log((void *)(soc->link_desc_banks[i].base_vaddr), - soc->link_desc_banks[i].size, "link_desc_bank"); - } + FL("total_mem_size: %d"), total_mem_size); - if (last_bank_size) { - /* Allocate last bank in case total memory required is not exact - * multiple of max_alloc_size - */ - if (!dp_is_soc_reinit(soc)) { - baseaddr = &soc->link_desc_banks[i]. - base_paddr_unaligned; - soc->link_desc_banks[i].base_vaddr_unaligned = - qdf_mem_alloc_consistent(soc->osdev, - soc->osdev->dev, - last_bank_size, - baseaddr); + pages = &soc->link_desc_pages; + dp_set_max_page_size(pages, max_alloc_size); + if (!dp_is_soc_reinit(soc)) { + dp_desc_multi_pages_mem_alloc(soc, DP_HW_LINK_DESC_TYPE, + pages, + link_desc_size, + total_link_descs, + 0, false); + if (!pages->num_pages) { + dp_err("Multi page alloc fail for hw link desc pool"); + goto fail_page_alloc; } - soc->link_desc_banks[i].size = last_bank_size; - - soc->link_desc_banks[i].base_vaddr = (void *)((unsigned long) - (soc->link_desc_banks[i].base_vaddr_unaligned) + - ((unsigned long)( - soc->link_desc_banks[i].base_vaddr_unaligned) % - link_desc_align)); - - soc->link_desc_banks[i].base_paddr = - (unsigned long)( - soc->link_desc_banks[i].base_paddr_unaligned) + - ((unsigned long)(soc->link_desc_banks[i].base_vaddr) - - (unsigned long)( - soc->link_desc_banks[i].base_vaddr_unaligned)); - - qdf_minidump_log((void *)(soc->link_desc_banks[i].base_vaddr), - soc->link_desc_banks[i].size, "link_desc_bank"); + qdf_minidump_log( + (void *)(pages->dma_pages->page_v_addr_start), + pages->num_pages * + sizeof(struct qdf_mem_dma_page_t), + "hw_link_desc_bank"); } - /* Allocate and setup link descriptor idle list for HW internal use */ entry_size = hal_srng_get_entrysize(soc->hal_soc, WBM_IDLE_LINK); total_mem_size = entry_size * total_link_descs; @@ -2308,34 +2478,33 @@ static int dp_hw_link_desc_pool_setup(struct dp_soc *soc) goto fail; } - qdf_minidump_log( - (void *)(soc->wbm_idle_link_ring.base_vaddr_unaligned), - soc->wbm_idle_link_ring.alloc_size, - "wbm_idle_link_ring"); + qdf_minidump_log(soc->wbm_idle_link_ring.base_vaddr_unaligned, + soc->wbm_idle_link_ring.alloc_size, + "wbm_idle_link_ring"); hal_srng_access_start_unlocked(soc->hal_soc, soc->wbm_idle_link_ring.hal_srng); - - for (i = 0; i < MAX_LINK_DESC_BANKS && - soc->link_desc_banks[i].base_paddr; i++) { - uint32_t num_entries = (soc->link_desc_banks[i].size - - ((unsigned long)( - soc->link_desc_banks[i].base_vaddr) - - (unsigned long)( - soc->link_desc_banks[i].base_vaddr_unaligned))) - / link_desc_size; - unsigned long paddr = (unsigned long)( - soc->link_desc_banks[i].base_paddr); - - while (num_entries && (desc = hal_srng_src_get_next( + page_idx = 0; count = 0; + offset = 0; + pages = &soc->link_desc_pages; + if (pages->dma_pages) + dma_pages = pages->dma_pages; + else + goto fail; + num_descs_per_page = + pages->num_element_per_page; + while ((desc = hal_srng_src_get_next( soc->hal_soc, - soc->wbm_idle_link_ring.hal_srng))) { - hal_set_link_desc_addr(desc, - LINK_DESC_COOKIE(desc_id, i), paddr); - num_entries--; - desc_id++; - paddr += link_desc_size; - } + soc->wbm_idle_link_ring.hal_srng)) && + (count < total_link_descs)) { + page_idx = count / num_descs_per_page; + offset = count % num_descs_per_page; + cookie = LINK_DESC_COOKIE(count, page_idx); + hal_set_link_desc_addr( + desc, cookie, + dma_pages[page_idx].page_p_addr + + (offset * link_desc_size)); + count++; } hal_srng_access_end_unlocked(soc->hal_soc, soc->wbm_idle_link_ring.hal_srng); @@ -2387,40 +2556,38 @@ static int dp_hw_link_desc_pool_setup(struct dp_soc *soc) scatter_buf_ptr = (uint8_t *)( soc->wbm_idle_scatter_buf_base_vaddr[scatter_buf_num]); rem_entries = num_entries_per_buf; - - for (i = 0; i < MAX_LINK_DESC_BANKS && - soc->link_desc_banks[i].base_paddr; i++) { - uint32_t num_link_descs = - (soc->link_desc_banks[i].size - - ((unsigned long)( - soc->link_desc_banks[i].base_vaddr) - - (unsigned long)( - soc->link_desc_banks[i].base_vaddr_unaligned))) - / link_desc_size; - unsigned long paddr = (unsigned long)( - soc->link_desc_banks[i].base_paddr); - - while (num_link_descs) { - hal_set_link_desc_addr((void *)scatter_buf_ptr, - LINK_DESC_COOKIE(desc_id, i), paddr); - num_link_descs--; - desc_id++; - paddr += link_desc_size; - rem_entries--; - if (rem_entries) { - scatter_buf_ptr += entry_size; - } else { - rem_entries = num_entries_per_buf; - scatter_buf_num++; - - if (scatter_buf_num >= num_scatter_bufs) - break; - - scatter_buf_ptr = (uint8_t *)( - soc->wbm_idle_scatter_buf_base_vaddr[ - scatter_buf_num]); - } + pages = &soc->link_desc_pages; + page_idx = 0; count = 0; + offset = 0; + num_descs_per_page = + pages->num_element_per_page; + if (pages->dma_pages) + dma_pages = pages->dma_pages; + else + goto fail; + while (count < total_link_descs) { + page_idx = count / num_descs_per_page; + offset = count % num_descs_per_page; + cookie = LINK_DESC_COOKIE(count, page_idx); + hal_set_link_desc_addr( + (void *)scatter_buf_ptr, + cookie, + dma_pages[page_idx].page_p_addr + + (offset * link_desc_size)); + rem_entries--; + if (rem_entries) { + scatter_buf_ptr += entry_size; + } else { + rem_entries = num_entries_per_buf; + scatter_buf_num++; + if (scatter_buf_num >= num_scatter_bufs) + break; + scatter_buf_ptr = + (uint8_t *) + (soc->wbm_idle_scatter_buf_base_vaddr[ + scatter_buf_num]); } + count++; } /* Setup link descriptor idle list in HW */ hal_setup_link_idle_list(soc->hal_soc, @@ -2449,17 +2616,15 @@ static int dp_hw_link_desc_pool_setup(struct dp_soc *soc) } } - for (i = 0; i < MAX_LINK_DESC_BANKS; i++) { - if (soc->link_desc_banks[i].base_vaddr_unaligned) { - qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, - soc->link_desc_banks[i].size, - soc->link_desc_banks[i].base_vaddr_unaligned, - soc->link_desc_banks[i].base_paddr_unaligned, - 0); - soc->link_desc_banks[i].base_vaddr_unaligned = NULL; - } - } + pages = &soc->link_desc_pages; + qdf_minidump_remove( + (void *)pages->dma_pages->page_v_addr_start); + dp_desc_multi_pages_mem_free(soc, DP_HW_LINK_DESC_TYPE, + pages, 0, false); return QDF_STATUS_E_FAILURE; + +fail_page_alloc: + return QDF_STATUS_E_FAULT; } /* @@ -2468,8 +2633,11 @@ static int dp_hw_link_desc_pool_setup(struct dp_soc *soc) static void dp_hw_link_desc_pool_cleanup(struct dp_soc *soc) { int i; + struct qdf_mem_multi_page_t *pages; if (soc->wbm_idle_link_ring.hal_srng) { + qdf_minidump_remove( + soc->wbm_idle_link_ring.base_vaddr_unaligned); dp_srng_cleanup(soc, &soc->wbm_idle_link_ring, WBM_IDLE_LINK, 0); } @@ -2484,34 +2652,33 @@ static void dp_hw_link_desc_pool_cleanup(struct dp_soc *soc) } } - for (i = 0; i < MAX_LINK_DESC_BANKS; i++) { - if (soc->link_desc_banks[i].base_vaddr_unaligned) { - qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, - soc->link_desc_banks[i].size, - soc->link_desc_banks[i].base_vaddr_unaligned, - soc->link_desc_banks[i].base_paddr_unaligned, - 0); - soc->link_desc_banks[i].base_vaddr_unaligned = NULL; - } - } + pages = &soc->link_desc_pages; + qdf_minidump_remove( + (void *)pages->dma_pages->page_v_addr_start); + dp_desc_multi_pages_mem_free(soc, DP_HW_LINK_DESC_TYPE, + pages, 0, false); } #ifdef IPA_OFFLOAD #define REO_DST_RING_SIZE_QCA6290 1023 -#ifndef QCA_WIFI_QCA8074_VP +#ifndef CONFIG_WIFI_EMULATION_WIFI_3_0 #define REO_DST_RING_SIZE_QCA8074 1023 +#define REO_DST_RING_SIZE_QCN9000 2048 #else #define REO_DST_RING_SIZE_QCA8074 8 -#endif /* QCA_WIFI_QCA8074_VP */ +#define REO_DST_RING_SIZE_QCN9000 8 +#endif /* CONFIG_WIFI_EMULATION_WIFI_3_0 */ #else #define REO_DST_RING_SIZE_QCA6290 1024 -#ifndef QCA_WIFI_QCA8074_VP +#ifndef CONFIG_WIFI_EMULATION_WIFI_3_0 #define REO_DST_RING_SIZE_QCA8074 2048 +#define REO_DST_RING_SIZE_QCN9000 2048 #else #define REO_DST_RING_SIZE_QCA8074 8 -#endif /* QCA_WIFI_QCA8074_VP */ +#define REO_DST_RING_SIZE_QCN9000 8 +#endif /* CONFIG_WIFI_EMULATION_WIFI_3_0 */ #endif /* IPA_OFFLOAD */ #ifndef FEATURE_WDS @@ -2600,6 +2767,38 @@ static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc, enum hal_ring_ty return status; } +/* + * dp_soc_disable_mac2_intr_mask() - reset interrupt mask for WMAC2 hw rings + * @dp_soc - DP Soc handle + * + * Return: Return void + */ +static void dp_soc_disable_mac2_intr_mask(struct dp_soc *soc) +{ + int *grp_mask = NULL; + int group_number; + + grp_mask = &soc->wlan_cfg_ctx->int_host2rxdma_ring_mask[0]; + group_number = dp_srng_find_ring_in_mask(0x2, grp_mask); + wlan_cfg_set_host2rxdma_ring_mask(soc->wlan_cfg_ctx, + group_number, 0x0); + + grp_mask = &soc->wlan_cfg_ctx->int_rx_mon_ring_mask[0]; + group_number = dp_srng_find_ring_in_mask(0x2, grp_mask); + wlan_cfg_set_rx_mon_ring_mask(soc->wlan_cfg_ctx, + group_number, 0x0); + + grp_mask = &soc->wlan_cfg_ctx->int_rxdma2host_ring_mask[0]; + group_number = dp_srng_find_ring_in_mask(0x2, grp_mask); + wlan_cfg_set_rxdma2host_ring_mask(soc->wlan_cfg_ctx, + group_number, 0x0); + + grp_mask = &soc->wlan_cfg_ctx->int_host2rxdma_mon_ring_mask[0]; + group_number = dp_srng_find_ring_in_mask(0x2, grp_mask); + wlan_cfg_set_host2rxdma_mon_ring_mask(soc->wlan_cfg_ctx, + group_number, 0x0); +} + /* * dp_soc_reset_intr_mask() - reset interrupt mask * @dp_soc - DP Soc handle @@ -2689,6 +2888,8 @@ static void dp_soc_reset_intr_mask(struct dp_soc *soc) /* loop and reset the mask for only offloaded ring */ for (j = 0; j < MAX_PDEV_CNT; j++) { + int lmac_id = wlan_cfg_get_hw_mac_idx(soc->wlan_cfg_ctx, j); + if (!dp_soc_ring_if_nss_offloaded(soc, RXDMA_BUF, j)) { continue; } @@ -2696,18 +2897,18 @@ static void dp_soc_reset_intr_mask(struct dp_soc *soc) /* * Group number corresponding to rx offloaded ring. */ - group_number = dp_srng_find_ring_in_mask(j, grp_mask); + group_number = dp_srng_find_ring_in_mask(lmac_id, grp_mask); if (group_number < 0) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, FL("ring not part of any group; ring_type: %d,ring_num %d"), - REO_DST, j); + REO_DST, lmac_id); return; } /* set the interrupt mask for offloaded ring */ mask = wlan_cfg_get_host2rxdma_ring_mask(soc->wlan_cfg_ctx, group_number); - mask &= (~(1 << j)); + mask &= (~(1 << lmac_id)); /* * set the interrupt mask to zero for rx offloaded radio. @@ -2735,53 +2936,126 @@ static void dp_soc_reset_intr_mask(struct dp_soc *soc) */ bool dp_reo_remap_config(struct dp_soc *soc, uint32_t *remap1, uint32_t *remap2) { - *remap1 = ((0x1 << 0) | (0x2 << 3) | (0x3 << 6) | (0x1 << 9) | - (0x2 << 12) | (0x3 << 15) | (0x1 << 18) | (0x2 << 21)) << 8; - - *remap2 = ((0x3 << 0) | (0x1 << 3) | (0x2 << 6) | (0x3 << 9) | - (0x1 << 12) | (0x2 << 15) | (0x3 << 18) | (0x1 << 21)) << 8; + *remap1 = HAL_REO_REMAP_IX2(REO_REMAP_SW1, 16) | + HAL_REO_REMAP_IX2(REO_REMAP_SW2, 17) | + HAL_REO_REMAP_IX2(REO_REMAP_SW3, 18) | + HAL_REO_REMAP_IX2(REO_REMAP_SW1, 19) | + HAL_REO_REMAP_IX2(REO_REMAP_SW2, 20) | + HAL_REO_REMAP_IX2(REO_REMAP_SW3, 21) | + HAL_REO_REMAP_IX2(REO_REMAP_SW1, 22) | + HAL_REO_REMAP_IX2(REO_REMAP_SW2, 23); + + *remap2 = HAL_REO_REMAP_IX3(REO_REMAP_SW3, 24) | + HAL_REO_REMAP_IX3(REO_REMAP_SW1, 25) | + HAL_REO_REMAP_IX3(REO_REMAP_SW2, 26) | + HAL_REO_REMAP_IX3(REO_REMAP_SW3, 27) | + HAL_REO_REMAP_IX3(REO_REMAP_SW1, 28) | + HAL_REO_REMAP_IX3(REO_REMAP_SW2, 29) | + HAL_REO_REMAP_IX3(REO_REMAP_SW3, 30) | + HAL_REO_REMAP_IX3(REO_REMAP_SW1, 31); dp_debug("remap1 %x remap2 %x", *remap1, *remap2); return true; } + +/** + * dp_ipa_get_tx_ring_size() - Get Tx ring size for IPA + * + * @tx_ring_num: Tx ring number + * @tx_ipa_ring_sz: Return param only updated for IPA. + * + * Return: None + */ +static void dp_ipa_get_tx_ring_size(int tx_ring_num, int *tx_ipa_ring_sz) +{ + if (tx_ring_num == WLAN_CFG_IPA_TX_N_TXCMPL_RING) + *tx_ipa_ring_sz = WLAN_CFG_IPA_TX_RING_SIZE; +} + +/** + * dp_ipa_get_tx_comp_ring_size() - Get Tx comp ring size for IPA + * + * @tx_comp_ring_num: Tx comp ring number + * @tx_comp_ipa_ring_sz: Return param only updated for IPA. + * + * Return: None + */ +static void dp_ipa_get_tx_comp_ring_size(int tx_comp_ring_num, + int *tx_comp_ipa_ring_sz) +{ + if (tx_comp_ring_num == WLAN_CFG_IPA_TX_N_TXCMPL_RING) + *tx_comp_ipa_ring_sz = WLAN_CFG_IPA_TX_COMP_RING_SIZE; +} #else static bool dp_reo_remap_config(struct dp_soc *soc, uint32_t *remap1, uint32_t *remap2) { uint8_t offload_radio = wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx); + uint8_t target_type; + + target_type = hal_get_target_type(soc->hal_soc); switch (offload_radio) { case dp_nss_cfg_default: - *remap1 = ((0x1 << 0) | (0x2 << 3) | (0x3 << 6) | - (0x4 << 9) | (0x1 << 12) | (0x2 << 15) | - (0x3 << 18) | (0x4 << 21)) << 8; - - *remap2 = ((0x1 << 0) | (0x2 << 3) | (0x3 << 6) | - (0x4 << 9) | (0x1 << 12) | (0x2 << 15) | - (0x3 << 18) | (0x4 << 21)) << 8; + *remap1 = HAL_REO_REMAP_IX2(REO_REMAP_SW1, 16) | + HAL_REO_REMAP_IX2(REO_REMAP_SW2, 17) | + HAL_REO_REMAP_IX2(REO_REMAP_SW3, 18) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 19) | + HAL_REO_REMAP_IX2(REO_REMAP_SW1, 20) | + HAL_REO_REMAP_IX2(REO_REMAP_SW2, 21) | + HAL_REO_REMAP_IX2(REO_REMAP_SW3, 22) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 23); + + *remap2 = HAL_REO_REMAP_IX3(REO_REMAP_SW1, 24) | + HAL_REO_REMAP_IX3(REO_REMAP_SW2, 25) | + HAL_REO_REMAP_IX3(REO_REMAP_SW3, 26) | + HAL_REO_REMAP_IX3(REO_REMAP_SW4, 27) | + HAL_REO_REMAP_IX3(REO_REMAP_SW1, 28) | + HAL_REO_REMAP_IX3(REO_REMAP_SW2, 29) | + HAL_REO_REMAP_IX3(REO_REMAP_SW3, 30) | + HAL_REO_REMAP_IX3(REO_REMAP_SW4, 31); break; case dp_nss_cfg_first_radio: - *remap1 = ((0x2 << 0) | (0x3 << 3) | (0x4 << 6) | - (0x2 << 9) | (0x3 << 12) | (0x4 << 15) | - (0x2 << 18) | (0x3 << 21)) << 8; - - *remap2 = ((0x4 << 0) | (0x2 << 3) | (0x3 << 6) | - (0x4 << 9) | (0x2 << 12) | (0x3 << 15) | - (0x4 << 18) | (0x2 << 21)) << 8; + *remap1 = HAL_REO_REMAP_IX2(REO_REMAP_SW2, 16) | + HAL_REO_REMAP_IX2(REO_REMAP_SW3, 17) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 18) | + HAL_REO_REMAP_IX2(REO_REMAP_SW2, 19) | + HAL_REO_REMAP_IX2(REO_REMAP_SW3, 20) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 21) | + HAL_REO_REMAP_IX2(REO_REMAP_SW2, 22) | + HAL_REO_REMAP_IX2(REO_REMAP_SW3, 23); + + *remap2 = HAL_REO_REMAP_IX3(REO_REMAP_SW4, 24) | + HAL_REO_REMAP_IX3(REO_REMAP_SW2, 25) | + HAL_REO_REMAP_IX3(REO_REMAP_SW3, 26) | + HAL_REO_REMAP_IX3(REO_REMAP_SW4, 27) | + HAL_REO_REMAP_IX3(REO_REMAP_SW2, 28) | + HAL_REO_REMAP_IX3(REO_REMAP_SW3, 29) | + HAL_REO_REMAP_IX3(REO_REMAP_SW4, 30) | + HAL_REO_REMAP_IX3(REO_REMAP_SW2, 31); break; - case dp_nss_cfg_second_radio: - *remap1 = ((0x1 << 0) | (0x3 << 3) | (0x4 << 6) | - (0x1 << 9) | (0x3 << 12) | (0x4 << 15) | - (0x1 << 18) | (0x3 << 21)) << 8; + *remap1 = HAL_REO_REMAP_IX2(REO_REMAP_SW1, 16) | + HAL_REO_REMAP_IX2(REO_REMAP_SW3, 17) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 18) | + HAL_REO_REMAP_IX2(REO_REMAP_SW1, 19) | + HAL_REO_REMAP_IX2(REO_REMAP_SW3, 20) | + HAL_REO_REMAP_IX2(REO_REMAP_SW4, 21) | + HAL_REO_REMAP_IX2(REO_REMAP_SW1, 22) | + HAL_REO_REMAP_IX2(REO_REMAP_SW3, 23); + + *remap2 = HAL_REO_REMAP_IX3(REO_REMAP_SW4, 24) | + HAL_REO_REMAP_IX3(REO_REMAP_SW1, 25) | + HAL_REO_REMAP_IX3(REO_REMAP_SW3, 26) | + HAL_REO_REMAP_IX3(REO_REMAP_SW4, 27) | + HAL_REO_REMAP_IX3(REO_REMAP_SW1, 28) | + HAL_REO_REMAP_IX3(REO_REMAP_SW3, 29) | + HAL_REO_REMAP_IX3(REO_REMAP_SW4, 30) | + HAL_REO_REMAP_IX3(REO_REMAP_SW1, 31); - *remap2 = ((0x4 << 0) | (0x1 << 3) | (0x3 << 6) | - (0x4 << 9) | (0x1 << 12) | (0x3 << 15) | - (0x4 << 18) | (0x1 << 21)) << 8; break; - case dp_nss_cfg_dbdc: case dp_nss_cfg_dbtc: /* return false if both or all are offloaded to NSS */ @@ -2792,7 +3066,16 @@ static bool dp_reo_remap_config(struct dp_soc *soc, *remap1, *remap2, offload_radio); return true; } -#endif + +static void dp_ipa_get_tx_ring_size(int ring_num, int *tx_ipa_ring_sz) +{ +} + +static void dp_ipa_get_tx_comp_ring_size(int tx_comp_ring_num, + int *tx_comp_ipa_ring_sz) +{ +} +#endif /* IPA_OFFLOAD */ /* * dp_reo_frag_dst_set() - configure reo register to set the @@ -2820,6 +3103,11 @@ static void dp_reo_frag_dst_set(struct dp_soc *soc, uint8_t *frag_dst_ring) case dp_nss_cfg_default: *frag_dst_ring = REO_REMAP_TCL; break; + case dp_nss_cfg_first_radio: + /* + * This configuration is valid for single band radio which + * is also NSS offload. + */ case dp_nss_cfg_dbdc: case dp_nss_cfg_dbtc: *frag_dst_ring = HAL_SRNG_REO_ALTERNATE_SELECT; @@ -2872,7 +3160,7 @@ static inline void dp_create_ext_stats_event(struct dp_soc *soc) */ static int dp_soc_cmn_setup(struct dp_soc *soc) { - int i; + int i, cached; struct hal_reo_params reo_params; int tx_ring_size; int tx_comp_ring_size; @@ -2901,9 +3189,9 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) goto fail1; } - qdf_minidump_log( - (void *)(soc->wbm_desc_rel_ring.base_vaddr_unaligned), - soc->wbm_desc_rel_ring.alloc_size, "wbm_desc_rel_ring"); + qdf_minidump_log(soc->wbm_desc_rel_ring.base_vaddr_unaligned, + soc->wbm_desc_rel_ring.alloc_size, + "wbm_desc_rel_ring"); soc->num_tcl_data_rings = 0; /* Tx data rings */ @@ -2915,6 +3203,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) tx_ring_size = wlan_cfg_tx_ring_size(soc_cfg_ctx); for (i = 0; i < soc->num_tcl_data_rings; i++) { + dp_ipa_get_tx_ring_size(i, &tx_ring_size); + if (dp_srng_setup(soc, &soc->tcl_data_ring[i], TCL_DATA, i, 0, tx_ring_size, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, @@ -2922,6 +3212,13 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) FL("dp_srng_setup failed for tcl_data_ring[%d]"), i); goto fail1; } + + /* Disable cached desc if NSS offload is enabled */ + cached = WLAN_CFG_DST_RING_CACHED_DESC; + if (wlan_cfg_get_dp_soc_nss_cfg(soc_cfg_ctx)) + cached = 0; + + dp_ipa_get_tx_comp_ring_size(i, &tx_comp_ring_size); /* * TBD: Set IPA WBM ring size with ini IPA UC tx buffer * count @@ -2929,7 +3226,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) if (dp_srng_setup(soc, &soc->tx_comp_ring[i], WBM2SW_RELEASE, i, 0, tx_comp_ring_size, - WLAN_CFG_DST_RING_CACHED_DESC)) { + cached)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for tx_comp_ring[%d]"), i); @@ -2953,7 +3250,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for tcl_cmd_ring")); - goto fail1; + goto fail2; } entries = wlan_cfg_get_dp_soc_tcl_status_ring_size(soc_cfg_ctx); @@ -2961,7 +3258,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for tcl_status_ring")); - goto fail1; + goto fail2; } reo_dst_ring_size = wlan_cfg_get_reo_dst_ring_size(soc->wlan_cfg_ctx); @@ -2977,14 +3274,19 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, FL("num_reo_dest_rings %d"), soc->num_reo_dest_rings); + + /* Disable cached desc if NSS offload is enabled */ + cached = WLAN_CFG_DST_RING_CACHED_DESC; + if (wlan_cfg_get_dp_soc_nss_cfg(soc_cfg_ctx)) + cached = 0; + for (i = 0; i < soc->num_reo_dest_rings; i++) { if (dp_srng_setup(soc, &soc->reo_dest_ring[i], REO_DST, - i, 0, reo_dst_ring_size, - WLAN_CFG_DST_RING_CACHED_DESC)) { + i, 0, reo_dst_ring_size, cached)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL(RNG_ERR "reo_dest_ring [%d]"), i); - goto fail1; + goto fail2; } } } else { @@ -2995,16 +3297,14 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) entries = wlan_cfg_get_dp_soc_rxdma_err_dst_ring_size(soc_cfg_ctx); /* LMAC RxDMA to SW Rings configuration */ if (!wlan_cfg_per_pdev_lmac_ring(soc_cfg_ctx)) { - /* Only valid for MCL */ - struct dp_pdev *pdev = soc->pdev_list[0]; for (i = 0; i < MAX_RX_MAC_RINGS; i++) { - if (dp_srng_setup(soc, &pdev->rxdma_err_dst_ring[i], + if (dp_srng_setup(soc, &soc->rxdma_err_dst_ring[i], RXDMA_DST, 0, i, entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL(RNG_ERR "rxdma_err_dst_ring")); - goto fail1; + goto fail2; } } } @@ -3016,7 +3316,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for reo_reinject_ring")); - goto fail1; + goto fail2; } @@ -3026,7 +3326,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for rx_rel_ring")); - goto fail1; + goto fail2; } @@ -3036,7 +3336,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) REO_EXCEPTION, 0, MAX_REO_DEST_RINGS, entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for reo_exception_ring")); - goto fail1; + goto fail2; } @@ -3046,7 +3346,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for reo_cmd_ring")); - goto fail1; + goto fail2; } hal_reo_init_cmd_ring(soc->hal_soc, soc->reo_cmd_ring.hal_srng); @@ -3058,9 +3358,16 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for reo_status_ring")); - goto fail1; + goto fail2; } + /* + * Skip registering hw ring interrupts for WMAC2 on IPQ6018 + * WMAC2 is not there in IPQ6018 platform. + */ + if (hal_get_target_type(soc->hal_soc) == TARGET_TYPE_QCA6018) { + dp_soc_disable_mac2_intr_mask(soc); + } /* Reset the cpu ring map if radio is NSS offloaded */ if (wlan_cfg_get_dp_soc_nss_cfg(soc_cfg_ctx)) { @@ -3111,6 +3418,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) qdf_nbuf_queue_init(&soc->htt_stats.msg); return 0; +fail2: + dp_tx_soc_detach(soc); fail1: /* * Cleanup will be done as part of soc_detach, which will @@ -3132,13 +3441,17 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) */ static void dp_soc_cmn_cleanup(struct dp_soc *soc) { - dp_tx_soc_detach(soc); + if (!dp_is_soc_reinit(soc)) { + dp_tx_soc_detach(soc); + } qdf_spinlock_destroy(&soc->rx.defrag.defrag_lock); qdf_spinlock_destroy(&soc->rx.reo_cmd_lock); } -static void dp_pdev_detach_wifi3(struct cdp_pdev *txrx_pdev, int force); +static QDF_STATUS +dp_pdev_detach_wifi3(struct cdp_soc_t *psoc, uint8_t pdev_id, + int force); static QDF_STATUS dp_lro_hash_setup(struct dp_soc *soc, struct dp_pdev *pdev) { @@ -3178,7 +3491,8 @@ static QDF_STATUS dp_lro_hash_setup(struct dp_soc *soc, struct dp_pdev *pdev) return QDF_STATUS_E_FAILURE; } - status = soc->cdp_soc.ol_ops->lro_hash_config(pdev->ctrl_pdev, + status = soc->cdp_soc.ol_ops->lro_hash_config(soc->ctrl_psoc, + pdev->pdev_id, &lro_hash); if (!QDF_IS_STATUS_SUCCESS(status)) { dp_err("failed to send lro_hash_config to FW %u", status); @@ -3191,13 +3505,13 @@ static QDF_STATUS dp_lro_hash_setup(struct dp_soc *soc, struct dp_pdev *pdev) dp_info("toeplitz_hash_ipv4:"); qdf_trace_hex_dump(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - (void *)lro_hash.toeplitz_hash_ipv4, + lro_hash.toeplitz_hash_ipv4, (sizeof(lro_hash.toeplitz_hash_ipv4[0]) * LRO_IPV4_SEED_ARR_SZ)); dp_info("toeplitz_hash_ipv6:"); qdf_trace_hex_dump(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - (void *)lro_hash.toeplitz_hash_ipv6, + lro_hash.toeplitz_hash_ipv6, (sizeof(lro_hash.toeplitz_hash_ipv6[0]) * LRO_IPV6_SEED_ARR_SZ)); @@ -3366,14 +3680,14 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev) pdev_cfg_ctx = pdev->wlan_cfg_ctx; for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); + int lmac_id = dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev_id); if (soc->wlan_cfg_ctx->rxdma1_enable) { entries = wlan_cfg_get_dma_mon_buf_ring_size(pdev_cfg_ctx); if (dp_srng_setup(soc, - &pdev->rxdma_mon_buf_ring[mac_id], - RXDMA_MONITOR_BUF, 0, mac_for_pdev, + &soc->rxdma_mon_buf_ring[lmac_id], + RXDMA_MONITOR_BUF, 0, lmac_id, entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -3384,8 +3698,8 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev) entries = wlan_cfg_get_dma_mon_dest_ring_size(pdev_cfg_ctx); if (dp_srng_setup(soc, - &pdev->rxdma_mon_dst_ring[mac_id], - RXDMA_MONITOR_DST, 0, mac_for_pdev, + &soc->rxdma_mon_dst_ring[lmac_id], + RXDMA_MONITOR_DST, 0, lmac_id, entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -3396,8 +3710,8 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev) entries = wlan_cfg_get_dma_mon_stat_ring_size(pdev_cfg_ctx); if (dp_srng_setup(soc, - &pdev->rxdma_mon_status_ring[mac_id], - RXDMA_MONITOR_STATUS, 0, mac_for_pdev, + &soc->rxdma_mon_status_ring[lmac_id], + RXDMA_MONITOR_STATUS, 0, lmac_id, entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -3408,8 +3722,8 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev) entries = wlan_cfg_get_dma_mon_desc_ring_size(pdev_cfg_ctx); if (dp_srng_setup(soc, - &pdev->rxdma_mon_desc_ring[mac_id], - RXDMA_MONITOR_DESC, 0, mac_for_pdev, + &soc->rxdma_mon_desc_ring[lmac_id], + RXDMA_MONITOR_DESC, 0, lmac_id, entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -3420,8 +3734,8 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev) entries = wlan_cfg_get_dma_mon_stat_ring_size(pdev_cfg_ctx); if (dp_srng_setup(soc, - &pdev->rxdma_mon_status_ring[mac_id], - RXDMA_MONITOR_STATUS, 0, mac_for_pdev, + &soc->rxdma_mon_status_ring[lmac_id], + RXDMA_MONITOR_STATUS, 0, lmac_id, entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -3445,7 +3759,7 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev) * @pdev_hdl: pdev handle */ #ifdef ATH_SUPPORT_EXT_STAT -void dp_iterate_update_peer_list(void *pdev_hdl) +void dp_iterate_update_peer_list(struct cdp_pdev *pdev_hdl) { struct dp_pdev *pdev = (struct dp_pdev *)pdev_hdl; struct dp_soc *soc = pdev->soc; @@ -3463,7 +3777,7 @@ void dp_iterate_update_peer_list(void *pdev_hdl) qdf_spin_unlock_bh(&soc->peer_ref_mutex); } #else -void dp_iterate_update_peer_list(void *pdev_hdl) +void dp_iterate_update_peer_list(struct cdp_pdev *pdev_hdl) { } #endif @@ -3487,40 +3801,141 @@ static QDF_STATUS dp_htt_ppdu_stats_attach(struct dp_pdev *pdev) return QDF_STATUS_SUCCESS; } +#ifdef WLAN_FEATURE_DP_RX_RING_HISTORY +#ifndef RX_DEFRAG_DO_NOT_REINJECT +/** + * dp_soc_rx_reinject_ring_history_attach - Attach the reo reinject ring + * history. + * @soc: DP soc handle + * + * Return: None + */ +static void dp_soc_rx_reinject_ring_history_attach(struct dp_soc *soc) +{ + soc->rx_reinject_ring_history = dp_context_alloc_mem( + soc, DP_RX_REINJECT_RING_HIST_TYPE, rx_ring_hist_size); + if (soc->rx_reinject_ring_history) + qdf_atomic_init(&soc->rx_reinject_ring_history->index); +} +#else /* RX_DEFRAG_DO_NOT_REINJECT */ +static inline void +dp_soc_rx_reinject_ring_history_attach(struct dp_soc *soc) +{ +} +#endif /* RX_DEFRAG_DO_NOT_REINJECT */ + +/** + * dp_soc_rx_history_attach() - Attach the ring history record buffers + * @soc: DP soc structure + * + * This function allocates the memory for recording the rx ring, rx error + * ring and the reinject ring entries. There is no error returned in case + * of allocation failure since the record function checks if the history is + * initialized or not. We do not want to fail the driver load in case of + * failure to allocate memory for debug history. + * + * Returns: None + */ +static void dp_soc_rx_history_attach(struct dp_soc *soc) +{ + int i; + uint32_t rx_ring_hist_size; + uint32_t rx_err_ring_hist_size; + uint32_t rx_reinject_hist_size; + + rx_ring_hist_size = sizeof(*soc->rx_ring_history[0]); + rx_err_ring_hist_size = sizeof(*soc->rx_err_ring_history); + rx_reinject_hist_size = sizeof(*soc->rx_reinject_ring_history); + + for (i = 0; i < MAX_REO_DEST_RINGS; i++) { + soc->rx_ring_history[i] = dp_context_alloc_mem( + soc, DP_RX_RING_HIST_TYPE, rx_ring_hist_size); + if (soc->rx_ring_history[i]) + qdf_atomic_init(&soc->rx_ring_history[i]->index); + } + + soc->rx_err_ring_history = dp_context_alloc_mem( + soc, DP_RX_ERR_RING_HIST_TYPE, rx_ring_hist_size); + if (soc->rx_err_ring_history) + qdf_atomic_init(&soc->rx_err_ring_history->index); + + dp_soc_rx_reinject_ring_history_attach(soc); +} + +static void dp_soc_rx_history_detach(struct dp_soc *soc) +{ + int i; + + for (i = 0; i < MAX_REO_DEST_RINGS; i++) + dp_context_free_mem(soc, DP_RX_RING_HIST_TYPE, + soc->rx_ring_history[i]); + + dp_context_free_mem(soc, DP_RX_ERR_RING_HIST_TYPE, + soc->rx_err_ring_history); + + /* + * No need for a featurized detach since qdf_mem_free takes + * care of NULL pointer. + */ + dp_context_free_mem(soc, DP_RX_REINJECT_RING_HIST_TYPE, + soc->rx_reinject_ring_history); +} + +#else +static inline void dp_soc_rx_history_attach(struct dp_soc *soc) +{ +} + +static inline void dp_soc_rx_history_detach(struct dp_soc *soc) +{ +} +#endif + /* * dp_pdev_attach_wifi3() - attach txrx pdev -* @ctrl_pdev: Opaque PDEV object * @txrx_soc: Datapath SOC handle * @htc_handle: HTC handle for host-target interface * @qdf_osdev: QDF OS device * @pdev_id: PDEV ID * -* Return: DP PDEV handle on success, NULL on failure +* Return: QDF_STATUS */ -static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, - struct cdp_ctrl_objmgr_pdev *ctrl_pdev, - HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, uint8_t pdev_id) +static inline QDF_STATUS dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, + HTC_HANDLE htc_handle, + qdf_device_t qdf_osdev, + uint8_t pdev_id) { int ring_size; int entries; struct wlan_cfg_dp_soc_ctxt *soc_cfg_ctx; int nss_cfg; void *sojourn_buf; - struct dp_soc *soc = (struct dp_soc *)txrx_soc; struct dp_pdev *pdev = NULL; + QDF_STATUS ret; - if (dp_is_soc_reinit(soc)) + if (dp_is_soc_reinit(soc)) { pdev = soc->pdev_list[pdev_id]; - else - pdev = qdf_mem_malloc(sizeof(*pdev)); + } else { + pdev = dp_context_alloc_mem(soc, DP_PDEV_TYPE, sizeof(*pdev)); + qdf_minidump_log(pdev, sizeof(*pdev), "dp_pdev"); + } if (!pdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("DP PDEV memory allocation failed")); + ret = QDF_STATUS_E_NOMEM; + goto fail0; + } + + pdev->filter = dp_mon_filter_alloc(pdev); + if (!pdev->filter) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Memory allocation failed for monitor filters")); + qdf_mem_free(pdev); + ret = QDF_STATUS_E_NOMEM; goto fail0; } - qdf_minidump_log((void *)pdev, sizeof(*pdev), "dp_pdev"); /* * Variable to prevent double pdev deinitialization during @@ -3532,7 +3947,9 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, if (!pdev->invalid_peer) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("Invalid peer memory allocation failed")); + dp_mon_filter_dealloc(pdev); qdf_mem_free(pdev); + ret = QDF_STATUS_E_NOMEM; goto fail0; } @@ -3544,7 +3961,9 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, FL("pdev cfg_attach failed")); qdf_mem_free(pdev->invalid_peer); + dp_mon_filter_dealloc(pdev); qdf_mem_free(pdev); + ret = QDF_STATUS_E_FAILURE; goto fail0; } @@ -3556,7 +3975,6 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, (nss_cfg & (1 << pdev_id))); pdev->soc = soc; - pdev->ctrl_pdev = ctrl_pdev; pdev->pdev_id = pdev_id; soc->pdev_list[pdev_id] = pdev; @@ -3572,10 +3990,12 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, TAILQ_INIT(&pdev->neighbour_peers_list); pdev->neighbour_peers_added = false; pdev->monitor_configured = false; + pdev->enable_reap_timer_non_pkt = false; if (dp_soc_cmn_setup(soc)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_soc_cmn_setup failed")); + ret = QDF_STATUS_E_FAILURE; goto fail1; } @@ -3588,6 +4008,7 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, pdev_id, pdev_id, ring_size, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for tcl_data_ring")); + ret = QDF_STATUS_E_FAILURE; goto fail1; } @@ -3599,6 +4020,7 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, ring_size, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for tx_comp_ring")); + ret = QDF_STATUS_E_FAILURE; goto fail1; } soc->num_tcl_data_rings++; @@ -3608,6 +4030,7 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, if (dp_tx_pdev_attach(pdev)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_tx_pdev_attach failed")); + ret = QDF_STATUS_E_FAILURE; goto fail1; } @@ -3618,53 +4041,64 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, pdev_id, pdev_id, ring_size, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed for reo_dest_ringn")); + ret = QDF_STATUS_E_FAILURE; goto fail1; } soc->num_reo_dest_rings++; - } ring_size = wlan_cfg_get_dp_soc_rxdma_refill_ring_size(soc->wlan_cfg_ctx); - if (dp_srng_setup(soc, &pdev->rx_refill_buf_ring, RXDMA_BUF, 0, pdev_id, - ring_size, 0)) { + if (dp_srng_setup(soc, &soc->rx_refill_buf_ring[pdev->lmac_id], + RXDMA_BUF, 0, pdev->lmac_id, ring_size, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_srng_setup failed rx refill ring")); + ret = QDF_STATUS_E_FAILURE; goto fail1; } if (dp_rxdma_ring_setup(soc, pdev)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("RXDMA ring config failed")); + ret = QDF_STATUS_E_FAILURE; goto fail1; } if (dp_mon_rings_setup(soc, pdev)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("MONITOR rings setup failed")); + ret = QDF_STATUS_E_FAILURE; goto fail1; } entries = wlan_cfg_get_dp_soc_rxdma_err_dst_ring_size(soc_cfg_ctx); if (wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) { - if (dp_srng_setup(soc, &pdev->rxdma_err_dst_ring[0], RXDMA_DST, - 0, pdev_id, entries, 0)) { + if (dp_srng_setup(soc, + &soc->rxdma_err_dst_ring[pdev->lmac_id], + RXDMA_DST, + 0, pdev->lmac_id, entries, 0)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL(RNG_ERR "rxdma_err_dst_ring")); + ret = QDF_STATUS_E_FAILURE; goto fail1; } } - if (dp_setup_ipa_rx_refill_buf_ring(soc, pdev)) + if (dp_setup_ipa_rx_refill_buf_ring(soc, pdev)) { + ret = QDF_STATUS_E_FAILURE; goto fail1; + } - if (dp_ipa_ring_resource_setup(soc, pdev)) + if (dp_ipa_ring_resource_setup(soc, pdev)) { + ret = QDF_STATUS_E_FAILURE; goto fail1; + } if (dp_ipa_uc_attach(soc, pdev) != QDF_STATUS_SUCCESS) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_ipa_uc_attach failed")); + ret = QDF_STATUS_E_FAILURE; goto fail1; } @@ -3672,6 +4106,7 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, if (dp_rx_pdev_attach(pdev)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("dp_rx_pdev_attach failed")); + ret = QDF_STATUS_E_FAILURE; goto fail2; } @@ -3695,12 +4130,14 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, if (dp_rx_pdev_mon_attach(pdev)) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "dp_rx_pdev_mon_attach failed"); + ret = QDF_STATUS_E_FAILURE; goto fail2; } if (dp_wdi_event_attach(pdev)) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "dp_wdi_evet_attach failed"); + ret = QDF_STATUS_E_FAILURE; goto wdi_attach_fail; } @@ -3725,18 +4162,24 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, qdf_mem_zero(sojourn_buf, sizeof(struct cdp_tx_sojourn_stats)); } /* initlialize cal client timer */ - dp_cal_client_attach(&pdev->cal_client_ctx, pdev, pdev->soc->osdev, + dp_cal_client_attach(&pdev->cal_client_ctx, + dp_pdev_to_cdp_pdev(pdev), + pdev->soc->osdev, &dp_iterate_update_peer_list); qdf_event_create(&pdev->fw_peer_stats_event); pdev->num_tx_allowed = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx); - if (dp_htt_ppdu_stats_attach(pdev) != QDF_STATUS_SUCCESS) + dp_init_tso_stats(pdev); + + if (dp_htt_ppdu_stats_attach(pdev) != QDF_STATUS_SUCCESS) { + ret = QDF_STATUS_E_FAILURE; goto fail1; + } dp_tx_ppdu_stats_attach(pdev); - return (struct cdp_pdev *)pdev; + return QDF_STATUS_SUCCESS; wdi_attach_fail: /* @@ -3753,10 +4196,13 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, soc->pdev_count--; if (pdev->invalid_peer) qdf_mem_free(pdev->invalid_peer); - dp_pdev_detach((struct cdp_pdev *)pdev, 0); + if (pdev->filter) + dp_mon_filter_dealloc(pdev); + + dp_pdev_detach((struct cdp_pdev *)pdev, 0); fail0: - return NULL; + return ret; } /* @@ -3785,6 +4231,11 @@ static void dp_rxdma_ring_cleanup(struct dp_soc *soc, static void dp_rxdma_ring_cleanup(struct dp_soc *soc, struct dp_pdev *pdev) { + if (soc->lmac_timer_init) { + qdf_timer_stop(&soc->lmac_reap_timer); + qdf_timer_free(&soc->lmac_reap_timer); + soc->lmac_timer_init = 0; + } } #endif @@ -3840,35 +4291,35 @@ static void dp_mon_ring_cleanup(struct dp_soc *soc, struct dp_pdev *pdev, int mac_id) { - if (soc->wlan_cfg_ctx->rxdma1_enable) { - dp_srng_cleanup(soc, - &pdev->rxdma_mon_buf_ring[mac_id], - RXDMA_MONITOR_BUF, 0); + if (soc->wlan_cfg_ctx->rxdma1_enable) { + dp_srng_cleanup(soc, + &soc->rxdma_mon_buf_ring[mac_id], + RXDMA_MONITOR_BUF, 0); - dp_srng_cleanup(soc, - &pdev->rxdma_mon_dst_ring[mac_id], - RXDMA_MONITOR_DST, 0); + dp_srng_cleanup(soc, + &soc->rxdma_mon_dst_ring[mac_id], + RXDMA_MONITOR_DST, 0); - dp_srng_cleanup(soc, - &pdev->rxdma_mon_status_ring[mac_id], - RXDMA_MONITOR_STATUS, 0); + dp_srng_cleanup(soc, + &soc->rxdma_mon_status_ring[mac_id], + RXDMA_MONITOR_STATUS, 0); - dp_srng_cleanup(soc, - &pdev->rxdma_mon_desc_ring[mac_id], - RXDMA_MONITOR_DESC, 0); + dp_srng_cleanup(soc, + &soc->rxdma_mon_desc_ring[mac_id], + RXDMA_MONITOR_DESC, 0); - dp_srng_cleanup(soc, - &pdev->rxdma_err_dst_ring[mac_id], - RXDMA_DST, 0); - } else { - dp_srng_cleanup(soc, - &pdev->rxdma_mon_status_ring[mac_id], - RXDMA_MONITOR_STATUS, 0); + dp_srng_cleanup(soc, + &soc->rxdma_err_dst_ring[mac_id], + RXDMA_DST, 0); + } else { + dp_srng_cleanup(soc, + &soc->rxdma_mon_status_ring[mac_id], + RXDMA_MONITOR_STATUS, 0); - dp_srng_cleanup(soc, - &pdev->rxdma_err_dst_ring[mac_id], - RXDMA_DST, 0); - } + dp_srng_cleanup(soc, + &soc->rxdma_err_dst_ring[mac_id], + RXDMA_DST, 0); + } } #else @@ -3991,6 +4442,7 @@ static void dp_pdev_deinit(struct cdp_pdev *txrx_pdev, int force) dp_pktlogmod_exit(pdev); + dp_rx_fst_detach(soc, pdev); dp_rx_pdev_detach(pdev); dp_rx_pdev_mon_detach(pdev); dp_neighbour_peers_detach(pdev); @@ -4007,13 +4459,18 @@ static void dp_pdev_deinit(struct cdp_pdev *txrx_pdev, int force) REO_DST, pdev->pdev_id); } - dp_srng_deinit(soc, &pdev->rx_refill_buf_ring, RXDMA_BUF, 0); + dp_srng_deinit(soc, &soc->rx_refill_buf_ring[pdev->lmac_id], + RXDMA_BUF, 0); dp_rxdma_ring_cleanup(soc, pdev); for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - dp_mon_ring_deinit(soc, pdev, mac_id); - dp_srng_deinit(soc, &pdev->rxdma_err_dst_ring[mac_id], + int lmac_id = + dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev->pdev_id); + + dp_mon_ring_deinit(soc, pdev, lmac_id); + + dp_srng_deinit(soc, &soc->rxdma_err_dst_ring[lmac_id], RXDMA_DST, 0); } @@ -4028,7 +4485,10 @@ static void dp_pdev_deinit(struct cdp_pdev *txrx_pdev, int force) dp_htt_ppdu_stats_detach(pdev); + dp_tx_ppdu_stats_detach(pdev); + qdf_nbuf_free(pdev->sojourn_buf); + qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q); dp_cal_client_detach(&pdev->cal_client_ctx); @@ -4041,25 +4501,42 @@ static void dp_pdev_deinit(struct cdp_pdev *txrx_pdev, int force) wlan_cfg_pdev_detach(pdev->wlan_cfg_ctx); if (pdev->invalid_peer) qdf_mem_free(pdev->invalid_peer); + + /* + * Fee the monitor filter allocated and stored + */ + if (pdev->filter) + dp_mon_filter_dealloc(pdev); + qdf_mem_free(pdev->dp_txrx_handle); dp_pdev_mem_reset(pdev); } /** * dp_pdev_deinit_wifi3() - Deinit txrx pdev - * @txrx_pdev: Datapath PDEV handle + * @psoc: Datapath psoc handle + * @pdev_id: Id of datapath PDEV handle * @force: Force deinit * - * Return: None + * Return: QDF_STATUS */ -static void dp_pdev_deinit_wifi3(struct cdp_pdev *txrx_pdev, int force) +static QDF_STATUS +dp_pdev_deinit_wifi3(struct cdp_soc_t *psoc, uint8_t pdev_id, + int force) { - struct dp_pdev *pdev = (struct dp_pdev *)txrx_pdev; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = (struct dp_soc *)psoc; + struct dp_pdev *txrx_pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)psoc, + pdev_id); + + if (!txrx_pdev) + return QDF_STATUS_E_FAILURE; soc->dp_soc_reinit = TRUE; - dp_pdev_deinit(txrx_pdev, force); + dp_pdev_deinit((struct cdp_pdev *)txrx_pdev, force); + + return QDF_STATUS_SUCCESS; } /* @@ -4075,6 +4552,7 @@ static void dp_pdev_detach(struct cdp_pdev *txrx_pdev, int force) struct dp_soc *soc = pdev->soc; struct rx_desc_pool *rx_desc_pool; int mac_id, mac_for_pdev; + int lmac_id; if (wlan_cfg_per_pdev_tx_ring(soc->wlan_cfg_ctx)) { dp_srng_cleanup(soc, &soc->tcl_data_ring[pdev->pdev_id], @@ -4085,8 +4563,6 @@ static void dp_pdev_detach(struct cdp_pdev *txrx_pdev, int force) dp_mon_link_free(pdev); - dp_tx_ppdu_stats_detach(pdev); - /* Cleanup per PDEV REO rings if configured */ if (wlan_cfg_per_pdev_rx_ring(soc->wlan_cfg_ctx)) { dp_srng_cleanup(soc, &soc->reo_dest_ring[pdev->pdev_id], @@ -4095,16 +4571,21 @@ static void dp_pdev_detach(struct cdp_pdev *txrx_pdev, int force) dp_rxdma_ring_cleanup(soc, pdev); wlan_cfg_pdev_detach(pdev->wlan_cfg_ctx); - dp_srng_cleanup(soc, &pdev->rx_refill_buf_ring, RXDMA_BUF, 0); + dp_srng_cleanup(soc, &soc->rx_refill_buf_ring[pdev->lmac_id], + RXDMA_BUF, 0); dp_cleanup_ipa_rx_refill_buf_ring(soc, pdev); for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - dp_mon_ring_cleanup(soc, pdev, mac_id); - dp_srng_cleanup(soc, &pdev->rxdma_err_dst_ring[mac_id], + lmac_id = + dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev->pdev_id); + dp_mon_ring_cleanup(soc, pdev, lmac_id); + dp_srng_cleanup(soc, &soc->rxdma_err_dst_ring[lmac_id], RXDMA_DST, 0); + if (dp_is_soc_reinit(soc)) { - mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); + mac_for_pdev = + dp_get_lmac_id_for_pdev_id(soc, mac_id, + pdev->pdev_id); rx_desc_pool = &soc->rx_desc_status[mac_for_pdev]; dp_rx_desc_pool_free(soc, rx_desc_pool); rx_desc_pool = &soc->rx_desc_mon[mac_for_pdev]; @@ -4113,7 +4594,7 @@ static void dp_pdev_detach(struct cdp_pdev *txrx_pdev, int force) } if (dp_is_soc_reinit(soc)) { - rx_desc_pool = &soc->rx_desc_buf[pdev->pdev_id]; + rx_desc_pool = &soc->rx_desc_buf[pdev->lmac_id]; dp_rx_desc_pool_free(soc, rx_desc_pool); } @@ -4122,27 +4603,39 @@ static void dp_pdev_detach(struct cdp_pdev *txrx_pdev, int force) dp_soc_cmn_cleanup(soc); soc->pdev_list[pdev->pdev_id] = NULL; - qdf_mem_free(pdev); + qdf_minidump_remove(pdev); + dp_context_free_mem(soc, DP_PDEV_TYPE, pdev); } /* * dp_pdev_detach_wifi3() - detach txrx pdev - * @txrx_pdev: Datapath PDEV handle + * @psoc: Datapath soc handle + * @pdev_id: pdev id of pdev * @force: Force detach * - * Return: None + * Return: QDF_STATUS */ -static void dp_pdev_detach_wifi3(struct cdp_pdev *txrx_pdev, int force) +static QDF_STATUS dp_pdev_detach_wifi3(struct cdp_soc_t *psoc, uint8_t pdev_id, + int force) { - struct dp_pdev *pdev = (struct dp_pdev *)txrx_pdev; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = (struct dp_soc *)psoc; + struct dp_pdev *txrx_pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)psoc, + pdev_id); + + if (!txrx_pdev) { + dp_err("Couldn't find dp pdev"); + return QDF_STATUS_E_FAILURE; + } if (dp_is_soc_reinit(soc)) { - dp_pdev_detach(txrx_pdev, force); + dp_pdev_detach((struct cdp_pdev *)txrx_pdev, force); } else { - dp_pdev_deinit(txrx_pdev, force); - dp_pdev_detach(txrx_pdev, force); + dp_pdev_deinit((struct cdp_pdev *)txrx_pdev, force); + dp_pdev_detach((struct cdp_pdev *)txrx_pdev, force); } + + return QDF_STATUS_SUCCESS; } /* @@ -4286,7 +4779,7 @@ static void dp_soc_deinit(void *txrx_soc) * * Return: None */ -static void dp_soc_deinit_wifi3(void *txrx_soc) +static void dp_soc_deinit_wifi3(struct cdp_soc_t *txrx_soc) { struct dp_soc *soc = (struct dp_soc *)txrx_soc; @@ -4300,7 +4793,7 @@ static void dp_soc_deinit_wifi3(void *txrx_soc) * * Return: None */ -static void dp_soc_detach(void *txrx_soc) +static void dp_soc_detach(struct cdp_soc_t *txrx_soc) { struct dp_soc *soc = (struct dp_soc *)txrx_soc; int i; @@ -4319,8 +4812,13 @@ static void dp_soc_detach(void *txrx_soc) /* Free the ring memories */ /* Common rings */ + qdf_minidump_remove(soc->wbm_desc_rel_ring.base_vaddr_unaligned); dp_srng_cleanup(soc, &soc->wbm_desc_rel_ring, SW2WBM_RELEASE, 0); + if (dp_is_soc_reinit(soc)) { + dp_tx_soc_detach(soc); + } + /* Tx data rings */ if (!wlan_cfg_per_pdev_tx_ring(soc->wlan_cfg_ctx)) { for (i = 0; i < soc->num_tcl_data_rings; i++) { @@ -4369,7 +4867,9 @@ static void dp_soc_detach(void *txrx_soc) soc->dp_soc_reinit = 0; wlan_cfg_soc_detach(soc->wlan_cfg_ctx); + dp_soc_rx_history_detach(soc); + qdf_minidump_remove(soc); qdf_mem_free(soc); } @@ -4379,7 +4879,7 @@ static void dp_soc_detach(void *txrx_soc) * * Return: None */ -static void dp_soc_detach_wifi3(void *txrx_soc) +static void dp_soc_detach_wifi3(struct cdp_soc_t *txrx_soc) { struct dp_soc *soc = (struct dp_soc *)txrx_soc; @@ -4389,7 +4889,6 @@ static void dp_soc_detach_wifi3(void *txrx_soc) dp_soc_deinit(txrx_soc); dp_soc_detach(txrx_soc); } - } #if !defined(DISABLE_MON_CONFIG) @@ -4411,7 +4910,7 @@ static QDF_STATUS dp_mon_htt_srng_setup(struct dp_soc *soc, if (soc->wlan_cfg_ctx->rxdma1_enable) { status = htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_buf_ring[mac_id] + soc->rxdma_mon_buf_ring[mac_id] .hal_srng, RXDMA_MONITOR_BUF); @@ -4421,7 +4920,7 @@ static QDF_STATUS dp_mon_htt_srng_setup(struct dp_soc *soc, } status = htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_dst_ring[mac_id] + soc->rxdma_mon_dst_ring[mac_id] .hal_srng, RXDMA_MONITOR_DST); @@ -4431,7 +4930,7 @@ static QDF_STATUS dp_mon_htt_srng_setup(struct dp_soc *soc, } status = htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id] + soc->rxdma_mon_status_ring[mac_id] .hal_srng, RXDMA_MONITOR_STATUS); @@ -4441,7 +4940,7 @@ static QDF_STATUS dp_mon_htt_srng_setup(struct dp_soc *soc, } status = htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_desc_ring[mac_id] + soc->rxdma_mon_desc_ring[mac_id] .hal_srng, RXDMA_MONITOR_DESC); @@ -4451,7 +4950,7 @@ static QDF_STATUS dp_mon_htt_srng_setup(struct dp_soc *soc, } } else { status = htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id] + soc->rxdma_mon_status_ring[mac_id] .hal_srng, RXDMA_MONITOR_STATUS); @@ -4500,10 +4999,12 @@ static QDF_STATUS dp_rxdma_ring_config(struct dp_soc *soc) int max_mac_rings = wlan_cfg_get_num_mac_rings (pdev->wlan_cfg_ctx); + int lmac_id = dp_get_lmac_id_for_pdev_id(soc, 0, i); htt_srng_setup(soc->htt_handle, 0, - pdev->rx_refill_buf_ring.hal_srng, - RXDMA_BUF); + soc->rx_refill_buf_ring[lmac_id] + .hal_srng, + RXDMA_BUF); if (pdev->rx_refill_buf_ring2.hal_srng) htt_srng_setup(soc->htt_handle, 0, @@ -4513,7 +5014,8 @@ static QDF_STATUS dp_rxdma_ring_config(struct dp_soc *soc) if (soc->cdp_soc.ol_ops-> is_hw_dbs_2x2_capable) { dbs_enable = soc->cdp_soc.ol_ops-> - is_hw_dbs_2x2_capable(soc->ctrl_psoc); + is_hw_dbs_2x2_capable( + (void *)soc->ctrl_psoc); } if (dbs_enable) { @@ -4534,9 +5036,17 @@ static QDF_STATUS dp_rxdma_ring_config(struct dp_soc *soc) pdev->pdev_id, max_mac_rings); for (mac_id = 0; mac_id < max_mac_rings; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev( - mac_id, pdev->pdev_id); - + int mac_for_pdev = + dp_get_mac_id_for_pdev(mac_id, + pdev->pdev_id); + /* + * Obtain lmac id from pdev to access the LMAC + * ring in soc context + */ + lmac_id = + dp_get_lmac_id_for_pdev_id(soc, + mac_id, + pdev->pdev_id); QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, FL("mac_id %d"), mac_for_pdev); @@ -4546,13 +5056,13 @@ static QDF_STATUS dp_rxdma_ring_config(struct dp_soc *soc) .hal_srng, RXDMA_BUF); htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rxdma_err_dst_ring[mac_id] - .hal_srng, + soc->rxdma_err_dst_ring[lmac_id] + .hal_srng, RXDMA_DST); /* Configure monitor mode rings */ status = dp_mon_htt_srng_setup(soc, pdev, - mac_id, + lmac_id, mac_for_pdev); if (status != QDF_STATUS_SUCCESS) { dp_err("Failed to send htt monitor messages to target"); @@ -4578,38 +5088,52 @@ static QDF_STATUS dp_rxdma_ring_config(struct dp_soc *soc) static QDF_STATUS dp_rxdma_ring_config(struct dp_soc *soc) { int i; - int mac_id; QDF_STATUS status = QDF_STATUS_SUCCESS; + int mac_for_pdev; + int lmac_id; for (i = 0; i < MAX_PDEV_CNT; i++) { - struct dp_pdev *pdev = soc->pdev_list[i]; + struct dp_pdev *pdev = soc->pdev_list[i]; if (!pdev) continue; - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, i); + mac_for_pdev = i; + lmac_id = dp_get_lmac_id_for_pdev_id(soc, 0, i); - htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rx_refill_buf_ring.hal_srng, RXDMA_BUF); + htt_srng_setup(soc->htt_handle, mac_for_pdev, + soc->rx_refill_buf_ring[lmac_id]. + hal_srng, RXDMA_BUF); #ifndef DISABLE_MON_CONFIG - htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_buf_ring[mac_id].hal_srng, - RXDMA_MONITOR_BUF); - htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_dst_ring[mac_id].hal_srng, - RXDMA_MONITOR_DST); - htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id].hal_srng, - RXDMA_MONITOR_STATUS); - htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_desc_ring[mac_id].hal_srng, - RXDMA_MONITOR_DESC); + + htt_srng_setup(soc->htt_handle, mac_for_pdev, + soc->rxdma_mon_buf_ring[lmac_id].hal_srng, + RXDMA_MONITOR_BUF); + htt_srng_setup(soc->htt_handle, mac_for_pdev, + soc->rxdma_mon_dst_ring[lmac_id].hal_srng, + RXDMA_MONITOR_DST); + htt_srng_setup(soc->htt_handle, mac_for_pdev, + soc->rxdma_mon_status_ring[lmac_id].hal_srng, + RXDMA_MONITOR_STATUS); + htt_srng_setup(soc->htt_handle, mac_for_pdev, + soc->rxdma_mon_desc_ring[lmac_id].hal_srng, + RXDMA_MONITOR_DESC); #endif - htt_srng_setup(soc->htt_handle, mac_for_pdev, - pdev->rxdma_err_dst_ring[mac_id].hal_srng, - RXDMA_DST); - } + htt_srng_setup(soc->htt_handle, mac_for_pdev, + soc->rxdma_err_dst_ring[lmac_id].hal_srng, + RXDMA_DST); + } + + /* Configure LMAC rings in Polled mode */ + if (soc->lmac_polled_mode) { + /* + * Timer to reap lmac rings. + */ + qdf_timer_init(soc->osdev, &soc->lmac_reap_timer, + dp_service_lmac_rings, (void *)soc, + QDF_TIMER_TYPE_WAKE_APPS); + soc->lmac_timer_init = 1; + qdf_timer_mod(&soc->lmac_reap_timer, DP_INTR_POLL_TIMER_MS); } return status; } @@ -4675,12 +5199,20 @@ dp_rxdma_ring_sel_cfg(struct dp_soc *soc) continue; for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); + int mac_for_pdev = + dp_get_mac_id_for_pdev(mac_id, pdev->pdev_id); + /* + * Obtain lmac id from pdev to access the LMAC ring + * in soc context + */ + int lmac_id = + dp_get_lmac_id_for_pdev_id(soc, mac_id, + pdev->pdev_id); htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, - pdev->rx_refill_buf_ring.hal_srng, - RXDMA_BUF, RX_BUFFER_SIZE, + soc->rx_refill_buf_ring[lmac_id]. + hal_srng, + RXDMA_BUF, RX_DATA_BUFFER_SIZE, &htt_tlv_filter); } } @@ -4695,83 +5227,139 @@ dp_rxdma_ring_sel_cfg(struct dp_soc *soc) #endif /* - * dp_soc_attach_target_wifi3() - SOC initialization in the target - * @cdp_soc: Opaque Datapath SOC handle + * dp_rx_target_fst_config() - configure the RXOLE Flow Search Engine + * + * This function is used to configure the FSE HW block in RX OLE on a + * per pdev basis. Here, we will be programming parameters related to + * the Flow Search Table. + * + * @soc: data path SoC handle * * Return: zero on success, non-zero on failure */ +#ifdef WLAN_SUPPORT_RX_FLOW_TAG static QDF_STATUS -dp_soc_attach_target_wifi3(struct cdp_soc_t *cdp_soc) +dp_rx_target_fst_config(struct dp_soc *soc) { - struct dp_soc *soc = (struct dp_soc *)cdp_soc; + int i; QDF_STATUS status = QDF_STATUS_SUCCESS; - htt_soc_attach_target(soc->htt_handle); + for (i = 0; i < MAX_PDEV_CNT; i++) { + struct dp_pdev *pdev = soc->pdev_list[i]; - status = dp_rxdma_ring_config(soc); - if (status != QDF_STATUS_SUCCESS) { - dp_err("Failed to send htt srng setup messages to target"); - return status; + /* Flow search is not enabled if NSS offload is enabled */ + if (pdev && + !wlan_cfg_get_dp_pdev_nss_enabled(pdev->wlan_cfg_ctx)) { + status = dp_rx_flow_send_fst_fw_setup(pdev->soc, pdev); + if (status != QDF_STATUS_SUCCESS) + break; + } } - - status = dp_rxdma_ring_sel_cfg(soc); - if (status != QDF_STATUS_SUCCESS) { - dp_err("Failed to send htt ring config message to target"); - return status; + return status; +} +#elif defined(WLAN_SUPPORT_RX_FISA) +/** + * dp_rx_target_fst_config() - Configure RX OLE FSE engine in HW + * @soc: SoC handle + * + * Return: Success + */ +static inline QDF_STATUS dp_rx_target_fst_config(struct dp_soc *soc) +{ + /* Check if it is enabled in the INI */ + if (!soc->fisa_enable) { + dp_err("RX FISA feature is disabled"); + return QDF_STATUS_E_NOSUPPORT; } - DP_STATS_INIT(soc); + return dp_rx_flow_send_fst_fw_setup(soc, soc->pdev_list[0]); +} - /* initialize work queue for stats processing */ - qdf_create_work(0, &soc->htt_stats.work, htt_t2h_stats_handler, soc); +#define FISA_MAX_TIMEOUT 0xffffffff +#define FISA_DISABLE_TIMEOUT 0 +static QDF_STATUS dp_rx_fisa_config(struct dp_soc *soc) +{ + struct dp_htt_rx_fisa_cfg fisa_config; - qdf_minidump_log((void *)soc, sizeof(*soc), "dp_soc"); + fisa_config.pdev_id = 0; + fisa_config.fisa_timeout = FISA_MAX_TIMEOUT; + return dp_htt_rx_fisa_config(soc->pdev_list[0], &fisa_config); +} +#else /* !WLAN_SUPPORT_RX_FISA */ +static inline QDF_STATUS dp_rx_target_fst_config(struct dp_soc *soc) +{ return QDF_STATUS_SUCCESS; } +#endif /* !WLAN_SUPPORT_RX_FISA */ -/* - * dp_soc_get_nss_cfg_wifi3() - SOC get nss config - * @txrx_soc: Datapath SOC handle - */ -static int dp_soc_get_nss_cfg_wifi3(struct cdp_soc_t *cdp_soc) +#ifndef WLAN_SUPPORT_RX_FISA +static QDF_STATUS dp_rx_fisa_config(struct dp_soc *soc) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS dp_rx_dump_fisa_stats(struct dp_soc *soc) +{ + return QDF_STATUS_SUCCESS; +} + +static void dp_rx_dump_fisa_table(struct dp_soc *soc) { - struct dp_soc *dsoc = (struct dp_soc *)cdp_soc; - return wlan_cfg_get_dp_soc_nss_cfg(dsoc->wlan_cfg_ctx); } +#endif /* !WLAN_SUPPORT_RX_FISA */ /* - * dp_soc_set_nss_cfg_wifi3() - SOC set nss config - * @txrx_soc: Datapath SOC handle - * @nss_cfg: nss config + * dp_soc_attach_target_wifi3() - SOC initialization in the target + * @cdp_soc: Opaque Datapath SOC handle + * + * Return: zero on success, non-zero on failure */ -static void dp_soc_set_nss_cfg_wifi3(struct cdp_soc_t *cdp_soc, int config) +static QDF_STATUS +dp_soc_attach_target_wifi3(struct cdp_soc_t *cdp_soc) { - struct dp_soc *dsoc = (struct dp_soc *)cdp_soc; - struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx = dsoc->wlan_cfg_ctx; + struct dp_soc *soc = (struct dp_soc *)cdp_soc; + QDF_STATUS status = QDF_STATUS_SUCCESS; - wlan_cfg_set_dp_soc_nss_cfg(wlan_cfg_ctx, config); + htt_soc_attach_target(soc->htt_handle); - /* - * TODO: masked out based on the per offloaded radio - */ - switch (config) { - case dp_nss_cfg_default: - break; - case dp_nss_cfg_dbdc: - case dp_nss_cfg_dbtc: - wlan_cfg_set_num_tx_desc_pool(wlan_cfg_ctx, 0); - wlan_cfg_set_num_tx_ext_desc_pool(wlan_cfg_ctx, 0); - wlan_cfg_set_num_tx_desc(wlan_cfg_ctx, 0); - wlan_cfg_set_num_tx_ext_desc(wlan_cfg_ctx, 0); - break; - default: - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "Invalid offload config %d", config); + status = dp_rxdma_ring_config(soc); + if (status != QDF_STATUS_SUCCESS) { + dp_err("Failed to send htt srng setup messages to target"); + return status; } - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - FL("nss-wifi<0> nss config is enabled")); + status = dp_rxdma_ring_sel_cfg(soc); + if (status != QDF_STATUS_SUCCESS) { + dp_err("Failed to send htt ring config message to target"); + return status; + } + + status = dp_rx_target_fst_config(soc); + if (status != QDF_STATUS_SUCCESS && + status != QDF_STATUS_E_NOSUPPORT) { + dp_err("Failed to send htt fst setup config message to target"); + return status; + } + + if (status == QDF_STATUS_SUCCESS) { + status = dp_rx_fisa_config(soc); + if (status != QDF_STATUS_SUCCESS) { + dp_err("Failed to send htt FISA config message to target"); + return status; + } + } + + DP_STATS_INIT(soc); + + dp_runtime_init(soc); + + /* initialize work queue for stats processing */ + qdf_create_work(0, &soc->htt_stats.work, htt_t2h_stats_handler, soc); + + qdf_minidump_log(soc, sizeof(*soc), "dp_soc"); + + return QDF_STATUS_SUCCESS; } /* @@ -4782,16 +5370,28 @@ static void dp_soc_set_nss_cfg_wifi3(struct cdp_soc_t *cdp_soc, int config) * @wlan_op_mode: VDEV operating mode * @subtype: VDEV operating subtype * -* Return: DP VDEV handle on success, NULL on failure +* Return: status */ -static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev, - uint8_t *vdev_mac_addr, uint8_t vdev_id, enum wlan_op_mode op_mode, - enum wlan_op_subtype subtype) +static QDF_STATUS dp_vdev_attach_wifi3(struct cdp_soc_t *cdp_soc, + uint8_t pdev_id, + uint8_t *vdev_mac_addr, + uint8_t vdev_id, + enum wlan_op_mode op_mode, + enum wlan_op_subtype subtype) { - struct dp_pdev *pdev = (struct dp_pdev *)txrx_pdev; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = (struct dp_soc *)cdp_soc; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); struct dp_vdev *vdev = qdf_mem_malloc(sizeof(*vdev)); + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("DP PDEV is Null for pdev id %d"), pdev_id); + qdf_mem_free(vdev); + goto fail0; + } + if (!vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("DP VDEV memory allocation failed")); @@ -4815,6 +5415,7 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev, vdev->safemode = 0; vdev->drop_unenc = 1; vdev->sec_type = cdp_sec_type_none; + vdev->multipass_en = false; #ifdef notyet vdev->filters_num = 0; #endif @@ -4827,6 +5428,7 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev, */ TAILQ_INIT(&vdev->peer_list); + dp_peer_multipass_list_init(vdev); if ((soc->intr_mode == DP_INTR_POLL) && wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx) != 0) { @@ -4835,9 +5437,11 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev, qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS); } + soc->vdev_id_map[vdev_id] = vdev; + if (wlan_op_mode_monitor == vdev->opmode) { pdev->monitor_vdev = vdev; - return (struct cdp_vdev *)vdev; + return QDF_STATUS_SUCCESS; } vdev->tx_encap_type = wlan_cfg_pkt_type(soc->wlan_cfg_ctx); @@ -4854,46 +5458,63 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev, qdf_spin_unlock_bh(&pdev->vdev_list_lock); pdev->vdev_count++; + if (wlan_op_mode_sta != vdev->opmode && + wlan_op_mode_ndi != vdev->opmode) + vdev->ap_bridge_enabled = true; + else + vdev->ap_bridge_enabled = false; + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s: wlan_cfg_ap_bridge_enabled %d", + __func__, vdev->ap_bridge_enabled); + dp_tx_vdev_attach(vdev); if (pdev->vdev_count == 1) dp_lro_hash_setup(soc, pdev); - dp_info("Created vdev %pK (%pM)", vdev, vdev->mac_addr.raw); + dp_info("Created vdev %pK ("QDF_MAC_ADDR_FMT")", vdev, + QDF_MAC_ADDR_REF(vdev->mac_addr.raw)); DP_STATS_INIT(vdev); if (wlan_op_mode_sta == vdev->opmode) - dp_peer_create_wifi3((struct cdp_vdev *)vdev, - vdev->mac_addr.raw, - NULL); + dp_peer_create_wifi3((struct cdp_soc_t *)soc, vdev_id, + vdev->mac_addr.raw); - return (struct cdp_vdev *)vdev; + return QDF_STATUS_SUCCESS; fail0: - return NULL; + return QDF_STATUS_E_FAILURE; } /** * dp_vdev_register_wifi3() - Register VDEV operations from osif layer - * @vdev: Datapath VDEV handle + * @soc: Datapath soc handle + * @vdev_id: id of Datapath VDEV handle * @osif_vdev: OSIF vdev handle - * @ctrl_vdev: UMAC vdev handle * @txrx_ops: Tx and Rx operations * * Return: DP VDEV handle on success, NULL on failure */ -static void dp_vdev_register_wifi3(struct cdp_vdev *vdev_handle, - void *osif_vdev, struct cdp_ctrl_objmgr_vdev *ctrl_vdev, - struct ol_txrx_ops *txrx_ops) +static QDF_STATUS dp_vdev_register_wifi3(struct cdp_soc_t *soc, + uint8_t vdev_id, + ol_osif_vdev_handle osif_vdev, + struct ol_txrx_ops *txrx_ops) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + + if (!vdev) + return QDF_STATUS_E_FAILURE; + vdev->osif_vdev = osif_vdev; - vdev->ctrl_vdev = ctrl_vdev; vdev->osif_rx = txrx_ops->rx.rx; vdev->osif_rx_stack = txrx_ops->rx.rx_stack; vdev->osif_rx_flush = txrx_ops->rx.rx_flush; vdev->osif_gro_flush = txrx_ops->rx.rx_gro_flush; vdev->osif_rsim_rx_decap = txrx_ops->rx.rsim_rx_decap; + vdev->osif_fisa_rx = txrx_ops->rx.osif_fisa_rx; + vdev->osif_fisa_flush = txrx_ops->rx.osif_fisa_flush; vdev->osif_get_key = txrx_ops->get_key; vdev->osif_rx_mon = txrx_ops->rx.mon; vdev->osif_tx_free_ext = txrx_ops->tx.tx_free_ext; @@ -4918,6 +5539,8 @@ static void dp_vdev_register_wifi3(struct cdp_vdev *vdev_handle, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW, "DP Vdev Register success"); + + return QDF_STATUS_SUCCESS; } /** @@ -5001,11 +5624,13 @@ static void dp_vdev_flush_peers(struct cdp_vdev *vdev_handle, bool unmap_only) for (m = 0; m < n ; m++) { peer = peer_array[m]; - dp_info("peer: %pM is getting deleted", - peer->mac_addr.raw); + dp_info("peer: "QDF_MAC_ADDR_FMT" is getting deleted", + QDF_MAC_ADDR_REF(peer->mac_addr.raw)); /* only if peer valid is true */ if (peer->valid) - dp_peer_delete_wifi3(peer, 0); + dp_peer_delete_wifi3((struct cdp_soc_t *)soc, + vdev->vdev_id, + peer->mac_addr.raw, 0); } qdf_mem_free(peer_array); } @@ -5022,8 +5647,8 @@ static void dp_vdev_flush_peers(struct cdp_vdev *vdev_handle, bool unmap_only) * with ref count leak */ SET_PEER_REF_CNT_ONE(peer); - dp_info("peer: %pM is getting unmap", - peer->mac_addr.raw); + dp_info("peer: "QDF_MAC_ADDR_FMT" is getting unmap", + QDF_MAC_ADDR_REF(peer->mac_addr.raw)); /* free AST entries of peer */ dp_peer_flush_ast_entry(soc, peer, peer_ids[i], @@ -5040,27 +5665,31 @@ static void dp_vdev_flush_peers(struct cdp_vdev *vdev_handle, bool unmap_only) /* * dp_vdev_detach_wifi3() - Detach txrx vdev - * @txrx_vdev: Datapath VDEV handle - * @callback: Callback OL_IF on completion of detach + * @cdp_soc: Datapath soc handle + * @vdev_id: VDEV Id + * @callback: Callback OL_IF on completion of detach * @cb_context: Callback context * */ -static void dp_vdev_detach_wifi3(struct cdp_vdev *vdev_handle, - ol_txrx_vdev_delete_cb callback, void *cb_context) +static QDF_STATUS dp_vdev_detach_wifi3(struct cdp_soc_t *cdp_soc, + uint8_t vdev_id, + ol_txrx_vdev_delete_cb callback, + void *cb_context) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; + struct dp_soc *soc = (struct dp_soc *)cdp_soc; struct dp_pdev *pdev; - struct dp_soc *soc; struct dp_neighbour_peer *peer = NULL; struct dp_neighbour_peer *temp_peer = NULL; + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + + if (!vdev) + return QDF_STATUS_E_FAILURE; - /* preconditions */ - qdf_assert_always(vdev); pdev = vdev->pdev; - soc = pdev->soc; if (wlan_op_mode_sta == vdev->opmode) - dp_peer_delete_wifi3(vdev->vap_self_peer, 0); + dp_peer_delete_wifi3((struct cdp_soc_t *)soc, vdev->vdev_id, + vdev->vap_self_peer->mac_addr.raw, 0); /* * If Target is hung, flush all peers before detaching vdev @@ -5069,8 +5698,16 @@ static void dp_vdev_detach_wifi3(struct cdp_vdev *vdev_handle, */ if (!hif_is_target_ready(HIF_GET_SOFTC(soc->hif_handle))) dp_vdev_flush_peers((struct cdp_vdev *)vdev, false); + else if (hif_get_target_status(soc->hif_handle) == TARGET_STATUS_RESET) + dp_vdev_flush_peers((struct cdp_vdev *)vdev, true); dp_rx_vdev_detach(vdev); + /* + * move it after dp_rx_vdev_detach(), + * as the call back done in dp_rx_vdev_detach() + * still need to get vdev pointer by vdev_id. + */ + soc->vdev_id_map[vdev->vdev_id] = NULL; /* * Use peer_ref_mutex while accessing peer_list, in case * a peer is in the process of being removed from the list. @@ -5079,14 +5716,19 @@ static void dp_vdev_detach_wifi3(struct cdp_vdev *vdev_handle, /* check that the vdev has no peers allocated */ if (!TAILQ_EMPTY(&vdev->peer_list)) { /* debug print - will be removed later */ - dp_warn("not deleting vdev object %pK (%pM) until deletion finishes for all its peers", - vdev, vdev->mac_addr.raw); + dp_warn("not deleting vdev object %pK ("QDF_MAC_ADDR_FMT") until deletion finishes for all its peers", + vdev, QDF_MAC_ADDR_REF(vdev->mac_addr.raw)); + + if (vdev->vdev_dp_ext_handle) { + qdf_mem_free(vdev->vdev_dp_ext_handle); + vdev->vdev_dp_ext_handle = NULL; + } /* indicate that the vdev needs to be deleted */ vdev->delete.pending = 1; vdev->delete.callback = callback; vdev->delete.context = cb_context; qdf_spin_unlock_bh(&soc->peer_ref_mutex); - return; + return QDF_STATUS_E_FAILURE; } qdf_spin_unlock_bh(&soc->peer_ref_mutex); @@ -5124,11 +5766,20 @@ static void dp_vdev_detach_wifi3(struct cdp_vdev *vdev_handle, pdev->monitor_vdev = NULL; } - dp_info("deleting vdev object %pK (%pM)", vdev, vdev->mac_addr.raw); + if (vdev->vdev_dp_ext_handle) { + qdf_mem_free(vdev->vdev_dp_ext_handle); + vdev->vdev_dp_ext_handle = NULL; + } + + dp_info("deleting vdev object %pK ("QDF_MAC_ADDR_FMT")", vdev, + QDF_MAC_ADDR_REF(vdev->mac_addr.raw)); + qdf_mem_free(vdev); if (callback) callback(cb_context); + + return QDF_STATUS_SUCCESS; } #ifdef FEATURE_AST @@ -5144,6 +5795,7 @@ static inline void dp_peer_delete_ast_entries(struct dp_soc *soc, { struct dp_ast_entry *ast_entry, *temp_ast_entry; + dp_debug("peer: %pK, self_ast: %pK", peer, peer->self_ast_entry); DP_PEER_ITERATE_ASE_LIST(peer, ast_entry, temp_ast_entry) dp_peer_del_ast(soc, ast_entry); @@ -5227,25 +5879,26 @@ static inline void dp_peer_rx_bufq_resources_init(struct dp_peer *peer) /* * dp_peer_create_wifi3() - attach txrx peer - * @txrx_vdev: Datapath VDEV handle + * @soc_hdl: Datapath soc handle + * @vdev_id: id of vdev * @peer_mac_addr: Peer MAC address * - * Return: DP peeer handle on success, NULL on failure + * Return: 0 on success, -1 on failure */ -static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, - uint8_t *peer_mac_addr, struct cdp_ctrl_objmgr_peer *ctrl_peer) +static QDF_STATUS +dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_mac_addr) { struct dp_peer *peer; int i; - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; struct dp_pdev *pdev; - struct dp_soc *soc; struct cdp_peer_cookie peer_cookie; enum cdp_txrx_ast_entry_type ast_type = CDP_TXRX_AST_TYPE_STATIC; + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); - /* preconditions */ - qdf_assert(vdev); - qdf_assert(peer_mac_addr); + if (!vdev || !peer_mac_addr) + return QDF_STATUS_E_FAILURE; pdev = vdev->pdev; soc = pdev->soc; @@ -5279,11 +5932,12 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, * increment the count back. */ if (soc->cdp_soc.ol_ops->peer_unref_delete) { - soc->cdp_soc.ol_ops->peer_unref_delete(pdev->ctrl_pdev, + soc->cdp_soc.ol_ops->peer_unref_delete( + soc->ctrl_psoc, + pdev->pdev_id, peer->mac_addr.raw, vdev->mac_addr.raw, - vdev->opmode, peer->ctrl_peer, ctrl_peer); + vdev->opmode); } - peer->ctrl_peer = ctrl_peer; peer->valid = 1; dp_local_peer_id_alloc(pdev, peer); @@ -5294,7 +5948,7 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, DP_STATS_INIT(peer); DP_STATS_UPD(peer, rx.avg_rssi, INVALID_RSSI); - return (void *)peer; + return QDF_STATUS_SUCCESS; } else { /* * When a STA roams from RPTR AP to ROOT AP and vice versa, we @@ -5314,7 +5968,7 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, #endif if (!peer) - return NULL; /* failure */ + return QDF_STATUS_E_FAILURE; /* failure */ qdf_mem_zero(peer, sizeof(struct dp_peer)); @@ -5322,7 +5976,6 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, /* store provided params */ peer->vdev = vdev; - peer->ctrl_peer = ctrl_peer; if ((vdev->opmode == wlan_op_mode_sta) && !qdf_mem_cmp(peer_mac_addr, &vdev->mac_addr.raw[0], @@ -5337,13 +5990,13 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, qdf_mem_copy( &peer->mac_addr.raw[0], peer_mac_addr, QDF_MAC_ADDR_SIZE); - /* TODO: See of rx_opt_proc is really required */ - peer->rx_opt_proc = soc->rx_opt_proc; - /* initialize the peer_id */ for (i = 0; i < MAX_NUM_PEER_ID_PER_PEER; i++) peer->peer_ids[i] = HTT_INVALID_PEER; + /* reset the ast index to flowid table */ + dp_peer_reset_flowq_map(peer); + qdf_spin_lock_bh(&soc->peer_ref_mutex); qdf_atomic_init(&peer->ref_cnt); @@ -5365,8 +6018,8 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, /* Initialize the peer state */ peer->state = OL_TXRX_PEER_STATE_DISC; - dp_info("vdev %pK created peer %pK (%pM) ref_cnt: %d", - vdev, peer, peer->mac_addr.raw, + dp_info("vdev %pK created peer %pK ("QDF_MAC_ADDR_FMT") ref_cnt: %d", + vdev, peer, QDF_MAC_ADDR_REF(peer->mac_addr.raw), qdf_atomic_read(&peer->ref_cnt)); /* * For every peer MAp message search and set if bss_peer @@ -5396,6 +6049,7 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, qdf_mem_copy(peer_cookie.mac_addr, peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); peer_cookie.ctx = NULL; + peer_cookie.pdev_id = pdev->pdev_id; peer_cookie.cookie = pdev->next_peer_cookie++; #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE dp_wdi_event_handler(WDI_EVENT_PEER_CREATE, pdev->soc, @@ -5407,10 +6061,11 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle, pdev->next_peer_cookie--; qdf_err("Failed to initialize peer rate stats"); } else { - peer->wlanstats_ctx = (void *)peer_cookie.ctx; + peer->wlanstats_ctx = (struct cdp_peer_rate_stats_ctx *) + peer_cookie.ctx; } } - return (void *)peer; + return QDF_STATUS_SUCCESS; } /* @@ -5533,27 +6188,32 @@ static void dp_peer_setup_get_reo_hash(struct dp_vdev *vdev, /* * dp_peer_setup_wifi3() - initialize the peer - * @vdev_hdl: virtual device object - * @peer: Peer object + * @soc_hdl: soc handle object + * @vdev_id : vdev_id of vdev object + * @peer_mac: Peer's mac address * - * Return: void + * Return: QDF_STATUS */ -static void dp_peer_setup_wifi3(struct cdp_vdev *vdev_hdl, void *peer_hdl) +static QDF_STATUS +dp_peer_setup_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_mac) { - struct dp_peer *peer = (struct dp_peer *)peer_hdl; - struct dp_vdev *vdev = (struct dp_vdev *)vdev_hdl; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; struct dp_pdev *pdev; - struct dp_soc *soc; bool hash_based = 0; enum cdp_host_reo_dest_ring reo_dest; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_peer *peer = + dp_peer_find_hash_find(soc, peer_mac, 0, vdev_id); - /* preconditions */ - qdf_assert(vdev); - qdf_assert(peer); + if (!vdev || !peer || peer->delete_in_progress) { + status = QDF_STATUS_E_FAILURE; + goto fail; + } pdev = vdev->pdev; - soc = pdev->soc; - dp_peer_setup_get_reo_hash(vdev, &reo_dest, &hash_based); dp_info("pdev: %d vdev :%d opmode:%u hash-based-steering:%d default-reo_dest:%u", @@ -5568,13 +6228,17 @@ static void dp_peer_setup_wifi3(struct cdp_vdev *vdev_hdl, void *peer_hdl) * which is REO2TCL ring. for this reason we should * not setup reo_queues and default route for bss_peer. */ - if (peer->bss_peer && vdev->opmode == wlan_op_mode_ap) - return; + if (peer->bss_peer && vdev->opmode == wlan_op_mode_ap) { + status = QDF_STATUS_E_FAILURE; + goto fail; + } if (soc->cdp_soc.ol_ops->peer_set_default_routing) { /* TODO: Check the destination ring number to be passed to FW */ soc->cdp_soc.ol_ops->peer_set_default_routing( - pdev->ctrl_pdev, peer->mac_addr.raw, + soc->ctrl_psoc, + peer->vdev->pdev->pdev_id, + peer->mac_addr.raw, peer->vdev->vdev_id, hash_based, reo_dest); } @@ -5583,26 +6247,34 @@ static void dp_peer_setup_wifi3(struct cdp_vdev *vdev_hdl, void *peer_hdl) dp_peer_rx_init(pdev, peer); dp_peer_tx_init(pdev, peer); - return; + dp_peer_ppdu_delayed_ba_init(peer); + +fail: + if (peer) + dp_peer_unref_delete(peer); + return status; } /* * dp_cp_peer_del_resp_handler - Handle the peer delete response * @soc_hdl: Datapath SOC handle - * @vdev_hdl: virtual device object + * @vdev_id: id of virtual device object * @mac_addr: Mac address of the peer * - * Return: void + * Return: QDF_STATUS */ -static void dp_cp_peer_del_resp_handler(struct cdp_soc_t *soc_hdl, - struct cdp_vdev *vdev_hdl, - uint8_t *mac_addr) +static QDF_STATUS dp_cp_peer_del_resp_handler(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, + uint8_t *mac_addr) { struct dp_soc *soc = (struct dp_soc *)soc_hdl; struct dp_ast_entry *ast_entry = NULL; - struct dp_vdev *vdev = (struct dp_vdev *)vdev_hdl; txrx_ast_free_cb cb = NULL; void *cookie; + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + + if (!vdev) + return QDF_STATUS_E_FAILURE; qdf_spin_lock_bh(&soc->ast_lock); @@ -5621,7 +6293,7 @@ static void dp_cp_peer_del_resp_handler(struct cdp_soc_t *soc_hdl, */ if (!ast_entry || ast_entry->peer || !ast_entry->delete_in_progress) { qdf_spin_unlock_bh(&soc->ast_lock); - return; + return QDF_STATUS_E_FAILURE; } if (ast_entry->is_mapped) @@ -5640,39 +6312,13 @@ static void dp_cp_peer_del_resp_handler(struct cdp_soc_t *soc_hdl, if (cb) { cb(soc->ctrl_psoc, - soc, + dp_soc_to_cdp_soc(soc), cookie, CDP_TXRX_AST_DELETED); } qdf_mem_free(ast_entry); -} - -/* - * dp_set_vdev_tx_encap_type() - set the encap type of the vdev - * @vdev_handle: virtual device object - * @htt_pkt_type: type of pkt - * - * Return: void - */ -static void dp_set_vdev_tx_encap_type(struct cdp_vdev *vdev_handle, - enum htt_cmn_pkt_type val) -{ - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - vdev->tx_encap_type = val; -} -/* - * dp_set_vdev_rx_decap_type() - set the decap type of the vdev - * @vdev_handle: virtual device object - * @htt_pkt_type: type of pkt - * - * Return: void - */ -static void dp_set_vdev_rx_decap_type(struct cdp_vdev *vdev_handle, - enum htt_cmn_pkt_type val) -{ - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - vdev->rx_decap_type = val; + return QDF_STATUS_SUCCESS; } /* @@ -5709,30 +6355,41 @@ static void dp_get_ba_aging_timeout(struct cdp_soc_t *txrx_soc, /* * dp_set_pdev_reo_dest() - set the reo destination ring for this pdev - * @pdev_handle: physical device object + * @txrx_soc: cdp soc handle + * @pdev_id: id of physical device object * @val: reo destination ring index (1 - 4) * - * Return: void + * Return: QDF_STATUS */ -static void dp_set_pdev_reo_dest(struct cdp_pdev *pdev_handle, - enum cdp_host_reo_dest_ring val) +static QDF_STATUS +dp_set_pdev_reo_dest(struct cdp_soc_t *txrx_soc, uint8_t pdev_id, + enum cdp_host_reo_dest_ring val) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)txrx_soc, + pdev_id); - if (pdev) + if (pdev) { pdev->reo_dest = val; + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; } /* * dp_get_pdev_reo_dest() - get the reo destination for this pdev - * @pdev_handle: physical device object + * @txrx_soc: cdp soc handle + * @pdev_id: id of physical device object * * Return: reo destination ring index */ static enum cdp_host_reo_dest_ring -dp_get_pdev_reo_dest(struct cdp_pdev *pdev_handle) +dp_get_pdev_reo_dest(struct cdp_soc_t *txrx_soc, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)txrx_soc, + pdev_id); if (pdev) return pdev->reo_dest; @@ -5740,42 +6397,58 @@ dp_get_pdev_reo_dest(struct cdp_pdev *pdev_handle) return cdp_host_reo_dest_ring_unknown; } +#ifdef ATH_SUPPORT_NAC /* - * dp_set_filter_neighbour_peers() - set filter neighbour peers for smart mesh + * dp_set_filter_neigh_peers() - set filter neighbour peers for smart mesh * @pdev_handle: device object * @val: value to be set * * Return: void */ -static int dp_set_filter_neighbour_peers(struct cdp_pdev *pdev_handle, - uint32_t val) +static int dp_set_filter_neigh_peers(struct dp_pdev *pdev, + bool val) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - /* Enable/Disable smart mesh filtering. This flag will be checked * during rx processing to check if packets are from NAC clients. */ pdev->filter_neighbour_peers = val; return 0; } +#else +static int dp_set_filter_neigh_peers(struct dp_pdev *pdev, + bool val) +{ + return 0; +} +#endif /* ATH_SUPPORT_NAC */ +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) /* * dp_update_filter_neighbour_peers() - set neighbour peers(nac clients) * address for smart mesh filtering - * @vdev_handle: virtual device object + * @txrx_soc: cdp soc handle + * @vdev_id: id of virtual device object * @cmd: Add/Del command * @macaddr: nac client mac address * - * Return: void + * Return: success/failure */ -static int dp_update_filter_neighbour_peers(struct cdp_vdev *vdev_handle, +static int dp_update_filter_neighbour_peers(struct cdp_soc_t *soc, + uint8_t vdev_id, uint32_t cmd, uint8_t *macaddr) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - struct dp_pdev *pdev = vdev->pdev; + struct dp_pdev *pdev; struct dp_neighbour_peer *peer = NULL; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); - if (!macaddr) + if (!vdev || !macaddr) + goto fail0; + + pdev = vdev->pdev; + + if (!pdev) goto fail0; /* Store address of NAC (neighbour peer) which will be checked @@ -5804,8 +6477,18 @@ static int dp_update_filter_neighbour_peers(struct cdp_vdev *vdev_handle, /* first neighbour */ if (!pdev->neighbour_peers_added) { + QDF_STATUS status = QDF_STATUS_SUCCESS; + pdev->neighbour_peers_added = true; - dp_ppdu_ring_cfg(pdev); + dp_mon_filter_setup_smart_monitor(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("smart mon filter setup failed")); + dp_mon_filter_reset_smart_monitor(pdev); + pdev->neighbour_peers_added = false; + } } return 1; @@ -5824,15 +6507,20 @@ static int dp_update_filter_neighbour_peers(struct cdp_vdev *vdev_handle, } /* last neighbour deleted */ if (TAILQ_EMPTY(&pdev->neighbour_peers_list)) { + QDF_STATUS status = QDF_STATUS_SUCCESS; + pdev->neighbour_peers_added = false; - dp_ppdu_ring_cfg(pdev); + dp_mon_filter_reset_smart_monitor(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("smart mon filter clear failed")); + } + } qdf_spin_unlock_bh(&pdev->neighbour_peer_mutex); - - if (!pdev->mcopy_mode && !pdev->neighbour_peers_added && - !pdev->enhanced_stats_en) - dp_ppdu_ring_reset(pdev); return 1; } @@ -5840,38 +6528,69 @@ static int dp_update_filter_neighbour_peers(struct cdp_vdev *vdev_handle, fail0: return 0; } +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ /* * dp_get_sec_type() - Get the security type - * @peer: Datapath peer handle + * @soc: soc handle + * @vdev_id: id of dp handle + * @peer_mac: mac of datapath PEER handle * @sec_idx: Security id (mcast, ucast) * * return sec_type: Security type */ -static int dp_get_sec_type(struct cdp_peer *peer, uint8_t sec_idx) +static int dp_get_sec_type(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, uint8_t sec_idx) { - struct dp_peer *dpeer = (struct dp_peer *)peer; + int sec_type = 0; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc, + peer_mac, 0, vdev_id); - return dpeer->security[sec_idx].sec_type; + if (!peer || peer->delete_in_progress) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s: Peer is NULL!\n", __func__); + goto fail; + } + + sec_type = peer->security[sec_idx].sec_type; +fail: + if (peer) + dp_peer_unref_delete(peer); + return sec_type; } /* * dp_peer_authorize() - authorize txrx peer - * @peer_handle: Datapath peer handle + * @soc: soc handle + * @vdev_id: id of dp handle + * @peer_mac: mac of datapath PEER handle * @authorize * */ -static void dp_peer_authorize(struct cdp_peer *peer_handle, uint32_t authorize) +static QDF_STATUS +dp_peer_authorize(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_mac, uint32_t authorize) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; - struct dp_soc *soc; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_peer *peer = dp_peer_find_hash_find(soc, + peer_mac, + 0, vdev_id); - if (peer) { - soc = peer->vdev->pdev->soc; + if (!peer || peer->delete_in_progress) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s: Peer is NULL!\n", __func__); + status = QDF_STATUS_E_FAILURE; + } else { qdf_spin_lock_bh(&soc->peer_ref_mutex); peer->authorize = authorize ? 1 : 0; qdf_spin_unlock_bh(&soc->peer_ref_mutex); } + + if (peer) + dp_peer_unref_delete(peer); + + return status; } /* @@ -5921,10 +6640,10 @@ static void dp_peer_release_mem(struct dp_soc *soc, { if (soc->cdp_soc.ol_ops->peer_unref_delete) soc->cdp_soc.ol_ops->peer_unref_delete( - pdev->ctrl_pdev, + soc->ctrl_psoc, + pdev->pdev_id, peer->mac_addr.raw, vdev_mac_addr, - vdev_opmode, peer->ctrl_peer, - NULL); + vdev_opmode); /* * Peer AST list hast to be empty here @@ -5954,13 +6673,15 @@ static void dp_delete_pending_vdev(struct dp_pdev *pdev, struct dp_vdev *vdev, vdev_delete_cb = vdev->delete.callback; vdev_delete_context = vdev->delete.context; - dp_info("deleting vdev object %pK (%pM)- its last peer is done", - vdev, vdev->mac_addr.raw); + dp_info("deleting vdev object %pK ("QDF_MAC_ADDR_FMT")- its last peer is done", + vdev, QDF_MAC_ADDR_REF(vdev->mac_addr.raw)); /* all peers are gone, go ahead and delete it */ dp_tx_flow_pool_unmap_handler(pdev, vdev_id, FLOW_TYPE_VDEV, vdev_id); dp_tx_vdev_detach(vdev); + pdev->soc->vdev_id_map[vdev_id] = NULL; + if (wlan_op_mode_monitor == vdev->opmode) { pdev->monitor_vdev = NULL; } else { @@ -5969,8 +6690,8 @@ static void dp_delete_pending_vdev(struct dp_pdev *pdev, struct dp_vdev *vdev, qdf_spin_unlock_bh(&pdev->vdev_list_lock); } - dp_info("deleting vdev object %pK (%pM)", - vdev, vdev->mac_addr.raw); + dp_info("deleting vdev object %pK ("QDF_MAC_ADDR_FMT")", + vdev, QDF_MAC_ADDR_REF(vdev->mac_addr.raw)); qdf_mem_free(vdev); vdev = NULL; @@ -5983,9 +6704,8 @@ static void dp_delete_pending_vdev(struct dp_pdev *pdev, struct dp_vdev *vdev, * @peer_handle: Datapath peer handle * */ -void dp_peer_unref_delete(void *peer_handle) +void dp_peer_unref_delete(struct dp_peer *peer) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; struct dp_vdev *vdev = peer->vdev; struct dp_pdev *pdev = vdev->pdev; struct dp_soc *soc = pdev->soc; @@ -5998,7 +6718,6 @@ void dp_peer_unref_delete(void *peer_handle) enum wlan_op_mode vdev_opmode; uint8_t vdev_mac_addr[QDF_MAC_ADDR_SIZE]; - /* * Hold the lock all the way from checking if the peer ref count * is zero until the peer references are removed from the hash @@ -6022,7 +6741,8 @@ void dp_peer_unref_delete(void *peer_handle) soc->peer_id_to_obj_map[peer_id] = NULL; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "Deleting peer %pK (%pM)", peer, peer->mac_addr.raw); + "Deleting peer %pK ("QDF_MAC_ADDR_FMT")", peer, + QDF_MAC_ADDR_REF(peer->mac_addr.raw)); /* remove the reference to the peer from the hash table */ dp_peer_find_hash_remove(soc, peer); @@ -6030,7 +6750,6 @@ void dp_peer_unref_delete(void *peer_handle) qdf_spin_lock_bh(&soc->ast_lock); if (peer->self_ast_entry) { dp_peer_del_ast(soc, peer->self_ast_entry); - peer->self_ast_entry = NULL; } qdf_spin_unlock_bh(&soc->ast_lock); @@ -6055,7 +6774,8 @@ void dp_peer_unref_delete(void *peer_handle) qdf_mem_copy(peer_cookie.mac_addr, peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); peer_cookie.ctx = NULL; - peer_cookie.ctx = (void *)peer->wlanstats_ctx; + peer_cookie.ctx = (struct cdp_stats_cookie *) + peer->wlanstats_ctx; #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE dp_wdi_event_handler(WDI_EVENT_PEER_DESTROY, pdev->soc, @@ -6119,39 +6839,39 @@ static inline void dp_peer_rx_bufq_resources_deinit(struct dp_peer *peer) /* * dp_peer_detach_wifi3() – Detach txrx peer - * @peer_handle: Datapath peer handle + * @soc_hdl: soc handle + * @vdev_id: id of dp handle + * @peer_mac: mac of datapath PEER handle * @bitmap: bitmap indicating special handling of request. * */ -static void dp_peer_delete_wifi3(void *peer_handle, uint32_t bitmap) +static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, + uint8_t *peer_mac, uint32_t bitmap) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; - struct dp_soc *soc = peer->vdev->pdev->soc; - - /* redirect the peer's rx delivery function to point to a - * discard func - */ - - peer->rx_opt_proc = dp_rx_discard; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_peer *peer = dp_peer_find_hash_find(soc, peer_mac, + 0, vdev_id); - /* Do not make ctrl_peer to NULL for connected sta peers. - * We need ctrl_peer to release the reference during dp - * peer free. This reference was held for - * obj_mgr peer during the creation of dp peer. - */ - if (!(peer->vdev && (peer->vdev->opmode != wlan_op_mode_sta) && - !peer->bss_peer)) - peer->ctrl_peer = NULL; + /* Peer can be null for monitor vap mac address */ + if (!peer) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid peer\n", __func__); + return QDF_STATUS_E_FAILURE; + } if (!peer->valid) { - dp_err("Invalid peer: %pM", peer->mac_addr.raw); - return; + dp_peer_unref_delete(peer); + dp_err("Invalid peer: "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(peer_mac)); + return QDF_STATUS_E_ALREADY; } peer->valid = 0; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, - FL("peer %pK (%pM)"), peer, peer->mac_addr.raw); + FL("peer %pK ("QDF_MAC_ADDR_FMT")"), peer, + QDF_MAC_ADDR_REF(peer->mac_addr.raw)); dp_local_peer_id_free(peer->vdev->pdev, peer); @@ -6161,6 +6881,7 @@ static void dp_peer_delete_wifi3(void *peer_handle, uint32_t bitmap) dp_peer_rx_bufq_resources_deinit(peer); qdf_spinlock_destroy(&peer->peer_info_lock); + dp_peer_multipass_list_remove(peer); /* * Remove the reference added during peer_attach. @@ -6168,103 +6889,132 @@ static void dp_peer_delete_wifi3(void *peer_handle, uint32_t bitmap) * PEER_UNMAP message arrives to remove the other * reference, added by the PEER_MAP message. */ - dp_peer_unref_delete(peer_handle); + dp_peer_unref_delete(peer); + /* + * Remove the reference taken above + */ + dp_peer_unref_delete(peer); + + return QDF_STATUS_SUCCESS; } /* * dp_get_vdev_mac_addr_wifi3() – Detach txrx peer - * @peer_handle: Datapath peer handle + * @soc_hdl: Datapath soc handle + * @vdev_id: virtual interface id + * + * Return: MAC address on success, NULL on failure. * */ -static uint8 *dp_get_vdev_mac_addr_wifi3(struct cdp_vdev *pvdev) +static uint8 *dp_get_vdev_mac_addr_wifi3(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id) { - struct dp_vdev *vdev = (struct dp_vdev *)pvdev; - return vdev->mac_addr.raw; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + + if (!vdev) + return NULL; + + return vdev->mac_addr.raw; } /* * dp_vdev_set_wds() - Enable per packet stats - * @vdev_handle: DP VDEV handle + * @soc: DP soc handle + * @vdev_id: id of DP VDEV handle * @val: value * * Return: none */ -static int dp_vdev_set_wds(void *vdev_handle, uint32_t val) +static int dp_vdev_set_wds(struct cdp_soc_t *soc, uint8_t vdev_id, uint32_t val) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + + if (!vdev) + return QDF_STATUS_E_FAILURE; vdev->wds_enabled = val; - return 0; + return QDF_STATUS_SUCCESS; } /* - * dp_get_vdev_from_vdev_id_wifi3() – Detach txrx peer - * @peer_handle: Datapath peer handle + * dp_get_mon_vdev_from_pdev_wifi3() - Get vdev id of monitor mode + * @soc_hdl: datapath soc handle + * @pdev_id: physical device instance id * + * Return: virtual interface id */ -static struct cdp_vdev *dp_get_vdev_from_vdev_id_wifi3(struct cdp_pdev *dev, - uint8_t vdev_id) +static uint8_t dp_get_mon_vdev_from_pdev_wifi3(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)dev; - struct dp_vdev *vdev = NULL; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); if (qdf_unlikely(!pdev)) - return NULL; + return -EINVAL; - qdf_spin_lock_bh(&pdev->vdev_list_lock); - TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { - if (vdev->delete.pending) - continue; - - if (vdev->vdev_id == vdev_id) - break; - } - qdf_spin_unlock_bh(&pdev->vdev_list_lock); - - return (struct cdp_vdev *)vdev; + return pdev->monitor_vdev->vdev_id; } -/* - * dp_get_mon_vdev_from_pdev_wifi3() - Get vdev handle of monitor mode - * @dev: PDEV handle - * - * Return: VDEV handle of monitor mode - */ - -static struct cdp_vdev *dp_get_mon_vdev_from_pdev_wifi3(struct cdp_pdev *dev) +static int dp_get_opmode(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)dev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); - if (qdf_unlikely(!pdev)) - return NULL; - - return (struct cdp_vdev *)pdev->monitor_vdev; -} - -static int dp_get_opmode(struct cdp_vdev *vdev_handle) -{ - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; + if (!vdev) { + dp_err("vdev for id %d is NULL", vdev_id); + return -EINVAL; + } return vdev->opmode; } +/** + * dp_get_os_rx_handles_from_vdev_wifi3() - Get os rx handles for a vdev + * @soc_hdl: ol_txrx_soc_handle handle + * @vdev_id: vdev id for which os rx handles are needed + * @stack_fn_p: pointer to stack function pointer + * @osif_handle_p: pointer to ol_osif_vdev_handle + * + * Return: void + */ static -void dp_get_os_rx_handles_from_vdev_wifi3(struct cdp_vdev *pvdev, +void dp_get_os_rx_handles_from_vdev_wifi3(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, ol_txrx_rx_fp *stack_fn_p, ol_osif_vdev_handle *osif_vdev_p) { - struct dp_vdev *vdev = dp_get_dp_vdev_from_cdp_vdev(pvdev); + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + + if (!vdev) + return; - qdf_assert(vdev); *stack_fn_p = vdev->osif_rx_stack; *osif_vdev_p = vdev->osif_vdev; } -static struct cdp_cfg *dp_get_ctrl_pdev_from_vdev_wifi3(struct cdp_vdev *pvdev) +/** + * dp_get_ctrl_pdev_from_vdev() - Get control pdev of vdev + * @soc_hdl: datapath soc handle + * @vdev_id: virtual device/interface id + * + * Return: Handle to control pdev + */ +static struct cdp_cfg *dp_get_ctrl_pdev_from_vdev_wifi3( + struct cdp_soc_t *soc_hdl, + uint8_t vdev_id) { - struct dp_vdev *vdev = (struct dp_vdev *)pvdev; - struct dp_pdev *pdev = vdev->pdev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_pdev *pdev; + if (!vdev || !vdev->pdev) + return NULL; + + pdev = vdev->pdev; return (struct cdp_cfg *)pdev->wlan_cfg_ctx; } @@ -6272,7 +7022,7 @@ static struct cdp_cfg *dp_get_ctrl_pdev_from_vdev_wifi3(struct cdp_vdev *pvdev) * dp_monitor_mode_ring_config() - Send the tlv config to fw for monitor buffer * ring based on target * @soc: soc handle - * @mac_for_pdev: pdev_id + * @mac_for_pdev: WIN- pdev_id, MCL- mac id * @pdev: physical device handle * @ring_num: mac id * @htt_tlv_filter: tlv filter @@ -6288,90 +7038,89 @@ QDF_STATUS dp_monitor_mode_ring_config(struct dp_soc *soc, uint8_t mac_for_pdev, if (soc->wlan_cfg_ctx->rxdma1_enable) status = htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_buf_ring[ring_num] + soc->rxdma_mon_buf_ring[ring_num] .hal_srng, - RXDMA_MONITOR_BUF, RX_BUFFER_SIZE, + RXDMA_MONITOR_BUF, + RX_MONITOR_BUFFER_SIZE, &htt_tlv_filter); else status = htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, pdev->rx_mac_buf_ring[ring_num] .hal_srng, - RXDMA_BUF, RX_BUFFER_SIZE, + RXDMA_BUF, RX_DATA_BUFFER_SIZE, &htt_tlv_filter); return status; } +static inline void +dp_pdev_disable_mcopy_code(struct dp_pdev *pdev) +{ + pdev->mcopy_mode = 0; + pdev->monitor_configured = false; + pdev->monitor_vdev = NULL; + qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q); +} + /** * dp_reset_monitor_mode() - Disable monitor mode - * @pdev_handle: Datapath PDEV handle + * @soc_hdl: Datapath soc handle + * @pdev_id: id of datapath PDEV handle * * Return: QDF_STATUS */ -QDF_STATUS dp_reset_monitor_mode(struct cdp_pdev *pdev_handle) +QDF_STATUS dp_reset_monitor_mode(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + uint8_t special_monitor) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - struct htt_rx_ring_tlv_filter htt_tlv_filter; - struct dp_soc *soc = pdev->soc; - uint8_t pdev_id; - int mac_id; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); QDF_STATUS status = QDF_STATUS_SUCCESS; - pdev_id = pdev->pdev_id; - soc = pdev->soc; + if (!pdev) + return QDF_STATUS_E_FAILURE; qdf_spin_lock_bh(&pdev->mon_lock); - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); - - status = dp_monitor_mode_ring_config(soc, mac_for_pdev, - pdev, mac_id, - htt_tlv_filter); - - if (status != QDF_STATUS_SUCCESS) { - dp_err("Failed to send tlv filter for monitor mode rings"); - qdf_spin_unlock_bh(&pdev->mon_lock); - return status; - } + pdev->monitor_vdev = NULL; + pdev->monitor_configured = false; - htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id].hal_srng, - RXDMA_MONITOR_STATUS, RX_BUFFER_SIZE, - &htt_tlv_filter); + /* + * Lite monitor mode, smart monitor mode and monitor + * mode uses this APIs to filter reset and mode disable + */ + if (pdev->mcopy_mode) { +#if defined(FEATURE_PERPKT_INFO) + dp_pdev_disable_mcopy_code(pdev); + dp_mon_filter_reset_mcopy_mode(pdev); +#endif /* FEATURE_PERPKT_INFO */ + } else if (special_monitor) { +#if defined(ATH_SUPPORT_NAC) + dp_mon_filter_reset_smart_monitor(pdev); +#endif /* ATH_SUPPORT_NAC */ + } else { + dp_mon_filter_reset_mon_mode(pdev); } - pdev->monitor_vdev = NULL; - pdev->mcopy_mode = 0; - pdev->monitor_configured = false; + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to reset monitor filters")); + } qdf_spin_unlock_bh(&pdev->mon_lock); - return QDF_STATUS_SUCCESS; } -/** - * dp_set_nac() - set peer_nac - * @peer_handle: Datapath PEER handle - * - * Return: void - */ -static void dp_set_nac(struct cdp_peer *peer_handle) -{ - struct dp_peer *peer = (struct dp_peer *)peer_handle; - - peer->nac = 1; -} - /** * dp_get_tx_pending() - read pending tx * @pdev_handle: Datapath PDEV handle * * Return: outstanding tx */ -static int dp_get_tx_pending(struct cdp_pdev *pdev_handle) +static uint32_t dp_get_tx_pending(struct cdp_pdev *pdev_handle) { struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; @@ -6384,172 +7133,26 @@ static int dp_get_tx_pending(struct cdp_pdev *pdev_handle) * @peer_id: Peer ID * @peer_mac: MAC addr of PEER * - * Return: void + * Return: QDF_STATUS */ -static void dp_get_peer_mac_from_peer_id(struct cdp_pdev *pdev_handle, - uint32_t peer_id, uint8_t *peer_mac) +static QDF_STATUS dp_get_peer_mac_from_peer_id(struct cdp_soc_t *soc, + uint32_t peer_id, + uint8_t *peer_mac) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; struct dp_peer *peer; - if (pdev && peer_mac) { - peer = dp_peer_find_by_id(pdev->soc, (uint16_t)peer_id); + if (soc && peer_mac) { + peer = dp_peer_find_by_id((struct dp_soc *)soc, + (uint16_t)peer_id); if (peer) { qdf_mem_copy(peer_mac, peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); dp_peer_unref_del_find_by_id(peer); + return QDF_STATUS_SUCCESS; } } -} - -/** - * dp_pdev_configure_monitor_rings() - configure monitor rings - * @vdev_handle: Datapath VDEV handle - * - * Return: QDF_STATUS - */ -QDF_STATUS dp_pdev_configure_monitor_rings(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; - - pdev_id = pdev->pdev_id; - soc = pdev->soc; - - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, - "MODE[%x] FP[%02x|%02x|%02x] MO[%02x|%02x|%02x]", - pdev->mon_filter_mode, pdev->fp_mgmt_filter, - pdev->fp_ctrl_filter, pdev->fp_data_filter, - pdev->mo_mgmt_filter, pdev->mo_ctrl_filter, - pdev->mo_data_filter); - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - htt_tlv_filter.mpdu_start = 1; - htt_tlv_filter.msdu_start = 1; - htt_tlv_filter.packet = 1; - htt_tlv_filter.msdu_end = 1; - htt_tlv_filter.mpdu_end = 1; - htt_tlv_filter.packet_header = 1; - htt_tlv_filter.attention = 1; - htt_tlv_filter.ppdu_start = 0; - htt_tlv_filter.ppdu_end = 0; - htt_tlv_filter.ppdu_end_user_stats = 0; - htt_tlv_filter.ppdu_end_user_stats_ext = 0; - htt_tlv_filter.ppdu_end_status_done = 0; - htt_tlv_filter.header_per_msdu = 1; - htt_tlv_filter.enable_fp = - (pdev->mon_filter_mode & MON_FILTER_PASS) ? 1 : 0; - htt_tlv_filter.enable_md = 0; - htt_tlv_filter.enable_mo = - (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; - - if (pdev->mcopy_mode) { - htt_tlv_filter.fp_data_filter = 0; - htt_tlv_filter.mo_data_filter = 0; - } else { - htt_tlv_filter.fp_data_filter = pdev->fp_data_filter; - htt_tlv_filter.mo_data_filter = pdev->mo_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.offset_valid = false; - - if ((pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU) || - (pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU_MSDU)) { - htt_tlv_filter.fp_mgmt_filter = 0; - htt_tlv_filter.fp_ctrl_filter = 0; - htt_tlv_filter.fp_data_filter = 0; - htt_tlv_filter.mo_mgmt_filter = 0; - htt_tlv_filter.mo_ctrl_filter = 0; - htt_tlv_filter.mo_data_filter = 0; - } - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); - - status = dp_monitor_mode_ring_config(soc, mac_for_pdev, - pdev, mac_id, - htt_tlv_filter); - - if (status != QDF_STATUS_SUCCESS) { - dp_err("Failed to send tlv filter for monitor mode rings"); - return status; - } - } - - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - htt_tlv_filter.mpdu_start = 1; - htt_tlv_filter.msdu_start = 0; - htt_tlv_filter.packet = 0; - htt_tlv_filter.msdu_end = 0; - htt_tlv_filter.mpdu_end = 0; - if ((pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU) || - (pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU_MSDU)) { - htt_tlv_filter.mpdu_end = 1; - } - htt_tlv_filter.attention = 0; - htt_tlv_filter.ppdu_start = 1; - htt_tlv_filter.ppdu_end = 1; - htt_tlv_filter.ppdu_end_user_stats = 1; - htt_tlv_filter.ppdu_end_user_stats_ext = 1; - htt_tlv_filter.ppdu_end_status_done = 1; - htt_tlv_filter.enable_fp = 1; - htt_tlv_filter.enable_md = 0; - htt_tlv_filter.enable_mo = 1; - if (pdev->mcopy_mode || - (pdev->rx_enh_capture_mode != CDP_RX_ENH_CAPTURE_DISABLED)) { - htt_tlv_filter.packet_header = 1; - if (pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU) { - htt_tlv_filter.header_per_msdu = 0; - htt_tlv_filter.enable_mo = 0; - } else if (pdev->rx_enh_capture_mode == - CDP_RX_ENH_CAPTURE_MPDU_MSDU) { - htt_tlv_filter.header_per_msdu = 1; - htt_tlv_filter.enable_mo = 0; - if (pdev->is_rx_protocol_tagging_enabled || - pdev->is_rx_enh_capture_trailer_enabled) - htt_tlv_filter.msdu_end = 1; - } - } - - htt_tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.fp_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.mo_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); - /* - * If two back to back HTT msg sending happened in - * short time, the second HTT msg source SRNG HP - * writing has chance to fail, this has been confirmed - * by HST HW. - * for monitor mode, here is the last HTT msg for sending. - * if the 2nd HTT msg for monitor status ring sending failed, - * HW won't provide anything into 2nd monitor status ring. - * as a WAR, add some delay before 2nd HTT msg start sending, - * > 2us is required per HST HW, delay 100 us for safe. - */ - if (mac_id) - qdf_udelay(100); - - htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id].hal_srng, - RXDMA_MONITOR_STATUS, RX_BUFFER_SIZE, &htt_tlv_filter); - } - - return status; + return QDF_STATUS_E_FAILURE; } /** @@ -6559,13 +7162,18 @@ QDF_STATUS dp_pdev_configure_monitor_rings(struct dp_pdev *pdev) * * Return: 0 on success, not 0 on failure */ -static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_vdev *vdev_handle, +static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_soc_t *soc, + uint8_t vdev_id, uint8_t special_monitor) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; struct dp_pdev *pdev; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + QDF_STATUS status = QDF_STATUS_SUCCESS; - qdf_assert(vdev); + if (!vdev) + return QDF_STATUS_E_FAILURE; pdev = vdev->pdev; pdev->monitor_vdev = vdev; @@ -6585,40 +7193,55 @@ static QDF_STATUS dp_vdev_set_monitor_mode(struct cdp_vdev *vdev_handle, /*Check if current pdev's monitor_vdev exists */ if (pdev->monitor_configured) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "monitor vap already created vdev=%pK\n", vdev); - qdf_assert(vdev); return QDF_STATUS_E_RESOURCES; } pdev->monitor_configured = true; + dp_mon_buf_delayed_replenish(pdev); + + dp_mon_filter_setup_mon_mode(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to reset monitor filters")); + dp_mon_filter_reset_mon_mode(pdev); + pdev->monitor_configured = false; + pdev->monitor_vdev = NULL; + } - return dp_pdev_configure_monitor_rings(pdev); + return status; } /** * dp_pdev_set_advance_monitor_filter() - Set DP PDEV monitor filter - * @pdev_handle: Datapath PDEV handle + * @soc: soc handle + * @pdev_id: id of Datapath PDEV handle * @filter_val: Flag to select Filter for monitor mode * Return: 0 on success, not 0 on failure */ static QDF_STATUS -dp_pdev_set_advance_monitor_filter(struct cdp_pdev *pdev_handle, +dp_pdev_set_advance_monitor_filter(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, struct cdp_monitor_filter *filter_val) { /* Many monitor VAPs can exists in a system but only one can be up at * anytime */ - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - struct dp_vdev *vdev = pdev->monitor_vdev; - struct htt_rx_ring_tlv_filter htt_tlv_filter; - struct dp_soc *soc; - uint8_t pdev_id; - int mac_id; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_vdev *vdev; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); QDF_STATUS status = QDF_STATUS_SUCCESS; - pdev_id = pdev->pdev_id; - soc = pdev->soc; + if (!pdev) + return QDF_STATUS_E_FAILURE; + + vdev = pdev->monitor_vdev; + + if (!vdev) + return QDF_STATUS_E_FAILURE; QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_WARN, "pdev=%pK, pdev_id=%d, soc=%pK vdev=%pK", @@ -6640,182 +7263,58 @@ dp_pdev_set_advance_monitor_filter(struct cdp_pdev *pdev_handle, pdev->mo_ctrl_filter = filter_val->mo_ctrl; pdev->mo_data_filter = filter_val->mo_data; - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, - "MODE[%x] FP[%02x|%02x|%02x] MO[%02x|%02x|%02x]", - pdev->mon_filter_mode, pdev->fp_mgmt_filter, - pdev->fp_ctrl_filter, pdev->fp_data_filter, - pdev->mo_mgmt_filter, pdev->mo_ctrl_filter, - pdev->mo_data_filter); - - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); - - status = dp_monitor_mode_ring_config(soc, mac_for_pdev, - pdev, mac_id, - htt_tlv_filter); - - if (status != QDF_STATUS_SUCCESS) { - dp_err("Failed to send tlv filter for monitor mode rings"); - return status; - } - - htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id].hal_srng, - RXDMA_MONITOR_STATUS, RX_BUFFER_SIZE, &htt_tlv_filter); - } - - htt_tlv_filter.mpdu_start = 1; - htt_tlv_filter.msdu_start = 1; - htt_tlv_filter.packet = 1; - htt_tlv_filter.msdu_end = 1; - htt_tlv_filter.mpdu_end = 1; - htt_tlv_filter.packet_header = 1; - htt_tlv_filter.attention = 1; - htt_tlv_filter.ppdu_start = 0; - htt_tlv_filter.ppdu_end = 0; - htt_tlv_filter.ppdu_end_user_stats = 0; - htt_tlv_filter.ppdu_end_user_stats_ext = 0; - htt_tlv_filter.ppdu_end_status_done = 0; - htt_tlv_filter.header_per_msdu = 1; - htt_tlv_filter.enable_fp = - (pdev->mon_filter_mode & MON_FILTER_PASS) ? 1 : 0; - htt_tlv_filter.enable_md = 0; - htt_tlv_filter.enable_mo = - (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; - 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; - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); - - status = dp_monitor_mode_ring_config(soc, mac_for_pdev, - pdev, mac_id, - htt_tlv_filter); - - if (status != QDF_STATUS_SUCCESS) { - dp_err("Failed to send tlv filter for monitor mode rings"); - return status; - } - } - - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - htt_tlv_filter.mpdu_start = 1; - htt_tlv_filter.msdu_start = 0; - htt_tlv_filter.packet = 0; - htt_tlv_filter.msdu_end = 0; - htt_tlv_filter.mpdu_end = 0; - htt_tlv_filter.attention = 0; - htt_tlv_filter.ppdu_start = 1; - htt_tlv_filter.ppdu_end = 1; - htt_tlv_filter.ppdu_end_user_stats = 1; - htt_tlv_filter.ppdu_end_user_stats_ext = 1; - htt_tlv_filter.ppdu_end_status_done = 1; - htt_tlv_filter.enable_fp = 1; - htt_tlv_filter.enable_md = 0; - htt_tlv_filter.enable_mo = 1; - if (pdev->mcopy_mode) { - htt_tlv_filter.packet_header = 1; - } - htt_tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.fp_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.mo_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); - - htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id].hal_srng, - RXDMA_MONITOR_STATUS, RX_BUFFER_SIZE, &htt_tlv_filter); + dp_mon_filter_setup_mon_mode(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to set filter for advance mon mode")); + dp_mon_filter_reset_mon_mode(pdev); } - return QDF_STATUS_SUCCESS; + return status; } /** - * dp_pdev_set_monitor_channel() - set monitor channel num in pdev - * @pdev_handle: Datapath PDEV handle - * - * Return: None + * dp_deliver_tx_mgmt() - Deliver mgmt frame for tx capture + * @cdp_soc : data path soc handle + * @pdev_id : pdev_id + * @nbuf: Management frame buffer */ -static -void dp_pdev_set_monitor_channel(struct cdp_pdev *pdev_handle, int chan_num) +static QDF_STATUS +dp_deliver_tx_mgmt(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, qdf_nbuf_t nbuf) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - - pdev->mon_chan_num = chan_num; -} + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)cdp_soc, + pdev_id); -/** - * dp_get_pdev_id_frm_pdev() - get pdev_id - * @pdev_handle: Datapath PDEV handle - * - * Return: pdev_id - */ -static -uint8_t dp_get_pdev_id_frm_pdev(struct cdp_pdev *pdev_handle) -{ - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + if (!pdev) + return QDF_STATUS_E_FAILURE; - return pdev->pdev_id; -} + dp_deliver_mgmt_frm(pdev, nbuf); -/** - * dp_get_delay_stats_flag() - get delay stats flag - * @pdev_handle: Datapath PDEV handle - * - * Return: 0 if flag is disabled else 1 - */ -static -bool dp_get_delay_stats_flag(struct cdp_pdev *pdev_handle) -{ - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - - return pdev->delay_stats_flag; + return QDF_STATUS_SUCCESS; } /** - * dp_pdev_set_chan_noise_floor() - set channel noise floor - * @pdev_handle: Datapath PDEV handle - * @chan_noise_floor: Channel Noise Floor - * - * Return: void + * dp_set_bsscolor() - sets bsscolor for tx capture + * @pdev: Datapath PDEV handle + * @bsscolor: new bsscolor */ -static -void dp_pdev_set_chan_noise_floor(struct cdp_pdev *pdev_handle, - int16_t chan_noise_floor) +static void +dp_mon_set_bsscolor(struct dp_pdev *pdev, uint8_t bsscolor) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - - pdev->chan_noise_floor = chan_noise_floor; + pdev->rx_mon_recv_status.bsscolor = bsscolor; } /** - * dp_vdev_get_filter_ucast_data() - get DP VDEV monitor ucast filter - * @vdev_handle: Datapath VDEV handle + * dp_pdev_get_filter_ucast_data() - get DP PDEV monitor ucast filter + * @soc : data path soc handle + * @pdev_id : pdev_id * Return: true on ucast filter flag set */ -static bool dp_vdev_get_filter_ucast_data(struct cdp_vdev *vdev_handle) +static bool dp_pdev_get_filter_ucast_data(struct cdp_pdev *pdev_handle) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - struct dp_pdev *pdev; - - pdev = vdev->pdev; + struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; if ((pdev->fp_data_filter & FILTER_DATA_UCAST) || (pdev->mo_data_filter & FILTER_DATA_UCAST)) @@ -6825,16 +7324,13 @@ static bool dp_vdev_get_filter_ucast_data(struct cdp_vdev *vdev_handle) } /** - * dp_vdev_get_filter_mcast_data() - get DP VDEV monitor mcast filter - * @vdev_handle: Datapath VDEV handle + * dp_pdev_get_filter_mcast_data() - get DP PDEV monitor mcast filter + * @pdev_handle: Datapath PDEV handle * Return: true on mcast filter flag set */ -static bool dp_vdev_get_filter_mcast_data(struct cdp_vdev *vdev_handle) +static bool dp_pdev_get_filter_mcast_data(struct cdp_pdev *pdev_handle) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - struct dp_pdev *pdev; - - pdev = vdev->pdev; + struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; if ((pdev->fp_data_filter & FILTER_DATA_MCAST) || (pdev->mo_data_filter & FILTER_DATA_MCAST)) @@ -6844,16 +7340,13 @@ static bool dp_vdev_get_filter_mcast_data(struct cdp_vdev *vdev_handle) } /** - * dp_vdev_get_filter_non_data() - get DP VDEV monitor non_data filter - * @vdev_handle: Datapath VDEV handle + * dp_pdev_get_filter_non_data() - get DP PDEV monitor non_data filter + * @pdev_handle: Datapath PDEV handle * Return: true on non data filter flag set */ -static bool dp_vdev_get_filter_non_data(struct cdp_vdev *vdev_handle) +static bool dp_pdev_get_filter_non_data(struct cdp_pdev *pdev_handle) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - struct dp_pdev *pdev; - - pdev = vdev->pdev; + struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; if ((pdev->fp_mgmt_filter & FILTER_MGMT_ALL) || (pdev->mo_mgmt_filter & FILTER_MGMT_ALL)) { @@ -6893,6 +7386,57 @@ void dp_peer_set_mesh_rx_filter(struct cdp_vdev *vdev_hdl, uint32_t val) } #endif +#ifdef VDEV_PEER_PROTOCOL_COUNT +static void dp_enable_vdev_peer_protocol_count(struct cdp_soc_t *soc, + int8_t vdev_id, + bool enable) +{ + struct dp_vdev *vdev; + + vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + dp_info("enable %d vdev_id %d", enable, vdev_id); + vdev->peer_protocol_count_track = enable; +} + +static void dp_enable_vdev_peer_protocol_drop_mask(struct cdp_soc_t *soc, + int8_t vdev_id, + int drop_mask) +{ + struct dp_vdev *vdev; + + vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + dp_info("drop_mask %d vdev_id %d", drop_mask, vdev_id); + vdev->peer_protocol_count_dropmask = drop_mask; +} + +static int dp_is_vdev_peer_protocol_count_enabled(struct cdp_soc_t *soc, + int8_t vdev_id) +{ + struct dp_vdev *vdev; + + vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + dp_info("enable %d vdev_id %d", vdev->peer_protocol_count_track, + vdev_id); + return vdev->peer_protocol_count_track; +} + +static int dp_get_vdev_peer_protocol_drop_mask(struct cdp_soc_t *soc, + int8_t vdev_id) +{ + struct dp_vdev *vdev; + + vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + dp_info("drop_mask %d vdev_id %d", vdev->peer_protocol_count_dropmask, + vdev_id); + return vdev->peer_protocol_count_dropmask; +} + +#endif + bool dp_check_pdev_exists(struct dp_soc *soc, struct dp_pdev *data) { uint8_t pdev_count; @@ -7012,10 +7556,10 @@ void dp_aggregate_pdev_stats(struct dp_pdev *pdev) * @vdev_handle: Datapath VDEV handle * @stats: cdp network device stats structure * - * Return: void + * Return: QDF_STATUS */ -static void dp_vdev_getstats(void *vdev_handle, - struct cdp_dev_stats *stats) +static QDF_STATUS dp_vdev_getstats(struct cdp_vdev *vdev_handle, + struct cdp_dev_stats *stats) { struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; struct dp_pdev *pdev; @@ -7023,11 +7567,11 @@ static void dp_vdev_getstats(void *vdev_handle, struct cdp_vdev_stats *vdev_stats; if (!vdev) - return; + return QDF_STATUS_E_FAILURE; pdev = vdev->pdev; if (!pdev) - return; + return QDF_STATUS_E_FAILURE; soc = pdev->soc; @@ -7036,7 +7580,7 @@ static void dp_vdev_getstats(void *vdev_handle, if (!vdev_stats) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "DP alloc failure - unable to get alloc vdev stats"); - return; + return QDF_STATUS_E_FAILURE; } qdf_spin_lock_bh(&soc->peer_ref_mutex); @@ -7059,6 +7603,7 @@ static void dp_vdev_getstats(void *vdev_handle, qdf_mem_free(vdev_stats); + return QDF_STATUS_SUCCESS; } @@ -7067,10 +7612,10 @@ static void dp_vdev_getstats(void *vdev_handle, * @pdev_handle: Datapath PDEV handle * @stats: cdp network device stats structure * - * Return: void + * Return: QDF_STATUS */ -static void dp_pdev_getstats(void *pdev_handle, - struct cdp_dev_stats *stats) +static void dp_pdev_getstats(struct cdp_pdev *pdev_handle, + struct cdp_dev_stats *stats) { struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; @@ -7089,25 +7634,51 @@ static void dp_pdev_getstats(void *pdev_handle, stats->rx_bytes = pdev->stats.rx.unicast.bytes + pdev->stats.rx.multicast.bytes + pdev->stats.rx.bcast.bytes; + stats->rx_errors = pdev->stats.err.desc_alloc_fail + + pdev->stats.err.ip_csum_err + + pdev->stats.err.tcp_udp_csum_err + + pdev->stats.rx.err.mic_err + + pdev->stats.rx.err.decrypt_err + + pdev->stats.err.rxdma_error + + pdev->stats.err.reo_error; + stats->rx_dropped = pdev->stats.dropped.msdu_not_done + + pdev->stats.dropped.mec + + pdev->stats.dropped.mesh_filter + + pdev->stats.dropped.wifi_parse + + pdev->stats.dropped.mon_rx_drop + + pdev->stats.dropped.mon_radiotap_update_err; } /** * dp_get_device_stats() - get interface level packet stats - * @handle: device handle + * @soc: soc handle + * @id : vdev_id or pdev_id based on type * @stats: cdp network device stats structure * @type: device type pdev/vdev * - * Return: void + * Return: QDF_STATUS */ -static void dp_get_device_stats(void *handle, - struct cdp_dev_stats *stats, uint8_t type) +static QDF_STATUS dp_get_device_stats(struct cdp_soc_t *soc, uint8_t id, + struct cdp_dev_stats *stats, + uint8_t type) { switch (type) { case UPDATE_VDEV_STATS: - dp_vdev_getstats(handle, stats); - break; + return dp_vdev_getstats( + (struct cdp_vdev *)dp_get_vdev_from_soc_vdev_id_wifi3( + (struct dp_soc *)soc, id), stats); case UPDATE_PDEV_STATS: - dp_pdev_getstats(handle, stats); + { + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3( + (struct dp_soc *)soc, + id); + if (pdev) { + dp_pdev_getstats((struct cdp_pdev *)pdev, + stats); + return QDF_STATUS_SUCCESS; + } + } break; default: QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, @@ -7116,6 +7687,7 @@ static void dp_get_device_stats(void *handle, break; } + return QDF_STATUS_E_FAILURE; } const @@ -7163,7 +7735,7 @@ char *dp_srng_get_str_from_hal_ring_type(enum hal_ring_type ring_type) * dp_print_napi_stats(): NAPI stats * @soc - soc handle */ -static void dp_print_napi_stats(struct dp_soc *soc) +void dp_print_napi_stats(struct dp_soc *soc) { hif_print_napi_stats(soc->hif_handle); } @@ -7172,15 +7744,15 @@ static void dp_print_napi_stats(struct dp_soc *soc) * dp_txrx_host_stats_clr(): Reinitialize the txrx stats * @vdev: DP_VDEV handle * - * Return:void + * Return: QDF_STATUS */ -static inline void +static inline QDF_STATUS dp_txrx_host_stats_clr(struct dp_vdev *vdev) { struct dp_peer *peer = NULL; if (!vdev || !vdev->pdev) - return; + return QDF_STATUS_E_FAILURE; DP_STATS_CLR(vdev->pdev); DP_STATS_CLR(vdev->pdev->soc); @@ -7190,7 +7762,7 @@ dp_txrx_host_stats_clr(struct dp_vdev *vdev) TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { if (!peer) - return; + return QDF_STATUS_E_FAILURE; DP_STATS_CLR(peer); #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE @@ -7205,45 +7777,37 @@ dp_txrx_host_stats_clr(struct dp_vdev *vdev) &vdev->stats, vdev->vdev_id, UPDATE_VDEV_STATS, vdev->pdev->pdev_id); #endif + return QDF_STATUS_SUCCESS; } /* * dp_get_host_peer_stats()- function to print peer stats - * @pdev_handle: DP_PDEV handle + * @soc: dp_soc handle * @mac_addr: mac address of the peer * - * Return: void + * Return: QDF_STATUS */ -static void -dp_get_host_peer_stats(struct cdp_pdev *pdev_handle, char *mac_addr) +static QDF_STATUS +dp_get_host_peer_stats(struct cdp_soc_t *soc, uint8_t *mac_addr) { - struct dp_peer *peer; - uint8_t local_id; - - if (!mac_addr) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "Invalid MAC address\n"); - return; - } - - peer = (struct dp_peer *)dp_find_peer_by_addr(pdev_handle, mac_addr, - &local_id); - - if (!peer) { + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc, + mac_addr, 0, + DP_VDEV_ALL); + if (!peer || peer->delete_in_progress) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s: Invalid peer\n", __func__); - return; - } - - /* Making sure the peer is for the specific pdev */ - if ((struct dp_pdev *)pdev_handle != peer->vdev->pdev) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "%s: Peer is not for this pdev\n", __func__); - return; + status = QDF_STATUS_E_FAILURE; + goto fail; } dp_print_peer_stats(peer); dp_peer_rxtid_stats(peer, dp_rx_tid_stats_cb, NULL); +fail: + if (peer) + dp_peer_unref_delete(peer); + + return status; } /** @@ -7284,6 +7848,7 @@ static void dp_txrx_stats_help(void) dp_info(" 28 -- Host REO Queue Statistics"); dp_info(" 29 -- Host Soc cfg param Statistics"); dp_info(" 30 -- Host pdev cfg param Statistics"); + dp_info(" 31 -- Host FISA stats"); dp_info(" 32 -- Host Register Work stats"); } @@ -7295,10 +7860,9 @@ static void dp_txrx_stats_help(void) * Return: 0 on success, print error message in case of failure */ static int -dp_print_host_stats(struct cdp_vdev *vdev_handle, +dp_print_host_stats(struct dp_vdev *vdev, struct cdp_txrx_stats_req *req) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev; enum cdp_host_txrx_stats type = dp_stats_mapping_table[req->stats][STATS_HOST]; @@ -7334,7 +7898,8 @@ dp_print_host_stats(struct cdp_vdev *vdev_handle, dp_print_pdev_rx_mon_stats(pdev); break; case TXRX_REO_QUEUE_STATS: - dp_get_host_peer_stats((struct cdp_pdev *)pdev, req->peer_addr); + dp_get_host_peer_stats((struct cdp_soc_t *)pdev->soc, + req->peer_addr); break; case TXRX_SOC_CFG_PARAMS: dp_print_soc_cfg_params(pdev->soc); @@ -7348,10 +7913,17 @@ dp_print_host_stats(struct cdp_vdev *vdev_handle, case TXRX_SOC_INTERRUPT_STATS: dp_print_soc_interrupt_stats(pdev->soc); break; + case TXRX_SOC_FSE_STATS: + dp_rx_dump_fisa_table(pdev->soc); + break; case TXRX_HAL_REG_WRITE_STATS: hal_dump_reg_write_stats(pdev->soc->hal_soc); hal_dump_reg_write_srng_stats(pdev->soc->hal_soc); break; + case TXRX_SOC_REO_HW_DESC_DUMP: + dp_get_rx_reo_queue_info((struct cdp_soc_t *)pdev->soc, + vdev->vdev_id); + break; default: dp_info("Wrong Input For TxRx Host Stats"); dp_txrx_stats_help(); @@ -7360,86 +7932,6 @@ dp_print_host_stats(struct cdp_vdev *vdev_handle, return 0; } -/* - * dp_ppdu_ring_reset()- Reset PPDU Stats ring - * @pdev: DP_PDEV handle - * - * Return: void - */ -static void -dp_ppdu_ring_reset(struct dp_pdev *pdev) -{ - struct htt_rx_ring_tlv_filter htt_tlv_filter; - int mac_id; - - qdf_mem_zero(&(htt_tlv_filter), sizeof(htt_tlv_filter)); - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); - - htt_h2t_rx_ring_cfg(pdev->soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id].hal_srng, - RXDMA_MONITOR_STATUS, RX_BUFFER_SIZE, &htt_tlv_filter); - } -} - -/* - * dp_ppdu_ring_cfg()- Configure PPDU Stats ring - * @pdev: DP_PDEV handle - * - * Return: void - */ -static void -dp_ppdu_ring_cfg(struct dp_pdev *pdev) -{ - struct htt_rx_ring_tlv_filter htt_tlv_filter = {0}; - int mac_id; - - htt_tlv_filter.mpdu_start = 1; - htt_tlv_filter.msdu_start = 0; - htt_tlv_filter.packet = 0; - htt_tlv_filter.msdu_end = 0; - htt_tlv_filter.mpdu_end = 0; - htt_tlv_filter.attention = 0; - htt_tlv_filter.ppdu_start = 1; - htt_tlv_filter.ppdu_end = 1; - htt_tlv_filter.ppdu_end_user_stats = 1; - htt_tlv_filter.ppdu_end_user_stats_ext = 1; - htt_tlv_filter.ppdu_end_status_done = 1; - htt_tlv_filter.enable_fp = 1; - htt_tlv_filter.enable_md = 0; - if (pdev->neighbour_peers_added && - pdev->soc->hw_nac_monitor_support) { - htt_tlv_filter.enable_md = 1; - htt_tlv_filter.packet_header = 1; - } - if (pdev->mcopy_mode) { - htt_tlv_filter.packet_header = 1; - htt_tlv_filter.enable_mo = 1; - } - htt_tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.fp_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.mo_data_filter = FILTER_DATA_ALL; - if (pdev->neighbour_peers_added && - pdev->soc->hw_nac_monitor_support) - htt_tlv_filter.md_data_filter = FILTER_DATA_ALL; - - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); - - htt_h2t_rx_ring_cfg(pdev->soc->htt_handle, mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id].hal_srng, - RXDMA_MONITOR_STATUS, RX_BUFFER_SIZE, &htt_tlv_filter); - } -} - /* * is_ppdu_txrx_capture_enabled() - API to check both pktlog and debug_sniffer * modes are enabled or not. @@ -7464,10 +7956,8 @@ static inline bool is_ppdu_txrx_capture_enabled(struct dp_pdev *pdev) *Return: 0 for success. nonzero for failure. */ static QDF_STATUS -dp_set_bpr_enable(struct cdp_pdev *pdev_handle, int val) +dp_set_bpr_enable(struct dp_pdev *pdev, int val) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - switch (val) { case CDP_BPR_DISABLE: pdev->bpr_enable = CDP_BPR_DISABLE; @@ -7516,11 +8006,9 @@ dp_set_bpr_enable(struct cdp_pdev *pdev_handle, int val) * Return: void */ static void -dp_pdev_tid_stats_ingress_inc(struct cdp_pdev *pdev, uint32_t val) +dp_pdev_tid_stats_ingress_inc(struct dp_pdev *pdev, uint32_t val) { - struct dp_pdev *dp_pdev = (struct dp_pdev *)pdev; - - dp_pdev->stats.tid_stats.ingress_stack += val; + pdev->stats.tid_stats.ingress_stack += val; } /* @@ -7531,39 +8019,55 @@ dp_pdev_tid_stats_ingress_inc(struct cdp_pdev *pdev, uint32_t val) * Return: void */ static void -dp_pdev_tid_stats_osif_drop(struct cdp_pdev *pdev, uint32_t val) +dp_pdev_tid_stats_osif_drop(struct dp_pdev *pdev, uint32_t val) { - struct dp_pdev *dp_pdev = (struct dp_pdev *)pdev; - - dp_pdev->stats.tid_stats.osif_drop += val; + pdev->stats.tid_stats.osif_drop += val; } + /* * dp_config_debug_sniffer()- API to enable/disable debug sniffer - * @pdev_handle: DP_PDEV handle + * @pdev: DP_PDEV handle * @val: user provided value * * Return: 0 for success. nonzero for failure. */ static QDF_STATUS -dp_config_debug_sniffer(struct cdp_pdev *pdev_handle, int val) +dp_config_debug_sniffer(struct dp_pdev *pdev, 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); + /* + * Note: The mirror copy mode cannot co-exist with any other + * monitor modes. Hence disabling the filter for this mode will + * reset the monitor destination ring filters. + */ + if (pdev->mcopy_mode) { +#ifdef FEATURE_PERPKT_INFO + dp_pdev_disable_mcopy_code(pdev); + dp_mon_filter_reset_mcopy_mode(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to reset AM copy mode filters")); + } +#endif /* FEATURE_PERPKT_INFO */ + } switch (val) { case 0: pdev->tx_sniffer_enable = 0; - pdev->mcopy_mode = 0; pdev->monitor_configured = false; + /* + * We don't need to reset the Rx monitor status ring or call + * the API dp_ppdu_ring_reset() if all debug sniffer mode is + * disabled. The Rx monitor status ring will be disabled when + * the last mode using the monitor status ring get disabled. + */ if (!pdev->pktlog_ppdu_stats && !pdev->enhanced_stats_en && !pdev->bpr_enable) { dp_h2t_cfg_stats_msg_send(pdev, 0, pdev->pdev_id); - dp_ppdu_ring_reset(pdev); } else if (pdev->enhanced_stats_en && !pdev->bpr_enable) { dp_h2t_cfg_stats_msg_send(pdev, DP_PPDU_STATS_CFG_ENH_STATS, pdev->pdev_id); @@ -7580,7 +8084,6 @@ dp_config_debug_sniffer(struct cdp_pdev *pdev_handle, int val) case 1: pdev->tx_sniffer_enable = 1; - pdev->mcopy_mode = 0; pdev->monitor_configured = false; if (!pdev->pktlog_ppdu_stats) @@ -7593,14 +8096,28 @@ dp_config_debug_sniffer(struct cdp_pdev *pdev_handle, int val) break; } +#ifdef FEATURE_PERPKT_INFO pdev->mcopy_mode = 1; - dp_pdev_configure_monitor_rings(pdev); - pdev->monitor_configured = true; pdev->tx_sniffer_enable = 0; + pdev->monitor_configured = true; + + /* + * Setup the M copy mode filter. + */ + dp_mon_filter_setup_mcopy_mode(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to set M_copy mode filters")); + dp_mon_filter_reset_mcopy_mode(pdev); + dp_pdev_disable_mcopy_code(pdev); + return status; + } if (!pdev->pktlog_ppdu_stats) dp_h2t_cfg_stats_msg_send(pdev, DP_PPDU_STATS_CFG_SNIFFER, pdev->pdev_id); +#endif /* FEATURE_PERPKT_INFO */ break; default: @@ -7611,25 +8128,41 @@ dp_config_debug_sniffer(struct cdp_pdev *pdev_handle, int val) return status; } +#ifdef FEATURE_PERPKT_INFO /* * dp_enable_enhanced_stats()- API to enable enhanced statistcs - * @pdev_handle: DP_PDEV handle + * @soc_handle: DP_SOC handle + * @pdev_id: id of DP_PDEV handle * - * Return: void + * Return: QDF_STATUS */ -static void -dp_enable_enhanced_stats(struct cdp_pdev *pdev_handle) +static QDF_STATUS +dp_enable_enhanced_stats(struct cdp_soc_t *soc, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + struct dp_pdev *pdev = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + pdev = dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + + if (!pdev) + return QDF_STATUS_E_FAILURE; if (pdev->enhanced_stats_en == 0) dp_cal_client_timer_start(pdev->cal_client_ctx); pdev->enhanced_stats_en = 1; - if (!pdev->mcopy_mode && !pdev->neighbour_peers_added && - !pdev->monitor_vdev) - dp_ppdu_ring_cfg(pdev); + dp_mon_filter_setup_enhanced_stats(pdev); + status = dp_mon_filter_update(pdev); + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to set enhanced mode filters")); + dp_mon_filter_reset_enhanced_stats(pdev); + dp_cal_client_timer_stop(pdev->cal_client_ctx); + pdev->enhanced_stats_en = 0; + return QDF_STATUS_E_FAILURE; + } if (is_ppdu_txrx_capture_enabled(pdev) && !pdev->bpr_enable) { dp_h2t_cfg_stats_msg_send(pdev, DP_PPDU_STATS_CFG_ENH_STATS, pdev->pdev_id); @@ -7638,18 +8171,26 @@ dp_enable_enhanced_stats(struct cdp_pdev *pdev_handle) DP_PPDU_STATS_CFG_BPR_ENH, pdev->pdev_id); } + + return QDF_STATUS_SUCCESS; } /* * dp_disable_enhanced_stats()- API to disable enhanced statistcs - * @pdev_handle: DP_PDEV handle * - * Return: void + * @param soc - the soc handle + * @param pdev_id - pdev_id of pdev + * @return - QDF_STATUS */ -static void -dp_disable_enhanced_stats(struct cdp_pdev *pdev_handle) +static QDF_STATUS +dp_disable_enhanced_stats(struct cdp_soc_t *soc, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + + if (!pdev) + return QDF_STATUS_E_FAILURE; if (pdev->enhanced_stats_en == 1) dp_cal_client_timer_stop(pdev->cal_client_ctx); @@ -7664,14 +8205,20 @@ dp_disable_enhanced_stats(struct cdp_pdev *pdev_handle) pdev->pdev_id); } - if (!pdev->mcopy_mode && !pdev->neighbour_peers_added && - !pdev->monitor_vdev) - dp_ppdu_ring_reset(pdev); + dp_mon_filter_reset_enhanced_stats(pdev); + if (dp_mon_filter_update(pdev) != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Failed to reset enhanced mode filters")); + } + + return QDF_STATUS_SUCCESS; } +#endif /* FEATURE_PERPKT_INFO */ /* * dp_get_fw_peer_stats()- function to print peer stats - * @pdev_handle: DP_PDEV handle + * @soc: soc handle + * @pdev_id : id of the pdev handle * @mac_addr: mac address of the peer * @cap: Type of htt stats requested * @is_wait: if set, wait on completion from firmware response @@ -7681,18 +8228,24 @@ dp_disable_enhanced_stats(struct cdp_pdev *pdev_handle) * 2: HTT_PEER_STATS_REQ_MODE_QUERY_TQM * 3: HTT_PEER_STATS_REQ_MODE_FLUSH_TQM * - * Return: void + * Return: QDF_STATUS */ -static void -dp_get_fw_peer_stats(struct cdp_pdev *pdev_handle, uint8_t *mac_addr, - uint32_t cap, uint32_t is_wait) +static QDF_STATUS +dp_get_fw_peer_stats(struct cdp_soc_t *soc, uint8_t pdev_id, + uint8_t *mac_addr, + uint32_t cap, uint32_t is_wait) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; int i; uint32_t config_param0 = 0; uint32_t config_param1 = 0; uint32_t config_param2 = 0; uint32_t config_param3 = 0; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + + if (!pdev) + return QDF_STATUS_E_FAILURE; HTT_DBG_EXT_STATS_PEER_INFO_IS_MAC_ADDR_SET(config_param0, 1); config_param0 |= (1 << (cap + 1)); @@ -7724,6 +8277,8 @@ dp_get_fw_peer_stats(struct cdp_pdev *pdev_handle, uint8_t *mac_addr, 0, 0, 0); } + return QDF_STATUS_SUCCESS; + } /* This struct definition will be removed from here @@ -7739,62 +8294,229 @@ struct httstats_cmd_req { /* * dp_get_htt_stats: function to process the httstas request - * @pdev_handle: DP pdev handle + * @soc: DP soc handle + * @pdev_id: id of pdev handle * @data: pointer to request data * @data_len: length for request data * - * return: void + * return: QDF_STATUS */ -static void -dp_get_htt_stats(struct cdp_pdev *pdev_handle, void *data, uint32_t data_len) +static QDF_STATUS +dp_get_htt_stats(struct cdp_soc_t *soc, uint8_t pdev_id, void *data, + uint32_t data_len) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; struct httstats_cmd_req *req = (struct httstats_cmd_req *)data; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + + if (!pdev) + return QDF_STATUS_E_FAILURE; QDF_ASSERT(data_len == sizeof(struct httstats_cmd_req)); dp_h2t_ext_stats_msg_send(pdev, req->stats_id, req->config_param0, req->config_param1, req->config_param2, req->config_param3, req->cookie, 0, 0); + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_set_pdev_tidmap_prty_wifi3(): update tidmap priority in pdev + * @pdev: DP_PDEV handle + * @prio: tidmap priority value passed by the user + * + * Return: QDF_STATUS_SUCCESS on success + */ +static QDF_STATUS dp_set_pdev_tidmap_prty_wifi3(struct dp_pdev *pdev, + uint8_t prio) +{ + struct dp_soc *soc = pdev->soc; + + soc->tidmap_prty = prio; + + hal_tx_set_tidmap_prty(soc->hal_soc, prio); + return QDF_STATUS_SUCCESS; +} + +/* + * dp_get_peer_param: function to get parameters in peer + * @cdp_soc: DP soc handle + * @vdev_id: id of vdev handle + * @peer_mac: peer mac address + * @param: parameter type to be set + * @val : address of buffer + * + * Return: val + */ +static QDF_STATUS dp_get_peer_param(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, + uint8_t *peer_mac, + enum cdp_peer_param_type param, + cdp_config_param_type *val) +{ + return QDF_STATUS_SUCCESS; +} + +/* + * dp_set_peer_param: function to set parameters in peer + * @cdp_soc: DP soc handle + * @vdev_id: id of vdev handle + * @peer_mac: peer mac address + * @param: parameter type to be set + * @val: value of parameter to be set + * + * Return: 0 for success. nonzero for failure. + */ +static QDF_STATUS dp_set_peer_param(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, + uint8_t *peer_mac, + enum cdp_peer_param_type param, + cdp_config_param_type val) +{ + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)cdp_soc, + peer_mac, 0, vdev_id); + + if (!peer || peer->delete_in_progress) + goto fail; + + switch (param) { + case CDP_CONFIG_NAWDS: + peer->nawds_enabled = val.cdp_peer_param_nawds; + break; + case CDP_CONFIG_NAC: + peer->nac = !!(val.cdp_peer_param_nac); + break; + default: + break; + } + +fail: + if (peer) + dp_peer_unref_delete(peer); + + return QDF_STATUS_SUCCESS; +} + +/* + * dp_get_pdev_param: function to get parameters from pdev + * @cdp_soc: DP soc handle + * @pdev_id: id of pdev handle + * @param: parameter type to be get + * @value : buffer for value + * + * Return: status + */ +static QDF_STATUS dp_get_pdev_param(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, + enum cdp_pdev_param_type param, + cdp_config_param_type *val) +{ + struct cdp_pdev *pdev = (struct cdp_pdev *) + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)cdp_soc, + pdev_id); + if (!pdev) + return QDF_STATUS_E_FAILURE; + + switch (param) { + case CDP_CONFIG_VOW: + val->cdp_pdev_param_cfg_vow = + ((struct dp_pdev *)pdev)->delay_stats_flag; + break; + case CDP_TX_PENDING: + val->cdp_pdev_param_tx_pending = dp_get_tx_pending(pdev); + break; + case CDP_FILTER_MCAST_DATA: + val->cdp_pdev_param_fltr_mcast = + dp_pdev_get_filter_mcast_data(pdev); + break; + case CDP_FILTER_NO_DATA: + val->cdp_pdev_param_fltr_none = + dp_pdev_get_filter_non_data(pdev); + break; + case CDP_FILTER_UCAST_DATA: + val->cdp_pdev_param_fltr_ucast = + dp_pdev_get_filter_ucast_data(pdev); + break; + default: + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; } /* * dp_set_pdev_param: function to set parameters in pdev - * @pdev_handle: DP pdev handle + * @cdp_soc: DP soc handle + * @pdev_id: id of pdev handle * @param: parameter type to be set * @val: value of parameter to be set * * Return: 0 for success. nonzero for failure. */ -static QDF_STATUS dp_set_pdev_param(struct cdp_pdev *pdev_handle, +static QDF_STATUS dp_set_pdev_param(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, enum cdp_pdev_param_type param, - uint8_t val) + cdp_config_param_type val) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)cdp_soc, + pdev_id); + if (!pdev) + return QDF_STATUS_E_FAILURE; + switch (param) { + case CDP_CONFIG_TX_CAPTURE: + return dp_config_debug_sniffer(pdev, + val.cdp_pdev_param_tx_capture); case CDP_CONFIG_DEBUG_SNIFFER: - return dp_config_debug_sniffer(pdev_handle, val); + return dp_config_debug_sniffer(pdev, + val.cdp_pdev_param_dbg_snf); case CDP_CONFIG_BPR_ENABLE: - return dp_set_bpr_enable(pdev_handle, val); + return dp_set_bpr_enable(pdev, val.cdp_pdev_param_bpr_enable); case CDP_CONFIG_PRIMARY_RADIO: - pdev->is_primary = val; + pdev->is_primary = val.cdp_pdev_param_primary_radio; break; case CDP_CONFIG_CAPTURE_LATENCY: - if (val == 1) - pdev->latency_capture_enable = true; - else - pdev->latency_capture_enable = false; + pdev->latency_capture_enable = val.cdp_pdev_param_cptr_latcy; break; case CDP_INGRESS_STATS: - dp_pdev_tid_stats_ingress_inc(pdev_handle, val); + dp_pdev_tid_stats_ingress_inc(pdev, + val.cdp_pdev_param_ingrs_stats); break; case CDP_OSIF_DROP: - dp_pdev_tid_stats_osif_drop(pdev_handle, val); + dp_pdev_tid_stats_osif_drop(pdev, + val.cdp_pdev_param_osif_drop); break; case CDP_CONFIG_ENH_RX_CAPTURE: - return dp_config_enh_rx_capture(pdev_handle, val); - case CDP_CONFIG_TX_CAPTURE: - return dp_config_enh_tx_capture(pdev_handle, val); + return dp_config_enh_rx_capture(pdev, + val.cdp_pdev_param_en_rx_cap); + case CDP_CONFIG_ENH_TX_CAPTURE: + return dp_config_enh_tx_capture(pdev, + val.cdp_pdev_param_en_tx_cap); + case CDP_CONFIG_HMMC_TID_OVERRIDE: + pdev->hmmc_tid_override_en = val.cdp_pdev_param_hmmc_tid_ovrd; + break; + case CDP_CONFIG_HMMC_TID_VALUE: + pdev->hmmc_tid = val.cdp_pdev_param_hmmc_tid; + break; + case CDP_CHAN_NOISE_FLOOR: + pdev->chan_noise_floor = val.cdp_pdev_param_chn_noise_flr; + break; + case CDP_TIDMAP_PRTY: + dp_set_pdev_tidmap_prty_wifi3(pdev, + val.cdp_pdev_param_tidmap_prty); + break; + case CDP_FILTER_NEIGH_PEERS: + dp_set_filter_neigh_peers(pdev, + val.cdp_pdev_param_fltr_neigh_peers); + break; + case CDP_MONITOR_CHANNEL: + pdev->mon_chan_num = val.cdp_pdev_param_monitor_chan; + break; + case CDP_MONITOR_FREQUENCY: + pdev->mon_chan_freq = val.cdp_pdev_param_mon_freq; + break; + case CDP_CONFIG_BSS_COLOR: + dp_mon_set_bsscolor(pdev, val.cdp_pdev_param_bss_color); + break; default: return QDF_STATUS_E_INVAL; } @@ -7803,149 +8525,311 @@ static QDF_STATUS dp_set_pdev_param(struct cdp_pdev *pdev_handle, /* * dp_calculate_delay_stats: function to get rx delay stats - * @vdev_handle: DP vdev handle + * @cdp_soc: DP soc handle + * @vdev_id: id of DP vdev handle * @nbuf: skb * - * Return: void + * Return: QDF_STATUS */ -static void dp_calculate_delay_stats(struct cdp_vdev *vdev_handle, - qdf_nbuf_t nbuf) +static QDF_STATUS +dp_calculate_delay_stats(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, + qdf_nbuf_t nbuf) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)cdp_soc, + vdev_id); + if (vdev) { + dp_rx_compute_delay(vdev, nbuf); + return QDF_STATUS_E_FAILURE; + } - dp_rx_compute_delay(vdev, nbuf); + return QDF_STATUS_SUCCESS; } /* * dp_get_vdev_param: function to get parameters from vdev + * @cdp_soc : DP soc handle + * @vdev_id: id of DP vdev handle * @param: parameter type to get value + * @val: buffer address * - * return: void + * return: status */ -static uint32_t dp_get_vdev_param(struct cdp_vdev *vdev_handle, - enum cdp_vdev_param_type param) +static QDF_STATUS dp_get_vdev_param(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, + enum cdp_vdev_param_type param, + cdp_config_param_type *val) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - uint32_t val; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)cdp_soc, + vdev_id); + if (!vdev) + return QDF_STATUS_E_FAILURE; switch (param) { case CDP_ENABLE_WDS: - val = vdev->wds_enabled; + val->cdp_vdev_param_wds = vdev->wds_enabled; break; case CDP_ENABLE_MEC: - val = vdev->mec_enabled; + val->cdp_vdev_param_mec = vdev->mec_enabled; break; case CDP_ENABLE_DA_WAR: - val = vdev->pdev->soc->da_war_enabled; + val->cdp_vdev_param_da_war = vdev->pdev->soc->da_war_enabled; break; default: QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "param value %d is wrong\n", param); - val = -1; - break; + return QDF_STATUS_E_FAILURE; } - return val; + return QDF_STATUS_SUCCESS; } /* * dp_set_vdev_param: function to set parameters in vdev - * @param: parameter type to be set - * @val: value of parameter to be set + * @cdp_soc : DP soc handle + * @vdev_id: id of DP vdev handle + * @param: parameter type to get value + * @val: value * - * return: void + * return: QDF_STATUS */ -static void dp_set_vdev_param(struct cdp_vdev *vdev_handle, - enum cdp_vdev_param_type param, uint32_t val) +static QDF_STATUS +dp_set_vdev_param(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, + enum cdp_vdev_param_type param, cdp_config_param_type val) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; + struct dp_soc *dsoc = (struct dp_soc *)cdp_soc; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3(dsoc, vdev_id); + uint32_t var = 0; + + if (!vdev) + return QDF_STATUS_E_FAILURE; + switch (param) { case CDP_ENABLE_WDS: QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "wds_enable %d for vdev(%pK) id(%d)\n", - val, vdev, vdev->vdev_id); - vdev->wds_enabled = val; + val.cdp_vdev_param_wds, vdev, vdev->vdev_id); + vdev->wds_enabled = val.cdp_vdev_param_wds; break; case CDP_ENABLE_MEC: QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "mec_enable %d for vdev(%pK) id(%d)\n", - val, vdev, vdev->vdev_id); - vdev->mec_enabled = val; + val.cdp_vdev_param_mec, vdev, vdev->vdev_id); + vdev->mec_enabled = val.cdp_vdev_param_mec; break; case CDP_ENABLE_DA_WAR: QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "da_war_enable %d for vdev(%pK) id(%d)\n", - val, vdev, vdev->vdev_id); - vdev->pdev->soc->da_war_enabled = val; + val.cdp_vdev_param_da_war, vdev, vdev->vdev_id); + vdev->pdev->soc->da_war_enabled = val.cdp_vdev_param_da_war; dp_wds_flush_ast_table_wifi3(((struct cdp_soc_t *) vdev->pdev->soc)); break; case CDP_ENABLE_NAWDS: - vdev->nawds_enabled = val; + vdev->nawds_enabled = val.cdp_vdev_param_nawds; break; case CDP_ENABLE_MCAST_EN: - vdev->mcast_enhancement_en = val; + vdev->mcast_enhancement_en = val.cdp_vdev_param_mcast_en; break; case CDP_ENABLE_PROXYSTA: - vdev->proxysta_vdev = val; + vdev->proxysta_vdev = val.cdp_vdev_param_proxysta; break; case CDP_UPDATE_TDLS_FLAGS: - vdev->tdls_link_connected = val; + vdev->tdls_link_connected = val.cdp_vdev_param_tdls_flags; break; case CDP_CFG_WDS_AGING_TIMER: - if (val == 0) + var = val.cdp_vdev_param_aging_tmr; + if (!var) qdf_timer_stop(&vdev->pdev->soc->ast_aging_timer); - else if (val != vdev->wds_aging_timer_val) - qdf_timer_mod(&vdev->pdev->soc->ast_aging_timer, val); + else if (var != vdev->wds_aging_timer_val) + qdf_timer_mod(&vdev->pdev->soc->ast_aging_timer, var); - vdev->wds_aging_timer_val = val; + vdev->wds_aging_timer_val = var; break; case CDP_ENABLE_AP_BRIDGE: if (wlan_op_mode_sta != vdev->opmode) - vdev->ap_bridge_enabled = val; + vdev->ap_bridge_enabled = val.cdp_vdev_param_ap_brdg_en; else vdev->ap_bridge_enabled = false; break; case CDP_ENABLE_CIPHER: - vdev->sec_type = val; + vdev->sec_type = val.cdp_vdev_param_cipher_en; break; case CDP_ENABLE_QWRAP_ISOLATION: - vdev->isolation_vdev = val; + vdev->isolation_vdev = val.cdp_vdev_param_qwrap_isolation; + break; + case CDP_UPDATE_MULTIPASS: + vdev->multipass_en = val.cdp_vdev_param_update_multipass; + break; + case CDP_TX_ENCAP_TYPE: + vdev->tx_encap_type = val.cdp_vdev_param_tx_encap; + break; + case CDP_RX_DECAP_TYPE: + vdev->rx_decap_type = val.cdp_vdev_param_rx_decap; + break; + case CDP_TID_VDEV_PRTY: + vdev->tidmap_prty = val.cdp_vdev_param_tidmap_prty; + break; + case CDP_TIDMAP_TBL_ID: + vdev->tidmap_tbl_id = val.cdp_vdev_param_tidmap_tbl_id; + break; +#ifdef MESH_MODE_SUPPORT + case CDP_MESH_RX_FILTER: + dp_peer_set_mesh_rx_filter((struct cdp_vdev *)vdev, + val.cdp_vdev_param_mesh_rx_filter); + break; + case CDP_MESH_MODE: + dp_peer_set_mesh_mode((struct cdp_vdev *)vdev, + val.cdp_vdev_param_mesh_mode); + break; +#endif + case CDP_ENABLE_CSUM: + dp_info("vdev_id %d enable Checksum %d", vdev_id, + val.cdp_enable_tx_checksum); + vdev->csum_enabled = val.cdp_enable_tx_checksum; + break; + default: + break; + } + + dp_tx_vdev_update_search_flags((struct dp_vdev *)vdev); + + return QDF_STATUS_SUCCESS; +} + +/* + * dp_set_psoc_param: function to set parameters in psoc + * @cdp_soc : DP soc handle + * @param: parameter type to be set + * @val: value of parameter to be set + * + * return: QDF_STATUS + */ +static QDF_STATUS +dp_set_psoc_param(struct cdp_soc_t *cdp_soc, + enum cdp_psoc_param_type param, cdp_config_param_type val) +{ + struct dp_soc *soc = (struct dp_soc *)cdp_soc; + struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx = soc->wlan_cfg_ctx; + + switch (param) { + case CDP_ENABLE_RATE_STATS: + soc->wlanstats_enabled = val.cdp_psoc_param_en_rate_stats; + break; + case CDP_SET_NSS_CFG: + wlan_cfg_set_dp_soc_nss_cfg(wlan_cfg_ctx, + val.cdp_psoc_param_en_nss_cfg); + /* + * TODO: masked out based on the per offloaded radio + */ + switch (val.cdp_psoc_param_en_nss_cfg) { + case dp_nss_cfg_default: + break; + case dp_nss_cfg_first_radio: + /* + * This configuration is valid for single band radio which + * is also NSS offload. + */ + case dp_nss_cfg_dbdc: + case dp_nss_cfg_dbtc: + wlan_cfg_set_num_tx_desc_pool(wlan_cfg_ctx, 0); + wlan_cfg_set_num_tx_ext_desc_pool(wlan_cfg_ctx, 0); + wlan_cfg_set_num_tx_desc(wlan_cfg_ctx, 0); + wlan_cfg_set_num_tx_ext_desc(wlan_cfg_ctx, 0); + break; + default: + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "Invalid offload config %d", + val.cdp_psoc_param_en_nss_cfg); + } + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + FL("nss-wifi<0> nss config is enabled")); break; + default: break; } - dp_tx_vdev_update_search_flags(vdev); + return QDF_STATUS_SUCCESS; } -/** - * dp_peer_set_nawds: set nawds bit in peer - * @peer_handle: pointer to peer - * @value: enable/disable nawds +/* + * dp_get_psoc_param: function to get parameters in soc + * @cdp_soc : DP soc handle + * @param: parameter type to be set + * @val: address of buffer * - * return: void + * return: status */ -static void dp_peer_set_nawds(struct cdp_peer *peer_handle, uint8_t value) +static QDF_STATUS dp_get_psoc_param(struct cdp_soc_t *cdp_soc, + enum cdp_psoc_param_type param, + cdp_config_param_type *val) +{ + return QDF_STATUS_SUCCESS; +} + +/** + * dp_peer_update_pkt_capture_params: Set Rx & Tx Capture flags for a peer + * @soc: DP_SOC handle + * @pdev_id: id of DP_PDEV handle + * @is_rx_pkt_cap_enable: enable/disable Rx packet capture in monitor mode + * @is_tx_pkt_cap_enable: enable/disable Tx packet capture in monitor mode + * @peer_mac: MAC address for which the above need to be enabled/disabled + * + * Return: Success if Rx & Tx capture is enabled for peer, false otherwise + */ +QDF_STATUS +dp_peer_update_pkt_capture_params(ol_txrx_soc_handle soc, + uint8_t pdev_id, + bool is_rx_pkt_cap_enable, + bool is_tx_pkt_cap_enable, + uint8_t *peer_mac) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; - peer->nawds_enabled = value; + struct dp_peer *peer; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + + if (!pdev) + return QDF_STATUS_E_FAILURE; + + peer = (struct dp_peer *)dp_find_peer_by_addr((struct cdp_pdev *)pdev, + peer_mac); + if (!peer) { + dp_err("Invalid Peer"); + return QDF_STATUS_E_FAILURE; + } + + dp_peer_set_rx_capture_enabled(peer, is_rx_pkt_cap_enable); + dp_peer_set_tx_capture_enabled(peer, is_tx_pkt_cap_enable); + + return QDF_STATUS_SUCCESS; } /* * dp_set_vdev_dscp_tid_map_wifi3(): Update Map ID selected for particular vdev - * @vdev_handle: DP_VDEV handle + * @soc: DP_SOC handle + * @vdev_id: id of DP_VDEV handle * @map_id:ID of map that needs to be updated * - * Return: void + * Return: QDF_STATUS */ -static void dp_set_vdev_dscp_tid_map_wifi3(struct cdp_vdev *vdev_handle, - uint8_t map_id) +static QDF_STATUS dp_set_vdev_dscp_tid_map_wifi3(ol_txrx_soc_handle soc, + uint8_t vdev_id, + uint8_t map_id) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - vdev->dscp_tid_map_id = map_id; - return; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + if (vdev) { + vdev->dscp_tid_map_id = map_id; + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; } #ifdef DP_RATETABLE_SUPPORT @@ -7953,9 +8837,10 @@ static int dp_txrx_get_ratekbps(int preamb, int mcs, int htflag, int gintval) { uint32_t rix; + uint16_t ratecode; return dp_getrateindex((uint32_t)gintval, (uint16_t)mcs, 1, - (uint8_t)preamb, 1, &rix); + (uint8_t)preamb, 1, &rix, &ratecode); } #else static int dp_txrx_get_ratekbps(int preamb, int mcs, @@ -7966,39 +8851,39 @@ static int dp_txrx_get_ratekbps(int preamb, int mcs, #endif /* dp_txrx_get_pdev_stats - Returns cdp_pdev_stats - * @peer_handle: DP pdev handle + * @soc: DP soc handle + * @pdev_id: id of DP pdev handle + * @pdev_stats: buffer to copy to * - * return : cdp_pdev_stats pointer + * return : status success/failure */ -static struct cdp_pdev_stats* -dp_txrx_get_pdev_stats(struct cdp_pdev *pdev_handle) +static QDF_STATUS +dp_txrx_get_pdev_stats(struct cdp_soc_t *soc, uint8_t pdev_id, + struct cdp_pdev_stats *pdev_stats) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + if (!pdev) + return QDF_STATUS_E_FAILURE; dp_aggregate_pdev_stats(pdev); - return &pdev->stats; + qdf_mem_copy(pdev_stats, &pdev->stats, sizeof(struct cdp_pdev_stats)); + return QDF_STATUS_SUCCESS; } /* dp_txrx_update_vdev_me_stats(): Update vdev ME stats sent from CDP - * @vdev_handle: DP vdev handle + * @vdev: DP vdev handle * @buf: buffer containing specific stats structure * * Returns: void */ -static void dp_txrx_update_vdev_me_stats(struct cdp_vdev *vdev_handle, +static void dp_txrx_update_vdev_me_stats(struct dp_vdev *vdev, void *buf) { - struct dp_vdev *vdev = NULL; struct cdp_tx_ingress_stats *host_stats = NULL; - if (!vdev_handle) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "Invalid vdev handle"); - return; - } - vdev = (struct dp_vdev *)vdev_handle; - if (!buf) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "Invalid host stats buf"); @@ -8024,55 +8909,179 @@ static void dp_txrx_update_vdev_me_stats(struct cdp_vdev *vdev_handle, } /* dp_txrx_update_vdev_host_stats(): Update stats sent through CDP - * @vdev_handle: DP vdev handle + * @soc: DP soc handle + * @vdev_id: id of DP vdev handle * @buf: buffer containing specific stats structure * @stats_id: stats type * - * Returns: void + * Returns: QDF_STATUS */ -static void dp_txrx_update_vdev_host_stats(struct cdp_vdev *vdev_handle, - void *buf, - uint16_t stats_id) +static QDF_STATUS dp_txrx_update_vdev_host_stats(struct cdp_soc_t *soc, + uint8_t vdev_id, + void *buf, + uint16_t stats_id) { + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + if (!vdev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "Invalid vdev handle"); + return QDF_STATUS_E_FAILURE; + } + switch (stats_id) { case DP_VDEV_STATS_PKT_CNT_ONLY: break; case DP_VDEV_STATS_TX_ME: - dp_txrx_update_vdev_me_stats(vdev_handle, buf); + dp_txrx_update_vdev_me_stats(vdev, buf); break; default: qdf_info("Invalid stats_id %d", stats_id); break; } + + return QDF_STATUS_SUCCESS; } /* dp_txrx_get_peer_stats - will return cdp_peer_stats - * @peer_handle: DP_PEER handle - * - * return : cdp_peer_stats pointer + * @soc: soc handle + * @vdev_id: id of vdev handle + * @peer_mac: mac of DP_PEER handle + * @peer_stats: buffer to copy to + * return : status success/failure + */ +static QDF_STATUS +dp_txrx_get_peer_stats(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, struct cdp_peer_stats *peer_stats) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc, + peer_mac, 0, vdev_id); + + if (!peer || peer->delete_in_progress) { + status = QDF_STATUS_E_FAILURE; + } else + qdf_mem_copy(peer_stats, &peer->stats, + sizeof(struct cdp_peer_stats)); + + if (peer) + dp_peer_unref_delete(peer); + + return status; +} + +/* dp_txrx_get_peer_stats_param - will return specified cdp_peer_stats + * @param soc - soc handle + * @param vdev_id - vdev_id of vdev object + * @param peer_mac - mac address of the peer + * @param type - enum of required stats + * @param buf - buffer to hold the value + * return : status success/failure */ -static struct cdp_peer_stats* - dp_txrx_get_peer_stats(struct cdp_peer *peer_handle) +static QDF_STATUS +dp_txrx_get_peer_stats_param(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, enum cdp_peer_stats_type type, + cdp_peer_stats_param_t *buf) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; + QDF_STATUS ret = QDF_STATUS_SUCCESS; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc, + peer_mac, 0, vdev_id); + + if (!peer || peer->delete_in_progress) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "Invalid Peer for Mac "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(peer_mac)); + ret = QDF_STATUS_E_FAILURE; + } else if (type < cdp_peer_stats_max) { + switch (type) { + case cdp_peer_tx_ucast: + buf->tx_ucast = peer->stats.tx.ucast; + break; + case cdp_peer_tx_mcast: + buf->tx_mcast = peer->stats.tx.mcast; + break; + case cdp_peer_tx_rate: + buf->tx_rate = peer->stats.tx.tx_rate; + break; + case cdp_peer_tx_last_tx_rate: + buf->last_tx_rate = peer->stats.tx.last_tx_rate; + break; + case cdp_peer_tx_inactive_time: + buf->tx_inactive_time = peer->stats.tx.inactive_time; + break; + case cdp_peer_tx_ratecode: + buf->tx_ratecode = peer->stats.tx.tx_ratecode; + break; + case cdp_peer_tx_flags: + buf->tx_flags = peer->stats.tx.tx_flags; + break; + case cdp_peer_tx_power: + buf->tx_power = peer->stats.tx.tx_power; + break; + case cdp_peer_rx_rate: + buf->rx_rate = peer->stats.rx.rx_rate; + break; + case cdp_peer_rx_last_rx_rate: + buf->last_rx_rate = peer->stats.rx.last_rx_rate; + break; + case cdp_peer_rx_ratecode: + buf->rx_ratecode = peer->stats.rx.rx_ratecode; + break; + case cdp_peer_rx_ucast: + buf->rx_ucast = peer->stats.rx.unicast; + break; + case cdp_peer_rx_flags: + buf->rx_flags = peer->stats.rx.rx_flags; + break; + case cdp_peer_rx_avg_rssi: + buf->rx_avg_rssi = peer->stats.rx.avg_rssi; + break; + default: + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "Invalid value"); + ret = QDF_STATUS_E_FAILURE; + break; + } + } else { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "Invalid value"); + ret = QDF_STATUS_E_FAILURE; + } - qdf_assert(peer); + if (peer) + dp_peer_unref_delete(peer); - return &peer->stats; + return ret; } /* dp_txrx_reset_peer_stats - reset cdp_peer_stats for particular peer - * @peer_handle: DP_PEER handle + * @soc: soc handle + * @vdev_id: id of vdev handle + * @peer_mac: mac of DP_PEER handle * - * return : void + * return : QDF_STATUS */ -static void dp_txrx_reset_peer_stats(struct cdp_peer *peer_handle) +static QDF_STATUS +dp_txrx_reset_peer_stats(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc, + peer_mac, 0, vdev_id); - qdf_assert(peer); + if (!peer || peer->delete_in_progress) { + status = QDF_STATUS_E_FAILURE; + goto fail; + } qdf_mem_zero(&peer->stats, sizeof(peer->stats)); + +fail: + if (peer) + dp_peer_unref_delete(peer); + + return status; } /* dp_txrx_get_vdev_stats - Update buffer with cdp_vdev_stats @@ -8081,13 +9090,14 @@ static void dp_txrx_reset_peer_stats(struct cdp_peer *peer_handle) * * return : int */ -static int dp_txrx_get_vdev_stats(struct cdp_vdev *vdev_handle, void *buf, - bool is_aggregate) +static int dp_txrx_get_vdev_stats(struct cdp_soc_t *soc, uint8_t vdev_id, + void *buf, bool is_aggregate) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; struct cdp_vdev_stats *vdev_stats; struct dp_pdev *pdev; - struct dp_soc *soc; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); if (!vdev) return 1; @@ -8096,13 +9106,12 @@ static int dp_txrx_get_vdev_stats(struct cdp_vdev *vdev_handle, void *buf, if (!pdev) return 1; - soc = pdev->soc; vdev_stats = (struct cdp_vdev_stats *)buf; if (is_aggregate) { - qdf_spin_lock_bh(&soc->peer_ref_mutex); + qdf_spin_lock_bh(&((struct dp_soc *)soc)->peer_ref_mutex); dp_aggregate_vdev_stats(vdev, buf); - qdf_spin_unlock_bh(&soc->peer_ref_mutex); + qdf_spin_unlock_bh(&((struct dp_soc *)soc)->peer_ref_mutex); } else { qdf_mem_copy(vdev_stats, &vdev->stats, sizeof(vdev->stats)); } @@ -8112,13 +9121,19 @@ static int dp_txrx_get_vdev_stats(struct cdp_vdev *vdev_handle, void *buf, /* * dp_get_total_per(): get total per - * @pdev_handle: DP_PDEV handle + * @soc: DP soc handle + * @pdev_id: id of DP_PDEV handle * * Return: % error rate using retries per packet and success packets */ -static int dp_get_total_per(struct cdp_pdev *pdev_handle) +static int dp_get_total_per(struct cdp_soc_t *soc, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + + if (!pdev) + return 0; dp_aggregate_pdev_stats(pdev); if ((pdev->stats.tx.tx_success.num + pdev->stats.tx.retries) == 0) @@ -8129,17 +9144,23 @@ static int dp_get_total_per(struct cdp_pdev *pdev_handle) /* * dp_txrx_stats_publish(): publish pdev stats into a buffer - * @pdev_handle: DP_PDEV handle + * @soc: DP soc handle + * @pdev_id: id of DP_PDEV handle * @buf: to hold pdev_stats * * Return: int */ static int -dp_txrx_stats_publish(struct cdp_pdev *pdev_handle, struct cdp_stats_extd *buf) +dp_txrx_stats_publish(struct cdp_soc_t *soc, uint8_t pdev_id, + struct cdp_stats_extd *buf) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - struct cdp_pdev_stats *buffer = (struct cdp_pdev_stats *) buf; struct cdp_txrx_stats_req req = {0,}; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + + if (!pdev) + return TXRX_STATS_LEVEL_OFF; dp_aggregate_pdev_stats(pdev); req.stats = (enum cdp_stats)HTT_DBG_EXT_STATS_PDEV_TX; @@ -8157,29 +9178,33 @@ dp_txrx_stats_publish(struct cdp_pdev *pdev_handle, struct cdp_stats_extd *buf) req.cookie_val, 0); msleep(DP_MAX_SLEEP_TIME); - qdf_mem_copy(buffer, &pdev->stats, sizeof(pdev->stats)); + qdf_mem_copy(buf, &pdev->stats, sizeof(struct cdp_pdev_stats)); return TXRX_STATS_LEVEL; } /** * dp_set_pdev_dscp_tid_map_wifi3(): update dscp tid map in pdev - * @pdev: DP_PDEV handle + * @soc: soc handle + * @pdev_id: id of DP_PDEV handle * @map_id: ID of map that needs to be updated * @tos: index value in map * @tid: tid value passed by the user * - * Return: void + * Return: QDF_STATUS */ -static void dp_set_pdev_dscp_tid_map_wifi3(struct cdp_pdev *pdev_handle, - uint8_t map_id, uint8_t tos, uint8_t tid) +static QDF_STATUS +dp_set_pdev_dscp_tid_map_wifi3(struct cdp_soc_t *soc_handle, + uint8_t pdev_id, + uint8_t map_id, + uint8_t tos, uint8_t tid) { uint8_t dscp; - struct dp_pdev *pdev = (struct dp_pdev *) pdev_handle; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = (struct dp_soc *)soc_handle; + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); - if (!soc) - return; + if (!pdev) + return QDF_STATUS_E_FAILURE; dscp = (tos >> DP_IP_DSCP_SHIFT) & DP_IP_DSCP_MASK; pdev->dscp_tid_map[map_id][dscp] = tid; @@ -8187,37 +9212,10 @@ static void dp_set_pdev_dscp_tid_map_wifi3(struct cdp_pdev *pdev_handle, if (map_id < soc->num_hw_dscp_tid_map) hal_tx_update_dscp_tid(soc->hal_soc, tid, map_id, dscp); - return; -} - -/** - * dp_hmmc_tid_override_en_wifi3(): Function to enable hmmc tid override. - * @pdev_handle: pdev handle - * @val: hmmc-dscp flag value - * - * Return: void - */ -static void dp_hmmc_tid_override_en_wifi3(struct cdp_pdev *pdev_handle, - bool val) -{ - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - - pdev->hmmc_tid_override_en = val; -} - -/** - * dp_set_hmmc_tid_val_wifi3(): Function to set hmmc tid value. - * @pdev_handle: pdev handle - * @tid: tid value - * - * Return: void - */ -static void dp_set_hmmc_tid_val_wifi3(struct cdp_pdev *pdev_handle, - uint8_t tid) -{ - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + else + return QDF_STATUS_E_FAILURE; - pdev->hmmc_tid = tid; + return QDF_STATUS_SUCCESS; } /** @@ -8227,10 +9225,9 @@ static void dp_set_hmmc_tid_val_wifi3(struct cdp_pdev *pdev_handle, * * return: int */ -static int dp_fw_stats_process(struct cdp_vdev *vdev_handle, - struct cdp_txrx_stats_req *req) +static int dp_fw_stats_process(struct dp_vdev *vdev, + struct cdp_txrx_stats_req *req) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; struct dp_pdev *pdev = NULL; uint32_t stats = req->stats; uint8_t mac_id = req->mac_id; @@ -8267,19 +9264,24 @@ static int dp_fw_stats_process(struct cdp_vdev *vdev_handle, /** * dp_txrx_stats_request - function to map to firmware and host stats - * @vdev: virtual handle + * @soc: soc handle + * @vdev_id: virtual device ID * @req: stats request * * Return: QDF_STATUS */ static -QDF_STATUS dp_txrx_stats_request(struct cdp_vdev *vdev, +QDF_STATUS dp_txrx_stats_request(struct cdp_soc_t *soc_handle, + uint8_t vdev_id, struct cdp_txrx_stats_req *req) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_handle); int host_stats; int fw_stats; enum cdp_stats stats; int num_stats; + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, + vdev_id); if (!vdev || !req) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -8338,7 +9340,7 @@ QDF_STATUS dp_txrx_stats_request(struct cdp_vdev *vdev, * dp_txrx_dump_stats() - Dump statistics * @value - Statistics option */ -static QDF_STATUS dp_txrx_dump_stats(void *psoc, uint16_t value, +static QDF_STATUS dp_txrx_dump_stats(struct cdp_soc_t *psoc, uint16_t value, enum qdf_stats_verbosity_level level) { struct dp_soc *soc = @@ -8363,11 +9365,12 @@ static QDF_STATUS dp_txrx_dump_stats(void *psoc, uint16_t value, break; case CDP_TXRX_TSO_STATS: - /* TODO: NOT IMPLEMENTED */ + dp_print_tso_stats(soc, level); break; case CDP_DUMP_TX_FLOW_POOL_INFO: - cdp_dump_flow_pool_info((struct cdp_soc_t *)soc); + if (level == QDF_STATS_VERBOSITY_LEVEL_HIGH) + cdp_dump_flow_pool_info((struct cdp_soc_t *)soc); break; case CDP_DP_NAPI_STATS: @@ -8378,6 +9381,10 @@ static QDF_STATUS dp_txrx_dump_stats(void *psoc, uint16_t value, /* TODO: NOT IMPLEMENTED */ break; + case CDP_DP_RX_FISA_STATS: + dp_rx_dump_fisa_stats(soc); + break; + default: status = QDF_STATUS_E_INVAL; break; @@ -8387,6 +9394,38 @@ static QDF_STATUS dp_txrx_dump_stats(void *psoc, uint16_t value, } +/** + * dp_txrx_clear_dump_stats() - clear dumpStats + * @soc- soc handle + * @value - stats option + * + * Return: 0 - Success, non-zero - failure + */ +static +QDF_STATUS dp_txrx_clear_dump_stats(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint8_t value) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (!soc) { + dp_err("%s: soc is NULL", __func__); + return QDF_STATUS_E_INVAL; + } + + switch (value) { + case CDP_TXRX_TSO_STATS: + dp_txrx_clear_tso_stats(soc); + break; + + default: + status = QDF_STATUS_E_INVAL; + break; + } + + return status; +} + #ifdef QCA_LL_TX_FLOW_CONTROL_V2 /** * dp_update_flow_control_parameters() - API to store datapath @@ -8480,6 +9519,10 @@ QDF_STATUS dp_update_config_parameters(struct cdp_soc *psoc, soc->wlan_cfg_ctx->tso_enabled = params->tso_enable; soc->wlan_cfg_ctx->lro_enabled = params->lro_enable; soc->wlan_cfg_ctx->rx_hash = params->flow_steering_enable; + soc->wlan_cfg_ctx->p2p_tcp_udp_checksumoffload = + params->p2p_tcp_udp_checksumoffload; + soc->wlan_cfg_ctx->nan_tcp_udp_checksumoffload = + params->nan_tcp_udp_checksumoffload; soc->wlan_cfg_ctx->tcp_udp_checksumoffload = params->tcp_udp_checksumoffload; soc->wlan_cfg_ctx->napi_enabled = params->napi_enable; @@ -8502,16 +9545,21 @@ static struct cdp_wds_ops dp_ops_wds = { /* * dp_txrx_data_tx_cb_set(): set the callback for non standard tx - * @vdev_handle - datapath vdev handle + * @soc_hdl - datapath soc handle + * @vdev_id - virtual interface id * @callback - callback function * @ctxt: callback context * */ static void -dp_txrx_data_tx_cb_set(struct cdp_vdev *vdev_handle, +dp_txrx_data_tx_cb_set(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, ol_txrx_data_tx_cb callback, void *ctxt) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + + if (!vdev) + return; vdev->tx_non_std_data_callback.func = callback; vdev->tx_non_std_data_callback.ctxt = ctxt; @@ -8519,32 +9567,92 @@ dp_txrx_data_tx_cb_set(struct cdp_vdev *vdev_handle, /** * dp_pdev_get_dp_txrx_handle() - get dp handle from pdev - * @pdev_hdl: datapath pdev handle + * @soc: datapath soc handle + * @pdev_id: id of datapath pdev handle * * Return: opaque pointer to dp txrx handle */ -static void *dp_pdev_get_dp_txrx_handle(struct cdp_pdev *pdev_hdl) +static void *dp_pdev_get_dp_txrx_handle(struct cdp_soc_t *soc, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_hdl; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + if (qdf_unlikely(!pdev)) + return NULL; return pdev->dp_txrx_handle; } /** * dp_pdev_set_dp_txrx_handle() - set dp handle in pdev - * @pdev_hdl: datapath pdev handle + * @soc: datapath soc handle + * @pdev_id: id of datapath pdev handle * @dp_txrx_hdl: opaque pointer for dp_txrx_handle * * Return: void */ static void -dp_pdev_set_dp_txrx_handle(struct cdp_pdev *pdev_hdl, void *dp_txrx_hdl) +dp_pdev_set_dp_txrx_handle(struct cdp_soc_t *soc, uint8_t pdev_id, + void *dp_txrx_hdl) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_hdl; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + + if (!pdev) + return; pdev->dp_txrx_handle = dp_txrx_hdl; } +/** + * dp_vdev_get_dp_ext_handle() - get dp handle from vdev + * @soc: datapath soc handle + * @vdev_id: vdev id + * + * Return: opaque pointer to dp txrx handle + */ +static void *dp_vdev_get_dp_ext_handle(ol_txrx_soc_handle soc, uint8_t vdev_id) +{ + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + + if (!vdev) + return NULL; + + return vdev->vdev_dp_ext_handle; +} + +/** + * dp_vdev_set_dp_ext_handle() - set dp handle in vdev + * @soc: datapath soc handle + * @vdev_id: vdev id + * @size: size of advance dp handle + * + * Return: QDF_STATUS + */ +static QDF_STATUS +dp_vdev_set_dp_ext_handle(ol_txrx_soc_handle soc, uint8_t vdev_id, + uint16_t size) +{ + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + void *dp_ext_handle; + + if (!vdev) + return QDF_STATUS_E_FAILURE; + + dp_ext_handle = qdf_mem_malloc(size); + + if (!dp_ext_handle) + return QDF_STATUS_E_FAILURE; + + vdev->vdev_dp_ext_handle = dp_ext_handle; + return QDF_STATUS_SUCCESS; +} + /** * dp_soc_get_dp_txrx_handle() - get context for external-dp from dp soc * @soc_handle: datapath soc handle @@ -8575,21 +9683,111 @@ dp_soc_set_dp_txrx_handle(struct cdp_soc *soc_handle, void *txrx_handle) /** * dp_soc_map_pdev_to_lmac() - Save pdev_id to lmac_id mapping - * @pdev_hdl: datapath pdev handle + * @soc_hdl: datapath soc handle + * @pdev_id: id of the datapath pdev handle * @lmac_id: lmac id * - * Return: void + * Return: QDF_STATUS */ -static void -dp_soc_map_pdev_to_lmac(struct cdp_pdev *pdev_hdl, uint32_t lmac_id) +static QDF_STATUS +dp_soc_map_pdev_to_lmac + (struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint32_t lmac_id) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_hdl; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + + wlan_cfg_set_hw_mac_idx(soc->wlan_cfg_ctx, + pdev_id, + lmac_id); + + /*Set host PDEV ID for lmac_id*/ + wlan_cfg_set_pdev_idx(soc->wlan_cfg_ctx, + pdev_id, + lmac_id); + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_soc_handle_pdev_mode_change() - Update pdev to lmac mapping + * @soc_hdl: datapath soc handle + * @pdev_id: id of the datapath pdev handle + * @lmac_id: lmac id + * + * In the event of a dynamic mode change, update the pdev to lmac mapping + * + * Return: QDF_STATUS + */ +static QDF_STATUS +dp_soc_handle_pdev_mode_change + (struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint32_t lmac_id) +{ + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_vdev *vdev = NULL; + uint8_t hw_pdev_id, mac_id; + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, + pdev_id); + int nss_config = wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx); + + if (qdf_unlikely(!pdev)) + return QDF_STATUS_E_FAILURE; pdev->lmac_id = lmac_id; - wlan_cfg_set_hw_macid(soc->wlan_cfg_ctx, + dp_info(" mode change %d %d\n", pdev->pdev_id, pdev->lmac_id); + + /*Set host PDEV ID for lmac_id*/ + wlan_cfg_set_pdev_idx(soc->wlan_cfg_ctx, pdev->pdev_id, - (lmac_id + 1)); + lmac_id); + + hw_pdev_id = + dp_get_target_pdev_id_for_host_pdev_id(soc, + pdev->pdev_id); + + /* + * When NSS offload is enabled, send pdev_id->lmac_id + * and pdev_id to hw_pdev_id to NSS FW + */ + if (nss_config) { + mac_id = pdev->lmac_id; + if (soc->cdp_soc.ol_ops->pdev_update_lmac_n_target_pdev_id) + soc->cdp_soc.ol_ops-> + pdev_update_lmac_n_target_pdev_id( + soc->ctrl_psoc, + &pdev_id, &mac_id, &hw_pdev_id); + } + + qdf_spin_lock_bh(&pdev->vdev_list_lock); + TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { + HTT_TX_TCL_METADATA_PDEV_ID_SET(vdev->htt_tcl_metadata, + hw_pdev_id); + } + qdf_spin_unlock_bh(&pdev->vdev_list_lock); + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_soc_set_pdev_status_down() - set pdev down/up status + * @soc: datapath soc handle + * @pdev_id: id of datapath pdev handle + * @is_pdev_down: pdev down/up status + * + * Return: QDF_STATUS + */ +static QDF_STATUS +dp_soc_set_pdev_status_down(struct cdp_soc_t *soc, uint8_t pdev_id, + bool is_pdev_down) +{ + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + if (!pdev) + return QDF_STATUS_E_FAILURE; + + pdev->is_pdev_down = is_pdev_down; + return QDF_STATUS_SUCCESS; } /** @@ -8609,48 +9807,73 @@ dp_get_cfg_capabilities(struct cdp_soc_t *soc_handle, } #ifdef FEATURE_AST -static void dp_peer_teardown_wifi3(struct cdp_vdev *vdev_hdl, void *peer_hdl) +static QDF_STATUS +dp_peer_teardown_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_mac) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_hdl; - struct dp_peer *peer = (struct dp_peer *)peer_hdl; - struct dp_soc *soc = (struct dp_soc *)vdev->pdev->soc; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_peer *peer = + dp_peer_find_hash_find(soc, peer_mac, 0, vdev_id); + /* Peer can be null for monitor vap mac address */ + if (!peer) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid peer\n", __func__); + return QDF_STATUS_E_FAILURE; + } /* * For BSS peer, new peer is not created on alloc_node if the * peer with same address already exists , instead refcnt is * increased for existing peer. Correspondingly in delete path, * only refcnt is decreased; and peer is only deleted , when all * references are deleted. So delete_in_progress should not be set - * for bss_peer, unless only 2 reference remains (peer map reference - * and peer hash table reference). + * for bss_peer, unless only 3 reference remains (peer map reference, + * peer hash table reference and above local reference). */ - if (peer->bss_peer && (qdf_atomic_read(&peer->ref_cnt) > 2)) - return; + if (peer->bss_peer && (qdf_atomic_read(&peer->ref_cnt) > 3)) { + status = QDF_STATUS_E_FAILURE; + goto fail; + } qdf_spin_lock_bh(&soc->ast_lock); peer->delete_in_progress = true; dp_peer_delete_ast_entries(soc, peer); qdf_spin_unlock_bh(&soc->ast_lock); + +fail: + if (peer) + dp_peer_unref_delete(peer); + return status; } #endif #ifdef ATH_SUPPORT_NAC_RSSI /** * dp_vdev_get_neighbour_rssi(): Store RSSI for configured NAC - * @vdev_hdl: DP vdev handle + * @soc_hdl: DP soc handle + * @vdev_id: id of DP vdev handle + * @mac_addr: neighbour mac * @rssi: rssi value * * Return: 0 for success. nonzero for failure. */ -static QDF_STATUS dp_vdev_get_neighbour_rssi(struct cdp_vdev *vdev_hdl, +static QDF_STATUS dp_vdev_get_neighbour_rssi(struct cdp_soc_t *soc, + uint8_t vdev_id, char *mac_addr, uint8_t *rssi) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_hdl; - struct dp_pdev *pdev = vdev->pdev; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + struct dp_pdev *pdev; struct dp_neighbour_peer *peer = NULL; QDF_STATUS status = QDF_STATUS_E_FAILURE; + if (!vdev) + return status; + + pdev = vdev->pdev; *rssi = 0; qdf_spin_lock_bh(&pdev->neighbour_peer_mutex); TAILQ_FOREACH(peer, &pdev->neighbour_peers_list, @@ -8666,33 +9889,42 @@ static QDF_STATUS dp_vdev_get_neighbour_rssi(struct cdp_vdev *vdev_hdl, return status; } -static QDF_STATUS dp_config_for_nac_rssi(struct cdp_vdev *vdev_handle, - enum cdp_nac_param_cmd cmd, char *bssid, char *client_macaddr, - uint8_t chan_num) +static QDF_STATUS +dp_config_for_nac_rssi(struct cdp_soc_t *cdp_soc, + uint8_t vdev_id, + enum cdp_nac_param_cmd cmd, char *bssid, + char *client_macaddr, + uint8_t chan_num) { + struct dp_soc *soc = (struct dp_soc *)cdp_soc; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3(soc, + vdev_id); + struct dp_pdev *pdev; - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev; - struct dp_soc *soc = (struct dp_soc *) vdev->pdev->soc; + if (!vdev) + return QDF_STATUS_E_FAILURE; + pdev = (struct dp_pdev *)vdev->pdev; pdev->nac_rssi_filtering = 1; /* Store address of NAC (neighbour peer) which will be checked * against TA of received packets. */ if (cmd == CDP_NAC_PARAM_ADD) { - dp_update_filter_neighbour_peers(vdev_handle, DP_NAC_PARAM_ADD, - client_macaddr); + dp_update_filter_neighbour_peers(cdp_soc, vdev->vdev_id, + DP_NAC_PARAM_ADD, + (uint8_t *)client_macaddr); } else if (cmd == CDP_NAC_PARAM_DEL) { - dp_update_filter_neighbour_peers(vdev_handle, + dp_update_filter_neighbour_peers(cdp_soc, vdev->vdev_id, DP_NAC_PARAM_DEL, - client_macaddr); + (uint8_t *)client_macaddr); } if (soc->cdp_soc.ol_ops->config_bssid_in_fw_for_nac_rssi) soc->cdp_soc.ol_ops->config_bssid_in_fw_for_nac_rssi - ((void *)vdev->pdev->ctrl_pdev, - vdev->vdev_id, cmd, bssid); + (soc->ctrl_psoc, pdev->pdev_id, + vdev->vdev_id, cmd, bssid, client_macaddr); return QDF_STATUS_SUCCESS; } @@ -8701,22 +9933,29 @@ static QDF_STATUS dp_config_for_nac_rssi(struct cdp_vdev *vdev_handle, /** * dp_enable_peer_based_pktlog() - Set Flag for peer based filtering * for pktlog - * @txrx_pdev_handle: cdp_pdev handle + * @soc: cdp_soc handle + * @pdev_id: id of dp pdev handle + * @mac_addr: Peer mac address * @enb_dsb: Enable or disable peer based filtering * * Return: QDF_STATUS */ static int -dp_enable_peer_based_pktlog( - struct cdp_pdev *txrx_pdev_handle, - char *mac_addr, uint8_t enb_dsb) +dp_enable_peer_based_pktlog(struct cdp_soc_t *soc, uint8_t pdev_id, + uint8_t *mac_addr, uint8_t enb_dsb) { struct dp_peer *peer; - uint8_t local_id; - struct dp_pdev *pdev = (struct dp_pdev *)txrx_pdev_handle; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + + if (!pdev) { + dp_err("Invalid Pdev for pdev_id %d", pdev_id); + return QDF_STATUS_E_FAILURE; + } - peer = (struct dp_peer *)dp_find_peer_by_addr(txrx_pdev_handle, - mac_addr, &local_id); + peer = (struct dp_peer *)dp_find_peer_by_addr((struct cdp_pdev *)pdev, + mac_addr); if (!peer) { dp_err("Invalid Peer"); @@ -8729,139 +9968,79 @@ dp_enable_peer_based_pktlog( return QDF_STATUS_SUCCESS; } -#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG -#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS -/** - * dp_summarize_tag_stats - sums up the given protocol type's counters - * across all the rings and dumps the same - * @pdev_handle: cdp_pdev handle - * @protocol_type: protocol type for which stats should be displayed - * - * Return: none - */ -static uint64_t dp_summarize_tag_stats(struct cdp_pdev *pdev_handle, - uint16_t protocol_type) -{ - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - uint8_t ring_idx; - uint64_t total_tag_cnt = 0; - - for (ring_idx = 0; ring_idx < MAX_REO_DEST_RINGS; ring_idx++) { - total_tag_cnt += - pdev->reo_proto_tag_stats[ring_idx][protocol_type].tag_ctr; - } - total_tag_cnt += pdev->rx_err_proto_tag_stats[protocol_type].tag_ctr; - DP_PRINT_STATS("ProtoID: %d, Tag: %u Tagged MSDU cnt: %llu", - protocol_type, - pdev->rx_proto_tag_map[protocol_type].tag, - total_tag_cnt); - return total_tag_cnt; -} - +#ifndef WLAN_SUPPORT_RX_TAG_STATISTICS /** * dp_dump_pdev_rx_protocol_tag_stats - dump the number of packets tagged for * given protocol type (RX_PROTOCOL_TAG_ALL indicates for all protocol) - * @pdev_handle: cdp_pdev handle + * @soc: cdp_soc handle + * @pdev_id: id of cdp_pdev handle * @protocol_type: protocol type for which stats should be displayed * * Return: none */ -static void -dp_dump_pdev_rx_protocol_tag_stats(struct cdp_pdev *pdev_handle, +static inline void +dp_dump_pdev_rx_protocol_tag_stats(struct cdp_soc_t *soc, uint8_t pdev_id, uint16_t protocol_type) { - uint16_t proto_idx; - - if (protocol_type != RX_PROTOCOL_TAG_ALL && - protocol_type >= RX_PROTOCOL_TAG_MAX) { - DP_PRINT_STATS("Invalid protocol type : %u", protocol_type); - return; - } - - /* protocol_type in [0 ... RX_PROTOCOL_TAG_MAX] */ - if (protocol_type != RX_PROTOCOL_TAG_ALL) { - dp_summarize_tag_stats(pdev_handle, protocol_type); - return; - } - - /* protocol_type == RX_PROTOCOL_TAG_ALL */ - for (proto_idx = 0; proto_idx < RX_PROTOCOL_TAG_MAX; proto_idx++) - dp_summarize_tag_stats(pdev_handle, proto_idx); -} -#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */ - -/** - * dp_reset_pdev_rx_protocol_tag_stats - resets the stats counters for - * given protocol type - * @pdev_handle: cdp_pdev handle - * @protocol_type: protocol type for which stats should be reset - * - * Return: none - */ -#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS -static void -dp_reset_pdev_rx_protocol_tag_stats(struct cdp_pdev *pdev_handle, - uint16_t protocol_type) -{ - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - uint8_t ring_idx; - - for (ring_idx = 0; ring_idx < MAX_REO_DEST_RINGS; ring_idx++) - pdev->reo_proto_tag_stats[ring_idx][protocol_type].tag_ctr = 0; - pdev->rx_err_proto_tag_stats[protocol_type].tag_ctr = 0; -} -#else -static void -dp_reset_pdev_rx_protocol_tag_stats(struct cdp_pdev *pdev_handle, - uint16_t protocol_type) -{ - /** Stub API */ } #endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */ +#ifndef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG /** * dp_update_pdev_rx_protocol_tag - Add/remove a protocol tag that should be * applied to the desired protocol type packets - * @txrx_pdev_handle: cdp_pdev handle + * @soc: soc handle + * @pdev_id: id of cdp_pdev handle * @enable_rx_protocol_tag - bitmask that indicates what protocol types * are enabled for tagging. zero indicates disable feature, non-zero indicates * enable feature * @protocol_type: new protocol type for which the tag is being added * @tag: user configured tag for the new protocol * - * Return: QDF_STATUS + * Return: Success */ -static QDF_STATUS -dp_update_pdev_rx_protocol_tag(struct cdp_pdev *pdev_handle, +static inline QDF_STATUS +dp_update_pdev_rx_protocol_tag(struct cdp_soc_t *soc, uint8_t pdev_id, uint32_t enable_rx_protocol_tag, uint16_t protocol_type, uint16_t tag) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - /* - * dynamically enable/disable tagging based on enable_rx_protocol_tag - * flag. - */ - if (enable_rx_protocol_tag) { - /* Tagging for one or more protocols has been set by user */ - pdev->is_rx_protocol_tagging_enabled = true; - } else { - /* - * No protocols being tagged, disable feature till next add - * operation - */ - pdev->is_rx_protocol_tagging_enabled = false; - } - - /** Reset stats counter across all rings for given protocol */ - dp_reset_pdev_rx_protocol_tag_stats(pdev_handle, protocol_type); - - pdev->rx_proto_tag_map[protocol_type].tag = tag; - return QDF_STATUS_SUCCESS; } #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ +#ifndef WLAN_SUPPORT_RX_FLOW_TAG +/** + * dp_set_rx_flow_tag - add/delete a flow + * @soc: soc handle + * @pdev_id: id of cdp_pdev handle + * @flow_info: flow tuple that is to be added to/deleted from flow search table + * + * Return: Success + */ +static inline QDF_STATUS +dp_set_rx_flow_tag(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, + struct cdp_rx_flow_info *flow_info) +{ + return QDF_STATUS_SUCCESS; +} +/** + * dp_dump_rx_flow_tag_stats - dump the number of packets tagged for + * given flow 5-tuple + * @cdp_soc: soc handle + * @pdev_id: id of cdp_pdev handle + * @flow_info: flow 5-tuple for which stats should be displayed + * + * Return: Success + */ +static inline QDF_STATUS +dp_dump_rx_flow_tag_stats(struct cdp_soc_t *cdp_soc, uint8_t pdev_id, + struct cdp_rx_flow_info *flow_info) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* WLAN_SUPPORT_RX_FLOW_TAG */ + static QDF_STATUS dp_peer_map_attach_wifi3(struct cdp_soc_t *soc_hdl, uint32_t max_peers, uint32_t max_ast_index, @@ -8883,86 +10062,71 @@ static QDF_STATUS dp_peer_map_attach_wifi3(struct cdp_soc_t *soc_hdl, return QDF_STATUS_SUCCESS; } -/** - * dp_pdev_set_ctrl_pdev() - set ctrl pdev handle in dp pdev - * @dp_pdev: dp pdev handle - * @ctrl_pdev: UMAC ctrl pdev handle - * - * Return: void - */ -static void dp_pdev_set_ctrl_pdev(struct cdp_pdev *dp_pdev, - struct cdp_ctrl_objmgr_pdev *ctrl_pdev) -{ - struct dp_pdev *pdev = (struct dp_pdev *)dp_pdev; - - pdev->ctrl_pdev = ctrl_pdev; -} - -static void dp_set_rate_stats_cap(struct cdp_soc_t *soc_hdl, - uint8_t val) -{ - struct dp_soc *soc = (struct dp_soc *)soc_hdl; - - soc->wlanstats_enabled = val; -} - static void dp_soc_set_rate_stats_ctx(struct cdp_soc_t *soc_handle, void *stats_ctx) { struct dp_soc *soc = (struct dp_soc *)soc_handle; - soc->rate_stats_ctx = stats_ctx; + soc->rate_stats_ctx = (struct cdp_soc_rate_stats_ctx *)stats_ctx; } #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE -static void dp_flush_rate_stats_req(struct cdp_soc_t *soc_hdl, - struct cdp_pdev *pdev_hdl) +static QDF_STATUS dp_flush_rate_stats_req(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_hdl; - struct dp_soc *soc = (struct dp_soc *)pdev->soc; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; struct dp_vdev *vdev = NULL; struct dp_peer *peer = NULL; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); + + if (!pdev) + return QDF_STATUS_E_FAILURE; qdf_spin_lock_bh(&soc->peer_ref_mutex); qdf_spin_lock_bh(&pdev->vdev_list_lock); TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { - if (peer) + if (peer && !peer->bss_peer) dp_wdi_event_handler( WDI_EVENT_FLUSH_RATE_STATS_REQ, - pdev->soc, peer->wlanstats_ctx, + soc, peer->wlanstats_ctx, peer->peer_ids[0], - WDI_NO_VAL, pdev->pdev_id); + WDI_NO_VAL, pdev_id); } } qdf_spin_unlock_bh(&pdev->vdev_list_lock); qdf_spin_unlock_bh(&soc->peer_ref_mutex); + + return QDF_STATUS_SUCCESS; } #else -static inline void +static inline QDF_STATUS dp_flush_rate_stats_req(struct cdp_soc_t *soc_hdl, - struct cdp_pdev *pdev_hdl) + uint8_t pdev_id) { + return QDF_STATUS_SUCCESS; } #endif #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE -static void dp_peer_flush_rate_stats(struct cdp_soc_t *soc, - struct cdp_pdev *pdev_handle, - void *buf) +static QDF_STATUS dp_peer_flush_rate_stats(struct cdp_soc_t *soc, + uint8_t pdev_id, + void *buf) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - dp_wdi_event_handler(WDI_EVENT_PEER_FLUSH_RATE_STATS, - pdev->soc, buf, HTT_INVALID_PEER, - WDI_NO_VAL, pdev->pdev_id); + (struct dp_soc *)soc, buf, HTT_INVALID_PEER, + WDI_NO_VAL, pdev_id); + return QDF_STATUS_SUCCESS; } #else -static inline void +static inline QDF_STATUS dp_peer_flush_rate_stats(struct cdp_soc_t *soc, - struct cdp_pdev *pdev_handle, + uint8_t pdev_id, void *buf) { + return QDF_STATUS_SUCCESS; } #endif @@ -8980,7 +10144,7 @@ static void *dp_soc_get_rate_stats_ctx(struct cdp_soc_t *soc_handle) * * Return: cfg value */ -static uint32_t dp_get_cfg(void *soc, enum cdp_dp_cfg cfg) +static uint32_t dp_get_cfg(struct cdp_soc_t *soc, enum cdp_dp_cfg cfg) { struct dp_soc *dpsoc = (struct dp_soc *)soc; uint32_t value = 0; @@ -8989,9 +10153,19 @@ static uint32_t dp_get_cfg(void *soc, enum cdp_dp_cfg cfg) case cfg_dp_enable_data_stall: value = dpsoc->wlan_cfg_ctx->enable_data_stall_detection; break; + case cfg_dp_enable_p2p_ip_tcp_udp_checksum_offload: + value = dpsoc->wlan_cfg_ctx->p2p_tcp_udp_checksumoffload; + break; + case cfg_dp_enable_nan_ip_tcp_udp_checksum_offload: + value = dpsoc->wlan_cfg_ctx->nan_tcp_udp_checksumoffload; + break; case cfg_dp_enable_ip_tcp_udp_checksum_offload: value = dpsoc->wlan_cfg_ctx->tcp_udp_checksumoffload; break; + case cfg_dp_disable_legacy_mode_csum_offload: + value = dpsoc->wlan_cfg_ctx-> + legacy_mode_checksumoffload_disable; + break; case cfg_dp_tso_enable: value = dpsoc->wlan_cfg_ctx->tso_enabled; break; @@ -9001,6 +10175,15 @@ static uint32_t dp_get_cfg(void *soc, enum cdp_dp_cfg cfg) case cfg_dp_gro_enable: value = dpsoc->wlan_cfg_ctx->gro_enabled; break; + case cfg_dp_sg_enable: + value = dpsoc->wlan_cfg_ctx->sg_enabled; + break; + case cfg_dp_tc_based_dyn_gro_enable: + value = dpsoc->wlan_cfg_ctx->tc_based_dynamic_gro; + break; + case cfg_dp_tc_ingress_prio: + value = dpsoc->wlan_cfg_ctx->tc_ingress_prio; + break; case cfg_dp_tx_flow_start_queue_offset: value = dpsoc->wlan_cfg_ctx->tx_flow_start_queue_offset; break; @@ -9013,6 +10196,9 @@ static uint32_t dp_get_cfg(void *soc, enum cdp_dp_cfg cfg) case cfg_dp_pktlog_buffer_size: value = dpsoc->wlan_cfg_ctx->pktlog_buffer_size; break; + case cfg_dp_wow_check_rx_pending: + value = dpsoc->wlan_cfg_ctx->wow_check_rx_pending_enable; + break; default: value = 0; } @@ -9020,10 +10206,11 @@ static uint32_t dp_get_cfg(void *soc, enum cdp_dp_cfg cfg) return value; } -#ifdef CONFIG_WIN +#ifdef PEER_FLOW_CONTROL /** * dp_tx_flow_ctrl_configure_pdev() - Configure flow control params - * @pdev_hdl: datapath pdev handle + * @soc_handle: datapath soc handle + * @pdev_id: id of datapath pdev handle * @param: ol ath params * @value: value of the flag * @buff: Buffer to be passed @@ -9033,12 +10220,15 @@ static uint32_t dp_get_cfg(void *soc, enum cdp_dp_cfg cfg) * * Return: 0 for success. nonzero for failure. */ -static uint32_t dp_tx_flow_ctrl_configure_pdev(void *pdev_handle, +static uint32_t dp_tx_flow_ctrl_configure_pdev(struct cdp_soc_t *soc_handle, + uint8_t pdev_id, enum _ol_ath_param_t param, uint32_t value, void *buff) { - struct dp_soc *soc = NULL; - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + struct dp_soc *soc = (struct dp_soc *)soc_handle; + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); if (qdf_unlikely(!pdev)) return 1; @@ -9048,6 +10238,7 @@ static uint32_t dp_tx_flow_ctrl_configure_pdev(void *pdev_handle, return 1; switch (param) { +#ifdef QCA_ENH_V3_STATS_SUPPORT case OL_ATH_PARAM_VIDEO_DELAY_STATS_FC: if (value) pdev->delay_stats_flag = true; @@ -9060,6 +10251,7 @@ static uint32_t dp_tx_flow_ctrl_configure_pdev(void *pdev_handle, qdf_print("------ Delay Stats ------\n"); dp_pdev_print_delay_stats(pdev); break; +#endif case OL_ATH_PARAM_TOTAL_Q_SIZE: { uint32_t tx_min, tx_max; @@ -9094,17 +10286,18 @@ static uint32_t dp_tx_flow_ctrl_configure_pdev(void *pdev_handle, /** * dp_set_pdev_pcp_tid_map_wifi3(): update pcp tid map in pdev - * @vdev: DP_PDEV handle + * @psoc: dp soc handle + * @pdev_id: id of DP_PDEV handle * @pcp: pcp value * @tid: tid value passed by the user * * Return: QDF_STATUS_SUCCESS on success */ -static QDF_STATUS dp_set_pdev_pcp_tid_map_wifi3(struct cdp_pdev *pdev_handle, +static QDF_STATUS dp_set_pdev_pcp_tid_map_wifi3(ol_txrx_soc_handle psoc, + uint8_t pdev_id, uint8_t pcp, uint8_t tid) { - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = (struct dp_soc *)psoc; soc->pcp_tid_map[pcp] = tid; @@ -9112,73 +10305,27 @@ static QDF_STATUS dp_set_pdev_pcp_tid_map_wifi3(struct cdp_pdev *pdev_handle, return QDF_STATUS_SUCCESS; } -/** - * dp_set_pdev_tidmap_prty_wifi3(): update tidmap priority in pdev - * @vdev: DP_PDEV handle - * @prio: tidmap priority value passed by the user - * - * Return: QDF_STATUS_SUCCESS on success - */ -static QDF_STATUS dp_set_pdev_tidmap_prty_wifi3(struct cdp_pdev *pdev_handle, - uint8_t prio) -{ - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - struct dp_soc *soc = pdev->soc; - - soc->tidmap_prty = prio; - - hal_tx_set_tidmap_prty(soc->hal_soc, prio); - return QDF_STATUS_SUCCESS; -} - /** * dp_set_vdev_pcp_tid_map_wifi3(): update pcp tid map in vdev - * @vdev: DP_VDEV handle + * @soc: DP soc handle + * @vdev_id: id of DP_VDEV handle * @pcp: pcp value * @tid: tid value passed by the user * * Return: QDF_STATUS_SUCCESS on success */ -static QDF_STATUS dp_set_vdev_pcp_tid_map_wifi3(struct cdp_vdev *vdev_handle, +static QDF_STATUS dp_set_vdev_pcp_tid_map_wifi3(struct cdp_soc_t *soc, + uint8_t vdev_id, uint8_t pcp, uint8_t tid) { - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - - vdev->pcp_tid_map[pcp] = tid; - - return QDF_STATUS_SUCCESS; -} - -/** - * dp_set_vdev_tidmap_tbl_id_wifi3(): update tidmapi tbl id in vdev - * @vdev: DP_VDEV handle - * @mapid: map_id value passed by the user - * - * Return: QDF_STATUS_SUCCESS on success - */ -static QDF_STATUS dp_set_vdev_tidmap_tbl_id_wifi3(struct cdp_vdev *vdev_handle, - uint8_t mapid) -{ - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; - - vdev->tidmap_tbl_id = mapid; - - return QDF_STATUS_SUCCESS; -} + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); -/** - * dp_set_vdev_tidmap_prty_wifi3(): update tidmap priority in vdev - * @vdev: DP_VDEV handle - * @prio: tidmap priority value passed by the user - * - * Return: QDF_STATUS_SUCCESS on success - */ -static QDF_STATUS dp_set_vdev_tidmap_prty_wifi3(struct cdp_vdev *vdev_handle, - uint8_t prio) -{ - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; + if (!vdev) + return QDF_STATUS_E_FAILURE; - vdev->tidmap_prty = prio; + vdev->pcp_tid_map[pcp] = tid; return QDF_STATUS_SUCCESS; } @@ -9208,14 +10355,12 @@ static struct cdp_cmn_ops dp_ops_cmn = { dp_peer_ast_entry_del_by_pdev, .txrx_peer_delete = dp_peer_delete_wifi3, .txrx_vdev_register = dp_vdev_register_wifi3, - .txrx_vdev_flush_peers = dp_vdev_flush_peers, .txrx_soc_detach = dp_soc_detach_wifi3, .txrx_soc_deinit = dp_soc_deinit_wifi3, .txrx_soc_init = dp_soc_init_wifi3, .txrx_tso_soc_attach = dp_tso_soc_attach, .txrx_tso_soc_detach = dp_tso_soc_detach, .txrx_get_vdev_mac_addr = dp_get_vdev_mac_addr_wifi3, - .txrx_get_vdev_from_vdev_id = dp_get_vdev_from_vdev_id_wifi3, .txrx_get_mon_vdev_from_pdev = dp_get_mon_vdev_from_pdev_wifi3, .txrx_get_ctrl_pdev_from_vdev = dp_get_ctrl_pdev_from_vdev_wifi3, .txrx_ath_getstats = dp_get_device_stats, @@ -9224,26 +10369,15 @@ static struct cdp_cmn_ops dp_ops_cmn = { .addba_resp_tx_completion = dp_addba_resp_tx_completion_wifi3, .delba_process = dp_delba_process_wifi3, .set_addba_response = dp_set_addba_response, - .get_peer_mac_addr_frm_id = dp_get_peer_mac_addr_frm_id, .flush_cache_rx_queue = NULL, /* TODO: get API's for dscp-tid need to be added*/ .set_vdev_dscp_tid_map = dp_set_vdev_dscp_tid_map_wifi3, .set_pdev_dscp_tid_map = dp_set_pdev_dscp_tid_map_wifi3, - .hmmc_tid_override_en = dp_hmmc_tid_override_en_wifi3, - .set_hmmc_tid_val = dp_set_hmmc_tid_val_wifi3, .txrx_get_total_per = dp_get_total_per, .txrx_stats_request = dp_txrx_stats_request, .txrx_set_monitor_mode = dp_vdev_set_monitor_mode, - .txrx_get_pdev_id_frm_pdev = dp_get_pdev_id_frm_pdev, - .txrx_get_vow_config_frm_pdev = dp_get_delay_stats_flag, - .txrx_pdev_set_chan_noise_floor = dp_pdev_set_chan_noise_floor, - .txrx_set_nac = dp_set_nac, - .txrx_get_tx_pending = dp_get_tx_pending, - .txrx_set_pdev_tx_capture = dp_config_debug_sniffer, .txrx_get_peer_mac_from_peer_id = dp_get_peer_mac_from_peer_id, .display_stats = dp_txrx_dump_stats, - .txrx_soc_set_nss_cfg = dp_soc_set_nss_cfg_wifi3, - .txrx_soc_get_nss_cfg = dp_soc_get_nss_cfg_wifi3, .txrx_intr_attach = dp_soc_interrupt_attach_wrapper, .txrx_intr_detach = dp_soc_interrupt_detach, .set_pn_check = dp_set_pn_check_wifi3, @@ -9253,9 +10387,13 @@ static struct cdp_cmn_ops dp_ops_cmn = { .txrx_data_tx_cb_set = dp_txrx_data_tx_cb_set, .get_dp_txrx_handle = dp_pdev_get_dp_txrx_handle, .set_dp_txrx_handle = dp_pdev_set_dp_txrx_handle, + .get_vdev_dp_ext_txrx_handle = dp_vdev_get_dp_ext_handle, + .set_vdev_dp_ext_txrx_handle = dp_vdev_set_dp_ext_handle, .get_soc_dp_txrx_handle = dp_soc_get_dp_txrx_handle, .set_soc_dp_txrx_handle = dp_soc_set_dp_txrx_handle, .map_pdev_to_lmac = dp_soc_map_pdev_to_lmac, + .handle_mode_change = dp_soc_handle_pdev_mode_change, + .set_pdev_status_down = dp_soc_set_pdev_status_down, .txrx_set_ba_aging_timeout = dp_set_ba_aging_timeout, .txrx_get_ba_aging_timeout = dp_get_ba_aging_timeout, .tx_send = dp_tx_send, @@ -9263,7 +10401,6 @@ static struct cdp_cmn_ops dp_ops_cmn = { .txrx_peer_reset_ast_table = dp_wds_reset_ast_table_wifi3, .txrx_peer_flush_ast_table = dp_wds_flush_ast_table_wifi3, .txrx_peer_map_attach = dp_peer_map_attach_wifi3, - .txrx_pdev_set_ctrl_pdev = dp_pdev_set_ctrl_pdev, .txrx_get_os_rx_handles_from_vdev = dp_get_os_rx_handles_from_vdev_wifi3, .delba_tx_completion = dp_delba_tx_completion_wifi3, @@ -9275,37 +10412,48 @@ static struct cdp_cmn_ops dp_ops_cmn = { .txrx_flush_rate_stats_request = dp_flush_rate_stats_req, .set_pdev_pcp_tid_map = dp_set_pdev_pcp_tid_map_wifi3, - .set_pdev_tidmap_prty = dp_set_pdev_tidmap_prty_wifi3, .set_vdev_pcp_tid_map = dp_set_vdev_pcp_tid_map_wifi3, - .set_vdev_tidmap_prty = dp_set_vdev_tidmap_prty_wifi3, - .set_vdev_tidmap_tbl_id = dp_set_vdev_tidmap_tbl_id_wifi3, .txrx_cp_peer_del_response = dp_cp_peer_del_resp_handler, +#ifdef QCA_MULTIPASS_SUPPORT + .set_vlan_groupkey = dp_set_vlan_groupkey, +#endif + .get_peer_mac_list = dp_get_peer_mac_list, + .tx_send_exc = dp_tx_send_exception, }; static struct cdp_ctrl_ops dp_ops_ctrl = { .txrx_peer_authorize = dp_peer_authorize, - .txrx_set_vdev_rx_decap_type = dp_set_vdev_rx_decap_type, - .txrx_set_tx_encap_type = dp_set_vdev_tx_encap_type, -#ifdef MESH_MODE_SUPPORT - .txrx_set_mesh_mode = dp_peer_set_mesh_mode, - .txrx_set_mesh_rx_filter = dp_peer_set_mesh_rx_filter, +#ifdef VDEV_PEER_PROTOCOL_COUNT + .txrx_enable_peer_protocol_count = dp_enable_vdev_peer_protocol_count, + .txrx_set_peer_protocol_drop_mask = + dp_enable_vdev_peer_protocol_drop_mask, + .txrx_is_peer_protocol_count_enabled = + dp_is_vdev_peer_protocol_count_enabled, + .txrx_get_peer_protocol_drop_mask = dp_get_vdev_peer_protocol_drop_mask, #endif .txrx_set_vdev_param = dp_set_vdev_param, - .txrx_peer_set_nawds = dp_peer_set_nawds, + .txrx_set_psoc_param = dp_set_psoc_param, + .txrx_get_psoc_param = dp_get_psoc_param, .txrx_set_pdev_reo_dest = dp_set_pdev_reo_dest, .txrx_get_pdev_reo_dest = dp_get_pdev_reo_dest, - .txrx_set_filter_neighbour_peers = dp_set_filter_neighbour_peers, +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) .txrx_update_filter_neighbour_peers = dp_update_filter_neighbour_peers, +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ .txrx_get_sec_type = dp_get_sec_type, - /* TODO: Add other functions */ .txrx_wdi_event_sub = dp_wdi_event_sub, .txrx_wdi_event_unsub = dp_wdi_event_unsub, #ifdef WDI_EVENT_ENABLE .txrx_get_pldev = dp_get_pldev, #endif .txrx_set_pdev_param = dp_set_pdev_param, + .txrx_get_pdev_param = dp_get_pdev_param, + .txrx_set_peer_param = dp_set_peer_param, + .txrx_get_peer_param = dp_get_peer_param, +#ifdef VDEV_PEER_PROTOCOL_COUNT + .txrx_peer_protocol_cnt = dp_peer_stats_update_protocol_cnt, +#endif #ifdef ATH_SUPPORT_NAC_RSSI .txrx_vdev_config_for_nac_rssi = dp_config_for_nac_rssi, .txrx_vdev_get_neighbour_rssi = dp_vdev_get_neighbour_rssi, @@ -9321,6 +10469,17 @@ static struct cdp_ctrl_ops dp_ops_ctrl = { dp_dump_pdev_rx_protocol_tag_stats, #endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */ #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ +#ifdef WLAN_SUPPORT_RX_FLOW_TAG + .txrx_set_rx_flow_tag = dp_set_rx_flow_tag, + .txrx_dump_rx_flow_tag_stats = dp_dump_rx_flow_tag_stats, +#endif /* WLAN_SUPPORT_RX_FLOW_TAG */ +#ifdef QCA_MULTIPASS_SUPPORT + .txrx_peer_set_vlan_id = dp_peer_set_vlan_id, +#endif /*QCA_MULTIPASS_SUPPORT*/ +#if defined(WLAN_TX_PKT_CAPTURE_ENH) || defined(WLAN_RX_PKT_CAPTURE_ENH) + .txrx_update_peer_pkt_capture_params = + dp_peer_update_pkt_capture_params, +#endif /* WLAN_TX_PKT_CAPTURE_ENH || WLAN_RX_PKT_CAPTURE_ENH */ }; static struct cdp_me_ops dp_ops_me = { @@ -9332,31 +10491,27 @@ static struct cdp_me_ops dp_ops_me = { }; static struct cdp_mon_ops dp_ops_mon = { - .txrx_monitor_set_filter_ucast_data = NULL, - .txrx_monitor_set_filter_mcast_data = NULL, - .txrx_monitor_set_filter_non_data = NULL, - .txrx_monitor_get_filter_ucast_data = dp_vdev_get_filter_ucast_data, - .txrx_monitor_get_filter_mcast_data = dp_vdev_get_filter_mcast_data, - .txrx_monitor_get_filter_non_data = dp_vdev_get_filter_non_data, .txrx_reset_monitor_mode = dp_reset_monitor_mode, /* Added support for HK advance filter */ .txrx_set_advance_monitor_filter = dp_pdev_set_advance_monitor_filter, - .txrx_monitor_record_channel = dp_pdev_set_monitor_channel, + .txrx_deliver_tx_mgmt = dp_deliver_tx_mgmt, }; static struct cdp_host_stats_ops dp_ops_host_stats = { .txrx_per_peer_stats = dp_get_host_peer_stats, .get_fw_peer_stats = dp_get_fw_peer_stats, .get_htt_stats = dp_get_htt_stats, +#ifdef FEATURE_PERPKT_INFO .txrx_enable_enhanced_stats = dp_enable_enhanced_stats, .txrx_disable_enhanced_stats = dp_disable_enhanced_stats, +#endif /* FEATURE_PERPKT_INFO */ .txrx_stats_publish = dp_txrx_stats_publish, .txrx_get_vdev_stats = dp_txrx_get_vdev_stats, .txrx_get_peer_stats = dp_txrx_get_peer_stats, + .txrx_get_peer_stats_param = dp_txrx_get_peer_stats_param, .txrx_reset_peer_stats = dp_txrx_reset_peer_stats, .txrx_get_pdev_stats = dp_txrx_get_pdev_stats, .txrx_get_ratekbps = dp_txrx_get_ratekbps, - .configure_rate_stats = dp_set_rate_stats_cap, .txrx_update_vdev_stats = dp_txrx_update_vdev_host_stats, /* TODO */ }; @@ -9365,39 +10520,24 @@ static struct cdp_raw_ops dp_ops_raw = { /* TODO */ }; -#ifdef CONFIG_WIN +#ifdef PEER_FLOW_CONTROL static struct cdp_pflow_ops dp_ops_pflow = { dp_tx_flow_ctrl_configure_pdev, }; #endif /* CONFIG_WIN */ -#ifdef FEATURE_RUNTIME_PM -/** - * dp_runtime_suspend() - ensure DP is ready to runtime suspend - * @opaque_pdev: DP pdev context - * - * DP is ready to runtime suspend if there are no pending TX packets. - * - * Return: QDF_STATUS - */ -static QDF_STATUS dp_runtime_suspend(struct cdp_pdev *opaque_pdev) -{ - struct dp_pdev *pdev = (struct dp_pdev *)opaque_pdev; - struct dp_soc *soc = pdev->soc; - - /* Abort if there are any pending TX packets */ - if (dp_get_tx_pending(opaque_pdev) > 0) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - FL("Abort suspend due to pending TX packets")); - return QDF_STATUS_E_AGAIN; - } - - if (soc->intr_mode == DP_INTR_POLL) - qdf_timer_stop(&soc->int_timer); - - return QDF_STATUS_SUCCESS; -} +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) +static struct cdp_cfr_ops dp_ops_cfr = { + .txrx_cfr_filter = dp_cfr_filter, + .txrx_get_cfr_rcc = dp_get_cfr_rcc, + .txrx_set_cfr_rcc = dp_set_cfr_rcc, + .txrx_get_cfr_dbg_stats = dp_get_cfr_dbg_stats, + .txrx_clear_cfr_dbg_stats = dp_clear_cfr_dbg_stats, + .txrx_enable_mon_reap_timer = dp_enable_mon_reap_timer, +}; +#endif +#ifdef FEATURE_RUNTIME_PM /** * dp_flush_ring_hptp() - Update ring shadow * register HP/TP address when runtime @@ -9407,10 +10547,8 @@ static QDF_STATUS dp_runtime_suspend(struct cdp_pdev *opaque_pdev) * Return: None */ static -void dp_flush_ring_hptp(struct dp_soc *soc, void *hal_ring) +void dp_flush_ring_hptp(struct dp_soc *soc, hal_ring_handle_t hal_srng) { - struct hal_srng *hal_srng = (struct hal_srng *)hal_ring; - if (hal_srng && hal_srng_get_clear_event(hal_srng, HAL_SRNG_FLUSH_EVENT)) { /* Acquire the lock */ @@ -9419,26 +10557,91 @@ void dp_flush_ring_hptp(struct dp_soc *soc, void *hal_ring) hal_srng_access_end(soc->hal_soc, hal_srng); hal_srng_set_flush_last_ts(hal_srng); + dp_debug("flushed"); + } +} + +/** + * dp_runtime_suspend() - ensure DP is ready to runtime suspend + * @soc_hdl: Datapath soc handle + * @pdev_id: id of data path pdev handle + * + * DP is ready to runtime suspend if there are no pending TX packets. + * + * Return: QDF_STATUS + */ +static QDF_STATUS dp_runtime_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev; + uint8_t i; + + pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + if (!pdev) { + dp_err("pdev is NULL"); + return QDF_STATUS_E_INVAL; + } + + /* Abort if there are any pending TX packets */ + if (dp_get_tx_pending(dp_pdev_to_cdp_pdev(pdev)) > 0) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + FL("Abort suspend due to pending TX packets")); + + /* perform a force flush if tx is pending */ + for (i = 0; i < soc->num_tcl_data_rings; i++) { +#ifdef IPA_OFFLOAD + if (i == IPA_TCL_DATA_RING_IDX) + continue; +#endif + hal_srng_set_event(soc->tcl_data_ring[i].hal_srng, + HAL_SRNG_FLUSH_EVENT); + dp_flush_ring_hptp(soc, soc->tcl_data_ring[i].hal_srng); + } + + return QDF_STATUS_E_AGAIN; + } + + if (dp_runtime_get_refcount(soc)) { + dp_info("refcount: %d", dp_runtime_get_refcount(soc)); + + return QDF_STATUS_E_AGAIN; } + + if (soc->intr_mode == DP_INTR_POLL) + qdf_timer_stop(&soc->int_timer); + + return QDF_STATUS_SUCCESS; } +#define DP_FLUSH_WAIT_CNT 10 +#define DP_RUNTIME_SUSPEND_WAIT_MS 10 /** * dp_runtime_resume() - ensure DP is ready to runtime resume - * @opaque_pdev: DP pdev context + * @soc_hdl: Datapath soc handle + * @pdev_id: id of data path pdev handle * * Resume DP for runtime PM. * * Return: QDF_STATUS */ -static QDF_STATUS dp_runtime_resume(struct cdp_pdev *opaque_pdev) +static QDF_STATUS dp_runtime_resume(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)opaque_pdev; - struct dp_soc *soc = pdev->soc; - int i; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + int i, suspend_wait = 0; if (soc->intr_mode == DP_INTR_POLL) qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS); + /* + * Wait until dp runtime refcount becomes zero or time out, then flush + * pending tx for runtime suspend. + */ + while (dp_runtime_get_refcount(soc) && + suspend_wait < DP_FLUSH_WAIT_CNT) { + qdf_sleep(DP_RUNTIME_SUSPEND_WAIT_MS); + suspend_wait++; + } + for (i = 0; i < MAX_TCL_DATA_RINGS; i++) { dp_flush_ring_hptp(soc, soc->tcl_data_ring[i].hal_srng); } @@ -9451,20 +10654,20 @@ static QDF_STATUS dp_runtime_resume(struct cdp_pdev *opaque_pdev) /** * dp_tx_get_success_ack_stats() - get tx success completion count - * @opaque_pdev: dp pdev context + * @soc_hdl: Datapath soc handle * @vdevid: vdev identifier * * Return: tx success ack count */ -static uint32_t dp_tx_get_success_ack_stats(struct cdp_pdev *pdev, +static uint32_t dp_tx_get_success_ack_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) { - struct dp_vdev *vdev = - (struct dp_vdev *)dp_get_vdev_from_vdev_id_wifi3(pdev, - vdev_id); - struct dp_soc *soc = ((struct dp_pdev *)pdev)->soc; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct cdp_vdev_stats *vdev_stats = NULL; uint32_t tx_success; + struct dp_vdev *vdev = + (struct dp_vdev *)dp_get_vdev_from_soc_vdev_id_wifi3(soc, + vdev_id); if (!vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -9492,49 +10695,59 @@ static uint32_t dp_tx_get_success_ack_stats(struct cdp_pdev *pdev, #ifdef WLAN_SUPPORT_DATA_STALL /** * dp_register_data_stall_detect_cb() - register data stall callback - * @opaque_pdev: DP pdev context + * @soc_hdl: Datapath soc handle + * @pdev_id: id of data path pdev handle * @data_stall_detect_callback: data stall callback function * * Return: QDF_STATUS Enumeration */ -static QDF_STATUS dp_register_data_stall_detect_cb( - struct cdp_pdev *opaque_pdev, - data_stall_detect_cb data_stall_detect_callback) +static +QDF_STATUS dp_register_data_stall_detect_cb( + struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + data_stall_detect_cb data_stall_detect_callback) { - struct dp_pdev *pdev = (struct dp_pdev *)opaque_pdev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev; + pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); if (!pdev) { dp_err("pdev NULL!"); return QDF_STATUS_E_INVAL; } + pdev->data_stall_detect_callback = data_stall_detect_callback; return QDF_STATUS_SUCCESS; } /** * dp_deregister_data_stall_detect_cb() - de-register data stall callback - * @opaque_pdev: DP pdev context + * @soc_hdl: Datapath soc handle + * @pdev_id: id of data path pdev handle * @data_stall_detect_callback: data stall callback function * * Return: QDF_STATUS Enumeration */ -static QDF_STATUS dp_deregister_data_stall_detect_cb( - struct cdp_pdev *opaque_pdev, - data_stall_detect_cb data_stall_detect_callback) +static +QDF_STATUS dp_deregister_data_stall_detect_cb( + struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + data_stall_detect_cb data_stall_detect_callback) { - struct dp_pdev *pdev = (struct dp_pdev *)opaque_pdev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev; + pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); if (!pdev) { dp_err("pdev NULL!"); return QDF_STATUS_E_INVAL; } + pdev->data_stall_detect_callback = NULL; return QDF_STATUS_SUCCESS; } /** * dp_txrx_post_data_stall_event() - post data stall event - * @opaque_pdev: DP pdev context + * @soc_hdl: Datapath soc handle * @indicator: Module triggering data stall * @data_stall_type: data stall event type * @pdev_id: pdev id @@ -9543,17 +10756,18 @@ static QDF_STATUS dp_deregister_data_stall_detect_cb( * * Return: None */ -static void dp_txrx_post_data_stall_event( - struct cdp_pdev *opaque_pdev, - enum data_stall_log_event_indicator indicator, - enum data_stall_log_event_type data_stall_type, - uint32_t pdev_id, uint32_t vdev_id_bitmap, - enum data_stall_log_recovery_type recovery_type) +static void +dp_txrx_post_data_stall_event(struct cdp_soc_t *soc_hdl, + enum data_stall_log_event_indicator indicator, + enum data_stall_log_event_type data_stall_type, + uint32_t pdev_id, uint32_t vdev_id_bitmap, + enum data_stall_log_recovery_type recovery_type) { + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct data_stall_event_info data_stall_info; struct dp_pdev *pdev; - pdev = (struct dp_pdev *)opaque_pdev; + pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); if (!pdev) { dp_err("pdev NULL!"); return; @@ -9577,6 +10791,7 @@ static void dp_txrx_post_data_stall_event( } #endif /* WLAN_SUPPORT_DATA_STALL */ +#ifdef DP_PEER_EXTENDED_API /** * dp_peer_get_ref_find_by_addr - get peer with addr by ref count inc * @dev: physical device instance @@ -9587,7 +10802,6 @@ static void dp_txrx_post_data_stall_event( */ static void * dp_peer_get_ref_find_by_addr(struct cdp_pdev *dev, uint8_t *peer_mac_addr, - uint8_t *local_id, enum peer_debug_id_type debug_id) { struct dp_pdev *pdev = (struct dp_pdev *)dev; @@ -9604,35 +10818,36 @@ dp_peer_get_ref_find_by_addr(struct cdp_pdev *dev, uint8_t *peer_mac_addr, return NULL; } - *local_id = peer->local_id; - dp_info_rl("peer %pK mac: %pM", peer, peer->mac_addr.raw); + dp_info_rl("peer %pK mac: "QDF_MAC_ADDR_FMT, peer, + QDF_MAC_ADDR_REF(peer->mac_addr.raw)); return peer; } +#endif /* DP_PEER_EXTENDED_API */ #ifdef WLAN_FEATURE_STATS_EXT /* rx hw stats event wait timeout in ms */ #define DP_REO_STATUS_STATS_TIMEOUT 1500 /** * dp_txrx_ext_stats_request - request dp txrx extended stats request - * @ppdev: pdev handle + * @soc_hdl: soc handle + * @pdev_id: pdev id * @req: stats request * * Return: QDF_STATUS */ static QDF_STATUS -dp_txrx_ext_stats_request(struct cdp_pdev *ppdev, +dp_txrx_ext_stats_request(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, struct cdp_txrx_ext_stats *req) { - struct dp_pdev *pdev = (struct dp_pdev *)ppdev; - struct dp_soc *soc = NULL; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); if (!pdev) { dp_err("pdev is null"); return QDF_STATUS_E_INVAL; } - soc = pdev->soc; dp_aggregate_pdev_stats(pdev); req->tx_msdu_enqueue = pdev->stats.tx_i.processed.num; @@ -9640,8 +10855,8 @@ dp_txrx_ext_stats_request(struct cdp_pdev *ppdev, req->rx_mpdu_received = soc->ext_stats.rx_mpdu_received; req->rx_mpdu_delivered = soc->ext_stats.rx_mpdu_received; req->rx_mpdu_missed = soc->ext_stats.rx_mpdu_missed; - req->rx_mpdu_error = soc->stats.rx.err_ring_pkts - - soc->stats.rx.rx_frags; + /* only count error source from RXDMA */ + req->rx_mpdu_error = pdev->stats.err.rxdma_error; return QDF_STATUS_SUCCESS; } @@ -9684,7 +10899,7 @@ static void dp_rx_hw_stats_cb(struct dp_soc *soc, void *cb_ctxt, soc->ext_stats.rx_mpdu_received += queue_status->mpdu_frms_cnt; soc->ext_stats.rx_mpdu_missed += - queue_status->late_recv_mpdu_cnt; + queue_status->hole_cnt; } qdf_spin_unlock_bh(&soc->rx_hw_stats_lock); } @@ -9692,7 +10907,7 @@ static void dp_rx_hw_stats_cb(struct dp_soc *soc, void *cb_ctxt, /** * dp_request_rx_hw_stats - request rx hardware stats * @soc_hdl: soc handle - * @pvdev: vdev handle + * @vdev_id: vdev id * * Return: None */ @@ -9700,13 +10915,13 @@ static QDF_STATUS dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) { struct dp_soc *soc = (struct dp_soc *)soc_hdl; - struct dp_vdev *vdev = - dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); struct dp_peer *peer; - uint8_t local_id = 0; QDF_STATUS status; struct dp_req_rx_hw_stats_t *rx_hw_stats; int rx_stats_sent_cnt = 0; + uint32_t last_rx_mpdu_received; + uint32_t last_rx_mpdu_missed; if (!vdev) { dp_err("vdev is null for vdev_id: %u", vdev_id); @@ -9714,9 +10929,7 @@ dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) } peer = dp_peer_get_ref_find_by_addr((struct cdp_pdev *)vdev->pdev, - vdev->vap_bss_peer_mac_addr, - &local_id, - 0); + vdev->vap_bss_peer_mac_addr, 0); if (!peer) { dp_err("Peer is NULL"); @@ -9733,6 +10946,12 @@ dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) qdf_event_reset(&soc->rx_hw_stats_event); qdf_spin_lock_bh(&soc->rx_hw_stats_lock); + /* save the last soc cumulative stats and reset it to 0 */ + last_rx_mpdu_received = soc->ext_stats.rx_mpdu_received; + last_rx_mpdu_missed = soc->ext_stats.rx_mpdu_missed; + soc->ext_stats.rx_mpdu_received = 0; + soc->ext_stats.rx_mpdu_missed = 0; + rx_stats_sent_cnt = dp_peer_rxtid_stats(peer, dp_rx_hw_stats_cb, rx_hw_stats); if (!rx_stats_sent_cnt) { @@ -9756,6 +10975,12 @@ dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) dp_info("rx hw stats event timeout"); if (soc->is_last_stats_ctx_init) rx_hw_stats->is_query_timeout = true; + /** + * If query timeout happened, use the last saved stats + * for this time query. + */ + soc->ext_stats.rx_mpdu_received = last_rx_mpdu_received; + soc->ext_stats.rx_mpdu_missed = last_rx_mpdu_missed; } qdf_spin_unlock_bh(&soc->rx_hw_stats_lock); dp_peer_unref_delete(peer); @@ -9764,7 +10989,7 @@ dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) } #endif /* WLAN_FEATURE_STATS_EXT */ -#ifndef CONFIG_WIN +#ifdef DP_PEER_EXTENDED_API static struct cdp_misc_ops dp_ops_misc = { #ifdef FEATURE_WLAN_TDLS .tx_non_std = dp_tx_non_std, @@ -9789,7 +11014,9 @@ static struct cdp_misc_ops dp_ops_misc = { .request_rx_hw_stats = dp_request_rx_hw_stats, #endif /* WLAN_FEATURE_STATS_EXT */ }; +#endif +#ifdef DP_FLOW_CTL static struct cdp_flowctl_ops dp_ops_flowctl = { /* WIFI 3.0 DP implement as required. */ #ifdef QCA_LL_TX_FLOW_CONTROL_V2 @@ -9804,6 +11031,7 @@ static struct cdp_flowctl_ops dp_ops_flowctl = { static struct cdp_lflowctl_ops dp_ops_l_flowctl = { /* WIFI 3.0 DP NOT IMPLEMENTED YET */ }; +#endif #ifdef IPA_OFFLOAD static struct cdp_ipa_ops dp_ops_ipa = { @@ -9826,15 +11054,21 @@ static struct cdp_ipa_ops dp_ops_ipa = { }; #endif -static QDF_STATUS dp_bus_suspend(struct cdp_pdev *opaque_pdev) +#ifdef DP_POWER_SAVE +static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)opaque_pdev; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); int timeout = SUSPEND_DRAIN_WAIT; int drain_wait_delay = 50; /* 50 ms */ + if (qdf_unlikely(!pdev)) { + dp_err("pdev is NULL"); + return QDF_STATUS_E_INVAL; + } + /* Abort if there are any pending TX packets */ - while (dp_get_tx_pending(opaque_pdev) > 0) { + while (dp_get_tx_pending((struct cdp_pdev *)pdev) > 0) { qdf_sleep(drain_wait_delay); if (timeout <= 0) { dp_err("TX frames are pending, abort suspend"); @@ -9847,7 +11081,8 @@ static QDF_STATUS dp_bus_suspend(struct cdp_pdev *opaque_pdev) qdf_timer_stop(&soc->int_timer); /* Stop monitor reap timer and reap any pending frames in ring */ - if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED && + if (((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) || + dp_is_enable_reap_timer_non_pkt(pdev)) && soc->reap_timer_init) { qdf_timer_sync_cancel(&soc->mon_reap_timer); dp_service_mon_rings(soc, DP_MON_REAP_BUDGET); @@ -9856,16 +11091,22 @@ static QDF_STATUS dp_bus_suspend(struct cdp_pdev *opaque_pdev) return QDF_STATUS_SUCCESS; } -static QDF_STATUS dp_bus_resume(struct cdp_pdev *opaque_pdev) +static QDF_STATUS dp_bus_resume(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)opaque_pdev; - struct dp_soc *soc = pdev->soc; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (qdf_unlikely(!pdev)) { + dp_err("pdev is NULL"); + return QDF_STATUS_E_INVAL; + } if (soc->intr_mode == DP_INTR_POLL) qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS); /* Start monitor reap timer */ - if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED && + if (((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) || + dp_is_enable_reap_timer_non_pkt(pdev)) && soc->reap_timer_init) qdf_timer_mod(&soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS); @@ -9876,22 +11117,27 @@ static QDF_STATUS dp_bus_resume(struct cdp_pdev *opaque_pdev) /** * dp_process_wow_ack_rsp() - process wow ack response * @soc_hdl: datapath soc handle - * @opaque_pdev: data path pdev handle + * @pdev_id: data path pdev handle id * * Return: none */ -static void dp_process_wow_ack_rsp(struct cdp_soc_t *soc_hdl, - struct cdp_pdev *opaque_pdev) +static void dp_process_wow_ack_rsp(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) { - struct dp_soc *soc = (struct dp_soc *)soc_hdl; - struct dp_pdev *pdev = (struct dp_pdev *)opaque_pdev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (qdf_unlikely(!pdev)) { + dp_err("pdev is NULL"); + return; + } /* * As part of wow enable FW disables the mon status ring and in wow ack * response from FW reap mon status ring to make sure no packets pending * in the ring. */ - if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED && + if (((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) || + dp_is_enable_reap_timer_non_pkt(pdev)) && soc->reap_timer_init) { dp_service_mon_rings(soc, DP_MON_REAP_BUDGET); } @@ -9905,10 +11151,10 @@ static void dp_process_wow_ack_rsp(struct cdp_soc_t *soc_hdl, * Return: none */ static void dp_process_target_suspend_req(struct cdp_soc_t *soc_hdl, - struct cdp_pdev *opaque_pdev) + uint8_t pdev_id) { - struct dp_soc *soc = (struct dp_soc *)soc_hdl; - struct dp_pdev *pdev = (struct dp_pdev *)opaque_pdev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); if (qdf_unlikely(!pdev)) { dp_err("pdev is NULL"); @@ -9916,7 +11162,8 @@ static void dp_process_target_suspend_req(struct cdp_soc_t *soc_hdl, } /* Stop monitor reap timer and reap any pending frames in ring */ - if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED && + if (((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) || + dp_is_enable_reap_timer_non_pkt(pdev)) && soc->reap_timer_init) { qdf_timer_sync_cancel(&soc->mon_reap_timer); dp_service_mon_rings(soc, DP_MON_REAP_BUDGET); @@ -9929,52 +11176,39 @@ static struct cdp_bus_ops dp_ops_bus = { .process_wow_ack_rsp = dp_process_wow_ack_rsp, .process_target_suspend_req = dp_process_target_suspend_req }; +#endif -static struct cdp_ocb_ops dp_ops_ocb = { - /* WIFI 3.0 DP NOT IMPLEMENTED YET */ -}; - - +#ifdef DP_FLOW_CTL static struct cdp_throttle_ops dp_ops_throttle = { /* WIFI 3.0 DP NOT IMPLEMENTED YET */ }; -static struct cdp_mob_stats_ops dp_ops_mob_stats = { +static struct cdp_cfg_ops dp_ops_cfg = { /* WIFI 3.0 DP NOT IMPLEMENTED YET */ }; +#endif -static struct cdp_cfg_ops dp_ops_cfg = { +#ifdef DP_PEER_EXTENDED_API +static struct cdp_ocb_ops dp_ops_ocb = { /* WIFI 3.0 DP NOT IMPLEMENTED YET */ }; -/* - * dp_peer_release_ref - release peer ref count - * @peer: peer handle - * @debug_id: to track enum peer access - * - * Return: None - */ -static inline -void dp_peer_release_ref(void *peer, enum peer_debug_id_type debug_id) -{ - dp_peer_unref_delete(peer); -} +static struct cdp_mob_stats_ops dp_ops_mob_stats = { + .clear_stats = dp_txrx_clear_dump_stats, +}; static struct cdp_peer_ops dp_ops_peer = { .register_peer = dp_register_peer, .clear_peer = dp_clear_peer, - .find_peer_by_addr = dp_find_peer_by_addr, - .find_peer_by_addr_and_vdev = dp_find_peer_by_addr_and_vdev, - .peer_get_ref_by_addr = dp_peer_get_ref_find_by_addr, - .peer_release_ref = dp_peer_release_ref, - .local_peer_id = dp_local_peer_id, - .peer_find_by_local_id = dp_peer_find_by_local_id, + .find_peer_exist = dp_find_peer_exist, + .find_peer_exist_on_vdev = dp_find_peer_exist_on_vdev, + .find_peer_exist_on_other_vdev = dp_find_peer_exist_on_other_vdev, .peer_state_update = dp_peer_state_update, .get_vdevid = dp_get_vdevid, - .get_vdev_by_sta_id = dp_get_vdev_by_sta_id, + .get_vdev_by_peer_addr = dp_get_vdev_by_peer_addr, .peer_get_peer_mac_addr = dp_peer_get_peer_mac_addr, - .get_vdev_for_peer = dp_get_vdev_for_peer, .get_peer_state = dp_get_peer_state, + .peer_flush_frags = dp_peer_flush_frags, }; #endif @@ -9986,22 +11220,29 @@ static struct cdp_ops dp_txrx_ops = { .host_stats_ops = &dp_ops_host_stats, .wds_ops = &dp_ops_wds, .raw_ops = &dp_ops_raw, -#ifdef CONFIG_WIN +#ifdef PEER_FLOW_CONTROL .pflow_ops = &dp_ops_pflow, -#endif /* CONFIG_WIN */ -#ifndef CONFIG_WIN +#endif /* PEER_FLOW_CONTROL */ +#ifdef DP_PEER_EXTENDED_API .misc_ops = &dp_ops_misc, + .ocb_ops = &dp_ops_ocb, + .peer_ops = &dp_ops_peer, + .mob_stats_ops = &dp_ops_mob_stats, +#endif +#ifdef DP_FLOW_CTL .cfg_ops = &dp_ops_cfg, .flowctl_ops = &dp_ops_flowctl, .l_flowctl_ops = &dp_ops_l_flowctl, + .throttle_ops = &dp_ops_throttle, +#endif #ifdef IPA_OFFLOAD .ipa_ops = &dp_ops_ipa, #endif +#ifdef DP_POWER_SAVE .bus_ops = &dp_ops_bus, - .ocb_ops = &dp_ops_ocb, - .peer_ops = &dp_ops_peer, - .throttle_ops = &dp_ops_throttle, - .mob_stats_ops = &dp_ops_mob_stats, +#endif +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) + .cfr_ops = &dp_ops_cfr, #endif }; @@ -10034,9 +11275,11 @@ void dp_soc_set_txrx_ring_map(struct dp_soc *soc) * * Return: DP SOC handle on success, NULL on failure */ -void *dp_soc_attach_wifi3(void *ctrl_psoc, void *hif_handle, - HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, - struct ol_if_ops *ol_ops, uint16_t device_id) +struct cdp_soc_t * +dp_soc_attach_wifi3(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + struct hif_opaque_softc *hif_handle, + HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, + struct ol_if_ops *ol_ops, uint16_t device_id) { struct dp_soc *dp_soc = NULL; @@ -10048,7 +11291,7 @@ void *dp_soc_attach_wifi3(void *ctrl_psoc, void *hif_handle, if (!dp_soc_init(dp_soc, htc_handle, hif_handle)) return NULL; - return (void *)dp_soc; + return dp_soc_to_cdp_soc_t(dp_soc); } #else @@ -10063,15 +11306,17 @@ void *dp_soc_attach_wifi3(void *ctrl_psoc, void *hif_handle, * * Return: DP SOC handle on success, NULL on failure */ -void *dp_soc_attach_wifi3(void *ctrl_psoc, void *hif_handle, - HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, - struct ol_if_ops *ol_ops, uint16_t device_id) +struct cdp_soc_t * +dp_soc_attach_wifi3(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + struct hif_opaque_softc *hif_handle, + HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, + struct ol_if_ops *ol_ops, uint16_t device_id) { struct dp_soc *dp_soc = NULL; dp_soc = dp_soc_attach(ctrl_psoc, htc_handle, qdf_osdev, ol_ops, device_id); - return (void *)dp_soc; + return dp_soc_to_cdp_soc_t(dp_soc); } #endif @@ -10087,12 +11332,13 @@ void *dp_soc_attach_wifi3(void *ctrl_psoc, void *hif_handle, * Return: DP SOC handle on success, NULL on failure */ static struct dp_soc * -dp_soc_attach(void *ctrl_psoc, HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, +dp_soc_attach(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, struct ol_if_ops *ol_ops, uint16_t device_id) { int int_ctx; struct dp_soc *soc = NULL; - struct htt_soc *htt_soc = NULL; + struct htt_soc *htt_soc; soc = qdf_mem_malloc(sizeof(*soc)); @@ -10109,7 +11355,9 @@ dp_soc_attach(void *ctrl_psoc, HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, soc->osdev = qdf_osdev; soc->num_hw_dscp_tid_map = HAL_MAX_HW_DSCP_TID_MAPS; + dp_soc_rx_history_attach(soc); wlan_set_srng_cfg(&soc->wlan_srng_cfg); + qdf_mem_zero(&soc->vdev_id_map, sizeof(soc->vdev_id_map)); soc->wlan_cfg_ctx = wlan_cfg_soc_attach(soc->ctrl_psoc); if (!soc->wlan_cfg_ctx) { @@ -10118,22 +11366,22 @@ dp_soc_attach(void *ctrl_psoc, HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, } dp_soc_set_interrupt_mode(soc); - htt_soc = qdf_mem_malloc(sizeof(*htt_soc)); - if (!htt_soc) { - dp_err("HTT attach failed"); + + htt_soc = htt_soc_attach(soc, htc_handle); + + if (!htt_soc) goto fail1; - } + soc->htt_handle = htt_soc; - htt_soc->dp_soc = soc; - htt_soc->htc_soc = htc_handle; if (htt_soc_htc_prealloc(htt_soc) != QDF_STATUS_SUCCESS) goto fail2; - return (void *)soc; + return soc; fail2: - qdf_mem_free(htt_soc); + htt_soc_detach(htt_soc); fail1: + dp_soc_rx_history_detach(soc); qdf_mem_free(soc); fail0: return NULL; @@ -10147,20 +11395,22 @@ dp_soc_attach(void *ctrl_psoc, HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, * * Return: DP SOC handle on success, NULL on failure */ -void *dp_soc_init(void *dpsoc, HTC_HANDLE htc_handle, void *hif_handle) +void *dp_soc_init(struct dp_soc *soc, HTC_HANDLE htc_handle, + struct hif_opaque_softc *hif_handle) { int target_type; - struct dp_soc *soc = (struct dp_soc *)dpsoc; struct htt_soc *htt_soc = (struct htt_soc *)soc->htt_handle; + bool is_monitor_mode = false; - htt_soc->htc_soc = htc_handle; + htt_set_htc_handle(htt_soc, htc_handle); soc->hif_handle = hif_handle; soc->hal_soc = hif_get_hal_handle(soc->hif_handle); if (!soc->hal_soc) return NULL; - htt_soc_initialize(soc->htt_handle, soc->ctrl_psoc, htt_soc->htc_soc, + htt_soc_initialize(soc->htt_handle, soc->ctrl_psoc, + htt_get_htc_handle(htt_soc), soc->hal_soc, soc->osdev); target_type = hal_get_target_type(soc->hal_soc); switch (target_type) { @@ -10170,8 +11420,11 @@ void *dp_soc_init(void *dpsoc, HTC_HANDLE htc_handle, void *hif_handle) soc->ast_override_support = 1; soc->da_war_enabled = false; break; -#ifdef QCA_WIFI_QCA6390 +#if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490) || \ + defined(QCA_WIFI_QCA6750) case TARGET_TYPE_QCA6390: + case TARGET_TYPE_QCA6490: + case TARGET_TYPE_QCA6750: wlan_cfg_set_reo_dst_ring_size(soc->wlan_cfg_ctx, REO_DST_RING_SIZE_QCA6290); wlan_cfg_set_raw_mode_war(soc->wlan_cfg_ctx, true); @@ -10188,13 +11441,14 @@ void *dp_soc_init(void *dpsoc, HTC_HANDLE htc_handle, void *hif_handle) } soc->wlan_cfg_ctx->rxdma1_enable = 0; break; -#endif +#endif /* QCA_WIFI_QCA6390 || QCA_WIFI_QCA6490 || QCA_WIFI_QCA6750 */ + case TARGET_TYPE_QCA8074: wlan_cfg_set_reo_dst_ring_size(soc->wlan_cfg_ctx, REO_DST_RING_SIZE_QCA8074); wlan_cfg_set_raw_mode_war(soc->wlan_cfg_ctx, true); - soc->hw_nac_monitor_support = 1; soc->da_war_enabled = true; + soc->is_rx_fse_full_cache_invalidate_war_enabled = true; break; case TARGET_TYPE_QCA8074V2: case TARGET_TYPE_QCA6018: @@ -10206,6 +11460,18 @@ void *dp_soc_init(void *dpsoc, HTC_HANDLE htc_handle, void *hif_handle) soc->per_tid_basize_max_tid = 8; soc->num_hw_dscp_tid_map = HAL_MAX_HW_DSCP_TID_V2_MAPS; soc->da_war_enabled = false; + soc->is_rx_fse_full_cache_invalidate_war_enabled = true; + break; + case TARGET_TYPE_QCN9000: + wlan_cfg_set_reo_dst_ring_size(soc->wlan_cfg_ctx, + REO_DST_RING_SIZE_QCN9000); + soc->ast_override_support = 1; + soc->da_war_enabled = false; + wlan_cfg_set_raw_mode_war(soc->wlan_cfg_ctx, false); + soc->hw_nac_monitor_support = 1; + soc->per_tid_basize_max_tid = 8; + soc->num_hw_dscp_tid_map = HAL_MAX_HW_DSCP_TID_V2_MAPS; + soc->lmac_polled_mode = 1; break; default: qdf_print("%s: Unknown tgt type %d\n", __func__, target_type); @@ -10213,10 +11479,22 @@ void *dp_soc_init(void *dpsoc, HTC_HANDLE htc_handle, void *hif_handle) break; } + dp_soc_set_interrupt_mode(soc); + if (soc->cdp_soc.ol_ops->get_con_mode && + soc->cdp_soc.ol_ops->get_con_mode() == + QDF_GLOBAL_MONITOR_MODE) + is_monitor_mode = true; + + wlan_cfg_fill_interrupt_mask(soc->wlan_cfg_ctx, soc->intr_mode, + is_monitor_mode); wlan_cfg_set_rx_hash(soc->wlan_cfg_ctx, cfg_get(soc->ctrl_psoc, CFG_DP_RX_HASH)); soc->cce_disable = false; + qdf_atomic_init(&soc->num_tx_outstanding); + soc->num_tx_allowed = + wlan_cfg_get_dp_soc_tx_device_limit(soc->wlan_cfg_ctx); + if (soc->cdp_soc.ol_ops->get_dp_cfg_param) { int ret = soc->cdp_soc.ol_ops->get_dp_cfg_param(soc->ctrl_psoc, CDP_CFG_MAX_PEER_ID); @@ -10251,7 +11529,7 @@ void *dp_soc_init(void *dpsoc, HTC_HANDLE htc_handle, void *hif_handle) /** * dp_soc_init_wifi3() - Initialize txrx SOC - * @dp_soc: Opaque DP SOC handle + * @soc: Opaque DP SOC handle * @ctrl_psoc: Opaque SOC handle from control plane(Unused) * @hif_handle: Opaque HIF handle * @htc_handle: Opaque HTC handle @@ -10261,11 +11539,13 @@ void *dp_soc_init(void *dpsoc, HTC_HANDLE htc_handle, void *hif_handle) * * Return: DP SOC handle on success, NULL on failure */ -void *dp_soc_init_wifi3(void *dpsoc, void *ctrl_psoc, void *hif_handle, +void *dp_soc_init_wifi3(struct cdp_soc_t *soc, + struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + struct hif_opaque_softc *hif_handle, HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, struct ol_if_ops *ol_ops, uint16_t device_id) { - return dp_soc_init(dpsoc, htc_handle, hif_handle); + return dp_soc_init((struct dp_soc *)soc, htc_handle, hif_handle); } #endif @@ -10294,18 +11574,240 @@ void *dp_get_pdev_for_mac_id(struct dp_soc *soc, uint32_t mac_id) * * Return: None */ -static void dp_is_hw_dbs_enable(struct dp_soc *soc, int *max_mac_rings) { bool dbs_enable = false; if (soc->cdp_soc.ol_ops->is_hw_dbs_2x2_capable) dbs_enable = soc->cdp_soc.ol_ops-> - is_hw_dbs_2x2_capable(soc->ctrl_psoc); + is_hw_dbs_2x2_capable((void *)soc->ctrl_psoc); *max_mac_rings = (dbs_enable)?(*max_mac_rings):1; } +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) +/* + * dp_cfr_filter() - Configure HOST RX monitor status ring for CFR + * @soc_hdl: Datapath soc handle + * @pdev_id: id of data path pdev handle + * @enable: Enable/Disable CFR + * @filter_val: Flag to select Filter for monitor mode + */ +static void dp_cfr_filter(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + bool enable, + struct cdp_monitor_filter *filter_val) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = NULL; + struct htt_rx_ring_tlv_filter htt_tlv_filter = {0}; + int max_mac_rings; + uint8_t mac_id = 0; + + pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + if (!pdev) { + dp_err("pdev is NULL"); + return; + } + + if (pdev->monitor_vdev) { + dp_info("No action is needed since monitor mode is enabled\n"); + return; + } + soc = pdev->soc; + pdev->cfr_rcc_mode = false; + max_mac_rings = wlan_cfg_get_num_mac_rings(pdev->wlan_cfg_ctx); + dp_is_hw_dbs_enable(soc, &max_mac_rings); + + dp_debug("Max_mac_rings %d", max_mac_rings); + dp_info("enable : %d, mode: 0x%x", enable, filter_val->mode); + + if (enable) { + pdev->cfr_rcc_mode = true; + + htt_tlv_filter.ppdu_start = 1; + htt_tlv_filter.ppdu_end = 1; + htt_tlv_filter.ppdu_end_user_stats = 1; + htt_tlv_filter.ppdu_end_user_stats_ext = 1; + htt_tlv_filter.ppdu_end_status_done = 1; + htt_tlv_filter.mpdu_start = 1; + htt_tlv_filter.offset_valid = false; + + htt_tlv_filter.enable_fp = + (filter_val->mode & MON_FILTER_PASS) ? 1 : 0; + htt_tlv_filter.enable_md = 0; + htt_tlv_filter.enable_mo = + (filter_val->mode & MON_FILTER_OTHER) ? 1 : 0; + htt_tlv_filter.fp_mgmt_filter = filter_val->fp_mgmt; + htt_tlv_filter.fp_ctrl_filter = filter_val->fp_ctrl; + htt_tlv_filter.fp_data_filter = filter_val->fp_data; + htt_tlv_filter.mo_mgmt_filter = filter_val->mo_mgmt; + htt_tlv_filter.mo_ctrl_filter = filter_val->mo_ctrl; + htt_tlv_filter.mo_data_filter = filter_val->mo_data; + } + + for (mac_id = 0; mac_id < max_mac_rings; mac_id++) { + int mac_for_pdev = + dp_get_mac_id_for_pdev(mac_id, + pdev->pdev_id); + + htt_h2t_rx_ring_cfg(soc->htt_handle, + mac_for_pdev, + soc->rxdma_mon_status_ring[mac_id] + .hal_srng, + RXDMA_MONITOR_STATUS, + RX_DATA_BUFFER_SIZE, + &htt_tlv_filter); + } +} + +/** + * dp_get_cfr_rcc() - get cfr rcc config + * @soc_hdl: Datapath soc handle + * @pdev_id: id of objmgr pdev + * + * Return: true/false based on cfr mode setting + */ +static +bool dp_get_cfr_rcc(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = NULL; + + pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + if (!pdev) { + dp_err("pdev is NULL"); + return false; + } + + return pdev->cfr_rcc_mode; +} + +/** + * dp_set_cfr_rcc() - enable/disable cfr rcc config + * @soc_hdl: Datapath soc handle + * @pdev_id: id of objmgr pdev + * @enable: Enable/Disable cfr rcc mode + * + * Return: none + */ +static +void dp_set_cfr_rcc(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, bool enable) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = NULL; + + pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + if (!pdev) { + dp_err("pdev is NULL"); + return; + } + + pdev->cfr_rcc_mode = enable; +} + +/* + * dp_get_cfr_dbg_stats - Get the debug statistics for CFR + * @soc_hdl: Datapath soc handle + * @pdev_id: id of data path pdev handle + * @cfr_rcc_stats: CFR RCC debug statistics buffer + * + * Return: none + */ +static inline void +dp_get_cfr_dbg_stats(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct cdp_cfr_rcc_stats *cfr_rcc_stats) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (!pdev) { + dp_err("Invalid pdev"); + return; + } + + qdf_mem_copy(cfr_rcc_stats, &pdev->stats.rcc, + sizeof(struct cdp_cfr_rcc_stats)); +} + +/* + * dp_clear_cfr_dbg_stats - Clear debug statistics for CFR + * @soc_hdl: Datapath soc handle + * @pdev_id: id of data path pdev handle + * + * Return: none + */ +static void dp_clear_cfr_dbg_stats(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (!pdev) { + dp_err("dp pdev is NULL"); + return; + } + + qdf_mem_zero(&pdev->stats.rcc, sizeof(pdev->stats.rcc)); +} + +/* + * dp_enable_mon_reap_timer() - enable/disable reap timer + * @soc_hdl: Datapath soc handle + * @pdev_id: id of objmgr pdev + * @enable: Enable/Disable reap timer of monitor status ring + * + * Return: none + */ +static void +dp_enable_mon_reap_timer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + bool enable) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = NULL; + + pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + if (!pdev) { + dp_err("pdev is NULL"); + return; + } + + pdev->enable_reap_timer_non_pkt = enable; + if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) { + dp_debug("pktlog enabled %d", pdev->rx_pktlog_mode); + return; + } + + if (!soc->reap_timer_init) { + dp_err("reap timer not init"); + return; + } + + if (enable) + qdf_timer_mod(&soc->mon_reap_timer, + DP_INTR_POLL_TIMER_MS); + else + qdf_timer_sync_cancel(&soc->mon_reap_timer); +} +#endif + +/* + * dp_is_enable_reap_timer_non_pkt() - check if mon reap timer is + * enabled by non-pkt log or not + * @pdev: point to dp pdev + * + * Return: true if mon reap timer is enabled by non-pkt log + */ +static bool dp_is_enable_reap_timer_non_pkt(struct dp_pdev *pdev) +{ + if (!pdev) { + dp_err("null pdev"); + return false; + } + + return pdev->enable_reap_timer_non_pkt; +} + /* * dp_is_soc_reinit() - Check if soc reinit is true * @soc: DP SoC context @@ -10330,7 +11832,6 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, bool enable) { struct dp_soc *soc = NULL; - struct htt_rx_ring_tlv_filter htt_tlv_filter = {0}; int max_mac_rings = wlan_cfg_get_num_mac_rings (pdev->wlan_cfg_ctx); uint8_t mac_id = 0; @@ -10351,45 +11852,22 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, */ return 0; } + if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_FULL) { pdev->rx_pktlog_mode = DP_RX_PKTLOG_FULL; - htt_tlv_filter.mpdu_start = 1; - htt_tlv_filter.msdu_start = 1; - htt_tlv_filter.msdu_end = 1; - htt_tlv_filter.mpdu_end = 1; - htt_tlv_filter.packet_header = 1; - htt_tlv_filter.attention = 1; - htt_tlv_filter.ppdu_start = 1; - htt_tlv_filter.ppdu_end = 1; - htt_tlv_filter.ppdu_end_user_stats = 1; - htt_tlv_filter.ppdu_end_user_stats_ext = 1; - htt_tlv_filter.ppdu_end_status_done = 1; - htt_tlv_filter.enable_fp = 1; - htt_tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.fp_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.mo_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < max_mac_rings; - mac_id++) { - int mac_for_pdev = - dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); - - htt_h2t_rx_ring_cfg(soc->htt_handle, - mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id] - .hal_srng, - RXDMA_MONITOR_STATUS, - RX_BUFFER_SIZE, - &htt_tlv_filter); - + dp_mon_filter_setup_rx_pkt_log_full(pdev); + if (dp_mon_filter_update(pdev) != + QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("Pktlog full filters set failed")); + dp_mon_filter_reset_rx_pkt_log_full(pdev); + pdev->rx_pktlog_mode = DP_RX_PKTLOG_DISABLED; + return 0; } - if (soc->reap_timer_init) + if (soc->reap_timer_init && + (!dp_is_enable_reap_timer_non_pkt(pdev))) qdf_timer_mod(&soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS); } @@ -10402,41 +11880,25 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, */ return 0; } - if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_LITE) { pdev->rx_pktlog_mode = DP_RX_PKTLOG_LITE; - htt_tlv_filter.ppdu_start = 1; - htt_tlv_filter.ppdu_end = 1; - htt_tlv_filter.ppdu_end_user_stats = 1; - htt_tlv_filter.ppdu_end_user_stats_ext = 1; - htt_tlv_filter.ppdu_end_status_done = 1; - htt_tlv_filter.mpdu_start = 1; - htt_tlv_filter.enable_fp = 1; - htt_tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.fp_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; - htt_tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; - htt_tlv_filter.mo_data_filter = FILTER_DATA_ALL; - htt_tlv_filter.offset_valid = false; - - for (mac_id = 0; mac_id < max_mac_rings; - mac_id++) { - int mac_for_pdev = - dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); - - htt_h2t_rx_ring_cfg(soc->htt_handle, - mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id] - .hal_srng, - RXDMA_MONITOR_STATUS, - RX_BUFFER_SIZE_PKTLOG_LITE, - &htt_tlv_filter); + /* + * Set the packet log lite mode filter. + */ + dp_mon_filter_setup_rx_pkt_log_lite(pdev); + if (dp_mon_filter_update(pdev) != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("Pktlog lite filters set failed")); + dp_mon_filter_reset_rx_pkt_log_lite(pdev); + pdev->rx_pktlog_mode = + DP_RX_PKTLOG_DISABLED; + return 0; } - if (soc->reap_timer_init) + if (soc->reap_timer_init && + (!dp_is_enable_reap_timer_non_pkt(pdev))) qdf_timer_mod(&soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS); } @@ -10477,23 +11939,26 @@ int dp_set_pktlog_wifi3(struct dp_pdev *pdev, uint32_t event, } if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) { pdev->rx_pktlog_mode = DP_RX_PKTLOG_DISABLED; + dp_mon_filter_reset_rx_pkt_log_full(pdev); + if (dp_mon_filter_update(pdev) != + QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("Pktlog filters reset failed")); + return 0; + } - for (mac_id = 0; mac_id < max_mac_rings; - mac_id++) { - int mac_for_pdev = - dp_get_mac_id_for_pdev(mac_id, - pdev->pdev_id); - - htt_h2t_rx_ring_cfg(soc->htt_handle, - mac_for_pdev, - pdev->rxdma_mon_status_ring[mac_id] - .hal_srng, - RXDMA_MONITOR_STATUS, - RX_BUFFER_SIZE, - &htt_tlv_filter); + dp_mon_filter_reset_rx_pkt_log_lite(pdev); + if (dp_mon_filter_update(pdev) != + QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + FL("Pktlog filters reset failed")); + return 0; } - if (soc->reap_timer_init) + if (soc->reap_timer_init && + (!dp_is_enable_reap_timer_non_pkt(pdev))) qdf_timer_stop(&soc->mon_reap_timer); } break; @@ -10548,7 +12013,7 @@ static uint8_t dp_bucket_index(uint32_t delay, uint16_t *array) { uint8_t i = CDP_DELAY_BUCKET_0; - for (; i < CDP_DELAY_BUCKET_MAX; i++) { + for (; i < CDP_DELAY_BUCKET_MAX - 1; i++) { if (delay >= array[i] && delay <= array[i + 1]) return i; } @@ -10687,3 +12152,39 @@ void dp_update_delay_stats(struct dp_pdev *pdev, uint32_t delay, dstats->avg_delay = ((delay + dstats->avg_delay) / 2); } } + +/** + * dp_get_peer_mac_list(): function to get peer mac list of vdev + * @soc: Datapath soc handle + * @vdev_id: vdev id + * @newmac: Table of the clients mac + * @mac_cnt: No. of MACs required + * + * return: no of clients + */ +uint16_t dp_get_peer_mac_list(ol_txrx_soc_handle soc, uint8_t vdev_id, + u_int8_t newmac[][QDF_MAC_ADDR_SIZE], + u_int16_t mac_cnt) +{ + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + struct dp_soc *dp_soc = (struct dp_soc *)soc; + struct dp_peer *peer; + uint16_t new_mac_cnt = 0; + + if (!vdev) + return new_mac_cnt; + + qdf_spin_lock_bh(&dp_soc->peer_ref_mutex); + TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) { + if (peer->bss_peer) + continue; + if (new_mac_cnt < mac_cnt) { + WLAN_ADDR_COPY(newmac[new_mac_cnt], peer->mac_addr.raw); + new_mac_cnt++; + } + } + qdf_spin_unlock_bh(&dp_soc->peer_ref_mutex); + return new_mac_cnt; +} diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_mon_filter.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_mon_filter.c new file mode 100644 index 0000000000000000000000000000000000000000..cfd9619be4c033726173b01f40b58628271e70d4 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_mon_filter.c @@ -0,0 +1,1182 @@ +/* + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include "dp_types.h" +#include "dp_internal.h" +#include "dp_htt.h" +#include "dp_mon_filter.h" + +/** + * dp_mon_filter_mode_type_to_str + * Monitor Filter mode to string + */ +static int8_t *dp_mon_filter_mode_type_to_str[DP_MON_FILTER_MAX_MODE] = { +#ifdef FEATURE_PERPKT_INFO + "DP MON FILTER ENHACHED STATS MODE", + "DP MON FILTER MCOPY MODE", +#endif /* FEATURE_PERPKT_INFO */ +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) + "DP MON FILTER SMART MONITOR MODE", +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ + "DP_MON FILTER MONITOR MODE", +#ifdef WLAN_RX_PKT_CAPTURE_ENH + "DP MON FILTER RX CAPTURE MODE", +#endif /* WLAN_RX_PKT_CAPTURE_ENH */ +#ifdef WDI_EVENT_ENABLE + "DP MON FILTER PKT LOG FULL MODE", + "DP MON FILTER PKT LOG LITE_MODE", +#endif /* WDI_EVENT_ENABLE */ +}; + +/** + * dp_mon_filter_show_filter() - Show the set filters + * @pdev: DP pdev handle + * @mode: The filter modes + * @tlv_filter: tlv filter + */ +static void dp_mon_filter_show_filter(struct dp_pdev *pdev, + enum dp_mon_filter_mode mode, + struct dp_mon_filter *filter) +{ + struct htt_rx_ring_tlv_filter *tlv_filter = &filter->tlv_filter; + + DP_MON_FILTER_PRINT("[%s]: Valid: %d", + dp_mon_filter_mode_type_to_str[mode], + filter->valid); + DP_MON_FILTER_PRINT("mpdu_start: %d", tlv_filter->mpdu_start); + DP_MON_FILTER_PRINT("msdu_start: %d", tlv_filter->msdu_start); + DP_MON_FILTER_PRINT("packet: %d", tlv_filter->packet); + DP_MON_FILTER_PRINT("msdu_end: %d", tlv_filter->msdu_end); + DP_MON_FILTER_PRINT("mpdu_end: %d", tlv_filter->mpdu_end); + DP_MON_FILTER_PRINT("packet_header: %d", + tlv_filter->packet_header); + DP_MON_FILTER_PRINT("attention: %d", tlv_filter->attention); + DP_MON_FILTER_PRINT("ppdu_start: %d", tlv_filter->ppdu_start); + DP_MON_FILTER_PRINT("ppdu_end: %d", tlv_filter->ppdu_end); + DP_MON_FILTER_PRINT("ppdu_end_user_stats: %d", + tlv_filter->ppdu_end_user_stats); + DP_MON_FILTER_PRINT("ppdu_end_user_stats_ext: %d", + tlv_filter->ppdu_end_user_stats_ext); + DP_MON_FILTER_PRINT("ppdu_end_status_done: %d", + tlv_filter->ppdu_end_status_done); + DP_MON_FILTER_PRINT("header_per_msdu: %d", tlv_filter->header_per_msdu); + DP_MON_FILTER_PRINT("enable_fp: %d", tlv_filter->enable_fp); + DP_MON_FILTER_PRINT("enable_md: %d", tlv_filter->enable_md); + DP_MON_FILTER_PRINT("enable_mo: %d", tlv_filter->enable_mo); + DP_MON_FILTER_PRINT("fp_mgmt_filter: 0x%x", tlv_filter->fp_mgmt_filter); + DP_MON_FILTER_PRINT("mo_mgmt_filter: 0x%x", tlv_filter->mo_mgmt_filter); + DP_MON_FILTER_PRINT("fp_ctrl_filter: 0x%x", tlv_filter->fp_ctrl_filter); + DP_MON_FILTER_PRINT("mo_ctrl_filter: 0x%x", tlv_filter->mo_ctrl_filter); + DP_MON_FILTER_PRINT("fp_data_filter: 0x%x", tlv_filter->fp_data_filter); + DP_MON_FILTER_PRINT("mo_data_filter: 0x%x", tlv_filter->mo_data_filter); + DP_MON_FILTER_PRINT("md_data_filter: 0x%x", tlv_filter->md_data_filter); + DP_MON_FILTER_PRINT("md_mgmt_filter: 0x%x", tlv_filter->md_mgmt_filter); + DP_MON_FILTER_PRINT("md_ctrl_filter: 0x%x", tlv_filter->md_ctrl_filter); +} + +/** + * dp_mon_ht2_rx_ring_cfg() - Send the tlv config to fw for a srng_type + * based on target + * @soc: DP soc handle + * @pdev: DP pdev handle + * @srng_type: The srng type for which filter wll be set + * @tlv_filter: tlv filter + */ +static QDF_STATUS +dp_mon_ht2_rx_ring_cfg(struct dp_soc *soc, + struct dp_pdev *pdev, + enum dp_mon_filter_srng_type srng_type, + struct htt_rx_ring_tlv_filter *tlv_filter) +{ + int mac_id; + int max_mac_rings = wlan_cfg_get_num_mac_rings(pdev->wlan_cfg_ctx); + QDF_STATUS status = QDF_STATUS_SUCCESS; + + /* + * Overwrite the max_mac_rings for the status rings. + */ + if (srng_type == DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS) + dp_is_hw_dbs_enable(soc, &max_mac_rings); + + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_INFO, + FL("srng type %d Max_mac_rings %d "), + srng_type, + max_mac_rings); + + /* + * Loop through all MACs per radio and set the filter to the individual + * macs. For MCL + */ + for (mac_id = 0; mac_id < max_mac_rings; mac_id++) { + int mac_for_pdev = + dp_get_mac_id_for_pdev(mac_id, pdev->pdev_id); + int lmac_id = dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev->pdev_id); + int hal_ring_type, ring_buf_size; + hal_ring_handle_t hal_ring_hdl; + + switch (srng_type) { + case DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF: + hal_ring_hdl = pdev->rx_mac_buf_ring[lmac_id].hal_srng; + hal_ring_type = RXDMA_BUF; + ring_buf_size = RX_DATA_BUFFER_SIZE; + break; + + case DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS: + /* + * If two back to back HTT msg sending happened in + * short time, the second HTT msg source SRNG HP + * writing has chance to fail, this has been confirmed + * by HST HW. + * for monitor mode, here is the last HTT msg for sending. + * if the 2nd HTT msg for monitor status ring sending failed, + * HW won't provide anything into 2nd monitor status ring. + * as a WAR, add some delay before 2nd HTT msg start sending, + * > 2us is required per HST HW, delay 100 us for safe. + */ + if (mac_id) + qdf_udelay(100); + + hal_ring_hdl = + soc->rxdma_mon_status_ring[lmac_id].hal_srng; + hal_ring_type = RXDMA_MONITOR_STATUS; + ring_buf_size = RX_DATA_BUFFER_SIZE; + break; + + case DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF: + hal_ring_hdl = + soc->rxdma_mon_buf_ring[lmac_id].hal_srng; + hal_ring_type = RXDMA_MONITOR_BUF; + ring_buf_size = RX_DATA_BUFFER_SIZE; + break; + + default: + return QDF_STATUS_E_FAILURE; + } + + status = htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, + hal_ring_hdl, hal_ring_type, + ring_buf_size, + tlv_filter); + if (status != QDF_STATUS_SUCCESS) + return status; + } + + return status; +} + +/** + * dp_mon_filter_ht2_setup() - Setup the filter for the Target setup + * @soc: DP soc handle + * @pdev: DP pdev handle + * @srng_type: The srng type for which filter wll be set + * @tlv_filter: tlv filter + */ +static void dp_mon_filter_ht2_setup(struct dp_soc *soc, struct dp_pdev *pdev, + enum dp_mon_filter_srng_type srng_type, + struct dp_mon_filter *filter) +{ + int32_t current_mode = 0; + struct htt_rx_ring_tlv_filter *tlv_filter = &filter->tlv_filter; + + /* + * Loop through all the modes. + */ + for (current_mode = 0; current_mode < DP_MON_FILTER_MAX_MODE; + current_mode++) { + struct dp_mon_filter *mon_filter = + &pdev->filter[current_mode][srng_type]; + uint32_t src_filter = 0, dst_filter = 0; + + /* + * Check if the correct mode is enabled or not. + */ + if (!mon_filter->valid) + continue; + + filter->valid = true; + + /* + * Set the super bit fields + */ + src_filter = + DP_MON_FILTER_GET(&mon_filter->tlv_filter, FILTER_TLV); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_TLV); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_TLV, dst_filter); + + /* + * Set the filter management filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_FP_MGMT); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_FP_MGMT); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_FP_MGMT, dst_filter); + + /* + * Set the monitor other management filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MO_MGMT); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MO_MGMT); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_MO_MGMT, dst_filter); + + /* + * Set the filter pass control filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_FP_CTRL); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_FP_CTRL); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_FP_CTRL, dst_filter); + + /* + * Set the monitor other control filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MO_CTRL); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MO_CTRL); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_MO_CTRL, dst_filter); + + /* + * Set the filter pass data filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_FP_DATA); + dst_filter = DP_MON_FILTER_GET(tlv_filter, + FILTER_FP_DATA); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, + FILTER_FP_DATA, dst_filter); + + /* + * Set the monitor other data filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MO_DATA); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MO_DATA); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_MO_DATA, dst_filter); + + /* + * Set the monitor direct data filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MD_DATA); + dst_filter = DP_MON_FILTER_GET(tlv_filter, + FILTER_MD_DATA); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, + FILTER_MD_DATA, dst_filter); + + /* + * Set the monitor direct management filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MD_MGMT); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MD_MGMT); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_MD_MGMT, dst_filter); + + /* + * Set the monitor direct management filter. + */ + src_filter = DP_MON_FILTER_GET(&mon_filter->tlv_filter, + FILTER_MD_CTRL); + dst_filter = DP_MON_FILTER_GET(tlv_filter, FILTER_MD_CTRL); + dst_filter |= src_filter; + DP_MON_FILTER_SET(tlv_filter, FILTER_MD_CTRL, dst_filter); + } + + dp_mon_filter_show_filter(pdev, 0, filter); +} + +/** + * dp_mon_filter_reset_mon_srng() + * @soc: DP SoC handle + * @pdev: DP pdev handle + * @mon_srng_type: Monitor srng type + */ +static void +dp_mon_filter_reset_mon_srng(struct dp_soc *soc, struct dp_pdev *pdev, + enum dp_mon_filter_srng_type mon_srng_type) +{ + struct htt_rx_ring_tlv_filter tlv_filter = {0}; + + if (dp_mon_ht2_rx_ring_cfg(soc, pdev, mon_srng_type, + &tlv_filter) != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Monitor destinatin ring filter setting failed")); + } +} + +#if defined(FEATURE_PERPKT_INFO) || defined(ATH_SUPPORT_NAC_RSSI) \ + || defined(ATH_SUPPORT_NAC) || defined(WLAN_RX_PKT_CAPTURE_ENH) +/** + * dp_mon_filter_check_co_exist() - Check the co-existing of the + * enabled modes. + * @pdev: DP pdev handle + * + * Return: QDF_STATUS + */ +static QDF_STATUS dp_mon_filter_check_co_exist(struct dp_pdev *pdev) +{ + /* + * Check if the Rx Enhanced capture mode, monitor mode, + * smart_monitor_mode and mcopy mode can co-exist together. + */ + if ((pdev->rx_enh_capture_mode != CDP_RX_ENH_CAPTURE_DISABLED) && + ((pdev->neighbour_peers_added && pdev->monitor_vdev) || + pdev->mcopy_mode)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Rx Capture mode can't exist with modes:\n" + "Smart Monitor Mode:%d\n" + "M_Copy Mode:%d"), + pdev->neighbour_peers_added, + pdev->mcopy_mode); + return QDF_STATUS_E_FAILURE; + } + + /* + * Check if the monitor mode cannot co-exist with any other mode. + */ + if ((pdev->monitor_vdev && pdev->monitor_configured) && + (pdev->mcopy_mode || pdev->neighbour_peers_added)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Monitor mode can't exist with modes\n" + "M_Copy Mode:%d\n" + "Smart Monitor Mode:%d"), + pdev->mcopy_mode, + pdev->neighbour_peers_added); + return QDF_STATUS_E_FAILURE; + } + + /* + * Check if the smart monitor mode can co-exist with any other mode + */ + if (pdev->neighbour_peers_added && + ((pdev->mcopy_mode) || pdev->monitor_configured)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Smart Monitor mode can't exist with modes\n" + "M_Copy Mode:%d\n" + "Monitor Mode:%d"), + pdev->mcopy_mode, + pdev->monitor_configured); + return QDF_STATUS_E_FAILURE; + } + + /* + * Check if the m_copy, monitor mode and the smart_monitor_mode + * can co-exist togther. + */ + if (pdev->mcopy_mode && + (pdev->monitor_vdev || pdev->neighbour_peers_added)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("mcopy mode can't exist with modes\n" + "Monitor Mode:%d\n" + "Smart Monitor Mode:%d"), + pdev->monitor_vdev, + pdev->neighbour_peers_added); + return QDF_STATUS_E_FAILURE; + } + + /* + * Check if the Rx packet log lite or full can co-exist with + * the enable modes. + */ + if ((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) && + (pdev->monitor_vdev || pdev->monitor_configured)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Rx pktlog full/lite can't exist with modes\n" + "Monitor Mode:%d"), + pdev->monitor_configured); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} +#else +static QDF_STATUS dp_mon_filter_check_co_exist(struct dp_pdev *pdev) +{ + /* + * Check if the Rx packet log lite or full can co-exist with + * the enable modes. + */ + if ((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) && + (pdev->monitor_vdev || pdev->monitor_configured)) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Rx pktlog full/lite can't exist with modes\n" + "Monitor Mode:%d"), + pdev->monitor_configured); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} +#endif + +/** + * dp_mon_filter_set_mon_cmn() - Setp the common mon filters + * @pdev: DP pdev handle + * @filter: DP mon filter + * + * Return: QDF_STATUS + */ +static void dp_mon_filter_set_mon_cmn(struct dp_pdev *pdev, + struct dp_mon_filter *filter) +{ + filter->tlv_filter.mpdu_start = 1; + filter->tlv_filter.msdu_start = 1; + filter->tlv_filter.packet = 1; + filter->tlv_filter.msdu_end = 1; + filter->tlv_filter.mpdu_end = 1; + filter->tlv_filter.packet_header = 1; + filter->tlv_filter.attention = 1; + filter->tlv_filter.ppdu_start = 0; + filter->tlv_filter.ppdu_end = 0; + filter->tlv_filter.ppdu_end_user_stats = 0; + filter->tlv_filter.ppdu_end_user_stats_ext = 0; + filter->tlv_filter.ppdu_end_status_done = 0; + filter->tlv_filter.header_per_msdu = 1; + filter->tlv_filter.enable_fp = + (pdev->mon_filter_mode & MON_FILTER_PASS) ? 1 : 0; + filter->tlv_filter.enable_mo = + (pdev->mon_filter_mode & MON_FILTER_OTHER) ? 1 : 0; + + filter->tlv_filter.fp_mgmt_filter = pdev->fp_mgmt_filter; + filter->tlv_filter.fp_ctrl_filter = pdev->fp_ctrl_filter; + filter->tlv_filter.fp_data_filter = pdev->fp_data_filter; + filter->tlv_filter.mo_mgmt_filter = pdev->mo_mgmt_filter; + filter->tlv_filter.mo_ctrl_filter = pdev->mo_ctrl_filter; + filter->tlv_filter.mo_data_filter = pdev->mo_data_filter; + filter->tlv_filter.offset_valid = false; +} + +/** + * dp_mon_filter_set_status_cmn() - Setp the common status filters + * @pdev: DP pdev handle + * @filter: Dp mon filters + * + * Return: QDF_STATUS + */ +static void dp_mon_filter_set_status_cmn(struct dp_pdev *pdev, + struct dp_mon_filter *filter) +{ + filter->tlv_filter.mpdu_start = 1; + filter->tlv_filter.msdu_start = 0; + filter->tlv_filter.packet = 0; + filter->tlv_filter.msdu_end = 0; + filter->tlv_filter.mpdu_end = 0; + filter->tlv_filter.attention = 0; + filter->tlv_filter.ppdu_start = 1; + filter->tlv_filter.ppdu_end = 1; + filter->tlv_filter.ppdu_end_user_stats = 1; + filter->tlv_filter.ppdu_end_user_stats_ext = 1; + filter->tlv_filter.ppdu_end_status_done = 1; + filter->tlv_filter.enable_fp = 1; + filter->tlv_filter.enable_md = 0; + filter->tlv_filter.fp_mgmt_filter = FILTER_MGMT_ALL; + filter->tlv_filter.fp_ctrl_filter = FILTER_CTRL_ALL; + filter->tlv_filter.fp_data_filter = FILTER_DATA_ALL; + filter->tlv_filter.mo_mgmt_filter = FILTER_MGMT_ALL; + filter->tlv_filter.mo_ctrl_filter = FILTER_CTRL_ALL; + filter->tlv_filter.mo_data_filter = FILTER_DATA_ALL; + filter->tlv_filter.offset_valid = false; +} + +#ifdef FEATURE_PERPKT_INFO +/** + * dp_mon_filter_setup_enhanced_stats() - Setup the enhanced stats filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_enhanced_stats(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_ENHACHED_STATS_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + + dp_mon_filter_set_status_cmn(pdev, &filter); + dp_mon_filter_show_filter(pdev, mode, &filter); + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_enhanced_stats() - Reset the enhanced stats filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_enhanced_stats(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_ENHACHED_STATS_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_setup_mcopy_mode() - Setup the m_copy mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_mcopy_mode(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_MCOPY_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_mon_cmn(pdev, &filter); + + filter.tlv_filter.fp_data_filter = 0; + filter.tlv_filter.mo_data_filter = 0; + + dp_mon_filter_show_filter(pdev, mode, &filter); + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + /* Clear the filter as the same filter will be used to set the + * monitor status ring + */ + qdf_mem_zero(&(filter), sizeof(struct dp_mon_filter)); + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + + /* Setup the filter */ + filter.tlv_filter.enable_mo = 1; + filter.tlv_filter.packet_header = 1; + dp_mon_filter_show_filter(pdev, mode, &filter); + + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_mcopy_mode() - Reset the m_copy mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_mcopy_mode(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_MCOPY_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} +#endif /* FEATURE_PERPKT_INFO */ + +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) +/** + * dp_mon_filter_setup_smart_monitor() - Setup the smart monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_smart_monitor(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_SMART_MONITOR_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + + if (soc->hw_nac_monitor_support) { + filter.tlv_filter.enable_md = 1; + filter.tlv_filter.packet_header = 1; + filter.tlv_filter.md_data_filter = FILTER_DATA_ALL; + } + + dp_mon_filter_show_filter(pdev, mode, &filter); + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_smart_monitor() - Reset the smart monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_smart_monitor(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_SMART_MONITOR_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + pdev->filter[mode][srng_type] = filter; +} +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ + +#ifdef WLAN_RX_PKT_CAPTURE_ENH +/** + * dp_mon_filter_setup_rx_enh_capture() - Setup the Rx capture mode filters + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_enh_capture(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_RX_CAPTURE_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_mon_cmn(pdev, &filter); + + filter.tlv_filter.fp_mgmt_filter = 0; + filter.tlv_filter.fp_ctrl_filter = 0; + filter.tlv_filter.fp_data_filter = 0; + filter.tlv_filter.mo_mgmt_filter = 0; + filter.tlv_filter.mo_ctrl_filter = 0; + filter.tlv_filter.mo_data_filter = 0; + + dp_mon_filter_show_filter(pdev, mode, &filter); + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + /* Clear the filter as the same filter will be used to set the + * monitor status ring + */ + qdf_mem_zero(&(filter), sizeof(struct dp_mon_filter)); + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + + /* Setup the filter */ + filter.tlv_filter.mpdu_end = 1; + filter.tlv_filter.enable_mo = 1; + filter.tlv_filter.packet_header = 1; + + if (pdev->rx_enh_capture_mode == CDP_RX_ENH_CAPTURE_MPDU) { + filter.tlv_filter.header_per_msdu = 0; + filter.tlv_filter.enable_mo = 0; + } else if (pdev->rx_enh_capture_mode == + CDP_RX_ENH_CAPTURE_MPDU_MSDU) { + bool is_rx_mon_proto_flow_tag_enabled = + wlan_cfg_is_rx_mon_protocol_flow_tag_enabled(soc->wlan_cfg_ctx); + filter.tlv_filter.header_per_msdu = 1; + filter.tlv_filter.enable_mo = 0; + if (pdev->is_rx_enh_capture_trailer_enabled || + is_rx_mon_proto_flow_tag_enabled) + filter.tlv_filter.msdu_end = 1; + } + + dp_mon_filter_show_filter(pdev, mode, &filter); + + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_rx_enh_capture() - Reset the Rx capture mode filters + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_rx_enh_capture(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_RX_CAPTURE_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} +#endif /* WLAN_RX_PKT_CAPTURE_ENH */ + +/** + * dp_mon_filter_setup_mon_mode() - Setup the Rx monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_mon_mode(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_MONITOR_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + filter.valid = true; + dp_mon_filter_set_mon_cmn(pdev, &filter); + dp_mon_filter_show_filter(pdev, mode, &filter); + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + /* Clear the filter as the same filter will be used to set the + * monitor status ring + */ + qdf_mem_zero(&(filter), sizeof(struct dp_mon_filter)); + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + filter.tlv_filter.enable_mo = 1; + + dp_mon_filter_show_filter(pdev, mode, &filter); + + /* Store the above filter */ + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_mon_mode() - Reset the Rx monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_mon_mode(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + struct dp_soc *soc = NULL; + enum dp_mon_filter_mode mode = DP_MON_FILTER_MONITOR_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return; + } + + srng_type = ((soc->wlan_cfg_ctx->rxdma1_enable) ? + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF : + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF); + pdev->filter[mode][srng_type] = filter; + + srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + pdev->filter[mode][srng_type] = filter; +} + +#ifdef WDI_EVENT_ENABLE +/** + * dp_mon_filter_setup_rx_pkt_log_full() - Setup the Rx pktlog full mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_pkt_log_full(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_PKT_LOG_FULL_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + + /* Setup the filter */ + filter.tlv_filter.packet_header = 1; + filter.tlv_filter.msdu_start = 1; + filter.tlv_filter.msdu_end = 1; + filter.tlv_filter.mpdu_end = 1; + filter.tlv_filter.attention = 1; + + dp_mon_filter_show_filter(pdev, mode, &filter); + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_rx_pkt_log_full() - Reset the Rx pktlog full mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_rx_pkt_log_full(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_PKT_LOG_FULL_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_setup_rx_pkt_log_lite() - Setup the Rx pktlog lite mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_pkt_log_lite(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_PKT_LOG_LITE_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + /* Enabled the filter */ + filter.valid = true; + dp_mon_filter_set_status_cmn(pdev, &filter); + + dp_mon_filter_show_filter(pdev, mode, &filter); + pdev->filter[mode][srng_type] = filter; +} + +/** + * dp_mon_filter_reset_rx_pkt_log_lite() - Reset the Rx pktlog lite mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_rx_pkt_log_lite(struct dp_pdev *pdev) +{ + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_mode mode = DP_MON_FILTER_PKT_LOG_LITE_MODE; + enum dp_mon_filter_srng_type srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + pdev->filter[mode][srng_type] = filter; +} +#endif /* WDI_EVENT_ENABLE */ + +/** + * dp_mon_filter_update() - Setup the monitor filter setting for a srng + * type + * @pdev: DP pdev handle + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_mon_filter_update(struct dp_pdev *pdev) +{ + struct dp_soc *soc; + bool mon_mode_set = false; + struct dp_mon_filter filter = {0}; + enum dp_mon_filter_srng_type mon_srng_type = + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return QDF_STATUS_E_FAILURE; + } + + soc = pdev->soc; + if (!soc) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Soc Context is null")); + return QDF_STATUS_E_FAILURE; + } + + status = dp_mon_filter_check_co_exist(pdev); + if (status != QDF_STATUS_SUCCESS) + return status; + + /* + * Setup the filters for the monitor destination ring. + */ + if (!soc->wlan_cfg_ctx->rxdma1_enable) + mon_srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF; + + /* + * Setup the filters for the monitor mode. + */ + qdf_mem_zero(&(filter), sizeof(filter)); + dp_mon_filter_ht2_setup(soc, pdev, mon_srng_type, &filter); + + mon_mode_set = filter.valid; + if (mon_mode_set) { + status = dp_mon_ht2_rx_ring_cfg(soc, pdev, + mon_srng_type, + &filter.tlv_filter); + } else { + /* + * For WIN case the monitor buffer ring is used and it does need + * reset when monitor mode gets disabled. + */ + if (soc->wlan_cfg_ctx->rxdma1_enable) { + status = dp_mon_ht2_rx_ring_cfg(soc, pdev, + mon_srng_type, + &filter.tlv_filter); + } + } + + if (status != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Monitor destination ring filter setting failed")); + return QDF_STATUS_E_FAILURE; + } + + /* + * Setup the filters for the status ring. + */ + qdf_mem_zero(&(filter), sizeof(filter)); + dp_mon_filter_ht2_setup(soc, pdev, + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS, + &filter); + + /* + * Reset the monitor filters if the all the modes for the status rings + * are disabled. This is done to prevent the HW backpressure from the + * monitor destination ring in case the status ring filters + * are not enabled. + */ + if (!filter.valid && mon_mode_set) + dp_mon_filter_reset_mon_srng(soc, pdev, mon_srng_type); + + if (dp_mon_ht2_rx_ring_cfg(soc, pdev, + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS, + &filter.tlv_filter) != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Monitor status ring filter setting failed")); + dp_mon_filter_reset_mon_srng(soc, pdev, mon_srng_type); + return QDF_STATUS_E_FAILURE; + } + + return status; +} + +/** + * dp_mon_filter_dealloc() - Deallocate the filter objects to be stored in + * the radio object. + * @pdev: DP pdev handle + */ +void dp_mon_filter_dealloc(struct dp_pdev *pdev) +{ + enum dp_mon_filter_mode mode; + struct dp_mon_filter **mon_filter = NULL; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return; + } + + mon_filter = pdev->filter; + + /* + * Check if the monitor filters are already allocated to the pdev. + */ + if (!mon_filter) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Found NULL memmory for the Monitor filter")); + return; + } + + /* + * Iterate through the every mode and free the filter object. + */ + for (mode = 0; mode < DP_MON_FILTER_MAX_MODE; mode++) { + if (!mon_filter[mode]) { + continue; + } + + qdf_mem_free(mon_filter[mode]); + mon_filter[mode] = NULL; + } + + qdf_mem_free(mon_filter); + pdev->filter = NULL; +} + +/** + * dp_mon_filter_alloc() - Allocate the filter objects to be stored in + * the radio object. + * @pdev: DP pdev handle + */ +struct dp_mon_filter **dp_mon_filter_alloc(struct dp_pdev *pdev) +{ + struct dp_mon_filter **mon_filter = NULL; + enum dp_mon_filter_mode mode; + + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("pdev Context is null")); + return NULL; + } + + mon_filter = (struct dp_mon_filter **)qdf_mem_malloc( + (sizeof(struct dp_mon_filter *) * + DP_MON_FILTER_MAX_MODE)); + if (!mon_filter) { + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_ERROR, + FL("Monitor filter mem allocation failed")); + return NULL; + } + + qdf_mem_zero(mon_filter, + sizeof(struct dp_mon_filter *) * DP_MON_FILTER_MAX_MODE); + + /* + * Allocate the memory for filters for different srngs for each modes. + */ + for (mode = 0; mode < DP_MON_FILTER_MAX_MODE; mode++) { + mon_filter[mode] = qdf_mem_malloc(sizeof(struct dp_mon_filter) * + DP_MON_FILTER_SRNG_TYPE_MAX); + /* Assign the mon_filter to the pdev->filter such + * that the dp_mon_filter_dealloc() can free up the filters. */ + if (!mon_filter[mode]) { + pdev->filter = mon_filter; + goto fail; + } + } + + return mon_filter; +fail: + dp_mon_filter_dealloc(pdev); + return NULL; +} diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_mon_filter.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_mon_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..711185f28b424457655d71670686ab9c57b3ed31 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_mon_filter.h @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _DP_MON_FILTER_H_ +#define _DP_MON_FILTER_H_ + +/** + * Accessor Macros to access the software + * defined HTT filter htt_rx_ring_tlv_filter. + */ +#define DP_MON_FILTER_TLV_OFFSET 0x00000000 +#define DP_MON_FILTER_TLV_MASK 0xffffffff +#define DP_MON_FILTER_TLV_LSB 0 + +#define DP_MON_FILTER_FP_MGMT_OFFSET 0x00000004 +#define DP_MON_FILTER_FP_MGMT_MASK 0x0000ffff +#define DP_MON_FILTER_FP_MGMT_LSB 0 + +#define DP_MON_FILTER_MO_MGMT_OFFSET 0x00000004 +#define DP_MON_FILTER_MO_MGMT_MASK 0xffff0000 +#define DP_MON_FILTER_MO_MGMT_LSB 16 + +#define DP_MON_FILTER_FP_CTRL_OFFSET 0x00000008 +#define DP_MON_FILTER_FP_CTRL_MASK 0x0000ffff +#define DP_MON_FILTER_FP_CTRL_LSB 0 + +#define DP_MON_FILTER_MO_CTRL_OFFSET 0x00000008 +#define DP_MON_FILTER_MO_CTRL_MASK 0xffff0000 +#define DP_MON_FILTER_MO_CTRL_LSB 16 + +#define DP_MON_FILTER_FP_DATA_OFFSET 0x0000000c +#define DP_MON_FILTER_FP_DATA_MASK 0x0000ffff +#define DP_MON_FILTER_FP_DATA_LSB 0 + +#define DP_MON_FILTER_MO_DATA_OFFSET 0x0000000c +#define DP_MON_FILTER_MO_DATA_MASK 0xffff0000 +#define DP_MON_FILTER_MO_DATA_LSB 16 + +#define DP_MON_FILTER_MD_DATA_OFFSET 0x00000010 +#define DP_MON_FILTER_MD_DATA_MASK 0x0000ffff +#define DP_MON_FILTER_MD_DATA_LSB 0 + +#define DP_MON_FILTER_MD_MGMT_OFFSET 0x00000010 +#define DP_MON_FILTER_MD_MGMT_MASK 0xffff0000 +#define DP_MON_FILTER_MD_MGMT_LSB 16 + +#define DP_MON_FILTER_MD_CTRL_OFFSET 0x00000014 +#define DP_MON_FILTER_MD_CTRL_MASK 0x0000ffff +#define DP_MON_FILTER_MD_CTRL_LSB 0 + +#define DP_MON_FILTER_GET(src, field) \ + ((*((uint32_t *)((uint8_t *)(src) + DP_MON_ ## field ## _OFFSET)) & \ + (DP_MON_ ## field ## _MASK)) >> DP_MON_ ## field ## _LSB) \ + +#define DP_MON_FILTER_SET(dst, field, value) \ +do { \ + uint32_t *val = \ + ((uint32_t *)((uint8_t *)(dst) + DP_MON_ ## field ## _OFFSET)); \ + *val &= ~(DP_MON_ ## field ## _MASK); \ + *val |= ((value) << DP_MON_ ## field ## _LSB); \ +} while (0) + +#define DP_MON_FILTER_PRINT(fmt, args ...) \ + QDF_TRACE(QDF_MODULE_ID_MON_FILTER, QDF_TRACE_LEVEL_DEBUG, \ + fmt, ## args) +/** + * struct dp_mon_filter - Monitor TLV filter + * @valid: enable/disable TLV filter + * @tlv_filter: Rx ring TLV filter + */ +struct dp_mon_filter { + bool valid; + struct htt_rx_ring_tlv_filter tlv_filter; +}; + +/** + * enum dp_mon_filter_mode - Different modes for SRNG filters + * @DP_MON_FILTER_ENHACHED_STATS_MODE: PPDU enhanced stats mode + * @DP_MON_FILTER_SMART_MONITOR_MODE: Smart monitor mode + * @DP_MON_FILTER_MCOPY_MODE: AM copy mode + * @DP_MON_FILTER_MONITOR_MODE: Monitor mode + * @DP_MON_FILTER_RX_CAPTURE_MODE: Rx Capture mode + * @DP_MON_FILTER_PKT_LOG_FULL_MODE: Packet log full mode + * @DP_MON_FILTER_PKT_LOG_LITE_MODE: Packet log lite mode + */ +enum dp_mon_filter_mode { +#ifdef FEATURE_PERPKT_INFO + DP_MON_FILTER_ENHACHED_STATS_MODE, + DP_MON_FILTER_MCOPY_MODE, +#endif /* FEATURE_PERPKT_INFO */ +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) + DP_MON_FILTER_SMART_MONITOR_MODE, +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ + DP_MON_FILTER_MONITOR_MODE, +#ifdef WLAN_RX_PKT_CAPTURE_ENH + DP_MON_FILTER_RX_CAPTURE_MODE, +#endif /* WLAN_RX_PKT_CAPTURE_ENH */ + +#ifdef WDI_EVENT_ENABLE + DP_MON_FILTER_PKT_LOG_FULL_MODE, + DP_MON_FILTER_PKT_LOG_LITE_MODE, +#endif /* WDI_EVENT_ENABLE */ + DP_MON_FILTER_MAX_MODE +}; + +/** + * enum dp_mon_filter_srng_type - Srng types dynamic mode filter + * settings. + * @DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF: RXDMA srng type + * @DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS: RxDMA monitor status srng + * @DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF: RxDMA destination srng + * @DP_MON_FILTER_SRNG_TYPE_MAX: Srng max type + */ +enum dp_mon_filter_srng_type { + DP_MON_FILTER_SRNG_TYPE_RXDMA_BUF, + DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS, + DP_MON_FILTER_SRNG_TYPE_RXDMA_MON_BUF, + DP_MON_FILTER_SRNG_TYPE_MAX +}; + +/** + * enum dp_mon_filter_action - Action for storing the filters + * into the radio structure. + * @DP_MON_FILTER_CLEAR - Clears the filter for a mode + * @DP_MON_FILTER_SET - Set the filtes for a mode + */ +enum dp_mon_filter_action { + DP_MON_FILTER_CLEAR, + DP_MON_FILTER_SET, +}; + +#ifdef FEATURE_PERPKT_INFO +/** + * dp_mon_filter_setup_enhanced_stats() - Setup the enhanced stats filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_enhanced_stats(struct dp_pdev *pdev); + +/*** + * dp_mon_filter_reset_enhanced_stats() - Reset the enhanced stats filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_enhanced_stats(struct dp_pdev *pdev); + +/** + * dp_mon_filter_setup_mcopy_mode() - Setup the m_copy mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_mcopy_mode(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_mcopy_mode() - Reset the m_copy mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_mcopy_mode(struct dp_pdev *pdev); +#endif /* FEATURE_PERPKT_INFO */ + +#if defined(ATH_SUPPORT_NAC_RSSI) || defined(ATH_SUPPORT_NAC) +/** + * dp_mon_filter_setup_smart_monitor() - Setup the smart monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_smart_monitor(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_smart_monitor() - Reset the smart monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_smart_monitor(struct dp_pdev *pdev); +#endif /* ATH_SUPPORT_NAC_RSSI || ATH_SUPPORT_NAC */ + +#ifdef WLAN_RX_PKT_CAPTURE_ENH +/** + * dp_mon_filter_setup_rx_enh_capture() - Setup the Rx capture mode filters + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_enh_capture(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_rx_enh_capture() - Reset the Rx capture mode filters + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_rx_enh_capture(struct dp_pdev *pdev); +#endif /* WLAN_RX_PKT_CAPTURE_ENH */ + +/** + * dp_mon_filter_setup_mon_mode() - Setup the Rx monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_mon_mode(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_mon_mode() - Reset the Rx monitor mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_mon_mode(struct dp_pdev *pdev); + +#ifdef WDI_EVENT_ENABLE +/** + * dp_mon_filter_setup_rx_pkt_log_full() - Setup the Rx pktlog full mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_pkt_log_full(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_rx_pkt_log_full() - Reset the Rx pktlog full mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_rx_pkt_log_full(struct dp_pdev *pdev); + +/** + * dp_mon_filter_setup_rx_pkt_log_lite() - Setup the Rx pktlog lite mode filter + * in the radio object. + * @pdev: DP pdev handle + */ +void dp_mon_filter_setup_rx_pkt_log_lite(struct dp_pdev *pdev); + +/** + * dp_mon_filter_reset_rx_pkt_log_lite() - Reset the Rx pktlog lite mode filter + * @pdev: DP pdev handle + */ +void dp_mon_filter_reset_rx_pkt_log_lite(struct dp_pdev *pdev); +#endif /* WDI_EVENT_ENABLE */ + +/** + * dp_mon_filter_update() - Setup the monitor filter setting for a srng + * type + * @pdev: DP pdev handle + * + * Return: QDF_STATUS + */ +QDF_STATUS dp_mon_filter_update(struct dp_pdev *pdev); + +/** + * dp_mon_filter_dealloc() - Deallocate the filter objects to be stored in + * the radio object. + * @pdev: DP pdev handle + */ +void dp_mon_filter_dealloc(struct dp_pdev *pdev); + +/** + * dp_mon_filter_alloc() - Allocate the filter objects to be stored in + * the radio object. + * @pdev: DP pdev handle + */ +struct dp_mon_filter **dp_mon_filter_alloc(struct dp_pdev *pdev); +#endif /* #ifndef _DP_MON_FILTER_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.c index b332621f7691d2d01098fb3aafc09d634de60fd5..9cc238688bd8eb270ec54cea220039dd3e5af6b8 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -27,10 +28,6 @@ #include "dp_rx.h" #include #include -#ifdef CONFIG_MCL -#include -#include -#endif #include #include @@ -38,7 +35,34 @@ #include "dp_tx_capture.h" #endif -#ifdef DP_LFR +#ifdef FEATURE_WDS +static inline bool +dp_peer_ast_free_in_unmap_supported(struct dp_peer *peer, + struct dp_ast_entry *ast_entry) +{ + /* if peer map v2 is enabled we are not freeing ast entry + * here and it is supposed to be freed in unmap event (after + * we receive delete confirmation from target) + * + * if peer_id is invalid we did not get the peer map event + * for the peer free ast entry from here only in this case + */ + + if ((ast_entry->type != CDP_TXRX_AST_TYPE_WDS_HM_SEC) && + (ast_entry->type != CDP_TXRX_AST_TYPE_SELF)) + return true; + + return false; +} +#else +static inline bool +dp_peer_ast_free_in_unmap_supported(struct dp_peer *peer, + struct dp_ast_entry *ast_entry) +{ + return false; +} +#endif + static inline void dp_set_ssn_valid_flag(struct hal_reo_cmd_params *params, uint8_t valid) @@ -49,11 +73,6 @@ dp_set_ssn_valid_flag(struct hal_reo_cmd_params *params, "%s: Setting SSN valid bit to %d", __func__, valid); } -#else -static inline void -dp_set_ssn_valid_flag(struct hal_reo_cmd_params *params, - uint8_t valid) {}; -#endif static inline int dp_peer_find_mac_addr_cmp( union dp_align_mac_addr *mac_addr1, @@ -268,12 +287,15 @@ static inline void dp_peer_ast_cleanup(struct dp_soc *soc, txrx_ast_free_cb cb = ast->callback; void *cookie = ast->cookie; + dp_debug("mac_addr: " QDF_MAC_ADDR_FMT ", cb: %pK, cookie: %pK", + QDF_MAC_ADDR_REF(ast->mac_addr.raw), cb, cookie); + /* Call the callbacks to free up the cookie */ if (cb) { ast->callback = NULL; ast->cookie = NULL; cb(soc->ctrl_psoc, - soc, + dp_soc_to_cdp_soc(soc), cookie, CDP_TXRX_AST_DELETE_IN_PROGRESS); } @@ -296,6 +318,8 @@ static void dp_peer_ast_hash_detach(struct dp_soc *soc) if (!soc->ast_hash.bins) return; + dp_debug("%pK: num_ast_entries: %u", soc, soc->num_ast_entries); + qdf_spin_lock_bh(&soc->ast_lock); for (index = 0; index <= soc->ast_hash.mask; index++) { if (!TAILQ_EMPTY(&soc->ast_hash.bins[index])) { @@ -372,6 +396,9 @@ void dp_peer_ast_hash_remove(struct dp_soc *soc, /* Check if tail is not empty before delete*/ QDF_ASSERT(!TAILQ_EMPTY(&soc->ast_hash.bins[index])); + dp_debug("ast_idx: %u idx: %u mac_addr: " QDF_MAC_ADDR_FMT, + ase->ast_idx, index, QDF_MAC_ADDR_REF(ase->mac_addr.raw)); + TAILQ_FOREACH(tmpase, &soc->ast_hash.bins[index], hash_list_elem) { if (tmpase == ase) { found = 1; @@ -496,10 +523,9 @@ static inline void dp_peer_map_ast(struct dp_soc *soc, } QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: peer %pK ID %d vid %d mac %02x:%02x:%02x:%02x:%02x:%02x", - __func__, peer, hw_peer_id, vdev_id, mac_addr[0], - mac_addr[1], mac_addr[2], mac_addr[3], - mac_addr[4], mac_addr[5]); + "%s: peer %pK ID %d vid %d mac "QDF_MAC_ADDR_FMT, + __func__, peer, hw_peer_id, vdev_id, + QDF_MAC_ADDR_REF(mac_addr)); qdf_spin_lock_bh(&soc->ast_lock); @@ -530,8 +556,8 @@ static inline void dp_peer_map_ast(struct dp_soc *soc, return; } -void dp_peer_free_hmwds_cb(void *ctrl_psoc, - void *dp_soc, +void dp_peer_free_hmwds_cb(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + struct cdp_soc *dp_soc, void *cookie, enum cdp_ast_free_status status) { @@ -577,34 +603,53 @@ int dp_peer_add_ast(struct dp_soc *soc, uint32_t flags) { struct dp_ast_entry *ast_entry = NULL; - struct dp_vdev *vdev = NULL; + struct dp_vdev *vdev = NULL, *tmp_vdev = NULL; struct dp_pdev *pdev = NULL; uint8_t next_node_mac[6]; int ret = -1; txrx_ast_free_cb cb = NULL; void *cookie = NULL; - - qdf_spin_lock_bh(&soc->ast_lock); - if (peer->delete_in_progress) { - qdf_spin_unlock_bh(&soc->ast_lock); - return ret; - } + struct dp_peer *tmp_peer = NULL; + bool is_peer_found = false; vdev = peer->vdev; if (!vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, FL("Peers vdev is NULL")); QDF_ASSERT(0); - qdf_spin_unlock_bh(&soc->ast_lock); return ret; } pdev = vdev->pdev; + tmp_peer = dp_peer_find_hash_find(soc, mac_addr, 0, + DP_VDEV_ALL); + if (tmp_peer) { + tmp_vdev = tmp_peer->vdev; + if (!tmp_vdev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Peers vdev is NULL")); + QDF_ASSERT(0); + dp_peer_unref_delete(tmp_peer); + return ret; + } + if (tmp_vdev->pdev->pdev_id == pdev->pdev_id) + is_peer_found = true; + + dp_peer_unref_delete(tmp_peer); + } + + qdf_spin_lock_bh(&soc->ast_lock); + if (peer->delete_in_progress) { + qdf_spin_unlock_bh(&soc->ast_lock); + return ret; + } + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s: pdevid: %u vdev: %u ast_entry->type: %d flags: 0x%x peer_mac: %pM peer: %pK mac %pM", + "%s: pdevid: %u vdev: %u ast_entry->type: %d flags: 0x%x peer_mac: "QDF_MAC_ADDR_FMT" peer: %pK mac "QDF_MAC_ADDR_FMT, __func__, pdev->pdev_id, vdev->vdev_id, type, flags, - peer->mac_addr.raw, peer, mac_addr); + QDF_MAC_ADDR_REF(peer->mac_addr.raw), peer, + QDF_MAC_ADDR_REF(mac_addr)); /* fw supports only 2 times the max_peers ast entries */ @@ -632,6 +677,17 @@ int dp_peer_add_ast(struct dp_soc *soc, qdf_spin_unlock_bh(&soc->ast_lock); return 0; } + if (is_peer_found) { + /* During WDS to static roaming, peer is added + * to the list before static AST entry create. + * So, allow AST entry for STATIC type + * even if peer is present + */ + if (type != CDP_TXRX_AST_TYPE_STATIC) { + qdf_spin_unlock_bh(&soc->ast_lock); + return 0; + } + } } else { /* For HWMWDS_SEC entries can be added for same mac address * do not check for existing entry @@ -660,8 +716,7 @@ int dp_peer_add_ast(struct dp_soc *soc, * can take care of adding HMWDS ast enty on delete * confirmation from target */ - if ((type == CDP_TXRX_AST_TYPE_WDS_HM) && - soc->is_peer_map_unmap_v2) { + if (type == CDP_TXRX_AST_TYPE_WDS_HM) { struct dp_ast_free_cb_params *param = NULL; if (ast_entry->type == @@ -709,8 +764,8 @@ int dp_peer_add_ast(struct dp_soc *soc, * packet from station to the root via the repeater * should not remove the wds entry. */ - if ((ast_entry->type == CDP_TXRX_AST_TYPE_WDS) && - (type == CDP_TXRX_AST_TYPE_MEC) && + else if ((type == CDP_TXRX_AST_TYPE_MEC) && + (ast_entry->type == CDP_TXRX_AST_TYPE_WDS) && (ast_entry->peer == peer)) { ast_entry->is_active = FALSE; dp_peer_del_ast(soc, ast_entry); @@ -719,7 +774,9 @@ int dp_peer_add_ast(struct dp_soc *soc, /* Call the saved callback*/ if (cb) { - cb(soc->ctrl_psoc, soc, cookie, + cb(soc->ctrl_psoc, + dp_soc_to_cdp_soc(soc), + cookie, CDP_TXRX_AST_DELETE_IN_PROGRESS); } return 0; @@ -740,7 +797,6 @@ int dp_peer_add_ast(struct dp_soc *soc, qdf_mem_copy(&ast_entry->mac_addr.raw[0], mac_addr, QDF_MAC_ADDR_SIZE); ast_entry->pdev_id = vdev->pdev->pdev_id; - ast_entry->vdev_id = vdev->vdev_id; ast_entry->is_mapped = false; ast_entry->delete_in_progress = false; @@ -801,11 +857,13 @@ int dp_peer_add_ast(struct dp_soc *soc, (ast_entry->type != CDP_TXRX_AST_TYPE_WDS_HM_SEC)) { if (QDF_STATUS_SUCCESS == soc->cdp_soc.ol_ops->peer_add_wds_entry( - peer->vdev->osif_vdev, - (struct cdp_peer *)peer, + soc->ctrl_psoc, + peer->vdev->vdev_id, + peer->mac_addr.raw, mac_addr, next_node_mac, - flags)) { + flags, + ast_entry->type)) { qdf_spin_unlock_bh(&soc->ast_lock); return 0; } @@ -815,6 +873,71 @@ int dp_peer_add_ast(struct dp_soc *soc, return ret; } +/* + * dp_peer_free_ast_entry() - Free up the ast entry memory + * @soc: SoC handle + * @ast_entry: Address search entry + * + * This API is used to free up the memory associated with + * AST entry. + * + * Return: None + */ +void dp_peer_free_ast_entry(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + /* + * NOTE: Ensure that call to this API is done + * after soc->ast_lock is taken + */ + dp_debug("type: %d ast_idx: %u mac_addr: " QDF_MAC_ADDR_FMT, + ast_entry->type, ast_entry->ast_idx, + QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw)); + + ast_entry->callback = NULL; + ast_entry->cookie = NULL; + + DP_STATS_INC(soc, ast.deleted, 1); + dp_peer_ast_hash_remove(soc, ast_entry); + dp_peer_ast_cleanup(soc, ast_entry); + qdf_mem_free(ast_entry); + soc->num_ast_entries--; +} + +/* + * dp_peer_unlink_ast_entry() - Free up the ast entry memory + * @soc: SoC handle + * @ast_entry: Address search entry + * + * This API is used to remove/unlink AST entry from the peer list + * and hash list. + * + * Return: None + */ +void dp_peer_unlink_ast_entry(struct dp_soc *soc, + struct dp_ast_entry *ast_entry) +{ + /* + * NOTE: Ensure that call to this API is done + * after soc->ast_lock is taken + */ + struct dp_peer *peer = ast_entry->peer; + + TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); + + if (ast_entry == peer->self_ast_entry) + peer->self_ast_entry = NULL; + + /* + * release the reference only if it is mapped + * to ast_table + */ + if (ast_entry->is_mapped) + soc->ast_table[ast_entry->ast_idx] = NULL; + + ast_entry->peer = NULL; +} + /* * dp_peer_del_ast() - Delete and free AST entry * @soc: SoC handle @@ -833,45 +956,44 @@ void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry) if (!ast_entry) return; - peer = ast_entry->peer; + if (ast_entry->delete_in_progress) + return; + + dp_debug("call by %ps: ast_idx: %u mac_addr: " QDF_MAC_ADDR_FMT, + (void *)_RET_IP_, ast_entry->ast_idx, + QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw)); + + ast_entry->delete_in_progress = true; + peer = ast_entry->peer; dp_peer_ast_send_wds_del(soc, ast_entry); - /* - * release the reference only if it is mapped - * to ast_table - */ + /* Remove SELF and STATIC entries in teardown itself */ + if (!ast_entry->next_hop) + dp_peer_unlink_ast_entry(soc, ast_entry); + if (ast_entry->is_mapped) soc->ast_table[ast_entry->ast_idx] = NULL; - /* - * if peer map v2 is enabled we are not freeing ast entry + /* if peer map v2 is enabled we are not freeing ast entry * here and it is supposed to be freed in unmap event (after * we receive delete confirmation from target) * * if peer_id is invalid we did not get the peer map event * for the peer free ast entry from here only in this case */ - if (soc->is_peer_map_unmap_v2) { - - /* - * For HM_SEC and SELF type we do not receive unmap event - * free ast_entry from here it self - */ - if ((ast_entry->type != CDP_TXRX_AST_TYPE_WDS_HM_SEC) && - (ast_entry->type != CDP_TXRX_AST_TYPE_SELF)) - return; - } + if (dp_peer_ast_free_in_unmap_supported(peer, ast_entry)) + return; - /* SELF and STATIC entries are removed in teardown itself */ - if (ast_entry->next_hop) - TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); + /* for WDS secondary entry ast_entry->next_hop would be set so + * unlinking has to be done explicitly here. + * As this entry is not a mapped entry unmap notification from + * FW wil not come. Hence unlinkling is done right here. + */ + if (ast_entry->type == CDP_TXRX_AST_TYPE_WDS_HM_SEC) + dp_peer_unlink_ast_entry(soc, ast_entry); - DP_STATS_INC(soc, ast.deleted, 1); - dp_peer_ast_hash_remove(soc, ast_entry); - dp_peer_ast_cleanup(soc, ast_entry); - qdf_mem_free(ast_entry); - soc->num_ast_entries--; + dp_peer_free_ast_entry(soc, ast_entry); } /* @@ -895,12 +1017,19 @@ int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer, struct dp_peer *old_peer; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s: ast_entry->type: %d pdevid: %u vdevid: %u flags: 0x%x mac_addr: %pM peer_mac: %pM\n", + "%s: ast_entry->type: %d pdevid: %u vdevid: %u flags: 0x%x mac_addr: "QDF_MAC_ADDR_FMT" peer_mac: "QDF_MAC_ADDR_FMT"\n", __func__, ast_entry->type, peer->vdev->pdev->pdev_id, - peer->vdev->vdev_id, flags, ast_entry->mac_addr.raw, - peer->mac_addr.raw); - - if (ast_entry->delete_in_progress) + peer->vdev->vdev_id, flags, + QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw), + QDF_MAC_ADDR_REF(peer->mac_addr.raw)); + + /* Do not send AST update in below cases + * 1) Ast entry delete has already triggered + * 2) Peer delete is already triggered + * 3) We did not get the HTT map for create event + */ + if (ast_entry->delete_in_progress || peer->delete_in_progress || + !ast_entry->is_mapped) return ret; if ((ast_entry->type == CDP_TXRX_AST_TYPE_STATIC) || @@ -914,7 +1043,7 @@ int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer, */ if (qdf_unlikely(ast_entry->peer == peer) && (ast_entry->type == CDP_TXRX_AST_TYPE_WDS) && - (ast_entry->vdev_id == peer->vdev->vdev_id) && + (ast_entry->peer->vdev == peer->vdev) && (ast_entry->is_active)) return 0; @@ -924,12 +1053,12 @@ int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer, ast_entry->peer = peer; ast_entry->type = CDP_TXRX_AST_TYPE_WDS; ast_entry->pdev_id = peer->vdev->pdev->pdev_id; - ast_entry->vdev_id = peer->vdev->vdev_id; ast_entry->is_active = TRUE; TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry, ase_list_elem); ret = soc->cdp_soc.ol_ops->peer_update_wds_entry( - peer->vdev->osif_vdev, + soc->ctrl_psoc, + peer->vdev->vdev_id, ast_entry->mac_addr.raw, peer->mac_addr.raw, flags); @@ -1062,35 +1191,39 @@ void dp_peer_ast_send_wds_del(struct dp_soc *soc, struct dp_peer *peer = ast_entry->peer; struct cdp_soc_t *cdp_soc = &soc->cdp_soc; - if (ast_entry->delete_in_progress) - return; - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_TRACE, - "%s: ast_entry->type: %d pdevid: %u vdev: %u mac_addr: %pM next_hop: %u peer_mac: %pM\n", + "%s: ast_entry->type: %d pdevid: %u vdev: %u mac_addr: "QDF_MAC_ADDR_FMT" next_hop: %u peer_mac: "QDF_MAC_ADDR_FMT"\n", __func__, ast_entry->type, peer->vdev->pdev->pdev_id, - peer->vdev->vdev_id, ast_entry->mac_addr.raw, - ast_entry->next_hop, ast_entry->peer->mac_addr.raw); + peer->vdev->vdev_id, + QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw), + ast_entry->next_hop, + QDF_MAC_ADDR_REF(ast_entry->peer->mac_addr.raw)); if (ast_entry->next_hop) { - cdp_soc->ol_ops->peer_del_wds_entry(peer->vdev->osif_vdev, + cdp_soc->ol_ops->peer_del_wds_entry(soc->ctrl_psoc, + peer->vdev->vdev_id, ast_entry->mac_addr.raw, ast_entry->type); } - /* Remove SELF and STATIC entries in teardown itself */ - if (!ast_entry->next_hop) { - TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); - peer->self_ast_entry = NULL; - ast_entry->peer = NULL; - } - - ast_entry->delete_in_progress = true; } -static void dp_peer_ast_free_entry(struct dp_soc *soc, - struct dp_ast_entry *ast_entry) +/** + * dp_peer_ast_free_entry_by_mac() - find ast entry by MAC address and delete + * @soc: soc handle + * @peer: peer handle + * @mac_addr: mac address of the AST entry to searc and delete + * + * find the ast entry from the peer list using the mac address and free + * the entry. + * + * Return: SUCCESS or NOENT + */ +static int dp_peer_ast_free_entry_by_mac(struct dp_soc *soc, + struct dp_peer *peer, + uint8_t *mac_addr) { - struct dp_peer *peer = ast_entry->peer; + struct dp_ast_entry *ast_entry; void *cookie = NULL; txrx_ast_free_cb cb = NULL; @@ -1100,31 +1233,32 @@ static void dp_peer_ast_free_entry(struct dp_soc *soc, */ qdf_spin_lock_bh(&soc->ast_lock); - if (ast_entry->is_mapped) - soc->ast_table[ast_entry->ast_idx] = NULL; - TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem); - DP_STATS_INC(soc, ast.deleted, 1); - dp_peer_ast_hash_remove(soc, ast_entry); + ast_entry = dp_peer_ast_list_find(soc, peer, mac_addr); + if (!ast_entry) { + qdf_spin_unlock_bh(&soc->ast_lock); + return QDF_STATUS_E_NOENT; + } else if (ast_entry->is_mapped) { + soc->ast_table[ast_entry->ast_idx] = NULL; + } cb = ast_entry->callback; cookie = ast_entry->cookie; - ast_entry->callback = NULL; - ast_entry->cookie = NULL; - if (ast_entry == peer->self_ast_entry) - peer->self_ast_entry = NULL; + + dp_peer_unlink_ast_entry(soc, ast_entry); + dp_peer_free_ast_entry(soc, ast_entry); qdf_spin_unlock_bh(&soc->ast_lock); if (cb) { cb(soc->ctrl_psoc, - soc, + dp_soc_to_cdp_soc(soc), cookie, CDP_TXRX_AST_DELETED); } - qdf_mem_free(ast_entry); - soc->num_ast_entries--; + + return QDF_STATUS_SUCCESS; } struct dp_peer *dp_peer_find_hash_find(struct dp_soc *soc, @@ -1145,16 +1279,9 @@ struct dp_peer *dp_peer_find_hash_find(struct dp_soc *soc, index = dp_peer_find_hash_index(soc, mac_addr); qdf_spin_lock_bh(&soc->peer_ref_mutex); TAILQ_FOREACH(peer, &soc->peer_hash.bins[index], hash_list_elem) { -#if ATH_SUPPORT_WRAP - /* ProxySTA may have multiple BSS peer with same MAC address, - * modified find will take care of finding the correct BSS peer. - */ if (dp_peer_find_mac_addr_cmp(mac_addr, &peer->mac_addr) == 0 && ((peer->vdev->vdev_id == vdev_id) || (vdev_id == DP_VDEV_ALL))) { -#else - if (dp_peer_find_mac_addr_cmp(mac_addr, &peer->mac_addr) == 0) { -#endif /* found it - increment the ref count before releasing * the lock */ @@ -1286,6 +1413,9 @@ void dp_rx_tid_stats_cb(struct dp_soc *soc, void *cb_ctxt, struct dp_rx_tid *rx_tid = (struct dp_rx_tid *)cb_ctxt; struct hal_reo_queue_status *queue_status = &(reo_status->queue_status); + if (queue_status->header.status == HAL_REO_CMD_DRAIN) + return; + if (queue_status->header.status != HAL_REO_CMD_SUCCESS) { DP_PRINT_STATS("REO stats failure %d for TID %d\n", queue_status->header.status, rx_tid->tid); @@ -1383,10 +1513,9 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc, peer = dp_peer_find_hash_find(soc, peer_mac_addr, 0 /* is aligned */, vdev_id); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: peer %pK ID %d vid %d mac %02x:%02x:%02x:%02x:%02x:%02x", - __func__, peer, peer_id, vdev_id, peer_mac_addr[0], - peer_mac_addr[1], peer_mac_addr[2], peer_mac_addr[3], - peer_mac_addr[4], peer_mac_addr[5]); + "%s: peer %pK ID %d vid %d mac "QDF_MAC_ADDR_FMT, + __func__, peer, peer_id, vdev_id, + QDF_MAC_ADDR_REF(peer_mac_addr)); if (peer) { /* peer's ref count was already incremented by @@ -1432,33 +1561,64 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc, */ void -dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, +dp_rx_peer_map_handler(struct dp_soc *soc, uint16_t peer_id, uint16_t hw_peer_id, uint8_t vdev_id, uint8_t *peer_mac_addr, uint16_t ast_hash, uint8_t is_wds) { - struct dp_soc *soc = (struct dp_soc *)soc_handle; struct dp_peer *peer = NULL; enum cdp_txrx_ast_entry_type type = CDP_TXRX_AST_TYPE_STATIC; - dp_info("peer_map_event (soc:%pK): peer_id %d, hw_peer_id %d, peer_mac %02x:%02x:%02x:%02x:%02x:%02x, vdev_id %d", - soc, peer_id, hw_peer_id, peer_mac_addr[0], peer_mac_addr[1], - peer_mac_addr[2], peer_mac_addr[3], peer_mac_addr[4], - peer_mac_addr[5], vdev_id); - - if ((hw_peer_id < 0) || - (hw_peer_id >= wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx))) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "invalid hw_peer_id: %d", hw_peer_id); - qdf_assert_always(0); - } + dp_info("peer_map_event (soc:%pK): peer_id %d, hw_peer_id %d, peer_mac "QDF_MAC_ADDR_FMT", vdev_id %d", + soc, peer_id, hw_peer_id, + QDF_MAC_ADDR_REF(peer_mac_addr), vdev_id); /* Peer map event for WDS ast entry get the peer from * obj map */ if (is_wds) { peer = soc->peer_id_to_obj_map[peer_id]; + /* + * In certain cases like Auth attack on a repeater + * can result in the number of ast_entries falling + * in the same hash bucket to exceed the max_skid + * length supported by HW in root AP. In these cases + * the FW will return the hw_peer_id (ast_index) as + * 0xffff indicating HW could not add the entry in + * its table. Host has to delete the entry from its + * table in these cases. + */ + if (hw_peer_id == HTT_INVALID_PEER) { + DP_STATS_INC(soc, ast.map_err, 1); + if (!dp_peer_ast_free_entry_by_mac(soc, + peer, + peer_mac_addr)) + return; + + dp_alert("AST entry not found with peer %pK peer_id %u peer_mac "QDF_MAC_ADDR_FMT" mac_addr "QDF_MAC_ADDR_FMT" vdev_id %u next_hop %u", + peer, peer->peer_ids[0], + QDF_MAC_ADDR_REF(peer->mac_addr.raw), + QDF_MAC_ADDR_REF(peer_mac_addr), vdev_id, + is_wds); + + return; + } + } else { + /* + * It's the responsibility of the CP and FW to ensure + * that peer is created successfully. Ideally DP should + * not hit the below condition for directly assocaited + * peers. + */ + if ((hw_peer_id < 0) || + (hw_peer_id >= + wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx))) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "invalid hw_peer_id: %d", hw_peer_id); + qdf_assert_always(0); + } + peer = dp_peer_find_add_id(soc, peer_mac_addr, peer_id, hw_peer_id, vdev_id); @@ -1475,8 +1635,10 @@ dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, QDF_MAC_ADDR_SIZE); } - if (peer->vdev->opmode == wlan_op_mode_sta) + if (peer->vdev->opmode == wlan_op_mode_sta) { peer->vdev->bss_ast_hash = ast_hash; + peer->vdev->bss_ast_idx = hw_peer_id; + } /* Add ast entry incase self ast entry is * deleted due to DP CP sync issue @@ -1487,8 +1649,8 @@ dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, * referring it */ if (!peer->self_ast_entry) { - dp_info("Add self ast from map %pM", - peer_mac_addr); + dp_info("Add self ast from map "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(peer_mac_addr)); dp_peer_add_ast(soc, peer, peer_mac_addr, type, 0); @@ -1511,13 +1673,11 @@ dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, * Return: none */ void -dp_rx_peer_unmap_handler(void *soc_handle, uint16_t peer_id, +dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id, uint8_t vdev_id, uint8_t *mac_addr, uint8_t is_wds) { struct dp_peer *peer; - struct dp_ast_entry *ast_entry; - struct dp_soc *soc = (struct dp_soc *)soc_handle; uint8_t i; peer = __dp_peer_find_by_id(soc, peer_id); @@ -1534,21 +1694,14 @@ dp_rx_peer_unmap_handler(void *soc_handle, uint16_t peer_id, /* If V2 Peer map messages are enabled AST entry has to be freed here */ - if (soc->is_peer_map_unmap_v2 && is_wds) { - - qdf_spin_lock_bh(&soc->ast_lock); - ast_entry = dp_peer_ast_list_find(soc, peer, - mac_addr); - qdf_spin_unlock_bh(&soc->ast_lock); - - if (ast_entry) { - dp_peer_ast_free_entry(soc, ast_entry); + if (is_wds) { + if (!dp_peer_ast_free_entry_by_mac(soc, peer, mac_addr)) return; - } - dp_alert("AST entry not found with peer %pK peer_id %u peer_mac %pM mac_addr %pM vdev_id %u next_hop %u", + dp_alert("AST entry not found with peer %pK peer_id %u peer_mac "QDF_MAC_ADDR_FMT" mac_addr "QDF_MAC_ADDR_FMT" vdev_id %u next_hop %u", peer, peer->peer_ids[0], - peer->mac_addr.raw, mac_addr, vdev_id, + QDF_MAC_ADDR_REF(peer->mac_addr.raw), + QDF_MAC_ADDR_REF(mac_addr), vdev_id, is_wds); return; @@ -1565,6 +1718,11 @@ dp_rx_peer_unmap_handler(void *soc_handle, uint16_t peer_id, } } + /* + * Reset ast flow mapping table + */ + dp_peer_reset_flowq_map(peer); + if (soc->cdp_soc.ol_ops->peer_unmap_event) { soc->cdp_soc.ol_ops->peer_unmap_event(soc->ctrl_psoc, peer_id, vdev_id); @@ -1608,12 +1766,10 @@ static void dp_rx_tid_update_cb(struct dp_soc *soc, void *cb_ctxt, * dp_find_peer_by_addr - find peer instance by mac address * @dev: physical device instance * @peer_mac_addr: peer mac address - * @local_id: local id for the peer * * Return: peer instance pointer */ -void *dp_find_peer_by_addr(struct cdp_pdev *dev, uint8_t *peer_mac_addr, - uint8_t *local_id) +void *dp_find_peer_by_addr(struct cdp_pdev *dev, uint8_t *peer_mac_addr) { struct dp_pdev *pdev = (struct dp_pdev *)dev; struct dp_peer *peer; @@ -1623,9 +1779,8 @@ void *dp_find_peer_by_addr(struct cdp_pdev *dev, uint8_t *peer_mac_addr, if (!peer) return NULL; - /* Multiple peer ids? How can know peer id? */ - *local_id = peer->local_id; - dp_verbose_debug("peer %pK id %d", peer, *local_id); + dp_verbose_debug("peer %pK mac: "QDF_MAC_ADDR_FMT, peer, + QDF_MAC_ADDR_REF(peer->mac_addr.raw)); /* ref_cnt is incremented inside dp_peer_find_hash_find(). * Decrement it here. @@ -1640,20 +1795,23 @@ static bool dp_get_peer_vdev_roaming_in_progress(struct dp_peer *peer) struct ol_if_ops *ol_ops = NULL; bool is_roaming = false; uint8_t vdev_id = -1; + struct cdp_soc_t *soc; if (!peer) { dp_info("Peer is NULL. No roaming possible"); return false; } + + soc = dp_soc_to_cdp_soc_t(peer->vdev->pdev->soc); ol_ops = peer->vdev->pdev->soc->cdp_soc.ol_ops; if (ol_ops && ol_ops->is_roam_inprogress) { - dp_get_vdevid(peer, &vdev_id); + dp_get_vdevid(soc, peer->mac_addr.raw, &vdev_id); is_roaming = ol_ops->is_roam_inprogress(vdev_id); } - dp_info("peer: %pM, vdev_id: %d, is_roaming: %d", - peer->mac_addr.raw, vdev_id, is_roaming); + dp_info("peer: "QDF_MAC_ADDR_FMT", vdev_id: %d, is_roaming: %d", + QDF_MAC_ADDR_REF(peer->mac_addr.raw), vdev_id, is_roaming); return is_roaming; } @@ -1676,9 +1834,10 @@ QDF_STATUS dp_rx_tid_update_wifi3(struct dp_peer *peer, int tid, uint32_t if (start_seq < IEEE80211_SEQ_MAX) { params.u.upd_queue_params.update_ssn = 1; params.u.upd_queue_params.ssn = start_seq; + } else { + dp_set_ssn_valid_flag(¶ms, 0); } - dp_set_ssn_valid_flag(¶ms, 0); if (dp_reo_send_cmd(soc, CMD_UPDATE_RX_REO_QUEUE, ¶ms, dp_rx_tid_update_cb, rx_tid)) { dp_err_log("failed to send reo cmd CMD_UPDATE_RX_REO_QUEUE"); @@ -1692,7 +1851,7 @@ QDF_STATUS dp_rx_tid_update_wifi3(struct dp_peer *peer, int tid, uint32_t if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup) soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup( - peer->vdev->pdev->ctrl_pdev, + soc->ctrl_psoc, peer->vdev->pdev->pdev_id, peer->vdev->vdev_id, peer->mac_addr.raw, rx_tid->hw_qdesc_paddr, tid, tid, 1, ba_window_size); @@ -1737,7 +1896,7 @@ static void dp_reo_desc_free(struct dp_soc *soc, void *cb_ctxt, qdf_mem_free(freedesc); } -#if defined(QCA_WIFI_QCA8074_VP) && defined(BUILD_X86) +#if defined(CONFIG_WIFI_EMULATION_WIFI_3_0) && defined(BUILD_X86) /* Hawkeye emulation requires bus address to be >= 0x50000000 */ static inline int dp_reo_desc_addr_chk(qdf_dma_addr_t dma_addr) { @@ -1856,6 +2015,7 @@ QDF_STATUS dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid, } else { hw_qdesc_vaddr = rx_tid->hw_qdesc_vaddr_unaligned; } + rx_tid->hw_qdesc_vaddr_aligned = hw_qdesc_vaddr; /* TODO: Ensure that sec_type is set before ADDBA is received. * Currently this is set based on htt indication @@ -1909,7 +2069,9 @@ QDF_STATUS dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid, if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup) { if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup( - vdev->pdev->ctrl_pdev, peer->vdev->vdev_id, + soc->ctrl_psoc, + peer->vdev->pdev->pdev_id, + peer->vdev->vdev_id, peer->mac_addr.raw, rx_tid->hw_qdesc_paddr, tid, tid, 1, ba_window_size)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -2010,10 +2172,13 @@ static inline void dp_reo_limit_clean_batch_sz(uint32_t *list_size) * @desc: desc with resend update cmd flag set * @rx_tid: Desc RX tid associated with update cmd for resetting * valid field to 0 in h/w + * + * Return: QDF status */ -static void dp_resend_update_reo_cmd(struct dp_soc *soc, - struct reo_desc_list_node *desc, - struct dp_rx_tid *rx_tid) +static QDF_STATUS +dp_resend_update_reo_cmd(struct dp_soc *soc, + struct reo_desc_list_node *desc, + struct dp_rx_tid *rx_tid) { struct hal_reo_cmd_params params; @@ -2042,7 +2207,10 @@ static void dp_resend_update_reo_cmd(struct dp_soc *soc, (qdf_list_node_t *)desc); dp_err_log("failed to send reo cmd CMD_UPDATE_RX_REO_QUEUE"); DP_STATS_INC(soc, rx.err.reo_cmd_send_fail, 1); + return QDF_STATUS_E_FAILURE; } + + return QDF_STATUS_SUCCESS; } /* @@ -2063,6 +2231,7 @@ void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt, unsigned long curr_ts = qdf_get_system_timestamp(); uint32_t desc_size, tot_desc_size; struct hal_reo_cmd_params params; + bool flush_failure = false; if (reo_status->rx_queue_status.header.status == HAL_REO_CMD_DRAIN) { qdf_mem_zero(reo_status, sizeof(*reo_status)); @@ -2073,11 +2242,10 @@ void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt, } else if (reo_status->rx_queue_status.header.status != HAL_REO_CMD_SUCCESS) { /* Should not happen normally. Just print error for now */ - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: Rx tid HW desc deletion failed(%d): tid %d", - __func__, - reo_status->rx_queue_status.header.status, - freedesc->rx_tid.tid); + dp_info_rl("%s: Rx tid HW desc deletion failed(%d): tid %d", + __func__, + reo_status->rx_queue_status.header.status, + freedesc->rx_tid.tid); } QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW, @@ -2112,13 +2280,19 @@ void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt, /* First process descs with resend_update_reo_cmd set */ if (desc->resend_update_reo_cmd) { - dp_resend_update_reo_cmd(soc, desc, rx_tid); - continue; + if (dp_resend_update_reo_cmd(soc, desc, rx_tid) != + QDF_STATUS_SUCCESS) + break; + else + continue; } /* Flush and invalidate REO descriptor from HW cache: Base and * extension descriptors should be flushed separately */ - tot_desc_size = rx_tid->hw_qdesc_alloc_size; + if (desc->pending_ext_desc_size) + tot_desc_size = desc->pending_ext_desc_size; + else + tot_desc_size = rx_tid->hw_qdesc_alloc_size; /* Get base descriptor size by passing non-qos TID */ desc_size = hal_get_reo_qdesc_size(soc->hal_soc, 0, DP_NON_QOS_TID); @@ -2137,13 +2311,22 @@ void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt, ¶ms, NULL, NULL)) { - dp_err_rl("fail to send CMD_CACHE_FLUSH:" - "tid %d desc %pK", rx_tid->tid, - (void *)(rx_tid->hw_qdesc_paddr)); - DP_STATS_INC(soc, rx.err.reo_cmd_send_fail, 1); + dp_info_rl("fail to send CMD_CACHE_FLUSH:" + "tid %d desc %pK", rx_tid->tid, + (void *)(rx_tid->hw_qdesc_paddr)); + desc->pending_ext_desc_size = tot_desc_size + + desc_size; + dp_reo_desc_clean_up(soc, desc, reo_status); + flush_failure = true; + break; } } + if (flush_failure) + break; + else + desc->pending_ext_desc_size = desc_size; + /* Flush base descriptor */ qdf_mem_zero(¶ms, sizeof(params)); params.std.need_status = 1; @@ -2167,10 +2350,11 @@ void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt, * In case of MCL path add the desc back to the free * desc list and defer deletion. */ - dp_err_log("%s: fail to send REO cmd to flush cache: tid %d", + dp_info_rl("%s: fail to send REO cmd to flush cache: tid %d", __func__, rx_tid->tid); dp_reo_desc_clean_up(soc, desc, &reo_status); DP_STATS_INC(soc, rx.err.reo_cmd_send_fail, 1); + break; } } qdf_spin_unlock_bh(&soc->reo_desc_freelist_lock); @@ -2382,7 +2566,8 @@ void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer, bool reuse) } #ifdef notyet /* See if FW can remove queues as part of peer cleanup */ if (soc->ol_ops->peer_rx_reorder_queue_remove) { - soc->ol_ops->peer_rx_reorder_queue_remove(vdev->pdev->ctrl_pdev, + soc->ol_ops->peer_rx_reorder_queue_remove(soc->ctrl_psoc, + peer->vdev->pdev->pdev_id, peer->vdev->vdev_id, peer->mac_addr.raw, tid_delete_mask); } @@ -2392,6 +2577,32 @@ void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer, bool reuse) qdf_spinlock_destroy(&peer->rx_tid[tid].tid_lock); } +#ifdef FEATURE_PERPKT_INFO +/* + * dp_peer_ppdu_delayed_ba_init() Initialize ppdu in peer + * @peer: Datapath peer + * + * return: void + */ +void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer) +{ + qdf_mem_zero(&peer->delayed_ba_ppdu_stats, + sizeof(struct cdp_delayed_tx_completion_ppdu_user)); + peer->last_delayed_ba = false; + peer->last_delayed_ba_ppduid = 0; +} +#else +/* + * dp_peer_ppdu_delayed_ba_init() Initialize ppdu in peer + * @peer: Datapath peer + * + * return: void + */ +void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer) +{ +} +#endif + /* * dp_peer_cleanup() – Cleanup peer information * @vdev: Datapath vdev @@ -2448,11 +2659,10 @@ static void dp_teardown_256_ba_sessions(struct dp_peer *peer) qdf_spin_unlock_bh(&rx_tid->tid_lock); if (peer->vdev->pdev->soc->cdp_soc.ol_ops->send_delba) peer->vdev->pdev->soc->cdp_soc.ol_ops->send_delba( - peer->vdev->pdev->ctrl_pdev, - peer->ctrl_peer, - peer->mac_addr.raw, - tid, peer->vdev->ctrl_vdev, - delba_rcode); + peer->vdev->pdev->soc->ctrl_psoc, + peer->vdev->vdev_id, + peer->mac_addr.raw, + tid, delba_rcode); } else { qdf_spin_unlock_bh(&rx_tid->tid_lock); } @@ -2466,21 +2676,26 @@ static void dp_teardown_256_ba_sessions(struct dp_peer *peer) /* * dp_rx_addba_resp_tx_completion_wifi3() – Update Rx Tid State * -* @peer: Datapath peer handle +* @soc: Datapath soc handle +* @peer_mac: Datapath peer mac address +* @vdev_id: id of atapath vdev * @tid: TID number * @status: tx completion status * Return: 0 on success, error code on failure */ -int dp_addba_resp_tx_completion_wifi3(void *peer_handle, +int dp_addba_resp_tx_completion_wifi3(struct cdp_soc_t *cdp_soc, + uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, int status) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)cdp_soc, + peer_mac, 0, vdev_id); struct dp_rx_tid *rx_tid = NULL; if (!peer || peer->delete_in_progress) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "%s: Peer is NULL!\n", __func__); - return QDF_STATUS_E_FAILURE; + goto fail; } rx_tid = &peer->rx_tid[tid]; qdf_spin_lock_bh(&rx_tid->tid_lock); @@ -2491,7 +2706,8 @@ int dp_addba_resp_tx_completion_wifi3(void *peer_handle, rx_tid->ba_status = DP_RX_BA_INACTIVE; qdf_spin_unlock_bh(&rx_tid->tid_lock); dp_err("RxTid- %d addba rsp tx completion failed", tid); - return QDF_STATUS_SUCCESS; + + goto success; } rx_tid->num_addba_rsp_success++; @@ -2500,15 +2716,15 @@ int dp_addba_resp_tx_completion_wifi3(void *peer_handle, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "%s: Rx Tid- %d hw qdesc is not in IN_PROGRESS", __func__, tid); - return QDF_STATUS_E_FAILURE; + goto fail; } if (!qdf_atomic_read(&peer->is_default_route_set)) { qdf_spin_unlock_bh(&rx_tid->tid_lock); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s: default route is not set for peer: %pM", - __func__, peer->mac_addr.raw); - return QDF_STATUS_E_FAILURE; + "%s: default route is not set for peer: "QDF_MAC_ADDR_FMT, + __func__, QDF_MAC_ADDR_REF(peer->mac_addr.raw)); + goto fail; } if (dp_rx_tid_update_wifi3(peer, tid, @@ -2543,30 +2759,46 @@ int dp_addba_resp_tx_completion_wifi3(void *peer_handle, dp_teardown_256_ba_sessions(peer); peer->kill_256_sessions = 0; } + +success: + dp_peer_unref_delete(peer); return QDF_STATUS_SUCCESS; + +fail: + if (peer) + dp_peer_unref_delete(peer); + + return QDF_STATUS_E_FAILURE; } /* * dp_rx_addba_responsesetup_wifi3() – Process ADDBA request from peer * -* @peer: Datapath peer handle +* @soc: Datapath soc handle +* @peer_mac: Datapath peer mac address +* @vdev_id: id of atapath vdev * @tid: TID number * @dialogtoken: output dialogtoken * @statuscode: output dialogtoken * @buffersize: Output BA window size * @batimeout: Output BA timeout */ -void dp_addba_responsesetup_wifi3(void *peer_handle, uint8_t tid, - uint8_t *dialogtoken, uint16_t *statuscode, - uint16_t *buffersize, uint16_t *batimeout) +QDF_STATUS +dp_addba_responsesetup_wifi3(struct cdp_soc_t *cdp_soc, uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, + uint8_t *dialogtoken, uint16_t *statuscode, + uint16_t *buffersize, uint16_t *batimeout) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; struct dp_rx_tid *rx_tid = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)cdp_soc, + peer_mac, 0, vdev_id); if (!peer || peer->delete_in_progress) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "%s: Peer is NULL!\n", __func__); - return; + status = QDF_STATUS_E_FAILURE; + goto fail; } rx_tid = &peer->rx_tid[tid]; qdf_spin_lock_bh(&rx_tid->tid_lock); @@ -2577,6 +2809,12 @@ void dp_addba_responsesetup_wifi3(void *peer_handle, uint8_t tid, *buffersize = rx_tid->ba_win_size; *batimeout = 0; qdf_spin_unlock_bh(&rx_tid->tid_lock); + +fail: + if (peer) + dp_peer_unref_delete(peer); + + return status; } /* dp_check_ba_buffersize() - Check buffer size in request @@ -2626,7 +2864,9 @@ static void dp_check_ba_buffersize(struct dp_peer *peer, /* * dp_addba_requestprocess_wifi3() - Process ADDBA request from peer * - * @peer: Datapath peer handle + * @soc: Datapath soc handle + * @peer_mac: Datapath peer mac address + * @vdev_id: id of atapath vdev * @dialogtoken: dialogtoken from ADDBA frame * @tid: TID number * @batimeout: BA timeout @@ -2635,19 +2875,25 @@ static void dp_check_ba_buffersize(struct dp_peer *peer, * * Return: 0 on success, error code on failure */ -int dp_addba_requestprocess_wifi3(void *peer_handle, +int dp_addba_requestprocess_wifi3(struct cdp_soc_t *cdp_soc, + uint8_t *peer_mac, + uint16_t vdev_id, uint8_t dialogtoken, uint16_t tid, uint16_t batimeout, uint16_t buffersize, uint16_t startseqnum) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; + QDF_STATUS status = QDF_STATUS_SUCCESS; struct dp_rx_tid *rx_tid = NULL; + struct dp_soc *soc = (struct dp_soc *)cdp_soc; + struct dp_peer *peer = dp_peer_find_hash_find(soc, + peer_mac, 0, vdev_id); if (!peer || peer->delete_in_progress) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "%s: Peer is NULL!\n", __func__); - return QDF_STATUS_E_FAILURE; + status = QDF_STATUS_E_FAILURE; + goto fail; } rx_tid = &peer->rx_tid[tid]; qdf_spin_lock_bh(&rx_tid->tid_lock); @@ -2658,32 +2904,38 @@ int dp_addba_requestprocess_wifi3(void *peer_handle, rx_tid->ba_status = DP_RX_BA_INACTIVE; peer->active_ba_session_cnt--; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s: Addba recvd for Rx Tid-%d hw qdesc is already setup", - __func__, tid); + "%s: Rx Tid- %d hw qdesc is already setup", + __func__, tid); } if (rx_tid->ba_status == DP_RX_BA_IN_PROGRESS) { qdf_spin_unlock_bh(&rx_tid->tid_lock); - return QDF_STATUS_E_FAILURE; + status = QDF_STATUS_E_FAILURE; + goto fail; + } + + if (wlan_cfg_is_dp_force_rx_64_ba(soc->wlan_cfg_ctx)) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "force use BA64 scheme"); + buffersize = qdf_min((uint16_t)64, buffersize); } if (rx_tid->rx_ba_win_size_override == DP_RX_BA_SESSION_DISABLE) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "%s disable BA session by refuse addba req", - __func__); + "%s disable BA session", + __func__); buffersize = 1; } else if (rx_tid->rx_ba_win_size_override) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, "%s override BA win to %d", __func__, - rx_tid->rx_ba_win_size_override); + rx_tid->rx_ba_win_size_override); buffersize = rx_tid->rx_ba_win_size_override; } else { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, "%s restore BA win %d based on addba req", - __func__, buffersize); - + __func__, buffersize); } dp_check_ba_buffersize(peer, tid, buffersize); @@ -2692,7 +2944,8 @@ int dp_addba_requestprocess_wifi3(void *peer_handle, rx_tid->ba_win_size, startseqnum)) { rx_tid->ba_status = DP_RX_BA_INACTIVE; qdf_spin_unlock_bh(&rx_tid->tid_lock); - return QDF_STATUS_E_FAILURE; + status = QDF_STATUS_E_FAILURE; + goto fail; } rx_tid->ba_status = DP_RX_BA_IN_PROGRESS; @@ -2709,46 +2962,80 @@ int dp_addba_requestprocess_wifi3(void *peer_handle, qdf_spin_unlock_bh(&rx_tid->tid_lock); - return QDF_STATUS_SUCCESS; +fail: + if (peer) + dp_peer_unref_delete(peer); + + return status; } /* * dp_set_addba_response() – Set a user defined ADDBA response status code * -* @peer: Datapath peer handle +* @soc: Datapath soc handle +* @peer_mac: Datapath peer mac address +* @vdev_id: id of atapath vdev * @tid: TID number * @statuscode: response status code to be set */ -void dp_set_addba_response(void *peer_handle, uint8_t tid, - uint16_t statuscode) +QDF_STATUS +dp_set_addba_response(struct cdp_soc_t *cdp_soc, uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, uint16_t statuscode) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; - struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)cdp_soc, + peer_mac, 0, vdev_id); + struct dp_rx_tid *rx_tid; + QDF_STATUS status = QDF_STATUS_SUCCESS; + if (!peer || peer->delete_in_progress) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s: Peer is NULL!\n", __func__); + status = QDF_STATUS_E_FAILURE; + goto fail; + } + + rx_tid = &peer->rx_tid[tid]; qdf_spin_lock_bh(&rx_tid->tid_lock); rx_tid->userstatuscode = statuscode; qdf_spin_unlock_bh(&rx_tid->tid_lock); +fail: + if (peer) + dp_peer_unref_delete(peer); + + return status; } /* * dp_rx_delba_process_wifi3() – Process DELBA from peer -* @peer: Datapath peer handle +* @soc: Datapath soc handle +* @peer_mac: Datapath peer mac address +* @vdev_id: id of atapath vdev * @tid: TID number * @reasoncode: Reason code received in DELBA frame * * Return: 0 on success, error code on failure */ -int dp_delba_process_wifi3(void *peer_handle, - int tid, uint16_t reasoncode) +int dp_delba_process_wifi3(struct cdp_soc_t *cdp_soc, uint8_t *peer_mac, + uint16_t vdev_id, int tid, uint16_t reasoncode) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; - struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_rx_tid *rx_tid; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)cdp_soc, + peer_mac, 0, vdev_id); + if (!peer || peer->delete_in_progress) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s: Peer is NULL!\n", __func__); + status = QDF_STATUS_E_FAILURE; + goto fail; + } + rx_tid = &peer->rx_tid[tid]; qdf_spin_lock_bh(&rx_tid->tid_lock); if (rx_tid->ba_status == DP_RX_BA_INACTIVE || rx_tid->ba_status == DP_RX_BA_IN_PROGRESS) { qdf_spin_unlock_bh(&rx_tid->tid_lock); - return QDF_STATUS_E_FAILURE; + status = QDF_STATUS_E_FAILURE; + goto fail; } /* TODO: See if we can delete the existing REO queue descriptor and * replace with a new one without queue extenstion descript to save @@ -2761,28 +3048,38 @@ int dp_delba_process_wifi3(void *peer_handle, rx_tid->ba_status = DP_RX_BA_INACTIVE; peer->active_ba_session_cnt--; qdf_spin_unlock_bh(&rx_tid->tid_lock); - return 0; +fail: + if (peer) + dp_peer_unref_delete(peer); + + return status; } /* * dp_rx_delba_tx_completion_wifi3() – Send Delba Request * - * @peer: Datapath peer handle + * @soc: Datapath soc handle + * @peer_mac: Datapath peer mac address + * @vdev_id: id of atapath vdev * @tid: TID number * @status: tx completion status * Return: 0 on success, error code on failure */ -int dp_delba_tx_completion_wifi3(void *peer_handle, +int dp_delba_tx_completion_wifi3(struct cdp_soc_t *cdp_soc, uint8_t *peer_mac, + uint16_t vdev_id, uint8_t tid, int status) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; + QDF_STATUS ret = QDF_STATUS_SUCCESS; struct dp_rx_tid *rx_tid = NULL; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)cdp_soc, + peer_mac, 0, vdev_id); if (!peer || peer->delete_in_progress) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "%s: Peer is NULL!", __func__); - return QDF_STATUS_E_FAILURE; + ret = QDF_STATUS_E_FAILURE; + goto end; } rx_tid = &peer->rx_tid[tid]; qdf_spin_lock_bh(&rx_tid->tid_lock); @@ -2798,11 +3095,12 @@ int dp_delba_tx_completion_wifi3(void *peer_handle, qdf_spin_unlock_bh(&rx_tid->tid_lock); if (peer->vdev->pdev->soc->cdp_soc.ol_ops->send_delba) peer->vdev->pdev->soc->cdp_soc.ol_ops->send_delba( - peer->vdev->pdev->ctrl_pdev, peer->ctrl_peer, - peer->mac_addr.raw, tid, peer->vdev->ctrl_vdev, + peer->vdev->pdev->soc->ctrl_psoc, + peer->vdev->vdev_id, + peer->mac_addr.raw, tid, rx_tid->delba_rcode); } - return QDF_STATUS_SUCCESS; + goto end; } else { rx_tid->delba_tx_success_cnt++; rx_tid->delba_tx_retry = 0; @@ -2819,30 +3117,18 @@ int dp_delba_tx_completion_wifi3(void *peer_handle, } qdf_spin_unlock_bh(&rx_tid->tid_lock); - return QDF_STATUS_SUCCESS; -} - -void dp_rx_discard(struct dp_vdev *vdev, struct dp_peer *peer, unsigned tid, - qdf_nbuf_t msdu_list) -{ - while (msdu_list) { - qdf_nbuf_t msdu = msdu_list; +end: + if (peer) + dp_peer_unref_delete(peer); - msdu_list = qdf_nbuf_next(msdu_list); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, - "discard rx %pK from partly-deleted peer %pK (%02x:%02x:%02x:%02x:%02x:%02x)", - msdu, peer, - peer->mac_addr.raw[0], peer->mac_addr.raw[1], - peer->mac_addr.raw[2], peer->mac_addr.raw[3], - peer->mac_addr.raw[4], peer->mac_addr.raw[5]); - qdf_nbuf_free(msdu); - } + return ret; } - /** * dp_set_pn_check_wifi3() - enable PN check in REO for security - * @peer: Datapath peer handle + * @soc: Datapath soc handle + * @peer_mac: Datapath peer mac address + * @vdev_id: id of atapath vdev * @vdev: Datapath vdev * @pdev - data path device instance * @sec_type - security type @@ -2850,24 +3136,30 @@ void dp_rx_discard(struct dp_vdev *vdev, struct dp_peer *peer, unsigned tid, * */ -void -dp_set_pn_check_wifi3(struct cdp_vdev *vdev_handle, struct cdp_peer *peer_handle, enum cdp_sec_type sec_type, uint32_t *rx_pn) +QDF_STATUS +dp_set_pn_check_wifi3(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, enum cdp_sec_type sec_type, + uint32_t *rx_pn) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; - struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; struct dp_pdev *pdev; - struct dp_soc *soc; int i; uint8_t pn_size; struct hal_reo_cmd_params params; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc, + peer_mac, 0, vdev_id); + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); - /* preconditions */ - qdf_assert(vdev); + if (!vdev || !peer || peer->delete_in_progress) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s: Peer is NULL!\n", __func__); + status = QDF_STATUS_E_FAILURE; + goto fail; + } pdev = vdev->pdev; - soc = pdev->soc; - - qdf_mem_zero(¶ms, sizeof(params)); params.std.need_status = 1; @@ -2929,13 +3221,15 @@ dp_set_pn_check_wifi3(struct cdp_vdev *vdev_handle, struct cdp_peer *peer_handle params.u.upd_queue_params.pn_127_96 = rx_pn[3]; } rx_tid->pn_size = pn_size; - if (dp_reo_send_cmd(soc, CMD_UPDATE_RX_REO_QUEUE, + if (dp_reo_send_cmd(cdp_soc_t_to_dp_soc(soc), + CMD_UPDATE_RX_REO_QUEUE, ¶ms, dp_rx_tid_update_cb, rx_tid)) { dp_err_log("fail to send CMD_UPDATE_RX_REO_QUEUE" "tid %d desc %pK", rx_tid->tid, (void *)(rx_tid->hw_qdesc_paddr)); - DP_STATS_INC(soc, rx.err.reo_cmd_send_fail, 1); + DP_STATS_INC(cdp_soc_t_to_dp_soc(soc), + rx.err.reo_cmd_send_fail, 1); } } else { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, @@ -2943,48 +3237,66 @@ dp_set_pn_check_wifi3(struct cdp_vdev *vdev_handle, struct cdp_peer *peer_handle } qdf_spin_unlock_bh(&rx_tid->tid_lock); } +fail: + if (peer) + dp_peer_unref_delete(peer); + + return status; } /** - * dp_set_key_sec_type_wifi3() - * @peer: Datapath peer handle + * dp_set_key_sec_type_wifi3() - set security mode of key + * @soc: Datapath soc handle + * @peer_mac: Datapath peer mac address + * @vdev_id: id of atapath vdev * @vdev: Datapath vdev * @pdev - data path device instance * @sec_type - security type - * @rx_pn - Receive pn starting number - * #is_unicast ucast/mcast key type + * #is_unicast - key type + * */ -void -dp_set_key_sec_type_wifi3(struct cdp_vdev *vdev_handle, - struct cdp_peer *peer_handle, - enum cdp_sec_type sec_type, +QDF_STATUS +dp_set_key_sec_type_wifi3(struct cdp_soc_t *soc, uint8_t vdev_id, + uint8_t *peer_mac, enum cdp_sec_type sec_type, bool is_unicast) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc, + peer_mac, 0, vdev_id); + QDF_STATUS status = QDF_STATUS_SUCCESS; int sec_index; + if (!peer || peer->delete_in_progress) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s: Peer is NULL!\n", __func__); + status = QDF_STATUS_E_FAILURE; + goto fail; + } + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, - "sec type for peer %pK (%02x:%02x:%02x:%02x:%02x:%02x): %s key of type %d", + "key sec spec for peer %pK "QDF_MAC_ADDR_FMT": %s key of type %d", peer, - peer->mac_addr.raw[0], peer->mac_addr.raw[1], - peer->mac_addr.raw[2], peer->mac_addr.raw[3], - peer->mac_addr.raw[4], peer->mac_addr.raw[5], + QDF_MAC_ADDR_REF(peer->mac_addr.raw), is_unicast ? "ucast" : "mcast", sec_type); sec_index = is_unicast ? dp_sec_ucast : dp_sec_mcast; peer->security[sec_index].sec_type = sec_type; -} +fail: + if (peer) + dp_peer_unref_delete(peer); + + return status; +} void -dp_rx_sec_ind_handler(void *soc_handle, uint16_t peer_id, - enum cdp_sec_type sec_type, int is_unicast, u_int32_t *michael_key, - u_int32_t *rx_pn) +dp_rx_sec_ind_handler(struct dp_soc *soc, uint16_t peer_id, + enum cdp_sec_type sec_type, int is_unicast, + u_int32_t *michael_key, + u_int32_t *rx_pn) { - struct dp_soc *soc = (struct dp_soc *)soc_handle; struct dp_peer *peer; int sec_index; @@ -2996,11 +3308,9 @@ dp_rx_sec_ind_handler(void *soc_handle, uint16_t peer_id, return; } QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, - "sec spec for peer %pK (%02x:%02x:%02x:%02x:%02x:%02x): %s key of type %d", + "sec spec for peer %pK "QDF_MAC_ADDR_FMT": %s key of type %d", peer, - peer->mac_addr.raw[0], peer->mac_addr.raw[1], - peer->mac_addr.raw[2], peer->mac_addr.raw[3], - peer->mac_addr.raw[4], peer->mac_addr.raw[5], + QDF_MAC_ADDR_REF(peer->mac_addr.raw), is_unicast ? "ucast" : "mcast", sec_type); sec_index = is_unicast ? dp_sec_ucast : dp_sec_mcast; @@ -3089,11 +3399,10 @@ dp_rx_delba_ind_handler(void *soc_handle, uint16_t peer_id, if (soc->cdp_soc.ol_ops->send_delba) soc->cdp_soc.ol_ops->send_delba( - peer->vdev->pdev->ctrl_pdev, - peer->ctrl_peer, + peer->vdev->pdev->soc->ctrl_psoc, + peer->vdev->vdev_id, peer->mac_addr.raw, tid, - peer->vdev->ctrl_vdev, rx_tid->delba_rcode); } } else { @@ -3106,25 +3415,21 @@ dp_rx_delba_ind_handler(void *soc_handle, uint16_t peer_id, return status; } -#ifdef CONFIG_MCL -/** - * dp_register_peer() - Register peer into physical device - * @pdev - data path device instance - * @sta_desc - peer description - * - * Register peer into physical device - * - * Return: QDF_STATUS_SUCCESS registration success - * QDF_STATUS_E_FAULT peer not found - */ -QDF_STATUS dp_register_peer(struct cdp_pdev *pdev_handle, - struct ol_txrx_desc_type *sta_desc) + +#ifdef DP_PEER_EXTENDED_API +QDF_STATUS dp_register_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct ol_txrx_desc_type *sta_desc) { struct dp_peer *peer; - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (!pdev) + return QDF_STATUS_E_FAULT; + + peer = dp_find_peer_by_addr((struct cdp_pdev *)pdev, + sta_desc->peer_addr.bytes); - peer = dp_peer_find_by_local_id((struct cdp_pdev *)pdev, - sta_desc->sta_id); if (!peer) return QDF_STATUS_E_FAULT; @@ -3137,29 +3442,22 @@ QDF_STATUS dp_register_peer(struct cdp_pdev *pdev_handle, return QDF_STATUS_SUCCESS; } -/** - * dp_clear_peer() - remove peer from physical device - * @pdev - data path device instance - * @sta_id - local peer id - * - * remove peer from physical device - * - * Return: QDF_STATUS_SUCCESS registration success - * QDF_STATUS_E_FAULT peer not found - */ -QDF_STATUS dp_clear_peer(struct cdp_pdev *pdev_handle, uint8_t local_id) +QDF_STATUS +dp_clear_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct qdf_mac_addr peer_addr) { struct dp_peer *peer; - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - struct dp_soc *soc; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (!pdev) + return QDF_STATUS_E_FAULT; - peer = dp_peer_find_by_local_id((struct cdp_pdev *)pdev, local_id); + peer = dp_find_peer_by_addr((struct cdp_pdev *)pdev, peer_addr.bytes); if (!peer || !peer->valid) return QDF_STATUS_E_FAULT; - soc = pdev->soc; dp_clear_peer_internal(soc, peer); - return QDF_STATUS_SUCCESS; } @@ -3168,7 +3466,6 @@ QDF_STATUS dp_clear_peer(struct cdp_pdev *pdev_handle, uint8_t local_id) * @pdev - data path device instance * @vdev - virtual interface instance * @peer_addr - peer mac address - * @peer_id - local peer id with target mac address * * Find peer by peer mac address within vdev * @@ -3177,13 +3474,13 @@ QDF_STATUS dp_clear_peer(struct cdp_pdev *pdev_handle, uint8_t local_id) */ void *dp_find_peer_by_addr_and_vdev(struct cdp_pdev *pdev_handle, struct cdp_vdev *vdev_handle, - uint8_t *peer_addr, uint8_t *local_id) + uint8_t *peer_addr) { struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle; struct dp_peer *peer; - peer = dp_peer_find_hash_find(pdev->soc, peer_addr, 0, 0); + peer = dp_peer_find_hash_find(pdev->soc, peer_addr, 0, DP_VDEV_ALL); if (!peer) return NULL; @@ -3193,8 +3490,6 @@ void *dp_find_peer_by_addr_and_vdev(struct cdp_pdev *pdev_handle, return NULL; } - *local_id = peer->local_id; - /* ref_cnt is incremented inside dp_peer_find_hash_find(). * Decrement it here. */ @@ -3203,70 +3498,23 @@ void *dp_find_peer_by_addr_and_vdev(struct cdp_pdev *pdev_handle, return peer; } -/** - * dp_local_peer_id() - Find local peer id within peer instance - * @peer - peer instance - * - * Find local peer id within peer instance - * - * Return: local peer id - */ -uint16_t dp_local_peer_id(void *peer) -{ - return ((struct dp_peer *)peer)->local_id; -} - -/** - * dp_peer_find_by_local_id() - Find peer by local peer id - * @pdev - data path device instance - * @local_peer_id - local peer id want to find - * - * Find peer by local peer id within physical device - * - * Return: peer instance void pointer - * NULL cannot find target peer - */ -void *dp_peer_find_by_local_id(struct cdp_pdev *pdev_handle, uint8_t local_id) -{ - struct dp_peer *peer; - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; - - if (local_id >= OL_TXRX_NUM_LOCAL_PEER_IDS) { - QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_DP, - "Incorrect local id %u", local_id); - return NULL; - } - qdf_spin_lock_bh(&pdev->local_peer_ids.lock); - peer = pdev->local_peer_ids.map[local_id]; - qdf_spin_unlock_bh(&pdev->local_peer_ids.lock); - DP_TRACE(DEBUG, "peer %pK local id %d", peer, local_id); - return peer; -} - -/** - * dp_peer_state_update() - update peer local state - * @pdev - data path device instance - * @peer_addr - peer mac address - * @state - new peer local state - * - * update peer local state - * - * Return: QDF_STATUS_SUCCESS registration success - */ -QDF_STATUS dp_peer_state_update(struct cdp_pdev *pdev_handle, uint8_t *peer_mac, - enum ol_txrx_peer_state state) +QDF_STATUS dp_peer_state_update(struct cdp_soc_t *soc_hdl, uint8_t *peer_mac, + enum ol_txrx_peer_state state) { struct dp_peer *peer; - struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); - peer = dp_peer_find_hash_find(pdev->soc, peer_mac, 0, DP_VDEV_ALL); + peer = dp_peer_find_hash_find(soc, peer_mac, 0, DP_VDEV_ALL); if (!peer) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "Failed to find peer for: [%pM]", peer_mac); + "Failed to find peer for: ["QDF_MAC_ADDR_FMT"]", + QDF_MAC_ADDR_REF(peer_mac)); return QDF_STATUS_E_FAILURE; } peer->state = state; + peer->authorize = (state == OL_TXRX_PEER_STATE_AUTH) ? 1 : 0; + dp_info("peer %pK state %d", peer, peer->state); /* ref_cnt is incremented inside dp_peer_find_hash_find(). * Decrement it here. @@ -3276,47 +3524,46 @@ QDF_STATUS dp_peer_state_update(struct cdp_pdev *pdev_handle, uint8_t *peer_mac, return QDF_STATUS_SUCCESS; } -/** - * dp_get_vdevid() - Get virtual interface id which peer registered - * @peer - peer instance - * @vdev_id - virtual interface id which peer registered - * - * Get virtual interface id which peer registered - * - * Return: QDF_STATUS_SUCCESS registration success - */ -QDF_STATUS dp_get_vdevid(void *peer_handle, uint8_t *vdev_id) +QDF_STATUS dp_get_vdevid(struct cdp_soc_t *soc_hdl, uint8_t *peer_mac, + uint8_t *vdev_id) { - struct dp_peer *peer = peer_handle; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_peer *peer = + dp_peer_find_hash_find(soc, peer_mac, 0, DP_VDEV_ALL); + + if (!peer) + return QDF_STATUS_E_FAILURE; dp_info("peer %pK vdev %pK vdev id %d", peer, peer->vdev, peer->vdev->vdev_id); *vdev_id = peer->vdev->vdev_id; + /* ref_cnt is incremented inside dp_peer_find_hash_find(). + * Decrement it here. + */ + dp_peer_unref_delete(peer); + return QDF_STATUS_SUCCESS; } -struct cdp_vdev *dp_get_vdev_by_sta_id(struct cdp_pdev *pdev_handle, - uint8_t sta_id) +struct cdp_vdev * +dp_get_vdev_by_peer_addr(struct cdp_pdev *pdev_handle, + struct qdf_mac_addr peer_addr) { struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle; struct dp_peer *peer = NULL; - if (sta_id >= WLAN_MAX_STA_COUNT) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, - "Invalid sta id passed"); - return NULL; - } - if (!pdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, - "PDEV not found for sta_id [%d]", sta_id); + "PDEV not found for peer_addr: "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(peer_addr.bytes)); return NULL; } - peer = dp_peer_find_by_local_id((struct cdp_pdev *)pdev, sta_id); + peer = dp_find_peer_by_addr((struct cdp_pdev *)pdev, peer_addr.bytes); if (!peer) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, - "PEER [%d] not found", sta_id); + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH, + "PDEV not found for peer_addr: "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(peer_addr.bytes)); return NULL; } @@ -3360,20 +3607,22 @@ uint8_t *dp_peer_get_peer_mac_addr(void *peer_handle) return peer->mac_addr.raw; } -/** - * dp_get_peer_state() - Get local peer state - * @peer - peer instance - * - * Get local peer state - * - * Return: peer status - */ -int dp_get_peer_state(void *peer_handle) +int dp_get_peer_state(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_mac) { - struct dp_peer *peer = peer_handle; + enum ol_txrx_peer_state peer_state; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_peer *peer = dp_peer_find_hash_find(soc, peer_mac, 0, + vdev_id); + + if (!peer) + return QDF_STATUS_E_FAILURE; DP_TRACE(DEBUG, "peer %pK stats %d", peer, peer->state); - return peer->state; + peer_state = peer->state; + dp_peer_unref_delete(peer); + + return peer_state; } /** @@ -3457,40 +3706,60 @@ void dp_local_peer_id_free(struct dp_pdev *pdev, struct dp_peer *peer) pdev->local_peer_ids.map[i] = NULL; qdf_spin_unlock_bh(&pdev->local_peer_ids.lock); } -#endif -/** - * dp_get_peer_mac_addr_frm_id(): get mac address of the peer - * @soc_handle: DP SOC handle - * @peer_id:peer_id of the peer - * - * return: vdev_id of the vap - */ -uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle, - uint16_t peer_id, uint8_t *peer_mac) +bool dp_find_peer_exist_on_vdev(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, uint8_t *peer_addr) { - struct dp_soc *soc = (struct dp_soc *)soc_handle; - struct dp_peer *peer; - uint8_t vdev_id; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); - peer = dp_peer_find_by_id(soc, peer_id); + if (!vdev) + return false; - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "soc %pK peer_id %d", soc, peer_id); + return !!dp_find_peer_by_addr_and_vdev( + dp_pdev_to_cdp_pdev(vdev->pdev), + dp_vdev_to_cdp_vdev(vdev), + peer_addr); +} - if (!peer) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "peer not found "); - return CDP_INVALID_VDEV_ID; +bool dp_find_peer_exist_on_other_vdev(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, uint8_t *peer_addr, + uint16_t max_bssid) +{ + int i; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev; + + for (i = 0; i < max_bssid; i++) { + vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, i); + /* Need to check vdevs other than the vdev_id */ + if (vdev_id == i || !vdev) + continue; + if (dp_find_peer_by_addr_and_vdev( + dp_pdev_to_cdp_pdev(vdev->pdev), + dp_vdev_to_cdp_vdev(vdev), + peer_addr)) { + dp_err("%s: Duplicate peer "QDF_MAC_ADDR_FMT" already exist on vdev %d", + __func__, QDF_MAC_ADDR_REF(peer_addr), i); + return true; + } } - qdf_mem_copy(peer_mac, peer->mac_addr.raw, 6); - vdev_id = peer->vdev->vdev_id; + return false; +} - dp_peer_unref_del_find_by_id(peer); +bool dp_find_peer_exist(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + uint8_t *peer_addr) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (!pdev) + return false; - return vdev_id; + return !!dp_find_peer_by_addr(dp_pdev_to_cdp_pdev(pdev), peer_addr); } +#endif /** * dp_peer_rxtid_stats: Retried Rx TID (REO queue) stats from HW @@ -3500,7 +3769,8 @@ uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle, * * Return: count of tid stats cmd send succeeded */ -int dp_peer_rxtid_stats(struct dp_peer *peer, void (*dp_stats_cmd_cb), +int dp_peer_rxtid_stats(struct dp_peer *peer, + dp_rxtid_stats_cmd_cb dp_stats_cmd_cb, void *cb_ctxt) { struct dp_soc *soc = peer->vdev->pdev->soc; @@ -3554,20 +3824,32 @@ int dp_peer_rxtid_stats(struct dp_peer *peer, void (*dp_stats_cmd_cb), return stats_cmd_sent_cnt; } -void dp_set_michael_key(struct cdp_peer *peer_handle, - bool is_unicast, uint32_t *key) +QDF_STATUS +dp_set_michael_key(struct cdp_soc_t *soc, + uint8_t vdev_id, + uint8_t *peer_mac, + bool is_unicast, uint32_t *key) { - struct dp_peer *peer = (struct dp_peer *)peer_handle; + QDF_STATUS status = QDF_STATUS_SUCCESS; uint8_t sec_index = is_unicast ? 1 : 0; + struct dp_peer *peer = dp_peer_find_hash_find((struct dp_soc *)soc, + peer_mac, 0, vdev_id); - if (!peer) { + if (!peer || peer->delete_in_progress) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "peer not found "); - return; + status = QDF_STATUS_E_FAILURE; + goto fail; } qdf_mem_copy(&peer->security[sec_index].michael_key[0], key, IEEE80211_WEP_MICLEN); + +fail: + if (peer) + dp_peer_unref_delete(peer); + + return status; } bool dp_peer_find_by_id_valid(struct dp_soc *soc, uint16_t peer_id) @@ -3586,3 +3868,112 @@ bool dp_peer_find_by_id_valid(struct dp_soc *soc, uint16_t peer_id) return false; } + +void dp_peer_flush_frags(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_mac) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_peer *peer = dp_peer_find_hash_find(soc, peer_mac, 0, + vdev_id); + struct dp_rx_tid *rx_tid; + uint8_t tid; + + if (!peer) + return; + + dp_info("Flushing fragments for peer " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(peer->mac_addr.raw)); + + for (tid = 0; tid < DP_MAX_TIDS; tid++) { + rx_tid = &peer->rx_tid[tid]; + + qdf_spin_lock_bh(&rx_tid->tid_lock); + dp_rx_defrag_waitlist_remove(peer, tid); + dp_rx_reorder_flush_frag(peer, tid); + qdf_spin_unlock_bh(&rx_tid->tid_lock); + } + + dp_peer_unref_delete(peer); +} + +#ifdef DUMP_REO_QUEUE_INFO_IN_DDR +void dp_dump_rx_reo_queue_info( + struct dp_soc *soc, void *cb_ctxt, union hal_reo_status *reo_status) +{ + struct dp_rx_tid *rx_tid = (struct dp_rx_tid *)cb_ctxt; + + if (!rx_tid) + return; + + if (reo_status->fl_cache_status.header.status != + HAL_REO_CMD_SUCCESS) { + dp_err_rl("Rx tid REO HW desc flush failed(%d)", + reo_status->rx_queue_status.header.status); + return; + } + qdf_spin_lock_bh(&rx_tid->tid_lock); + hal_dump_rx_reo_queue_desc(rx_tid->hw_qdesc_vaddr_aligned); + qdf_spin_unlock_bh(&rx_tid->tid_lock); +} + +void dp_send_cache_flush_for_rx_tid( + struct dp_soc *soc, struct dp_peer *peer) +{ + int i; + struct dp_rx_tid *rx_tid; + struct hal_reo_cmd_params params; + + if (!peer) { + dp_err_rl("Peer is NULL"); + return; + } + + for (i = 0; i < DP_MAX_TIDS; i++) { + rx_tid = &peer->rx_tid[i]; + if (!rx_tid) + continue; + qdf_spin_lock_bh(&rx_tid->tid_lock); + if (rx_tid->hw_qdesc_vaddr_aligned) { + qdf_mem_zero(¶ms, sizeof(params)); + params.std.need_status = 1; + params.std.addr_lo = + rx_tid->hw_qdesc_paddr & 0xffffffff; + params.std.addr_hi = + (uint64_t)(rx_tid->hw_qdesc_paddr) >> 32; + params.u.fl_cache_params.flush_no_inval = 0; + if (QDF_STATUS_SUCCESS != + dp_reo_send_cmd( + soc, CMD_FLUSH_CACHE, + ¶ms, dp_dump_rx_reo_queue_info, + (void *)rx_tid)) { + dp_err_rl("cache flush send failed tid %d", + rx_tid->tid); + qdf_spin_unlock_bh(&rx_tid->tid_lock); + break; + } + } + qdf_spin_unlock_bh(&rx_tid->tid_lock); + } +} + +void dp_get_rx_reo_queue_info( + struct cdp_soc_t *soc_hdl, uint8_t vdev_id) +{ + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_peer *peer = NULL; + + if (!vdev) { + dp_err_rl("vdev is null for vdev_id: %u", vdev_id); + return; + } + + peer = vdev->vap_bss_peer; + + if (!peer) { + dp_err_rl("Peer is NULL"); + return; + } + dp_send_cache_flush_for_rx_tid(soc, peer); +} +#endif /* DUMP_REO_QUEUE_INFO_IN_DDR */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.h index 28e402b46f6c9b527669cc9f4a6c4d6240330ee2..4992673a76aa2c710da317ff746be7a01845362f 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -22,6 +23,10 @@ #include #include "dp_types.h" +#ifdef DUMP_REO_QUEUE_INFO_IN_DDR +#include "hal_reo.h" +#endif + #define DP_INVALID_PEER_ID 0xffff #define DP_FW_PEER_STATS_CMP_TIMEOUT_MSEC 5000 @@ -115,16 +120,16 @@ dp_clear_peer_internal(struct dp_soc *soc, struct dp_peer *peer) } void dp_print_ast_stats(struct dp_soc *soc); -void dp_rx_peer_map_handler(void *soc_handle, uint16_t peer_id, +void dp_rx_peer_map_handler(struct dp_soc *soc, uint16_t peer_id, uint16_t hw_peer_id, uint8_t vdev_id, uint8_t *peer_mac_addr, uint16_t ast_hash, uint8_t is_wds); -void dp_rx_peer_unmap_handler(void *soc_handle, uint16_t peer_id, +void dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id, uint8_t vdev_id, uint8_t *peer_mac_addr, uint8_t is_wds); -void dp_rx_sec_ind_handler(void *soc_handle, uint16_t peer_id, - enum cdp_sec_type sec_type, int is_unicast, - u_int32_t *michael_key, u_int32_t *rx_pn); +void dp_rx_sec_ind_handler(struct dp_soc *soc, uint16_t peer_id, + enum cdp_sec_type sec_type, int is_unicast, + u_int32_t *michael_key, u_int32_t *rx_pn); QDF_STATUS dp_rx_delba_ind_handler(void *soc_handle, uint16_t peer_id, uint8_t tid, uint16_t win_sz); @@ -169,14 +174,20 @@ void dp_peer_ast_set_type(struct dp_soc *soc, void dp_peer_ast_send_wds_del(struct dp_soc *soc, struct dp_ast_entry *ast_entry); -void dp_peer_free_hmwds_cb(void *ctrl_psoc, - void *dp_soc, +void dp_peer_free_hmwds_cb(struct cdp_ctrl_objmgr_psoc *ctrl_psoc, + struct cdp_soc *dp_soc, void *cookie, enum cdp_ast_free_status status); void dp_peer_ast_hash_remove(struct dp_soc *soc, struct dp_ast_entry *ase); +void dp_peer_free_ast_entry(struct dp_soc *soc, + struct dp_ast_entry *ast_entry); + +void dp_peer_unlink_ast_entry(struct dp_soc *soc, + struct dp_ast_entry *ast_entry); + /* * dp_peer_find_by_id_exist - check if peer exists for given id * @soc: core DP soc context @@ -204,6 +215,123 @@ void dp_peer_update_inactive_time(struct dp_pdev *pdev, uint32_t tag_type, uint32_t *tag_buf); +#ifndef QCA_MULTIPASS_SUPPORT +/** + * dp_peer_set_vlan_id: set vlan_id for this peer + * @cdp_soc: soc handle + * @vdev_id: id of vdev object + * @peer_mac: mac address + * @vlan_id: vlan id for peer + * + * return: void + */ +static inline +void dp_peer_set_vlan_id(struct cdp_soc_t *cdp_soc, + uint8_t vdev_id, uint8_t *peer_mac, + uint16_t vlan_id) +{ +} + +/** + * dp_set_vlan_groupkey: set vlan map for vdev + * @soc: pointer to soc + * @vdev_id: id of vdev handle + * @vlan_id: vlan_id + * @group_key: group key for vlan + * + * return: set success/failure + */ +static inline +QDF_STATUS dp_set_vlan_groupkey(struct cdp_soc_t *soc, uint8_t vdev_id, + uint16_t vlan_id, uint16_t group_key) +{ + return QDF_STATUS_SUCCESS; +} + +/** + * dp_peer_multipass_list_init: initialize multipass peer list + * @vdev: pointer to vdev + * + * return: void + */ +static inline +void dp_peer_multipass_list_init(struct dp_vdev *vdev) +{ +} + +/** + * dp_peer_multipass_list_remove: remove peer from special peer list + * @peer: peer handle + * + * return: void + */ +static inline +void dp_peer_multipass_list_remove(struct dp_peer *peer) +{ +} +#else +void dp_peer_set_vlan_id(struct cdp_soc_t *cdp_soc, + uint8_t vdev_id, uint8_t *peer_mac, + uint16_t vlan_id); +QDF_STATUS dp_set_vlan_groupkey(struct cdp_soc_t *soc, uint8_t vdev_id, + uint16_t vlan_id, uint16_t group_key); +void dp_peer_multipass_list_init(struct dp_vdev *vdev); +void dp_peer_multipass_list_remove(struct dp_peer *peer); +#endif + + +#ifndef QCA_PEER_MULTIQ_SUPPORT +/** + * dp_peer_reset_flowq_map() - reset peer flowq map table + * @peer - dp peer handle + * + * Return: none + */ +static inline +void dp_peer_reset_flowq_map(struct dp_peer *peer) +{ +} + +/** + * dp_peer_ast_index_flow_queue_map_create() - create ast index flow queue map + * @soc - genereic soc handle + * @is_wds - flag to indicate if peer is wds + * @peer_id - peer_id from htt peer map message + * @peer_mac_addr - mac address of the peer + * @ast_info - ast flow override information from peer map + * + * Return: none + */ +static inline +void dp_peer_ast_index_flow_queue_map_create(void *soc_hdl, + bool is_wds, uint16_t peer_id, uint8_t *peer_mac_addr, + struct dp_ast_flow_override_info *ast_info) +{ +} +#else +void dp_peer_reset_flowq_map(struct dp_peer *peer); +void dp_peer_ast_index_flow_queue_map_create(void *soc_hdl, + bool is_wds, uint16_t peer_id, uint8_t *peer_mac_addr, + struct dp_ast_flow_override_info *ast_info); +#endif + +/** + * dp_peer_update_pkt_capture_params: Set Rx & Tx Capture flags for a peer + * @soc: DP SOC handle + * @pdev_id: id of DP pdev handle + * @is_rx_pkt_cap_enable: enable/disable Rx packet capture in monitor mode + * @is_tx_pkt_cap_enable: enable/disable Tx packet capture in monitor mode + * @peer_mac: MAC address for which the above need to be enabled/disabled + * + * Return: Success if Rx & Tx capture is enabled for peer, false otherwise + */ +QDF_STATUS +dp_peer_update_pkt_capture_params(ol_txrx_soc_handle soc, + uint8_t pdev_id, + bool is_rx_pkt_cap_enable, + bool is_tx_pkt_cap_enable, + uint8_t *peer_mac); + /* * dp_rx_tid_delete_cb() - Callback to flush reo descriptor HW cache * after deleting the entries (ie., setting valid=0) @@ -215,4 +343,55 @@ dp_peer_update_inactive_time(struct dp_pdev *pdev, uint32_t tag_type, void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt, union hal_reo_status *reo_status); + +#ifdef DUMP_REO_QUEUE_INFO_IN_DDR +/** + * dp_send_cache_flush_for_rx_tid() - Send cache flush cmd to REO per tid + * @soc : dp_soc handle + * @peer: peer + * + * This function is used to send cache flush cmd to reo and + * to register the callback to handle the dumping of the reo + * queue stas from DDR + * + * Return: none + */ +void dp_send_cache_flush_for_rx_tid( + struct dp_soc *soc, struct dp_peer *peer); + +/** + * dp_get_rx_reo_queue_info() - Handler to get rx tid info + * @soc : cdp_soc_t handle + * @vdev_id: vdev id + * + * Handler to get rx tid info from DDR after h/w cache is + * invalidated first using the cache flush cmd. + * + * Return: none + */ +void dp_get_rx_reo_queue_info( + struct cdp_soc_t *soc_hdl, uint8_t vdev_id); + +/** + * dp_dump_rx_reo_queue_info() - Callback function to dump reo queue stats + * @soc : dp_soc handle + * @cb_ctxt - callback context + * @reo_status: vdev id + * + * This is the callback function registered after sending the reo cmd + * to flush the h/w cache and invalidate it. In the callback the reo + * queue desc info is dumped from DDR. + * + * Return: none + */ +void dp_dump_rx_reo_queue_info( + struct dp_soc *soc, void *cb_ctxt, union hal_reo_status *reo_status); + +#else /* DUMP_REO_QUEUE_INFO_IN_DDR */ + +static inline void dp_get_rx_reo_queue_info( + struct cdp_soc_t *soc_hdl, uint8_t vdev_id) +{ +} +#endif /* DUMP_REO_QUEUE_INFO_IN_DDR */ #endif /* _DP_PEER_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_reo.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_reo.c index 0b490131f6cb0de059cb0421ba716661439a4173..352c8fd3db4d5483a995a9bc21209908fbbd1c76 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_reo.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_reo.c @@ -61,8 +61,20 @@ QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc, enum hal_reo_cmd_type type, struct hal_reo_cmd_params *params, void (*callback_fn), void *data) { - struct dp_reo_cmd_info *reo_cmd; + struct dp_reo_cmd_info *reo_cmd = NULL; int num; + QDF_STATUS ret; + + if (callback_fn) { + reo_cmd = qdf_mem_malloc(sizeof(*reo_cmd)); + if (!reo_cmd) { + dp_err_log("alloc failed for REO cmd:%d!!", + type); + ret = QDF_STATUS_E_NOMEM; + goto fail; + } + qdf_spin_lock_bh(&soc->rx.reo_cmd_lock); + } switch (type) { case CMD_GET_QUEUE_STATS: @@ -91,34 +103,36 @@ QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc, enum hal_reo_cmd_type type, break; default: dp_err_log("Invalid REO command type: %d", type); - return QDF_STATUS_E_INVAL; + ret = QDF_STATUS_E_INVAL; + goto fail_unlock; }; dp_reo_cmd_srng_event_record(soc, type, num); if (num < 0) { - return QDF_STATUS_E_FAILURE; + ret = QDF_STATUS_E_FAILURE; + goto fail_unlock; } if (callback_fn) { - reo_cmd = qdf_mem_malloc(sizeof(*reo_cmd)); - if (!reo_cmd) { - dp_err_log("alloc failed for REO cmd:%d!!", - type); - return QDF_STATUS_E_NOMEM; - } - reo_cmd->cmd = num; reo_cmd->cmd_type = type; reo_cmd->handler = callback_fn; reo_cmd->data = data; - qdf_spin_lock_bh(&soc->rx.reo_cmd_lock); TAILQ_INSERT_TAIL(&soc->rx.reo_cmd_list, reo_cmd, reo_cmd_list_elem); - qdf_spin_unlock_bh(&soc->rx.reo_cmd_lock); + reo_cmd = NULL; } - return QDF_STATUS_SUCCESS; + ret = QDF_STATUS_SUCCESS; + +fail_unlock: + if (callback_fn) + qdf_spin_unlock_bh(&soc->rx.reo_cmd_lock); +fail: + if (reo_cmd) + qdf_mem_free(reo_cmd); + return ret; } uint32_t dp_reo_status_ring_handler(struct dp_intr *int_ctx, struct dp_soc *soc) @@ -153,7 +167,7 @@ uint32_t dp_reo_status_ring_handler(struct dp_intr *int_ctx, struct dp_soc *soc) num = reo_status.fl_queue_status.header.cmd_num; break; case HAL_REO_FLUSH_CACHE_STATUS_TLV: - hal_reo_flush_cache_status(reo_desc, soc->hal_soc, + hal_reo_flush_cache_status(reo_desc, &reo_status.fl_cache_status, soc->hal_soc); num = reo_status.fl_cache_status.header.cmd_num; diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.c index 4a9420ecb57ea3b85b65f05ad44bc273dab56fb2..b4107090a023c528abfc52e113c8c694e5a2fbe2 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -58,25 +58,16 @@ bool dp_rx_check_ndi_mdns_fwding(struct dp_peer *ta_peer, qdf_nbuf_t nbuf) return true; } #endif - -#ifdef CONFIG_MCL -static inline bool dp_rx_check_ap_bridge(struct dp_vdev *vdev) -{ - if (vdev->opmode != wlan_op_mode_sta) - return true; - else - return false; -} -#else static inline bool dp_rx_check_ap_bridge(struct dp_vdev *vdev) { return vdev->ap_bridge_enabled; } -#endif #ifdef DUP_RX_DESC_WAR -void dp_rx_dump_info_and_assert(struct dp_soc *soc, void *hal_ring, - void *ring_desc, struct dp_rx_desc *rx_desc) +void dp_rx_dump_info_and_assert(struct dp_soc *soc, + hal_ring_handle_t hal_ring, + hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc) { void *hal_soc = soc->hal_soc; @@ -84,18 +75,65 @@ void dp_rx_dump_info_and_assert(struct dp_soc *soc, void *hal_ring, dp_rx_desc_dump(rx_desc); } #else -void dp_rx_dump_info_and_assert(struct dp_soc *soc, void *hal_ring, - void *ring_desc, struct dp_rx_desc *rx_desc) +void dp_rx_dump_info_and_assert(struct dp_soc *soc, + hal_ring_handle_t hal_ring_hdl, + hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc) { - void *hal_soc = soc->hal_soc; + hal_soc_handle_t hal_soc = soc->hal_soc; dp_rx_desc_dump(rx_desc); - hal_srng_dump_ring_desc(hal_soc, hal_ring, ring_desc); - hal_srng_dump_ring(hal_soc, hal_ring); + hal_srng_dump_ring_desc(hal_soc, hal_ring_hdl, ring_desc); + hal_srng_dump_ring(hal_soc, hal_ring_hdl); qdf_assert_always(0); } #endif +#ifdef RX_DESC_SANITY_WAR +static inline +QDF_STATUS dp_rx_desc_sanity(struct dp_soc *soc, hal_soc_handle_t hal_soc, + hal_ring_handle_t hal_ring_hdl, + hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc) +{ + uint8_t return_buffer_manager; + + if (qdf_unlikely(!rx_desc)) { + /* + * This is an unlikely case where the cookie obtained + * from the ring_desc is invalid and hence we are not + * able to find the corresponding rx_desc + */ + goto fail; + } + + return_buffer_manager = hal_rx_ret_buf_manager_get(ring_desc); + if (qdf_unlikely(!(return_buffer_manager == HAL_RX_BUF_RBM_SW1_BM || + return_buffer_manager == HAL_RX_BUF_RBM_SW3_BM))) { + goto fail; + } + + return QDF_STATUS_SUCCESS; + +fail: + DP_STATS_INC(soc, rx.err.invalid_cookie, 1); + dp_err("Ring Desc:"); + hal_srng_dump_ring_desc(hal_soc, hal_ring_hdl, + ring_desc); + return QDF_STATUS_E_NULL_VALUE; + +} +#else +static inline +QDF_STATUS dp_rx_desc_sanity(struct dp_soc *soc, hal_soc_handle_t hal_soc, + hal_ring_handle_t hal_ring_hdl, + hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /* * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs * called during dp rx initialization @@ -123,7 +161,7 @@ QDF_STATUS __dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, { uint32_t num_alloc_desc; uint16_t num_desc_to_free = 0; - struct dp_pdev *dp_pdev = dp_get_pdev_for_mac_id(dp_soc, mac_id); + struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(dp_soc, mac_id); uint32_t num_entries_avail; uint32_t count; int sync_hw_ptr = 1; @@ -132,6 +170,8 @@ QDF_STATUS __dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, void *rxdma_ring_entry; union dp_rx_desc_list_elem_t *next; QDF_STATUS ret; + uint16_t buf_size = rx_desc_pool->buf_size; + uint8_t buf_alignment = rx_desc_pool->buf_alignment; void *rxdma_srng; @@ -199,14 +239,14 @@ QDF_STATUS __dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, while (count < num_req_buffers) { rx_netbuf = qdf_nbuf_alloc(dp_soc->osdev, - RX_BUFFER_SIZE, + buf_size, RX_BUFFER_RESERVATION, - RX_BUFFER_ALIGNMENT, + buf_alignment, FALSE); if (qdf_unlikely(!rx_netbuf)) { DP_STATS_INC(dp_pdev, replenish.nbuf_alloc_fail, 1); - continue; + break; } ret = qdf_nbuf_map_single(dp_soc->osdev, rx_netbuf, @@ -226,7 +266,7 @@ QDF_STATUS __dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, * allocating new nbuf. We can try for 100 times. * this is a temp WAR till we fix it properly. */ - ret = check_x86_paddr(dp_soc, &rx_netbuf, &paddr, dp_pdev); + ret = check_x86_paddr(dp_soc, &rx_netbuf, &paddr, rx_desc_pool); if (ret == QDF_STATUS_E_FAILURE) { DP_STATS_INC(dp_pdev, replenish.x86_fail, 1); break; @@ -246,6 +286,7 @@ QDF_STATUS __dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, qdf_assert_always((*desc_list)->rx_desc.in_use == 0); (*desc_list)->rx_desc.in_use = 1; + (*desc_list)->rx_desc.in_err_state = 0; dp_rx_desc_update_dbg_info(&(*desc_list)->rx_desc, func_name, RX_DESC_REPLENISHED); dp_verbose_debug("rx_netbuf=%pK, buf=%pK, paddr=0x%llx, cookie=%d", @@ -264,10 +305,12 @@ QDF_STATUS __dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, hal_srng_access_end(dp_soc->hal_soc, rxdma_srng); dp_verbose_debug("replenished buffers %d, rx desc added back to free list %u", - num_req_buffers, num_desc_to_free); + count, num_desc_to_free); - DP_STATS_INC_PKT(dp_pdev, replenish.pkts, num_req_buffers, - (RX_BUFFER_SIZE * num_req_buffers)); + /* No need to count the number of bytes received during replenish. + * Therefore set replenish.pkts.bytes as 0. + */ + DP_STATS_INC_PKT(dp_pdev, replenish.pkts, count, 0); free_descs: DP_STATS_INC(dp_pdev, buf_freelist, num_desc_to_free); @@ -323,7 +366,7 @@ dp_rx_deliver_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf_list, } vdev->osif_rsim_rx_decap(vdev->osif_vdev, &deliver_list_head, - &deliver_list_tail, (struct cdp_peer*) peer); + &deliver_list_tail, peer->mac_addr.raw); vdev->osif_rx(vdev->osif_vdev, deliver_list_head); } @@ -345,14 +388,14 @@ dp_get_vdev_from_peer(struct dp_soc *soc, if (unlikely(!peer)) { if (peer_id != HTT_INVALID_PEER) { - vdev_id = DP_PEER_METADATA_ID_GET( + vdev_id = DP_PEER_METADATA_VDEV_ID_GET( mpdu_desc_info.peer_meta_data); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, FL("PeerID %d not found use vdevID %d"), peer_id, vdev_id); vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, - vdev_id); + vdev_id); } else { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, @@ -407,9 +450,9 @@ static bool dp_rx_intrabss_fwd(struct dp_soc *soc, struct dp_peer *ta_peer, uint8_t *rx_tlv_hdr, - qdf_nbuf_t nbuf) + qdf_nbuf_t nbuf, + struct hal_rx_msdu_metadata msdu_metadata) { - uint16_t da_idx; uint16_t len; uint8_t is_frag; struct dp_peer *da_peer; @@ -426,9 +469,8 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, */ if ((qdf_nbuf_is_da_valid(nbuf) && !qdf_nbuf_is_da_mcbc(nbuf))) { - da_idx = hal_rx_msdu_end_da_idx_get(soc->hal_soc, rx_tlv_hdr); - ast_entry = soc->ast_table[da_idx]; + ast_entry = soc->ast_table[msdu_metadata.da_idx]; if (!ast_entry) return false; @@ -476,7 +518,8 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, } } - if (!dp_tx_send(ta_peer->vdev, nbuf)) { + if (!dp_tx_send((struct cdp_soc_t *)soc, + ta_peer->vdev->vdev_id, nbuf)) { DP_STATS_INC_PKT(ta_peer, rx.intra_bss.pkts, 1, len); return true; @@ -508,7 +551,10 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); memset(nbuf_copy->cb, 0x0, sizeof(nbuf_copy->cb)); - if (dp_tx_send(ta_peer->vdev, nbuf_copy)) { + /* Set cb->ftype to intrabss FWD */ + qdf_nbuf_set_tx_ftype(nbuf_copy, CB_FTYPE_INTRABSS_FWD); + if (dp_tx_send((struct cdp_soc_t *)soc, + ta_peer->vdev->vdev_id, nbuf_copy)) { DP_STATS_INC_PKT(ta_peer, rx.intra_bss.fail, 1, len); tid_stats->fail_cnt[INTRABSS_DROP]++; qdf_nbuf_free(nbuf_copy); @@ -617,23 +663,29 @@ QDF_STATUS dp_rx_filter_mesh_packets(struct dp_vdev *vdev, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr) { union dp_align_mac_addr mac_addr; + struct dp_soc *soc = vdev->pdev->soc; if (qdf_unlikely(vdev->mesh_rx_filter)) { if (vdev->mesh_rx_filter & MESH_FILTER_OUT_FROMDS) - if (hal_rx_mpdu_get_fr_ds(rx_tlv_hdr)) + if (hal_rx_mpdu_get_fr_ds(soc->hal_soc, + rx_tlv_hdr)) return QDF_STATUS_SUCCESS; if (vdev->mesh_rx_filter & MESH_FILTER_OUT_TODS) - if (hal_rx_mpdu_get_to_ds(rx_tlv_hdr)) + if (hal_rx_mpdu_get_to_ds(soc->hal_soc, + rx_tlv_hdr)) return QDF_STATUS_SUCCESS; if (vdev->mesh_rx_filter & MESH_FILTER_OUT_NODS) - if (!hal_rx_mpdu_get_fr_ds(rx_tlv_hdr) - && !hal_rx_mpdu_get_to_ds(rx_tlv_hdr)) + if (!hal_rx_mpdu_get_fr_ds(soc->hal_soc, + rx_tlv_hdr) && + !hal_rx_mpdu_get_to_ds(soc->hal_soc, + rx_tlv_hdr)) return QDF_STATUS_SUCCESS; if (vdev->mesh_rx_filter & MESH_FILTER_OUT_RA) { - if (hal_rx_mpdu_get_addr1(rx_tlv_hdr, + if (hal_rx_mpdu_get_addr1(soc->hal_soc, + rx_tlv_hdr, &mac_addr.raw[0])) return QDF_STATUS_E_FAILURE; @@ -644,8 +696,9 @@ QDF_STATUS dp_rx_filter_mesh_packets(struct dp_vdev *vdev, qdf_nbuf_t nbuf, } if (vdev->mesh_rx_filter & MESH_FILTER_OUT_TA) { - if (hal_rx_mpdu_get_addr2(rx_tlv_hdr, - &mac_addr.raw[0])) + if (hal_rx_mpdu_get_addr2(soc->hal_soc, + rx_tlv_hdr, + &mac_addr.raw[0])) return QDF_STATUS_E_FAILURE; if (!qdf_mem_cmp(&mac_addr.raw[0], @@ -740,7 +793,7 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu, rx_pkt_hdr = hal_rx_pkt_hdr_get(rx_tlv_hdr); - if (!HAL_IS_DECAP_FORMAT_RAW(rx_tlv_hdr)) { + if (!HAL_IS_DECAP_FORMAT_RAW(soc->hal_soc, rx_tlv_hdr)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "Drop decapped frames"); goto free; @@ -760,11 +813,11 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu, goto free; } - pdev = dp_get_pdev_for_mac_id(soc, mac_id); + pdev = dp_get_pdev_for_lmac_id(soc, mac_id); - if (!pdev) { + if (!pdev || qdf_unlikely(pdev->is_pdev_down)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "PDEV not found"); + "PDEV %s", !pdev ? "not found" : "down"); goto free; } @@ -783,7 +836,6 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu, } } - TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) { if (qdf_mem_cmp(wh->i_addr1, vdev->mac_addr.raw, @@ -804,8 +856,9 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu, msg.nbuf = mpdu; msg.vdev_id = vdev->vdev_id; if (pdev->soc->cdp_soc.ol_ops->rx_invalid_peer) - pdev->soc->cdp_soc.ol_ops->rx_invalid_peer(pdev->ctrl_pdev, - &msg); + pdev->soc->cdp_soc.ol_ops->rx_invalid_peer( + (struct cdp_ctrl_objmgr_psoc *)soc->ctrl_psoc, + pdev->pdev_id, &msg); free: /* Drop and free packet */ @@ -862,7 +915,7 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu, goto free; } - pdev = dp_get_pdev_for_mac_id(soc, mac_id); + pdev = dp_get_pdev_for_lmac_id(soc, mac_id); if (!pdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -891,7 +944,7 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu, soc->cdp_soc.ol_ops->rx_invalid_peer(vdev->vdev_id, wh); free: /* reset the head and tail pointers */ - pdev = dp_get_pdev_for_mac_id(soc, mac_id); + pdev = dp_get_pdev_for_lmac_id(soc, mac_id); if (pdev) { pdev->invalid_peer_head_msdu = NULL; pdev->invalid_peer_tail_msdu = NULL; @@ -905,6 +958,13 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu, curr_nbuf = next_nbuf; } + /* Reset the head and tail pointers */ + pdev = dp_get_pdev_for_mac_id(soc, mac_id); + if (pdev) { + pdev->invalid_peer_head_msdu = NULL; + pdev->invalid_peer_tail_msdu = NULL; + } + return 0; } @@ -920,16 +980,18 @@ void dp_rx_process_invalid_peer_wrapper(struct dp_soc *soc, #ifdef RECEIVE_OFFLOAD /** * dp_rx_print_offload_info() - Print offload info from RX TLV + * @soc: dp soc handle * @rx_tlv: RX TLV for which offload information is to be printed * * Return: None */ -static void dp_rx_print_offload_info(uint8_t *rx_tlv) +static void dp_rx_print_offload_info(struct dp_soc *soc, uint8_t *rx_tlv) { dp_verbose_debug("----------------------RX DESC LRO/GRO----------------------"); dp_verbose_debug("lro_eligible 0x%x", HAL_RX_TLV_GET_LRO_ELIGIBLE(rx_tlv)); dp_verbose_debug("pure_ack 0x%x", HAL_RX_TLV_GET_TCP_PURE_ACK(rx_tlv)); - dp_verbose_debug("chksum 0x%x", HAL_RX_TLV_GET_TCP_CHKSUM(rx_tlv)); + dp_verbose_debug("chksum 0x%x", hal_rx_tlv_get_tcp_chksum(soc->hal_soc, + rx_tlv)); dp_verbose_debug("TCP seq num 0x%x", HAL_RX_TLV_GET_TCP_SEQ(rx_tlv)); dp_verbose_debug("TCP ack num 0x%x", HAL_RX_TLV_GET_TCP_ACK(rx_tlv)); dp_verbose_debug("TCP window 0x%x", HAL_RX_TLV_GET_TCP_WIN(rx_tlv)); @@ -966,7 +1028,8 @@ void dp_rx_fill_gro_info(struct dp_soc *soc, uint8_t *rx_tlv, QDF_NBUF_CB_RX_TCP_PURE_ACK(msdu) = HAL_RX_TLV_GET_TCP_PURE_ACK(rx_tlv); QDF_NBUF_CB_RX_TCP_CHKSUM(msdu) = - HAL_RX_TLV_GET_TCP_CHKSUM(rx_tlv); + hal_rx_tlv_get_tcp_chksum(soc->hal_soc, + rx_tlv); QDF_NBUF_CB_RX_TCP_SEQ_NUM(msdu) = HAL_RX_TLV_GET_TCP_SEQ(rx_tlv); QDF_NBUF_CB_RX_TCP_ACK_NUM(msdu) = @@ -982,7 +1045,7 @@ void dp_rx_fill_gro_info(struct dp_soc *soc, uint8_t *rx_tlv, QDF_NBUF_CB_RX_FLOW_ID(msdu) = HAL_RX_TLV_GET_FLOW_ID_TOEPLITZ(rx_tlv); - dp_rx_print_offload_info(rx_tlv); + dp_rx_print_offload_info(soc, rx_tlv); } #else static void dp_rx_fill_gro_info(struct dp_soc *soc, uint8_t *rx_tlv, @@ -996,29 +1059,67 @@ static void dp_rx_fill_gro_info(struct dp_soc *soc, uint8_t *rx_tlv, * * @nbuf: pointer to msdu. * @mpdu_len: mpdu length + * @l3_pad_len: L3 padding length by HW * * Return: returns true if nbuf is last msdu of mpdu else retuns false. */ -static inline bool dp_rx_adjust_nbuf_len(qdf_nbuf_t nbuf, uint16_t *mpdu_len) +static inline bool dp_rx_adjust_nbuf_len(qdf_nbuf_t nbuf, + uint16_t *mpdu_len, + uint32_t l3_pad_len) { bool last_nbuf; + uint32_t pkt_hdr_size; + + pkt_hdr_size = RX_PKT_TLVS_LEN + l3_pad_len; - if (*mpdu_len > (RX_BUFFER_SIZE - RX_PKT_TLVS_LEN)) { - qdf_nbuf_set_pktlen(nbuf, RX_BUFFER_SIZE); + if ((*mpdu_len + pkt_hdr_size) > RX_DATA_BUFFER_SIZE) { + qdf_nbuf_set_pktlen(nbuf, RX_DATA_BUFFER_SIZE); last_nbuf = false; + *mpdu_len -= (RX_DATA_BUFFER_SIZE - pkt_hdr_size); } else { - qdf_nbuf_set_pktlen(nbuf, (*mpdu_len + RX_PKT_TLVS_LEN)); + qdf_nbuf_set_pktlen(nbuf, (*mpdu_len + pkt_hdr_size)); last_nbuf = true; + *mpdu_len = 0; } - *mpdu_len -= (RX_BUFFER_SIZE - RX_PKT_TLVS_LEN); - return last_nbuf; } +/** + * dp_get_l3_hdr_pad_len() - get L3 header padding length. + * + * @soc: DP soc handle + * @nbuf: pointer to msdu. + * + * Return: returns padding length in bytes. + */ +static inline uint32_t dp_get_l3_hdr_pad_len(struct dp_soc *soc, + qdf_nbuf_t nbuf) +{ + uint32_t l3_hdr_pad = 0; + uint8_t *rx_tlv_hdr; + struct hal_rx_msdu_metadata msdu_metadata; + + while (nbuf) { + if (!qdf_nbuf_is_rx_chfrag_cont(nbuf)) { + /* scattered msdu end with continuation is 0 */ + rx_tlv_hdr = qdf_nbuf_data(nbuf); + hal_rx_msdu_metadata_get(soc->hal_soc, + rx_tlv_hdr, + &msdu_metadata); + l3_hdr_pad = msdu_metadata.l3_hdr_pad; + break; + } + nbuf = nbuf->next; + } + + return l3_hdr_pad; +} + /** * dp_rx_sg_create() - create a frag_list for MSDUs which are spread across * multiple nbufs. + * @soc: DP SOC handle * @nbuf: pointer to the first msdu of an amsdu. * * This function implements the creation of RX frag_list for cases @@ -1026,12 +1127,13 @@ static inline bool dp_rx_adjust_nbuf_len(qdf_nbuf_t nbuf, uint16_t *mpdu_len) * * Return: returns the head nbuf which contains complete frag_list. */ -qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf) +qdf_nbuf_t dp_rx_sg_create(struct dp_soc *soc, qdf_nbuf_t nbuf) { - qdf_nbuf_t parent, next, frag_list; + qdf_nbuf_t parent, frag_list, next = NULL; uint16_t frag_list_len = 0; uint16_t mpdu_len; bool last_nbuf; + uint32_t l3_hdr_pad_offset = 0; /* * Use msdu len got from REO entry descriptor instead since @@ -1039,6 +1141,7 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf) * from REO descriptor is right for non-raw RX scatter msdu. */ mpdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); + /* * this is a case where the complete msdu fits in one single nbuf. * in this case HW sets both start and end bit and we only need to @@ -1051,6 +1154,8 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf) return nbuf; } + l3_hdr_pad_offset = dp_get_l3_hdr_pad_len(soc, nbuf); + /* * This is a case where we have multiple msdus (A-MSDU) spread across * multiple nbufs. here we create a fraglist out of these nbufs. @@ -1070,7 +1175,24 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf) * nbufs will form the frag_list of the parent nbuf. */ qdf_nbuf_set_rx_chfrag_start(parent, 1); - last_nbuf = dp_rx_adjust_nbuf_len(parent, &mpdu_len); + /* + * L3 header padding is only needed for the 1st buffer + * in a scattered msdu + */ + last_nbuf = dp_rx_adjust_nbuf_len(parent, &mpdu_len, + l3_hdr_pad_offset); + + /* + * HW issue: MSDU cont bit is set but reported MPDU length can fit + * in to single buffer + * + * Increment error stats and avoid SG list creation + */ + if (last_nbuf) { + qdf_nbuf_pull_head(parent, + RX_PKT_TLVS_LEN + l3_hdr_pad_offset); + return parent; + } /* * this is where we set the length of the fragments which are @@ -1078,7 +1200,7 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf) * till we hit the last_nbuf of the list. */ do { - last_nbuf = dp_rx_adjust_nbuf_len(nbuf, &mpdu_len); + last_nbuf = dp_rx_adjust_nbuf_len(nbuf, &mpdu_len, 0); qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN); frag_list_len += qdf_nbuf_len(nbuf); @@ -1095,7 +1217,8 @@ qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf) qdf_nbuf_append_ext_list(parent, frag_list, frag_list_len); parent->next = next; - qdf_nbuf_pull_head(parent, RX_PKT_TLVS_LEN); + qdf_nbuf_pull_head(parent, + RX_PKT_TLVS_LEN + l3_hdr_pad_offset); return parent; } @@ -1312,7 +1435,12 @@ static void dp_rx_check_delivery_to_stack(struct dp_soc *soc, struct dp_peer *peer, qdf_nbuf_t nbuf_head) { - vdev->osif_rx(vdev->osif_vdev, nbuf_head); + /* Function pointer initialized only when FISA is enabled */ + if (vdev->osif_fisa_rx) + /* on failure send it via regular path */ + vdev->osif_fisa_rx(soc, vdev, nbuf_head); + else + vdev->osif_rx(vdev->osif_vdev, nbuf_head); } #else @@ -1338,7 +1466,11 @@ static void dp_rx_check_delivery_to_stack(struct dp_soc *soc, int num_nbuf = 0; QDF_STATUS ret_val = QDF_STATUS_E_FAILURE; - if (vdev->osif_rx) + /* Function pointer initialized only when FISA is enabled */ + if (vdev->osif_fisa_rx) + /* on failure send it via regular path */ + ret_val = vdev->osif_fisa_rx(soc, vdev, nbuf_head); + else if (vdev->osif_rx) ret_val = vdev->osif_rx(vdev->osif_vdev, nbuf_head); if (!QDF_IS_STATUS_SUCCESS(ret_val)) { @@ -1387,8 +1519,9 @@ void dp_rx_deliver_to_stack(struct dp_soc *soc, if (qdf_unlikely(vdev->rx_decap_type == htt_cmn_pkt_type_raw) || (vdev->rx_decap_type == htt_cmn_pkt_type_native_wifi)) { vdev->osif_rsim_rx_decap(vdev->osif_vdev, &nbuf_head, - &nbuf_tail, (struct cdp_peer *) peer); + &nbuf_tail, peer->mac_addr.raw); } + dp_rx_check_delivery_to_stack(soc, vdev, peer, nbuf_head); } @@ -1419,6 +1552,30 @@ static inline void dp_rx_cksum_offload(struct dp_pdev *pdev, } } +#ifdef VDEV_PEER_PROTOCOL_COUNT +#define dp_rx_msdu_stats_update_prot_cnts(vdev_hdl, nbuf, peer) \ +{ \ + qdf_nbuf_t nbuf_local; \ + struct dp_peer *peer_local; \ + struct dp_vdev *vdev_local = vdev_hdl; \ + do { \ + if (qdf_likely(!((vdev_local)->peer_protocol_count_track))) \ + break; \ + nbuf_local = nbuf; \ + peer_local = peer; \ + if (qdf_unlikely(qdf_nbuf_is_frag((nbuf_local)))) \ + break; \ + else if (qdf_unlikely(qdf_nbuf_is_raw_frame((nbuf_local)))) \ + break; \ + dp_vdev_peer_stats_update_protocol_cnt((vdev_local), \ + (nbuf_local), \ + (peer_local), 0, 1); \ + } while (0); \ +} +#else +#define dp_rx_msdu_stats_update_prot_cnts(vdev_hdl, nbuf, peer) +#endif + /** * dp_rx_msdu_stats_update() - update per msdu stats. * @soc: core txrx main context @@ -1444,6 +1601,7 @@ static void dp_rx_msdu_stats_update(struct dp_soc *soc, qdf_ether_header_t *eh; uint16_t msdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); + dp_rx_msdu_stats_update_prot_cnts(vdev, nbuf, peer); is_not_amsdu = qdf_nbuf_is_rx_chfrag_start(nbuf) & qdf_nbuf_is_rx_chfrag_end(nbuf); @@ -1544,16 +1702,15 @@ static void dp_rx_msdu_stats_update(struct dp_soc *soc, } static inline bool is_sa_da_idx_valid(struct dp_soc *soc, - void *rx_tlv_hdr, - qdf_nbuf_t nbuf) + uint8_t *rx_tlv_hdr, + qdf_nbuf_t nbuf, + struct hal_rx_msdu_metadata msdu_info) { if ((qdf_nbuf_is_sa_valid(nbuf) && - (hal_rx_msdu_end_sa_idx_get(rx_tlv_hdr) > - wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx))) || + (msdu_info.sa_idx > wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx))) || (!qdf_nbuf_is_da_mcbc(nbuf) && qdf_nbuf_is_da_valid(nbuf) && - (hal_rx_msdu_end_da_idx_get(soc->hal_soc, rx_tlv_hdr) > - wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)))) + (msdu_info.da_idx > wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)))) return false; return true; @@ -1578,20 +1735,25 @@ int dp_wds_rx_policy_check(uint8_t *rx_tlv_hdr, * * Return: NONE */ -static inline void dp_rx_desc_nbuf_sanity_check(void *ring_desc, - struct dp_rx_desc *rx_desc) +static inline +QDF_STATUS dp_rx_desc_nbuf_sanity_check(hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc) { struct hal_buf_info hbi; hal_rx_reo_buf_paddr_get(ring_desc, &hbi); /* Sanity check for possible buffer paddr corruption */ - qdf_assert_always((&hbi)->paddr == - qdf_nbuf_get_frag_paddr(rx_desc->nbuf, 0)); + if (dp_rx_desc_paddr_sanity_check(rx_desc, (&hbi)->paddr)) + return QDF_STATUS_SUCCESS; + + return QDF_STATUS_E_FAILURE; } #else -static inline void dp_rx_desc_nbuf_sanity_check(void *ring_desc, - struct dp_rx_desc *rx_desc) +static inline +QDF_STATUS dp_rx_desc_nbuf_sanity_check(hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc) { + return QDF_STATUS_SUCCESS; } #endif @@ -1646,7 +1808,6 @@ static inline bool dp_rx_enable_eol_data_check(struct dp_soc *soc) static void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) { - uint32_t peer_mdata; uint16_t peer_id; uint8_t vdev_id; struct dp_vdev *vdev; @@ -1657,13 +1818,11 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) uint32_t frame_mask = FRAME_MASK_IPV4_ARP | FRAME_MASK_IPV4_DHCP | FRAME_MASK_IPV4_EAPOL | FRAME_MASK_IPV6_DHCP; - peer_mdata = QDF_NBUF_CB_RX_PEER_ID(nbuf); - - peer_id = DP_PEER_METADATA_PEER_ID_GET(peer_mdata); + peer_id = QDF_NBUF_CB_RX_PEER_ID(nbuf); if (peer_id > soc->max_peers) goto deliver_fail; - vdev_id = DP_PEER_METADATA_ID_GET(peer_mdata); + vdev_id = QDF_NBUF_CB_RX_VDEV_ID(nbuf); vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); if (!vdev || vdev->delete.pending || !vdev->osif_rx) goto deliver_fail; @@ -1673,7 +1832,7 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) rx_tlv_hdr = qdf_nbuf_data(nbuf); l2_hdr_offset = - hal_rx_msdu_end_l3_hdr_padding_get(rx_tlv_hdr); + hal_rx_msdu_end_l3_hdr_padding_get(soc->hal_soc, rx_tlv_hdr); msdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); pkt_len = msdu_len + l2_hdr_offset + RX_PKT_TLVS_LEN; @@ -1685,7 +1844,10 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) l2_hdr_offset); if (dp_rx_is_special_frame(nbuf, frame_mask)) { - vdev->osif_rx(vdev->osif_vdev, nbuf); + qdf_nbuf_set_exc_frame(nbuf, 1); + if (QDF_STATUS_SUCCESS != + vdev->osif_rx(vdev->osif_vdev, nbuf)) + goto deliver_fail; DP_STATS_INC(soc, rx.err.pkt_delivered_no_peer, 1); return; } @@ -1720,11 +1882,11 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) * entries. It should not be called within a SRNG lock. HW pointer value is * synced into cached_hp. * - * Return: Number of pending entries in the hal_ring + * Return: Number of pending entries if any */ static -uint32_t dp_rx_srng_get_num_pending(void *hal_soc, - void *hal_ring_hdl, +uint32_t dp_rx_srng_get_num_pending(hal_soc_handle_t hal_soc, + hal_ring_handle_t hal_ring_hdl, uint32_t num_entries, bool *near_full) { @@ -1742,6 +1904,145 @@ uint32_t dp_rx_srng_get_num_pending(void *hal_soc, return num_pending; } +#ifdef WLAN_SUPPORT_RX_FISA +void dp_rx_skip_tlvs(qdf_nbuf_t nbuf, uint32_t l3_padding) +{ + QDF_NBUF_CB_RX_PACKET_L3_HDR_PAD(nbuf) = l3_padding; + qdf_nbuf_pull_head(nbuf, l3_padding + RX_PKT_TLVS_LEN); +} + +/** + * dp_rx_set_hdr_pad() - set l3 padding in nbuf cb + * @nbuf: pkt skb pointer + * @l3_padding: l3 padding + * + * Return: None + */ +static inline +void dp_rx_set_hdr_pad(qdf_nbuf_t nbuf, uint32_t l3_padding) +{ + QDF_NBUF_CB_RX_PACKET_L3_HDR_PAD(nbuf) = l3_padding; +} +#else +void dp_rx_skip_tlvs(qdf_nbuf_t nbuf, uint32_t l3_padding) +{ + qdf_nbuf_pull_head(nbuf, l3_padding + RX_PKT_TLVS_LEN); +} + +static inline +void dp_rx_set_hdr_pad(qdf_nbuf_t nbuf, uint32_t l3_padding) +{ +} +#endif + +#ifdef DP_RX_DROP_RAW_FRM +/** + * dp_rx_is_raw_frame_dropped() - if raw frame nbuf, free and drop + * @nbuf: pkt skb pointer + * + * Return: true - raw frame, dropped + * false - not raw frame, do nothing + */ +static inline +bool dp_rx_is_raw_frame_dropped(qdf_nbuf_t nbuf) +{ + if (qdf_nbuf_is_raw_frame(nbuf)) { + qdf_nbuf_free(nbuf); + return true; + } + + return false; +} +#else +static inline +bool dp_rx_is_raw_frame_dropped(qdf_nbuf_t nbuf) +{ + return false; +} +#endif + +#ifdef WLAN_FEATURE_DP_RX_RING_HISTORY +/** + * dp_rx_ring_record_entry() - Record an entry into the rx ring history. + * @soc: Datapath soc structure + * @ring_num: REO ring number + * @ring_desc: REO ring descriptor + * + * Returns: None + */ +static inline void +dp_rx_ring_record_entry(struct dp_soc *soc, uint8_t ring_num, + hal_ring_desc_t ring_desc) +{ + struct dp_buf_info_record *record; + uint8_t rbm; + struct hal_buf_info hbi; + uint32_t idx; + + if (qdf_unlikely(!soc->rx_ring_history[ring_num])) + return; + + hal_rx_reo_buf_paddr_get(ring_desc, &hbi); + rbm = hal_rx_ret_buf_manager_get(ring_desc); + + idx = dp_history_get_next_index(&soc->rx_ring_history[ring_num]->index, + DP_RX_HIST_MAX); + + /* No NULL check needed for record since its an array */ + record = &soc->rx_ring_history[ring_num]->entry[idx]; + + record->timestamp = qdf_get_log_timestamp(); + record->hbi.paddr = hbi.paddr; + record->hbi.sw_cookie = hbi.sw_cookie; + record->hbi.rbm = rbm; +} +#else +static inline void +dp_rx_ring_record_entry(struct dp_soc *soc, uint8_t ring_num, + hal_ring_desc_t ring_desc) +{ +} +#endif + +#ifdef DISABLE_EAPOL_INTRABSS_FWD +/* + * dp_rx_intrabss_fwd_wrapper() - Wrapper API for intrabss fwd. For EAPOL + * pkt with DA not equal to vdev mac addr, fwd is not allowed. + * @soc: core txrx main context + * @ta_peer: source peer entry + * @rx_tlv_hdr: start address of rx tlvs + * @nbuf: nbuf that has to be intrabss forwarded + * @msdu_metadata: msdu metadata + * + * Return: true if it is forwarded else false + */ +static inline +bool dp_rx_intrabss_fwd_wrapper(struct dp_soc *soc, struct dp_peer *ta_peer, + uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf, + struct hal_rx_msdu_metadata msdu_metadata) +{ + if (qdf_unlikely(qdf_nbuf_is_ipv4_eapol_pkt(nbuf) && + qdf_mem_cmp(qdf_nbuf_data(nbuf) + + QDF_NBUF_DEST_MAC_OFFSET, + ta_peer->vdev->mac_addr.raw, + QDF_MAC_ADDR_SIZE))) { + qdf_nbuf_free(nbuf); + DP_STATS_INC(soc, rx.err.intrabss_eapol_drop, 1); + return true; + } + + return dp_rx_intrabss_fwd(soc, ta_peer, rx_tlv_hdr, nbuf, + msdu_metadata); + +} +#define DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata) \ + dp_rx_intrabss_fwd_wrapper(soc, peer, rx_tlv_hdr, nbuf, \ + msdu_metadata) +#else +#define DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata) \ + dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata) +#endif + /** * dp_rx_process() - Brain of the Rx processing functionality * Called from the bottom half (tasklet/NET_RX_SOFTIRQ) @@ -1755,11 +2056,11 @@ uint32_t dp_rx_srng_get_num_pending(void *hal_soc, * * Return: uint32_t: No. of elements processed */ -uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, - uint8_t reo_ring_num, uint32_t quota) +uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl, + uint8_t reo_ring_num, uint32_t quota) { - void *hal_soc; - void *ring_desc; + hal_ring_desc_t ring_desc; + hal_soc_handle_t hal_soc; struct dp_rx_desc *rx_desc = NULL; qdf_nbuf_t nbuf, next; bool near_full; @@ -1767,9 +2068,9 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, union dp_rx_desc_list_elem_t *tail[MAX_PDEV_CNT]; uint32_t num_pending; uint32_t rx_bufs_used = 0, rx_buf_cookie; - uint32_t l2_hdr_offset = 0; uint16_t msdu_len = 0; uint16_t peer_id; + uint8_t vdev_id; struct dp_peer *peer; struct dp_vdev *vdev; uint32_t pkt_len = 0; @@ -1780,7 +2081,6 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint8_t *rx_tlv_hdr; uint32_t rx_bufs_reaped[MAX_PDEV_CNT]; uint8_t mac_id = 0; - struct dp_pdev *pdev; struct dp_pdev *rx_pdev; struct dp_srng *dp_rxdma_srng; struct rx_desc_pool *rx_desc_pool; @@ -1800,18 +2100,19 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t num_entries_avail = 0; uint32_t rx_ol_pkt_cnt = 0; uint32_t num_entries = 0; + struct hal_rx_msdu_metadata msdu_metadata; + QDF_STATUS status; DP_HIST_INIT(); - qdf_assert_always(soc && hal_ring); + qdf_assert_always(soc && hal_ring_hdl); hal_soc = soc->hal_soc; qdf_assert_always(hal_soc); scn = soc->hif_handle; hif_pm_runtime_mark_dp_rx_busy(scn); intr_id = int_ctx->dp_intr_id; - num_entries = hal_srng_get_num_entries(hal_soc, - hal_ring); + num_entries = hal_srng_get_num_entries(hal_soc, hal_ring_hdl); more_data: /* reset local variables here to be re-used in the function */ @@ -1829,7 +2130,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, qdf_mem_zero(head, sizeof(head)); qdf_mem_zero(tail, sizeof(tail)); - if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring))) { + if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring_hdl))) { /* * Need API to convert from hal_ring pointer to @@ -1837,7 +2138,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, */ DP_STATS_INC(soc, rx.err.hal_ring_access_fail, 1); QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - FL("HAL RING Access Failed -- %pK"), hal_ring); + FL("HAL RING Access Failed -- %pK"), hal_ring_hdl); goto done; } @@ -1847,23 +2148,50 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, * Process the received pkts in a different per vdev loop. */ while (qdf_likely(quota && - (ring_desc = hal_srng_dst_peek(hal_soc, hal_ring)))) { + (ring_desc = hal_srng_dst_peek(hal_soc, + hal_ring_hdl)))) { error = HAL_RX_ERROR_STATUS_GET(ring_desc); - ring_id = hal_srng_ring_id_get(hal_ring); + ring_id = hal_srng_ring_id_get(hal_ring_hdl); if (qdf_unlikely(error == HAL_REO_ERROR_DETECTED)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - FL("HAL RING 0x%pK:error %d"), hal_ring, error); + FL("HAL RING 0x%pK:error %d"), hal_ring_hdl, error); DP_STATS_INC(soc, rx.err.hal_reo_error[ring_id], 1); /* Don't know how to deal with this -- assert */ qdf_assert(0); } + dp_rx_ring_record_entry(soc, reo_ring_num, ring_desc); rx_buf_cookie = HAL_RX_REO_BUF_COOKIE_GET(ring_desc); + status = dp_rx_cookie_check_and_invalidate(ring_desc); + if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) { + DP_STATS_INC(soc, rx.err.stale_cookie, 1); + break; + } rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, rx_buf_cookie); - qdf_assert(rx_desc); + status = dp_rx_desc_sanity(soc, hal_soc, hal_ring_hdl, + ring_desc, rx_desc); + if (QDF_IS_STATUS_ERROR(status)) { + if (qdf_unlikely(rx_desc && rx_desc->nbuf)) { + qdf_assert_always(rx_desc->unmapped); + dp_ipa_handle_rx_buf_smmu_mapping(soc, + rx_desc->nbuf, + false); + qdf_nbuf_unmap_single(soc->osdev, + rx_desc->nbuf, + QDF_DMA_FROM_DEVICE); + rx_desc->unmapped = 1; + qdf_nbuf_free(rx_desc->nbuf); + dp_rx_add_to_free_desc_list( + &head[rx_desc->pool_id], + &tail[rx_desc->pool_id], + rx_desc); + } + hal_srng_dst_get_next(hal_soc, hal_ring_hdl); + continue; + } /* * this is a unlikely scenario where the host is reaping @@ -1872,26 +2200,33 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, * In this case host will dump the last 128 descriptors * including the software descriptor rx_desc and assert. */ + if (qdf_unlikely(!rx_desc->in_use)) { DP_STATS_INC(soc, rx.err.hal_reo_dest_dup, 1); dp_info_rl("Reaping rx_desc not in use!"); - dp_rx_dump_info_and_assert(soc, hal_ring, + dp_rx_dump_info_and_assert(soc, hal_ring_hdl, ring_desc, rx_desc); /* ignore duplicate RX desc and continue to process */ - /* Pop out the descriptor*/ - hal_srng_dst_get_next(hal_soc, hal_ring); + /* Pop out the descriptor */ + hal_srng_dst_get_next(hal_soc, hal_ring_hdl); + continue; + } + + status = dp_rx_desc_nbuf_sanity_check(ring_desc, rx_desc); + if (QDF_IS_STATUS_ERROR(status)) { + DP_STATS_INC(soc, rx.err.nbuf_sanity_fail, 1); + rx_desc->in_err_state = 1; + hal_srng_dst_get_next(hal_soc, hal_ring_hdl); continue; } if (qdf_unlikely(!dp_rx_desc_check_magic(rx_desc))) { dp_err("Invalid rx_desc cookie=%d", rx_buf_cookie); DP_STATS_INC(soc, rx.err.rx_desc_invalid_magic, 1); - dp_rx_dump_info_and_assert(soc, hal_ring, + dp_rx_dump_info_and_assert(soc, hal_ring_hdl, ring_desc, rx_desc); } - dp_rx_desc_nbuf_sanity_check(ring_desc, rx_desc); - /* Get MPDU DESC info */ hal_rx_mpdu_desc_info_get(ring_desc, &mpdu_desc_info); @@ -1906,7 +2241,8 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, if (is_prev_msdu_last) { /* Get number of entries available in HW ring */ num_entries_avail = - hal_srng_dst_num_valid(hal_soc, hal_ring, 1); + hal_srng_dst_num_valid(hal_soc, + hal_ring_hdl, 1); /* For new MPDU check if we can read complete * MPDU by comparing the number of buffers @@ -1914,8 +2250,8 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, * reap this MPDU */ if (((msdu_desc_info.msdu_len / - (RX_BUFFER_SIZE - RX_PKT_TLVS_LEN) + 1)) > - num_entries_avail) { + (RX_DATA_BUFFER_SIZE - RX_PKT_TLVS_LEN) + + 1)) > num_entries_avail) { DP_STATS_INC( soc, rx.msdu_scatter_wait_break, @@ -1951,12 +2287,14 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, is_prev_msdu_last = true; /* Pop out the descriptor*/ - hal_srng_dst_get_next(hal_soc, hal_ring); + hal_srng_dst_get_next(hal_soc, hal_ring_hdl); rx_bufs_reaped[rx_desc->pool_id]++; peer_mdata = mpdu_desc_info.peer_meta_data; QDF_NBUF_CB_RX_PEER_ID(rx_desc->nbuf) = DP_PEER_METADATA_PEER_ID_GET(peer_mdata); + QDF_NBUF_CB_RX_VDEV_ID(rx_desc->nbuf) = + DP_PEER_METADATA_VDEV_ID_GET(peer_mdata); /* * save msdu flags first, last and continuation msdu in @@ -1986,6 +2324,9 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, qdf_nbuf_set_tid_val(rx_desc->nbuf, HAL_RX_REO_QUEUE_NUMBER_GET(ring_desc)); + qdf_nbuf_set_rx_reo_dest_ind( + rx_desc->nbuf, + HAL_RX_REO_MSDU_REO_DST_IND_GET(ring_desc)); QDF_NBUF_CB_RX_PKT_LEN(rx_desc->nbuf) = msdu_desc_info.msdu_len; @@ -2015,7 +2356,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, break; } done: - dp_srng_access_end(int_ctx, soc, hal_ring); + dp_srng_access_end(int_ctx, soc, hal_ring_hdl); for (mac_id = 0; mac_id < MAX_PDEV_CNT; mac_id++) { /* @@ -2025,8 +2366,8 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, if (!rx_bufs_reaped[mac_id]) continue; - pdev = soc->pdev_list[mac_id]; - dp_rxdma_srng = &pdev->rx_refill_buf_ring; + dp_rxdma_srng = &soc->rx_refill_buf_ring[mac_id]; + rx_desc_pool = &soc->rx_desc_buf[mac_id]; dp_rx_buffers_replenish(soc, mac_id, dp_rxdma_srng, @@ -2049,39 +2390,43 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, nbuf = nbuf_head; while (nbuf) { next = nbuf->next; + if (qdf_unlikely(dp_rx_is_raw_frame_dropped(nbuf))) { + nbuf = next; + DP_STATS_INC(soc, rx.err.raw_frm_drop, 1); + continue; + } + rx_tlv_hdr = qdf_nbuf_data(nbuf); + vdev_id = QDF_NBUF_CB_RX_VDEV_ID(nbuf); + + if (deliver_list_head && vdev && (vdev->vdev_id != vdev_id)) { + dp_rx_deliver_to_stack(soc, vdev, peer, + deliver_list_head, + deliver_list_tail); + deliver_list_head = NULL; + deliver_list_tail = NULL; + } + /* Get TID from struct cb->tid_val, save to tid */ - if (qdf_nbuf_is_rx_chfrag_start(nbuf)) + if (qdf_nbuf_is_rx_chfrag_start(nbuf)) { tid = qdf_nbuf_get_tid_val(nbuf); + if (tid >= CDP_MAX_DATA_TIDS) { + DP_STATS_INC(soc, rx.err.rx_invalid_tid_err, 1); + qdf_nbuf_free(nbuf); + nbuf = next; + continue; + } + } - /* - * Check if DMA completed -- msdu_done is the last bit - * to be written - */ - rx_pdev = soc->pdev_list[rx_desc->pool_id]; - DP_RX_TID_SAVE(nbuf, tid); - if (qdf_unlikely(rx_pdev->delay_stats_flag)) - qdf_nbuf_set_timestamp(nbuf); + peer_id = QDF_NBUF_CB_RX_PEER_ID(nbuf); - tid_stats = &rx_pdev->stats.tid_stats. - tid_rx_stats[ring_id][tid]; - if (qdf_unlikely(!qdf_nbuf_is_rx_chfrag_cont(nbuf) && - !hal_rx_attn_msdu_done_get(rx_tlv_hdr))) { - dp_err("MSDU DONE failure"); - DP_STATS_INC(soc, rx.err.msdu_done_fail, 1); - hal_rx_dump_pkt_tlvs(hal_soc, rx_tlv_hdr, - QDF_TRACE_LEVEL_INFO); - tid_stats->fail_cnt[MSDU_DONE_FAILURE]++; - qdf_nbuf_free(nbuf); - qdf_assert(0); - nbuf = next; - continue; + if (qdf_unlikely(!peer)) { + peer = dp_peer_find_by_id(soc, peer_id); + } else if (peer && peer->peer_ids[0] != peer_id) { + dp_peer_unref_del_find_by_id(peer); + peer = dp_peer_find_by_id(soc, peer_id); } - peer_mdata = QDF_NBUF_CB_RX_PEER_ID(nbuf); - peer_id = DP_PEER_METADATA_PEER_ID_GET(peer_mdata); - peer = dp_peer_find_by_id(soc, peer_id); - if (peer) { QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) = false; qdf_dp_trace_set_track(nbuf, QDF_RX); @@ -2092,18 +2437,9 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, rx_bufs_used++; - if (deliver_list_head && peer && (vdev != peer->vdev)) { - dp_rx_deliver_to_stack(soc, vdev, peer, - deliver_list_head, - deliver_list_tail); - deliver_list_head = NULL; - deliver_list_tail = NULL; - } - if (qdf_likely(peer)) { vdev = peer->vdev; } else { - tid_stats->fail_cnt[INVALID_PEER_VDEV]++; nbuf->next = NULL; dp_rx_deliver_to_stack_no_peer(soc, nbuf); nbuf = next; @@ -2111,14 +2447,46 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, } if (qdf_unlikely(!vdev)) { - tid_stats->fail_cnt[INVALID_PEER_VDEV]++; qdf_nbuf_free(nbuf); nbuf = next; DP_STATS_INC(soc, rx.err.invalid_vdev, 1); - dp_peer_unref_del_find_by_id(peer); continue; } + rx_pdev = vdev->pdev; + DP_RX_TID_SAVE(nbuf, tid); + if (qdf_unlikely(rx_pdev->delay_stats_flag)) + qdf_nbuf_set_timestamp(nbuf); + + ring_id = QDF_NBUF_CB_RX_CTX_ID(nbuf); + tid_stats = + &rx_pdev->stats.tid_stats.tid_rx_stats[ring_id][tid]; + + /* + * Check if DMA completed -- msdu_done is the last bit + * to be written + */ + if (qdf_likely(!qdf_nbuf_is_rx_chfrag_cont(nbuf))) { + if (qdf_unlikely(!hal_rx_attn_msdu_done_get( + rx_tlv_hdr))) { + dp_err_rl("MSDU DONE failure"); + DP_STATS_INC(soc, rx.err.msdu_done_fail, 1); + hal_rx_dump_pkt_tlvs(hal_soc, rx_tlv_hdr, + QDF_TRACE_LEVEL_INFO); + tid_stats->fail_cnt[MSDU_DONE_FAILURE]++; + qdf_assert(0); + qdf_nbuf_free(nbuf); + nbuf = next; + continue; + } else if (qdf_unlikely(hal_rx_attn_msdu_len_err_get( + rx_tlv_hdr))) { + DP_STATS_INC(soc, rx.err.msdu_len_err, 1); + qdf_nbuf_free(nbuf); + nbuf = next; + continue; + } + } + DP_HIST_PACKET_COUNT_INC(vdev->pdev->pdev_id); /* * First IF condition: @@ -2145,12 +2513,18 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, * This is the most likely case, we receive 802.3 pkts * decapsulated by HW, here we need to set the pkt length. */ + hal_rx_msdu_metadata_get(hal_soc, rx_tlv_hdr, &msdu_metadata); if (qdf_unlikely(qdf_nbuf_is_frag(nbuf))) { bool is_mcbc, is_sa_vld, is_da_vld; - is_mcbc = hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr); - is_sa_vld = hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr); - is_da_vld = hal_rx_msdu_end_da_is_valid_get(rx_tlv_hdr); + is_mcbc = hal_rx_msdu_end_da_is_mcbc_get(soc->hal_soc, + rx_tlv_hdr); + is_sa_vld = + hal_rx_msdu_end_sa_is_valid_get(soc->hal_soc, + rx_tlv_hdr); + is_da_vld = + hal_rx_msdu_end_da_is_valid_get(soc->hal_soc, + rx_tlv_hdr); qdf_nbuf_set_da_mcbc(nbuf, is_mcbc); qdf_nbuf_set_da_valid(nbuf, is_da_vld); @@ -2159,7 +2533,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN); } else if (qdf_nbuf_is_rx_chfrag_cont(nbuf)) { msdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); - nbuf = dp_rx_sg_create(nbuf); + nbuf = dp_rx_sg_create(soc, nbuf); next = nbuf->next; if (qdf_nbuf_is_raw_frame(nbuf)) { @@ -2168,22 +2542,32 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, } else { qdf_nbuf_free(nbuf); DP_STATS_INC(soc, rx.err.scatter_msdu, 1); - dp_info_rl("scatter msdu len %d, dropped", msdu_len); + dp_info_rl("scatter msdu len %d, dropped", + msdu_len); nbuf = next; - dp_peer_unref_del_find_by_id(peer); continue; } } else { - l2_hdr_offset = - hal_rx_msdu_end_l3_hdr_padding_get(rx_tlv_hdr); msdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); - pkt_len = msdu_len + l2_hdr_offset + RX_PKT_TLVS_LEN; + pkt_len = msdu_len + + msdu_metadata.l3_hdr_pad + + RX_PKT_TLVS_LEN; qdf_nbuf_set_pktlen(nbuf, pkt_len); - qdf_nbuf_pull_head(nbuf, - RX_PKT_TLVS_LEN + - l2_hdr_offset); + dp_rx_skip_tlvs(nbuf, msdu_metadata.l3_hdr_pad); + } + + /* + * process frame for mulitpass phrase processing + */ + if (qdf_unlikely(vdev->multipass_en)) { + if (dp_rx_multipass_process(peer, nbuf, tid) == false) { + DP_STATS_INC(peer, rx.multipass_rx_pkt_drop, 1); + qdf_nbuf_free(nbuf); + nbuf = next; + continue; + } } if (!dp_wds_rx_policy_check(rx_tlv_hdr, vdev, peer)) { @@ -2195,22 +2579,38 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, qdf_nbuf_free(nbuf); /* Statistics */ nbuf = next; - dp_peer_unref_del_find_by_id(peer); continue; } if (qdf_unlikely(peer && (peer->nawds_enabled) && (qdf_nbuf_is_da_mcbc(nbuf)) && - (hal_rx_get_mpdu_mac_ad4_valid(rx_tlv_hdr) == + (hal_rx_get_mpdu_mac_ad4_valid(soc->hal_soc, + rx_tlv_hdr) == false))) { tid_stats->fail_cnt[NAWDS_MCAST_DROP]++; DP_STATS_INC(peer, rx.nawds_mcast_drop, 1); qdf_nbuf_free(nbuf); nbuf = next; - dp_peer_unref_del_find_by_id(peer); continue; } + /* + * Drop non-EAPOL frames from unauthorized peer. + */ + if (qdf_likely(peer) && qdf_unlikely(!peer->authorize)) { + bool is_eapol = qdf_nbuf_is_ipv4_eapol_pkt(nbuf) || + qdf_nbuf_is_ipv4_wapi_pkt(nbuf); + + if (!is_eapol) { + DP_STATS_INC(soc, + rx.err.peer_unauth_rx_pkt_drop, + 1); + qdf_nbuf_free(nbuf); + nbuf = next; + continue; + } + } + if (soc->process_rx_status) dp_rx_cksum_offload(vdev->pdev, nbuf, rx_tlv_hdr); @@ -2218,6 +2618,9 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, dp_rx_update_protocol_tag(soc, vdev, nbuf, rx_tlv_hdr, reo_ring_num, false, true); + /* Update the flow tag in SKB based on FSE metadata */ + dp_rx_update_flow_tag(soc, vdev, nbuf, rx_tlv_hdr, true); + dp_rx_msdu_stats_update(soc, nbuf, rx_tlv_hdr, peer, ring_id, tid_stats); @@ -2233,7 +2636,6 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, qdf_nbuf_free(nbuf); nbuf = next; - dp_peer_unref_del_find_by_id(peer); continue; } dp_rx_fill_mesh_stats(vdev, nbuf, rx_tlv_hdr, peer); @@ -2255,26 +2657,29 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, * Drop the packet if sa_idx and da_idx OOB or * sa_sw_peerid is 0 */ - if (!is_sa_da_idx_valid(soc, rx_tlv_hdr, nbuf)) { + if (!is_sa_da_idx_valid(soc, rx_tlv_hdr, nbuf, + msdu_metadata)) { qdf_nbuf_free(nbuf); nbuf = next; DP_STATS_INC(soc, rx.err.invalid_sa_da_idx, 1); - dp_peer_unref_del_find_by_id(peer); continue; } /* WDS Source Port Learning */ if (qdf_likely(vdev->wds_enabled)) - dp_rx_wds_srcport_learn(soc, rx_tlv_hdr, - peer, nbuf); + dp_rx_wds_srcport_learn(soc, + rx_tlv_hdr, + peer, + nbuf, + msdu_metadata); /* Intrabss-fwd */ if (dp_rx_check_ap_bridge(vdev)) - if (dp_rx_intrabss_fwd(soc, + if (DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, - nbuf)) { + nbuf, + msdu_metadata)) { nbuf = next; - dp_peer_unref_del_find_by_id(peer); tid_stats->intrabss_cnt++; continue; /* Get next desc */ } @@ -2290,19 +2695,32 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, tid_stats->delivered_to_stack++; nbuf = next; - dp_peer_unref_del_find_by_id(peer); } - if (deliver_list_head && peer) - dp_rx_deliver_to_stack(soc, vdev, peer, - deliver_list_head, - deliver_list_tail); + if (qdf_likely(deliver_list_head)) { + if (qdf_likely(peer)) + dp_rx_deliver_to_stack(soc, vdev, peer, + deliver_list_head, + deliver_list_tail); + else { + nbuf = deliver_list_head; + while (nbuf) { + next = nbuf->next; + nbuf->next = NULL; + dp_rx_deliver_to_stack_no_peer(soc, nbuf); + nbuf = next; + } + } + } + + if (qdf_likely(peer)) + dp_peer_unref_del_find_by_id(peer); if (dp_rx_enable_eol_data_check(soc) && rx_bufs_used) { if (quota) { num_pending = dp_rx_srng_get_num_pending(hal_soc, - hal_ring, + hal_ring_hdl, num_entries, &near_full); if (num_pending) { @@ -2318,6 +2736,9 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, } } + if (vdev && vdev->osif_fisa_flush) + vdev->osif_fisa_flush(soc, reo_ring_num); + if (vdev && vdev->osif_gro_flush && rx_ol_pkt_cnt) { vdev->osif_gro_flush(vdev->osif_vdev, reo_ring_num); @@ -2358,15 +2779,15 @@ QDF_STATUS dp_rx_vdev_detach(struct dp_vdev *vdev) void dp_rx_pdev_detach(struct dp_pdev *pdev) { - uint8_t pdev_id = pdev->pdev_id; + uint8_t mac_for_pdev = pdev->lmac_id; struct dp_soc *soc = pdev->soc; struct rx_desc_pool *rx_desc_pool; - rx_desc_pool = &soc->rx_desc_buf[pdev_id]; + rx_desc_pool = &soc->rx_desc_buf[mac_for_pdev]; if (rx_desc_pool->pool_size != 0) { if (!dp_is_soc_reinit(soc)) - dp_rx_desc_nbuf_and_pool_free(soc, pdev_id, + dp_rx_desc_nbuf_and_pool_free(soc, mac_for_pdev, rx_desc_pool); else dp_rx_desc_nbuf_free(soc, rx_desc_pool); @@ -2377,14 +2798,15 @@ dp_rx_pdev_detach(struct dp_pdev *pdev) static QDF_STATUS dp_pdev_nbuf_alloc_and_map(struct dp_soc *dp_soc, qdf_nbuf_t *nbuf, - struct dp_pdev *dp_pdev) + struct dp_pdev *dp_pdev, + struct rx_desc_pool *rx_desc_pool) { qdf_dma_addr_t paddr; QDF_STATUS ret = QDF_STATUS_E_FAILURE; - *nbuf = qdf_nbuf_alloc(dp_soc->osdev, RX_BUFFER_SIZE, - RX_BUFFER_RESERVATION, RX_BUFFER_ALIGNMENT, - FALSE); + *nbuf = qdf_nbuf_alloc(dp_soc->osdev, rx_desc_pool->buf_size, + RX_BUFFER_RESERVATION, + rx_desc_pool->buf_alignment, FALSE); if (!(*nbuf)) { dp_err("nbuf alloc failed"); DP_STATS_INC(dp_pdev, replenish.nbuf_alloc_fail, 1); @@ -2402,7 +2824,7 @@ dp_pdev_nbuf_alloc_and_map(struct dp_soc *dp_soc, qdf_nbuf_t *nbuf, paddr = qdf_nbuf_get_frag_paddr(*nbuf, 0); - ret = check_x86_paddr(dp_soc, nbuf, &paddr, dp_pdev); + ret = check_x86_paddr(dp_soc, nbuf, &paddr, rx_desc_pool); if (ret == QDF_STATUS_E_FAILURE) { qdf_nbuf_unmap_single(dp_soc->osdev, *nbuf, QDF_DMA_FROM_DEVICE); @@ -2415,14 +2837,14 @@ dp_pdev_nbuf_alloc_and_map(struct dp_soc *dp_soc, qdf_nbuf_t *nbuf, return QDF_STATUS_SUCCESS; } -static QDF_STATUS +QDF_STATUS dp_pdev_rx_buffers_attach(struct dp_soc *dp_soc, uint32_t mac_id, struct dp_srng *dp_rxdma_srng, struct rx_desc_pool *rx_desc_pool, uint32_t num_req_buffers) { - struct dp_pdev *dp_pdev = dp_get_pdev_for_mac_id(dp_soc, mac_id); - void *rxdma_srng = dp_rxdma_srng->hal_srng; + struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(dp_soc, mac_id); + hal_ring_handle_t rxdma_srng = dp_rxdma_srng->hal_srng; union dp_rx_desc_list_elem_t *next; void *rxdma_ring_entry; qdf_dma_addr_t paddr; @@ -2490,7 +2912,7 @@ dp_pdev_rx_buffers_attach(struct dp_soc *dp_soc, uint32_t mac_id, break; ret = dp_pdev_nbuf_alloc_and_map(dp_soc, &rx_nbuf_arr[nr_nbuf], - dp_pdev); + dp_pdev, rx_desc_pool); if (QDF_IS_STATUS_ERROR(ret)) break; @@ -2536,8 +2958,11 @@ dp_pdev_rx_buffers_attach(struct dp_soc *dp_soc, uint32_t mac_id, QDF_BUG(0); return QDF_STATUS_E_RESOURCES; } - DP_STATS_INC_PKT(dp_pdev, replenish.pkts, nr_nbuf, - RX_BUFFER_SIZE * nr_nbuf_total); + + /* No need to count the number of bytes received during replenish. + * Therefore set replenish.pkts.bytes as 0. + */ + DP_STATS_INC_PKT(dp_pdev, replenish.pkts, nr_nbuf, 0); return QDF_STATUS_SUCCESS; } @@ -2559,8 +2984,11 @@ dp_rx_pdev_attach(struct dp_pdev *pdev) uint8_t pdev_id = pdev->pdev_id; struct dp_soc *soc = pdev->soc; uint32_t rxdma_entries; + uint32_t rx_sw_desc_weight; struct dp_srng *dp_rxdma_srng; struct rx_desc_pool *rx_desc_pool; + QDF_STATUS ret_val; + int mac_for_pdev; if (wlan_cfg_get_dp_pdev_nss_enabled(pdev->wlan_cfg_ctx)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, @@ -2569,20 +2997,37 @@ dp_rx_pdev_attach(struct dp_pdev *pdev) } pdev = soc->pdev_list[pdev_id]; - dp_rxdma_srng = &pdev->rx_refill_buf_ring; + mac_for_pdev = pdev->lmac_id; + dp_rxdma_srng = &soc->rx_refill_buf_ring[mac_for_pdev]; + rxdma_entries = dp_rxdma_srng->num_entries; soc->process_rx_status = CONFIG_PROCESS_RX_STATUS; - rx_desc_pool = &soc->rx_desc_buf[pdev_id]; - dp_rx_desc_pool_alloc(soc, pdev_id, - DP_RX_DESC_ALLOC_MULTIPLIER * rxdma_entries, + rx_desc_pool = &soc->rx_desc_buf[mac_for_pdev]; + rx_sw_desc_weight = wlan_cfg_get_dp_soc_rx_sw_desc_weight(soc->wlan_cfg_ctx); + + rx_desc_pool->desc_type = DP_RX_DESC_BUF_TYPE; + dp_rx_desc_pool_alloc(soc, mac_for_pdev, + rx_sw_desc_weight * rxdma_entries, rx_desc_pool); rx_desc_pool->owner = DP_WBM2SW_RBM; + rx_desc_pool->buf_size = RX_DATA_BUFFER_SIZE; + rx_desc_pool->buf_alignment = RX_DATA_BUFFER_ALIGNMENT; + /* For Rx buffers, WBM release ring is SW RING 3,for all pdev's */ - return dp_pdev_rx_buffers_attach(soc, pdev_id, dp_rxdma_srng, + ret_val = dp_rx_fst_attach(soc, pdev); + if ((ret_val != QDF_STATUS_SUCCESS) && + (ret_val != QDF_STATUS_E_NOSUPPORT)) { + QDF_TRACE(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_ERROR, + "RX Flow Search Table attach failed: pdev %d err %d", + pdev_id, ret_val); + return ret_val; + } + + return dp_pdev_rx_buffers_attach(soc, mac_for_pdev, dp_rxdma_srng, rx_desc_pool, rxdma_entries - 1); } @@ -2609,9 +3054,9 @@ dp_rx_nbuf_prepare(struct dp_soc *soc, struct dp_pdev *pdev) nbuf_retry_count++) { /* Allocate a new skb */ nbuf = qdf_nbuf_alloc(soc->osdev, - RX_BUFFER_SIZE, + RX_DATA_BUFFER_SIZE, RX_BUFFER_RESERVATION, - RX_BUFFER_ALIGNMENT, + RX_DATA_BUFFER_ALIGNMENT, FALSE); if (!nbuf) { @@ -2622,7 +3067,7 @@ dp_rx_nbuf_prepare(struct dp_soc *soc, struct dp_pdev *pdev) buf = qdf_nbuf_data(nbuf); - memset(buf, 0, RX_BUFFER_SIZE); + memset(buf, 0, RX_DATA_BUFFER_SIZE); ret = qdf_nbuf_map_single(soc->osdev, nbuf, QDF_DMA_FROM_DEVICE); @@ -2655,7 +3100,7 @@ bool dp_rx_deliver_special_frame(struct dp_soc *soc, struct dp_peer *peer, uint32_t skip_len; l2_hdr_offset = - hal_rx_msdu_end_l3_hdr_padding_get(rx_tlv_hdr); + hal_rx_msdu_end_l3_hdr_padding_get(soc->hal_soc, rx_tlv_hdr); if (qdf_unlikely(qdf_nbuf_is_frag(nbuf))) { skip_len = l2_hdr_offset; @@ -2666,9 +3111,11 @@ bool dp_rx_deliver_special_frame(struct dp_soc *soc, struct dp_peer *peer, } QDF_NBUF_CB_RX_NUM_ELEMENTS_IN_LIST(nbuf) = 1; + dp_rx_set_hdr_pad(nbuf, l2_hdr_offset); qdf_nbuf_pull_head(nbuf, skip_len); if (dp_rx_is_special_frame(nbuf, frame_mask)) { + qdf_nbuf_set_exc_frame(nbuf, 1); dp_rx_deliver_to_stack(soc, peer->vdev, peer, nbuf, NULL); return true; diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.h index 236df33e6407a863de0555ce7a807bfa8e291acd..9e30da08facefb99d9fef1242fa2aee3c9325c61 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.h @@ -23,54 +23,40 @@ #include "dp_tx.h" #include "dp_peer.h" #include "dp_internal.h" -#include #ifdef RXDMA_OPTIMIZATION -#ifdef NO_RX_PKT_HDR_TLV -#define RX_BUFFER_ALIGNMENT 0 -#else -#define RX_BUFFER_ALIGNMENT 128 -#endif /* NO_RX_PKT_HDR_TLV */ +#ifndef RX_DATA_BUFFER_ALIGNMENT +#define RX_DATA_BUFFER_ALIGNMENT 128 +#endif +#ifndef RX_MONITOR_BUFFER_ALIGNMENT +#define RX_MONITOR_BUFFER_ALIGNMENT 128 +#endif #else /* RXDMA_OPTIMIZATION */ -#define RX_BUFFER_ALIGNMENT 4 +#define RX_DATA_BUFFER_ALIGNMENT 4 +#define RX_MONITOR_BUFFER_ALIGNMENT 4 #endif /* RXDMA_OPTIMIZATION */ #ifdef QCA_HOST2FW_RXBUF_RING +#define DP_WBM2SW_RBM HAL_RX_BUF_RBM_SW1_BM /* RBM value used for re-injecting defragmented packets into REO */ #define DP_DEFRAG_RBM HAL_RX_BUF_RBM_SW3_BM -#define DP_WBM2SW_RBM HAL_RX_BUF_RBM_SW1_BM - -/** - * For MCL cases, allocate as many RX descriptors as buffers in the SW2RXDMA - * ring. This value may need to be tuned later. - */ -#define DP_RX_DESC_ALLOC_MULTIPLIER 1 #else -#define DP_DEFRAG_RBM DP_WBM2SW_RBM #define DP_WBM2SW_RBM HAL_RX_BUF_RBM_SW3_BM - -/** - * AP use cases need to allocate more RX Descriptors than the number of - * entries avaialable in the SW2RXDMA buffer replenish ring. This is to account - * for frames sitting in REO queues, HW-HW DMA rings etc. Hence using a - * multiplication factor of 3, to allocate three times as many RX descriptors - * as RX buffers. - */ -#define DP_RX_DESC_ALLOC_MULTIPLIER 3 +#define DP_DEFRAG_RBM DP_WBM2SW_RBM #endif /* QCA_HOST2FW_RXBUF_RING */ #define RX_BUFFER_RESERVATION 0 #define DP_PEER_METADATA_PEER_ID_MASK 0x0000ffff #define DP_PEER_METADATA_PEER_ID_SHIFT 0 -#define DP_PEER_METADATA_VDEV_ID_MASK 0x00070000 +#define DP_PEER_METADATA_VDEV_ID_MASK 0x003f0000 #define DP_PEER_METADATA_VDEV_ID_SHIFT 16 #define DP_PEER_METADATA_PEER_ID_GET(_peer_metadata) \ (((_peer_metadata) & DP_PEER_METADATA_PEER_ID_MASK) \ >> DP_PEER_METADATA_PEER_ID_SHIFT) -#define DP_PEER_METADATA_ID_GET(_peer_metadata) \ +#define DP_PEER_METADATA_VDEV_ID_GET(_peer_metadata) \ (((_peer_metadata) & DP_PEER_METADATA_VDEV_ID_MASK) \ >> DP_PEER_METADATA_VDEV_ID_SHIFT) @@ -122,6 +108,7 @@ struct dp_rx_desc_dbg_info { * @in_use rx_desc is in use * @unmapped used to mark rx_desc an unmapped if the corresponding * nbuf is already unmapped + * @in_err_state : Nbuf sanity failed for this descriptor. */ struct dp_rx_desc { qdf_nbuf_t nbuf; @@ -133,7 +120,8 @@ struct dp_rx_desc { struct dp_rx_desc_dbg_info *dbg_info; #endif uint8_t in_use:1, - unmapped:1; + unmapped:1, + in_err_state:1; }; /* RX Descriptor Multi Page memory alloc related */ @@ -549,6 +537,24 @@ void *dp_rx_cookie_2_va_mon_status(struct dp_soc *soc, uint32_t cookie) } #endif /* RX_DESC_MULTI_PAGE_ALLOC */ +#ifdef DP_RX_DESC_COOKIE_INVALIDATE +static inline QDF_STATUS +dp_rx_cookie_check_and_invalidate(hal_ring_desc_t ring_desc) +{ + if (qdf_unlikely(HAL_RX_REO_BUF_COOKIE_INVALID_GET(ring_desc))) + return QDF_STATUS_E_FAILURE; + + HAL_RX_REO_BUF_COOKIE_INVALID_SET(ring_desc); + return QDF_STATUS_SUCCESS; +} +#else +static inline QDF_STATUS +dp_rx_cookie_check_and_invalidate(hal_ring_desc_t ring_desc) +{ + return QDF_STATUS_SUCCESS; +} +#endif + void dp_rx_add_desc_list_to_free_list(struct dp_soc *soc, union dp_rx_desc_list_elem_t **local_desc_list, union dp_rx_desc_list_elem_t **tail, @@ -566,6 +572,7 @@ QDF_STATUS dp_rx_pdev_attach(struct dp_pdev *pdev); void dp_rx_pdev_detach(struct dp_pdev *pdev); +void dp_print_napi_stats(struct dp_soc *soc); /** * dp_rx_vdev_detach() - detach vdev from dp rx @@ -577,7 +584,8 @@ void dp_rx_pdev_detach(struct dp_pdev *pdev); QDF_STATUS dp_rx_vdev_detach(struct dp_vdev *vdev); uint32_t -dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint8_t reo_ring_num, +dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl, + uint8_t reo_ring_num, uint32_t quota); /** @@ -593,7 +601,7 @@ dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint8_t reo_ring_num, * Return: uint32_t: No. of elements processed */ uint32_t dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, - void *hal_ring, uint32_t quota); + hal_ring_handle_t hal_ring_hdl, uint32_t quota); /** * dp_rx_wbm_err_process() - Processes error frames routed to WBM release ring @@ -609,11 +617,12 @@ uint32_t dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, */ uint32_t dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, - void *hal_ring, uint32_t quota); + hal_ring_handle_t hal_ring_hdl, uint32_t quota); /** * dp_rx_sg_create() - create a frag_list for MSDUs which are spread across * multiple nbufs. + * @soc: core txrx main context * @nbuf: pointer to the first msdu of an amsdu. * * This function implements the creation of RX frag_list for cases @@ -621,7 +630,7 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, * * Return: returns the head nbuf which contains complete frag_list. */ -qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf); +qdf_nbuf_t dp_rx_sg_create(struct dp_soc *soc, qdf_nbuf_t nbuf); /* * dp_rx_desc_pool_alloc() - create a pool of software rx_descs @@ -679,6 +688,20 @@ void dp_rx_deliver_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf_list, struct dp_peer *peer); #ifdef RX_DESC_DEBUG_CHECK +/** + * dp_rx_desc_paddr_sanity_check() - paddr sanity for ring desc vs rx_desc + * @rx_desc: rx descriptor + * @ring_paddr: paddr obatined from the ring + * + * Returns: QDF_STATUS + */ +static inline +bool dp_rx_desc_paddr_sanity_check(struct dp_rx_desc *rx_desc, + uint64_t ring_paddr) +{ + return (ring_paddr == qdf_nbuf_get_frag_paddr(rx_desc->nbuf, 0)); +} + /* * dp_rx_desc_alloc_dbg_info() - Alloc memory for rx descriptor debug * structure @@ -733,6 +756,13 @@ void dp_rx_desc_update_dbg_info(struct dp_rx_desc *rx_desc, } #else +static inline +bool dp_rx_desc_paddr_sanity_check(struct dp_rx_desc *rx_desc, + uint64_t ring_paddr) +{ + return true; +} + static inline void dp_rx_desc_alloc_dbg_info(struct dp_rx_desc *rx_desc) { @@ -785,8 +815,8 @@ void dp_rx_process_invalid_peer_wrapper(struct dp_soc *soc, qdf_nbuf_t mpdu, bool mpdu_done, uint8_t mac_id); void dp_rx_process_mic_error(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, struct dp_peer *peer); -void dp_2k_jump_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, - uint16_t peer_id, uint8_t tid, uint8_t *rx_tlv_hdr); +void dp_2k_jump_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, + uint16_t peer_id, uint8_t tid); #define DP_RX_LIST_APPEND(head, tail, elem) \ @@ -802,16 +832,17 @@ void dp_2k_jump_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, qdf_nbuf_set_next((tail), NULL); \ } while (0) -#ifndef BUILD_X86 +/*for qcn9000 emulation the pcie is complete phy and no address restrictions*/ +#if !defined(BUILD_X86) || defined(QCA_WIFI_QCN9000) static inline int check_x86_paddr(struct dp_soc *dp_soc, qdf_nbuf_t *rx_netbuf, - qdf_dma_addr_t *paddr, struct dp_pdev *pdev) + qdf_dma_addr_t *paddr, struct rx_desc_pool *rx_desc_pool) { return QDF_STATUS_SUCCESS; } #else #define MAX_RETRY 100 static inline int check_x86_paddr(struct dp_soc *dp_soc, qdf_nbuf_t *rx_netbuf, - qdf_dma_addr_t *paddr, struct dp_pdev *pdev) + qdf_dma_addr_t *paddr, struct rx_desc_pool *rx_desc_pool) { uint32_t nbuf_retry = 0; int32_t ret; @@ -842,10 +873,10 @@ static inline int check_x86_paddr(struct dp_soc *dp_soc, qdf_nbuf_t *rx_netbuf, } *rx_netbuf = qdf_nbuf_alloc(dp_soc->osdev, - RX_BUFFER_SIZE, - RX_BUFFER_RESERVATION, - RX_BUFFER_ALIGNMENT, - FALSE); + rx_desc_pool->buf_size, + RX_BUFFER_RESERVATION, + rx_desc_pool->buf_alignment, + FALSE); if (qdf_unlikely(!(*rx_netbuf))) return QDF_STATUS_E_FAILURE; @@ -877,8 +908,9 @@ static inline int check_x86_paddr(struct dp_soc *dp_soc, qdf_nbuf_t *rx_netbuf, * dp_rx_cookie_2_link_desc_va() - Converts cookie to a virtual address of * the MSDU Link Descriptor * @soc: core txrx main context - * @buf_info: buf_info include cookie that used to lookup virtual address of - * link descriptor Normally this is just an index into a per SOC array. + * @buf_info: buf_info includes cookie that is used to lookup + * virtual address of link descriptor after deriving the page id + * and the offset or index of the desc on the associatde page. * * This is the VA of the link descriptor, that HAL layer later uses to * retrieve the list of MSDU's for a given MPDU. @@ -890,16 +922,16 @@ void *dp_rx_cookie_2_link_desc_va(struct dp_soc *soc, struct hal_buf_info *buf_info) { void *link_desc_va; - uint32_t bank_id = LINK_DESC_COOKIE_BANK_ID(buf_info->sw_cookie); - - - /* TODO */ - /* Add sanity for cookie */ - - link_desc_va = soc->link_desc_banks[bank_id].base_vaddr + - (buf_info->paddr - - soc->link_desc_banks[bank_id].base_paddr); + struct qdf_mem_multi_page_t *pages; + uint16_t page_id = LINK_DESC_COOKIE_PAGE_ID(buf_info->sw_cookie); + pages = &soc->link_desc_pages; + if (!pages) + return NULL; + if (qdf_unlikely(page_id >= pages->num_pages)) + return NULL; + link_desc_va = pages->dma_pages[page_id].page_v_addr_start + + (buf_info->paddr - pages->dma_pages[page_id].page_p_addr); return link_desc_va; } @@ -921,15 +953,16 @@ void *dp_rx_cookie_2_mon_link_desc_va(struct dp_pdev *pdev, int mac_id) { void *link_desc_va; - int mac_for_pdev = dp_get_mac_id_for_mac(pdev->soc, mac_id); /* TODO */ /* Add sanity for cookie */ link_desc_va = - pdev->link_desc_banks[mac_for_pdev][buf_info->sw_cookie].base_vaddr + + pdev->soc->mon_link_desc_banks[mac_id][buf_info->sw_cookie] + .base_vaddr + (buf_info->paddr - - pdev->link_desc_banks[mac_for_pdev][buf_info->sw_cookie].base_paddr); + pdev->soc->mon_link_desc_banks[mac_id][buf_info->sw_cookie] + .base_paddr); return link_desc_va; } @@ -974,7 +1007,8 @@ static inline void dp_rx_wds_srcport_learn(struct dp_soc *soc, uint8_t *rx_tlv_hdr, struct dp_peer *ta_peer, - qdf_nbuf_t nbuf) + qdf_nbuf_t nbuf, + struct hal_rx_msdu_metadata msdu_metadata) { } #endif @@ -987,8 +1021,8 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc, static inline void dp_rx_desc_dump(struct dp_rx_desc *rx_desc) { dp_info("rx_desc->nbuf: %pK, rx_desc->cookie: %d, rx_desc->pool_id: %d, rx_desc->in_use: %d, rx_desc->unmapped: %d", - rx_desc->nbuf, rx_desc->cookie, rx_desc->pool_id, - rx_desc->in_use, rx_desc->unmapped); + rx_desc->nbuf, rx_desc->cookie, rx_desc->pool_id, + rx_desc->in_use, rx_desc->unmapped); } /* @@ -1036,76 +1070,13 @@ static inline bool check_qwrap_multicast_loopback(struct dp_vdev *vdev, } #endif -#if defined(WLAN_SUPPORT_RX_TAG_STATISTICS) && \ - defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG) -/** - * dp_rx_update_rx_protocol_tag_stats() - Increments the protocol tag stats - * for the given protocol type - * @soc: core txrx main context - * @pdev: TXRX pdev context for which stats should be incremented - * @protocol_index: Protocol index for which the stats should be incremented - * @ring_index: REO ring number from which this tag was received. - * - * Since HKv2 is a SMP, two or more cores may simultaneously receive packets - * of same type, and hence attempt to increment counters for the same protocol - * type at the same time. This creates the possibility of missing stats. - * - * For example, when two or more CPUs have each read the old tag value, V, - * for protocol type, P and each increment the value to V+1. Instead, the - * operations should have been sequenced to achieve a final value of V+2. - * - * In order to avoid this scenario, we can either use locks or store stats - * on a per-CPU basis. Since tagging happens in the core data path, locks - * are not preferred. Instead, we use a per-ring counter, since each CPU - * operates on a REO ring. - * - * Return: void - */ -static inline void dp_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev, - uint16_t protocol_index, - uint16_t ring_index) -{ - if (ring_index >= MAX_REO_DEST_RINGS) - return; - - pdev->reo_proto_tag_stats[ring_index][protocol_index].tag_ctr++; -} -#else -static inline void dp_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev, - uint16_t protocol_index, - uint16_t ring_index) -{ -} -#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */ +#if defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG) ||\ + defined(WLAN_SUPPORT_RX_TAG_STATISTICS) ||\ + defined(WLAN_SUPPORT_RX_FLOW_TAG) +#include "dp_rx_tag.h" +#endif -#if defined(WLAN_SUPPORT_RX_TAG_STATISTICS) && \ - defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG) -/** - * dp_rx_update_rx_err_protocol_tag_stats() - Increments the protocol tag stats - * for the given protocol type - * received from exception ring - * @soc: core txrx main context - * @pdev: TXRX pdev context for which stats should be incremented - * @protocol_index: Protocol index for which the stats should be incremented - * - * In HKv2, all exception packets are received on Ring-0 (along with normal - * Rx). Hence tags are maintained separately for exception ring as well. - * - * Return: void - */ -static inline -void dp_rx_update_rx_err_protocol_tag_stats(struct dp_pdev *pdev, - uint16_t protocol_index) -{ - pdev->rx_err_proto_tag_stats[protocol_index].tag_ctr++; -} -#else -static inline -void dp_rx_update_rx_err_protocol_tag_stats(struct dp_pdev *pdev, - uint16_t protocol_index) -{ -} -#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */ +#ifndef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG /** * dp_rx_update_protocol_tag() - Reads CCE metadata from the RX MSDU end TLV * and set the corresponding tag in QDF packet @@ -1118,159 +1089,53 @@ void dp_rx_update_rx_err_protocol_tag_stats(struct dp_pdev *pdev, * @is_update_stats: flag to indicate whether to update stats or not * Return: void */ -#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG static inline void dp_rx_update_protocol_tag(struct dp_soc *soc, struct dp_vdev *vdev, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, uint16_t ring_index, bool is_reo_exception, bool is_update_stats) { - uint16_t cce_metadata = RX_PROTOCOL_TAG_START_OFFSET; - bool cce_match = false; - struct dp_pdev *pdev; - uint16_t protocol_tag = 0; - - if (qdf_unlikely(!vdev)) - return; - - pdev = vdev->pdev; - - if (qdf_likely(!pdev->is_rx_protocol_tagging_enabled)) - return; - - /* - * In case of raw frames, rx_attention and rx_msdu_end tlv - * may be stale or invalid. Do not tag such frames. - * Default decap_type is set to ethernet for monitor vdev, - * therefore, cannot check decap_type for monitor mode. - * We will call this only for eth frames from dp_rx_mon_dest.c. - */ - if (qdf_likely(!(pdev->monitor_vdev && pdev->monitor_vdev == vdev) && - (vdev->rx_decap_type != htt_cmn_pkt_type_ethernet))) - return; - - /* - * Check whether HW has filled in the CCE metadata in - * this packet, if not filled, just return - */ - if (qdf_likely(!hal_rx_msdu_cce_match_get(rx_tlv_hdr))) - return; - - cce_match = true; - /* Get the cce_metadata from RX MSDU TLV */ - cce_metadata = (hal_rx_msdu_cce_metadata_get(rx_tlv_hdr) & - RX_MSDU_END_16_CCE_METADATA_MASK); - /* - * Received CCE metadata should be within the - * valid limits - */ - qdf_assert_always((cce_metadata >= RX_PROTOCOL_TAG_START_OFFSET) && - (cce_metadata < (RX_PROTOCOL_TAG_START_OFFSET + - RX_PROTOCOL_TAG_MAX))); - - /* - * The CCE metadata received is just the - * packet_type + RX_PROTOCOL_TAG_START_OFFSET - */ - cce_metadata -= RX_PROTOCOL_TAG_START_OFFSET; - - /* - * Update the QDF packet with the user-specified - * tag/metadata by looking up tag value for - * received protocol type. - */ - protocol_tag = pdev->rx_proto_tag_map[cce_metadata].tag; - qdf_nbuf_set_rx_protocol_tag(nbuf, protocol_tag); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW, - "Seq:%u decap:%u CCE Match:%d ProtoID:%u Tag:%u US:%d", - hal_rx_get_rx_sequence(rx_tlv_hdr), - vdev->rx_decap_type, cce_match, cce_metadata, - protocol_tag, is_update_stats); - - if (qdf_likely(!is_update_stats)) - return; - - if (qdf_unlikely(is_reo_exception)) { - dp_rx_update_rx_err_protocol_tag_stats(pdev, - cce_metadata); - } else { - dp_rx_update_rx_protocol_tag_stats(pdev, - cce_metadata, - ring_index); - } - } -#else +#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ + +#ifndef WLAN_SUPPORT_RX_FLOW_TAG +/** + * dp_rx_update_flow_tag() - Reads FSE metadata from the RX MSDU end TLV + * and set the corresponding tag in QDF packet + * @soc: core txrx main context + * @vdev: vdev on which the packet is received + * @nbuf: QDF pkt buffer on which the protocol tag should be set + * @rx_tlv_hdr: base address where the RX TLVs starts + * @is_update_stats: flag to indicate whether to update stats or not + * + * Return: void + */ static inline void -dp_rx_update_protocol_tag(struct dp_soc *soc, struct dp_vdev *vdev, - qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, - uint16_t ring_index, - bool is_reo_exception, bool is_update_stats) +dp_rx_update_flow_tag(struct dp_soc *soc, struct dp_vdev *vdev, + qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, bool update_stats) { - /* Stub API */ } -#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ +#endif /* WLAN_SUPPORT_RX_FLOW_TAG */ +#if !defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG) &&\ + !defined(WLAN_SUPPORT_RX_FLOW_TAG) /** - * dp_rx_mon_update_protocol_tag() - Performs necessary checks for monitor mode - * and then tags appropriate packets + * dp_rx_mon_update_protocol_flow_tag() - Performs necessary checks for monitor + * mode and then tags appropriate packets * @soc: core txrx main context * @vdev: pdev on which packet is received * @msdu: QDF packet buffer on which the protocol tag should be set * @rx_desc: base address where the RX TLVs start * Return: void */ -#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG static inline -void dp_rx_mon_update_protocol_tag(struct dp_soc *soc, struct dp_pdev *dp_pdev, - qdf_nbuf_t msdu, void *rx_desc) +void dp_rx_mon_update_protocol_flow_tag(struct dp_soc *soc, + struct dp_pdev *dp_pdev, + qdf_nbuf_t msdu, void *rx_desc) { - uint32_t msdu_ppdu_id = 0; - struct mon_rx_status *mon_recv_status; - - if (qdf_likely(!dp_pdev->is_rx_protocol_tagging_enabled)) - return; - - if (qdf_likely(!dp_pdev->monitor_vdev)) - return; - - if (qdf_likely(1 != dp_pdev->ppdu_info.rx_status.rxpcu_filter_pass)) - return; - - msdu_ppdu_id = HAL_RX_HW_DESC_GET_PPDUID_GET(rx_desc); - - if (msdu_ppdu_id != dp_pdev->ppdu_info.com_info.ppdu_id) { - QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_ERROR, - "msdu_ppdu_id=%x,com_info.ppdu_id=%x", - msdu_ppdu_id, - dp_pdev->ppdu_info.com_info.ppdu_id); - return; - } - - /* - * Update the protocol tag in SKB for packets received on BSS. - * Do not update tag stats since it would double actual received count - */ - mon_recv_status = &dp_pdev->ppdu_info.rx_status; - if (mon_recv_status->frame_control_info_valid && - ((mon_recv_status->frame_control & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_DATA)) { - dp_rx_update_protocol_tag(soc, - dp_pdev->monitor_vdev, - msdu, rx_desc, - MAX_REO_DEST_RINGS, - false, false); - } } -#else -static inline -void dp_rx_mon_update_protocol_tag(struct dp_soc *soc, struct dp_pdev *dp_pdev, - qdf_nbuf_t msdu, void *rx_desc) -{ - /* Stub API */ -} -#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ +#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG || WLAN_SUPPORT_RX_FLOW_TAG */ + /* * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs * called during dp rx initialization @@ -1296,6 +1161,24 @@ QDF_STATUS __dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, union dp_rx_desc_list_elem_t **tail, const char *func_name); +/* + * dp_pdev_rx_buffers_attach() - replenish rxdma ring with rx nbufs + * called during dp rx initialization + * + * @soc: core txrx main context + * @mac_id: mac_id which is one of 3 mac_ids + * @dp_rxdma_srng: dp rxdma circular ring + * @rx_desc_pool: Pointer to free Rx descriptor pool + * @num_req_buffers: number of buffer to be replenished + * + * Return: return success or failure + */ +QDF_STATUS +dp_pdev_rx_buffers_attach(struct dp_soc *dp_soc, uint32_t mac_id, + struct dp_srng *dp_rxdma_srng, + struct rx_desc_pool *rx_desc_pool, + uint32_t num_req_buffers); + /** * dp_rx_link_desc_return() - Return a MPDU link descriptor to HW * (WBM), following error handling @@ -1304,14 +1187,13 @@ QDF_STATUS __dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, * @buf_addr_info: opaque pointer to the REO error ring descriptor * @buf_addr_info: void pointer to the buffer_addr_info * @bm_action: put to idle_list or release to msdu_list - * Return: QDF_STATUS + * + * Return: QDF_STATUS_E_FAILURE for failure else QDF_STATUS_SUCCESS */ QDF_STATUS -dp_rx_link_desc_return(struct dp_soc *soc, void *ring_desc, uint8_t bm_action); +dp_rx_link_desc_return(struct dp_soc *soc, hal_ring_desc_t ring_desc, + uint8_t bm_action); -QDF_STATUS -dp_rx_link_desc_buf_return(struct dp_soc *soc, struct dp_srng *dp_rxdma_srng, - void *buf_addr_info, uint8_t bm_action); /** * dp_rx_link_desc_return_by_addr - Return a MPDU link descriptor to * (WBM) by address @@ -1319,11 +1201,12 @@ dp_rx_link_desc_buf_return(struct dp_soc *soc, struct dp_srng *dp_rxdma_srng, * @soc: core DP main context * @link_desc_addr: link descriptor addr * - * Return: QDF_STATUS + * Return: QDF_STATUS_E_FAILURE for failure else QDF_STATUS_SUCCESS */ QDF_STATUS -dp_rx_link_desc_return_by_addr(struct dp_soc *soc, void *link_desc_addr, - uint8_t bm_action); +dp_rx_link_desc_return_by_addr(struct dp_soc *soc, + hal_buff_addrinfo_t link_desc_addr, + uint8_t bm_action); /** * dp_rxdma_err_process() - RxDMA error processing functionality @@ -1359,8 +1242,10 @@ dp_rx_nbuf_prepare(struct dp_soc *soc, struct dp_pdev *pdev); * * Return: void */ -void dp_rx_dump_info_and_assert(struct dp_soc *soc, void *hal_ring, - void *ring_desc, struct dp_rx_desc *rx_desc); +void dp_rx_dump_info_and_assert(struct dp_soc *soc, + hal_ring_handle_t hal_ring_hdl, + hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc); void dp_rx_compute_delay(struct dp_vdev *vdev, qdf_nbuf_t nbuf); #ifdef RX_DESC_DEBUG_CHECK @@ -1413,6 +1298,24 @@ void dp_rx_process_rxdma_err(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, struct dp_peer *peer, uint8_t err_code, uint8_t mac_id); +#ifndef QCA_MULTIPASS_SUPPORT +static inline +bool dp_rx_multipass_process(struct dp_peer *peer, qdf_nbuf_t nbuf, uint8_t tid) +{ + return false; +} +#else +bool dp_rx_multipass_process(struct dp_peer *peer, qdf_nbuf_t nbuf, + uint8_t tid); +#endif + +#ifndef WLAN_RX_PKT_CAPTURE_ENH +static inline +void dp_peer_set_rx_capture_enabled(struct dp_peer *peer_handle, bool value) +{ +} +#endif + /** * dp_rx_deliver_to_stack() - deliver pkts to network stack * Caller to hold peer refcount and check for valid peer @@ -1430,4 +1333,17 @@ void dp_rx_deliver_to_stack(struct dp_soc *soc, qdf_nbuf_t nbuf_head, qdf_nbuf_t nbuf_tail); +/* + * dp_rx_link_desc_refill_duplicate_check() - check if link desc duplicate + to refill + * @soc: DP SOC handle + * @buf_info: the last link desc buf info + * @ring_buf_info: current buf address pointor including link desc + * + * return: none. + */ +void dp_rx_link_desc_refill_duplicate_check( + struct dp_soc *soc, + struct hal_buf_info *buf_info, + hal_buff_addrinfo_t ring_buf_info); #endif /* _DP_RX_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.c index 2b1d1e04b2a4f92ad114afbcc7a8d3140676a603..e807a6d00ee3bba9df329ac94fac0acabb8b3f3e 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -96,13 +96,15 @@ static void dp_rx_return_head_frag_desc(struct dp_peer *peer, struct rx_desc_pool *rx_desc_pool; union dp_rx_desc_list_elem_t *head = NULL; union dp_rx_desc_list_elem_t *tail = NULL; + uint8_t pool_id; pdev = peer->vdev->pdev; soc = pdev->soc; if (peer->rx_tid[tid].head_frag_desc) { - dp_rxdma_srng = &pdev->rx_refill_buf_ring; - rx_desc_pool = &soc->rx_desc_buf[pdev->pdev_id]; + pool_id = peer->rx_tid[tid].head_frag_desc->pool_id; + dp_rxdma_srng = &soc->rx_refill_buf_ring[pool_id]; + rx_desc_pool = &soc->rx_desc_buf[pool_id]; dp_rx_add_to_free_desc_list(&head, &tail, peer->rx_tid[tid].head_frag_desc); @@ -132,8 +134,7 @@ static void dp_rx_return_head_frag_desc(struct dp_peer *peer, void dp_rx_reorder_flush_frag(struct dp_peer *peer, unsigned int tid) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, - FL("Flushing TID %d"), tid); + dp_info_rl("Flushing TID %d", tid); if (!peer) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -237,8 +238,8 @@ static void dp_rx_defrag_waitlist_add(struct dp_peer *peer, unsigned tid) struct dp_soc *psoc = peer->vdev->pdev->soc; struct dp_rx_tid *rx_reorder = &peer->rx_tid[tid]; - dp_debug("Adding TID %u to waitlist for peer %pK at MAC address %pM", - tid, peer, peer->mac_addr.raw); + dp_debug("Adding TID %u to waitlist for peer %pK at MAC address "QDF_MAC_ADDR_FMT, + tid, peer, QDF_MAC_ADDR_REF(peer->mac_addr.raw)); /* TODO: use LIST macros instead of TAIL macros */ qdf_spin_lock_bh(&psoc->rx.defrag.defrag_lock); @@ -266,8 +267,8 @@ void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid) struct dp_rx_tid *rx_reorder; struct dp_rx_tid *tmp; - dp_debug("Removing TID %u to waitlist for peer %pK at MAC address %pM", - tid, peer, peer->mac_addr.raw); + dp_debug("Removing TID %u to waitlist for peer %pK at MAC address "QDF_MAC_ADDR_FMT, + tid, peer, QDF_MAC_ADDR_REF(peer->mac_addr.raw)); if (tid >= DP_MAX_TIDS) { dp_err("TID out of bounds: %d", tid); @@ -328,6 +329,7 @@ static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned ti rx_desc_info = qdf_nbuf_data(frag); cur_fragno = dp_rx_frag_get_mpdu_frag_number(rx_desc_info); + dp_debug("cur_fragno %d\n", cur_fragno); /* If this is the first fragment */ if (!(*head_addr)) { *head_addr = *tail_addr = frag; @@ -360,10 +362,12 @@ static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned ti while ((cur_fragno > head_fragno) && cur) { prev = cur; cur = qdf_nbuf_next(cur); - rx_desc_info = qdf_nbuf_data(cur); - head_fragno = - dp_rx_frag_get_mpdu_frag_number( + if (cur) { + rx_desc_info = qdf_nbuf_data(cur); + head_fragno = + dp_rx_frag_get_mpdu_frag_number( rx_desc_info); + } } if (cur_fragno == head_fragno) { @@ -399,6 +403,8 @@ static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned ti if (!next) { *all_frag_present = 1; return QDF_STATUS_SUCCESS; + } else { + /* revisit */ } } @@ -422,7 +428,7 @@ static QDF_STATUS dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned ti static QDF_STATUS dp_rx_defrag_tkip_decap(qdf_nbuf_t msdu, uint16_t hdrlen) { uint8_t *ivp, *orig_hdr; - int rx_desc_len = sizeof(struct rx_pkt_tlvs); + int rx_desc_len = SIZE_OF_DATA_RX_TLV; /* start of 802.11 header info */ orig_hdr = (uint8_t *)(qdf_nbuf_data(msdu) + rx_desc_len); @@ -452,7 +458,7 @@ static QDF_STATUS dp_rx_defrag_tkip_decap(qdf_nbuf_t msdu, uint16_t hdrlen) static QDF_STATUS dp_rx_defrag_ccmp_demic(qdf_nbuf_t nbuf, uint16_t hdrlen) { uint8_t *ivp, *orig_hdr; - int rx_desc_len = sizeof(struct rx_pkt_tlvs); + int rx_desc_len = SIZE_OF_DATA_RX_TLV; /* start of the 802.11 header */ orig_hdr = (uint8_t *)(qdf_nbuf_data(nbuf) + rx_desc_len); @@ -479,7 +485,7 @@ static QDF_STATUS dp_rx_defrag_ccmp_demic(qdf_nbuf_t nbuf, uint16_t hdrlen) static QDF_STATUS dp_rx_defrag_ccmp_decap(qdf_nbuf_t nbuf, uint16_t hdrlen) { uint8_t *ivp, *origHdr; - int rx_desc_len = sizeof(struct rx_pkt_tlvs); + int rx_desc_len = SIZE_OF_DATA_RX_TLV; origHdr = (uint8_t *) (qdf_nbuf_data(nbuf) + rx_desc_len); ivp = origHdr + hdrlen; @@ -504,7 +510,7 @@ static QDF_STATUS dp_rx_defrag_ccmp_decap(qdf_nbuf_t nbuf, uint16_t hdrlen) static QDF_STATUS dp_rx_defrag_wep_decap(qdf_nbuf_t msdu, uint16_t hdrlen) { uint8_t *origHdr; - int rx_desc_len = sizeof(struct rx_pkt_tlvs); + int rx_desc_len = SIZE_OF_DATA_RX_TLV; origHdr = (uint8_t *) (qdf_nbuf_data(msdu) + rx_desc_len); qdf_mem_move(origHdr + dp_f_wep.ic_header, origHdr, hdrlen); @@ -516,13 +522,14 @@ static QDF_STATUS dp_rx_defrag_wep_decap(qdf_nbuf_t msdu, uint16_t hdrlen) /* * dp_rx_defrag_hdrsize(): Calculate the header size of the received fragment + * @soc: soc handle * @nbuf: Pointer to the fragment * * Calculate the header size of the received fragment * * Returns: header size (uint16_t) */ -static uint16_t dp_rx_defrag_hdrsize(qdf_nbuf_t nbuf) +static uint16_t dp_rx_defrag_hdrsize(struct dp_soc *soc, qdf_nbuf_t nbuf) { uint8_t *rx_tlv_hdr = qdf_nbuf_data(nbuf); uint16_t size = sizeof(struct ieee80211_frame); @@ -531,9 +538,11 @@ static uint16_t dp_rx_defrag_hdrsize(qdf_nbuf_t nbuf) uint8_t frm_ctrl_valid; uint16_t frm_ctrl_field; - to_ds = hal_rx_mpdu_get_to_ds(rx_tlv_hdr); - fr_ds = hal_rx_mpdu_get_fr_ds(rx_tlv_hdr); - frm_ctrl_valid = hal_rx_get_mpdu_frame_control_valid(rx_tlv_hdr); + to_ds = hal_rx_mpdu_get_to_ds(soc->hal_soc, rx_tlv_hdr); + fr_ds = hal_rx_mpdu_get_fr_ds(soc->hal_soc, rx_tlv_hdr); + frm_ctrl_valid = + hal_rx_get_mpdu_frame_control_valid(soc->hal_soc, + rx_tlv_hdr); frm_ctrl_field = hal_rx_get_frame_ctrl_field(rx_tlv_hdr); if (to_ds && fr_ds) @@ -634,7 +643,7 @@ static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf, uint32_t l, r; const uint8_t *data; uint32_t space; - int rx_desc_len = sizeof(struct rx_pkt_tlvs); + int rx_desc_len = SIZE_OF_DATA_RX_TLV; dp_rx_defrag_michdr((struct ieee80211_frame *)(qdf_nbuf_data(wbuf) + rx_desc_len), hdr); @@ -802,14 +811,55 @@ static QDF_STATUS dp_rx_defrag_tkip_demic(const uint8_t *key, */ static void dp_rx_frag_pull_hdr(qdf_nbuf_t nbuf, uint16_t hdrsize) { - qdf_nbuf_pull_head(nbuf, - RX_PKT_TLVS_LEN + hdrsize); + struct rx_pkt_tlvs *rx_pkt_tlv = + (struct rx_pkt_tlvs *)qdf_nbuf_data(nbuf); + struct rx_mpdu_info *rx_mpdu_info_details = + &rx_pkt_tlv->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + + dp_debug("pn_31_0 0x%x pn_63_32 0x%x pn_95_64 0x%x pn_127_96 0x%x\n", + rx_mpdu_info_details->pn_31_0, rx_mpdu_info_details->pn_63_32, + rx_mpdu_info_details->pn_95_64, + rx_mpdu_info_details->pn_127_96); + + qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN + hdrsize); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "%s: final pktlen %d .11len %d", __func__, (uint32_t)qdf_nbuf_len(nbuf), hdrsize); } +/* + * dp_rx_defrag_pn_check(): Check the PN of current fragmented with prev PN + * @msdu: msdu to get the current PN + * @cur_pn128: PN extracted from current msdu + * @prev_pn128: Prev PN + * + * Returns: 0 on success, non zero on failure + */ +static int dp_rx_defrag_pn_check(qdf_nbuf_t msdu, + uint64_t *cur_pn128, uint64_t *prev_pn128) +{ + struct rx_pkt_tlvs *rx_pkt_tlv = + (struct rx_pkt_tlvs *)qdf_nbuf_data(msdu); + struct rx_mpdu_info *rx_mpdu_info_details = + &rx_pkt_tlv->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + int out_of_order = 0; + + cur_pn128[0] = rx_mpdu_info_details->pn_31_0; + cur_pn128[0] |= + ((uint64_t)rx_mpdu_info_details->pn_63_32 << 32); + cur_pn128[1] = rx_mpdu_info_details->pn_95_64; + cur_pn128[1] |= + ((uint64_t)rx_mpdu_info_details->pn_127_96 << 32); + + if (cur_pn128[1] == prev_pn128[1]) + out_of_order = (cur_pn128[0] - prev_pn128[0] != 1); + else + out_of_order = (cur_pn128[1] - prev_pn128[1] != 1); + + return out_of_order; +} + /* * dp_rx_construct_fraglist(): Construct a nbuf fraglist * @peer: Pointer to the peer @@ -820,15 +870,53 @@ static void dp_rx_frag_pull_hdr(qdf_nbuf_t nbuf, uint16_t hdrsize) * * Returns: None */ -static void -dp_rx_construct_fraglist(struct dp_peer *peer, - qdf_nbuf_t head, uint16_t hdrsize) +static int +dp_rx_construct_fraglist(struct dp_peer *peer, int tid, qdf_nbuf_t head, + uint16_t hdrsize) { qdf_nbuf_t msdu = qdf_nbuf_next(head); qdf_nbuf_t rx_nbuf = msdu; + struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; uint32_t len = 0; + uint64_t cur_pn128[2] = {0, 0}, prev_pn128[2]; + int out_of_order = 0; + int index; + int needs_pn_check = 0; + + prev_pn128[0] = rx_tid->pn128[0]; + prev_pn128[1] = rx_tid->pn128[1]; + + index = hal_rx_msdu_is_wlan_mcast(msdu) ? dp_sec_mcast : dp_sec_ucast; + if (qdf_likely(peer->security[index].sec_type != cdp_sec_type_none)) + needs_pn_check = 1; while (msdu) { + if (qdf_likely(needs_pn_check)) + out_of_order = dp_rx_defrag_pn_check(msdu, + &cur_pn128[0], + &prev_pn128[0]); + + if (qdf_unlikely(out_of_order)) { + dp_info_rl("cur_pn128[0] 0x%llx cur_pn128[1] 0x%llx prev_pn128[0] 0x%llx prev_pn128[1] 0x%llx", + cur_pn128[0], cur_pn128[1], + prev_pn128[0], prev_pn128[1]); + return QDF_STATUS_E_FAILURE; + } + + prev_pn128[0] = cur_pn128[0]; + prev_pn128[1] = cur_pn128[1]; + + /* + * Broadcast and multicast frames should never be fragmented. + * Iterating through all msdus and dropping fragments if even + * one of them has mcast/bcast destination address. + */ + if (hal_rx_msdu_is_wlan_mcast(msdu)) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "Dropping multicast/broadcast fragments"); + return QDF_STATUS_E_FAILURE; + } + dp_rx_frag_pull_hdr(msdu, hdrsize); len += qdf_nbuf_len(msdu); msdu = qdf_nbuf_next(msdu); @@ -844,6 +932,8 @@ dp_rx_construct_fraglist(struct dp_peer *peer, (uint32_t)qdf_nbuf_len(head), (uint32_t)qdf_nbuf_len(rx_nbuf), (uint32_t)(head->data_len)); + + return QDF_STATUS_SUCCESS; } /** @@ -866,21 +956,36 @@ static void dp_rx_defrag_err(struct dp_vdev *vdev, qdf_nbuf_t nbuf) { struct ol_if_ops *tops = NULL; struct dp_pdev *pdev = vdev->pdev; - int rx_desc_len = sizeof(struct rx_pkt_tlvs); + int rx_desc_len = SIZE_OF_DATA_RX_TLV; uint8_t *orig_hdr; struct ieee80211_frame *wh; + struct cdp_rx_mic_err_info mic_failure_info; orig_hdr = (uint8_t *)(qdf_nbuf_data(nbuf) + rx_desc_len); wh = (struct ieee80211_frame *)orig_hdr; + qdf_copy_macaddr((struct qdf_mac_addr *)&mic_failure_info.da_mac_addr, + (struct qdf_mac_addr *)&wh->i_addr1); + qdf_copy_macaddr((struct qdf_mac_addr *)&mic_failure_info.ta_mac_addr, + (struct qdf_mac_addr *)&wh->i_addr2); + mic_failure_info.key_id = 0; + mic_failure_info.multicast = + IEEE80211_IS_MULTICAST(wh->i_addr1); + qdf_mem_zero(mic_failure_info.tsc, MIC_SEQ_CTR_SIZE); + mic_failure_info.frame_type = cdp_rx_frame_type_802_11; + mic_failure_info.data = (uint8_t *)wh; + mic_failure_info.vdev_id = vdev->vdev_id; + tops = pdev->soc->cdp_soc.ol_ops; if (tops->rx_mic_error) - tops->rx_mic_error(pdev->ctrl_pdev, vdev->vdev_id, wh); + tops->rx_mic_error(pdev->soc->ctrl_psoc, pdev->pdev_id, + &mic_failure_info); } /* * dp_rx_defrag_nwifi_to_8023(): Transcap 802.11 to 802.3 + * @soc: dp soc handle * @nbuf: Pointer to the fragment buffer * @hdrsize: Size of headers * @@ -889,7 +994,8 @@ static void dp_rx_defrag_err(struct dp_vdev *vdev, qdf_nbuf_t nbuf) * Returns: None */ static void -dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf, uint16_t hdrsize) +dp_rx_defrag_nwifi_to_8023(struct dp_soc *soc, struct dp_peer *peer, int tid, + qdf_nbuf_t nbuf, uint16_t hdrsize) { struct llc_snap_hdr_t *llchdr; struct ethernet_hdr_t *eth_hdr; @@ -897,6 +1003,21 @@ dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf, uint16_t hdrsize) uint16_t fc = 0; union dp_align_mac_addr mac_addr; uint8_t *rx_desc_info = qdf_mem_malloc(RX_PKT_TLVS_LEN); + struct rx_pkt_tlvs *rx_pkt_tlv = + (struct rx_pkt_tlvs *)qdf_nbuf_data(nbuf); + struct rx_mpdu_info *rx_mpdu_info_details = + &rx_pkt_tlv->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; + + dp_debug("head_nbuf pn_31_0 0x%x pn_63_32 0x%x pn_95_64 0x%x pn_127_96 0x%x\n", + rx_mpdu_info_details->pn_31_0, rx_mpdu_info_details->pn_63_32, + rx_mpdu_info_details->pn_95_64, + rx_mpdu_info_details->pn_127_96); + + rx_tid->pn128[0] = rx_mpdu_info_details->pn_31_0; + rx_tid->pn128[0] |= ((uint64_t)rx_mpdu_info_details->pn_63_32 << 32); + rx_tid->pn128[1] = rx_mpdu_info_details->pn_95_64; + rx_tid->pn128[1] |= ((uint64_t)rx_mpdu_info_details->pn_127_96 << 32); if (!rx_desc_info) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -917,50 +1038,51 @@ dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf, uint16_t hdrsize) eth_hdr = (struct ethernet_hdr_t *)(qdf_nbuf_data(nbuf)); - if (hal_rx_get_mpdu_frame_control_valid(rx_desc_info)) + if (hal_rx_get_mpdu_frame_control_valid(soc->hal_soc, + rx_desc_info)) fc = hal_rx_get_frame_ctrl_field(rx_desc_info); dp_debug("%s: frame control type: 0x%x", __func__, fc); switch (((fc & 0xff00) >> 8) & IEEE80211_FC1_DIR_MASK) { case IEEE80211_FC1_DIR_NODS: - hal_rx_mpdu_get_addr1(rx_desc_info, - &mac_addr.raw[0]); + hal_rx_mpdu_get_addr1(soc->hal_soc, rx_desc_info, + &mac_addr.raw[0]); qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0], QDF_MAC_ADDR_SIZE); - hal_rx_mpdu_get_addr2(rx_desc_info, - &mac_addr.raw[0]); + hal_rx_mpdu_get_addr2(soc->hal_soc, rx_desc_info, + &mac_addr.raw[0]); qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0], QDF_MAC_ADDR_SIZE); break; case IEEE80211_FC1_DIR_TODS: - hal_rx_mpdu_get_addr3(rx_desc_info, - &mac_addr.raw[0]); + hal_rx_mpdu_get_addr3(soc->hal_soc, rx_desc_info, + &mac_addr.raw[0]); qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0], QDF_MAC_ADDR_SIZE); - hal_rx_mpdu_get_addr2(rx_desc_info, - &mac_addr.raw[0]); + hal_rx_mpdu_get_addr2(soc->hal_soc, rx_desc_info, + &mac_addr.raw[0]); qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0], QDF_MAC_ADDR_SIZE); break; case IEEE80211_FC1_DIR_FROMDS: - hal_rx_mpdu_get_addr1(rx_desc_info, - &mac_addr.raw[0]); + hal_rx_mpdu_get_addr1(soc->hal_soc, rx_desc_info, + &mac_addr.raw[0]); qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0], QDF_MAC_ADDR_SIZE); - hal_rx_mpdu_get_addr3(rx_desc_info, - &mac_addr.raw[0]); + hal_rx_mpdu_get_addr3(soc->hal_soc, rx_desc_info, + &mac_addr.raw[0]); qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0], QDF_MAC_ADDR_SIZE); break; case IEEE80211_FC1_DIR_DSTODS: - hal_rx_mpdu_get_addr3(rx_desc_info, - &mac_addr.raw[0]); + hal_rx_mpdu_get_addr3(soc->hal_soc, rx_desc_info, + &mac_addr.raw[0]); qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0], QDF_MAC_ADDR_SIZE); - hal_rx_mpdu_get_addr4(rx_desc_info, - &mac_addr.raw[0]); + hal_rx_mpdu_get_addr4(soc->hal_soc, rx_desc_info, + &mac_addr.raw[0]); qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0], QDF_MAC_ADDR_SIZE); break; @@ -978,6 +1100,102 @@ dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf, uint16_t hdrsize) qdf_mem_free(rx_desc_info); } +#ifdef RX_DEFRAG_DO_NOT_REINJECT +/* + * dp_rx_defrag_deliver(): Deliver defrag packet to stack + * @peer: Pointer to the peer + * @tid: Transmit Identifier + * @head: Nbuf to be delivered + * + * Returns: None + */ +static inline void dp_rx_defrag_deliver(struct dp_peer *peer, + unsigned int tid, + qdf_nbuf_t head) +{ + struct dp_vdev *vdev = peer->vdev; + struct dp_soc *soc = vdev->pdev->soc; + qdf_nbuf_t deliver_list_head = NULL; + qdf_nbuf_t deliver_list_tail = NULL; + uint8_t *rx_tlv_hdr; + + rx_tlv_hdr = qdf_nbuf_data(head); + + QDF_NBUF_CB_RX_VDEV_ID(head) = vdev->vdev_id; + qdf_nbuf_set_tid_val(head, tid); + qdf_nbuf_pull_head(head, RX_PKT_TLVS_LEN); + + DP_RX_LIST_APPEND(deliver_list_head, deliver_list_tail, + head); + dp_rx_deliver_to_stack(soc, vdev, peer, deliver_list_head, + deliver_list_tail); +} + +/* + * dp_rx_defrag_reo_reinject(): Reinject the fragment chain back into REO + * @peer: Pointer to the peer + * @tid: Transmit Identifier + * @head: Buffer to be reinjected back + * + * Reinject the fragment chain back into REO + * + * Returns: QDF_STATUS + */ +static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer, + unsigned int tid, qdf_nbuf_t head) +{ + struct dp_rx_reorder_array_elem *rx_reorder_array_elem; + + rx_reorder_array_elem = peer->rx_tid[tid].array; + + dp_rx_defrag_deliver(peer, tid, head); + rx_reorder_array_elem->head = NULL; + rx_reorder_array_elem->tail = NULL; + dp_rx_return_head_frag_desc(peer, tid); + + return QDF_STATUS_SUCCESS; +} +#else + +#ifdef WLAN_FEATURE_DP_RX_RING_HISTORY +/** + * dp_rx_reinject_ring_record_entry() - Record reinject ring history + * @soc: Datapath soc structure + * @paddr: paddr of the buffer reinjected to SW2REO ring + * @sw_cookie: SW cookie of the buffer reinjected to SW2REO ring + * @rbm: Return buffer manager of the buffer reinjected to SW2REO ring + * + * Returns: None + */ +static inline void +dp_rx_reinject_ring_record_entry(struct dp_soc *soc, uint64_t paddr, + uint32_t sw_cookie, uint8_t rbm) +{ + struct dp_buf_info_record *record; + uint32_t idx; + + if (qdf_unlikely(!soc->rx_reinject_ring_history)) + return; + + idx = dp_history_get_next_index(&soc->rx_reinject_ring_history->index, + DP_RX_REINJECT_HIST_MAX); + + /* No NULL check needed for record since its an array */ + record = &soc->rx_reinject_ring_history->entry[idx]; + + record->timestamp = qdf_get_log_timestamp(); + record->hbi.paddr = paddr; + record->hbi.sw_cookie = sw_cookie; + record->hbi.rbm = rbm; +} +#else +static inline void +dp_rx_reinject_ring_record_entry(struct dp_soc *soc, uint64_t paddr, + uint32_t sw_cookie, uint8_t rbm) +{ +} +#endif + /* * dp_rx_defrag_reo_reinject(): Reinject the fragment chain back into REO * @peer: Pointer to the peer @@ -1002,14 +1220,21 @@ static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer, uint32_t nbuf_len, seq_no, dst_ind; uint32_t *mpdu_wrd; uint32_t ret, cookie; - - void *dst_ring_desc = + hal_ring_desc_t dst_ring_desc = peer->rx_tid[tid].dst_ring_desc; - void *hal_srng = soc->reo_reinject_ring.hal_srng; + hal_ring_handle_t hal_srng = soc->reo_reinject_ring.hal_srng; struct dp_rx_desc *rx_desc = peer->rx_tid[tid].head_frag_desc; struct dp_rx_reorder_array_elem *rx_reorder_array_elem = peer->rx_tid[tid].array; qdf_nbuf_t nbuf_head; + struct rx_desc_pool *rx_desc_pool = NULL; + void *buf_addr_info = HAL_RX_REO_BUF_ADDR_INFO_GET(dst_ring_desc); + + /* do duplicate link desc address check */ + dp_rx_link_desc_refill_duplicate_check( + soc, + &soc->last_op_info.reo_reinject_link_desc, + buf_addr_info); nbuf_head = dp_ipa_handle_rx_reo_reinject(soc, head); if (qdf_unlikely(!nbuf_head)) { @@ -1026,8 +1251,7 @@ static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer, ent_ring_desc = hal_srng_src_get_next(soc->hal_soc, hal_srng); if (!ent_ring_desc) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "HAL src ring next entry NULL"); + dp_err_rl("HAL src ring next entry NULL"); return QDF_STATUS_E_FAILURE; } @@ -1035,11 +1259,9 @@ static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer, link_desc_va = dp_rx_cookie_2_link_desc_va(soc, &buf_info); - qdf_assert(link_desc_va); - - msdu0 = (uint8_t *)link_desc_va + - RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET; + qdf_assert_always(link_desc_va); + msdu0 = hal_rx_msdu0_buffer_addr_lsb(soc->hal_soc, link_desc_va); nbuf_len = qdf_nbuf_len(head) - RX_PKT_TLVS_LEN; HAL_RX_UNIFORM_HDR_SET(link_desc_va, OWNER, UNI_DESC_OWNER_SW); @@ -1047,8 +1269,7 @@ static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer, UNI_DESC_BUF_TYPE_RX_MSDU_LINK); /* msdu reconfig */ - msdu_desc_info = (uint8_t *)msdu0 + - RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET; + msdu_desc_info = hal_rx_msdu_desc_info_ptr_get(soc->hal_soc, msdu0); dst_ind = hal_rx_msdu_reo_dst_ind_get(soc->hal_soc, link_desc_va); @@ -1094,8 +1315,9 @@ static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer, dp_ipa_handle_rx_buf_smmu_mapping(soc, head, true); paddr = qdf_nbuf_get_frag_paddr(head, 0); + rx_desc_pool = &soc->rx_desc_buf[pdev->lmac_id]; - ret = check_x86_paddr(soc, &head, &paddr, pdev); + ret = check_x86_paddr(soc, &head, &paddr, rx_desc_pool); if (ret == QDF_STATUS_E_FAILURE) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -1114,17 +1336,17 @@ static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer, return QDF_STATUS_E_FAILURE; } + dp_rx_reinject_ring_record_entry(soc, paddr, cookie, DP_DEFRAG_RBM); paddr = (uint64_t)buf_info.paddr; /* buf addr */ hal_rxdma_buff_addr_info_set(ent_ring_desc, paddr, buf_info.sw_cookie, HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST); /* mpdu desc info */ - ent_mpdu_desc_info = (uint8_t *)ent_ring_desc + - RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET; - - dst_mpdu_desc_info = (uint8_t *)dst_ring_desc + - REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET; + ent_mpdu_desc_info = hal_ent_mpdu_desc_info(soc->hal_soc, + ent_ring_desc); + dst_mpdu_desc_info = hal_dst_mpdu_desc_info(soc->hal_soc, + dst_ring_desc); qdf_mem_copy(ent_mpdu_desc_info, dst_mpdu_desc_info, sizeof(struct rx_mpdu_desc_info)); @@ -1167,6 +1389,7 @@ static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer, "%s: reinjection done !", __func__); return QDF_STATUS_SUCCESS; } +#endif /* * dp_rx_defrag(): Defragment the fragment chain @@ -1191,7 +1414,7 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, struct dp_soc *soc = vdev->pdev->soc; uint8_t status = 0; - hdr_space = dp_rx_defrag_hdrsize(cur); + hdr_space = dp_rx_defrag_hdrsize(soc, cur); index = hal_rx_msdu_is_wlan_mcast(cur) ? dp_sec_mcast : dp_sec_ucast; @@ -1278,41 +1501,34 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, hdr_space += dp_f_wep.ic_header; break; default: - QDF_TRACE(QDF_MODULE_ID_TXRX, - QDF_TRACE_LEVEL_ERROR, - "dp_rx_defrag: Did not match any security type"); break; } if (tkip_demic) { msdu = frag_list_head; - if (soc->cdp_soc.ol_ops->rx_frag_tkip_demic) { - status = soc->cdp_soc.ol_ops->rx_frag_tkip_demic( - (void *)peer->ctrl_peer, msdu, hdr_space); - } else { - qdf_mem_copy(key, - &peer->security[index].michael_key[0], - IEEE80211_WEP_MICLEN); - status = dp_rx_defrag_tkip_demic(key, msdu, - RX_PKT_TLVS_LEN + - hdr_space); + qdf_mem_copy(key, + &peer->security[index].michael_key[0], + IEEE80211_WEP_MICLEN); + status = dp_rx_defrag_tkip_demic(key, msdu, + RX_PKT_TLVS_LEN + + hdr_space); - if (status) { - dp_rx_defrag_err(vdev, frag_list_head); + if (status) { + dp_rx_defrag_err(vdev, frag_list_head); - QDF_TRACE(QDF_MODULE_ID_TXRX, - QDF_TRACE_LEVEL_ERROR, - "%s: TKIP demic failed status %d", - __func__, status); + QDF_TRACE(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_ERROR, + "%s: TKIP demic failed status %d", + __func__, status); - return QDF_STATUS_E_DEFRAG_ERROR; - } + return QDF_STATUS_E_DEFRAG_ERROR; } } /* Convert the header to 802.3 header */ - dp_rx_defrag_nwifi_to_8023(frag_list_head, hdr_space); - dp_rx_construct_fraglist(peer, frag_list_head, hdr_space); + dp_rx_defrag_nwifi_to_8023(soc, peer, tid, frag_list_head, hdr_space); + if (dp_rx_construct_fraglist(peer, tid, frag_list_head, hdr_space)) + return QDF_STATUS_E_DEFRAG_ERROR; return QDF_STATUS_SUCCESS; } @@ -1335,8 +1551,8 @@ void dp_rx_defrag_cleanup(struct dp_peer *peer, unsigned tid) rx_reorder_array_elem->head = NULL; rx_reorder_array_elem->tail = NULL; } else { - dp_info("Cleanup self peer %pK and TID %u at MAC address %pM", - peer, tid, peer->mac_addr.raw); + dp_info("Cleanup self peer %pK and TID %u at MAC address "QDF_MAC_ADDR_FMT, + peer, tid, QDF_MAC_ADDR_REF(peer->mac_addr.raw)); } /* Free up saved ring descriptors */ @@ -1355,8 +1571,11 @@ void dp_rx_defrag_cleanup(struct dp_peer *peer, unsigned tid) * * Returns: None */ -static QDF_STATUS dp_rx_defrag_save_info_from_ring_desc(void *ring_desc, - struct dp_rx_desc *rx_desc, struct dp_peer *peer, unsigned tid) +static QDF_STATUS +dp_rx_defrag_save_info_from_ring_desc(hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc, + struct dp_peer *peer, + unsigned int tid) { void *dst_ring_desc = qdf_mem_malloc( sizeof(struct reo_destination_ring)); @@ -1388,13 +1607,14 @@ static QDF_STATUS dp_rx_defrag_save_info_from_ring_desc(void *ring_desc, * * Returns: QDF_STATUS */ -static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, - void *ring_desc, - union dp_rx_desc_list_elem_t **head, - union dp_rx_desc_list_elem_t **tail, - struct hal_rx_mpdu_desc_info *mpdu_desc_info, - unsigned tid, struct dp_rx_desc *rx_desc, - uint32_t *rx_bfs) +static QDF_STATUS +dp_rx_defrag_store_fragment(struct dp_soc *soc, + hal_ring_desc_t ring_desc, + union dp_rx_desc_list_elem_t **head, + union dp_rx_desc_list_elem_t **tail, + struct hal_rx_mpdu_desc_info *mpdu_desc_info, + unsigned int tid, struct dp_rx_desc *rx_desc, + uint32_t *rx_bfs) { struct dp_rx_reorder_array_elem *rx_reorder_array_elem; struct dp_pdev *pdev; @@ -1442,13 +1662,15 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, if (tid >= DP_MAX_TIDS) { dp_info("TID out of bounds: %d", tid); qdf_assert_always(0); + goto discard_frag; } pdev = peer->vdev->pdev; rx_tid = &peer->rx_tid[tid]; mpdu_sequence_control_valid = - hal_rx_get_mpdu_sequence_control_valid(rx_desc->rx_buf_start); + hal_rx_get_mpdu_sequence_control_valid(soc->hal_soc, + rx_desc->rx_buf_start); /* Invalid MPDU sequence control field, MPDU is of no use */ if (!mpdu_sequence_control_valid) { @@ -1460,7 +1682,8 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, } mpdu_frame_control_valid = - hal_rx_get_mpdu_frame_control_valid(rx_desc->rx_buf_start); + hal_rx_get_mpdu_frame_control_valid(soc->hal_soc, + rx_desc->rx_buf_start); /* Invalid frame control field */ if (!mpdu_frame_control_valid) { @@ -1505,21 +1728,21 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, } /* Check if the fragment is for the same sequence or a different one */ + dp_debug("rx_tid %d", tid); if (rx_reorder_array_elem->head) { + dp_debug("rxseq %d\n", rxseq); if (rxseq != rx_tid->curr_seq_num) { + dp_debug("mismatch cur_seq %d rxseq %d\n", + rx_tid->curr_seq_num, rxseq); /* Drop stored fragments if out of sequence * fragment is received */ dp_rx_reorder_flush_frag(peer, tid); - DP_STATS_INC(soc, rx.rx_frag_err, 1); - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "%s mismatch, dropping earlier sequence ", - (rxseq == rx_tid->curr_seq_num) - ? "address" - : "seq number"); + DP_STATS_INC(soc, rx.rx_frag_oor, 1); + dp_debug("cur rxseq %d\n", rxseq); /* * The sequence number for this fragment becomes the * new sequence number to be processed @@ -1527,9 +1750,11 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, rx_tid->curr_seq_num = rxseq; } } else { + dp_debug("cur rxseq %d\n", rxseq); /* Start of a new sequence */ dp_rx_defrag_cleanup(peer, tid); rx_tid->curr_seq_num = rxseq; + /* store PN number also */ } /* @@ -1671,7 +1896,7 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc, * * Return: uint32_t: No. of elements processed */ -uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc, +uint32_t dp_rx_frag_handle(struct dp_soc *soc, hal_ring_desc_t ring_desc, struct hal_rx_mpdu_desc_info *mpdu_desc_info, struct dp_rx_desc *rx_desc, uint8_t *mac_id, @@ -1702,6 +1927,9 @@ uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc, pdev = soc->pdev_list[rx_desc->pool_id]; *mac_id = rx_desc->pool_id; + if (rx_desc->unmapped) + return rx_bufs_used; + msdu = rx_desc->nbuf; dp_ipa_handle_rx_buf_smmu_mapping(soc, msdu, false); @@ -1751,9 +1979,9 @@ QDF_STATUS dp_rx_defrag_add_last_frag(struct dp_soc *soc, */ if (!rx_reorder_array_elem) { dp_verbose_debug( - "peer id:%d mac:" QDF_MAC_ADDR_STR "drop rx frame!", + "peer id:%d mac: "QDF_MAC_ADDR_FMT" drop rx frame!", peer->peer_ids[0], - QDF_MAC_ADDR_ARRAY(peer->mac_addr.raw)); + QDF_MAC_ADDR_REF(peer->mac_addr.raw)); DP_STATS_INC(soc, rx.err.defrag_peer_uninit, 1); qdf_nbuf_free(nbuf); goto fail; diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.h index 0c24f88cf314edd2278562a4846bec9bb290149f..02d2b1df7c480751312a3c94b9acf63164c0da21 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -21,10 +21,6 @@ #include "hal_rx.h" -#ifdef CONFIG_MCL -#include -#endif - #define DEFRAG_IEEE80211_KEY_LEN 8 #define DEFRAG_IEEE80211_FCS_LEN 4 @@ -52,11 +48,11 @@ struct dp_rx_defrag_cipher { uint8_t ic_miclen; }; -uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc, - struct hal_rx_mpdu_desc_info *mpdu_desc_info, - struct dp_rx_desc *rx_desc, - uint8_t *mac_id, - uint32_t quota); +uint32_t dp_rx_frag_handle(struct dp_soc *soc, hal_ring_desc_t ring_desc, + struct hal_rx_mpdu_desc_info *mpdu_desc_info, + struct dp_rx_desc *rx_desc, + uint8_t *mac_id, + uint32_t quota); /* * dp_rx_frag_get_mac_hdr() - Return pointer to the mac hdr @@ -73,7 +69,7 @@ uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc, static inline struct ieee80211_frame *dp_rx_frag_get_mac_hdr(uint8_t *rx_desc_info) { - int rx_desc_len = hal_rx_get_desc_len(); + int rx_desc_len = SIZE_OF_DATA_RX_TLV; return (struct ieee80211_frame *)(rx_desc_info + rx_desc_len); } diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_desc.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_desc.c index 55654b526d391ff2c7762327549ad8b2f15b8792..e80121e85612c0e1079bf22e870514ef88fae4b6 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_desc.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_desc.c @@ -36,8 +36,9 @@ QDF_STATUS dp_rx_desc_pool_alloc(struct dp_soc *soc, uint32_t pool_id, desc_size = sizeof(*rx_desc_elem); rx_desc_pool->elem_size = desc_size; if (!dp_is_soc_reinit(soc)) { - qdf_mem_multi_pages_alloc(soc->osdev, &rx_desc_pool->desc_pages, - desc_size, num_elem, 0, true); + dp_desc_multi_pages_mem_alloc(soc, rx_desc_pool->desc_type, + &rx_desc_pool->desc_pages, + desc_size, num_elem, 0, true); if (!rx_desc_pool->desc_pages.num_pages) { qdf_err("Multi page alloc fail,size=%d, elem=%d", desc_size, num_elem); @@ -163,8 +164,8 @@ void dp_rx_desc_pool_free(struct dp_soc *soc, { if (qdf_unlikely(!(rx_desc_pool->desc_pages.cacheable_pages))) return; - qdf_mem_multi_pages_free(soc->osdev, - &rx_desc_pool->desc_pages, 0, true); + dp_desc_multi_pages_mem_free(soc, rx_desc_pool->desc_type, + &rx_desc_pool->desc_pages, 0, true); } #else QDF_STATUS dp_rx_desc_pool_alloc(struct dp_soc *soc, uint32_t pool_id, @@ -333,6 +334,7 @@ void dp_rx_add_desc_list_to_free_list(struct dp_soc *soc, rx_desc_pool->freelist = *local_desc_list; (*tail)->next = temp_list; *tail = NULL; + *local_desc_list = NULL; qdf_spin_unlock_bh(&rx_desc_pool->lock); } diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_err.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_err.c index 3889a23be360fecff33004fd7c0ec8144ad3c1ea..b9fded46fe9cdd289aabc1b5e19e04c36862889c 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_err.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_err.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -24,9 +25,6 @@ #include "hal_api.h" #include "qdf_trace.h" #include "qdf_nbuf.h" -#ifdef CONFIG_MCL -#include -#endif #include "dp_rx_defrag.h" #include "dp_ipa.h" #ifdef FEATURE_WDS @@ -35,6 +33,9 @@ #include /* LLC_SNAP_HDR_LEN */ #include "qdf_net_types.h" +/* Max buffer in invalid peer SG list*/ +#define DP_MAX_INVALID_BUFFERS 10 + /** * dp_rx_mcast_echo_check() - check if the mcast pkt is a loop * back on same vap or a different vap. @@ -65,7 +66,7 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc, if (vdev->opmode != wlan_op_mode_sta) return false; - if (!hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr)) + if (!hal_rx_msdu_end_da_is_mcbc_get(soc->hal_soc, rx_tlv_hdr)) return false; data = qdf_nbuf_data(nbuf); @@ -93,8 +94,8 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc, * then drop the pkt as it is looped back */ qdf_spin_lock_bh(&soc->ast_lock); - if (hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr)) { - sa_idx = hal_rx_msdu_end_sa_idx_get(rx_tlv_hdr); + if (hal_rx_msdu_end_sa_is_valid_get(soc->hal_soc, rx_tlv_hdr)) { + sa_idx = hal_rx_msdu_end_sa_idx_get(soc->hal_soc, rx_tlv_hdr); if ((sa_idx < 0) || (sa_idx >= wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx))) { @@ -134,8 +135,9 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc, qdf_spin_unlock_bh(&soc->ast_lock); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "Detected DBDC Root AP %pM, %d %d", - &data[QDF_MAC_ADDR_SIZE], vdev->pdev->pdev_id, + "Detected DBDC Root AP "QDF_MAC_ADDR_FMT", %d %d", + QDF_MAC_ADDR_REF(&data[QDF_MAC_ADDR_SIZE]), + vdev->pdev->pdev_id, ase->pdev_id); return false; } @@ -145,8 +147,8 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc, qdf_spin_unlock_bh(&soc->ast_lock); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "received pkt with same src mac %pM", - &data[QDF_MAC_ADDR_SIZE]); + "received pkt with same src mac "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(&data[QDF_MAC_ADDR_SIZE])); return true; } @@ -155,6 +157,26 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc, return false; } +void dp_rx_link_desc_refill_duplicate_check( + struct dp_soc *soc, + struct hal_buf_info *buf_info, + hal_buff_addrinfo_t ring_buf_info) +{ + struct hal_buf_info current_link_desc_buf_info = { 0 }; + + /* do duplicate link desc address check */ + hal_rx_buffer_addr_info_get_paddr(ring_buf_info, + ¤t_link_desc_buf_info); + if (qdf_unlikely(current_link_desc_buf_info.paddr == + buf_info->paddr)) { + dp_info_rl("duplicate link desc addr: %llu, cookie: 0x%x", + current_link_desc_buf_info.paddr, + current_link_desc_buf_info.sw_cookie); + DP_STATS_INC(soc, rx.err.dup_refill_link_desc, 1); + } + *buf_info = current_link_desc_buf_info; +} + /** * dp_rx_link_desc_return_by_addr - Return a MPDU link descriptor to * (WBM) by address @@ -165,12 +187,13 @@ static inline bool dp_rx_mcast_echo_check(struct dp_soc *soc, * Return: QDF_STATUS */ QDF_STATUS -dp_rx_link_desc_return_by_addr(struct dp_soc *soc, void *link_desc_addr, - uint8_t bm_action) +dp_rx_link_desc_return_by_addr(struct dp_soc *soc, + hal_buff_addrinfo_t link_desc_addr, + uint8_t bm_action) { struct dp_srng *wbm_desc_rel_ring = &soc->wbm_desc_rel_ring; - void *wbm_rel_srng = wbm_desc_rel_ring->hal_srng; - void *hal_soc = soc->hal_soc; + hal_ring_handle_t wbm_rel_srng = wbm_desc_rel_ring->hal_srng; + hal_soc_handle_t hal_soc = soc->hal_soc; QDF_STATUS status = QDF_STATUS_E_FAILURE; void *src_srng_desc; @@ -180,6 +203,12 @@ dp_rx_link_desc_return_by_addr(struct dp_soc *soc, void *link_desc_addr, return status; } + /* do duplicate link desc address check */ + dp_rx_link_desc_refill_duplicate_check( + soc, + &soc->last_op_info.wbm_rel_link_desc, + link_desc_addr); + if (qdf_unlikely(hal_srng_access_start(hal_soc, wbm_rel_srng))) { /* TODO */ @@ -230,9 +259,11 @@ dp_rx_link_desc_return_by_addr(struct dp_soc *soc, void *link_desc_addr, * Return: QDF_STATUS */ QDF_STATUS -dp_rx_link_desc_return(struct dp_soc *soc, void *ring_desc, uint8_t bm_action) +dp_rx_link_desc_return(struct dp_soc *soc, hal_ring_desc_t ring_desc, + uint8_t bm_action) { void *buf_addr_info = HAL_RX_REO_BUF_ADDR_INFO_GET(ring_desc); + return dp_rx_link_desc_return_by_addr(soc, buf_addr_info, bm_action); } @@ -250,10 +281,11 @@ dp_rx_link_desc_return(struct dp_soc *soc, void *ring_desc, uint8_t bm_action) * * Return: uint32_t: No. of elements processed */ -static uint32_t dp_rx_msdus_drop(struct dp_soc *soc, void *ring_desc, - struct hal_rx_mpdu_desc_info *mpdu_desc_info, - uint8_t *mac_id, - uint32_t quota) +static uint32_t +dp_rx_msdus_drop(struct dp_soc *soc, hal_ring_desc_t ring_desc, + struct hal_rx_mpdu_desc_info *mpdu_desc_info, + uint8_t *mac_id, + uint32_t quota) { uint32_t rx_bufs_used = 0; void *link_desc_va; @@ -281,7 +313,7 @@ static uint32_t dp_rx_msdus_drop(struct dp_soc *soc, void *ring_desc, /* all buffers from a MSDU link link belong to same pdev */ *mac_id = rx_desc->pool_id; - pdev = soc->pdev_list[rx_desc->pool_id]; + pdev = dp_get_pdev_for_lmac_id(soc, rx_desc->pool_id); if (!dp_rx_desc_check_magic(rx_desc)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -303,8 +335,8 @@ static uint32_t dp_rx_msdus_drop(struct dp_soc *soc, void *ring_desc, "Packet received with PN error for tid :%d", tid); rx_tlv_hdr = qdf_nbuf_data(rx_desc->nbuf); - if (hal_rx_encryption_info_valid(rx_tlv_hdr)) - hal_rx_print_pn(rx_tlv_hdr); + if (hal_rx_encryption_info_valid(soc->hal_soc, rx_tlv_hdr)) + hal_rx_print_pn(soc->hal_soc, rx_tlv_hdr); /* Just free the buffers */ qdf_nbuf_free(rx_desc->nbuf); @@ -338,7 +370,7 @@ static uint32_t dp_rx_msdus_drop(struct dp_soc *soc, void *ring_desc, * Return: uint32_t: No. of elements processed */ static uint32_t -dp_rx_pn_error_handle(struct dp_soc *soc, void *ring_desc, +dp_rx_pn_error_handle(struct dp_soc *soc, hal_ring_desc_t ring_desc, struct hal_rx_mpdu_desc_info *mpdu_desc_info, uint8_t *mac_id, uint32_t quota) @@ -359,12 +391,8 @@ dp_rx_pn_error_handle(struct dp_soc *soc, void *ring_desc, * TODO: Check for peer specific policies & set peer_pn_policy */ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "discard rx due to PN error for peer %pK " - "(%02x:%02x:%02x:%02x:%02x:%02x)", - peer, - peer->mac_addr.raw[0], peer->mac_addr.raw[1], - peer->mac_addr.raw[2], peer->mac_addr.raw[3], - peer->mac_addr.raw[4], peer->mac_addr.raw[5]); + "discard rx due to PN error for peer %pK "QDF_MAC_ADDR_FMT, + peer, QDF_MAC_ADDR_REF(peer->mac_addr.raw)); dp_peer_unref_del_find_by_id(peer); } @@ -479,7 +507,7 @@ dp_rx_reo_err_entry_process(struct dp_soc *soc, qdf_assert_always(rx_desc); /* all buffers from a MSDU link belong to same pdev */ - pdev = soc->pdev_list[rx_desc->pool_id]; + pdev = dp_get_pdev_for_lmac_id(soc, rx_desc->pool_id); nbuf = rx_desc->nbuf; dp_ipa_handle_rx_buf_smmu_mapping(soc, nbuf, false); @@ -501,7 +529,7 @@ dp_rx_reo_err_entry_process(struct dp_soc *soc, rx_tlv_hdr_last = qdf_nbuf_data(tail_nbuf); if (qdf_unlikely(head_nbuf != tail_nbuf)) { - nbuf = dp_rx_sg_create(head_nbuf); + nbuf = dp_rx_sg_create(soc, head_nbuf); qdf_nbuf_set_is_frag(nbuf, 1); DP_STATS_INC(soc, rx.err.reo_err_oor_sg_count, 1); } @@ -512,12 +540,13 @@ dp_rx_reo_err_entry_process(struct dp_soc *soc, * only first msdu, mpdu start description tlv valid? * and use it for following msdu. */ - if (hal_rx_msdu_end_first_msdu_get(rx_tlv_hdr_last)) + if (hal_rx_msdu_end_first_msdu_get(soc->hal_soc, + rx_tlv_hdr_last)) tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, rx_tlv_hdr_first); - dp_2k_jump_handle(soc, nbuf, peer_id, tid, - rx_tlv_hdr_last); + dp_2k_jump_handle(soc, nbuf, rx_tlv_hdr_last, + peer_id, tid); break; case HAL_REO_ERR_REGULAR_FRAME_OOR: @@ -559,12 +588,13 @@ dp_rx_reo_err_entry_process(struct dp_soc *soc, dp_rx_link_desc_return_by_addr(soc, buf_addr_info, HAL_BM_ACTION_PUT_IN_IDLE_LIST); - QDF_BUG(msdu_processed == mpdu_desc_info->msdu_count); + if (qdf_unlikely(msdu_processed != mpdu_desc_info->msdu_count)) + DP_STATS_INC(soc, rx.err.msdu_count_mismatch, 1); return rx_bufs_used; } -#ifdef CONFIG_MCL +#ifdef DP_INVALID_PEER_ASSERT #define DP_PDEV_INVALID_PEER_MSDU_CHECK(head, tail) \ do { \ qdf_assert_always(!(head)); \ @@ -586,8 +616,8 @@ dp_rx_reo_err_entry_process(struct dp_soc *soc, * Return: bool: true for last msdu of mpdu */ static bool -dp_rx_chain_msdus(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, - uint8_t mac_id) +dp_rx_chain_msdus(struct dp_soc *soc, qdf_nbuf_t nbuf, + uint8_t *rx_tlv_hdr, uint8_t mac_id) { bool mpdu_done = false; qdf_nbuf_t curr_nbuf = NULL; @@ -596,11 +626,22 @@ dp_rx_chain_msdus(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, /* TODO: Currently only single radio is supported, hence * pdev hard coded to '0' index */ - struct dp_pdev *dp_pdev = soc->pdev_list[mac_id]; - - if (!dp_pdev->first_nbuf) { + struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); + + /* if invalid peer SG list has max values free the buffers in list + * and treat current buffer as start of list + * + * current logic to detect the last buffer from attn_tlv is not reliable + * in OFDMA UL scenario hence add max buffers check to avoid list pile + * up + */ + if (!dp_pdev->first_nbuf || + (dp_pdev->invalid_peer_head_msdu && + QDF_NBUF_CB_RX_NUM_ELEMENTS_IN_LIST + (dp_pdev->invalid_peer_head_msdu) >= DP_MAX_INVALID_BUFFERS)) { qdf_nbuf_set_rx_chfrag_start(nbuf, 1); - dp_pdev->ppdu_id = HAL_RX_HW_DESC_GET_PPDUID_GET(rx_tlv_hdr); + dp_pdev->ppdu_id = hal_rx_hw_desc_get_ppduid_get(soc->hal_soc, + rx_tlv_hdr); dp_pdev->first_nbuf = true; /* If the new nbuf received is the first msdu of the @@ -648,9 +689,9 @@ dp_rx_chain_msdus(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, } static -void dp_rx_wbm_err_handle_bar(struct dp_soc *soc, - struct dp_peer *peer, - qdf_nbuf_t nbuf) +void dp_rx_err_handle_bar(struct dp_soc *soc, + struct dp_peer *peer, + qdf_nbuf_t nbuf) { uint8_t *rx_tlv_hdr; unsigned char type, subtype; @@ -665,8 +706,7 @@ void dp_rx_wbm_err_handle_bar(struct dp_soc *soc, */ rx_tlv_hdr = qdf_nbuf_data(nbuf); - bar = (struct ieee80211_frame_bar *)(rx_tlv_hdr + - sizeof(struct rx_pkt_tlvs)); + bar = (struct ieee80211_frame_bar *)(rx_tlv_hdr + SIZE_OF_DATA_RX_TLV); type = bar->i_fc[0] & IEEE80211_FC0_TYPE_MASK; subtype = bar->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; @@ -690,15 +730,99 @@ void dp_rx_wbm_err_handle_bar(struct dp_soc *soc, start_seq_num); } +/** + * dp_rx_bar_frame_handle() - Function to handle err BAR frames + * @soc: core DP main context + * @ring_desc: Hal ring desc + * @rx_desc: dp rx desc + * @mpdu_desc_info: mpdu desc info + * + * Handle the error BAR frames received. Ensure the SOC level + * stats are updated based on the REO error code. The BAR frames + * are further processed by updating the Rx tids with the start + * sequence number (SSN) and BA window size. Desc is returned + * to the free desc list + * + * Return: none + */ +static void +dp_rx_bar_frame_handle(struct dp_soc *soc, + hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc, + struct hal_rx_mpdu_desc_info *mpdu_desc_info) +{ + qdf_nbuf_t nbuf; + struct dp_pdev *pdev; + struct dp_peer *peer; + struct rx_desc_pool *rx_desc_pool; + uint16_t peer_id; + uint8_t *rx_tlv_hdr; + uint32_t tid; + uint8_t reo_err_code; + + nbuf = rx_desc->nbuf; + rx_desc_pool = &soc->rx_desc_buf[rx_desc->pool_id]; + dp_ipa_handle_rx_buf_smmu_mapping(soc, nbuf, + false); + qdf_nbuf_unmap_single(soc->osdev, nbuf, + QDF_DMA_FROM_DEVICE); + rx_desc->unmapped = 1; + rx_tlv_hdr = qdf_nbuf_data(nbuf); + peer_id = + hal_rx_mpdu_start_sw_peer_id_get(soc->hal_soc, + rx_tlv_hdr); + peer = dp_peer_find_by_id(soc, peer_id); + tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, + rx_tlv_hdr); + pdev = dp_get_pdev_for_lmac_id(soc, rx_desc->pool_id); + + if (!peer) + goto next; + + reo_err_code = HAL_RX_REO_ERROR_GET(ring_desc); + dp_info("BAR frame: peer = "QDF_MAC_ADDR_FMT + " peer_id = %d" + " tid = %u" + " SSN = %d" + " error code = %d", + QDF_MAC_ADDR_REF(peer->mac_addr.raw), + peer_id, + tid, + mpdu_desc_info->mpdu_seq, + reo_err_code); + + switch (reo_err_code) { + case HAL_REO_ERR_BAR_FRAME_2K_JUMP: + DP_STATS_INC(soc, + rx.err.reo_error[reo_err_code], 1); + case HAL_REO_ERR_BAR_FRAME_OOR: + dp_rx_err_handle_bar(soc, peer, nbuf); + DP_STATS_INC(soc, + rx.err.reo_error[reo_err_code], 1); + break; + default: + DP_STATS_INC(soc, rx.bar_frame, 1); + } + + dp_peer_unref_del_find_by_id(peer); +next: + dp_rx_link_desc_return(soc, ring_desc, + HAL_BM_ACTION_PUT_IN_IDLE_LIST); + dp_rx_add_to_free_desc_list(&pdev->free_list_head, + &pdev->free_list_tail, + rx_desc); + qdf_nbuf_free(nbuf); +} + /** * dp_2k_jump_handle() - Function to handle 2k jump exception * on WBM ring * * @soc: core DP main context * @nbuf: buffer pointer + * @rx_tlv_hdr: start of rx tlv header * @peer_id: peer id of first msdu * @tid: Tid for which exception occurred - * @rx_tlv_hdr: start of rx tlv header * * This function handles 2k jump violations arising out * of receiving aggregates in non BA case. This typically @@ -712,9 +836,9 @@ void dp_rx_wbm_err_handle_bar(struct dp_soc *soc, void dp_2k_jump_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, + uint8_t *rx_tlv_hdr, uint16_t peer_id, - uint8_t tid, - uint8_t *rx_tlv_hdr) + uint8_t tid) { struct dp_peer *peer = NULL; struct dp_rx_tid *rx_tid = NULL; @@ -749,12 +873,11 @@ dp_2k_jump_handle(struct dp_soc *soc, if (soc->cdp_soc.ol_ops->send_delba) { DP_STATS_INC(soc, rx.err.rx_2k_jump_delba_sent, 1); soc->cdp_soc.ol_ops->send_delba( - peer->vdev->pdev->ctrl_pdev, - peer->ctrl_peer, - peer->mac_addr.raw, - tid, - peer->vdev->ctrl_vdev, - rx_tid->delba_rcode); + peer->vdev->pdev->soc->ctrl_psoc, + peer->vdev->vdev_id, + peer->mac_addr.raw, + tid, + rx_tid->delba_rcode); } } else { qdf_spin_unlock_bh(&rx_tid->tid_lock); @@ -776,7 +899,8 @@ dp_2k_jump_handle(struct dp_soc *soc, qdf_nbuf_free(nbuf); } -#ifdef QCA_WIFI_QCA6390 +#if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490) || \ + defined(QCA_WIFI_QCA6750) /** * dp_rx_null_q_handle_invalid_peer_id_exception() - to find exception * @soc: pointer to dp_soc struct @@ -797,10 +921,9 @@ dp_rx_null_q_handle_invalid_peer_id_exception(struct dp_soc *soc, uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf) { - uint8_t local_id; struct dp_peer *peer = NULL; uint8_t *rx_pkt_hdr = hal_rx_pkt_hdr_get(rx_tlv_hdr); - struct dp_pdev *pdev = soc->pdev_list[pool_id]; + struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, pool_id); struct ieee80211_frame *wh = (struct ieee80211_frame *)rx_pkt_hdr; /* @@ -810,7 +933,7 @@ dp_rx_null_q_handle_invalid_peer_id_exception(struct dp_soc *soc, */ if (wh) peer = dp_find_peer_by_addr((struct cdp_pdev *)pdev, - wh->i_addr2, &local_id); + wh->i_addr2); if (peer) { dp_verbose_debug("MPDU sw_peer_id & ast_idx is corrupted"); hal_rx_dump_pkt_tlvs(soc->hal_soc, rx_tlv_hdr, @@ -835,7 +958,7 @@ dp_rx_null_q_handle_invalid_peer_id_exception(struct dp_soc *soc, static inline bool dp_rx_check_pkt_len(struct dp_soc *soc, uint32_t pkt_len) { - if (qdf_unlikely(pkt_len > RX_BUFFER_SIZE)) { + if (qdf_unlikely(pkt_len > RX_DATA_BUFFER_SIZE)) { DP_STATS_INC_PKT(soc, rx.err.rx_invalid_pkt_len, 1, pkt_len); return true; @@ -889,34 +1012,40 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, uint8_t pool_id, struct dp_peer *peer) { - uint32_t pkt_len, l2_hdr_offset; + uint32_t pkt_len; uint16_t msdu_len; struct dp_vdev *vdev; uint8_t tid; qdf_ether_header_t *eh; + struct hal_rx_msdu_metadata msdu_metadata; uint16_t sa_idx = 0; qdf_nbuf_set_rx_chfrag_start(nbuf, - hal_rx_msdu_end_first_msdu_get(rx_tlv_hdr)); + hal_rx_msdu_end_first_msdu_get(soc->hal_soc, + rx_tlv_hdr)); qdf_nbuf_set_rx_chfrag_end(nbuf, - hal_rx_msdu_end_last_msdu_get(rx_tlv_hdr)); - qdf_nbuf_set_da_mcbc(nbuf, hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr)); + hal_rx_msdu_end_last_msdu_get(soc->hal_soc, + rx_tlv_hdr)); + qdf_nbuf_set_da_mcbc(nbuf, hal_rx_msdu_end_da_is_mcbc_get(soc->hal_soc, + rx_tlv_hdr)); qdf_nbuf_set_da_valid(nbuf, - hal_rx_msdu_end_da_is_valid_get(rx_tlv_hdr)); + hal_rx_msdu_end_da_is_valid_get(soc->hal_soc, + rx_tlv_hdr)); qdf_nbuf_set_sa_valid(nbuf, - hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr)); + hal_rx_msdu_end_sa_is_valid_get(soc->hal_soc, + rx_tlv_hdr)); - l2_hdr_offset = hal_rx_msdu_end_l3_hdr_padding_get(rx_tlv_hdr); + hal_rx_msdu_metadata_get(soc->hal_soc, rx_tlv_hdr, &msdu_metadata); msdu_len = hal_rx_msdu_start_msdu_len_get(rx_tlv_hdr); - pkt_len = msdu_len + l2_hdr_offset + RX_PKT_TLVS_LEN; + pkt_len = msdu_len + msdu_metadata.l3_hdr_pad + RX_PKT_TLVS_LEN; if (qdf_likely(!qdf_nbuf_is_frag(nbuf))) { if (dp_rx_check_pkt_len(soc, pkt_len)) goto drop_nbuf; /* Set length in nbuf */ - qdf_nbuf_set_pktlen(nbuf, - qdf_min(pkt_len, (uint32_t)RX_BUFFER_SIZE)); + qdf_nbuf_set_pktlen( + nbuf, qdf_min(pkt_len, (uint32_t)RX_DATA_BUFFER_SIZE)); qdf_assert_always(nbuf->data == rx_tlv_hdr); } @@ -939,7 +1068,7 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, if (!peer) { bool mpdu_done = false; - struct dp_pdev *pdev = soc->pdev_list[pool_id]; + struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, pool_id); dp_err_rl("peer is NULL"); DP_STATS_INC_PKT(soc, rx.err.rx_invalid_peer, 1, @@ -955,6 +1084,7 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, pdev->invalid_peer_head_msdu = NULL; pdev->invalid_peer_tail_msdu = NULL; } + return QDF_STATUS_E_FAILURE; } @@ -972,10 +1102,13 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, if (qdf_nbuf_is_frag(nbuf)) qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN); else - qdf_nbuf_pull_head(nbuf, (l2_hdr_offset + RX_PKT_TLVS_LEN)); + qdf_nbuf_pull_head(nbuf, (msdu_metadata.l3_hdr_pad + + RX_PKT_TLVS_LEN)); + + dp_vdev_peer_stats_update_protocol_cnt(vdev, nbuf, NULL, 0, 1); - if (hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr)) { - sa_idx = hal_rx_msdu_end_sa_idx_get(rx_tlv_hdr); + if (hal_rx_msdu_end_sa_is_valid_get(soc->hal_soc, rx_tlv_hdr)) { + sa_idx = hal_rx_msdu_end_sa_idx_get(soc->hal_soc, rx_tlv_hdr); if ((sa_idx < 0) || (sa_idx >= wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx))) { @@ -1002,7 +1135,8 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, if (qdf_unlikely((peer->nawds_enabled == true) && - hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr))) { + hal_rx_msdu_end_da_is_mcbc_get(soc->hal_soc, + rx_tlv_hdr))) { dp_err_rl("free buffer for multicast packet"); DP_STATS_INC(peer, rx.nawds_mcast_drop, 1); goto drop_nbuf; @@ -1015,57 +1149,51 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, /* WDS Source Port Learning */ if (qdf_likely(vdev->rx_decap_type == htt_cmn_pkt_type_ethernet && vdev->wds_enabled)) - dp_rx_wds_srcport_learn(soc, rx_tlv_hdr, peer, nbuf); + dp_rx_wds_srcport_learn(soc, rx_tlv_hdr, peer, nbuf, + msdu_metadata); - if (hal_rx_mpdu_start_mpdu_qos_control_valid_get(rx_tlv_hdr)) { - /* TODO: Assuming that qos_control_valid also indicates - * unicast. Should we check this? - */ - tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, rx_tlv_hdr); - if (peer && !peer->rx_tid[tid].hw_qdesc_vaddr_unaligned) { - /* IEEE80211_SEQ_MAX indicates invalid start_seq */ + if (hal_rx_is_unicast(soc->hal_soc, rx_tlv_hdr)) { + tid = hal_rx_tid_get(soc->hal_soc, rx_tlv_hdr); + if (!peer->rx_tid[tid].hw_qdesc_vaddr_unaligned) dp_rx_tid_setup_wifi3(peer, tid, 1, IEEE80211_SEQ_MAX); - } + /* IEEE80211_SEQ_MAX indicates invalid start_seq */ } if (qdf_unlikely(vdev->rx_decap_type == htt_cmn_pkt_type_raw)) { qdf_nbuf_set_next(nbuf, NULL); dp_rx_deliver_raw(vdev, nbuf, peer); } else { - if (vdev->osif_rx) { - qdf_nbuf_set_next(nbuf, NULL); - DP_STATS_INC_PKT(peer, rx.to_stack, 1, - qdf_nbuf_len(nbuf)); - - /* - * Update the protocol tag in SKB based on - * CCE metadata - */ - dp_rx_update_protocol_tag(soc, vdev, nbuf, rx_tlv_hdr, - EXCEPTION_DEST_RING_ID, - true, true); + qdf_nbuf_set_next(nbuf, NULL); + DP_STATS_INC_PKT(peer, rx.to_stack, 1, + qdf_nbuf_len(nbuf)); - if (qdf_unlikely(hal_rx_msdu_end_da_is_mcbc_get( - rx_tlv_hdr) && - (vdev->rx_decap_type == - htt_cmn_pkt_type_ethernet))) { - eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf); + /* + * Update the protocol tag in SKB based on + * CCE metadata + */ + dp_rx_update_protocol_tag(soc, vdev, nbuf, rx_tlv_hdr, + EXCEPTION_DEST_RING_ID, + true, true); + + /* Update the flow tag in SKB based on FSE metadata */ + dp_rx_update_flow_tag(soc, vdev, nbuf, + rx_tlv_hdr, true); + + if (qdf_unlikely(hal_rx_msdu_end_da_is_mcbc_get( + soc->hal_soc, rx_tlv_hdr) && + (vdev->rx_decap_type == + htt_cmn_pkt_type_ethernet))) { + eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf); + DP_STATS_INC_PKT(peer, rx.multicast, 1, + qdf_nbuf_len(nbuf)); - DP_STATS_INC_PKT(peer, rx.multicast, 1, + if (QDF_IS_ADDR_BROADCAST(eh->ether_dhost)) + DP_STATS_INC_PKT(peer, rx.bcast, 1, qdf_nbuf_len(nbuf)); - if (QDF_IS_ADDR_BROADCAST(eh->ether_dhost)) { - DP_STATS_INC_PKT(peer, rx.bcast, 1, - qdf_nbuf_len(nbuf)); - } - } - - vdev->osif_rx(vdev->osif_vdev, nbuf); - - } else { - dp_err_rl("INVALID osif_rx. vdev %pK", vdev); - DP_STATS_INC(soc, rx.err.invalid_vdev, 1); - goto drop_nbuf; } + + qdf_nbuf_set_exc_frame(nbuf, 1); + dp_rx_deliver_to_stack(soc, vdev, peer, nbuf, NULL); } return QDF_STATUS_SUCCESS; @@ -1111,7 +1239,8 @@ dp_rx_process_rxdma_err(struct dp_soc *soc, qdf_nbuf_t nbuf, qdf_assert(0); } - l2_hdr_offset = hal_rx_msdu_end_l3_hdr_padding_get(rx_tlv_hdr); + l2_hdr_offset = hal_rx_msdu_end_l3_hdr_padding_get(soc->hal_soc, + rx_tlv_hdr); msdu_len = hal_rx_msdu_start_msdu_len_get(rx_tlv_hdr); pkt_len = msdu_len + l2_hdr_offset + RX_PKT_TLVS_LEN; @@ -1151,23 +1280,22 @@ dp_rx_process_rxdma_err(struct dp_soc *soc, qdf_nbuf_t nbuf, * Advance the packet start pointer by total size of * pre-header TLV's */ - qdf_nbuf_pull_head(nbuf, l2_hdr_offset + RX_PKT_TLVS_LEN); + dp_rx_skip_tlvs(nbuf, l2_hdr_offset); if (err_code == HAL_RXDMA_ERR_WIFI_PARSE) { uint8_t *pkt_type; pkt_type = qdf_nbuf_data(nbuf) + (2 * QDF_MAC_ADDR_SIZE); - if (*(uint16_t *)pkt_type == htons(QDF_ETH_TYPE_8021Q) && - *(uint16_t *)(pkt_type + DP_SKIP_VLAN) == htons(QDF_LLC_STP)) { - DP_STATS_INC(vdev->pdev, vlan_tag_stp_cnt, 1); - goto process_mesh; - } else { - DP_STATS_INC(vdev->pdev, dropped.wifi_parse, 1); - qdf_nbuf_free(nbuf); - return; + if (*(uint16_t *)pkt_type == htons(QDF_ETH_TYPE_8021Q)) { + if (*(uint16_t *)(pkt_type + DP_SKIP_VLAN) == + htons(QDF_LLC_STP)) { + DP_STATS_INC(vdev->pdev, vlan_tag_stp_cnt, 1); + goto process_mesh; + } else { + goto process_rx; + } } } - if (vdev->rx_decap_type == htt_cmn_pkt_type_raw) goto process_mesh; @@ -1210,8 +1338,9 @@ dp_rx_process_rxdma_err(struct dp_soc *soc, qdf_nbuf_t nbuf, dp_rx_fill_mesh_stats(vdev, nbuf, rx_tlv_hdr, peer); } process_rx: - if (qdf_unlikely(hal_rx_msdu_end_da_is_mcbc_get(rx_tlv_hdr) && - (vdev->rx_decap_type == + if (qdf_unlikely(hal_rx_msdu_end_da_is_mcbc_get(soc->hal_soc, + rx_tlv_hdr) && + (vdev->rx_decap_type == htt_cmn_pkt_type_ethernet))) { eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf); is_broadcast = (QDF_IS_ADDR_BROADCAST @@ -1229,7 +1358,10 @@ dp_rx_process_rxdma_err(struct dp_soc *soc, qdf_nbuf_t nbuf, /* Update the protocol tag in SKB based on CCE metadata */ dp_rx_update_protocol_tag(soc, vdev, nbuf, rx_tlv_hdr, EXCEPTION_DEST_RING_ID, true, true); + /* Update the flow tag in SKB based on FSE metadata */ + dp_rx_update_flow_tag(soc, vdev, nbuf, rx_tlv_hdr, true); DP_STATS_INC(peer, rx.to_stack.num, 1); + qdf_nbuf_set_exc_frame(nbuf, 1); dp_rx_deliver_to_stack(soc, vdev, peer, nbuf, NULL); } @@ -1251,18 +1383,16 @@ void dp_rx_process_mic_error(struct dp_soc *soc, qdf_nbuf_t nbuf, struct dp_vdev *vdev = NULL; struct dp_pdev *pdev = NULL; struct ol_if_ops *tops = NULL; - struct ieee80211_frame *wh; - uint8_t *rx_pkt_hdr; uint16_t rx_seq, fragno; + uint8_t is_raw; unsigned int tid; QDF_STATUS status; + struct cdp_rx_mic_err_info mic_failure_info; - if (!hal_rx_msdu_end_first_msdu_get(rx_tlv_hdr)) + if (!hal_rx_msdu_end_first_msdu_get(soc->hal_soc, + rx_tlv_hdr)) return; - rx_pkt_hdr = hal_rx_pkt_hdr_get(qdf_nbuf_data(nbuf)); - wh = (struct ieee80211_frame *)rx_pkt_hdr; - if (!peer) { dp_info_rl("peer not found"); goto fail; @@ -1280,37 +1410,139 @@ void dp_rx_process_mic_error(struct dp_soc *soc, qdf_nbuf_t nbuf, goto fail; } - tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, qdf_nbuf_data(nbuf)); - rx_seq = (((*(uint16_t *)wh->i_seq) & - IEEE80211_SEQ_SEQ_MASK) >> - IEEE80211_SEQ_SEQ_SHIFT); + is_raw = HAL_IS_DECAP_FORMAT_RAW(soc->hal_soc, qdf_nbuf_data(nbuf)); + if (is_raw) { + fragno = dp_rx_frag_get_mpdu_frag_number(qdf_nbuf_data(nbuf)); + /* Can get only last fragment */ + if (fragno) { + tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, + qdf_nbuf_data(nbuf)); + rx_seq = hal_rx_get_rx_sequence(soc->hal_soc, + qdf_nbuf_data(nbuf)); + + status = dp_rx_defrag_add_last_frag(soc, peer, + tid, rx_seq, nbuf); + dp_info_rl("Frag pkt seq# %d frag# %d consumed " + "status %d !", rx_seq, fragno, status); + return; + } + } - fragno = dp_rx_frag_get_mpdu_frag_number(qdf_nbuf_data(nbuf)); + if (hal_rx_mpdu_get_addr1(soc->hal_soc, qdf_nbuf_data(nbuf), + &mic_failure_info.da_mac_addr.bytes[0])) { + dp_err_rl("Failed to get da_mac_addr"); + goto fail; + } - /* Can get only last fragment */ - if (fragno) { - status = dp_rx_defrag_add_last_frag(soc, peer, - tid, rx_seq, nbuf); - dp_info_rl("Frag pkt seq# %d frag# %d consumed status %d !", - rx_seq, fragno, status); - return; + if (hal_rx_mpdu_get_addr2(soc->hal_soc, qdf_nbuf_data(nbuf), + &mic_failure_info.ta_mac_addr.bytes[0])) { + dp_err_rl("Failed to get ta_mac_addr"); + goto fail; } + mic_failure_info.key_id = 0; + mic_failure_info.multicast = + IEEE80211_IS_MULTICAST(mic_failure_info.da_mac_addr.bytes); + qdf_mem_zero(mic_failure_info.tsc, MIC_SEQ_CTR_SIZE); + mic_failure_info.frame_type = cdp_rx_frame_type_802_11; + mic_failure_info.data = NULL; + mic_failure_info.vdev_id = vdev->vdev_id; + tops = pdev->soc->cdp_soc.ol_ops; if (tops->rx_mic_error) - tops->rx_mic_error(pdev->ctrl_pdev, vdev->vdev_id, wh); + tops->rx_mic_error(soc->ctrl_psoc, pdev->pdev_id, + &mic_failure_info); fail: qdf_nbuf_free(nbuf); return; } +#ifdef DP_RX_DESC_COOKIE_INVALIDATE +/** + * dp_rx_link_cookie_check() - Validate link desc cookie + * @ring_desc: ring descriptor + * + * Return: qdf status + */ +static inline QDF_STATUS +dp_rx_link_cookie_check(hal_ring_desc_t ring_desc) +{ + if (qdf_unlikely(HAL_RX_REO_BUF_LINK_COOKIE_INVALID_GET(ring_desc))) + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_rx_link_cookie_invalidate() - Invalidate link desc cookie + * @ring_desc: ring descriptor + * + * Return: None + */ +static inline void +dp_rx_link_cookie_invalidate(hal_ring_desc_t ring_desc) +{ + HAL_RX_REO_BUF_LINK_COOKIE_INVALID_SET(ring_desc); +} +#else +static inline QDF_STATUS +dp_rx_link_cookie_check(hal_ring_desc_t ring_desc) +{ + return QDF_STATUS_SUCCESS; +} + +static inline void +dp_rx_link_cookie_invalidate(hal_ring_desc_t ring_desc) +{ +} +#endif + +#ifdef WLAN_FEATURE_DP_RX_RING_HISTORY +/** + * dp_rx_err_ring_record_entry() - Record rx err ring history + * @soc: Datapath soc structure + * @paddr: paddr of the buffer in RX err ring + * @sw_cookie: SW cookie of the buffer in RX err ring + * @rbm: Return buffer manager of the buffer in RX err ring + * + * Returns: None + */ +static inline void +dp_rx_err_ring_record_entry(struct dp_soc *soc, uint64_t paddr, + uint32_t sw_cookie, uint8_t rbm) +{ + struct dp_buf_info_record *record; + uint32_t idx; + + if (qdf_unlikely(!soc->rx_err_ring_history)) + return; + + idx = dp_history_get_next_index(&soc->rx_err_ring_history->index, + DP_RX_ERR_HIST_MAX); + + /* No NULL check needed for record since its an array */ + record = &soc->rx_err_ring_history->entry[idx]; + + record->timestamp = qdf_get_log_timestamp(); + record->hbi.paddr = paddr; + record->hbi.sw_cookie = sw_cookie; + record->hbi.rbm = rbm; +} +#else +static inline void +dp_rx_err_ring_record_entry(struct dp_soc *soc, uint64_t paddr, + uint32_t sw_cookie, uint8_t rbm) +{ +} +#endif + uint32_t dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, - void *hal_ring, uint32_t quota) + hal_ring_handle_t hal_ring_hdl, uint32_t quota) { - void *hal_soc; - void *ring_desc; + hal_ring_desc_t ring_desc; + hal_soc_handle_t hal_soc; uint32_t count = 0; uint32_t rx_bufs_used = 0; uint32_t rx_bufs_reaped[MAX_PDEV_CNT] = { 0 }; @@ -1327,16 +1559,18 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, struct hal_rx_msdu_list msdu_list; /* MSDU's per MPDU */ uint16_t num_msdus; struct dp_rx_desc *rx_desc = NULL; + QDF_STATUS status; + bool ret; /* Debug -- Remove later */ - qdf_assert(soc && hal_ring); + qdf_assert(soc && hal_ring_hdl); hal_soc = soc->hal_soc; /* Debug -- Remove later */ qdf_assert(hal_soc); - if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring))) { + if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring_hdl))) { /* TODO */ /* @@ -1345,20 +1579,26 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, */ DP_STATS_INC(soc, rx.err.hal_ring_access_fail, 1); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - FL("HAL RING Access Failed -- %pK"), hal_ring); + FL("HAL RING Access Failed -- %pK"), hal_ring_hdl); goto done; } while (qdf_likely(quota-- && (ring_desc = - hal_srng_dst_get_next(hal_soc, hal_ring)))) { + hal_srng_dst_peek(hal_soc, + hal_ring_hdl)))) { DP_STATS_INC(soc, rx.err_ring_pkts, 1); error = HAL_RX_ERROR_STATUS_GET(ring_desc); - qdf_assert(error == HAL_REO_ERROR_DETECTED); - buf_type = HAL_RX_REO_BUF_TYPE_GET(ring_desc); + + /* Get the MPDU DESC info */ + hal_rx_mpdu_desc_info_get(ring_desc, &mpdu_desc_info); + + if (mpdu_desc_info.msdu_count == 0) + goto next_entry; + /* * For REO error ring, expect only MSDU LINK DESC */ @@ -1371,6 +1611,12 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, qdf_assert_always((cookie >> LINK_DESC_ID_SHIFT) & LINK_DESC_ID_START); + status = dp_rx_link_cookie_check(ring_desc); + if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) { + DP_STATS_INC(soc, rx.err.invalid_link_cookie, 1); + break; + } + /* * Check if the buffer is to be processed on this processor */ @@ -1380,7 +1626,9 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, link_desc_va = dp_rx_cookie_2_link_desc_va(soc, &hbi); hal_rx_msdu_list_get(soc->hal_soc, link_desc_va, &msdu_list, &num_msdus); - + dp_rx_err_ring_record_entry(soc, msdu_list.paddr[0], + msdu_list.sw_cookie[0], + msdu_list.rbm[0]); if (qdf_unlikely((msdu_list.rbm[0] != DP_WBM2SW_RBM) && (msdu_list.rbm[0] != HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST) && @@ -1398,7 +1646,7 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, /* Return link descriptor through WBM ring (SW2WBM)*/ dp_rx_link_desc_return(soc, ring_desc, HAL_BM_ACTION_RELEASE_MSDU_LIST); - continue; + goto next_entry; } rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, @@ -1407,8 +1655,19 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, mac_id = rx_desc->pool_id; - /* Get the MPDU DESC info */ - hal_rx_mpdu_desc_info_get(ring_desc, &mpdu_desc_info); + if (mpdu_desc_info.bar_frame) { + qdf_assert_always(mpdu_desc_info.msdu_count == 1); + + dp_rx_bar_frame_handle(soc, + ring_desc, + rx_desc, + &mpdu_desc_info); + + rx_bufs_reaped[mac_id] += 1; + goto next_entry; + } + + dp_info("Got pkt with REO ERROR: %d", error); if (mpdu_desc_info.mpdu_flags & HAL_MPDU_F_FRAGMENT) { /* @@ -1421,7 +1680,33 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, &mpdu_desc_info, &mac_id, quota); rx_bufs_reaped[mac_id] += count; - continue; + goto next_entry; + } + + /* + * this is a unlikely scenario where the host is reaping + * a descriptor which it already reaped just a while ago + * but is yet to replenish it back to HW. + * In this case host will dump the last 128 descriptors + * including the software descriptor rx_desc and assert. + */ + + if (qdf_unlikely(!rx_desc->in_use)) { + DP_STATS_INC(soc, rx.err.hal_reo_dest_dup, 1); + dp_info_rl("Reaping rx_desc not in use!"); + dp_rx_dump_info_and_assert(soc, hal_ring_hdl, + ring_desc, rx_desc); + /* ignore duplicate RX desc and continue */ + /* Pop out the descriptor */ + goto next_entry; + } + + ret = dp_rx_desc_paddr_sanity_check(rx_desc, + msdu_list.paddr[0]); + if (!ret) { + DP_STATS_INC(soc, rx.err.nbuf_sanity_fail, 1); + rx_desc->in_err_state = 1; + goto next_entry; } count = dp_rx_frag_handle(soc, @@ -1430,22 +1715,31 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, rx_bufs_reaped[mac_id] += count; DP_STATS_INC(soc, rx.rx_frags, 1); - continue; + goto next_entry; } + /* + * Expect REO errors to be handled after this point + */ + qdf_assert_always(error == HAL_REO_ERROR_DETECTED); + if (hal_rx_reo_is_pn_error(ring_desc)) { /* TOD0 */ DP_STATS_INC(soc, rx.err. reo_error[HAL_REO_ERR_PN_CHECK_FAILED], 1); + /* increment @pdev level */ + dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); + if (dp_pdev) + DP_STATS_INC(dp_pdev, err.reo_error, 1); count = dp_rx_pn_error_handle(soc, ring_desc, &mpdu_desc_info, &mac_id, quota); rx_bufs_reaped[mac_id] += count; - continue; + goto next_entry; } if (hal_rx_reo_is_2k_jump(ring_desc)) { @@ -1454,6 +1748,10 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, rx.err. reo_error[HAL_REO_ERR_REGULAR_FRAME_2K_JUMP], 1); + /* increment @pdev level */ + dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); + if (dp_pdev) + DP_STATS_INC(dp_pdev, err.reo_error, 1); count = dp_rx_reo_err_entry_process( soc, @@ -1463,7 +1761,7 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, HAL_REO_ERR_REGULAR_FRAME_2K_JUMP); rx_bufs_reaped[mac_id] += count; - continue; + goto next_entry; } if (hal_rx_reo_is_oor_error(ring_desc)) { @@ -1472,7 +1770,10 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, rx.err. reo_error[HAL_REO_ERR_REGULAR_FRAME_OOR], 1); - + /* increment @pdev level */ + dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); + if (dp_pdev) + DP_STATS_INC(dp_pdev, err.reo_error, 1); count = dp_rx_reo_err_entry_process( soc, ring_desc, @@ -1481,12 +1782,17 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, HAL_REO_ERR_REGULAR_FRAME_OOR); rx_bufs_reaped[mac_id] += count; - continue; + goto next_entry; } + /* Assert if unexpected error type */ + qdf_assert_always(0); +next_entry: + dp_rx_link_cookie_invalidate(ring_desc); + hal_srng_dst_get_next(hal_soc, hal_ring_hdl); } done: - dp_srng_access_end(int_ctx, soc, hal_ring); + dp_srng_access_end(int_ctx, soc, hal_ring_hdl); if (soc->rx.flags.defrag_timeout_check) { uint32_t now_ms = @@ -1498,8 +1804,8 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, for (mac_id = 0; mac_id < MAX_PDEV_CNT; mac_id++) { if (rx_bufs_reaped[mac_id]) { - dp_pdev = soc->pdev_list[mac_id]; - dp_rxdma_srng = &dp_pdev->rx_refill_buf_ring; + dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); + dp_rxdma_srng = &soc->rx_refill_buf_ring[mac_id]; rx_desc_pool = &soc->rx_desc_buf[mac_id]; dp_rx_buffers_replenish(soc, mac_id, dp_rxdma_srng, @@ -1533,10 +1839,10 @@ static inline bool dp_handle_rxdma_decrypt_err(void) uint32_t dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, - void *hal_ring, uint32_t quota) + hal_ring_handle_t hal_ring_hdl, uint32_t quota) { - void *hal_soc; - void *ring_desc; + hal_ring_desc_t ring_desc; + hal_soc_handle_t hal_soc; struct dp_rx_desc *rx_desc; union dp_rx_desc_list_elem_t *head[MAX_PDEV_CNT] = { NULL }; union dp_rx_desc_list_elem_t *tail[MAX_PDEV_CNT] = { NULL }; @@ -1557,14 +1863,14 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, uint8_t tid = 0; /* Debug -- Remove later */ - qdf_assert(soc && hal_ring); + qdf_assert(soc && hal_ring_hdl); hal_soc = soc->hal_soc; /* Debug -- Remove later */ qdf_assert(hal_soc); - if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring))) { + if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring_hdl))) { /* TODO */ /* @@ -1572,12 +1878,13 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, * Ring Type / Ring Id combo */ QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - FL("HAL RING Access Failed -- %pK"), hal_ring); + FL("HAL RING Access Failed -- %pK"), hal_ring_hdl); goto done; } while (qdf_likely(quota-- && (ring_desc = - hal_srng_dst_get_next(hal_soc, hal_ring)))) { + hal_srng_dst_get_next(hal_soc, + hal_ring_hdl)))) { /* XXX */ buf_type = HAL_RX_WBM_BUF_TYPE_GET(ring_desc); @@ -1627,7 +1934,7 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, */ if (qdf_unlikely(!rx_desc->in_use)) { DP_STATS_INC(soc, rx.err.hal_wbm_rel_dup, 1); - dp_rx_dump_info_and_assert(soc, hal_ring, + dp_rx_dump_info_and_assert(soc, hal_ring_hdl, ring_desc, rx_desc); } @@ -1652,12 +1959,12 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, rx_desc); } done: - dp_srng_access_end(int_ctx, soc, hal_ring); + dp_srng_access_end(int_ctx, soc, hal_ring_hdl); for (mac_id = 0; mac_id < MAX_PDEV_CNT; mac_id++) { if (rx_bufs_reaped[mac_id]) { - dp_pdev = soc->pdev_list[mac_id]; - dp_rxdma_srng = &dp_pdev->rx_refill_buf_ring; + dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); + dp_rxdma_srng = &soc->rx_refill_buf_ring[mac_id]; rx_desc_pool = &soc->rx_desc_buf[mac_id]; dp_rx_buffers_replenish(soc, mac_id, dp_rxdma_srng, @@ -1681,7 +1988,8 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, */ hal_rx_wbm_err_info_get_from_tlv(rx_tlv_hdr, &wbm_err_info); - peer_id = hal_rx_mpdu_start_sw_peer_id_get(rx_tlv_hdr); + peer_id = hal_rx_mpdu_start_sw_peer_id_get(soc->hal_soc, + rx_tlv_hdr); peer = dp_peer_find_by_id(soc, peer_id); if (!peer) @@ -1701,6 +2009,12 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, DP_STATS_INC(soc, rx.err.reo_error [wbm_err_info.reo_err_code], 1); + /* increment @pdev level */ + pool_id = wbm_err_info.pool_id; + dp_pdev = dp_get_pdev_for_lmac_id(soc, pool_id); + if (dp_pdev) + DP_STATS_INC(dp_pdev, err.reo_error, + 1); switch (wbm_err_info.reo_err_code) { /* @@ -1722,9 +2036,11 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, case HAL_REO_ERR_REGULAR_FRAME_2K_JUMP: pool_id = wbm_err_info.pool_id; - if (hal_rx_msdu_end_first_msdu_get(rx_tlv_hdr)) { + if (hal_rx_msdu_end_first_msdu_get(soc->hal_soc, + rx_tlv_hdr)) { peer_id = - hal_rx_mpdu_start_sw_peer_id_get(rx_tlv_hdr); + hal_rx_mpdu_start_sw_peer_id_get(soc->hal_soc, + rx_tlv_hdr); tid = hal_rx_mpdu_start_tid_get(hal_soc, rx_tlv_hdr); } @@ -1733,8 +2049,8 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, rx_tlv_hdr); nbuf->next = NULL; dp_2k_jump_handle(soc, nbuf, - peer_id, tid, - rx_tlv_hdr); + rx_tlv_hdr, + peer_id, tid); nbuf = next; if (peer) dp_peer_unref_del_find_by_id( @@ -1743,9 +2059,10 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, case HAL_REO_ERR_BAR_FRAME_2K_JUMP: case HAL_REO_ERR_BAR_FRAME_OOR: if (peer) - dp_rx_wbm_err_handle_bar(soc, - peer, - nbuf); + dp_rx_err_handle_bar(soc, + peer, + nbuf); + qdf_nbuf_free(nbuf); break; default: @@ -1761,6 +2078,12 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, DP_STATS_INC(soc, rx.err.rxdma_error [wbm_err_info.rxdma_err_code], 1); + /* increment @pdev level */ + pool_id = wbm_err_info.pool_id; + dp_pdev = dp_get_pdev_for_lmac_id(soc, pool_id); + if (dp_pdev) + DP_STATS_INC(dp_pdev, + err.rxdma_error, 1); switch (wbm_err_info.rxdma_err_code) { case HAL_RXDMA_ERR_UNENCRYPTED: @@ -1845,14 +2168,15 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, * Return: void */ static void dup_desc_dbg(struct dp_soc *soc, - void *rxdma_dst_ring_desc, + hal_rxdma_desc_t rxdma_dst_ring_desc, void *rx_desc) { DP_STATS_INC(soc, rx.err.hal_rxdma_err_dup, 1); - dp_rx_dump_info_and_assert(soc, - soc->rx_rel_ring.hal_srng, - rxdma_dst_ring_desc, - rx_desc); + dp_rx_dump_info_and_assert( + soc, + soc->rx_rel_ring.hal_srng, + hal_rxdma_desc_to_hal_ring_desc(rxdma_dst_ring_desc), + rx_desc); } /** @@ -1868,7 +2192,7 @@ static void dup_desc_dbg(struct dp_soc *soc, */ static inline uint32_t dp_rx_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, - void *rxdma_dst_ring_desc, + hal_rxdma_desc_t rxdma_dst_ring_desc, union dp_rx_desc_list_elem_t **head, union dp_rx_desc_list_elem_t **tail) { @@ -1878,23 +2202,22 @@ dp_rx_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, struct hal_rx_msdu_list msdu_list; uint16_t num_msdus; struct hal_buf_info buf_info; - void *p_buf_addr_info; - void *p_last_buf_addr_info; uint32_t rx_bufs_used = 0; uint32_t msdu_cnt; uint32_t i; uint8_t push_reason; uint8_t rxdma_error_code = 0; uint8_t bm_action = HAL_BM_ACTION_PUT_IN_IDLE_LIST; - struct dp_pdev *pdev = dp_get_pdev_for_mac_id(soc, mac_id); - void *ring_desc; + struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id); + uint32_t rx_link_buf_info[HAL_RX_BUFFINFO_NUM_DWORDS]; + hal_rxdma_desc_t ring_desc; msdu = 0; last = NULL; hal_rx_reo_ent_buf_paddr_get(rxdma_dst_ring_desc, &buf_info, - &p_last_buf_addr_info, &msdu_cnt); + &msdu_cnt); push_reason = hal_rx_reo_ent_rxdma_push_reason_get(rxdma_dst_ring_desc); @@ -1907,7 +2230,7 @@ dp_rx_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, rx_msdu_link_desc = dp_rx_cookie_2_link_desc_va(soc, &buf_info); - qdf_assert(rx_msdu_link_desc); + qdf_assert_always(rx_msdu_link_desc); hal_rx_msdu_list_get(soc->hal_soc, rx_msdu_link_desc, &msdu_list, &num_msdus); @@ -1973,15 +2296,23 @@ dp_rx_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, rxdma_error_code = HAL_RXDMA_ERR_WAR; } - hal_rx_mon_next_link_desc_get(rx_msdu_link_desc, &buf_info, - &p_buf_addr_info); - - dp_rx_link_desc_return(soc, p_last_buf_addr_info, bm_action); - p_last_buf_addr_info = p_buf_addr_info; - + /* + * Store the current link buffer into to the local structure + * to be used for release purpose. + */ + hal_rxdma_buff_addr_info_set(rx_link_buf_info, buf_info.paddr, + buf_info.sw_cookie, buf_info.rbm); + + hal_rx_mon_next_link_desc_get(rx_msdu_link_desc, &buf_info); + dp_rx_link_desc_return_by_addr(soc, + (hal_buff_addrinfo_t) + rx_link_buf_info, + bm_action); } while (buf_info.paddr); DP_STATS_INC(soc, rx.err.rxdma_error[rxdma_error_code], 1); + if (pdev) + DP_STATS_INC(pdev, err.rxdma_error, 1); if (rxdma_error_code == HAL_RXDMA_ERR_DECRYPT) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -1995,10 +2326,9 @@ uint32_t dp_rxdma_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, uint32_t mac_id, uint32_t quota) { - struct dp_pdev *pdev = dp_get_pdev_for_mac_id(soc, mac_id); - int mac_for_pdev = dp_get_mac_id_for_mac(soc, mac_id); - void *hal_soc; - void *rxdma_dst_ring_desc; + struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id); + hal_rxdma_desc_t rxdma_dst_ring_desc; + hal_soc_handle_t hal_soc; void *err_dst_srng; union dp_rx_desc_list_elem_t *head = NULL; union dp_rx_desc_list_elem_t *tail = NULL; @@ -2010,7 +2340,7 @@ dp_rxdma_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, if (!pdev) return 0; - err_dst_srng = pdev->rxdma_err_dst_ring[mac_for_pdev].hal_srng; + err_dst_srng = soc->rxdma_err_dst_ring[mac_id].hal_srng; if (!err_dst_srng) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -2043,7 +2373,10 @@ dp_rxdma_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, dp_srng_access_end(int_ctx, soc, err_dst_srng); if (rx_bufs_used) { - dp_rxdma_srng = &pdev->rx_refill_buf_ring; + if (wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) + dp_rxdma_srng = &soc->rx_refill_buf_ring[mac_id]; + else + dp_rxdma_srng = &soc->rx_refill_buf_ring[pdev->lmac_id]; rx_desc_pool = &soc->rx_desc_buf[mac_id]; dp_rx_buffers_replenish(soc, mac_id, dp_rxdma_srng, @@ -2054,3 +2387,154 @@ dp_rxdma_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, return work_done; } + +static inline uint32_t +dp_wbm_int_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, + hal_rxdma_desc_t rxdma_dst_ring_desc, + union dp_rx_desc_list_elem_t **head, + union dp_rx_desc_list_elem_t **tail) +{ + void *rx_msdu_link_desc; + qdf_nbuf_t msdu; + qdf_nbuf_t last; + struct hal_rx_msdu_list msdu_list; + uint16_t num_msdus; + struct hal_buf_info buf_info; + uint32_t rx_bufs_used = 0, msdu_cnt, i; + uint32_t rx_link_buf_info[HAL_RX_BUFFINFO_NUM_DWORDS]; + + msdu = 0; + + last = NULL; + + hal_rx_reo_ent_buf_paddr_get(rxdma_dst_ring_desc, &buf_info, + &msdu_cnt); + + do { + rx_msdu_link_desc = + dp_rx_cookie_2_link_desc_va(soc, &buf_info); + + if (!rx_msdu_link_desc) { + DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_LINK_DESC], 1); + break; + } + + hal_rx_msdu_list_get(soc->hal_soc, rx_msdu_link_desc, + &msdu_list, &num_msdus); + + if (msdu_list.sw_cookie[0] != HAL_RX_COOKIE_SPECIAL) { + for (i = 0; i < num_msdus; i++) { + struct dp_rx_desc *rx_desc = + dp_rx_cookie_2_va_rxdma_buf( + soc, + msdu_list.sw_cookie[i]); + qdf_assert_always(rx_desc); + msdu = rx_desc->nbuf; + + qdf_nbuf_unmap_single(soc->osdev, msdu, + QDF_DMA_FROM_DEVICE); + + qdf_nbuf_free(msdu); + rx_bufs_used++; + dp_rx_add_to_free_desc_list(head, + tail, rx_desc); + } + } + + /* + * Store the current link buffer into to the local structure + * to be used for release purpose. + */ + hal_rxdma_buff_addr_info_set(rx_link_buf_info, buf_info.paddr, + buf_info.sw_cookie, buf_info.rbm); + + hal_rx_mon_next_link_desc_get(rx_msdu_link_desc, &buf_info); + dp_rx_link_desc_return_by_addr(soc, (hal_buff_addrinfo_t) + rx_link_buf_info, + HAL_BM_ACTION_PUT_IN_IDLE_LIST); + } while (buf_info.paddr); + + return rx_bufs_used; +} + +/* + * + * dp_handle_wbm_internal_error() - handles wbm_internal_error case + * + * @soc: core DP main context + * @hal_desc: hal descriptor + * @buf_type: indicates if the buffer is of type link disc or msdu + * Return: None + * + * wbm_internal_error is seen in following scenarios : + * + * 1. Null pointers detected in WBM_RELEASE_RING descriptors + * 2. Null pointers detected during delinking process + * + * Some null pointer cases: + * + * a. MSDU buffer pointer is NULL + * b. Next_MSDU_Link_Desc pointer is NULL, with no last msdu flag + * c. MSDU buffer pointer is NULL or Next_Link_Desc pointer is NULL + */ +void +dp_handle_wbm_internal_error(struct dp_soc *soc, void *hal_desc, + uint32_t buf_type) +{ + struct hal_buf_info buf_info = {0}; + struct dp_pdev *dp_pdev; + struct dp_rx_desc *rx_desc = NULL; + uint32_t rx_buf_cookie; + uint32_t rx_bufs_reaped = 0; + union dp_rx_desc_list_elem_t *head = NULL; + union dp_rx_desc_list_elem_t *tail = NULL; + uint8_t pool_id; + + hal_rx_reo_buf_paddr_get(hal_desc, &buf_info); + + if (!buf_info.paddr) { + DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_BUFFER], 1); + return; + } + + rx_buf_cookie = HAL_RX_REO_BUF_COOKIE_GET(hal_desc); + pool_id = DP_RX_DESC_COOKIE_POOL_ID_GET(rx_buf_cookie); + + if (buf_type == HAL_WBM_RELEASE_RING_2_BUFFER_TYPE) { + DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_MSDU_BUFF], 1); + rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, rx_buf_cookie); + + if (rx_desc && rx_desc->nbuf) { + qdf_nbuf_unmap_single(soc->osdev, rx_desc->nbuf, + QDF_DMA_FROM_DEVICE); + + rx_desc->unmapped = 1; + + qdf_nbuf_free(rx_desc->nbuf); + dp_rx_add_to_free_desc_list(&head, + &tail, + rx_desc); + + rx_bufs_reaped++; + } + } else if (buf_type == HAL_WBM_RELEASE_RING_2_DESC_TYPE) { + rx_bufs_reaped = dp_wbm_int_err_mpdu_pop(soc, pool_id, + hal_desc, + &head, &tail); + } + + if (rx_bufs_reaped) { + struct rx_desc_pool *rx_desc_pool; + struct dp_srng *dp_rxdma_srng; + + DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_REO_BUFF_REAPED], 1); + dp_pdev = dp_get_pdev_for_lmac_id(soc, pool_id); + dp_rxdma_srng = &soc->rx_refill_buf_ring[pool_id]; + rx_desc_pool = &soc->rx_desc_buf[pool_id]; + + dp_rx_buffers_replenish(soc, pool_id, dp_rxdma_srng, + rx_desc_pool, + rx_bufs_reaped, + &head, &tail); + } +} diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon.h index 975b2418877c4287c0857e0e1cb1712c19a13ff0..80eda34f67425be62faf80f6817ae52a6fc6e430 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -45,15 +45,9 @@ QDF_STATUS dp_rx_pdev_mon_status_detach(struct dp_pdev *pdev, int mac_id); * * Return: QDF_STATUS */ -QDF_STATUS dp_reset_monitor_mode(struct cdp_pdev *pdev_handle); - -/** - * dp_pdev_configure_monitor_rings() - configure monitor rings - * @vdev_handle: Datapath VDEV handle - * - * Return: QDF_STATUS - */ -QDF_STATUS dp_pdev_configure_monitor_rings(struct dp_pdev *pdev); +QDF_STATUS dp_reset_monitor_mode(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + uint8_t smart_monitor); /** * dp_mon_link_free() - free monitor link desc pool @@ -95,6 +89,13 @@ QDF_STATUS dp_rx_mon_deliver_non_std(struct dp_soc *soc, uint32_t mac_id); uint32_t dp_rxdma_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, uint32_t mac_id, uint32_t quota); +/** + * dp_mon_buf_delayed_replenish() - Helper routine to replenish monitor dest buf + * @pdev: DP pdev object + * + * Return: None + */ +void dp_mon_buf_delayed_replenish(struct dp_pdev *pdev); #ifndef REMOVE_MON_DBG_STATS /* * dp_rx_mon_update_dbg_ppdu_stats() - Update status ring TLV count diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon_dest.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon_dest.c index 39cb49200440e6635b61af035cf8cec369a5556a..07a9760e4ee3b1e95cca6c842ff8067eb92a8645 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon_dest.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon_dest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -55,23 +55,22 @@ */ static QDF_STATUS dp_rx_mon_link_desc_return(struct dp_pdev *dp_pdev, - void *buf_addr_info, int mac_id) + hal_buff_addrinfo_t buf_addr_info, int mac_id) { struct dp_srng *dp_srng; - void *hal_srng; - void *hal_soc; + hal_ring_handle_t hal_ring_hdl; + hal_soc_handle_t hal_soc; QDF_STATUS status = QDF_STATUS_E_FAILURE; void *src_srng_desc; - int mac_for_pdev = dp_get_mac_id_for_mac(dp_pdev->soc, mac_id); hal_soc = dp_pdev->soc->hal_soc; - dp_srng = &dp_pdev->rxdma_mon_desc_ring[mac_for_pdev]; - hal_srng = dp_srng->hal_srng; + dp_srng = &dp_pdev->soc->rxdma_mon_desc_ring[mac_id]; + hal_ring_hdl = dp_srng->hal_srng; - qdf_assert(hal_srng); + qdf_assert(hal_ring_hdl); - if (qdf_unlikely(hal_srng_access_start(hal_soc, hal_srng))) { + if (qdf_unlikely(hal_srng_access_start(hal_soc, hal_ring_hdl))) { /* TODO */ /* @@ -81,11 +80,11 @@ dp_rx_mon_link_desc_return(struct dp_pdev *dp_pdev, QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s %d : \ HAL RING Access For WBM Release SRNG Failed -- %pK", - __func__, __LINE__, hal_srng); + __func__, __LINE__, hal_ring_hdl); goto done; } - src_srng_desc = hal_srng_src_get_next(hal_soc, hal_srng); + src_srng_desc = hal_srng_src_get_next(hal_soc, hal_ring_hdl); if (qdf_likely(src_srng_desc)) { /* Return link descriptor through WBM ring (SW2WBM)*/ @@ -98,7 +97,7 @@ dp_rx_mon_link_desc_return(struct dp_pdev *dp_pdev, __func__, __LINE__); } done: - hal_srng_access_end(hal_soc, hal_srng); + hal_srng_access_end(hal_soc, hal_ring_hdl); return status; } @@ -114,8 +113,8 @@ dp_rx_mon_link_desc_return(struct dp_pdev *dp_pdev, static inline void dp_mon_adjust_frag_len(uint32_t *total_len, uint32_t *frag_len) { - if (*total_len >= (RX_BUFFER_SIZE - RX_PKT_TLVS_LEN)) { - *frag_len = RX_BUFFER_SIZE - RX_PKT_TLVS_LEN; + if (*total_len >= (RX_MONITOR_BUFFER_SIZE - RX_PKT_TLVS_LEN)) { + *frag_len = RX_MONITOR_BUFFER_SIZE - RX_PKT_TLVS_LEN; *total_len -= *frag_len; } else { *frag_len = *total_len; @@ -153,14 +152,15 @@ void *dp_rx_cookie_2_mon_link_desc(struct dp_pdev *pdev, */ static inline QDF_STATUS dp_rx_monitor_link_desc_return(struct dp_pdev *pdev, - void *p_last_buf_addr_info, + hal_buff_addrinfo_t + p_last_buf_addr_info, uint8_t mac_id, uint8_t bm_action) { if (pdev->soc->wlan_cfg_ctx->rxdma1_enable) return dp_rx_mon_link_desc_return(pdev, p_last_buf_addr_info, mac_id); - return dp_rx_link_desc_return(pdev->soc, p_last_buf_addr_info, + return dp_rx_link_desc_return_by_addr(pdev->soc, p_last_buf_addr_info, bm_action); } @@ -177,9 +177,9 @@ void *dp_rxdma_get_mon_dst_ring(struct dp_pdev *pdev, uint8_t mac_for_pdev) { if (pdev->soc->wlan_cfg_ctx->rxdma1_enable) - return pdev->rxdma_mon_dst_ring[mac_for_pdev].hal_srng; + return pdev->soc->rxdma_mon_dst_ring[mac_for_pdev].hal_srng; - return pdev->rxdma_err_dst_ring[mac_for_pdev].hal_srng; + return pdev->soc->rxdma_err_dst_ring[mac_for_pdev].hal_srng; } /** @@ -195,9 +195,10 @@ struct dp_srng *dp_rxdma_get_mon_buf_ring(struct dp_pdev *pdev, uint8_t mac_for_pdev) { if (pdev->soc->wlan_cfg_ctx->rxdma1_enable) - return &pdev->rxdma_mon_buf_ring[mac_for_pdev]; + return &pdev->soc->rxdma_mon_buf_ring[mac_for_pdev]; - return &pdev->rx_refill_buf_ring; + /* For MCL there is only 1 rx refill ring */ + return &pdev->soc->rx_refill_buf_ring[0]; } /** @@ -255,12 +256,12 @@ struct dp_rx_desc *dp_rx_get_mon_desc(struct dp_soc *soc, */ static inline uint32_t dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, - void *rxdma_dst_ring_desc, qdf_nbuf_t *head_msdu, + hal_rxdma_desc_t rxdma_dst_ring_desc, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, uint32_t *npackets, uint32_t *ppdu_id, union dp_rx_desc_list_elem_t **head, union dp_rx_desc_list_elem_t **tail) { - struct dp_pdev *dp_pdev = dp_get_pdev_for_mac_id(soc, mac_id); + struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); void *rx_desc_tlv; void *rx_msdu_link_desc; qdf_nbuf_t msdu; @@ -269,8 +270,6 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, uint16_t num_msdus; uint32_t rx_buf_size, rx_pkt_offset; struct hal_buf_info buf_info; - void *p_buf_addr_info; - void *p_last_buf_addr_info; uint32_t rx_bufs_used = 0; uint32_t msdu_ppdu_id, msdu_cnt; uint8_t *data; @@ -280,13 +279,13 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, bool drop_mpdu = false; uint8_t bm_action = HAL_BM_ACTION_PUT_IN_IDLE_LIST; uint64_t nbuf_paddr = 0; + uint32_t rx_link_buf_info[HAL_RX_BUFFINFO_NUM_DWORDS]; msdu = 0; last = NULL; - hal_rx_reo_ent_buf_paddr_get(rxdma_dst_ring_desc, &buf_info, - &p_last_buf_addr_info, &msdu_cnt); + hal_rx_reo_ent_buf_paddr_get(rxdma_dst_ring_desc, &buf_info, &msdu_cnt); if ((hal_rx_reo_ent_rxdma_push_reason_get(rxdma_dst_ring_desc) == HAL_RX_WBM_RXDMA_PSH_RSN_ERROR)) { @@ -316,7 +315,7 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, dp_rx_cookie_2_mon_link_desc(dp_pdev, buf_info, mac_id); - qdf_assert(rx_msdu_link_desc); + qdf_assert_always(rx_msdu_link_desc); hal_rx_msdu_list_get(soc->hal_soc, rx_msdu_link_desc, &msdu_list, &num_msdus); @@ -383,7 +382,8 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, goto next_msdu; } - msdu_ppdu_id = HAL_RX_HW_DESC_GET_PPDUID_GET( + msdu_ppdu_id = hal_rx_hw_desc_get_ppduid_get( + soc->hal_soc, rx_desc_tlv); is_first_msdu = false; @@ -415,7 +415,8 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, buf_info.paddr; } - if (hal_rx_desc_is_first_msdu(rx_desc_tlv)) + if (hal_rx_desc_is_first_msdu(soc->hal_soc, + rx_desc_tlv)) hal_rx_mon_hw_desc_get_mpdu_status(soc->hal_soc, rx_desc_tlv, &(dp_pdev->ppdu_info.rx_status)); @@ -446,7 +447,7 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, __func__, total_frag_len, frag_len, msdu_list.msdu_info[i].msdu_flags); - rx_pkt_offset = HAL_RX_MON_HW_RX_DESC_SIZE(); + rx_pkt_offset = SIZE_OF_MONITOR_TLV; /* * HW structures call this L3 header padding * -- even though this is actually the offset @@ -454,7 +455,7 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, * header begins. */ l2_hdr_offset = - hal_rx_msdu_end_l3_hdr_padding_get(data); + hal_rx_msdu_end_l3_hdr_padding_get(soc->hal_soc, data); rx_buf_size = rx_pkt_offset + l2_hdr_offset + frag_len; @@ -503,18 +504,21 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, tail, rx_desc); } - hal_rx_mon_next_link_desc_get(rx_msdu_link_desc, &buf_info, - &p_buf_addr_info); + /* + * Store the current link buffer into to the local + * structure to be used for release purpose. + */ + hal_rxdma_buff_addr_info_set(rx_link_buf_info, buf_info.paddr, + buf_info.sw_cookie, buf_info.rbm); + hal_rx_mon_next_link_desc_get(rx_msdu_link_desc, &buf_info); if (dp_rx_monitor_link_desc_return(dp_pdev, - p_last_buf_addr_info, + (hal_buff_addrinfo_t) + rx_link_buf_info, mac_id, bm_action) != QDF_STATUS_SUCCESS) dp_err_rl("monitor link desc return failed"); - - p_last_buf_addr_info = p_buf_addr_info; - } while (buf_info.paddr && msdu_cnt); if (last) @@ -527,14 +531,14 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, } static inline -void dp_rx_msdus_set_payload(qdf_nbuf_t msdu) +void dp_rx_msdus_set_payload(struct dp_soc *soc, qdf_nbuf_t msdu) { uint8_t *data; uint32_t rx_pkt_offset, l2_hdr_offset; data = qdf_nbuf_data(msdu); - rx_pkt_offset = HAL_RX_MON_HW_RX_DESC_SIZE(); - l2_hdr_offset = hal_rx_msdu_end_l3_hdr_padding_get(data); + rx_pkt_offset = SIZE_OF_MONITOR_TLV; + l2_hdr_offset = hal_rx_msdu_end_l3_hdr_padding_get(soc->hal_soc, data); qdf_nbuf_pull_head(msdu, rx_pkt_offset + l2_hdr_offset); } @@ -552,7 +556,7 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc, unsigned char *dest; struct ieee80211_frame *wh; struct ieee80211_qoscntl *qos; - struct dp_pdev *dp_pdev = dp_get_pdev_for_mac_id(soc, mac_id); + struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); head_frag_list = NULL; mpdu_buf = NULL; @@ -594,7 +598,7 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc, * - but the RX status is usually enough */ - dp_rx_msdus_set_payload(head_msdu); + dp_rx_msdus_set_payload(soc, head_msdu); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "[%s][%d] decap format raw head %pK head->next %pK last_msdu %pK last_msdu->next %pK", @@ -611,7 +615,7 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc, while (msdu) { - dp_rx_msdus_set_payload(msdu); + dp_rx_msdus_set_payload(soc, msdu); if (is_first_frag) { is_first_frag = 0; @@ -757,8 +761,9 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc, is_first_frag = 0; } - /* Update protocol tag for MSDU */ - dp_rx_mon_update_protocol_tag(soc, dp_pdev, msdu_orig, rx_desc); + /* Update protocol and flow tag for MSDU */ + dp_rx_mon_update_protocol_flow_tag(soc, dp_pdev, + msdu_orig, rx_desc); dest = qdf_nbuf_put_tail(prev_buf, msdu_llc_len + amsdu_pad); @@ -769,7 +774,7 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc, dest += amsdu_pad; qdf_mem_copy(dest, hdr_desc, msdu_llc_len); - dp_rx_msdus_set_payload(msdu); + dp_rx_msdus_set_payload(soc, msdu); /* Push the MSDU buffer beyond the decap header */ qdf_nbuf_pull_head(msdu, decap_hdr_pull_bytes); @@ -930,7 +935,7 @@ void dp_rx_extract_radiotap_info(struct cdp_mon_status *rx_status, QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, qdf_nbuf_t head_msdu, qdf_nbuf_t tail_msdu) { - struct dp_pdev *pdev = dp_get_pdev_for_mac_id(soc, mac_id); + struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id); struct cdp_mon_status *rs = &pdev->rx_mon_recv_status; qdf_nbuf_t mon_skb, skb_next; qdf_nbuf_t mon_mpdu = NULL; @@ -955,15 +960,14 @@ 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; - /* - * if chan_num is not fetched correctly from ppdu RX TLV, - * get it from pdev saved. - */ - if (pdev->ppdu_info.rx_status.chan_num == 0) - pdev->ppdu_info.rx_status.chan_num = pdev->mon_chan_num; - qdf_nbuf_update_radiotap(&(pdev->ppdu_info.rx_status), - mon_mpdu, sizeof(struct rx_pkt_tlvs)); + if (!qdf_nbuf_update_radiotap(&pdev->ppdu_info.rx_status, + mon_mpdu, + qdf_nbuf_headroom(mon_mpdu))) { + DP_STATS_INC(pdev, dropped.mon_radiotap_update_err, 1); + goto mon_deliver_fail; + } + pdev->monitor_vdev->osif_rx_mon(pdev->monitor_vdev->osif_vdev, mon_mpdu, &pdev->ppdu_info.rx_status); @@ -1006,7 +1010,7 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, QDF_STATUS dp_rx_mon_deliver_non_std(struct dp_soc *soc, uint32_t mac_id) { - struct dp_pdev *pdev = dp_get_pdev_for_mac_id(soc, mac_id); + struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id); ol_txrx_rx_mon_fp osif_rx_mon; qdf_nbuf_t dummy_msdu; @@ -1028,8 +1032,12 @@ QDF_STATUS dp_rx_mon_deliver_non_std(struct dp_soc *soc, pdev->ppdu_info.com_info.ppdu_id; /* Apply the radio header to this dummy skb */ - qdf_nbuf_update_radiotap(&pdev->ppdu_info.rx_status, - dummy_msdu, MAX_MONITOR_HEADER); + if (!qdf_nbuf_update_radiotap(&pdev->ppdu_info.rx_status, dummy_msdu, + qdf_nbuf_headroom(dummy_msdu))) { + DP_STATS_INC(pdev, dropped.mon_radiotap_update_err, 1); + qdf_nbuf_free(dummy_msdu); + goto mon_deliver_non_std_fail; + } /* deliver to the user layer application */ osif_rx_mon(pdev->monitor_vdev->osif_vdev, @@ -1064,17 +1072,17 @@ QDF_STATUS dp_rx_mon_deliver_non_std(struct dp_soc *soc, */ void dp_rx_mon_dest_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) { - struct dp_pdev *pdev = dp_get_pdev_for_mac_id(soc, mac_id); + struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id); uint8_t pdev_id; - void *hal_soc; - void *rxdma_dst_ring_desc; + hal_rxdma_desc_t rxdma_dst_ring_desc; + hal_soc_handle_t hal_soc; void *mon_dst_srng; union dp_rx_desc_list_elem_t *head = NULL; union dp_rx_desc_list_elem_t *tail = NULL; uint32_t ppdu_id; uint32_t rx_bufs_used; uint32_t mpdu_rx_bufs_used; - int mac_for_pdev = dp_get_mac_id_for_mac(soc, mac_id); + int mac_for_pdev = mac_id; struct cdp_pdev_mon_stats *rx_mon_stats; mon_dst_srng = dp_rxdma_get_mon_dst_ring(pdev, mac_for_pdev); @@ -1178,7 +1186,8 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) } #ifndef DISABLE_MON_CONFIG -#ifndef QCA_WIFI_QCA6390 +#if !defined(QCA_WIFI_QCA6390) && !defined(QCA_WIFI_QCA6490) && \ + !defined(QCA_WIFI_QCA6750) /** * dp_rx_pdev_mon_buf_attach() - Allocate the monitor descriptor pool * @@ -1187,20 +1196,18 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) * * Return: QDF_STATUS */ +#define MON_BUF_MIN_ALLOC_ENTRIES 128 static QDF_STATUS dp_rx_pdev_mon_buf_attach(struct dp_pdev *pdev, int mac_id) { uint8_t pdev_id = pdev->pdev_id; struct dp_soc *soc = pdev->soc; - union dp_rx_desc_list_elem_t *desc_list = NULL; - union dp_rx_desc_list_elem_t *tail = NULL; struct dp_srng *mon_buf_ring; uint32_t num_entries; struct rx_desc_pool *rx_desc_pool; QDF_STATUS status = QDF_STATUS_SUCCESS; - uint8_t mac_for_pdev = dp_get_mac_id_for_mac(soc, mac_id); - uint32_t rx_desc_pool_size; + uint32_t rx_desc_pool_size, replenish_size; - mon_buf_ring = &pdev->rxdma_mon_buf_ring[mac_for_pdev]; + mon_buf_ring = &soc->rxdma_mon_buf_ring[mac_id]; num_entries = mon_buf_ring->num_entries; @@ -1209,17 +1216,20 @@ dp_rx_pdev_mon_buf_attach(struct dp_pdev *pdev, int mac_id) { dp_debug("Mon RX Desc Pool[%d] entries=%u", pdev_id, num_entries); - rx_desc_pool_size = DP_RX_DESC_ALLOC_MULTIPLIER * num_entries; + rx_desc_pool_size = wlan_cfg_get_dp_soc_rx_sw_desc_weight(soc->wlan_cfg_ctx) * num_entries; status = dp_rx_desc_pool_alloc(soc, mac_id, rx_desc_pool_size, rx_desc_pool); if (!QDF_IS_STATUS_SUCCESS(status)) return status; rx_desc_pool->owner = HAL_RX_BUF_RBM_SW3_BM; + rx_desc_pool->buf_size = RX_MONITOR_BUFFER_SIZE; + rx_desc_pool->buf_alignment = RX_MONITOR_BUFFER_ALIGNMENT; - status = dp_rx_buffers_replenish(soc, mac_id, mon_buf_ring, - rx_desc_pool, num_entries, - &desc_list, &tail); + replenish_size = ((num_entries - 1) < MON_BUF_MIN_ALLOC_ENTRIES) ? + (num_entries - 1) : MON_BUF_MIN_ALLOC_ENTRIES; + status = dp_pdev_rx_buffers_attach(soc, mac_id, mon_buf_ring, + rx_desc_pool, replenish_size); return status; } @@ -1255,8 +1265,6 @@ dp_rx_pdev_mon_buf_detach(struct dp_pdev *pdev, int mac_id) static QDF_STATUS dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) { - struct dp_pdev *dp_pdev = dp_get_pdev_for_mac_id(soc, mac_id); - int mac_for_pdev = dp_get_mac_id_for_mac(soc, mac_id); int link_desc_size = hal_get_link_desc_size(soc->hal_soc); int link_desc_align = hal_get_link_desc_align(soc->hal_soc); uint32_t max_alloc_size = wlan_cfg_max_alloc_size(soc->wlan_cfg_ctx); @@ -1270,7 +1278,7 @@ QDF_STATUS dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) int i; qdf_dma_addr_t *baseaddr = NULL; - dp_srng = &dp_pdev->rxdma_mon_desc_ring[mac_for_pdev]; + dp_srng = &soc->rxdma_mon_desc_ring[mac_id]; num_entries = dp_srng->alloc_size/hal_srng_get_entrysize( soc->hal_soc, RXDMA_MONITOR_DESC); @@ -1306,17 +1314,17 @@ QDF_STATUS dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) __func__, max_alloc_size, last_bank_size); for (i = 0; i < num_link_desc_banks; i++) { - baseaddr = &dp_pdev->link_desc_banks[mac_for_pdev][i]. + baseaddr = &soc->mon_link_desc_banks[mac_id][i]. base_paddr_unaligned; if (!dp_is_soc_reinit(soc)) { - dp_pdev->link_desc_banks[mac_for_pdev][i]. + soc->mon_link_desc_banks[mac_id][i]. base_vaddr_unaligned = qdf_mem_alloc_consistent(soc->osdev, soc->osdev->dev, max_alloc_size, baseaddr); - if (!dp_pdev->link_desc_banks[mac_for_pdev][i]. + if (!soc->mon_link_desc_banks[mac_id][i]. base_vaddr_unaligned) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, @@ -1325,25 +1333,25 @@ QDF_STATUS dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) goto fail; } } - dp_pdev->link_desc_banks[mac_for_pdev][i].size = max_alloc_size; + soc->mon_link_desc_banks[mac_id][i].size = max_alloc_size; - dp_pdev->link_desc_banks[mac_for_pdev][i].base_vaddr = + soc->mon_link_desc_banks[mac_id][i].base_vaddr = (void *)((unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i]. + (soc->mon_link_desc_banks[mac_id][i]. base_vaddr_unaligned) + ((unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i]. + (soc->mon_link_desc_banks[mac_id][i]. base_vaddr_unaligned) % link_desc_align)); - dp_pdev->link_desc_banks[mac_for_pdev][i].base_paddr = + soc->mon_link_desc_banks[mac_id][i].base_paddr = (unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i]. + (soc->mon_link_desc_banks[mac_id][i]. base_paddr_unaligned) + ((unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i].base_vaddr) - + (soc->mon_link_desc_banks[mac_id][i].base_vaddr) - (unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i]. + (soc->mon_link_desc_banks[mac_id][i]. base_vaddr_unaligned)); } @@ -1351,17 +1359,17 @@ QDF_STATUS dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) /* Allocate last bank in case total memory required is not exact * multiple of max_alloc_size */ - baseaddr = &dp_pdev->link_desc_banks[mac_for_pdev][i]. + baseaddr = &soc->mon_link_desc_banks[mac_id][i]. base_paddr_unaligned; if (!dp_is_soc_reinit(soc)) { - dp_pdev->link_desc_banks[mac_for_pdev][i]. + soc->mon_link_desc_banks[mac_id][i]. base_vaddr_unaligned = qdf_mem_alloc_consistent(soc->osdev, soc->osdev->dev, last_bank_size, baseaddr); - if (!dp_pdev->link_desc_banks[mac_for_pdev][i]. + if (!soc->mon_link_desc_banks[mac_id][i]. base_vaddr_unaligned) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, @@ -1370,33 +1378,34 @@ QDF_STATUS dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) goto fail; } } - dp_pdev->link_desc_banks[mac_for_pdev][i].size = last_bank_size; + soc->mon_link_desc_banks[mac_id][i].size = + last_bank_size; - dp_pdev->link_desc_banks[mac_for_pdev][i].base_vaddr = + soc->mon_link_desc_banks[mac_id][i].base_vaddr = (void *)((unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_vaddr_unaligned) + + (soc->mon_link_desc_banks[mac_id][i]. + base_vaddr_unaligned) + ((unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_vaddr_unaligned) % + (soc->mon_link_desc_banks[mac_id][i]. + base_vaddr_unaligned) % link_desc_align)); - dp_pdev->link_desc_banks[mac_for_pdev][i].base_paddr = + soc->mon_link_desc_banks[mac_id][i].base_paddr = (unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_paddr_unaligned) + + (soc->mon_link_desc_banks[mac_id][i]. + base_paddr_unaligned) + ((unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i].base_vaddr) - + (soc->mon_link_desc_banks[mac_id][i].base_vaddr) - (unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_vaddr_unaligned)); + (soc->mon_link_desc_banks[mac_id][i]. + base_vaddr_unaligned)); } /* Allocate and setup link descriptor idle list for HW internal use */ entry_size = hal_srng_get_entrysize(soc->hal_soc, RXDMA_MONITOR_DESC); total_mem_size = entry_size * total_link_descs; - mon_desc_srng = dp_pdev->rxdma_mon_desc_ring[mac_for_pdev].hal_srng; + mon_desc_srng = soc->rxdma_mon_desc_ring[mac_id].hal_srng; num_replenish_buf = 0; @@ -1405,22 +1414,22 @@ QDF_STATUS dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) for (i = 0; - i < MAX_MON_LINK_DESC_BANKS && - dp_pdev->link_desc_banks[mac_for_pdev][i].base_paddr; - i++) { + i < MAX_MON_LINK_DESC_BANKS && + soc->mon_link_desc_banks[mac_id][i].base_paddr; + i++) { uint32_t num_entries = - (dp_pdev->link_desc_banks[mac_for_pdev][i].size - + (soc->mon_link_desc_banks[mac_id][i].size - (unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i].base_vaddr) - + (soc->mon_link_desc_banks[mac_id][i].base_vaddr) - (unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i]. + (soc->mon_link_desc_banks[mac_id][i]. base_vaddr_unaligned)) / link_desc_size; unsigned long paddr = (unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i].base_paddr); + (soc->mon_link_desc_banks[mac_id][i].base_paddr); unsigned long vaddr = (unsigned long) - (dp_pdev->link_desc_banks[mac_for_pdev][i].base_vaddr); + (soc->mon_link_desc_banks[mac_id][i].base_vaddr); hal_srng_access_start_unlocked(soc->hal_soc, mon_desc_srng); @@ -1429,7 +1438,7 @@ QDF_STATUS dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) hal_srng_src_get_next(soc->hal_soc, mon_desc_srng))) { - hal_set_link_desc_addr(desc, i, paddr); + hal_set_link_desc_addr(desc, i, paddr); num_entries--; num_replenish_buf++; paddr += link_desc_size; @@ -1450,16 +1459,17 @@ QDF_STATUS dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) fail: for (i = 0; i < MAX_MON_LINK_DESC_BANKS; i++) { - if (dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_vaddr_unaligned) { - qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, - dp_pdev->link_desc_banks[mac_for_pdev][i].size, - dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_vaddr_unaligned, - dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_paddr_unaligned, 0); - dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_vaddr_unaligned = NULL; + if (soc->mon_link_desc_banks[mac_id][i]. + base_vaddr_unaligned) { + qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, + soc->mon_link_desc_banks[mac_id][i]. + size, + soc->mon_link_desc_banks[mac_id][i]. + base_vaddr_unaligned, + soc->mon_link_desc_banks[mac_id][i]. + base_paddr_unaligned, 0); + soc->mon_link_desc_banks[mac_id][i]. + base_vaddr_unaligned = NULL; } } return QDF_STATUS_E_FAILURE; @@ -1471,24 +1481,62 @@ QDF_STATUS dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) static void dp_mon_link_desc_pool_cleanup(struct dp_soc *soc, uint32_t mac_id) { - struct dp_pdev *dp_pdev = dp_get_pdev_for_mac_id(soc, mac_id); - int mac_for_pdev = dp_get_mac_id_for_mac(soc, mac_id); int i; for (i = 0; i < MAX_MON_LINK_DESC_BANKS; i++) { - if (dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_vaddr_unaligned) { - qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, - dp_pdev->link_desc_banks[mac_for_pdev][i].size, - dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_vaddr_unaligned, - dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_paddr_unaligned, 0); - dp_pdev->link_desc_banks[mac_for_pdev][i]. - base_vaddr_unaligned = NULL; + if (soc->mon_link_desc_banks[mac_id][i]. + base_vaddr_unaligned) { + qdf_mem_free_consistent(soc->osdev, soc->osdev->dev, + soc->mon_link_desc_banks[mac_id][i]. + size, + soc->mon_link_desc_banks[mac_id][i]. + base_vaddr_unaligned, + soc->mon_link_desc_banks[mac_id][i]. + base_paddr_unaligned, 0); + soc->mon_link_desc_banks[mac_id][i]. + base_vaddr_unaligned = NULL; } } } + +/** + * dp_mon_buf_delayed_replenish() - Helper routine to replenish monitor dest buf + * @pdev: DP pdev object + * + * Return: None + */ +void dp_mon_buf_delayed_replenish(struct dp_pdev *pdev) +{ + struct dp_soc *soc; + uint32_t mac_for_pdev; + union dp_rx_desc_list_elem_t *tail = NULL; + union dp_rx_desc_list_elem_t *desc_list = NULL; + uint32_t num_entries; + uint32_t id; + + soc = pdev->soc; + num_entries = wlan_cfg_get_dma_mon_buf_ring_size(pdev->wlan_cfg_ctx); + + for (id = 0; id < NUM_RXDMA_RINGS_PER_PDEV; id++) { + /* + * Get mac_for_pdev appropriately for both MCL & WIN, + * since MCL have multiple mon buf rings and WIN just + * has one mon buffer ring mapped per pdev, below API + * helps identify accurate buffer_ring for both cases + * + */ + mac_for_pdev = + dp_get_lmac_id_for_pdev_id(soc, id, pdev->pdev_id); + + dp_rx_buffers_replenish(soc, mac_for_pdev, + dp_rxdma_get_mon_buf_ring(pdev, + mac_for_pdev), + dp_rx_get_mon_desc_pool(soc, + mac_for_pdev, + pdev->pdev_id), + num_entries, &desc_list, &tail); + } +} #else static QDF_STATUS dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) @@ -1512,6 +1560,9 @@ dp_rx_pdev_mon_buf_detach(struct dp_pdev *pdev, int mac_id) { return QDF_STATUS_SUCCESS; } + +void dp_mon_buf_delayed_replenish(struct dp_pdev *pdev) +{} #endif /** @@ -1529,7 +1580,7 @@ static QDF_STATUS dp_rx_pdev_mon_cmn_detach(struct dp_pdev *pdev, int mac_id) { struct dp_soc *soc = pdev->soc; uint8_t pdev_id = pdev->pdev_id; - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); + int mac_for_pdev = dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev_id); dp_mon_link_desc_pool_cleanup(soc, mac_for_pdev); dp_rx_pdev_mon_status_detach(pdev, mac_for_pdev); @@ -1553,7 +1604,7 @@ static QDF_STATUS dp_rx_pdev_mon_cmn_attach(struct dp_pdev *pdev, int mac_id) { struct dp_soc *soc = pdev->soc; uint8_t pdev_id = pdev->pdev_id; - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); + int mac_for_pdev = dp_get_lmac_id_for_pdev_id(soc, mac_id, pdev_id); QDF_STATUS status; status = dp_rx_pdev_mon_buf_attach(pdev, mac_for_pdev); @@ -1635,7 +1686,8 @@ dp_mon_link_free(struct dp_pdev *pdev) { int mac_id; for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); + int mac_for_pdev = dp_get_lmac_id_for_pdev_id(soc, + mac_id, pdev_id); dp_mon_link_desc_pool_cleanup(soc, mac_for_pdev); } @@ -1660,7 +1712,8 @@ dp_rx_pdev_mon_detach(struct dp_pdev *pdev) { qdf_spinlock_destroy(&pdev->mon_lock); for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); + int mac_for_pdev = dp_get_lmac_id_for_pdev_id(pdev->soc, + mac_id, pdev_id); dp_rx_pdev_mon_status_detach(pdev, mac_for_pdev); dp_rx_pdev_mon_buf_detach(pdev, mac_for_pdev); @@ -1683,4 +1736,7 @@ QDF_STATUS dp_mon_link_free(struct dp_pdev *pdev) { return QDF_STATUS_SUCCESS; } + +void dp_mon_buf_delayed_replenish(struct dp_pdev *pdev) +{} #endif /* DISABLE_MON_CONFIG */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon_status.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon_status.c index 61afbb9193a30671ef2fb584b2ce0391047ab9a4..251b6d4a0d60193fec1056b22845b62c5cd27a56 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon_status.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_mon_status.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -28,10 +28,17 @@ #include "dp_internal.h" #include "qdf_mem.h" /* qdf_mem_malloc,free */ +#include "htt.h" + #ifdef FEATURE_PERPKT_INFO #include "dp_ratetable.h" #endif +static inline void +dp_rx_populate_cfr_non_assoc_sta(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu); + #ifdef WLAN_RX_PKT_CAPTURE_ENH #include "dp_rx_mon_feature.h" #else @@ -51,99 +58,354 @@ dp_rx_mon_enh_capture_process(struct dp_pdev *pdev, uint32_t tlv_status, } #endif -/** -* dp_rx_populate_cdp_indication_ppdu() - Populate cdp rx indication structure -* @pdev: pdev ctx -* @ppdu_info: ppdu info structure from ppdu ring -* @ppdu_nbuf: qdf nbuf abstraction for linux skb -* -* Return: none -*/ +#ifdef WLAN_TX_PKT_CAPTURE_ENH +#include "dp_rx_mon_feature.h" +#else +static QDF_STATUS +dp_send_ack_frame_to_stack(struct dp_soc *soc, + struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info) +{ + return QDF_STATUS_SUCCESS; +} +#endif + #ifdef FEATURE_PERPKT_INFO static inline void -dp_rx_populate_cdp_indication_ppdu(struct dp_pdev *pdev, - struct hal_rx_ppdu_info *ppdu_info, - qdf_nbuf_t ppdu_nbuf) +dp_rx_populate_rx_rssi_chain(struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) +{ + uint8_t chain, bw; + int8_t rssi; + + for (chain = 0; chain < SS_COUNT; chain++) { + for (bw = 0; bw < MAX_BW; bw++) { + rssi = ppdu_info->rx_status.rssi_chain[chain][bw]; + if (rssi != DP_RSSI_INVAL) + cdp_rx_ppdu->rssi_chain[chain][bw] = rssi; + else + cdp_rx_ppdu->rssi_chain[chain][bw] = 0; + } + } +} + +/* + * dp_rx_populate_su_evm_details() - Populate su evm info + * @ppdu_info: ppdu info structure from ppdu ring + * @cdp_rx_ppdu: rx ppdu indication structure + */ +static inline void +dp_rx_populate_su_evm_details(struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) +{ + uint8_t pilot_evm; + uint8_t nss_count; + uint8_t pilot_count; + + nss_count = ppdu_info->evm_info.nss_count; + pilot_count = ppdu_info->evm_info.pilot_count; + + if ((nss_count * pilot_count) > DP_RX_MAX_SU_EVM_COUNT) { + qdf_err("pilot evm count is more than expected"); + return; + } + cdp_rx_ppdu->evm_info.pilot_count = pilot_count; + cdp_rx_ppdu->evm_info.nss_count = nss_count; + + /* Populate evm for pilot_evm = nss_count*pilot_count */ + for (pilot_evm = 0; pilot_evm < nss_count * pilot_count; pilot_evm++) { + cdp_rx_ppdu->evm_info.pilot_evm[pilot_evm] = + ppdu_info->evm_info.pilot_evm[pilot_evm]; + } +} + +/** + * dp_rx_inc_rusize_cnt() - increment pdev stats based on RU size + * @pdev: pdev ctx + * @rx_user_status: mon rx user status + * + * Return: bool + */ +static inline bool +dp_rx_inc_rusize_cnt(struct dp_pdev *pdev, + struct mon_rx_user_status *rx_user_status) +{ + uint32_t ru_size; + bool is_data; + + ru_size = rx_user_status->ofdma_ru_size; + + if (dp_is_subtype_data(rx_user_status->frame_control)) { + DP_STATS_INC(pdev, + ul_ofdma.data_rx_ru_size[ru_size], 1); + is_data = true; + } else { + DP_STATS_INC(pdev, + ul_ofdma.nondata_rx_ru_size[ru_size], 1); + is_data = false; + } + + return is_data; +} + +/** + * dp_rx_populate_cdp_indication_ppdu_user() - Populate per user cdp indication + * @pdev: pdev ctx + * @ppdu_info: ppdu info structure from ppdu ring + * @cdp_rx_ppdu: Rx PPDU indication structure + * + * Return: none + */ +static inline void +dp_rx_populate_cdp_indication_ppdu_user(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu + *cdp_rx_ppdu) { struct dp_peer *peer; struct dp_soc *soc = pdev->soc; struct dp_ast_entry *ast_entry; - struct cdp_rx_indication_ppdu *cdp_rx_ppdu; uint32_t ast_index; + int i; + struct mon_rx_user_status *rx_user_status; + struct cdp_rx_stats_ppdu_user *rx_stats_peruser; + int ru_size; + bool is_data = false; + uint32_t num_users; + + num_users = ppdu_info->com_info.num_users; + for (i = 0; i < num_users; i++) { + if (i > OFDMA_NUM_USERS) + return; + + rx_user_status = &ppdu_info->rx_user_status[i]; + rx_stats_peruser = &cdp_rx_ppdu->user[i]; + + ast_index = rx_user_status->ast_index; + if (ast_index >= wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)) { + rx_stats_peruser->peer_id = HTT_INVALID_PEER; + continue; + } + + ast_entry = soc->ast_table[ast_index]; + if (!ast_entry) { + rx_stats_peruser->peer_id = HTT_INVALID_PEER; + continue; + } + + peer = ast_entry->peer; + if (!peer || peer->peer_ids[0] == HTT_INVALID_PEER) { + rx_stats_peruser->peer_id = HTT_INVALID_PEER; + continue; + } - cdp_rx_ppdu = (struct cdp_rx_indication_ppdu *)ppdu_nbuf->data; + rx_stats_peruser->first_data_seq_ctrl = + rx_user_status->first_data_seq_ctrl; + + rx_stats_peruser->frame_control_info_valid = + rx_user_status->frame_control_info_valid; + rx_stats_peruser->frame_control = + rx_user_status->frame_control; + + rx_stats_peruser->tcp_msdu_count = + rx_user_status->tcp_msdu_count; + rx_stats_peruser->udp_msdu_count = + rx_user_status->udp_msdu_count; + rx_stats_peruser->other_msdu_count = + rx_user_status->other_msdu_count; + + rx_stats_peruser->num_msdu = + rx_stats_peruser->tcp_msdu_count + + rx_stats_peruser->udp_msdu_count + + rx_stats_peruser->other_msdu_count; + + rx_stats_peruser->preamble_type = + rx_user_status->preamble_type; + rx_stats_peruser->mpdu_cnt_fcs_ok = + rx_user_status->mpdu_cnt_fcs_ok; + rx_stats_peruser->mpdu_cnt_fcs_err = + rx_user_status->mpdu_cnt_fcs_err; + qdf_mem_copy(&rx_stats_peruser->mpdu_fcs_ok_bitmap, + &rx_user_status->mpdu_fcs_ok_bitmap, + HAL_RX_NUM_WORDS_PER_PPDU_BITMAP * + sizeof(rx_user_status->mpdu_fcs_ok_bitmap[0])); + rx_stats_peruser->mpdu_ok_byte_count = + rx_user_status->mpdu_ok_byte_count; + rx_stats_peruser->mpdu_err_byte_count = + rx_user_status->mpdu_err_byte_count; + + cdp_rx_ppdu->num_mpdu += rx_user_status->mpdu_cnt_fcs_ok; + cdp_rx_ppdu->num_msdu += rx_stats_peruser->num_msdu; + rx_stats_peruser->retries = + CDP_FC_IS_RETRY_SET(rx_stats_peruser->frame_control) ? + rx_stats_peruser->mpdu_cnt_fcs_ok : 0; + + if (rx_stats_peruser->mpdu_cnt_fcs_ok > 1) + rx_stats_peruser->is_ampdu = 1; + else + rx_stats_peruser->is_ampdu = 0; + + rx_stats_peruser->tid = ppdu_info->rx_status.tid; + + qdf_mem_copy(rx_stats_peruser->mac_addr, + peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); + rx_stats_peruser->peer_id = peer->peer_ids[0]; + cdp_rx_ppdu->vdev_id = peer->vdev->vdev_id; + rx_stats_peruser->vdev_id = peer->vdev->vdev_id; + rx_stats_peruser->mu_ul_info_valid = 0; + + if (cdp_rx_ppdu->u.ppdu_type == HAL_RX_TYPE_MU_OFDMA || + cdp_rx_ppdu->u.ppdu_type == HAL_RX_TYPE_MU_MIMO) { + if (rx_user_status->mu_ul_info_valid) { + rx_stats_peruser->nss = rx_user_status->nss; + rx_stats_peruser->mcs = rx_user_status->mcs; + rx_stats_peruser->mu_ul_info_valid = + rx_user_status->mu_ul_info_valid; + rx_stats_peruser->ofdma_ru_start_index = + rx_user_status->ofdma_ru_start_index; + rx_stats_peruser->ofdma_ru_width = + rx_user_status->ofdma_ru_width; + rx_stats_peruser->user_index = i; + ru_size = rx_user_status->ofdma_ru_size; + /* + * max RU size will be equal to + * HTT_UL_OFDMA_V0_RU_SIZE_RU_996x2 + */ + if (ru_size >= OFDMA_NUM_RU_SIZE) { + dp_err("invalid ru_size %d\n", + ru_size); + return; + } + is_data = dp_rx_inc_rusize_cnt(pdev, + rx_user_status); + } + if (is_data) { + /* counter to get number of MU OFDMA */ + pdev->stats.ul_ofdma.data_rx_ppdu++; + pdev->stats.ul_ofdma.data_users[num_users]++; + } + } + } +} + +/** + * dp_rx_populate_cdp_indication_ppdu() - Populate cdp rx indication structure + * @pdev: pdev ctx + * @ppdu_info: ppdu info structure from ppdu ring + * @cdp_rx_ppdu: Rx PPDU indication structure + * + * Return: none + */ +static inline void +dp_rx_populate_cdp_indication_ppdu(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) +{ + struct dp_peer *peer; + struct dp_soc *soc = pdev->soc; + struct dp_ast_entry *ast_entry; + uint32_t ast_index; + uint32_t i; cdp_rx_ppdu->first_data_seq_ctrl = ppdu_info->rx_status.first_data_seq_ctrl; cdp_rx_ppdu->frame_ctrl = ppdu_info->rx_status.frame_control; - cdp_rx_ppdu->ppdu_id = ppdu_info->com_info.ppdu_id; - cdp_rx_ppdu->length = ppdu_info->rx_status.ppdu_len; - cdp_rx_ppdu->duration = ppdu_info->rx_status.duration; - cdp_rx_ppdu->u.bw = ppdu_info->rx_status.bw; cdp_rx_ppdu->tcp_msdu_count = ppdu_info->rx_status.tcp_msdu_count; cdp_rx_ppdu->udp_msdu_count = ppdu_info->rx_status.udp_msdu_count; cdp_rx_ppdu->other_msdu_count = ppdu_info->rx_status.other_msdu_count; - cdp_rx_ppdu->u.nss = ppdu_info->rx_status.nss; - cdp_rx_ppdu->u.mcs = ppdu_info->rx_status.mcs; - if ((ppdu_info->rx_status.sgi == VHT_SGI_NYSM) && - (ppdu_info->rx_status.preamble_type == HAL_RX_PKT_TYPE_11AC)) - cdp_rx_ppdu->u.gi = CDP_SGI_0_4_US; - else - cdp_rx_ppdu->u.gi = ppdu_info->rx_status.sgi; - cdp_rx_ppdu->u.ldpc = ppdu_info->rx_status.ldpc; cdp_rx_ppdu->u.preamble = ppdu_info->rx_status.preamble_type; - cdp_rx_ppdu->u.ppdu_type = ppdu_info->rx_status.reception_type; - cdp_rx_ppdu->u.ltf_size = (ppdu_info->rx_status.he_data5 >> - QDF_MON_STATUS_HE_LTF_SIZE_SHIFT) & 0x3; + /* num mpdu is consolidated and added together in num user loop */ cdp_rx_ppdu->num_mpdu = ppdu_info->com_info.mpdu_cnt_fcs_ok; - cdp_rx_ppdu->rssi = ppdu_info->rx_status.rssi_comb; - cdp_rx_ppdu->timestamp = ppdu_info->rx_status.tsft; - cdp_rx_ppdu->channel = ppdu_info->rx_status.chan_num; - cdp_rx_ppdu->beamformed = ppdu_info->rx_status.beamformed; + /* num msdu is consolidated and added together in num user loop */ cdp_rx_ppdu->num_msdu = (cdp_rx_ppdu->tcp_msdu_count + - cdp_rx_ppdu->udp_msdu_count + - cdp_rx_ppdu->other_msdu_count); - cdp_rx_ppdu->num_bytes = ppdu_info->rx_status.ppdu_len; + cdp_rx_ppdu->udp_msdu_count + + cdp_rx_ppdu->other_msdu_count); + cdp_rx_ppdu->retries = CDP_FC_IS_RETRY_SET(cdp_rx_ppdu->frame_ctrl) ? - ppdu_info->com_info.mpdu_cnt_fcs_ok : 0; + ppdu_info->com_info.mpdu_cnt_fcs_ok : 0; if (ppdu_info->com_info.mpdu_cnt_fcs_ok > 1) cdp_rx_ppdu->is_ampdu = 1; else cdp_rx_ppdu->is_ampdu = 0; - cdp_rx_ppdu->tid = ppdu_info->rx_status.tid; - cdp_rx_ppdu->lsig_a = ppdu_info->rx_status.rate; + ast_index = ppdu_info->rx_status.ast_index; if (ast_index >= wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)) { cdp_rx_ppdu->peer_id = HTT_INVALID_PEER; - return; + cdp_rx_ppdu->num_users = 0; + goto end; } ast_entry = soc->ast_table[ast_index]; if (!ast_entry) { cdp_rx_ppdu->peer_id = HTT_INVALID_PEER; - return; + cdp_rx_ppdu->num_users = 0; + goto end; } peer = ast_entry->peer; if (!peer || peer->peer_ids[0] == HTT_INVALID_PEER) { cdp_rx_ppdu->peer_id = HTT_INVALID_PEER; - return; + cdp_rx_ppdu->num_users = 0; + goto end; } qdf_mem_copy(cdp_rx_ppdu->mac_addr, peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); cdp_rx_ppdu->peer_id = peer->peer_ids[0]; cdp_rx_ppdu->vdev_id = peer->vdev->vdev_id; + + cdp_rx_ppdu->ppdu_id = ppdu_info->com_info.ppdu_id; + cdp_rx_ppdu->length = ppdu_info->rx_status.ppdu_len; + cdp_rx_ppdu->duration = ppdu_info->rx_status.duration; + cdp_rx_ppdu->u.bw = ppdu_info->rx_status.bw; + cdp_rx_ppdu->u.nss = ppdu_info->rx_status.nss; + cdp_rx_ppdu->u.mcs = ppdu_info->rx_status.mcs; + if ((ppdu_info->rx_status.sgi == VHT_SGI_NYSM) && + (ppdu_info->rx_status.preamble_type == HAL_RX_PKT_TYPE_11AC)) + cdp_rx_ppdu->u.gi = CDP_SGI_0_4_US; + else + cdp_rx_ppdu->u.gi = ppdu_info->rx_status.sgi; + cdp_rx_ppdu->u.ldpc = ppdu_info->rx_status.ldpc; + cdp_rx_ppdu->u.ppdu_type = ppdu_info->rx_status.reception_type; + cdp_rx_ppdu->u.ltf_size = (ppdu_info->rx_status.he_data5 >> + QDF_MON_STATUS_HE_LTF_SIZE_SHIFT) & 0x3; + cdp_rx_ppdu->rssi = ppdu_info->rx_status.rssi_comb; + cdp_rx_ppdu->timestamp = ppdu_info->rx_status.tsft; + cdp_rx_ppdu->channel = ppdu_info->rx_status.chan_num; + cdp_rx_ppdu->beamformed = ppdu_info->rx_status.beamformed; + cdp_rx_ppdu->num_bytes = ppdu_info->rx_status.ppdu_len; + cdp_rx_ppdu->lsig_a = ppdu_info->rx_status.rate; cdp_rx_ppdu->u.ltf_size = ppdu_info->rx_status.ltf_size; + + dp_rx_populate_rx_rssi_chain(ppdu_info, cdp_rx_ppdu); + dp_rx_populate_su_evm_details(ppdu_info, cdp_rx_ppdu); + cdp_rx_ppdu->rx_antenna = ppdu_info->rx_status.rx_antenna; + + cdp_rx_ppdu->nf = ppdu_info->rx_status.chan_noise_floor; + for (i = 0; i < MAX_CHAIN; i++) + cdp_rx_ppdu->per_chain_rssi[i] = ppdu_info->rx_status.rssi[i]; + + cdp_rx_ppdu->is_mcast_bcast = ppdu_info->nac_info.mcast_bcast; + + cdp_rx_ppdu->num_users = ppdu_info->com_info.num_users; + + cdp_rx_ppdu->num_mpdu = 0; + cdp_rx_ppdu->num_msdu = 0; + + dp_rx_populate_cdp_indication_ppdu_user(pdev, ppdu_info, cdp_rx_ppdu); + + return; +end: + dp_rx_populate_cfr_non_assoc_sta(pdev, ppdu_info, cdp_rx_ppdu); } #else static inline void dp_rx_populate_cdp_indication_ppdu(struct dp_pdev *pdev, - struct hal_rx_ppdu_info *ppdu_info, - qdf_nbuf_t ppdu_nbuf) + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) { } #endif @@ -157,27 +419,33 @@ dp_rx_populate_cdp_indication_ppdu(struct dp_pdev *pdev, */ #ifdef FEATURE_PERPKT_INFO static inline void dp_rx_rate_stats_update(struct dp_peer *peer, - struct cdp_rx_indication_ppdu *ppdu) + struct cdp_rx_indication_ppdu *ppdu, + uint32_t user) { uint32_t ratekbps = 0; uint32_t ppdu_rx_rate = 0; uint32_t nss = 0; uint32_t rix; + uint16_t ratecode; + struct cdp_rx_stats_ppdu_user *ppdu_user; if (!peer || !ppdu) return; - if (ppdu->u.nss == 0) + ppdu_user = &ppdu->user[user]; + + if (ppdu_user->nss == 0) nss = 0; else - nss = ppdu->u.nss - 1; + nss = ppdu_user->nss - 1; ratekbps = dp_getrateindex(ppdu->u.gi, - ppdu->u.mcs, + ppdu_user->mcs, nss, ppdu->u.preamble, ppdu->u.bw, - &rix); + &rix, + &ratecode); if (!ratekbps) return; @@ -188,109 +456,290 @@ static inline void dp_rx_rate_stats_update(struct dp_peer *peer, ppdu_rx_rate = dp_ath_rate_out(peer->stats.rx.avg_rx_rate); DP_STATS_UPD(peer, rx.rnd_avg_rx_rate, ppdu_rx_rate); ppdu->rx_ratekbps = ratekbps; + ppdu->rx_ratecode = ratecode; if (peer->vdev) peer->vdev->stats.rx.last_rx_rate = ratekbps; } -static void dp_rx_stats_update(struct dp_pdev *pdev, struct dp_peer *peer, +static void dp_rx_stats_update(struct dp_pdev *pdev, struct cdp_rx_indication_ppdu *ppdu) { struct dp_soc *soc = NULL; - uint8_t mcs, preamble, ac = 0; + uint8_t mcs, preamble, ac = 0, nss, ppdu_type; uint16_t num_msdu; - bool is_invalid_peer = false; - - mcs = ppdu->u.mcs; - preamble = ppdu->u.preamble; - num_msdu = ppdu->num_msdu; + uint8_t pkt_bw_offset; + struct dp_peer *peer; + struct cdp_rx_stats_ppdu_user *ppdu_user; + uint32_t i; + enum cdp_mu_packet_type mu_pkt_type; if (pdev) soc = pdev->soc; else return; - if (!peer) { - is_invalid_peer = true; - peer = pdev->invalid_peer; - } - if (!soc || soc->process_rx_status) return; - DP_STATS_UPD(peer, rx.rssi, ppdu->rssi); - if (peer->stats.rx.avg_rssi == INVALID_RSSI) - peer->stats.rx.avg_rssi = ppdu->rssi; - else - peer->stats.rx.avg_rssi = - DP_GET_AVG_RSSI(peer->stats.rx.avg_rssi, ppdu->rssi); - - if ((preamble == DOT11_A) || (preamble == DOT11_B)) - ppdu->u.nss = 1; - - if (ppdu->u.nss) - DP_STATS_INC(peer, rx.nss[ppdu->u.nss - 1], num_msdu); - - DP_STATS_INC(peer, rx.sgi_count[ppdu->u.gi], num_msdu); - DP_STATS_INC(peer, rx.bw[ppdu->u.bw], num_msdu); - DP_STATS_INC(peer, rx.reception_type[ppdu->u.ppdu_type], num_msdu); - DP_STATS_INCC(peer, rx.ampdu_cnt, num_msdu, ppdu->is_ampdu); - DP_STATS_INCC(peer, rx.non_ampdu_cnt, num_msdu, !(ppdu->is_ampdu)); - DP_STATS_UPD(peer, rx.rx_rate, mcs); - DP_STATS_INCC(peer, + preamble = ppdu->u.preamble; + ppdu_type = ppdu->u.ppdu_type; + + for (i = 0; i < ppdu->num_users; i++) { + ppdu_user = &ppdu->user[i]; + peer = dp_peer_find_by_id(soc, ppdu_user->peer_id); + + if (!peer) + peer = pdev->invalid_peer; + + ppdu->cookie = (void *)peer->wlanstats_ctx; + + if (ppdu_type == HAL_RX_TYPE_SU) { + mcs = ppdu->u.mcs; + nss = ppdu->u.nss; + } else { + mcs = ppdu_user->mcs; + nss = ppdu_user->nss; + } + + num_msdu = ppdu_user->num_msdu; + switch (ppdu->u.bw) { + case CMN_BW_20MHZ: + pkt_bw_offset = PKT_BW_GAIN_20MHZ; + break; + case CMN_BW_40MHZ: + pkt_bw_offset = PKT_BW_GAIN_40MHZ; + break; + case CMN_BW_80MHZ: + pkt_bw_offset = PKT_BW_GAIN_80MHZ; + break; + case CMN_BW_160MHZ: + pkt_bw_offset = PKT_BW_GAIN_160MHZ; + break; + default: + pkt_bw_offset = 0; + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "Invalid BW index = %d", ppdu->u.bw); + } + + DP_STATS_UPD(peer, rx.rssi, (ppdu->rssi + pkt_bw_offset)); + + if (peer->stats.rx.avg_rssi == INVALID_RSSI) + peer->stats.rx.avg_rssi = + CDP_RSSI_IN(peer->stats.rx.rssi); + else + CDP_RSSI_UPDATE_AVG(peer->stats.rx.avg_rssi, + peer->stats.rx.rssi); + + if ((preamble == DOT11_A) || (preamble == DOT11_B)) + nss = 1; + + if (ppdu_type == HAL_RX_TYPE_SU) { + if (nss) { + DP_STATS_INC(peer, rx.nss[nss - 1], num_msdu); + DP_STATS_INC(peer, rx.ppdu_nss[nss - 1], 1); + } + + DP_STATS_INC(peer, rx.mpdu_cnt_fcs_ok, + ppdu_user->mpdu_cnt_fcs_ok); + DP_STATS_INC(peer, rx.mpdu_cnt_fcs_err, + ppdu_user->mpdu_cnt_fcs_err); + } + + if (ppdu_type >= HAL_RX_TYPE_MU_MIMO && + ppdu_type <= HAL_RX_TYPE_MU_OFDMA) { + if (ppdu_type == HAL_RX_TYPE_MU_MIMO) + mu_pkt_type = RX_TYPE_MU_MIMO; + else + mu_pkt_type = RX_TYPE_MU_OFDMA; + + if (nss) { + DP_STATS_INC(peer, rx.nss[nss - 1], num_msdu); + DP_STATS_INC(peer, + rx.rx_mu[mu_pkt_type].ppdu_nss[nss - 1], + 1); + } + + DP_STATS_INC(peer, + rx.rx_mu[mu_pkt_type].mpdu_cnt_fcs_ok, + ppdu_user->mpdu_cnt_fcs_ok); + DP_STATS_INC(peer, + rx.rx_mu[mu_pkt_type].mpdu_cnt_fcs_err, + ppdu_user->mpdu_cnt_fcs_err); + } + + DP_STATS_INC(peer, rx.sgi_count[ppdu->u.gi], num_msdu); + DP_STATS_INC(peer, rx.bw[ppdu->u.bw], num_msdu); + DP_STATS_INC(peer, rx.reception_type[ppdu->u.ppdu_type], + num_msdu); + DP_STATS_INC(peer, rx.ppdu_cnt[ppdu->u.ppdu_type], 1); + DP_STATS_INCC(peer, rx.ampdu_cnt, num_msdu, + ppdu_user->is_ampdu); + DP_STATS_INCC(peer, rx.non_ampdu_cnt, num_msdu, + !(ppdu_user->is_ampdu)); + DP_STATS_UPD(peer, rx.rx_rate, mcs); + DP_STATS_INCC(peer, rx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, ((mcs >= MAX_MCS_11A) && (preamble == DOT11_A))); - DP_STATS_INCC(peer, + DP_STATS_INCC(peer, rx.pkt_type[preamble].mcs_count[mcs], num_msdu, ((mcs < MAX_MCS_11A) && (preamble == DOT11_A))); - DP_STATS_INCC(peer, + DP_STATS_INCC(peer, rx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, ((mcs >= MAX_MCS_11B) && (preamble == DOT11_B))); - DP_STATS_INCC(peer, + DP_STATS_INCC(peer, rx.pkt_type[preamble].mcs_count[mcs], num_msdu, ((mcs < MAX_MCS_11B) && (preamble == DOT11_B))); - DP_STATS_INCC(peer, + DP_STATS_INCC(peer, rx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, ((mcs >= MAX_MCS_11A) && (preamble == DOT11_N))); - DP_STATS_INCC(peer, + DP_STATS_INCC(peer, rx.pkt_type[preamble].mcs_count[mcs], num_msdu, ((mcs < MAX_MCS_11A) && (preamble == DOT11_N))); - DP_STATS_INCC(peer, + DP_STATS_INCC(peer, rx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, ((mcs >= MAX_MCS_11AC) && (preamble == DOT11_AC))); - DP_STATS_INCC(peer, + DP_STATS_INCC(peer, rx.pkt_type[preamble].mcs_count[mcs], num_msdu, ((mcs < MAX_MCS_11AC) && (preamble == DOT11_AC))); - DP_STATS_INCC(peer, + DP_STATS_INCC(peer, rx.pkt_type[preamble].mcs_count[MAX_MCS - 1], num_msdu, ((mcs >= (MAX_MCS - 1)) && (preamble == DOT11_AX))); - DP_STATS_INCC(peer, + DP_STATS_INCC(peer, rx.pkt_type[preamble].mcs_count[mcs], num_msdu, ((mcs < (MAX_MCS - 1)) && (preamble == DOT11_AX))); - /* - * If invalid TID, it could be a non-qos frame, hence do not update - * any AC counters - */ - ac = TID_TO_WME_AC(ppdu->tid); - if (ppdu->tid != HAL_TID_INVALID) - DP_STATS_INC(peer, rx.wme_ac_type[ac], num_msdu); - dp_peer_stats_notify(peer); - DP_STATS_UPD(peer, rx.last_rssi, ppdu->rssi); + DP_STATS_INCC(peer, + rx.su_ax_ppdu_cnt.mcs_count[MAX_MCS - 1], 1, + ((mcs >= (MAX_MCS - 1)) && (preamble == DOT11_AX) && + (ppdu_type == HAL_RX_TYPE_SU))); + DP_STATS_INCC(peer, + rx.su_ax_ppdu_cnt.mcs_count[mcs], 1, + ((mcs < (MAX_MCS - 1)) && (preamble == DOT11_AX) && + (ppdu_type == HAL_RX_TYPE_SU))); + DP_STATS_INCC(peer, + rx.rx_mu[RX_TYPE_MU_OFDMA].ppdu.mcs_count[MAX_MCS - 1], + 1, ((mcs >= (MAX_MCS - 1)) && + (preamble == DOT11_AX) && + (ppdu_type == HAL_RX_TYPE_MU_OFDMA))); + DP_STATS_INCC(peer, + rx.rx_mu[RX_TYPE_MU_OFDMA].ppdu.mcs_count[mcs], + 1, ((mcs < (MAX_MCS - 1)) && + (preamble == DOT11_AX) && + (ppdu_type == HAL_RX_TYPE_MU_OFDMA))); + DP_STATS_INCC(peer, + rx.rx_mu[RX_TYPE_MU_MIMO].ppdu.mcs_count[MAX_MCS - 1], + 1, ((mcs >= (MAX_MCS - 1)) && + (preamble == DOT11_AX) && + (ppdu_type == HAL_RX_TYPE_MU_MIMO))); + DP_STATS_INCC(peer, + rx.rx_mu[RX_TYPE_MU_MIMO].ppdu.mcs_count[mcs], + 1, ((mcs < (MAX_MCS - 1)) && + (preamble == DOT11_AX) && + (ppdu_type == HAL_RX_TYPE_MU_MIMO))); - if (is_invalid_peer) - return; + /* + * If invalid TID, it could be a non-qos frame, hence do not + * update any AC counters + */ + ac = TID_TO_WME_AC(ppdu_user->tid); + + if (ppdu->tid != HAL_TID_INVALID) + DP_STATS_INC(peer, rx.wme_ac_type[ac], num_msdu); + dp_peer_stats_notify(pdev, peer); + DP_STATS_UPD(peer, rx.last_rssi, ppdu->rssi); + + if (peer == pdev->invalid_peer) + continue; - if (dp_is_subtype_data(ppdu->frame_ctrl)) - dp_rx_rate_stats_update(peer, ppdu); + if (dp_is_subtype_data(ppdu->frame_ctrl)) + dp_rx_rate_stats_update(peer, ppdu, i); #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE - dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, pdev->soc, - &peer->stats, ppdu->peer_id, - UPDATE_PEER_STATS, pdev->pdev_id); + dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, pdev->soc, + &peer->stats, ppdu->peer_id, + UPDATE_PEER_STATS, pdev->pdev_id); #endif + dp_peer_unref_del_find_by_id(peer); + } } #endif +/* + * dp_rx_get_fcs_ok_msdu() - get ppdu status buffer containing fcs_ok msdu + * @pdev: pdev object + * @ppdu_info: ppdu info object + * + * Return: nbuf + */ + +static inline qdf_nbuf_t +dp_rx_get_fcs_ok_msdu(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info) +{ + uint16_t mpdu_fcs_ok; + qdf_nbuf_t status_nbuf = NULL; + unsigned long *fcs_ok_bitmap; + + if (qdf_unlikely(qdf_nbuf_is_queue_empty(&pdev->rx_ppdu_buf_q))) + return NULL; + + /* Obtain fcs_ok passed index from bitmap + * this index is used to get fcs passed first msdu payload + */ + + fcs_ok_bitmap = + (unsigned long *)&ppdu_info->com_info.mpdu_fcs_ok_bitmap[0]; + mpdu_fcs_ok = qdf_find_first_bit(fcs_ok_bitmap, + HAL_RX_MAX_MPDU); + + if (qdf_unlikely(mpdu_fcs_ok >= HAL_RX_MAX_MPDU)) + goto end; + + if (qdf_unlikely(!ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].nbuf)) + goto end; + + /* Get status buffer by indexing mpdu_fcs_ok index + * containing first msdu payload with fcs passed + * and clone the buffer + */ + status_nbuf = ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].nbuf; + ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].nbuf = NULL; + + /* Take ref of status nbuf as this nbuf is to be + * freeed by upper layer. + */ + qdf_nbuf_ref(status_nbuf); + ppdu_info->fcs_ok_msdu_info.first_msdu_payload = + ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].first_msdu_payload; + ppdu_info->fcs_ok_msdu_info.payload_len = + ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].payload_len; + + +end: + /* Free the ppdu status buffer queue */ + qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q); + + qdf_mem_zero(&ppdu_info->ppdu_msdu_info, + (ppdu_info->com_info.mpdu_cnt_fcs_ok + + ppdu_info->com_info.mpdu_cnt_fcs_err) + * sizeof(struct hal_rx_msdu_payload_info)); + return status_nbuf; +} + +static inline void +dp_rx_handle_ppdu_status_buf(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + qdf_nbuf_t status_nbuf) +{ + qdf_nbuf_t dropnbuf; + + if (qdf_nbuf_queue_len(&pdev->rx_ppdu_buf_q) > + HAL_RX_MAX_MPDU) { + dropnbuf = qdf_nbuf_queue_remove(&pdev->rx_ppdu_buf_q); + qdf_nbuf_free(dropnbuf); + } + qdf_nbuf_queue_add(&pdev->rx_ppdu_buf_q, status_nbuf); +} /** * dp_rx_handle_mcopy_mode() - Allocate and deliver first MSDU payload * @soc: core txrx main context @@ -309,7 +758,7 @@ dp_rx_handle_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, struct ieee80211_frame *wh; uint32_t *nbuf_data; - if (!ppdu_info->msdu_info.first_msdu_payload) + if (!ppdu_info->fcs_ok_msdu_info.first_msdu_payload) return QDF_STATUS_SUCCESS; if (pdev->m_copy_id.rx_ppdu_id == ppdu_info->com_info.ppdu_id) @@ -317,11 +766,11 @@ 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; - wh = (struct ieee80211_frame *)(ppdu_info->msdu_info.first_msdu_payload - + 4); - size = (ppdu_info->msdu_info.first_msdu_payload - + wh = (struct ieee80211_frame *) + (ppdu_info->fcs_ok_msdu_info.first_msdu_payload + 4); + + size = (ppdu_info->fcs_ok_msdu_info.first_msdu_payload - qdf_nbuf_data(nbuf)); - ppdu_info->msdu_info.first_msdu_payload = NULL; if (qdf_nbuf_pull_head(nbuf, size) == NULL) return QDF_STATUS_SUCCESS; @@ -333,11 +782,12 @@ dp_rx_handle_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, return QDF_STATUS_SUCCESS; } + ppdu_info->fcs_ok_msdu_info.first_msdu_payload = NULL; 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); + ppdu_info->fcs_ok_msdu_info.payload_len); dp_wdi_event_handler(WDI_EVENT_RX_DATA, soc, nbuf, HTT_INVALID_PEER, WDI_NO_VAL, pdev->pdev_id); return QDF_STATUS_E_ALREADY; @@ -351,6 +801,55 @@ dp_rx_handle_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, } #endif +#ifdef FEATURE_PERPKT_INFO +static inline void +dp_rx_process_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + uint32_t tlv_status, + qdf_nbuf_t status_nbuf) +{ + QDF_STATUS mcopy_status; + + if (qdf_unlikely(!ppdu_info->com_info.mpdu_cnt)) { + qdf_nbuf_free(status_nbuf); + return; + } + /* Add buffers to queue until we receive + * HAL_TLV_STATUS_PPDU_DONE + */ + dp_rx_handle_ppdu_status_buf(pdev, ppdu_info, status_nbuf); + + /* If tlv_status is PPDU_DONE, process rx_ppdu_buf_q + * and devliver fcs_ok msdu buffer + */ + if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) { + if (qdf_unlikely(ppdu_info->com_info.mpdu_cnt != + (ppdu_info->com_info.mpdu_cnt_fcs_ok + + ppdu_info->com_info.mpdu_cnt_fcs_err))) { + qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q); + return; + } + /* Get rx ppdu status buffer having fcs ok msdu */ + status_nbuf = dp_rx_get_fcs_ok_msdu(pdev, ppdu_info); + if (status_nbuf) { + mcopy_status = dp_rx_handle_mcopy_mode(soc, pdev, + ppdu_info, + status_nbuf); + if (mcopy_status == QDF_STATUS_SUCCESS) + qdf_nbuf_free(status_nbuf); + } + } +} +#else +static inline void +dp_rx_process_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + uint32_t tlv_status, + qdf_nbuf_t status_nbuf) +{ +} +#endif + /** * dp_rx_handle_smart_mesh_mode() - Deliver header for smart mesh * @soc: Datapath SOC handle @@ -395,14 +894,321 @@ dp_rx_handle_smart_mesh_mode(struct dp_soc *soc, struct dp_pdev *pdev, /* Only retain RX MSDU payload in the skb */ qdf_nbuf_trim_tail(nbuf, qdf_nbuf_len(nbuf) - ppdu_info->msdu_info.payload_len); - qdf_nbuf_update_radiotap(&(pdev->ppdu_info.rx_status), - nbuf, sizeof(struct rx_pkt_tlvs)); + if (!qdf_nbuf_update_radiotap(&pdev->ppdu_info.rx_status, nbuf, + qdf_nbuf_headroom(nbuf))) { + DP_STATS_INC(pdev, dropped.mon_radiotap_update_err, 1); + return 1; + } + pdev->monitor_vdev->osif_rx_mon(pdev->monitor_vdev->osif_vdev, nbuf, NULL); pdev->ppdu_info.rx_status.monitor_direct_used = 0; return 0; } +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) +/* + * dp_rx_mon_handle_cfr_mu_info() - Gather macaddr and ast_index of peer(s) in + * the PPDU received, this will be used for correlation of CFR data captured + * for an UL-MU-PPDU + * @pdev: pdev ctx + * @ppdu_info: pointer to ppdu info structure populated from ppdu status TLVs + * @cdp_rx_ppdu: Rx PPDU indication structure + * + * Return: none + */ +static inline void +dp_rx_mon_handle_cfr_mu_info(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) +{ + struct dp_peer *peer; + struct dp_soc *soc = pdev->soc; + struct dp_ast_entry *ast_entry; + struct mon_rx_user_status *rx_user_status; + struct cdp_rx_stats_ppdu_user *rx_stats_peruser; + uint32_t num_users; + int user_id; + uint32_t ast_index; + + qdf_spin_lock_bh(&soc->ast_lock); + + num_users = ppdu_info->com_info.num_users; + for (user_id = 0; user_id < num_users; user_id++) { + if (user_id > OFDMA_NUM_USERS) { + qdf_spin_unlock_bh(&soc->ast_lock); + return; + } + + rx_user_status = &ppdu_info->rx_user_status[user_id]; + rx_stats_peruser = &cdp_rx_ppdu->user[user_id]; + ast_index = rx_user_status->ast_index; + + if (ast_index >= wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)) { + rx_stats_peruser->peer_id = HTT_INVALID_PEER; + continue; + } + + ast_entry = soc->ast_table[ast_index]; + if (!ast_entry) { + rx_stats_peruser->peer_id = HTT_INVALID_PEER; + continue; + } + + peer = ast_entry->peer; + if (!peer || peer->peer_ids[0] == HTT_INVALID_PEER) { + rx_stats_peruser->peer_id = HTT_INVALID_PEER; + continue; + } + + qdf_mem_copy(rx_stats_peruser->mac_addr, + peer->mac_addr.raw, QDF_MAC_ADDR_SIZE); + } + + qdf_spin_unlock_bh(&soc->ast_lock); +} + +/* + * dp_rx_mon_populate_cfr_ppdu_info() - Populate cdp ppdu info from hal ppdu + * info + * @pdev: pdev ctx + * @ppdu_info: ppdu info structure from ppdu ring + * @cdp_rx_ppdu : Rx PPDU indication structure + * + * Return: none + */ +static inline void +dp_rx_mon_populate_cfr_ppdu_info(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) +{ + int chain; + + cdp_rx_ppdu->ppdu_id = ppdu_info->com_info.ppdu_id; + cdp_rx_ppdu->timestamp = ppdu_info->rx_status.tsft; + cdp_rx_ppdu->u.ppdu_type = ppdu_info->rx_status.reception_type; + cdp_rx_ppdu->num_users = ppdu_info->com_info.num_users; + + for (chain = 0; chain < MAX_CHAIN; chain++) + cdp_rx_ppdu->per_chain_rssi[chain] = + ppdu_info->rx_status.rssi[chain]; + dp_rx_mon_handle_cfr_mu_info(pdev, ppdu_info, cdp_rx_ppdu); +} + +/** + * dp_cfr_rcc_mode_status() - Return status of cfr rcc mode + * @pdev: pdev ctx + * + * Return: True or False + */ + +static inline bool +dp_cfr_rcc_mode_status(struct dp_pdev *pdev) +{ + return pdev->cfr_rcc_mode; +} + +/* + * dp_rx_mon_populate_cfr_info() - Populate cdp ppdu info from hal cfr info + * @pdev: pdev ctx + * @ppdu_info: ppdu info structure from ppdu ring + * @cdp_rx_ppdu: Rx PPDU indication structure + * + * Return: none + */ +static inline void +dp_rx_mon_populate_cfr_info(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) +{ + struct cdp_rx_ppdu_cfr_info *cfr_info; + + if (!dp_cfr_rcc_mode_status(pdev)) + return; + + cfr_info = &cdp_rx_ppdu->cfr_info; + + cfr_info->bb_captured_channel + = ppdu_info->cfr_info.bb_captured_channel; + cfr_info->bb_captured_timeout + = ppdu_info->cfr_info.bb_captured_timeout; + cfr_info->bb_captured_reason + = ppdu_info->cfr_info.bb_captured_reason; + cfr_info->rx_location_info_valid + = ppdu_info->cfr_info.rx_location_info_valid; + cfr_info->chan_capture_status + = ppdu_info->cfr_info.chan_capture_status; + cfr_info->rtt_che_buffer_pointer_high8 + = ppdu_info->cfr_info.rtt_che_buffer_pointer_high8; + cfr_info->rtt_che_buffer_pointer_low32 + = ppdu_info->cfr_info.rtt_che_buffer_pointer_low32; +} + +/** + * dp_update_cfr_dbg_stats() - Increment RCC debug statistics + * @pdev: pdev structure + * @ppdu_info: structure for rx ppdu ring + * + * Return: none + */ +static inline void +dp_update_cfr_dbg_stats(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info) +{ + struct hal_rx_ppdu_cfr_info *cfr = &ppdu_info->cfr_info; + + DP_STATS_INC(pdev, + rcc.chan_capture_status[cfr->chan_capture_status], 1); + if (cfr->rx_location_info_valid) { + DP_STATS_INC(pdev, rcc.rx_loc_info_valid_cnt, 1); + if (cfr->bb_captured_channel) { + DP_STATS_INC(pdev, rcc.bb_captured_channel_cnt, 1); + DP_STATS_INC(pdev, + rcc.reason_cnt[cfr->bb_captured_reason], + 1); + } else if (cfr->bb_captured_timeout) { + DP_STATS_INC(pdev, rcc.bb_captured_timeout_cnt, 1); + DP_STATS_INC(pdev, + rcc.reason_cnt[cfr->bb_captured_reason], + 1); + } + } +} + +/* + * dp_rx_handle_cfr() - Gather cfr info from hal ppdu info + * @soc: core txrx main context + * @pdev: pdev ctx + * @ppdu_info: ppdu info structure from ppdu ring + * + * Return: none + */ +static inline void +dp_rx_handle_cfr(struct dp_soc *soc, struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info) +{ + qdf_nbuf_t ppdu_nbuf; + struct cdp_rx_indication_ppdu *cdp_rx_ppdu; + + dp_update_cfr_dbg_stats(pdev, ppdu_info); + if (!ppdu_info->cfr_info.bb_captured_channel) + return; + + ppdu_nbuf = qdf_nbuf_alloc(soc->osdev, + sizeof(struct cdp_rx_indication_ppdu), + 0, + 0, + FALSE); + if (ppdu_nbuf) { + cdp_rx_ppdu = (struct cdp_rx_indication_ppdu *)ppdu_nbuf->data; + + dp_rx_mon_populate_cfr_info(pdev, ppdu_info, cdp_rx_ppdu); + dp_rx_mon_populate_cfr_ppdu_info(pdev, ppdu_info, cdp_rx_ppdu); + qdf_nbuf_put_tail(ppdu_nbuf, + sizeof(struct cdp_rx_indication_ppdu)); + dp_wdi_event_handler(WDI_EVENT_RX_PPDU_DESC, soc, + ppdu_nbuf, HTT_INVALID_PEER, + WDI_NO_VAL, pdev->pdev_id); + } +} + +/** + * dp_rx_populate_cfr_non_assoc_sta() - Populate cfr ppdu info for PPDUs from + * non-associated stations + * @pdev: pdev ctx + * @ppdu_info: ppdu info structure from ppdu ring + * @cdp_rx_ppdu: Rx PPDU indication structure + * + * Return: none + */ +static inline void +dp_rx_populate_cfr_non_assoc_sta(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) +{ + if (!dp_cfr_rcc_mode_status(pdev)) + return; + + if (ppdu_info->cfr_info.bb_captured_channel) + dp_rx_mon_populate_cfr_ppdu_info(pdev, ppdu_info, cdp_rx_ppdu); +} + +/** + * dp_bb_captured_chan_status() - Get the bb_captured_channel status + * @ppdu_info: structure for rx ppdu ring + * + * Return: Success/ Failure + */ + +static inline QDF_STATUS +dp_bb_captured_chan_status(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct hal_rx_ppdu_cfr_info *cfr = &ppdu_info->cfr_info; + + if (dp_cfr_rcc_mode_status(pdev)) { + if (cfr->bb_captured_channel) + status = QDF_STATUS_SUCCESS; + } + + return status; +} +#else +static inline void +dp_rx_mon_handle_cfr_mu_info(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) +{ +} + +static inline void +dp_rx_mon_populate_cfr_ppdu_info(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) +{ +} + +static inline void +dp_rx_mon_populate_cfr_info(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) +{ +} + +static inline void +dp_rx_handle_cfr(struct dp_soc *soc, struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info) +{ +} + +static inline void +dp_rx_populate_cfr_non_assoc_sta(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + struct cdp_rx_indication_ppdu *cdp_rx_ppdu) +{ +} + +static inline void +dp_update_cfr_dbg_stats(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info) +{ +} + +static inline QDF_STATUS +dp_bb_captured_chan_status(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info) +{ + return QDF_STATUS_E_NOSUPPORT; +} + +static inline bool +dp_cfr_rcc_mode_status(struct dp_pdev *pdev) +{ + return false; +} +#endif + /** * dp_rx_handle_ppdu_stats() - Allocate and deliver ppdu stats to cdp layer * @soc: core txrx main context @@ -417,12 +1223,13 @@ dp_rx_handle_ppdu_stats(struct dp_soc *soc, struct dp_pdev *pdev, struct hal_rx_ppdu_info *ppdu_info) { qdf_nbuf_t ppdu_nbuf; - struct dp_peer *peer; struct cdp_rx_indication_ppdu *cdp_rx_ppdu; /* * Do not allocate if fcs error, * ast idx invalid / fctl invalid + * + * In CFR RCC mode - PPDU status TLVs of error pkts are also needed */ if (ppdu_info->com_info.mpdu_cnt_fcs_ok == 0) return; @@ -448,41 +1255,46 @@ dp_rx_handle_ppdu_stats(struct dp_soc *soc, struct dp_pdev *pdev, qdf_spin_unlock_bh(&pdev->neighbour_peer_mutex); } - /* need not generate wdi event when mcopy and + /* need not generate wdi event when mcopy, cfr rcc mode and * enhanced stats are not enabled */ - if (!pdev->mcopy_mode && !pdev->enhanced_stats_en) + if (!pdev->mcopy_mode && !pdev->enhanced_stats_en && + !dp_cfr_rcc_mode_status(pdev)) return; - if (!pdev->mcopy_mode) { - if (!ppdu_info->rx_status.frame_control_info_valid) - return; + if (dp_cfr_rcc_mode_status(pdev)) + dp_update_cfr_dbg_stats(pdev, ppdu_info); - if (ppdu_info->rx_status.ast_index == HAL_AST_IDX_INVALID) + if (!ppdu_info->rx_status.frame_control_info_valid || + (ppdu_info->rx_status.ast_index == HAL_AST_IDX_INVALID)) { + if (!(pdev->mcopy_mode || + (dp_bb_captured_chan_status(pdev, ppdu_info) == + QDF_STATUS_SUCCESS))) return; } + ppdu_nbuf = qdf_nbuf_alloc(soc->osdev, - sizeof(struct cdp_rx_indication_ppdu), 0, 0, FALSE); + sizeof(struct cdp_rx_indication_ppdu), + 0, 0, FALSE); if (ppdu_nbuf) { - dp_rx_populate_cdp_indication_ppdu(pdev, ppdu_info, ppdu_nbuf); - qdf_nbuf_put_tail(ppdu_nbuf, - sizeof(struct cdp_rx_indication_ppdu)); cdp_rx_ppdu = (struct cdp_rx_indication_ppdu *)ppdu_nbuf->data; - peer = dp_peer_find_by_id(soc, cdp_rx_ppdu->peer_id); - if (peer) { - cdp_rx_ppdu->cookie = (void *)peer->wlanstats_ctx; - dp_rx_stats_update(pdev, peer, cdp_rx_ppdu); - dp_peer_unref_del_find_by_id(peer); - } + + dp_rx_mon_populate_cfr_info(pdev, ppdu_info, cdp_rx_ppdu); + dp_rx_populate_cdp_indication_ppdu(pdev, + ppdu_info, cdp_rx_ppdu); + qdf_nbuf_put_tail(ppdu_nbuf, + sizeof(struct cdp_rx_indication_ppdu)); + dp_rx_stats_update(pdev, cdp_rx_ppdu); + if (cdp_rx_ppdu->peer_id != HTT_INVALID_PEER) { dp_wdi_event_handler(WDI_EVENT_RX_PPDU_DESC, soc, ppdu_nbuf, cdp_rx_ppdu->peer_id, WDI_NO_VAL, pdev->pdev_id); - } else if (pdev->mcopy_mode) { + } else if (pdev->mcopy_mode || dp_cfr_rcc_mode_status(pdev)) { dp_wdi_event_handler(WDI_EVENT_RX_PPDU_DESC, soc, - ppdu_nbuf, HTT_INVALID_PEER, - WDI_NO_VAL, pdev->pdev_id); + ppdu_nbuf, HTT_INVALID_PEER, + WDI_NO_VAL, pdev->pdev_id); } else { qdf_nbuf_free(ppdu_nbuf); } @@ -516,7 +1328,7 @@ dp_rx_process_peer_based_pktlog(struct dp_soc *soc, uint32_t ast_index; ast_index = ppdu_info->rx_status.ast_index; - if (ast_index < (WLAN_UMAC_PSOC_MAX_PEERS * 2)) { + if (ast_index < wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)) { ast_entry = soc->ast_table[ast_index]; if (ast_entry) { peer = ast_entry->peer; @@ -533,6 +1345,102 @@ dp_rx_process_peer_based_pktlog(struct dp_soc *soc, } } +#if defined(HTT_UL_OFDMA_USER_INFO_V0_W0_VALID_M) +static inline void +dp_rx_ul_ofdma_ru_size_to_width( + uint32_t ru_size, + uint32_t *ru_width) +{ + uint32_t width; + + width = 0; + switch (ru_size) { + case HTT_UL_OFDMA_V0_RU_SIZE_RU_26: + width = 1; + break; + case HTT_UL_OFDMA_V0_RU_SIZE_RU_52: + width = 2; + break; + case HTT_UL_OFDMA_V0_RU_SIZE_RU_106: + width = 4; + break; + case HTT_UL_OFDMA_V0_RU_SIZE_RU_242: + width = 9; + break; + case HTT_UL_OFDMA_V0_RU_SIZE_RU_484: + width = 18; + break; + case HTT_UL_OFDMA_V0_RU_SIZE_RU_996: + width = 37; + break; + case HTT_UL_OFDMA_V0_RU_SIZE_RU_996x2: + width = 74; + break; + default: + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "RU size to width convert err"); + break; + } + *ru_width = width; +} + +static inline void +dp_rx_mon_handle_mu_ul_info(struct hal_rx_ppdu_info *ppdu_info) +{ + struct mon_rx_user_status *mon_rx_user_status; + uint32_t num_users; + uint32_t i; + uint32_t mu_ul_user_v0_word0; + uint32_t mu_ul_user_v0_word1; + uint32_t ru_width; + uint32_t ru_size; + + if (!(ppdu_info->rx_status.reception_type == HAL_RX_TYPE_MU_OFDMA || + ppdu_info->rx_status.reception_type == HAL_RX_TYPE_MU_MIMO)) + return; + + num_users = ppdu_info->com_info.num_users; + if (num_users > HAL_MAX_UL_MU_USERS) + num_users = HAL_MAX_UL_MU_USERS; + for (i = 0; i < num_users; i++) { + mon_rx_user_status = &ppdu_info->rx_user_status[i]; + mu_ul_user_v0_word0 = + mon_rx_user_status->mu_ul_user_v0_word0; + mu_ul_user_v0_word1 = + mon_rx_user_status->mu_ul_user_v0_word1; + + if (HTT_UL_OFDMA_USER_INFO_V0_W0_VALID_GET( + mu_ul_user_v0_word0) && + !HTT_UL_OFDMA_USER_INFO_V0_W0_VER_GET( + mu_ul_user_v0_word0)) { + mon_rx_user_status->mcs = + HTT_UL_OFDMA_USER_INFO_V0_W1_MCS_GET( + mu_ul_user_v0_word1); + mon_rx_user_status->nss = + HTT_UL_OFDMA_USER_INFO_V0_W1_NSS_GET( + mu_ul_user_v0_word1) + 1; + + mon_rx_user_status->mu_ul_info_valid = 1; + mon_rx_user_status->ofdma_ru_start_index = + HTT_UL_OFDMA_USER_INFO_V0_W1_RU_START_GET( + mu_ul_user_v0_word1); + + ru_size = + HTT_UL_OFDMA_USER_INFO_V0_W1_RU_SIZE_GET( + mu_ul_user_v0_word1); + dp_rx_ul_ofdma_ru_size_to_width(ru_size, &ru_width); + mon_rx_user_status->ofdma_ru_width = ru_width; + mon_rx_user_status->ofdma_ru_size = ru_size; + } + } +} +#else +static inline void +dp_rx_mon_handle_mu_ul_info(struct hal_rx_ppdu_info *ppdu_info) +{ +} +#endif + /** * dp_rx_mon_status_process_tlv() - Process status TLV in status * buffer on Rx status Queue posted by status SRNG processing. @@ -545,13 +1453,12 @@ static inline void dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) { - struct dp_pdev *pdev = dp_get_pdev_for_mac_id(soc, mac_id); + struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id); struct hal_rx_ppdu_info *ppdu_info; qdf_nbuf_t status_nbuf; uint8_t *rx_tlv; uint8_t *rx_tlv_start; uint32_t tlv_status = HAL_TLV_STATUS_BUF_DONE; - QDF_STATUS m_copy_status = QDF_STATUS_SUCCESS; QDF_STATUS enh_log_status = QDF_STATUS_SUCCESS; struct cdp_pdev_mon_stats *rx_mon_stats; int smart_mesh_status; @@ -577,11 +1484,12 @@ dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id, nbuf_used = false; if ((pdev->monitor_vdev) || (pdev->enhanced_stats_en) || - pdev->mcopy_mode || + (pdev->mcopy_mode) || (dp_cfr_rcc_mode_status(pdev)) || (rx_enh_capture_mode != CDP_RX_ENH_CAPTURE_DISABLED)) { do { tlv_status = hal_rx_status_get_tlv_info(rx_tlv, - ppdu_info, pdev->soc->hal_soc); + ppdu_info, pdev->soc->hal_soc, + status_nbuf); dp_rx_mon_update_dbg_ppdu_stats(ppdu_info, rx_mon_stats); @@ -592,7 +1500,8 @@ dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id, rx_tlv = hal_rx_status_get_next_tlv(rx_tlv); - if ((rx_tlv - rx_tlv_start) >= RX_BUFFER_SIZE) + if ((rx_tlv - rx_tlv_start) >= + RX_DATA_BUFFER_SIZE) break; } while ((tlv_status == HAL_TLV_STATUS_PPDU_NOT_DONE) || @@ -623,11 +1532,10 @@ dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id, pdev, ppdu_info, status_nbuf); if (smart_mesh_status) qdf_nbuf_free(status_nbuf); - } else if (pdev->mcopy_mode) { - m_copy_status = dp_rx_handle_mcopy_mode(soc, - pdev, ppdu_info, status_nbuf); - if (m_copy_status == QDF_STATUS_SUCCESS) - qdf_nbuf_free(status_nbuf); + } else if (qdf_unlikely(pdev->mcopy_mode)) { + dp_rx_process_mcopy_mode(soc, pdev, + ppdu_info, tlv_status, + status_nbuf); } else if (rx_enh_capture_mode != CDP_RX_ENH_CAPTURE_DISABLED) { if (!nbuf_used) qdf_nbuf_free(status_nbuf); @@ -644,11 +1552,36 @@ dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id, dp_rx_mon_deliver_non_std(soc, mac_id); } else if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) { rx_mon_stats->status_ppdu_done++; + dp_rx_mon_handle_mu_ul_info(ppdu_info); + + if (pdev->tx_capture_enabled + != CDP_TX_ENH_CAPTURE_DISABLED) + dp_send_ack_frame_to_stack(soc, pdev, + ppdu_info); + if (pdev->enhanced_stats_en || pdev->mcopy_mode || pdev->neighbour_peers_added) dp_rx_handle_ppdu_stats(soc, pdev, ppdu_info); + else if (dp_cfr_rcc_mode_status(pdev)) + dp_rx_handle_cfr(soc, pdev, ppdu_info); pdev->mon_ppdu_status = DP_PPDU_STATUS_DONE; + + /* + * if chan_num is not fetched correctly from ppdu RX TLV, + * get it from pdev saved. + */ + if (qdf_unlikely(pdev->ppdu_info.rx_status.chan_num == 0)) + pdev->ppdu_info.rx_status.chan_num = pdev->mon_chan_num; + /* + * if chan_freq is not fetched correctly from ppdu RX TLV, + * get it from pdev saved. + */ + if (qdf_unlikely(pdev->ppdu_info.rx_status.chan_freq == 0)) { + pdev->ppdu_info.rx_status.chan_freq = + pdev->mon_chan_freq; + } + dp_rx_mon_dest_process(soc, mac_id, quota); pdev->mon_ppdu_status = DP_PPDU_STATUS_START; } @@ -673,15 +1606,14 @@ static inline uint32_t dp_rx_mon_status_srng_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) { - struct dp_pdev *pdev = dp_get_pdev_for_mac_id(soc, mac_id); - void *hal_soc; + struct dp_pdev *pdev = dp_get_pdev_for_lmac_id(soc, mac_id); + hal_soc_handle_t hal_soc; void *mon_status_srng; void *rxdma_mon_status_ring_entry; QDF_STATUS status; uint32_t work_done = 0; - int mac_for_pdev = dp_get_mac_id_for_mac(soc, mac_id); - mon_status_srng = pdev->rxdma_mon_status_ring[mac_for_pdev].hal_srng; + mon_status_srng = soc->rxdma_mon_status_ring[mac_id].hal_srng; qdf_assert(mon_status_srng); if (!mon_status_srng || !hal_srng_initialized(mon_status_srng)) { @@ -748,7 +1680,7 @@ dp_rx_mon_status_srng_process(struct dp_soc *soc, uint32_t mac_id, hal_srng_src_get_next(hal_soc, mon_status_srng); continue; } - qdf_nbuf_set_pktlen(status_nbuf, RX_BUFFER_SIZE); + qdf_nbuf_set_pktlen(status_nbuf, RX_DATA_BUFFER_SIZE); qdf_nbuf_unmap_single(soc->osdev, status_nbuf, QDF_DMA_FROM_DEVICE); @@ -848,6 +1780,8 @@ dp_rx_mon_status_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) { return work_done; } + +#ifndef DISABLE_MON_CONFIG /** * dp_mon_process() - Main monitor mode processing roution. * This call monitor status ring process then monitor @@ -863,6 +1797,12 @@ uint32_t dp_mon_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) { return dp_rx_mon_status_process(soc, mac_id, quota); } +#else +uint32_t +dp_mon_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) { + return 0; +} +#endif /** * dp_rx_pdev_mon_status_detach() - detach dp rx for status ring @@ -931,7 +1871,7 @@ QDF_STATUS dp_rx_mon_status_buffers_replenish(struct dp_soc *dp_soc, void *rxdma_ring_entry; union dp_rx_desc_list_elem_t *next; void *rxdma_srng; - struct dp_pdev *dp_pdev = dp_get_pdev_for_mac_id(dp_soc, mac_id); + struct dp_pdev *dp_pdev = dp_get_pdev_for_lmac_id(dp_soc, mac_id); rxdma_srng = dp_rxdma_srng->hal_srng; @@ -1066,9 +2006,8 @@ dp_rx_pdev_mon_status_attach(struct dp_pdev *pdev, int ring_id) { uint32_t i; struct rx_desc_pool *rx_desc_pool; QDF_STATUS status; - int mac_for_pdev = dp_get_mac_id_for_mac(soc, ring_id); - mon_status_ring = &pdev->rxdma_mon_status_ring[mac_for_pdev]; + mon_status_ring = &soc->rxdma_mon_status_ring[ring_id]; num_entries = mon_status_ring->num_entries; @@ -1077,11 +2016,15 @@ dp_rx_pdev_mon_status_attach(struct dp_pdev *pdev, int ring_id) { dp_info("Mon RX Status Pool[%d] entries=%d", ring_id, num_entries); + rx_desc_pool->desc_type = DP_RX_DESC_STATUS_TYPE; status = dp_rx_desc_pool_alloc(soc, ring_id, num_entries + 1, rx_desc_pool); if (!QDF_IS_STATUS_SUCCESS(status)) return status; + rx_desc_pool->buf_size = RX_DATA_BUFFER_SIZE; + rx_desc_pool->buf_alignment = RX_DATA_BUFFER_ALIGNMENT; + dp_debug("Mon RX Status Buffers Replenish ring_id=%d", ring_id); status = dp_rx_mon_status_buffers_replenish(soc, ring_id, @@ -1095,6 +2038,7 @@ dp_rx_pdev_mon_status_attach(struct dp_pdev *pdev, int ring_id) { return status; qdf_nbuf_queue_init(&pdev->rx_status_q); + qdf_nbuf_queue_init(&pdev->rx_ppdu_buf_q); pdev->mon_ppdu_status = DP_PPDU_STATUS_START; diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_stats.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_stats.c index 6162e734e77fdecd8488eb97240e8944f207f21e..094e1214f2587ca00633fb4218432e8c24df1445 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_stats.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_stats.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -56,7 +57,7 @@ #define DP_NSS_LENGTH (6 * SS_COUNT) #define DP_MU_GROUP_LENGTH (6 * DP_MU_GROUP_SHOW) #define DP_MU_GROUP_SHOW 16 -#define DP_MAX_MCS_STRING_LEN 30 +#define DP_MAX_MCS_STRING_LEN 34 #define DP_RXDMA_ERR_LENGTH (6 * HAL_RXDMA_ERR_MAX) #define DP_REO_ERR_LENGTH (6 * HAL_REO_ERR_MAX) #define STATS_PROC_TIMEOUT (HZ / 1000) @@ -153,7 +154,62 @@ static const struct dp_rate_debug dp_rate_string[DOT11_MAX][MAX_MCS] = { } }; -#ifdef CONFIG_WIN +static const struct dp_rate_debug dp_ppdu_rate_string[DOT11_MAX][MAX_MCS] = { + { + {"HE MCS 0 (BPSK 1/2) ", MCS_VALID}, + {"HE MCS 1 (QPSK 1/2) ", MCS_VALID}, + {"HE MCS 2 (QPSK 3/4) ", MCS_VALID}, + {"HE MCS 3 (16-QAM 1/2) ", MCS_VALID}, + {"HE MCS 4 (16-QAM 3/4) ", MCS_VALID}, + {"HE MCS 5 (64-QAM 2/3) ", MCS_VALID}, + {"HE MCS 6 (64-QAM 3/4) ", MCS_VALID}, + {"HE MCS 7 (64-QAM 5/6) ", MCS_VALID}, + {"HE MCS 8 (256-QAM 3/4) ", MCS_VALID}, + {"HE MCS 9 (256-QAM 5/6) ", MCS_VALID}, + {"HE MCS 10 (1024-QAM 3/4)", MCS_VALID}, + {"HE MCS 11 (1024-QAM 5/6)", MCS_VALID}, + {"INVALID ", MCS_VALID}, + } +}; + +static const struct dp_rate_debug dp_mu_rate_string[RX_TYPE_MU_MAX][MAX_MCS] = { + { + {"HE MU-MIMO MCS 0 (BPSK 1/2) ", MCS_VALID}, + {"HE MU-MIMO MCS 1 (QPSK 1/2) ", MCS_VALID}, + {"HE MU-MIMO MCS 2 (QPSK 3/4) ", MCS_VALID}, + {"HE MU-MIMO MCS 3 (16-QAM 1/2) ", MCS_VALID}, + {"HE MU-MIMO MCS 4 (16-QAM 3/4) ", MCS_VALID}, + {"HE MU-MIMO MCS 5 (64-QAM 2/3) ", MCS_VALID}, + {"HE MU-MIMO MCS 6 (64-QAM 3/4) ", MCS_VALID}, + {"HE MU-MIMO MCS 7 (64-QAM 5/6) ", MCS_VALID}, + {"HE MU-MIMO MCS 8 (256-QAM 3/4) ", MCS_VALID}, + {"HE MU-MIMO MCS 9 (256-QAM 5/6) ", MCS_VALID}, + {"HE MU-MIMO MCS 10 (1024-QAM 3/4)", MCS_VALID}, + {"HE MU-MIMO MCS 11 (1024-QAM 5/6)", MCS_VALID}, + {"INVALID ", MCS_VALID}, + }, + { + {"HE OFDMA MCS 0 (BPSK 1/2) ", MCS_VALID}, + {"HE OFDMA MCS 1 (QPSK 1/2) ", MCS_VALID}, + {"HE OFDMA MCS 2 (QPSK 3/4) ", MCS_VALID}, + {"HE OFDMA MCS 3 (16-QAM 1/2) ", MCS_VALID}, + {"HE OFDMA MCS 4 (16-QAM 3/4) ", MCS_VALID}, + {"HE OFDMA MCS 5 (64-QAM 2/3) ", MCS_VALID}, + {"HE OFDMA MCS 6 (64-QAM 3/4) ", MCS_VALID}, + {"HE OFDMA MCS 7 (64-QAM 5/6) ", MCS_VALID}, + {"HE OFDMA MCS 8 (256-QAM 3/4) ", MCS_VALID}, + {"HE OFDMA MCS 9 (256-QAM 5/6) ", MCS_VALID}, + {"HE OFDMA MCS 10 (1024-QAM 3/4)", MCS_VALID}, + {"HE OFDMA MCS 11 (1024-QAM 5/6)", MCS_VALID}, + {"INVALID ", MCS_VALID}, + }, +}; + +const char *mu_reception_mode[RX_TYPE_MU_MAX] = { + "MU MIMO", "MU OFDMA" +}; + +#ifdef QCA_ENH_V3_STATS_SUPPORT const char *fw_to_hw_delay_bucket[CDP_DELAY_BUCKET_MAX + 1] = { "0 to 10 ms", "11 to 20 ms", "21 to 30 ms", "31 to 40 ms", @@ -2894,7 +2950,8 @@ static void dp_print_tx_pdev_rate_stats_tlv(uint32_t *tag_buf) * * return:void */ -static inline void dp_print_rx_pdev_rate_stats_tlv(uint32_t *tag_buf) +static void dp_print_rx_pdev_rate_stats_tlv(struct dp_pdev *pdev, + uint32_t *tag_buf) { htt_rx_pdev_rate_stats_tlv *dp_stats_buf = (htt_rx_pdev_rate_stats_tlv *)tag_buf; @@ -2932,6 +2989,34 @@ static inline void dp_print_rx_pdev_rate_stats_tlv(uint32_t *tag_buf) } } + DP_PRINT_STATS("ul_ofdma_data_rx_ppdu = %d", + pdev->stats.ul_ofdma.data_rx_ppdu); + + for (i = 0; i < OFDMA_NUM_USERS; i++) { + DP_PRINT_STATS("ul_ofdma data %d user = %d", + i, pdev->stats.ul_ofdma.data_users[i]); + } + + index = 0; + qdf_mem_zero(str_buf, DP_MAX_STRING_LEN); + for (i = 0; i < OFDMA_NUM_RU_SIZE; i++) { + index += qdf_snprint(&str_buf[index], + DP_MAX_STRING_LEN - index, + " %u:%u,", i, + pdev->stats.ul_ofdma.data_rx_ru_size[i]); + } + DP_PRINT_STATS("ul_ofdma_data_rx_ru_size= %s", str_buf); + + index = 0; + qdf_mem_zero(str_buf, DP_MAX_STRING_LEN); + for (i = 0; i < OFDMA_NUM_RU_SIZE; i++) { + index += qdf_snprint(&str_buf[index], + DP_MAX_STRING_LEN - index, + " %u:%u,", i, + pdev->stats.ul_ofdma.nondata_rx_ru_size[i]); + } + DP_PRINT_STATS("ul_ofdma_nondata_rx_ru_size= %s", str_buf); + DP_PRINT_STATS("HTT_RX_PDEV_RATE_STATS_TLV:"); DP_PRINT_STATS("mac_id__word = %u", dp_stats_buf->mac_id__word); @@ -2947,7 +3032,7 @@ static inline void dp_print_rx_pdev_rate_stats_tlv(uint32_t *tag_buf) dp_stats_buf->rssi_data); DP_PRINT_STATS("rssi_comb = %u", dp_stats_buf->rssi_comb); - DP_PRINT_STATS("rx_in_dbm = %u", + DP_PRINT_STATS("rssi_in_dbm = %d", dp_stats_buf->rssi_in_dbm); DP_PRINT_STATS("rx_11ax_su_ext = %u", dp_stats_buf->rx_11ax_su_ext); @@ -2960,6 +3045,7 @@ static inline void dp_print_rx_pdev_rate_stats_tlv(uint32_t *tag_buf) DP_PRINT_STATS("txbf = %u", dp_stats_buf->txbf); + index = 0; qdf_mem_zero(str_buf, DP_MAX_STRING_LEN); for (i = 0; i < DP_HTT_RX_MCS_LEN; i++) { index += qdf_snprint(&str_buf[index], @@ -3592,12 +3678,14 @@ static inline void dp_print_rx_pdev_fw_stats_phy_err_tlv(uint32_t *tag_buf) /* * dp_htt_stats_print_tag: function to select the tag type and * print the corresponding tag structure + * @pdev: pdev pointer * @tag_type: tag type that is to be printed * @tag_buf: pointer to the tag structure * * return: void */ -void dp_htt_stats_print_tag(uint8_t tag_type, uint32_t *tag_buf) +void dp_htt_stats_print_tag(struct dp_pdev *pdev, + uint8_t tag_type, uint32_t *tag_buf) { switch (tag_type) { case HTT_STATS_TX_PDEV_CMN_TAG: @@ -3739,7 +3827,7 @@ void dp_htt_stats_print_tag(uint8_t tag_type, uint32_t *tag_buf) break; case HTT_STATS_RX_PDEV_RATE_STATS_TAG: - dp_print_rx_pdev_rate_stats_tlv(tag_buf); + dp_print_rx_pdev_rate_stats_tlv(pdev, tag_buf); break; case HTT_STATS_TX_PDEV_SCHEDULER_TXQ_STATS_TAG: @@ -3834,11 +3922,9 @@ void dp_htt_stats_print_tag(uint8_t tag_type, uint32_t *tag_buf) dp_print_tx_tid_stats_tlv(tag_buf); break; -#ifdef CONFIG_WIN case HTT_STATS_TX_TID_DETAILS_V1_TAG: dp_print_tx_tid_stats_v1_tlv(tag_buf); break; -#endif case HTT_STATS_RX_TID_DETAILS_TAG: dp_print_rx_tid_stats_tlv(tag_buf); @@ -3955,16 +4041,128 @@ void dp_htt_stats_copy_tag(struct dp_pdev *pdev, uint8_t tag_type, uint32_t *tag if (dest_ptr) qdf_mem_copy(dest_ptr, tag_buf, size); } -QDF_STATUS dp_peer_stats_notify(struct dp_peer *peer) + +#ifdef VDEV_PEER_PROTOCOL_COUNT +#ifdef VDEV_PEER_PROTOCOL_COUNT_TESTING +static QDF_STATUS dp_peer_stats_update_protocol_test_cnt(struct dp_vdev *vdev, + bool is_egress, + bool is_rx) +{ + int mask; + + if (is_egress) + if (is_rx) + mask = VDEV_PEER_PROTOCOL_RX_EGRESS_MASK; + else + mask = VDEV_PEER_PROTOCOL_TX_EGRESS_MASK; + else + if (is_rx) + mask = VDEV_PEER_PROTOCOL_RX_INGRESS_MASK; + else + mask = VDEV_PEER_PROTOCOL_TX_INGRESS_MASK; + + if (qdf_unlikely(vdev->peer_protocol_count_dropmask & mask)) { + dp_info("drop mask set %x", vdev->peer_protocol_count_dropmask); + return QDF_STATUS_SUCCESS; + } + return QDF_STATUS_E_FAILURE; +} + +#else +static QDF_STATUS dp_peer_stats_update_protocol_test_cnt(struct dp_vdev *vdev, + bool is_egress, + bool is_rx) +{ + return QDF_STATUS_E_FAILURE; +} +#endif + +void dp_vdev_peer_stats_update_protocol_cnt(struct dp_vdev *vdev, + qdf_nbuf_t nbuf, + struct dp_peer *peer, + bool is_egress, + bool is_rx) +{ + struct cdp_peer_stats *peer_stats; + struct protocol_trace_count *protocol_trace_cnt; + enum cdp_protocol_trace prot; + struct dp_soc *soc; + struct ether_header *eh; + char *mac; + bool new_peer_ref = false; + + if (qdf_likely(!vdev->peer_protocol_count_track)) + return; + if (qdf_unlikely(dp_peer_stats_update_protocol_test_cnt(vdev, + is_egress, + is_rx) == + QDF_STATUS_SUCCESS)) + return; + + soc = vdev->pdev->soc; + eh = (struct ether_header *)qdf_nbuf_data(nbuf); + if (is_rx) + mac = eh->ether_shost; + else + mac = eh->ether_dhost; + + if (!peer) { + peer = dp_peer_find_hash_find(soc, mac, 0, vdev->vdev_id); + new_peer_ref = true; + if (!peer) + return; + } + peer_stats = &peer->stats; + + if (qdf_nbuf_is_icmp_pkt(nbuf) == true) + prot = CDP_TRACE_ICMP; + else if (qdf_nbuf_is_ipv4_arp_pkt(nbuf) == true) + prot = CDP_TRACE_ARP; + else if (qdf_nbuf_is_ipv4_eapol_pkt(nbuf) == true) + prot = CDP_TRACE_EAP; + else + goto dp_vdev_peer_stats_update_protocol_cnt_free_peer; + + if (is_rx) + protocol_trace_cnt = peer_stats->rx.protocol_trace_cnt; + else + protocol_trace_cnt = peer_stats->tx.protocol_trace_cnt; + + if (is_egress) + protocol_trace_cnt[prot].egress_cnt++; + else + protocol_trace_cnt[prot].ingress_cnt++; +dp_vdev_peer_stats_update_protocol_cnt_free_peer: + if (new_peer_ref) + dp_peer_unref_delete(peer); +} + +void dp_peer_stats_update_protocol_cnt(struct cdp_soc_t *soc, + int8_t vdev_id, + qdf_nbuf_t nbuf, + bool is_egress, + bool is_rx) +{ + struct dp_vdev *vdev; + + vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + if (qdf_likely(!vdev->peer_protocol_count_track)) + return; + dp_vdev_peer_stats_update_protocol_cnt(vdev, nbuf, NULL, is_egress, + is_rx); +} +#endif + +#ifdef WDI_EVENT_ENABLE +QDF_STATUS dp_peer_stats_notify(struct dp_pdev *dp_pdev, struct dp_peer *peer) { - struct dp_pdev *dp_pdev; struct cdp_interface_peer_stats peer_stats_intf; struct cdp_peer_stats *peer_stats = &peer->stats; if (!peer->vdev) return QDF_STATUS_E_FAULT; - dp_pdev = peer->vdev->pdev; qdf_mem_zero(&peer_stats_intf, sizeof(peer_stats_intf)); if (peer_stats->rx.last_rssi != peer_stats->rx.rssi) peer_stats_intf.rssi_changed = true; @@ -3972,7 +4170,9 @@ QDF_STATUS dp_peer_stats_notify(struct dp_peer *peer) if ((peer_stats->rx.rssi && peer_stats_intf.rssi_changed) || (peer_stats->tx.tx_rate && peer_stats->tx.tx_rate != peer_stats->tx.last_tx_rate)) { - peer_stats_intf.peer_hdl = peer->ctrl_peer; + qdf_mem_copy(peer_stats_intf.peer_mac, peer->mac_addr.raw, + QDF_MAC_ADDR_SIZE); + peer_stats_intf.vdev_id = peer->vdev->vdev_id; peer_stats_intf.last_peer_tx_rate = peer_stats->tx.last_tx_rate; peer_stats_intf.peer_tx_rate = peer_stats->tx.tx_rate; peer_stats_intf.peer_rssi = peer_stats->rx.rssi; @@ -3989,8 +4189,9 @@ QDF_STATUS dp_peer_stats_notify(struct dp_peer *peer) return QDF_STATUS_SUCCESS; } +#endif -#ifdef CONFIG_WIN +#ifdef QCA_ENH_V3_STATS_SUPPORT /** * dp_vow_str_fw_to_hw_delay() - Return string for a delay * @index: Index of delay @@ -4068,7 +4269,7 @@ dp_accumulate_tid_stats(struct dp_pdev *pdev, uint8_t tid, struct cdp_tid_tx_stats *total_tx, struct cdp_tid_rx_stats *total_rx, uint8_t type) { - uint8_t ring_id = 0, drop = 0; + uint8_t ring_id = 0, drop = 0, tqm_status_idx = 0, htt_status_idx = 0; struct cdp_tid_stats *tid_stats = &pdev->stats.tid_stats; struct cdp_tid_tx_stats *per_ring_tx = NULL; struct cdp_tid_rx_stats *per_ring_rx = NULL; @@ -4090,7 +4291,16 @@ dp_accumulate_tid_stats(struct dp_pdev *pdev, uint8_t tid, for (ring_id = 0; ring_id < CDP_MAX_TX_COMP_RINGS; ring_id++) { per_ring_tx = &tid_stats->tid_tx_stats[ring_id][tid]; total_tx->success_cnt += per_ring_tx->success_cnt; - total_tx->comp_fail_cnt += per_ring_tx->comp_fail_cnt; + for (tqm_status_idx = 0; tqm_status_idx < CDP_MAX_TX_TQM_STATUS; tqm_status_idx++) { + total_tx->tqm_status_cnt[tqm_status_idx] += + per_ring_tx->tqm_status_cnt[tqm_status_idx]; + } + + for (htt_status_idx = 0; htt_status_idx < CDP_MAX_TX_HTT_STATUS; htt_status_idx++) { + total_tx->htt_status_cnt[htt_status_idx] += + per_ring_tx->htt_status_cnt[htt_status_idx]; + } + for (drop = 0; drop < TX_MAX_DROP; drop++) total_tx->swdrop_cnt[drop] += per_ring_tx->swdrop_cnt[drop]; @@ -4141,7 +4351,7 @@ void dp_pdev_print_tid_stats(struct dp_pdev *pdev) { struct cdp_tid_tx_stats total_tx; struct cdp_tid_rx_stats total_rx; - uint8_t tid; + uint8_t tid, tqm_status_idx, htt_status_idx; DP_PRINT_STATS("Packets received in hardstart: %llu ", pdev->stats.tid_stats.ingress_stack); @@ -4153,9 +4363,24 @@ void dp_pdev_print_tid_stats(struct dp_pdev *pdev) dp_accumulate_tid_stats(pdev, tid, &total_tx, &total_rx, TID_COUNTER_STATS); DP_PRINT_STATS("----TID: %d----", tid); - DP_PRINT_STATS("Tx Success Count: %llu", total_tx.success_cnt); - DP_PRINT_STATS("Tx Firmware Drop Count: %llu", - total_tx.comp_fail_cnt); + DP_PRINT_STATS("Tx TQM Success Count: %llu", + total_tx.tqm_status_cnt[HAL_TX_TQM_RR_FRAME_ACKED]); + DP_PRINT_STATS("Tx HTT Success Count: %llu", + total_tx.htt_status_cnt[HTT_TX_FW2WBM_TX_STATUS_OK]); + for (tqm_status_idx = 1; tqm_status_idx < CDP_MAX_TX_TQM_STATUS; tqm_status_idx++) { + if (total_tx.tqm_status_cnt[tqm_status_idx]) { + DP_PRINT_STATS("Tx TQM Drop Count[%d]: %llu", + tqm_status_idx, total_tx.tqm_status_cnt[tqm_status_idx]); + } + } + + for (htt_status_idx = 1; htt_status_idx < CDP_MAX_TX_HTT_STATUS; htt_status_idx++) { + if (total_tx.htt_status_cnt[htt_status_idx]) { + DP_PRINT_STATS("Tx HTT Drop Count[%d]: %llu", + htt_status_idx, total_tx.htt_status_cnt[htt_status_idx]); + } + } + DP_PRINT_STATS("Tx Hardware Drop Count: %llu", total_tx.swdrop_cnt[TX_HW_ENQUEUE]); DP_PRINT_STATS("Tx Software Drop Count: %llu", @@ -4453,12 +4678,20 @@ void dp_print_soc_cfg_params(struct dp_soc *soc) soc_cfg_ctx->sg_enabled); DP_PRINT_STATS("Gro enabled: %u ", soc_cfg_ctx->gro_enabled); + DP_PRINT_STATS("TC based dynamic GRO: %u ", + soc_cfg_ctx->tc_based_dynamic_gro); + DP_PRINT_STATS("TC ingress prio: %u ", + soc_cfg_ctx->tc_ingress_prio); DP_PRINT_STATS("rawmode enabled: %u ", soc_cfg_ctx->rawmode_enabled); DP_PRINT_STATS("peer flow ctrl enabled: %u ", soc_cfg_ctx->peer_flow_ctrl_enabled); DP_PRINT_STATS("napi enabled: %u ", soc_cfg_ctx->napi_enabled); + DP_PRINT_STATS("P2P Tcp Udp checksum offload: %u ", + soc_cfg_ctx->p2p_tcp_udp_checksumoffload); + DP_PRINT_STATS("NAN Tcp Udp checksum offload: %u ", + soc_cfg_ctx->nan_tcp_udp_checksumoffload); DP_PRINT_STATS("Tcp Udp checksum offload: %u ", soc_cfg_ctx->tcp_udp_checksumoffload); DP_PRINT_STATS("Defrag timeout check: %u ", @@ -4483,8 +4716,24 @@ void dp_print_soc_cfg_params(struct dp_soc *soc) soc_cfg_ctx->reo_status_ring); DP_PRINT_STATS("RXDMA refill ring: %u ", soc_cfg_ctx->rxdma_refill_ring); + DP_PRINT_STATS("TX_desc limit_0: %u ", + soc_cfg_ctx->tx_desc_limit_0); + DP_PRINT_STATS("TX_desc limit_1: %u ", + soc_cfg_ctx->tx_desc_limit_1); + DP_PRINT_STATS("TX_desc limit_2: %u ", + soc_cfg_ctx->tx_desc_limit_2); + DP_PRINT_STATS("TX device limit: %u ", + soc_cfg_ctx->tx_device_limit); + DP_PRINT_STATS("TX sw internode queue: %u ", + soc_cfg_ctx->tx_sw_internode_queue); DP_PRINT_STATS("RXDMA err dst ring: %u ", soc_cfg_ctx->rxdma_err_dst_ring); + DP_PRINT_STATS("RX Flow Tag Enabled: %u ", + soc_cfg_ctx->is_rx_flow_tag_enabled); + DP_PRINT_STATS("RX Flow Search Table Size (# of entries): %u ", + soc_cfg_ctx->rx_flow_search_table_size); + DP_PRINT_STATS("RX Flow Search Table Per PDev : %u ", + soc_cfg_ctx->is_rx_flow_search_table_per_pdev); } void @@ -4555,6 +4804,62 @@ dp_print_ring_stat_from_hal(struct dp_soc *soc, struct dp_srng *srng, } } +#ifdef FEATURE_TSO_STATS +/** + * dp_print_tso_seg_stats - tso segment stats + * @pdev: pdev handle + * @id: tso packet id + * + * Return: None + */ +static void dp_print_tso_seg_stats(struct dp_pdev *pdev, uint32_t id) +{ + uint8_t num_seg; + uint32_t segid; + + /* TSO LEVEL 2 - SEGMENT INFO */ + num_seg = pdev->stats.tso_stats.tso_info.tso_packet_info[id].num_seg; + for (segid = 0; segid < CDP_MAX_TSO_SEGMENTS && segid < num_seg; segid++) { + DP_PRINT_STATS( + "Segment id:[%u] fragments: %u | Segment Length %u | TCP Seq no.: %u | ip_id: %u", + segid, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].num_frags, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].total_len, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].tso_flags.tcp_seq_num, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].tso_flags.ip_id); + DP_PRINT_STATS( + "fin: %u syn: %u rst: %u psh: %u ack: %u urg: %u ece: %u cwr: %u ns: %u", + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].tso_flags.fin, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].tso_flags.syn, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].tso_flags.rst, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].tso_flags.psh, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].tso_flags.ack, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].tso_flags.urg, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].tso_flags.ece, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].tso_flags.cwr, + pdev->stats.tso_stats.tso_info.tso_packet_info[id] + .tso_seg[segid].tso_flags.ns); + } +} +#else +static inline +void dp_print_tso_seg_stats(struct dp_pdev *pdev, uint32_t id) +{ +} +#endif /* FEATURE_TSO_STATS */ + /** * dp_print_mon_ring_stats_from_hal() - Print stat for monitor rings based * on target @@ -4568,19 +4873,19 @@ void dp_print_mon_ring_stat_from_hal(struct dp_pdev *pdev, uint8_t mac_id) { if (pdev->soc->wlan_cfg_ctx->rxdma1_enable) { dp_print_ring_stat_from_hal(pdev->soc, - &pdev->rxdma_mon_buf_ring[mac_id], - RXDMA_MONITOR_BUF); + &pdev->soc->rxdma_mon_buf_ring[mac_id], + RXDMA_MONITOR_BUF); dp_print_ring_stat_from_hal(pdev->soc, - &pdev->rxdma_mon_dst_ring[mac_id], - RXDMA_MONITOR_DST); + &pdev->soc->rxdma_mon_dst_ring[mac_id], + RXDMA_MONITOR_DST); dp_print_ring_stat_from_hal(pdev->soc, - &pdev->rxdma_mon_desc_ring[mac_id], - RXDMA_MONITOR_DESC); + &pdev->soc->rxdma_mon_desc_ring[mac_id], + RXDMA_MONITOR_DESC); } dp_print_ring_stat_from_hal(pdev->soc, - &pdev->rxdma_mon_status_ring[mac_id], - RXDMA_MONITOR_STATUS); + &pdev->soc->rxdma_mon_status_ring[mac_id], + RXDMA_MONITOR_STATUS); } void @@ -4588,6 +4893,7 @@ dp_print_ring_stats(struct dp_pdev *pdev) { uint32_t i; int mac_id; + int lmac_id; if (hif_pm_runtime_get_sync(pdev->soc->hif_handle, RTPM_ID_DP_PRINT_RING_STATS)) @@ -4631,9 +4937,10 @@ dp_print_ring_stats(struct dp_pdev *pdev) &pdev->soc->tx_comp_ring[i], WBM2SW_RELEASE); + lmac_id = dp_get_lmac_id_for_pdev_id(pdev->soc, 0, pdev->pdev_id); dp_print_ring_stat_from_hal(pdev->soc, - &pdev->rx_refill_buf_ring, - RXDMA_BUF); + &pdev->soc->rx_refill_buf_ring[lmac_id], + RXDMA_BUF); dp_print_ring_stat_from_hal(pdev->soc, &pdev->rx_refill_buf_ring2, @@ -4644,14 +4951,22 @@ dp_print_ring_stats(struct dp_pdev *pdev) &pdev->rx_mac_buf_ring[i], RXDMA_BUF); - for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) - dp_print_mon_ring_stat_from_hal(pdev, mac_id); + for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { + lmac_id = dp_get_lmac_id_for_pdev_id(pdev->soc, + mac_id, pdev->pdev_id); + + dp_print_mon_ring_stat_from_hal(pdev, lmac_id); + } + + for (i = 0; i < NUM_RXDMA_RINGS_PER_PDEV; i++) { + lmac_id = dp_get_lmac_id_for_pdev_id(pdev->soc, + i, pdev->pdev_id); - for (i = 0; i < NUM_RXDMA_RINGS_PER_PDEV; i++) dp_print_ring_stat_from_hal(pdev->soc, - &pdev->rxdma_err_dst_ring[i], + &pdev->soc->rxdma_err_dst_ring + [lmac_id], RXDMA_DST); - + } hif_pm_runtime_put(pdev->soc->hif_handle, RTPM_ID_DP_PRINT_RING_STATS); } @@ -4667,6 +4982,7 @@ dp_print_common_rates_info(struct cdp_pkt_type *pkt_type_array) { uint8_t mcs, pkt_type; + DP_PRINT_STATS("MSDU Count"); for (pkt_type = 0; pkt_type < DOT11_MAX; pkt_type++) { for (mcs = 0; mcs < MAX_MCS; mcs++) { if (!dp_rate_string[pkt_type][mcs].valid) @@ -4681,6 +4997,56 @@ dp_print_common_rates_info(struct cdp_pkt_type *pkt_type_array) } } +/** + * dp_print_common_ppdu_rates_info(): Print common rate for tx or rx + * @pkt_type_array: rate type array contains rate info + * + * Return:void + */ +static inline void +dp_print_common_ppdu_rates_info(struct cdp_pkt_type *pkt_type_array) +{ + uint8_t mcs; + + DP_PRINT_STATS("PPDU Count"); + for (mcs = 0; mcs < MAX_MCS; mcs++) { + if (!dp_ppdu_rate_string[0][mcs].valid) + continue; + + DP_PRINT_STATS(" %s = %d", + dp_ppdu_rate_string[0][mcs].mcs_type, + pkt_type_array->mcs_count[mcs]); + } + + DP_PRINT_STATS("\n"); +} + +/** + * dp_print_mu_ppdu_rates_info(): Print mu rate for tx or rx + * @rx_mu: rx MU stats array + * + * Return:void + */ +static inline void +dp_print_mu_ppdu_rates_info(struct cdp_rx_mu *rx_mu) +{ + uint8_t mcs, pkt_type; + + DP_PRINT_STATS("PPDU Count"); + for (pkt_type = 0; pkt_type < RX_TYPE_MU_MAX; pkt_type++) { + for (mcs = 0; mcs < MAX_MCS; mcs++) { + if (!dp_mu_rate_string[pkt_type][mcs].valid) + continue; + + DP_PRINT_STATS(" %s = %d", + dp_mu_rate_string[pkt_type][mcs].mcs_type, + rx_mu[pkt_type].ppdu.mcs_count[mcs]); + } + + DP_PRINT_STATS("\n"); + } +} + void dp_print_rx_rates(struct dp_vdev *vdev) { struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev; @@ -4758,6 +5124,26 @@ void dp_print_tx_rates(struct dp_vdev *vdev) pdev->stats.tx.non_amsdu_cnt); } +/** + * dp_print_nss(): Print nss count + * @nss: printable nss count array + * @pnss: nss count array + * @ss_count: number of nss + * + * Return:void + */ +static void dp_print_nss(char *nss, uint32_t *pnss, uint32_t ss_count) +{ + uint32_t index; + uint8_t i; + + index = 0; + for (i = 0; i < ss_count; i++) { + index += qdf_snprint(&nss[index], DP_NSS_LENGTH - index, + " %d", *(pnss + i)); + } +} + void dp_print_peer_stats(struct dp_peer *peer) { uint8_t i; @@ -4765,6 +5151,12 @@ void dp_print_peer_stats(struct dp_peer *peer) uint32_t j; char nss[DP_NSS_LENGTH]; char mu_group_id[DP_MU_GROUP_LENGTH]; + struct dp_pdev *pdev; + uint32_t *pnss; + enum cdp_mu_packet_type rx_mu_type; + struct cdp_rx_mu *rx_mu; + + pdev = peer->vdev->pdev; DP_PRINT_STATS("Node Tx Stats:\n"); DP_PRINT_STATS("Total Packet Completions = %d", @@ -4807,8 +5199,10 @@ void dp_print_peer_stats(struct dp_peer *peer) peer->stats.tx.last_ack_rssi); DP_PRINT_STATS("Dropped At FW: Removed Pkts = %u", peer->stats.tx.dropped.fw_rem.num); - DP_PRINT_STATS("Dropped At FW: Removed bytes = %llu", - peer->stats.tx.dropped.fw_rem.bytes); + if (pdev && !wlan_cfg_get_dp_pdev_nss_enabled(pdev->wlan_cfg_ctx)) { + DP_PRINT_STATS("Dropped At FW: Removed bytes = %llu", + peer->stats.tx.dropped.fw_rem.bytes); + } DP_PRINT_STATS("Dropped At FW: Removed transmitted = %d", peer->stats.tx.dropped.fw_rem_tx); DP_PRINT_STATS("Dropped At FW: Removed Untransmitted = %d", @@ -4844,19 +5238,17 @@ void dp_print_peer_stats(struct dp_peer *peer) peer->stats.tx.bw[0], peer->stats.tx.bw[1], peer->stats.tx.bw[2], peer->stats.tx.bw[3]); - index = 0; - for (i = 0; i < SS_COUNT; i++) { - index += qdf_snprint(&nss[index], DP_NSS_LENGTH - index, - " %d", peer->stats.tx.nss[i]); - } + pnss = &peer->stats.tx.nss[0]; + dp_print_nss(nss, pnss, SS_COUNT); + DP_PRINT_STATS("NSS(1-8) = %s", nss); DP_PRINT_STATS("Transmit Type :"); DP_PRINT_STATS("SU %d, MU_MIMO %d, MU_OFDMA %d, MU_MIMO_OFDMA %d", - peer->stats.tx.transmit_type[0], - peer->stats.tx.transmit_type[1], - peer->stats.tx.transmit_type[2], - peer->stats.tx.transmit_type[3]); + peer->stats.tx.transmit_type[SU].num_msdu, + peer->stats.tx.transmit_type[MU_MIMO].num_msdu, + peer->stats.tx.transmit_type[MU_OFDMA].num_msdu, + peer->stats.tx.transmit_type[MU_MIMO_OFDMA].num_msdu); for (i = 0; i < MAX_MU_GROUP_ID;) { index = 0; @@ -4876,12 +5268,18 @@ void dp_print_peer_stats(struct dp_peer *peer) DP_PRINT_STATS("Last Packet RU index [%d], Size [%d]", peer->stats.tx.ru_start, peer->stats.tx.ru_tones); DP_PRINT_STATS("RU Locations RU[26 52 106 242 484 996]:"); - DP_PRINT_STATS("RU_26: %d", peer->stats.tx.ru_loc[0]); - DP_PRINT_STATS("RU 52: %d", peer->stats.tx.ru_loc[1]); - DP_PRINT_STATS("RU 106: %d", peer->stats.tx.ru_loc[2]); - DP_PRINT_STATS("RU 242: %d", peer->stats.tx.ru_loc[3]); - DP_PRINT_STATS("RU 484: %d", peer->stats.tx.ru_loc[4]); - DP_PRINT_STATS("RU 996: %d", peer->stats.tx.ru_loc[5]); + DP_PRINT_STATS("RU_26: %d", + peer->stats.tx.ru_loc[RU_26_INDEX].num_msdu); + DP_PRINT_STATS("RU 52: %d", + peer->stats.tx.ru_loc[RU_52_INDEX].num_msdu); + DP_PRINT_STATS("RU 106: %d", + peer->stats.tx.ru_loc[RU_106_INDEX].num_msdu); + DP_PRINT_STATS("RU 242: %d", + peer->stats.tx.ru_loc[RU_242_INDEX].num_msdu); + DP_PRINT_STATS("RU 484: %d", + peer->stats.tx.ru_loc[RU_484_INDEX].num_msdu); + DP_PRINT_STATS("RU 996: %d", + peer->stats.tx.ru_loc[RU_996_INDEX].num_msdu); DP_PRINT_STATS("Aggregation:"); DP_PRINT_STATS("Number of Msdu's Part of Amsdu = %d", @@ -4946,21 +5344,53 @@ void dp_print_peer_stats(struct dp_peer *peer) DP_PRINT_STATS("BW Counts = 20MHZ %d 40MHZ %d 80MHZ %d 160MHZ %d", peer->stats.rx.bw[0], peer->stats.rx.bw[1], peer->stats.rx.bw[2], peer->stats.rx.bw[3]); - DP_PRINT_STATS("Reception Type = SU %d MU_MIMO %d MU_OFDMA %d MU_OFDMA_MIMO %d", + DP_PRINT_STATS("MSDU Reception Type"); + DP_PRINT_STATS("SU %d MU_MIMO %d MU_OFDMA %d MU_OFDMA_MIMO %d", peer->stats.rx.reception_type[0], peer->stats.rx.reception_type[1], peer->stats.rx.reception_type[2], peer->stats.rx.reception_type[3]); + DP_PRINT_STATS("PPDU Reception Type"); + DP_PRINT_STATS("SU %d MU_MIMO %d MU_OFDMA %d MU_OFDMA_MIMO %d", + peer->stats.rx.ppdu_cnt[0], + peer->stats.rx.ppdu_cnt[1], + peer->stats.rx.ppdu_cnt[2], + peer->stats.rx.ppdu_cnt[3]); dp_print_common_rates_info(peer->stats.rx.pkt_type); + dp_print_common_ppdu_rates_info(&peer->stats.rx.su_ax_ppdu_cnt); + dp_print_mu_ppdu_rates_info(&peer->stats.rx.rx_mu[0]); - index = 0; - for (i = 0; i < SS_COUNT; i++) { - index += qdf_snprint(&nss[index], DP_NSS_LENGTH - index, - " %d", peer->stats.rx.nss[i]); + pnss = &peer->stats.rx.nss[0]; + dp_print_nss(nss, pnss, SS_COUNT); + DP_PRINT_STATS("MSDU Count"); + DP_PRINT_STATS(" NSS(1-8) = %s", nss); + + DP_PRINT_STATS("reception mode SU"); + pnss = &peer->stats.rx.ppdu_nss[0]; + dp_print_nss(nss, pnss, SS_COUNT); + + DP_PRINT_STATS(" PPDU Count"); + DP_PRINT_STATS(" NSS(1-8) = %s", nss); + + DP_PRINT_STATS(" MPDU OK = %d, MPDU Fail = %d", + peer->stats.rx.mpdu_cnt_fcs_ok, + peer->stats.rx.mpdu_cnt_fcs_err); + + for (rx_mu_type = 0; rx_mu_type < RX_TYPE_MU_MAX; rx_mu_type++) { + DP_PRINT_STATS("reception mode %s", + mu_reception_mode[rx_mu_type]); + rx_mu = &peer->stats.rx.rx_mu[rx_mu_type]; + + pnss = &rx_mu->ppdu_nss[0]; + dp_print_nss(nss, pnss, SS_COUNT); + DP_PRINT_STATS(" PPDU Count"); + DP_PRINT_STATS(" NSS(1-8) = %s", nss); + + DP_PRINT_STATS(" MPDU OK = %d, MPDU Fail = %d", + rx_mu->mpdu_cnt_fcs_ok, + rx_mu->mpdu_cnt_fcs_err); } - DP_PRINT_STATS("NSS(1-8) = %s", - nss); DP_PRINT_STATS("Aggregation:"); DP_PRINT_STATS(" Msdu's Part of Ampdu = %d", @@ -4977,6 +5407,8 @@ void dp_print_peer_stats(struct dp_peer *peer) peer->stats.rx.rx_byte_rate); DP_PRINT_STATS(" Data received in last sec: %d", peer->stats.rx.rx_data_rate); + DP_PRINT_STATS("Multipass Rx Packet Drop = %d", + peer->stats.rx.multipass_rx_pkt_drop); } void dp_print_per_ring_stats(struct dp_soc *soc) @@ -5094,6 +5526,8 @@ void dp_txrx_path_stats(struct dp_soc *soc) pdev->stats.rx.intra_bss.fail.bytes); DP_PRINT_STATS("intra-bss no mdns fwds %u msdus", pdev->stats.rx.intra_bss.mdns_no_fwd); + DP_PRINT_STATS("intra-bss EAPOL drops: %u", + soc->stats.rx.err.intrabss_eapol_drop); DP_PRINT_STATS("raw packets %u msdus ( %llu bytes),", pdev->stats.rx.raw.num, @@ -5112,6 +5546,10 @@ void dp_txrx_path_stats(struct dp_soc *soc) pdev->soc->stats.rx.err.defrag_peer_uninit); DP_PRINT_STATS("pkts delivered no peer %u", pdev->soc->stats.rx.err.pkt_delivered_no_peer); + DP_PRINT_STATS("RX invalid cookie: %d", + soc->stats.rx.err.invalid_cookie); + DP_PRINT_STATS("RX stale cookie: %d", + soc->stats.rx.err.stale_cookie); DP_PRINT_STATS("2k jump delba sent: %u", pdev->soc->stats.rx.err.rx_2k_jump_delba_sent); DP_PRINT_STATS("2k jump msdu to stack: %u", @@ -5124,6 +5562,14 @@ void dp_txrx_path_stats(struct dp_soc *soc) pdev->soc->stats.rx.err.reo_err_oor_drop); DP_PRINT_STATS("Rx err msdu rejected: %d", soc->stats.rx.err.rejected); + DP_PRINT_STATS("Rx raw frame dropped: %d", + soc->stats.rx.err.raw_frm_drop); + DP_PRINT_STATS("Rx stale link desc cookie: %d", + pdev->soc->stats.rx.err.invalid_link_cookie); + DP_PRINT_STATS("Rx nbuf sanity fails: %d", + pdev->soc->stats.rx.err.nbuf_sanity_fail); + DP_PRINT_STATS("Rx refill duplicate link desc: %d", + pdev->soc->stats.rx.err.dup_refill_link_desc); DP_PRINT_STATS("Reo Statistics"); DP_PRINT_STATS("near_full: %u ", soc->stats.rx.near_full); @@ -5135,6 +5581,8 @@ void dp_txrx_path_stats(struct dp_soc *soc) DP_PRINT_STATS("hal ring access full fail: %u msdus", pdev->soc->stats.rx.err.hal_ring_access_full_fail); + DP_PRINT_STATS("Rx BAR frames:%d", soc->stats.rx.bar_frame); + for (error_code = 0; error_code < HAL_REO_ERR_MAX; error_code++) { if (!pdev->soc->stats.rx.err.reo_error[error_code]) @@ -5306,17 +5754,6 @@ dp_print_pdev_tx_stats(struct dp_pdev *pdev) pdev->stats.tx_i.sg.dropped_host.num); DP_PRINT_STATS(" Dropped By Target = %d", pdev->stats.tx_i.sg.dropped_target); - DP_PRINT_STATS("TSO:"); - DP_PRINT_STATS(" Number of Segments = %d", - pdev->stats.tx_i.tso.num_seg); - DP_PRINT_STATS(" Packets = %d", - pdev->stats.tx_i.tso.tso_pkt.num); - DP_PRINT_STATS(" Bytes = %llu", - pdev->stats.tx_i.tso.tso_pkt.bytes); - DP_PRINT_STATS(" Dropped By Host = %d", - pdev->stats.tx_i.tso.dropped_host.num); - DP_PRINT_STATS(" Dropped By Host(no free TSO desc) = %d", - pdev->stats.tx_i.tso.tso_no_mem_dropped.num); DP_PRINT_STATS("Mcast Enhancement:"); DP_PRINT_STATS(" Packets = %d", pdev->stats.tx_i.mcast_en.mcast_pkt.num); @@ -5369,6 +5806,8 @@ dp_print_pdev_tx_stats(struct dp_pdev *pdev) DP_PRINT_STATS(" Tag[%d] = %llu", index, pdev->stats.ppdu_stats_counter[index]); } + DP_PRINT_STATS("BA not received for delayed_ba: %d", + pdev->stats.cdp_delayed_ba_not_recev); DP_PRINT_STATS("tx_ppdu_proc: %llu\n", pdev->tx_ppdu_proc); @@ -5377,6 +5816,8 @@ dp_print_pdev_tx_stats(struct dp_pdev *pdev) DP_PRINT_STATS("Wdi msgs received from fw[%d]:%d", i, pdev->stats.wdi_event[i]); } + + dp_print_pdev_tx_capture_stats(pdev); } void @@ -5397,8 +5838,6 @@ dp_print_pdev_rx_stats(struct dp_pdev *pdev) DP_PRINT_STATS("Replenished:"); DP_PRINT_STATS(" Packets = %d", pdev->stats.replenish.pkts.num); - DP_PRINT_STATS(" Bytes = %llu", - pdev->stats.replenish.pkts.bytes); DP_PRINT_STATS(" Buffers Added To Freelist = %d", pdev->stats.buf_freelist); DP_PRINT_STATS(" Low threshold intr = %d", @@ -5410,6 +5849,8 @@ dp_print_pdev_rx_stats(struct dp_pdev *pdev) pdev->stats.dropped.wifi_parse); DP_PRINT_STATS(" mon_rx_drop = %d", pdev->stats.dropped.mon_rx_drop); + DP_PRINT_STATS(" mon_radiotap_update_err = %d", + pdev->stats.dropped.mon_radiotap_update_err); DP_PRINT_STATS(" mec_drop = %d", pdev->stats.rx.mec_drop.num); DP_PRINT_STATS(" Bytes = %llu", @@ -5538,8 +5979,12 @@ dp_print_soc_tx_stats(struct dp_soc *soc) soc->stats.tx.tcl_ring_full[2]); DP_PRINT_STATS("Tx invalid completion release = %d", soc->stats.tx.invalid_release_source); - DP_PRINT_STATS("Tx comp wbm internal error = %d", - soc->stats.tx.wbm_internal_error); + DP_PRINT_STATS("Tx comp wbm internal error = %d : [%d %d %d %d]", + soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_ALL], + soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_BUFFER], + soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_LINK_DESC], + soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_MSDU_BUFF], + soc->stats.tx.wbm_internal_error[WBM_INT_ERROR_REO_BUFF_REAPED]); DP_PRINT_STATS("Tx comp non wbm internal error = %d", soc->stats.tx.non_wbm_internal_err); DP_PRINT_STATS("Tx comp loop pkt limit hit = %d", @@ -5602,6 +6047,8 @@ dp_print_soc_rx_stats(struct dp_soc *soc) soc->stats.rx.err.defrag_peer_uninit); DP_PRINT_STATS("Pkts delivered no peer = %d", soc->stats.rx.err.pkt_delivered_no_peer); + DP_PRINT_STATS("Pkts drop due to no peer auth :%d", + soc->stats.rx.err.peer_unauth_rx_pkt_drop); DP_PRINT_STATS("Invalid Pdev = %d", soc->stats.rx.err.invalid_pdev); DP_PRINT_STATS("Invalid Peer = %d", @@ -5615,6 +6062,7 @@ dp_print_soc_rx_stats(struct dp_soc *soc) DP_PRINT_STATS("RX frags: %d", soc->stats.rx.rx_frags); DP_PRINT_STATS("RX frag wait: %d", soc->stats.rx.rx_frag_wait); DP_PRINT_STATS("RX frag err: %d", soc->stats.rx.rx_frag_err); + DP_PRINT_STATS("RX frag OOR: %d", soc->stats.rx.rx_frag_oor); DP_PRINT_STATS("RX HP out_of_sync: %d", soc->stats.rx.hp_oos2); DP_PRINT_STATS("RX Ring Near Full: %d", soc->stats.rx.near_full); @@ -5634,6 +6082,12 @@ dp_print_soc_rx_stats(struct dp_soc *soc) DP_PRINT_STATS("RX scatter msdu: %d", soc->stats.rx.err.scatter_msdu); + DP_PRINT_STATS("RX invalid cookie: %d", + soc->stats.rx.err.invalid_cookie); + + DP_PRINT_STATS("RX stale cookie: %d", + soc->stats.rx.err.stale_cookie); + DP_PRINT_STATS("RX wait completed msdu break: %d", soc->stats.rx.msdu_scatter_wait_break); @@ -5655,6 +6109,12 @@ dp_print_soc_rx_stats(struct dp_soc *soc) DP_PRINT_STATS("Rx err msdu rejected: %d", soc->stats.rx.err.rejected); + DP_PRINT_STATS("Rx stale link desc cookie: %d", + soc->stats.rx.err.invalid_link_cookie); + + DP_PRINT_STATS("Rx nbuf sanity fail: %d", + soc->stats.rx.err.nbuf_sanity_fail); + for (i = 0; i < HAL_RXDMA_ERR_MAX; i++) { index += qdf_snprint(&rxdma_error[index], DP_RXDMA_ERR_LENGTH - index, @@ -5671,5 +6131,167 @@ dp_print_soc_rx_stats(struct dp_soc *soc) DP_PRINT_STATS("REO Error(0-14):%s", reo_error); DP_PRINT_STATS("REO CMD SEND FAIL: %d", soc->stats.rx.err.reo_cmd_send_fail); + + DP_PRINT_STATS("Rx BAR frames:%d", soc->stats.rx.bar_frame); + DP_PRINT_STATS("Rx invalid TID count:%d", + soc->stats.rx.err.rx_invalid_tid_err); +} + +#ifdef FEATURE_TSO_STATS +void dp_print_tso_stats(struct dp_soc *soc, + enum qdf_stats_verbosity_level level) +{ + uint8_t loop_pdev; + uint32_t id; + struct dp_pdev *pdev; + + for (loop_pdev = 0; loop_pdev < soc->pdev_count; loop_pdev++) { + pdev = soc->pdev_list[loop_pdev]; + DP_PRINT_STATS("TSO Statistics\n"); + DP_PRINT_STATS( + "From stack: %d | Successful completions: %d | TSO Packets: %d | TSO Completions: %d", + pdev->stats.tx_i.rcvd.num, + pdev->stats.tx.tx_success.num, + pdev->stats.tso_stats.num_tso_pkts.num, + pdev->stats.tso_stats.tso_comp); + + for (id = 0; id < CDP_MAX_TSO_PACKETS; id++) { + /* TSO LEVEL 1 - PACKET INFO */ + DP_PRINT_STATS( + "Packet_Id:[%u]: Packet Length %zu | No. of segments: %u", + id, + pdev->stats.tso_stats.tso_info + .tso_packet_info[id].tso_packet_len, + pdev->stats.tso_stats.tso_info + .tso_packet_info[id].num_seg); + /* TSO LEVEL 2 */ + if (level == QDF_STATS_VERBOSITY_LEVEL_HIGH) + dp_print_tso_seg_stats(pdev, id); + } + + DP_PRINT_STATS( + "TSO Histogram: Single: %llu | 2-5 segs: %llu | 6-10: %llu segs | 11-15 segs: %llu | 16-20 segs: %llu | 20+ segs: %llu", + pdev->stats.tso_stats.seg_histogram.segs_1, + pdev->stats.tso_stats.seg_histogram.segs_2_5, + pdev->stats.tso_stats.seg_histogram.segs_6_10, + pdev->stats.tso_stats.seg_histogram.segs_11_15, + pdev->stats.tso_stats.seg_histogram.segs_16_20, + pdev->stats.tso_stats.seg_histogram.segs_20_plus); + } } +void dp_stats_tso_segment_histogram_update(struct dp_pdev *pdev, + uint8_t _p_cntrs) +{ + if (_p_cntrs == 1) { + DP_STATS_INC(pdev, + tso_stats.seg_histogram.segs_1, 1); + } else if (_p_cntrs >= 2 && _p_cntrs <= 5) { + DP_STATS_INC(pdev, + tso_stats.seg_histogram.segs_2_5, 1); + } else if (_p_cntrs > 5 && _p_cntrs <= 10) { + DP_STATS_INC(pdev, + tso_stats.seg_histogram.segs_6_10, 1); + } else if (_p_cntrs > 10 && _p_cntrs <= 15) { + DP_STATS_INC(pdev, + tso_stats.seg_histogram.segs_11_15, 1); + } else if (_p_cntrs > 15 && _p_cntrs <= 20) { + DP_STATS_INC(pdev, + tso_stats.seg_histogram.segs_16_20, 1); + } else if (_p_cntrs > 20) { + DP_STATS_INC(pdev, + tso_stats.seg_histogram.segs_20_plus, 1); + } +} + +void dp_tso_segment_update(struct dp_pdev *pdev, + uint32_t stats_idx, + uint8_t idx, + struct qdf_tso_seg_t seg) +{ + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].num_frags, + seg.num_frags); + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].total_len, + seg.total_len); + + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.tso_enable, + seg.tso_flags.tso_enable); + + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.fin, + seg.tso_flags.fin); + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.syn, + seg.tso_flags.syn); + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.rst, + seg.tso_flags.rst); + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.psh, + seg.tso_flags.psh); + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.ack, + seg.tso_flags.ack); + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.urg, + seg.tso_flags.urg); + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.ece, + seg.tso_flags.ece); + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.cwr, + seg.tso_flags.cwr); + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.ns, + seg.tso_flags.ns); + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.tcp_seq_num, + seg.tso_flags.tcp_seq_num); + DP_STATS_UPD(pdev, tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_seg[idx].tso_flags.ip_id, + seg.tso_flags.ip_id); +} + +void dp_tso_packet_update(struct dp_pdev *pdev, uint32_t stats_idx, + qdf_nbuf_t msdu, uint16_t num_segs) +{ + DP_STATS_UPD(pdev, + tso_stats.tso_info.tso_packet_info[stats_idx] + .num_seg, + num_segs); + + DP_STATS_UPD(pdev, + tso_stats.tso_info.tso_packet_info[stats_idx] + .tso_packet_len, + qdf_nbuf_get_tcp_payload_len(msdu)); +} + +void dp_tso_segment_stats_update(struct dp_pdev *pdev, + struct qdf_tso_seg_elem_t *stats_seg, + uint32_t stats_idx) +{ + uint8_t tso_seg_idx = 0; + + while (stats_seg && (tso_seg_idx < CDP_MAX_TSO_SEGMENTS)) { + dp_tso_segment_update(pdev, stats_idx, + tso_seg_idx, + stats_seg->seg); + ++tso_seg_idx; + stats_seg = stats_seg->next; + } +} + +void dp_txrx_clear_tso_stats(struct dp_soc *soc) +{ + uint8_t loop_pdev; + struct dp_pdev *pdev; + + for (loop_pdev = 0; loop_pdev < soc->pdev_count; loop_pdev++) { + pdev = soc->pdev_list[loop_pdev]; + dp_init_tso_stats(pdev); + } +} +#endif /* FEATURE_TSO_STATS */ diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx.c index bbe07bf72a063b9e7c6701511c5a8d6502acee8d..b29c353632849cc79f8d893b795586ac782ee19a 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx.c @@ -17,6 +17,7 @@ */ #include "htt.h" +#include "dp_htt.h" #include "hal_hw_headers.h" #include "dp_tx.h" #include "dp_tx_desc.h" @@ -27,7 +28,7 @@ #include "qdf_nbuf.h" #include "qdf_net_types.h" #include -#ifdef MESH_MODE_SUPPORT +#if defined(MESH_MODE_SUPPORT) || defined(FEATURE_PERPKT_INFO) #include "if_meta_hdr.h" #endif #include "enet.h" @@ -35,8 +36,10 @@ #ifdef FEATURE_WDS #include "dp_txrx_wds.h" #endif +#ifdef ATH_SUPPORT_IQUE +#include "dp_txrx_me.h" +#endif -#define DP_TX_QUEUE_MASK 0x3 /* TODO Add support in TSO */ #define DP_DESC_NUM_FRAG(x) 0 @@ -63,56 +66,90 @@ static const uint8_t sec_type_map[MAX_CDP_SEC_TYPE] = { HAL_TX_ENCRYPT_TYPE_AES_GCMP_256, HAL_TX_ENCRYPT_TYPE_WAPI_GCM_SM4}; -#ifdef WLAN_TX_PKT_CAPTURE_ENH -#include "dp_tx_capture.h" -#endif - +#ifdef QCA_TX_LIMIT_CHECK /** - * dp_tx_get_queue() - Returns Tx queue IDs to be used for this Tx frame - * @vdev: DP Virtual device handle - * @nbuf: Buffer pointer - * @queue: queue ids container for nbuf + * dp_tx_limit_check - Check if allocated tx descriptors reached + * soc max limit and pdev max limit + * @vdev: DP vdev handle * - * TX packet queue has 2 instances, software descriptors id and dma ring id - * Based on tx feature and hardware configuration queue id combination - * could be different. - * For example - - * With XPS enabled,all TX descriptor pools and dma ring are assigned - * per cpu id - * With no XPS,lock based resource protection, Descriptor pool ids are - * different for each vdev, dma ring id will be same as single pdev id + * Return: true if allocated tx descriptors reached max configured value, else + * false + */ +static inline bool +dp_tx_limit_check(struct dp_vdev *vdev) +{ + struct dp_pdev *pdev = vdev->pdev; + struct dp_soc *soc = pdev->soc; + + if (qdf_atomic_read(&soc->num_tx_outstanding) >= + soc->num_tx_allowed) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s: queued packets are more than max tx, drop the frame", + __func__); + DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1); + return true; + } + + if (qdf_atomic_read(&pdev->num_tx_outstanding) >= + pdev->num_tx_allowed) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s: queued packets are more than max tx, drop the frame", + __func__); + DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1); + return true; + } + return false; +} + +/** + * dp_tx_outstanding_inc - Increment outstanding tx desc values on pdev and soc + * @vdev: DP pdev handle * - * Return: None + * Return: void */ -#ifdef QCA_OL_TX_MULTIQ_SUPPORT -static inline void dp_tx_get_queue(struct dp_vdev *vdev, - qdf_nbuf_t nbuf, struct dp_tx_queue *queue) +static inline void +dp_tx_outstanding_inc(struct dp_pdev *pdev) { - uint16_t queue_offset = qdf_nbuf_get_queue_mapping(nbuf) & DP_TX_QUEUE_MASK; - queue->desc_pool_id = queue_offset; - queue->ring_id = vdev->pdev->soc->tx_ring_map[queue_offset]; + struct dp_soc *soc = pdev->soc; - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s, pool_id:%d ring_id: %d", - __func__, queue->desc_pool_id, queue->ring_id); + qdf_atomic_inc(&pdev->num_tx_outstanding); + qdf_atomic_inc(&soc->num_tx_outstanding); +} - return; +/** + * dp_tx_outstanding__dec - Decrement outstanding tx desc values on pdev and soc + * @vdev: DP pdev handle + * + * Return: void + */ +static inline void +dp_tx_outstanding_dec(struct dp_pdev *pdev) +{ + struct dp_soc *soc = pdev->soc; + + qdf_atomic_dec(&pdev->num_tx_outstanding); + qdf_atomic_dec(&soc->num_tx_outstanding); } -#else /* QCA_OL_TX_MULTIQ_SUPPORT */ -static inline void dp_tx_get_queue(struct dp_vdev *vdev, - qdf_nbuf_t nbuf, struct dp_tx_queue *queue) + +#else //QCA_TX_LIMIT_CHECK +static inline bool +dp_tx_limit_check(struct dp_vdev *vdev) { - /* get flow id */ - queue->desc_pool_id = DP_TX_GET_DESC_POOL_ID(vdev); - queue->ring_id = DP_TX_GET_RING_ID(vdev); + return false; +} - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "%s, pool_id:%d ring_id: %d", - __func__, queue->desc_pool_id, queue->ring_id); +static inline void +dp_tx_outstanding_inc(struct dp_pdev *pdev) +{ + qdf_atomic_inc(&pdev->num_tx_outstanding); +} - return; +static inline void +dp_tx_outstanding_dec(struct dp_pdev *pdev) +{ + qdf_atomic_dec(&pdev->num_tx_outstanding); } -#endif +#endif //QCA_TX_LIMIT_CHECK #if defined(FEATURE_TSO) /** @@ -180,6 +217,7 @@ static void dp_tx_tso_desc_release(struct dp_soc *soc, dp_tso_num_seg_free(soc, tx_desc->pool_id, tx_desc->tso_num_desc); tx_desc->tso_num_desc = NULL; + DP_STATS_INC(tx_desc->pdev, tso_stats.tso_comp, 1); } /* Add the tso segment into the free list*/ @@ -232,7 +270,7 @@ dp_tx_desc_release(struct dp_tx_desc_s *tx_desc, uint8_t desc_pool_id) if (tx_desc->flags & DP_TX_DESC_FLAG_ME) dp_tx_me_free_buf(tx_desc->pdev, tx_desc->me_buffer); - qdf_atomic_dec(&pdev->num_tx_outstanding); + dp_tx_outstanding_dec(pdev); if (tx_desc->flags & DP_TX_DESC_FLAG_TO_FW) qdf_atomic_dec(&pdev->num_tx_exception); @@ -269,7 +307,7 @@ dp_tx_desc_release(struct dp_tx_desc_s *tx_desc, uint8_t desc_pool_id) * */ static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf, - struct dp_tx_msdu_info_s *msdu_info) + struct dp_tx_msdu_info_s *msdu_info) { uint32_t *meta_data = msdu_info->meta_data; struct htt_tx_msdu_desc_ext2_t *desc_ext = @@ -288,12 +326,26 @@ static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf, htt_desc_size = sizeof(struct htt_tx_msdu_desc_ext2_t); htt_desc_size_aligned = (htt_desc_size + 7) & ~0x7; - if (vdev->mesh_vdev || msdu_info->is_tx_sniffer) { + if (vdev->mesh_vdev || msdu_info->is_tx_sniffer || + HTT_TX_MSDU_EXT2_DESC_FLAG_VALID_KEY_FLAGS_GET(msdu_info-> + meta_data[0])) { if (qdf_unlikely(qdf_nbuf_headroom(nbuf) < - htt_desc_size_aligned)) { - DP_STATS_INC(vdev, - tx_i.dropped.headroom_insufficient, 1); - return 0; + htt_desc_size_aligned)) { + nbuf = qdf_nbuf_realloc_headroom(nbuf, + htt_desc_size_aligned); + if (!nbuf) { + /* + * qdf_nbuf_realloc_headroom won't do skb_clone + * as skb_realloc_headroom does. so, no free is + * needed here. + */ + DP_STATS_INC(vdev, + tx_i.dropped.headroom_insufficient, + 1); + qdf_print(" %s[%d] skb_realloc_headroom failed", + __func__, __LINE__); + return 0; + } } /* Fill and add HTT metaheader */ hdr = qdf_nbuf_push_head(nbuf, htt_desc_size_aligned); @@ -448,6 +500,28 @@ static void dp_tx_unmap_tso_seg_list( } } +#ifdef FEATURE_TSO_STATS +/** + * dp_tso_get_stats_idx: Retrieve the tso packet id + * @pdev - pdev handle + * + * Return: id + */ +static uint32_t dp_tso_get_stats_idx(struct dp_pdev *pdev) +{ + uint32_t stats_idx; + + stats_idx = (((uint32_t)qdf_atomic_inc_return(&pdev->tso_idx)) + % CDP_MAX_TSO_PACKETS); + return stats_idx; +} +#else +static int dp_tso_get_stats_idx(struct dp_pdev *pdev) +{ + return 0; +} +#endif /* FEATURE_TSO_STATS */ + /** * dp_tx_free_remaining_tso_desc() - do dma unmap for tso segments if any, * free the tso segments descriptor and @@ -493,9 +567,9 @@ static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev, struct qdf_tso_seg_elem_t *tso_seg; int num_seg = qdf_nbuf_get_tso_num_seg(msdu); struct dp_soc *soc = vdev->pdev->soc; + struct dp_pdev *pdev = vdev->pdev; struct qdf_tso_info_t *tso_info; struct qdf_tso_num_seg_elem_t *tso_num_seg; - tso_info = &msdu_info->u.tso_info; tso_info->curr_seg = NULL; tso_info->tso_seg_list = NULL; @@ -514,7 +588,8 @@ static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev, num_seg--; } else { dp_err_rl("Failed to alloc tso seg desc"); - DP_STATS_INC_PKT(vdev, tx_i.tso.tso_no_mem_dropped, 1, + DP_STATS_INC_PKT(vdev->pdev, + tso_stats.tso_no_mem_dropped, 1, qdf_nbuf_len(msdu)); dp_tx_free_remaining_tso_desc(soc, msdu_info, false); @@ -557,6 +632,12 @@ static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev, tso_info->curr_seg = tso_info->tso_seg_list; + tso_info->msdu_stats_idx = dp_tso_get_stats_idx(pdev); + dp_tso_packet_update(pdev, tso_info->msdu_stats_idx, + msdu, msdu_info->num_seg); + dp_tso_segment_stats_update(pdev, tso_info->tso_seg_list, + tso_info->msdu_stats_idx); + dp_stats_tso_segment_histogram_update(pdev, msdu_info->num_seg); return QDF_STATUS_SUCCESS; } #else @@ -567,6 +648,10 @@ static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev, } #endif +QDF_COMPILE_TIME_ASSERT(dp_tx_htt_metadata_len_check, + (DP_TX_MSDU_INFO_META_DATA_DWORDS * 4 >= + sizeof(struct htt_tx_msdu_desc_ext2_t))); + /** * dp_tx_prepare_ext_desc() - Allocate and prepare MSDU extension descriptor * @vdev: DP Vdev handle @@ -600,6 +685,7 @@ struct dp_tx_ext_desc_elem_s *dp_tx_prepare_ext_desc(struct dp_vdev *vdev, &msdu_info->meta_data[0], sizeof(struct htt_tx_msdu_desc_ext2_t)); qdf_atomic_inc(&vdev->pdev->num_tx_exception); + msdu_ext_desc->flags |= DP_TX_EXT_DESC_FLAG_METADATA_VALID; } switch (msdu_info->frm_type) { @@ -664,39 +750,6 @@ static void dp_tx_trace_pkt(qdf_nbuf_t skb, uint16_t msdu_id, msdu_id, QDF_TX)); } -#ifdef QCA_512M_CONFIG -/** - * dp_tx_pdev_pflow_control - Check if allocated tx descriptors reached max - * tx descriptor configured value - * @vdev: DP vdev handle - * - * Return: true if allocated tx descriptors reached max configured value, else - * false. - */ -static inline bool -dp_tx_pdev_pflow_control(struct dp_vdev *vdev) -{ - struct dp_pdev *pdev = vdev->pdev; - - if (qdf_atomic_read(&pdev->num_tx_outstanding) >= - pdev->num_tx_allowed) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "%s: queued packets are more than max tx, drop the frame", - __func__); - DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1); - return true; - } - - return false; -} -#else -static inline bool -dp_tx_pdev_pflow_control(struct dp_vdev *vdev) -{ - return false; -} -#endif - /** * dp_tx_desc_prepare_single - Allocate and prepare Tx descriptor * @vdev: DP vdev handle @@ -723,7 +776,7 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, struct dp_pdev *pdev = vdev->pdev; struct dp_soc *soc = pdev->soc; - if (dp_tx_pdev_pflow_control(vdev)) + if (dp_tx_limit_check(vdev)) return NULL; /* Allocate software Tx descriptor */ @@ -733,8 +786,7 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, return NULL; } - /* Flow control/Congestion Control counters */ - qdf_atomic_inc(&pdev->num_tx_outstanding); + dp_tx_outstanding_inc(pdev); /* Initialize the SW tx descriptor */ tx_desc->nbuf = nbuf; @@ -749,6 +801,11 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, dp_tx_trace_pkt(nbuf, tx_desc->id, vdev->vdev_id); + if (qdf_unlikely(vdev->multipass_en)) { + if (!dp_tx_multipass_process(soc, vdev, nbuf, msdu_info)) + goto failure; + } + /* * For special modes (vdev_type == ocb or mesh), data frames should be * transmitted using varying transmit parameters (tx spec) which include @@ -864,7 +921,7 @@ static struct dp_tx_desc_s *dp_tx_prepare_desc(struct dp_vdev *vdev, struct dp_pdev *pdev = vdev->pdev; struct dp_soc *soc = pdev->soc; - if (dp_tx_pdev_pflow_control(vdev)) + if (dp_tx_limit_check(vdev)) return NULL; /* Allocate software Tx descriptor */ @@ -874,8 +931,7 @@ static struct dp_tx_desc_s *dp_tx_prepare_desc(struct dp_vdev *vdev, return NULL; } - /* Flow control/Congestion Control counters */ - qdf_atomic_inc(&pdev->num_tx_outstanding); + dp_tx_outstanding_inc(pdev); /* Initialize the SW tx descriptor */ tx_desc->nbuf = nbuf; @@ -999,6 +1055,113 @@ static qdf_nbuf_t dp_tx_prepare_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf, } +/** + * dp_tx_raw_prepare_unset() - unmap the chain of nbufs belonging to RAW frame. + * @soc: DP soc handle + * @nbuf: Buffer pointer + * + * unmap the chain of nbufs that belong to this RAW frame. + * + * Return: None + */ +static void dp_tx_raw_prepare_unset(struct dp_soc *soc, + qdf_nbuf_t nbuf) +{ + qdf_nbuf_t cur_nbuf = nbuf; + + do { + qdf_nbuf_unmap(soc->osdev, cur_nbuf, QDF_DMA_TO_DEVICE); + cur_nbuf = qdf_nbuf_next(cur_nbuf); + } while (cur_nbuf); +} + +#ifdef VDEV_PEER_PROTOCOL_COUNT +#define dp_vdev_peer_stats_update_protocol_cnt_tx(vdev_hdl, nbuf) \ +{ \ + qdf_nbuf_t nbuf_local; \ + struct dp_vdev *vdev_local = vdev_hdl; \ + do { \ + if (qdf_likely(!((vdev_local)->peer_protocol_count_track))) \ + break; \ + nbuf_local = nbuf; \ + if (qdf_unlikely(((vdev_local)->tx_encap_type) == \ + htt_cmn_pkt_type_raw)) \ + break; \ + else if (qdf_unlikely(qdf_nbuf_is_nonlinear((nbuf_local)))) \ + break; \ + else if (qdf_nbuf_is_tso((nbuf_local))) \ + break; \ + dp_vdev_peer_stats_update_protocol_cnt((vdev_local), \ + (nbuf_local), \ + NULL, 1, 0); \ + } while (0); \ +} +#else +#define dp_vdev_peer_stats_update_protocol_cnt_tx(vdev_hdl, skb) +#endif + +#ifdef FEATURE_RUNTIME_PM +/** + * dp_tx_ring_access_end_wrapper() - Wrapper for ring access end + * @soc: Datapath soc handle + * @hal_ring_hdl: HAL ring handle + * + * Wrapper for HAL ring access end for data transmission for + * FEATURE_RUNTIME_PM + * + * Returns: none + */ +static inline void +dp_tx_ring_access_end_wrapper(struct dp_soc *soc, + hal_ring_handle_t hal_ring_hdl) +{ + int ret; + + ret = hif_pm_runtime_get(soc->hif_handle, + RTPM_ID_DW_TX_HW_ENQUEUE); + switch (ret) { + case 0: + hal_srng_access_end(soc->hal_soc, hal_ring_hdl); + hif_pm_runtime_put(soc->hif_handle, + RTPM_ID_DW_TX_HW_ENQUEUE); + break; + /* + * If hif_pm_runtime_get returns -EBUSY or -EINPROGRESS, + * take the dp runtime refcount using dp_runtime_get, + * check link state,if up, write TX ring HP, else just set flush event. + * In dp_runtime_resume, wait until dp runtime refcount becomes + * zero or time out, then flush pending tx. + */ + case -EBUSY: + case -EINPROGRESS: + dp_runtime_get(soc); + if (hif_pm_get_link_state(soc->hif_handle) == + HIF_PM_LINK_STATE_UP) { + hal_srng_access_end(soc->hal_soc, hal_ring_hdl); + } else { + hal_srng_access_end_reap(soc->hal_soc, hal_ring_hdl); + hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT); + hal_srng_inc_flush_cnt(hal_ring_hdl); + } + dp_runtime_put(soc); + break; + default: + dp_runtime_get(soc); + hal_srng_access_end_reap(soc->hal_soc, hal_ring_hdl); + hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT); + hal_srng_inc_flush_cnt(hal_ring_hdl); + dp_runtime_put(soc); + } +} +#else +static inline void +dp_tx_ring_access_end_wrapper(struct dp_soc *soc, + hal_ring_handle_t hal_ring_hdl) +{ + hal_srng_access_end(soc->hal_soc, hal_ring_hdl); +} +#endif + /** * dp_tx_hw_enqueue() - Enqueue to TCL HW for transmit * @soc: DP Soc Handle @@ -1032,7 +1195,7 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, /* Return Buffer Manager ID */ uint8_t bm_id = ring_id; - void *hal_srng = soc->tcl_data_ring[ring_id].hal_srng; + hal_ring_handle_t hal_ring_hdl = soc->tcl_data_ring[ring_id].hal_srng; hal_tx_desc_cached = (void *) cached_desc; qdf_mem_zero(hal_tx_desc_cached, HAL_TX_DESC_LEN_BYTES); @@ -1041,6 +1204,12 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, length = HAL_TX_EXT_DESC_WITH_META_DATA; type = HAL_TX_BUF_TYPE_EXT_DESC; dma_addr = tx_desc->msdu_ext_desc->paddr; + + if (tx_desc->msdu_ext_desc->flags & + DP_TX_EXT_DESC_FLAG_METADATA_VALID) + length = HAL_TX_EXT_DESC_WITH_META_DATA; + else + length = HAL_TX_EXTENSION_DESC_LEN_BYTES; } else { length = qdf_nbuf_len(tx_desc->nbuf) - tx_desc->pkt_offset; type = HAL_TX_BUF_TYPE_BUFFER; @@ -1065,11 +1234,13 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, hal_tx_desc_set_search_type(soc->hal_soc, hal_tx_desc_cached, vdev->search_type); hal_tx_desc_set_search_index(soc->hal_soc, hal_tx_desc_cached, - vdev->bss_ast_hash); + vdev->bss_ast_idx); hal_tx_desc_set_dscp_tid_table_id(soc->hal_soc, hal_tx_desc_cached, vdev->dscp_tid_map_id); hal_tx_desc_set_encrypt_type(hal_tx_desc_cached, sec_type_map[sec_type]); + hal_tx_desc_set_cache_set_num(soc->hal_soc, hal_tx_desc_cached, + (vdev->bss_ast_hash & 0xF)); dp_verbose_debug("length:%d , type = %d, dma_addr %llx, offset %d desc id %u", length, type, (uint64_t)dma_addr, @@ -1082,8 +1253,8 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, vdev->hal_desc_addr_search_flags); /* verify checksum offload configuration*/ - if ((wlan_cfg_get_checksum_offload(soc->wlan_cfg_ctx)) && - ((qdf_nbuf_get_tx_cksum(tx_desc->nbuf) == QDF_NBUF_TX_CKSUM_TCP_UDP) + if (vdev->csum_enabled && + ((qdf_nbuf_get_tx_cksum(tx_desc->nbuf) == QDF_NBUF_TX_CKSUM_TCP_UDP) || qdf_nbuf_is_tso(tx_desc->nbuf))) { hal_tx_desc_set_l3_checksum_en(hal_tx_desc_cached, 1); hal_tx_desc_set_l4_checksum_en(hal_tx_desc_cached, 1); @@ -1093,12 +1264,12 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, hal_tx_desc_set_hlos_tid(hal_tx_desc_cached, tid); if (tx_desc->flags & DP_TX_DESC_FLAG_MESH) - hal_tx_desc_set_mesh_en(hal_tx_desc_cached, 1); + hal_tx_desc_set_mesh_en(soc->hal_soc, hal_tx_desc_cached, 1); tx_desc->timestamp = qdf_ktime_to_ms(qdf_ktime_get()); /* Sync cached descriptor with HW */ - hal_tx_desc = hal_srng_src_get_next(soc->hal_soc, hal_srng); + hal_tx_desc = hal_srng_src_get_next(soc->hal_soc, hal_ring_hdl); if (!hal_tx_desc) { dp_verbose_debug("TCL ring full ring_id:%d", ring_id); @@ -1108,6 +1279,7 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, } tx_desc->flags |= DP_TX_DESC_FLAG_QUEUED_TX; + dp_vdev_peer_stats_update_protocol_cnt_tx(vdev, tx_desc->nbuf); hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc); DP_STATS_INC_PKT(vdev, tx_i.processed, 1, length); @@ -1249,7 +1421,7 @@ static void dp_tx_get_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf, DP_TX_TID_OVERRIDE(msdu_info, nbuf); if (qdf_likely(vdev->tx_encap_type != htt_cmn_pkt_type_raw)) { eh = (qdf_ether_header_t *)nbuf->data; - hdr_ptr = eh->ether_dhost; + hdr_ptr = (uint8_t *)(eh->ether_dhost); L3datap = hdr_ptr + sizeof(qdf_ether_header_t); } else { qdf_dot3_qosframe_t *qos_wh = @@ -1443,6 +1615,39 @@ static inline void dp_non_std_tx_comp_free_buff(struct dp_soc *soc, } #endif +/** + * dp_tx_frame_is_drop() - checks if the packet is loopback + * @vdev: DP vdev handle + * @nbuf: skb + * + * Return: 1 if frame needs to be dropped else 0 + */ +int dp_tx_frame_is_drop(struct dp_vdev *vdev, uint8_t *srcmac, uint8_t *dstmac) +{ + struct dp_pdev *pdev = NULL; + struct dp_ast_entry *src_ast_entry = NULL; + struct dp_ast_entry *dst_ast_entry = NULL; + struct dp_soc *soc = NULL; + + qdf_assert(vdev); + pdev = vdev->pdev; + qdf_assert(pdev); + soc = pdev->soc; + + dst_ast_entry = dp_peer_ast_hash_find_by_pdevid + (soc, dstmac, vdev->pdev->pdev_id); + + src_ast_entry = dp_peer_ast_hash_find_by_pdevid + (soc, srcmac, vdev->pdev->pdev_id); + if (dst_ast_entry && src_ast_entry) { + if (dst_ast_entry->peer->peer_ids[0] == + src_ast_entry->peer->peer_ids[0]) + return 1; + } + + return 0; +} + /** * dp_tx_send_msdu_single() - Setup descriptor and enqueue single MSDU to TCL * @vdev: DP vdev handle @@ -1456,16 +1661,18 @@ static inline void dp_non_std_tx_comp_free_buff(struct dp_soc *soc, * Return: NULL on success, * nbuf when it fails to send */ -static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, - struct dp_tx_msdu_info_s *msdu_info, uint16_t peer_id, - struct cdp_tx_exception_metadata *tx_exc_metadata) +qdf_nbuf_t +dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info, uint16_t peer_id, + struct cdp_tx_exception_metadata *tx_exc_metadata) { struct dp_pdev *pdev = vdev->pdev; struct dp_soc *soc = pdev->soc; struct dp_tx_desc_s *tx_desc; QDF_STATUS status; struct dp_tx_queue *tx_q = &(msdu_info->tx_queue); - void *hal_srng = soc->tcl_data_ring[tx_q->ring_id].hal_srng; + hal_ring_handle_t hal_ring_hdl = + soc->tcl_data_ring[tx_q->ring_id].hal_srng; uint16_t htt_tcl_metadata = 0; uint8_t tid = msdu_info->tid; struct cdp_tid_tx_stats *tid_stats = NULL; @@ -1493,10 +1700,10 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, dp_tx_update_tdls_flags(tx_desc); - if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) { + if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_ring_hdl))) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s %d : HAL RING Access Failed -- %pK", - __func__, __LINE__, hal_srng); + __func__, __LINE__, hal_ring_hdl); dp_tx_get_tid(vdev, nbuf, msdu_info); tid_stats = &pdev->stats.tid_stats. tid_tx_stats[tx_q->ring_id][tid]; @@ -1543,20 +1750,62 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, nbuf = NULL; fail_return: - if (hif_pm_runtime_get(soc->hif_handle, - RTPM_ID_DW_TX_HW_ENQUEUE) == 0) { - hal_srng_access_end(soc->hal_soc, hal_srng); - hif_pm_runtime_put(soc->hif_handle, - RTPM_ID_DW_TX_HW_ENQUEUE); - } else { - hal_srng_access_end_reap(soc->hal_soc, hal_srng); - hal_srng_set_event(hal_srng, HAL_SRNG_FLUSH_EVENT); - hal_srng_inc_flush_cnt(hal_srng); - } + dp_tx_ring_access_end_wrapper(soc, hal_ring_hdl); return nbuf; } +/** + * dp_tx_comp_free_buf() - Free nbuf associated with the Tx Descriptor + * @soc: Soc handle + * @desc: software Tx descriptor to be processed + * + * Return: none + */ +static inline void dp_tx_comp_free_buf(struct dp_soc *soc, + struct dp_tx_desc_s *desc) +{ + struct dp_vdev *vdev = desc->vdev; + qdf_nbuf_t nbuf = desc->nbuf; + + /* nbuf already freed in vdev detach path */ + if (!nbuf) + return; + + /* If it is TDLS mgmt, don't unmap or free the frame */ + if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME) + return dp_non_std_tx_comp_free_buff(soc, desc, vdev); + + /* 0 : MSDU buffer, 1 : MLE */ + if (desc->msdu_ext_desc) { + /* TSO free */ + if (hal_tx_ext_desc_get_tso_enable( + desc->msdu_ext_desc->vaddr)) { + /* unmap eash TSO seg before free the nbuf */ + dp_tx_tso_unmap_segment(soc, desc->tso_desc, + desc->tso_num_desc); + qdf_nbuf_free(nbuf); + return; + } + } + + qdf_nbuf_unmap(soc->osdev, nbuf, QDF_DMA_TO_DEVICE); + + if (qdf_unlikely(!vdev)) { + qdf_nbuf_free(nbuf); + return; + } + + if (qdf_likely(!vdev->mesh_vdev)) + qdf_nbuf_free(nbuf); + else { + if (desc->flags & DP_TX_DESC_FLAG_TO_FW) { + qdf_nbuf_free(nbuf); + DP_STATS_INC(vdev, tx_i.mesh.completion_fw, 1); + } else + vdev->osif_tx_free_ext((nbuf)); + } +} /** * dp_tx_send_msdu_multiple() - Enqueue multiple MSDUs * @vdev: DP vdev handle @@ -1569,9 +1818,8 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, * nbuf when it fails to send */ #if QDF_LOCK_STATS -static noinline +noinline #else -static #endif qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, struct dp_tx_msdu_info_s *msdu_info) @@ -1583,15 +1831,15 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, bool is_cce_classified = false; QDF_STATUS status; uint16_t htt_tcl_metadata = 0; - struct dp_tx_queue *tx_q = &msdu_info->tx_queue; - void *hal_srng = soc->tcl_data_ring[tx_q->ring_id].hal_srng; + hal_ring_handle_t hal_ring_hdl = + soc->tcl_data_ring[tx_q->ring_id].hal_srng; struct cdp_tid_tx_stats *tid_stats = NULL; - if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) { + if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_ring_hdl))) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s %d : HAL RING Access Failed -- %pK", - __func__, __LINE__, hal_srng); + __func__, __LINE__, hal_ring_hdl); dp_tx_get_tid(vdev, nbuf, msdu_info); tid_stats = &pdev->stats.tid_stats. tid_tx_stats[tx_q->ring_id][msdu_info->tid]; @@ -1630,7 +1878,25 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, dp_tx_me_free_buf(pdev, (void *)(msdu_info->u.sg_info .curr_seg->frags[0].vaddr)); + i++; + continue; } + + if (msdu_info->frm_type == dp_tx_frm_tso) { + dp_tx_tso_unmap_segment(soc, + msdu_info->u.tso_info. + curr_seg, + msdu_info->u.tso_info. + tso_num_seg_list); + + if (msdu_info->u.tso_info.curr_seg->next) { + msdu_info->u.tso_info.curr_seg = + msdu_info->u.tso_info.curr_seg->next; + i++; + continue; + } + } + goto done; } @@ -1658,15 +1924,17 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, msdu_info->u.tso_info.curr_seg->next; /* - * If this is a jumbo nbuf, then increment the number of - * nbuf users for each additional segment of the msdu. - * This will ensure that the skb is freed only after - * receiving tx completion for all segments of an nbuf + * If this is a jumbo nbuf, then increment the + * number of nbuf users for each additional + * segment of the msdu. This will ensure that + * the skb is freed only after receiving tx + * completion for all segments of an nbuf */ qdf_nbuf_inc_users(nbuf); /* Check with MCL if this is needed */ - /* nbuf = msdu_info->u.tso_info.curr_seg->nbuf; */ + /* nbuf = msdu_info->u.tso_info.curr_seg->nbuf; + */ } } @@ -1685,19 +1953,29 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, tid_stats = &pdev->stats.tid_stats. tid_tx_stats[tx_q->ring_id][msdu_info->tid]; tid_stats->swdrop_cnt[TX_HW_ENQUEUE]++; - if (tx_desc->flags & DP_TX_DESC_FLAG_ME) - dp_tx_me_free_buf(pdev, tx_desc->me_buffer); dp_tx_desc_release(tx_desc, tx_q->desc_pool_id); + if (msdu_info->frm_type == dp_tx_frm_me) { + i++; + continue; + } + /* * For TSO frames, the nbuf users increment done for * the current segment has to be reverted, since the * hw enqueue for this segment failed */ if (msdu_info->frm_type == dp_tx_frm_tso && - msdu_info->u.tso_info.curr_seg) { - qdf_nbuf_free(nbuf); + msdu_info->u.tso_info.curr_seg) { + /* + * unmap and free current, + * retransmit remaining segments + */ + dp_tx_comp_free_buf(soc, tx_desc); + i++; + continue; } + goto done; } @@ -1729,13 +2007,13 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, done: if (hif_pm_runtime_get(soc->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE) == 0) { - hal_srng_access_end(soc->hal_soc, hal_srng); + hal_srng_access_end(soc->hal_soc, hal_ring_hdl); hif_pm_runtime_put(soc->hif_handle, RTPM_ID_DW_TX_HW_ENQUEUE); } else { - hal_srng_access_end_reap(soc->hal_soc, hal_srng); - hal_srng_set_event(hal_srng, HAL_SRNG_FLUSH_EVENT); - hal_srng_inc_flush_cnt(hal_srng); + hal_srng_access_end_reap(soc->hal_soc, hal_ring_hdl); + hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT); + hal_srng_inc_flush_cnt(hal_ring_hdl); } return nbuf; @@ -1944,8 +2222,9 @@ static bool dp_check_exc_metadata(struct cdp_tx_exception_metadata *tx_exc) { bool invalid_tid = (tx_exc->tid > DP_MAX_TIDS && tx_exc->tid != HTT_INVALID_TID); - bool invalid_encap_type = (tx_exc->tid > DP_MAX_TIDS && tx_exc->tid != - HTT_INVALID_TID); + bool invalid_encap_type = + (tx_exc->tx_encap_type > htt_cmn_pkt_num_types && + tx_exc->tx_encap_type != CDP_INVALID_TX_ENCAP_TYPE); bool invalid_sec_type = (tx_exc->sec_type > cdp_num_sec_types && tx_exc->sec_type != CDP_INVALID_SEC_TYPE); bool invalid_cookie = (tx_exc->is_tx_sniffer == 1 && @@ -1961,7 +2240,8 @@ static bool dp_check_exc_metadata(struct cdp_tx_exception_metadata *tx_exc) /** * dp_tx_send_exception() - Transmit a frame on a given VAP in exception path - * @vap_dev: DP vdev handle + * @soc: DP soc handle + * @vdev_id: id of DP vdev handle * @nbuf: skb * @tx_exc_metadata: Handle that holds exception path meta data * @@ -1971,12 +2251,18 @@ static bool dp_check_exc_metadata(struct cdp_tx_exception_metadata *tx_exc) * Return: NULL on success, * nbuf when it fails to send */ -qdf_nbuf_t dp_tx_send_exception(void *vap_dev, qdf_nbuf_t nbuf, - struct cdp_tx_exception_metadata *tx_exc_metadata) +qdf_nbuf_t +dp_tx_send_exception(struct cdp_soc_t *soc, uint8_t vdev_id, qdf_nbuf_t nbuf, + struct cdp_tx_exception_metadata *tx_exc_metadata) { qdf_ether_header_t *eh = NULL; - struct dp_vdev *vdev = (struct dp_vdev *) vap_dev; struct dp_tx_msdu_info_s msdu_info; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + + if (qdf_unlikely(!vdev)) + goto fail; qdf_mem_zero(&msdu_info, sizeof(msdu_info)); @@ -1986,7 +2272,8 @@ qdf_nbuf_t dp_tx_send_exception(void *vap_dev, qdf_nbuf_t nbuf, msdu_info.tid = tx_exc_metadata->tid; eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf); - dp_verbose_debug("skb %pM", nbuf->data); + dp_verbose_debug("skb "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(nbuf->data)); DP_STATS_INC_PKT(vdev, tx_i.rcvd, 1, qdf_nbuf_len(nbuf)); @@ -2067,7 +2354,8 @@ qdf_nbuf_t dp_tx_send_exception(void *vap_dev, qdf_nbuf_t nbuf, /** * dp_tx_send_mesh() - Transmit mesh frame on a given VAP - * @vap_dev: DP vdev handle + * @soc: DP soc handle + * @vdev_id: DP vdev handle * @nbuf: skb * * Entry point for Core Tx layer (DP_TX) invoked from @@ -2077,12 +2365,13 @@ qdf_nbuf_t dp_tx_send_exception(void *vap_dev, qdf_nbuf_t nbuf, * nbuf when it fails to send */ #ifdef MESH_MODE_SUPPORT -qdf_nbuf_t dp_tx_send_mesh(void *vap_dev, qdf_nbuf_t nbuf) +qdf_nbuf_t dp_tx_send_mesh(struct cdp_soc_t *soc, uint8_t vdev_id, + qdf_nbuf_t nbuf) { struct meta_hdr_s *mhdr; qdf_nbuf_t nbuf_mesh = NULL; qdf_nbuf_t nbuf_clone = NULL; - struct dp_vdev *vdev = (struct dp_vdev *) vap_dev; + struct dp_vdev *vdev; uint8_t no_enc_frame = 0; nbuf_mesh = qdf_nbuf_unshare(nbuf); @@ -2091,6 +2380,15 @@ qdf_nbuf_t dp_tx_send_mesh(void *vap_dev, qdf_nbuf_t nbuf) "qdf_nbuf_unshare failed"); return nbuf; } + + vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + if (!vdev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "vdev is NULL for vdev_id %d", vdev_id); + return nbuf; + } + nbuf = nbuf_mesh; mhdr = (struct meta_hdr_s *)qdf_nbuf_data(nbuf); @@ -2114,7 +2412,7 @@ qdf_nbuf_t dp_tx_send_mesh(void *vap_dev, qdf_nbuf_t nbuf) } if (nbuf_clone) { - if (!dp_tx_send(vap_dev, nbuf_clone)) { + if (!dp_tx_send(soc, vdev_id, nbuf_clone)) { DP_STATS_INC(vdev, tx_i.mesh.exception_fw, 1); } else { qdf_nbuf_free(nbuf_clone); @@ -2126,7 +2424,7 @@ qdf_nbuf_t dp_tx_send_mesh(void *vap_dev, qdf_nbuf_t nbuf) else qdf_nbuf_set_tx_ftype(nbuf, CB_FTYPE_INVALID); - nbuf = dp_tx_send(vap_dev, nbuf); + nbuf = dp_tx_send(soc, vdev_id, nbuf); if ((!nbuf) && no_enc_frame) { DP_STATS_INC(vdev, tx_i.mesh.exception_fw, 1); } @@ -2136,16 +2434,18 @@ qdf_nbuf_t dp_tx_send_mesh(void *vap_dev, qdf_nbuf_t nbuf) #else -qdf_nbuf_t dp_tx_send_mesh(void *vap_dev, qdf_nbuf_t nbuf) +qdf_nbuf_t dp_tx_send_mesh(struct cdp_soc_t *soc, uint8_t vdev_id, + qdf_nbuf_t nbuf) { - return dp_tx_send(vap_dev, nbuf); + return dp_tx_send(soc, vdev_id, nbuf); } #endif /** * dp_tx_send() - Transmit a frame on a given VAP - * @vap_dev: DP vdev handle + * @soc: DP soc handle + * @vdev_id: id of DP vdev handle * @nbuf: skb * * Entry point for Core Tx layer (DP_TX) invoked from @@ -2155,21 +2455,27 @@ qdf_nbuf_t dp_tx_send_mesh(void *vap_dev, qdf_nbuf_t nbuf) * Return: NULL on success, * nbuf when it fails to send */ -qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf) +qdf_nbuf_t dp_tx_send(struct cdp_soc_t *soc, uint8_t vdev_id, qdf_nbuf_t nbuf) { qdf_ether_header_t *eh = NULL; struct dp_tx_msdu_info_s msdu_info; struct dp_tx_seg_info_s seg_info; - struct dp_vdev *vdev = (struct dp_vdev *) vap_dev; uint16_t peer_id = HTT_INVALID_PEER; qdf_nbuf_t nbuf_mesh = NULL; + struct dp_vdev *vdev = + dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + + if (qdf_unlikely(!vdev)) + return nbuf; qdf_mem_zero(&msdu_info, sizeof(msdu_info)); qdf_mem_zero(&seg_info, sizeof(seg_info)); eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf); - dp_verbose_debug("skb %pM", nbuf->data); + dp_verbose_debug("skb "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(nbuf->data)); /* * Set Default Host TID value to invalid TID @@ -2219,11 +2525,11 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf) */ if (qdf_nbuf_is_tso(nbuf)) { dp_verbose_debug("TSO frame %pK", vdev); - DP_STATS_INC_PKT(vdev, tx_i.tso.tso_pkt, 1, - qdf_nbuf_len(nbuf)); + DP_STATS_INC_PKT(vdev->pdev, tso_stats.num_tso_pkts, 1, + qdf_nbuf_len(nbuf)); if (dp_tx_prepare_tso(vdev, nbuf, &msdu_info)) { - DP_STATS_INC_PKT(vdev, tx_i.tso.dropped_host, 1, + DP_STATS_INC_PKT(vdev->pdev, tso_stats.dropped_host, 1, qdf_nbuf_len(nbuf)); return nbuf; } @@ -2290,6 +2596,9 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf) send_multiple: nbuf = dp_tx_send_msdu_multiple(vdev, nbuf, &msdu_info); + if (qdf_unlikely(nbuf && msdu_info.frm_type == dp_tx_frm_raw)) + dp_tx_raw_prepare_unset(vdev->pdev->soc, nbuf); + return nbuf; } @@ -2605,58 +2914,6 @@ dp_send_completion_to_stack(struct dp_soc *soc, struct dp_pdev *pdev, } #endif -/** - * dp_tx_comp_free_buf() - Free nbuf associated with the Tx Descriptor - * @soc: Soc handle - * @desc: software Tx descriptor to be processed - * - * Return: none - */ -static inline void dp_tx_comp_free_buf(struct dp_soc *soc, - struct dp_tx_desc_s *desc) -{ - struct dp_vdev *vdev = desc->vdev; - qdf_nbuf_t nbuf = desc->nbuf; - - /* nbuf already freed in vdev detach path */ - if (!nbuf) - return; - - /* If it is TDLS mgmt, don't unmap or free the frame */ - if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME) - return dp_non_std_tx_comp_free_buff(soc, desc, vdev); - - /* 0 : MSDU buffer, 1 : MLE */ - if (desc->msdu_ext_desc) { - /* TSO free */ - if (hal_tx_ext_desc_get_tso_enable( - desc->msdu_ext_desc->vaddr)) { - /* unmap eash TSO seg before free the nbuf */ - dp_tx_tso_unmap_segment(soc, desc->tso_desc, - desc->tso_num_desc); - qdf_nbuf_free(nbuf); - return; - } - } - - qdf_nbuf_unmap(soc->osdev, nbuf, QDF_DMA_TO_DEVICE); - - if (qdf_unlikely(!vdev)) { - qdf_nbuf_free(nbuf); - return; - } - - if (qdf_likely(!vdev->mesh_vdev)) - qdf_nbuf_free(nbuf); - else { - if (desc->flags & DP_TX_DESC_FLAG_TO_FW) { - qdf_nbuf_free(nbuf); - DP_STATS_INC(vdev, tx_i.mesh.completion_fw, 1); - } else - vdev->osif_tx_free_ext((nbuf)); - } -} - #ifdef MESH_MODE_SUPPORT /** * dp_tx_comp_fill_tx_completion_stats() - Fill per packet Tx completion stats @@ -2836,14 +3093,30 @@ dp_tx_update_peer_stats(struct dp_tx_desc_s *tx_desc, DP_STATS_INCC(peer, tx.dropped.fw_reason3, 1, (ts->status == HAL_TX_TQM_RR_FW_REASON3)); + /* + * tx_failed is ideally supposed to be updated from HTT ppdu completion + * stats. But in IPQ807X/IPQ6018 chipsets owing to hw limitation there + * are no completions for failed cases. Hence updating tx_failed from + * data path. Please note that if tx_failed is fixed to be from ppdu, + * then this has to be removed + */ + peer->stats.tx.tx_failed = peer->stats.tx.dropped.fw_rem.num + + peer->stats.tx.dropped.fw_rem_notx + + peer->stats.tx.dropped.fw_rem_tx + + peer->stats.tx.dropped.age_out + + peer->stats.tx.dropped.fw_reason1 + + peer->stats.tx.dropped.fw_reason2 + + peer->stats.tx.dropped.fw_reason3; + + if (ts->status < CDP_MAX_TX_TQM_STATUS) { + tid_stats->tqm_status_cnt[ts->status]++; + } + if (ts->status != HAL_TX_TQM_RR_FRAME_ACKED) { - tid_stats->comp_fail_cnt++; dp_update_no_ack_stats(tx_desc->nbuf, peer); return; } - tid_stats->success_cnt++; - DP_STATS_INCC(peer, tx.ofdma, 1, ts->ofdma); DP_STATS_INCC(peer, tx.amsdu_cnt, 1, ts->msdu_part_of_amsdu); @@ -3027,6 +3300,7 @@ static inline void dp_tx_sojourn_stats_process(struct dp_pdev *pdev, } #else static inline void dp_tx_sojourn_stats_process(struct dp_pdev *pdev, + struct dp_peer *peer, uint8_t tid, uint64_t txdesc_ts, uint32_t ppdu_id) @@ -3085,6 +3359,7 @@ dp_tx_comp_process_desc(struct dp_soc *soc, /** * dp_tx_comp_process_tx_status() - Parse and Dump Tx completion status info + * @soc: DP soc handle * @tx_desc: software descriptor head pointer * @ts: Tx completion status * @peer: peer handle @@ -3093,13 +3368,13 @@ dp_tx_comp_process_desc(struct dp_soc *soc, * Return: none */ static inline -void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc, +void dp_tx_comp_process_tx_status(struct dp_soc *soc, + struct dp_tx_desc_s *tx_desc, struct hal_tx_completion_status *ts, struct dp_peer *peer, uint8_t ring_id) { uint32_t length; qdf_ether_header_t *eh; - struct dp_soc *soc = NULL; struct dp_vdev *vdev = tx_desc->vdev; qdf_nbuf_t nbuf = tx_desc->nbuf; @@ -3109,6 +3384,7 @@ void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc, } eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf); + length = qdf_nbuf_len(nbuf); DPTRACE(qdf_dp_trace_ptr(tx_desc->nbuf, QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD, @@ -3147,26 +3423,22 @@ void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc, ts->tones_in_ru, ts->tsf, ts->ppdu_id, ts->transmit_cnt, ts->tid, ts->peer_id); - soc = vdev->pdev->soc; - /* Update SoC level stats */ DP_STATS_INCC(soc, tx.dropped_fw_removed, 1, (ts->status == HAL_TX_TQM_RR_REM_CMD_REM)); + if (!peer) { + dp_err_rl("peer is null or deletion in progress"); + DP_STATS_INC_PKT(soc, tx.tx_invalid_peer, 1, length); + goto out; + } + /* Update per-packet stats for mesh mode */ if (qdf_unlikely(vdev->mesh_vdev) && !(tx_desc->flags & DP_TX_DESC_FLAG_TO_FW)) dp_tx_comp_fill_tx_completion_stats(tx_desc, ts); - length = qdf_nbuf_len(nbuf); /* Update peer level stats */ - if (!peer) { - QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_DP, - "peer is null or deletion in progress"); - DP_STATS_INC_PKT(soc, tx.tx_invalid_peer, 1, length); - goto out; - } - if (qdf_unlikely(peer->bss_peer && vdev->opmode == wlan_op_mode_ap)) { if (ts->status != HAL_TX_TQM_RR_REM_CMD_REM) { DP_STATS_INC_PKT(peer, tx.mcast, 1, length); @@ -3195,6 +3467,7 @@ void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc, out: return; } + /** * dp_tx_comp_process_desc_list() - Tx complete software descriptor handler * @soc: core txrx main context @@ -3221,7 +3494,7 @@ dp_tx_comp_process_desc_list(struct dp_soc *soc, while (desc) { hal_tx_comp_get_status(&desc->comp, &ts, soc->hal_soc); peer = dp_peer_find_by_id(soc, ts.peer_id); - dp_tx_comp_process_tx_status(desc, &ts, peer, ring_id); + dp_tx_comp_process_tx_status(soc, desc, &ts, peer, ring_id); netbuf = desc->nbuf; /* check tx complete notification */ @@ -3263,6 +3536,7 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status, uint32_t *htt_desc = (uint32_t *)status; struct dp_peer *peer; struct cdp_tid_tx_stats *tid_stats = NULL; + struct htt_soc *htt_handle; qdf_assert(tx_desc->pdev); @@ -3272,8 +3546,9 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status, if (!vdev) return; - tx_status = HTT_TX_WBM_COMPLETION_V2_TX_STATUS_GET(htt_desc[0]); + htt_handle = (struct htt_soc *)soc->htt_handle; + htt_wbm_event_record(htt_handle->htt_logger_handle, tx_status, status); switch (tx_status) { case HTT_TX_FW2WBM_TX_STATUS_OK: @@ -3309,11 +3584,8 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status, if (qdf_unlikely(pdev->delay_stats_flag)) dp_tx_compute_delay(vdev, tx_desc, tid, ring_id); - if (qdf_unlikely(tx_status != HTT_TX_FW2WBM_TX_STATUS_OK)) { - ts.status = HAL_TX_TQM_RR_REM_CMD_REM; - tid_stats->comp_fail_cnt++; - } else { - tid_stats->success_cnt++; + if (tx_status < CDP_MAX_TX_HTT_STATUS) { + tid_stats->htt_status_cnt[tx_status]++; } peer = dp_peer_find_by_id(soc, ts.peer_id); @@ -3321,7 +3593,7 @@ void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status, if (qdf_likely(peer)) dp_peer_unref_del_find_by_id(peer); - dp_tx_comp_process_tx_status(tx_desc, &ts, peer, ring_id); + dp_tx_comp_process_tx_status(soc, tx_desc, &ts, peer, ring_id); dp_tx_comp_process_desc(soc, tx_desc, &ts, peer); dp_tx_desc_release(tx_desc, tx_desc->pool_id); @@ -3384,7 +3656,8 @@ static inline bool dp_tx_comp_enable_eol_data_check(struct dp_soc *soc) #endif uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc, - void *hal_srng, uint8_t ring_id, uint32_t quota) + hal_ring_handle_t hal_ring_hdl, uint8_t ring_id, + uint32_t quota) { void *tx_comp_hal_desc; uint8_t buffer_src; @@ -3405,14 +3678,14 @@ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc, tail_desc = NULL; count = 0; - if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_srng))) { - dp_err("HAL RING Access Failed -- %pK", hal_srng); + if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring_hdl))) { + dp_err("HAL RING Access Failed -- %pK", hal_ring_hdl); return 0; } /* Find head descriptor from completion ring */ while (qdf_likely(tx_comp_hal_desc = - hal_srng_dst_get_next(soc->hal_soc, hal_srng))) { + hal_srng_dst_get_next(soc->hal_soc, hal_ring_hdl))) { buffer_src = hal_tx_comp_get_buffer_source(tx_comp_hal_desc); @@ -3436,13 +3709,22 @@ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc, * completion ring. These errors are not related to * Tx completions, and should just be ignored */ - - wbm_internal_error = - hal_get_wbm_internal_error(tx_comp_hal_desc); + wbm_internal_error = hal_get_wbm_internal_error( + soc->hal_soc, + tx_comp_hal_desc); if (wbm_internal_error) { dp_err_rl("Tx comp wbm_internal_error!!"); - DP_STATS_INC(soc, tx.wbm_internal_error, 1); + DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_ALL], 1); + + if (HAL_TX_COMP_RELEASE_SOURCE_REO == + buffer_src) + dp_handle_wbm_internal_error( + soc, + tx_comp_hal_desc, + hal_tx_comp_get_buffer_type( + tx_comp_hal_desc)); + } else { dp_err_rl("Tx comp wbm_internal_error false"); DP_STATS_INC(soc, tx.non_wbm_internal_err, 1); @@ -3477,6 +3759,20 @@ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc, continue; } + if (qdf_unlikely(tx_desc->pdev->is_pdev_down)) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_INFO, + "pdev in down state %d", + tx_desc_id); + + num_processed += !(count & DP_TX_NAPI_BUDGET_DIV_MASK); + count++; + + dp_tx_comp_free_buf(soc, tx_desc); + dp_tx_desc_release(tx_desc, tx_desc->pool_id); + continue; + } + /* * If the release source is FW, process the HTT status */ @@ -3542,7 +3838,7 @@ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc, break; } - dp_srng_access_end(int_ctx, soc, hal_srng); + dp_srng_access_end(int_ctx, soc, hal_ring_hdl); /* Process the reaped descriptors */ if (head_desc) @@ -3550,7 +3846,8 @@ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc, if (dp_tx_comp_enable_eol_data_check(soc)) { if (!force_break && - hal_srng_dst_peek_sync_locked(soc, hal_srng)) { + hal_srng_dst_peek_sync_locked(soc->hal_soc, + hal_ring_hdl)) { DP_STATS_INC(soc, tx.hp_oos2, 1); if (!hif_exec_should_yield(soc->hif_handle, int_ctx->dp_intr_id)) @@ -3563,27 +3860,48 @@ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc, } #ifdef FEATURE_WLAN_TDLS -/** - * dp_tx_non_std() - Allow the control-path SW to send data frames - * - * @data_vdev - which vdev should transmit the tx data frames - * @tx_spec - what non-standard handling to apply to the tx data frames - * @msdu_list - NULL-terminated list of tx MSDUs - * - * Return: NULL on success, - * nbuf when it fails to send - */ -qdf_nbuf_t dp_tx_non_std(struct cdp_vdev *vdev_handle, - enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list) +qdf_nbuf_t dp_tx_non_std(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list) { - struct dp_vdev *vdev = (struct dp_vdev *) vdev_handle; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + + if (!vdev) { + dp_err("vdev handle for id %d is NULL", vdev_id); + return NULL; + } if (tx_spec & OL_TX_SPEC_NO_FREE) vdev->is_tdls_frame = true; - return dp_tx_send(vdev_handle, msdu_list); + + return dp_tx_send(soc_hdl, vdev_id, msdu_list); } #endif +static void dp_tx_vdev_update_feature_flags(struct dp_vdev *vdev) +{ + struct wlan_cfg_dp_soc_ctxt *cfg; + + struct dp_soc *soc; + + soc = vdev->pdev->soc; + if (!soc) + return; + + cfg = soc->wlan_cfg_ctx; + if (!cfg) + return; + + if (vdev->opmode == wlan_op_mode_ndi) + vdev->csum_enabled = wlan_cfg_get_nan_checksum_offload(cfg); + else if ((vdev->subtype == wlan_op_subtype_p2p_device) || + (vdev->subtype == wlan_op_subtype_p2p_cli) || + (vdev->subtype == wlan_op_subtype_p2p_go)) + vdev->csum_enabled = wlan_cfg_get_p2p_checksum_offload(cfg); + else + vdev->csum_enabled = wlan_cfg_get_checksum_offload(cfg); +} + /** * dp_tx_vdev_attach() - attach vdev to dp tx * @vdev: virtual device instance @@ -3593,6 +3911,7 @@ qdf_nbuf_t dp_tx_non_std(struct cdp_vdev *vdev_handle, */ QDF_STATUS dp_tx_vdev_attach(struct dp_vdev *vdev) { + int pdev_id; /* * Fill HTT TCL Metadata with Vdev ID and MAC ID */ @@ -3602,8 +3921,10 @@ QDF_STATUS dp_tx_vdev_attach(struct dp_vdev *vdev) HTT_TX_TCL_METADATA_VDEV_ID_SET(vdev->htt_tcl_metadata, vdev->vdev_id); - HTT_TX_TCL_METADATA_PDEV_ID_SET(vdev->htt_tcl_metadata, - DP_SW2HW_MACID(vdev->pdev->pdev_id)); + pdev_id = + dp_get_target_pdev_id_for_host_pdev_id(vdev->pdev->soc, + vdev->pdev->pdev_id); + HTT_TX_TCL_METADATA_PDEV_ID_SET(vdev->htt_tcl_metadata, pdev_id); /* * Set HTT Extension Valid bit to 0 by default @@ -3612,6 +3933,8 @@ QDF_STATUS dp_tx_vdev_attach(struct dp_vdev *vdev) dp_tx_vdev_update_search_flags(vdev); + dp_tx_vdev_update_feature_flags(vdev); + return QDF_STATUS_SUCCESS; } @@ -3841,6 +4164,7 @@ QDF_STATUS dp_tx_vdev_detach(struct dp_vdev *vdev) /* Reset TX desc associated to this Vdev as NULL */ dp_tx_desc_flush(pdev, vdev, false); + dp_tx_vdev_multipass_deinit(vdev); return QDF_STATUS_SUCCESS; } @@ -3983,7 +4307,7 @@ QDF_STATUS dp_tso_detach_wifi3(void *txrx_soc) } #endif -QDF_STATUS dp_tso_soc_detach(void *txrx_soc) +QDF_STATUS dp_tso_soc_detach(struct cdp_soc_t *txrx_soc) { struct dp_soc *soc = (struct dp_soc *)txrx_soc; uint8_t i; @@ -4017,7 +4341,7 @@ QDF_STATUS dp_tso_soc_detach(void *txrx_soc) * Return: QDF_STATUS_E_FAILURE on failure or * QDF_STATUS_SUCCESS on success */ -QDF_STATUS dp_tso_soc_attach(void *txrx_soc) +QDF_STATUS dp_tso_soc_attach(struct cdp_soc_t *txrx_soc) { struct dp_soc *soc = (struct dp_soc *)txrx_soc; uint8_t i; @@ -4121,7 +4445,12 @@ QDF_STATUS dp_tx_soc_attach(struct dp_soc *soc) num_desc = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx); num_ext_desc = wlan_cfg_get_num_tx_ext_desc(soc->wlan_cfg_ctx); - if (num_pool > MAX_TXDESC_POOLS) + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s Tx Desc Alloc num_pool = %d, descs = %d", + __func__, num_pool, num_desc); + + if ((num_pool > MAX_TXDESC_POOLS) || + (num_desc > WLAN_CFG_NUM_TX_DESC_MAX)) goto fail; if (dp_tx_alloc_static_pools(soc, num_pool, num_desc)) @@ -4129,10 +4458,6 @@ QDF_STATUS dp_tx_soc_attach(struct dp_soc *soc) dp_tx_flow_control_init(soc); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "%s Tx Desc Alloc num_pool = %d, descs = %d", - __func__, num_pool, num_desc); - /* Allocate extension tx descriptor pools */ for (i = 0; i < num_pool; i++) { if (dp_tx_ext_desc_pool_alloc(soc, i, num_ext_desc)) { @@ -4181,232 +4506,3 @@ QDF_STATUS dp_tx_soc_attach(struct dp_soc *soc) dp_tx_soc_detach(soc); return QDF_STATUS_E_RESOURCES; } - -/* - * dp_tx_me_mem_free(): Function to free allocated memory in mcast enahncement - * pdev: pointer to DP PDEV structure - * seg_info_head: Pointer to the head of list - * - * return: void - */ -static void dp_tx_me_mem_free(struct dp_pdev *pdev, - struct dp_tx_seg_info_s *seg_info_head) -{ - struct dp_tx_me_buf_t *mc_uc_buf; - struct dp_tx_seg_info_s *seg_info_new = NULL; - qdf_nbuf_t nbuf = NULL; - uint64_t phy_addr; - - while (seg_info_head) { - nbuf = seg_info_head->nbuf; - mc_uc_buf = (struct dp_tx_me_buf_t *) - seg_info_head->frags[0].vaddr; - phy_addr = seg_info_head->frags[0].paddr_hi; - phy_addr = (phy_addr << 32) | seg_info_head->frags[0].paddr_lo; - qdf_mem_unmap_nbytes_single(pdev->soc->osdev, - phy_addr, - QDF_DMA_TO_DEVICE , QDF_MAC_ADDR_SIZE); - dp_tx_me_free_buf(pdev, mc_uc_buf); - qdf_nbuf_free(nbuf); - seg_info_new = seg_info_head; - seg_info_head = seg_info_head->next; - qdf_mem_free(seg_info_new); - } -} - -/** - * dp_tx_me_send_convert_ucast(): function to convert multicast to unicast - * @vdev: DP VDEV handle - * @nbuf: Multicast nbuf - * @newmac: Table of the clients to which packets have to be sent - * @new_mac_cnt: No of clients - * - * return: no of converted packets - */ -uint16_t -dp_tx_me_send_convert_ucast(struct cdp_vdev *vdev_handle, qdf_nbuf_t nbuf, - uint8_t newmac[][QDF_MAC_ADDR_SIZE], uint8_t new_mac_cnt) -{ - struct dp_vdev *vdev = (struct dp_vdev *) vdev_handle; - struct dp_pdev *pdev = vdev->pdev; - qdf_ether_header_t *eh; - uint8_t *data; - uint16_t len; - - /* reference to frame dst addr */ - uint8_t *dstmac; - /* copy of original frame src addr */ - uint8_t srcmac[QDF_MAC_ADDR_SIZE]; - - /* local index into newmac */ - uint8_t new_mac_idx = 0; - struct dp_tx_me_buf_t *mc_uc_buf; - qdf_nbuf_t nbuf_clone; - struct dp_tx_msdu_info_s msdu_info; - struct dp_tx_seg_info_s *seg_info_head = NULL; - struct dp_tx_seg_info_s *seg_info_tail = NULL; - struct dp_tx_seg_info_s *seg_info_new; - qdf_dma_addr_t paddr_data; - qdf_dma_addr_t paddr_mcbuf = 0; - uint8_t empty_entry_mac[QDF_MAC_ADDR_SIZE] = {0}; - QDF_STATUS status; - - qdf_mem_zero(&msdu_info, sizeof(msdu_info)); - - dp_tx_get_queue(vdev, nbuf, &msdu_info.tx_queue); - - eh = (qdf_ether_header_t *)nbuf; - qdf_mem_copy(srcmac, eh->ether_shost, QDF_MAC_ADDR_SIZE); - - len = qdf_nbuf_len(nbuf); - - data = qdf_nbuf_data(nbuf); - - status = qdf_nbuf_map(vdev->osdev, nbuf, - QDF_DMA_TO_DEVICE); - - if (status) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "Mapping failure Error:%d", status); - DP_STATS_INC(vdev, tx_i.mcast_en.dropped_map_error, 1); - qdf_nbuf_free(nbuf); - return 1; - } - - paddr_data = qdf_nbuf_mapped_paddr_get(nbuf) + QDF_MAC_ADDR_SIZE; - - for (new_mac_idx = 0; new_mac_idx < new_mac_cnt; new_mac_idx++) { - dstmac = newmac[new_mac_idx]; - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "added mac addr (%pM)", dstmac); - - /* Check for NULL Mac Address */ - if (!qdf_mem_cmp(dstmac, empty_entry_mac, QDF_MAC_ADDR_SIZE)) - continue; - - /* frame to self mac. skip */ - if (!qdf_mem_cmp(dstmac, srcmac, QDF_MAC_ADDR_SIZE)) - continue; - - /* - * TODO: optimize to avoid malloc in per-packet path - * For eg. seg_pool can be made part of vdev structure - */ - seg_info_new = qdf_mem_malloc(sizeof(*seg_info_new)); - - if (!seg_info_new) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "alloc failed"); - DP_STATS_INC(vdev, tx_i.mcast_en.fail_seg_alloc, 1); - goto fail_seg_alloc; - } - - mc_uc_buf = dp_tx_me_alloc_buf(pdev); - if (!mc_uc_buf) - goto fail_buf_alloc; - - /* - * TODO: Check if we need to clone the nbuf - * Or can we just use the reference for all cases - */ - if (new_mac_idx < (new_mac_cnt - 1)) { - nbuf_clone = qdf_nbuf_clone((qdf_nbuf_t)nbuf); - if (!nbuf_clone) { - DP_STATS_INC(vdev, tx_i.mcast_en.clone_fail, 1); - goto fail_clone; - } - } else { - /* - * Update the ref - * to account for frame sent without cloning - */ - qdf_nbuf_ref(nbuf); - nbuf_clone = nbuf; - } - - qdf_mem_copy(mc_uc_buf->data, dstmac, QDF_MAC_ADDR_SIZE); - - status = qdf_mem_map_nbytes_single(vdev->osdev, mc_uc_buf->data, - QDF_DMA_TO_DEVICE, QDF_MAC_ADDR_SIZE, - &paddr_mcbuf); - - if (status) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "Mapping failure Error:%d", status); - DP_STATS_INC(vdev, tx_i.mcast_en.dropped_map_error, 1); - goto fail_map; - } - - seg_info_new->frags[0].vaddr = (uint8_t *)mc_uc_buf; - seg_info_new->frags[0].paddr_lo = (uint32_t) paddr_mcbuf; - seg_info_new->frags[0].paddr_hi = - (uint16_t)((uint64_t)paddr_mcbuf >> 32); - seg_info_new->frags[0].len = QDF_MAC_ADDR_SIZE; - - /*preparing data fragment*/ - seg_info_new->frags[1].vaddr = - qdf_nbuf_data(nbuf) + QDF_MAC_ADDR_SIZE; - seg_info_new->frags[1].paddr_lo = (uint32_t)paddr_data; - seg_info_new->frags[1].paddr_hi = - (uint16_t)(((uint64_t)paddr_data) >> 32); - seg_info_new->frags[1].len = len - QDF_MAC_ADDR_SIZE; - - seg_info_new->nbuf = nbuf_clone; - seg_info_new->frag_cnt = 2; - seg_info_new->total_len = len; - - seg_info_new->next = NULL; - - if (!seg_info_head) - seg_info_head = seg_info_new; - else - seg_info_tail->next = seg_info_new; - - seg_info_tail = seg_info_new; - } - - if (!seg_info_head) { - goto free_return; - } - - msdu_info.u.sg_info.curr_seg = seg_info_head; - msdu_info.num_seg = new_mac_cnt; - msdu_info.frm_type = dp_tx_frm_me; - - msdu_info.tid = HTT_INVALID_TID; - if (qdf_unlikely(vdev->mcast_enhancement_en > 0) && - qdf_unlikely(pdev->hmmc_tid_override_en)) - msdu_info.tid = pdev->hmmc_tid; - - DP_STATS_INC(vdev, tx_i.mcast_en.ucast, new_mac_cnt); - dp_tx_send_msdu_multiple(vdev, nbuf, &msdu_info); - - while (seg_info_head->next) { - seg_info_new = seg_info_head; - seg_info_head = seg_info_head->next; - qdf_mem_free(seg_info_new); - } - qdf_mem_free(seg_info_head); - - qdf_nbuf_unmap(pdev->soc->osdev, nbuf, QDF_DMA_TO_DEVICE); - qdf_nbuf_free(nbuf); - return new_mac_cnt; - -fail_map: - qdf_nbuf_free(nbuf_clone); - -fail_clone: - dp_tx_me_free_buf(pdev, mc_uc_buf); - -fail_buf_alloc: - qdf_mem_free(seg_info_new); - -fail_seg_alloc: - dp_tx_me_mem_free(pdev, seg_info_head); - -free_return: - qdf_nbuf_unmap(pdev->soc->osdev, nbuf, QDF_DMA_TO_DEVICE); - qdf_nbuf_free(nbuf); - return 1; -} - diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx.h index 494fc1bd251178b47bd290a7264a4595788d04df..570e780fb6a1ad044d41ae820e8dcd827fb7d2f9 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. 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 @@ -35,6 +36,8 @@ #define DP_TX_DESC_FLAG_ME 0x80 #define DP_TX_DESC_FLAG_TDLS_FRAME 0x100 +#define DP_TX_EXT_DESC_FLAG_METADATA_VALID 0x1 + #define DP_TX_FREE_SINGLE_BUF(soc, buf) \ do { \ qdf_nbuf_unmap(soc->osdev, buf, QDF_DMA_TO_DEVICE); \ @@ -43,6 +46,22 @@ do { \ #define OCB_HEADER_VERSION 1 +#ifdef TX_PER_PDEV_DESC_POOL +#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +#define DP_TX_GET_DESC_POOL_ID(vdev) (vdev->vdev_id) +#else /* QCA_LL_TX_FLOW_CONTROL_V2 */ +#define DP_TX_GET_DESC_POOL_ID(vdev) (vdev->pdev->pdev_id) +#endif /* QCA_LL_TX_FLOW_CONTROL_V2 */ + #define DP_TX_GET_RING_ID(vdev) (vdev->pdev->pdev_id) +#else + #ifdef TX_PER_VDEV_DESC_POOL + #define DP_TX_GET_DESC_POOL_ID(vdev) (vdev->vdev_id) + #define DP_TX_GET_RING_ID(vdev) (vdev->pdev->pdev_id) + #endif /* TX_PER_VDEV_DESC_POOL */ +#endif /* TX_PER_PDEV_DESC_POOL */ +#define DP_TX_QUEUE_MASK 0x3 +#define DP_TX_MSDU_INFO_META_DATA_DWORDS 9 + /** * struct dp_tx_frag_info_s * @vaddr: hlos vritual address for buffer @@ -133,7 +152,7 @@ struct dp_tx_msdu_info_s { struct qdf_tso_info_t tso_info; struct dp_tx_sg_info_s sg_info; } u; - uint32_t meta_data[7]; + uint32_t meta_data[DP_TX_MSDU_INFO_META_DATA_DWORDS]; uint8_t exception_fw; uint16_t ppdu_cookie; uint8_t is_tx_sniffer; @@ -155,7 +174,7 @@ QDF_STATUS dp_tx_soc_detach(struct dp_soc *soc); * Return: QDF_STATUS_E_FAILURE on failure or * QDF_STATUS_SUCCESS on success */ -QDF_STATUS dp_tso_soc_attach(void *txrx_soc); +QDF_STATUS dp_tso_soc_attach(struct cdp_soc_t *txrx_soc); /** * dp_tso_detach() - TSO Detach handler @@ -166,20 +185,46 @@ QDF_STATUS dp_tso_soc_attach(void *txrx_soc); * Return: QDF_STATUS_E_FAILURE on failure or * QDF_STATUS_SUCCESS on success */ -QDF_STATUS dp_tso_soc_detach(void *txrx_soc); +QDF_STATUS dp_tso_soc_detach(struct cdp_soc_t *txrx_soc); QDF_STATUS dp_tx_pdev_detach(struct dp_pdev *pdev); QDF_STATUS dp_tx_pdev_attach(struct dp_pdev *pdev); -qdf_nbuf_t dp_tx_send(void *data_vdev, qdf_nbuf_t nbuf); -qdf_nbuf_t dp_tx_send_exception(void *data_vdev, qdf_nbuf_t nbuf, +qdf_nbuf_t dp_tx_send(struct cdp_soc_t *soc, uint8_t vdev_id, qdf_nbuf_t nbuf); + +qdf_nbuf_t dp_tx_send_exception(struct cdp_soc_t *soc, uint8_t vdev_id, + qdf_nbuf_t nbuf, struct cdp_tx_exception_metadata *tx_exc); -qdf_nbuf_t dp_tx_send_mesh(void *data_vdev, qdf_nbuf_t nbuf); +qdf_nbuf_t dp_tx_send_mesh(struct cdp_soc_t *soc, uint8_t vdev_id, + qdf_nbuf_t nbuf); +qdf_nbuf_t +dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info, uint16_t peer_id, + struct cdp_tx_exception_metadata *tx_exc_metadata); +#if QDF_LOCK_STATS +noinline qdf_nbuf_t +dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info); +#else +qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info); +#endif #ifdef FEATURE_WLAN_TDLS -qdf_nbuf_t dp_tx_non_std(struct cdp_vdev *vdev_handle, - enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list); +/** + * dp_tx_non_std() - Allow the control-path SW to send data frames + * @soc_hdl: Datapath soc handle + * @vdev_id: id of vdev + * @tx_spec: what non-standard handling to apply to the tx data frames + * @msdu_list: NULL-terminated list of tx MSDUs + * + * Return: NULL on success, + * nbuf when it fails to send + */ +qdf_nbuf_t dp_tx_non_std(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list); #endif +int dp_tx_frame_is_drop(struct dp_vdev *vdev, uint8_t *srcmac, uint8_t *dstmac); /** * dp_tx_comp_handler() - Tx completion handler @@ -196,7 +241,8 @@ qdf_nbuf_t dp_tx_non_std(struct cdp_vdev *vdev_handle, * Return: Number of TX completions processed */ uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc, - void *hal_srng, uint8_t ring_id, uint32_t quota); + hal_ring_handle_t hal_srng, uint8_t ring_id, + uint32_t quota); QDF_STATUS dp_tx_prepare_send_me(struct dp_vdev *vdev, qdf_nbuf_t nbuf); @@ -208,15 +254,78 @@ static inline void dp_tx_mec_handler(struct dp_vdev *vdev, uint8_t *status) } #endif -#ifdef ATH_SUPPORT_IQUE -void dp_tx_me_exit(struct dp_pdev *pdev); -#else +#ifndef ATH_SUPPORT_IQUE static inline void dp_tx_me_exit(struct dp_pdev *pdev) { return; } #endif +#ifndef QCA_MULTIPASS_SUPPORT +static inline +bool dp_tx_multipass_process(struct dp_soc *soc, struct dp_vdev *vdev, + qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info) +{ + return true; +} + +static inline +void dp_tx_vdev_multipass_deinit(struct dp_vdev *vdev) +{ +} + +#else +bool dp_tx_multipass_process(struct dp_soc *soc, struct dp_vdev *vdev, + qdf_nbuf_t nbuf, + struct dp_tx_msdu_info_s *msdu_info); + +void dp_tx_vdev_multipass_deinit(struct dp_vdev *vdev); +#endif + +/** + * dp_tx_get_queue() - Returns Tx queue IDs to be used for this Tx frame + * @vdev: DP Virtual device handle + * @nbuf: Buffer pointer + * @queue: queue ids container for nbuf + * + * TX packet queue has 2 instances, software descriptors id and dma ring id + * Based on tx feature and hardware configuration queue id combination could be + * different. + * For example - + * With XPS enabled,all TX descriptor pools and dma ring are assigned per cpu id + * With no XPS,lock based resource protection, Descriptor pool ids are different + * for each vdev, dma ring id will be same as single pdev id + * + * Return: None + */ +#ifdef QCA_OL_TX_MULTIQ_SUPPORT +static inline void dp_tx_get_queue(struct dp_vdev *vdev, + qdf_nbuf_t nbuf, struct dp_tx_queue *queue) +{ + uint16_t queue_offset = qdf_nbuf_get_queue_mapping(nbuf) & + DP_TX_QUEUE_MASK; + + queue->desc_pool_id = queue_offset; + queue->ring_id = vdev->pdev->soc->tx_ring_map[queue_offset]; + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s, pool_id:%d ring_id: %d", + __func__, queue->desc_pool_id, queue->ring_id); +} +#else /* QCA_OL_TX_MULTIQ_SUPPORT */ +static inline void dp_tx_get_queue(struct dp_vdev *vdev, + qdf_nbuf_t nbuf, struct dp_tx_queue *queue) +{ + /* get flow id */ + queue->desc_pool_id = DP_TX_GET_DESC_POOL_ID(vdev); + queue->ring_id = DP_TX_GET_RING_ID(vdev); + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "%s, pool_id:%d ring_id: %d", + __func__, queue->desc_pool_id, queue->ring_id); +} +#endif #ifdef FEATURE_PERPKT_INFO QDF_STATUS dp_get_completion_indication_for_stack(struct dp_soc *soc, @@ -231,7 +340,7 @@ void dp_send_completion_to_stack(struct dp_soc *soc, struct dp_pdev *pdev, qdf_nbuf_t netbuf); #endif -void dp_iterate_update_peer_list(void *pdev_hdl); +void dp_iterate_update_peer_list(struct cdp_pdev *pdev_hdl); #ifdef ATH_TX_PRI_OVERRIDE #define DP_TX_TID_OVERRIDE(_msdu_info, _nbuf) \ @@ -240,6 +349,10 @@ void dp_iterate_update_peer_list(void *pdev_hdl); #define DP_TX_TID_OVERRIDE(_msdu_info, _nbuf) #endif +void +dp_handle_wbm_internal_error(struct dp_soc *soc, void *hal_desc, + uint32_t buf_type); + /* TODO TX_FEATURE_NOT_YET */ static inline void dp_tx_comp_process_exception(struct dp_tx_desc_s *tx_desc) { @@ -247,6 +360,12 @@ static inline void dp_tx_comp_process_exception(struct dp_tx_desc_s *tx_desc) } /* TODO TX_FEATURE_NOT_YET */ +#ifndef WLAN_TX_PKT_CAPTURE_ENH +static inline +void dp_peer_set_tx_capture_enabled(struct dp_peer *peer_handle, bool value) +{ +} +#endif void dp_tx_desc_flush(struct dp_pdev *pdev, struct dp_vdev *vdev, bool force_free); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_desc.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_desc.c index dc3e34eb60a627441b288794cf024a4cdd8bdb0f..0e0fdb6e04cd89c01234cc9ad2b6d547e72bed87 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_desc.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_desc.c @@ -102,16 +102,15 @@ QDF_STATUS dp_tx_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, desc_size = DP_TX_DESC_SIZE(sizeof(*tx_desc_elem)); tx_desc_pool->elem_size = desc_size; if (!dp_is_soc_reinit(soc)) - qdf_mem_multi_pages_alloc(soc->osdev, - &tx_desc_pool->desc_pages, - desc_size, num_elem, - 0, true); + dp_desc_multi_pages_mem_alloc(soc, DP_TX_DESC_TYPE, + &tx_desc_pool->desc_pages, + desc_size, num_elem, + 0, true); if (!tx_desc_pool->desc_pages.num_pages) { dp_err("Multi page alloc fail, tx desc"); goto fail_exit; } - num_desc_per_page = tx_desc_pool->desc_pages.num_element_per_page; tx_desc_pool->freelist = (struct dp_tx_desc_s *) @@ -144,8 +143,8 @@ QDF_STATUS dp_tx_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, return QDF_STATUS_SUCCESS; free_tx_desc: - qdf_mem_multi_pages_free(soc->osdev, - &tx_desc_pool->desc_pages, 0, true); + dp_desc_multi_pages_mem_free(soc, DP_TX_DESC_TYPE, + &tx_desc_pool->desc_pages, 0, true); fail_exit: return QDF_STATUS_E_FAULT; @@ -164,8 +163,9 @@ QDF_STATUS dp_tx_desc_pool_free(struct dp_soc *soc, uint8_t pool_id) struct dp_tx_desc_pool_s *tx_desc_pool = &((soc)->tx_desc[(pool_id)]); - qdf_mem_multi_pages_free(soc->osdev, - &tx_desc_pool->desc_pages, 0, true); + dp_desc_multi_pages_mem_free(soc, DP_TX_DESC_TYPE, + &tx_desc_pool->desc_pages, + 0, true); TX_DESC_LOCK_DESTROY(&tx_desc_pool->lock); TX_DESC_POOL_MEMBER_CLEAN(tx_desc_pool); return QDF_STATUS_SUCCESS; @@ -194,12 +194,13 @@ QDF_STATUS dp_tx_ext_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, soc->tx_ext_desc[pool_id].elem_count = num_elem; memctx = qdf_get_dma_mem_context((&soc->tx_ext_desc[pool_id]), memctx); if (!dp_is_soc_reinit(soc)) { - qdf_mem_multi_pages_alloc(soc->osdev, - &soc->tx_ext_desc[pool_id]. - desc_pages, - soc->tx_ext_desc[pool_id].elem_size, - soc->tx_ext_desc[pool_id].elem_count, - memctx, false); + dp_desc_multi_pages_mem_alloc(soc, + DP_TX_EXT_DESC_TYPE, + &soc->tx_ext_desc[pool_id]. + desc_pages, + soc->tx_ext_desc[pool_id].elem_size, + soc->tx_ext_desc[pool_id].elem_count, + memctx, false); } if (!soc->tx_ext_desc[pool_id].desc_pages.num_pages) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -218,14 +219,12 @@ QDF_STATUS dp_tx_ext_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, soc->tx_ext_desc[pool_id].link_elem_size = sizeof(struct dp_tx_ext_desc_elem_s); if (!dp_is_soc_reinit(soc)) { - qdf_mem_multi_pages_alloc(soc->osdev, - &soc->tx_ext_desc[pool_id]. - desc_link_pages, - soc->tx_ext_desc[pool_id]. - link_elem_size, - soc->tx_ext_desc[pool_id]. - elem_count, - 0, true); + dp_desc_multi_pages_mem_alloc(soc, + DP_TX_EXT_DESC_LINK_TYPE, + &soc->tx_ext_desc[pool_id].desc_link_pages, + soc->tx_ext_desc[pool_id].link_elem_size, + soc->tx_ext_desc[pool_id].elem_count, + 0, true); } if (!soc->tx_ext_desc[pool_id].desc_link_pages.num_pages) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -285,11 +284,11 @@ QDF_STATUS dp_tx_ext_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, return QDF_STATUS_SUCCESS; free_ext_link_desc_page: - qdf_mem_multi_pages_free(soc->osdev, + dp_desc_multi_pages_mem_free(soc, DP_TX_EXT_DESC_LINK_TYPE, &soc->tx_ext_desc[pool_id].desc_link_pages, 0, true); free_ext_desc_page: - qdf_mem_multi_pages_free(soc->osdev, + dp_desc_multi_pages_mem_free(soc, DP_TX_EXT_DESC_TYPE, &soc->tx_ext_desc[pool_id].desc_pages, qdf_get_dma_mem_context((&soc->tx_ext_desc[pool_id]), memctx), false); @@ -308,10 +307,10 @@ QDF_STATUS dp_tx_ext_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, */ QDF_STATUS dp_tx_ext_desc_pool_free(struct dp_soc *soc, uint8_t pool_id) { - qdf_mem_multi_pages_free(soc->osdev, + dp_desc_multi_pages_mem_free(soc, DP_TX_EXT_DESC_LINK_TYPE, &soc->tx_ext_desc[pool_id].desc_link_pages, 0, true); - qdf_mem_multi_pages_free(soc->osdev, + dp_desc_multi_pages_mem_free(soc, DP_TX_EXT_DESC_TYPE, &soc->tx_ext_desc[pool_id].desc_pages, qdf_get_dma_mem_context((&soc->tx_ext_desc[pool_id]), memctx), false); @@ -339,10 +338,11 @@ QDF_STATUS dp_tx_tso_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, tso_desc_pool->num_free = 0; desc_size = DP_TX_DESC_SIZE(sizeof(struct qdf_tso_seg_elem_t)); if (!dp_is_soc_reinit(soc)) - qdf_mem_multi_pages_alloc(soc->osdev, - &tso_desc_pool->desc_pages, - desc_size, - num_elem, 0, true); + dp_desc_multi_pages_mem_alloc(soc, + DP_TX_TSO_DESC_TYPE, + &tso_desc_pool->desc_pages, + desc_size, + num_elem, 0, true); if (!tso_desc_pool->desc_pages.num_pages) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, @@ -369,8 +369,8 @@ QDF_STATUS dp_tx_tso_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id, return QDF_STATUS_SUCCESS; free_tso_desc: - qdf_mem_multi_pages_free(soc->osdev, - &tso_desc_pool->desc_pages, 0, true); + dp_desc_multi_pages_mem_free(soc, DP_TX_TSO_DESC_TYPE, + &tso_desc_pool->desc_pages, 0, true); return QDF_STATUS_E_FAULT; } @@ -390,8 +390,8 @@ void dp_tx_tso_desc_pool_free(struct dp_soc *soc, uint8_t pool_id) qdf_spin_lock_bh(&tso_desc_pool->lock); - qdf_mem_multi_pages_free(soc->osdev, - &tso_desc_pool->desc_pages, 0, true); + dp_desc_multi_pages_mem_free(soc, DP_TX_TSO_DESC_TYPE, + &tso_desc_pool->desc_pages, 0, true); tso_desc_pool->freelist = NULL; tso_desc_pool->num_free = 0; tso_desc_pool->pool_size = 0; @@ -417,10 +417,11 @@ QDF_STATUS dp_tx_tso_num_seg_pool_alloc(struct dp_soc *soc, uint8_t pool_id, tso_num_seg_pool->num_free = 0; desc_size = DP_TX_DESC_SIZE(sizeof(struct qdf_tso_num_seg_elem_t)); if (!dp_is_soc_reinit(soc)) - qdf_mem_multi_pages_alloc(soc->osdev, - &tso_num_seg_pool->desc_pages, - desc_size, - num_elem, 0, true); + dp_desc_multi_pages_mem_alloc(soc, + DP_TX_TSO_NUM_SEG_TYPE, + &tso_num_seg_pool->desc_pages, + desc_size, + num_elem, 0, true); if (!tso_num_seg_pool->desc_pages.num_pages) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, FL("Alloc Failed %pK pool_id %d"), @@ -447,8 +448,8 @@ QDF_STATUS dp_tx_tso_num_seg_pool_alloc(struct dp_soc *soc, uint8_t pool_id, return QDF_STATUS_SUCCESS; fail: - qdf_mem_multi_pages_free(soc->osdev, - &tso_num_seg_pool->desc_pages, 0, true); + dp_desc_multi_pages_mem_free(soc, DP_TX_TSO_NUM_SEG_TYPE, + &tso_num_seg_pool->desc_pages, 0, true); return QDF_STATUS_E_NOMEM; } @@ -468,8 +469,8 @@ void dp_tx_tso_num_seg_pool_free(struct dp_soc *soc, uint8_t pool_id) tso_num_seg_pool = &soc->tx_tso_num_seg[pool_id]; qdf_spin_lock_bh(&tso_num_seg_pool->lock); - qdf_mem_multi_pages_free(soc->osdev, - &tso_num_seg_pool->desc_pages, 0, true); + dp_desc_multi_pages_mem_free(soc, DP_TX_TSO_NUM_SEG_TYPE, + &tso_num_seg_pool->desc_pages, 0, true); tso_num_seg_pool->freelist = NULL; tso_num_seg_pool->num_free = 0; tso_num_seg_pool->num_seg_pool_size = 0; diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_desc.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_desc.h index c73b828c67abfaac6dc34b7e7e1cf2802514c180..07ed3741f60ff9956b311559fb56711875385381 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_desc.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_desc.h @@ -23,20 +23,6 @@ #include "dp_tx.h" #include "dp_internal.h" -#ifdef TX_PER_PDEV_DESC_POOL -#ifdef QCA_LL_TX_FLOW_CONTROL_V2 -#define DP_TX_GET_DESC_POOL_ID(vdev) (vdev->vdev_id) -#else /* QCA_LL_TX_FLOW_CONTROL_V2 */ -#define DP_TX_GET_DESC_POOL_ID(vdev) (vdev->pdev->pdev_id) -#endif /* QCA_LL_TX_FLOW_CONTROL_V2 */ - #define DP_TX_GET_RING_ID(vdev) (vdev->pdev->pdev_id) -#else - #ifdef TX_PER_VDEV_DESC_POOL - #define DP_TX_GET_DESC_POOL_ID(vdev) (vdev->vdev_id) - #define DP_TX_GET_RING_ID(vdev) (vdev->pdev->pdev_id) - #endif /* TX_PER_VDEV_DESC_POOL */ -#endif /* TX_PER_PDEV_DESC_POOL */ - /** * 21 bits cookie * 2 bits pool id 0 ~ 3, @@ -110,9 +96,9 @@ void dp_tx_flow_control_deinit(struct dp_soc *); QDF_STATUS dp_txrx_register_pause_cb(struct cdp_soc_t *soc, tx_pause_callback pause_cb); -QDF_STATUS dp_tx_flow_pool_map(struct cdp_soc_t *soc, struct cdp_pdev *pdev, - uint8_t vdev_id); -void dp_tx_flow_pool_unmap(struct cdp_soc_t *soc, struct cdp_pdev *pdev, +QDF_STATUS dp_tx_flow_pool_map(struct cdp_soc_t *soc, uint8_t pdev_id, + uint8_t vdev_id); +void dp_tx_flow_pool_unmap(struct cdp_soc_t *handle, uint8_t pdev_id, uint8_t vdev_id); void dp_tx_clear_flow_pool_stats(struct dp_soc *soc); struct dp_tx_desc_pool_s *dp_tx_create_flow_pool(struct dp_soc *soc, @@ -505,15 +491,17 @@ dp_tx_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc, #endif /* QCA_AC_BASED_FLOW_CONTROL */ static inline bool -dp_tx_desc_thresh_reached(struct cdp_vdev *vdev) +dp_tx_desc_thresh_reached(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) { - struct dp_vdev *dp_vdev = (struct dp_vdev *)vdev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, + vdev_id); struct dp_tx_desc_pool_s *pool; if (!vdev) return false; - pool = dp_vdev->pool; + pool = vdev->pool; return dp_tx_is_threshold_reached(pool, pool->avail_desc); } @@ -817,7 +805,7 @@ static inline void dp_tx_ext_desc_free_multiple(struct dp_soc *soc, uint8_t freed = num_free; /* caller should always guarantee atleast list of num_free nodes */ - qdf_assert_always(head); + qdf_assert_always(elem); head = elem; c_elem = head; diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_flow_control.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_flow_control.c index 7e674a0c2f24b4b92de59b7b291fb013b2cde141..4e5a5a620dc4090e90aa528232156826b72fc2d9 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_flow_control.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_flow_control.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 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 @@ -90,8 +90,8 @@ dp_tx_flow_pool_reattach(struct dp_tx_desc_pool_s *pool) if (pool->avail_desc > pool->start_th[DP_TH_BE_BK]) pool->status = FLOW_POOL_ACTIVE_UNPAUSED; - if (pool->avail_desc <= pool->start_th[DP_TH_BE_BK] && - pool->avail_desc > pool->start_th[DP_TH_VI]) + else if (pool->avail_desc <= pool->start_th[DP_TH_BE_BK] && + pool->avail_desc > pool->start_th[DP_TH_VI]) pool->status = FLOW_POOL_BE_BK_PAUSED; else if (pool->avail_desc <= pool->start_th[DP_TH_VI] && pool->avail_desc > pool->start_th[DP_TH_VO]) @@ -173,9 +173,9 @@ dp_tx_flow_pool_dump_threshold(struct dp_tx_desc_pool_s *pool) * * Return: none */ -void dp_tx_dump_flow_pool_info(void *ctx) +void dp_tx_dump_flow_pool_info(struct cdp_soc_t *soc_hdl) { - struct dp_soc *soc = ctx; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct dp_txrx_pool_stats *pool_stats = &soc->pool_stats; struct dp_tx_desc_pool_s *pool = NULL; struct dp_tx_desc_pool_s tmp_pool; @@ -364,8 +364,7 @@ static void dp_tx_flow_pool_vdev_map(struct dp_pdev *pdev, struct dp_vdev *vdev; struct dp_soc *soc = pdev->soc; - vdev = (struct dp_vdev *)cdp_get_vdev_from_vdev_id((void *)soc, - (struct cdp_pdev *)pdev, vdev_id); + vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); if (!vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "%s: invalid vdev_id %d", @@ -394,8 +393,7 @@ static void dp_tx_flow_pool_vdev_unmap(struct dp_pdev *pdev, struct dp_vdev *vdev; struct dp_soc *soc = pdev->soc; - vdev = (struct dp_vdev *)cdp_get_vdev_from_vdev_id((void *)soc, - (struct cdp_pdev *)pdev, vdev_id); + vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); if (!vdev) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "%s: invalid vdev_id %d", @@ -523,12 +521,12 @@ void dp_tx_flow_control_init(struct dp_soc *soc) } /** - * dp_tx_flow_control_deinit() - Deregister fw based tx flow control + * dp_tx_desc_pool_dealloc() - De-allocate tx desc pool * @tx_desc_pool: Handle to flow_pool * * Return: none */ -void dp_tx_flow_control_deinit(struct dp_soc *soc) +static inline void dp_tx_desc_pool_dealloc(struct dp_soc *soc) { struct dp_tx_desc_pool_s *tx_desc_pool; int i; @@ -538,11 +536,20 @@ void dp_tx_flow_control_deinit(struct dp_soc *soc) if (!tx_desc_pool->desc_pages.num_pages) continue; - if (dp_tx_desc_pool_free(soc, i)) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "%s Tx Desc Pool Free failed", __func__); - } + if (dp_tx_desc_pool_free(soc, i) != QDF_STATUS_SUCCESS) + dp_err("Tx Desc Pool:%d Free failed", i); } +} + +/** + * dp_tx_flow_control_deinit() - Deregister fw based tx flow control + * @tx_desc_pool: Handle to flow_pool + * + * Return: none + */ +void dp_tx_flow_control_deinit(struct dp_soc *soc) +{ + dp_tx_desc_pool_dealloc(soc); qdf_spinlock_destroy(&soc->flow_pool_array_lock); } @@ -569,19 +576,35 @@ QDF_STATUS dp_txrx_register_pause_cb(struct cdp_soc_t *handle, return QDF_STATUS_SUCCESS; } -QDF_STATUS dp_tx_flow_pool_map(struct cdp_soc_t *handle, struct cdp_pdev *pdev, - uint8_t vdev_id) +QDF_STATUS dp_tx_flow_pool_map(struct cdp_soc_t *handle, uint8_t pdev_id, + uint8_t vdev_id) { - struct dp_soc *soc = (struct dp_soc *)handle; - int tx_ring_size = wlan_cfg_tx_ring_size(soc->wlan_cfg_ctx); + struct dp_soc *soc = cdp_soc_t_to_dp_soc(handle); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + int tx_ring_size = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx); + + if (!pdev) { + dp_err("pdev is NULL"); + return QDF_STATUS_E_INVAL; + } - return (dp_tx_flow_pool_map_handler((struct dp_pdev *)pdev, vdev_id, - FLOW_TYPE_VDEV, vdev_id, tx_ring_size)); + return dp_tx_flow_pool_map_handler(pdev, vdev_id, FLOW_TYPE_VDEV, + vdev_id, tx_ring_size); } -void dp_tx_flow_pool_unmap(struct cdp_soc_t *soc, struct cdp_pdev *pdev, +void dp_tx_flow_pool_unmap(struct cdp_soc_t *handle, uint8_t pdev_id, uint8_t vdev_id) { - return(dp_tx_flow_pool_unmap_handler((struct dp_pdev *)pdev, vdev_id, - FLOW_TYPE_VDEV, vdev_id)); + struct dp_soc *soc = cdp_soc_t_to_dp_soc(handle); + struct dp_pdev *pdev = + dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (!pdev) { + dp_err("pdev is NULL"); + return; + } + + return dp_tx_flow_pool_unmap_handler(pdev, vdev_id, + FLOW_TYPE_VDEV, vdev_id); } diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_me.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_me.c deleted file mode 100644 index 8637ece92d91306e7b3983eec8ce33e8ed89c62d..0000000000000000000000000000000000000000 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_tx_me.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2017-2019 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 - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include "hal_hw_headers.h" -#include "dp_types.h" -#include "qdf_nbuf.h" -#include "qdf_atomic.h" -#include "qdf_types.h" -#include "dp_tx.h" -#include "dp_tx_desc.h" -#include "dp_internal.h" - -#ifdef ATH_SUPPORT_IQUE -#define MAX_ME_BUF_CHUNK 1424 -#define ME_US_TO_SEC(_x) ((_x)/(1000 * 1000)) -#define ME_CLEAN_WAIT_TIMEOUT (200000) /*200ms*/ -#define ME_CLEAN_WAIT_COUNT 400 - -/** - * dp_tx_me_init():Initialize ME buffer ppol - * @pdev: DP PDEV handle - * - * Return:0 on Succes 1 on failure - */ -static inline uint16_t -dp_tx_me_init(struct dp_pdev *pdev) -{ - - uint16_t i, mc_uc_buf_len, num_pool_elems; - uint32_t pool_size; - - struct dp_tx_me_buf_t *p; - - mc_uc_buf_len = sizeof(struct dp_tx_me_buf_t); - - num_pool_elems = MAX_ME_BUF_CHUNK; - /* Add flow control buffer count */ - pool_size = (mc_uc_buf_len) * num_pool_elems; - pdev->me_buf.size = mc_uc_buf_len; - if (!pdev->me_buf.vaddr) { - qdf_spin_lock_bh(&pdev->tx_mutex); - pdev->me_buf.vaddr = qdf_mem_malloc(pool_size); - if (!pdev->me_buf.vaddr) { - qdf_spin_unlock_bh(&pdev->tx_mutex); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "Error allocating memory pool"); - return 1; - } - pdev->me_buf.buf_in_use = 0; - pdev->me_buf.freelist = - (struct dp_tx_me_buf_t *) pdev->me_buf.vaddr; - /* - * me_buf looks like this - * |=======+==========================| - * | ptr | Dst MAC | - * |=======+==========================| - */ - p = pdev->me_buf.freelist; - for (i = 0; i < num_pool_elems-1; i++) { - p->next = (struct dp_tx_me_buf_t *) - ((char *)p + pdev->me_buf.size); - p = p->next; - } - p->next = NULL; - qdf_spin_unlock_bh(&pdev->tx_mutex); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "ME Pool successfully initialized vaddr - %x \ - paddr - %x\n num_elems = %d buf_size - %d" - "pool_size = %d", - pdev->me_buf.vaddr, - (unsigned int)pdev->me_buf.paddr, - (unsigned int)num_pool_elems, - (unsigned int)pdev->me_buf.size, - (unsigned int)pool_size); - } else { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "ME Already Enabled!!"); - } - return 0; -} - -/** - * dp_tx_me_alloc_descriptor():Allocate ME descriptor - * @pdev_handle: DP PDEV handle - * - * Return:void - */ -void -dp_tx_me_alloc_descriptor(struct cdp_pdev *pdev_handle) -{ - struct dp_pdev *pdev = (struct dp_pdev *) pdev_handle; - if (qdf_atomic_read(&pdev->mc_num_vap_attached) == 0) { - dp_tx_me_init(pdev); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - FL("Enable MCAST_TO_UCAST ")); - } - qdf_atomic_inc(&pdev->mc_num_vap_attached); -} - -/** - * dp_tx_me_exit():Free memory and other cleanup required for - * multicast unicast conversion - * @pdev - DP_PDEV handle - * - * Return:void - */ -void -dp_tx_me_exit(struct dp_pdev *pdev) -{ - /* Add flow control buffer count */ - uint32_t wait_time = ME_US_TO_SEC(ME_CLEAN_WAIT_TIMEOUT * - ME_CLEAN_WAIT_COUNT); - - if (pdev->me_buf.vaddr) { - uint16_t wait_cnt = 0; - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "Disabling Mcastenhance" - "This may take some time"); - qdf_spin_lock_bh(&pdev->tx_mutex); - while ((pdev->me_buf.buf_in_use > 0) && - (wait_cnt < ME_CLEAN_WAIT_COUNT)) { - qdf_spin_unlock_bh(&pdev->tx_mutex); - OS_SLEEP(ME_CLEAN_WAIT_TIMEOUT); - wait_cnt++; - qdf_spin_lock_bh(&pdev->tx_mutex); - } - if (pdev->me_buf.buf_in_use > 0) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, - "Tx-comp pending for %d " - "ME frames after waiting %ds!!", - pdev->me_buf.buf_in_use, wait_time); - qdf_assert_always(0); - } - - qdf_mem_free(pdev->me_buf.vaddr); - pdev->me_buf.vaddr = NULL; - pdev->me_buf.freelist = NULL; - qdf_spin_unlock_bh(&pdev->tx_mutex); - } else { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "ME Already Disabled !!!"); - } -} - -/** - * dp_tx_me_free_descriptor():free ME descriptor - * @pdev_handle:DP_PDEV handle - * - * Return:void - */ -void -dp_tx_me_free_descriptor(struct cdp_pdev *pdev_handle) -{ - struct dp_pdev *pdev = (struct dp_pdev *) pdev_handle; - qdf_atomic_dec(&pdev->mc_num_vap_attached); - if (atomic_read(&pdev->mc_num_vap_attached) == 0) { - dp_tx_me_exit(pdev); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, - "Disable MCAST_TO_UCAST"); - } -} - -/** - * dp_tx_prepare_send_me(): Call to the umac to get the list of clients - * @vdev: DP VDEV handle - * @nbuf: Multicast buffer - * - * Return: no of packets transmitted - */ -QDF_STATUS -dp_tx_prepare_send_me(struct dp_vdev *vdev, qdf_nbuf_t nbuf) -{ - if (vdev->me_convert) { - if (vdev->me_convert(vdev->osif_vdev, nbuf) > 0) - return QDF_STATUS_SUCCESS; - } - - return QDF_STATUS_E_FAILURE; -} - -#endif diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_types.h b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_types.h index 363e98087873f3e590ff03215d4653befc1c9017..cefa475982f5e75fe71b747188df62ac416e14bb 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_types.h +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_types.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -30,10 +31,10 @@ #include #include -#ifdef CONFIG_MCL +#ifdef DP_MOB_DEFS #include -#include /* WDI subscriber event list */ #endif +#include /* WDI subscriber event list */ #include "hal_hw_headers.h" #include @@ -43,6 +44,7 @@ #include #include #include "hal_rx.h" +//#include "hal_rx_flow.h" #define MAX_BW 7 #define MAX_RETRIES 4 @@ -71,13 +73,19 @@ #define MAX_MON_LINK_DESC_BANKS 2 #define DP_VDEV_ALL 0xff -#if defined(CONFIG_MCL) +#if defined(WLAN_MAX_PDEVS) && (WLAN_MAX_PDEVS == 1) #define MAX_PDEV_CNT 1 #else #define MAX_PDEV_CNT 3 #endif -#define MAX_LINK_DESC_BANKS 8 +/* Max no. of VDEV per PSOC */ +#ifdef WLAN_PSOC_MAX_VDEVS +#define MAX_VDEV_CNT WLAN_PSOC_MAX_VDEVS +#else +#define MAX_VDEV_CNT 51 +#endif + #define MAX_TXDESC_POOLS 4 #define MAX_RXDESC_POOLS 4 #define MAX_REO_DEST_RINGS 4 @@ -87,6 +95,13 @@ #define DP_MAX_IRQ_PER_CONTEXT 12 #define DEFAULT_HW_PEER_ID 0xffff +#define WBM_INT_ERROR_ALL 0 +#define WBM_INT_ERROR_REO_NULL_BUFFER 1 +#define WBM_INT_ERROR_REO_NULL_LINK_DESC 2 +#define WBM_INT_ERROR_REO_NULL_MSDU_BUFF 3 +#define WBM_INT_ERROR_REO_BUFF_REAPED 4 +#define MAX_WBM_INT_ERROR_REASONS 5 + #define MAX_TX_HW_QUEUES MAX_TCL_DATA_RINGS /* Maximum retries for Delba per tid per peer */ #define DP_MAX_DELBA_RETRY 3 @@ -96,13 +111,11 @@ #define REO_CMD_EVENT_HIST_MAX 64 -#ifndef REMOVE_PKT_LOG enum rx_pktlog_mode { DP_RX_PKTLOG_DISABLED = 0, DP_RX_PKTLOG_FULL, DP_RX_PKTLOG_LITE, }; -#endif struct msdu_list { qdf_nbuf_t head; @@ -118,6 +131,8 @@ struct dp_soc; union dp_rx_desc_list_elem_t; struct cdp_peer_rate_stats_ctx; struct cdp_soc_rate_stats_ctx; +struct dp_rx_fst; +struct dp_mon_filter; #define DP_PDEV_ITERATE_VDEV_LIST(_pdev, _vdev) \ TAILQ_FOREACH((_vdev), &(_pdev)->vdev_list, vdev_list_elem) @@ -184,12 +199,12 @@ enum dp_fl_ctrl_threshold { /** * enum dp_intr_mode - * @DP_INTR_LEGACY: Legacy/Line interrupts, for WIN - * @DP_INTR_MSI: MSI interrupts, for MCL + * @DP_INTR_INTEGRATED: Line interrupts + * @DP_INTR_MSI: MSI interrupts * @DP_INTR_POLL: Polling */ enum dp_intr_mode { - DP_INTR_LEGACY = 0, + DP_INTR_INTEGRATED = 0, DP_INTR_MSI, DP_INTR_POLL, }; @@ -267,6 +282,42 @@ enum dp_cpu_ring_map_types { DP_NSS_CPU_RING_MAP_MAX }; +/** + * enum dp_ctxt - context type + * @DP_PDEV_TYPE: PDEV context + * @DP_RX_RING_HIST_TYPE: Datapath rx ring history + * @DP_RX_ERR_RING_HIST_TYPE: Datapath rx error ring history + * @DP_RX_REINJECT_RING_HIST_TYPE: Datapath reinject ring history + */ +enum dp_ctxt_type { + DP_PDEV_TYPE, + DP_RX_RING_HIST_TYPE, + DP_RX_ERR_RING_HIST_TYPE, + DP_RX_REINJECT_RING_HIST_TYPE, +}; + +/** + * enum dp_desc_type - source type for multiple pages allocation + * @DP_TX_DESC_TYPE: DP SW TX descriptor + * @DP_TX_EXT_DESC_TYPE: DP TX msdu extension descriptor + * @DP_TX_EXT_DESC_LINK_TYPE: DP link descriptor for msdu ext_desc + * @DP_TX_TSO_DESC_TYPE: DP TX TSO descriptor + * @DP_TX_TSO_NUM_SEG_TYPE: DP TX number of segments + * @DP_RX_DESC_BUF_TYPE: DP RX SW descriptor + * @DP_RX_DESC_STATUS_TYPE: DP RX SW descriptor for monitor status + * @DP_HW_LINK_DESC_TYPE: DP HW link descriptor + */ +enum dp_desc_type { + DP_TX_DESC_TYPE, + DP_TX_EXT_DESC_TYPE, + DP_TX_EXT_DESC_LINK_TYPE, + DP_TX_TSO_DESC_TYPE, + DP_TX_TSO_NUM_SEG_TYPE, + DP_RX_DESC_BUF_TYPE, + DP_RX_DESC_STATUS_TYPE, + DP_HW_LINK_DESC_TYPE, +}; + /** * struct rx_desc_pool * @pool_size: number of RX descriptor in the pool @@ -276,6 +327,9 @@ enum dp_cpu_ring_map_types { * @freelist: pointer to free RX descriptor link list * @lock: Protection for the RX descriptor pool * @owner: owner for nbuf + * @buf_size: Buffer size + * @buf_alignment: Buffer alignment + * @desc_type: type of desc this pool serves */ struct rx_desc_pool { uint32_t pool_size; @@ -288,6 +342,9 @@ struct rx_desc_pool { union dp_rx_desc_list_elem_t *freelist; qdf_spinlock_t lock; uint8_t owner; + uint16_t buf_size; + uint8_t buf_alignment; + enum dp_desc_type desc_type; }; /** @@ -295,11 +352,13 @@ struct rx_desc_pool { * @next: next extension descriptor pointer * @vaddr: hlos virtual address pointer * @paddr: physical address pointer for descriptor + * @flags: mark features for extension descriptor */ struct dp_tx_ext_desc_elem_s { struct dp_tx_ext_desc_elem_s *next; void *vaddr; qdf_dma_addr_t paddr; + uint16_t flags; }; /** @@ -476,13 +535,16 @@ struct dp_txrx_pool_stats { }; struct dp_srng { - void *hal_srng; + hal_ring_handle_t hal_srng; void *base_vaddr_unaligned; qdf_dma_addr_t base_paddr_unaligned; uint32_t alloc_size; uint8_t cached; int irq; uint32_t num_entries; +#ifdef DP_MEM_PRE_ALLOC + uint8_t is_mem_prealloc; +#endif }; struct dp_rx_reorder_array_elem { @@ -525,6 +587,7 @@ struct dp_rx_tid { uint8_t pn_size; /* REO TID queue descriptors */ void *hw_qdesc_vaddr_unaligned; + void *hw_qdesc_vaddr_aligned; qdf_dma_addr_t hw_qdesc_paddr_unaligned; qdf_dma_addr_t hw_qdesc_paddr; uint32_t hw_qdesc_alloc_size; @@ -547,7 +610,7 @@ struct dp_rx_tid { TAILQ_ENTRY(dp_rx_tid) defrag_waitlist_elem; /* Store dst desc for reinjection */ - void *dst_ring_desc; + hal_ring_desc_t dst_ring_desc; struct dp_rx_desc *head_frag_desc; /* rx_tid lock */ @@ -557,6 +620,9 @@ struct dp_rx_tid { uint32_t curr_seq_num; uint32_t curr_frag_num; + /* head PN number */ + uint64_t pn128[2]; + uint32_t defrag_timeout_ms; uint16_t dialogtoken; uint16_t statuscode; @@ -581,7 +647,6 @@ struct dp_rx_tid { /* Coex Override preserved windows size 1 based */ uint16_t rx_ba_win_size_override; - }; /** @@ -642,6 +707,7 @@ struct reo_desc_list_node { unsigned long free_ts; struct dp_rx_tid rx_tid; bool resend_update_reo_cmd; + uint32_t pending_ext_desc_size; }; #ifdef WLAN_FEATURE_DP_EVENT_HISTORY @@ -674,6 +740,7 @@ struct dp_soc_stats { uint32_t added; uint32_t deleted; uint32_t aged_out; + uint32_t map_err; } ast; /* SOC level TX stats */ @@ -689,7 +756,7 @@ struct dp_soc_stats { /* tx completion release_src != TQM or FW */ uint32_t invalid_release_source; /* tx completion wbm_internal_error */ - uint32_t wbm_internal_error; + uint32_t wbm_internal_error[MAX_WBM_INT_ERROR_REASONS]; /* tx completion non_wbm_internal_error */ uint32_t non_wbm_internal_err; /* TX Comp loop packet limit hit */ @@ -709,6 +776,8 @@ struct dp_soc_stats { uint32_t rx_frag_wait; /* Fragments dropped due to errors */ uint32_t rx_frag_err; + /* Fragments received OOR causing sequence num mismatch */ + uint32_t rx_frag_oor; /* Fragments dropped due to len errors in skb */ uint32_t rx_frag_err_len_error; /* Fragments dropped due to no peer found */ @@ -723,6 +792,8 @@ struct dp_soc_stats { uint32_t near_full; /* Break ring reaping as not all scattered msdu received */ uint32_t msdu_scatter_wait_break; + /* Number of bar frames received */ + uint32_t bar_frame; struct { /* Invalid RBM error count */ @@ -770,6 +841,10 @@ struct dp_soc_stats { uint32_t reo_cmd_send_drain; /* RX msdu drop count due to scatter */ uint32_t scatter_msdu; + /* RX msdu drop count due to invalid cookie */ + uint32_t invalid_cookie; + /* Count of stale cookie read in RX path */ + uint32_t stale_cookie; /* Delba sent count due to RX 2k jump */ uint32_t rx_2k_jump_delba_sent; /* RX 2k jump msdu indicated to stack count */ @@ -784,6 +859,24 @@ struct dp_soc_stats { uint32_t reo_err_oor_sg_count; /* RX msdu rejected count on delivery to vdev stack_fn*/ uint32_t rejected; + /* Incorrect msdu count in MPDU desc info */ + uint32_t msdu_count_mismatch; + /* RX raw frame dropped count */ + uint32_t raw_frm_drop; + /* Stale link desc cookie count*/ + uint32_t invalid_link_cookie; + /* Nbuf sanity failure */ + uint32_t nbuf_sanity_fail; + /* Duplicate link desc refilled */ + uint32_t dup_refill_link_desc; + /* EAPOL drop count in intrabss scenario */ + uint32_t intrabss_eapol_drop; + /* Non Eapol pkt drop cnt due to peer not authorized */ + uint32_t peer_unauth_rx_pkt_drop; + /* MSDU len err count */ + uint32_t msdu_len_err; + /* Rx invalid tid count */ + uint32_t rx_invalid_tid_err; } err; /* packet count per core - per ring */ @@ -859,10 +952,8 @@ struct dp_ast_entry { struct dp_peer *peer; bool next_hop; bool is_active; - bool is_bss; bool is_mapped; uint8_t pdev_id; - uint8_t vdev_id; uint16_t ast_hash_value; qdf_atomic_t ref_cnt; enum cdp_txrx_ast_entry_type type; @@ -888,6 +979,69 @@ struct htt_t2h_stats { uint32_t num_stats; }; +/* + * The logic for get current index of these history is dependent on this + * value being power of 2. + */ +#define DP_RX_HIST_MAX 2048 +#define DP_RX_ERR_HIST_MAX 4096 +#define DP_RX_REINJECT_HIST_MAX 1024 + +QDF_COMPILE_TIME_ASSERT(rx_history_size, + (DP_RX_HIST_MAX & + (DP_RX_HIST_MAX - 1)) == 0); +QDF_COMPILE_TIME_ASSERT(rx_err_history_size, + (DP_RX_ERR_HIST_MAX & + (DP_RX_ERR_HIST_MAX - 1)) == 0); +QDF_COMPILE_TIME_ASSERT(rx_reinject_history_size, + (DP_RX_REINJECT_HIST_MAX & + (DP_RX_REINJECT_HIST_MAX - 1)) == 0); + +/** + * struct dp_buf_info_record - ring buffer info + * @hbi: HW ring buffer info + * @timestamp: timestamp when this entry was recorded + */ +struct dp_buf_info_record { + struct hal_buf_info hbi; + uint64_t timestamp; +}; + +/* struct dp_rx_history - rx ring hisotry + * @index: Index where the last entry is written + * @entry: history entries + */ +struct dp_rx_history { + qdf_atomic_t index; + struct dp_buf_info_record entry[DP_RX_HIST_MAX]; +}; + +/* struct dp_rx_err_history - rx err ring hisotry + * @index: Index where the last entry is written + * @entry: history entries + */ +struct dp_rx_err_history { + qdf_atomic_t index; + struct dp_buf_info_record entry[DP_RX_ERR_HIST_MAX]; +}; + +/* struct dp_rx_reinject_history - rx reinject ring hisotry + * @index: Index where the last entry is written + * @entry: history entries + */ +struct dp_rx_reinject_history { + qdf_atomic_t index; + struct dp_buf_info_record entry[DP_RX_REINJECT_HIST_MAX]; +}; + +/* structure to record recent operation related variable */ +struct dp_last_op_info { + /* last link desc buf info through WBM release ring */ + struct hal_buf_info wbm_rel_link_desc; + /* last link desc buf info through REO reinject ring */ + struct hal_buf_info reo_reinject_link_desc; +}; + /* SOC level structure for data path */ struct dp_soc { /** @@ -898,7 +1052,7 @@ struct dp_soc { struct cdp_soc_t cdp_soc; /* SoC Obj */ - void *ctrl_psoc; + struct cdp_ctrl_objmgr_psoc *ctrl_psoc; /* OS device abstraction */ qdf_device_t osdev; @@ -907,7 +1061,7 @@ struct dp_soc { struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx; /* HTT handle for host-fw interaction */ - void *htt_handle; + struct htt_soc *htt_handle; /* Commint init done */ qdf_atomic_t cmn_init_done; @@ -918,6 +1072,32 @@ struct dp_soc { /* PDEVs on this SOC */ struct dp_pdev *pdev_list[MAX_PDEV_CNT]; + /* Ring used to replenish rx buffers (maybe to the firmware of MAC) */ + struct dp_srng rx_refill_buf_ring[MAX_PDEV_CNT]; + + struct dp_srng rxdma_mon_desc_ring[MAX_NUM_LMAC_HW]; + + /* RXDMA error destination ring */ + struct dp_srng rxdma_err_dst_ring[MAX_NUM_LMAC_HW]; + + /* Link descriptor memory banks */ + struct { + void *base_vaddr_unaligned; + void *base_vaddr; + qdf_dma_addr_t base_paddr_unaligned; + qdf_dma_addr_t base_paddr; + uint32_t size; + } mon_link_desc_banks[MAX_NUM_LMAC_HW][MAX_MON_LINK_DESC_BANKS]; + + /* RXDMA monitor buffer replenish ring */ + struct dp_srng rxdma_mon_buf_ring[MAX_NUM_LMAC_HW]; + + /* RXDMA monitor destination ring */ + struct dp_srng rxdma_mon_dst_ring[MAX_NUM_LMAC_HW]; + + /* RXDMA monitor status ring. TBD: Check format of this ring */ + struct dp_srng rxdma_mon_status_ring[MAX_NUM_LMAC_HW]; + /* Number of PDEVs */ uint8_t pdev_count; @@ -931,19 +1111,13 @@ struct dp_soc { uint8_t num_hw_dscp_tid_map; /* HAL SOC handle */ - void *hal_soc; + hal_soc_handle_t hal_soc; /* Device ID coming from Bus sub-system */ uint32_t device_id; - /* Link descriptor memory banks */ - struct { - void *base_vaddr_unaligned; - void *base_vaddr; - qdf_dma_addr_t base_paddr_unaligned; - qdf_dma_addr_t base_paddr; - uint32_t size; - } link_desc_banks[MAX_LINK_DESC_BANKS]; + /* Link descriptor pages */ + struct qdf_mem_multi_page_t link_desc_pages; /* Link descriptor Idle list for HW internal use (SRNG mode) */ struct dp_srng wbm_idle_link_ring; @@ -1016,6 +1190,10 @@ struct dp_soc { /* Number of REO destination rings */ uint8_t num_reo_dest_rings; + struct dp_rx_history *rx_ring_history[MAX_REO_DEST_RINGS]; + struct dp_rx_err_history *rx_err_ring_history; + struct dp_rx_reinject_history *rx_reinject_ring_history; + #ifdef QCA_LL_TX_FLOW_CONTROL_V2 /* lock to control access to soc TX descriptors */ qdf_spinlock_t flow_pool_array_lock; @@ -1038,6 +1216,9 @@ struct dp_soc { uint32_t wbm_idle_scatter_buf_size; + /* VDEVs on this SOC */ + struct dp_vdev *vdev_id_map[MAX_VDEV_CNT]; + /* Tx H/W queues lock */ qdf_spinlock_t tx_queue_lock[MAX_TX_HW_QUEUES]; @@ -1123,8 +1304,11 @@ struct dp_soc { /*interrupt timer*/ qdf_timer_t mon_reap_timer; uint8_t reap_timer_init; + qdf_timer_t lmac_reap_timer; + uint8_t lmac_timer_init; qdf_timer_t int_timer; uint8_t intr_mode; + uint8_t lmac_polled_mode; qdf_list_t reo_desc_freelist; qdf_spinlock_t reo_desc_freelist_lock; @@ -1147,6 +1331,8 @@ struct dp_soc { void *ipa_wbm_ring_base_vaddr; uint32_t ipa_wbm_ring_size; qdf_dma_addr_t ipa_wbm_tp_paddr; + /* WBM2SW HP shadow paddr */ + qdf_dma_addr_t ipa_wbm_hp_shadow_paddr; /* TX buffers populated into the WBM ring */ void **tx_buf_pool_vaddr_unaligned; @@ -1203,6 +1389,41 @@ struct dp_soc { uint8_t tidmap_prty; /* Pointer to global per ring type specific configuration table */ struct wlan_srng_cfg *wlan_srng_cfg; + /* Num Tx outstanding on device */ + qdf_atomic_t num_tx_outstanding; + /* Num Tx allowed */ + uint32_t num_tx_allowed; + + /** + * Flag to indicate whether WAR to address single cache entry + * invalidation bug is enabled or not + */ + bool is_rx_fse_full_cache_invalidate_war_enabled; +#if defined(WLAN_SUPPORT_RX_FLOW_TAG) || defined(WLAN_SUPPORT_RX_FISA) + /** + * Pointer to DP RX Flow FST at SOC level if + * is_rx_flow_search_table_per_pdev is false + * TBD: rx_fst[num_macs] if we decide to have per mac FST + */ + struct dp_rx_fst *rx_fst; +#ifdef WLAN_SUPPORT_RX_FISA + uint8_t fisa_enable; + + /** + * Params used for controlling the fisa aggregation dynamically + */ + struct { + qdf_atomic_t skip_fisa; + uint8_t fisa_force_flush[MAX_REO_DEST_RINGS]; + } skip_fisa_param; +#endif +#endif /* WLAN_SUPPORT_RX_FLOW_TAG || WLAN_SUPPORT_RX_FISA */ + /* Save recent operation related variable */ + struct dp_last_op_info last_op_info; +#ifdef FEATURE_RUNTIME_PM + /* Dp runtime refcount */ + qdf_atomic_t dp_runtime_refcount; +#endif }; #ifdef IPA_OFFLOAD @@ -1228,21 +1449,37 @@ struct dp_ipa_resources { /* Same as NAC_MAX_CLENT */ #define DP_NAC_MAX_CLIENT 24 +/* + * 24 bits cookie size + * 10 bits page id 0 ~ 1023 for MCL + * 3 bits page id 0 ~ 7 for WIN + * WBM Idle List Desc size = 128, + * Num descs per page = 4096/128 = 32 for MCL + * Num descs per page = 2MB/128 = 16384 for WIN + */ /* * Macros to setup link descriptor cookies - for link descriptors, we just - * need first 3 bits to store bank ID. The remaining bytes will be used set a - * unique ID, which will be useful in debugging + * need first 3 bits to store bank/page ID for WIN. The + * remaining bytes will be used to set a unique ID, which will + * be useful in debugging */ -#define LINK_DESC_BANK_ID_MASK 0x7 -#define LINK_DESC_ID_SHIFT 3 +#ifdef MAX_ALLOC_PAGE_SIZE +#define LINK_DESC_PAGE_ID_MASK 0x007FE0 +#define LINK_DESC_ID_SHIFT 5 +#define LINK_DESC_COOKIE(_desc_id, _page_id) \ + ((((_page_id) + LINK_DESC_ID_START) << LINK_DESC_ID_SHIFT) | (_desc_id)) +#define LINK_DESC_COOKIE_PAGE_ID(_cookie) \ + (((_cookie) & LINK_DESC_PAGE_ID_MASK) >> LINK_DESC_ID_SHIFT) +#else +#define LINK_DESC_PAGE_ID_MASK 0x7 +#define LINK_DESC_ID_SHIFT 3 +#define LINK_DESC_COOKIE(_desc_id, _page_id) \ + ((((_desc_id) + LINK_DESC_ID_START) << LINK_DESC_ID_SHIFT) | (_page_id)) +#define LINK_DESC_COOKIE_PAGE_ID(_cookie) \ + ((_cookie) & LINK_DESC_PAGE_ID_MASK) +#endif #define LINK_DESC_ID_START 0x8000 -#define LINK_DESC_COOKIE(_desc_id, _bank_id) \ - ((((_desc_id) + LINK_DESC_ID_START) << LINK_DESC_ID_SHIFT) | (_bank_id)) - -#define LINK_DESC_COOKIE_BANK_ID(_cookie) \ - ((_cookie) & LINK_DESC_BANK_ID_MASK) - /* same as ieee80211_nac_param */ enum dp_nac_param_cmd { /* IEEE80211_NAC_PARAM_ADD */ @@ -1286,8 +1523,10 @@ struct dp_neighbour_peer { * @is_ampdu - set if Ampdu aggregate * @nbuf - ppdu descriptor payload * @ppdu_desc - ppdu descriptor - * @ppdu_info_list_elem - linked list of ppdu tlvs + * @ppdu_info_list_elem - linked list of ppdu tlvs * @ppdu_info_queue_elem - Singly linked list (queue) of ppdu tlvs + * @mpdu_compltn_common_tlv - Successful MPDU counter from COMPLTN COMMON tlv + * @mpdu_ack_ba_tlv - Successful MPDU from ACK BA tlv */ struct ppdu_info { uint32_t ppdu_id; @@ -1309,6 +1548,8 @@ struct ppdu_info { #else TAILQ_ENTRY(ppdu_info) ppdu_info_list_elem; #endif + uint16_t mpdu_compltn_common_tlv; + uint16_t mpdu_ack_ba_tlv; }; /** @@ -1320,6 +1561,7 @@ struct ppdu_info { * @last_msdu - last msdu indication * @msdu_part_of_amsdu - msdu part of amsdu * @transmit_cnt - retried count + * @status - transmit status * @tsf - timestamp which it transmitted */ struct msdu_completion_info { @@ -1330,6 +1572,7 @@ struct msdu_completion_info { last_msdu:1, msdu_part_of_amsdu:1; uint8_t transmit_cnt; + uint8_t status; uint32_t tsf; }; @@ -1363,13 +1606,13 @@ struct dp_peer_tx_capture { * at end of each MSDU in monitor-lite mode * @reserved1: reserved for future use * @reserved2: reserved for future use - * @reserved3: reserved for future use + * @flow_tag: flow tag value read from skb->cb * @protocol_tag: protocol tag value read from skb->cb */ struct dp_rx_mon_enh_trailer_data { uint16_t reserved1; uint16_t reserved2; - uint16_t reserved3; + uint16_t flow_tag; uint16_t protocol_tag; }; #endif /* WLAN_RX_PKT_CAPTURE_ENH */ @@ -1379,8 +1622,6 @@ struct dp_pdev { /** * Re-use Memory Section Starts */ - /* PDEV handle from OSIF layer TBD: see if we really need osif_pdev */ - struct cdp_ctrl_objmgr_pdev *ctrl_pdev; /* PDEV Id */ int pdev_id; @@ -1391,32 +1632,6 @@ struct dp_pdev { /* TXRX SOC handle */ struct dp_soc *soc; - /* Ring used to replenish rx buffers (maybe to the firmware of MAC) */ - struct dp_srng rx_refill_buf_ring; - - /* RXDMA error destination ring */ - struct dp_srng rxdma_err_dst_ring[NUM_RXDMA_RINGS_PER_PDEV]; - - /* Link descriptor memory banks */ - struct { - void *base_vaddr_unaligned; - void *base_vaddr; - qdf_dma_addr_t base_paddr_unaligned; - qdf_dma_addr_t base_paddr; - uint32_t size; - } link_desc_banks[NUM_RXDMA_RINGS_PER_PDEV][MAX_MON_LINK_DESC_BANKS]; - - /* RXDMA monitor buffer replenish ring */ - struct dp_srng rxdma_mon_buf_ring[NUM_RXDMA_RINGS_PER_PDEV]; - - /* RXDMA monitor destination ring */ - struct dp_srng rxdma_mon_dst_ring[NUM_RXDMA_RINGS_PER_PDEV]; - - /* RXDMA monitor status ring. TBD: Check format of this ring */ - struct dp_srng rxdma_mon_status_ring[NUM_RXDMA_RINGS_PER_PDEV]; - - struct dp_srng rxdma_mon_desc_ring[NUM_RXDMA_RINGS_PER_PDEV]; - /* Stuck count on monitor destination ring MPDU process */ uint32_t mon_dest_ring_stuck_cnt; @@ -1428,6 +1643,13 @@ struct dp_pdev { */ bool pdev_deinit; + /* pdev status down or up required to handle dynamic hw + * mode switch between DBS and DBS_SBS. + * 1 = down + * 0 = up + */ + bool is_pdev_down; + /* Second ring used to replenish rx buffers */ struct dp_srng rx_refill_buf_ring2; @@ -1471,6 +1693,9 @@ struct dp_pdev { /* Monitor mode operation channel */ int mon_chan_num; + /* Monitor mode operation frequency */ + qdf_freq_t mon_chan_freq; + /* monitor mode lock */ qdf_spinlock_t mon_lock; @@ -1552,11 +1777,14 @@ struct dp_pdev { struct msdu_list msdu_list[MAX_MU_USERS]; /* RX enhanced capture mode */ uint8_t rx_enh_capture_mode; + /* Rx per peer enhanced capture mode */ + bool rx_enh_capture_peer; + struct dp_vdev *rx_enh_monitor_vdev; /* RX enhanced capture trailer enable/disable flag */ bool is_rx_enh_capture_trailer_enabled; #ifdef WLAN_RX_PKT_CAPTURE_ENH /* RX per MPDU/PPDU information */ - struct cdp_rx_indication_mpdu mpdu_ind[MAX_MU_USERS]; + struct cdp_rx_indication_mpdu mpdu_ind; #endif /* pool addr for mcast enhance buff */ struct { @@ -1587,10 +1815,8 @@ struct dp_pdev { /* map this pdev to a particular Reo Destination ring */ enum cdp_host_reo_dest_ring reo_dest; -#ifndef REMOVE_PKT_LOG /* Packet log mode */ uint8_t rx_pktlog_mode; -#endif /* WDI event handlers */ struct wdi_event_subscribe_t **wdi_event_list; @@ -1605,6 +1831,8 @@ struct dp_pdev { bool tx_sniffer_enable; /* mirror copy mode */ bool mcopy_mode; + bool cfr_rcc_mode; + bool enable_reap_timer_non_pkt; bool bpr_enable; /* enable time latency check for tx completion */ @@ -1654,7 +1882,7 @@ struct dp_pdev { */ uint8_t is_primary; /* Context of cal client timer */ - void *cal_client_ctx; + struct cdp_cal_client *cal_client_ctx; struct cdp_tx_sojourn_stats sojourn_stats; qdf_nbuf_t sojourn_buf; @@ -1707,16 +1935,35 @@ struct dp_pdev { #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ /* tx packet capture enhancement */ - bool tx_capture_enabled; + enum cdp_tx_enh_capture_mode tx_capture_enabled; struct dp_pdev_tx_capture tx_capture; /* stats counter for tx ppdu processed */ uint64_t tx_ppdu_proc; uint32_t *ppdu_tlv_buf; /* Buffer to hold HTT ppdu stats TLVs*/ + /* nbuf queue to maintain rx ppdu status buffer + * belonging to one ppdu + */ + qdf_nbuf_queue_t rx_ppdu_buf_q; +#ifdef WLAN_SUPPORT_RX_FLOW_TAG + /** + * Pointer to DP Flow FST at SOC level if + * is_rx_flow_search_table_per_pdev is true + */ + struct dp_rx_fst *rx_fst; +#endif /* WLAN_SUPPORT_RX_FLOW_TAG */ + +#ifdef FEATURE_TSO_STATS + /* TSO Id to index into TSO packet information */ + qdf_atomic_t tso_idx; +#endif /* FEATURE_TSO_STATS */ + #ifdef WLAN_SUPPORT_DATA_STALL data_stall_detect_cb data_stall_detect_callback; #endif /* WLAN_SUPPORT_DATA_STALL */ + + struct dp_mon_filter **filter; /* Monitor Filter pointer */ }; struct dp_peer; @@ -1728,11 +1975,12 @@ struct dp_vdev { /* physical device that is the parent of this virtual device */ struct dp_pdev *pdev; + /* HW TX Checksum Enabled Flag */ + uint8_t csum_enabled; + /* Handle to the OS shim SW's virtual device */ ol_osif_vdev_handle osif_vdev; - /* Handle to the UMAC handle */ - struct cdp_ctrl_objmgr_vdev *ctrl_vdev; /* vdev_id - ID used to specify a particular vdev to the target */ uint8_t vdev_id; @@ -1751,6 +1999,10 @@ struct dp_vdev { ol_txrx_rx_fp osif_rx; /* callback to deliver rx frames to the OS */ ol_txrx_rx_fp osif_rx_stack; + /* Callback to handle rx fisa frames */ + ol_txrx_fisa_rx_fp osif_fisa_rx; + ol_txrx_fisa_flush_fp osif_fisa_flush; + /* call back function to flush out queued rx packets*/ ol_txrx_rx_flush_fp osif_rx_flush; ol_txrx_rsim_rx_decap_fp osif_rsim_rx_decap; @@ -1869,7 +2121,7 @@ struct dp_vdev { struct dp_tx_desc_pool_s *pool; #endif /* AP BRIDGE enabled */ - uint32_t ap_bridge_enabled; + bool ap_bridge_enabled; enum cdp_sec_type sec_type; @@ -1882,6 +2134,9 @@ struct dp_vdev { /* AST hash value for BSS peer in HW valid for STA VAP*/ uint16_t bss_ast_hash; + /* AST hash index for BSS peer in HW valid for STA VAP*/ + uint16_t bss_ast_idx; + /* Capture timestamp of previous tx packet enqueued */ uint64_t prev_tx_enq_tstamp; @@ -1899,8 +2154,42 @@ struct dp_vdev { /* Self Peer in STA mode */ struct dp_peer *vap_self_peer; + bool multipass_en; +#ifdef QCA_MULTIPASS_SUPPORT + uint16_t *iv_vlan_map; + + /* dp_peer special list */ + TAILQ_HEAD(, dp_peer) mpass_peer_list; + DP_MUTEX_TYPE mpass_peer_mutex; +#endif + /* Extended data path handle */ + struct cdp_ext_vdev *vdev_dp_ext_handle; +#ifdef VDEV_PEER_PROTOCOL_COUNT + /* + * Rx-Ingress and Tx-Egress are in the lower level DP layer + * Rx-Egress and Tx-ingress are handled in osif layer for DP + * So + * Rx-Egress and Tx-ingress mask definitions are in OSIF layer + * Rx-Ingress and Tx-Egress definitions are here below + */ +#define VDEV_PEER_PROTOCOL_RX_INGRESS_MASK 1 +#define VDEV_PEER_PROTOCOL_TX_INGRESS_MASK 2 +#define VDEV_PEER_PROTOCOL_RX_EGRESS_MASK 4 +#define VDEV_PEER_PROTOCOL_TX_EGRESS_MASK 8 + bool peer_protocol_count_track; + int peer_protocol_count_dropmask; +#endif + /* vap bss peer mac addr */ uint8_t vap_bss_peer_mac_addr[QDF_MAC_ADDR_SIZE]; + +#ifdef WLAN_SUPPORT_RX_FISA + /** + * Params used for controlling the fisa aggregation dynamically + */ + uint8_t fisa_disallowed[MAX_REO_DEST_RINGS]; + uint8_t fisa_force_flushed[MAX_REO_DEST_RINGS]; +#endif }; @@ -1936,13 +2225,56 @@ struct dp_peer_cached_bufq { uint32_t dropped; }; +/** + * enum dp_peer_ast_flowq + * @DP_PEER_AST_FLOWQ_HI_PRIO: Hi Priority flow queue + * @DP_PEER_AST_FLOWQ_LOW_PRIO: Low priority flow queue + * @DP_PEER_AST_FLOWQ_UDP: flow queue type is UDP + * @DP_PEER_AST_FLOWQ_NON_UDP: flow queue type is Non UDP + */ +enum dp_peer_ast_flowq { + DP_PEER_AST_FLOWQ_HI_PRIO, + DP_PEER_AST_FLOWQ_LOW_PRIO, + DP_PEER_AST_FLOWQ_UDP, + DP_PEER_AST_FLOWQ_NON_UDP, + DP_PEER_AST_FLOWQ_MAX, +}; + +/* + * struct dp_ast_flow_override_info - ast override info + * @ast_index - ast indexes in peer map message + * @ast_valid_mask - ast valid mask for each ast index + * @ast_flow_mask - ast flow mask for each ast index + * @tid_valid_low_pri_mask - per tid mask for low priority flow + * @tid_valid_hi_pri_mask - per tid mask for hi priority flow + */ +struct dp_ast_flow_override_info { + uint16_t ast_idx[DP_PEER_AST_FLOWQ_MAX]; + uint8_t ast_valid_mask; + uint8_t ast_flow_mask[DP_PEER_AST_FLOWQ_MAX]; + uint8_t tid_valid_low_pri_mask; + uint8_t tid_valid_hi_pri_mask; +}; + +/* + * struct dp_peer_ast_params - ast parameters for a msdu flow-queue + * @ast_index - ast index populated by FW + * @is_valid - ast flow valid mask + * @valid_tid_mask - per tid mask for this ast index + * @flowQ - flow queue id associated with this ast index + */ +struct dp_peer_ast_params { + uint16_t ast_idx; + uint8_t is_valid; + uint8_t valid_tid_mask; + uint8_t flowQ; +}; + /* Peer structure for data path state */ struct dp_peer { /* VDEV to which this peer is associated */ struct dp_vdev *vdev; - struct cdp_ctrl_objmgr_peer *ctrl_peer; - struct dp_ast_entry *self_ast_entry; qdf_atomic_t ref_cnt; @@ -1970,29 +2302,15 @@ struct dp_peer { u_int32_t michael_key[2]; /* relevant for TKIP */ } security[2]; /* 0 -> multicast, 1 -> unicast */ - /* - * rx proc function: this either is a copy of pdev's rx_opt_proc for - * regular rx processing, or has been redirected to a /dev/null discard - * function when peer deletion is in progress. - */ - void (*rx_opt_proc)(struct dp_vdev *vdev, struct dp_peer *peer, - unsigned tid, qdf_nbuf_t msdu_list); - - /* set when node is authorized */ - uint8_t authorize:1; - - u_int8_t nac; - - /* Band steering: Set when node is inactive */ - uint8_t peer_bs_inact_flag:1; - u_int16_t peer_bs_inact; /* inactivity mark count */ - /* NAWDS Flag and Bss Peer bit */ - uint8_t nawds_enabled:1, - bss_peer:1, - wapi:1, - wds_enabled:1, - valid:1; + uint8_t nawds_enabled:1, /* NAWDS flag */ + bss_peer:1, /* set for bss peer */ + wds_enabled:1, /* WDS peer */ + authorize:1, /* Set when authorized */ + nac:1, /* NAC Peer*/ + tx_cap_enabled:1, /* Peer's tx-capture is enabled */ + rx_cap_enabled:1, /* Peer's rx-capture is enabled */ + valid:1; /* valid bit */ /* MCL specific peer local id */ uint16_t local_id; @@ -2032,10 +2350,28 @@ struct dp_peer { /* average sojourn time */ qdf_ewma_tx_lag avg_sojourn_msdu[CDP_DATA_TID_MAX]; +#ifdef QCA_MULTIPASS_SUPPORT + /* node in the special peer list element */ + TAILQ_ENTRY(dp_peer) mpass_peer_list_elem; + /* vlan id for key */ + uint16_t vlan_id; +#endif + #ifdef PEER_CACHE_RX_PKTS qdf_atomic_t flush_in_progress; struct dp_peer_cached_bufq bufq_info; #endif +#ifdef FEATURE_PERPKT_INFO + /* delayed ba ppdu stats handling */ + struct cdp_delayed_tx_completion_ppdu_user delayed_ba_ppdu_stats; + /* delayed ba flag */ + bool last_delayed_ba; + /* delayed ba ppdu id */ + uint32_t last_delayed_ba_ppduid; +#endif +#ifdef QCA_PEER_MULTIQ_SUPPORT + struct dp_peer_ast_params peer_ast_flowq_idx[DP_PEER_AST_FLOWQ_MAX]; +#endif }; /* @@ -2062,6 +2398,151 @@ struct dp_tx_me_buf_t { uint8_t data[QDF_MAC_ADDR_SIZE]; }; +#if defined(WLAN_SUPPORT_RX_FLOW_TAG) || defined(WLAN_SUPPORT_RX_FISA) +struct hal_rx_fst; + +#ifdef WLAN_SUPPORT_RX_FLOW_TAG +struct dp_rx_fse { + /* HAL Rx Flow Search Entry which matches HW definition */ + void *hal_rx_fse; + /* Toeplitz hash value */ + uint32_t flow_hash; + /* Flow index, equivalent to hash value truncated to FST size */ + uint32_t flow_id; + /* Stats tracking for this flow */ + struct cdp_flow_stats stats; + /* Flag indicating whether flow is IPv4 address tuple */ + uint8_t is_ipv4_addr_entry; + /* Flag indicating whether flow is valid */ + uint8_t is_valid; +}; + +struct dp_rx_fst { + /* Software (DP) FST */ + uint8_t *base; + /* Pointer to HAL FST */ + struct hal_rx_fst *hal_rx_fst; + /* Base physical address of HAL RX HW FST */ + uint64_t hal_rx_fst_base_paddr; + /* Maximum number of flows FSE supports */ + uint16_t max_entries; + /* Num entries in flow table */ + uint16_t num_entries; + /* SKID Length */ + uint16_t max_skid_length; + /* Hash mask to obtain legitimate hash entry */ + uint32_t hash_mask; + /* Timer for bundling of flows */ + qdf_timer_t cache_invalidate_timer; + /** + * Flag which tracks whether cache update + * is needed on timer expiry + */ + qdf_atomic_t is_cache_update_pending; + /* Flag to indicate completion of FSE setup in HW/FW */ + bool fse_setup_done; +}; + +#define DP_RX_GET_SW_FT_ENTRY_SIZE sizeof(struct dp_rx_fse) +#elif WLAN_SUPPORT_RX_FISA + +struct dp_fisa_stats { + /* flow index invalid from RX HW TLV */ + uint32_t invalid_flow_index; +}; + +enum fisa_aggr_ret { + FISA_AGGR_DONE, + FISA_AGGR_NOT_ELIGIBLE, + FISA_FLUSH_FLOW +}; + +struct dp_fisa_rx_sw_ft { + /* HAL Rx Flow Search Entry which matches HW definition */ + void *hw_fse; + /* Toeplitz hash value */ + uint32_t flow_hash; + /* Flow index, equivalent to hash value truncated to FST size */ + uint32_t flow_id; + /* Stats tracking for this flow */ + struct cdp_flow_stats stats; + /* Flag indicating whether flow is IPv4 address tuple */ + uint8_t is_ipv4_addr_entry; + /* Flag indicating whether flow is valid */ + uint8_t is_valid; + uint8_t is_populated; + uint8_t is_flow_udp; + uint8_t is_flow_tcp; + qdf_nbuf_t head_skb; + uint16_t cumulative_l4_checksum; + uint16_t adjusted_cumulative_ip_length; + uint16_t cur_aggr; + uint16_t napi_flush_cumulative_l4_checksum; + uint16_t napi_flush_cumulative_ip_length; + qdf_nbuf_t last_skb; + uint32_t head_skb_ip_hdr_offset; + uint32_t head_skb_l4_hdr_offset; + struct cdp_rx_flow_tuple_info rx_flow_tuple_info; + uint8_t napi_id; + struct dp_vdev *vdev; + uint64_t bytes_aggregated; + uint32_t flush_count; + uint32_t aggr_count; + uint8_t do_not_aggregate; + uint16_t hal_cumultive_ip_len; + struct dp_soc *soc_hdl; + /* last aggregate count fetched from RX PKT TLV */ + uint32_t last_hal_aggr_count; + uint32_t cur_aggr_gso_size; + struct udphdr *head_skb_udp_hdr; + uint32_t reo_dest_indication; +}; + +#define DP_RX_GET_SW_FT_ENTRY_SIZE sizeof(struct dp_fisa_rx_sw_ft) +#define MAX_FSE_CACHE_FL_HST 10 +/** + * struct fse_cache_flush_history - Debug history cache flush + * @timestamp: Entry update timestamp + * @flows_added: Number of flows added for this flush + * @flows_deleted: Number of flows deleted for this flush + */ +struct fse_cache_flush_history { + uint64_t timestamp; + uint32_t flows_added; + uint32_t flows_deleted; +}; + +struct dp_rx_fst { + /* Software (DP) FST */ + uint8_t *base; + /* Pointer to HAL FST */ + struct hal_rx_fst *hal_rx_fst; + /* Base physical address of HAL RX HW FST */ + uint64_t hal_rx_fst_base_paddr; + /* Maximum number of flows FSE supports */ + uint16_t max_entries; + /* Num entries in flow table */ + uint16_t num_entries; + /* SKID Length */ + uint16_t max_skid_length; + /* Hash mask to obtain legitimate hash entry */ + uint32_t hash_mask; + /* Lock for adding/deleting entries of FST */ + qdf_spinlock_t dp_rx_fst_lock; + uint32_t add_flow_count; + uint32_t del_flow_count; + uint32_t hash_collision_cnt; + struct dp_soc *soc_hdl; + qdf_atomic_t fse_cache_flush_posted; + qdf_timer_t fse_cache_flush_timer; + struct fse_cache_flush_history cache_fl_rec[MAX_FSE_CACHE_FL_HST]; + /* FISA DP stats */ + struct dp_fisa_stats stats; +}; + +#endif /* WLAN_SUPPORT_RX_FISA */ +#endif /* WLAN_SUPPORT_RX_FLOW_TAG || WLAN_SUPPORT_RX_FISA */ + #ifdef WLAN_FEATURE_STATS_EXT /* * dp_req_rx_hw_stats_t: RX peer HW stats query structure diff --git a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_wdi_event.c b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_wdi_event.c index 3417b95ce2342b9da41831f110daf2a22d58b2fc..697a570ac53069c4fb35ca806227151aac2a1434 100644 --- a/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_wdi_event.c +++ b/drivers/staging/qca-wifi-host-cmn/dp/wifi3.0/dp_wdi_event.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -21,9 +21,14 @@ #include "qdf_mem.h" /* qdf_mem_malloc,free */ #ifdef WDI_EVENT_ENABLE -void *dp_get_pldev(struct cdp_pdev *txrx_pdev) +void *dp_get_pldev(struct cdp_soc_t *soc_hdl, uint8_t pdev_id) { - struct dp_pdev *pdev = (struct dp_pdev *)txrx_pdev; + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (!pdev) + return NULL; + return pdev->pl_dev; } /* @@ -110,7 +115,7 @@ dp_wdi_event_iter_sub( void dp_wdi_event_handler( enum WDI_EVENT event, - void *soc, + struct dp_soc *soc, void *data, uint16_t peer_id, int status, uint8_t pdev_id) @@ -149,7 +154,8 @@ dp_wdi_event_handler( /* * dp_wdi_event_sub() - Subscribe WDI event - * @txrx_pdev_handle: cdp_pdev handle + * @soc: soc handle + * @pdev_id: id of pdev * @event_cb_sub_handle: subcribe evnet handle * @event: Event to be subscribe * @@ -157,13 +163,15 @@ dp_wdi_event_handler( */ int dp_wdi_event_sub( - struct cdp_pdev *txrx_pdev_handle, - void *event_cb_sub_handle, + struct cdp_soc_t *soc, uint8_t pdev_id, + wdi_event_subscribe *event_cb_sub_handle, uint32_t event) { uint32_t event_index; wdi_event_subscribe *wdi_sub; - struct dp_pdev *txrx_pdev = (struct dp_pdev *)txrx_pdev_handle; + struct dp_pdev *txrx_pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); wdi_event_subscribe *event_cb_sub = (wdi_event_subscribe *) event_cb_sub_handle; @@ -206,7 +214,8 @@ dp_wdi_event_sub( /* * dp_wdi_event_unsub() - WDI event unsubscribe - * @txrx_pdev_handle: cdp_pdev handle + * @soc: soc handle + * @pdev_id: id of pdev * @event_cb_sub_handle: subscribed event handle * @event: Event to be unsubscribe * @@ -215,18 +224,20 @@ dp_wdi_event_sub( */ int dp_wdi_event_unsub( - struct cdp_pdev *txrx_pdev_handle, - void *event_cb_sub_handle, + struct cdp_soc_t *soc, uint8_t pdev_id, + wdi_event_subscribe *event_cb_sub_handle, uint32_t event) { uint32_t event_index = event - WDI_EVENT_BASE; - struct dp_pdev *txrx_pdev = (struct dp_pdev *)txrx_pdev_handle; + struct dp_pdev *txrx_pdev = + dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, + pdev_id); wdi_event_subscribe *event_cb_sub = (wdi_event_subscribe *) event_cb_sub_handle; - if (!event_cb_sub) { + if (!txrx_pdev || !event_cb_sub) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "Invalid callback in %s", __func__); + "Invalid callback or pdev in %s", __func__); return -EINVAL; } diff --git a/drivers/staging/qca-wifi-host-cmn/global_lmac_if/src/wlan_global_lmac_if.c b/drivers/staging/qca-wifi-host-cmn/global_lmac_if/src/wlan_global_lmac_if.c index 0d4ef2e96e6f8fadf6bcea2129c23d8df9523396..f304973bf93d07dbe5cc4bca8c794e6f56c8fba1 100644 --- a/drivers/staging/qca-wifi-host-cmn/global_lmac_if/src/wlan_global_lmac_if.c +++ b/drivers/staging/qca-wifi-host-cmn/global_lmac_if/src/wlan_global_lmac_if.c @@ -25,6 +25,8 @@ #ifdef WLAN_CONV_SPECTRAL_ENABLE #include #endif +#include + /* Function pointer to call DA/OL specific tx_ops registration function */ QDF_STATUS (*wlan_global_lmac_if_tx_ops_register[MAX_DEV_TYPE]) (struct wlan_lmac_if_tx_ops *tx_ops); @@ -135,6 +137,8 @@ QDF_STATUS wlan_global_lmac_if_open(struct wlan_objmgr_psoc *psoc) /* Function call to register rx-ops handlers */ wlan_global_lmac_if_rx_ops_register(&psoc->soc_cb.rx_ops); + target_if_wake_lock_init(psoc); + return QDF_STATUS_SUCCESS; } qdf_export_symbol(wlan_global_lmac_if_open); @@ -149,6 +153,7 @@ qdf_export_symbol(wlan_global_lmac_if_open); */ QDF_STATUS wlan_global_lmac_if_close(struct wlan_objmgr_psoc *psoc) { + target_if_wake_lock_deinit(psoc); qdf_mem_zero(&psoc->soc_cb.tx_ops, sizeof(psoc->soc_cb.tx_ops)); qdf_mem_zero(&psoc->soc_cb.rx_ops, sizeof(psoc->soc_cb.rx_ops)); diff --git a/drivers/staging/qca-wifi-host-cmn/gpio/core/inc/wlan_gpio_api.h b/drivers/staging/qca-wifi-host-cmn/gpio/core/inc/wlan_gpio_api.h new file mode 100644 index 0000000000000000000000000000000000000000..5989812fb2001d6a0cb935ecc568e0c541f785d3 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/gpio/core/inc/wlan_gpio_api.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_gpio_api.h + * + * This header file provide API declarations required for gpio cfg + * that called by other components + */ + +#ifndef __WLAN_GPIO_CFG_API_H__ +#define __WLAN_GPIO_CFG_API_H__ + +#include + +#ifdef WLAN_FEATURE_GPIO_CFG + +/** + * wlan_gpio_init() - API to init component + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS wlan_gpio_init(void); + +/** + * wlan_gpio_deinit() - API to deinit component + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS wlan_gpio_deinit(void); + +#else +static inline +QDF_STATUS wlan_gpio_init(void) +{ + return QDF_STATUS_SUCCESS; +} + +static inline +QDF_STATUS wlan_gpio_deinit(void) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_GPIO_CFG */ +#endif /*__WLAN_GPIO_CFG_API_H__*/ + diff --git a/drivers/staging/qca-wifi-host-cmn/gpio/core/inc/wlan_gpio_priv_api.h b/drivers/staging/qca-wifi-host-cmn/gpio/core/inc/wlan_gpio_priv_api.h new file mode 100644 index 0000000000000000000000000000000000000000..4ea4ead5727a43afb85337b8aa24f4e87e509fa0 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/gpio/core/inc/wlan_gpio_priv_api.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_gpio_priv_api.h + * + * This header file provide API declarations required for gpio cfg + * that called internally + */ + +#ifndef __WLAN_GPIO_CFG_PRIV_API_H__ +#define __WLAN_GPIO_CFG_PRIV_API_H__ + +#include +#include +#include + +#define gpio_debug(args ...) \ + QDF_TRACE_DEBUG(QDF_MODULE_ID_GPIO, ## args) +#define gpio_err(args ...) \ + QDF_TRACE_ERROR(QDF_MODULE_ID_GPIO, ## args) + +/** + * struct gpio_psoc_priv_obj - psoc private object + * @lock: qdf spin lock + * @soc: pointer to psoc object + */ +struct gpio_psoc_priv_obj { + qdf_spinlock_t lock; + struct wlan_objmgr_psoc *soc; +}; + +/** + * gpio_get_psoc_priv_obj() - get priv object from psoc object + * @psoc: pointer to psoc object + * + * Return: pointer to gpio psoc private object + */ +static inline +struct gpio_psoc_priv_obj * +gpio_get_psoc_priv_obj(struct wlan_objmgr_psoc *psoc) +{ + struct gpio_psoc_priv_obj *obj; + + if (!psoc) + return NULL; + obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_GPIO); + + return obj; +} + +/** + * wlan_psoc_get_gpio_txops() - get TX ops from the private object + * @psoc: pointer to psoc object + * + * Return: pointer to TX op callback + */ + +static inline struct wlan_lmac_if_gpio_tx_ops * +wlan_psoc_get_gpio_txops(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_lmac_if_tx_ops *tx_ops; + + tx_ops = wlan_psoc_get_lmac_if_txops(psoc); + if (!tx_ops) { + gpio_err("tx_ops is NULL"); + return NULL; + } + + return &tx_ops->gpio_ops; +} +#endif /*__WLAN_GPIO_CFG_PRIV_API_H__*/ diff --git a/drivers/staging/qca-wifi-host-cmn/gpio/core/src/wlan_gpio_api.c b/drivers/staging/qca-wifi-host-cmn/gpio/core/src/wlan_gpio_api.c new file mode 100644 index 0000000000000000000000000000000000000000..8525368d67aae9ad12b1395c8bb90d144a32e391 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/gpio/core/src/wlan_gpio_api.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_gpio_api.c + */ +#include +#include +#include + +/** + * gpio_psoc_obj_created_notification() - PSOC obj create callback + * @psoc: PSOC object + * @arg_list: Variable argument list + * + * This callback is registered with object manager during initialization to + * get notified when the object is created. + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +static QDF_STATUS +gpio_psoc_obj_created_notification(struct wlan_objmgr_psoc *psoc, + void *arg_list) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct gpio_psoc_priv_obj *gpio_obj; + + gpio_obj = qdf_mem_malloc(sizeof(*gpio_obj)); + if (!gpio_obj) + return QDF_STATUS_E_NOMEM; + + qdf_spinlock_create(&gpio_obj->lock); + status = wlan_objmgr_psoc_component_obj_attach(psoc, + WLAN_UMAC_COMP_GPIO, + gpio_obj, + QDF_STATUS_SUCCESS); + if (QDF_IS_STATUS_ERROR(status)) { + gpio_err("obj attach with psoc failed"); + goto gpio_psoc_attach_failed; + } + + return QDF_STATUS_SUCCESS; + +gpio_psoc_attach_failed: + qdf_spinlock_destroy(&gpio_obj->lock); + qdf_mem_free(gpio_obj); + return status; +} + +/** + * gpio_psoc_obj_destroyed_notification() - obj delete callback + * @psoc: PSOC object + * @arg_list: Variable argument list + * + * This callback is registered with object manager during initialization to + * get notified when the object is deleted. + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +static QDF_STATUS +gpio_psoc_obj_destroyed_notification(struct wlan_objmgr_psoc *psoc, + void *arg_list) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct gpio_psoc_priv_obj *gpio_obj; + + gpio_obj = gpio_get_psoc_priv_obj(psoc); + + if (!gpio_obj) { + gpio_err("gpio_obj is NULL"); + return QDF_STATUS_E_FAULT; + } + + status = wlan_objmgr_psoc_component_obj_detach(psoc, + WLAN_UMAC_COMP_GPIO, + gpio_obj); + if (QDF_IS_STATUS_ERROR(status)) + gpio_err("gpio_obj detach failed"); + + qdf_spinlock_destroy(&gpio_obj->lock); + qdf_mem_free(gpio_obj); + + return status; +} + +QDF_STATUS wlan_gpio_init(void) +{ + QDF_STATUS status; + + /* register psoc create handler functions. */ + status = wlan_objmgr_register_psoc_create_handler( + WLAN_UMAC_COMP_GPIO, + gpio_psoc_obj_created_notification, + NULL); + if (QDF_IS_STATUS_ERROR(status)) { + gpio_err("register create handler failed"); + return status; + } + + /* register psoc delete handler functions. */ + status = wlan_objmgr_register_psoc_destroy_handler( + WLAN_UMAC_COMP_GPIO, + gpio_psoc_obj_destroyed_notification, + NULL); + if (QDF_IS_STATUS_ERROR(status)) { + gpio_err("register destroy handler failed"); + goto fail_delete_psoc; + } + + return status; + +fail_delete_psoc: + wlan_objmgr_unregister_psoc_create_handler( + WLAN_UMAC_COMP_GPIO, + gpio_psoc_obj_created_notification, + NULL); + return status; +} + +QDF_STATUS wlan_gpio_deinit(void) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS, status; + + /* unregister psoc delete handler functions. */ + status = wlan_objmgr_unregister_psoc_destroy_handler( + WLAN_UMAC_COMP_GPIO, + gpio_psoc_obj_destroyed_notification, + NULL); + if (QDF_IS_STATUS_ERROR(status)) { + gpio_err("unregister destroy handler failed"); + ret = status; + } + + /* unregister psoc create handler functions. */ + status = wlan_objmgr_unregister_psoc_create_handler( + WLAN_UMAC_COMP_GPIO, + gpio_psoc_obj_created_notification, + NULL); + if (QDF_IS_STATUS_ERROR(status)) { + gpio_err("unregister create handler failed"); + ret = status; + } + + return ret; +} diff --git a/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/inc/wlan_gpio_tgt_api.h b/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/inc/wlan_gpio_tgt_api.h new file mode 100644 index 0000000000000000000000000000000000000000..0b706f516f2c07e7cd911561991e025876eb0019 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/inc/wlan_gpio_tgt_api.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_gpio_tgt_api.h + * + * This header file provide with API declarations to interface with Southbound + */ +#ifndef __WLAN_GPIO_CFG_TGT_API_H__ +#define __WLAN_GPIO_CFG_TGT_API_H__ + +#ifdef WLAN_FEATURE_GPIO_CFG +#include +#include +struct wlan_objmgr_psoc; + +/** + * tgt_set_gpio_config_req(): API to set GPIO configuration to lmac + * @psoc: the pointer to psoc object manager + * @param: the pointer to gpio cfg info + * + * Return: status of operation + */ +QDF_STATUS +tgt_set_gpio_config_req(struct wlan_objmgr_psoc *psoc, + struct gpio_config_params *param); + +/** + * tgt_set_gpio_output_req(): API to set GPIO output info to lmac + * @psoc: the pointer to psoc object manager + * @param: the pointer to gpio output info + * + * Return: status of operation + */ + +QDF_STATUS +tgt_set_gpio_output_req(struct wlan_objmgr_psoc *psoc, + struct gpio_output_params *param); + +/** + * tgt_if_gpio_config() - API to send gpio config request + * @psoc: pointer to psoc object + * @gpio_num: gpio pin number + * @input: enable/disable the gpio pin + * @pull_type: gpio pull type + * @intr_mode: gpio interrupt mode + * @mux_config_val: gpio MUX value + * @drive: gpio drive + * @init_enable: gpio init_enable + * + * Return: status of operation + */ +QDF_STATUS tgt_gpio_config(struct wlan_objmgr_psoc *psoc, uint32_t gpio_num, + uint32_t input, uint32_t pull_type, + uint32_t intr_mode, uint32_t mux_config_val, + uint32_t drive, uint32_t init_enable); +/** + * tgt_if_gpio_output() - API to send gpio output request + * @psoc: pointer to psoc object + * @gpio_num: gpio pin number + * @set: enable/disable the gpio pin + * + * Return: status of operation + */ +QDF_STATUS tgt_gpio_output(struct wlan_objmgr_psoc *psoc, uint32_t gpio_num, + uint32_t set); +#else +static QDF_STATUS tgt_gpio_config(struct wlan_objmgr_psoc *psoc, + uint32_t gpio_num, uint32_t input, + uint32_t pull_type, uint32_t intr_mode) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS tgt_gpio_output(struct wlan_objmgr_psoc *psoc, + uint32_t gpio_num, uint32_t set) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* WLAN_FEATURE_GPIO_CFG */ +#endif /* __WLAN_GPIO_TGT_API_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/inc/wlan_gpio_ucfg_api.h b/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/inc/wlan_gpio_ucfg_api.h new file mode 100644 index 0000000000000000000000000000000000000000..933825f8a1a64e0414e15d16d2530668fb41b4c7 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/inc/wlan_gpio_ucfg_api.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_gpio_ucfg_api.h + * + * This header file maintain API declaration required for northbound interaction + */ + +#ifndef __WLAN_GPIO_CFG_UCFG_API_H__ +#define __WLAN_GPIO_CFG_UCFG_API_H__ + +#include +#include +struct wlan_objmgr_psoc; + +#ifdef WLAN_FEATURE_GPIO_CFG + +/** + * ucfg_set_gpio_config() - API to set gpio config + * @psoc: the pointer of psoc object + * @param: the pointer of gpio configuration info + * + * Return:QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS ucfg_set_gpio_config(struct wlan_objmgr_psoc *psoc, + struct gpio_config_params *param); + +/** + * ucfg_set_gpio_output() - API to set gpio output + * @psoc: the pointer of psoc object + * @param: the pointer of gpio output info + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS ucfg_set_gpio_output(struct wlan_objmgr_psoc *psoc, + struct gpio_output_params *param); +#endif /* WLAN_FEATURE_GPIO_CFG */ +#endif /* __WLAN_GPIO_CFG_UCFG_API_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/src/wlan_gpio_tgt_api.c b/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/src/wlan_gpio_tgt_api.c new file mode 100644 index 0000000000000000000000000000000000000000..293cfdf0bb24dcd875827ef1deee794c7ef29497 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/src/wlan_gpio_tgt_api.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC:wlan_gpio_tgt_api.c + * + * This file provide API definitions to update gpio configuration from interface + */ +#include +#include +#include +#include + +QDF_STATUS tgt_set_gpio_config_req(struct wlan_objmgr_psoc *psoc, + struct gpio_config_params *param) +{ + struct wlan_lmac_if_gpio_tx_ops *gpio_tx_ops; + + if (!psoc) { + gpio_err("NULL psoc"); + return QDF_STATUS_E_NULL_VALUE; + } + gpio_tx_ops = wlan_psoc_get_gpio_txops(psoc); + if (!gpio_tx_ops) + return QDF_STATUS_E_NULL_VALUE; + + return gpio_tx_ops->set_gpio_config(psoc, param); +} + +QDF_STATUS tgt_set_gpio_output_req(struct wlan_objmgr_psoc *psoc, + struct gpio_output_params *param) +{ + struct wlan_lmac_if_gpio_tx_ops *gpio_tx_ops; + + if (!psoc) { + gpio_err("NULL psoc"); + return QDF_STATUS_E_NULL_VALUE; + } + + gpio_tx_ops = wlan_psoc_get_gpio_txops(psoc); + if (!gpio_tx_ops) + return QDF_STATUS_E_NULL_VALUE; + + return gpio_tx_ops->set_gpio_output(psoc, param); +} + +QDF_STATUS tgt_gpio_config(struct wlan_objmgr_psoc *psoc, uint32_t gpio_num, + uint32_t input, uint32_t pull_type, + uint32_t intr_mode, uint32_t mux_config_val, + uint32_t drive, uint32_t init_enable) +{ + struct gpio_config_params param; + + if (!psoc) { + gpio_err("psoc_obj is null"); + return QDF_STATUS_E_INVAL; + } + + qdf_mem_set(¶m, sizeof(param), 0); + param.pin_pull_type = pull_type; + param.pin_num = gpio_num; + param.pin_dir = input; + param.pin_intr_mode = intr_mode; + param.mux_config_val = mux_config_val; + param.drive = drive; + param.init_enable = init_enable; + + return tgt_set_gpio_config_req(psoc, ¶m); +} + +qdf_export_symbol(tgt_gpio_config); + +static bool tgt_gpio_disabled(struct wlan_objmgr_psoc *psoc) +{ + uint32_t target_type = 0; + struct wlan_lmac_if_target_tx_ops *target_type_tx_ops; + struct wlan_lmac_if_tx_ops *tx_ops; + + tx_ops = wlan_psoc_get_lmac_if_txops(psoc); + if (!tx_ops) { + gpio_err("tx_ops is NULL"); + return false; + } + target_type_tx_ops = &tx_ops->target_tx_ops; + + if (target_type_tx_ops->tgt_get_tgt_type) + target_type = target_type_tx_ops->tgt_get_tgt_type(psoc); + + if ((target_type == TARGET_TYPE_QCA8074) || + (target_type == TARGET_TYPE_QCN6122) || + (target_type == TARGET_TYPE_QCA8074V2) || + (target_type == TARGET_TYPE_QCA5018) || + (target_type == TARGET_TYPE_QCA6018)) { + return true; + } + + return false; +} + +QDF_STATUS tgt_gpio_output(struct wlan_objmgr_psoc *psoc, uint32_t gpio_num, + uint32_t set) +{ + struct gpio_output_params param; + + if (!psoc) { + gpio_err("psoc_obj is null"); + return QDF_STATUS_E_INVAL; + } + + if (tgt_gpio_disabled(psoc)) + return QDF_STATUS_E_INVAL; + + qdf_mem_set(¶m, sizeof(param), 0); + param.pin_num = gpio_num; + param.pin_set = set; + + return tgt_set_gpio_output_req(psoc, ¶m); +} + +qdf_export_symbol(tgt_gpio_output); diff --git a/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/src/wlan_gpio_ucfg_api.c b/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/src/wlan_gpio_ucfg_api.c new file mode 100644 index 0000000000000000000000000000000000000000..648658a7fbe331cff4f6d83be71d6bb611ea6890 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/gpio/dispatcher/src/wlan_gpio_ucfg_api.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: This file contains gpio north bound interface definitions + */ +#include +#include +#include "qdf_module.h" + +QDF_STATUS +ucfg_set_gpio_config(struct wlan_objmgr_psoc *psoc, + struct gpio_config_params *param) +{ + return tgt_set_gpio_config_req(psoc, param); +} +qdf_export_symbol(ucfg_set_gpio_config); + +QDF_STATUS +ucfg_set_gpio_output(struct wlan_objmgr_psoc *psoc, + struct gpio_output_params *param) +{ + return tgt_set_gpio_output_req(psoc, param); +} +qdf_export_symbol(ucfg_set_gpio_output); diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_api.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_api.h index d048a3fb5112761cdc4a83055ac300b98ac24761..649852dcac214a381a563ae4171dcf4ebc743cc5 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_api.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -23,10 +24,36 @@ #include "qdf_util.h" #include "qdf_atomic.h" #include "hal_internal.h" +#include "hif.h" +#include "hif_io32.h" #include "qdf_platform.h" +#ifdef DUMP_REO_QUEUE_INFO_IN_DDR +#include "hal_hw_headers.h" +#endif + +/* Ring index for WBM2SW2 release ring */ +#define HAL_IPA_TX_COMP_RING_IDX 2 + +/* calculate the register address offset from bar0 of shadow register x */ +#if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490) || \ + defined(QCA_WIFI_QCA6750) +#define SHADOW_REGISTER_START_ADDRESS_OFFSET 0x000008FC +#define SHADOW_REGISTER_END_ADDRESS_OFFSET \ + ((SHADOW_REGISTER_START_ADDRESS_OFFSET) + (4 * (MAX_SHADOW_REGISTERS))) +#define SHADOW_REGISTER(x) ((SHADOW_REGISTER_START_ADDRESS_OFFSET) + (4 * (x))) +#elif defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCN9000) +#define SHADOW_REGISTER_START_ADDRESS_OFFSET 0x00003024 +#define SHADOW_REGISTER_END_ADDRESS_OFFSET \ + ((SHADOW_REGISTER_START_ADDRESS_OFFSET) + (4 * (MAX_SHADOW_REGISTERS))) +#define SHADOW_REGISTER(x) ((SHADOW_REGISTER_START_ADDRESS_OFFSET) + (4 * (x))) +#else +#define SHADOW_REGISTER(x) 0 +#endif /* QCA_WIFI_QCA6390 || QCA_WIFI_QCA6490 || QCA_WIFI_QCA6750 */ + #define MAX_UNWINDOWED_ADDRESS 0x80000 -#ifdef QCA_WIFI_QCA6390 +#if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490) || \ + defined(QCA_WIFI_QCN9000) || defined(QCA_WIFI_QCA6750) #define WINDOW_ENABLE_BIT 0x40000000 #else #define WINDOW_ENABLE_BIT 0x80000000 @@ -36,21 +63,36 @@ #define WINDOW_VALUE_MASK 0x3F #define WINDOW_START MAX_UNWINDOWED_ADDRESS #define WINDOW_RANGE_MASK 0x7FFFF - /* * BAR + 4K is always accessible, any access outside this * space requires force wake procedure. - * OFFSET = 4K - 32 bytes = 0x4063 + * OFFSET = 4K - 32 bytes = 0xFE0 */ -#define MAPPED_REF_OFF 0x4063 +#define MAPPED_REF_OFF 0xFE0 -#ifdef HAL_CONFIG_SLUB_DEBUG_ON -#define FORCE_WAKE_DELAY_TIMEOUT 500 -#else -#define FORCE_WAKE_DELAY_TIMEOUT 50 -#endif /* HAL_CONFIG_SLUB_DEBUG_ON */ +/** + * hal_ring_desc - opaque handle for DP ring descriptor + */ +struct hal_ring_desc; +typedef struct hal_ring_desc *hal_ring_desc_t; -#define FORCE_WAKE_DELAY_MS 5 +/** + * hal_link_desc - opaque handle for DP link descriptor + */ +struct hal_link_desc; +typedef struct hal_link_desc *hal_link_desc_t; + +/** + * hal_rxdma_desc - opaque handle for DP rxdma dst ring descriptor + */ +struct hal_rxdma_desc; +typedef struct hal_rxdma_desc *hal_rxdma_desc_t; + +/** + * hal_buff_addrinfo - opaque handle for DP buffer address info + */ +struct hal_buff_addrinfo; +typedef struct hal_buff_addrinfo *hal_buff_addrinfo_t; #ifdef ENABLE_VERBOSE_DEBUG static inline void @@ -99,6 +141,7 @@ static inline int hal_history_get_next_index(qdf_atomic_t *table_index, * @hal_soc: HAL soc handle * @offset: register offset to read * @exp_val: the expected value of register + * @ret_confirm: result confirm flag * * Return: none */ @@ -115,17 +158,7 @@ static inline void hal_reg_write_result_check(struct hal_soc *hal_soc, } } -#ifndef QCA_WIFI_QCA6390 -static inline int hal_force_wake_request(struct hal_soc *soc) -{ - return 0; -} - -static inline int hal_force_wake_release(struct hal_soc *soc) -{ - return 0; -} - +#if !defined(QCA_WIFI_QCA6390) && !defined(QCA_WIFI_QCA6490) static inline void hal_lock_reg_access(struct hal_soc *soc, unsigned long *flags) { @@ -137,36 +170,7 @@ static inline void hal_unlock_reg_access(struct hal_soc *soc, { qdf_spin_unlock_irqrestore(&soc->register_access_lock); } - #else -static inline int hal_force_wake_request(struct hal_soc *soc) -{ - int ret; - - ret = pld_force_wake_request_sync(soc->qdf_dev->dev, - FORCE_WAKE_DELAY_TIMEOUT * 1000); - if (ret) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: Request send failed %d\n", __func__, ret); - return -EINVAL; - } - - /* If device's M1 state-change event races here, it can be ignored, - * as the device is expected to immediately move from M2 to M0 - * without entering low power state. - */ - if (!pld_is_device_awake(soc->qdf_dev->dev)) - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW, - "%s: state-change event races, ignore\n", __func__); - - return 0; -} - -static inline int hal_force_wake_release(struct hal_soc *soc) -{ - return pld_force_wake_release(soc->qdf_dev->dev); -} - static inline void hal_lock_reg_access(struct hal_soc *soc, unsigned long *flags) { @@ -182,7 +186,7 @@ static inline void hal_unlock_reg_access(struct hal_soc *soc, #ifdef PCIE_REG_WINDOW_LOCAL_NO_CACHE /** - * hal_select_window_confirm() - write window register and + * hal_select_window_confirm() - write remap window register and check writing result * */ @@ -217,33 +221,86 @@ static inline void hal_select_window_confirm(struct hal_soc *hal_soc, } #endif +static inline qdf_iomem_t hal_get_window_address(struct hal_soc *hal_soc, + qdf_iomem_t addr) +{ + return hal_soc->ops->hal_get_window_address(hal_soc, addr); +} + /** + * hal_write32_mb() - Access registers to update configuration + * @hal_soc: hal soc handle + * @offset: offset address from the BAR + * @value: value to write + * + * Return: None + * + * Description: Register address space is split below: + * SHADOW REGION UNWINDOWED REGION WINDOWED REGION + * |--------------------|-------------------|------------------| + * BAR NO FORCE WAKE BAR+4K FORCE WAKE BAR+512K FORCE WAKE + * + * 1. Any access to the shadow region, doesn't need force wake + * and windowing logic to access. + * 2. Any access beyond BAR + 4K: + * If init_phase enabled, no force wake is needed and access + * should be based on windowed or unwindowed access. + * If init_phase disabled, force wake is needed and access + * should be based on windowed or unwindowed access. + * * note1: WINDOW_RANGE_MASK = (1 << WINDOW_SHIFT) -1 * note2: 1 << WINDOW_SHIFT = MAX_UNWINDOWED_ADDRESS - * note3: WINDOW_VALUE_MASK = big enough that trying to write past that window - * would be a bug + * note3: WINDOW_VALUE_MASK = big enough that trying to write past + * that window would be a bug */ -#ifndef QCA_WIFI_QCA6390 +#if !defined(QCA_WIFI_QCA6390) && !defined(QCA_WIFI_QCA6490) && \ + !defined(QCA_WIFI_QCA6750) static inline void hal_write32_mb(struct hal_soc *hal_soc, uint32_t offset, uint32_t value) { unsigned long flags; + qdf_iomem_t new_addr; if (!hal_soc->use_register_windowing || offset < MAX_UNWINDOWED_ADDRESS) { qdf_iowrite32(hal_soc->dev_base_addr + offset, value); + } else if (hal_soc->static_window_map) { + new_addr = hal_get_window_address(hal_soc, + hal_soc->dev_base_addr + offset); + qdf_iowrite32(new_addr, value); } else { hal_lock_reg_access(hal_soc, &flags); hal_select_window_confirm(hal_soc, offset); qdf_iowrite32(hal_soc->dev_base_addr + WINDOW_START + (offset & WINDOW_RANGE_MASK), value); - hal_unlock_reg_access(hal_soc, &flags); } } +/** + * hal_write_address_32_mb - write a value to a register + * + */ +static inline +void hal_write_address_32_mb(struct hal_soc *hal_soc, + qdf_iomem_t addr, uint32_t value) +{ + uint32_t offset; + qdf_iomem_t new_addr; + + if (!hal_soc->use_register_windowing) + return qdf_iowrite32(addr, value); + + offset = addr - hal_soc->dev_base_addr; + if (hal_soc->static_window_map) { + new_addr = hal_get_window_address(hal_soc, addr); + return qdf_iowrite32(new_addr, value); + } + hal_write32_mb(hal_soc, offset, value); +} + #define hal_write32_mb_confirm(_hal_soc, _offset, _value) \ - hal_write32_mb(_hal_soc, _offset, _value) + hal_write32_mb(_hal_soc, _offset, _value) #else static inline void hal_write32_mb(struct hal_soc *hal_soc, uint32_t offset, uint32_t value) @@ -251,12 +308,17 @@ static inline void hal_write32_mb(struct hal_soc *hal_soc, uint32_t offset, int ret; unsigned long flags; - if (offset > MAPPED_REF_OFF) { - ret = hal_force_wake_request(hal_soc); + /* Region < BAR + 4K can be directly accessed */ + if (offset < MAPPED_REF_OFF) { + qdf_iowrite32(hal_soc->dev_base_addr + offset, value); + return; + } + + /* Region greater than BAR + 4K */ + if (!hal_soc->init_phase) { + ret = hif_force_wake_request(hal_soc->hif_handle); if (ret) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: Wake up request failed %d\n", - __func__, ret); + hal_err("Wake up request failed"); qdf_check_state_before_panic(); return; } @@ -270,18 +332,22 @@ static inline void hal_write32_mb(struct hal_soc *hal_soc, uint32_t offset, hal_select_window_confirm(hal_soc, offset); qdf_iowrite32(hal_soc->dev_base_addr + WINDOW_START + (offset & WINDOW_RANGE_MASK), value); - hal_unlock_reg_access(hal_soc, &flags); } - if ((offset > MAPPED_REF_OFF) && - hal_force_wake_release(hal_soc)) - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: Wake up release failed\n", __func__); + if (!hal_soc->init_phase) { + ret = hif_force_wake_release(hal_soc->hif_handle); + if (ret) { + hal_err("Wake up release failed"); + qdf_check_state_before_panic(); + return; + } + } } /** - * hal_write32_mb_confirm() - write register and check writing result + * hal_write32_mb_confirm() - write register and check wirting result + * */ static inline void hal_write32_mb_confirm(struct hal_soc *hal_soc, uint32_t offset, @@ -290,12 +356,17 @@ static inline void hal_write32_mb_confirm(struct hal_soc *hal_soc, int ret; unsigned long flags; - if (offset > MAPPED_REF_OFF) { - ret = hal_force_wake_request(hal_soc); + /* Region < BAR + 4K can be directly accessed */ + if (offset < MAPPED_REF_OFF) { + qdf_iowrite32(hal_soc->dev_base_addr + offset, value); + return; + } + + /* Region greater than BAR + 4K */ + if (!hal_soc->init_phase) { + ret = hif_force_wake_request(hal_soc->hif_handle); if (ret) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: Wake up request failed %d\n", - __func__, ret); + hal_err("Wake up request failed"); qdf_check_state_before_panic(); return; } @@ -319,21 +390,23 @@ static inline void hal_write32_mb_confirm(struct hal_soc *hal_soc, hal_unlock_reg_access(hal_soc, &flags); } - if ((offset > MAPPED_REF_OFF) && - hal_force_wake_release(hal_soc)) - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: Wake up release failed\n", __func__); + if (!hal_soc->init_phase) { + ret = hif_force_wake_release(hal_soc->hif_handle); + if (ret) { + hal_err("Wake up release failed"); + qdf_check_state_before_panic(); + return; + } + } } -#endif /** * hal_write_address_32_mb - write a value to a register * */ -static inline void hal_write_address_32_mb(struct hal_soc *hal_soc, - void __iomem *addr, uint32_t value, - bool wr_confirm) - +static inline +void hal_write_address_32_mb(struct hal_soc *hal_soc, + qdf_iomem_t addr, uint32_t value, bool wr_confirm) { uint32_t offset; @@ -342,14 +415,23 @@ static inline void hal_write_address_32_mb(struct hal_soc *hal_soc, offset = addr - hal_soc->dev_base_addr; - if (qdf_unlikely(wr_confirm)) hal_write32_mb_confirm(hal_soc, offset, value); else hal_write32_mb(hal_soc, offset, value); } +#endif -#if defined(FEATURE_HAL_DELAYED_REG_WRITE) + +#ifdef DP_HAL_MULTIWINDOW_DIRECT_ACCESS +static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc, + struct hal_srng *srng, + void __iomem *addr, + uint32_t value) +{ + qdf_iowrite32(addr, value); +} +#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, @@ -367,7 +449,8 @@ static inline void hal_srng_write_address_32_mb(struct hal_soc *hal_soc, } #endif -#ifndef QCA_WIFI_QCA6390 +#if !defined(QCA_WIFI_QCA6390) && !defined(QCA_WIFI_QCA6490) && \ + !defined(QCA_WIFI_QCA6750) /** * hal_read32_mb() - Access registers to read configuration * @hal_soc: hal soc handle @@ -393,10 +476,14 @@ static inline uint32_t hal_read32_mb(struct hal_soc *hal_soc, uint32_t offset) { uint32_t ret; unsigned long flags; + qdf_iomem_t new_addr; if (!hal_soc->use_register_windowing || offset < MAX_UNWINDOWED_ADDRESS) { return qdf_ioread32(hal_soc->dev_base_addr + offset); + } else if (hal_soc->static_window_map) { + new_addr = hal_get_window_address(hal_soc, hal_soc->dev_base_addr + offset); + return qdf_ioread32(new_addr); } hal_lock_reg_access(hal_soc, &flags); @@ -407,59 +494,225 @@ static inline uint32_t hal_read32_mb(struct hal_soc *hal_soc, uint32_t offset) return ret; } - -/** - * hal_read_address_32_mb() - Read 32-bit value from the register - * @soc: soc handle - * @addr: register address to read - * - * Return: 32-bit value - */ -static inline uint32_t hal_read_address_32_mb(struct hal_soc *soc, - void __iomem *addr) -{ - uint32_t offset; - uint32_t ret; - - if (!soc->use_register_windowing) - return qdf_ioread32(addr); - - offset = addr - soc->dev_base_addr; - ret = hal_read32_mb(soc, offset); - return ret; -} #else -static inline uint32_t hal_read32_mb(struct hal_soc *hal_soc, uint32_t offset) +static +uint32_t hal_read32_mb(struct hal_soc *hal_soc, uint32_t offset) { uint32_t ret; unsigned long flags; - if ((offset > MAPPED_REF_OFF) && - hal_force_wake_request(hal_soc)) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: Wake up request failed\n", __func__); - return -EINVAL; + /* Region < BAR + 4K can be directly accessed */ + if (offset < MAPPED_REF_OFF) + return qdf_ioread32(hal_soc->dev_base_addr + offset); + + if ((!hal_soc->init_phase) && + hif_force_wake_request(hal_soc->hif_handle)) { + hal_err("Wake up request failed"); + qdf_check_state_before_panic(); + return 0; } if (!hal_soc->use_register_windowing || offset < MAX_UNWINDOWED_ADDRESS) { - return qdf_ioread32(hal_soc->dev_base_addr + offset); + ret = qdf_ioread32(hal_soc->dev_base_addr + offset); + } else { + hal_lock_reg_access(hal_soc, &flags); + hal_select_window_confirm(hal_soc, offset); + ret = qdf_ioread32(hal_soc->dev_base_addr + WINDOW_START + + (offset & WINDOW_RANGE_MASK)); + hal_unlock_reg_access(hal_soc, &flags); } - hal_lock_reg_access(hal_soc, &flags); - hal_select_window_confirm(hal_soc, offset); - ret = qdf_ioread32(hal_soc->dev_base_addr + WINDOW_START + - (offset & WINDOW_RANGE_MASK)); - hal_unlock_reg_access(hal_soc, &flags); + if ((!hal_soc->init_phase) && + hif_force_wake_release(hal_soc->hif_handle)) { + hal_err("Wake up release failed"); + qdf_check_state_before_panic(); + return 0; + } + + return ret; +} +#endif - if ((offset > MAPPED_REF_OFF) && - hal_force_wake_release(hal_soc)) - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: Wake up release failed\n", __func__); +#ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE +/* To check shadow config index range between 0..31 */ +#define HAL_SHADOW_REG_INDEX_LOW 32 +/* To check shadow config index range between 32..39 */ +#define HAL_SHADOW_REG_INDEX_HIGH 40 +/* Dirty bit reg offsets corresponding to shadow config index */ +#define HAL_SHADOW_REG_DIRTY_BIT_DATA_LOW_OFFSET 0x30C8 +#define HAL_SHADOW_REG_DIRTY_BIT_DATA_HIGH_OFFSET 0x30C4 +/* PCIE_PCIE_TOP base addr offset */ +#define HAL_PCIE_PCIE_TOP_WRAPPER 0x01E00000 +/* Max retry attempts to read the dirty bit reg */ +#ifdef HAL_CONFIG_SLUB_DEBUG_ON +#define HAL_SHADOW_DIRTY_BIT_POLL_MAX 10000 +#else +#define HAL_SHADOW_DIRTY_BIT_POLL_MAX 2000 +#endif +/* Delay in usecs for polling dirty bit reg */ +#define HAL_SHADOW_DIRTY_BIT_POLL_DELAY 5 + +/** + * hal_poll_dirty_bit_reg() - Poll dirty register bit to confirm + * write was successful + * @hal_soc: hal soc handle + * @shadow_config_index: index of shadow reg used to confirm + * write + * + * Return: QDF_STATUS_SUCCESS on success + */ +static inline QDF_STATUS hal_poll_dirty_bit_reg(struct hal_soc *hal, + int shadow_config_index) +{ + uint32_t read_value = 0; + int retry_cnt = 0; + uint32_t reg_offset = 0; + + if (shadow_config_index > 0 && + shadow_config_index < HAL_SHADOW_REG_INDEX_LOW) { + reg_offset = + HAL_SHADOW_REG_DIRTY_BIT_DATA_LOW_OFFSET; + } else if (shadow_config_index >= HAL_SHADOW_REG_INDEX_LOW && + shadow_config_index < HAL_SHADOW_REG_INDEX_HIGH) { + reg_offset = + HAL_SHADOW_REG_DIRTY_BIT_DATA_HIGH_OFFSET; + } else { + hal_err("Invalid shadow_config_index = %d", + shadow_config_index); + return QDF_STATUS_E_INVAL; + } + while (retry_cnt < HAL_SHADOW_DIRTY_BIT_POLL_MAX) { + read_value = hal_read32_mb( + hal, HAL_PCIE_PCIE_TOP_WRAPPER + reg_offset); + /* Check if dirty bit corresponding to shadow_index is set */ + if (read_value & BIT(shadow_config_index)) { + /* Dirty reg bit not reset */ + qdf_udelay(HAL_SHADOW_DIRTY_BIT_POLL_DELAY); + retry_cnt++; + } else { + hal_debug("Shadow write: offset 0x%x read val 0x%x", + reg_offset, read_value); + return QDF_STATUS_SUCCESS; + } + } + return QDF_STATUS_E_TIMEOUT; +} +/** + * hal_write32_mb_shadow_confirm() - write to shadow reg and + * poll dirty register bit to confirm write + * @hal_soc: hal soc handle + * @reg_offset: target reg offset address from BAR + * @value: value to write + * + * Return: QDF_STATUS_SUCCESS on success + */ +static inline QDF_STATUS hal_write32_mb_shadow_confirm( + struct hal_soc *hal, + uint32_t reg_offset, + uint32_t value) +{ + int i; + QDF_STATUS ret; + uint32_t shadow_reg_offset; + uint32_t read_value; + int shadow_config_index; + bool is_reg_offset_present = false; + + for (i = 0; i < MAX_GENERIC_SHADOW_REG; i++) { + /* Found the shadow config for the reg_offset */ + struct shadow_reg_config *hal_shadow_reg_list = + &hal->list_shadow_reg_config[i]; + if (hal_shadow_reg_list->target_register == + reg_offset) { + shadow_config_index = + hal_shadow_reg_list->shadow_config_index; + shadow_reg_offset = + SHADOW_REGISTER(shadow_config_index); + hal_write32_mb_confirm( + hal, shadow_reg_offset, value); + is_reg_offset_present = true; + break; + } + ret = QDF_STATUS_E_FAILURE; + } + if (is_reg_offset_present) { + ret = hal_poll_dirty_bit_reg(hal, shadow_config_index); + read_value = hal_read32_mb(hal, reg_offset); + hal_info("Shadow retry:reg 0x%x val 0x%x readval 0x%x ret %d", + reg_offset, value, read_value, ret); + if (QDF_IS_STATUS_ERROR(ret)) { + HAL_STATS_INC(hal, shadow_reg_write_fail, 1); + return ret; + } + HAL_STATS_INC(hal, shadow_reg_write_succ, 1); + } return ret; } +#else /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */ + +static inline QDF_STATUS hal_write32_mb_shadow_confirm( + struct hal_soc *hal_soc, + uint32_t offset, + uint32_t value) +{ + return QDF_STATUS_SUCCESS; +} + +#endif /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */ + +/* Max times allowed for register writing retry */ +#define HAL_REG_WRITE_RETRY_MAX 5 +/* Delay milliseconds for each time retry */ +#define HAL_REG_WRITE_RETRY_DELAY 1 + +/** + * hal_write32_mb_confirm_retry() - write register with confirming and + do retry/recovery if writing failed + * @hal_soc: hal soc handle + * @offset: offset address from the BAR + * @value: value to write + * @recovery: is recovery needed or not. + * + * Write the register value with confirming and read it back, if + * read back value is not as expected, do retry for writing, if + * retry hit max times allowed but still fail, check if recovery + * needed. + * + * Return: None + */ +static inline void hal_write32_mb_confirm_retry(struct hal_soc *hal_soc, + uint32_t offset, + uint32_t value, + bool recovery) +{ + uint8_t retry_cnt = 0; + uint32_t read_value; + QDF_STATUS ret; + + while (retry_cnt <= HAL_REG_WRITE_RETRY_MAX) { + hal_write32_mb_confirm(hal_soc, offset, value); + read_value = hal_read32_mb(hal_soc, offset); + if (qdf_likely(read_value == value)) + break; + + /* write failed, do retry */ + hal_warn("Retry reg offset 0x%x, value 0x%x, read value 0x%x", + offset, value, read_value); + qdf_mdelay(HAL_REG_WRITE_RETRY_DELAY); + retry_cnt++; + } + + if (retry_cnt > HAL_REG_WRITE_RETRY_MAX) { + ret = hal_write32_mb_shadow_confirm(hal_soc, offset, value); + if (QDF_IS_STATUS_ERROR(ret) && recovery) + qdf_trigger_self_recovery( + NULL, QDF_HAL_REG_WRITE_FAILURE); + } +} + #ifdef FEATURE_HAL_DELAYED_REG_WRITE /** * hal_dump_reg_write_srng_stats() - dump SRNG reg write stats @@ -467,7 +720,7 @@ static inline uint32_t hal_read32_mb(struct hal_soc *hal_soc, uint32_t offset) * * Return: none */ -void hal_dump_reg_write_srng_stats(struct hal_soc *hal_soc_hdl); +void hal_dump_reg_write_srng_stats(hal_soc_handle_t hal_soc_hdl); /** * hal_dump_reg_write_stats() - dump reg write stats @@ -475,7 +728,7 @@ void hal_dump_reg_write_srng_stats(struct hal_soc *hal_soc_hdl); * * Return: none */ -void hal_dump_reg_write_stats(struct hal_soc *hal_soc_hdl); +void hal_dump_reg_write_stats(hal_soc_handle_t hal_soc_hdl); /** * hal_get_reg_write_pending_work() - get the number of entries @@ -487,11 +740,11 @@ void hal_dump_reg_write_stats(struct hal_soc *hal_soc_hdl); int hal_get_reg_write_pending_work(void *hal_soc); #else -static inline void hal_dump_reg_write_srng_stats(struct hal_soc *hal_soc_hdl) +static inline void hal_dump_reg_write_srng_stats(hal_soc_handle_t hal_soc_hdl) { } -static inline void hal_dump_reg_write_stats(struct hal_soc *hal_soc_hdl) +static inline void hal_dump_reg_write_stats(hal_soc_handle_t hal_soc_hdl) { } @@ -509,21 +762,25 @@ static inline int hal_get_reg_write_pending_work(void *hal_soc) * Return: 32-bit value */ static inline -uint32_t hal_read_address_32_mb(struct hal_soc *soc, void __iomem *addr) +uint32_t hal_read_address_32_mb(struct hal_soc *soc, + qdf_iomem_t addr) { uint32_t offset; uint32_t ret; + qdf_iomem_t new_addr; if (!soc->use_register_windowing) return qdf_ioread32(addr); offset = addr - soc->dev_base_addr; + if (soc->static_window_map) { + new_addr = hal_get_window_address(soc, addr); + return qdf_ioread32(new_addr); + } + ret = hal_read32_mb(soc, offset); return ret; } -#endif - -#include "hif_io32.h" /** * hal_attach - Initialize HAL layer @@ -536,7 +793,7 @@ uint32_t hal_read_address_32_mb(struct hal_soc *soc, void __iomem *addr) * This function should be called as part of HIF initialization (for accessing * copy engines). DP layer will get hal_soc handle using hif_get_hal_handle() */ -extern void *hal_attach(void *hif_handle, qdf_device_t qdf_dev); +void *hal_attach(struct hif_opaque_softc *hif_handle, qdf_device_t qdf_dev); /** * hal_detach - Detach HAL layer @@ -585,10 +842,34 @@ enum hal_ring_type { #define HAL_SRNG_MSI_INTR 0x00020000 #define HAL_SRNG_CACHED_DESC 0x00040000 +#ifdef QCA_WIFI_QCA6490 +#define HAL_SRNG_PREFETCH_TIMER 1 +#else +#define HAL_SRNG_PREFETCH_TIMER 0 +#endif + #define PN_SIZE_24 0 #define PN_SIZE_48 1 #define PN_SIZE_128 2 +#ifdef FORCE_WAKE +/** + * hal_set_init_phase() - Indicate initialization of + * datapath rings + * @soc: hal_soc handle + * @init_phase: flag to indicate datapath rings + * initialization status + * + * Return: None + */ +void hal_set_init_phase(hal_soc_handle_t soc, bool init_phase); +#else +static inline +void hal_set_init_phase(hal_soc_handle_t soc, bool init_phase) +{ +} +#endif /* FORCE_WAKE */ + /** * hal_srng_get_entrysize - Returns size of ring entry in bytes. Should be * used by callers for calculating the size of memory to be allocated before @@ -672,14 +953,17 @@ struct hal_srng_params { uint32_t entry_size; /* hw register base address */ void *hwreg_base[MAX_SRNG_REG_GROUPS]; + /* prefetch timer config - in micro seconds */ + uint32_t prefetch_timer; }; -/* hal_construct_shadow_config() - initialize the shadow registers for dp rings +/* hal_construct_srng_shadow_regs() - initialize the shadow + * registers for srngs * @hal_soc: hal handle * * Return: QDF_STATUS_OK on success */ -extern QDF_STATUS hal_construct_shadow_config(void *hal_soc); +QDF_STATUS hal_construct_srng_shadow_regs(void *hal_soc); /* hal_set_one_shadow_config() - add a config for the specified ring * @hal_soc: hal handle @@ -696,8 +980,8 @@ extern QDF_STATUS hal_construct_shadow_config(void *hal_soc); * * Return: QDF_STATUS_OK on success */ -extern QDF_STATUS hal_set_one_shadow_config(void *hal_soc, int ring_type, - int ring_num); +QDF_STATUS hal_set_one_shadow_config(void *hal_soc, int ring_type, + int ring_num); /** * hal_get_shadow_config() - retrieve the config table * @hal_soc: hal handle @@ -749,54 +1033,83 @@ extern void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num, DESTINATION_RING_ ## _OFFSET ## _SHFT)) /* - * currently this macro only works for IX0 since all the rings we are remapping - * can be remapped from HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0 - */ -#define HAL_REO_REMAP_VAL(_ORIGINAL_DEST, _NEW_DEST) \ - HAL_REO_REMAP_VAL_(_ORIGINAL_DEST, _NEW_DEST) -/* allow the destination macros to be expanded */ -#define HAL_REO_REMAP_VAL_(_ORIGINAL_DEST, _NEW_DEST) \ - (_NEW_DEST << \ + * Macro to access HWIO_REO_R0_ERROR_DESTINATION_RING_CTRL_IX_1 + * to map destination to rings + */ +#define HAL_REO_ERR_REMAP_IX1(_VALUE, _OFFSET) \ + ((_VALUE) << \ + (HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_1_ERROR_ ## \ + DESTINATION_RING_ ## _OFFSET ## _SHFT)) + +/* + * Macro to access HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0 + * to map destination to rings + */ +#define HAL_REO_REMAP_IX0(_VALUE, _OFFSET) \ + ((_VALUE) << \ (HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0_DEST_RING_MAPPING_ ## \ - _ORIGINAL_DEST ## _SHFT)) + _OFFSET ## _SHFT)) + +/* + * Macro to access HWIO_REO_R0_DESTINATION_RING_CTRL_IX_1 + * to map destination to rings + */ +#define HAL_REO_REMAP_IX2(_VALUE, _OFFSET) \ + ((_VALUE) << \ + (HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_DEST_RING_MAPPING_ ## \ + _OFFSET ## _SHFT)) + +/* + * Macro to access HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3 + * to map destination to rings + */ +#define HAL_REO_REMAP_IX3(_VALUE, _OFFSET) \ + ((_VALUE) << \ + (HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_DEST_RING_MAPPING_ ## \ + _OFFSET ## _SHFT)) /** * hal_reo_read_write_ctrl_ix - Read or write REO_DESTINATION_RING_CTRL_IX - * @hal: HAL SOC handle + * @hal_soc_hdl: HAL SOC handle * @read: boolean value to indicate if read or write * @ix0: pointer to store IX0 reg value * @ix1: pointer to store IX1 reg value * @ix2: pointer to store IX2 reg value * @ix3: pointer to store IX3 reg value */ -extern void hal_reo_read_write_ctrl_ix(struct hal_soc *hal, bool read, - uint32_t *ix0, uint32_t *ix1, - uint32_t *ix2, uint32_t *ix3); +void hal_reo_read_write_ctrl_ix(hal_soc_handle_t hal_soc_hdl, bool read, + uint32_t *ix0, uint32_t *ix1, + uint32_t *ix2, uint32_t *ix3); /** - * hal_srng_set_hp_paddr() - Set physical address to dest SRNG head pointer + * hal_srng_set_hp_paddr_confirm() - Set physical address to dest SRNG head + * pointer and confirm that write went through by reading back the value * @sring: sring pointer * @paddr: physical address */ -extern void hal_srng_dst_set_hp_paddr(struct hal_srng *sring, uint64_t paddr); +extern void hal_srng_dst_set_hp_paddr_confirm(struct hal_srng *sring, + uint64_t paddr); /** * hal_srng_dst_init_hp() - Initilaize head pointer with cached head pointer + * @hal_soc: hal_soc handle * @srng: sring pointer * @vaddr: virtual address */ -extern void hal_srng_dst_init_hp(struct hal_srng *srng, uint32_t *vaddr); +void hal_srng_dst_init_hp(struct hal_soc_handle *hal_soc, + struct hal_srng *srng, + uint32_t *vaddr); /** * hal_srng_cleanup - Deinitialize HW SRNG ring. * @hal_soc: Opaque HAL SOC handle * @hal_srng: Opaque HAL SRNG pointer */ -extern void hal_srng_cleanup(void *hal_soc, void *hal_srng); +void hal_srng_cleanup(void *hal_soc, hal_ring_handle_t hal_ring_hdl); -static inline bool hal_srng_initialized(void *hal_ring) +static inline bool hal_srng_initialized(hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; return !!srng->initialized; } @@ -804,16 +1117,17 @@ static inline bool hal_srng_initialized(void *hal_ring) /** * hal_srng_dst_peek - Check if there are any entries in the ring (peek) * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Destination ring pointer + * @hal_ring_hdl: Destination ring pointer * * Caller takes responsibility for any locking needs. * * Return: Opaque pointer for next ring entry; NULL on failire */ static inline -void *hal_srng_dst_peek(void *hal_soc, void *hal_ring) +void *hal_srng_dst_peek(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp) return (void *)(&srng->ring_base_vaddr[srng->u.dst_ring.tp]); @@ -826,14 +1140,16 @@ void *hal_srng_dst_peek(void *hal_soc, void *hal_ring) * hal_srng_access_start if locked access is required * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Ring pointer (Source or Destination ring) + * @hal_ring_hdl: Ring pointer (Source or Destination ring) * * Return: 0 on success; error on failire */ -static inline int hal_srng_access_start_unlocked(void *hal_soc, void *hal_ring) +static inline int +hal_srng_access_start_unlocked(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; - struct hal_soc *soc = (struct hal_soc *)hal_soc; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + struct hal_soc *soc = (struct hal_soc *)hal_soc_hdl; uint32_t *desc; if (srng->ring_dir == HAL_SRNG_SRC_RING) @@ -844,7 +1160,7 @@ static inline int hal_srng_access_start_unlocked(void *hal_soc, void *hal_ring) *(volatile uint32_t *)(srng->u.dst_ring.hp_addr); if (srng->flags & HAL_SRNG_CACHED_DESC) { - desc = hal_srng_dst_peek(hal_soc, hal_ring); + desc = hal_srng_dst_peek(hal_soc_hdl, hal_ring_hdl); if (qdf_likely(desc)) { qdf_mem_dma_cache_sync(soc->qdf_dev, qdf_mem_virt_to_phys @@ -864,22 +1180,23 @@ static inline int hal_srng_access_start_unlocked(void *hal_soc, void *hal_ring) * hal_srng_access_start - Start (locked) ring access * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Ring pointer (Source or Destination ring) + * @hal_ring_hdl: Ring pointer (Source or Destination ring) * * Return: 0 on success; error on failire */ -static inline int hal_srng_access_start(void *hal_soc, void *hal_ring) +static inline int hal_srng_access_start(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; - if (qdf_unlikely(!hal_ring)) { + if (qdf_unlikely(!hal_ring_hdl)) { qdf_print("Error: Invalid hal_ring\n"); return -EINVAL; } SRNG_LOCK(&(srng->lock)); - return hal_srng_access_start_unlocked(hal_soc, hal_ring); + return hal_srng_access_start_unlocked(hal_soc_hdl, hal_ring_hdl); } /** @@ -887,13 +1204,15 @@ static inline int hal_srng_access_start(void *hal_soc, void *hal_ring) * cached tail pointer * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Destination ring pointer + * @hal_ring_hdl: Destination ring pointer * * Return: Opaque pointer for next ring entry; NULL on failire */ -static inline void *hal_srng_dst_get_next(void *hal_soc, void *hal_ring) +static inline +void *hal_srng_dst_get_next(void *hal_soc, + hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; struct hal_soc *soc = (struct hal_soc *)hal_soc; uint32_t *desc; uint32_t *desc_next; @@ -932,13 +1251,15 @@ static inline void *hal_srng_dst_get_next(void *hal_soc, void *hal_ring) * cached head pointer * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Destination ring pointer + * @hal_ring_hdl: Destination ring pointer * * Return: Opaque pointer for next ring entry; NULL on failire */ -static inline void *hal_srng_dst_get_next_hp(void *hal_soc, void *hal_ring) +static inline void * +hal_srng_dst_get_next_hp(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; uint32_t *desc; /* TODO: Using % is expensive, but we have to do this since * size of some SRNG rings is not power of 2 (due to descriptor @@ -961,7 +1282,7 @@ static inline void *hal_srng_dst_get_next_hp(void *hal_soc, void *hal_ring) /** * hal_srng_dst_peek_sync - Check if there are any entries in the ring (peek) * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Destination ring pointer + * @hal_ring_hdl: Destination ring pointer * * Sync cached head pointer with HW. * Caller takes responsibility for any locking needs. @@ -969,9 +1290,10 @@ static inline void *hal_srng_dst_get_next_hp(void *hal_soc, void *hal_ring) * Return: Opaque pointer for next ring entry; NULL on failire */ static inline -void *hal_srng_dst_peek_sync(void *hal_soc, void *hal_ring) +void *hal_srng_dst_peek_sync(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; srng->u.dst_ring.cached_hp = *(volatile uint32_t *)(srng->u.dst_ring.hp_addr); @@ -985,7 +1307,7 @@ void *hal_srng_dst_peek_sync(void *hal_soc, void *hal_ring) /** * hal_srng_dst_peek_sync_locked - Peek for any entries in the ring * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Destination ring pointer + * @hal_ring_hdl: Destination ring pointer * * Sync cached head pointer with HW. * This function takes up SRNG_LOCK. Should not be called with SRNG lock held. @@ -993,19 +1315,20 @@ void *hal_srng_dst_peek_sync(void *hal_soc, void *hal_ring) * Return: Opaque pointer for next ring entry; NULL on failire */ static inline -void *hal_srng_dst_peek_sync_locked(void *hal_soc, void *hal_ring) +void *hal_srng_dst_peek_sync_locked(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; void *ring_desc_ptr = NULL; - if (qdf_unlikely(!hal_ring)) { + if (qdf_unlikely(!hal_ring_hdl)) { qdf_print("Error: Invalid hal_ring\n"); return NULL; } SRNG_LOCK(&srng->lock); - ring_desc_ptr = hal_srng_dst_peek_sync(hal_soc, hal_ring); + ring_desc_ptr = hal_srng_dst_peek_sync(hal_soc_hdl, hal_ring_hdl); SRNG_UNLOCK(&srng->lock); @@ -1017,14 +1340,16 @@ void *hal_srng_dst_peek_sync_locked(void *hal_soc, void *hal_ring) * by SW) in destination ring * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Destination ring pointer + * @hal_ring_hdl: Destination ring pointer * @sync_hw_ptr: Sync cached head pointer with HW * */ -static inline uint32_t hal_srng_dst_num_valid(void *hal_soc, void *hal_ring, - int sync_hw_ptr) +static inline +uint32_t hal_srng_dst_num_valid(void *hal_soc, + hal_ring_handle_t hal_ring_hdl, + int sync_hw_ptr) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; uint32_t hp; uint32_t tp = srng->u.dst_ring.tp; @@ -1054,8 +1379,8 @@ static inline uint32_t hal_srng_dst_num_valid(void *hal_soc, void *hal_ring, * Return: Number of valid destination entries */ static inline uint32_t -hal_srng_dst_num_valid_locked(void *hal_soc, - void *hal_ring_hdl, +hal_srng_dst_num_valid_locked(hal_soc_handle_t hal_soc, + hal_ring_handle_t hal_ring_hdl, int sync_hw_ptr) { uint32_t num_valid; @@ -1076,13 +1401,14 @@ hal_srng_dst_num_valid_locked(void *hal_soc, * hal_srng_src_get_next_reaped when this function is used for reaping. * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer * * Return: Opaque pointer for next ring entry; NULL on failire */ -static inline void *hal_srng_src_reap_next(void *hal_soc, void *hal_ring) +static inline void * +hal_srng_src_reap_next(void *hal_soc, hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; uint32_t *desc; /* TODO: Using % is expensive, but we have to do this since @@ -1109,13 +1435,14 @@ static inline void *hal_srng_src_reap_next(void *hal_soc, void *hal_ring) * the ring * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer * * Return: Opaque pointer for next (reaped) source ring entry; NULL on failire */ -static inline void *hal_srng_src_get_next_reaped(void *hal_soc, void *hal_ring) +static inline void * +hal_srng_src_get_next_reaped(void *hal_soc, hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; uint32_t *desc; if (srng->u.src_ring.hp != srng->u.src_ring.reap_hp) { @@ -1135,13 +1462,14 @@ static inline void *hal_srng_src_get_next_reaped(void *hal_soc, void *hal_ring) * associated with ring entries which are pending reap. * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer * * Return: Opaque pointer for next ring entry; NULL on failire */ -static inline void *hal_srng_src_pending_reap_next(void *hal_soc, void *hal_ring) +static inline void * +hal_srng_src_pending_reap_next(void *hal_soc, hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; uint32_t *desc; uint32_t next_reap_hp = (srng->u.src_ring.reap_hp + srng->entry_size) % @@ -1160,13 +1488,14 @@ static inline void *hal_srng_src_pending_reap_next(void *hal_soc, void *hal_ring * hal_srng_src_done_val - * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer * * Return: Opaque pointer for next ring entry; NULL on failire */ -static inline uint32_t hal_srng_src_done_val(void *hal_soc, void *hal_ring) +static inline uint32_t +hal_srng_src_done_val(void *hal_soc, hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; /* TODO: Using % is expensive, but we have to do this since * size of some SRNG rings is not power of 2 (due to descriptor * sizes). Need to create separate API for rings used @@ -1189,14 +1518,14 @@ static inline uint32_t hal_srng_src_done_val(void *hal_soc, void *hal_ring) /** * hal_get_entrysize_from_srng() - Retrieve ring entry size - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer * * Return: uint8_t */ static inline -uint8_t hal_get_entrysize_from_srng(void *hal_ring) +uint8_t hal_get_entrysize_from_srng(hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; return srng->entry_size; } @@ -1204,16 +1533,17 @@ uint8_t hal_get_entrysize_from_srng(void *hal_ring) /** * hal_get_sw_hptp - Get SW head and tail pointer location for any ring * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer * @tailp: Tail Pointer * @headp: Head Pointer * * Return: Update tail pointer and head pointer in arguments. */ -static inline void hal_get_sw_hptp(void *hal_soc, void *hal_ring, - uint32_t *tailp, uint32_t *headp) +static inline +void hal_get_sw_hptp(void *hal_soc, hal_ring_handle_t hal_ring_hdl, + uint32_t *tailp, uint32_t *headp) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; if (srng->ring_dir == HAL_SRNG_SRC_RING) { *headp = srng->u.src_ring.hp; @@ -1228,13 +1558,15 @@ static inline void hal_get_sw_hptp(void *hal_soc, void *hal_ring, * hal_srng_src_get_next - Get next entry from a source ring and move cached tail pointer * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer * * Return: Opaque pointer for next ring entry; NULL on failire */ -static inline void *hal_srng_src_get_next(void *hal_soc, void *hal_ring) +static inline +void *hal_srng_src_get_next(void *hal_soc, + hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; uint32_t *desc; /* TODO: Using % is expensive, but we have to do this since * size of some SRNG rings is not power of 2 (due to descriptor @@ -1265,13 +1597,15 @@ static inline void *hal_srng_src_get_next(void *hal_soc, void *hal_ring) * hal_srng_src_get_next should be called subsequently to move the head pointer * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer * * Return: Opaque pointer for next ring entry; NULL on failire */ -static inline void *hal_srng_src_peek(void *hal_soc, void *hal_ring) +static inline +void *hal_srng_src_peek(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; uint32_t *desc; /* TODO: Using % is expensive, but we have to do this since @@ -1293,14 +1627,15 @@ static inline void *hal_srng_src_peek(void *hal_soc, void *hal_ring) * hal_srng_src_num_avail - Returns number of available entries in src ring * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer * @sync_hw_ptr: Sync cached tail pointer with HW * */ -static inline uint32_t hal_srng_src_num_avail(void *hal_soc, - void *hal_ring, int sync_hw_ptr) +static inline uint32_t +hal_srng_src_num_avail(void *hal_soc, + hal_ring_handle_t hal_ring_hdl, int sync_hw_ptr) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; uint32_t tp; uint32_t hp = srng->u.src_ring.hp; @@ -1324,13 +1659,14 @@ static inline uint32_t hal_srng_src_num_avail(void *hal_soc, * access * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Ring pointer (Source or Destination ring) + * @hal_ring_hdl: Ring pointer (Source or Destination ring) * * Return: 0 on success; error on failire */ -static inline void hal_srng_access_end_unlocked(void *hal_soc, void *hal_ring) +static inline void +hal_srng_access_end_unlocked(void *hal_soc, hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; /* TODO: See if we need a write memory barrier here */ if (srng->flags & HAL_SRNG_LMAC_RING) { @@ -1362,20 +1698,21 @@ static inline void hal_srng_access_end_unlocked(void *hal_soc, void *hal_ring) * This should be used only if hal_srng_access_start to start ring access * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Ring pointer (Source or Destination ring) + * @hal_ring_hdl: Ring pointer (Source or Destination ring) * * Return: 0 on success; error on failire */ -static inline void hal_srng_access_end(void *hal_soc, void *hal_ring) +static inline void +hal_srng_access_end(void *hal_soc, hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; - if (qdf_unlikely(!hal_ring)) { + if (qdf_unlikely(!hal_ring_hdl)) { qdf_print("Error: Invalid hal_ring\n"); return; } - hal_srng_access_end_unlocked(hal_soc, hal_ring); + hal_srng_access_end_unlocked(hal_soc, hal_ring_hdl); SRNG_UNLOCK(&(srng->lock)); } @@ -1385,13 +1722,14 @@ static inline void hal_srng_access_end(void *hal_soc, void *hal_ring) * and should be used only while reaping SRC ring completions * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Ring pointer (Source or Destination ring) + * @hal_ring_hdl: Ring pointer (Source or Destination ring) * * Return: 0 on success; error on failire */ -static inline void hal_srng_access_end_reap(void *hal_soc, void *hal_ring) +static inline void +hal_srng_access_end_reap(void *hal_soc, hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; SRNG_UNLOCK(&(srng->lock)); } @@ -1425,7 +1763,8 @@ static inline void hal_srng_access_end_reap(void *hal_soc, void *hal_ring) * @hal_soc: Opaque HAL SOC handle * */ -static inline uint32_t hal_idle_list_scatter_buf_size(void *hal_soc) +static inline +uint32_t hal_idle_list_scatter_buf_size(hal_soc_handle_t hal_soc_hdl) { return WBM_IDLE_SCATTER_BUF_SIZE; } @@ -1436,8 +1775,10 @@ static inline uint32_t hal_idle_list_scatter_buf_size(void *hal_soc) * @hal_soc: Opaque HAL SOC handle * */ -static inline uint32_t hal_get_link_desc_size(struct hal_soc *hal_soc) +static inline uint32_t hal_get_link_desc_size(hal_soc_handle_t hal_soc_hdl) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + if (!hal_soc || !hal_soc->ops) { qdf_print("Error: Invalid ops\n"); QDF_BUG(0); @@ -1458,7 +1799,8 @@ static inline uint32_t hal_get_link_desc_size(struct hal_soc *hal_soc) * @hal_soc: Opaque HAL SOC handle * */ -static inline uint32_t hal_get_link_desc_align(void *hal_soc) +static inline +uint32_t hal_get_link_desc_align(hal_soc_handle_t hal_soc_hdl) { return LINK_DESC_ALIGN; } @@ -1469,7 +1811,8 @@ static inline uint32_t hal_get_link_desc_align(void *hal_soc) * @hal_soc: Opaque HAL SOC handle * */ -static inline uint32_t hal_num_mpdus_per_link_desc(void *hal_soc) +static inline +uint32_t hal_num_mpdus_per_link_desc(hal_soc_handle_t hal_soc_hdl) { return NUM_MPDUS_PER_LINK_DESC; } @@ -1480,7 +1823,8 @@ static inline uint32_t hal_num_mpdus_per_link_desc(void *hal_soc) * @hal_soc: Opaque HAL SOC handle * */ -static inline uint32_t hal_num_msdus_per_link_desc(void *hal_soc) +static inline +uint32_t hal_num_msdus_per_link_desc(hal_soc_handle_t hal_soc_hdl) { return NUM_MSDUS_PER_LINK_DESC; } @@ -1492,7 +1836,8 @@ static inline uint32_t hal_num_msdus_per_link_desc(void *hal_soc) * @hal_soc: Opaque HAL SOC handle * */ -static inline uint32_t hal_num_mpdu_links_per_queue_desc(void *hal_soc) +static inline +uint32_t hal_num_mpdu_links_per_queue_desc(hal_soc_handle_t hal_soc_hdl) { return NUM_MPDU_LINKS_PER_QUEUE_DESC; } @@ -1505,11 +1850,12 @@ static inline uint32_t hal_num_mpdu_links_per_queue_desc(void *hal_soc) * @scatter_buf_size: Size of scatter buffer * */ -static inline uint32_t hal_idle_scatter_buf_num_entries(void *hal_soc, - uint32_t scatter_buf_size) +static inline +uint32_t hal_idle_scatter_buf_num_entries(hal_soc_handle_t hal_soc_hdl, + uint32_t scatter_buf_size) { return (scatter_buf_size - WBM_IDLE_SCATTER_BUF_NEXT_PTR_SIZE) / - hal_srng_get_entrysize(hal_soc, WBM_IDLE_LINK); + hal_srng_get_entrysize(hal_soc_hdl, WBM_IDLE_LINK); } /** @@ -1521,8 +1867,10 @@ static inline uint32_t hal_idle_scatter_buf_num_entries(void *hal_soc, * @scatter_buf_size: Size of scatter buffer * */ -static inline uint32_t hal_idle_list_num_scatter_bufs(void *hal_soc, - uint32_t total_mem, uint32_t scatter_buf_size) +static inline +uint32_t hal_idle_list_num_scatter_bufs(hal_soc_handle_t hal_soc_hdl, + uint32_t total_mem, + uint32_t scatter_buf_size) { uint8_t rem = (total_mem % (scatter_buf_size - WBM_IDLE_SCATTER_BUF_NEXT_PTR_SIZE)) ? 1 : 0; @@ -1533,21 +1881,6 @@ static inline uint32_t hal_idle_list_num_scatter_bufs(void *hal_soc, return num_scatter_bufs; } -/* REO parameters to be passed to hal_reo_setup */ -struct hal_reo_params { - /** rx hash steering enabled or disabled */ - bool rx_hash_enabled; - /** reo remap 1 register */ - uint32_t remap1; - /** reo remap 2 register */ - uint32_t remap2; - /** fragment destination ring */ - uint8_t frag_dst_ring; - /** padding */ - uint8_t padding[3]; -}; - - enum hal_pn_type { HAL_PN_NONE, HAL_PN_WPA, @@ -1564,7 +1897,8 @@ enum hal_pn_type { * @hal_soc: Opaque HAL SOC handle * */ -static inline uint32_t hal_get_reo_qdesc_align(void *hal_soc) +static inline +uint32_t hal_get_reo_qdesc_align(hal_soc_handle_t hal_soc_hdl) { return REO_QUEUE_DESC_ALIGN; } @@ -1580,20 +1914,24 @@ static inline uint32_t hal_get_reo_qdesc_align(void *hal_soc) * @pn_type: PN type (one of the types defined in 'enum hal_pn_type') * */ -extern void hal_reo_qdesc_setup(void *hal_soc, int tid, uint32_t ba_window_size, - uint32_t start_seq, void *hw_qdesc_vaddr, qdf_dma_addr_t hw_qdesc_paddr, - int pn_type); +void hal_reo_qdesc_setup(hal_soc_handle_t hal_soc_hdl, + int tid, uint32_t ba_window_size, + uint32_t start_seq, void *hw_qdesc_vaddr, + qdf_dma_addr_t hw_qdesc_paddr, + int pn_type); /** * hal_srng_get_hp_addr - Get head pointer physical address * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Ring pointer (Source or Destination ring) + * @hal_ring_hdl: Ring pointer (Source or Destination ring) * */ -static inline qdf_dma_addr_t hal_srng_get_hp_addr(void *hal_soc, void *hal_ring) +static inline qdf_dma_addr_t +hal_srng_get_hp_addr(void *hal_soc, + hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; struct hal_soc *hal = (struct hal_soc *)hal_soc; if (srng->ring_dir == HAL_SRNG_SRC_RING) { @@ -1611,12 +1949,13 @@ static inline qdf_dma_addr_t hal_srng_get_hp_addr(void *hal_soc, void *hal_ring) * hal_srng_get_tp_addr - Get tail pointer physical address * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Ring pointer (Source or Destination ring) + * @hal_ring_hdl: Ring pointer (Source or Destination ring) * */ -static inline qdf_dma_addr_t hal_srng_get_tp_addr(void *hal_soc, void *hal_ring) +static inline qdf_dma_addr_t +hal_srng_get_tp_addr(void *hal_soc, hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; struct hal_soc *hal = (struct hal_soc *)hal_soc; if (srng->ring_dir == HAL_SRNG_SRC_RING) { @@ -1639,8 +1978,8 @@ static inline qdf_dma_addr_t hal_srng_get_tp_addr(void *hal_soc, void *hal_ring) * Return: total number of entries in hal ring */ static inline -uint32_t hal_srng_get_num_entries(void *hal_soc_hdl, - void *hal_ring_hdl) +uint32_t hal_srng_get_num_entries(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; @@ -1651,11 +1990,12 @@ uint32_t hal_srng_get_num_entries(void *hal_soc_hdl, * hal_get_srng_params - Retrieve SRNG parameters for a given ring from HAL * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Ring pointer (Source or Destination ring) + * @hal_ring_hdl: Ring pointer (Source or Destination ring) * @ring_params: SRNG parameters will be returned through this structure */ -extern void hal_get_srng_params(void *hal_soc, void *hal_ring, - struct hal_srng_params *ring_params); +void hal_get_srng_params(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl, + struct hal_srng_params *ring_params); /** * hal_mem_info - Retrieve hal memory base address @@ -1663,14 +2003,14 @@ extern void hal_get_srng_params(void *hal_soc, void *hal_ring, * @hal_soc: Opaque HAL SOC handle * @mem: pointer to structure to be updated with hal mem info */ -extern void hal_get_meminfo(void *hal_soc,struct hal_mem_info *mem ); +void hal_get_meminfo(hal_soc_handle_t hal_soc_hdl, struct hal_mem_info *mem); /** * hal_get_target_type - Return target type * * @hal_soc: Opaque HAL SOC handle */ -uint32_t hal_get_target_type(struct hal_soc *hal); +uint32_t hal_get_target_type(hal_soc_handle_t hal_soc_hdl); /** * hal_get_ba_aging_timeout - Retrieve BA aging timeout @@ -1679,7 +2019,7 @@ uint32_t hal_get_target_type(struct hal_soc *hal); * @ac: Access category * @value: timeout duration in millisec */ -void hal_get_ba_aging_timeout(void *hal_soc, uint8_t ac, +void hal_get_ba_aging_timeout(hal_soc_handle_t hal_soc_hdl, uint8_t ac, uint32_t *value); /** * hal_set_aging_timeout - Set BA aging timeout @@ -1688,7 +2028,7 @@ void hal_get_ba_aging_timeout(void *hal_soc, uint8_t ac, * @ac: Access category in millisec * @value: timeout duration value */ -void hal_set_ba_aging_timeout(void *hal_soc, uint8_t ac, +void hal_set_ba_aging_timeout(hal_soc_handle_t hal_soc_hdl, uint8_t ac, uint32_t value); /** * hal_srng_dst_hw_init - Private function to initialize SRNG @@ -1717,18 +2057,23 @@ static inline void hal_srng_src_hw_init(struct hal_soc *hal, /** * hal_get_hw_hptp() - Get HW head and tail pointer value for any ring * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer * @headp: Head Pointer * @tailp: Tail Pointer * @ring_type: Ring * * Return: Update tail pointer and head pointer in arguments. */ -static inline void hal_get_hw_hptp(struct hal_soc *hal, void *hal_ring, - uint32_t *headp, uint32_t *tailp, - uint8_t ring_type) +static inline +void hal_get_hw_hptp(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl, + uint32_t *headp, uint32_t *tailp, + uint8_t ring_type) { - hal->ops->hal_get_hw_hptp(hal, hal_ring, headp, tailp, ring_type); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + hal_soc->ops->hal_get_hw_hptp(hal_soc, hal_ring_hdl, + headp, tailp, ring_type); } /** @@ -1737,12 +2082,12 @@ static inline void hal_get_hw_hptp(struct hal_soc *hal, void *hal_ring, * @hal_soc: Opaque HAL SOC handle * @reo_params: parameters needed by HAL for REO config */ -static inline void hal_reo_setup(void *halsoc, - void *reoparams) +static inline void hal_reo_setup(hal_soc_handle_t hal_soc_hdl, + void *reoparams) { - struct hal_soc *hal_soc = (struct hal_soc *)halsoc; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - hal_soc->ops->hal_reo_setup(halsoc, reoparams); + hal_soc->ops->hal_reo_setup(hal_soc, reoparams); } /** @@ -1758,32 +2103,108 @@ static inline void hal_reo_setup(void *halsoc, * @num_entries: Total entries of all scatter bufs * */ -static inline void hal_setup_link_idle_list(void *halsoc, - qdf_dma_addr_t scatter_bufs_base_paddr[], - void *scatter_bufs_base_vaddr[], uint32_t num_scatter_bufs, - uint32_t scatter_buf_size, uint32_t last_buf_end_offset, - uint32_t num_entries) +static inline +void hal_setup_link_idle_list(hal_soc_handle_t hal_soc_hdl, + qdf_dma_addr_t scatter_bufs_base_paddr[], + void *scatter_bufs_base_vaddr[], + uint32_t num_scatter_bufs, + uint32_t scatter_buf_size, + uint32_t last_buf_end_offset, + uint32_t num_entries) { - struct hal_soc *hal_soc = (struct hal_soc *)halsoc; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - hal_soc->ops->hal_setup_link_idle_list(halsoc, scatter_bufs_base_paddr, + hal_soc->ops->hal_setup_link_idle_list(hal_soc, scatter_bufs_base_paddr, scatter_bufs_base_vaddr, num_scatter_bufs, scatter_buf_size, last_buf_end_offset, num_entries); } +#ifdef DUMP_REO_QUEUE_INFO_IN_DDR +/** + * hal_dump_rx_reo_queue_desc() - Dump reo queue descriptor fields + * @hw_qdesc_vaddr_aligned: Pointer to hw reo queue desc virtual addr + * + * Use the virtual addr pointer to reo h/w queue desc to read + * the values from ddr and log them. + * + * Return: none + */ +static inline void hal_dump_rx_reo_queue_desc( + void *hw_qdesc_vaddr_aligned) +{ + struct rx_reo_queue *hw_qdesc = + (struct rx_reo_queue *)hw_qdesc_vaddr_aligned; + + if (!hw_qdesc) + return; + + hal_info("receive_queue_number %u vld %u window_jump_2k %u" + " hole_count %u ba_window_size %u ignore_ampdu_flag %u" + " svld %u ssn %u current_index %u" + " disable_duplicate_detection %u soft_reorder_enable %u" + " chk_2k_mode %u oor_mode %u mpdu_frames_processed_count %u" + " msdu_frames_processed_count %u total_processed_byte_count %u" + " late_receive_mpdu_count %u seq_2k_error_detected_flag %u" + " pn_error_detected_flag %u current_mpdu_count %u" + " current_msdu_count %u timeout_count %u" + " forward_due_to_bar_count %u duplicate_count %u" + " frames_in_order_count %u bar_received_count %u" + " pn_check_needed %u pn_shall_be_even %u" + " pn_shall_be_uneven %u pn_size %u", + hw_qdesc->receive_queue_number, + hw_qdesc->vld, + hw_qdesc->window_jump_2k, + hw_qdesc->hole_count, + hw_qdesc->ba_window_size, + hw_qdesc->ignore_ampdu_flag, + hw_qdesc->svld, + hw_qdesc->ssn, + hw_qdesc->current_index, + hw_qdesc->disable_duplicate_detection, + hw_qdesc->soft_reorder_enable, + hw_qdesc->chk_2k_mode, + hw_qdesc->oor_mode, + hw_qdesc->mpdu_frames_processed_count, + hw_qdesc->msdu_frames_processed_count, + hw_qdesc->total_processed_byte_count, + hw_qdesc->late_receive_mpdu_count, + hw_qdesc->seq_2k_error_detected_flag, + hw_qdesc->pn_error_detected_flag, + hw_qdesc->current_mpdu_count, + hw_qdesc->current_msdu_count, + hw_qdesc->timeout_count, + hw_qdesc->forward_due_to_bar_count, + hw_qdesc->duplicate_count, + hw_qdesc->frames_in_order_count, + hw_qdesc->bar_received_count, + hw_qdesc->pn_check_needed, + hw_qdesc->pn_shall_be_even, + hw_qdesc->pn_shall_be_uneven, + hw_qdesc->pn_size); +} + +#else /* DUMP_REO_QUEUE_INFO_IN_DDR */ + +static inline void hal_dump_rx_reo_queue_desc( + void *hw_qdesc_vaddr_aligned) +{ +} +#endif /* DUMP_REO_QUEUE_INFO_IN_DDR */ + /** * hal_srng_dump_ring_desc() - Dump ring descriptor info * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer * @ring_desc: Opaque ring descriptor handle */ -static inline void hal_srng_dump_ring_desc(struct hal_soc *hal, void *hal_ring, - void *ring_desc) +static inline void hal_srng_dump_ring_desc(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl, + hal_ring_desc_t ring_desc) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH, ring_desc, (srng->entry_size << 2)); @@ -1793,11 +2214,12 @@ static inline void hal_srng_dump_ring_desc(struct hal_soc *hal, void *hal_ring, * hal_srng_dump_ring() - Dump last 128 descs of the ring * * @hal_soc: Opaque HAL SOC handle - * @hal_ring: Source ring pointer + * @hal_ring_hdl: Source ring pointer */ -static inline void hal_srng_dump_ring(struct hal_soc *hal, void *hal_ring) +static inline void hal_srng_dump_ring(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; uint32_t *desc; uint32_t tp, i; @@ -1816,61 +2238,86 @@ static inline void hal_srng_dump_ring(struct hal_soc *hal, void *hal_ring) } } +/* + * hal_rxdma_desc_to_hal_ring_desc - API to convert rxdma ring desc + * to opaque dp_ring desc type + * @ring_desc - rxdma ring desc + * + * Return: hal_rxdma_desc_t type + */ +static inline +hal_ring_desc_t hal_rxdma_desc_to_hal_ring_desc(hal_rxdma_desc_t ring_desc) +{ + return (hal_ring_desc_t)ring_desc; +} + /** * hal_srng_set_event() - Set hal_srng event - * @srng: SRNG ring pointer + * @hal_ring_hdl: Source ring pointer * @event: SRNG ring event * * Return: None */ -static inline void hal_srng_set_event(struct hal_srng *srng, int event) +static inline void hal_srng_set_event(hal_ring_handle_t hal_ring_hdl, int event) { + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + qdf_atomic_set_bit(event, &srng->srng_event); } /** * hal_srng_clear_event() - Clear hal_srng event - * @srng: SRNG ring pointer + * @hal_ring_hdl: Source ring pointer * @event: SRNG ring event * * Return: None */ -static inline void hal_srng_clear_event(struct hal_srng *srng, int event) +static inline +void hal_srng_clear_event(hal_ring_handle_t hal_ring_hdl, int event) { + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + qdf_atomic_clear_bit(event, &srng->srng_event); } /** * hal_srng_get_clear_event() - Clear srng event and return old value - * @srng: SRNG ring pointer + * @hal_ring_hdl: Source ring pointer * @event: SRNG ring event * * Return: Return old event value */ -static inline int hal_srng_get_clear_event(struct hal_srng *srng, int event) +static inline +int hal_srng_get_clear_event(hal_ring_handle_t hal_ring_hdl, int event) { + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + return qdf_atomic_test_and_clear_bit(event, &srng->srng_event); } /** * hal_srng_set_flush_last_ts() - Record last flush time stamp - * @srng: SRNG ring pointer + * @hal_ring_hdl: Source ring pointer * * Return: None */ -static inline void hal_srng_set_flush_last_ts(struct hal_srng *srng) +static inline void hal_srng_set_flush_last_ts(hal_ring_handle_t hal_ring_hdl) { + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + srng->last_flush_ts = qdf_get_log_timestamp(); } /** * hal_srng_inc_flush_cnt() - Increment flush counter - * @srng: Source ring pointer + * @hal_ring_hdl: Source ring pointer * * Return: None */ -static inline void hal_srng_inc_flush_cnt(struct hal_srng *srng) +static inline void hal_srng_inc_flush_cnt(hal_ring_handle_t hal_ring_hdl) { + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + srng->flush_count++; } @@ -1878,12 +2325,70 @@ static inline void hal_srng_inc_flush_cnt(struct hal_srng *srng) * hal_reo_set_err_dst_remap() - Set REO error destination ring remap * register value. * - * @hal_soc: Opaque HAL soc handle + * @hal_soc_hdl: Opaque HAL soc handle * * Return: None */ -static inline void hal_reo_set_err_dst_remap(struct hal_soc *hal_soc) +static inline void hal_reo_set_err_dst_remap(hal_soc_handle_t hal_soc_hdl) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (hal_soc->ops->hal_reo_set_err_dst_remap) + hal_soc->ops->hal_reo_set_err_dst_remap(hal_soc); +} + +#ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE + +/** + * hal_set_one_target_reg_config() - Populate the target reg + * offset in hal_soc for one non srng related register at the + * given list index + * @hal_soc: hal handle + * @target_reg_offset: target register offset + * @list_index: index in hal list for shadow regs + * + * Return: none + */ +void hal_set_one_target_reg_config(struct hal_soc *hal, + uint32_t target_reg_offset, + int list_index); + +/** + * hal_set_shadow_regs() - Populate register offset for + * registers that need to be populated in list_shadow_reg_config + * in order to be sent to FW. These reg offsets will be mapped + * to shadow registers. + * @hal_soc: hal handle + * + * Return: QDF_STATUS_OK on success + */ +QDF_STATUS hal_set_shadow_regs(void *hal_soc); + +/** + * hal_construct_shadow_regs() - initialize the shadow registers + * for non-srng related register configs + * @hal_soc: hal handle + * + * Return: QDF_STATUS_OK on success + */ +QDF_STATUS hal_construct_shadow_regs(void *hal_soc); + +#else /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */ +static inline void hal_set_one_target_reg_config( + struct hal_soc *hal, + uint32_t target_reg_offset, + int list_index) +{ +} + +static inline QDF_STATUS hal_set_shadow_regs(void *hal_soc) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS hal_construct_shadow_regs(void *hal_soc) { - hal_soc->ops->hal_reo_set_err_dst_remap(hal_soc); + return QDF_STATUS_SUCCESS; } +#endif /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */ #endif /* _HAL_APIH_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_api_mon.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_api_mon.h index c4ff12da3b72b6318dcf1df03586ca6de5759735..5913d9a7ab02091660dd7dcf58bd019664524a99 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_api_mon.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_api_mon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -148,18 +148,32 @@ #define HAL_RX_GET_MSDU_AGGREGATION(rx_desc, rs) #endif +/* Max MPDUs per status buffer */ +#define HAL_RX_MAX_MPDU 256 +#define HAL_RX_NUM_WORDS_PER_PPDU_BITMAP (HAL_RX_MAX_MPDU >> 5) + +/* Max pilot count */ +#define HAL_RX_MAX_SU_EVM_COUNT 32 + +/* + * Struct hal_rx_su_evm_info - SU evm info + * @number_of_symbols: number of symbols + * @nss_count: nss count + * @pilot_count: pilot count + * @pilot_evm: Array of pilot evm values + */ +struct hal_rx_su_evm_info { + uint32_t number_of_symbols; + uint8_t nss_count; + uint8_t pilot_count; + uint32_t pilot_evm[HAL_RX_MAX_SU_EVM_COUNT]; +}; + enum { DP_PPDU_STATUS_START, DP_PPDU_STATUS_DONE, }; -static inline -uint32_t HAL_RX_MON_HW_RX_DESC_SIZE(void) -{ - /* return the HW_RX_DESC size */ - return sizeof(struct rx_pkt_tlvs); -} - static inline uint8_t *HAL_RX_MON_DEST_GET_DESC(uint8_t *data) { @@ -170,7 +184,8 @@ static inline uint32_t HAL_RX_DESC_GET_MPDU_LENGTH_ERR(void *hw_desc_addr) { struct rx_attention *rx_attn; - struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + struct rx_mon_pkt_tlvs *rx_desc = + (struct rx_mon_pkt_tlvs *)hw_desc_addr; rx_attn = &rx_desc->attn_tlv.rx_attn; @@ -181,7 +196,8 @@ static inline uint32_t HAL_RX_DESC_GET_MPDU_FCS_ERR(void *hw_desc_addr) { struct rx_attention *rx_attn; - struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + struct rx_mon_pkt_tlvs *rx_desc = + (struct rx_mon_pkt_tlvs *)hw_desc_addr; rx_attn = &rx_desc->attn_tlv.rx_attn; @@ -198,7 +214,8 @@ uint32_t HAL_RX_DESC_GET_MPDU_FCS_ERR(void *hw_desc_addr) static inline bool HAL_RX_HW_DESC_MPDU_VALID(void *hw_desc_addr) { - struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + struct rx_mon_pkt_tlvs *rx_desc = + (struct rx_mon_pkt_tlvs *)hw_desc_addr; uint32_t tlv_tag; tlv_tag = HAL_RX_GET_USER_TLV32_TYPE( @@ -207,17 +224,6 @@ bool HAL_RX_HW_DESC_MPDU_VALID(void *hw_desc_addr) return tlv_tag == WIFIRX_MPDU_START_E ? true : false; } -static inline -uint32_t HAL_RX_HW_DESC_GET_PPDUID_GET(void *hw_desc_addr) -{ - struct rx_mpdu_info *rx_mpdu_info; - struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; - - rx_mpdu_info = - &rx_desc->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; - - return HAL_RX_GET(rx_mpdu_info, RX_MPDU_INFO_0, PHY_PPDU_ID); -} /* TODO: Move all Rx descriptor functions to hal_rx.h to avoid duplication */ @@ -253,10 +259,9 @@ uint32_t HAL_RX_HW_DESC_GET_PPDUID_GET(void *hw_desc_addr) * Return: void */ static inline -void hal_rx_reo_ent_buf_paddr_get(void *rx_desc, - struct hal_buf_info *buf_info, - void **pp_buf_addr_info, - uint32_t *msdu_cnt +void hal_rx_reo_ent_buf_paddr_get(hal_rxdma_desc_t rx_desc, + struct hal_buf_info *buf_info, + uint32_t *msdu_cnt ) { struct reo_entrance_ring *reo_ent_ring = @@ -282,18 +287,17 @@ void hal_rx_reo_ent_buf_paddr_get(void *rx_desc, (HAL_RX_BUFFER_ADDR_39_32_GET(buf_addr_info)) << 32)); buf_info->sw_cookie = HAL_RX_BUF_COOKIE_GET(buf_addr_info); + buf_info->rbm = HAL_RX_BUF_RBM_GET(buf_addr_info); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "[%s][%d] ReoAddr=%pK, addrInfo=%pK, paddr=0x%llx, loopcnt=%d", __func__, __LINE__, reo_ent_ring, buf_addr_info, (unsigned long long)buf_info->paddr, loop_cnt); - - *pp_buf_addr_info = (void *)buf_addr_info; } static inline void hal_rx_mon_next_link_desc_get(void *rx_msdu_link_desc, - struct hal_buf_info *buf_info, void **pp_buf_addr_info) + struct hal_buf_info *buf_info) { struct rx_msdu_link *msdu_link = (struct rx_msdu_link *)rx_msdu_link_desc; @@ -307,8 +311,7 @@ void hal_rx_mon_next_link_desc_get(void *rx_msdu_link_desc, (HAL_RX_BUFFER_ADDR_39_32_GET(buf_addr_info)) << 32)); buf_info->sw_cookie = HAL_RX_BUF_COOKIE_GET(buf_addr_info); - - *pp_buf_addr_info = (void *)buf_addr_info; + buf_info->rbm = HAL_RX_BUF_RBM_GET(buf_addr_info); } /** @@ -321,8 +324,10 @@ void hal_rx_mon_next_link_desc_get(void *rx_msdu_link_desc, * Return: void */ -static inline void hal_rx_mon_msdu_link_desc_set(struct hal_soc *soc, - void *src_srng_desc, void *buf_addr_info) +static inline +void hal_rx_mon_msdu_link_desc_set(hal_soc_handle_t hal_soc_hdl, + void *src_srng_desc, + hal_buff_addrinfo_t buf_addr_info) { struct buffer_addr_info *wbm_srng_buffer_addr_info = (struct buffer_addr_info *)src_srng_desc; @@ -390,16 +395,37 @@ enum { HAL_RX_MON_PPDU_END, }; +/* struct hal_rx_ppdu_common_info - common ppdu info + * @ppdu_id - ppdu id number + * @ppdu_timestamp - timestamp at ppdu received + * @mpdu_cnt_fcs_ok - mpdu count in ppdu with fcs ok + * @mpdu_cnt_fcs_err - mpdu count in ppdu with fcs err + * @mpdu_fcs_ok_bitmap - fcs ok mpdu count in ppdu bitmap + * @last_ppdu_id - last received ppdu id + * @mpdu_cnt - total mpdu count + * @num_users - num users + */ struct hal_rx_ppdu_common_info { uint32_t ppdu_id; uint32_t ppdu_timestamp; uint32_t mpdu_cnt_fcs_ok; uint32_t mpdu_cnt_fcs_err; + uint32_t mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP]; + uint32_t last_ppdu_id; + uint32_t mpdu_cnt; + uint8_t num_users; }; +/** + * struct hal_rx_msdu_payload_info - msdu payload info + * @first_msdu_payload: pointer to first msdu payload + * @payload_len: payload len + * @nbuf: status network buffer to which msdu belongs to + */ struct hal_rx_msdu_payload_info { uint8_t *first_msdu_payload; uint32_t payload_len; + qdf_nbuf_t nbuf; }; /** @@ -409,6 +435,7 @@ struct hal_rx_msdu_payload_info { * @to_ds_flag: flag indicate to_ds bit * @mac_addr2_valid: flag indicate if mac_addr2 is valid * @mac_addr2: mac address2 in wh + * @mcast_bcast: multicast/broadcast */ struct hal_rx_nac_info { uint8_t fc_valid; @@ -416,21 +443,123 @@ struct hal_rx_nac_info { uint8_t to_ds_flag; uint8_t mac_addr2_valid; uint8_t mac_addr2[QDF_MAC_ADDR_SIZE]; + uint8_t mcast_bcast; }; /** * struct hal_rx_ppdu_msdu_info - struct for msdu info from HW TLVs - * @cce_metadata: cached metadata value received in the MSDU_END TLV + * @cce_metadata: cached CCE metadata value received in the MSDU_END TLV + * @is_flow_idx_timeout: flag to indicate if flow search timeout occurred + * @is_flow_idx_invalid: flag to indicate if flow idx is valid or not + * @fse_metadata: cached FSE metadata value received in the MSDU END TLV + * @flow_idx: flow idx matched in FSE received in the MSDU END TLV */ struct hal_rx_ppdu_msdu_info { uint16_t cce_metadata; + bool is_flow_idx_timeout; + bool is_flow_idx_invalid; + uint32_t fse_metadata; + uint32_t flow_idx; +}; + +#if defined(WLAN_CFR_ENABLE) && defined(WLAN_ENH_CFR_ENABLE) +/** + * struct hal_rx_ppdu_cfr_user_info - struct for storing peer info extracted + * from HW TLVs, this will be used for correlating CFR data with multiple peers + * in MU PPDUs + * + * @peer_macaddr: macaddr of the peer + * @ast_index: AST index of the peer + */ +struct hal_rx_ppdu_cfr_user_info { + uint8_t peer_macaddr[QDF_MAC_ADDR_SIZE]; + uint32_t ast_index; +}; + +/** + * struct hal_rx_ppdu_cfr_info - struct for storing ppdu info extracted from HW + * TLVs, this will be used for CFR correlation + * + * @bb_captured_channel : Set by RXPCU when MACRX_FREEZE_CAPTURE_CHANNEL TLV is + * sent to PHY, SW checks it to correlate current PPDU TLVs with uploaded + * channel information. + * + * @bb_captured_timeout : Set by RxPCU to indicate channel capture condition is + * met, but MACRX_FREEZE_CAPTURE_CHANNEL is not sent to PHY due to AST delay, + * which means the rx_frame_falling edge to FREEZE TLV ready time exceeds + * the threshold time defined by RXPCU register FREEZE_TLV_DELAY_CNT_THRESH. + * Bb_captured_reason is still valid in this case. + * + * @rx_location_info_valid: Indicates whether CFR DMA address in the PPDU TLV + * is valid + * + * + * + * + * @bb_captured_reason : Copy capture_reason of MACRX_FREEZE_CAPTURE_CHANNEL + * TLV to here for FW usage. Valid when bb_captured_channel or + * bb_captured_timeout is set. + * + * + * + * + * + * + * + * + * @rtt_che_buffer_pointer_low32 : The low 32 bits of the 40 bits pointer to + * external RTT channel information buffer + * + * @rtt_che_buffer_pointer_high8 : The high 8 bits of the 40 bits pointer to + * external RTT channel information buffer + * + * @chan_capture_status : capture status reported by ucode + * a. CAPTURE_IDLE: FW has disabled "REPETITIVE_CHE_CAPTURE_CTRL" + * b. CAPTURE_BUSY: previous PPDU’s channel capture upload DMA ongoing. (Note + * that this upload is triggered after receiving freeze_channel_capture TLV + * after last PPDU is rx) + * c. CAPTURE_ACTIVE: channel capture is enabled and no previous channel + * capture ongoing + * d. CAPTURE_NO_BUFFER: next buffer in IPC ring not available + * + * @cfr_user_info: Peer mac for upto 4 MU users + */ + +struct hal_rx_ppdu_cfr_info { + bool bb_captured_channel; + bool bb_captured_timeout; + uint8_t bb_captured_reason; + bool rx_location_info_valid; + uint8_t chan_capture_status; + uint8_t rtt_che_buffer_pointer_high8; + uint32_t rtt_che_buffer_pointer_low32; + struct hal_rx_ppdu_cfr_user_info cfr_user_info[HAL_MAX_UL_MU_USERS]; +}; +#else +struct hal_rx_ppdu_cfr_info {}; +#endif + +struct mon_rx_info { + uint8_t qos_control_info_valid; + uint16_t qos_control; + uint8_t mac_addr1_valid; + uint8_t mac_addr1[QDF_MAC_ADDR_SIZE]; +}; + +struct mon_rx_user_info { + uint16_t qos_control; + uint8_t qos_control_info_valid; + uint32_t bar_frame:1; }; struct hal_rx_ppdu_info { struct hal_rx_ppdu_common_info com_info; struct mon_rx_status rx_status; struct mon_rx_user_status rx_user_status[HAL_MAX_UL_MU_USERS]; + struct mon_rx_info rx_info; + struct mon_rx_user_info rx_user_info[HAL_MAX_UL_MU_USERS]; struct hal_rx_msdu_payload_info msdu_info; + struct hal_rx_msdu_payload_info fcs_ok_msdu_info; struct hal_rx_nac_info nac_info; /* status ring PPDU start and end state */ uint32_t rx_state; @@ -442,7 +571,18 @@ struct hal_rx_ppdu_info { uint32_t hdr_len; /* MPDU FCS error */ bool fcs_err; + /* Id to indicate how to process mpdu */ + uint8_t sw_frame_group_id; struct hal_rx_ppdu_msdu_info rx_msdu_info[HAL_MAX_UL_MU_USERS]; + /* first msdu payload for all mpdus in ppdu */ + struct hal_rx_msdu_payload_info ppdu_msdu_info[HAL_RX_MAX_MPDU]; + /* evm info */ + struct hal_rx_su_evm_info evm_info; + /** + * Will be used to store ppdu info extracted from HW TLVs, + * and for CFR correlation as well + */ + struct hal_rx_ppdu_cfr_info cfr_info; }; static inline uint32_t @@ -491,19 +631,27 @@ static inline void hal_rx_proc_phyrx_other_receive_info_tlv(struct hal_soc *hal_ * hal_rx_status_get_tlv_info() - process receive info TLV * @rx_tlv_hdr: pointer to TLV header * @ppdu_info: pointer to ppdu_info + * @hal_soc: HAL soc handle + * @nbuf: PPDU status netowrk buffer * * Return: HAL_TLV_STATUS_PPDU_NOT_DONE or HAL_TLV_STATUS_PPDU_DONE from tlv */ static inline uint32_t hal_rx_status_get_tlv_info(void *rx_tlv_hdr, void *ppdu_info, - struct hal_soc *hal_soc) + hal_soc_handle_t hal_soc_hdl, + qdf_nbuf_t nbuf) { - return hal_soc->ops->hal_rx_status_get_tlv_info(rx_tlv_hdr, - ppdu_info, hal_soc); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_status_get_tlv_info( + rx_tlv_hdr, + ppdu_info, + hal_soc_hdl, + nbuf); } static inline -uint32_t hal_get_rx_status_done_tlv_size(void *hal_soc) +uint32_t hal_get_rx_status_done_tlv_size(hal_soc_handle_t hal_soc_hdl) { return HAL_RX_TLV32_HDR_SIZE; } diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_flow.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_flow.h new file mode 100644 index 0000000000000000000000000000000000000000..b89146d10ab1b650f0908d0f94645df1d6e1cba6 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_flow.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __HAL_FLOW_H +#define __HAL_FLOW_H + +#define HAL_SET_FLD_SM(block, field, value) \ + (((value) << (block ## _ ## field ## _LSB)) & \ + (block ## _ ## field ## _MASK)) + +#define HAL_SET_FLD_MS(block, field, value) \ + (((value) & (block ## _ ## field ## _MASK)) >> \ + (block ## _ ## field ## _LSB)) + +#define HAL_CLR_FLD(desc, block, field) \ +do { \ + uint32_t val; \ + typeof(desc) desc_ = desc; \ + val = *((uint32_t *)((uint8_t *)(desc_) + \ + HAL_OFFSET(block, field))); \ + val &= ~(block ## _ ## field ## _MASK); \ + HAL_SET_FLD(desc_, block, field) = val; \ +} while (0) + +#define HAL_GET_FLD(desc, block, field) \ + ((*((uint32_t *)((uint8_t *)(desc) + HAL_OFFSET(block, field))) & \ + (block ## _ ## field ## _MASK)) >> (block ## _ ## field ## _LSB)) + +/** + * struct hal_flow_tuple_info - Hal Flow 5-tuple + * @dest_ip_127_96: Destination IP address bits 96-127 + * @dest_ip_95_64: Destination IP address bits 64-95 + * @dest_ip_63_32: Destination IP address bits 32-63 + * @dest_ip_31_0: Destination IP address bits 0-31 + * @src_ip_127_96: Source IP address bits 96-127 + * @src_ip_95_64: Source IP address bits 64-95 + * @src_ip_63_32: Source IP address bits 32-63 + * @src_ip_31_0: Source IP address bits 0-31 + * @dest_port: Destination Port + * @src_port: Source Port + * @l4_protocol: Layer-4 protocol type (TCP/UDP) + */ +struct hal_flow_tuple_info { + uint32_t dest_ip_127_96; + uint32_t dest_ip_95_64; + uint32_t dest_ip_63_32; + uint32_t dest_ip_31_0; + uint32_t src_ip_127_96; + uint32_t src_ip_95_64; + uint32_t src_ip_63_32; + uint32_t src_ip_31_0; + uint16_t dest_port; + uint16_t src_port; + uint16_t l4_protocol; +}; + +/** + * key_bitwise_shift_left() - Bitwise left shift (in place) an array of bytes + * @key: Pointer to array to key bytes + * @len: size of array (number of key bytes) + * @shift: number of shift operations to be performed + * + * Return: + */ +static inline void +key_bitwise_shift_left(uint8_t *key, int len, int shift) +{ + int i; + int next; + + while (shift--) { + for (i = len - 1; i >= 0 ; i--) { + if (i > 0) + next = (key[i - 1] & 0x80 ? 1 : 0); + else + next = 0; + key[i] = (key[i] << 1) | next; + } + } +} + +/** + * key_reverse() - Reverse the key buffer from MSB to LSB + * @dest: pointer to the destination key + * @src: pointer to the source key which should be shifted + * @len: size of key in bytes + * + * Return: + */ +static inline void +key_reverse(uint8_t *dest, uint8_t *src, int len) +{ + int i, j; + + for (i = 0, j = len - 1; i < len; i++, j--) + dest[i] = src[j]; +} +#endif /* HAL_FLOW_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_generic_api.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_generic_api.h index 9abdb17ae1b7fecc73cb89de34a01d710843d33e..3f02ab4daa9c1e65e2ed58a648311c8591aaf172 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_generic_api.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_generic_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -18,37 +18,7 @@ #ifndef _HAL_GENERIC_API_H_ #define _HAL_GENERIC_API_H_ -#define HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr) \ - ((struct rx_msdu_desc_info *) \ - _OFFSET_TO_BYTE_PTR(msdu_details_ptr, \ -UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET)) -/** - * hal_rx_msdu_desc_info_get_ptr_generic() - Get msdu desc info ptr - * @msdu_details_ptr - Pointer to msdu_details_ptr - * Return - Pointer to rx_msdu_desc_info structure. - * - */ -static void *hal_rx_msdu_desc_info_get_ptr_generic(void *msdu_details_ptr) -{ - return HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr); -} - - -#define HAL_RX_LINK_DESC_MSDU0_PTR(link_desc) \ - ((struct rx_msdu_details *) \ - _OFFSET_TO_BYTE_PTR((link_desc),\ - UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET)) -/** - * hal_rx_link_desc_msdu0_ptr_generic - Get pointer to rx_msdu details - * @link_desc - Pointer to link desc - * Return - Pointer to rx_msdu_details structure - * - */ - -static void *hal_rx_link_desc_msdu0_ptr_generic(void *link_desc) -{ - return HAL_RX_LINK_DESC_MSDU0_PTR(link_desc); -} +#include /** * hal_tx_comp_get_status() - TQM Release reason @@ -59,8 +29,10 @@ static void *hal_rx_link_desc_msdu0_ptr_generic(void *link_desc) * * Return: none */ -static inline void hal_tx_comp_get_status_generic(void *desc, - void *ts1, void *hal) +static inline +void hal_tx_comp_get_status_generic(void *desc, + void *ts1, + struct hal_soc *hal) { uint8_t rate_stats_valid = 0; uint32_t rate_stats = 0; @@ -109,7 +81,9 @@ static inline void hal_tx_comp_get_status_generic(void *desc, } ts->release_src = hal_tx_comp_get_buffer_source(desc); - ts->status = hal_tx_comp_get_release_reason(desc, hal); + ts->status = hal_tx_comp_get_release_reason( + desc, + hal_soc_to_hal_soc_handle(hal)); ts->tsf = HAL_TX_DESC_GET(desc, UNIFIED_WBM_RELEASE_RING_6, TX_RATE_STATS_INFO_TX_RATE_STATS); @@ -157,7 +131,7 @@ static inline void hal_tx_desc_set_buf_addr_generic(void *desc, HAL_TX_SM(UNIFIED_TCL_DATA_CMD_2, BUF_OR_EXT_DESC_TYPE, type); } -#if defined(CONFIG_MCL) && defined(QCA_WIFI_QCA6290_11AX) +#if defined(QCA_WIFI_QCA6290_11AX_MU_UL) && defined(QCA_WIFI_QCA6290_11AX) /** * hal_rx_handle_other_tlvs() - handle special TLVs like MU_UL * tlv_tag: Taf of the TLVs @@ -239,32 +213,218 @@ hal_rx_handle_other_tlvs(uint32_t tlv_tag, void *rx_tlv, { return false; } -#endif /* CONFIG_MCL && QCA_WIFI_QCA6290_11AX */ +#endif /* QCA_WIFI_QCA6290_11AX_MU_UL && QCA_WIFI_QCA6290_11AX */ + +#if defined(RX_PPDU_END_USER_STATS_1_OFDMA_INFO_VALID_OFFSET) && \ +defined(RX_PPDU_END_USER_STATS_22_SW_RESPONSE_REFERENCE_PTR_EXT_OFFSET) -#if defined(RX_PPDU_END_USER_STATS_1_OFDMA_INFO_VALID_OFFSET) static inline void -hal_rx_handle_ofdma_info( +hal_rx_handle_mu_ul_info( void *rx_tlv, struct mon_rx_user_status *mon_rx_user_status) { - mon_rx_user_status->ofdma_info_valid = - HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_1, - OFDMA_INFO_VALID); - mon_rx_user_status->dl_ofdma_ru_start_index = - HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_1, - DL_OFDMA_RU_START_INDEX); - mon_rx_user_status->dl_ofdma_ru_width = - HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_2, - DL_OFDMA_RU_WIDTH); + mon_rx_user_status->mu_ul_user_v0_word0 = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_11, + SW_RESPONSE_REFERENCE_PTR); + + mon_rx_user_status->mu_ul_user_v0_word1 = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_22, + SW_RESPONSE_REFERENCE_PTR_EXT); +} + +static inline void +hal_rx_populate_byte_count(void *rx_tlv, void *ppduinfo, + struct mon_rx_user_status *mon_rx_user_status) +{ + uint32_t mpdu_ok_byte_count; + uint32_t mpdu_err_byte_count; + + mpdu_ok_byte_count = HAL_RX_GET(rx_tlv, + RX_PPDU_END_USER_STATS_17, + MPDU_OK_BYTE_COUNT); + mpdu_err_byte_count = HAL_RX_GET(rx_tlv, + RX_PPDU_END_USER_STATS_19, + MPDU_ERR_BYTE_COUNT); + + mon_rx_user_status->mpdu_ok_byte_count = mpdu_ok_byte_count; + mon_rx_user_status->mpdu_err_byte_count = mpdu_err_byte_count; } #else static inline void -hal_rx_handle_ofdma_info(void *rx_tlv, +hal_rx_handle_mu_ul_info(void *rx_tlv, struct mon_rx_user_status *mon_rx_user_status) { } + +static inline void +hal_rx_populate_byte_count(void *rx_tlv, void *ppduinfo, + struct mon_rx_user_status *mon_rx_user_status) +{ + struct hal_rx_ppdu_info *ppdu_info = + (struct hal_rx_ppdu_info *)ppduinfo; + + /* HKV1: doesn't support mpdu byte count */ + mon_rx_user_status->mpdu_ok_byte_count = ppdu_info->rx_status.ppdu_len; + mon_rx_user_status->mpdu_err_byte_count = 0; +} +#endif + +static inline void +hal_rx_populate_mu_user_info(void *rx_tlv, void *ppduinfo, + struct mon_rx_user_status *mon_rx_user_status) +{ + struct hal_rx_ppdu_info *ppdu_info = + (struct hal_rx_ppdu_info *)ppduinfo; + + mon_rx_user_status->ast_index = ppdu_info->rx_status.ast_index; + mon_rx_user_status->tid = ppdu_info->rx_status.tid; + mon_rx_user_status->tcp_msdu_count = + ppdu_info->rx_status.tcp_msdu_count; + mon_rx_user_status->udp_msdu_count = + ppdu_info->rx_status.udp_msdu_count; + mon_rx_user_status->other_msdu_count = + ppdu_info->rx_status.other_msdu_count; + mon_rx_user_status->frame_control = ppdu_info->rx_status.frame_control; + mon_rx_user_status->frame_control_info_valid = + ppdu_info->rx_status.frame_control_info_valid; + mon_rx_user_status->data_sequence_control_info_valid = + ppdu_info->rx_status.data_sequence_control_info_valid; + mon_rx_user_status->first_data_seq_ctrl = + ppdu_info->rx_status.first_data_seq_ctrl; + mon_rx_user_status->preamble_type = ppdu_info->rx_status.preamble_type; + mon_rx_user_status->ht_flags = ppdu_info->rx_status.ht_flags; + mon_rx_user_status->rtap_flags = ppdu_info->rx_status.rtap_flags; + mon_rx_user_status->vht_flags = ppdu_info->rx_status.vht_flags; + mon_rx_user_status->he_flags = ppdu_info->rx_status.he_flags; + mon_rx_user_status->rs_flags = ppdu_info->rx_status.rs_flags; + + mon_rx_user_status->mpdu_cnt_fcs_ok = + ppdu_info->com_info.mpdu_cnt_fcs_ok; + mon_rx_user_status->mpdu_cnt_fcs_err = + ppdu_info->com_info.mpdu_cnt_fcs_err; + qdf_mem_copy(&mon_rx_user_status->mpdu_fcs_ok_bitmap, + &ppdu_info->com_info.mpdu_fcs_ok_bitmap, + HAL_RX_NUM_WORDS_PER_PPDU_BITMAP * + sizeof(ppdu_info->com_info.mpdu_fcs_ok_bitmap[0])); + + hal_rx_populate_byte_count(rx_tlv, ppdu_info, mon_rx_user_status); +} + +#ifdef WLAN_TX_PKT_CAPTURE_ENH +static inline void +hal_rx_populate_tx_capture_user_info(void *ppduinfo, + uint32_t user_id) +{ + struct hal_rx_ppdu_info *ppdu_info; + struct mon_rx_info *mon_rx_info; + struct mon_rx_user_info *mon_rx_user_info; + + ppdu_info = (struct hal_rx_ppdu_info *)ppduinfo; + mon_rx_info = &ppdu_info->rx_info; + mon_rx_user_info = &ppdu_info->rx_user_info[user_id]; + mon_rx_user_info->qos_control_info_valid = + mon_rx_info->qos_control_info_valid; + mon_rx_user_info->qos_control = mon_rx_info->qos_control; +} +#else +static inline void +hal_rx_populate_tx_capture_user_info(void *ppduinfo, + uint32_t user_id) +{ +} #endif +#define HAL_RX_UPDATE_RSSI_PER_CHAIN_BW(chain, word_1, word_2, \ + ppdu_info, rssi_info_tlv) \ + { \ + ppdu_info->rx_status.rssi_chain[chain][0] = \ + HAL_RX_GET(rssi_info_tlv, RECEIVE_RSSI_INFO_##word_1,\ + RSSI_PRI20_CHAIN##chain); \ + ppdu_info->rx_status.rssi_chain[chain][1] = \ + HAL_RX_GET(rssi_info_tlv, RECEIVE_RSSI_INFO_##word_1,\ + RSSI_EXT20_CHAIN##chain); \ + ppdu_info->rx_status.rssi_chain[chain][2] = \ + HAL_RX_GET(rssi_info_tlv, RECEIVE_RSSI_INFO_##word_1,\ + RSSI_EXT40_LOW20_CHAIN##chain); \ + ppdu_info->rx_status.rssi_chain[chain][3] = \ + HAL_RX_GET(rssi_info_tlv, RECEIVE_RSSI_INFO_##word_1,\ + RSSI_EXT40_HIGH20_CHAIN##chain); \ + ppdu_info->rx_status.rssi_chain[chain][4] = \ + HAL_RX_GET(rssi_info_tlv, RECEIVE_RSSI_INFO_##word_2,\ + RSSI_EXT80_LOW20_CHAIN##chain); \ + ppdu_info->rx_status.rssi_chain[chain][5] = \ + HAL_RX_GET(rssi_info_tlv, RECEIVE_RSSI_INFO_##word_2,\ + RSSI_EXT80_LOW_HIGH20_CHAIN##chain); \ + ppdu_info->rx_status.rssi_chain[chain][6] = \ + HAL_RX_GET(rssi_info_tlv, RECEIVE_RSSI_INFO_##word_2,\ + RSSI_EXT80_HIGH_LOW20_CHAIN##chain); \ + ppdu_info->rx_status.rssi_chain[chain][7] = \ + HAL_RX_GET(rssi_info_tlv, RECEIVE_RSSI_INFO_##word_2,\ + RSSI_EXT80_HIGH20_CHAIN##chain); \ + } \ + +#define HAL_RX_PPDU_UPDATE_RSSI(ppdu_info, rssi_info_tlv) \ + {HAL_RX_UPDATE_RSSI_PER_CHAIN_BW(0, 0, 1, ppdu_info, rssi_info_tlv) \ + HAL_RX_UPDATE_RSSI_PER_CHAIN_BW(1, 2, 3, ppdu_info, rssi_info_tlv) \ + HAL_RX_UPDATE_RSSI_PER_CHAIN_BW(2, 4, 5, ppdu_info, rssi_info_tlv) \ + HAL_RX_UPDATE_RSSI_PER_CHAIN_BW(3, 6, 7, ppdu_info, rssi_info_tlv) \ + HAL_RX_UPDATE_RSSI_PER_CHAIN_BW(4, 8, 9, ppdu_info, rssi_info_tlv) \ + HAL_RX_UPDATE_RSSI_PER_CHAIN_BW(5, 10, 11, ppdu_info, rssi_info_tlv) \ + HAL_RX_UPDATE_RSSI_PER_CHAIN_BW(6, 12, 13, ppdu_info, rssi_info_tlv) \ + HAL_RX_UPDATE_RSSI_PER_CHAIN_BW(7, 14, 15, ppdu_info, rssi_info_tlv)} \ + +static inline uint32_t +hal_rx_update_rssi_chain(struct hal_rx_ppdu_info *ppdu_info, + uint8_t *rssi_info_tlv) +{ + HAL_RX_PPDU_UPDATE_RSSI(ppdu_info, rssi_info_tlv) + return 0; +} + +#ifdef WLAN_TX_PKT_CAPTURE_ENH +static inline void +hal_get_qos_control(void *rx_tlv, + struct hal_rx_ppdu_info *ppdu_info) +{ + ppdu_info->rx_info.qos_control_info_valid = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_3, + QOS_CONTROL_INFO_VALID); + + if (ppdu_info->rx_info.qos_control_info_valid) + ppdu_info->rx_info.qos_control = + HAL_RX_GET(rx_tlv, + RX_PPDU_END_USER_STATS_5, + QOS_CONTROL_FIELD); +} + +static inline void +hal_get_mac_addr1(uint8_t *rx_mpdu_start, + struct hal_rx_ppdu_info *ppdu_info) +{ + if (ppdu_info->sw_frame_group_id + == HAL_MPDU_SW_FRAME_GROUP_MGMT_PROBE_REQ) { + ppdu_info->rx_info.mac_addr1_valid = + HAL_RX_GET_MAC_ADDR1_VALID(rx_mpdu_start); + + *(uint32_t *)&ppdu_info->rx_info.mac_addr1[0] = + HAL_RX_GET(rx_mpdu_start, + RX_MPDU_INFO_15, + MAC_ADDR_AD1_31_0); + } +} +#else +static inline void +hal_get_qos_control(void *rx_tlv, + struct hal_rx_ppdu_info *ppdu_info) +{ +} + +static inline void +hal_get_mac_addr1(uint8_t *rx_mpdu_start, + struct hal_rx_ppdu_info *ppdu_info) +{ +} +#endif /** * hal_rx_status_get_tlv_info() - process receive info TLV * @rx_tlv_hdr: pointer to TLV header @@ -274,9 +434,10 @@ hal_rx_handle_ofdma_info(void *rx_tlv, */ static inline uint32_t hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, - void *halsoc) + hal_soc_handle_t hal_soc_hdl, + qdf_nbuf_t nbuf) { - struct hal_soc *hal = (struct hal_soc *)halsoc; + struct hal_soc *hal = (struct hal_soc *)hal_soc_hdl; uint32_t tlv_tag, user_id, tlv_len, value; uint8_t group_id = 0; uint8_t he_dcm = 0; @@ -301,20 +462,42 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, switch (tlv_tag) { case WIFIRX_PPDU_START_E: + { + struct hal_rx_ppdu_common_info *com_info = &ppdu_info->com_info; + ppdu_info->com_info.ppdu_id = HAL_RX_GET(rx_tlv, RX_PPDU_START_0, PHY_PPDU_ID); /* channel number is set in PHY meta data */ ppdu_info->rx_status.chan_num = - HAL_RX_GET(rx_tlv, RX_PPDU_START_1, - SW_PHY_META_DATA); + (HAL_RX_GET(rx_tlv, RX_PPDU_START_1, + SW_PHY_META_DATA) & 0x0000FFFF); + ppdu_info->rx_status.chan_freq = + (HAL_RX_GET(rx_tlv, RX_PPDU_START_1, + SW_PHY_META_DATA) & 0xFFFF0000)>>16; ppdu_info->com_info.ppdu_timestamp = HAL_RX_GET(rx_tlv, RX_PPDU_START_2, PPDU_START_TIMESTAMP); ppdu_info->rx_status.ppdu_timestamp = ppdu_info->com_info.ppdu_timestamp; ppdu_info->rx_state = HAL_RX_MON_PPDU_START; + + /* If last ppdu_id doesn't match new ppdu_id, + * 1. reset mpdu_cnt + * 2. update last_ppdu_id with new + * 3. reset mpdu fcs bitmap + */ + if (com_info->ppdu_id != com_info->last_ppdu_id) { + com_info->mpdu_cnt = 0; + com_info->last_ppdu_id = + com_info->ppdu_id; + com_info->num_users = 0; + qdf_mem_zero(&com_info->mpdu_fcs_ok_bitmap, + HAL_RX_NUM_WORDS_PER_PPDU_BITMAP * + sizeof(com_info->mpdu_fcs_ok_bitmap[0])); + } break; + } case WIFIRX_PPDU_START_USER_INFO_E: break; @@ -327,7 +510,13 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, ppdu_info->rx_state = HAL_RX_MON_PPDU_END; break; + case WIFIPHYRX_PKT_END_E: + hal_rx_get_rtt_info(hal_soc_hdl, rx_tlv, ppdu_info); + break; + case WIFIRXPCU_PPDU_END_INFO_E: + ppdu_info->rx_status.rx_antenna = + HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_2, RX_ANTENNA); ppdu_info->rx_status.tsft = HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_1, WB_TIMESTAMP_UPPER_32); @@ -337,8 +526,13 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, ppdu_info->rx_status.duration = HAL_RX_GET(rx_tlv, UNIFIED_RXPCU_PPDU_END_INFO_8, RX_PPDU_DURATION); + hal_rx_get_bb_info(hal_soc_hdl, rx_tlv, ppdu_info); break; + /* + * WIFIRX_PPDU_END_USER_STATS_E comes for each user received. + * for MU, based on num users we see this tlv that many times. + */ case WIFIRX_PPDU_END_USER_STATS_E: { unsigned long tid = 0; @@ -367,14 +561,20 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_10, OTHER_MSDU_COUNT); - ppdu_info->rx_status.frame_control_info_valid = - HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_3, - FRAME_CONTROL_INFO_VALID); + if (ppdu_info->sw_frame_group_id + != HAL_MPDU_SW_FRAME_GROUP_NULL_DATA) { + ppdu_info->rx_status.frame_control_info_valid = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_3, + FRAME_CONTROL_INFO_VALID); - if (ppdu_info->rx_status.frame_control_info_valid) - ppdu_info->rx_status.frame_control = - HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_4, - FRAME_CONTROL_FIELD); + if (ppdu_info->rx_status.frame_control_info_valid) + ppdu_info->rx_status.frame_control = + HAL_RX_GET(rx_tlv, + RX_PPDU_END_USER_STATS_4, + FRAME_CONTROL_FIELD); + + hal_get_qos_control(rx_tlv, ppdu_info); + } ppdu_info->rx_status.data_sequence_control_info_valid = HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_3, @@ -402,19 +602,6 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, default: break; } - if (user_id < HAL_MAX_UL_MU_USERS) { - mon_rx_user_status = - &ppdu_info->rx_user_status[user_id]; - - mon_rx_user_status->mcs = - HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_1, - MCS); - mon_rx_user_status->nss = - HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_1, - NSS); - - hal_rx_handle_ofdma_info(rx_tlv, mon_rx_user_status); - } ppdu_info->com_info.mpdu_cnt_fcs_ok = HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_3, @@ -428,10 +615,57 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, else ppdu_info->rx_status.rs_flags &= (~IEEE80211_AMPDU_FLAG); + + ppdu_info->com_info.mpdu_fcs_ok_bitmap[0] = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_7, + FCS_OK_BITMAP_31_0); + + ppdu_info->com_info.mpdu_fcs_ok_bitmap[1] = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_8, + FCS_OK_BITMAP_63_32); + + if (user_id < HAL_MAX_UL_MU_USERS) { + mon_rx_user_status = + &ppdu_info->rx_user_status[user_id]; + + hal_rx_handle_mu_ul_info(rx_tlv, mon_rx_user_status); + + ppdu_info->com_info.num_users++; + + hal_rx_populate_mu_user_info(rx_tlv, ppdu_info, + mon_rx_user_status); + + hal_rx_populate_tx_capture_user_info(ppdu_info, + user_id); + + } break; } case WIFIRX_PPDU_END_USER_STATS_EXT_E: + ppdu_info->com_info.mpdu_fcs_ok_bitmap[2] = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_EXT_1, + FCS_OK_BITMAP_95_64); + + ppdu_info->com_info.mpdu_fcs_ok_bitmap[3] = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_EXT_2, + FCS_OK_BITMAP_127_96); + + ppdu_info->com_info.mpdu_fcs_ok_bitmap[4] = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_EXT_3, + FCS_OK_BITMAP_159_128); + + ppdu_info->com_info.mpdu_fcs_ok_bitmap[5] = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_EXT_4, + FCS_OK_BITMAP_191_160); + + ppdu_info->com_info.mpdu_fcs_ok_bitmap[6] = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_EXT_5, + FCS_OK_BITMAP_223_192); + + ppdu_info->com_info.mpdu_fcs_ok_bitmap[7] = + HAL_RX_GET(rx_tlv, RX_PPDU_END_USER_STATS_EXT_6, + FCS_OK_BITMAP_255_224); break; case WIFIRX_PPDU_END_STATUS_DONE_E: @@ -578,6 +812,7 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, case TARGET_TYPE_QCA8074: case TARGET_TYPE_QCA8074V2: case TARGET_TYPE_QCA6018: + case TARGET_TYPE_QCN9000: #ifdef QCA_WIFI_QCA6390 case TARGET_TYPE_QCA6390: #endif @@ -586,6 +821,7 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, VHT_SIG_A_INFO_0, STBC); value = HAL_RX_GET(vht_sig_a_info, VHT_SIG_A_INFO_0, N_STS); + value = value & VHT_SIG_SU_NSS_MASK; if (ppdu_info->rx_status.is_stbc && (value > 0)) value = ((value + 1) >> 1) - 1; ppdu_info->rx_status.nss = @@ -599,6 +835,7 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, VHT_SIG_A_INFO_0, STBC); value = HAL_RX_GET(vht_sig_a_info, VHT_SIG_A_INFO_0, N_STS); + value = value & VHT_SIG_SU_NSS_MASK; if (ppdu_info->rx_status.is_stbc && (value > 0)) value = ((value + 1) >> 1) - 1; ppdu_info->rx_status.nss = @@ -607,6 +844,10 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, ppdu_info->rx_status.nss = 0; #endif break; + case TARGET_TYPE_QCA6490: + case TARGET_TYPE_QCA6750: + ppdu_info->rx_status.nss = 0; + break; default: break; } @@ -1078,6 +1319,7 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, case WIFIPHYRX_RSSI_LEGACY_E: { uint8_t reception_type; + int8_t rssi_value; uint8_t *rssi_info_tlv = (uint8_t *)rx_tlv + HAL_RX_OFFSET(UNIFIED_PHYRX_RSSI_LEGACY_19, RECEIVE_RSSI_INFO_PREAMBLE_RSSI_INFO_DETAILS); @@ -1092,64 +1334,74 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, RECEPTION_TYPE); switch (reception_type) { case QDF_RECEPTION_TYPE_ULOFMDA: + ppdu_info->rx_status.reception_type = + HAL_RX_TYPE_MU_OFDMA; ppdu_info->rx_status.ulofdma_flag = 1; ppdu_info->rx_status.he_data1 = QDF_MON_STATUS_HE_TRIG_FORMAT_TYPE; break; case QDF_RECEPTION_TYPE_ULMIMO: + ppdu_info->rx_status.reception_type = + HAL_RX_TYPE_MU_MIMO; ppdu_info->rx_status.he_data1 = QDF_MON_STATUS_HE_MU_FORMAT_TYPE; break; default: + ppdu_info->rx_status.reception_type = + HAL_RX_TYPE_SU; break; } - value = HAL_RX_GET(rssi_info_tlv, - RECEIVE_RSSI_INFO_0, RSSI_PRI20_CHAIN0); - ppdu_info->rx_status.rssi[0] = value; + hal_rx_update_rssi_chain(ppdu_info, rssi_info_tlv); + rssi_value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_0, RSSI_PRI20_CHAIN0); + ppdu_info->rx_status.rssi[0] = rssi_value; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "RSSI_PRI20_CHAIN0: %d\n", value); + "RSSI_PRI20_CHAIN0: %d\n", rssi_value); - value = HAL_RX_GET(rssi_info_tlv, - RECEIVE_RSSI_INFO_2, RSSI_PRI20_CHAIN1); - ppdu_info->rx_status.rssi[1] = value; + rssi_value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_2, RSSI_PRI20_CHAIN1); + ppdu_info->rx_status.rssi[1] = rssi_value; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "RSSI_PRI20_CHAIN1: %d\n", value); + "RSSI_PRI20_CHAIN1: %d\n", rssi_value); - value = HAL_RX_GET(rssi_info_tlv, - RECEIVE_RSSI_INFO_4, RSSI_PRI20_CHAIN2); - ppdu_info->rx_status.rssi[2] = value; + rssi_value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_4, RSSI_PRI20_CHAIN2); + ppdu_info->rx_status.rssi[2] = rssi_value; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "RSSI_PRI20_CHAIN2: %d\n", value); + "RSSI_PRI20_CHAIN2: %d\n", rssi_value); - value = HAL_RX_GET(rssi_info_tlv, - RECEIVE_RSSI_INFO_6, RSSI_PRI20_CHAIN3); - ppdu_info->rx_status.rssi[3] = value; + rssi_value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_6, RSSI_PRI20_CHAIN3); + ppdu_info->rx_status.rssi[3] = rssi_value; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "RSSI_PRI20_CHAIN3: %d\n", value); + "RSSI_PRI20_CHAIN3: %d\n", rssi_value); - value = HAL_RX_GET(rssi_info_tlv, - RECEIVE_RSSI_INFO_8, RSSI_PRI20_CHAIN4); - ppdu_info->rx_status.rssi[4] = value; + rssi_value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_8, RSSI_PRI20_CHAIN4); + ppdu_info->rx_status.rssi[4] = rssi_value; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "RSSI_PRI20_CHAIN4: %d\n", value); + "RSSI_PRI20_CHAIN4: %d\n", rssi_value); - value = HAL_RX_GET(rssi_info_tlv, - RECEIVE_RSSI_INFO_10, RSSI_PRI20_CHAIN5); - ppdu_info->rx_status.rssi[5] = value; + rssi_value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_10, + RSSI_PRI20_CHAIN5); + ppdu_info->rx_status.rssi[5] = rssi_value; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "RSSI_PRI20_CHAIN5: %d\n", value); + "RSSI_PRI20_CHAIN5: %d\n", rssi_value); - value = HAL_RX_GET(rssi_info_tlv, - RECEIVE_RSSI_INFO_12, RSSI_PRI20_CHAIN6); - ppdu_info->rx_status.rssi[6] = value; + rssi_value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_12, + RSSI_PRI20_CHAIN6); + ppdu_info->rx_status.rssi[6] = rssi_value; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "RSSI_PRI20_CHAIN1: %d\n", value); + "RSSI_PRI20_CHAIN6: %d\n", rssi_value); - value = HAL_RX_GET(rssi_info_tlv, - RECEIVE_RSSI_INFO_14, RSSI_PRI20_CHAIN7); - ppdu_info->rx_status.rssi[7] = value; + rssi_value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_14, + RSSI_PRI20_CHAIN7); + ppdu_info->rx_status.rssi[7] = rssi_value; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "RSSI_PRI20_CHAIN7: %d\n", value); + "RSSI_PRI20_CHAIN7: %d\n", rssi_value); break; } case WIFIPHYRX_OTHER_RECEIVE_INFO_E: @@ -1157,41 +1409,68 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, ppdu_info); break; case WIFIRX_HEADER_E: + { + struct hal_rx_ppdu_common_info *com_info = &ppdu_info->com_info; + uint16_t mpdu_cnt = com_info->mpdu_cnt; + + if (mpdu_cnt >= HAL_RX_MAX_MPDU) { + hal_alert("Number of MPDUs per PPDU exceeded"); + break; + } + /* Update first_msdu_payload for every mpdu and increment + * com_info->mpdu_cnt for every WIFIRX_HEADER_E TLV + */ + ppdu_info->ppdu_msdu_info[mpdu_cnt].first_msdu_payload = + rx_tlv; + ppdu_info->ppdu_msdu_info[mpdu_cnt].payload_len = tlv_len; + ppdu_info->ppdu_msdu_info[mpdu_cnt].nbuf = nbuf; ppdu_info->msdu_info.first_msdu_payload = rx_tlv; ppdu_info->msdu_info.payload_len = tlv_len; ppdu_info->user_id = user_id; ppdu_info->hdr_len = tlv_len; ppdu_info->data = rx_tlv; ppdu_info->data += 4; + + /* for every RX_HEADER TLV increment mpdu_cnt */ + com_info->mpdu_cnt++; return HAL_TLV_STATUS_HEADER; + } case WIFIRX_MPDU_START_E: { uint8_t *rx_mpdu_start = (uint8_t *)rx_tlv + HAL_RX_OFFSET(UNIFIED_RX_MPDU_START_0, RX_MPDU_INFO_RX_MPDU_INFO_DETAILS); - uint32_t ppdu_id = HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, - PHY_PPDU_ID); + uint32_t ppdu_id = + HAL_RX_GET_PPDU_ID(rx_mpdu_start); uint8_t filter_category = 0; ppdu_info->nac_info.fc_valid = - HAL_RX_GET(rx_mpdu_start, - RX_MPDU_INFO_2, - MPDU_FRAME_CONTROL_VALID); + HAL_RX_GET_FC_VALID(rx_mpdu_start); ppdu_info->nac_info.to_ds_flag = - HAL_RX_GET(rx_mpdu_start, - RX_MPDU_INFO_2, - TO_DS); + HAL_RX_GET_TO_DS_FLAG(rx_mpdu_start); ppdu_info->nac_info.frame_control = HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_14, MPDU_FRAME_CONTROL_FIELD); + ppdu_info->sw_frame_group_id = + HAL_RX_GET_SW_FRAME_GROUP_ID(rx_mpdu_start); + + if (ppdu_info->sw_frame_group_id == + HAL_MPDU_SW_FRAME_GROUP_NULL_DATA) { + ppdu_info->rx_status.frame_control_info_valid = + ppdu_info->nac_info.fc_valid; + ppdu_info->rx_status.frame_control = + ppdu_info->nac_info.frame_control; + } + + hal_get_mac_addr1(rx_mpdu_start, + ppdu_info); + ppdu_info->nac_info.mac_addr2_valid = - HAL_RX_GET(rx_mpdu_start, - RX_MPDU_INFO_2, - MAC_ADDR_AD2_VALID); + HAL_RX_GET_MAC_ADDR2_VALID(rx_mpdu_start); *(uint16_t *)&ppdu_info->nac_info.mac_addr2[0] = HAL_RX_GET(rx_mpdu_start, @@ -1214,14 +1493,18 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, MPDU_LENGTH); } - filter_category = HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, - RXPCU_MPDU_FILTER_IN_CATEGORY); + filter_category = + HAL_RX_GET_FILTER_CATEGORY(rx_mpdu_start); if (filter_category == 0) ppdu_info->rx_status.rxpcu_filter_pass = 1; else if (filter_category == 1) ppdu_info->rx_status.monitor_direct_used = 1; + ppdu_info->nac_info.mcast_bcast = + HAL_RX_GET(rx_mpdu_start, + RX_MPDU_INFO_13, + MCAST_BCAST); break; } case WIFIRX_MPDU_END_E: @@ -1231,8 +1514,18 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, FCS_ERR); return HAL_TLV_STATUS_MPDU_END; case WIFIRX_MSDU_END_E: - ppdu_info->rx_msdu_info[user_id].cce_metadata = - HAL_RX_MSDU_END_CCE_METADATA_GET(rx_tlv); + if (user_id < HAL_MAX_UL_MU_USERS) { + ppdu_info->rx_msdu_info[user_id].cce_metadata = + HAL_RX_MSDU_END_CCE_METADATA_GET(rx_tlv); + ppdu_info->rx_msdu_info[user_id].fse_metadata = + HAL_RX_MSDU_END_FSE_METADATA_GET(rx_tlv); + ppdu_info->rx_msdu_info[user_id].is_flow_idx_timeout = + HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(rx_tlv); + ppdu_info->rx_msdu_info[user_id].is_flow_idx_invalid = + HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(rx_tlv); + ppdu_info->rx_msdu_info[user_id].flow_idx = + HAL_RX_MSDU_END_FLOW_IDX_GET(rx_tlv); + } return HAL_TLV_STATUS_MSDU_END; case 0: return HAL_TLV_STATUS_PPDU_DONE; @@ -1256,101 +1549,6 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, return HAL_TLV_STATUS_PPDU_NOT_DONE; } -/** - * hal_reo_status_get_header_generic - Process reo desc info - * @d - Pointer to reo descriptior - * @b - tlv type info - * @h1 - Pointer to hal_reo_status_header where info to be stored - * - * Return - none. - * - */ -static void hal_reo_status_get_header_generic(uint32_t *d, int b, void *h1) -{ - - uint32_t val1 = 0; - struct hal_reo_status_header *h = - (struct hal_reo_status_header *)h1; - - switch (b) { - case HAL_REO_QUEUE_STATS_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_0, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; - break; - case HAL_REO_FLUSH_QUEUE_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_0, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; - break; - case HAL_REO_FLUSH_CACHE_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_0, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; - break; - case HAL_REO_UNBLK_CACHE_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_0, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; - break; - case HAL_REO_TIMOUT_LIST_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_0, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; - break; - case HAL_REO_DESC_THRES_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_0, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; - break; - case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_0, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; - break; - default: - pr_err("ERROR: Unknown tlv\n"); - break; - } - h->cmd_num = - HAL_GET_FIELD( - UNIFORM_REO_STATUS_HEADER_0, REO_STATUS_NUMBER, - val1); - h->exec_time = - HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, - CMD_EXECUTION_TIME, val1); - h->status = - HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, - REO_CMD_EXECUTION_STATUS, val1); - switch (b) { - case HAL_REO_QUEUE_STATS_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_1, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; - break; - case HAL_REO_FLUSH_QUEUE_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_1, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; - break; - case HAL_REO_FLUSH_CACHE_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_1, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; - break; - case HAL_REO_UNBLK_CACHE_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_1, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; - break; - case HAL_REO_TIMOUT_LIST_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_1, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; - break; - case HAL_REO_DESC_THRES_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_1, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; - break; - case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: - val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_1, - UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; - break; - default: - pr_err("ERROR: Unknown tlv\n"); - break; - } - h->tstamp = - HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_1, TIMESTAMP, val1); -} /** * hal_reo_setup - Initialize HW REO block @@ -1358,28 +1556,16 @@ static void hal_reo_status_get_header_generic(uint32_t *d, int b, void *h1) * @hal_soc: Opaque HAL SOC handle * @reo_params: parameters needed by HAL for REO config */ -static void hal_reo_setup_generic(void *hal_soc, - void *reoparams) +static void hal_reo_setup_generic(struct hal_soc *soc, + void *reoparams) { - struct hal_soc *soc = (struct hal_soc *)hal_soc; uint32_t reg_val; struct hal_reo_params *reo_params = (struct hal_reo_params *)reoparams; reg_val = HAL_REG_READ(soc, HWIO_REO_R0_GENERAL_ENABLE_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET)); - reg_val &= ~(HWIO_REO_R0_GENERAL_ENABLE_FRAGMENT_DEST_RING_BMSK | - HWIO_REO_R0_GENERAL_ENABLE_AGING_LIST_ENABLE_BMSK | - HWIO_REO_R0_GENERAL_ENABLE_AGING_FLUSH_ENABLE_BMSK); - - reg_val |= HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, - FRAGMENT_DEST_RING, reo_params->frag_dst_ring) | - HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, AGING_LIST_ENABLE, 1) | - HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, AGING_FLUSH_ENABLE, 1); - - HAL_REG_WRITE(soc, HWIO_REO_R0_GENERAL_ENABLE_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET), reg_val); - + hal_reo_config(soc, reg_val, reo_params); /* Other ring enable bits and REO_ENABLE will be set by FW */ /* TODO: Setup destination ring mapping if enabled */ @@ -1427,22 +1613,20 @@ static void hal_reo_setup_generic(void *hal_soc, SEQ_WCSS_UMAC_REO_REG_OFFSET), reo_params->remap1); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - FL("HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR 0x%x"), - HAL_REG_READ(soc, - HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET))); + hal_debug("HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR 0x%x", + HAL_REG_READ(soc, + HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET))); HAL_REG_WRITE(soc, HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET), reo_params->remap2); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - FL("HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR 0x%x"), - HAL_REG_READ(soc, - HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET))); + hal_debug("HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR 0x%x", + HAL_REG_READ(soc, + HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET))); } /* TODO: Check if the following registers shoould be setup by host: @@ -1464,21 +1648,22 @@ static void hal_reo_setup_generic(void *hal_soc, * Return: Update tail pointer and head pointer in arguments. */ static inline -void hal_get_hw_hptp_generic(struct hal_soc *soc, void *hal_ring, +void hal_get_hw_hptp_generic(struct hal_soc *hal_soc, + hal_ring_handle_t hal_ring_hdl, uint32_t *headp, uint32_t *tailp, uint8_t ring) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; struct hal_hw_srng_config *ring_config; enum hal_ring_type ring_type = (enum hal_ring_type)ring; - if (!soc || !srng) { + if (!hal_soc || !srng) { QDF_TRACE(QDF_MODULE_ID_HAL, QDF_TRACE_LEVEL_ERROR, "%s: Context is Null", __func__); return; } - ring_config = HAL_SRNG_CONFIG(soc, ring_type); + ring_config = HAL_SRNG_CONFIG(hal_soc, ring_type); if (!ring_config->lmac_ring) { if (srng->ring_dir == HAL_SRNG_SRC_RING) { *headp = SRNG_SRC_REG_READ(srng, HP); @@ -1496,10 +1681,10 @@ void hal_get_hw_hptp_generic(struct hal_soc *soc, void *hal_ring, * @hal_soc: HAL SOC handle * @srng: SRNG ring pointer */ -static inline void hal_srng_src_hw_init_generic(void *halsoc, - struct hal_srng *srng) +static inline +void hal_srng_src_hw_init_generic(struct hal_soc *hal, + struct hal_srng *srng) { - struct hal_soc *hal = (struct hal_soc *)halsoc; uint32_t reg_val = 0; uint64_t tp_addr = 0; @@ -1609,10 +1794,10 @@ static inline void hal_srng_src_hw_init_generic(void *halsoc, * @hal_soc: HAL SOC handle * @srng: SRNG ring pointer */ -static inline void hal_srng_dst_hw_init_generic(void *halsoc, - struct hal_srng *srng) +static inline +void hal_srng_dst_hw_init_generic(struct hal_soc *hal, + struct hal_srng *srng) { - struct hal_soc *hal = (struct hal_soc *)halsoc; uint32_t reg_val = 0; uint64_t hp_addr = 0; @@ -1756,6 +1941,24 @@ static inline uint8_t hal_tx_comp_get_release_reason_generic(void *hal_desc) WBM_RELEASE_RING_2_TQM_RELEASE_REASON_LSB; } +/** + * hal_get_wbm_internal_error_generic() - is WBM internal error + * @hal_desc: completion ring descriptor pointer + * + * This function will return 0 or 1 - is it WBM internal error or not + * + * Return: uint8_t + */ +static inline uint8_t hal_get_wbm_internal_error_generic(void *hal_desc) +{ + uint32_t comp_desc = + *(uint32_t *)(((uint8_t *)hal_desc) + + WBM_RELEASE_RING_2_WBM_INTERNAL_ERROR_OFFSET); + + return (comp_desc & WBM_RELEASE_RING_2_WBM_INTERNAL_ERROR_MASK) >> + WBM_RELEASE_RING_2_WBM_INTERNAL_ERROR_LSB; +} + /** * hal_rx_dump_mpdu_start_tlv_generic: dump RX mpdu_start TLV in structured * human readable format. @@ -2005,6 +2208,33 @@ static void hal_tx_desc_set_search_index_generic(void *desc, } #endif +/** + * hal_tx_desc_set_cache_set_num_generic - Set the cache-set-num value + * @desc: Handle to Tx Descriptor + * @cache_num: Cache set number that should be used to cache the index + * based search results, for address and flow search. + * This value should be equal to LSB four bits of the hash value + * of match data, in case of search index points to an entry + * which may be used in content based search also. The value can + * be anything when the entry pointed by search index will not be + * used for content based search. + * + * Return: void + */ +#ifdef TCL_DATA_CMD_5_CACHE_SET_NUM_OFFSET +static void hal_tx_desc_set_cache_set_num_generic(void *desc, + uint8_t cache_num) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_5, CACHE_SET_NUM) |= + HAL_TX_SM(TCL_DATA_CMD_5, CACHE_SET_NUM, cache_num); +} +#else +static void hal_tx_desc_set_cache_set_num_generic(void *desc, + uint8_t cache_num) +{ +} +#endif + /** * hal_tx_set_pcp_tid_map_generic() - Configure default PCP to TID map table * @soc: HAL SoC context @@ -2016,12 +2246,10 @@ static void hal_tx_desc_set_search_index_generic(void *desc, * * Return: none */ -static void hal_tx_set_pcp_tid_map_generic(void *hal_soc, uint8_t *map) +static void hal_tx_set_pcp_tid_map_generic(struct hal_soc *soc, uint8_t *map) { uint32_t addr, value; - struct hal_soc *soc = (struct hal_soc *)hal_soc; - addr = HWIO_TCL_R0_PCP_TID_MAP_ADDR( SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET); @@ -2047,12 +2275,11 @@ static void hal_tx_set_pcp_tid_map_generic(void *hal_soc, uint8_t *map) * Return: void */ static -void hal_tx_update_pcp_tid_generic(void *hal_soc, uint8_t pcp, uint8_t tid) +void hal_tx_update_pcp_tid_generic(struct hal_soc *soc, + uint8_t pcp, uint8_t tid) { uint32_t addr, value, regval; - struct hal_soc *soc = (struct hal_soc *)hal_soc; - addr = HWIO_TCL_R0_PCP_TID_MAP_ADDR( SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET); @@ -2077,16 +2304,38 @@ void hal_tx_update_pcp_tid_generic(void *hal_soc, uint8_t pcp, uint8_t tid) * Return: void */ static -void hal_tx_update_tidmap_prty_generic(void *hal_soc, uint8_t value) +void hal_tx_update_tidmap_prty_generic(struct hal_soc *soc, uint8_t value) { uint32_t addr; - struct hal_soc *soc = (struct hal_soc *)hal_soc; - addr = HWIO_TCL_R0_TID_MAP_PRTY_ADDR( SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET); HAL_REG_WRITE(soc, addr, (value & HWIO_TCL_R0_TID_MAP_PRTY_RMSK)); } + +/** + * hal_rx_msdu_packet_metadata_get(): API to get the + * msdu information from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * @ hal_rx_msdu_metadata: pointer to the msdu info structure + */ +static void +hal_rx_msdu_packet_metadata_get_generic(uint8_t *buf, + void *pkt_msdu_metadata) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + struct hal_rx_msdu_metadata *msdu_metadata = + (struct hal_rx_msdu_metadata *)pkt_msdu_metadata; + + msdu_metadata->l3_hdr_pad = + HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(msdu_end); + msdu_metadata->sa_idx = HAL_RX_MSDU_END_SA_IDX_GET(msdu_end); + msdu_metadata->da_idx = HAL_RX_MSDU_END_DA_IDX_GET(msdu_end); + msdu_metadata->sa_sw_peer_id = + HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(msdu_end); +} #endif /* _HAL_GENERIC_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_hw_headers.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_hw_headers.h index 89a0f9be3436fe12c1e350f68256abe78b351ec7..49aff583a367982b9c41c3931d3035b0cd2d88d3 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_hw_headers.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_hw_headers.h @@ -38,7 +38,12 @@ #include "mac_tcl_reg_seq_hwioreg.h" #include "ce_src_desc.h" #include "ce_stat_desc.h" +#ifdef QCA_WIFI_QCA6490 +#include "wfss_ce_channel_dst_reg_seq_hwioreg.h" +#include "wfss_ce_channel_src_reg_seq_hwioreg.h" +#else #include "wfss_ce_reg_seq_hwioreg.h" +#endif /* QCA_WIFI_QCA6490 */ #include "wbm_link_descriptor_ring.h" #include "wbm_reg_seq_hwioreg.h" #include "wbm_buffer_ring.h" @@ -57,7 +62,7 @@ #include "rxpcu_ppdu_end_info.h" #include "phyrx_he_sig_a_su.h" #include "phyrx_he_sig_a_mu_dl.h" -#if defined(CONFIG_MCL) && defined(QCA_WIFI_QCA6290_11AX) +#if defined(QCA_WIFI_QCA6290_11AX_MU_UL) && defined(QCA_WIFI_QCA6290_11AX) #include "phyrx_he_sig_a_mu_ul.h" #endif #include "phyrx_he_sig_b1_mu.h" @@ -73,22 +78,19 @@ #include "phyrx_rssi_legacy.h" #include "wcss_version.h" #include "rx_msdu_link.h" +#include "hal_internal.h" #define HAL_SRNG_REO_EXCEPTION HAL_SRNG_REO2SW1 #define HAL_SRNG_REO_ALTERNATE_SELECT 0x7 #define HAL_NON_QOS_TID 16 -/* calculate the register address offset from bar0 of shadow register x */ -#ifdef QCA_WIFI_QCA6390 -#define SHADOW_REGISTER(x) (0x000008FC + (4 * (x))) -#else -#define SHADOW_REGISTER(x) (0x00003024 + (4 * (x))) -#endif - /* TODO: Check if the following can be provided directly by HW headers */ #define SRNG_LOOP_CNT_MASK REO_DESTINATION_RING_15_LOOPING_COUNT_MASK #define SRNG_LOOP_CNT_LSB REO_DESTINATION_RING_15_LOOPING_COUNT_LSB +/* HAL Macro to get the buffer info size */ +#define HAL_RX_BUFFINFO_NUM_DWORDS NUM_OF_DWORDS_BUFFER_ADDR_INFO + #define HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_MS 100 /* milliseconds */ #define HAL_DEFAULT_VO_REO_TIMEOUT_MS 40 /* milliseconds */ @@ -114,6 +116,9 @@ #define HAL_REG_WRITE_CONFIRM(_soc, _reg, _value) \ hal_write32_mb_confirm(_soc, (_reg), (_value)) +#define HAL_REG_WRITE_CONFIRM_RETRY(_soc, _reg, _value, _recovery) \ + hal_write32_mb_confirm_retry(_soc, (_reg), (_value), (_recovery)) + #define HAL_REG_READ(_soc, _offset) \ hal_read32_mb(_soc, (_offset)) @@ -339,8 +344,9 @@ static inline void hal_set_link_desc_addr(void *desc, uint32_t cookie, * @tid: TID number * */ -static inline uint32_t hal_get_reo_qdesc_size(void *hal_soc, - uint32_t ba_window_size, int tid) +static inline +uint32_t hal_get_reo_qdesc_size(hal_soc_handle_t hal_soc_hdl, + uint32_t ba_window_size, int tid) { /* Return descriptor size corresponding to window size of 2 since * we set ba_window_size to 2 while setting up REO descriptors as diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_internal.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_internal.h index aced2ab0fb012f7f1ea3d3ddbb35ddec2bcc7e09..6c796e3764255800676ef9d601b749a83ed16f74 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_internal.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -62,6 +62,11 @@ extern bool is_hal_verbose_debug_enabled; params) #endif +/* + * dp_hal_soc - opaque handle for DP HAL soc + */ +struct hal_soc_handle; +typedef struct hal_soc_handle *hal_soc_handle_t; /* TBD: This should be movded to shared HW header file */ enum hal_srng_ring_id { @@ -178,6 +183,13 @@ enum hal_srng_dir { #define SRNG_LOCK_DESTROY(_lock) qdf_spinlock_destroy(_lock) struct hal_soc; + +/** + * dp_hal_ring - opaque handle for DP HAL SRNG + */ +struct hal_ring_handle; +typedef struct hal_ring_handle *hal_ring_handle_t; + #define MAX_SRNG_REG_GROUPS 2 /* Hal Srng bit mask @@ -195,6 +207,7 @@ struct hal_soc; * @dequeue_val: register value at the time of delayed write dequeue * @valid: whether this entry is valid or not * @enqueue_time: enqueue time (qdf_log_timestamp) + * @work_scheduled_time: work scheduled time (qdf_log_timestamp) * @dequeue_time: dequeue time (qdf_log_timestamp) */ struct hal_reg_write_q_elem { @@ -204,6 +217,7 @@ struct hal_reg_write_q_elem { uint32_t dequeue_val; uint8_t valid; qdf_time_t enqueue_time; + qdf_time_t work_scheduled_time; qdf_time_t dequeue_time; }; @@ -213,12 +227,14 @@ struct hal_reg_write_q_elem { * @dequeues: writes dequeued from delayed work (not written yet) * @coalesces: writes not enqueued since srng is already queued up * @direct: writes not enqueued and written to register directly + * @dequeue_delay: dequeue operation be delayed */ struct hal_reg_write_srng_stats { uint32_t enqueues; uint32_t dequeues; uint32_t coalesces; uint32_t direct; + uint32_t dequeue_delay; }; /** @@ -226,14 +242,14 @@ struct hal_reg_write_srng_stats { * @REG_WRITE_SCHED_DELAY_SUB_100us: index for delay < 100us * @REG_WRITE_SCHED_DELAY_SUB_1000us: index for delay < 1000us * @REG_WRITE_SCHED_DELAY_SUB_5000us: index for delay < 5000us - * @REG_WRITE_SCHED_DELAY_GE_5000us: index for delay >= 5000us + * @REG_WRITE_SCHED_DELAY_GT_5000us: index for delay >= 5000us * @REG_WRITE_SCHED_DELAY_HIST_MAX: Max value (nnsize of histogram array) */ enum hal_reg_sched_delay { REG_WRITE_SCHED_DELAY_SUB_100us, REG_WRITE_SCHED_DELAY_SUB_1000us, REG_WRITE_SCHED_DELAY_SUB_5000us, - REG_WRITE_SCHED_DELAY_GE_5000us, + REG_WRITE_SCHED_DELAY_GT_5000us, REG_WRITE_SCHED_DELAY_HIST_MAX, }; @@ -247,6 +263,7 @@ enum hal_reg_sched_delay { * @q_depth: current queue depth in delayed register write queue * @max_q_depth: maximum queue for delayed register write queue * @sched_delay: = kernel work sched delay + bus wakeup delay, histogram + * @dequeue_delay: dequeue operation be delayed */ struct hal_reg_write_soc_stats { qdf_atomic_t enqueues; @@ -257,6 +274,7 @@ struct hal_reg_write_soc_stats { qdf_atomic_t q_depth; uint32_t max_q_depth; uint32_t sched_delay[REG_WRITE_SCHED_DELAY_HIST_MAX]; + uint32_t dequeue_delay; }; #endif @@ -295,6 +313,9 @@ struct hal_srng { /* Interrupt batch counter threshold – in number of ring entries */ uint32_t intr_batch_cntr_thres_entries; + /* Applicable only for CE dest ring */ + uint32_t prefetch_timer; + /* MSI Address */ qdf_dma_addr_t msi_addr; @@ -373,6 +394,8 @@ struct hal_srng { #ifdef 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 */ + qdf_time_t last_dequeue_time; /* srng specific delayed write stats */ struct hal_reg_write_srng_stats wstats; @@ -392,38 +415,83 @@ struct hal_hw_srng_config { }; #define MAX_SHADOW_REGISTERS 36 +#define MAX_GENERIC_SHADOW_REG 5 + +/** + * struct shadow_reg_config - Hal soc structure that contains + * the list of generic shadow registers + * @target_register: target reg offset + * @shadow_config_index: shadow config index in shadow config + * list sent to FW + * @va: virtual addr of shadow reg + * + * This structure holds the generic registers that are mapped to + * the shadow region and holds the mapping of the target + * register offset to shadow config index provided to FW during + * init + */ +struct shadow_reg_config { + uint32_t target_register; + int shadow_config_index; + uint64_t va; +}; + +/* REO parameters to be passed to hal_reo_setup */ +struct hal_reo_params { + /** rx hash steering enabled or disabled */ + bool rx_hash_enabled; + /** reo remap 1 register */ + uint32_t remap1; + /** reo remap 2 register */ + uint32_t remap2; + /** fragment destination ring */ + uint8_t frag_dst_ring; + /** padding */ + uint8_t padding[3]; +}; struct hal_hw_txrx_ops { /* init and setup */ - void (*hal_srng_dst_hw_init)(void *hal, - struct hal_srng *srng); - void (*hal_srng_src_hw_init)(void *hal, - struct hal_srng *srng); - void (*hal_get_hw_hptp)(struct hal_soc *hal, void *hal_ring, + void (*hal_srng_dst_hw_init)(struct hal_soc *hal, + struct hal_srng *srng); + void (*hal_srng_src_hw_init)(struct hal_soc *hal, + struct hal_srng *srng); + void (*hal_get_hw_hptp)(struct hal_soc *hal, + hal_ring_handle_t hal_ring_hdl, uint32_t *headp, uint32_t *tailp, uint8_t ring_type); - void (*hal_reo_setup)(void *hal_soc, void *reoparams); - void (*hal_setup_link_idle_list)(void *hal_soc, - qdf_dma_addr_t scatter_bufs_base_paddr[], - void *scatter_bufs_base_vaddr[], uint32_t num_scatter_bufs, - uint32_t scatter_buf_size, uint32_t last_buf_end_offset, - uint32_t num_entries); + void (*hal_reo_setup)(struct hal_soc *hal_soc, void *reoparams); + void (*hal_setup_link_idle_list)( + struct hal_soc *hal_soc, + qdf_dma_addr_t scatter_bufs_base_paddr[], + void *scatter_bufs_base_vaddr[], + uint32_t num_scatter_bufs, + uint32_t scatter_buf_size, + uint32_t last_buf_end_offset, + uint32_t num_entries); + qdf_iomem_t (*hal_get_window_address)(struct hal_soc *hal_soc, + qdf_iomem_t addr); void (*hal_reo_set_err_dst_remap)(void *hal_soc); /* tx */ void (*hal_tx_desc_set_dscp_tid_table_id)(void *desc, uint8_t id); - void (*hal_tx_set_dscp_tid_map)(void *hal_soc, uint8_t *map, + void (*hal_tx_set_dscp_tid_map)(struct hal_soc *hal_soc, uint8_t *map, uint8_t id); - void (*hal_tx_update_dscp_tid)(void *hal_soc, uint8_t tid, uint8_t id, + void (*hal_tx_update_dscp_tid)(struct hal_soc *hal_soc, uint8_t tid, + uint8_t id, uint8_t dscp); void (*hal_tx_desc_set_lmac_id)(void *desc, uint8_t lmac_id); void (*hal_tx_desc_set_buf_addr)(void *desc, dma_addr_t paddr, uint8_t pool_id, uint32_t desc_id, uint8_t type); void (*hal_tx_desc_set_search_type)(void *desc, uint8_t search_type); void (*hal_tx_desc_set_search_index)(void *desc, uint32_t search_index); - void (*hal_tx_comp_get_status)(void *desc, void *ts, void *hal); + void (*hal_tx_desc_set_cache_set_num)(void *desc, uint8_t search_index); + void (*hal_tx_comp_get_status)(void *desc, void *ts, + struct hal_soc *hal); uint8_t (*hal_tx_comp_get_release_reason)(void *hal_desc); + uint8_t (*hal_get_wbm_internal_error)(void *hal_desc); + void (*hal_tx_desc_set_mesh_en)(void *desc, uint8_t en); /* rx */ uint32_t (*hal_rx_msdu_start_nss_get)(uint8_t *); @@ -443,23 +511,93 @@ struct hal_hw_txrx_ops { void* (*hal_rx_link_desc_msdu0_ptr)(void *msdu_link_ptr); void (*hal_reo_status_get_header)(uint32_t *d, int b, void *h); uint32_t (*hal_rx_status_get_tlv_info)(void *rx_tlv_hdr, - void *ppdu_info, - void *hal); + void *ppdu_info, + hal_soc_handle_t hal_soc_hdl, + qdf_nbuf_t nbuf); void (*hal_rx_wbm_err_info_get)(void *wbm_desc, void *wbm_er_info); void (*hal_rx_dump_mpdu_start_tlv)(void *mpdustart, uint8_t dbg_level); - void (*hal_tx_set_pcp_tid_map)(void *hal_soc, uint8_t *map); - void (*hal_tx_update_pcp_tid_map)(void *hal_soc, uint8_t pcp, + void (*hal_tx_set_pcp_tid_map)(struct hal_soc *hal_soc, uint8_t *map); + void (*hal_tx_update_pcp_tid_map)(struct hal_soc *hal_soc, uint8_t pcp, uint8_t id); - void (*hal_tx_set_tidmap_prty)(void *hal_soc, uint8_t prio); + void (*hal_tx_set_tidmap_prty)(struct hal_soc *hal_soc, uint8_t prio); + uint8_t (*hal_rx_get_rx_fragment_number)(uint8_t *buf); + uint8_t (*hal_rx_msdu_end_da_is_mcbc_get)(uint8_t *buf); + uint8_t (*hal_rx_msdu_end_sa_is_valid_get)(uint8_t *buf); + uint16_t (*hal_rx_msdu_end_sa_idx_get)(uint8_t *buf); + uint32_t (*hal_rx_desc_is_first_msdu)(void *hw_desc_addr); + uint32_t (*hal_rx_msdu_end_l3_hdr_padding_get)(uint8_t *buf); + uint32_t (*hal_rx_encryption_info_valid)(uint8_t *buf); + void (*hal_rx_print_pn)(uint8_t *buf); + uint8_t (*hal_rx_msdu_end_first_msdu_get)(uint8_t *buf); + uint8_t (*hal_rx_msdu_end_da_is_valid_get)(uint8_t *buf); + uint8_t (*hal_rx_msdu_end_last_msdu_get)(uint8_t *buf); + bool (*hal_rx_get_mpdu_mac_ad4_valid)(uint8_t *buf); + uint32_t (*hal_rx_mpdu_start_sw_peer_id_get)(uint8_t *buf); + uint32_t (*hal_rx_mpdu_get_to_ds)(uint8_t *buf); + uint32_t (*hal_rx_mpdu_get_fr_ds)(uint8_t *buf); + uint8_t (*hal_rx_get_mpdu_frame_control_valid)(uint8_t *buf); + QDF_STATUS + (*hal_rx_mpdu_get_addr1)(uint8_t *buf, uint8_t *mac_addr); + QDF_STATUS + (*hal_rx_mpdu_get_addr2)(uint8_t *buf, uint8_t *mac_addr); + QDF_STATUS + (*hal_rx_mpdu_get_addr3)(uint8_t *buf, uint8_t *mac_addr); + QDF_STATUS + (*hal_rx_mpdu_get_addr4)(uint8_t *buf, uint8_t *mac_addr); + uint8_t (*hal_rx_get_mpdu_sequence_control_valid)(uint8_t *buf); + bool (*hal_rx_is_unicast)(uint8_t *buf); + uint32_t (*hal_rx_tid_get)(hal_soc_handle_t hal_soc_hdl, uint8_t *buf); + uint32_t (*hal_rx_hw_desc_get_ppduid_get)(void *hw_desc_addr); + uint32_t (*hal_rx_mpdu_start_mpdu_qos_control_valid_get)(uint8_t *buf); + uint32_t (*hal_rx_msdu_end_sa_sw_peer_id_get)(uint8_t *buf); + void * (*hal_rx_msdu0_buffer_addr_lsb)(void *link_desc_addr); + void * (*hal_rx_msdu_desc_info_ptr_get)(void *msdu0); + void * (*hal_ent_mpdu_desc_info)(void *hw_addr); + void * (*hal_dst_mpdu_desc_info)(void *hw_addr); + uint8_t (*hal_rx_get_fc_valid)(uint8_t *buf); + uint8_t (*hal_rx_get_to_ds_flag)(uint8_t *buf); + uint8_t (*hal_rx_get_mac_addr2_valid)(uint8_t *buf); + uint8_t (*hal_rx_get_filter_category)(uint8_t *buf); + uint32_t (*hal_rx_get_ppdu_id)(uint8_t *buf); + void (*hal_reo_config)(struct hal_soc *soc, + uint32_t reg_val, + struct hal_reo_params *reo_params); + uint32_t (*hal_rx_msdu_flow_idx_get)(uint8_t *buf); + bool (*hal_rx_msdu_flow_idx_invalid)(uint8_t *buf); + bool (*hal_rx_msdu_flow_idx_timeout)(uint8_t *buf); + uint32_t (*hal_rx_msdu_fse_metadata_get)(uint8_t *buf); + uint16_t (*hal_rx_msdu_cce_metadata_get)(uint8_t *buf); + void + (*hal_rx_msdu_get_flow_params)( + uint8_t *buf, + bool *flow_invalid, + bool *flow_timeout, + uint32_t *flow_index); + uint16_t (*hal_rx_tlv_get_tcp_chksum)(uint8_t *buf); + uint16_t (*hal_rx_get_rx_sequence)(uint8_t *buf); + void (*hal_rx_get_bb_info)(void *rx_tlv, void *ppdu_info_handle); + void (*hal_rx_get_rtt_info)(void *rx_tlv, void *ppdu_info_handle); + void (*hal_rx_msdu_packet_metadata_get)(uint8_t *buf, + void *msdu_pkt_metadata); + uint16_t (*hal_rx_get_fisa_cumulative_l4_checksum)(uint8_t *buf); + uint16_t (*hal_rx_get_fisa_cumulative_ip_length)(uint8_t *buf); + bool (*hal_rx_get_udp_proto)(uint8_t *buf); + bool (*hal_rx_get_fisa_flow_agg_continuation)(uint8_t *buf); + uint8_t (*hal_rx_get_fisa_flow_agg_count)(uint8_t *buf); + bool (*hal_rx_get_fisa_timeout)(uint8_t *buf); + void (*hal_rx_msdu_get_reo_destination_indication)(uint8_t *buf, + uint32_t *reo_destination_indication); }; /** * struct hal_soc_stats - Hal layer stats * @reg_write_fail: number of failed register writes * @wstats: delayed register write stats + * @shadow_reg_write_fail: shadow reg write failure stats + * @shadow_reg_write_succ: shadow reg write success stats * * This structure holds all the statistics at HAL layer. */ @@ -468,6 +606,10 @@ struct hal_soc_stats { #ifdef FEATURE_HAL_DELAYED_REG_WRITE struct hal_reg_write_soc_stats wstats; #endif +#ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE + uint32_t shadow_reg_write_fail; + uint32_t shadow_reg_write_succ; +#endif }; #ifdef ENABLE_HAL_REG_WR_HISTORY @@ -505,12 +647,17 @@ struct hal_reg_write_fail_history { #endif /** - * HAL context to be used to access SRNG APIs (currently used by data path - * and transport (CE) modules) + * struct hal_soc - HAL context to be used to access SRNG APIs + * (currently used by data path and + * transport (CE) modules) + * @list_shadow_reg_config: array of generic regs mapped to + * shadow regs + * @num_generic_shadow_regs_configured: number of generic regs + * mapped to shadow regs */ struct hal_soc { /* HIF handle to access HW registers */ - void *hif_handle; + struct hif_opaque_softc *hif_handle; /* QDF device handle */ qdf_device_t qdf_dev; @@ -543,11 +690,16 @@ struct hal_soc { uint32_t register_window; qdf_spinlock_t register_access_lock; + /* Static window map configuration for multiple window write*/ + bool static_window_map; + /* srng table */ struct hal_hw_srng_config *hw_srng_table; int32_t *hal_hw_reg_offset; struct hal_hw_txrx_ops *ops; + /* Indicate srngs initialization */ + bool init_phase; /* Hal level stats */ struct hal_soc_stats stats; #ifdef ENABLE_HAL_REG_WR_HISTORY @@ -566,6 +718,11 @@ struct hal_soc { uint32_t read_idx; #endif qdf_atomic_t active_work_cnt; +#ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE + struct shadow_reg_config + list_shadow_reg_config[MAX_GENERIC_SHADOW_REG]; + int num_generic_shadow_regs_configured; +#endif }; #ifdef FEATURE_HAL_DELAYED_REG_WRITE @@ -583,7 +740,48 @@ void hal_delayed_reg_write(struct hal_soc *hal_soc, void __iomem *addr, uint32_t value); #endif + +void hal_qca6750_attach(struct hal_soc *hal_soc); +void hal_qca6490_attach(struct hal_soc *hal_soc); void hal_qca6390_attach(struct hal_soc *hal_soc); void hal_qca6290_attach(struct hal_soc *hal_soc); void hal_qca8074_attach(struct hal_soc *hal_soc); + +/* + * hal_soc_to_dp_hal_roc - API to convert hal_soc to opaque + * dp_hal_soc handle type + * @hal_soc - hal_soc type + * + * Return: hal_soc_handle_t type + */ +static inline +hal_soc_handle_t hal_soc_to_hal_soc_handle(struct hal_soc *hal_soc) +{ + return (hal_soc_handle_t)hal_soc; +} + +/* + * hal_srng_to_hal_ring_handle - API to convert hal_srng to opaque + * dp_hal_ring handle type + * @hal_srng - hal_srng type + * + * Return: hal_ring_handle_t type + */ +static inline +hal_ring_handle_t hal_srng_to_hal_ring_handle(struct hal_srng *hal_srng) +{ + return (hal_ring_handle_t)hal_srng; +} + +/* + * hal_ring_handle_to_hal_srng - API to convert dp_hal_ring to hal_srng handle + * @hal_ring - hal_ring_handle_t type + * + * Return: hal_srng pointer type + */ +static inline +struct hal_srng *hal_ring_handle_to_hal_srng(hal_ring_handle_t hal_ring) +{ + return (struct hal_srng *)hal_ring; +} #endif /* _HAL_INTERNAL_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_reo.c b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_reo.c index 97b1d28f2a6826b808b523628f17be2bf43ec04d..6a0b155a022b4b1f7f167134c85d7bb190ce4ec8 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_reo.c +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_reo.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2016-2018, 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -91,9 +92,11 @@ static inline uint32_t hal_update_non_ba_win_size(int tid, * @tid: TID * */ -void hal_reo_qdesc_setup(void *hal_soc, int tid, uint32_t ba_window_size, - uint32_t start_seq, void *hw_qdesc_vaddr, qdf_dma_addr_t hw_qdesc_paddr, - int pn_type) +void hal_reo_qdesc_setup(hal_soc_handle_t hal_soc_hdl, int tid, + uint32_t ba_window_size, + uint32_t start_seq, void *hw_qdesc_vaddr, + qdf_dma_addr_t hw_qdesc_paddr, + int pn_type) { uint32_t *reo_queue_desc = (uint32_t *)hw_qdesc_vaddr; uint32_t *reo_queue_ext_desc; @@ -172,8 +175,10 @@ void hal_reo_qdesc_setup(void *hal_soc, int tid, uint32_t ba_window_size, HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, PN_SHALL_BE_UNEVEN, 1); - HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, PN_HANDLING_ENABLE, - pn_enable); + /* + * TODO: Need to check if PN handling in SW needs to be enabled + * So far this is not a requirement + */ HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, PN_SIZE, pn_size); @@ -273,10 +278,10 @@ qdf_export_symbol(hal_reo_qdesc_setup); * @ac: Access category * @value: window size to get */ -void hal_get_ba_aging_timeout(void *hal_soc, uint8_t ac, +void hal_get_ba_aging_timeout(hal_soc_handle_t hal_soc_hdl, uint8_t ac, uint32_t *value) { - struct hal_soc *soc = (struct hal_soc *)hal_soc; + struct hal_soc *soc = (struct hal_soc *)hal_soc_hdl; switch (ac) { case WME_AC_BE: @@ -315,10 +320,10 @@ qdf_export_symbol(hal_get_ba_aging_timeout); * ac: 0 - Background, 1 - Best Effort, 2 - Video, 3 - Voice * @value: Input value to set */ -void hal_set_ba_aging_timeout(void *hal_soc, uint8_t ac, +void hal_set_ba_aging_timeout(hal_soc_handle_t hal_soc_hdl, uint8_t ac, uint32_t value) { - struct hal_soc *soc = (struct hal_soc *)hal_soc; + struct hal_soc *soc = (struct hal_soc *)hal_soc_hdl; switch (ac) { case WME_AC_BE: @@ -413,18 +418,20 @@ inline void hal_reo_cmd_set_descr_addr(uint32_t *reo_desc, } } -inline int hal_reo_cmd_queue_stats(void *reo_ring, struct hal_soc *soc, - struct hal_reo_cmd_params *cmd) +inline int hal_reo_cmd_queue_stats(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, + struct hal_reo_cmd_params *cmd) { uint32_t *reo_desc, val; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - hal_srng_access_start(soc, reo_ring); - reo_desc = hal_srng_src_get_next(soc, reo_ring); + hal_srng_access_start(hal_soc_hdl, hal_ring_hdl); + reo_desc = hal_srng_src_get_next(hal_soc, hal_ring_hdl); if (!reo_desc) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "%s: Out of cmd ring entries", __func__); - hal_srng_access_end(soc, reo_ring); + hal_srng_access_end(hal_soc, hal_ring_hdl); return -EBUSY; } @@ -434,7 +441,7 @@ inline int hal_reo_cmd_queue_stats(void *reo_ring, struct hal_soc *soc, /* Offsets of descriptor fields defined in HW headers start from * the field after TLV header */ reo_desc += (sizeof(struct tlv_32_hdr) >> 2); - qdf_mem_zero((void *)(reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), + qdf_mem_zero((reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), sizeof(struct reo_get_queue_stats) - (NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER << 2)); @@ -448,15 +455,15 @@ inline int hal_reo_cmd_queue_stats(void *reo_ring, struct hal_soc *soc, HAL_DESC_SET_FIELD(reo_desc, REO_GET_QUEUE_STATS_2, CLEAR_STATS, cmd->u.stats_params.clear); - if (hif_pm_runtime_get(soc->hif_handle, + if (hif_pm_runtime_get(hal_soc->hif_handle, RTPM_ID_HAL_REO_CMD) == 0) { - hal_srng_access_end(soc, reo_ring); - hif_pm_runtime_put(soc->hif_handle, + hal_srng_access_end(hal_soc_hdl, hal_ring_hdl); + hif_pm_runtime_put(hal_soc->hif_handle, RTPM_ID_HAL_REO_CMD); } else { - hal_srng_access_end_reap(soc, reo_ring); - hal_srng_set_event(reo_ring, HAL_SRNG_FLUSH_EVENT); - hal_srng_inc_flush_cnt(reo_ring); + hal_srng_access_end_reap(hal_soc_hdl, hal_ring_hdl); + hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT); + hal_srng_inc_flush_cnt(hal_ring_hdl); } val = reo_desc[CMD_HEADER_DW_OFFSET]; @@ -465,17 +472,19 @@ inline int hal_reo_cmd_queue_stats(void *reo_ring, struct hal_soc *soc, } qdf_export_symbol(hal_reo_cmd_queue_stats); -inline int hal_reo_cmd_flush_queue(void *reo_ring, struct hal_soc *soc, - struct hal_reo_cmd_params *cmd) +inline int hal_reo_cmd_flush_queue(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, + struct hal_reo_cmd_params *cmd) { uint32_t *reo_desc, val; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - hal_srng_access_start(soc, reo_ring); - reo_desc = hal_srng_src_get_next(soc, reo_ring); + hal_srng_access_start(hal_soc_hdl, hal_ring_hdl); + reo_desc = hal_srng_src_get_next(hal_soc, hal_ring_hdl); if (!reo_desc) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "%s: Out of cmd ring entries", __func__); - hal_srng_access_end(soc, reo_ring); + hal_srng_access_end(hal_soc, hal_ring_hdl); return -EBUSY; } @@ -485,7 +494,7 @@ inline int hal_reo_cmd_flush_queue(void *reo_ring, struct hal_soc *soc, /* Offsets of descriptor fields defined in HW headers start from * the field after TLV header */ reo_desc += (sizeof(struct tlv_32_hdr) >> 2); - qdf_mem_zero((void *)(reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), + qdf_mem_zero((reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), sizeof(struct reo_flush_queue) - (NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER << 2)); @@ -504,43 +513,45 @@ inline int hal_reo_cmd_flush_queue(void *reo_ring, struct hal_soc *soc, BLOCK_RESOURCE_INDEX, cmd->u.fl_queue_params.index); } - hal_srng_access_end(soc, reo_ring); + hal_srng_access_end(hal_soc, hal_ring_hdl); val = reo_desc[CMD_HEADER_DW_OFFSET]; return HAL_GET_FIELD(UNIFORM_REO_CMD_HEADER_0, REO_CMD_NUMBER, val); } qdf_export_symbol(hal_reo_cmd_flush_queue); -inline int hal_reo_cmd_flush_cache(void *reo_ring, struct hal_soc *soc, - struct hal_reo_cmd_params *cmd) +inline int hal_reo_cmd_flush_cache(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, + struct hal_reo_cmd_params *cmd) { uint32_t *reo_desc, val; struct hal_reo_cmd_flush_cache_params *cp; uint8_t index = 0; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; cp = &cmd->u.fl_cache_params; - hal_srng_access_start(soc, reo_ring); + hal_srng_access_start(hal_soc_hdl, hal_ring_hdl); /* We need a cache block resource for this operation, and REO HW has * only 4 such blocking resources. These resources are managed using * reo_res_bitmap, and we return failure if none is available. */ if (cp->block_use_after_flush) { - index = hal_find_zero_bit(soc->reo_res_bitmap); + index = hal_find_zero_bit(hal_soc->reo_res_bitmap); if (index > 3) { qdf_print("%s, No blocking resource available!", __func__); - hal_srng_access_end(soc, reo_ring); + hal_srng_access_end(hal_soc, hal_ring_hdl); return -EBUSY; } - soc->index = index; + hal_soc->index = index; } - reo_desc = hal_srng_src_get_next(soc, reo_ring); + reo_desc = hal_srng_src_get_next(hal_soc, hal_ring_hdl); if (!reo_desc) { - hal_srng_access_end(soc, reo_ring); - hal_srng_dump(reo_ring); + hal_srng_access_end(hal_soc, hal_ring_hdl); + hal_srng_dump(hal_ring_handle_to_hal_srng(hal_ring_hdl)); return -EBUSY; } @@ -550,7 +561,7 @@ inline int hal_reo_cmd_flush_cache(void *reo_ring, struct hal_soc *soc, /* Offsets of descriptor fields defined in HW headers start from * the field after TLV header */ reo_desc += (sizeof(struct tlv_32_hdr) >> 2); - qdf_mem_zero((void *)(reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), + qdf_mem_zero((reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), sizeof(struct reo_flush_cache) - (NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER << 2)); @@ -580,17 +591,17 @@ inline int hal_reo_cmd_flush_cache(void *reo_ring, struct hal_soc *soc, BLOCK_CACHE_USAGE_AFTER_FLUSH, cp->block_use_after_flush); HAL_DESC_SET_FIELD(reo_desc, REO_FLUSH_CACHE_2, FLUSH_ENTIRE_CACHE, - cp->flush_all); + cp->flush_entire_cache); - if (hif_pm_runtime_get(soc->hif_handle, + if (hif_pm_runtime_get(hal_soc->hif_handle, RTPM_ID_HAL_REO_CMD) == 0) { - hal_srng_access_end(soc, reo_ring); - hif_pm_runtime_put(soc->hif_handle, + hal_srng_access_end(hal_soc_hdl, hal_ring_hdl); + hif_pm_runtime_put(hal_soc->hif_handle, RTPM_ID_HAL_REO_CMD); } else { - hal_srng_access_end_reap(soc, reo_ring); - hal_srng_set_event(reo_ring, HAL_SRNG_FLUSH_EVENT); - hal_srng_inc_flush_cnt(reo_ring); + hal_srng_access_end_reap(hal_soc_hdl, hal_ring_hdl); + hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT); + hal_srng_inc_flush_cnt(hal_ring_hdl); } val = reo_desc[CMD_HEADER_DW_OFFSET]; @@ -599,30 +610,32 @@ inline int hal_reo_cmd_flush_cache(void *reo_ring, struct hal_soc *soc, } qdf_export_symbol(hal_reo_cmd_flush_cache); -inline int hal_reo_cmd_unblock_cache(void *reo_ring, struct hal_soc *soc, - struct hal_reo_cmd_params *cmd) +inline int hal_reo_cmd_unblock_cache(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, + struct hal_reo_cmd_params *cmd) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; uint32_t *reo_desc, val; uint8_t index = 0; - hal_srng_access_start(soc, reo_ring); + hal_srng_access_start(hal_soc_hdl, hal_ring_hdl); if (cmd->u.unblk_cache_params.type == UNBLOCK_RES_INDEX) { - index = hal_find_one_bit(soc->reo_res_bitmap); + index = hal_find_one_bit(hal_soc->reo_res_bitmap); if (index > 3) { - hal_srng_access_end(soc, reo_ring); + hal_srng_access_end(hal_soc, hal_ring_hdl); qdf_print("%s: No blocking resource to unblock!", __func__); return -EBUSY; } } - reo_desc = hal_srng_src_get_next(soc, reo_ring); + reo_desc = hal_srng_src_get_next(hal_soc, hal_ring_hdl); if (!reo_desc) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "%s: Out of cmd ring entries", __func__); - hal_srng_access_end(soc, reo_ring); + hal_srng_access_end(hal_soc, hal_ring_hdl); return -EBUSY; } @@ -632,7 +645,7 @@ inline int hal_reo_cmd_unblock_cache(void *reo_ring, struct hal_soc *soc, /* Offsets of descriptor fields defined in HW headers start from * the field after TLV header */ reo_desc += (sizeof(struct tlv_32_hdr) >> 2); - qdf_mem_zero((void *)(reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), + qdf_mem_zero((reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), sizeof(struct reo_unblock_cache) - (NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER << 2)); @@ -648,24 +661,26 @@ inline int hal_reo_cmd_unblock_cache(void *reo_ring, struct hal_soc *soc, cmd->u.unblk_cache_params.index); } - hal_srng_access_end(soc, reo_ring); + hal_srng_access_end(hal_soc, hal_ring_hdl); val = reo_desc[CMD_HEADER_DW_OFFSET]; return HAL_GET_FIELD(UNIFORM_REO_CMD_HEADER_0, REO_CMD_NUMBER, val); } qdf_export_symbol(hal_reo_cmd_unblock_cache); -inline int hal_reo_cmd_flush_timeout_list(void *reo_ring, struct hal_soc *soc, - struct hal_reo_cmd_params *cmd) +inline int hal_reo_cmd_flush_timeout_list(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, + struct hal_reo_cmd_params *cmd) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; uint32_t *reo_desc, val; - hal_srng_access_start(soc, reo_ring); - reo_desc = hal_srng_src_get_next(soc, reo_ring); + hal_srng_access_start(hal_soc_hdl, hal_ring_hdl); + reo_desc = hal_srng_src_get_next(hal_soc, hal_ring_hdl); if (!reo_desc) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "%s: Out of cmd ring entries", __func__); - hal_srng_access_end(soc, reo_ring); + hal_srng_access_end(hal_soc, hal_ring_hdl); return -EBUSY; } @@ -675,7 +690,7 @@ inline int hal_reo_cmd_flush_timeout_list(void *reo_ring, struct hal_soc *soc, /* Offsets of descriptor fields defined in HW headers start from * the field after TLV header */ reo_desc += (sizeof(struct tlv_32_hdr) >> 2); - qdf_mem_zero((void *)(reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), + qdf_mem_zero((reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), sizeof(struct reo_flush_timeout_list) - (NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER << 2)); @@ -693,27 +708,29 @@ inline int hal_reo_cmd_flush_timeout_list(void *reo_ring, struct hal_soc *soc, MINIMUM_FORWARD_BUF_COUNT, cmd->u.fl_tim_list_params.min_fwd_buf); - hal_srng_access_end(soc, reo_ring); + hal_srng_access_end(hal_soc, hal_ring_hdl); val = reo_desc[CMD_HEADER_DW_OFFSET]; return HAL_GET_FIELD(UNIFORM_REO_CMD_HEADER_0, REO_CMD_NUMBER, val); } qdf_export_symbol(hal_reo_cmd_flush_timeout_list); -inline int hal_reo_cmd_update_rx_queue(void *reo_ring, struct hal_soc *soc, - struct hal_reo_cmd_params *cmd) +inline int hal_reo_cmd_update_rx_queue(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, + struct hal_reo_cmd_params *cmd) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; uint32_t *reo_desc, val; struct hal_reo_cmd_update_queue_params *p; p = &cmd->u.upd_queue_params; - hal_srng_access_start(soc, reo_ring); - reo_desc = hal_srng_src_get_next(soc, reo_ring); + hal_srng_access_start(hal_soc_hdl, hal_ring_hdl); + reo_desc = hal_srng_src_get_next(hal_soc, hal_ring_hdl); if (!reo_desc) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "%s: Out of cmd ring entries", __func__); - hal_srng_access_end(soc, reo_ring); + hal_srng_access_end(hal_soc, hal_ring_hdl); return -EBUSY; } @@ -723,7 +740,7 @@ inline int hal_reo_cmd_update_rx_queue(void *reo_ring, struct hal_soc *soc, /* Offsets of descriptor fields defined in HW headers start from * the field after TLV header */ reo_desc += (sizeof(struct tlv_32_hdr) >> 2); - qdf_mem_zero((void *)(reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), + qdf_mem_zero((reo_desc + NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER), sizeof(struct reo_update_rx_reo_queue) - (NUM_OF_DWORDS_UNIFORM_REO_CMD_HEADER << 2)); @@ -901,15 +918,15 @@ inline int hal_reo_cmd_update_rx_queue(void *reo_ring, struct hal_soc *soc, HAL_DESC_SET_FIELD(reo_desc, REO_UPDATE_RX_REO_QUEUE_8, PN_127_96, p->pn_127_96); - if (hif_pm_runtime_get(soc->hif_handle, + if (hif_pm_runtime_get(hal_soc->hif_handle, RTPM_ID_HAL_REO_CMD) == 0) { - hal_srng_access_end(soc, reo_ring); - hif_pm_runtime_put(soc->hif_handle, + hal_srng_access_end(hal_soc_hdl, hal_ring_hdl); + hif_pm_runtime_put(hal_soc->hif_handle, RTPM_ID_HAL_REO_CMD); } else { - hal_srng_access_end_reap(soc, reo_ring); - hal_srng_set_event(reo_ring, HAL_SRNG_FLUSH_EVENT); - hal_srng_inc_flush_cnt(reo_ring); + hal_srng_access_end_reap(hal_soc_hdl, hal_ring_hdl); + hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT); + hal_srng_inc_flush_cnt(hal_ring_hdl); } val = reo_desc[CMD_HEADER_DW_OFFSET]; @@ -918,10 +935,12 @@ inline int hal_reo_cmd_update_rx_queue(void *reo_ring, struct hal_soc *soc, } qdf_export_symbol(hal_reo_cmd_update_rx_queue); -inline void hal_reo_queue_stats_status(uint32_t *reo_desc, - struct hal_reo_queue_status *st, - struct hal_soc *hal_soc) +inline void +hal_reo_queue_stats_status(uint32_t *reo_desc, + struct hal_reo_queue_status *st, + hal_soc_handle_t hal_soc_hdl) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; uint32_t val; /* Offsets of descriptor fields defined in HW headers start @@ -1111,10 +1130,12 @@ inline void hal_reo_queue_stats_status(uint32_t *reo_desc, } qdf_export_symbol(hal_reo_queue_stats_status); -inline void hal_reo_flush_queue_status(uint32_t *reo_desc, - struct hal_reo_flush_queue_status *st, - struct hal_soc *hal_soc) +inline void +hal_reo_flush_queue_status(uint32_t *reo_desc, + struct hal_reo_flush_queue_status *st, + hal_soc_handle_t hal_soc_hdl) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; uint32_t val; /* Offsets of descriptor fields defined in HW headers start @@ -1133,10 +1154,12 @@ inline void hal_reo_flush_queue_status(uint32_t *reo_desc, } qdf_export_symbol(hal_reo_flush_queue_status); -inline void hal_reo_flush_cache_status(uint32_t *reo_desc, struct hal_soc *soc, - struct hal_reo_flush_cache_status *st, - struct hal_soc *hal_soc) +inline void +hal_reo_flush_cache_status(uint32_t *reo_desc, + struct hal_reo_flush_cache_status *st, + hal_soc_handle_t hal_soc_hdl) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; uint32_t val; /* Offsets of descriptor fields defined in HW headers start @@ -1160,7 +1183,8 @@ inline void hal_reo_flush_cache_status(uint32_t *reo_desc, struct hal_soc *soc, BLOCK_ERROR_DETAILS, val); if (!st->block_error) - qdf_set_bit(soc->index, (unsigned long *)&soc->reo_res_bitmap); + qdf_set_bit(hal_soc->index, + (unsigned long *)&hal_soc->reo_res_bitmap); /* cache flush status */ val = reo_desc[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_2, @@ -1189,9 +1213,10 @@ inline void hal_reo_flush_cache_status(uint32_t *reo_desc, struct hal_soc *soc, qdf_export_symbol(hal_reo_flush_cache_status); inline void hal_reo_unblock_cache_status(uint32_t *reo_desc, - struct hal_soc *soc, + hal_soc_handle_t hal_soc_hdl, struct hal_reo_unblk_cache_status *st) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; uint32_t val; /* Offsets of descriptor fields defined in HW headers start @@ -1200,7 +1225,7 @@ inline void hal_reo_unblock_cache_status(uint32_t *reo_desc, /* header */ hal_reo_status_get_header(reo_desc, HAL_REO_UNBLK_CACHE_STATUS_TLV, - &(st->header), soc); + &st->header, hal_soc); /* error bit */ val = reo_desc[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_2, @@ -1217,17 +1242,18 @@ inline void hal_reo_unblock_cache_status(uint32_t *reo_desc, val); if (!st->error && (st->unblock_type == UNBLOCK_RES_INDEX)) - qdf_clear_bit(soc->index, - (unsigned long *)&soc->reo_res_bitmap); + qdf_clear_bit(hal_soc->index, + (unsigned long *)&hal_soc->reo_res_bitmap); } qdf_export_symbol(hal_reo_unblock_cache_status); inline void hal_reo_flush_timeout_list_status( uint32_t *reo_desc, struct hal_reo_flush_timeout_list_status *st, - struct hal_soc *hal_soc) + hal_soc_handle_t hal_soc_hdl) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; uint32_t val; /* Offsets of descriptor fields defined in HW headers start @@ -1271,8 +1297,9 @@ qdf_export_symbol(hal_reo_flush_timeout_list_status); inline void hal_reo_desc_thres_reached_status( uint32_t *reo_desc, struct hal_reo_desc_thres_reached_status *st, - struct hal_soc *hal_soc) + hal_soc_handle_t hal_soc_hdl) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; uint32_t val; /* Offsets of descriptor fields defined in HW headers start @@ -1328,10 +1355,13 @@ inline void hal_reo_desc_thres_reached_status( } qdf_export_symbol(hal_reo_desc_thres_reached_status); -inline void hal_reo_rx_update_queue_status(uint32_t *reo_desc, - struct hal_reo_update_rx_queue_status *st, - struct hal_soc *hal_soc) +inline void +hal_reo_rx_update_queue_status(uint32_t *reo_desc, + struct hal_reo_update_rx_queue_status *st, + hal_soc_handle_t hal_soc_hdl) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + /* Offsets of descriptor fields defined in HW headers start * from the field after TLV header */ reo_desc += (sizeof(struct tlv_32_hdr) >> 2); @@ -1351,15 +1381,17 @@ qdf_export_symbol(hal_reo_rx_update_queue_status); * * Return: none */ -inline void hal_reo_init_cmd_ring(struct hal_soc *soc, void *hal_srng) +inline void hal_reo_init_cmd_ring(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { int cmd_num; uint32_t *desc_addr; struct hal_srng_params srng_params; uint32_t desc_size; uint32_t num_desc; + struct hal_soc *soc = (struct hal_soc *)hal_soc_hdl; - hal_get_srng_params(soc, hal_srng, &srng_params); + hal_get_srng_params(hal_soc_hdl, hal_ring_hdl, &srng_params); desc_addr = (uint32_t *)(srng_params.ring_base_vaddr); desc_addr += (sizeof(struct tlv_32_hdr) >> 2); diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_reo.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_reo.h index c9b1265afa199593a5fbe1ab4933ddf0333a05fd..e6d4ba1fede6810aea743829afd0de0cdcff9139 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_reo.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_reo.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -179,7 +180,7 @@ struct hal_reo_cmd_flush_queue_params { * @cache_block_res_index: Blocking resource to be used * @flush_no_inval: Flush without invalidatig descriptor * @use_after_flush: Block usage after flush till unblock command - * @flush_all: Flush entire REO cache + * @flush_entire_cache: Flush entire REO cache */ struct hal_reo_cmd_flush_cache_params { bool fwd_mpdus_in_queue; @@ -187,7 +188,7 @@ struct hal_reo_cmd_flush_cache_params { uint8_t cache_block_res_index; bool flush_no_inval; bool block_use_after_flush; - bool flush_all; + bool flush_entire_cache; }; /** @@ -496,43 +497,51 @@ void hal_reo_cmd_set_descr_addr(uint32_t *reo_desc, enum hal_reo_cmd_type type, uint32_t paddr_lo, uint8_t paddr_hi); -int hal_reo_cmd_queue_stats(void *reo_ring, struct hal_soc *soc, +int hal_reo_cmd_queue_stats(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, struct hal_reo_cmd_params *cmd); -int hal_reo_cmd_flush_queue(void *reo_ring, struct hal_soc *soc, +int hal_reo_cmd_flush_queue(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, struct hal_reo_cmd_params *cmd); -int hal_reo_cmd_flush_cache(void *reo_ring, struct hal_soc *soc, +int hal_reo_cmd_flush_cache(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, struct hal_reo_cmd_params *cmd); -int hal_reo_cmd_unblock_cache(void *reo_ring, struct hal_soc *soc, +int hal_reo_cmd_unblock_cache(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, struct hal_reo_cmd_params *cmd); -int hal_reo_cmd_flush_timeout_list(void *reo_ring, struct hal_soc *soc, +int hal_reo_cmd_flush_timeout_list(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, struct hal_reo_cmd_params *cmd); -int hal_reo_cmd_update_rx_queue(void *reo_ring, struct hal_soc *soc, +int hal_reo_cmd_update_rx_queue(hal_ring_handle_t hal_ring_hdl, + hal_soc_handle_t hal_soc_hdl, struct hal_reo_cmd_params *cmd); /* REO status ring routines */ void hal_reo_queue_stats_status(uint32_t *reo_desc, struct hal_reo_queue_status *st, - struct hal_soc *hal_soc); + hal_soc_handle_t hal_soc_hdl); void hal_reo_flush_queue_status(uint32_t *reo_desc, - struct hal_reo_flush_queue_status *st, - struct hal_soc *hal_soc); -void hal_reo_flush_cache_status(uint32_t *reo_desc, struct hal_soc *soc, - struct hal_reo_flush_cache_status *st, - struct hal_soc *hal_soc); -void hal_reo_unblock_cache_status(uint32_t *reo_desc, struct hal_soc *soc, - struct hal_reo_unblk_cache_status *st); + struct hal_reo_flush_queue_status *st, + hal_soc_handle_t hal_soc_hdl); +void hal_reo_flush_cache_status(uint32_t *reo_desc, + struct hal_reo_flush_cache_status *st, + hal_soc_handle_t hal_soc_hdl); +void hal_reo_unblock_cache_status(uint32_t *reo_desc, + hal_soc_handle_t hal_soc_hdl, + struct hal_reo_unblk_cache_status *st); void hal_reo_flush_timeout_list_status( uint32_t *reo_desc, struct hal_reo_flush_timeout_list_status *st, - struct hal_soc *hal_soc); + hal_soc_handle_t hal_soc_hdl); void hal_reo_desc_thres_reached_status( uint32_t *reo_desc, struct hal_reo_desc_thres_reached_status *st, - struct hal_soc *hal_soc); + hal_soc_handle_t hal_soc_hdl); void hal_reo_rx_update_queue_status(uint32_t *reo_desc, struct hal_reo_update_rx_queue_status *st, - struct hal_soc *hal_soc); + hal_soc_handle_t hal_soc_hdl); -void hal_reo_init_cmd_ring(struct hal_soc *soc, void *hal_srng); +void hal_reo_init_cmd_ring(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl); #endif /* _HAL_REO_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_rx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_rx.h index d49fba1e46275259e2146bd2ed4139b9e9f28011..2de9b90d51f41e876ba986f76fcd0a7598af276b 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_rx.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_rx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -19,7 +19,7 @@ #ifndef _HAL_RX_H_ #define _HAL_RX_H_ -#include +#include #define HAL_RX_OFFSET(block, field) block##_##field##_OFFSET #define HAL_RX_LSB(block, field) block##_##field##_LSB @@ -30,16 +30,18 @@ HAL_RX_MASk(block, field)) >> \ HAL_RX_LSB(block, field)) -#ifdef NO_RX_PKT_HDR_TLV -/* RX_BUFFER_SIZE = 1536 data bytes + 256 RX TLV bytes. We are avoiding - * 128 bytes of RX_PKT_HEADER_TLV. - */ -#define RX_BUFFER_SIZE 1792 -#else -/* RX_BUFFER_SIZE = 1536 data bytes + 384 RX TLV bytes + some spare bytes */ -#define RX_BUFFER_SIZE 2048 +/* BUFFER_SIZE = 1536 data bytes + 384 RX TLV bytes + some spare bytes */ +#ifndef RX_DATA_BUFFER_SIZE +#define RX_DATA_BUFFER_SIZE 2048 +#endif + +#ifndef RX_MONITOR_BUFFER_SIZE +#define RX_MONITOR_BUFFER_SIZE 2048 #endif +/* HAL_RX_NON_QOS_TID = NON_QOS_TID which is 16 */ +#define HAL_RX_NON_QOS_TID 16 + enum { HAL_HW_RX_DECAP_FORMAT_RAW = 0, HAL_HW_RX_DECAP_FORMAT_NWIFI, @@ -70,6 +72,22 @@ struct hal_wbm_err_desc_info { reserved_2:3; }; +/** + * struct hal_rx_msdu_metadata:Structure to hold rx fast path information. + * + * @l3_hdr_pad: l3 header padding + * @reserved: Reserved bits + * @sa_sw_peer_id: sa sw peer id + * @sa_idx: sa index + * @da_idx: da index + */ +struct hal_rx_msdu_metadata { + uint32_t l3_hdr_pad:16, + sa_sw_peer_id:16; + uint32_t sa_idx:16, + da_idx:16; +}; + /** * enum hal_reo_error_code: Enum which encapsulates "reo_push_reason" * @@ -128,12 +146,14 @@ enum hal_rx_msdu_desc_flags { * [2] AMPDU flag * [3] raw_ampdu * @peer_meta_data: Upper bits containing peer id, vdev id + * @bar_frame: indicates if received frame is a bar frame */ struct hal_rx_mpdu_desc_info { uint16_t msdu_count; uint16_t mpdu_seq; /* 12 bits for length */ uint32_t mpdu_flags; uint32_t peer_meta_data; /* sw progamed meta-data:MAC Id & peer Id */ + uint16_t bar_frame; }; /** @@ -209,6 +229,24 @@ enum hal_rx_ret_buf_manager { (paddr_hi << BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_LSB) & \ BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_MASK) +#define HAL_RX_COOKIE_INVALID_MASK 0x80000000 + +/* + * macro to get the invalid bit for sw cookie + */ +#define HAL_RX_BUF_COOKIE_INVALID_GET(buff_addr_info) \ + ((*(((unsigned int *) buff_addr_info) + \ + (BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_OFFSET >> 2))) & \ + HAL_RX_COOKIE_INVALID_MASK) + +/* + * macro to set the invalid bit for sw cookie + */ +#define HAL_RX_BUF_COOKIE_INVALID_SET(buff_addr_info) \ + ((*(((unsigned int *) buff_addr_info) + \ + (BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_OFFSET >> 2))) |= \ + HAL_RX_COOKIE_INVALID_MASK) + /* * macro to set the cookie into the rxdma ring entry */ @@ -263,6 +301,28 @@ enum hal_rx_ret_buf_manager { BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_MASK, \ BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_LSB)) +#define HAL_RX_LINK_COOKIE_INVALID_MASK 0x40000000 + +#define HAL_RX_BUF_LINK_COOKIE_INVALID_GET(buff_addr_info) \ + ((*(((unsigned int *)buff_addr_info) + \ + (BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_OFFSET >> 2))) & \ + HAL_RX_LINK_COOKIE_INVALID_MASK) + +#define HAL_RX_BUF_LINK_COOKIE_INVALID_SET(buff_addr_info) \ + ((*(((unsigned int *)buff_addr_info) + \ + (BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_OFFSET >> 2))) |= \ + HAL_RX_LINK_COOKIE_INVALID_MASK) + +#define HAL_RX_REO_BUF_LINK_COOKIE_INVALID_GET(reo_desc) \ + (HAL_RX_BUF_LINK_COOKIE_INVALID_GET(& \ + (((struct reo_destination_ring *) \ + reo_desc)->buf_or_link_desc_addr_info))) + +#define HAL_RX_REO_BUF_LINK_COOKIE_INVALID_SET(reo_desc) \ + (HAL_RX_BUF_LINK_COOKIE_INVALID_SET(& \ + (((struct reo_destination_ring *) \ + reo_desc)->buf_or_link_desc_addr_info))) + /* TODO: Convert the following structure fields accesseses to offsets */ #define HAL_RX_REO_BUFFER_ADDR_39_32_GET(reo_desc) \ @@ -275,6 +335,16 @@ enum hal_rx_ret_buf_manager { (((struct reo_destination_ring *) \ reo_desc)->buf_or_link_desc_addr_info))) +#define HAL_RX_REO_BUF_COOKIE_INVALID_GET(reo_desc) \ + (HAL_RX_BUF_COOKIE_INVALID_GET(& \ + (((struct reo_destination_ring *) \ + reo_desc)->buf_or_link_desc_addr_info))) + +#define HAL_RX_REO_BUF_COOKIE_INVALID_SET(reo_desc) \ + (HAL_RX_BUF_COOKIE_INVALID_SET(& \ + (((struct reo_destination_ring *) \ + reo_desc)->buf_or_link_desc_addr_info))) + #define HAL_RX_REO_BUF_COOKIE_GET(reo_desc) \ (HAL_RX_BUF_COOKIE_GET(& \ (((struct reo_destination_ring *) \ @@ -319,6 +389,11 @@ enum hal_rx_ret_buf_manager { HAL_RX_MPDU_AMPDU_FLAG_GET(mpdu_info_ptr) | \ HAL_RX_MPDU_RAW_MPDU_GET(mpdu_info_ptr)) +#define HAL_RX_MPDU_BAR_FRAME_GET(mpdu_info_ptr) \ + ((mpdu_info_ptr[RX_MPDU_DESC_INFO_0_BAR_FRAME_OFFSET >> 2] & \ + RX_MPDU_DESC_INFO_0_BAR_FRAME_MASK) >> \ + RX_MPDU_DESC_INFO_0_BAR_FRAME_LSB) + #define HAL_RX_MSDU_PKT_LENGTH_GET(msdu_info_ptr) \ (_HAL_MS((*_OFFSET_TO_WORD_PTR(msdu_info_ptr, \ @@ -396,6 +471,10 @@ enum hal_rx_ret_buf_manager { RX_MSDU_DESC_INFO_0_DA_IDX_TIMEOUT_OFFSET)) & \ RX_MSDU_DESC_INFO_0_DA_IDX_TIMEOUT_MASK) +#define HAL_RX_REO_MSDU_REO_DST_IND_GET(reo_desc) \ + (HAL_RX_MSDU_REO_DST_IND_GET(& \ + (((struct reo_destination_ring *) \ + reo_desc)->rx_msdu_desc_info_details))) #define HAL_RX_MSDU_FLAGS_GET(msdu_info_ptr) \ (HAL_RX_FIRST_MSDU_IN_MPDU_FLAG_GET(msdu_info_ptr) | \ @@ -407,43 +486,12 @@ enum hal_rx_ret_buf_manager { HAL_RX_MSDU_DA_IS_MCBC_FLAG_GET(msdu_info_ptr) | \ HAL_RX_MSDU_DA_IDX_TIMEOUT_FLAG_GET(msdu_info_ptr)) - -#define HAL_RX_MPDU_PN_31_0_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_4_PN_31_0_OFFSET)), \ - RX_MPDU_INFO_4_PN_31_0_MASK, \ - RX_MPDU_INFO_4_PN_31_0_LSB)) - -#define HAL_RX_MPDU_PN_63_32_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_5_PN_63_32_OFFSET)), \ - RX_MPDU_INFO_5_PN_63_32_MASK, \ - RX_MPDU_INFO_5_PN_63_32_LSB)) - -#define HAL_RX_MPDU_PN_95_64_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_6_PN_95_64_OFFSET)), \ - RX_MPDU_INFO_6_PN_95_64_MASK, \ - RX_MPDU_INFO_6_PN_95_64_LSB)) - -#define HAL_RX_MPDU_PN_127_96_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_7_PN_127_96_OFFSET)), \ - RX_MPDU_INFO_7_PN_127_96_MASK, \ - RX_MPDU_INFO_7_PN_127_96_LSB)) - #define HAL_RX_MPDU_ENCRYPT_TYPE_GET(_rx_mpdu_info) \ (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ RX_MPDU_INFO_3_ENCRYPT_TYPE_OFFSET)), \ RX_MPDU_INFO_3_ENCRYPT_TYPE_MASK, \ RX_MPDU_INFO_3_ENCRYPT_TYPE_LSB)) -#define HAL_RX_MPDU_ENCRYPTION_INFO_VALID(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_OFFSET)), \ - RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_MASK, \ - RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_LSB)) - #define HAL_RX_FLD_SET(_ptr, _wrd, _field, _val) \ (*(uint32_t *)(((uint8_t *)_ptr) + \ _wrd ## _ ## _field ## _OFFSET) |= \ @@ -477,6 +525,7 @@ static inline void hal_rx_mpdu_desc_info_get(void *desc_addr, mpdu_desc_info->mpdu_flags = HAL_RX_MPDU_FLAGS_GET(mpdu_info); mpdu_desc_info->peer_meta_data = HAL_RX_MPDU_DESC_PEER_META_DATA_GET(mpdu_info); + mpdu_desc_info->bar_frame = HAL_RX_MPDU_BAR_FRAME_GET(mpdu_info); } /* @@ -605,6 +654,9 @@ struct rx_pkt_hdr_tlv { #define RXDMA_OPTIMIZATION +/* rx_pkt_tlvs structure should be used to process Data buffers, monitor status + * buffers, monitor destination buffers and monitor descriptor buffers. + */ #ifdef RXDMA_OPTIMIZATION /* * The RX_PADDING_BYTES is required so that the TLV's don't @@ -639,7 +691,33 @@ struct rx_pkt_tlvs { }; #endif /* RXDMA_OPTIMIZATION */ -#define RX_PKT_TLVS_LEN (sizeof(struct rx_pkt_tlvs)) +/* rx_mon_pkt_tlvs structure should be used to process monitor data buffers */ +#ifdef RXDMA_OPTIMIZATION +struct rx_mon_pkt_tlvs { + struct rx_msdu_end_tlv msdu_end_tlv; /* 72 bytes */ + struct rx_attention_tlv attn_tlv; /* 16 bytes */ + struct rx_msdu_start_tlv msdu_start_tlv;/* 40 bytes */ + uint8_t rx_padding0[RX_PADDING0_BYTES]; /* 4 bytes */ + struct rx_mpdu_start_tlv mpdu_start_tlv;/* 96 bytes */ + struct rx_mpdu_end_tlv mpdu_end_tlv; /* 12 bytes */ + uint8_t rx_padding1[RX_PADDING1_BYTES]; /* 16 bytes */ + struct rx_pkt_hdr_tlv pkt_hdr_tlv; /* 128 bytes */ +}; +#else /* RXDMA_OPTIMIZATION */ +struct rx_mon_pkt_tlvs { + struct rx_attention_tlv attn_tlv; + struct rx_mpdu_start_tlv mpdu_start_tlv; + struct rx_msdu_start_tlv msdu_start_tlv; + struct rx_msdu_end_tlv msdu_end_tlv; + struct rx_mpdu_end_tlv mpdu_end_tlv; + struct rx_pkt_hdr_tlv pkt_hdr_tlv; +}; +#endif + +#define SIZE_OF_MONITOR_TLV sizeof(struct rx_mon_pkt_tlvs) +#define SIZE_OF_DATA_RX_TLV sizeof(struct rx_pkt_tlvs) + +#define RX_PKT_TLVS_LEN SIZE_OF_DATA_RX_TLV #ifdef NO_RX_PKT_HDR_TLV static inline uint8_t @@ -678,45 +756,35 @@ static inline uint8_t } /* - * @ hal_rx_encryption_info_valid: Returns encryption type. + * hal_rx_encryption_info_valid(): Returns encryption type. * - * @ buf: rx_tlv_hdr of the received packet - * @ Return: encryption type + * @hal_soc_hdl: hal soc handle + * @buf: rx_tlv_hdr of the received packet + * + * Return: encryption type */ static inline uint32_t -hal_rx_encryption_info_valid(uint8_t *buf) +hal_rx_encryption_info_valid(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_mpdu_start *mpdu_start = - &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; - struct rx_mpdu_info *mpdu_info = &(mpdu_start->rx_mpdu_info_details); - uint32_t encryption_info = HAL_RX_MPDU_ENCRYPTION_INFO_VALID(mpdu_info); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_encryption_info_valid(buf); - return encryption_info; } /* - * @ hal_rx_print_pn: Prints the PN of rx packet. + * hal_rx_print_pn: Prints the PN of rx packet. + * @hal_soc_hdl: hal soc handle + * @buf: rx_tlv_hdr of the received packet * - * @ buf: rx_tlv_hdr of the received packet - * @ Return: void + * Return: void */ static inline void -hal_rx_print_pn(uint8_t *buf) +hal_rx_print_pn(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_mpdu_start *mpdu_start = - &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; - struct rx_mpdu_info *mpdu_info = &(mpdu_start->rx_mpdu_info_details); - - uint32_t pn_31_0 = HAL_RX_MPDU_PN_31_0_GET(mpdu_info); - uint32_t pn_63_32 = HAL_RX_MPDU_PN_63_32_GET(mpdu_info); - uint32_t pn_95_64 = HAL_RX_MPDU_PN_95_64_GET(mpdu_info); - uint32_t pn_127_96 = HAL_RX_MPDU_PN_127_96_GET(mpdu_info); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "PN number pn_127_96 0x%x pn_95_64 0x%x pn_63_32 0x%x pn_31_0 0x%x ", - pn_127_96, pn_95_64, pn_63_32, pn_31_0); + hal_soc->ops->hal_rx_print_pn(buf); } /* @@ -938,12 +1006,6 @@ hal_rx_mpdu_peer_meta_data_set(uint8_t *buf, uint32_t peer_mdata) HAL_RX_MPDU_PEER_META_DATA_SET(mpdu_info, peer_mdata); } -#define HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(_rx_msdu_end) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ - RX_MSDU_END_5_L3_HEADER_PADDING_OFFSET)), \ - RX_MSDU_END_5_L3_HEADER_PADDING_MASK, \ - RX_MSDU_END_5_L3_HEADER_PADDING_LSB)) - /** * LRO information needed from the TLVs */ @@ -955,14 +1017,6 @@ hal_rx_mpdu_peer_meta_data_set(uint8_t *buf, uint32_t peer_mdata) RX_MSDU_END_9_LRO_ELIGIBLE_MASK, \ RX_MSDU_END_9_LRO_ELIGIBLE_LSB)) -#define HAL_RX_TLV_GET_TCP_CHKSUM(buf) \ - (_HAL_MS( \ - (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ - msdu_end_tlv.rx_msdu_end), \ - RX_MSDU_END_1_TCP_UDP_CHKSUM_OFFSET)), \ - RX_MSDU_END_1_TCP_UDP_CHKSUM_MASK, \ - RX_MSDU_END_1_TCP_UDP_CHKSUM_LSB)) - #define HAL_RX_TLV_GET_TCP_ACK(buf) \ (_HAL_MS( \ (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ @@ -1003,6 +1057,14 @@ hal_rx_mpdu_peer_meta_data_set(uint8_t *buf, uint32_t peer_mdata) RX_MSDU_START_2_TCP_PROTO_MASK, \ RX_MSDU_START_2_TCP_PROTO_LSB)) +#define HAL_RX_TLV_GET_UDP_PROTO(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_start_tlv.rx_msdu_start), \ + RX_MSDU_START_2_UDP_PROTO_OFFSET)), \ + RX_MSDU_START_2_UDP_PROTO_MASK, \ + RX_MSDU_START_2_UDP_PROTO_LSB)) + #define HAL_RX_TLV_GET_IPV6(buf) \ (_HAL_MS( \ (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ @@ -1035,32 +1097,23 @@ hal_rx_mpdu_peer_meta_data_set(uint8_t *buf, uint32_t peer_mdata) RX_MSDU_START_4_FLOW_ID_TOEPLITZ_MASK, \ RX_MSDU_START_4_FLOW_ID_TOEPLITZ_LSB)) - /** +/** * hal_rx_msdu_end_l3_hdr_padding_get(): API to get the * l3_header padding from rx_msdu_end TLV * - * @ buf: pointer to the start of RX PKT TLV headers + * @buf: pointer to the start of RX PKT TLV headers * Return: number of l3 header padding bytes */ static inline uint32_t -hal_rx_msdu_end_l3_hdr_padding_get(uint8_t *buf) +hal_rx_msdu_end_l3_hdr_padding_get(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; - uint32_t l3_header_padding; - - l3_header_padding = HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(msdu_end); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - return l3_header_padding; + return hal_soc->ops->hal_rx_msdu_end_l3_hdr_padding_get(buf); } -#define HAL_RX_MSDU_END_SA_IDX_GET(_rx_msdu_end) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ - RX_MSDU_END_13_SA_IDX_OFFSET)), \ - RX_MSDU_END_13_SA_IDX_MASK, \ - RX_MSDU_END_13_SA_IDX_LSB)) - - /** +/** * hal_rx_msdu_end_sa_idx_get(): API to get the * sa_idx from rx_msdu_end TLV * @@ -1068,23 +1121,14 @@ hal_rx_msdu_end_l3_hdr_padding_get(uint8_t *buf) * Return: sa_idx (SA AST index) */ static inline uint16_t -hal_rx_msdu_end_sa_idx_get(uint8_t *buf) +hal_rx_msdu_end_sa_idx_get(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; - uint16_t sa_idx; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - sa_idx = HAL_RX_MSDU_END_SA_IDX_GET(msdu_end); - - return sa_idx; + return hal_soc->ops->hal_rx_msdu_end_sa_idx_get(buf); } -#define HAL_RX_MSDU_END_SA_IS_VALID_GET(_rx_msdu_end) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ - RX_MSDU_END_5_SA_IS_VALID_OFFSET)), \ - RX_MSDU_END_5_SA_IS_VALID_MASK, \ - RX_MSDU_END_5_SA_IS_VALID_LSB)) - /** * hal_rx_msdu_end_sa_is_valid_get(): API to get the * sa_is_valid bit from rx_msdu_end TLV @@ -1093,40 +1137,12 @@ hal_rx_msdu_end_sa_idx_get(uint8_t *buf) * Return: sa_is_valid bit */ static inline uint8_t -hal_rx_msdu_end_sa_is_valid_get(uint8_t *buf) -{ - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; - uint8_t sa_is_valid; - - sa_is_valid = HAL_RX_MSDU_END_SA_IS_VALID_GET(msdu_end); - - return sa_is_valid; -} - -#define HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(_rx_msdu_end) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ - RX_MSDU_END_16_SA_SW_PEER_ID_OFFSET)), \ - RX_MSDU_END_16_SA_SW_PEER_ID_MASK, \ - RX_MSDU_END_16_SA_SW_PEER_ID_LSB)) - - /** - * hal_rx_msdu_end_sa_sw_peer_id_get(): API to get the - * sa_sw_peer_id from rx_msdu_end TLV - * - * @ buf: pointer to the start of RX PKT TLV headers - * Return: sa_sw_peer_id index - */ -static inline uint32_t -hal_rx_msdu_end_sa_sw_peer_id_get(uint8_t *buf) +hal_rx_msdu_end_sa_is_valid_get(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; - uint32_t sa_sw_peer_id; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - sa_sw_peer_id = HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(msdu_end); - - return sa_sw_peer_id; + return hal_soc->ops->hal_rx_msdu_end_sa_is_valid_get(buf); } #define HAL_RX_MSDU_START_MSDU_LEN_GET(_rx_msdu_start) \ @@ -1227,51 +1243,108 @@ hal_rx_msdu_start_toeplitz_get(uint8_t *buf) return HAL_RX_MSDU_START_FLOWID_TOEPLITZ_GET(msdu_start); } -/* - * Get qos_control_valid from RX_MPDU_START - */ -#define HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ - RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_OFFSET)), \ - RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_MASK, \ - RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_LSB)) +/** + * enum hal_rx_mpdu_info_sw_frame_group_id_type: Enum for group id in MPDU_INFO + * + * @ HAL_MPDU_SW_FRAME_GROUP_NDP_FRAME: NDP frame + * @ HAL_MPDU_SW_FRAME_GROUP_MULTICAST_DATA: multicast data frame + * @ HAL_MPDU_SW_FRAME_GROUP_UNICAST_DATA: unicast data frame + * @ HAL_MPDU_SW_FRAME_GROUP_NULL_DATA: NULL data frame + * @ HAL_MPDU_SW_FRAME_GROUP_MGMT: management frame + * @ HAL_MPDU_SW_FRAME_GROUP_MGMT_PROBE_REQ: probe req frame + * @ HAL_MPDU_SW_FRAME_GROUP_CTRL: control frame + * @ HAL_MPDU_SW_FRAME_GROUP_CTRL_BAR: BAR frame + * @ HAL_MPDU_SW_FRAME_GROUP_CTRL_RTS: RTS frame + * @ HAL_MPDU_SW_FRAME_GROUP_UNSUPPORTED: unsupported + * @ HAL_MPDU_SW_FRAME_GROUP_MAX: max limit + */ +enum hal_rx_mpdu_info_sw_frame_group_id_type { + HAL_MPDU_SW_FRAME_GROUP_NDP_FRAME = 0, + HAL_MPDU_SW_FRAME_GROUP_MULTICAST_DATA, + HAL_MPDU_SW_FRAME_GROUP_UNICAST_DATA, + HAL_MPDU_SW_FRAME_GROUP_NULL_DATA, + HAL_MPDU_SW_FRAME_GROUP_MGMT, + HAL_MPDU_SW_FRAME_GROUP_MGMT_PROBE_REQ = 8, + HAL_MPDU_SW_FRAME_GROUP_MGMT_BEACON = 12, + HAL_MPDU_SW_FRAME_GROUP_CTRL = 20, + HAL_MPDU_SW_FRAME_GROUP_CTRL_BAR = 28, + HAL_MPDU_SW_FRAME_GROUP_CTRL_RTS = 31, + HAL_MPDU_SW_FRAME_GROUP_UNSUPPORTED = 36, + HAL_MPDU_SW_FRAME_GROUP_MAX = 37, +}; +/** + * hal_rx_mpdu_start_mpdu_qos_control_valid_get(): + * Retrieve qos control valid bit from the tlv. + * @hal_soc_hdl: hal_soc handle + * @buf: pointer to rx pkt TLV. + * + * Return: qos control value. + */ static inline uint32_t -hal_rx_mpdu_start_mpdu_qos_control_valid_get(uint8_t *buf) +hal_rx_mpdu_start_mpdu_qos_control_valid_get( + hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_mpdu_start *mpdu_start = - &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; - uint32_t qos_control_valid; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - qos_control_valid = HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET( - &(mpdu_start->rx_mpdu_info_details)); + if ((!hal_soc) || (!hal_soc->ops)) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return QDF_STATUS_E_INVAL; + } - return qos_control_valid; -} + if (hal_soc->ops->hal_rx_mpdu_start_mpdu_qos_control_valid_get) + return hal_soc->ops-> + hal_rx_mpdu_start_mpdu_qos_control_valid_get(buf); + return QDF_STATUS_E_INVAL; +} -/* - * Get SW peer id from RX_MPDU_START +/** + * hal_rx_is_unicast: check packet is unicast frame or not. + * @hal_soc_hdl: hal_soc handle + * @buf: pointer to rx pkt TLV. + * + * Return: true on unicast. */ -#define HAL_RX_MPDU_INFO_SW_PEER_ID_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ - RX_MPDU_INFO_1_SW_PEER_ID_OFFSET)), \ - RX_MPDU_INFO_1_SW_PEER_ID_MASK, \ - RX_MPDU_INFO_1_SW_PEER_ID_LSB)) +static inline bool +hal_rx_is_unicast(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + return hal_soc->ops->hal_rx_is_unicast(buf); +} + +/** + * hal_rx_tid_get: get tid based on qos control valid. + * @hal_soc_hdl: hal soc handle + * @buf: pointer to rx pkt TLV. + * + * Return: tid + */ static inline uint32_t -hal_rx_mpdu_start_sw_peer_id_get(uint8_t *buf) +hal_rx_tid_get(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_mpdu_start *mpdu_start = - &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; - uint32_t sw_peer_id; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_tid_get(hal_soc_hdl, buf); +} - sw_peer_id = HAL_RX_MPDU_INFO_SW_PEER_ID_GET( - &(mpdu_start->rx_mpdu_info_details)); +/** + * hal_rx_mpdu_start_sw_peer_id_get() - Retrieve sw peer id + * @hal_soc_hdl: hal soc handle + * @buf: pointer to rx pkt TLV. + * + * Return: sw peer_id + */ +static inline uint32_t +hal_rx_mpdu_start_sw_peer_id_get(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - return sw_peer_id; + return hal_soc->ops->hal_rx_mpdu_start_sw_peer_id_get(buf); } #define HAL_RX_MSDU_START_SGI_GET(_rx_msdu_start) \ @@ -1462,12 +1535,6 @@ hal_rx_msdu_start_get_pkt_type(uint8_t *buf) return pkt_type; } -#define HAL_RX_MPDU_GET_TODS(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_2_TO_DS_OFFSET)), \ - RX_MPDU_INFO_2_TO_DS_MASK, \ - RX_MPDU_INFO_2_TO_DS_LSB)) - /* * hal_rx_mpdu_get_tods(): API to get the tods info * from rx_mpdu_start @@ -1477,109 +1544,30 @@ hal_rx_msdu_start_get_pkt_type(uint8_t *buf) */ static inline uint32_t -hal_rx_mpdu_get_to_ds(uint8_t *buf) +hal_rx_mpdu_get_to_ds(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_mpdu_start *mpdu_start = - &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; - - struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; - uint32_t to_ds; - - to_ds = HAL_RX_MPDU_GET_TODS(mpdu_info); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - return to_ds; + return hal_soc->ops->hal_rx_mpdu_get_to_ds(buf); } -#define HAL_RX_MPDU_GET_FROMDS(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_2_FR_DS_OFFSET)), \ - RX_MPDU_INFO_2_FR_DS_MASK, \ - RX_MPDU_INFO_2_FR_DS_LSB)) /* * hal_rx_mpdu_get_fr_ds(): API to get the from ds info * from rx_mpdu_start - * + * @hal_soc_hdl: hal soc handle * @buf: pointer to the start of RX PKT TLV header + * * Return: uint32_t(fr_ds) */ - static inline uint32_t -hal_rx_mpdu_get_fr_ds(uint8_t *buf) +hal_rx_mpdu_get_fr_ds(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_mpdu_start *mpdu_start = - &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; - - struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; - uint32_t fr_ds; - - fr_ds = HAL_RX_MPDU_GET_FROMDS(mpdu_info); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - return fr_ds; + return hal_soc->ops->hal_rx_mpdu_get_fr_ds(buf); } -#define HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_OFFSET)), \ - RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_MASK, \ - RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_LSB)) - -#define HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_OFFSET)), \ - RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_MASK, \ - RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_LSB)) - -#define HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_OFFSET)), \ - RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_MASK, \ - RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_LSB)) - -#define HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_OFFSET)), \ - RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_MASK, \ - RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_LSB)) - -#define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \ - RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_MASK, \ - RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_LSB)) - -#define HAL_RX_MPDU_AD1_47_32_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_OFFSET)), \ - RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_MASK, \ - RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_LSB)) - -#define HAL_RX_MPDU_AD2_15_0_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_OFFSET)), \ - RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_MASK, \ - RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_LSB)) - -#define HAL_RX_MPDU_AD2_47_16_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_OFFSET)), \ - RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_MASK, \ - RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_LSB)) - -#define HAL_RX_MPDU_AD3_31_0_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_OFFSET)), \ - RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_MASK, \ - RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_LSB)) - -#define HAL_RX_MPDU_AD3_47_32_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_OFFSET)), \ - RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_MASK, \ - RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_LSB)) - #define HAL_RX_MPDU_AD4_31_0_GET(_rx_mpdu_info) \ (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_OFFSET)), \ @@ -1594,141 +1582,72 @@ hal_rx_mpdu_get_fr_ds(uint8_t *buf) /* * hal_rx_mpdu_get_addr1(): API to check get address1 of the mpdu - * + * @hal_soc_hdl: hal soc handle * @buf: pointer to the start of RX PKT TLV headera * @mac_addr: pointer to mac address + * * Return: success/failure */ static inline -QDF_STATUS hal_rx_mpdu_get_addr1(uint8_t *buf, uint8_t *mac_addr) +QDF_STATUS hal_rx_mpdu_get_addr1(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf, uint8_t *mac_addr) { - struct __attribute__((__packed__)) hal_addr1 { - uint32_t ad1_31_0; - uint16_t ad1_47_32; - }; - - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_mpdu_start *mpdu_start = - &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; - - struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; - struct hal_addr1 *addr = (struct hal_addr1 *)mac_addr; - uint32_t mac_addr_ad1_valid; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - mac_addr_ad1_valid = HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(mpdu_info); - - if (mac_addr_ad1_valid) { - addr->ad1_31_0 = HAL_RX_MPDU_AD1_31_0_GET(mpdu_info); - addr->ad1_47_32 = HAL_RX_MPDU_AD1_47_32_GET(mpdu_info); - return QDF_STATUS_SUCCESS; - } - - return QDF_STATUS_E_FAILURE; + return hal_soc->ops->hal_rx_mpdu_get_addr1(buf, mac_addr); } /* * hal_rx_mpdu_get_addr2(): API to check get address2 of the mpdu * in the packet - * + * @hal_soc_hdl: hal soc handle * @buf: pointer to the start of RX PKT TLV header * @mac_addr: pointer to mac address + * * Return: success/failure */ static inline -QDF_STATUS hal_rx_mpdu_get_addr2(uint8_t *buf, uint8_t *mac_addr) +QDF_STATUS hal_rx_mpdu_get_addr2(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf, uint8_t *mac_addr) { - struct __attribute__((__packed__)) hal_addr2 { - uint16_t ad2_15_0; - uint32_t ad2_47_16; - }; - - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_mpdu_start *mpdu_start = - &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; - - struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; - struct hal_addr2 *addr = (struct hal_addr2 *)mac_addr; - uint32_t mac_addr_ad2_valid; - - mac_addr_ad2_valid = HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(mpdu_info); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - if (mac_addr_ad2_valid) { - addr->ad2_15_0 = HAL_RX_MPDU_AD2_15_0_GET(mpdu_info); - addr->ad2_47_16 = HAL_RX_MPDU_AD2_47_16_GET(mpdu_info); - return QDF_STATUS_SUCCESS; - } - - return QDF_STATUS_E_FAILURE; + return hal_soc->ops->hal_rx_mpdu_get_addr2(buf, mac_addr); } /* * hal_rx_mpdu_get_addr3(): API to get address3 of the mpdu * in the packet - * + * @hal_soc_hdl: hal soc handle * @buf: pointer to the start of RX PKT TLV header * @mac_addr: pointer to mac address + * * Return: success/failure */ static inline -QDF_STATUS hal_rx_mpdu_get_addr3(uint8_t *buf, uint8_t *mac_addr) +QDF_STATUS hal_rx_mpdu_get_addr3(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf, uint8_t *mac_addr) { - struct __attribute__((__packed__)) hal_addr3 { - uint32_t ad3_31_0; - uint16_t ad3_47_32; - }; - - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_mpdu_start *mpdu_start = - &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; - struct hal_addr3 *addr = (struct hal_addr3 *)mac_addr; - uint32_t mac_addr_ad3_valid; - - mac_addr_ad3_valid = HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(mpdu_info); - - if (mac_addr_ad3_valid) { - addr->ad3_31_0 = HAL_RX_MPDU_AD3_31_0_GET(mpdu_info); - addr->ad3_47_32 = HAL_RX_MPDU_AD3_47_32_GET(mpdu_info); - return QDF_STATUS_SUCCESS; - } - - return QDF_STATUS_E_FAILURE; + return hal_soc->ops->hal_rx_mpdu_get_addr3(buf, mac_addr); } /* * hal_rx_mpdu_get_addr4(): API to get address4 of the mpdu * in the packet - * + * @hal_soc_hdl: hal_soc handle * @buf: pointer to the start of RX PKT TLV header * @mac_addr: pointer to mac address * Return: success/failure */ static inline -QDF_STATUS hal_rx_mpdu_get_addr4(uint8_t *buf, uint8_t *mac_addr) +QDF_STATUS hal_rx_mpdu_get_addr4(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf, uint8_t *mac_addr) { - struct __attribute__((__packed__)) hal_addr4 { - uint32_t ad4_31_0; - uint16_t ad4_47_32; - }; - - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_mpdu_start *mpdu_start = - &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; - - struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; - struct hal_addr4 *addr = (struct hal_addr4 *)mac_addr; - uint32_t mac_addr_ad4_valid; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - mac_addr_ad4_valid = HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(mpdu_info); - - if (mac_addr_ad4_valid) { - addr->ad4_31_0 = HAL_RX_MPDU_AD4_31_0_GET(mpdu_info); - addr->ad4_47_32 = HAL_RX_MPDU_AD4_47_32_GET(mpdu_info); - return QDF_STATUS_SUCCESS; - } - - return QDF_STATUS_E_FAILURE; + return hal_soc->ops->hal_rx_mpdu_get_addr4(buf, mac_addr); } /** @@ -1739,133 +1658,93 @@ QDF_STATUS hal_rx_mpdu_get_addr4(uint8_t *buf, uint8_t *mac_addr) * Return: da index */ static inline uint16_t -hal_rx_msdu_end_da_idx_get(struct hal_soc *hal_soc, uint8_t *buf) +hal_rx_msdu_end_da_idx_get(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + return hal_soc->ops->hal_rx_msdu_end_da_idx_get(buf); } -#define HAL_RX_MSDU_END_DA_IS_VALID_GET(_rx_msdu_end) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ - RX_MSDU_END_5_DA_IS_VALID_OFFSET)), \ - RX_MSDU_END_5_DA_IS_VALID_MASK, \ - RX_MSDU_END_5_DA_IS_VALID_LSB)) - - /** +/** * hal_rx_msdu_end_da_is_valid_get: API to check if da is valid * from rx_msdu_end TLV - * + * @hal_soc_hdl: hal soc handle * @ buf: pointer to the start of RX PKT TLV headers + * * Return: da_is_valid */ static inline uint8_t -hal_rx_msdu_end_da_is_valid_get(uint8_t *buf) +hal_rx_msdu_end_da_is_valid_get(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; - uint8_t da_is_valid; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - da_is_valid = HAL_RX_MSDU_END_DA_IS_VALID_GET(msdu_end); - - return da_is_valid; + return hal_soc->ops->hal_rx_msdu_end_da_is_valid_get(buf); } -#define HAL_RX_MSDU_END_DA_IS_MCBC_GET(_rx_msdu_end) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ - RX_MSDU_END_5_DA_IS_MCBC_OFFSET)), \ - RX_MSDU_END_5_DA_IS_MCBC_MASK, \ - RX_MSDU_END_5_DA_IS_MCBC_LSB)) - - /** +/** * hal_rx_msdu_end_da_is_mcbc_get: API to check if pkt is MCBC * from rx_msdu_end TLV * - * @ buf: pointer to the start of RX PKT TLV headers + * @buf: pointer to the start of RX PKT TLV headers + * * Return: da_is_mcbc */ static inline uint8_t -hal_rx_msdu_end_da_is_mcbc_get(uint8_t *buf) +hal_rx_msdu_end_da_is_mcbc_get(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; - uint8_t da_is_mcbc; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - da_is_mcbc = HAL_RX_MSDU_END_DA_IS_MCBC_GET(msdu_end); - - return da_is_mcbc; + return hal_soc->ops->hal_rx_msdu_end_da_is_mcbc_get(buf); } -#define HAL_RX_MSDU_END_FIRST_MSDU_GET(_rx_msdu_end) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ - RX_MSDU_END_5_FIRST_MSDU_OFFSET)), \ - RX_MSDU_END_5_FIRST_MSDU_MASK, \ - RX_MSDU_END_5_FIRST_MSDU_LSB)) - - /** +/** * hal_rx_msdu_end_first_msdu_get: API to get first msdu status * from rx_msdu_end TLV + * @hal_soc_hdl: hal soc handle + * @buf: pointer to the start of RX PKT TLV headers * - * @ buf: pointer to the start of RX PKT TLV headers * Return: first_msdu */ static inline uint8_t -hal_rx_msdu_end_first_msdu_get(uint8_t *buf) +hal_rx_msdu_end_first_msdu_get(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; - uint8_t first_msdu; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - first_msdu = HAL_RX_MSDU_END_FIRST_MSDU_GET(msdu_end); - - return first_msdu; + return hal_soc->ops->hal_rx_msdu_end_first_msdu_get(buf); } -#define HAL_RX_MSDU_END_LAST_MSDU_GET(_rx_msdu_end) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ - RX_MSDU_END_5_LAST_MSDU_OFFSET)), \ - RX_MSDU_END_5_LAST_MSDU_MASK, \ - RX_MSDU_END_5_LAST_MSDU_LSB)) - - /** +/** * hal_rx_msdu_end_last_msdu_get: API to get last msdu status * from rx_msdu_end TLV + * @hal_soc_hdl: hal soc handle + * @buf: pointer to the start of RX PKT TLV headers * - * @ buf: pointer to the start of RX PKT TLV headers * Return: last_msdu */ static inline uint8_t -hal_rx_msdu_end_last_msdu_get(uint8_t *buf) +hal_rx_msdu_end_last_msdu_get(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; - uint8_t last_msdu; - - last_msdu = HAL_RX_MSDU_END_LAST_MSDU_GET(msdu_end); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - return last_msdu; + return hal_soc->ops->hal_rx_msdu_end_last_msdu_get(buf); } -#define HAL_RX_MSDU_END_CCE_METADATA_GET(_rx_msdu_end) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ - RX_MSDU_END_16_CCE_METADATA_OFFSET)), \ - RX_MSDU_END_16_CCE_METADATA_MASK, \ - RX_MSDU_END_16_CCE_METADATA_LSB)) - /** * hal_rx_msdu_cce_metadata_get: API to get CCE metadata * from rx_msdu_end TLV - * @ buf: pointer to the start of RX PKT TLV headers - * Return: last_msdu + * @buf: pointer to the start of RX PKT TLV headers + * Return: cce_meta_data */ - -static inline uint32_t -hal_rx_msdu_cce_metadata_get(uint8_t *buf) +static inline uint16_t +hal_rx_msdu_cce_metadata_get(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; - uint32_t cce_metadata; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - cce_metadata = HAL_RX_MSDU_END_CCE_METADATA_GET(msdu_end); - return cce_metadata; + return hal_soc->ops->hal_rx_msdu_cce_metadata_get(buf); } /******************************************************************************* @@ -1943,6 +1822,7 @@ struct hal_rx_msdu_list { struct hal_buf_info { uint64_t paddr; uint32_t sw_cookie; + uint8_t rbm; }; /** @@ -1952,10 +1832,10 @@ struct hal_buf_info { * Return - Pointer to rx_msdu_details structure * */ -static inline void *hal_rx_link_desc_msdu0_ptr(void *msdu_link_ptr, void *hal) +static inline +void *hal_rx_link_desc_msdu0_ptr(void *msdu_link_ptr, + struct hal_soc *hal_soc) { - struct hal_soc *hal_soc = (struct hal_soc *)hal; - return hal_soc->ops->hal_rx_link_desc_msdu0_ptr(msdu_link_ptr); } @@ -1966,10 +1846,10 @@ static inline void *hal_rx_link_desc_msdu0_ptr(void *msdu_link_ptr, void *hal) * Return - Pointer to rx_msdu_desc_info structure. * */ -static inline void *hal_rx_msdu_desc_info_get_ptr(void *msdu_details_ptr, void *hal) +static inline +void *hal_rx_msdu_desc_info_get_ptr(void *msdu_details_ptr, + struct hal_soc *hal_soc) { - struct hal_soc *hal_soc = (struct hal_soc *)hal; - return hal_soc->ops->hal_rx_msdu_desc_info_get_ptr(msdu_details_ptr); } @@ -1991,11 +1871,12 @@ static inline void *hal_rx_msdu_desc_info_get_ptr(void *msdu_details_ptr, void * * * Return: void */ -static inline void hal_rx_msdu_list_get(struct hal_soc *hal_soc, +static inline void hal_rx_msdu_list_get(hal_soc_handle_t hal_soc_hdl, void *msdu_link_desc, struct hal_rx_msdu_list *msdu_list, uint16_t *num_msdus) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; struct rx_msdu_details *msdu_details; struct rx_msdu_desc_info *msdu_desc_info; struct rx_msdu_link *msdu_link = (struct rx_msdu_link *)msdu_link_desc; @@ -2011,6 +1892,9 @@ static inline void hal_rx_msdu_list_get(struct hal_soc *hal_soc, /* num_msdus received in mpdu descriptor may be incorrect * sometimes due to HW issue. Check msdu buffer address also */ + if (!i && (HAL_RX_BUFFER_ADDR_31_0_GET( + &msdu_details[i].buffer_addr_info_details) == 0)) + break; if (HAL_RX_BUFFER_ADDR_31_0_GET( &msdu_details[i].buffer_addr_info_details) == 0) { /* set the last msdu bit in the prev msdu_desc_info */ @@ -2058,8 +1942,9 @@ static inline void hal_rx_msdu_list_get(struct hal_soc *hal_soc, * Return: dst_ind (REO destination ring ID) */ static inline uint32_t -hal_rx_msdu_reo_dst_ind_get(struct hal_soc *hal_soc, void *msdu_link_desc) +hal_rx_msdu_reo_dst_ind_get(hal_soc_handle_t hal_soc_hdl, void *msdu_link_desc) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; struct rx_msdu_details *msdu_details; struct rx_msdu_desc_info *msdu_desc_info; struct rx_msdu_link *msdu_link = (struct rx_msdu_link *)msdu_link_desc; @@ -2083,8 +1968,9 @@ hal_rx_msdu_reo_dst_ind_get(struct hal_soc *hal_soc, void *msdu_link_desc) * @ buf_info: structure to return the buffer information * Return: void */ -static inline void hal_rx_reo_buf_paddr_get(void *rx_desc, - struct hal_buf_info *buf_info) +static inline +void hal_rx_reo_buf_paddr_get(hal_ring_desc_t rx_desc, + struct hal_buf_info *buf_info) { struct reo_destination_ring *reo_ring = (struct reo_destination_ring *)rx_desc; @@ -2265,7 +2151,7 @@ enum hal_rx_wbm_buf_type { * * Return: true: error caused by PN check, false: other error */ -static inline bool hal_rx_reo_is_pn_error(void *rx_desc) +static inline bool hal_rx_reo_is_pn_error(hal_ring_desc_t rx_desc) { struct reo_destination_ring *reo_desc = (struct reo_destination_ring *)rx_desc; @@ -2285,7 +2171,7 @@ static inline bool hal_rx_reo_is_pn_error(void *rx_desc) * * Return: true: error caused by 2K jump, false: other error */ -static inline bool hal_rx_reo_is_2k_jump(void *rx_desc) +static inline bool hal_rx_reo_is_2k_jump(hal_ring_desc_t rx_desc) { struct reo_destination_ring *reo_desc = (struct reo_destination_ring *)rx_desc; @@ -2339,7 +2225,7 @@ static inline void hal_dump_wbm_rel_desc(void *src_srng_desc) /** * hal_rx_msdu_link_desc_set: Retrieves MSDU Link Descriptor to WBM * - * @ soc : HAL version of the SOC pointer + * @ hal_soc_hdl : HAL version of the SOC pointer * @ src_srng_desc : void pointer to the WBM Release Ring descriptor * @ buf_addr_info : void pointer to the buffer_addr_info * @ bm_action : put in IDLE list or release to MSDU_LIST @@ -2347,9 +2233,11 @@ static inline void hal_dump_wbm_rel_desc(void *src_srng_desc) * Return: void */ /* look at implementation at dp_hw_link_desc_pool_setup()*/ -static inline void hal_rx_msdu_link_desc_set(struct hal_soc *soc, - void *src_srng_desc, void *buf_addr_info, - uint8_t bm_action) +static inline +void hal_rx_msdu_link_desc_set(hal_soc_handle_t hal_soc_hdl, + void *src_srng_desc, + hal_buff_addrinfo_t buf_addr_info, + uint8_t bm_action) { struct wbm_release_ring *wbm_rel_srng = (struct wbm_release_ring *)src_srng_desc; @@ -2409,7 +2297,8 @@ static inline void hal_rx_msdu_link_desc_reinject(struct hal_soc *soc, * (Assumption -- BUFFER_ADDR_INFO is the * first field in the descriptor structure) */ -#define HAL_RX_BUF_ADDR_INFO_GET(ring_desc) ((void *)(ring_desc)) +#define HAL_RX_BUF_ADDR_INFO_GET(ring_desc) \ + ((hal_link_desc_t)(ring_desc)) #define HAL_RX_REO_BUF_ADDR_INFO_GET HAL_RX_BUF_ADDR_INFO_GET @@ -2424,7 +2313,7 @@ static inline void hal_rx_msdu_link_desc_reinject(struct hal_soc *soc, * Return: uint8_t (value of the return_buffer_manager) */ static inline -uint8_t hal_rx_ret_buf_manager_get(void *ring_desc) +uint8_t hal_rx_ret_buf_manager_get(hal_ring_desc_t ring_desc) { /* * The following macro takes buf_addr_info as argument, @@ -2716,9 +2605,9 @@ static inline void hal_rx_dump_pkt_hdr_tlv(struct rx_pkt_tlvs *pkt_tlvs, * * Return: ring_id */ -static inline uint8_t hal_srng_ring_id_get(void *hal_ring) +static inline uint8_t hal_srng_ring_id_get(hal_ring_handle_t hal_ring_hdl) { - return ((struct hal_srng *)hal_ring)->ring_id; + return ((struct hal_srng *)hal_ring_hdl)->ring_id; } /* Rx MSDU link pointer info */ @@ -2751,32 +2640,9 @@ struct rx_mpdu_info *hal_rx_get_mpdu_info(struct rx_pkt_tlvs *pkt_tlvs) return &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; } -/** - * hal_rx_get_rx_sequence(): Function to retrieve rx sequence number - * - * @nbuf: Network buffer - * Returns: rx sequence number - */ #define DOT11_SEQ_FRAG_MASK 0x000f #define DOT11_FC1_MORE_FRAG_OFFSET 0x04 -#define HAL_RX_MPDU_GET_SEQUENCE_NUMBER(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_OFFSET)), \ - RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_MASK, \ - RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_LSB)) -static inline -uint16_t hal_rx_get_rx_sequence(uint8_t *buf) -{ - struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); - struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); - uint16_t seq_number = 0; - - seq_number = HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info); - - return seq_number; -} - /** * hal_rx_get_rx_fragment_number(): Function to retrieve rx fragment number * @@ -2784,17 +2650,10 @@ uint16_t hal_rx_get_rx_sequence(uint8_t *buf) * Returns: rx fragment number */ static inline -uint8_t hal_rx_get_rx_fragment_number(uint8_t *buf) +uint8_t hal_rx_get_rx_fragment_number(struct hal_soc *hal_soc, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); - struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); - uint8_t frag_number = 0; - - frag_number = HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info) & - DOT11_SEQ_FRAG_MASK; - - /* Return first 4 bits as fragment number */ - return frag_number; + return hal_soc->ops->hal_rx_get_rx_fragment_number(buf); } #define HAL_RX_MPDU_GET_FRAME_CONTROL_FIELD(_rx_mpdu_info) \ @@ -2858,75 +2717,51 @@ uint32_t hal_rx_msdu_is_wlan_mcast(qdf_nbuf_t nbuf) return rx_attn->mcast_bcast; } -#define HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_OFFSET)), \ - RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_MASK, \ - RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_LSB)) /* * hal_rx_get_mpdu_sequence_control_valid(): Get mpdu sequence control valid - * + * @hal_soc_hdl: hal soc handle * @nbuf: Network buffer - * Returns: value of sequence control valid field + * + * Return: value of sequence control valid field */ static inline -uint8_t hal_rx_get_mpdu_sequence_control_valid(uint8_t *buf) +uint8_t hal_rx_get_mpdu_sequence_control_valid(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); - struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); - uint8_t seq_ctrl_valid = 0; - - seq_ctrl_valid = - HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(rx_mpdu_info); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - return seq_ctrl_valid; + return hal_soc->ops->hal_rx_get_mpdu_sequence_control_valid(buf); } -#define HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_OFFSET)), \ - RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_MASK, \ - RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_LSB)) /* * hal_rx_get_mpdu_frame_control_valid(): Retrieves mpdu frame control valid - * + * @hal_soc_hdl: hal soc handle * @nbuf: Network buffer + * * Returns: value of frame control valid field */ static inline -uint8_t hal_rx_get_mpdu_frame_control_valid(uint8_t *buf) +uint8_t hal_rx_get_mpdu_frame_control_valid(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); - struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); - uint8_t frm_ctrl_valid = 0; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - frm_ctrl_valid = - HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(rx_mpdu_info); - - return frm_ctrl_valid; + return hal_soc->ops->hal_rx_get_mpdu_frame_control_valid(buf); } -#define HAL_RX_MPDU_GET_MAC_AD4_VALID(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ - RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_OFFSET)), \ - RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_MASK, \ - RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_LSB)) -/* +/** * hal_rx_get_mpdu_mac_ad4_valid(): Retrieves if mpdu 4th addr is valid - * + * @hal_soc_hdl: hal soc handle * @nbuf: Network buffer * Returns: value of mpdu 4th address valid field */ static inline -bool hal_rx_get_mpdu_mac_ad4_valid(uint8_t *buf) +bool hal_rx_get_mpdu_mac_ad4_valid(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) { - struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); - struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); - bool ad4_valid = 0; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - ad4_valid = HAL_RX_MPDU_GET_MAC_AD4_VALID(rx_mpdu_info); - - return ad4_valid; + return hal_soc->ops->hal_rx_get_mpdu_mac_ad4_valid(buf); } /* @@ -3019,7 +2854,7 @@ int hal_rx_chain_msdu_links(struct hal_soc *hal_soc, qdf_nbuf_t msdu, if (num_msdus < HAL_RX_NUM_MSDU_DESC) { /* mark first and last MSDUs */ rx_desc_info = qdf_nbuf_data(msdu); - fragno = hal_rx_get_rx_fragment_number(rx_desc_info); + fragno = hal_rx_get_rx_fragment_number(hal_soc, rx_desc_info); more_frag = hal_rx_get_rx_more_frag_bit(rx_desc_info); /* TODO: create skb->fragslist[] */ @@ -3061,9 +2896,10 @@ int hal_rx_chain_msdu_links(struct hal_soc *hal_soc, qdf_nbuf_t msdu, * Returns: None */ static inline -void hal_rx_defrag_update_src_ring_desc(void *ring_desc, - void *saved_mpdu_desc_info, - struct hal_rx_msdu_link_ptr_info *saved_msdu_link_ptr) +void hal_rx_defrag_update_src_ring_desc( + hal_ring_desc_t ring_desc, + void *saved_mpdu_desc_info, + struct hal_rx_msdu_link_ptr_info *saved_msdu_link_ptr) { struct reo_entrance_ring *reo_ent_ring; struct rx_mpdu_desc_info *reo_ring_mpdu_desc_info; @@ -3125,7 +2961,7 @@ void hal_rx_defrag_save_info_from_ring_desc(void *msdu_link_desc_va, static inline uint16_t hal_rx_get_desc_len(void) { - return sizeof(struct rx_pkt_tlvs); + return SIZE_OF_DATA_RX_TLV; } /* @@ -3136,7 +2972,7 @@ uint16_t hal_rx_get_desc_len(void) * Returns: value of rxdma_push_reason */ static inline -uint8_t hal_rx_reo_ent_rxdma_push_reason_get(void *reo_ent_desc) +uint8_t hal_rx_reo_ent_rxdma_push_reason_get(hal_rxdma_desc_t reo_ent_desc) { return _HAL_MS((*_OFFSET_TO_WORD_PTR(reo_ent_desc, REO_ENTRANCE_RING_6_RXDMA_PUSH_REASON_OFFSET)), @@ -3151,7 +2987,7 @@ uint8_t hal_rx_reo_ent_rxdma_push_reason_get(void *reo_ent_desc) * Return: value of rxdma_error_code */ static inline -uint8_t hal_rx_reo_ent_rxdma_error_code_get(void *reo_ent_desc) +uint8_t hal_rx_reo_ent_rxdma_error_code_get(hal_rxdma_desc_t reo_ent_desc) { return _HAL_MS((*_OFFSET_TO_WORD_PTR(reo_ent_desc, REO_ENTRANCE_RING_6_RXDMA_ERROR_CODE_OFFSET)), @@ -3168,8 +3004,10 @@ uint8_t hal_rx_reo_ent_rxdma_error_code_get(void *reo_ent_desc) */ static inline void hal_rx_wbm_err_info_get(void *wbm_desc, struct hal_wbm_err_desc_info *wbm_er_info, - struct hal_soc *hal_soc) + hal_soc_handle_t hal_soc_hdl) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + hal_soc->ops->hal_rx_wbm_err_info_get(wbm_desc, (void *)wbm_er_info); } @@ -3220,10 +3058,13 @@ static inline void hal_rx_wbm_err_info_get_from_tlv(uint8_t *buf, * * Return: void */ -static inline void hal_rx_mon_hw_desc_get_mpdu_status(struct hal_soc *hal_soc, - void *hw_desc_addr, - struct mon_rx_status *rs) +static inline +void hal_rx_mon_hw_desc_get_mpdu_status(hal_soc_handle_t hal_soc_hdl, + void *hw_desc_addr, + struct mon_rx_status *rs) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + hal_soc->ops->hal_rx_mon_hw_desc_get_mpdu_status(hw_desc_addr, rs); } @@ -3247,9 +3088,11 @@ static inline uint8_t hal_rx_get_tlv(struct hal_soc *hal_soc, void *rx_tlv) * @buf: pointer to the start of RX PKT TLV header * Return: uint32_t(nss) */ -static inline uint32_t hal_rx_msdu_start_nss_get(struct hal_soc *hal_soc, - uint8_t *buf) +static inline +uint32_t hal_rx_msdu_start_nss_get(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + return hal_soc->ops->hal_rx_msdu_start_nss_get(buf); } @@ -3276,9 +3119,11 @@ static inline void hal_rx_dump_msdu_start_tlv(struct hal_soc *hal_soc, * * */ -static inline uint32_t hal_rx_mpdu_start_tid_get(struct hal_soc *hal_soc, +static inline uint32_t hal_rx_mpdu_start_tid_get(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + return hal_soc->ops->hal_rx_mpdu_start_tid_get(buf); } @@ -3290,9 +3135,11 @@ static inline uint32_t hal_rx_mpdu_start_tid_get(struct hal_soc *hal_soc, * Return: uint32_t(reception_type) */ static inline -uint32_t hal_rx_msdu_start_reception_type_get(struct hal_soc *hal_soc, +uint32_t hal_rx_msdu_start_reception_type_get(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + return hal_soc->ops->hal_rx_msdu_start_reception_type_get(buf); } @@ -3304,7 +3151,7 @@ uint32_t hal_rx_msdu_start_reception_type_get(struct hal_soc *hal_soc, * * Return: void */ -static inline void hal_rx_dump_pkt_tlvs(struct hal_soc *hal_soc, +static inline void hal_rx_dump_pkt_tlvs(hal_soc_handle_t hal_soc_hdl, uint8_t *buf, uint8_t dbg_level) { struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; @@ -3315,6 +3162,7 @@ static inline void hal_rx_dump_pkt_tlvs(struct hal_soc *hal_soc, &pkt_tlvs->msdu_start_tlv.rx_msdu_start; struct rx_mpdu_end *mpdu_end = &pkt_tlvs->mpdu_end_tlv.rx_mpdu_end; struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; hal_rx_dump_rx_attention_tlv(rx_attn, dbg_level); hal_rx_dump_mpdu_start_tlv(mpdu_start, dbg_level, hal_soc); @@ -3334,21 +3182,28 @@ static inline void hal_rx_dump_pkt_tlvs(struct hal_soc *hal_soc, * Return - none. * */ -static inline void hal_reo_status_get_header(uint32_t *d, int b, - void *h, void *hal) +static inline +void hal_reo_status_get_header(uint32_t *d, int b, + void *h, struct hal_soc *hal_soc) { - struct hal_soc *hal_soc = (struct hal_soc *)hal; - hal_soc->ops->hal_reo_status_get_header(d, b, h); } +/** + * hal_rx_desc_is_first_msdu() - Check if first msdu + * + * @hal_soc_hdl: hal_soc handle + * @hw_desc_addr: hardware descriptor address + * + * Return: 0 - success/ non-zero failure + */ static inline -uint32_t hal_rx_desc_is_first_msdu(void *hw_desc_addr) +uint32_t hal_rx_desc_is_first_msdu(hal_soc_handle_t hal_soc_hdl, + void *hw_desc_addr) { - struct rx_pkt_tlvs *rx_tlvs = (struct rx_pkt_tlvs *)hw_desc_addr; - struct rx_msdu_end *msdu_end = &rx_tlvs->msdu_end_tlv.rx_msdu_end; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - return HAL_RX_GET(msdu_end, RX_MSDU_END_5, FIRST_MSDU); + return hal_soc->ops->hal_rx_desc_is_first_msdu(hw_desc_addr); } static inline @@ -3366,10 +3221,13 @@ HAL_RX_DESC_GET_DECAP_FORMAT(void *hw_desc_addr) { static inline uint8_t * HAL_RX_DESC_GET_80211_HDR(void *hw_desc_addr) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "[%s][%d] decap format not raw", __func__, __LINE__); - QDF_ASSERT(0); - return 0; + uint8_t *rx_pkt_hdr; + struct rx_mon_pkt_tlvs *rx_desc = + (struct rx_mon_pkt_tlvs *)hw_desc_addr; + + rx_pkt_hdr = &rx_desc->pkt_hdr_tlv.rx_pkt_hdr[0]; + + return rx_pkt_hdr; } #else static inline @@ -3384,13 +3242,13 @@ HAL_RX_DESC_GET_80211_HDR(void *hw_desc_addr) { } #endif -#ifdef NO_RX_PKT_HDR_TLV static inline -bool HAL_IS_DECAP_FORMAT_RAW(uint8_t *rx_tlv_hdr) +bool HAL_IS_DECAP_FORMAT_RAW(hal_soc_handle_t hal_soc_hdl, + uint8_t *rx_tlv_hdr) { uint8_t decap_format; - if (hal_rx_desc_is_first_msdu(rx_tlv_hdr)) { + if (hal_rx_desc_is_first_msdu(hal_soc_hdl, rx_tlv_hdr)) { decap_format = HAL_RX_DESC_GET_DECAP_FORMAT(rx_tlv_hdr); if (decap_format == HAL_HW_RX_DECAP_FORMAT_RAW) return true; @@ -3398,13 +3256,473 @@ bool HAL_IS_DECAP_FORMAT_RAW(uint8_t *rx_tlv_hdr) return false; } -#else + +/** + * hal_rx_msdu_fse_metadata_get: API to get FSE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: fse metadata value from MSDU END TLV + */ +static inline uint32_t +hal_rx_msdu_fse_metadata_get(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_msdu_fse_metadata_get(buf); +} + +/** + * hal_rx_msdu_flow_idx_get: API to get flow index + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index value from MSDU END TLV + */ +static inline uint32_t +hal_rx_msdu_flow_idx_get(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_msdu_flow_idx_get(buf); +} + +/** + * hal_rx_msdu_get_reo_destination_indication: API to get reo + * destination index from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * @reo_destination_indication: pointer to return value of + * reo_destination_indication + * + * Return: reo_destination_indication value from MSDU END TLV + */ +static inline void +hal_rx_msdu_get_reo_destination_indication(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf, + uint32_t *reo_destination_indication) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if ((!hal_soc) || (!hal_soc->ops)) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return; + } + + hal_soc->ops->hal_rx_msdu_get_reo_destination_indication(buf, + reo_destination_indication); +} + +/** + * hal_rx_msdu_flow_idx_timeout: API to get flow index timeout + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index timeout value from MSDU END TLV + */ +static inline bool +hal_rx_msdu_flow_idx_timeout(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_msdu_flow_idx_timeout(buf); +} + +/** + * hal_rx_msdu_flow_idx_invalid: API to get flow index invalid + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index invalid value from MSDU END TLV + */ +static inline bool +hal_rx_msdu_flow_idx_invalid(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_msdu_flow_idx_invalid(buf); +} + +/** + * hal_rx_hw_desc_get_ppduid_get() - Retrieve ppdu id + * @hal_soc_hdl: hal_soc handle + * @hw_desc_addr: hardware descriptor address + * + * Return: 0 - success/ non-zero failure + */ static inline -bool HAL_IS_DECAP_FORMAT_RAW(uint8_t *rx_tlv_hdr) +uint32_t hal_rx_hw_desc_get_ppduid_get(hal_soc_handle_t hal_soc_hdl, + void *hw_desc_addr) { - return true; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_hw_desc_get_ppduid_get(hw_desc_addr); +} + +/** + * hal_rx_msdu_end_sa_sw_peer_id_get() - get sw peer id + * @hal_soc_hdl: hal_soc handle + * @buf: rx tlv address + * + * Return: sw peer id + */ +static inline +uint32_t hal_rx_msdu_end_sa_sw_peer_id_get(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if ((!hal_soc) || (!hal_soc->ops)) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return QDF_STATUS_E_INVAL; + } + + if (hal_soc->ops->hal_rx_msdu_end_sa_sw_peer_id_get) + return hal_soc->ops->hal_rx_msdu_end_sa_sw_peer_id_get(buf); + + return QDF_STATUS_E_INVAL; +} + +static inline +void *hal_rx_msdu0_buffer_addr_lsb(hal_soc_handle_t hal_soc_hdl, + void *link_desc_addr) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_msdu0_buffer_addr_lsb(link_desc_addr); +} + +static inline +void *hal_rx_msdu_desc_info_ptr_get(hal_soc_handle_t hal_soc_hdl, + void *msdu_addr) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_msdu_desc_info_ptr_get(msdu_addr); +} + +static inline +void *hal_ent_mpdu_desc_info(hal_soc_handle_t hal_soc_hdl, + void *hw_addr) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_ent_mpdu_desc_info(hw_addr); +} + +static inline +void *hal_dst_mpdu_desc_info(hal_soc_handle_t hal_soc_hdl, + void *hw_addr) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_dst_mpdu_desc_info(hw_addr); +} + +static inline +uint8_t hal_rx_get_fc_valid(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_get_fc_valid(buf); +} + +static inline +uint8_t hal_rx_get_to_ds_flag(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_get_to_ds_flag(buf); +} + +static inline +uint8_t hal_rx_get_mac_addr2_valid(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_get_mac_addr2_valid(buf); +} + +static inline +uint8_t hal_rx_get_filter_category(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_get_filter_category(buf); +} + +static inline +uint32_t hal_rx_get_ppdu_id(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_get_ppdu_id(buf); +} + +/** + * hal_reo_config(): Set reo config parameters + * @soc: hal soc handle + * @reg_val: value to be set + * @reo_params: reo parameters + * + * Return: void + */ +static inline +void hal_reo_config(struct hal_soc *hal_soc, + uint32_t reg_val, + struct hal_reo_params *reo_params) +{ + hal_soc->ops->hal_reo_config(hal_soc, + reg_val, + reo_params); +} + +/** + * hal_rx_msdu_get_flow_params: API to get flow index, + * flow index invalid and flow index timeout from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * @flow_invalid: pointer to return value of flow_idx_valid + * @flow_timeout: pointer to return value of flow_idx_timeout + * @flow_index: pointer to return value of flow_idx + * + * Return: none + */ +static inline void +hal_rx_msdu_get_flow_params(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf, + bool *flow_invalid, + bool *flow_timeout, + uint32_t *flow_index) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if ((!hal_soc) || (!hal_soc->ops)) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return; + } + + if (hal_soc->ops->hal_rx_msdu_get_flow_params) + hal_soc->ops-> + hal_rx_msdu_get_flow_params(buf, + flow_invalid, + flow_timeout, + flow_index); +} + +static inline +uint16_t hal_rx_tlv_get_tcp_chksum(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_tlv_get_tcp_chksum(buf); +} + +static inline +uint16_t hal_rx_get_rx_sequence(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_get_rx_sequence(buf); +} + +static inline void +hal_rx_get_bb_info(hal_soc_handle_t hal_soc_hdl, + void *rx_tlv, + void *ppdu_info) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (hal_soc->ops->hal_rx_get_bb_info) + hal_soc->ops->hal_rx_get_bb_info(rx_tlv, ppdu_info); +} + +static inline void +hal_rx_get_rtt_info(hal_soc_handle_t hal_soc_hdl, + void *rx_tlv, + void *ppdu_info) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (hal_soc->ops->hal_rx_get_rtt_info) + hal_soc->ops->hal_rx_get_rtt_info(rx_tlv, ppdu_info); +} + +/** + * hal_rx_msdu_metadata_get(): API to get the + * fast path information from rx_msdu_end TLV + * + * @ hal_soc_hdl: DP soc handle + * @ buf: pointer to the start of RX PKT TLV headers + * @ msdu_metadata: Structure to hold msdu end information + * Return: none + */ +static inline void +hal_rx_msdu_metadata_get(hal_soc_handle_t hal_soc_hdl, uint8_t *buf, + struct hal_rx_msdu_metadata *msdu_md) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + return hal_soc->ops->hal_rx_msdu_packet_metadata_get(buf, msdu_md); +} + +/** + * hal_rx_get_fisa_cumulative_l4_checksum: API to get cumulative_l4_checksum + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: cumulative_l4_checksum + */ +static inline uint16_t +hal_rx_get_fisa_cumulative_l4_checksum(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (!hal_soc->ops->hal_rx_get_fisa_cumulative_l4_checksum) + return 0; + + return hal_soc->ops->hal_rx_get_fisa_cumulative_l4_checksum(buf); +} + +/** + * hal_rx_get_fisa_cumulative_ip_length: API to get cumulative_ip_length + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: cumulative_ip_length + */ +static inline uint16_t +hal_rx_get_fisa_cumulative_ip_length(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (hal_soc->ops->hal_rx_get_fisa_cumulative_ip_length) + return hal_soc->ops->hal_rx_get_fisa_cumulative_ip_length(buf); + + return 0; +} + +/** + * hal_rx_get_udp_proto: API to get UDP proto field + * from rx_msdu_start TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: UDP proto field value + */ +static inline bool +hal_rx_get_udp_proto(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (hal_soc->ops->hal_rx_get_udp_proto) + return hal_soc->ops->hal_rx_get_udp_proto(buf); + + return 0; +} + +/** + * hal_rx_get_fisa_flow_agg_continuation: API to get fisa flow_agg_continuation + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow_agg_continuation bit field value + */ +static inline bool +hal_rx_get_fisa_flow_agg_continuation(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (hal_soc->ops->hal_rx_get_fisa_flow_agg_continuation) + return hal_soc->ops->hal_rx_get_fisa_flow_agg_continuation(buf); + + return 0; +} + +/** + * hal_rx_get_fisa_flow_agg_count: API to get fisa flow_agg count from + * rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow_agg count value + */ +static inline uint8_t +hal_rx_get_fisa_flow_agg_count(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (hal_soc->ops->hal_rx_get_fisa_flow_agg_count) + return hal_soc->ops->hal_rx_get_fisa_flow_agg_count(buf); + + return 0; +} + +/** + * hal_rx_get_fisa_timeout: API to get fisa time out from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: fisa flow_agg timeout bit value + */ +static inline bool +hal_rx_get_fisa_timeout(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (!hal_soc || !hal_soc->ops) { + hal_err("hal handle is NULL"); + QDF_BUG(0); + return 0; + } + + if (hal_soc->ops->hal_rx_get_fisa_timeout) + return hal_soc->ops->hal_rx_get_fisa_timeout(buf); + + return 0; } -#endif /** * hal_rx_buffer_addr_info_get_paddr(): get paddr/sw_cookie from @@ -3464,4 +3782,26 @@ bool hal_rx_is_buf_addr_info_valid( return (HAL_RX_BUFFER_ADDR_31_0_GET(buf_addr_info) == 0) ? false : true; } + +#define HAL_RX_ATTN_MSDU_LEN_ERR_GET(_rx_attn) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_attn, \ + RX_ATTENTION_1_MSDU_LENGTH_ERR_OFFSET)), \ + RX_ATTENTION_1_MSDU_LENGTH_ERR_MASK, \ + RX_ATTENTION_1_MSDU_LENGTH_ERR_LSB)) + +/** + * hal_rx_attn_msdu_len_err_get(): Get msdu_len_err value from + * rx attention tlvs + * @buf: pointer to rx pkt tlvs hdr + * + * Return: msdu_len_err value + */ +static inline uint32_t +hal_rx_attn_msdu_len_err_get(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_attention *rx_attn = &pkt_tlvs->attn_tlv.rx_attn; + + return HAL_RX_ATTN_MSDU_LEN_ERR_GET(rx_attn); +} #endif /* _HAL_RX_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_rx_flow.c b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_rx_flow.c new file mode 100644 index 0000000000000000000000000000000000000000..98d0923ea48c584612df6b89e3412eb9a69b3cbb --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_rx_flow.c @@ -0,0 +1,774 @@ +/* + * Copyright (c) 2019-2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "qdf_module.h" +#include "dp_types.h" +#include "hal_rx_flow.h" + +#if defined(WLAN_SUPPORT_RX_FISA) +void hal_rx_dump_fse_table(struct hal_rx_fst *fst) +{ + int i = 0; + struct rx_flow_search_entry *fse = + (struct rx_flow_search_entry *)fst->base_vaddr; + + dp_info("Number flow table entries %d", fst->add_flow_count); + for (i = 0; i < fst->max_entries; i++) { + if (fse[i].valid) { + dp_info("index %d:" + " src_ip_127_96 0x%x" + " src_ip_95_640 0x%x" + " src_ip_63_32 0x%x" + " src_ip_31_0 0x%x" + " dest_ip_127_96 0x%x" + " dest_ip_95_64 0x%x" + " dest_ip_63_32 0x%x" + " dest_ip_31_0 0x%x" + " src_port 0x%x" + " dest_port 0x%x" + " l4_protocol 0x%x" + " valid 0x%x" + " reo_destination_indication 0x%x" + " msdu_drop 0x%x" + " reo_destination_handler 0x%x" + " metadata 0x%x" + " aggregation_count0x%x" + " lro_eligible 0x%x" + " msdu_count 0x%x" + " msdu_byte_count 0x%x" + " timestamp 0x%x" + " cumulative_l4_checksum 0x%x" + " cumulative_ip_length 0x%x" + " tcp_sequence_number 0x%x", + i, + fse[i].src_ip_127_96, + fse[i].src_ip_95_64, + fse[i].src_ip_63_32, + fse[i].src_ip_31_0, + fse[i].dest_ip_127_96, + fse[i].dest_ip_95_64, + fse[i].dest_ip_63_32, + fse[i].dest_ip_31_0, + fse[i].src_port, + fse[i].dest_port, + fse[i].l4_protocol, + fse[i].valid, + fse[i].reo_destination_indication, + fse[i].msdu_drop, + fse[i].reo_destination_handler, + fse[i].metadata, + fse[i].aggregation_count, + fse[i].lro_eligible, + fse[i].msdu_count, + fse[i].msdu_byte_count, + fse[i].timestamp, + fse[i].cumulative_l4_checksum, + fse[i].cumulative_ip_length, + fse[i].tcp_sequence_number); + } + } +} +#else +void hal_rx_dump_fse_table(struct hal_rx_fst *fst) +{ +} +#endif + +/** + * hal_rx_flow_setup_fse() - Setup a flow search entry in HW FST + * @fst: Pointer to the Rx Flow Search Table + * @table_offset: offset into the table where the flow is to be setup + * @flow: Flow Parameters + * + * Return: Success/Failure + */ +#ifdef WLAN_SUPPORT_RX_FLOW_TAG +void * +hal_rx_flow_setup_fse(struct hal_rx_fst *fst, uint32_t table_offset, + struct hal_rx_flow *flow) +{ + uint8_t *fse; + bool fse_valid; + + if (table_offset >= fst->max_entries) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "HAL FSE table offset %u exceeds max entries %u", + table_offset, fst->max_entries); + return NULL; + } + + fse = (uint8_t *)fst->base_vaddr + + (table_offset * HAL_RX_FST_ENTRY_SIZE); + + fse_valid = HAL_GET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); + + if (fse_valid) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "HAL FSE %pK already valid", fse); + return NULL; + } + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96, + qdf_htonl(flow->tuple_info.src_ip_127_96)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64, + qdf_htonl(flow->tuple_info.src_ip_95_64)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32, + qdf_htonl(flow->tuple_info.src_ip_63_32)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0, + qdf_htonl(flow->tuple_info.src_ip_31_0)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96, + qdf_htonl(flow->tuple_info.dest_ip_127_96)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64, + qdf_htonl(flow->tuple_info.dest_ip_95_64)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32, + qdf_htonl(flow->tuple_info.dest_ip_63_32)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0, + qdf_htonl(flow->tuple_info.dest_ip_31_0)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, DEST_PORT, + (flow->tuple_info.dest_port)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, SRC_PORT, + (flow->tuple_info.src_port)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL, + flow->tuple_info.l4_protocol); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER, + flow->reo_destination_handler); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, VALID, 1); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_10, METADATA, + flow->fse_metadata); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, REO_DESTINATION_INDICATION); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, REO_DESTINATION_INDICATION) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_11, + REO_DESTINATION_INDICATION, + flow->reo_destination_indication); + + /* Reset all the other fields in FSE */ + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, RESERVED_9); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, MSDU_DROP); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, RESERVED_11); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, MSDU_COUNT); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_12, MSDU_BYTE_COUNT); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_13, TIMESTAMP); + + return fse; +} +#elif defined(WLAN_SUPPORT_RX_FISA) +/** + * hal_rx_flow_setup_fse() - Setup a flow search entry in HW FST + * @fst: Pointer to the Rx Flow Search Table + * @table_offset: offset into the table where the flow is to be setup + * @flow: Flow Parameters + * + * Flow table entry fields are updated in host byte order, little endian order. + * + * Return: Success/Failure + */ +void * +hal_rx_flow_setup_fse(struct hal_rx_fst *fst, uint32_t table_offset, + struct hal_rx_flow *flow) +{ + uint8_t *fse; + bool fse_valid; + + if (table_offset >= fst->max_entries) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "HAL FSE table offset %u exceeds max entries %u", + table_offset, fst->max_entries); + return NULL; + } + + fse = (uint8_t *)fst->base_vaddr + + (table_offset * HAL_RX_FST_ENTRY_SIZE); + + fse_valid = HAL_GET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); + + if (fse_valid) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "HAL FSE %pK already valid", fse); + return NULL; + } + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_0, SRC_IP_127_96, + (flow->tuple_info.src_ip_127_96)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_1, SRC_IP_95_64, + (flow->tuple_info.src_ip_95_64)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_2, SRC_IP_63_32, + (flow->tuple_info.src_ip_63_32)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_3, SRC_IP_31_0, + (flow->tuple_info.src_ip_31_0)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_4, DEST_IP_127_96, + (flow->tuple_info.dest_ip_127_96)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_5, DEST_IP_95_64, + (flow->tuple_info.dest_ip_95_64)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_6, DEST_IP_63_32, + (flow->tuple_info.dest_ip_63_32)); + + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_7, DEST_IP_31_0, + (flow->tuple_info.dest_ip_31_0)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, DEST_PORT) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, DEST_PORT, + (flow->tuple_info.dest_port)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_8, SRC_PORT) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_8, SRC_PORT, + (flow->tuple_info.src_port)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, L4_PROTOCOL, + flow->tuple_info.l4_protocol); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_HANDLER, + flow->reo_destination_handler); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, VALID, 1); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_10, METADATA) = + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_10, METADATA, + (flow->fse_metadata)); + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_INDICATION); + HAL_SET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, REO_DESTINATION_INDICATION) |= + HAL_SET_FLD_SM(RX_FLOW_SEARCH_ENTRY_9, + REO_DESTINATION_INDICATION, + flow->reo_destination_indication); + + /* Reset all the other fields in FSE */ + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, RESERVED_9); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, MSDU_DROP); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_11, MSDU_COUNT); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_12, MSDU_BYTE_COUNT); + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_13, TIMESTAMP); + + return fse; +} +#endif /* WLAN_SUPPORT_RX_FISA */ +qdf_export_symbol(hal_rx_flow_setup_fse); + +/** + * hal_rx_flow_delete_entry() - Delete a flow from the Rx Flow Search Table + * @fst: Pointer to the Rx Flow Search Table + * @hal_rx_fse: Pointer to the Rx Flow that is to be deleted from the FST + * + * Return: Success/Failure + */ +inline QDF_STATUS +hal_rx_flow_delete_entry(struct hal_rx_fst *fst, void *hal_rx_fse) +{ + uint8_t *fse = (uint8_t *)hal_rx_fse; + + if (!HAL_GET_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID)) + return QDF_STATUS_E_NOENT; + + HAL_CLR_FLD(fse, RX_FLOW_SEARCH_ENTRY_9, VALID); + + return QDF_STATUS_SUCCESS; +} +qdf_export_symbol(hal_rx_flow_delete_entry); + +#ifndef WLAN_SUPPORT_RX_FISA +/** + * hal_rx_fst_key_configure() - Configure the Toeplitz key in the FST + * @fst: Pointer to the Rx Flow Search Table + * + * Return: Success/Failure + */ +static void hal_rx_fst_key_configure(struct hal_rx_fst *fst) +{ + uint8_t key_bytes[HAL_FST_HASH_KEY_SIZE_BYTES]; + + qdf_mem_copy(key_bytes, fst->key, HAL_FST_HASH_KEY_SIZE_BYTES); + + /** + * The Toeplitz algorithm as per the Microsoft spec works in a + * “big-endian” manner, using the MSBs of the key to hash the + * initial bytes of the input going on to use up the lower order bits + * of the key to hash further bytes of the input until the LSBs of the + * key are used finally. + * + * So first, rightshift 320-bit input key 5 times to get 315 MS bits + */ + key_bitwise_shift_left(key_bytes, HAL_FST_HASH_KEY_SIZE_BYTES, 5); + key_reverse(fst->shifted_key, key_bytes, HAL_FST_HASH_KEY_SIZE_BYTES); +} +#else +static void hal_rx_fst_key_configure(struct hal_rx_fst *fst) +{ +} +#endif + +/** + * hal_rx_fst_get_base() - Retrieve the virtual base address of the Rx FST + * @fst: Pointer to the Rx Flow Search Table + * + * Return: Success/Failure + */ +static inline void *hal_rx_fst_get_base(struct hal_rx_fst *fst) +{ + return fst->base_vaddr; +} + +/** + * hal_rx_fst_get_fse_size() - Retrieve the size of each entry(flow) in Rx FST + * + * Return: size of each entry/flow in Rx FST + */ +static inline uint32_t hal_rx_fst_get_fse_size(void) +{ + return HAL_RX_FST_ENTRY_SIZE; +} + +/** + * hal_rx_flow_get_tuple_info() - Retrieve the 5-tuple flow info for an entry + * @hal_fse: Pointer to the Flow in Rx FST + * @tuple_info: 5-tuple info of the flow returned to the caller + * + * Return: Success/Failure + */ +QDF_STATUS hal_rx_flow_get_tuple_info(void *hal_fse, + struct hal_flow_tuple_info *tuple_info) +{ + if (!hal_fse || !tuple_info) + return QDF_STATUS_E_INVAL; + + if (!HAL_GET_FLD(hal_fse, RX_FLOW_SEARCH_ENTRY_9, VALID)) + return QDF_STATUS_E_NOENT; + + tuple_info->src_ip_127_96 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_0, + SRC_IP_127_96)); + tuple_info->src_ip_95_64 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_1, + SRC_IP_95_64)); + tuple_info->src_ip_63_32 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_2, + SRC_IP_63_32)); + tuple_info->src_ip_31_0 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_3, + SRC_IP_31_0)); + tuple_info->dest_ip_127_96 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_4, + DEST_IP_127_96)); + tuple_info->dest_ip_95_64 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_5, + DEST_IP_95_64)); + tuple_info->dest_ip_63_32 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_6, + DEST_IP_63_32)); + tuple_info->dest_ip_31_0 = + qdf_ntohl(HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_7, + DEST_IP_31_0)); + tuple_info->dest_port = HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_8, + DEST_PORT); + tuple_info->src_port = HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_8, + SRC_PORT); + tuple_info->l4_protocol = HAL_GET_FLD(hal_fse, + RX_FLOW_SEARCH_ENTRY_9, + L4_PROTOCOL); + + return QDF_STATUS_SUCCESS; +} + +#ifndef WLAN_SUPPORT_RX_FISA +/** + * hal_flow_toeplitz_create_cache() - Calculate hashes for each possible + * byte value with the key taken as is + * + * @fst: FST Handle + * @key: Hash Key + * + * Return: Success/Failure + */ +static void hal_flow_toeplitz_create_cache(struct hal_rx_fst *fst) +{ + int bit; + int val; + int i; + uint8_t *key = fst->shifted_key; + + /* + * Initialise to first 32 bits of the key; shift in further key material + * through the loop + */ + uint32_t cur_key = (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | + key[3]; + + for (i = 0; i < HAL_FST_HASH_KEY_SIZE_BYTES; i++) { + uint8_t new_key_byte; + uint32_t shifted_key[8]; + + if (i + 4 < HAL_FST_HASH_KEY_SIZE_BYTES) + new_key_byte = key[i + 4]; + else + new_key_byte = 0; + + shifted_key[0] = cur_key; + + for (bit = 1; bit < 8; bit++) { + /* + * For each iteration, shift out one more bit of the + * current key and shift in one more bit of the new key + * material + */ + shifted_key[bit] = cur_key << bit | + new_key_byte >> (8 - bit); + } + + for (val = 0; val < (1 << 8); val++) { + uint32_t hash = 0; + int mask; + + /* + * For each bit set in the input, XOR in + * the appropriately shifted key + */ + for (bit = 0, mask = 1 << 7; bit < 8; bit++, mask >>= 1) + if ((val & mask)) + hash ^= shifted_key[bit]; + + fst->key_cache[i][val] = hash; + } + + cur_key = cur_key << 8 | new_key_byte; + } +} +#else +static void hal_flow_toeplitz_create_cache(struct hal_rx_fst *fst) +{ +} +#endif + +/** + * hal_rx_fst_attach() - Initialize Rx flow search table in HW FST + * + * @qdf_dev: QDF device handle + * @hal_fst_base_paddr: Pointer to the physical base address of the Rx FST + * @max_entries: Max number of flows allowed in the FST + * @max_search: Number of collisions allowed in the hash-based FST + * @hash_key: Toeplitz key used for the hash FST + * + * Return: + */ +struct hal_rx_fst * +hal_rx_fst_attach(qdf_device_t qdf_dev, + uint64_t *hal_fst_base_paddr, uint16_t max_entries, + uint16_t max_search, uint8_t *hash_key) +{ + struct hal_rx_fst *fst = qdf_mem_malloc(sizeof(struct hal_rx_fst)); + + if (!fst) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + FL("hal fst allocation failed,")); + return NULL; + } + + qdf_mem_set(fst, 0, sizeof(struct hal_rx_fst)); + + fst->key = hash_key; + fst->max_skid_length = max_search; + fst->max_entries = max_entries; + fst->hash_mask = max_entries - 1; + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "HAL FST allocation %pK %d * %d\n", fst, + fst->max_entries, HAL_RX_FST_ENTRY_SIZE); + + fst->base_vaddr = (uint8_t *)qdf_mem_alloc_consistent(qdf_dev, + qdf_dev->dev, + (fst->max_entries * HAL_RX_FST_ENTRY_SIZE), + &fst->base_paddr); + + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, + "hal_rx_fst base address 0x%pK", (void *)fst->base_paddr); + if (!fst->base_vaddr) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + FL("hal fst->base_vaddr allocation failed")); + qdf_mem_free(fst); + return NULL; + } + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_DEBUG, + (void *)fst->key, HAL_FST_HASH_KEY_SIZE_BYTES); + + qdf_mem_set((uint8_t *)fst->base_vaddr, 0, + (fst->max_entries * HAL_RX_FST_ENTRY_SIZE)); + + hal_rx_fst_key_configure(fst); + hal_flow_toeplitz_create_cache(fst); + *hal_fst_base_paddr = (uint64_t)fst->base_paddr; + return fst; +} +qdf_export_symbol(hal_rx_fst_attach); + +/** + * hal_rx_fst_detach() - De-init the Rx flow search table from HW + * + * @rx_fst: Pointer to the Rx FST + * @qdf_dev: QDF device handle + * + * Return: + */ +void hal_rx_fst_detach(struct hal_rx_fst *rx_fst, + qdf_device_t qdf_dev) +{ + if (!rx_fst || !qdf_dev) + return; + + qdf_mem_free_consistent(qdf_dev, qdf_dev->dev, + rx_fst->max_entries * HAL_RX_FST_ENTRY_SIZE, + rx_fst->base_vaddr, rx_fst->base_paddr, 0); + + qdf_mem_free(rx_fst); +} +qdf_export_symbol(hal_rx_fst_detach); + +#ifndef WLAN_SUPPORT_RX_FISA +/** + * hal_flow_toeplitz_hash() - Calculate Toeplitz hash by using the cached key + * + * @hal_fst: FST Handle + * @flow: Flow Parameters + * + * Return: Success/Failure + */ +uint32_t +hal_flow_toeplitz_hash(void *hal_fst, struct hal_rx_flow *flow) +{ + int i, j; + uint32_t hash = 0; + struct hal_rx_fst *fst = (struct hal_rx_fst *)hal_fst; + uint32_t input[HAL_FST_HASH_KEY_SIZE_WORDS]; + uint8_t *tuple; + + qdf_mem_zero(input, HAL_FST_HASH_KEY_SIZE_BYTES); + *(uint32_t *)&input[0] = qdf_htonl(flow->tuple_info.src_ip_127_96); + *(uint32_t *)&input[1] = qdf_htonl(flow->tuple_info.src_ip_95_64); + *(uint32_t *)&input[2] = qdf_htonl(flow->tuple_info.src_ip_63_32); + *(uint32_t *)&input[3] = qdf_htonl(flow->tuple_info.src_ip_31_0); + *(uint32_t *)&input[4] = qdf_htonl(flow->tuple_info.dest_ip_127_96); + *(uint32_t *)&input[5] = qdf_htonl(flow->tuple_info.dest_ip_95_64); + *(uint32_t *)&input[6] = qdf_htonl(flow->tuple_info.dest_ip_63_32); + *(uint32_t *)&input[7] = qdf_htonl(flow->tuple_info.dest_ip_31_0); + *(uint32_t *)&input[8] = (flow->tuple_info.dest_port << 16) | + (flow->tuple_info.src_port); + *(uint32_t *)&input[9] = flow->tuple_info.l4_protocol; + + tuple = (uint8_t *)input; + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + tuple, sizeof(input)); + for (i = 0, j = HAL_FST_HASH_DATA_SIZE - 1; + i < HAL_FST_HASH_KEY_SIZE_BYTES && j >= 0; i++, j--) { + hash ^= fst->key_cache[i][tuple[j]]; + } + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW, + "Hash value %u %u truncated hash %u\n", hash, + (hash >> 12), (hash >> 12) % (fst->max_entries)); + + hash >>= 12; + hash &= (fst->max_entries - 1); + + return hash; +} +#else +uint32_t +hal_flow_toeplitz_hash(void *hal_fst, struct hal_rx_flow *flow) +{ + return 0; +} +#endif +qdf_export_symbol(hal_flow_toeplitz_hash); + +/** + * hal_rx_get_hal_hash() - Retrieve hash index of a flow in the FST table + * + * @hal_fst: HAL Rx FST Handle + * @flow_hash: Flow hash computed from flow tuple + * + * Return: hash index truncated to the size of the hash table + */ +uint32_t hal_rx_get_hal_hash(struct hal_rx_fst *hal_fst, uint32_t flow_hash) +{ + uint32_t trunc_hash = flow_hash; + + /* Take care of hash wrap around scenario */ + if (flow_hash >= hal_fst->max_entries) + trunc_hash &= hal_fst->hash_mask; + return trunc_hash; +} +qdf_export_symbol(hal_rx_get_hal_hash); + +/** + * hal_rx_insert_flow_entry() - Add a flow into the FST table + * + * @hal_fst: HAL Rx FST Handle + * @flow_hash: Flow hash computed from flow tuple + * @flow_tuple_info: Flow tuple used to compute the hash + * @flow_index: Hash index of the flow in the table when inserted successfully + * + * Return: Success if flow is inserted into the table, error otherwise + */ +QDF_STATUS +hal_rx_insert_flow_entry(struct hal_rx_fst *fst, uint32_t flow_hash, + void *flow_tuple_info, uint32_t *flow_idx) +{ + int i; + void *hal_fse = NULL; + uint32_t hal_hash = 0; + struct hal_flow_tuple_info hal_tuple_info = { 0 }; + QDF_STATUS status; + + for (i = 0; i < fst->max_skid_length; i++) { + hal_hash = hal_rx_get_hal_hash(fst, (flow_hash + i)); + hal_fse = (uint8_t *)fst->base_vaddr + + (hal_hash * HAL_RX_FST_ENTRY_SIZE); + status = hal_rx_flow_get_tuple_info(hal_fse, &hal_tuple_info); + if (status == QDF_STATUS_E_NOENT) + break; + + /* Find the matching flow entry in HW FST */ + if (!qdf_mem_cmp(&hal_tuple_info, + flow_tuple_info, + sizeof(struct hal_flow_tuple_info))) { + dp_err("Duplicate flow entry in FST %u at skid %u ", + hal_hash, i); + return QDF_STATUS_E_EXISTS; + } + } + if (i == fst->max_skid_length) { + dp_err("Max skid length reached for hash %u", flow_hash); + return QDF_STATUS_E_RANGE; + } + *flow_idx = hal_hash; + dp_info("flow_hash = %u, skid_entry = %d, flow_addr = %pK flow_idx = %d", + flow_hash, i, hal_fse, *flow_idx); + + return QDF_STATUS_SUCCESS; +} +qdf_export_symbol(hal_rx_insert_flow_entry); + +/** + * hal_rx_find_flow_from_tuple() - Find a flow in the FST table + * + * @fst: HAL Rx FST Handle + * @flow_hash: Flow hash computed from flow tuple + * @flow_tuple_info: Flow tuple used to compute the hash + * @flow_index: Hash index of the flow in the table when found + * + * Return: Success if matching flow is found in the table, error otherwise + */ +QDF_STATUS +hal_rx_find_flow_from_tuple(struct hal_rx_fst *fst, uint32_t flow_hash, + void *flow_tuple_info, uint32_t *flow_idx) +{ + int i; + void *hal_fse = NULL; + uint32_t hal_hash = 0; + struct hal_flow_tuple_info hal_tuple_info = { 0 }; + QDF_STATUS status; + + for (i = 0; i < fst->max_skid_length; i++) { + hal_hash = hal_rx_get_hal_hash(fst, (flow_hash + i)); + hal_fse = (uint8_t *)fst->base_vaddr + + (hal_hash * HAL_RX_FST_ENTRY_SIZE); + status = hal_rx_flow_get_tuple_info(hal_fse, &hal_tuple_info); + if (status != QDF_STATUS_SUCCESS) + continue; + + /* Find the matching flow entry in HW FST */ + if (!qdf_mem_cmp(&hal_tuple_info, + flow_tuple_info, + sizeof(struct hal_flow_tuple_info))) { + break; + } + } + + if (i == fst->max_skid_length) { + dp_err("Max skid length reached for hash %u", flow_hash); + return QDF_STATUS_E_RANGE; + } + + *flow_idx = hal_hash; + dp_info("flow_hash = %u, skid_entry = %d, flow_addr = %pK flow_idx = %d", + flow_hash, i, hal_fse, *flow_idx); + + return QDF_STATUS_SUCCESS; +} +qdf_export_symbol(hal_rx_find_flow_from_tuple); diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_rx_flow.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_rx_flow.h new file mode 100644 index 0000000000000000000000000000000000000000..6101034e74be5946310620184def12858572dd3c --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_rx_flow.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __HAL_RX_FLOW_H +#define __HAL_RX_FLOW_H + +#include "hal_flow.h" +#include "wlan_cfg.h" +#include "hal_api.h" +#include "qdf_mem.h" +#include "rx_flow_search_entry.h" + +#define HAL_FST_HASH_KEY_SIZE_BITS 315 +#define HAL_FST_HASH_KEY_SIZE_BYTES 40 +#define HAL_FST_HASH_KEY_SIZE_WORDS 10 +#define HAL_FST_HASH_DATA_SIZE 37 +#define HAL_FST_HASH_MASK 0x7ffff +#define HAL_RX_FST_ENTRY_SIZE (NUM_OF_DWORDS_RX_FLOW_SEARCH_ENTRY * 4) + +/** + * Four possible options for IP SA/DA prefix, currently use 0x0 which + * maps to type 2 in HW spec + */ +#define HAL_FST_IP_DA_SA_PFX_TYPE_IPV4_COMPATIBLE_IPV6 2 + +#define HAL_IP_DA_SA_PREFIX_IPV4_COMPATIBLE_IPV6 0x0 + +/** + * REO destination indication is a lower 4-bits of hash value + * This should match the REO destination used in Rx hash based routing. + */ +#define HAL_REO_DEST_IND_HASH_MASK 0xF + +/** + * REO destinations are valid from 16-31 for Hawkeye + * and 0-15 are not setup for SW + */ +#define HAL_REO_DEST_IND_START_OFFSET 0x10 + +/** + * struct hal_rx_flow - Rx Flow parameters to be sent to HW + * @tuple_info: Rx Flow 5-tuple (src & dest IP, src & dest ports, L4 protocol) + * @reo_destination_handler: REO destination for this flow + * @reo_destination_indication: REO indication for this flow + * @fse_metadata: Flow metadata or tag passed to HW for marking packets + */ +struct hal_rx_flow { + struct hal_flow_tuple_info tuple_info; + uint8_t reo_destination_handler; + uint8_t reo_destination_indication; + uint32_t fse_metadata; +}; + +/** + * enum hal_rx_fse_reo_destination_handler + * @HAL_RX_FSE_REO_DEST_FT: Use this entry's destination indication + * @HAL_RX_FSE_REO_DEST_ASPT: Use Address Search + Peer Table's entry + * @HAL_RX_FSE_REO_DEST_FT2: Use FT2's destination indication + * @HAL_RX_FSE_REO_DEST_CCE: Use CCE's destination indication for this entry + */ +enum hal_rx_fse_reo_destination_handler { + HAL_RX_FSE_REO_DEST_FT = 0, + HAL_RX_FSE_REO_DEST_ASPT = 1, + HAL_RX_FSE_REO_DEST_FT2 = 2, + HAL_RX_FSE_REO_DEST_CCE = 3, +}; + +/** + * struct hal_rx_fst - HAL RX Flow search table context + * @base_vaddr: Virtual Base address of HW FST + * @base_paddr: Physical Base address of HW FST + * @key: Pointer to 320-bit Key read from cfg + * @shifted_key: Pointer to left-shifted 320-bit Key used for Toeplitz Hash + * @max_entries : Max number of entries in flow searchh table + * @max_skid_length : Max search length if there is hash collision + * @hash_mask: Hash mask to apply to index into FST + * @key_cache: Toepliz Key Cache configured key + */ +struct hal_rx_fst { + uint8_t *base_vaddr; + qdf_dma_addr_t base_paddr; + uint8_t *key; +#ifndef WLAN_SUPPORT_RX_FISA + uint8_t shifted_key[HAL_FST_HASH_KEY_SIZE_BYTES]; + uint32_t key_cache[HAL_FST_HASH_KEY_SIZE_BYTES][1 << 8]; +#endif + uint16_t max_entries; + uint16_t max_skid_length; + uint16_t hash_mask; + uint32_t add_flow_count; + uint32_t del_flow_count; +}; + +/** + * hal_rx_flow_setup_fse() - Setup a flow search entry in HW FST + * @fst: Pointer to the Rx Flow Search Table + * @table_offset: offset into the table where the flow is to be setup + * @flow: Flow Parameters + * + * Return: Success/Failure + */ +void *hal_rx_flow_setup_fse(struct hal_rx_fst *fst, + uint32_t table_offset, + struct hal_rx_flow *flow); + +/** + * hal_rx_flow_delete_entry() - Delete a flow from the Rx Flow Search Table + * @fst: Pointer to the Rx Flow Search Table + * @hal_rx_fse: Pointer to the Rx Flow that is to be deleted from the FST + * + * Return: Success/Failure + */ +QDF_STATUS +hal_rx_flow_delete_entry(struct hal_rx_fst *fst, void *hal_rx_fse); + +/** + * hal_rx_flow_get_tuple_info() - Retrieve the 5-tuple flow info for an entry + * @hal_fse: Pointer to the Flow in Rx FST + * @tuple_info: 5-tuple info of the flow returned to the caller + * + * Return: Success/Failure + */ +QDF_STATUS hal_rx_flow_get_tuple_info(void *hal_fse, + struct hal_flow_tuple_info *tuple_info); + +/** + * hal_rx_fst_attach() - Initialize Rx flow search table in HW FST + * + * @qdf_dev: QDF device handle + * @hal_fst_base_paddr: Pointer to the physical base address of the Rx FST + * @max_entries: Max number of flows allowed in the FST + * @max_search: Number of collisions allowed in the hash-based FST + * @hash_key: Toeplitz key used for the hash FST + * + * Return: + */ +struct hal_rx_fst * +hal_rx_fst_attach(qdf_device_t qdf_dev, + uint64_t *hal_fst_base_paddr, uint16_t max_entries, + uint16_t max_search, uint8_t *hash_key); + +/** + * hal_rx_fst_detach() - De-init the Rx flow search table from HW + * + * @rx_fst: Pointer to the Rx FST + * @qdf_dev: QDF device handle + * + * Return: + */ +void hal_rx_fst_detach(struct hal_rx_fst *rx_fst, qdf_device_t qdf_dev); + +/** + * hal_rx_insert_flow_entry() - Add a flow into the FST table + * + * @hal_fst: HAL Rx FST Handle + * @flow_hash: Flow hash computed from flow tuple + * @flow_tuple_info: Flow tuple used to compute the hash + * @flow_index: Hash index of the flow in the table when inserted successfully + * + * Return: Success if flow is inserted into the table, error otherwise + */ +QDF_STATUS +hal_rx_insert_flow_entry(struct hal_rx_fst *fst, uint32_t flow_hash, + void *flow_tuple_info, uint32_t *flow_idx); + +/** + * hal_rx_find_flow_from_tuple() - Find a flow in the FST table + * + * @fst: HAL Rx FST Handle + * @flow_hash: Flow hash computed from flow tuple + * @flow_tuple_info: Flow tuple used to compute the hash + * @flow_index: Hash index of the flow in the table when found + * + * Return: Success if matching flow is found in the table, error otherwise + */ +QDF_STATUS +hal_rx_find_flow_from_tuple(struct hal_rx_fst *fst, uint32_t flow_hash, + void *flow_tuple_info, uint32_t *flow_idx); + +/** + * hal_rx_get_hal_hash() - Retrieve hash index of a flow in the FST table + * + * @hal_fst: HAL Rx FST Handle + * @flow_hash: Flow hash computed from flow tuple + * + * Return: hash index truncated to the size of the hash table + */ +uint32_t hal_rx_get_hal_hash(struct hal_rx_fst *hal_fst, uint32_t flow_hash); + +/** + * hal_flow_toeplitz_hash() - Calculate Toeplitz hash by using the cached key + * + * @hal_fst: FST Handle + * @flow: Flow Parameters + * + * Return: Success/Failure + */ +uint32_t +hal_flow_toeplitz_hash(void *hal_fst, struct hal_rx_flow *flow); + +void hal_rx_dump_fse_table(struct hal_rx_fst *fst); +#endif /* HAL_RX_FLOW_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_srng.c b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_srng.c index d8ae29eefa7a490be10d43a932434225aeddd3ba..1290984f77497e3b2d8696473b3fe2865e58933a 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_srng.c +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_srng.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -28,14 +28,20 @@ void hal_qca6290_attach(struct hal_soc *hal); #ifdef QCA_WIFI_QCA8074 void hal_qca8074_attach(struct hal_soc *hal); #endif -#ifdef QCA_WIFI_QCA8074V2 +#if defined(QCA_WIFI_QCA8074V2) || defined(QCA_WIFI_QCA6018) void hal_qca8074v2_attach(struct hal_soc *hal); #endif #ifdef QCA_WIFI_QCA6390 void hal_qca6390_attach(struct hal_soc *hal); #endif -#ifdef QCA_WIFI_QCA6018 -void hal_qca6018_attach(struct hal_soc *hal); +#ifdef QCA_WIFI_QCA6490 +void hal_qca6490_attach(struct hal_soc *hal); +#endif +#ifdef QCA_WIFI_QCN9000 +void hal_qcn9000_attach(struct hal_soc *hal); +#endif +#ifdef QCA_WIFI_QCA6750 +void hal_qca6750_attach(struct hal_soc *hal); #endif #ifdef ENABLE_VERBOSE_DEBUG @@ -117,16 +123,15 @@ static struct hal_srng *hal_get_srng(struct hal_soc *hal, int ring_id) #define HP_OFFSET_IN_REG_START 1 #define OFFSET_FROM_HP_TO_TP 4 -static void hal_update_srng_hp_tp_address(void *hal_soc, +static void hal_update_srng_hp_tp_address(struct hal_soc *hal_soc, int shadow_config_index, int ring_type, int ring_num) { struct hal_srng *srng; - struct hal_soc *hal = (struct hal_soc *)hal_soc; int ring_id; struct hal_hw_srng_config *ring_config = - HAL_SRNG_CONFIG(hal, ring_type); + HAL_SRNG_CONFIG(hal_soc, ring_type); ring_id = hal_get_srng_ring_id(hal_soc, ring_type, ring_num, 0); if (ring_id < 0) @@ -136,20 +141,93 @@ static void hal_update_srng_hp_tp_address(void *hal_soc, if (ring_config->ring_dir == HAL_SRNG_DST_RING) { srng->u.dst_ring.tp_addr = SHADOW_REGISTER(shadow_config_index) - + hal->dev_base_addr; + + hal_soc->dev_base_addr; hal_debug("tp_addr=%pK dev base addr %pK index %u", - srng->u.dst_ring.tp_addr, hal->dev_base_addr, + srng->u.dst_ring.tp_addr, hal_soc->dev_base_addr, shadow_config_index); } else { srng->u.src_ring.hp_addr = SHADOW_REGISTER(shadow_config_index) - + hal->dev_base_addr; + + hal_soc->dev_base_addr; hal_debug("hp_addr=%pK dev base addr %pK index %u", srng->u.src_ring.hp_addr, - hal->dev_base_addr, shadow_config_index); + hal_soc->dev_base_addr, shadow_config_index); + } + +} + +#ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE +void hal_set_one_target_reg_config(struct hal_soc *hal, + uint32_t target_reg_offset, + int list_index) +{ + int i = list_index; + + qdf_assert_always(i < MAX_GENERIC_SHADOW_REG); + hal->list_shadow_reg_config[i].target_register = + target_reg_offset; + hal->num_generic_shadow_regs_configured++; +} + +qdf_export_symbol(hal_set_one_target_reg_config); + +#define REO_R0_DESTINATION_RING_CTRL_ADDR_OFFSET 0x4 +#define MAX_REO_REMAP_SHADOW_REGS 4 +QDF_STATUS hal_set_shadow_regs(void *hal_soc) +{ + uint32_t target_reg_offset; + struct hal_soc *hal = (struct hal_soc *)hal_soc; + int i; + struct hal_hw_srng_config *srng_config = + &hal->hw_srng_table[WBM2SW_RELEASE]; + + target_reg_offset = + HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET); + + for (i = 0; i < MAX_REO_REMAP_SHADOW_REGS; i++) { + hal_set_one_target_reg_config(hal, target_reg_offset, i); + target_reg_offset += REO_R0_DESTINATION_RING_CTRL_ADDR_OFFSET; } + target_reg_offset = srng_config->reg_start[HP_OFFSET_IN_REG_START]; + target_reg_offset += (srng_config->reg_size[HP_OFFSET_IN_REG_START] + * HAL_IPA_TX_COMP_RING_IDX); + + hal_set_one_target_reg_config(hal, target_reg_offset, i); + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(hal_set_shadow_regs); + +QDF_STATUS hal_construct_shadow_regs(void *hal_soc) +{ + struct hal_soc *hal = (struct hal_soc *)hal_soc; + int shadow_config_index = hal->num_shadow_registers_configured; + int i; + int num_regs = hal->num_generic_shadow_regs_configured; + + for (i = 0; i < num_regs; i++) { + qdf_assert_always(shadow_config_index < MAX_SHADOW_REGISTERS); + hal->shadow_config[shadow_config_index].addr = + hal->list_shadow_reg_config[i].target_register; + hal->list_shadow_reg_config[i].shadow_config_index = + shadow_config_index; + hal->list_shadow_reg_config[i].va = + SHADOW_REGISTER(shadow_config_index) + + (uintptr_t)hal->dev_base_addr; + hal_debug("target_reg %x, shadow register 0x%x shadow_index 0x%x", + hal->shadow_config[shadow_config_index].addr, + SHADOW_REGISTER(shadow_config_index), + shadow_config_index); + shadow_config_index++; + hal->num_shadow_registers_configured++; + } + return QDF_STATUS_SUCCESS; } +qdf_export_symbol(hal_construct_shadow_regs); +#endif + QDF_STATUS hal_set_one_shadow_config(void *hal_soc, int ring_type, int ring_num) @@ -191,7 +269,7 @@ QDF_STATUS hal_set_one_shadow_config(void *hal_soc, qdf_export_symbol(hal_set_one_shadow_config); -QDF_STATUS hal_construct_shadow_config(void *hal_soc) +QDF_STATUS hal_construct_srng_shadow_regs(void *hal_soc) { int ring_type, ring_num; struct hal_soc *hal = (struct hal_soc *)hal_soc; @@ -216,7 +294,7 @@ QDF_STATUS hal_construct_shadow_config(void *hal_soc) return QDF_STATUS_SUCCESS; } -qdf_export_symbol(hal_construct_shadow_config); +qdf_export_symbol(hal_construct_srng_shadow_regs); void hal_get_shadow_config(void *hal_soc, struct pld_shadow_reg_v2_cfg **shadow_config, @@ -227,17 +305,14 @@ void hal_get_shadow_config(void *hal_soc, *shadow_config = hal->shadow_config; *num_shadow_registers_configured = hal->num_shadow_registers_configured; - - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "%s", __func__); } qdf_export_symbol(hal_get_shadow_config); -static void hal_validate_shadow_register(struct hal_soc *hal, - uint32_t *destination, - uint32_t *shadow_address) +static bool hal_validate_shadow_register(struct hal_soc *hal, + uint32_t *destination, + uint32_t *shadow_address) { unsigned int index; uint32_t *shadow_0_offset = SHADOW_REGISTER(0) + hal->dev_base_addr; @@ -257,17 +332,23 @@ static void hal_validate_shadow_register(struct hal_soc *hal, hal->shadow_config[index].addr); goto error; } - return; + return true; error: qdf_print("%s: baddr %pK, desination %pK, shadow_address %pK s0offset %pK index %x", __func__, hal->dev_base_addr, destination, shadow_address, shadow_0_offset, index); QDF_BUG(0); - return; + return false; } static void hal_target_based_configure(struct hal_soc *hal) { + /** + * Indicate Initialization of srngs to avoid force wake + * as umac power collapse is not enabled yet + */ + hal->init_phase = true; + switch (hal->target_type) { #ifdef QCA_WIFI_QCA6290 case TARGET_TYPE_QCA6290: @@ -281,21 +362,46 @@ static void hal_target_based_configure(struct hal_soc *hal) hal_qca6390_attach(hal); break; #endif -#if defined(QCA_WIFI_QCA8074) && defined(CONFIG_WIN) +#ifdef QCA_WIFI_QCA6490 + case TARGET_TYPE_QCA6490: + hal->use_register_windowing = true; + hal_qca6490_attach(hal); + hal->init_phase = false; + break; +#endif +#ifdef QCA_WIFI_QCA6750 + case TARGET_TYPE_QCA6750: + hal->use_register_windowing = true; + hal_qca6750_attach(hal); + break; +#endif +#if defined(QCA_WIFI_QCA8074) && defined(WIFI_TARGET_TYPE_3_0) case TARGET_TYPE_QCA8074: hal_qca8074_attach(hal); break; #endif -#if defined(QCA_WIFI_QCA8074V2) && defined(CONFIG_WIN) +#if defined(QCA_WIFI_QCA8074V2) case TARGET_TYPE_QCA8074V2: hal_qca8074v2_attach(hal); break; #endif -#if defined(QCA_WIFI_QCA6018) && defined(CONFIG_WIN) +#if defined(QCA_WIFI_QCA6018) case TARGET_TYPE_QCA6018: - hal_qca6018_attach(hal); + hal_qca8074v2_attach(hal); + break; +#endif + +#ifdef QCA_WIFI_QCN9000 + case TARGET_TYPE_QCN9000: + hal->use_register_windowing = true; + /* + * Static window map is enabled for qcn9000 to use 2mb bar + * size and use multiple windows to write into registers. + */ + hal->static_window_map = true; + hal_qcn9000_attach(hal); break; #endif default: @@ -303,10 +409,11 @@ static void hal_target_based_configure(struct hal_soc *hal) } } -uint32_t hal_get_target_type(struct hal_soc *hal) +uint32_t hal_get_target_type(hal_soc_handle_t hal_soc_hdl) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; struct hif_target_info *tgt_info = - hif_get_target_info_handle(hal->hif_handle); + hif_get_target_info_handle(hal_soc->hif_handle); return tgt_info->target_type; } @@ -317,7 +424,7 @@ qdf_export_symbol(hal_get_target_type); #ifdef MEMORY_DEBUG /* * Length of the queue(array) used to hold delayed register writes. - * Must be a power of 2. + * Must be a multiple of 2. */ #define HAL_REG_WRITE_QUEUE_LEN 128 #else @@ -371,6 +478,7 @@ hal_process_reg_write_q_elem(struct hal_soc *hal, } q_elem->valid = 0; + srng->last_dequeue_time = q_elem->dequeue_time; SRNG_UNLOCK(&srng->lock); return write_val; @@ -397,9 +505,67 @@ static inline void hal_reg_write_fill_sched_delay_hist(struct hal_soc *hal, else if (delay_us < 5000) hist[REG_WRITE_SCHED_DELAY_SUB_5000us]++; else - hist[REG_WRITE_SCHED_DELAY_GE_5000us]++; + hist[REG_WRITE_SCHED_DELAY_GT_5000us]++; } +#ifdef SHADOW_WRITE_DELAY + +#define SHADOW_WRITE_MIN_DELTA_US 5 +#define SHADOW_WRITE_DELAY_US 50 + +/* + * Never add those srngs which are performance relate. + * The delay itself will hit performance heavily. + */ +#define IS_SRNG_MATCH(s) ((s)->ring_id == HAL_SRNG_CE_1_DST_STATUS || \ + (s)->ring_id == HAL_SRNG_CE_1_DST) + +static inline bool hal_reg_write_need_delay(struct hal_reg_write_q_elem *elem) +{ + struct hal_srng *srng = elem->srng; + struct hal_soc *hal; + qdf_time_t now; + qdf_iomem_t real_addr; + + if (qdf_unlikely(!srng)) + return false; + + hal = srng->hal_soc; + if (qdf_unlikely(!hal)) + return false; + + /* Check if it is target srng, and valid shadow reg */ + if (qdf_likely(!IS_SRNG_MATCH(srng))) + return false; + + if (srng->ring_dir == HAL_SRNG_SRC_RING) + real_addr = SRNG_SRC_ADDR(srng, HP); + else + real_addr = SRNG_DST_ADDR(srng, TP); + if (!hal_validate_shadow_register(hal, real_addr, elem->addr)) + return false; + + /* Check the time delta from last write of same srng */ + now = qdf_get_log_timestamp(); + if (qdf_log_timestamp_to_usecs(now - srng->last_dequeue_time) > + SHADOW_WRITE_MIN_DELTA_US) + return false; + + /* Delay dequeue, and record */ + qdf_udelay(SHADOW_WRITE_DELAY_US); + + srng->wstats.dequeue_delay++; + hal->stats.wstats.dequeue_delay++; + + return true; +} +#else +static inline bool hal_reg_write_need_delay(struct hal_reg_write_q_elem *elem) +{ + return false; +} +#endif + /** * hal_reg_write_work() - Worker to process delayed writes * @arg: hal_soc pointer @@ -416,7 +582,10 @@ static void hal_reg_write_work(void *arg) uint32_t *addr; q_elem = &hal->reg_write_queue[(hal->read_idx)]; + q_elem->work_scheduled_time = qdf_get_log_timestamp(); + /* Make sure q_elem consistent in the memory for multi-cores */ + qdf_rmb(); if (!q_elem->valid) return; @@ -429,7 +598,11 @@ static void hal_reg_write_work(void *arg) return; } - while (q_elem->valid) { + while (true) { + qdf_rmb(); + if (!q_elem->valid) + break; + q_elem->dequeue_time = qdf_get_log_timestamp(); ring_id = q_elem->srng->ring_id; addr = q_elem->addr; @@ -440,6 +613,10 @@ static void hal_reg_write_work(void *arg) hal->stats.wstats.dequeues++; qdf_atomic_dec(&hal->stats.wstats.q_depth); + if (hal_reg_write_need_delay(q_elem)) + hal_verbose_debug("Delay reg writer for srng 0x%x, addr 0x%pK", + q_elem->srng->ring_id, q_elem->addr); + write_val = hal_process_reg_write_q_elem(hal, q_elem); hal_verbose_debug("read_idx %u srng 0x%x, addr 0x%pK dequeue_val %u sched delay %llu us", hal->read_idx, ring_id, addr, write_val, delta_us); @@ -524,6 +701,17 @@ static void hal_reg_write_enqueue(struct hal_soc *hal_soc, qdf_wmb(); q_elem->valid = true; + /* + * After all other fields in the q_elem has been updated + * in memory successfully, the valid flag needs to be updated + * in memory in time too. + * Else there is a chance that the dequeuing worker thread + * might read stale valid flag and the work will be bypassed + * for this round. And if there is no other work scheduled + * later, this hal register writing won't be updated any more. + */ + qdf_wmb(); + srng->reg_write_in_progress = true; qdf_atomic_inc(&hal_soc->active_work_cnt); @@ -606,7 +794,7 @@ char *hal_fill_reg_write_srng_stats(struct hal_srng *srng, /* bytes for local buffer */ #define HAL_REG_WRITE_SRNG_STATS_LEN 100 -void hal_dump_reg_write_srng_stats(struct hal_soc *hal_soc_hdl) +void hal_dump_reg_write_srng_stats(hal_soc_handle_t hal_soc_hdl) { struct hal_srng *srng; char buf[HAL_REG_WRITE_SRNG_STATS_LEN]; @@ -633,7 +821,7 @@ void hal_dump_reg_write_srng_stats(struct hal_soc *hal_soc_hdl) hal_fill_reg_write_srng_stats(srng, buf, sizeof(buf))); } -void hal_dump_reg_write_stats(struct hal_soc *hal_soc_hdl) +void hal_dump_reg_write_stats(hal_soc_handle_t hal_soc_hdl) { uint32_t *hist; struct hal_soc *hal = (struct hal_soc *)hal_soc_hdl; @@ -650,7 +838,7 @@ void hal_dump_reg_write_stats(struct hal_soc *hal_soc_hdl) 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_GE_5000us]); + hist[REG_WRITE_SCHED_DELAY_GT_5000us]); } int hal_get_reg_write_pending_work(void *hal_soc) @@ -683,7 +871,7 @@ static inline void hal_delayed_reg_write_deinit(struct hal_soc *hal) * copy engines). DP layer will get hal_soc handle using hif_get_hal_handle() * */ -void *hal_attach(void *hif_handle, qdf_device_t qdf_dev) +void *hal_attach(struct hif_opaque_softc *hif_handle, qdf_device_t qdf_dev) { struct hal_soc *hal; int i; @@ -695,7 +883,7 @@ void *hal_attach(void *hif_handle, qdf_device_t qdf_dev) "%s: hal_soc allocation failed", __func__); goto fail0; } - qdf_minidump_log((void *)hal, sizeof(*hal), "hal_soc"); + qdf_minidump_log(hal, sizeof(*hal), "hal_soc"); hal->hif_handle = hif_handle; hal->dev_base_addr = hif_get_dev_ba(hif_handle); hal->qdf_dev = qdf_dev; @@ -731,9 +919,10 @@ void *hal_attach(void *hif_handle, qdf_device_t qdf_dev) qdf_spinlock_create(&hal->register_access_lock); hal->register_window = 0; - hal->target_type = hal_get_target_type(hal); + hal->target_type = hal_get_target_type(hal_soc_to_hal_soc_handle(hal)); hal_target_based_configure(hal); + hal_reg_write_fail_history_init(hal); qdf_atomic_init(&hal->active_work_cnt); @@ -758,15 +947,16 @@ qdf_export_symbol(hal_attach); * @hal_soc: Opaque HAL SOC handle * @mem: pointer to structure to be updated with hal mem info */ -void hal_get_meminfo(void *hal_soc, struct hal_mem_info *mem ) +void hal_get_meminfo(hal_soc_handle_t hal_soc_hdl, struct hal_mem_info *mem) { - struct hal_soc *hal = (struct hal_soc *)hal_soc; + struct hal_soc *hal = (struct hal_soc *)hal_soc_hdl; mem->dev_base_addr = (void *)hal->dev_base_addr; mem->shadow_rdptr_mem_vaddr = (void *)hal->shadow_rdptr_mem_vaddr; mem->shadow_wrptr_mem_vaddr = (void *)hal->shadow_wrptr_mem_vaddr; mem->shadow_rdptr_mem_paddr = (void *)hal->shadow_rdptr_mem_paddr; mem->shadow_wrptr_mem_paddr = (void *)hal->shadow_wrptr_mem_paddr; - hif_read_phy_mem_base(hal->hif_handle, (qdf_dma_addr_t *)&mem->dev_base_paddr); + hif_read_phy_mem_base((void *)hal->hif_handle, + (qdf_dma_addr_t *)&mem->dev_base_paddr); return; } qdf_export_symbol(hal_get_meminfo); @@ -794,13 +984,13 @@ extern void hal_detach(void *hal_soc) qdf_mem_free_consistent(hal->qdf_dev, hal->qdf_dev->dev, sizeof(*(hal->shadow_wrptr_mem_vaddr)) * HAL_MAX_LMAC_RINGS, hal->shadow_wrptr_mem_vaddr, hal->shadow_wrptr_mem_paddr, 0); + qdf_minidump_remove(hal); qdf_mem_free(hal); return; } qdf_export_symbol(hal_detach); - /** * hal_ce_dst_setup - Initialize CE destination ring registers * @hal_soc: HAL SOC handle @@ -824,6 +1014,19 @@ static inline void hal_ce_dst_setup(struct hal_soc *hal, struct hal_srng *srng, reg_val |= srng->u.dst_ring.max_buffer_length & HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_CTRL_DEST_MAX_LENGTH_BMSK; HAL_REG_WRITE(hal, reg_addr, reg_val); + + if (srng->prefetch_timer) { + reg_addr = HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_CONSUMER_PREFETCH_TIMER_ADDR( + ring_config->reg_start[R0_INDEX] + + (ring_num * ring_config->reg_size[R0_INDEX])); + + reg_val = HAL_REG_READ(hal, reg_addr); + reg_val &= ~HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_CONSUMER_PREFETCH_TIMER_RMSK; + reg_val |= srng->prefetch_timer; + HAL_REG_WRITE(hal, reg_addr, reg_val); + reg_val = HAL_REG_READ(hal, reg_addr); + } + } /** @@ -835,10 +1038,12 @@ static inline void hal_ce_dst_setup(struct hal_soc *hal, struct hal_srng *srng, * @ix2: pointer to store IX2 reg value * @ix3: pointer to store IX3 reg value */ -void hal_reo_read_write_ctrl_ix(struct hal_soc *hal, bool read, uint32_t *ix0, - uint32_t *ix1, uint32_t *ix2, uint32_t *ix3) +void hal_reo_read_write_ctrl_ix(hal_soc_handle_t hal_soc_hdl, bool read, + uint32_t *ix0, uint32_t *ix1, + uint32_t *ix2, uint32_t *ix3) { uint32_t reg_offset; + struct hal_soc *hal = (struct hal_soc *)hal_soc_hdl; if (read) { if (ix0) { @@ -873,59 +1078,69 @@ void hal_reo_read_write_ctrl_ix(struct hal_soc *hal, bool read, uint32_t *ix0, reg_offset = HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET); - HAL_REG_WRITE_CONFIRM(hal, reg_offset, *ix0); + HAL_REG_WRITE_CONFIRM_RETRY(hal, reg_offset, + *ix0, true); } if (ix1) { reg_offset = HWIO_REO_R0_DESTINATION_RING_CTRL_IX_1_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET); - HAL_REG_WRITE(hal, reg_offset, *ix1); + HAL_REG_WRITE_CONFIRM_RETRY(hal, reg_offset, + *ix1, true); } if (ix2) { reg_offset = HWIO_REO_R0_DESTINATION_RING_CTRL_IX_2_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET); - HAL_REG_WRITE_CONFIRM(hal, reg_offset, *ix2); + HAL_REG_WRITE_CONFIRM_RETRY(hal, reg_offset, + *ix2, true); } if (ix3) { reg_offset = HWIO_REO_R0_DESTINATION_RING_CTRL_IX_3_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET); - HAL_REG_WRITE_CONFIRM(hal, reg_offset, *ix3); + HAL_REG_WRITE_CONFIRM_RETRY(hal, reg_offset, + *ix3, true); } } } /** - * hal_srng_dst_set_hp_paddr() - Set physical address to dest ring head pointer + * hal_srng_dst_set_hp_paddr_confirm() - Set physical address to dest ring head + * pointer and confirm that write went through by reading back the value * @srng: sring pointer * @paddr: physical address */ -void hal_srng_dst_set_hp_paddr(struct hal_srng *srng, - uint64_t paddr) +void hal_srng_dst_set_hp_paddr_confirm(struct hal_srng *srng, uint64_t paddr) { - SRNG_DST_REG_WRITE(srng, HP_ADDR_LSB, - paddr & 0xffffffff); - SRNG_DST_REG_WRITE(srng, HP_ADDR_MSB, - paddr >> 32); + SRNG_DST_REG_WRITE_CONFIRM(srng, HP_ADDR_LSB, paddr & 0xffffffff); + SRNG_DST_REG_WRITE_CONFIRM(srng, HP_ADDR_MSB, paddr >> 32); } /** - * hal_srng_dst_init_hp() - Initilaize destination ring head pointer + * hal_srng_dst_init_hp() - Initialize destination ring head + * pointer + * @hal_soc: hal_soc handle * @srng: sring pointer * @vaddr: virtual address */ -void hal_srng_dst_init_hp(struct hal_srng *srng, +void hal_srng_dst_init_hp(struct hal_soc_handle *hal_soc, + struct hal_srng *srng, uint32_t *vaddr) { + uint32_t reg_offset; + struct hal_soc *hal = (struct hal_soc *)hal_soc; + if (!srng) return; srng->u.dst_ring.hp_addr = vaddr; - SRNG_DST_REG_WRITE_CONFIRM(srng, HP, srng->u.dst_ring.cached_hp); + reg_offset = SRNG_DST_ADDR(srng, HP) - hal->dev_base_addr; + HAL_REG_WRITE_CONFIRM_RETRY( + hal, reg_offset, srng->u.dst_ring.cached_hp, true); if (vaddr) { *srng->u.dst_ring.hp_addr = srng->u.dst_ring.cached_hp; @@ -1016,6 +1231,7 @@ void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num, srng->intr_timer_thres_us = ring_params->intr_timer_thres_us; srng->intr_batch_cntr_thres_entries = ring_params->intr_batch_cntr_thres_entries; + srng->prefetch_timer = ring_params->prefetch_timer; srng->hal_soc = hal_soc; for (i = 0 ; i < MAX_SRNG_REG_GROUPS; i++) { @@ -1052,7 +1268,9 @@ void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num, HAL_SRNG_LMAC1_ID_START]); srng->flags |= HAL_SRNG_LMAC_RING; } else if (ignore_shadow || (srng->u.src_ring.hp_addr == 0)) { - srng->u.src_ring.hp_addr = SRNG_SRC_ADDR(srng, HP); + srng->u.src_ring.hp_addr = + hal_get_window_address(hal, + SRNG_SRC_ADDR(srng, HP)); if (CHECK_SHADOW_REGISTERS) { QDF_TRACE(QDF_MODULE_ID_TXRX, @@ -1087,7 +1305,9 @@ void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num, HAL_SRNG_LMAC1_ID_START]); srng->flags |= HAL_SRNG_LMAC_RING; } else if (ignore_shadow || srng->u.dst_ring.tp_addr == 0) { - srng->u.dst_ring.tp_addr = SRNG_DST_ADDR(srng, TP); + srng->u.dst_ring.tp_addr = + hal_get_window_address(hal, + SRNG_DST_ADDR(srng, TP)); if (CHECK_SHADOW_REGISTERS) { QDF_TRACE(QDF_MODULE_ID_TXRX, @@ -1126,9 +1346,9 @@ qdf_export_symbol(hal_srng_setup); * @hal_soc: Opaque HAL SOC handle * @hal_srng: Opaque HAL SRNG pointer */ -void hal_srng_cleanup(void *hal_soc, void *hal_srng) +void hal_srng_cleanup(void *hal_soc, hal_ring_handle_t hal_ring_hdl) { - struct hal_srng *srng = (struct hal_srng *)hal_srng; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; SRNG_LOCK_DESTROY(&srng->lock); srng->initialized = 0; } @@ -1205,10 +1425,11 @@ void hal_srng_dump(struct hal_srng *srng) * @hal_ring: Ring pointer (Source or Destination ring) * @ring_params: SRNG parameters will be returned through this structure */ -extern void hal_get_srng_params(void *hal_soc, void *hal_ring, - struct hal_srng_params *ring_params) +extern void hal_get_srng_params(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl, + struct hal_srng_params *ring_params) { - struct hal_srng *srng = (struct hal_srng *)hal_ring; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; int i =0; ring_params->ring_id = srng->ring_id; ring_params->ring_dir = srng->ring_dir; @@ -1229,3 +1450,12 @@ extern void hal_get_srng_params(void *hal_soc, void *hal_ring, ring_params->hwreg_base[i] = srng->hwreg_base[i]; } qdf_export_symbol(hal_get_srng_params); + +#ifdef FORCE_WAKE +void hal_set_init_phase(hal_soc_handle_t soc, bool init_phase) +{ + struct hal_soc *hal_soc = (struct hal_soc *)soc; + + hal_soc->init_phase = init_phase; +} +#endif /* FORCE_WAKE */ diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_tx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_tx.h index d5c87adc32e72bdeb96a16b11df2d67383a39f90..b5d7020ad58563225b7e7ef97332ab6544c13d0c 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_tx.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_tx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -29,6 +29,8 @@ #define WBM_RELEASE_RING_5_TX_RATE_STATS_LSB 0 #define WBM_RELEASE_RING_5_TX_RATE_STATS_MASK 0xffffffff +#define HAL_WBM_RELEASE_RING_2_BUFFER_TYPE 0 +#define HAL_WBM_RELEASE_RING_2_DESC_TYPE 1 /*--------------------------------------------------------------------------- Preprocessor definitions and constants @@ -91,6 +93,7 @@ do { \ #define HAL_TX_COMPLETION_DESC_BASE_LEN 12 #define HAL_TX_COMP_RELEASE_SOURCE_TQM 0 +#define HAL_TX_COMP_RELEASE_SOURCE_REO 2 #define HAL_TX_COMP_RELEASE_SOURCE_FW 3 /* Define a place-holder release reason for FW */ @@ -260,6 +263,8 @@ enum hal_tx_encap_type { * remove reason is fw_reason2 * @HAL_TX_TQM_RR_FW_REASON3 : Remove command where fw indicated that * remove reason is fw_reason3 + * @HAL_TX_TQM_RR_REM_CMD_DISABLE_QUEUE : Remove command where fw indicated that + * remove reason is remove disable queue */ enum hal_tx_tqm_release_reason { HAL_TX_TQM_RR_FRAME_ACKED, @@ -270,6 +275,7 @@ enum hal_tx_tqm_release_reason { HAL_TX_TQM_RR_FW_REASON1, HAL_TX_TQM_RR_FW_REASON2, HAL_TX_TQM_RR_FW_REASON3, + HAL_TX_TQM_RR_REM_CMD_DISABLE_QUEUE, }; /* enum - Table IDs for 2 DSCP-TID mapping Tables that TCL H/W supports @@ -426,6 +432,7 @@ static inline void hal_tx_desc_set_to_fw(void *desc, uint8_t to_fw) /** * hal_tx_desc_set_mesh_en - Set mesh_enable flag in Tx descriptor + * @hal_soc_hdl: hal soc handle * @desc: Handle to Tx Descriptor * @en: For raw WiFi frames, this indicates transmission to a mesh STA, * enabling the interpretation of the 'Mesh Control Present' bit @@ -435,10 +442,12 @@ static inline void hal_tx_desc_set_to_fw(void *desc, uint8_t to_fw) * * Return: void */ -static inline void hal_tx_desc_set_mesh_en(void *desc, uint8_t en) +static inline void hal_tx_desc_set_mesh_en(hal_soc_handle_t hal_soc_hdl, + void *desc, uint8_t en) { - HAL_SET_FLD(desc, TCL_DATA_CMD_4, MESH_ENABLE) |= - HAL_TX_SM(TCL_DATA_CMD_4, MESH_ENABLE, en); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + hal_soc->ops->hal_tx_desc_set_mesh_en(desc, en); } /** @@ -790,14 +799,15 @@ static inline uint32_t hal_tx_comp_get_buffer_type(void *hal_desc) * * Return: buffer type */ -static inline uint8_t hal_tx_comp_get_release_reason(void *hal_desc, void *hal) +static inline +uint8_t hal_tx_comp_get_release_reason(void *hal_desc, + hal_soc_handle_t hal_soc_hdl) { - struct hal_soc *hal_soc = hal; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; return hal_soc->ops->hal_tx_comp_get_release_reason(hal_desc); } - /** * hal_tx_comp_desc_sync() - collect hardware descriptor contents * @hal_desc: hardware descriptor pointer @@ -862,19 +872,20 @@ static inline void hal_tx_comp_get_htt_desc(void *hw_desc, uint8_t *htt_desc) /** * hal_tx_init_data_ring() - Initialize all the TCL Descriptors in SRNG - * @hal_soc: Handle to HAL SoC structure + * @hal_soc_hdl: Handle to HAL SoC structure * @hal_srng: Handle to HAL SRNG structure * * Return: none */ -static inline void hal_tx_init_data_ring(void *hal_soc, void *hal_srng) +static inline void hal_tx_init_data_ring(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) { uint8_t *desc_addr; struct hal_srng_params srng_params; uint32_t desc_size; uint32_t num_desc; - hal_get_srng_params(hal_soc, hal_srng, &srng_params); + hal_get_srng_params(hal_soc_hdl, hal_ring_hdl, &srng_params); desc_addr = (uint8_t *)srng_params.ring_base_vaddr; desc_size = sizeof(struct tcl_data_cmd); @@ -896,9 +907,12 @@ static inline void hal_tx_init_data_ring(void *hal_soc, void *hal_srng) * * Return: void */ -static inline void hal_tx_desc_set_dscp_tid_table_id(struct hal_soc *hal_soc, - void *desc, uint8_t id) +static inline +void hal_tx_desc_set_dscp_tid_table_id(hal_soc_handle_t hal_soc_hdl, + void *desc, uint8_t id) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + hal_soc->ops->hal_tx_desc_set_dscp_tid_table_id(desc, id); } @@ -911,9 +925,11 @@ static inline void hal_tx_desc_set_dscp_tid_table_id(struct hal_soc *hal_soc, * * Return: void */ -static inline void hal_tx_set_dscp_tid_map(struct hal_soc *hal_soc, +static inline void hal_tx_set_dscp_tid_map(hal_soc_handle_t hal_soc_hdl, uint8_t *map, uint8_t id) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + hal_soc->ops->hal_tx_set_dscp_tid_map(hal_soc, map, id); } @@ -927,9 +943,12 @@ static inline void hal_tx_set_dscp_tid_map(struct hal_soc *hal_soc, * * Return: void */ -static inline void hal_tx_update_dscp_tid(struct hal_soc *hal_soc, uint8_t tid, - uint8_t id, uint8_t dscp) +static inline +void hal_tx_update_dscp_tid(hal_soc_handle_t hal_soc_hdl, uint8_t tid, + uint8_t id, uint8_t dscp) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + hal_soc->ops->hal_tx_update_dscp_tid(hal_soc, tid, id, dscp); } @@ -944,9 +963,11 @@ static inline void hal_tx_update_dscp_tid(struct hal_soc *hal_soc, uint8_t tid, * * Return: void */ -static inline void hal_tx_desc_set_lmac_id(struct hal_soc *hal_soc, +static inline void hal_tx_desc_set_lmac_id(hal_soc_handle_t hal_soc_hdl, void *desc, uint8_t lmac_id) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + hal_soc->ops->hal_tx_desc_set_lmac_id(desc, lmac_id); } @@ -960,9 +981,11 @@ static inline void hal_tx_desc_set_lmac_id(struct hal_soc *hal_soc, * * Return: void */ -static inline void hal_tx_desc_set_search_type(struct hal_soc *hal_soc, +static inline void hal_tx_desc_set_search_type(hal_soc_handle_t hal_soc_hdl, void *desc, uint8_t search_type) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + hal_soc->ops->hal_tx_desc_set_search_type(desc, search_type); } @@ -975,13 +998,37 @@ static inline void hal_tx_desc_set_search_type(struct hal_soc *hal_soc, * * Return: void */ -static inline void hal_tx_desc_set_search_index(struct hal_soc *hal_soc, +static inline void hal_tx_desc_set_search_index(hal_soc_handle_t hal_soc_hdl, void *desc, uint32_t search_index) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + hal_soc->ops->hal_tx_desc_set_search_index(desc, search_index); } +/** + * hal_tx_desc_set_cache_set_num - Set the cache-set-num value + * @desc: Handle to Tx Descriptor + * @cache_num: Cache set number that should be used to cache the index + * based search results, for address and flow search. + * This value should be equal to LSB four bits of the hash value + * of match data, in case of search index points to an entry + * which may be used in content based search also. The value can + * be anything when the entry pointed by search index will not be + * used for content based search. + * + * Return: void + */ +static inline void hal_tx_desc_set_cache_set_num(hal_soc_handle_t hal_soc_hdl, + void *desc, + uint8_t cache_num) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + hal_soc->ops->hal_tx_desc_set_cache_set_num(desc, cache_num); +} + /** * hal_tx_comp_get_status() - TQM Release reason * @hal_desc: completion ring Tx status @@ -991,11 +1038,12 @@ static inline void hal_tx_desc_set_search_index(struct hal_soc *hal_soc, * * Return: none */ -static inline void hal_tx_comp_get_status(void *desc, void *ts, void *hal) +static inline void hal_tx_comp_get_status(void *desc, void *ts, + hal_soc_handle_t hal_soc_hdl) { - struct hal_soc *hal_soc = hal; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - hal_soc->ops->hal_tx_comp_get_status(desc, ts, hal); + hal_soc->ops->hal_tx_comp_get_status(desc, ts, hal_soc); } @@ -1010,10 +1058,12 @@ static inline void hal_tx_comp_get_status(void *desc, void *ts, void *hal) * * Return: void */ -static inline void hal_tx_desc_set_buf_addr(void *desc, dma_addr_t paddr, - uint8_t pool_id, uint32_t desc_id, uint8_t type, void *hal) +static inline +void hal_tx_desc_set_buf_addr(void *desc, dma_addr_t paddr, + uint8_t pool_id, uint32_t desc_id, + uint8_t type, hal_soc_handle_t hal_soc_hdl) { - struct hal_soc *hal_soc = hal; + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; hal_soc->ops->hal_tx_desc_set_buf_addr(desc, paddr, pool_id, desc_id, type); @@ -1028,9 +1078,11 @@ static inline void hal_tx_desc_set_buf_addr(void *desc, dma_addr_t paddr, * * Return: void */ -static inline void hal_tx_set_pcp_tid_map_default(struct hal_soc *hal_soc, +static inline void hal_tx_set_pcp_tid_map_default(hal_soc_handle_t hal_soc_hdl, uint8_t *map) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + hal_soc->ops->hal_tx_set_pcp_tid_map(hal_soc, map); } @@ -1043,9 +1095,11 @@ static inline void hal_tx_set_pcp_tid_map_default(struct hal_soc *hal_soc, * * Return: void */ -static inline void hal_tx_update_pcp_tid_map(struct hal_soc *hal_soc, +static inline void hal_tx_update_pcp_tid_map(hal_soc_handle_t hal_soc_hdl, uint8_t pcp, uint8_t tid) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + hal_soc->ops->hal_tx_update_pcp_tid_map(hal_soc, tid, tid); } @@ -1057,8 +1111,11 @@ static inline void hal_tx_update_pcp_tid_map(struct hal_soc *hal_soc, * * Return: void */ -static inline void hal_tx_set_tidmap_prty(struct hal_soc *hal_soc, uint8_t val) +static inline +void hal_tx_set_tidmap_prty(hal_soc_handle_t hal_soc_hdl, uint8_t val) { + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + hal_soc->ops->hal_tx_set_tidmap_prty(hal_soc, val); } @@ -1070,13 +1127,12 @@ static inline void hal_tx_set_tidmap_prty(struct hal_soc *hal_soc, uint8_t val) * * Return: buffer type */ -static inline uint8_t hal_get_wbm_internal_error(void *hal_desc) +static inline +uint8_t hal_get_wbm_internal_error(hal_soc_handle_t hal_soc_hdl, void *hal_desc) { - uint32_t comp_desc = - *(uint32_t *)(((uint8_t *)hal_desc) + - WBM_RELEASE_RING_2_WBM_INTERNAL_ERROR_OFFSET); + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; - return (comp_desc & WBM_RELEASE_RING_2_WBM_INTERNAL_ERROR_MASK) >> - WBM_RELEASE_RING_2_WBM_INTERNAL_ERROR_LSB; + return hal_soc->ops->hal_get_wbm_internal_error(hal_desc); } + #endif /* HAL_TX_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_wbm.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_wbm.h index b31497cb47e7fc27b7f2bcf60f84add8a4781850..f78d1ac862df57618f199f2f49dffce6a6f9c09c 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_wbm.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/hal_wbm.h @@ -29,15 +29,17 @@ * @num_entries: Total entries of all scatter bufs * */ -static void hal_setup_link_idle_list_generic(void *hal_soc, - qdf_dma_addr_t scatter_bufs_base_paddr[], - void *scatter_bufs_base_vaddr[], uint32_t num_scatter_bufs, - uint32_t scatter_buf_size, uint32_t last_buf_end_offset, - uint32_t num_entries) +static void +hal_setup_link_idle_list_generic(struct hal_soc *soc, + qdf_dma_addr_t scatter_bufs_base_paddr[], + void *scatter_bufs_base_vaddr[], + uint32_t num_scatter_bufs, + uint32_t scatter_buf_size, + uint32_t last_buf_end_offset, + uint32_t num_entries) { int i; uint32_t *prev_buf_link_ptr = NULL; - struct hal_soc *soc = (struct hal_soc *)hal_soc; uint32_t reg_scatter_buf_size, reg_tot_scatter_buf_size; uint32_t val; diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6018/hal_6018.c b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6018/hal_6018.c deleted file mode 100644 index e4fd12348637ab2fb43473fde371e0b41131284a..0000000000000000000000000000000000000000 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6018/hal_6018.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Copyright (c) 2016-2019 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 - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -#include "hal_hw_headers.h" -#include "hal_internal.h" -#include "hal_api.h" -#include "target_type.h" -#include "wcss_version.h" -#include "qdf_module.h" - -#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_OFFSET \ - RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_OFFSET -#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_MASK \ - RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_MASK -#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_LSB \ - RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_LSB -#define UNIFIED_PHYRX_HT_SIG_0_HT_SIG_INFO_PHYRX_HT_SIG_INFO_DETAILS_OFFSET \ - PHYRX_HT_SIG_0_PHYRX_HT_SIG_INFO_DETAILS_MCS_OFFSET -#define UNIFIED_PHYRX_L_SIG_B_0_L_SIG_B_INFO_PHYRX_L_SIG_B_INFO_DETAILS_OFFSET \ - PHYRX_L_SIG_B_0_PHYRX_L_SIG_B_INFO_DETAILS_RATE_OFFSET -#define UNIFIED_PHYRX_L_SIG_A_0_L_SIG_A_INFO_PHYRX_L_SIG_A_INFO_DETAILS_OFFSET \ - PHYRX_L_SIG_A_0_PHYRX_L_SIG_A_INFO_DETAILS_RATE_OFFSET -#define UNIFIED_PHYRX_VHT_SIG_A_0_VHT_SIG_A_INFO_PHYRX_VHT_SIG_A_INFO_DETAILS_OFFSET \ - PHYRX_VHT_SIG_A_0_PHYRX_VHT_SIG_A_INFO_DETAILS_BANDWIDTH_OFFSET -#define UNIFIED_PHYRX_HE_SIG_A_SU_0_HE_SIG_A_SU_INFO_PHYRX_HE_SIG_A_SU_INFO_DETAILS_OFFSET \ - PHYRX_HE_SIG_A_SU_0_PHYRX_HE_SIG_A_SU_INFO_DETAILS_FORMAT_INDICATION_OFFSET -#define UNIFIED_PHYRX_HE_SIG_A_MU_DL_0_HE_SIG_A_MU_DL_INFO_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS_OFFSET \ - PHYRX_HE_SIG_A_MU_DL_0_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS_DL_UL_FLAG_OFFSET -#define UNIFIED_PHYRX_HE_SIG_B1_MU_0_HE_SIG_B1_MU_INFO_PHYRX_HE_SIG_B1_MU_INFO_DETAILS_OFFSET \ - PHYRX_HE_SIG_B1_MU_0_PHYRX_HE_SIG_B1_MU_INFO_DETAILS_RU_ALLOCATION_OFFSET -#define UNIFIED_PHYRX_HE_SIG_B2_MU_0_HE_SIG_B2_MU_INFO_PHYRX_HE_SIG_B2_MU_INFO_DETAILS_OFFSET \ - PHYRX_HE_SIG_B2_MU_0_PHYRX_HE_SIG_B2_MU_INFO_DETAILS_STA_ID_OFFSET -#define UNIFIED_PHYRX_HE_SIG_B2_OFDMA_0_HE_SIG_B2_OFDMA_INFO_PHYRX_HE_SIG_B2_OFDMA_INFO_DETAILS_OFFSET \ - PHYRX_HE_SIG_B2_OFDMA_0_PHYRX_HE_SIG_B2_OFDMA_INFO_DETAILS_STA_ID_OFFSET -#define UNIFIED_PHYRX_RSSI_LEGACY_3_RECEIVE_RSSI_INFO_PRE_RSSI_INFO_DETAILS_OFFSET \ - PHYRX_RSSI_LEGACY_3_PRE_RSSI_INFO_DETAILS_RSSI_PRI20_CHAIN0_OFFSET -#define UNIFIED_PHYRX_RSSI_LEGACY_19_RECEIVE_RSSI_INFO_PREAMBLE_RSSI_INFO_DETAILS_OFFSET \ - PHYRX_RSSI_LEGACY_19_PREAMBLE_RSSI_INFO_DETAILS_RSSI_PRI20_CHAIN0_OFFSET -#define UNIFIED_RX_MPDU_START_0_RX_MPDU_INFO_RX_MPDU_INFO_DETAILS_OFFSET \ - RX_MPDU_START_0_RX_MPDU_INFO_DETAILS_RXPCU_MPDU_FILTER_IN_CATEGORY_OFFSET -#define UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET \ - RX_MSDU_LINK_8_MSDU_0_BUFFER_ADDR_INFO_DETAILS_BUFFER_ADDR_31_0_OFFSET -#define UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET \ - RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_DETAILS_FIRST_MSDU_IN_MPDU_FLAG_OFFSET -#define UNIFIED_RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET \ - RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_DETAILS_MSDU_COUNT_OFFSET -#define UNIFIED_REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET \ - REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_DETAILS_MSDU_COUNT_OFFSET -#define UNIFORM_REO_STATUS_HEADER_STATUS_HEADER \ - STATUS_HEADER_REO_STATUS_NUMBER -#define UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC \ - STATUS_HEADER_TIMESTAMP -#define UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET \ - RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_DETAILS_FIRST_MSDU_IN_MPDU_FLAG_OFFSET -#define UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET \ - RX_MSDU_LINK_8_MSDU_0_BUFFER_ADDR_INFO_DETAILS_BUFFER_ADDR_31_0_OFFSET -#define UNIFIED_TCL_DATA_CMD_0_BUFFER_ADDR_INFO_BUF_ADDR_INFO_OFFSET \ - TCL_DATA_CMD_0_BUF_ADDR_INFO_BUFFER_ADDR_31_0_OFFSET -#define UNIFIED_TCL_DATA_CMD_1_BUFFER_ADDR_INFO_BUF_ADDR_INFO_OFFSET \ - TCL_DATA_CMD_1_BUF_ADDR_INFO_BUFFER_ADDR_39_32_OFFSET -#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_OFFSET \ - TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_OFFSET -#define UNIFIED_BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_LSB \ - BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_LSB -#define UNIFIED_BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_MASK \ - BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_MASK -#define UNIFIED_BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_LSB \ - BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_LSB -#define UNIFIED_BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_MASK \ - BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_MASK -#define UNIFIED_BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_LSB \ - BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_LSB -#define UNIFIED_BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_MASK \ - BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_MASK -#define UNIFIED_BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_LSB \ - BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_LSB -#define UNIFIED_BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_MASK \ - BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_MASK -#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_LSB \ - TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_LSB -#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_MASK \ - TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_MASK -#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_MASK \ - WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_MASK -#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_OFFSET \ - WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_OFFSET -#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_LSB \ - WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_LSB -#include "hal_6018_tx.h" -#include "hal_6018_rx.h" -#include -#include - -struct hal_hw_txrx_ops qca6018_hal_hw_txrx_ops = { - /* init and setup */ - hal_srng_dst_hw_init_generic, - hal_srng_src_hw_init_generic, - hal_get_hw_hptp_generic, - hal_reo_setup_generic, - hal_setup_link_idle_list_generic, - NULL, - - /* tx */ - hal_tx_desc_set_dscp_tid_table_id_6018, - hal_tx_set_dscp_tid_map_6018, - hal_tx_update_dscp_tid_6018, - hal_tx_desc_set_lmac_id_6018, - hal_tx_desc_set_buf_addr_generic, - hal_tx_desc_set_search_type_generic, - hal_tx_desc_set_search_index_generic, - hal_tx_comp_get_status_generic, - hal_tx_comp_get_release_reason_generic, - - /* rx */ - hal_rx_msdu_start_nss_get_6018, - hal_rx_mon_hw_desc_get_mpdu_status_6018, - hal_rx_get_tlv_6018, - hal_rx_proc_phyrx_other_receive_info_tlv_6018, - hal_rx_dump_msdu_start_tlv_6018, - hal_rx_dump_msdu_end_tlv_6018, - hal_get_link_desc_size_6018, - hal_rx_mpdu_start_tid_get_6018, - hal_rx_msdu_start_reception_type_get_6018, - hal_rx_msdu_end_da_idx_get_6018, - hal_rx_msdu_desc_info_get_ptr_generic, - hal_rx_link_desc_msdu0_ptr_generic, - hal_reo_status_get_header_generic, - hal_rx_status_get_tlv_info_generic, - hal_rx_wbm_err_info_get_generic, - hal_rx_dump_mpdu_start_tlv_generic, - - hal_tx_set_pcp_tid_map_generic, - hal_tx_update_pcp_tid_generic, - hal_tx_update_tidmap_prty_generic, -}; - -struct hal_hw_srng_config hw_srng_table_6018[] = { - /* TODO: max_rings can populated by querying HW capabilities */ - { /* REO_DST */ - .start_ring_id = HAL_SRNG_REO2SW1, - .max_rings = 4, - .entry_size = sizeof(struct reo_destination_ring) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_DST_RING, - .reg_start = { - HWIO_REO_R0_REO2SW1_RING_BASE_LSB_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET), - HWIO_REO_R2_REO2SW1_RING_HP_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET) - }, - .reg_size = { - HWIO_REO_R0_REO2SW2_RING_BASE_LSB_ADDR(0) - - HWIO_REO_R0_REO2SW1_RING_BASE_LSB_ADDR(0), - HWIO_REO_R2_REO2SW2_RING_HP_ADDR(0) - - HWIO_REO_R2_REO2SW1_RING_HP_ADDR(0), - }, - .max_size = - HWIO_REO_R0_REO2SW1_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_REO_R0_REO2SW1_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* REO_EXCEPTION */ - /* Designating REO2TCL ring as exception ring. This ring is - * similar to other REO2SW rings though it is named as REO2TCL. - * Any of theREO2SW rings can be used as exception ring. - */ - .start_ring_id = HAL_SRNG_REO2TCL, - .max_rings = 1, - .entry_size = sizeof(struct reo_destination_ring) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_DST_RING, - .reg_start = { - HWIO_REO_R0_REO2TCL_RING_BASE_LSB_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET), - HWIO_REO_R2_REO2TCL_RING_HP_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET) - }, - /* Single ring - provide ring size if multiple rings of this - * type are supported - */ - .reg_size = {}, - .max_size = - HWIO_REO_R0_REO2TCL_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_REO_R0_REO2TCL_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* REO_REINJECT */ - .start_ring_id = HAL_SRNG_SW2REO, - .max_rings = 1, - .entry_size = sizeof(struct reo_entrance_ring) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_SRC_RING, - .reg_start = { - HWIO_REO_R0_SW2REO_RING_BASE_LSB_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET), - HWIO_REO_R2_SW2REO_RING_HP_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET) - }, - /* Single ring - provide ring size if multiple rings of this - * type are supported - */ - .reg_size = {}, - .max_size = HWIO_REO_R0_SW2REO_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_REO_R0_SW2REO_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* REO_CMD */ - .start_ring_id = HAL_SRNG_REO_CMD, - .max_rings = 1, - .entry_size = (sizeof(struct tlv_32_hdr) + - sizeof(struct reo_get_queue_stats)) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_SRC_RING, - .reg_start = { - HWIO_REO_R0_REO_CMD_RING_BASE_LSB_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET), - HWIO_REO_R2_REO_CMD_RING_HP_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET), - }, - /* Single ring - provide ring size if multiple rings of this - * type are supported - */ - .reg_size = {}, - .max_size = HWIO_REO_R0_REO_CMD_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_REO_R0_REO_CMD_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* REO_STATUS */ - .start_ring_id = HAL_SRNG_REO_STATUS, - .max_rings = 1, - .entry_size = (sizeof(struct tlv_32_hdr) + - sizeof(struct reo_get_queue_stats_status)) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_DST_RING, - .reg_start = { - HWIO_REO_R0_REO_STATUS_RING_BASE_LSB_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET), - HWIO_REO_R2_REO_STATUS_RING_HP_ADDR( - SEQ_WCSS_UMAC_REO_REG_OFFSET), - }, - /* Single ring - provide ring size if multiple rings of this - * type are supported - */ - .reg_size = {}, - .max_size = - HWIO_REO_R0_REO_STATUS_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_REO_R0_REO_STATUS_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* TCL_DATA */ - .start_ring_id = HAL_SRNG_SW2TCL1, - .max_rings = 3, - .entry_size = (sizeof(struct tlv_32_hdr) + - sizeof(struct tcl_data_cmd)) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_SRC_RING, - .reg_start = { - HWIO_TCL_R0_SW2TCL1_RING_BASE_LSB_ADDR( - SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), - HWIO_TCL_R2_SW2TCL1_RING_HP_ADDR( - SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), - }, - .reg_size = { - HWIO_TCL_R0_SW2TCL2_RING_BASE_LSB_ADDR(0) - - HWIO_TCL_R0_SW2TCL1_RING_BASE_LSB_ADDR(0), - HWIO_TCL_R2_SW2TCL2_RING_HP_ADDR(0) - - HWIO_TCL_R2_SW2TCL1_RING_HP_ADDR(0), - }, - .max_size = - HWIO_TCL_R0_SW2TCL1_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_TCL_R0_SW2TCL1_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* TCL_CMD */ - .start_ring_id = HAL_SRNG_SW2TCL_CMD, - .max_rings = 1, - .entry_size = (sizeof(struct tlv_32_hdr) + - sizeof(struct tcl_gse_cmd)) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_SRC_RING, - .reg_start = { - HWIO_TCL_R0_SW2TCL_CMD_RING_BASE_LSB_ADDR( - SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), - HWIO_TCL_R2_SW2TCL_CMD_RING_HP_ADDR( - SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), - }, - /* Single ring - provide ring size if multiple rings of this - * type are supported - */ - .reg_size = {}, - .max_size = - HWIO_TCL_R0_SW2TCL_CMD_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_TCL_R0_SW2TCL_CMD_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* TCL_STATUS */ - .start_ring_id = HAL_SRNG_TCL_STATUS, - .max_rings = 1, - .entry_size = (sizeof(struct tlv_32_hdr) + - sizeof(struct tcl_status_ring)) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_DST_RING, - .reg_start = { - HWIO_TCL_R0_TCL_STATUS1_RING_BASE_LSB_ADDR( - SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), - HWIO_TCL_R2_TCL_STATUS1_RING_HP_ADDR( - SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), - }, - /* Single ring - provide ring size if multiple rings of this - * type are supported - */ - .reg_size = {}, - .max_size = - HWIO_TCL_R0_TCL_STATUS1_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_TCL_R0_TCL_STATUS1_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* CE_SRC */ - .start_ring_id = HAL_SRNG_CE_0_SRC, - .max_rings = 12, - .entry_size = sizeof(struct ce_src_desc) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_SRC_RING, - .reg_start = { - HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR( - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET), - HWIO_WFSS_CE_CHANNEL_DST_R2_DEST_RING_HP_ADDR( - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET), - }, - .reg_size = { - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_SRC_REG_OFFSET - - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET, - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_SRC_REG_OFFSET - - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET, - }, - .max_size = - HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* CE_DST */ - .start_ring_id = HAL_SRNG_CE_0_DST, - .max_rings = 12, - .entry_size = 8 >> 2, - /*TODO: entry_size above should actually be - * sizeof(struct ce_dst_desc) >> 2, but couldn't find definition - * of struct ce_dst_desc in HW header files - */ - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_SRC_RING, - .reg_start = { - HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR( - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), - HWIO_WFSS_CE_CHANNEL_DST_R2_DEST_RING_HP_ADDR( - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), - }, - .reg_size = { - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, - }, - .max_size = - HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* CE_DST_STATUS */ - .start_ring_id = HAL_SRNG_CE_0_DST_STATUS, - .max_rings = 12, - .entry_size = sizeof(struct ce_stat_desc) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_DST_RING, - .reg_start = { - HWIO_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_LSB_ADDR( - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), - HWIO_WFSS_CE_CHANNEL_DST_R2_STATUS_RING_HP_ADDR( - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), - }, - /* TODO: check destination status ring registers */ - .reg_size = { - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - - SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, - }, - .max_size = - HWIO_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* WBM_IDLE_LINK */ - .start_ring_id = HAL_SRNG_WBM_IDLE_LINK, - .max_rings = 1, - .entry_size = sizeof(struct wbm_link_descriptor_ring) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_SRC_RING, - .reg_start = { - HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), - HWIO_WBM_R2_WBM_IDLE_LINK_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), - }, - /* Single ring - provide ring size if multiple rings of this - * type are supported - */ - .reg_size = {}, - .max_size = - HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* SW2WBM_RELEASE */ - .start_ring_id = HAL_SRNG_WBM_SW_RELEASE, - .max_rings = 1, - .entry_size = sizeof(struct wbm_release_ring) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_SRC_RING, - .reg_start = { - HWIO_WBM_R0_SW_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), - HWIO_WBM_R2_SW_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), - }, - /* Single ring - provide ring size if multiple rings of this - * type are supported - */ - .reg_size = {}, - .max_size = - HWIO_WBM_R0_SW_RELEASE_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_WBM_R0_SW_RELEASE_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* WBM2SW_RELEASE */ - .start_ring_id = HAL_SRNG_WBM2SW0_RELEASE, - .max_rings = 4, - .entry_size = sizeof(struct wbm_release_ring) >> 2, - .lmac_ring = FALSE, - .ring_dir = HAL_SRNG_DST_RING, - .reg_start = { - HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), - HWIO_WBM_R2_WBM2SW0_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), - }, - .reg_size = { - HWIO_WBM_R0_WBM2SW1_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET) - - HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), - HWIO_WBM_R2_WBM2SW1_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET) - - HWIO_WBM_R2_WBM2SW0_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), - }, - .max_size = - HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_MSB_RING_SIZE_BMSK >> - HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_MSB_RING_SIZE_SHFT, - }, - { /* RXDMA_BUF */ - .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA0_BUF0, -#ifdef IPA_OFFLOAD - .max_rings = 3, -#else - .max_rings = 2, -#endif - .entry_size = sizeof(struct wbm_buffer_ring) >> 2, - .lmac_ring = TRUE, - .ring_dir = HAL_SRNG_SRC_RING, - /* reg_start is not set because LMAC rings are not accessed - * from host - */ - .reg_start = {}, - .reg_size = {}, - .max_size = HAL_RXDMA_MAX_RING_SIZE, - }, - { /* RXDMA_DST */ - .start_ring_id = HAL_SRNG_WMAC1_RXDMA2SW0, - .max_rings = 1, - .entry_size = sizeof(struct reo_entrance_ring) >> 2, - .lmac_ring = TRUE, - .ring_dir = HAL_SRNG_DST_RING, - /* reg_start is not set because LMAC rings are not accessed - * from host - */ - .reg_start = {}, - .reg_size = {}, - .max_size = HAL_RXDMA_MAX_RING_SIZE, - }, - { /* RXDMA_MONITOR_BUF */ - .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA2_BUF, - .max_rings = 1, - .entry_size = sizeof(struct wbm_buffer_ring) >> 2, - .lmac_ring = TRUE, - .ring_dir = HAL_SRNG_SRC_RING, - /* reg_start is not set because LMAC rings are not accessed - * from host - */ - .reg_start = {}, - .reg_size = {}, - .max_size = HAL_RXDMA_MAX_RING_SIZE, - }, - { /* RXDMA_MONITOR_STATUS */ - .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA1_STATBUF, - .max_rings = 1, - .entry_size = sizeof(struct wbm_buffer_ring) >> 2, - .lmac_ring = TRUE, - .ring_dir = HAL_SRNG_SRC_RING, - /* reg_start is not set because LMAC rings are not accessed - * from host - */ - .reg_start = {}, - .reg_size = {}, - .max_size = HAL_RXDMA_MAX_RING_SIZE, - }, - { /* RXDMA_MONITOR_DST */ - .start_ring_id = HAL_SRNG_WMAC1_RXDMA2SW1, - .max_rings = 1, - .entry_size = sizeof(struct reo_entrance_ring) >> 2, - .lmac_ring = TRUE, - .ring_dir = HAL_SRNG_DST_RING, - /* reg_start is not set because LMAC rings are not accessed - * from host - */ - .reg_start = {}, - .reg_size = {}, - .max_size = HAL_RXDMA_MAX_RING_SIZE, - }, - { /* RXDMA_MONITOR_DESC */ - .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA1_DESC, - .max_rings = 1, - .entry_size = sizeof(struct wbm_buffer_ring) >> 2, - .lmac_ring = TRUE, - .ring_dir = HAL_SRNG_SRC_RING, - /* reg_start is not set because LMAC rings are not accessed - * from host - */ - .reg_start = {}, - .reg_size = {}, - .max_size = HAL_RXDMA_MAX_RING_SIZE, - }, - { /* DIR_BUF_RX_DMA_SRC */ - .start_ring_id = HAL_SRNG_DIR_BUF_RX_SRC_DMA_RING, - .max_rings = 1, - .entry_size = 2, - .lmac_ring = TRUE, - .ring_dir = HAL_SRNG_SRC_RING, - /* reg_start is not set because LMAC rings are not accessed - * from host - */ - .reg_start = {}, - .reg_size = {}, - .max_size = HAL_RXDMA_MAX_RING_SIZE, - }, -#ifdef WLAN_FEATURE_CIF_CFR - { /* WIFI_POS_SRC */ - .start_ring_id = HAL_SRNG_WIFI_POS_SRC_DMA_RING, - .max_rings = 1, - .entry_size = sizeof(wmi_oem_dma_buf_release_entry) >> 2, - .lmac_ring = TRUE, - .ring_dir = HAL_SRNG_SRC_RING, - /* reg_start is not set because LMAC rings are not accessed - * from host - */ - .reg_start = {}, - .reg_size = {}, - .max_size = HAL_RXDMA_MAX_RING_SIZE, - }, -#endif -}; - -int32_t hal_hw_reg_offset_qca6018[] = { - /* dst */ - REG_OFFSET(DST, HP), - REG_OFFSET(DST, TP), - REG_OFFSET(DST, ID), - REG_OFFSET(DST, MISC), - REG_OFFSET(DST, HP_ADDR_LSB), - REG_OFFSET(DST, HP_ADDR_MSB), - REG_OFFSET(DST, MSI1_BASE_LSB), - REG_OFFSET(DST, MSI1_BASE_MSB), - REG_OFFSET(DST, MSI1_DATA), - REG_OFFSET(DST, BASE_LSB), - REG_OFFSET(DST, BASE_MSB), - REG_OFFSET(DST, PRODUCER_INT_SETUP), - /* src */ - REG_OFFSET(SRC, HP), - REG_OFFSET(SRC, TP), - REG_OFFSET(SRC, ID), - REG_OFFSET(SRC, MISC), - REG_OFFSET(SRC, TP_ADDR_LSB), - REG_OFFSET(SRC, TP_ADDR_MSB), - REG_OFFSET(SRC, MSI1_BASE_LSB), - REG_OFFSET(SRC, MSI1_BASE_MSB), - REG_OFFSET(SRC, MSI1_DATA), - REG_OFFSET(SRC, BASE_LSB), - REG_OFFSET(SRC, BASE_MSB), - REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX0), - REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX1), -}; - -/** - * hal_qca6018_attach() - Attach 6018 target specific hal_soc ops, - * offset and srng table - */ -void hal_qca6018_attach(struct hal_soc *hal_soc) -{ - hal_soc->hw_srng_table = hw_srng_table_6018; - hal_soc->hal_hw_reg_offset = hal_hw_reg_offset_qca6018; - hal_soc->ops = &qca6018_hal_hw_txrx_ops; -} diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6018/hal_6018_rx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6018/hal_6018_rx.h deleted file mode 100644 index 30d827ebfffb8c16c7a6e18bda03f5079cc80eae..0000000000000000000000000000000000000000 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6018/hal_6018_rx.h +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright (c) 2016-2018 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 - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -#include "hal_hw_headers.h" -#include "hal_internal.h" -#include "cdp_txrx_mon_struct.h" -#include "qdf_trace.h" -#include "hal_rx.h" -#include "hal_tx.h" -#include "dp_types.h" -#include "hal_api_mon.h" - -#define HAL_RX_MSDU_START_MIMO_SS_BITMAP(_rx_msdu_start)\ - (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\ - RX_MSDU_START_5_MIMO_SS_BITMAP_OFFSET)), \ - RX_MSDU_START_5_MIMO_SS_BITMAP_MASK, \ - RX_MSDU_START_5_MIMO_SS_BITMAP_LSB)) -/* - * hal_rx_msdu_start_nss_get_6018(): API to get the NSS - * Interval from rx_msdu_start - * - * @buf: pointer to the start of RX PKT TLV header - * Return: uint32_t(nss) - */ -static uint32_t hal_rx_msdu_start_nss_get_6018(uint8_t *buf) -{ - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_start *msdu_start = - &pkt_tlvs->msdu_start_tlv.rx_msdu_start; - uint8_t mimo_ss_bitmap; - - mimo_ss_bitmap = HAL_RX_MSDU_START_MIMO_SS_BITMAP(msdu_start); - - return qdf_get_hweight8(mimo_ss_bitmap); -} - -/** - * hal_rx_mon_hw_desc_get_mpdu_status_6018(): Retrieve MPDU status - * - * @ hw_desc_addr: Start address of Rx HW TLVs - * @ rs: Status for monitor mode - * - * Return: void - */ -static void hal_rx_mon_hw_desc_get_mpdu_status_6018(void *hw_desc_addr, - struct mon_rx_status *rs) -{ - struct rx_msdu_start *rx_msdu_start; - struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; - uint32_t reg_value; - const uint32_t sgi_hw_to_cdp[] = { - CDP_SGI_0_8_US, - CDP_SGI_0_4_US, - CDP_SGI_1_6_US, - CDP_SGI_3_2_US, - }; - - rx_msdu_start = &rx_desc->msdu_start_tlv.rx_msdu_start; - - HAL_RX_GET_MSDU_AGGREGATION(rx_desc, rs); - - rs->ant_signal_db = HAL_RX_GET(rx_msdu_start, - RX_MSDU_START_5, USER_RSSI); - rs->is_stbc = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, STBC); - - reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, SGI); - rs->sgi = sgi_hw_to_cdp[reg_value]; - reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, PKT_TYPE); - switch (reg_value) { - case HAL_RX_PKT_TYPE_11N: - rs->ht_flags = 1; - break; - case HAL_RX_PKT_TYPE_11AC: - rs->vht_flags = 1; - reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, - RECEIVE_BANDWIDTH); - rs->vht_flag_values2 = reg_value; - break; - case HAL_RX_PKT_TYPE_11AX: - rs->he_flags = 1; - break; - default: - break; - } - reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEPTION_TYPE); - rs->beamformed = (reg_value == HAL_RX_RECEPTION_TYPE_MU_MIMO) ? 1 : 0; - /* TODO: rs->beamformed should be set for SU beamforming also */ -} - -#define LINK_DESC_SIZE (NUM_OF_DWORDS_RX_MSDU_LINK << 2) -static uint32_t hal_get_link_desc_size_6018(void) -{ - return LINK_DESC_SIZE; -} - -/* - * hal_rx_get_tlv_6018(): API to get the tlv - * - * @rx_tlv: TLV data extracted from the rx packet - * Return: uint8_t - */ -static uint8_t hal_rx_get_tlv_6018(void *rx_tlv) -{ - return HAL_RX_GET(rx_tlv, PHYRX_RSSI_LEGACY_0, RECEIVE_BANDWIDTH); -} - -/** - * hal_rx_proc_phyrx_other_receive_info_tlv_6018() - * -process other receive info TLV - * @rx_tlv_hdr: pointer to TLV header - * @ppdu_info: pointer to ppdu_info - * - * Return: None - */ -static -void hal_rx_proc_phyrx_other_receive_info_tlv_6018(void *rx_tlv_hdr, - void *ppdu_info) -{ -} - - -/** - * hal_rx_dump_msdu_start_tlv_6018() : dump RX msdu_start TLV in structured - * human readable format. - * @ msdu_start: pointer the msdu_start TLV in pkt. - * @ dbg_level: log level. - * - * Return: void - */ -static void hal_rx_dump_msdu_start_tlv_6018(void *msdustart, - uint8_t dbg_level) -{ - struct rx_msdu_start *msdu_start = (struct rx_msdu_start *)msdustart; - - QDF_TRACE(QDF_MODULE_ID_DP, dbg_level, - "rx_msdu_start tlv - " - "rxpcu_mpdu_filter_in_category: %d " - "sw_frame_group_id: %d " - "phy_ppdu_id: %d " - "msdu_length: %d " - "ipsec_esp: %d " - "l3_offset: %d " - "ipsec_ah: %d " - "l4_offset: %d " - "msdu_number: %d " - "decap_format: %d " - "ipv4_proto: %d " - "ipv6_proto: %d " - "tcp_proto: %d " - "udp_proto: %d " - "ip_frag: %d " - "tcp_only_ack: %d " - "da_is_bcast_mcast: %d " - "ip4_protocol_ip6_next_header: %d " - "toeplitz_hash_2_or_4: %d " - "flow_id_toeplitz: %d " - "user_rssi: %d " - "pkt_type: %d " - "stbc: %d " - "sgi: %d " - "rate_mcs: %d " - "receive_bandwidth: %d " - "reception_type: %d " - "ppdu_start_timestamp: %d " - "sw_phy_meta_data: %d ", - msdu_start->rxpcu_mpdu_filter_in_category, - msdu_start->sw_frame_group_id, - msdu_start->phy_ppdu_id, - msdu_start->msdu_length, - msdu_start->ipsec_esp, - msdu_start->l3_offset, - msdu_start->ipsec_ah, - msdu_start->l4_offset, - msdu_start->msdu_number, - msdu_start->decap_format, - msdu_start->ipv4_proto, - msdu_start->ipv6_proto, - msdu_start->tcp_proto, - msdu_start->udp_proto, - msdu_start->ip_frag, - msdu_start->tcp_only_ack, - msdu_start->da_is_bcast_mcast, - msdu_start->ip4_protocol_ip6_next_header, - msdu_start->toeplitz_hash_2_or_4, - msdu_start->flow_id_toeplitz, - msdu_start->user_rssi, - msdu_start->pkt_type, - msdu_start->stbc, - msdu_start->sgi, - msdu_start->rate_mcs, - msdu_start->receive_bandwidth, - msdu_start->reception_type, - msdu_start->ppdu_start_timestamp, - msdu_start->sw_phy_meta_data); -} - -/** - * hal_rx_dump_msdu_end_tlv_6018: dump RX msdu_end TLV in structured - * human readable format. - * @ msdu_end: pointer the msdu_end TLV in pkt. - * @ dbg_level: log level. - * - * Return: void - */ -static void hal_rx_dump_msdu_end_tlv_6018(void *msduend, - uint8_t dbg_level) -{ - struct rx_msdu_end *msdu_end = (struct rx_msdu_end *)msduend; - - QDF_TRACE(QDF_MODULE_ID_DP, dbg_level, - "rx_msdu_end tlv - " - "rxpcu_mpdu_filter_in_category: %d " - "sw_frame_group_id: %d " - "phy_ppdu_id: %d " - "ip_hdr_chksum: %d " - "tcp_udp_chksum: %d " - "key_id_octet: %d " - "cce_super_rule: %d " - "cce_classify_not_done_truncat: %d " - "cce_classify_not_done_cce_dis: %d " - "ext_wapi_pn_63_48: %d " - "ext_wapi_pn_95_64: %d " - "ext_wapi_pn_127_96: %d " - "reported_mpdu_length: %d " - "first_msdu: %d " - "last_msdu: %d " - "sa_idx_timeout: %d " - "da_idx_timeout: %d " - "msdu_limit_error: %d " - "flow_idx_timeout: %d " - "flow_idx_invalid: %d " - "wifi_parser_error: %d " - "amsdu_parser_error: %d " - "sa_is_valid: %d " - "da_is_valid: %d " - "da_is_mcbc: %d " - "l3_header_padding: %d " - "ipv6_options_crc: %d " - "tcp_seq_number: %d " - "tcp_ack_number: %d " - "tcp_flag: %d " - "lro_eligible: %d " - "window_size: %d " - "da_offset: %d " - "sa_offset: %d " - "da_offset_valid: %d " - "sa_offset_valid: %d " - "rule_indication_31_0: %d " - "rule_indication_63_32: %d " - "sa_idx: %d " - "msdu_drop: %d " - "reo_destination_indication: %d " - "flow_idx: %d " - "fse_metadata: %d " - "cce_metadata: %d " - "sa_sw_peer_id: %d ", - msdu_end->rxpcu_mpdu_filter_in_category, - msdu_end->sw_frame_group_id, - msdu_end->phy_ppdu_id, - msdu_end->ip_hdr_chksum, - msdu_end->tcp_udp_chksum, - msdu_end->key_id_octet, - msdu_end->cce_super_rule, - msdu_end->cce_classify_not_done_truncate, - msdu_end->cce_classify_not_done_cce_dis, - msdu_end->ext_wapi_pn_63_48, - msdu_end->ext_wapi_pn_95_64, - msdu_end->ext_wapi_pn_127_96, - msdu_end->reported_mpdu_length, - msdu_end->first_msdu, - msdu_end->last_msdu, - msdu_end->sa_idx_timeout, - msdu_end->da_idx_timeout, - msdu_end->msdu_limit_error, - msdu_end->flow_idx_timeout, - msdu_end->flow_idx_invalid, - msdu_end->wifi_parser_error, - msdu_end->amsdu_parser_error, - msdu_end->sa_is_valid, - msdu_end->da_is_valid, - msdu_end->da_is_mcbc, - msdu_end->l3_header_padding, - msdu_end->ipv6_options_crc, - msdu_end->tcp_seq_number, - msdu_end->tcp_ack_number, - msdu_end->tcp_flag, - msdu_end->lro_eligible, - msdu_end->window_size, - msdu_end->da_offset, - msdu_end->sa_offset, - msdu_end->da_offset_valid, - msdu_end->sa_offset_valid, - msdu_end->rule_indication_31_0, - msdu_end->rule_indication_63_32, - msdu_end->sa_idx, - msdu_end->msdu_drop, - msdu_end->reo_destination_indication, - msdu_end->flow_idx, - msdu_end->fse_metadata, - msdu_end->cce_metadata, - msdu_end->sa_sw_peer_id); -} - -/* - * Get tid from RX_MPDU_START - */ -#define HAL_RX_MPDU_INFO_TID_GET(_rx_mpdu_info) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ - RX_MPDU_INFO_3_TID_OFFSET)), \ - RX_MPDU_INFO_3_TID_MASK, \ - RX_MPDU_INFO_3_TID_LSB)) - -static uint32_t hal_rx_mpdu_start_tid_get_6018(uint8_t *buf) -{ - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_mpdu_start *mpdu_start = - &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; - uint32_t tid; - - tid = HAL_RX_MPDU_INFO_TID_GET(&mpdu_start->rx_mpdu_info_details); - - return tid; -} - -#define HAL_RX_MSDU_START_RECEPTION_TYPE_GET(_rx_msdu_start) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start), \ - RX_MSDU_START_5_RECEPTION_TYPE_OFFSET)), \ - RX_MSDU_START_5_RECEPTION_TYPE_MASK, \ - RX_MSDU_START_5_RECEPTION_TYPE_LSB)) - -/* - * hal_rx_msdu_start_reception_type_get(): API to get the reception type - * Interval from rx_msdu_start - * - * @buf: pointer to the start of RX PKT TLV header - * Return: uint32_t(reception_type) - */ -static uint32_t hal_rx_msdu_start_reception_type_get_6018(uint8_t *buf) -{ - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_start *msdu_start = - &pkt_tlvs->msdu_start_tlv.rx_msdu_start; - uint32_t reception_type; - - reception_type = HAL_RX_MSDU_START_RECEPTION_TYPE_GET(msdu_start); - - return reception_type; -} - -/* RX_MSDU_END_13_DA_IDX_OR_SW_PEER_ID_OFFSET */ -#define HAL_RX_MSDU_END_DA_IDX_GET(_rx_msdu_end) \ - (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ - RX_MSDU_END_13_DA_IDX_OR_SW_PEER_ID_OFFSET)), \ - RX_MSDU_END_13_DA_IDX_OR_SW_PEER_ID_MASK, \ - RX_MSDU_END_13_DA_IDX_OR_SW_PEER_ID_LSB)) - /** - * hal_rx_msdu_end_da_idx_get_6018: API to get da_idx - * from rx_msdu_end TLV - * - * @ buf: pointer to the start of RX PKT TLV headers - * Return: da index - */ -static uint16_t hal_rx_msdu_end_da_idx_get_6018(uint8_t *buf) -{ - struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; - struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; - uint16_t da_idx; - - da_idx = HAL_RX_MSDU_END_DA_IDX_GET(msdu_end); - - return da_idx; -} - diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290.c b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290.c index 7612caf8045f8f7c282eda9337c3edd3ea6cf529..dc22c00a99e093bd5b9cf1a8a2dce3dd30af1356 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290.c +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -110,6 +110,886 @@ #include #include +/** + * hal_rx_get_rx_fragment_number_6290(): Function to retrieve rx fragment number + * + * @nbuf: Network buffer + * Returns: rx fragment number + */ +static +uint8_t hal_rx_get_rx_fragment_number_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + /* Return first 4 bits as fragment number */ + return (HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info) & + DOT11_SEQ_FRAG_MASK); +} + +/** + * hal_rx_msdu_end_da_is_mcbc_get: API to check if pkt is MCBC + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_mcbc + */ +static inline uint8_t +hal_rx_msdu_end_da_is_mcbc_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_DA_IS_MCBC_GET(msdu_end); +} + +/** + * hal_rx_msdu_end_sa_is_valid_get_6290(): API to get_6290 the + * sa_is_valid bit from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_is_valid bit + */ +static uint8_t +hal_rx_msdu_end_sa_is_valid_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t sa_is_valid; + + sa_is_valid = HAL_RX_MSDU_END_SA_IS_VALID_GET(msdu_end); + + return sa_is_valid; +} + +/** + * hal_rx_msdu_end_sa_idx_get_6290(): API to get_6290 the + * sa_idx from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_idx (SA AST index) + */ +static +uint16_t hal_rx_msdu_end_sa_idx_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint16_t sa_idx; + + sa_idx = HAL_RX_MSDU_END_SA_IDX_GET(msdu_end); + + return sa_idx; +} + +/** + * hal_rx_desc_is_first_msdu_6290() - Check if first msdu + * + * @hal_soc_hdl: hal_soc handle + * @hw_desc_addr: hardware descriptor address + * + * Return: 0 - success/ non-zero failure + */ +static uint32_t hal_rx_desc_is_first_msdu_6290(void *hw_desc_addr) +{ + struct rx_pkt_tlvs *rx_tlvs = (struct rx_pkt_tlvs *)hw_desc_addr; + struct rx_msdu_end *msdu_end = &rx_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_GET(msdu_end, RX_MSDU_END_5, FIRST_MSDU); +} + +/** + * hal_rx_msdu_end_l3_hdr_padding_get_6290(): API to get_6290 the + * l3_header padding from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: number of l3 header padding bytes + */ +static uint32_t hal_rx_msdu_end_l3_hdr_padding_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint32_t l3_header_padding; + + l3_header_padding = HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(msdu_end); + + return l3_header_padding; +} + +/* + * @ hal_rx_encryption_info_valid_6290: Returns encryption type. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: encryption type + */ +static uint32_t hal_rx_encryption_info_valid_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + uint32_t encryption_info = HAL_RX_MPDU_ENCRYPTION_INFO_VALID(mpdu_info); + + return encryption_info; +} + +/* + * hal_rx_print_pn_6290: Prints the PN of rx packet. + * @buf: rx_tlv_hdr of the received packet + * + * Return: void + */ +static void hal_rx_print_pn_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + uint32_t pn_31_0 = HAL_RX_MPDU_PN_31_0_GET(mpdu_info); + uint32_t pn_63_32 = HAL_RX_MPDU_PN_63_32_GET(mpdu_info); + uint32_t pn_95_64 = HAL_RX_MPDU_PN_95_64_GET(mpdu_info); + uint32_t pn_127_96 = HAL_RX_MPDU_PN_127_96_GET(mpdu_info); + + hal_debug("PN number pn_127_96 0x%x pn_95_64 0x%x pn_63_32 0x%x pn_31_0 0x%x ", + pn_127_96, pn_95_64, pn_63_32, pn_31_0); +} + +/** + * hal_rx_msdu_end_first_msdu_get_6290: API to get first msdu status + * from rx_msdu_end TLV + * + * @buf: pointer to the start of RX PKT TLV headers + * Return: first_msdu + */ +static uint8_t +hal_rx_msdu_end_first_msdu_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t first_msdu; + + first_msdu = HAL_RX_MSDU_END_FIRST_MSDU_GET(msdu_end); + + return first_msdu; +} + +/** + * hal_rx_msdu_end_da_is_valid_get_6290: API to check if da is valid + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_valid + */ +static uint8_t hal_rx_msdu_end_da_is_valid_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t da_is_valid; + + da_is_valid = HAL_RX_MSDU_END_DA_IS_VALID_GET(msdu_end); + + return da_is_valid; +} + +/** + * hal_rx_msdu_end_last_msdu_get_6290: API to get last msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: last_msdu + */ +static uint8_t hal_rx_msdu_end_last_msdu_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t last_msdu; + + last_msdu = HAL_RX_MSDU_END_LAST_MSDU_GET(msdu_end); + + return last_msdu; +} + +/* + * hal_rx_get_mpdu_mac_ad4_valid_6290(): Retrieves if mpdu 4th addr is valid + * + * @nbuf: Network buffer + * Returns: value of mpdu 4th address valid field + */ +static bool hal_rx_get_mpdu_mac_ad4_valid_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + bool ad4_valid = 0; + + ad4_valid = HAL_RX_MPDU_GET_MAC_AD4_VALID(rx_mpdu_info); + + return ad4_valid; +} + +/** + * hal_rx_mpdu_start_sw_peer_id_get_6290: Retrieve sw peer_id + * @buf: network buffer + * + * Return: sw peer_id: + */ +static uint32_t hal_rx_mpdu_start_sw_peer_id_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_SW_PEER_ID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/* + * hal_rx_mpdu_get_to_ds_6290(): API to get the tods info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(to_ds) + */ + +static uint32_t hal_rx_mpdu_get_to_ds_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_TODS(mpdu_info); +} + +/* + * hal_rx_mpdu_get_fr_ds_6290(): API to get the from ds info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(fr_ds) + */ +static uint32_t hal_rx_mpdu_get_fr_ds_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_FROMDS(mpdu_info); +} + +/* + * hal_rx_get_mpdu_frame_control_valid_6290(): Retrieves mpdu frame + * control valid + * + * @nbuf: Network buffer + * Returns: value of frame control valid field + */ +static uint8_t hal_rx_get_mpdu_frame_control_valid_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(rx_mpdu_info); +} + +/* + * hal_rx_mpdu_get_addr1_6290(): API to check get address1 of the mpdu + * + * @buf: pointer to the start of RX PKT TLV headera + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr1_6290(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr1 { + uint32_t ad1_31_0; + uint16_t ad1_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr1 *addr = (struct hal_addr1 *)mac_addr; + uint32_t mac_addr_ad1_valid; + + mac_addr_ad1_valid = HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(mpdu_info); + + if (mac_addr_ad1_valid) { + addr->ad1_31_0 = HAL_RX_MPDU_AD1_31_0_GET(mpdu_info); + addr->ad1_47_32 = HAL_RX_MPDU_AD1_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr2_6290(): API to check get address2 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr2_6290(uint8_t *buf, + uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr2 { + uint16_t ad2_15_0; + uint32_t ad2_47_16; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr2 *addr = (struct hal_addr2 *)mac_addr; + uint32_t mac_addr_ad2_valid; + + mac_addr_ad2_valid = HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(mpdu_info); + + if (mac_addr_ad2_valid) { + addr->ad2_15_0 = HAL_RX_MPDU_AD2_15_0_GET(mpdu_info); + addr->ad2_47_16 = HAL_RX_MPDU_AD2_47_16_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr3_6290(): API to get address3 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr3_6290(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr3 { + uint32_t ad3_31_0; + uint16_t ad3_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr3 *addr = (struct hal_addr3 *)mac_addr; + uint32_t mac_addr_ad3_valid; + + mac_addr_ad3_valid = HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(mpdu_info); + + if (mac_addr_ad3_valid) { + addr->ad3_31_0 = HAL_RX_MPDU_AD3_31_0_GET(mpdu_info); + addr->ad3_47_32 = HAL_RX_MPDU_AD3_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr4_6290(): API to get address4 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr4_6290(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr4 { + uint32_t ad4_31_0; + uint16_t ad4_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr4 *addr = (struct hal_addr4 *)mac_addr; + uint32_t mac_addr_ad4_valid; + + mac_addr_ad4_valid = HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(mpdu_info); + + if (mac_addr_ad4_valid) { + addr->ad4_31_0 = HAL_RX_MPDU_AD4_31_0_GET(mpdu_info); + addr->ad4_47_32 = HAL_RX_MPDU_AD4_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_get_mpdu_sequence_control_valid_6290(): Get mpdu + * sequence control valid + * + * @nbuf: Network buffer + * Returns: value of sequence control valid field + */ +static uint8_t hal_rx_get_mpdu_sequence_control_valid_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(rx_mpdu_info); +} + +/** + * hal_rx_is_unicast_6290: check packet is unicast frame or not. + * + * @ buf: pointer to rx pkt TLV. + * + * Return: true on unicast. + */ +static bool hal_rx_is_unicast_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint32_t grp_id; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + + grp_id = (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_OFFSET)), + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_MASK, + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_LSB)); + + return (HAL_MPDU_SW_FRAME_GROUP_UNICAST_DATA == grp_id) ? true : false; +} + +/** + * hal_rx_tid_get_6290: get tid based on qos control valid. + * @hal_soc_hdl: hal soc handle + * @ buf: pointer to rx pkt TLV. + * + * Return: tid + */ +static uint32_t hal_rx_tid_get_6290(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + uint8_t qos_control_valid = + (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_OFFSET)), + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_MASK, + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_LSB)); + + if (qos_control_valid) + return hal_rx_mpdu_start_tid_get_6290(buf); + + return HAL_RX_NON_QOS_TID; +} + +/** + * hal_rx_hw_desc_get_ppduid_get_6290(): retrieve ppdu id + * @hw_desc_addr: hw addr + * + * Return: ppdu id + */ +static uint32_t hal_rx_hw_desc_get_ppduid_get_6290(void *hw_desc_addr) +{ + struct rx_mpdu_info *rx_mpdu_info; + struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + + rx_mpdu_info = + &rx_desc->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + + return HAL_RX_GET(rx_mpdu_info, RX_MPDU_INFO_0, PHY_PPDU_ID); +} + +/** + * hal_reo_status_get_header_6290 - Process reo desc info + * @d - Pointer to reo descriptior + * @b - tlv type info + * @h1 - Pointer to hal_reo_status_header where info to be stored + * + * Return - none. + * + */ +static void hal_reo_status_get_header_6290(uint32_t *d, int b, void *h1) +{ + uint32_t val1 = 0; + struct hal_reo_status_header *h = + (struct hal_reo_status_header *)h1; + + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->cmd_num = + HAL_GET_FIELD( + UNIFORM_REO_STATUS_HEADER_0, REO_STATUS_NUMBER, + val1); + h->exec_time = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + CMD_EXECUTION_TIME, val1); + h->status = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + REO_CMD_EXECUTION_STATUS, val1); + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->tstamp = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_1, TIMESTAMP, val1); +} + +/** + * hal_rx_mpdu_start_mpdu_qos_control_valid_get_6290(): + * Retrieve qos control valid bit from the tlv. + * @buf: pointer to rx pkt TLV. + * + * Return: qos control value. + */ +static inline uint32_t +hal_rx_mpdu_start_mpdu_qos_control_valid_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/** + * hal_rx_msdu_end_sa_sw_peer_id_get_6290(): API to get the + * sa_sw_peer_id from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: sa_sw_peer_id index + */ +static inline uint32_t +hal_rx_msdu_end_sa_sw_peer_id_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(msdu_end); +} + +/** + * hal_tx_desc_set_mesh_en_6290 - Set mesh_enable flag in Tx descriptor + * @desc: Handle to Tx Descriptor + * @en: For raw WiFi frames, this indicates transmission to a mesh STA, + * enabling the interpretation of the 'Mesh Control Present' bit + * (bit 8) of QoS Control (otherwise this bit is ignored), + * For native WiFi frames, this indicates that a 'Mesh Control' field + * is present between the header and the LLC. + * + * Return: void + */ +static inline +void hal_tx_desc_set_mesh_en_6290(void *desc, uint8_t en) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_4, MESH_ENABLE) |= + HAL_TX_SM(TCL_DATA_CMD_4, MESH_ENABLE, en); +} + +static +void *hal_rx_msdu0_buffer_addr_lsb_6290(void *link_desc_va) +{ + return (void *)HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va); +} + +static +void *hal_rx_msdu_desc_info_ptr_get_6290(void *msdu0) +{ + return (void *)HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0); +} + +static +void *hal_ent_mpdu_desc_info_6290(void *ent_ring_desc) +{ + return (void *)HAL_ENT_MPDU_DESC_INFO(ent_ring_desc); +} + +static +void *hal_dst_mpdu_desc_info_6290(void *dst_ring_desc) +{ + return (void *)HAL_DST_MPDU_DESC_INFO(dst_ring_desc); +} + +static +uint8_t hal_rx_get_fc_valid_6290(uint8_t *buf) +{ + return HAL_RX_GET_FC_VALID(buf); +} + +static uint8_t hal_rx_get_to_ds_flag_6290(uint8_t *buf) +{ + return HAL_RX_GET_TO_DS_FLAG(buf); +} + +static uint8_t hal_rx_get_mac_addr2_valid_6290(uint8_t *buf) +{ + return HAL_RX_GET_MAC_ADDR2_VALID(buf); +} + +static uint8_t hal_rx_get_filter_category_6290(uint8_t *buf) +{ + return HAL_RX_GET_FILTER_CATEGORY(buf); +} + +static uint32_t +hal_rx_get_ppdu_id_6290(uint8_t *buf) +{ + return HAL_RX_GET_PPDU_ID(buf); +} + +/** + * hal_reo_config_6290(): Set reo config parameters + * @soc: hal soc handle + * @reg_val: value to be set + * @reo_params: reo parameters + * + * Return: void + */ +static +void hal_reo_config_6290(struct hal_soc *soc, + uint32_t reg_val, + struct hal_reo_params *reo_params) +{ + HAL_REO_R0_CONFIG(soc, reg_val, reo_params); +} + +/** + * hal_rx_msdu_desc_info_get_ptr_6290() - Get msdu desc info ptr + * @msdu_details_ptr - Pointer to msdu_details_ptr + * + * Return - Pointer to rx_msdu_desc_info structure. + * + */ +static void *hal_rx_msdu_desc_info_get_ptr_6290(void *msdu_details_ptr) +{ + return HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr); +} + +/** + * hal_rx_link_desc_msdu0_ptr_6290 - Get pointer to rx_msdu details + * @link_desc - Pointer to link desc + * + * Return - Pointer to rx_msdu_details structure + * + */ +static void *hal_rx_link_desc_msdu0_ptr_6290(void *link_desc) +{ + return HAL_RX_LINK_DESC_MSDU0_PTR(link_desc); +} + +/** + * hal_rx_msdu_flow_idx_get_6290: API to get flow index + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index value from MSDU END TLV + */ +static inline uint32_t hal_rx_msdu_flow_idx_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_invalid_6290: API to get flow index invalid + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index invalid value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_invalid_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_timeout_6290: API to get flow index timeout + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index timeout value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_timeout_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); +} + +/** + * hal_rx_msdu_fse_metadata_get_6290: API to get FSE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: fse metadata value from MSDU END TLV + */ +static uint32_t hal_rx_msdu_fse_metadata_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FSE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_cce_metadata_get_6290: API to get CCE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: cce_metadata + */ +static uint16_t +hal_rx_msdu_cce_metadata_get_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_CCE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_get_flow_params_6290: API to get flow index, flow index invalid + * and flow index timeout from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * @flow_invalid: pointer to return value of flow_idx_valid + * @flow_timeout: pointer to return value of flow_idx_timeout + * @flow_index: pointer to return value of flow_idx + * + * Return: none + */ +static inline void +hal_rx_msdu_get_flow_params_6290(uint8_t *buf, + bool *flow_invalid, + bool *flow_timeout, + uint32_t *flow_index) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + *flow_invalid = HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); + *flow_timeout = HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); + *flow_index = HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_tlv_get_tcp_chksum_6290() - API to get tcp checksum + * @buf: rx_tlv_hdr + * + * Return: tcp checksum + */ +static uint16_t +hal_rx_tlv_get_tcp_chksum_6290(uint8_t *buf) +{ + return HAL_RX_TLV_GET_TCP_CHKSUM(buf); +} + +/** + * hal_rx_get_rx_sequence_6290(): Function to retrieve rx sequence number + * @nbuf: Network buffer + * + * Return: rx sequence number + */ +static +uint16_t hal_rx_get_rx_sequence_6290(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info); +} + +/** + * hal_get_window_address_6290(): Function to get hp/tp address + * @hal_soc: Pointer to hal_soc + * @addr: address offset of register + * + * Return: modified address offset of register + */ +static inline qdf_iomem_t hal_get_window_address_6290(struct hal_soc *hal_soc, + qdf_iomem_t addr) +{ + return addr; +} + struct hal_hw_txrx_ops qca6290_hal_hw_txrx_ops = { /* init and setup */ hal_srng_dst_hw_init_generic, @@ -117,6 +997,7 @@ struct hal_hw_txrx_ops qca6290_hal_hw_txrx_ops = { hal_get_hw_hptp_generic, hal_reo_setup_generic, hal_setup_link_idle_list_generic, + hal_get_window_address_6290, NULL, /* tx */ @@ -127,9 +1008,11 @@ struct hal_hw_txrx_ops qca6290_hal_hw_txrx_ops = { hal_tx_desc_set_buf_addr_generic, hal_tx_desc_set_search_type_generic, hal_tx_desc_set_search_index_generic, + hal_tx_desc_set_cache_set_num_generic, hal_tx_comp_get_status_generic, hal_tx_comp_get_release_reason_generic, - + hal_get_wbm_internal_error_generic, + hal_tx_desc_set_mesh_en_6290, /* rx */ hal_rx_msdu_start_nss_get_6290, hal_rx_mon_hw_desc_get_mpdu_status_6290, @@ -141,9 +1024,9 @@ struct hal_hw_txrx_ops qca6290_hal_hw_txrx_ops = { hal_rx_mpdu_start_tid_get_6290, hal_rx_msdu_start_reception_type_get_6290, hal_rx_msdu_end_da_idx_get_6290, - hal_rx_msdu_desc_info_get_ptr_generic, - hal_rx_link_desc_msdu0_ptr_generic, - hal_reo_status_get_header_generic, + hal_rx_msdu_desc_info_get_ptr_6290, + hal_rx_link_desc_msdu0_ptr_6290, + hal_reo_status_get_header_6290, hal_rx_status_get_tlv_info_generic, hal_rx_wbm_err_info_get_generic, hal_rx_dump_mpdu_start_tlv_generic, @@ -151,6 +1034,60 @@ struct hal_hw_txrx_ops qca6290_hal_hw_txrx_ops = { hal_tx_set_pcp_tid_map_generic, hal_tx_update_pcp_tid_generic, hal_tx_update_tidmap_prty_generic, + hal_rx_get_rx_fragment_number_6290, + hal_rx_msdu_end_da_is_mcbc_get_6290, + hal_rx_msdu_end_sa_is_valid_get_6290, + hal_rx_msdu_end_sa_idx_get_6290, + hal_rx_desc_is_first_msdu_6290, + hal_rx_msdu_end_l3_hdr_padding_get_6290, + hal_rx_encryption_info_valid_6290, + hal_rx_print_pn_6290, + hal_rx_msdu_end_first_msdu_get_6290, + hal_rx_msdu_end_da_is_valid_get_6290, + hal_rx_msdu_end_last_msdu_get_6290, + hal_rx_get_mpdu_mac_ad4_valid_6290, + hal_rx_mpdu_start_sw_peer_id_get_6290, + hal_rx_mpdu_get_to_ds_6290, + hal_rx_mpdu_get_fr_ds_6290, + hal_rx_get_mpdu_frame_control_valid_6290, + hal_rx_mpdu_get_addr1_6290, + hal_rx_mpdu_get_addr2_6290, + hal_rx_mpdu_get_addr3_6290, + hal_rx_mpdu_get_addr4_6290, + hal_rx_get_mpdu_sequence_control_valid_6290, + hal_rx_is_unicast_6290, + hal_rx_tid_get_6290, + hal_rx_hw_desc_get_ppduid_get_6290, + hal_rx_mpdu_start_mpdu_qos_control_valid_get_6290, + hal_rx_msdu_end_sa_sw_peer_id_get_6290, + hal_rx_msdu0_buffer_addr_lsb_6290, + hal_rx_msdu_desc_info_ptr_get_6290, + hal_ent_mpdu_desc_info_6290, + hal_dst_mpdu_desc_info_6290, + hal_rx_get_fc_valid_6290, + hal_rx_get_to_ds_flag_6290, + hal_rx_get_mac_addr2_valid_6290, + hal_rx_get_filter_category_6290, + hal_rx_get_ppdu_id_6290, + hal_reo_config_6290, + hal_rx_msdu_flow_idx_get_6290, + hal_rx_msdu_flow_idx_invalid_6290, + hal_rx_msdu_flow_idx_timeout_6290, + hal_rx_msdu_fse_metadata_get_6290, + hal_rx_msdu_cce_metadata_get_6290, + hal_rx_msdu_get_flow_params_6290, + hal_rx_tlv_get_tcp_chksum_6290, + hal_rx_get_rx_sequence_6290, + NULL, + NULL, + /* rx - msdu end fast path info fields */ + hal_rx_msdu_packet_metadata_get_generic, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; struct hal_hw_srng_config hw_srng_table_6290[] = { diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290_rx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290_rx.h index f4e387f747fb88f1ea7588b833dc0ee79654b0ca..9417cf728f59706fb1ddd4c4e7e25abc64e30bbc 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290_rx.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290_rx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -35,6 +35,309 @@ #include "hal_api_mon.h" #include "phyrx_other_receive_info_ru_details.h" +#define HAL_RX_MPDU_GET_SEQUENCE_NUMBER(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_MASK, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_MCBC_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_DA_IS_MCBC_OFFSET)), \ + RX_MSDU_END_5_DA_IS_MCBC_MASK, \ + RX_MSDU_END_5_DA_IS_MCBC_LSB)) + +#define HAL_RX_MSDU_END_SA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_SA_IS_VALID_OFFSET)), \ + RX_MSDU_END_5_SA_IS_VALID_MASK, \ + RX_MSDU_END_5_SA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_13_SA_IDX_OFFSET)), \ + RX_MSDU_END_13_SA_IDX_MASK, \ + RX_MSDU_END_13_SA_IDX_LSB)) + +#define HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_L3_HEADER_PADDING_OFFSET)), \ + RX_MSDU_END_5_L3_HEADER_PADDING_MASK, \ + RX_MSDU_END_5_L3_HEADER_PADDING_LSB)) + +#define HAL_RX_MPDU_ENCRYPTION_INFO_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_OFFSET)), \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_MASK, \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_LSB)) + +#define HAL_RX_MPDU_PN_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_4_PN_31_0_OFFSET)), \ + RX_MPDU_INFO_4_PN_31_0_MASK, \ + RX_MPDU_INFO_4_PN_31_0_LSB)) + +#define HAL_RX_MPDU_PN_63_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_5_PN_63_32_OFFSET)), \ + RX_MPDU_INFO_5_PN_63_32_MASK, \ + RX_MPDU_INFO_5_PN_63_32_LSB)) + +#define HAL_RX_MPDU_PN_95_64_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_6_PN_95_64_OFFSET)), \ + RX_MPDU_INFO_6_PN_95_64_MASK, \ + RX_MPDU_INFO_6_PN_95_64_LSB)) + +#define HAL_RX_MPDU_PN_127_96_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_7_PN_127_96_OFFSET)), \ + RX_MPDU_INFO_7_PN_127_96_MASK, \ + RX_MPDU_INFO_7_PN_127_96_LSB)) + +#define HAL_RX_MSDU_END_FIRST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FIRST_MSDU_OFFSET)), \ + RX_MSDU_END_5_FIRST_MSDU_MASK, \ + RX_MSDU_END_5_FIRST_MSDU_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_DA_IS_VALID_OFFSET)), \ + RX_MSDU_END_5_DA_IS_VALID_MASK, \ + RX_MSDU_END_5_DA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_LAST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_LAST_MSDU_OFFSET)), \ + RX_MSDU_END_5_LAST_MSDU_MASK, \ + RX_MSDU_END_5_LAST_MSDU_LSB)) + +#define HAL_RX_MPDU_GET_MAC_AD4_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_SW_PEER_ID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_1_SW_PEER_ID_OFFSET)), \ + RX_MPDU_INFO_1_SW_PEER_ID_MASK, \ + RX_MPDU_INFO_1_SW_PEER_ID_LSB)) + +#define HAL_RX_MPDU_GET_TODS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_TO_DS_OFFSET)), \ + RX_MPDU_INFO_2_TO_DS_MASK, \ + RX_MPDU_INFO_2_TO_DS_LSB)) + +#define HAL_RX_MPDU_GET_FROMDS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_FR_DS_OFFSET)), \ + RX_MPDU_INFO_2_FR_DS_MASK, \ + RX_MPDU_INFO_2_FR_DS_LSB)) + +#define HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_LSB)) + +#define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_MASK, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_LSB)) + +#define HAL_RX_MPDU_AD1_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_LSB)) + +#define HAL_RX_MPDU_AD2_15_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_LSB)) + +#define HAL_RX_MPDU_AD2_47_16_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_OFFSET)), \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_MASK, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_LSB)) + +#define HAL_RX_MPDU_AD3_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_OFFSET)), \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_MASK, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_LSB)) + +#define HAL_RX_MPDU_AD3_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_OFFSET)), \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_MASK, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_AD4_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_OFFSET)), \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_MASK, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_LSB)) + +#define HAL_RX_MPDU_AD4_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_OFFSET)), \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_MASK, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_LSB)) + +#define HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_16_SA_SW_PEER_ID_OFFSET)), \ + RX_MSDU_END_16_SA_SW_PEER_ID_MASK, \ + RX_MSDU_END_16_SA_SW_PEER_ID_LSB)) + +#define HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va) \ + (uint8_t *)(link_desc_va) + \ + RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET + +#define HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0) \ + (uint8_t *)(msdu0) + \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET + +#define HAL_ENT_MPDU_DESC_INFO(ent_ring_desc) \ + (uint8_t *)(ent_ring_desc) + \ + RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET + +#define HAL_DST_MPDU_DESC_INFO(dst_ring_desc) \ + (uint8_t *)(dst_ring_desc) + \ + REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET + +#define HAL_RX_GET_FC_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MPDU_FRAME_CONTROL_VALID) + +#define HAL_RX_GET_TO_DS_FLAG(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, TO_DS) + +#define HAL_RX_GET_MAC_ADDR1_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MAC_ADDR_AD1_VALID) + +#define HAL_RX_GET_MAC_ADDR2_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MAC_ADDR_AD2_VALID) + +#define HAL_RX_GET_FILTER_CATEGORY(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, RXPCU_MPDU_FILTER_IN_CATEGORY) + +#define HAL_RX_GET_PPDU_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, PHY_PPDU_ID) + +#define HAL_RX_GET_SW_FRAME_GROUP_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, SW_FRAME_GROUP_ID) + +#define HAL_REO_R0_CONFIG(soc, reg_val, reo_params) \ + do { \ + (reg_val) &= \ + ~(HWIO_REO_R0_GENERAL_ENABLE_FRAGMENT_DEST_RING_BMSK |\ + HWIO_REO_R0_GENERAL_ENABLE_AGING_LIST_ENABLE_BMSK |\ + HWIO_REO_R0_GENERAL_ENABLE_AGING_FLUSH_ENABLE_BMSK);\ + (reg_val) |= \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + FRAGMENT_DEST_RING, \ + (reo_params)->frag_dst_ring) | \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_LIST_ENABLE, 1) |\ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_FLUSH_ENABLE, 1);\ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ + } while (0) + +#define HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr) \ + ((struct rx_msdu_desc_info *) \ + _OFFSET_TO_BYTE_PTR(msdu_details_ptr, \ +UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET)) + +#define HAL_RX_LINK_DESC_MSDU0_PTR(link_desc) \ + ((struct rx_msdu_details *) \ + _OFFSET_TO_BYTE_PTR((link_desc),\ + UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET)) + +#define HAL_RX_MSDU_END_FLOW_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_14_FLOW_IDX_OFFSET)), \ + RX_MSDU_END_14_FLOW_IDX_MASK, \ + RX_MSDU_END_14_FLOW_IDX_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FLOW_IDX_INVALID_OFFSET)), \ + RX_MSDU_END_5_FLOW_IDX_INVALID_MASK, \ + RX_MSDU_END_5_FLOW_IDX_INVALID_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_OFFSET)), \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_MASK, \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_LSB)) + +#define HAL_RX_MSDU_END_FSE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_15_FSE_METADATA_OFFSET)), \ + RX_MSDU_END_15_FSE_METADATA_MASK, \ + RX_MSDU_END_15_FSE_METADATA_LSB)) + +#define HAL_RX_MSDU_END_CCE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_16_CCE_METADATA_OFFSET)), \ + RX_MSDU_END_16_CCE_METADATA_MASK, \ + RX_MSDU_END_16_CCE_METADATA_LSB)) + +#define HAL_RX_TLV_GET_TCP_CHKSUM(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_OFFSET)), \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_MASK, \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_LSB)) + #if defined(QCA_WIFI_QCA6290_11AX) #define HAL_RX_MSDU_START_MIMO_SS_BITMAP(_rx_msdu_start)\ (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\ diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290_tx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290_tx.h index 09b022fb75d96441e40b6190a3d4a77536fbed7e..2d4cc75acc8d1aa8081d3a0f5f2bb072bf5b3443 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290_tx.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6290/hal_6290_tx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 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 @@ -46,7 +46,6 @@ static void hal_tx_desc_set_dscp_tid_table_id_6290(void *desc, DSCP_TID_TABLE_NUM, id); } #else -#ifdef CONFIG_MCL static void hal_tx_desc_set_dscp_tid_table_id_6290(void *desc, uint8_t id) { @@ -56,7 +55,6 @@ static void hal_tx_desc_set_dscp_tid_table_id_6290(void *desc, DSCP_TO_TID_PRIORITY_TABLE_ID, id); } #endif -#endif #define DSCP_TID_TABLE_SIZE 24 @@ -74,7 +72,8 @@ static void hal_tx_desc_set_dscp_tid_table_id_6290(void *desc, * * Return: none */ -static void hal_tx_set_dscp_tid_map_6290(void *hal_soc, uint8_t *map, +static void hal_tx_set_dscp_tid_map_6290(struct hal_soc *soc, + uint8_t *map, uint8_t id) { int i; @@ -82,8 +81,6 @@ static void hal_tx_set_dscp_tid_map_6290(void *hal_soc, uint8_t *map, uint32_t value = 0, regval; uint8_t val[DSCP_TID_TABLE_SIZE], cnt = 0; - struct hal_soc *soc = (struct hal_soc *)hal_soc; - if (id >= HAL_MAX_HW_DSCP_TID_MAPS_11AX) return; @@ -112,7 +109,7 @@ static void hal_tx_set_dscp_tid_map_6290(void *hal_soc, uint8_t *map, (map[i + 6] << 0x12) | (map[i + 7] << 0x15)); - qdf_mem_copy(&val[cnt], (void *)&value, 3); + qdf_mem_copy(&val[cnt], &value, 3); cnt += 3; } @@ -131,15 +128,14 @@ static void hal_tx_set_dscp_tid_map_6290(void *hal_soc, uint8_t *map, HAL_REG_WRITE(soc, cmn_reg_addr, regval); } #else -static void hal_tx_set_dscp_tid_map_6290(void *hal_soc, uint8_t *map, +static void hal_tx_set_dscp_tid_map_6290(struct hal_soc *soc, + uint8_t *map, uint8_t id) { int i; uint32_t addr; uint32_t value; - struct hal_soc *soc = (struct hal_soc *)hal_soc; - if (id == HAL_TX_DSCP_TID_MAP_TABLE_DEFAULT) { addr = HWIO_TCL_R0_DSCP_TID1_MAP_0_ADDR( @@ -181,14 +177,13 @@ static void hal_tx_set_dscp_tid_map_6290(void *hal_soc, uint8_t *map, * * Return: void */ -static void hal_tx_update_dscp_tid_6290(void *hal_soc, uint8_t tid, +static void hal_tx_update_dscp_tid_6290(struct hal_soc *soc, uint8_t tid, uint8_t id, uint8_t dscp) { int index; uint32_t addr; uint32_t value; uint32_t regval; - struct hal_soc *soc = (struct hal_soc *)hal_soc; addr = HWIO_TCL_R0_DSCP_TID_MAP_n_ADDR( SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET, id); @@ -204,7 +199,7 @@ static void hal_tx_update_dscp_tid_6290(void *hal_soc, uint8_t tid, HAL_REG_WRITE(soc, addr, (regval & HWIO_TCL_R0_DSCP_TID_MAP_n_RMSK)); } #else -static void hal_tx_update_dscp_tid_6290(void *hal_soc, uint8_t tid, +static void hal_tx_update_dscp_tid_6290(struct hal_soc *soc, uint8_t tid, uint8_t id, uint8_t dscp) { int index; @@ -212,8 +207,6 @@ static void hal_tx_update_dscp_tid_6290(void *hal_soc, uint8_t tid, uint32_t value; uint32_t regval; - struct hal_soc *soc = (struct hal_soc *)hal_soc; - if (id == HAL_TX_DSCP_TID_MAP_TABLE_DEFAULT) addr = HWIO_TCL_R0_DSCP_TID1_MAP_0_ADDR( diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390.c b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390.c index 830f38d82588089e03e90c960c8189cadea19bc8..af5479b2c0195e0fe240100e2643f85a3b1d01fc 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390.c +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -110,6 +110,882 @@ #include #include +/** + * hal_rx_get_rx_fragment_number_6390(): Function to retrieve rx fragment number + * + * @nbuf: Network buffer + * Returns: rx fragment number + */ +static +uint8_t hal_rx_get_rx_fragment_number_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + /* Return first 4 bits as fragment number */ + return (HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info) & + DOT11_SEQ_FRAG_MASK); +} + +/** + * hal_rx_msdu_end_da_is_mcbc_get_6390(): API to check if pkt is MCBC + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_mcbc + */ +static uint8_t +hal_rx_msdu_end_da_is_mcbc_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_DA_IS_MCBC_GET(msdu_end); +} + +/** + * hal_rx_msdu_end_sa_is_valid_get_6390(): API to get_6390 the + * sa_is_valid bit from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_is_valid bit + */ +static uint8_t +hal_rx_msdu_end_sa_is_valid_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t sa_is_valid; + + sa_is_valid = HAL_RX_MSDU_END_SA_IS_VALID_GET(msdu_end); + + return sa_is_valid; +} + +/** + * hal_rx_msdu_end_sa_idx_get_6390(): API to get_6390 the + * sa_idx from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_idx (SA AST index) + */ +static +uint16_t hal_rx_msdu_end_sa_idx_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint16_t sa_idx; + + sa_idx = HAL_RX_MSDU_END_SA_IDX_GET(msdu_end); + + return sa_idx; +} + +/** + * hal_rx_desc_is_first_msdu_6390() - Check if first msdu + * + * @hal_soc_hdl: hal_soc handle + * @hw_desc_addr: hardware descriptor address + * + * Return: 0 - success/ non-zero failure + */ +static uint32_t hal_rx_desc_is_first_msdu_6390(void *hw_desc_addr) +{ + struct rx_pkt_tlvs *rx_tlvs = (struct rx_pkt_tlvs *)hw_desc_addr; + struct rx_msdu_end *msdu_end = &rx_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_GET(msdu_end, RX_MSDU_END_5, FIRST_MSDU); +} + +/** + * hal_rx_msdu_end_l3_hdr_padding_get_6390(): API to get_6390 the + * l3_header padding from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: number of l3 header padding bytes + */ +static uint32_t hal_rx_msdu_end_l3_hdr_padding_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint32_t l3_header_padding; + + l3_header_padding = HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(msdu_end); + + return l3_header_padding; +} + +/* + * @ hal_rx_encryption_info_valid_6390: Returns encryption type. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: encryption type + */ +static uint32_t hal_rx_encryption_info_valid_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + uint32_t encryption_info = HAL_RX_MPDU_ENCRYPTION_INFO_VALID(mpdu_info); + + return encryption_info; +} + +/* + * @ hal_rx_print_pn_6390: Prints the PN of rx packet. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: void + */ +static void hal_rx_print_pn_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + uint32_t pn_31_0 = HAL_RX_MPDU_PN_31_0_GET(mpdu_info); + uint32_t pn_63_32 = HAL_RX_MPDU_PN_63_32_GET(mpdu_info); + uint32_t pn_95_64 = HAL_RX_MPDU_PN_95_64_GET(mpdu_info); + uint32_t pn_127_96 = HAL_RX_MPDU_PN_127_96_GET(mpdu_info); + + hal_debug("PN number pn_127_96 0x%x pn_95_64 0x%x pn_63_32 0x%x pn_31_0 0x%x ", + pn_127_96, pn_95_64, pn_63_32, pn_31_0); +} + +/** + * hal_rx_msdu_end_first_msduget_6390: API to get first msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: first_msdu + */ +static uint8_t hal_rx_msdu_end_first_msdu_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t first_msdu; + + first_msdu = HAL_RX_MSDU_END_FIRST_MSDU_GET(msdu_end); + + return first_msdu; +} + +/** + * hal_rx_msdu_end_da_is_valid_get_6390: API to check if da is valid + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_valid + */ +static uint8_t hal_rx_msdu_end_da_is_valid_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t da_is_valid; + + da_is_valid = HAL_RX_MSDU_END_DA_IS_VALID_GET(msdu_end); + + return da_is_valid; +} + +/** + * hal_rx_msdu_end_last_msdu_get_6390: API to get last msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: last_msdu + */ +static uint8_t hal_rx_msdu_end_last_msdu_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t last_msdu; + + last_msdu = HAL_RX_MSDU_END_LAST_MSDU_GET(msdu_end); + + return last_msdu; +} + +/* + * hal_rx_get_mpdu_mac_ad4_valid_6390(): Retrieves if mpdu 4th addr is valid + * + * @nbuf: Network buffer + * Returns: value of mpdu 4th address valid field + */ +static bool hal_rx_get_mpdu_mac_ad4_valid_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + bool ad4_valid = 0; + + ad4_valid = HAL_RX_MPDU_GET_MAC_AD4_VALID(rx_mpdu_info); + + return ad4_valid; +} + +/** + * hal_rx_mpdu_start_sw_peer_id_get_6390: Retrieve sw peer_id + * @buf: network buffer + * + * Return: sw peer_id + */ +static uint32_t hal_rx_mpdu_start_sw_peer_id_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_SW_PEER_ID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/* + * hal_rx_mpdu_get_to_ds_6390(): API to get the tods info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(to_ds) + */ +static uint32_t hal_rx_mpdu_get_to_ds_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_TODS(mpdu_info); +} + +/* + * hal_rx_mpdu_get_fr_ds_6390(): API to get the from ds info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(fr_ds) + */ +static uint32_t hal_rx_mpdu_get_fr_ds_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_FROMDS(mpdu_info); +} + +/* + * hal_rx_get_mpdu_frame_control_valid_6390(): Retrieves mpdu + * frame control valid + * + * @nbuf: Network buffer + * Returns: value of frame control valid field + */ +static uint8_t hal_rx_get_mpdu_frame_control_valid_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(rx_mpdu_info); +} + +/* + * hal_rx_mpdu_get_addr1_6390(): API to check get address1 of the mpdu + * + * @buf: pointer to the start of RX PKT TLV headera + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr1_6390(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr1 { + uint32_t ad1_31_0; + uint16_t ad1_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr1 *addr = (struct hal_addr1 *)mac_addr; + uint32_t mac_addr_ad1_valid; + + mac_addr_ad1_valid = HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(mpdu_info); + + if (mac_addr_ad1_valid) { + addr->ad1_31_0 = HAL_RX_MPDU_AD1_31_0_GET(mpdu_info); + addr->ad1_47_32 = HAL_RX_MPDU_AD1_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr2_6390(): API to check get address2 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr2_6390(uint8_t *buf, + uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr2 { + uint16_t ad2_15_0; + uint32_t ad2_47_16; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr2 *addr = (struct hal_addr2 *)mac_addr; + uint32_t mac_addr_ad2_valid; + + mac_addr_ad2_valid = HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(mpdu_info); + + if (mac_addr_ad2_valid) { + addr->ad2_15_0 = HAL_RX_MPDU_AD2_15_0_GET(mpdu_info); + addr->ad2_47_16 = HAL_RX_MPDU_AD2_47_16_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr3_6390(): API to get address3 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr3_6390(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr3 { + uint32_t ad3_31_0; + uint16_t ad3_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr3 *addr = (struct hal_addr3 *)mac_addr; + uint32_t mac_addr_ad3_valid; + + mac_addr_ad3_valid = HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(mpdu_info); + + if (mac_addr_ad3_valid) { + addr->ad3_31_0 = HAL_RX_MPDU_AD3_31_0_GET(mpdu_info); + addr->ad3_47_32 = HAL_RX_MPDU_AD3_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr4_6390(): API to get address4 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr4_6390(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr4 { + uint32_t ad4_31_0; + uint16_t ad4_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr4 *addr = (struct hal_addr4 *)mac_addr; + uint32_t mac_addr_ad4_valid; + + mac_addr_ad4_valid = HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(mpdu_info); + + if (mac_addr_ad4_valid) { + addr->ad4_31_0 = HAL_RX_MPDU_AD4_31_0_GET(mpdu_info); + addr->ad4_47_32 = HAL_RX_MPDU_AD4_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_get_mpdu_sequence_control_valid_6390(): Get mpdu + * sequence control valid + * + * @nbuf: Network buffer + * Returns: value of sequence control valid field + */ +static uint8_t hal_rx_get_mpdu_sequence_control_valid_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(rx_mpdu_info); +} + +/** + * hal_rx_is_unicast_6390: check packet is unicast frame or not. + * + * @ buf: pointer to rx pkt TLV. + * + * Return: true on unicast. + */ +static bool hal_rx_is_unicast_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint32_t grp_id; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + + grp_id = (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_OFFSET)), + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_MASK, + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_LSB)); + + return (HAL_MPDU_SW_FRAME_GROUP_UNICAST_DATA == grp_id) ? true : false; +} + +/** + * hal_rx_tid_get_6390: get tid based on qos control valid. + * @hal_soc_hdl: hal soc handle + * @buf: pointer to rx pkt TLV. + * + * Return: tid + */ +static uint32_t hal_rx_tid_get_6390(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + uint8_t qos_control_valid = + (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_OFFSET)), + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_MASK, + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_LSB)); + + if (qos_control_valid) + return hal_rx_mpdu_start_tid_get_6390(buf); + + return HAL_RX_NON_QOS_TID; +} + +/** + * hal_rx_hw_desc_get_ppduid_get_6390(): retrieve ppdu id + * @hw_desc_addr: hw addr + * + * Return: ppdu id + */ +static uint32_t hal_rx_hw_desc_get_ppduid_get_6390(void *hw_desc_addr) +{ + struct rx_mpdu_info *rx_mpdu_info; + struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + + rx_mpdu_info = + &rx_desc->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + + return HAL_RX_GET(rx_mpdu_info, RX_MPDU_INFO_0, PHY_PPDU_ID); +} + +/** + * hal_reo_status_get_header_6390 - Process reo desc info + * @d - Pointer to reo descriptior + * @b - tlv type info + * @h1 - Pointer to hal_reo_status_header where info to be stored + * + * Return - none. + * + */ +static void hal_reo_status_get_header_6390(uint32_t *d, int b, void *h1) +{ + uint32_t val1 = 0; + struct hal_reo_status_header *h = + (struct hal_reo_status_header *)h1; + + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->cmd_num = + HAL_GET_FIELD( + UNIFORM_REO_STATUS_HEADER_0, REO_STATUS_NUMBER, + val1); + h->exec_time = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + CMD_EXECUTION_TIME, val1); + h->status = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + REO_CMD_EXECUTION_STATUS, val1); + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->tstamp = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_1, TIMESTAMP, val1); +} + +/** + * hal_rx_mpdu_start_mpdu_qos_control_valid_get_6390(): + * Retrieve qos control valid bit from the tlv. + * @buf: pointer to rx pkt TLV. + * + * Return: qos control value. + */ +static inline uint32_t +hal_rx_mpdu_start_mpdu_qos_control_valid_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/** + * hal_rx_msdu_end_sa_sw_peer_id_get_6390(): API to get the + * sa_sw_peer_id from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: sa_sw_peer_id index + */ +static inline uint32_t +hal_rx_msdu_end_sa_sw_peer_id_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(msdu_end); +} + +/** + * hal_tx_desc_set_mesh_en_6390 - Set mesh_enable flag in Tx descriptor + * @desc: Handle to Tx Descriptor + * @en: For raw WiFi frames, this indicates transmission to a mesh STA, + * enabling the interpretation of the 'Mesh Control Present' bit + * (bit 8) of QoS Control (otherwise this bit is ignored), + * For native WiFi frames, this indicates that a 'Mesh Control' field + * is present between the header and the LLC. + * + * Return: void + */ +static inline +void hal_tx_desc_set_mesh_en_6390(void *desc, uint8_t en) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_4, MESH_ENABLE) |= + HAL_TX_SM(TCL_DATA_CMD_4, MESH_ENABLE, en); +} + +static +void *hal_rx_msdu0_buffer_addr_lsb_6390(void *link_desc_va) +{ + return (void *)HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va); +} + +static +void *hal_rx_msdu_desc_info_ptr_get_6390(void *msdu0) +{ + return (void *)HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0); +} + +static +void *hal_ent_mpdu_desc_info_6390(void *ent_ring_desc) +{ + return (void *)HAL_ENT_MPDU_DESC_INFO(ent_ring_desc); +} + +static +void *hal_dst_mpdu_desc_info_6390(void *dst_ring_desc) +{ + return (void *)HAL_DST_MPDU_DESC_INFO(dst_ring_desc); +} + +static +uint8_t hal_rx_get_fc_valid_6390(uint8_t *buf) +{ + return HAL_RX_GET_FC_VALID(buf); +} + +static uint8_t hal_rx_get_to_ds_flag_6390(uint8_t *buf) +{ + return HAL_RX_GET_TO_DS_FLAG(buf); +} + +static uint8_t hal_rx_get_mac_addr2_valid_6390(uint8_t *buf) +{ + return HAL_RX_GET_MAC_ADDR2_VALID(buf); +} + +static uint8_t hal_rx_get_filter_category_6390(uint8_t *buf) +{ + return HAL_RX_GET_FILTER_CATEGORY(buf); +} + +static uint32_t +hal_rx_get_ppdu_id_6390(uint8_t *buf) +{ + return HAL_RX_GET_PPDU_ID(buf); +} + +/** + * hal_reo_config_6390(): Set reo config parameters + * @soc: hal soc handle + * @reg_val: value to be set + * @reo_params: reo parameters + * + * Return: void + */ +static +void hal_reo_config_6390(struct hal_soc *soc, + uint32_t reg_val, + struct hal_reo_params *reo_params) +{ + HAL_REO_R0_CONFIG(soc, reg_val, reo_params); +} + +/** + * hal_rx_msdu_desc_info_get_ptr_6390() - Get msdu desc info ptr + * @msdu_details_ptr - Pointer to msdu_details_ptr + * Return - Pointer to rx_msdu_desc_info structure. + * + */ +static void *hal_rx_msdu_desc_info_get_ptr_6390(void *msdu_details_ptr) +{ + return HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr); +} + +/** + * hal_rx_link_desc_msdu0_ptr_6390 - Get pointer to rx_msdu details + * @link_desc - Pointer to link desc + * Return - Pointer to rx_msdu_details structure + * + */ +static void *hal_rx_link_desc_msdu0_ptr_6390(void *link_desc) +{ + return HAL_RX_LINK_DESC_MSDU0_PTR(link_desc); +} + +/** + * hal_rx_msdu_flow_idx_get_6390: API to get flow index + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index value from MSDU END TLV + */ +static inline uint32_t hal_rx_msdu_flow_idx_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_invalid_6390: API to get flow index invalid + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index invalid value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_invalid_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_timeout_6390: API to get flow index timeout + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index timeout value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_timeout_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); +} + +/** + * hal_rx_msdu_fse_metadata_get_6390: API to get FSE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: fse metadata value from MSDU END TLV + */ +static uint32_t hal_rx_msdu_fse_metadata_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FSE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_cce_metadata_get_6390: API to get CCE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: cce metadata + */ +static uint16_t +hal_rx_msdu_cce_metadata_get_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_CCE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_get_flow_params_6390: API to get flow index, flow index invalid + * and flow index timeout from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * @flow_invalid: pointer to return value of flow_idx_valid + * @flow_timeout: pointer to return value of flow_idx_timeout + * @flow_index: pointer to return value of flow_idx + * + * Return: none + */ +static inline void +hal_rx_msdu_get_flow_params_6390(uint8_t *buf, + bool *flow_invalid, + bool *flow_timeout, + uint32_t *flow_index) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + *flow_invalid = HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); + *flow_timeout = HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); + *flow_index = HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_tlv_get_tcp_chksum_6390() - API to get tcp checksum + * @buf: rx_tlv_hdr + * + * Return: tcp checksum + */ +static uint16_t +hal_rx_tlv_get_tcp_chksum_6390(uint8_t *buf) +{ + return HAL_RX_TLV_GET_TCP_CHKSUM(buf); +} + +/** + * hal_rx_get_rx_sequence_6390(): Function to retrieve rx sequence number + * + * @nbuf: Network buffer + * Returns: rx sequence number + */ +static +uint16_t hal_rx_get_rx_sequence_6390(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info); +} + +/** + * hal_get_window_address_6390(): Function to get hp/tp address + * @hal_soc: Pointer to hal_soc + * @addr: address offset of register + * + * Return: modified address offset of register + */ +static inline qdf_iomem_t hal_get_window_address_6390(struct hal_soc *hal_soc, + qdf_iomem_t addr) +{ + return addr; +} + /** * hal_reo_set_err_dst_remap_6390(): Function to set REO error destination * ring remap register @@ -131,9 +1007,9 @@ hal_reo_set_err_dst_remap_6390(void *hal_soc) HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 3) | HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 4) | HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 5) | - HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 6) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 6) | HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 7) | - HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 8) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 8) | HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 9); HAL_REG_WRITE(hal_soc, @@ -155,6 +1031,7 @@ struct hal_hw_txrx_ops qca6390_hal_hw_txrx_ops = { hal_get_hw_hptp_generic, hal_reo_setup_generic, hal_setup_link_idle_list_generic, + hal_get_window_address_6390, hal_reo_set_err_dst_remap_6390, /* tx */ @@ -165,9 +1042,11 @@ struct hal_hw_txrx_ops qca6390_hal_hw_txrx_ops = { hal_tx_desc_set_buf_addr_generic, hal_tx_desc_set_search_type_generic, hal_tx_desc_set_search_index_generic, + hal_tx_desc_set_cache_set_num_generic, hal_tx_comp_get_status_generic, hal_tx_comp_get_release_reason_generic, - + hal_get_wbm_internal_error_generic, + hal_tx_desc_set_mesh_en_6390, /* rx */ hal_rx_msdu_start_nss_get_6390, hal_rx_mon_hw_desc_get_mpdu_status_6390, @@ -179,9 +1058,9 @@ struct hal_hw_txrx_ops qca6390_hal_hw_txrx_ops = { hal_rx_mpdu_start_tid_get_6390, hal_rx_msdu_start_reception_type_get_6390, hal_rx_msdu_end_da_idx_get_6390, - hal_rx_msdu_desc_info_get_ptr_generic, - hal_rx_link_desc_msdu0_ptr_generic, - hal_reo_status_get_header_generic, + hal_rx_msdu_desc_info_get_ptr_6390, + hal_rx_link_desc_msdu0_ptr_6390, + hal_reo_status_get_header_6390, hal_rx_status_get_tlv_info_generic, hal_rx_wbm_err_info_get_generic, hal_rx_dump_mpdu_start_tlv_generic, @@ -189,6 +1068,61 @@ struct hal_hw_txrx_ops qca6390_hal_hw_txrx_ops = { hal_tx_set_pcp_tid_map_generic, hal_tx_update_pcp_tid_generic, hal_tx_update_tidmap_prty_generic, + hal_rx_get_rx_fragment_number_6390, + hal_rx_msdu_end_da_is_mcbc_get_6390, + hal_rx_msdu_end_sa_is_valid_get_6390, + hal_rx_msdu_end_sa_idx_get_6390, + hal_rx_desc_is_first_msdu_6390, + hal_rx_msdu_end_l3_hdr_padding_get_6390, + hal_rx_encryption_info_valid_6390, + hal_rx_print_pn_6390, + hal_rx_msdu_end_first_msdu_get_6390, + hal_rx_msdu_end_da_is_valid_get_6390, + hal_rx_msdu_end_last_msdu_get_6390, + hal_rx_get_mpdu_mac_ad4_valid_6390, + hal_rx_mpdu_start_sw_peer_id_get_6390, + hal_rx_mpdu_get_to_ds_6390, + hal_rx_mpdu_get_fr_ds_6390, + hal_rx_get_mpdu_frame_control_valid_6390, + hal_rx_mpdu_get_addr1_6390, + hal_rx_mpdu_get_addr2_6390, + hal_rx_mpdu_get_addr3_6390, + hal_rx_mpdu_get_addr4_6390, + hal_rx_get_mpdu_sequence_control_valid_6390, + hal_rx_is_unicast_6390, + hal_rx_tid_get_6390, + hal_rx_hw_desc_get_ppduid_get_6390, + hal_rx_mpdu_start_mpdu_qos_control_valid_get_6390, + hal_rx_msdu_end_sa_sw_peer_id_get_6390, + hal_rx_msdu0_buffer_addr_lsb_6390, + hal_rx_msdu_desc_info_ptr_get_6390, + hal_ent_mpdu_desc_info_6390, + hal_dst_mpdu_desc_info_6390, + hal_rx_get_fc_valid_6390, + hal_rx_get_to_ds_flag_6390, + hal_rx_get_mac_addr2_valid_6390, + hal_rx_get_filter_category_6390, + hal_rx_get_ppdu_id_6390, + hal_reo_config_6390, + hal_rx_msdu_flow_idx_get_6390, + hal_rx_msdu_flow_idx_invalid_6390, + hal_rx_msdu_flow_idx_timeout_6390, + hal_rx_msdu_fse_metadata_get_6390, + hal_rx_msdu_cce_metadata_get_6390, + hal_rx_msdu_get_flow_params_6390, + hal_rx_tlv_get_tcp_chksum_6390, + hal_rx_get_rx_sequence_6390, + NULL, + NULL, + /* rx - msdu end fast path info fields */ + hal_rx_msdu_packet_metadata_get_generic, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL }; struct hal_hw_srng_config hw_srng_table_6390[] = { diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390_rx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390_rx.h index 601032de1408c153ec5cb4cd9ee8eb2132ba8e07..095b9f8de03b820cad9e29bbf7d5dd900d870599 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390_rx.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390_rx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -35,12 +35,325 @@ #include "hal_api_mon.h" #include "phyrx_other_receive_info_ru_details.h" +#define HAL_RX_MPDU_GET_SEQUENCE_NUMBER(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_MASK, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_MCBC_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_DA_IS_MCBC_OFFSET)), \ + RX_MSDU_END_5_DA_IS_MCBC_MASK, \ + RX_MSDU_END_5_DA_IS_MCBC_LSB)) + +#define HAL_RX_MSDU_END_SA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_SA_IS_VALID_OFFSET)), \ + RX_MSDU_END_5_SA_IS_VALID_MASK, \ + RX_MSDU_END_5_SA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_13_SA_IDX_OFFSET)), \ + RX_MSDU_END_13_SA_IDX_MASK, \ + RX_MSDU_END_13_SA_IDX_LSB)) + +#define HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_L3_HEADER_PADDING_OFFSET)), \ + RX_MSDU_END_5_L3_HEADER_PADDING_MASK, \ + RX_MSDU_END_5_L3_HEADER_PADDING_LSB)) + +#define HAL_RX_MPDU_ENCRYPTION_INFO_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_OFFSET)), \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_MASK, \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_LSB)) + +#define HAL_RX_MPDU_PN_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_4_PN_31_0_OFFSET)), \ + RX_MPDU_INFO_4_PN_31_0_MASK, \ + RX_MPDU_INFO_4_PN_31_0_LSB)) + +#define HAL_RX_MPDU_PN_63_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_5_PN_63_32_OFFSET)), \ + RX_MPDU_INFO_5_PN_63_32_MASK, \ + RX_MPDU_INFO_5_PN_63_32_LSB)) + +#define HAL_RX_MPDU_PN_95_64_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_6_PN_95_64_OFFSET)), \ + RX_MPDU_INFO_6_PN_95_64_MASK, \ + RX_MPDU_INFO_6_PN_95_64_LSB)) + +#define HAL_RX_MPDU_PN_127_96_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_7_PN_127_96_OFFSET)), \ + RX_MPDU_INFO_7_PN_127_96_MASK, \ + RX_MPDU_INFO_7_PN_127_96_LSB)) + +#define HAL_RX_MSDU_END_FIRST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FIRST_MSDU_OFFSET)), \ + RX_MSDU_END_5_FIRST_MSDU_MASK, \ + RX_MSDU_END_5_FIRST_MSDU_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_DA_IS_VALID_OFFSET)), \ + RX_MSDU_END_5_DA_IS_VALID_MASK, \ + RX_MSDU_END_5_DA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_LAST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_LAST_MSDU_OFFSET)), \ + RX_MSDU_END_5_LAST_MSDU_MASK, \ + RX_MSDU_END_5_LAST_MSDU_LSB)) + +#define HAL_RX_MPDU_GET_MAC_AD4_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_SW_PEER_ID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_1_SW_PEER_ID_OFFSET)), \ + RX_MPDU_INFO_1_SW_PEER_ID_MASK, \ + RX_MPDU_INFO_1_SW_PEER_ID_LSB)) + +#define HAL_RX_MPDU_GET_TODS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_TO_DS_OFFSET)), \ + RX_MPDU_INFO_2_TO_DS_MASK, \ + RX_MPDU_INFO_2_TO_DS_LSB)) + +#define HAL_RX_MPDU_GET_FROMDS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_FR_DS_OFFSET)), \ + RX_MPDU_INFO_2_FR_DS_MASK, \ + RX_MPDU_INFO_2_FR_DS_LSB)) + +#define HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_LSB)) + +#define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_MASK, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_LSB)) + +#define HAL_RX_MPDU_AD1_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_LSB)) + +#define HAL_RX_MPDU_AD2_15_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_LSB)) + +#define HAL_RX_MPDU_AD2_47_16_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_OFFSET)), \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_MASK, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_LSB)) + +#define HAL_RX_MPDU_AD3_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_OFFSET)), \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_MASK, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_LSB)) + +#define HAL_RX_MPDU_AD3_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_OFFSET)), \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_MASK, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_AD4_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_OFFSET)), \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_MASK, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_LSB)) + +#define HAL_RX_MPDU_AD4_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_OFFSET)), \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_MASK, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_LSB)) + +#define HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_LSB)) + #define HAL_RX_MSDU_START_MIMO_SS_BITMAP(_rx_msdu_start)\ (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\ RX_MSDU_START_5_MIMO_SS_BITMAP_OFFSET)), \ RX_MSDU_START_5_MIMO_SS_BITMAP_MASK, \ RX_MSDU_START_5_MIMO_SS_BITMAP_LSB)) +#define HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_16_SA_SW_PEER_ID_OFFSET)), \ + RX_MSDU_END_16_SA_SW_PEER_ID_MASK, \ + RX_MSDU_END_16_SA_SW_PEER_ID_LSB)) + +#define HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va) \ + (uint8_t *)(link_desc_va) + \ + RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET + +#define HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0) \ + (uint8_t *)(msdu0) + \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET + +#define HAL_ENT_MPDU_DESC_INFO(ent_ring_desc) \ + (uint8_t *)(ent_ring_desc) + \ + RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET + +#define HAL_DST_MPDU_DESC_INFO(dst_ring_desc) \ + (uint8_t *)(dst_ring_desc) + \ + REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET + +#define HAL_RX_GET_FC_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MPDU_FRAME_CONTROL_VALID) + +#define HAL_RX_GET_TO_DS_FLAG(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, TO_DS) + +#define HAL_RX_GET_MAC_ADDR1_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MAC_ADDR_AD1_VALID) + +#define HAL_RX_GET_MAC_ADDR2_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MAC_ADDR_AD2_VALID) + +#define HAL_RX_GET_FILTER_CATEGORY(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, RXPCU_MPDU_FILTER_IN_CATEGORY) + +#define HAL_RX_GET_PPDU_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, PHY_PPDU_ID) + +#define HAL_RX_GET_SW_FRAME_GROUP_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, SW_FRAME_GROUP_ID) + +#define HAL_REO_R0_CONFIG(soc, reg_val, reo_params) \ + do { \ + reg_val &= \ + ~(HWIO_REO_R0_GENERAL_ENABLE_FRAGMENT_DEST_RING_BMSK |\ + HWIO_REO_R0_GENERAL_ENABLE_AGING_LIST_ENABLE_BMSK | \ + HWIO_REO_R0_GENERAL_ENABLE_AGING_FLUSH_ENABLE_BMSK); \ + reg_val |= \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + FRAGMENT_DEST_RING, \ + (reo_params)->frag_dst_ring) | \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_LIST_ENABLE, 1) |\ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_FLUSH_ENABLE, 1);\ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ + reg_val = \ + HAL_REG_READ((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET)); \ + reg_val &= \ + (~HWIO_REO_R0_GENERAL_ENABLE_BAR_DEST_RING_BMSK |\ + (REO_REMAP_TCL << HWIO_REO_R0_GENERAL_ENABLE_BAR_DEST_RING_SHFT)); \ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ + } while (0) + +#define HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr) \ + ((struct rx_msdu_desc_info *) \ + _OFFSET_TO_BYTE_PTR(msdu_details_ptr, \ +UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET)) + +#define HAL_RX_LINK_DESC_MSDU0_PTR(link_desc) \ + ((struct rx_msdu_details *) \ + _OFFSET_TO_BYTE_PTR((link_desc),\ + UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET)) + +#define HAL_RX_MSDU_END_FLOW_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_14_FLOW_IDX_OFFSET)), \ + RX_MSDU_END_14_FLOW_IDX_MASK, \ + RX_MSDU_END_14_FLOW_IDX_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FLOW_IDX_INVALID_OFFSET)), \ + RX_MSDU_END_5_FLOW_IDX_INVALID_MASK, \ + RX_MSDU_END_5_FLOW_IDX_INVALID_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_OFFSET)), \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_MASK, \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_LSB)) + +#define HAL_RX_MSDU_END_FSE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_15_FSE_METADATA_OFFSET)), \ + RX_MSDU_END_15_FSE_METADATA_MASK, \ + RX_MSDU_END_15_FSE_METADATA_LSB)) + +#define HAL_RX_MSDU_END_CCE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_16_CCE_METADATA_OFFSET)), \ + RX_MSDU_END_16_CCE_METADATA_MASK, \ + RX_MSDU_END_16_CCE_METADATA_LSB)) + +#define HAL_RX_TLV_GET_TCP_CHKSUM(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_OFFSET)), \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_MASK, \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_LSB)) /* * hal_rx_msdu_start_nss_get_6390(): API to get the NSS * Interval from rx_msdu_start diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390_tx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390_tx.h index b827d4add7c630e1984929f2bcfbb56ccf267572..ddd25873247bbfd39c847025dba587727c94fb75 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390_tx.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6390/hal_6390_tx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 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 @@ -57,7 +57,7 @@ static void hal_tx_desc_set_dscp_tid_table_id_6390(void *desc, uint8_t id) * * Return: none */ -static void hal_tx_set_dscp_tid_map_6390(void *hal_soc, uint8_t *map, +static void hal_tx_set_dscp_tid_map_6390(struct hal_soc *soc, uint8_t *map, uint8_t id) { int i; @@ -65,8 +65,6 @@ static void hal_tx_set_dscp_tid_map_6390(void *hal_soc, uint8_t *map, uint32_t value = 0, regval; uint8_t val[DSCP_TID_TABLE_SIZE], cnt = 0; - struct hal_soc *soc = (struct hal_soc *)hal_soc; - if (id >= HAL_MAX_HW_DSCP_TID_MAPS_11AX) return; @@ -95,7 +93,7 @@ static void hal_tx_set_dscp_tid_map_6390(void *hal_soc, uint8_t *map, (map[i + 6] << 0x12) | (map[i + 7] << 0x15)); - qdf_mem_copy(&val[cnt], (void *)&value, 3); + qdf_mem_copy(&val[cnt], &value, 3); cnt += 3; } @@ -124,14 +122,13 @@ static void hal_tx_set_dscp_tid_map_6390(void *hal_soc, uint8_t *map, * * Return: void */ -static void hal_tx_update_dscp_tid_6390(void *hal_soc, uint8_t tid, +static void hal_tx_update_dscp_tid_6390(struct hal_soc *soc, uint8_t tid, uint8_t id, uint8_t dscp) { int index; uint32_t addr; uint32_t value; uint32_t regval; - struct hal_soc *soc = (struct hal_soc *)hal_soc; addr = HWIO_TCL_R0_DSCP_TID_MAP_n_ADDR( SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET, id); diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6490/hal_6490.c b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6490/hal_6490.c new file mode 100644 index 0000000000000000000000000000000000000000..6124a42d9dfd725cf83a94f897118700596ea3eb --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6490/hal_6490.c @@ -0,0 +1,2054 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "qdf_types.h" +#include "qdf_util.h" +#include "qdf_types.h" +#include "qdf_lock.h" +#include "qdf_mem.h" +#include "qdf_nbuf.h" +#include "hal_hw_headers.h" +#include "hal_internal.h" +#include "hal_api.h" +#include "target_type.h" +#include "wcss_version.h" +#include "qdf_module.h" + +#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_OFFSET \ + RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_OFFSET +#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_MASK \ + RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_MASK +#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_LSB \ + RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_LSB +#define UNIFIED_PHYRX_HT_SIG_0_HT_SIG_INFO_PHYRX_HT_SIG_INFO_DETAILS_OFFSET \ + PHYRX_L_SIG_B_0_PHYRX_L_SIG_B_INFO_DETAILS_RATE_OFFSET +#define UNIFIED_PHYRX_L_SIG_B_0_L_SIG_B_INFO_PHYRX_L_SIG_B_INFO_DETAILS_OFFSET \ + PHYRX_L_SIG_B_0_PHYRX_L_SIG_B_INFO_DETAILS_RATE_OFFSET +#define UNIFIED_PHYRX_L_SIG_A_0_L_SIG_A_INFO_PHYRX_L_SIG_A_INFO_DETAILS_OFFSET \ + PHYRX_L_SIG_A_0_PHYRX_L_SIG_A_INFO_DETAILS_RATE_OFFSET +#define UNIFIED_PHYRX_VHT_SIG_A_0_VHT_SIG_A_INFO_PHYRX_VHT_SIG_A_INFO_DETAILS_OFFSET \ + PHYRX_VHT_SIG_A_0_PHYRX_VHT_SIG_A_INFO_DETAILS_BANDWIDTH_OFFSET +#define UNIFIED_PHYRX_HE_SIG_A_SU_0_HE_SIG_A_SU_INFO_PHYRX_HE_SIG_A_SU_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_A_SU_0_PHYRX_HE_SIG_A_SU_INFO_DETAILS_FORMAT_INDICATION_OFFSET +#define UNIFIED_PHYRX_HE_SIG_A_MU_DL_0_HE_SIG_A_MU_DL_INFO_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_A_MU_DL_0_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS_DL_UL_FLAG_OFFSET +#define UNIFIED_PHYRX_HE_SIG_B1_MU_0_HE_SIG_B1_MU_INFO_PHYRX_HE_SIG_B1_MU_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_B1_MU_0_PHYRX_HE_SIG_B1_MU_INFO_DETAILS_RU_ALLOCATION_OFFSET +#define UNIFIED_PHYRX_HE_SIG_B2_MU_0_HE_SIG_B2_MU_INFO_PHYRX_HE_SIG_B2_MU_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_B2_MU_0_PHYRX_HE_SIG_B2_MU_INFO_DETAILS_STA_ID_OFFSET +#define UNIFIED_PHYRX_HE_SIG_B2_OFDMA_0_HE_SIG_B2_OFDMA_INFO_PHYRX_HE_SIG_B2_OFDMA_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_B2_OFDMA_0_PHYRX_HE_SIG_B2_OFDMA_INFO_DETAILS_STA_ID_OFFSET + +#define UNIFIED_PHYRX_RSSI_LEGACY_3_RECEIVE_RSSI_INFO_PRE_RSSI_INFO_DETAILS_OFFSET \ + PHYRX_RSSI_LEGACY_3_RECEIVE_RSSI_INFO_PRE_RSSI_INFO_DETAILS_OFFSET +#define UNIFIED_PHYRX_RSSI_LEGACY_19_RECEIVE_RSSI_INFO_PREAMBLE_RSSI_INFO_DETAILS_OFFSET \ + PHYRX_RSSI_LEGACY_19_PREAMBLE_RSSI_INFO_DETAILS_RSSI_PRI20_CHAIN0_OFFSET +#define UNIFIED_RX_MPDU_START_0_RX_MPDU_INFO_RX_MPDU_INFO_DETAILS_OFFSET \ + RX_MPDU_START_0_RX_MPDU_INFO_DETAILS_RXPT_CLASSIFY_INFO_DETAILS_REO_DESTINATION_INDICATION_OFFSET +#define UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET \ + RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET +#define UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET +#define UNIFIED_RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET \ + RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET +#define UNIFIED_REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET \ + REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET +#define UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC \ + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER +#define UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET +#define UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET \ + RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET +#define UNIFIED_TCL_DATA_CMD_0_BUFFER_ADDR_INFO_BUF_ADDR_INFO_OFFSET \ + TCL_DATA_CMD_0_BUF_ADDR_INFO_BUFFER_ADDR_31_0_OFFSET +#define UNIFIED_TCL_DATA_CMD_1_BUFFER_ADDR_INFO_BUF_ADDR_INFO_OFFSET \ + TCL_DATA_CMD_1_BUF_ADDR_INFO_BUFFER_ADDR_39_32_OFFSET +#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_OFFSET \ + TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_OFFSET +#define UNIFIED_BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_LSB \ + BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_LSB +#define UNIFIED_BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_MASK \ + BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_MASK +#define UNIFIED_BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_LSB \ + BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_LSB +#define UNIFIED_BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_MASK \ + BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_MASK +#define UNIFIED_BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_LSB \ + BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_LSB +#define UNIFIED_BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_MASK \ + BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_MASK +#define UNIFIED_BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_LSB \ + BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_LSB +#define UNIFIED_BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_MASK \ + BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_MASK +#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_LSB \ + TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_LSB +#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_MASK \ + TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_MASK +#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_MASK \ + WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_MASK +#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_OFFSET \ + WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_OFFSET +#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_LSB \ + WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_LSB + +#include "hal_6490_tx.h" +#include "hal_6490_rx.h" +#include +#include + +/* + * hal_rx_msdu_start_nss_get_6490(): API to get the NSS + * Interval from rx_msdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(nss) + */ +static uint32_t +hal_rx_msdu_start_nss_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_start *msdu_start = + &pkt_tlvs->msdu_start_tlv.rx_msdu_start; + uint8_t mimo_ss_bitmap; + + mimo_ss_bitmap = HAL_RX_MSDU_START_MIMO_SS_BITMAP(msdu_start); + + return qdf_get_hweight8(mimo_ss_bitmap); +} + +/** + * hal_rx_mon_hw_desc_get_mpdu_status_6490(): Retrieve MPDU status + * + * @ hw_desc_addr: Start address of Rx HW TLVs + * @ rs: Status for monitor mode + * + * Return: void + */ +static void hal_rx_mon_hw_desc_get_mpdu_status_6490(void *hw_desc_addr, + struct mon_rx_status *rs) +{ + struct rx_msdu_start *rx_msdu_start; + struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + uint32_t reg_value; + const uint32_t sgi_hw_to_cdp[] = { + CDP_SGI_0_8_US, + CDP_SGI_0_4_US, + CDP_SGI_1_6_US, + CDP_SGI_3_2_US, + }; + + rx_msdu_start = &rx_desc->msdu_start_tlv.rx_msdu_start; + + HAL_RX_GET_MSDU_AGGREGATION(rx_desc, rs); + + rs->ant_signal_db = HAL_RX_GET(rx_msdu_start, + RX_MSDU_START_5, USER_RSSI); + rs->is_stbc = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, STBC); + + reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, SGI); + rs->sgi = sgi_hw_to_cdp[reg_value]; + + reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEPTION_TYPE); + rs->beamformed = (reg_value == HAL_RX_RECEPTION_TYPE_MU_MIMO) ? 1 : 0; + /* TODO: rs->beamformed should be set for SU beamforming also */ +} + +#define LINK_DESC_SIZE (NUM_OF_DWORDS_RX_MSDU_LINK << 2) + +static uint32_t hal_get_link_desc_size_6490(void) +{ + return LINK_DESC_SIZE; +} + +/* + * hal_rx_get_tlv_6490(): API to get the tlv + * + * @rx_tlv: TLV data extracted from the rx packet + * Return: uint8_t + */ +static uint8_t hal_rx_get_tlv_6490(void *rx_tlv) +{ + return HAL_RX_GET(rx_tlv, PHYRX_RSSI_LEGACY_0, RECEIVE_BANDWIDTH); +} + +/** + * hal_rx_proc_phyrx_other_receive_info_tlv_6490() + * - process other receive info TLV + * @rx_tlv_hdr: pointer to TLV header + * @ppdu_info: pointer to ppdu_info + * + * Return: None + */ +static +void hal_rx_proc_phyrx_other_receive_info_tlv_6490(void *rx_tlv_hdr, + void *ppdu_info_handle) +{ + uint32_t tlv_tag, tlv_len; + uint32_t temp_len, other_tlv_len, other_tlv_tag; + void *rx_tlv = (uint8_t *)rx_tlv_hdr + HAL_RX_TLV32_HDR_SIZE; + void *other_tlv_hdr = NULL; + void *other_tlv = NULL; + + tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv_hdr); + tlv_len = HAL_RX_GET_USER_TLV32_LEN(rx_tlv_hdr); + temp_len = 0; + + other_tlv_hdr = rx_tlv + HAL_RX_TLV32_HDR_SIZE; + + other_tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(other_tlv_hdr); + other_tlv_len = HAL_RX_GET_USER_TLV32_LEN(other_tlv_hdr); + temp_len += other_tlv_len; + other_tlv = other_tlv_hdr + HAL_RX_TLV32_HDR_SIZE; + + switch (other_tlv_tag) { + default: + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "%s unhandled TLV type: %d, TLV len:%d", + __func__, other_tlv_tag, other_tlv_len); + break; + } +} + +/** + * hal_rx_dump_msdu_start_tlv_6490() : dump RX msdu_start TLV in structured + * human readable format. + * @ msdu_start: pointer the msdu_start TLV in pkt. + * @ dbg_level: log level. + * + * Return: void + */ +static void hal_rx_dump_msdu_start_tlv_6490(void *msdustart, uint8_t dbg_level) +{ + struct rx_msdu_start *msdu_start = (struct rx_msdu_start *)msdustart; + + __QDF_TRACE_RL(dbg_level, QDF_MODULE_ID_DP, + "rx_msdu_start tlv (1/2) - " + "rxpcu_mpdu_filter_in_category: %x " + "sw_frame_group_id: %x " + "phy_ppdu_id: %x " + "msdu_length: %x " + "ipsec_esp: %x " + "l3_offset: %x " + "ipsec_ah: %x " + "l4_offset: %x " + "msdu_number: %x " + "decap_format: %x " + "ipv4_proto: %x " + "ipv6_proto: %x " + "tcp_proto: %x " + "udp_proto: %x " + "ip_frag: %x " + "tcp_only_ack: %x " + "da_is_bcast_mcast: %x " + "ip4_protocol_ip6_next_header: %x " + "toeplitz_hash_2_or_4: %x " + "flow_id_toeplitz: %x " + "user_rssi: %x " + "pkt_type: %x " + "stbc: %x " + "sgi: %x " + "rate_mcs: %x " + "receive_bandwidth: %x " + "reception_type: %x " + "ppdu_start_timestamp: %u ", + msdu_start->rxpcu_mpdu_filter_in_category, + msdu_start->sw_frame_group_id, + msdu_start->phy_ppdu_id, + msdu_start->msdu_length, + msdu_start->ipsec_esp, + msdu_start->l3_offset, + msdu_start->ipsec_ah, + msdu_start->l4_offset, + msdu_start->msdu_number, + msdu_start->decap_format, + msdu_start->ipv4_proto, + msdu_start->ipv6_proto, + msdu_start->tcp_proto, + msdu_start->udp_proto, + msdu_start->ip_frag, + msdu_start->tcp_only_ack, + msdu_start->da_is_bcast_mcast, + msdu_start->ip4_protocol_ip6_next_header, + msdu_start->toeplitz_hash_2_or_4, + msdu_start->flow_id_toeplitz, + msdu_start->user_rssi, + msdu_start->pkt_type, + msdu_start->stbc, + msdu_start->sgi, + msdu_start->rate_mcs, + msdu_start->receive_bandwidth, + msdu_start->reception_type, + msdu_start->ppdu_start_timestamp); + + __QDF_TRACE_RL(dbg_level, QDF_MODULE_ID_DP, + "rx_msdu_start tlv (2/2) - " + "sw_phy_meta_data: %x ", + msdu_start->sw_phy_meta_data); +} + +/** + * hal_rx_dump_msdu_end_tlv_6490: dump RX msdu_end TLV in structured + * human readable format. + * @ msdu_end: pointer the msdu_end TLV in pkt. + * @ dbg_level: log level. + * + * Return: void + */ +static void hal_rx_dump_msdu_end_tlv_6490(void *msduend, + uint8_t dbg_level) +{ + struct rx_msdu_end *msdu_end = (struct rx_msdu_end *)msduend; + + __QDF_TRACE_RL(dbg_level, QDF_MODULE_ID_DP, + "rx_msdu_end tlv (1/3) - " + "rxpcu_mpdu_filter_in_category: %x " + "sw_frame_group_id: %x " + "phy_ppdu_id: %x " + "ip_hdr_chksum: %x " + "tcp_udp_chksum: %x " + "key_id_octet: %x " + "cce_super_rule: %x " + "cce_classify_not_done_truncat: %x " + "cce_classify_not_done_cce_dis: %x " + "ext_wapi_pn_63_48: %x " + "ext_wapi_pn_95_64: %x " + "ext_wapi_pn_127_96: %x " + "reported_mpdu_length: %x " + "first_msdu: %x " + "last_msdu: %x " + "sa_idx_timeout: %x " + "da_idx_timeout: %x " + "msdu_limit_error: %x " + "flow_idx_timeout: %x " + "flow_idx_invalid: %x " + "wifi_parser_error: %x " + "amsdu_parser_error: %x", + msdu_end->rxpcu_mpdu_filter_in_category, + msdu_end->sw_frame_group_id, + msdu_end->phy_ppdu_id, + msdu_end->ip_hdr_chksum, + msdu_end->tcp_udp_chksum, + msdu_end->key_id_octet, + msdu_end->cce_super_rule, + msdu_end->cce_classify_not_done_truncate, + msdu_end->cce_classify_not_done_cce_dis, + msdu_end->ext_wapi_pn_63_48, + msdu_end->ext_wapi_pn_95_64, + msdu_end->ext_wapi_pn_127_96, + msdu_end->reported_mpdu_length, + msdu_end->first_msdu, + msdu_end->last_msdu, + msdu_end->sa_idx_timeout, + msdu_end->da_idx_timeout, + msdu_end->msdu_limit_error, + msdu_end->flow_idx_timeout, + msdu_end->flow_idx_invalid, + msdu_end->wifi_parser_error, + msdu_end->amsdu_parser_error); + + __QDF_TRACE_RL(dbg_level, QDF_MODULE_ID_DP, + "rx_msdu_end tlv (2/3)- " + "sa_is_valid: %x " + "da_is_valid: %x " + "da_is_mcbc: %x " + "l3_header_padding: %x " + "ipv6_options_crc: %x " + "tcp_seq_number: %x " + "tcp_ack_number: %x " + "tcp_flag: %x " + "lro_eligible: %x " + "window_size: %x " + "da_offset: %x " + "sa_offset: %x " + "da_offset_valid: %x " + "sa_offset_valid: %x " + "rule_indication_31_0: %x " + "rule_indication_63_32: %x " + "sa_idx: %x " + "da_idx: %x " + "msdu_drop: %x " + "reo_destination_indication: %x " + "flow_idx: %x " + "fse_metadata: %x " + "cce_metadata: %x " + "sa_sw_peer_id: %x ", + msdu_end->sa_is_valid, + msdu_end->da_is_valid, + msdu_end->da_is_mcbc, + msdu_end->l3_header_padding, + msdu_end->ipv6_options_crc, + msdu_end->tcp_seq_number, + msdu_end->tcp_ack_number, + msdu_end->tcp_flag, + msdu_end->lro_eligible, + msdu_end->window_size, + msdu_end->da_offset, + msdu_end->sa_offset, + msdu_end->da_offset_valid, + msdu_end->sa_offset_valid, + msdu_end->rule_indication_31_0, + msdu_end->rule_indication_63_32, + msdu_end->sa_idx, + msdu_end->da_idx_or_sw_peer_id, + msdu_end->msdu_drop, + msdu_end->reo_destination_indication, + msdu_end->flow_idx, + msdu_end->fse_metadata, + msdu_end->cce_metadata, + msdu_end->sa_sw_peer_id); + __QDF_TRACE_RL(dbg_level, QDF_MODULE_ID_DP, + "rx_msdu_end tlv (3/3)" + "aggregation_count %x " + "flow_aggregation_continuation %x " + "fisa_timeout %x " + "cumulative_l4_checksum %x " + "cumulative_ip_length %x", + msdu_end->aggregation_count, + msdu_end->flow_aggregation_continuation, + msdu_end->fisa_timeout, + msdu_end->cumulative_l4_checksum, + msdu_end->cumulative_ip_length); +} + +/* + * Get tid from RX_MPDU_START + */ +#define HAL_RX_MPDU_INFO_TID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_7_TID_OFFSET)), \ + RX_MPDU_INFO_7_TID_MASK, \ + RX_MPDU_INFO_7_TID_LSB)) + +static uint32_t hal_rx_mpdu_start_tid_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint32_t tid; + + tid = HAL_RX_MPDU_INFO_TID_GET(&mpdu_start->rx_mpdu_info_details); + + return tid; +} + +#define HAL_RX_MSDU_START_RECEPTION_TYPE_GET(_rx_msdu_start) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start), \ + RX_MSDU_START_5_RECEPTION_TYPE_OFFSET)), \ + RX_MSDU_START_5_RECEPTION_TYPE_MASK, \ + RX_MSDU_START_5_RECEPTION_TYPE_LSB)) + +/* + * hal_rx_msdu_start_reception_type_get(): API to get the reception type + * Interval from rx_msdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(reception_type) + */ +static +uint32_t hal_rx_msdu_start_reception_type_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_start *msdu_start = + &pkt_tlvs->msdu_start_tlv.rx_msdu_start; + uint32_t reception_type; + + reception_type = HAL_RX_MSDU_START_RECEPTION_TYPE_GET(msdu_start); + + return reception_type; +} + +/** + * hal_rx_msdu_end_da_idx_get_6490: API to get da_idx + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da index + */ +static uint16_t hal_rx_msdu_end_da_idx_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint16_t da_idx; + + da_idx = HAL_RX_MSDU_END_DA_IDX_GET(msdu_end); + + return da_idx; +} +/** + * hal_rx_get_rx_fragment_number_6490(): Function to retrieve rx fragment number + * + * @nbuf: Network buffer + * Returns: rx fragment number + */ +static +uint8_t hal_rx_get_rx_fragment_number_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + /* Return first 4 bits as fragment number */ + return (HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info) & + DOT11_SEQ_FRAG_MASK); +} + +/** + * hal_rx_msdu_end_da_is_mcbc_get_6490(): API to check if pkt is MCBC + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_mcbc + */ +static uint8_t +hal_rx_msdu_end_da_is_mcbc_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_DA_IS_MCBC_GET(msdu_end); +} + +/** + * hal_rx_msdu_end_sa_is_valid_get_6490(): API to get_6490 the + * sa_is_valid bit from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_is_valid bit + */ +static uint8_t +hal_rx_msdu_end_sa_is_valid_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t sa_is_valid; + + sa_is_valid = HAL_RX_MSDU_END_SA_IS_VALID_GET(msdu_end); + + return sa_is_valid; +} + +/** + * hal_rx_msdu_end_sa_idx_get_6490(): API to get_6490 the + * sa_idx from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_idx (SA AST index) + */ +static +uint16_t hal_rx_msdu_end_sa_idx_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint16_t sa_idx; + + sa_idx = HAL_RX_MSDU_END_SA_IDX_GET(msdu_end); + + return sa_idx; +} + +/** + * hal_rx_desc_is_first_msdu_6490() - Check if first msdu + * + * @hal_soc_hdl: hal_soc handle + * @hw_desc_addr: hardware descriptor address + * + * Return: 0 - success/ non-zero failure + */ +static uint32_t hal_rx_desc_is_first_msdu_6490(void *hw_desc_addr) +{ + struct rx_pkt_tlvs *rx_tlvs = (struct rx_pkt_tlvs *)hw_desc_addr; + struct rx_msdu_end *msdu_end = &rx_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_GET(msdu_end, RX_MSDU_END_10, FIRST_MSDU); +} + +/** + * hal_rx_msdu_end_l3_hdr_padding_get_6490(): API to get_6490 the + * l3_header padding from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: number of l3 header padding bytes + */ +static uint32_t hal_rx_msdu_end_l3_hdr_padding_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint32_t l3_header_padding; + + l3_header_padding = HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(msdu_end); + + return l3_header_padding; +} + +/* + * @ hal_rx_encryption_info_valid_6490: Returns encryption type. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: encryption type + */ +static uint32_t hal_rx_encryption_info_valid_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + uint32_t encryption_info = HAL_RX_MPDU_ENCRYPTION_INFO_VALID(mpdu_info); + + return encryption_info; +} + +/* + * @ hal_rx_print_pn_6490: Prints the PN of rx packet. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: void + */ +static void hal_rx_print_pn_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + uint32_t pn_31_0 = HAL_RX_MPDU_PN_31_0_GET(mpdu_info); + uint32_t pn_63_32 = HAL_RX_MPDU_PN_63_32_GET(mpdu_info); + uint32_t pn_95_64 = HAL_RX_MPDU_PN_95_64_GET(mpdu_info); + uint32_t pn_127_96 = HAL_RX_MPDU_PN_127_96_GET(mpdu_info); + + hal_debug("PN number pn_127_96 0x%x pn_95_64 0x%x pn_63_32 0x%x pn_31_0 0x%x ", + pn_127_96, pn_95_64, pn_63_32, pn_31_0); +} + +/** + * hal_rx_msdu_end_first_msdu_get_6490: API to get first msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: first_msdu + */ +static uint8_t hal_rx_msdu_end_first_msdu_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t first_msdu; + + first_msdu = HAL_RX_MSDU_END_FIRST_MSDU_GET(msdu_end); + + return first_msdu; +} + +/** + * hal_rx_msdu_end_da_is_valid_get_6490: API to check if da is valid + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_valid + */ +static uint8_t hal_rx_msdu_end_da_is_valid_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t da_is_valid; + + da_is_valid = HAL_RX_MSDU_END_DA_IS_VALID_GET(msdu_end); + + return da_is_valid; +} + +/** + * hal_rx_msdu_end_last_msdu_get_6490: API to get last msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: last_msdu + */ +static uint8_t hal_rx_msdu_end_last_msdu_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t last_msdu; + + last_msdu = HAL_RX_MSDU_END_LAST_MSDU_GET(msdu_end); + + return last_msdu; +} + +/* + * hal_rx_get_mpdu_mac_ad4_valid_6490(): Retrieves if mpdu 4th addr is valid + * + * @nbuf: Network buffer + * Returns: value of mpdu 4th address valid field + */ +static bool hal_rx_get_mpdu_mac_ad4_valid_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + bool ad4_valid = 0; + + ad4_valid = HAL_RX_MPDU_GET_MAC_AD4_VALID(rx_mpdu_info); + + return ad4_valid; +} + +/** + * hal_rx_mpdu_start_sw_peer_id_get_6490: Retrieve sw peer_id + * @buf: network buffer + * + * Return: sw peer_id + */ +static uint32_t hal_rx_mpdu_start_sw_peer_id_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_SW_PEER_ID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/** + * hal_rx_mpdu_get_to_ds_6490(): API to get the tods info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(to_ds) + */ +static uint32_t hal_rx_mpdu_get_to_ds_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_TODS(mpdu_info); +} + +/* + * hal_rx_mpdu_get_fr_ds_6490(): API to get the from ds info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(fr_ds) + */ +static uint32_t hal_rx_mpdu_get_fr_ds_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_FROMDS(mpdu_info); +} + +/* + * hal_rx_get_mpdu_frame_control_valid_6490(): Retrieves mpdu + * frame control valid + * + * @nbuf: Network buffer + * Returns: value of frame control valid field + */ +static uint8_t hal_rx_get_mpdu_frame_control_valid_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(rx_mpdu_info); +} + +/* + * hal_rx_mpdu_get_addr1_6490(): API to check get address1 of the mpdu + * + * @buf: pointer to the start of RX PKT TLV headera + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr1_6490(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr1 { + uint32_t ad1_31_0; + uint16_t ad1_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr1 *addr = (struct hal_addr1 *)mac_addr; + uint32_t mac_addr_ad1_valid; + + mac_addr_ad1_valid = HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(mpdu_info); + + if (mac_addr_ad1_valid) { + addr->ad1_31_0 = HAL_RX_MPDU_AD1_31_0_GET(mpdu_info); + addr->ad1_47_32 = HAL_RX_MPDU_AD1_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr2_6490(): API to check get address2 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr2_6490(uint8_t *buf, + uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr2 { + uint16_t ad2_15_0; + uint32_t ad2_47_16; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr2 *addr = (struct hal_addr2 *)mac_addr; + uint32_t mac_addr_ad2_valid; + + mac_addr_ad2_valid = HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(mpdu_info); + + if (mac_addr_ad2_valid) { + addr->ad2_15_0 = HAL_RX_MPDU_AD2_15_0_GET(mpdu_info); + addr->ad2_47_16 = HAL_RX_MPDU_AD2_47_16_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr3_6490(): API to get address3 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr3_6490(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr3 { + uint32_t ad3_31_0; + uint16_t ad3_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr3 *addr = (struct hal_addr3 *)mac_addr; + uint32_t mac_addr_ad3_valid; + + mac_addr_ad3_valid = HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(mpdu_info); + + if (mac_addr_ad3_valid) { + addr->ad3_31_0 = HAL_RX_MPDU_AD3_31_0_GET(mpdu_info); + addr->ad3_47_32 = HAL_RX_MPDU_AD3_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr4_6490(): API to get address4 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr4_6490(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr4 { + uint32_t ad4_31_0; + uint16_t ad4_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr4 *addr = (struct hal_addr4 *)mac_addr; + uint32_t mac_addr_ad4_valid; + + mac_addr_ad4_valid = HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(mpdu_info); + + if (mac_addr_ad4_valid) { + addr->ad4_31_0 = HAL_RX_MPDU_AD4_31_0_GET(mpdu_info); + addr->ad4_47_32 = HAL_RX_MPDU_AD4_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_get_mpdu_sequence_control_valid_6490(): Get mpdu + * sequence control valid + * + * @nbuf: Network buffer + * Returns: value of sequence control valid field + */ +static uint8_t hal_rx_get_mpdu_sequence_control_valid_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(rx_mpdu_info); +} + +/** + * hal_rx_is_unicast_6490: check packet is unicast frame or not. + * + * @ buf: pointer to rx pkt TLV. + * + * Return: true on unicast. + */ +static bool hal_rx_is_unicast_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint32_t grp_id; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + + grp_id = (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_OFFSET)), + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_MASK, + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_LSB)); + + return (HAL_MPDU_SW_FRAME_GROUP_UNICAST_DATA == grp_id) ? true : false; +} + +/** + * hal_rx_tid_get_6490: get tid based on qos control valid. + * @hal_soc_hdl: hal_soc handle + * @ buf: pointer to rx pkt TLV. + * + * Return: tid + */ +static uint32_t hal_rx_tid_get_6490(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + uint8_t qos_control_valid = + (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_OFFSET)), + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_MASK, + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_LSB)); + + if (qos_control_valid) + return hal_rx_mpdu_start_tid_get_6490(buf); + + return HAL_RX_NON_QOS_TID; +} + +/** + * hal_rx_hw_desc_get_ppduid_get_6490(): retrieve ppdu id + * @hw_desc_addr: hw addr + * + * Return: ppdu id + */ +static uint32_t hal_rx_hw_desc_get_ppduid_get_6490(void *hw_desc_addr) +{ + struct rx_mpdu_info *rx_mpdu_info; + struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + + rx_mpdu_info = + &rx_desc->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + + return HAL_RX_GET(rx_mpdu_info, RX_MPDU_INFO_9, PHY_PPDU_ID); +} + +/** + * hal_reo_status_get_header_6490 - Process reo desc info + * @d - Pointer to reo descriptior + * @b - tlv type info + * @h1 - Pointer to hal_reo_status_header where info to be stored + * + * Return - none. + * + */ +static void hal_reo_status_get_header_6490(uint32_t *d, int b, void *h1) +{ + uint32_t val1 = 0; + struct hal_reo_status_header *h = + (struct hal_reo_status_header *)h1; + + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->cmd_num = + HAL_GET_FIELD( + UNIFORM_REO_STATUS_HEADER_0, REO_STATUS_NUMBER, + val1); + h->exec_time = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + CMD_EXECUTION_TIME, val1); + h->status = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + REO_CMD_EXECUTION_STATUS, val1); + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->tstamp = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_1, TIMESTAMP, val1); +} + +/** + * hal_tx_desc_set_mesh_en_6490 - Set mesh_enable flag in Tx descriptor + * @desc: Handle to Tx Descriptor + * @en: For raw WiFi frames, this indicates transmission to a mesh STA, + * enabling the interpretation of the 'Mesh Control Present' bit + * (bit 8) of QoS Control (otherwise this bit is ignored), + * For native WiFi frames, this indicates that a 'Mesh Control' field + * is present between the header and the LLC. + * + * Return: void + */ +static inline +void hal_tx_desc_set_mesh_en_6490(void *desc, uint8_t en) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_5, MESH_ENABLE) |= + HAL_TX_SM(TCL_DATA_CMD_5, MESH_ENABLE, en); +} + +static +void *hal_rx_msdu0_buffer_addr_lsb_6490(void *link_desc_va) +{ + return (void *)HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va); +} + +static +void *hal_rx_msdu_desc_info_ptr_get_6490(void *msdu0) +{ + return (void *)HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0); +} + +static +void *hal_ent_mpdu_desc_info_6490(void *ent_ring_desc) +{ + return (void *)HAL_ENT_MPDU_DESC_INFO(ent_ring_desc); +} + +static +void *hal_dst_mpdu_desc_info_6490(void *dst_ring_desc) +{ + return (void *)HAL_DST_MPDU_DESC_INFO(dst_ring_desc); +} + +static +uint8_t hal_rx_get_fc_valid_6490(uint8_t *buf) +{ + return HAL_RX_GET_FC_VALID(buf); +} + +static uint8_t hal_rx_get_to_ds_flag_6490(uint8_t *buf) +{ + return HAL_RX_GET_TO_DS_FLAG(buf); +} + +static uint8_t hal_rx_get_mac_addr2_valid_6490(uint8_t *buf) +{ + return HAL_RX_GET_MAC_ADDR2_VALID(buf); +} + +static uint8_t hal_rx_get_filter_category_6490(uint8_t *buf) +{ + return HAL_RX_GET_FILTER_CATEGORY(buf); +} + +static uint32_t +hal_rx_get_ppdu_id_6490(uint8_t *buf) +{ + return HAL_RX_GET_PPDU_ID(buf); +} + +/** + * hal_reo_config_6490(): Set reo config parameters + * @soc: hal soc handle + * @reg_val: value to be set + * @reo_params: reo parameters + * + * Return: void + */ +static +void hal_reo_config_6490(struct hal_soc *soc, + uint32_t reg_val, + struct hal_reo_params *reo_params) +{ + HAL_REO_R0_CONFIG(soc, reg_val, reo_params); +} + +/** + * hal_rx_msdu_desc_info_get_ptr_6490() - Get msdu desc info ptr + * @msdu_details_ptr - Pointer to msdu_details_ptr + * + * Return - Pointer to rx_msdu_desc_info structure. + * + */ +static void *hal_rx_msdu_desc_info_get_ptr_6490(void *msdu_details_ptr) +{ + return HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr); +} + +/** + * hal_rx_link_desc_msdu0_ptr_6490 - Get pointer to rx_msdu details + * @link_desc - Pointer to link desc + * + * Return - Pointer to rx_msdu_details structure + * + */ +static void *hal_rx_link_desc_msdu0_ptr_6490(void *link_desc) +{ + return HAL_RX_LINK_DESC_MSDU0_PTR(link_desc); +} + +/** + * hal_rx_msdu_flow_idx_get_6490: API to get flow index + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index value from MSDU END TLV + */ +static inline uint32_t hal_rx_msdu_flow_idx_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_msdu_get_reo_destination_indication_6490: API to get + * reo_destination_indication from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * @reo_destination_indication: pointer to return value of reo_destination_indication + * + * Return: none + */ +static inline void +hal_rx_msdu_get_reo_destination_indication_6490(uint8_t *buf, + uint32_t *reo_destination_indication) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + *reo_destination_indication = HAL_RX_MSDU_END_REO_DEST_IND_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_invalid_6490: API to get flow index invalid + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index invalid value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_invalid_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_timeout_6490: API to get flow index timeout + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index timeout value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_timeout_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); +} + +/** + * hal_rx_msdu_fse_metadata_get_6490: API to get FSE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: fse metadata value from MSDU END TLV + */ +static uint32_t hal_rx_msdu_fse_metadata_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FSE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_cce_metadata_get_6490: API to get CCE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: cce_metadata + */ +static uint16_t +hal_rx_msdu_cce_metadata_get_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_CCE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_get_flow_params_6490: API to get flow index, flow index invalid + * and flow index timeout from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * @flow_invalid: pointer to return value of flow_idx_valid + * @flow_timeout: pointer to return value of flow_idx_timeout + * @flow_index: pointer to return value of flow_idx + * + * Return: none + */ +static inline void +hal_rx_msdu_get_flow_params_6490(uint8_t *buf, + bool *flow_invalid, + bool *flow_timeout, + uint32_t *flow_index) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + *flow_invalid = HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); + *flow_timeout = HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); + *flow_index = HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_tlv_get_tcp_chksum_6490() - API to get tcp checksum + * @buf: rx_tlv_hdr + * + * Return: tcp checksum + */ +static uint16_t +hal_rx_tlv_get_tcp_chksum_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_TCP_CHKSUM(buf); +} + +/** + * hal_rx_get_rx_sequence_6490(): Function to retrieve rx sequence number + * + * @nbuf: Network buffer + * Returns: rx sequence number + */ +static +uint16_t hal_rx_get_rx_sequence_6490(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info); +} + +/** + * hal_get_window_address_6490(): Function to get hp/tp address + * @hal_soc: Pointer to hal_soc + * @addr: address offset of register + * + * Return: modified address offset of register + */ +static inline qdf_iomem_t hal_get_window_address_6490(struct hal_soc *hal_soc, + qdf_iomem_t addr) +{ + return addr; +} + +/** + * hal_rx_get_fisa_cumulative_l4_checksum_6490() - Retrieve cumulative + * checksum + * @buf: buffer pointer + * + * Return: cumulative checksum + */ +static inline +uint16_t hal_rx_get_fisa_cumulative_l4_checksum_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_FISA_CUMULATIVE_L4_CHECKSUM(buf); +} + +/** + * hal_rx_get_fisa_cumulative_ip_length_6490() - Retrieve cumulative + * ip length + * @buf: buffer pointer + * + * Return: cumulative length + */ +static inline +uint16_t hal_rx_get_fisa_cumulative_ip_length_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_FISA_CUMULATIVE_IP_LENGTH(buf); +} + +/** + * hal_rx_get_udp_proto_6490() - Retrieve udp proto value + * @buf: buffer + * + * Return: udp proto bit + */ +static inline +bool hal_rx_get_udp_proto_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_UDP_PROTO(buf); +} + +/** + * hal_rx_get_flow_agg_continuation_6490() - retrieve flow agg + * continuation + * @buf: buffer + * + * Return: flow agg + */ +static inline +bool hal_rx_get_flow_agg_continuation_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_FLOW_AGGR_CONT(buf); +} + +/** + * hal_rx_get_flow_agg_count_6490()- Retrieve flow agg count + * @buf: buffer + * + * Return: flow agg count + */ +static inline +uint8_t hal_rx_get_flow_agg_count_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_FLOW_AGGR_COUNT(buf); +} + +/** + * hal_rx_get_fisa_timeout_6490() - Retrieve fisa timeout + * @buf: buffer + * + * Return: fisa timeout + */ +static inline +bool hal_rx_get_fisa_timeout_6490(uint8_t *buf) +{ + return HAL_RX_TLV_GET_FISA_TIMEOUT(buf); +} + +/** + * hal_reo_set_err_dst_remap_6490(): Function to set REO error destination + * ring remap register + * @hal_soc: Pointer to hal_soc + * + * Return: none. + */ +static void +hal_reo_set_err_dst_remap_6490(void *hal_soc) +{ + /* + * Set REO error 2k jump (error code 5) / OOR (error code 7) + * frame routed to REO2TCL ring. + */ + uint32_t dst_remap_ix0 = + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 0) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 1) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 2) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 3) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 4) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 5) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 6) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 7); + + uint32_t dst_remap_ix1 = + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 14) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 13) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 12) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 11) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 10) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 9) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_TCL, 8); + + HAL_REG_WRITE(hal_soc, + HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + dst_remap_ix0); + + hal_info("HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0 0x%x", + HAL_REG_READ( + hal_soc, + HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET))); + + HAL_REG_WRITE(hal_soc, + HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_1_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + dst_remap_ix1); + + hal_info("HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_1 0x%x", + HAL_REG_READ( + hal_soc, + HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_1_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET))); +} + +struct hal_hw_txrx_ops qca6490_hal_hw_txrx_ops = { + /* init and setup */ + hal_srng_dst_hw_init_generic, + hal_srng_src_hw_init_generic, + hal_get_hw_hptp_generic, + hal_reo_setup_generic, + hal_setup_link_idle_list_generic, + hal_get_window_address_6490, + hal_reo_set_err_dst_remap_6490, + + /* tx */ + hal_tx_desc_set_dscp_tid_table_id_6490, + hal_tx_set_dscp_tid_map_6490, + hal_tx_update_dscp_tid_6490, + hal_tx_desc_set_lmac_id_6490, + hal_tx_desc_set_buf_addr_generic, + hal_tx_desc_set_search_type_generic, + hal_tx_desc_set_search_index_generic, + hal_tx_desc_set_cache_set_num_generic, + hal_tx_comp_get_status_generic, + hal_tx_comp_get_release_reason_generic, + hal_get_wbm_internal_error_generic, + hal_tx_desc_set_mesh_en_6490, + + /* rx */ + hal_rx_msdu_start_nss_get_6490, + hal_rx_mon_hw_desc_get_mpdu_status_6490, + hal_rx_get_tlv_6490, + hal_rx_proc_phyrx_other_receive_info_tlv_6490, + hal_rx_dump_msdu_start_tlv_6490, + hal_rx_dump_msdu_end_tlv_6490, + hal_get_link_desc_size_6490, + hal_rx_mpdu_start_tid_get_6490, + hal_rx_msdu_start_reception_type_get_6490, + hal_rx_msdu_end_da_idx_get_6490, + hal_rx_msdu_desc_info_get_ptr_6490, + hal_rx_link_desc_msdu0_ptr_6490, + hal_reo_status_get_header_6490, + hal_rx_status_get_tlv_info_generic, + hal_rx_wbm_err_info_get_generic, + hal_rx_dump_mpdu_start_tlv_generic, + + hal_tx_set_pcp_tid_map_generic, + hal_tx_update_pcp_tid_generic, + hal_tx_update_tidmap_prty_generic, + hal_rx_get_rx_fragment_number_6490, + hal_rx_msdu_end_da_is_mcbc_get_6490, + hal_rx_msdu_end_sa_is_valid_get_6490, + hal_rx_msdu_end_sa_idx_get_6490, + hal_rx_desc_is_first_msdu_6490, + hal_rx_msdu_end_l3_hdr_padding_get_6490, + hal_rx_encryption_info_valid_6490, + hal_rx_print_pn_6490, + hal_rx_msdu_end_first_msdu_get_6490, + hal_rx_msdu_end_da_is_valid_get_6490, + hal_rx_msdu_end_last_msdu_get_6490, + hal_rx_get_mpdu_mac_ad4_valid_6490, + hal_rx_mpdu_start_sw_peer_id_get_6490, + hal_rx_mpdu_get_to_ds_6490, + hal_rx_mpdu_get_fr_ds_6490, + hal_rx_get_mpdu_frame_control_valid_6490, + hal_rx_mpdu_get_addr1_6490, + hal_rx_mpdu_get_addr2_6490, + hal_rx_mpdu_get_addr3_6490, + hal_rx_mpdu_get_addr4_6490, + hal_rx_get_mpdu_sequence_control_valid_6490, + hal_rx_is_unicast_6490, + hal_rx_tid_get_6490, + hal_rx_hw_desc_get_ppduid_get_6490, + NULL, + NULL, + hal_rx_msdu0_buffer_addr_lsb_6490, + hal_rx_msdu_desc_info_ptr_get_6490, + hal_ent_mpdu_desc_info_6490, + hal_dst_mpdu_desc_info_6490, + hal_rx_get_fc_valid_6490, + hal_rx_get_to_ds_flag_6490, + hal_rx_get_mac_addr2_valid_6490, + hal_rx_get_filter_category_6490, + hal_rx_get_ppdu_id_6490, + hal_reo_config_6490, + hal_rx_msdu_flow_idx_get_6490, + hal_rx_msdu_flow_idx_invalid_6490, + hal_rx_msdu_flow_idx_timeout_6490, + hal_rx_msdu_fse_metadata_get_6490, + hal_rx_msdu_cce_metadata_get_6490, + hal_rx_msdu_get_flow_params_6490, + hal_rx_tlv_get_tcp_chksum_6490, + hal_rx_get_rx_sequence_6490, +#if defined(QCA_WIFI_QCA6490) && defined(WLAN_CFR_ENABLE) && \ + defined(WLAN_ENH_CFR_ENABLE) + hal_rx_get_bb_info_6490, + hal_rx_get_rtt_info_6490, +#else + NULL, + NULL, +#endif + /* rx - msdu end fast path info fields */ + hal_rx_msdu_packet_metadata_get_generic, + hal_rx_get_fisa_cumulative_l4_checksum_6490, + hal_rx_get_fisa_cumulative_ip_length_6490, + hal_rx_get_udp_proto_6490, + hal_rx_get_flow_agg_continuation_6490, + hal_rx_get_flow_agg_count_6490, + hal_rx_get_fisa_timeout_6490, + hal_rx_msdu_get_reo_destination_indication_6490 +}; + +struct hal_hw_srng_config hw_srng_table_6490[] = { + /* TODO: max_rings can populated by querying HW capabilities */ + { /* REO_DST */ + .start_ring_id = HAL_SRNG_REO2SW1, + .max_rings = 4, + .entry_size = sizeof(struct reo_destination_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_REO_R0_REO2SW1_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO2SW1_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET) + }, + .reg_size = { + HWIO_REO_R0_REO2SW2_RING_BASE_LSB_ADDR(0) - + HWIO_REO_R0_REO2SW1_RING_BASE_LSB_ADDR(0), + HWIO_REO_R2_REO2SW2_RING_HP_ADDR(0) - + HWIO_REO_R2_REO2SW1_RING_HP_ADDR(0), + }, + .max_size = + HWIO_REO_R0_REO2SW1_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO2SW1_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_EXCEPTION */ + /* Designating REO2TCL ring as exception ring. This ring is + * similar to other REO2SW rings though it is named as REO2TCL. + * Any of theREO2SW rings can be used as exception ring. + */ + .start_ring_id = HAL_SRNG_REO2TCL, + .max_rings = 1, + .entry_size = sizeof(struct reo_destination_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_REO_R0_REO2TCL_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO2TCL_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET) + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_REO_R0_REO2TCL_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO2TCL_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_REINJECT */ + .start_ring_id = HAL_SRNG_SW2REO, + .max_rings = 1, + .entry_size = sizeof(struct reo_entrance_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_REO_R0_SW2REO_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_SW2REO_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET) + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = HWIO_REO_R0_SW2REO_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_SW2REO_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_CMD */ + .start_ring_id = HAL_SRNG_REO_CMD, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct reo_get_queue_stats)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_REO_R0_REO_CMD_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO_CMD_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_REO_R0_REO_CMD_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO_CMD_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_STATUS */ + .start_ring_id = HAL_SRNG_REO_STATUS, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct reo_get_queue_stats_status)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_REO_R0_REO_STATUS_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO_STATUS_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_REO_R0_REO_STATUS_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO_STATUS_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* TCL_DATA */ + .start_ring_id = HAL_SRNG_SW2TCL1, + .max_rings = 3, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct tcl_data_cmd)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_TCL_R0_SW2TCL1_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + HWIO_TCL_R2_SW2TCL1_RING_HP_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + }, + .reg_size = { + HWIO_TCL_R0_SW2TCL2_RING_BASE_LSB_ADDR(0) - + HWIO_TCL_R0_SW2TCL1_RING_BASE_LSB_ADDR(0), + HWIO_TCL_R2_SW2TCL2_RING_HP_ADDR(0) - + HWIO_TCL_R2_SW2TCL1_RING_HP_ADDR(0), + }, + .max_size = + HWIO_TCL_R0_SW2TCL1_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_TCL_R0_SW2TCL1_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* TCL_CMD */ + .start_ring_id = HAL_SRNG_SW2TCL_CMD, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct tcl_gse_cmd)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_TCL_R0_SW2TCL_CREDIT_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + HWIO_TCL_R2_SW2TCL_CREDIT_RING_HP_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_TCL_R0_SW2TCL_CREDIT_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_TCL_R0_SW2TCL_CREDIT_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* TCL_STATUS */ + .start_ring_id = HAL_SRNG_TCL_STATUS, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct tcl_status_ring)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_TCL_R0_TCL_STATUS1_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + HWIO_TCL_R2_TCL_STATUS1_RING_HP_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_TCL_R0_TCL_STATUS1_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_TCL_R0_TCL_STATUS1_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* CE_SRC */ + .start_ring_id = HAL_SRNG_CE_0_SRC, + .max_rings = 12, + .entry_size = sizeof(struct ce_src_desc) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET), + HWIO_WFSS_CE_CHANNEL_DST_R2_DEST_RING_HP_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET), + }, + .reg_size = { + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_SRC_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET, + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_SRC_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET, + }, + .max_size = + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* CE_DST */ + .start_ring_id = HAL_SRNG_CE_0_DST, + .max_rings = 12, + .entry_size = 8 >> 2, + /*TODO: entry_size above should actually be + * sizeof(struct ce_dst_desc) >> 2, but couldn't find definition + * of struct ce_dst_desc in HW header files + */ + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), + HWIO_WFSS_CE_CHANNEL_DST_R2_DEST_RING_HP_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), + }, + .reg_size = { + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, + }, + .max_size = + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* CE_DST_STATUS */ + .start_ring_id = HAL_SRNG_CE_0_DST_STATUS, + .max_rings = 12, + .entry_size = sizeof(struct ce_stat_desc) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), + HWIO_WFSS_CE_CHANNEL_DST_R2_STATUS_RING_HP_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), + }, + /* TODO: check destination status ring registers */ + .reg_size = { + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, + }, + .max_size = + HWIO_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* WBM_IDLE_LINK */ + .start_ring_id = HAL_SRNG_WBM_IDLE_LINK, + .max_rings = 1, + .entry_size = sizeof(struct wbm_link_descriptor_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_WBM_IDLE_LINK_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* SW2WBM_RELEASE */ + .start_ring_id = HAL_SRNG_WBM_SW_RELEASE, + .max_rings = 1, + .entry_size = sizeof(struct wbm_release_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_WBM_R0_SW_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_SW_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_WBM_R0_SW_RELEASE_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WBM_R0_SW_RELEASE_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* 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, + .reg_start = { + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_WBM2SW0_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + .reg_size = { + HWIO_WBM_R0_WBM2SW1_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET) - + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_WBM2SW1_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET) - + HWIO_WBM_R2_WBM2SW0_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + .max_size = + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* RXDMA_BUF */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA0_BUF0, +#ifdef IPA_OFFLOAD + .max_rings = 3, +#else + .max_rings = 2, +#endif + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_DST */ + .start_ring_id = HAL_SRNG_WMAC1_RXDMA2SW0, + .max_rings = 1, + .entry_size = sizeof(struct reo_entrance_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_DST_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_BUF */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA2_BUF, + .max_rings = 1, + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_STATUS */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA1_STATBUF, + .max_rings = 1, + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_DST */ + .start_ring_id = HAL_SRNG_WMAC1_RXDMA2SW1, + .max_rings = 1, + .entry_size = sizeof(struct reo_entrance_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_DST_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_DESC */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA1_DESC, + .max_rings = 1, + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* DIR_BUF_RX_DMA_SRC */ + .start_ring_id = HAL_SRNG_DIR_BUF_RX_SRC_DMA_RING, + /* + * one ring is for spectral scan + * the other is for cfr + */ + .max_rings = 2, + .entry_size = 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, +#ifdef WLAN_FEATURE_CIF_CFR + { /* WIFI_POS_SRC */ + .start_ring_id = HAL_SRNG_WIFI_POS_SRC_DMA_RING, + .max_rings = 1, + .entry_size = sizeof(wmi_oem_dma_buf_release_entry) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, +#endif +}; + +int32_t hal_hw_reg_offset_qca6490[] = { + /* dst */ + REG_OFFSET(DST, HP), + REG_OFFSET(DST, TP), + REG_OFFSET(DST, ID), + REG_OFFSET(DST, MISC), + REG_OFFSET(DST, HP_ADDR_LSB), + REG_OFFSET(DST, HP_ADDR_MSB), + REG_OFFSET(DST, MSI1_BASE_LSB), + REG_OFFSET(DST, MSI1_BASE_MSB), + REG_OFFSET(DST, MSI1_DATA), + REG_OFFSET(DST, BASE_LSB), + REG_OFFSET(DST, BASE_MSB), + REG_OFFSET(DST, PRODUCER_INT_SETUP), + /* src */ + REG_OFFSET(SRC, HP), + REG_OFFSET(SRC, TP), + REG_OFFSET(SRC, ID), + REG_OFFSET(SRC, MISC), + REG_OFFSET(SRC, TP_ADDR_LSB), + REG_OFFSET(SRC, TP_ADDR_MSB), + REG_OFFSET(SRC, MSI1_BASE_LSB), + REG_OFFSET(SRC, MSI1_BASE_MSB), + REG_OFFSET(SRC, MSI1_DATA), + REG_OFFSET(SRC, BASE_LSB), + REG_OFFSET(SRC, BASE_MSB), + REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX0), + REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX1), +}; + +/** + * hal_qca6490_attach() - Attach 6490 target specific hal_soc ops, + * offset and srng table + */ +void hal_qca6490_attach(struct hal_soc *hal_soc) +{ + hal_soc->hw_srng_table = hw_srng_table_6490; + hal_soc->hal_hw_reg_offset = hal_hw_reg_offset_qca6490; + hal_soc->ops = &qca6490_hal_hw_txrx_ops; +} diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6490/hal_6490_rx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6490/hal_6490_rx.h new file mode 100644 index 0000000000000000000000000000000000000000..8859e95eb02febc828f1bbd0bb665ae9611a28af --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6490/hal_6490_rx.h @@ -0,0 +1,467 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _HAL_6490_RX_H_ +#define _HAL_6490_RX_H_ +#include "qdf_util.h" +#include "qdf_types.h" +#include "qdf_lock.h" +#include "qdf_mem.h" +#include "qdf_nbuf.h" +#include "tcl_data_cmd.h" +#include "mac_tcl_reg_seq_hwioreg.h" +#include "phyrx_rssi_legacy.h" +#include "rx_msdu_start.h" +#include "tlv_tag_def.h" +#include "hal_hw_headers.h" +#include "hal_internal.h" +#include "cdp_txrx_mon_struct.h" +#include "qdf_trace.h" +#include "hal_rx.h" +#include "hal_tx.h" +#include "dp_types.h" +#include "hal_api_mon.h" +#include "phyrx_other_receive_info_ru_details.h" + +#define HAL_RX_MSDU_START_MIMO_SS_BITMAP(_rx_msdu_start)\ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\ + RX_MSDU_START_5_MIMO_SS_BITMAP_OFFSET)), \ + RX_MSDU_START_5_MIMO_SS_BITMAP_MASK, \ + RX_MSDU_START_5_MIMO_SS_BITMAP_LSB)) + +#define HAL_RX_MPDU_GET_SEQUENCE_NUMBER(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_NUMBER_OFFSET)), \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_NUMBER_MASK, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_NUMBER_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_MCBC_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_DA_IS_MCBC_OFFSET)), \ + RX_MSDU_END_10_DA_IS_MCBC_MASK, \ + RX_MSDU_END_10_DA_IS_MCBC_LSB)) + +#define HAL_RX_MSDU_END_SA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_SA_IS_VALID_OFFSET)), \ + RX_MSDU_END_10_SA_IS_VALID_MASK, \ + RX_MSDU_END_10_SA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_11_SA_IDX_OFFSET)), \ + RX_MSDU_END_11_SA_IDX_MASK, \ + RX_MSDU_END_11_SA_IDX_LSB)) + +#define HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_L3_HEADER_PADDING_OFFSET)), \ + RX_MSDU_END_10_L3_HEADER_PADDING_MASK, \ + RX_MSDU_END_10_L3_HEADER_PADDING_LSB)) + +#define HAL_RX_MPDU_ENCRYPTION_INFO_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_FRAME_ENCRYPTION_INFO_VALID_OFFSET)), \ + RX_MPDU_INFO_11_FRAME_ENCRYPTION_INFO_VALID_MASK, \ + RX_MPDU_INFO_11_FRAME_ENCRYPTION_INFO_VALID_LSB)) + +#define HAL_RX_MPDU_PN_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_3_PN_31_0_OFFSET)), \ + RX_MPDU_INFO_3_PN_31_0_MASK, \ + RX_MPDU_INFO_3_PN_31_0_LSB)) + +#define HAL_RX_MPDU_PN_63_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_4_PN_63_32_OFFSET)), \ + RX_MPDU_INFO_4_PN_63_32_MASK, \ + RX_MPDU_INFO_4_PN_63_32_LSB)) + +#define HAL_RX_MPDU_PN_95_64_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_5_PN_95_64_OFFSET)), \ + RX_MPDU_INFO_5_PN_95_64_MASK, \ + RX_MPDU_INFO_5_PN_95_64_LSB)) + +#define HAL_RX_MPDU_PN_127_96_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_6_PN_127_96_OFFSET)), \ + RX_MPDU_INFO_6_PN_127_96_MASK, \ + RX_MPDU_INFO_6_PN_127_96_LSB)) + +#define HAL_RX_MSDU_END_FIRST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_FIRST_MSDU_OFFSET)), \ + RX_MSDU_END_10_FIRST_MSDU_MASK, \ + RX_MSDU_END_10_FIRST_MSDU_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_DA_IS_VALID_OFFSET)), \ + RX_MSDU_END_10_DA_IS_VALID_MASK, \ + RX_MSDU_END_10_DA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_LAST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_LAST_MSDU_OFFSET)), \ + RX_MSDU_END_10_LAST_MSDU_MASK, \ + RX_MSDU_END_10_LAST_MSDU_LSB)) + +#define HAL_RX_MPDU_GET_MAC_AD4_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_SW_PEER_ID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_10_SW_PEER_ID_OFFSET)), \ + RX_MPDU_INFO_10_SW_PEER_ID_MASK, \ + RX_MPDU_INFO_10_SW_PEER_ID_LSB)) + +#define HAL_RX_MPDU_GET_TODS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_TO_DS_OFFSET)), \ + RX_MPDU_INFO_11_TO_DS_MASK, \ + RX_MPDU_INFO_11_TO_DS_LSB)) + +#define HAL_RX_MPDU_GET_FROMDS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_FR_DS_OFFSET)), \ + RX_MPDU_INFO_11_FR_DS_MASK, \ + RX_MPDU_INFO_11_FR_DS_LSB)) + +#define HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MPDU_FRAME_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MPDU_FRAME_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_11_MPDU_FRAME_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD1_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD1_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD1_VALID_LSB)) + +#define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_MASK, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_LSB)) + +#define HAL_RX_MPDU_AD1_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD2_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD2_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD2_VALID_LSB)) + +#define HAL_RX_MPDU_AD2_15_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_LSB)) + +#define HAL_RX_MPDU_AD2_47_16_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_OFFSET)), \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_MASK, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD3_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD3_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD3_VALID_LSB)) + +#define HAL_RX_MPDU_AD3_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_OFFSET)), \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_MASK, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_LSB)) + +#define HAL_RX_MPDU_AD3_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_OFFSET)), \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_MASK, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_AD4_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_OFFSET)), \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_MASK, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_LSB)) + +#define HAL_RX_MPDU_AD4_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_OFFSET)), \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_MASK, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_LSB)) + +#define HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_OFFSET)),\ + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_14_SA_SW_PEER_ID_OFFSET)), \ + RX_MSDU_END_14_SA_SW_PEER_ID_MASK, \ + RX_MSDU_END_14_SA_SW_PEER_ID_LSB)) + +#define HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va) \ + (uint8_t *)(link_desc_va) + \ + RX_MSDU_LINK_8_MSDU_0_BUFFER_ADDR_INFO_DETAILS_BUFFER_ADDR_31_0_OFFSET + +#define HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0) \ + (uint8_t *)(msdu0) + \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_DETAILS_FIRST_MSDU_IN_MPDU_FLAG_OFFSET + +#define HAL_ENT_MPDU_DESC_INFO(ent_ring_desc) \ + (uint8_t *)(ent_ring_desc) + \ + RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_DETAILS_MPDU_SEQUENCE_NUMBER_OFFSET + +#define HAL_DST_MPDU_DESC_INFO(dst_ring_desc) \ + (uint8_t *)(dst_ring_desc) + \ + REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_DETAILS_MSDU_COUNT_OFFSET + +#define HAL_RX_GET_FC_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, MPDU_FRAME_CONTROL_VALID) + +#define HAL_RX_GET_TO_DS_FLAG(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, TO_DS) + +#define HAL_RX_GET_MAC_ADDR1_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, MAC_ADDR_AD1_VALID) + +#define HAL_RX_GET_MAC_ADDR2_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, MAC_ADDR_AD2_VALID) + +#define HAL_RX_GET_FILTER_CATEGORY(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_9, RXPCU_MPDU_FILTER_IN_CATEGORY) + +#define HAL_RX_GET_PPDU_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_9, PHY_PPDU_ID) + +#define HAL_RX_GET_SW_FRAME_GROUP_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_9, SW_FRAME_GROUP_ID) + +#define HAL_REO_R0_CONFIG(soc, reg_val, reo_params) \ + do { \ + reg_val &= \ + ~(HWIO_REO_R0_GENERAL_ENABLE_AGING_LIST_ENABLE_BMSK |\ + HWIO_REO_R0_GENERAL_ENABLE_AGING_FLUSH_ENABLE_BMSK); \ + reg_val |= \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_LIST_ENABLE, 1) |\ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_FLUSH_ENABLE, 1);\ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ + reg_val = \ + HAL_REG_READ((soc), \ + HWIO_REO_R0_MISC_CTL_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET)); \ + reg_val &= \ + ~(HWIO_REO_R0_MISC_CTL_FRAGMENT_DEST_RING_BMSK); \ + reg_val |= \ + HAL_SM(HWIO_REO_R0_MISC_CTL, \ + FRAGMENT_DEST_RING, \ + (reo_params)->frag_dst_ring); \ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_MISC_CTL_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ + reg_val = \ + HAL_REG_READ((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET)); \ + reg_val &= \ + (~HWIO_REO_R0_GENERAL_ENABLE_BAR_DEST_RING_BMSK |\ + (REO_REMAP_TCL << HWIO_REO_R0_GENERAL_ENABLE_BAR_DEST_RING_SHFT)); \ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ + } while (0) + +#define HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr) \ + ((struct rx_msdu_desc_info *) \ + _OFFSET_TO_BYTE_PTR(msdu_details_ptr, \ +RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_DETAILS_RESERVED_0A_OFFSET)) + +#define HAL_RX_LINK_DESC_MSDU0_PTR(link_desc) \ + ((struct rx_msdu_details *) \ + _OFFSET_TO_BYTE_PTR((link_desc),\ + RX_MSDU_LINK_8_MSDU_0_BUFFER_ADDR_INFO_DETAILS_BUFFER_ADDR_31_0_OFFSET)) + +#define HAL_RX_MSDU_END_FLOW_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_12_FLOW_IDX_OFFSET)), \ + RX_MSDU_END_12_FLOW_IDX_MASK, \ + RX_MSDU_END_12_FLOW_IDX_LSB)) + +#define HAL_RX_MSDU_END_REO_DEST_IND_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_12_REO_DESTINATION_INDICATION_OFFSET)), \ + RX_MSDU_END_12_REO_DESTINATION_INDICATION_MASK, \ + RX_MSDU_END_12_REO_DESTINATION_INDICATION_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_FLOW_IDX_INVALID_OFFSET)), \ + RX_MSDU_END_10_FLOW_IDX_INVALID_MASK, \ + RX_MSDU_END_10_FLOW_IDX_INVALID_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_FLOW_IDX_TIMEOUT_OFFSET)), \ + RX_MSDU_END_10_FLOW_IDX_TIMEOUT_MASK, \ + RX_MSDU_END_10_FLOW_IDX_TIMEOUT_LSB)) + +#define HAL_RX_MSDU_END_FSE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_13_FSE_METADATA_OFFSET)), \ + RX_MSDU_END_13_FSE_METADATA_MASK, \ + RX_MSDU_END_13_FSE_METADATA_LSB)) + +#define HAL_RX_MSDU_END_CCE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_14_CCE_METADATA_OFFSET)), \ + RX_MSDU_END_14_CCE_METADATA_MASK, \ + RX_MSDU_END_14_CCE_METADATA_LSB)) + +#define HAL_RX_TLV_GET_TCP_CHKSUM(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_10_TCP_UDP_CHKSUM_OFFSET)), \ + RX_MSDU_END_10_TCP_UDP_CHKSUM_MASK, \ + RX_MSDU_END_10_TCP_UDP_CHKSUM_LSB)) + +#define HAL_RX_MSDU_END_DA_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_11_DA_IDX_OR_SW_PEER_ID_OFFSET)), \ + RX_MSDU_END_11_DA_IDX_OR_SW_PEER_ID_MASK, \ + RX_MSDU_END_11_DA_IDX_OR_SW_PEER_ID_LSB)) + +#define HAL_RX_TLV_GET_FLOW_AGGR_CONT(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_17_FLOW_AGGREGATION_CONTINUATION_OFFSET)), \ + RX_MSDU_END_17_FLOW_AGGREGATION_CONTINUATION_MASK, \ + RX_MSDU_END_17_FLOW_AGGREGATION_CONTINUATION_LSB)) + +#define HAL_RX_TLV_GET_FLOW_AGGR_COUNT(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_17_AGGREGATION_COUNT_OFFSET)), \ + RX_MSDU_END_17_AGGREGATION_COUNT_MASK, \ + RX_MSDU_END_17_AGGREGATION_COUNT_LSB)) + +#define HAL_RX_TLV_GET_FISA_TIMEOUT(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_17_FISA_TIMEOUT_OFFSET)), \ + RX_MSDU_END_17_FISA_TIMEOUT_MASK, \ + RX_MSDU_END_17_FISA_TIMEOUT_LSB)) + +#define HAL_RX_TLV_GET_FISA_CUMULATIVE_L4_CHECKSUM(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_18_CUMULATIVE_L4_CHECKSUM_OFFSET)), \ + RX_MSDU_END_18_CUMULATIVE_L4_CHECKSUM_MASK, \ + RX_MSDU_END_18_CUMULATIVE_L4_CHECKSUM_LSB)) + +#define HAL_RX_TLV_GET_FISA_CUMULATIVE_IP_LENGTH(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_18_CUMULATIVE_IP_LENGTH_OFFSET)), \ + RX_MSDU_END_18_CUMULATIVE_IP_LENGTH_MASK, \ + RX_MSDU_END_18_CUMULATIVE_IP_LENGTH_LSB)) + +#if defined(QCA_WIFI_QCA6490) && defined(WLAN_CFR_ENABLE) && \ + defined(WLAN_ENH_CFR_ENABLE) +static inline +void hal_rx_get_bb_info_6490(void *rx_tlv, + void *ppdu_info_hdl) +{ + struct hal_rx_ppdu_info *ppdu_info = ppdu_info_hdl; + + ppdu_info->cfr_info.bb_captured_channel = + HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_3, BB_CAPTURED_CHANNEL); + + ppdu_info->cfr_info.bb_captured_timeout = + HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_3, BB_CAPTURED_TIMEOUT); + + ppdu_info->cfr_info.bb_captured_reason = + HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_3, BB_CAPTURED_REASON); +} + +static inline +void hal_rx_get_rtt_info_6490(void *rx_tlv, + void *ppdu_info_hdl) +{ + struct hal_rx_ppdu_info *ppdu_info = ppdu_info_hdl; + + ppdu_info->cfr_info.rx_location_info_valid = + HAL_RX_GET(rx_tlv, PHYRX_PKT_END_13_RX_PKT_END_DETAILS, + RX_LOCATION_INFO_DETAILS_RX_LOCATION_INFO_VALID); + + ppdu_info->cfr_info.rtt_che_buffer_pointer_low32 = + HAL_RX_GET(rx_tlv, + PHYRX_PKT_END_12_RX_PKT_END_DETAILS_RX_LOCATION_INFO_DETAILS, + RTT_CHE_BUFFER_POINTER_LOW32); + + ppdu_info->cfr_info.rtt_che_buffer_pointer_high8 = + HAL_RX_GET(rx_tlv, + PHYRX_PKT_END_11_RX_PKT_END_DETAILS_RX_LOCATION_INFO_DETAILS, + RTT_CHE_BUFFER_POINTER_HIGH8); + + ppdu_info->cfr_info.chan_capture_status = + HAL_RX_GET(rx_tlv, + PHYRX_PKT_END_13_RX_PKT_END_DETAILS_RX_LOCATION_INFO_DETAILS, + RESERVED_8); +} +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6018/hal_6018_tx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6490/hal_6490_tx.h similarity index 81% rename from drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6018/hal_6018_tx.h rename to drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6490/hal_6490_tx.h index fc915795c4e23adc02f61c6e21ec21eefd71c43c..90cf14fc337297e3436d0a63518ee1057484e41a 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6018/hal_6018_tx.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6490/hal_6490_tx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2019 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 @@ -15,6 +15,9 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +#include "tcl_data_cmd.h" +#include "mac_tcl_reg_seq_hwioreg.h" +#include "phyrx_rssi_legacy.h" #include "hal_hw_headers.h" #include "hal_internal.h" #include "cdp_txrx_mon_struct.h" @@ -25,39 +28,36 @@ #include "hal_api_mon.h" /** - * hal_tx_desc_set_dscp_tid_table_id_6018() - Sets DSCP to TID conversion + * hal_tx_desc_set_dscp_tid_table_id_6490() - Sets DSCP to TID conversion * table ID * @desc: Handle to Tx Descriptor * @id: DSCP to tid conversion table to be used for this frame * * Return: void */ - -static void hal_tx_desc_set_dscp_tid_table_id_6018(void *desc, uint8_t id) +static void hal_tx_desc_set_dscp_tid_table_id_6490(void *desc, uint8_t id) { HAL_SET_FLD(desc, TCL_DATA_CMD_5, DSCP_TID_TABLE_NUM) |= - HAL_TX_SM(TCL_DATA_CMD_5, - DSCP_TID_TABLE_NUM, id); + HAL_TX_SM(TCL_DATA_CMD_5, + DSCP_TID_TABLE_NUM, id); } #define DSCP_TID_TABLE_SIZE 24 #define NUM_WORDS_PER_DSCP_TID_TABLE (DSCP_TID_TABLE_SIZE / 4) + /** - * hal_tx_set_dscp_tid_map_6018() - Configure default DSCP to TID map table + * hal_tx_set_dscp_tid_map_6490() - Configure default DSCP to TID map table * @soc: HAL SoC context * @map: DSCP-TID mapping table - * @id: mapping table ID - 0,1 + * @id: mapping table ID - 0-31 * * DSCP are mapped to 8 TID values using TID values programmed - * in two set of mapping registers DSCP_TID1_MAP_<0 to 6> (id = 0) - * and DSCP_TID2_MAP_<0 to 6> (id = 1) - * Each mapping register has TID mapping for 10 DSCP values + * in any of the 32 DSCP_TID_MAPS (id = 0-31). * * Return: none */ - -static void hal_tx_set_dscp_tid_map_6018(void *hal_soc, uint8_t *map, +static void hal_tx_set_dscp_tid_map_6490(struct hal_soc *hal_soc, uint8_t *map, uint8_t id) { int i; @@ -80,7 +80,8 @@ static void hal_tx_set_dscp_tid_map_6018(void *hal_soc, uint8_t *map, /* Enable read/write access */ regval = HAL_REG_READ(soc, cmn_reg_addr); regval |= - (1 << HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_DSCP_TID_MAP_PROGRAM_EN_SHFT); + (1 << + HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_DSCP_TID_MAP_PROGRAM_EN_SHFT); HAL_REG_WRITE(soc, cmn_reg_addr, regval); @@ -115,8 +116,8 @@ static void hal_tx_set_dscp_tid_map_6018(void *hal_soc, uint8_t *map, } /** - * hal_tx_update_dscp_tid_6018() - Update the dscp tid map table as - updated by user + * hal_tx_update_dscp_tid_6490() - Update the dscp tid map table as updated + * by the user * @soc: HAL SoC context * @map: DSCP-TID mapping table * @id : MAP ID @@ -124,8 +125,7 @@ static void hal_tx_set_dscp_tid_map_6018(void *hal_soc, uint8_t *map, * * Return: void */ - -static void hal_tx_update_dscp_tid_6018(void *hal_soc, uint8_t tid, +static void hal_tx_update_dscp_tid_6490(struct hal_soc *hal_soc, uint8_t tid, uint8_t id, uint8_t dscp) { int index; @@ -159,10 +159,8 @@ static void hal_tx_update_dscp_tid_6018(void *hal_soc, uint8_t tid, * * Return: void */ - -static void hal_tx_desc_set_lmac_id_6018(void *desc, uint8_t lmac_id) +static void hal_tx_desc_set_lmac_id_6490(void *desc, uint8_t lmac_id) { HAL_SET_FLD(desc, TCL_DATA_CMD_4, LMAC_ID) |= HAL_TX_SM(TCL_DATA_CMD_4, LMAC_ID, lmac_id); } - diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6750/hal_6750.c b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6750/hal_6750.c new file mode 100644 index 0000000000000000000000000000000000000000..0542cb8fbdf71548e009bbfc87d6cb95fbdb6bd2 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6750/hal_6750.c @@ -0,0 +1,1835 @@ +/* + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "qdf_types.h" +#include "qdf_util.h" +#include "qdf_types.h" +#include "qdf_lock.h" +#include "qdf_mem.h" +#include "qdf_nbuf.h" +#include "hal_hw_headers.h" +#include "hal_internal.h" +#include "hal_api.h" +#include "target_type.h" +#include "wcss_version.h" +#include "qdf_module.h" + +#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_OFFSET \ + RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_OFFSET +#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_MASK \ + RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_MASK +#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_LSB \ + RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_LSB +#define UNIFIED_PHYRX_HT_SIG_0_HT_SIG_INFO_PHYRX_HT_SIG_INFO_DETAILS_OFFSET \ + PHYRX_L_SIG_B_0_PHYRX_L_SIG_B_INFO_DETAILS_RATE_OFFSET +#define UNIFIED_PHYRX_L_SIG_B_0_L_SIG_B_INFO_PHYRX_L_SIG_B_INFO_DETAILS_OFFSET \ + PHYRX_L_SIG_B_0_PHYRX_L_SIG_B_INFO_DETAILS_RATE_OFFSET +#define UNIFIED_PHYRX_L_SIG_A_0_L_SIG_A_INFO_PHYRX_L_SIG_A_INFO_DETAILS_OFFSET \ + PHYRX_L_SIG_A_0_PHYRX_L_SIG_A_INFO_DETAILS_RATE_OFFSET +#define UNIFIED_PHYRX_VHT_SIG_A_0_VHT_SIG_A_INFO_PHYRX_VHT_SIG_A_INFO_DETAILS_OFFSET \ + PHYRX_VHT_SIG_A_0_PHYRX_VHT_SIG_A_INFO_DETAILS_BANDWIDTH_OFFSET +#define UNIFIED_PHYRX_HE_SIG_A_SU_0_HE_SIG_A_SU_INFO_PHYRX_HE_SIG_A_SU_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_A_SU_0_PHYRX_HE_SIG_A_SU_INFO_DETAILS_FORMAT_INDICATION_OFFSET +#define UNIFIED_PHYRX_HE_SIG_A_MU_DL_0_HE_SIG_A_MU_DL_INFO_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_A_MU_DL_0_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS_DL_UL_FLAG_OFFSET +#define UNIFIED_PHYRX_HE_SIG_B1_MU_0_HE_SIG_B1_MU_INFO_PHYRX_HE_SIG_B1_MU_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_B1_MU_0_PHYRX_HE_SIG_B1_MU_INFO_DETAILS_RU_ALLOCATION_OFFSET +#define UNIFIED_PHYRX_HE_SIG_B2_MU_0_HE_SIG_B2_MU_INFO_PHYRX_HE_SIG_B2_MU_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_B2_MU_0_PHYRX_HE_SIG_B2_MU_INFO_DETAILS_STA_ID_OFFSET +#define UNIFIED_PHYRX_HE_SIG_B2_OFDMA_0_HE_SIG_B2_OFDMA_INFO_PHYRX_HE_SIG_B2_OFDMA_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_B2_OFDMA_0_PHYRX_HE_SIG_B2_OFDMA_INFO_DETAILS_STA_ID_OFFSET + +#define UNIFIED_PHYRX_RSSI_LEGACY_3_RECEIVE_RSSI_INFO_PRE_RSSI_INFO_DETAILS_OFFSET \ + PHYRX_RSSI_LEGACY_3_RECEIVE_RSSI_INFO_PRE_RSSI_INFO_DETAILS_OFFSET +#define UNIFIED_PHYRX_RSSI_LEGACY_19_RECEIVE_RSSI_INFO_PREAMBLE_RSSI_INFO_DETAILS_OFFSET \ + PHYRX_RSSI_LEGACY_19_PREAMBLE_RSSI_INFO_DETAILS_RSSI_PRI20_CHAIN0_OFFSET +#define UNIFIED_RX_MPDU_START_0_RX_MPDU_INFO_RX_MPDU_INFO_DETAILS_OFFSET \ + RX_MPDU_START_0_RX_MPDU_INFO_DETAILS_RXPT_CLASSIFY_INFO_DETAILS_REO_DESTINATION_INDICATION_OFFSET +#define UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET \ + RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET +#define UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET +#define UNIFIED_RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET \ + RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET +#define UNIFIED_REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET \ + REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET +#define UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC \ + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER +#define UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET +#define UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET \ + RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET +#define UNIFIED_TCL_DATA_CMD_0_BUFFER_ADDR_INFO_BUF_ADDR_INFO_OFFSET \ + TCL_DATA_CMD_0_BUF_ADDR_INFO_BUFFER_ADDR_31_0_OFFSET +#define UNIFIED_TCL_DATA_CMD_1_BUFFER_ADDR_INFO_BUF_ADDR_INFO_OFFSET \ + TCL_DATA_CMD_1_BUF_ADDR_INFO_BUFFER_ADDR_39_32_OFFSET +#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_OFFSET \ + TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_OFFSET +#define UNIFIED_BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_LSB \ + BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_LSB +#define UNIFIED_BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_MASK \ + BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_MASK +#define UNIFIED_BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_LSB \ + BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_LSB +#define UNIFIED_BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_MASK \ + BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_MASK +#define UNIFIED_BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_LSB \ + BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_LSB +#define UNIFIED_BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_MASK \ + BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_MASK +#define UNIFIED_BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_LSB \ + BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_LSB +#define UNIFIED_BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_MASK \ + BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_MASK +#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_LSB \ + TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_LSB +#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_MASK \ + TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_MASK +#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_MASK \ + WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_MASK +#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_OFFSET \ + WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_OFFSET +#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_LSB \ + WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_LSB + +#include "hal_6750_tx.h" +#include "hal_6750_rx.h" +#include +#include + +/* + * hal_rx_msdu_start_nss_get_6750(): API to get the NSS + * Interval from rx_msdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(nss) + */ +static uint32_t +hal_rx_msdu_start_nss_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_start *msdu_start = + &pkt_tlvs->msdu_start_tlv.rx_msdu_start; + uint8_t mimo_ss_bitmap; + + mimo_ss_bitmap = HAL_RX_MSDU_START_MIMO_SS_BITMAP(msdu_start); + + return qdf_get_hweight8(mimo_ss_bitmap); +} + +/** + * hal_rx_mon_hw_desc_get_mpdu_status_6750(): Retrieve MPDU status + * + * @ hw_desc_addr: Start address of Rx HW TLVs + * @ rs: Status for monitor mode + * + * Return: void + */ +static void hal_rx_mon_hw_desc_get_mpdu_status_6750(void *hw_desc_addr, + struct mon_rx_status *rs) +{ + struct rx_msdu_start *rx_msdu_start; + struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + uint32_t reg_value; + const uint32_t sgi_hw_to_cdp[] = { + CDP_SGI_0_8_US, + CDP_SGI_0_4_US, + CDP_SGI_1_6_US, + CDP_SGI_3_2_US, + }; + + rx_msdu_start = &rx_desc->msdu_start_tlv.rx_msdu_start; + + HAL_RX_GET_MSDU_AGGREGATION(rx_desc, rs); + + rs->ant_signal_db = HAL_RX_GET(rx_msdu_start, + RX_MSDU_START_5, USER_RSSI); + rs->is_stbc = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, STBC); + + reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, SGI); + rs->sgi = sgi_hw_to_cdp[reg_value]; + + reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEPTION_TYPE); + rs->beamformed = (reg_value == HAL_RX_RECEPTION_TYPE_MU_MIMO) ? 1 : 0; + /* TODO: rs->beamformed should be set for SU beamforming also */ +} + +#define LINK_DESC_SIZE (NUM_OF_DWORDS_RX_MSDU_LINK << 2) + +static uint32_t hal_get_link_desc_size_6750(void) +{ + return LINK_DESC_SIZE; +} + +/* + * hal_rx_get_tlv_6750(): API to get the tlv + * + * @rx_tlv: TLV data extracted from the rx packet + * Return: uint8_t + */ +static uint8_t hal_rx_get_tlv_6750(void *rx_tlv) +{ + return HAL_RX_GET(rx_tlv, PHYRX_RSSI_LEGACY_0, RECEIVE_BANDWIDTH); +} + +/** + * hal_rx_proc_phyrx_other_receive_info_tlv_6750() + * - process other receive info TLV + * @rx_tlv_hdr: pointer to TLV header + * @ppdu_info: pointer to ppdu_info + * + * Return: None + */ +static +void hal_rx_proc_phyrx_other_receive_info_tlv_6750(void *rx_tlv_hdr, + void *ppdu_info_handle) +{ + uint32_t tlv_tag, tlv_len; + uint32_t temp_len, other_tlv_len, other_tlv_tag; + void *rx_tlv = (uint8_t *)rx_tlv_hdr + HAL_RX_TLV32_HDR_SIZE; + void *other_tlv_hdr = NULL; + void *other_tlv = NULL; + + tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv_hdr); + tlv_len = HAL_RX_GET_USER_TLV32_LEN(rx_tlv_hdr); + temp_len = 0; + + other_tlv_hdr = rx_tlv + HAL_RX_TLV32_HDR_SIZE; + + other_tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(other_tlv_hdr); + other_tlv_len = HAL_RX_GET_USER_TLV32_LEN(other_tlv_hdr); + temp_len += other_tlv_len; + other_tlv = other_tlv_hdr + HAL_RX_TLV32_HDR_SIZE; + + switch (other_tlv_tag) { + default: + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "%s unhandled TLV type: %d, TLV len:%d", + __func__, other_tlv_tag, other_tlv_len); + break; + } +} + +/** + * hal_rx_dump_msdu_start_tlv_6750() : dump RX msdu_start TLV in structured + * human readable format. + * @ msdu_start: pointer the msdu_start TLV in pkt. + * @ dbg_level: log level. + * + * Return: void + */ +static void hal_rx_dump_msdu_start_tlv_6750(void *msdustart, uint8_t dbg_level) +{ + struct rx_msdu_start *msdu_start = (struct rx_msdu_start *)msdustart; + + hal_verbose_debug( + "rx_msdu_start tlv (1/2) - " + "rxpcu_mpdu_filter_in_category: %x " + "sw_frame_group_id: %x " + "phy_ppdu_id: %x " + "msdu_length: %x " + "ipsec_esp: %x " + "l3_offset: %x " + "ipsec_ah: %x " + "l4_offset: %x " + "msdu_number: %x " + "decap_format: %x " + "ipv4_proto: %x " + "ipv6_proto: %x " + "tcp_proto: %x " + "udp_proto: %x " + "ip_frag: %x " + "tcp_only_ack: %x " + "da_is_bcast_mcast: %x " + "ip4_protocol_ip6_next_header: %x " + "toeplitz_hash_2_or_4: %x " + "flow_id_toeplitz: %x " + "user_rssi: %x " + "pkt_type: %x " + "stbc: %x " + "sgi: %x " + "rate_mcs: %x " + "receive_bandwidth: %x " + "reception_type: %x " + "ppdu_start_timestamp: %u ", + msdu_start->rxpcu_mpdu_filter_in_category, + msdu_start->sw_frame_group_id, + msdu_start->phy_ppdu_id, + msdu_start->msdu_length, + msdu_start->ipsec_esp, + msdu_start->l3_offset, + msdu_start->ipsec_ah, + msdu_start->l4_offset, + msdu_start->msdu_number, + msdu_start->decap_format, + msdu_start->ipv4_proto, + msdu_start->ipv6_proto, + msdu_start->tcp_proto, + msdu_start->udp_proto, + msdu_start->ip_frag, + msdu_start->tcp_only_ack, + msdu_start->da_is_bcast_mcast, + msdu_start->ip4_protocol_ip6_next_header, + msdu_start->toeplitz_hash_2_or_4, + msdu_start->flow_id_toeplitz, + msdu_start->user_rssi, + msdu_start->pkt_type, + msdu_start->stbc, + msdu_start->sgi, + msdu_start->rate_mcs, + msdu_start->receive_bandwidth, + msdu_start->reception_type, + msdu_start->ppdu_start_timestamp); + + hal_verbose_debug( + "rx_msdu_start tlv (2/2) - " + "sw_phy_meta_data: %x ", + msdu_start->sw_phy_meta_data); +} + +/** + * hal_rx_dump_msdu_end_tlv_6750: dump RX msdu_end TLV in structured + * human readable format. + * @ msdu_end: pointer the msdu_end TLV in pkt. + * @ dbg_level: log level. + * + * Return: void + */ +static void hal_rx_dump_msdu_end_tlv_6750(void *msduend, + uint8_t dbg_level) +{ + struct rx_msdu_end *msdu_end = (struct rx_msdu_end *)msduend; + __QDF_TRACE_RL(dbg_level, QDF_MODULE_ID_DP, + "rx_msdu_end tlv (1/2) - " + "rxpcu_mpdu_filter_in_category: %x " + "sw_frame_group_id: %x " + "phy_ppdu_id: %x " + "ip_hdr_chksum: %x " + "tcp_udp_chksum: %x " + "key_id_octet: %x " + "cce_super_rule: %x " + "cce_classify_not_done_truncat: %x " + "cce_classify_not_done_cce_dis: %x " + "reported_mpdu_length: %x " + "first_msdu: %x " + "last_msdu: %x " + "sa_idx_timeout: %x " + "da_idx_timeout: %x " + "msdu_limit_error: %x " + "flow_idx_timeout: %x " + "flow_idx_invalid: %x " + "wifi_parser_error: %x " + "amsdu_parser_error: %x", + msdu_end->rxpcu_mpdu_filter_in_category, + msdu_end->sw_frame_group_id, + msdu_end->phy_ppdu_id, + msdu_end->ip_hdr_chksum, + msdu_end->tcp_udp_chksum, + msdu_end->key_id_octet, + msdu_end->cce_super_rule, + msdu_end->cce_classify_not_done_truncate, + msdu_end->cce_classify_not_done_cce_dis, + msdu_end->reported_mpdu_length, + msdu_end->first_msdu, + msdu_end->last_msdu, + msdu_end->sa_idx_timeout, + msdu_end->da_idx_timeout, + msdu_end->msdu_limit_error, + msdu_end->flow_idx_timeout, + msdu_end->flow_idx_invalid, + msdu_end->wifi_parser_error, + msdu_end->amsdu_parser_error); + __QDF_TRACE_RL(dbg_level, QDF_MODULE_ID_DP, + "rx_msdu_end tlv (2/2)- " + "sa_is_valid: %x " + "da_is_valid: %x " + "da_is_mcbc: %x " + "l3_header_padding: %x " + "ipv6_options_crc: %x " + "tcp_seq_number: %x " + "tcp_ack_number: %x " + "tcp_flag: %x " + "lro_eligible: %x " + "window_size: %x " + "da_offset: %x " + "sa_offset: %x " + "da_offset_valid: %x " + "sa_offset_valid: %x " + "rule_indication_31_0: %x " + "rule_indication_63_32: %x " + "sa_idx: %x " + "da_idx: %x " + "msdu_drop: %x " + "reo_destination_indication: %x " + "flow_idx: %x " + "fse_metadata: %x " + "cce_metadata: %x " + "sa_sw_peer_id: %x ", + msdu_end->sa_is_valid, + msdu_end->da_is_valid, + msdu_end->da_is_mcbc, + msdu_end->l3_header_padding, + msdu_end->ipv6_options_crc, + msdu_end->tcp_seq_number, + msdu_end->tcp_ack_number, + msdu_end->tcp_flag, + msdu_end->lro_eligible, + msdu_end->window_size, + msdu_end->da_offset, + msdu_end->sa_offset, + msdu_end->da_offset_valid, + msdu_end->sa_offset_valid, + msdu_end->rule_indication_31_0, + msdu_end->rule_indication_63_32, + msdu_end->sa_idx, + msdu_end->da_idx_or_sw_peer_id, + msdu_end->msdu_drop, + msdu_end->reo_destination_indication, + msdu_end->flow_idx, + msdu_end->fse_metadata, + msdu_end->cce_metadata, + msdu_end->sa_sw_peer_id); +} + +/* + * Get tid from RX_MPDU_START + */ +#define HAL_RX_MPDU_INFO_TID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_7_TID_OFFSET)), \ + RX_MPDU_INFO_7_TID_MASK, \ + RX_MPDU_INFO_7_TID_LSB)) + +static uint32_t hal_rx_mpdu_start_tid_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint32_t tid; + + tid = HAL_RX_MPDU_INFO_TID_GET(&mpdu_start->rx_mpdu_info_details); + + return tid; +} + +#define HAL_RX_MSDU_START_RECEPTION_TYPE_GET(_rx_msdu_start) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start), \ + RX_MSDU_START_5_RECEPTION_TYPE_OFFSET)), \ + RX_MSDU_START_5_RECEPTION_TYPE_MASK, \ + RX_MSDU_START_5_RECEPTION_TYPE_LSB)) + +/* + * hal_rx_msdu_start_reception_type_get(): API to get the reception type + * Interval from rx_msdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(reception_type) + */ +static +uint32_t hal_rx_msdu_start_reception_type_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_start *msdu_start = + &pkt_tlvs->msdu_start_tlv.rx_msdu_start; + uint32_t reception_type; + + reception_type = HAL_RX_MSDU_START_RECEPTION_TYPE_GET(msdu_start); + + return reception_type; +} + +/** + * hal_rx_msdu_end_da_idx_get_6750: API to get da_idx + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da index + */ +static uint16_t hal_rx_msdu_end_da_idx_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint16_t da_idx; + + da_idx = HAL_RX_MSDU_END_DA_IDX_GET(msdu_end); + + return da_idx; +} + +/** + * hal_rx_get_rx_fragment_number_6750(): Function to retrieve rx fragment number + * + * @nbuf: Network buffer + * Returns: rx fragment number + */ +static +uint8_t hal_rx_get_rx_fragment_number_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + /* Return first 4 bits as fragment number */ + return (HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info) & + DOT11_SEQ_FRAG_MASK); +} + +/** + * hal_rx_msdu_end_da_is_mcbc_get_6750(): API to check if pkt is MCBC + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_mcbc + */ +static uint8_t +hal_rx_msdu_end_da_is_mcbc_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_DA_IS_MCBC_GET(msdu_end); +} + +/** + * hal_rx_msdu_end_sa_is_valid_get_6750(): API to get_6750 the + * sa_is_valid bit from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_is_valid bit + */ +static uint8_t +hal_rx_msdu_end_sa_is_valid_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t sa_is_valid; + + sa_is_valid = HAL_RX_MSDU_END_SA_IS_VALID_GET(msdu_end); + + return sa_is_valid; +} + +/** + * hal_rx_msdu_end_sa_idx_get_6750(): API to get_6750 the + * sa_idx from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_idx (SA AST index) + */ +static +uint16_t hal_rx_msdu_end_sa_idx_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint16_t sa_idx; + + sa_idx = HAL_RX_MSDU_END_SA_IDX_GET(msdu_end); + + return sa_idx; +} + +/** + * hal_rx_desc_is_first_msdu_6750() - Check if first msdu + * + * @hal_soc_hdl: hal_soc handle + * @hw_desc_addr: hardware descriptor address + * + * Return: 0 - success/ non-zero failure + */ +static uint32_t hal_rx_desc_is_first_msdu_6750(void *hw_desc_addr) +{ + struct rx_pkt_tlvs *rx_tlvs = (struct rx_pkt_tlvs *)hw_desc_addr; + struct rx_msdu_end *msdu_end = &rx_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_GET(msdu_end, RX_MSDU_END_10, FIRST_MSDU); +} + +/** + * hal_rx_msdu_end_l3_hdr_padding_get_6750(): API to get_6750 the + * l3_header padding from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: number of l3 header padding bytes + */ +static uint32_t hal_rx_msdu_end_l3_hdr_padding_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint32_t l3_header_padding; + + l3_header_padding = HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(msdu_end); + + return l3_header_padding; +} + +/* + * @ hal_rx_encryption_info_valid_6750: Returns encryption type. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: encryption type + */ +static uint32_t hal_rx_encryption_info_valid_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + uint32_t encryption_info = HAL_RX_MPDU_ENCRYPTION_INFO_VALID(mpdu_info); + + return encryption_info; +} + +/* + * @ hal_rx_print_pn_6750: Prints the PN of rx packet. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: void + */ +static void hal_rx_print_pn_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + uint32_t pn_31_0 = HAL_RX_MPDU_PN_31_0_GET(mpdu_info); + uint32_t pn_63_32 = HAL_RX_MPDU_PN_63_32_GET(mpdu_info); + uint32_t pn_95_64 = HAL_RX_MPDU_PN_95_64_GET(mpdu_info); + uint32_t pn_127_96 = HAL_RX_MPDU_PN_127_96_GET(mpdu_info); + + hal_debug("PN number pn_127_96 0x%x pn_95_64 0x%x pn_63_32 0x%x pn_31_0 0x%x ", + pn_127_96, pn_95_64, pn_63_32, pn_31_0); +} + +/** + * hal_rx_msdu_end_first_msdu_get_6750: API to get first msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: first_msdu + */ +static uint8_t hal_rx_msdu_end_first_msdu_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t first_msdu; + + first_msdu = HAL_RX_MSDU_END_FIRST_MSDU_GET(msdu_end); + + return first_msdu; +} + +/** + * hal_rx_msdu_end_da_is_valid_get_6750: API to check if da is valid + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_valid + */ +static uint8_t hal_rx_msdu_end_da_is_valid_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t da_is_valid; + + da_is_valid = HAL_RX_MSDU_END_DA_IS_VALID_GET(msdu_end); + + return da_is_valid; +} + +/** + * hal_rx_msdu_end_last_msdu_get_6750: API to get last msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: last_msdu + */ +static uint8_t hal_rx_msdu_end_last_msdu_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t last_msdu; + + last_msdu = HAL_RX_MSDU_END_LAST_MSDU_GET(msdu_end); + + return last_msdu; +} + +/* + * hal_rx_get_mpdu_mac_ad4_valid_6750(): Retrieves if mpdu 4th addr is valid + * + * @nbuf: Network buffer + * Returns: value of mpdu 4th address valid field + */ +static bool hal_rx_get_mpdu_mac_ad4_valid_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + bool ad4_valid = 0; + + ad4_valid = HAL_RX_MPDU_GET_MAC_AD4_VALID(rx_mpdu_info); + + return ad4_valid; +} + +/** + * hal_rx_mpdu_start_sw_peer_id_get_6750: Retrieve sw peer_id + * @buf: network buffer + * + * Return: sw peer_id + */ +static uint32_t hal_rx_mpdu_start_sw_peer_id_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_SW_PEER_ID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/** + * hal_rx_mpdu_get_to_ds_6750(): API to get the tods info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(to_ds) + */ +static uint32_t hal_rx_mpdu_get_to_ds_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_TODS(mpdu_info); +} + +/* + * hal_rx_mpdu_get_fr_ds_6750(): API to get the from ds info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(fr_ds) + */ +static uint32_t hal_rx_mpdu_get_fr_ds_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_FROMDS(mpdu_info); +} + +/* + * hal_rx_get_mpdu_frame_control_valid_6750(): Retrieves mpdu + * frame control valid + * + * @nbuf: Network buffer + * Returns: value of frame control valid field + */ +static uint8_t hal_rx_get_mpdu_frame_control_valid_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(rx_mpdu_info); +} + +/* + * hal_rx_mpdu_get_addr1_6750(): API to check get address1 of the mpdu + * + * @buf: pointer to the start of RX PKT TLV headera + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr1_6750(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr1 { + uint32_t ad1_31_0; + uint16_t ad1_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr1 *addr = (struct hal_addr1 *)mac_addr; + uint32_t mac_addr_ad1_valid; + + mac_addr_ad1_valid = HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(mpdu_info); + + if (mac_addr_ad1_valid) { + addr->ad1_31_0 = HAL_RX_MPDU_AD1_31_0_GET(mpdu_info); + addr->ad1_47_32 = HAL_RX_MPDU_AD1_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr2_6750(): API to check get address2 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr2_6750(uint8_t *buf, + uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr2 { + uint16_t ad2_15_0; + uint32_t ad2_47_16; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr2 *addr = (struct hal_addr2 *)mac_addr; + uint32_t mac_addr_ad2_valid; + + mac_addr_ad2_valid = HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(mpdu_info); + + if (mac_addr_ad2_valid) { + addr->ad2_15_0 = HAL_RX_MPDU_AD2_15_0_GET(mpdu_info); + addr->ad2_47_16 = HAL_RX_MPDU_AD2_47_16_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr3_6750(): API to get address3 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr3_6750(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr3 { + uint32_t ad3_31_0; + uint16_t ad3_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr3 *addr = (struct hal_addr3 *)mac_addr; + uint32_t mac_addr_ad3_valid; + + mac_addr_ad3_valid = HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(mpdu_info); + + if (mac_addr_ad3_valid) { + addr->ad3_31_0 = HAL_RX_MPDU_AD3_31_0_GET(mpdu_info); + addr->ad3_47_32 = HAL_RX_MPDU_AD3_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr4_6750(): API to get address4 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr4_6750(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr4 { + uint32_t ad4_31_0; + uint16_t ad4_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr4 *addr = (struct hal_addr4 *)mac_addr; + uint32_t mac_addr_ad4_valid; + + mac_addr_ad4_valid = HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(mpdu_info); + + if (mac_addr_ad4_valid) { + addr->ad4_31_0 = HAL_RX_MPDU_AD4_31_0_GET(mpdu_info); + addr->ad4_47_32 = HAL_RX_MPDU_AD4_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_get_mpdu_sequence_control_valid_6750(): Get mpdu + * sequence control valid + * + * @nbuf: Network buffer + * Returns: value of sequence control valid field + */ +static uint8_t hal_rx_get_mpdu_sequence_control_valid_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(rx_mpdu_info); +} + +/** + * hal_rx_is_unicast_6750: check packet is unicast frame or not. + * + * @ buf: pointer to rx pkt TLV. + * + * Return: true on unicast. + */ +static bool hal_rx_is_unicast_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint32_t grp_id; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + + grp_id = (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_OFFSET)), + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_MASK, + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_LSB)); + + return (HAL_MPDU_SW_FRAME_GROUP_UNICAST_DATA == grp_id) ? true : false; +} + +/** + * hal_rx_tid_get_6750: get tid based on qos control valid. + * @hal_soc_hdl: hal_soc handle + * @ buf: pointer to rx pkt TLV. + * + * Return: tid + */ +static uint32_t hal_rx_tid_get_6750(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + uint8_t qos_control_valid = + (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_OFFSET)), + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_MASK, + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_LSB)); + + if (qos_control_valid) + return hal_rx_mpdu_start_tid_get_6750(buf); + + return HAL_RX_NON_QOS_TID; +} + +/** + * hal_rx_hw_desc_get_ppduid_get_6750(): retrieve ppdu id + * @hw_desc_addr: hw addr + * + * Return: ppdu id + */ +static uint32_t hal_rx_hw_desc_get_ppduid_get_6750(void *hw_desc_addr) +{ + struct rx_mpdu_info *rx_mpdu_info; + struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + + rx_mpdu_info = + &rx_desc->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + + return HAL_RX_GET(rx_mpdu_info, RX_MPDU_INFO_9, PHY_PPDU_ID); +} + +/** + * hal_reo_status_get_header_6750 - Process reo desc info + * @d - Pointer to reo descriptior + * @b - tlv type info + * @h1 - Pointer to hal_reo_status_header where info to be stored + * + * Return - none. + * + */ +static void hal_reo_status_get_header_6750(uint32_t *d, int b, void *h1) +{ + uint32_t val1 = 0; + struct hal_reo_status_header *h = + (struct hal_reo_status_header *)h1; + + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_0, + STATUS_HEADER_REO_STATUS_NUMBER)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->cmd_num = + HAL_GET_FIELD( + UNIFORM_REO_STATUS_HEADER_0, REO_STATUS_NUMBER, + val1); + h->exec_time = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + CMD_EXECUTION_TIME, val1); + h->status = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + REO_CMD_EXECUTION_STATUS, val1); + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_1, + STATUS_HEADER_TIMESTAMP)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->tstamp = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_1, TIMESTAMP, val1); +} + +/** + * hal_tx_desc_set_mesh_en_6750 - Set mesh_enable flag in Tx descriptor + * @desc: Handle to Tx Descriptor + * @en: For raw WiFi frames, this indicates transmission to a mesh STA, + * enabling the interpretation of the 'Mesh Control Present' bit + * (bit 8) of QoS Control (otherwise this bit is ignored), + * For native WiFi frames, this indicates that a 'Mesh Control' field + * is present between the header and the LLC. + * + * Return: void + */ +static inline +void hal_tx_desc_set_mesh_en_6750(void *desc, uint8_t en) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_5, MESH_ENABLE) |= + HAL_TX_SM(TCL_DATA_CMD_5, MESH_ENABLE, en); +} + +static +void *hal_rx_msdu0_buffer_addr_lsb_6750(void *link_desc_va) +{ + return (void *)HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va); +} + +static +void *hal_rx_msdu_desc_info_ptr_get_6750(void *msdu0) +{ + return (void *)HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0); +} + +static +void *hal_ent_mpdu_desc_info_6750(void *ent_ring_desc) +{ + return (void *)HAL_ENT_MPDU_DESC_INFO(ent_ring_desc); +} + +static +void *hal_dst_mpdu_desc_info_6750(void *dst_ring_desc) +{ + return (void *)HAL_DST_MPDU_DESC_INFO(dst_ring_desc); +} + +static +uint8_t hal_rx_get_fc_valid_6750(uint8_t *buf) +{ + return HAL_RX_GET_FC_VALID(buf); +} + +static uint8_t hal_rx_get_to_ds_flag_6750(uint8_t *buf) +{ + return HAL_RX_GET_TO_DS_FLAG(buf); +} + +static uint8_t hal_rx_get_mac_addr2_valid_6750(uint8_t *buf) +{ + return HAL_RX_GET_MAC_ADDR2_VALID(buf); +} + +static uint8_t hal_rx_get_filter_category_6750(uint8_t *buf) +{ + return HAL_RX_GET_FILTER_CATEGORY(buf); +} + +static uint32_t +hal_rx_get_ppdu_id_6750(uint8_t *buf) +{ + return HAL_RX_GET_PPDU_ID(buf); +} + +/** + * hal_reo_config_6750(): Set reo config parameters + * @soc: hal soc handle + * @reg_val: value to be set + * @reo_params: reo parameters + * + * Return: void + */ +static +void hal_reo_config_6750(struct hal_soc *soc, + uint32_t reg_val, + struct hal_reo_params *reo_params) +{ + HAL_REO_R0_CONFIG(soc, reg_val, reo_params); +} + +/** + * hal_rx_msdu_desc_info_get_ptr_6750() - Get msdu desc info ptr + * @msdu_details_ptr - Pointer to msdu_details_ptr + * + * Return - Pointer to rx_msdu_desc_info structure. + * + */ +static void *hal_rx_msdu_desc_info_get_ptr_6750(void *msdu_details_ptr) +{ + return HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr); +} + +/** + * hal_rx_link_desc_msdu0_ptr_6750 - Get pointer to rx_msdu details + * @link_desc - Pointer to link desc + * + * Return - Pointer to rx_msdu_details structure + * + */ +static void *hal_rx_link_desc_msdu0_ptr_6750(void *link_desc) +{ + return HAL_RX_LINK_DESC_MSDU0_PTR(link_desc); +} + +/** + * hal_rx_msdu_flow_idx_get_6750: API to get flow index + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index value from MSDU END TLV + */ +static inline uint32_t hal_rx_msdu_flow_idx_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_invalid_6750: API to get flow index invalid + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index invalid value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_invalid_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_timeout_6750: API to get flow index timeout + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index timeout value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_timeout_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); +} + +/** + * hal_rx_msdu_fse_metadata_get_6750: API to get FSE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: fse metadata value from MSDU END TLV + */ +static uint32_t hal_rx_msdu_fse_metadata_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FSE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_cce_metadata_get_6750: API to get CCE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: cce_metadata + */ +static uint16_t +hal_rx_msdu_cce_metadata_get_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_CCE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_tlv_get_tcp_chksum_6750() - API to get tcp checksum + * @buf: rx_tlv_hdr + * + * Return: tcp checksum + */ +static uint16_t +hal_rx_tlv_get_tcp_chksum_6750(uint8_t *buf) +{ + return HAL_RX_TLV_GET_TCP_CHKSUM(buf); +} + +/** + * hal_rx_get_rx_sequence_6750(): Function to retrieve rx sequence number + * + * @nbuf: Network buffer + * Returns: rx sequence number + */ +static +uint16_t hal_rx_get_rx_sequence_6750(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info); +} + +/** + * hal_get_window_address_6750(): Function to get hp/tp address + * @hal_soc: Pointer to hal_soc + * @addr: address offset of register + * + * Return: modified address offset of register + */ +static inline qdf_iomem_t hal_get_window_address_6750(struct hal_soc *hal_soc, + qdf_iomem_t addr) +{ + return addr; +} + +struct hal_hw_txrx_ops qca6750_hal_hw_txrx_ops = { + /* init and setup */ + hal_srng_dst_hw_init_generic, + hal_srng_src_hw_init_generic, + hal_get_hw_hptp_generic, + hal_reo_setup_generic, + hal_setup_link_idle_list_generic, + hal_get_window_address_6750, + NULL, + + /* tx */ + hal_tx_desc_set_dscp_tid_table_id_6750, + hal_tx_set_dscp_tid_map_6750, + hal_tx_update_dscp_tid_6750, + hal_tx_desc_set_lmac_id_6750, + hal_tx_desc_set_buf_addr_generic, + hal_tx_desc_set_search_type_generic, + hal_tx_desc_set_search_index_generic, + hal_tx_desc_set_cache_set_num_generic, + hal_tx_comp_get_status_generic, + hal_tx_comp_get_release_reason_generic, + hal_get_wbm_internal_error_generic, + hal_tx_desc_set_mesh_en_6750, + + /* rx */ + hal_rx_msdu_start_nss_get_6750, + hal_rx_mon_hw_desc_get_mpdu_status_6750, + hal_rx_get_tlv_6750, + hal_rx_proc_phyrx_other_receive_info_tlv_6750, + hal_rx_dump_msdu_start_tlv_6750, + hal_rx_dump_msdu_end_tlv_6750, + hal_get_link_desc_size_6750, + hal_rx_mpdu_start_tid_get_6750, + hal_rx_msdu_start_reception_type_get_6750, + hal_rx_msdu_end_da_idx_get_6750, + hal_rx_msdu_desc_info_get_ptr_6750, + hal_rx_link_desc_msdu0_ptr_6750, + hal_reo_status_get_header_6750, + hal_rx_status_get_tlv_info_generic, + hal_rx_wbm_err_info_get_generic, + hal_rx_dump_mpdu_start_tlv_generic, + + hal_tx_set_pcp_tid_map_generic, + hal_tx_update_pcp_tid_generic, + hal_tx_update_tidmap_prty_generic, + hal_rx_get_rx_fragment_number_6750, + hal_rx_msdu_end_da_is_mcbc_get_6750, + hal_rx_msdu_end_sa_is_valid_get_6750, + hal_rx_msdu_end_sa_idx_get_6750, + hal_rx_desc_is_first_msdu_6750, + hal_rx_msdu_end_l3_hdr_padding_get_6750, + hal_rx_encryption_info_valid_6750, + hal_rx_print_pn_6750, + hal_rx_msdu_end_first_msdu_get_6750, + hal_rx_msdu_end_da_is_valid_get_6750, + hal_rx_msdu_end_last_msdu_get_6750, + hal_rx_get_mpdu_mac_ad4_valid_6750, + hal_rx_mpdu_start_sw_peer_id_get_6750, + hal_rx_mpdu_get_to_ds_6750, + hal_rx_mpdu_get_fr_ds_6750, + hal_rx_get_mpdu_frame_control_valid_6750, + hal_rx_mpdu_get_addr1_6750, + hal_rx_mpdu_get_addr2_6750, + hal_rx_mpdu_get_addr3_6750, + hal_rx_mpdu_get_addr4_6750, + hal_rx_get_mpdu_sequence_control_valid_6750, + hal_rx_is_unicast_6750, + hal_rx_tid_get_6750, + hal_rx_hw_desc_get_ppduid_get_6750, + NULL, + NULL, + hal_rx_msdu0_buffer_addr_lsb_6750, + hal_rx_msdu_desc_info_ptr_get_6750, + hal_ent_mpdu_desc_info_6750, + hal_dst_mpdu_desc_info_6750, + hal_rx_get_fc_valid_6750, + hal_rx_get_to_ds_flag_6750, + hal_rx_get_mac_addr2_valid_6750, + hal_rx_get_filter_category_6750, + hal_rx_get_ppdu_id_6750, + hal_reo_config_6750, + hal_rx_msdu_flow_idx_get_6750, + hal_rx_msdu_flow_idx_invalid_6750, + hal_rx_msdu_flow_idx_timeout_6750, + hal_rx_msdu_fse_metadata_get_6750, + hal_rx_msdu_cce_metadata_get_6750, + NULL, + hal_rx_tlv_get_tcp_chksum_6750, + hal_rx_get_rx_sequence_6750, + NULL, + NULL, + /* rx - msdu end fast path info fields */ + hal_rx_msdu_packet_metadata_get_generic +}; + +struct hal_hw_srng_config hw_srng_table_6750[] = { + /* TODO: max_rings can populated by querying HW capabilities */ + { /* REO_DST */ + .start_ring_id = HAL_SRNG_REO2SW1, + .max_rings = 4, + .entry_size = sizeof(struct reo_destination_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_REO_R0_REO2SW1_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO2SW1_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET) + }, + .reg_size = { + HWIO_REO_R0_REO2SW2_RING_BASE_LSB_ADDR(0) - + HWIO_REO_R0_REO2SW1_RING_BASE_LSB_ADDR(0), + HWIO_REO_R2_REO2SW2_RING_HP_ADDR(0) - + HWIO_REO_R2_REO2SW1_RING_HP_ADDR(0), + }, + .max_size = + HWIO_REO_R0_REO2SW1_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO2SW1_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_EXCEPTION */ + /* Designating REO2TCL ring as exception ring. This ring is + * similar to other REO2SW rings though it is named as REO2TCL. + * Any of theREO2SW rings can be used as exception ring. + */ + .start_ring_id = HAL_SRNG_REO2TCL, + .max_rings = 1, + .entry_size = sizeof(struct reo_destination_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_REO_R0_REO2TCL_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO2TCL_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET) + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_REO_R0_REO2TCL_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO2TCL_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_REINJECT */ + .start_ring_id = HAL_SRNG_SW2REO, + .max_rings = 1, + .entry_size = sizeof(struct reo_entrance_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_REO_R0_SW2REO_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_SW2REO_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET) + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = HWIO_REO_R0_SW2REO_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_SW2REO_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_CMD */ + .start_ring_id = HAL_SRNG_REO_CMD, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct reo_get_queue_stats)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_REO_R0_REO_CMD_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO_CMD_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_REO_R0_REO_CMD_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO_CMD_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_STATUS */ + .start_ring_id = HAL_SRNG_REO_STATUS, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct reo_get_queue_stats_status)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_REO_R0_REO_STATUS_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO_STATUS_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_REO_R0_REO_STATUS_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO_STATUS_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* TCL_DATA */ + .start_ring_id = HAL_SRNG_SW2TCL1, + .max_rings = 3, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct tcl_data_cmd)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_TCL_R0_SW2TCL1_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + HWIO_TCL_R2_SW2TCL1_RING_HP_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + }, + .reg_size = { + HWIO_TCL_R0_SW2TCL2_RING_BASE_LSB_ADDR(0) - + HWIO_TCL_R0_SW2TCL1_RING_BASE_LSB_ADDR(0), + HWIO_TCL_R2_SW2TCL2_RING_HP_ADDR(0) - + HWIO_TCL_R2_SW2TCL1_RING_HP_ADDR(0), + }, + .max_size = + HWIO_TCL_R0_SW2TCL1_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_TCL_R0_SW2TCL1_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* TCL_CMD */ + .start_ring_id = HAL_SRNG_SW2TCL_CMD, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct tcl_gse_cmd)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_TCL_R0_SW2TCL_CREDIT_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + HWIO_TCL_R2_SW2TCL_CREDIT_RING_HP_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_TCL_R0_SW2TCL_CREDIT_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_TCL_R0_SW2TCL_CREDIT_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* TCL_STATUS */ + .start_ring_id = HAL_SRNG_TCL_STATUS, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct tcl_status_ring)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_TCL_R0_TCL_STATUS1_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + HWIO_TCL_R2_TCL_STATUS1_RING_HP_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_TCL_R0_TCL_STATUS1_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_TCL_R0_TCL_STATUS1_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* CE_SRC */ + .start_ring_id = HAL_SRNG_CE_0_SRC, + .max_rings = 12, + .entry_size = sizeof(struct ce_src_desc) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_SOC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_BASE_LSB_ADDR, + HWIO_SOC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R2_SRC_RING_HP_ADDR, + }, + .reg_size = { + HWIO_SOC_CE_1_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_BASE_LSB_ADDR - + HWIO_SOC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_BASE_LSB_ADDR, + HWIO_SOC_CE_1_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_BASE_LSB_ADDR - + HWIO_SOC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_BASE_LSB_ADDR, + }, + .max_size = + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_SHFT + }, + { /* CE_DST */ + .start_ring_id = HAL_SRNG_CE_0_DST, + .max_rings = 12, + .entry_size = 8 >> 2, + /*TODO: entry_size above should actually be + * sizeof(struct ce_dst_desc) >> 2, but couldn't find definition + * of struct ce_dst_desc in HW header files + */ + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR, + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R2_DEST_RING_HP_ADDR, + }, + .reg_size = { + HWIO_SOC_CE_1_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR - + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR, + HWIO_SOC_CE_1_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR - + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR + }, + .max_size = + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_SHFT + }, + { /* CE_DST_STATUS */ + .start_ring_id = HAL_SRNG_CE_0_DST_STATUS, + .max_rings = 12, + .entry_size = sizeof(struct ce_stat_desc) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_LSB_ADDR, + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R2_STATUS_RING_HP_ADDR, + }, + /* TODO: check destination status ring registers */ + .reg_size = { + HWIO_SOC_CE_1_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR - + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR, + HWIO_SOC_CE_1_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR - + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR + }, + .max_size = + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_SOC_CE_0_DST_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* WBM_IDLE_LINK */ + .start_ring_id = HAL_SRNG_WBM_IDLE_LINK, + .max_rings = 1, + .entry_size = sizeof(struct wbm_link_descriptor_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_WBM_IDLE_LINK_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* SW2WBM_RELEASE */ + .start_ring_id = HAL_SRNG_WBM_SW_RELEASE, + .max_rings = 1, + .entry_size = sizeof(struct wbm_release_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_WBM_R0_SW_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_SW_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_WBM_R0_SW_RELEASE_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WBM_R0_SW_RELEASE_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* WBM2SW_RELEASE */ + .start_ring_id = HAL_SRNG_WBM2SW0_RELEASE, + .max_rings = 4, + .entry_size = sizeof(struct wbm_release_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_WBM2SW0_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + .reg_size = { + HWIO_WBM_R0_WBM2SW1_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET) - + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_WBM2SW1_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET) - + HWIO_WBM_R2_WBM2SW0_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + .max_size = + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* RXDMA_BUF */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA0_BUF0, +#ifdef IPA_OFFLOAD + .max_rings = 3, +#else + .max_rings = 2, +#endif + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_DST */ + .start_ring_id = HAL_SRNG_WMAC1_RXDMA2SW0, + .max_rings = 1, + .entry_size = sizeof(struct reo_entrance_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_DST_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_BUF */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA2_BUF, + .max_rings = 1, + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_STATUS */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA1_STATBUF, + .max_rings = 1, + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_DST */ + .start_ring_id = HAL_SRNG_WMAC1_RXDMA2SW1, + .max_rings = 1, + .entry_size = sizeof(struct reo_entrance_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_DST_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_DESC */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA1_DESC, + .max_rings = 1, + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* DIR_BUF_RX_DMA_SRC */ + .start_ring_id = HAL_SRNG_DIR_BUF_RX_SRC_DMA_RING, + .max_rings = 1, + .entry_size = 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, +#ifdef WLAN_FEATURE_CIF_CFR + { /* WIFI_POS_SRC */ + .start_ring_id = HAL_SRNG_WIFI_POS_SRC_DMA_RING, + .max_rings = 1, + .entry_size = sizeof(wmi_oem_dma_buf_release_entry) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, +#endif +}; + +int32_t hal_hw_reg_offset_qca6750[] = { + /* dst */ + REG_OFFSET(DST, HP), + REG_OFFSET(DST, TP), + REG_OFFSET(DST, ID), + REG_OFFSET(DST, MISC), + REG_OFFSET(DST, HP_ADDR_LSB), + REG_OFFSET(DST, HP_ADDR_MSB), + REG_OFFSET(DST, MSI1_BASE_LSB), + REG_OFFSET(DST, MSI1_BASE_MSB), + REG_OFFSET(DST, MSI1_DATA), + REG_OFFSET(DST, BASE_LSB), + REG_OFFSET(DST, BASE_MSB), + REG_OFFSET(DST, PRODUCER_INT_SETUP), + /* src */ + REG_OFFSET(SRC, HP), + REG_OFFSET(SRC, TP), + REG_OFFSET(SRC, ID), + REG_OFFSET(SRC, MISC), + REG_OFFSET(SRC, TP_ADDR_LSB), + REG_OFFSET(SRC, TP_ADDR_MSB), + REG_OFFSET(SRC, MSI1_BASE_LSB), + REG_OFFSET(SRC, MSI1_BASE_MSB), + REG_OFFSET(SRC, MSI1_DATA), + REG_OFFSET(SRC, BASE_LSB), + REG_OFFSET(SRC, BASE_MSB), + REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX0), + REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX1), +}; + +/** + * hal_qca6750_attach() - Attach 6750 target specific hal_soc ops, + * offset and srng table + */ +void hal_qca6750_attach(struct hal_soc *hal_soc) +{ + hal_soc->hw_srng_table = hw_srng_table_6750; + hal_soc->hal_hw_reg_offset = hal_hw_reg_offset_qca6750; + hal_soc->ops = &qca6750_hal_hw_txrx_ops; +} diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6750/hal_6750_rx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6750/hal_6750_rx.h new file mode 100644 index 0000000000000000000000000000000000000000..10f70c5e0cc5f6113abe837eac2a378fee7274e4 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6750/hal_6750_rx.h @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _HAL_6750_RX_H_ +#define _HAL_6750_RX_H_ +#include "qdf_util.h" +#include "qdf_types.h" +#include "qdf_lock.h" +#include "qdf_mem.h" +#include "qdf_nbuf.h" +#include "tcl_data_cmd.h" +#include "mac_tcl_reg_seq_hwioreg.h" +#include "phyrx_rssi_legacy.h" +#include "rx_msdu_start.h" +#include "tlv_tag_def.h" +#include "hal_hw_headers.h" +#include "hal_internal.h" +#include "cdp_txrx_mon_struct.h" +#include "qdf_trace.h" +#include "hal_rx.h" +#include "hal_tx.h" +#include "dp_types.h" +#include "hal_api_mon.h" +#include "phyrx_other_receive_info_ru_details.h" + +#define HAL_RX_MSDU_START_MIMO_SS_BITMAP(_rx_msdu_start)\ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\ + RX_MSDU_START_5_MIMO_SS_BITMAP_OFFSET)), \ + RX_MSDU_START_5_MIMO_SS_BITMAP_MASK, \ + RX_MSDU_START_5_MIMO_SS_BITMAP_LSB)) + +#define HAL_RX_MPDU_GET_SEQUENCE_NUMBER(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_NUMBER_OFFSET)), \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_NUMBER_MASK, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_NUMBER_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_MCBC_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_DA_IS_MCBC_OFFSET)), \ + RX_MSDU_END_10_DA_IS_MCBC_MASK, \ + RX_MSDU_END_10_DA_IS_MCBC_LSB)) + +#define HAL_RX_MSDU_END_SA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_SA_IS_VALID_OFFSET)), \ + RX_MSDU_END_10_SA_IS_VALID_MASK, \ + RX_MSDU_END_10_SA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_11_SA_IDX_OFFSET)), \ + RX_MSDU_END_11_SA_IDX_MASK, \ + RX_MSDU_END_11_SA_IDX_LSB)) + +#define HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_L3_HEADER_PADDING_OFFSET)), \ + RX_MSDU_END_10_L3_HEADER_PADDING_MASK, \ + RX_MSDU_END_10_L3_HEADER_PADDING_LSB)) + +#define HAL_RX_MPDU_ENCRYPTION_INFO_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_FRAME_ENCRYPTION_INFO_VALID_OFFSET)), \ + RX_MPDU_INFO_11_FRAME_ENCRYPTION_INFO_VALID_MASK, \ + RX_MPDU_INFO_11_FRAME_ENCRYPTION_INFO_VALID_LSB)) + +#define HAL_RX_MPDU_PN_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_3_PN_31_0_OFFSET)), \ + RX_MPDU_INFO_3_PN_31_0_MASK, \ + RX_MPDU_INFO_3_PN_31_0_LSB)) + +#define HAL_RX_MPDU_PN_63_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_4_PN_63_32_OFFSET)), \ + RX_MPDU_INFO_4_PN_63_32_MASK, \ + RX_MPDU_INFO_4_PN_63_32_LSB)) + +#define HAL_RX_MPDU_PN_95_64_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_5_PN_95_64_OFFSET)), \ + RX_MPDU_INFO_5_PN_95_64_MASK, \ + RX_MPDU_INFO_5_PN_95_64_LSB)) + +#define HAL_RX_MPDU_PN_127_96_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_6_PN_127_96_OFFSET)), \ + RX_MPDU_INFO_6_PN_127_96_MASK, \ + RX_MPDU_INFO_6_PN_127_96_LSB)) + +#define HAL_RX_MSDU_END_FIRST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_FIRST_MSDU_OFFSET)), \ + RX_MSDU_END_10_FIRST_MSDU_MASK, \ + RX_MSDU_END_10_FIRST_MSDU_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_DA_IS_VALID_OFFSET)), \ + RX_MSDU_END_10_DA_IS_VALID_MASK, \ + RX_MSDU_END_10_DA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_LAST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_LAST_MSDU_OFFSET)), \ + RX_MSDU_END_10_LAST_MSDU_MASK, \ + RX_MSDU_END_10_LAST_MSDU_LSB)) + +#define HAL_RX_MPDU_GET_MAC_AD4_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_SW_PEER_ID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_10_SW_PEER_ID_OFFSET)), \ + RX_MPDU_INFO_10_SW_PEER_ID_MASK, \ + RX_MPDU_INFO_10_SW_PEER_ID_LSB)) + +#define HAL_RX_MPDU_GET_TODS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_TO_DS_OFFSET)), \ + RX_MPDU_INFO_11_TO_DS_MASK, \ + RX_MPDU_INFO_11_TO_DS_LSB)) + +#define HAL_RX_MPDU_GET_FROMDS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_FR_DS_OFFSET)), \ + RX_MPDU_INFO_11_FR_DS_MASK, \ + RX_MPDU_INFO_11_FR_DS_LSB)) + +#define HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MPDU_FRAME_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MPDU_FRAME_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_11_MPDU_FRAME_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD1_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD1_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD1_VALID_LSB)) + +#define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_MASK, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_LSB)) + +#define HAL_RX_MPDU_AD1_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD2_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD2_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD2_VALID_LSB)) + +#define HAL_RX_MPDU_AD2_15_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_LSB)) + +#define HAL_RX_MPDU_AD2_47_16_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_OFFSET)), \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_MASK, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD3_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD3_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD3_VALID_LSB)) + +#define HAL_RX_MPDU_AD3_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_OFFSET)), \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_MASK, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_LSB)) + +#define HAL_RX_MPDU_AD3_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_OFFSET)), \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_MASK, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_AD4_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_OFFSET)), \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_MASK, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_LSB)) + +#define HAL_RX_MPDU_AD4_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_OFFSET)), \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_MASK, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_LSB)) + +#define HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_OFFSET)),\ + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_14_SA_SW_PEER_ID_OFFSET)), \ + RX_MSDU_END_14_SA_SW_PEER_ID_MASK, \ + RX_MSDU_END_14_SA_SW_PEER_ID_LSB)) + +#define HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va) \ + (uint8_t *)(link_desc_va) + \ + RX_MSDU_LINK_8_MSDU_0_BUFFER_ADDR_INFO_DETAILS_BUFFER_ADDR_31_0_OFFSET + +#define HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0) \ + (uint8_t *)(msdu0) + \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_DETAILS_FIRST_MSDU_IN_MPDU_FLAG_OFFSET + +#define HAL_ENT_MPDU_DESC_INFO(ent_ring_desc) \ + (uint8_t *)(ent_ring_desc) + \ + RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_DETAILS_MPDU_SEQUENCE_NUMBER_OFFSET + +#define HAL_DST_MPDU_DESC_INFO(dst_ring_desc) \ + (uint8_t *)(dst_ring_desc) + \ + REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_DETAILS_MSDU_COUNT_OFFSET + +#define HAL_RX_GET_FC_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, MPDU_FRAME_CONTROL_VALID) + +#define HAL_RX_GET_TO_DS_FLAG(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, TO_DS) + +#define HAL_RX_GET_MAC_ADDR1_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, MAC_ADDR_AD1_VALID) + +#define HAL_RX_GET_MAC_ADDR2_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, MAC_ADDR_AD2_VALID) + +#define HAL_RX_GET_FILTER_CATEGORY(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_9, RXPCU_MPDU_FILTER_IN_CATEGORY) + +#define HAL_RX_GET_PPDU_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_9, PHY_PPDU_ID) + +#define HAL_RX_GET_SW_FRAME_GROUP_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_9, SW_FRAME_GROUP_ID) + +#define HAL_REO_R0_CONFIG(soc, reg_val, reo_params) \ + do { \ + reg_val &= \ + ~(HWIO_REO_R0_GENERAL_ENABLE_AGING_LIST_ENABLE_BMSK |\ + HWIO_REO_R0_GENERAL_ENABLE_AGING_FLUSH_ENABLE_BMSK); \ + reg_val |= \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_LIST_ENABLE, 1) |\ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_FLUSH_ENABLE, 1);\ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ + reg_val = \ + HAL_REG_READ((soc), \ + HWIO_REO_R0_MISC_CTL_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET)); \ + reg_val &= \ + ~(HWIO_REO_R0_MISC_CTL_FRAGMENT_DEST_RING_BMSK); \ + reg_val |= \ + HAL_SM(HWIO_REO_R0_MISC_CTL, \ + FRAGMENT_DEST_RING, \ + (reo_params)->frag_dst_ring); \ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_MISC_CTL_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ + } while (0) + +#define HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr) \ + ((struct rx_msdu_desc_info *) \ + _OFFSET_TO_BYTE_PTR(msdu_details_ptr, \ +RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_DETAILS_RESERVED_0A_OFFSET)) + +#define HAL_RX_LINK_DESC_MSDU0_PTR(link_desc) \ + ((struct rx_msdu_details *) \ + _OFFSET_TO_BYTE_PTR((link_desc),\ + RX_MSDU_LINK_8_MSDU_0_BUFFER_ADDR_INFO_DETAILS_BUFFER_ADDR_31_0_OFFSET)) + +#define HAL_RX_MSDU_END_FLOW_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_12_FLOW_IDX_OFFSET)), \ + RX_MSDU_END_12_FLOW_IDX_MASK, \ + RX_MSDU_END_12_FLOW_IDX_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_FLOW_IDX_INVALID_OFFSET)), \ + RX_MSDU_END_10_FLOW_IDX_INVALID_MASK, \ + RX_MSDU_END_10_FLOW_IDX_INVALID_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_FLOW_IDX_TIMEOUT_OFFSET)), \ + RX_MSDU_END_10_FLOW_IDX_TIMEOUT_MASK, \ + RX_MSDU_END_10_FLOW_IDX_TIMEOUT_LSB)) + +#define HAL_RX_MSDU_END_FSE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_13_FSE_METADATA_OFFSET)), \ + RX_MSDU_END_13_FSE_METADATA_MASK, \ + RX_MSDU_END_13_FSE_METADATA_LSB)) + +#define HAL_RX_MSDU_END_CCE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_14_CCE_METADATA_OFFSET)), \ + RX_MSDU_END_14_CCE_METADATA_MASK, \ + RX_MSDU_END_14_CCE_METADATA_LSB)) + +#define HAL_RX_TLV_GET_TCP_CHKSUM(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_10_TCP_UDP_CHKSUM_OFFSET)), \ + RX_MSDU_END_10_TCP_UDP_CHKSUM_MASK, \ + RX_MSDU_END_10_TCP_UDP_CHKSUM_LSB)) + +#define HAL_RX_MSDU_END_DA_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_11_DA_IDX_OR_SW_PEER_ID_OFFSET)), \ + RX_MSDU_END_11_DA_IDX_OR_SW_PEER_ID_MASK, \ + RX_MSDU_END_11_DA_IDX_OR_SW_PEER_ID_LSB)) +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6750/hal_6750_tx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6750/hal_6750_tx.h new file mode 100644 index 0000000000000000000000000000000000000000..422b775ef8e1a56ad0abc5b4652b5ac31ad7ad05 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca6750/hal_6750_tx.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _HAL_6750_TX_H_ +#define _HAL_6750_TX_H_ +#include "tcl_data_cmd.h" +#include "mac_tcl_reg_seq_hwioreg.h" +#include "phyrx_rssi_legacy.h" +#include "hal_hw_headers.h" +#include "hal_internal.h" +#include "cdp_txrx_mon_struct.h" +#include "qdf_trace.h" +#include "hal_rx.h" +#include "hal_tx.h" +#include "dp_types.h" +#include "hal_api_mon.h" + +/** + * hal_tx_desc_set_dscp_tid_table_id_6750() - Sets DSCP to TID conversion + * table ID + * @desc: Handle to Tx Descriptor + * @id: DSCP to tid conversion table to be used for this frame + * + * Return: void + */ +static void hal_tx_desc_set_dscp_tid_table_id_6750(void *desc, uint8_t id) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_5, + DSCP_TID_TABLE_NUM) |= + HAL_TX_SM(TCL_DATA_CMD_5, + DSCP_TID_TABLE_NUM, id); +} + +#define DSCP_TID_TABLE_SIZE 24 +#define NUM_WORDS_PER_DSCP_TID_TABLE (DSCP_TID_TABLE_SIZE / 4) + +/** + * hal_tx_set_dscp_tid_map_6750() - Configure default DSCP to TID map table + * @soc: HAL SoC context + * @map: DSCP-TID mapping table + * @id: mapping table ID - 0-31 + * + * DSCP are mapped to 8 TID values using TID values programmed + * in any of the 32 DSCP_TID_MAPS (id = 0-31). + * + * Return: none + */ +static void hal_tx_set_dscp_tid_map_6750(struct hal_soc *hal_soc, uint8_t *map, + uint8_t id) +{ + int i; + uint32_t addr, cmn_reg_addr; + uint32_t value = 0, regval; + uint8_t val[DSCP_TID_TABLE_SIZE], cnt = 0; + + struct hal_soc *soc = (struct hal_soc *)hal_soc; + + if (id >= HAL_MAX_HW_DSCP_TID_MAPS_11AX) + return; + + cmn_reg_addr = HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET); + + addr = HWIO_TCL_R0_DSCP_TID_MAP_n_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET, + id * NUM_WORDS_PER_DSCP_TID_TABLE); + + /* Enable read/write access */ + regval = HAL_REG_READ(soc, cmn_reg_addr); + regval |= + (1 << + HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_DSCP_TID_MAP_PROGRAM_EN_SHFT); + + HAL_REG_WRITE(soc, cmn_reg_addr, regval); + + /* Write 8 (24 bits) DSCP-TID mappings in each interation */ + for (i = 0; i < 64; i += 8) { + value = (map[i] | + (map[i + 1] << 0x3) | + (map[i + 2] << 0x6) | + (map[i + 3] << 0x9) | + (map[i + 4] << 0xc) | + (map[i + 5] << 0xf) | + (map[i + 6] << 0x12) | + (map[i + 7] << 0x15)); + + qdf_mem_copy(&val[cnt], (void *)&value, 3); + cnt += 3; + } + + for (i = 0; i < DSCP_TID_TABLE_SIZE; i += 4) { + regval = *(uint32_t *)(val + i); + HAL_REG_WRITE(soc, addr, + (regval & HWIO_TCL_R0_DSCP_TID_MAP_n_RMSK)); + addr += 4; + } + + /* Diasble read/write access */ + regval = HAL_REG_READ(soc, cmn_reg_addr); + regval &= + ~(HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_DSCP_TID_MAP_PROGRAM_EN_BMSK); + + HAL_REG_WRITE(soc, cmn_reg_addr, regval); +} + +/** + * hal_tx_update_dscp_tid_6750() - Update the dscp tid map table as updated + * by the user + * @soc: HAL SoC context + * @map: DSCP-TID mapping table + * @id : MAP ID + * @dscp: DSCP_TID map index + * + * Return: void + */ +static void hal_tx_update_dscp_tid_6750(struct hal_soc *hal_soc, uint8_t tid, + uint8_t id, uint8_t dscp) +{ + int index; + uint32_t addr; + uint32_t value; + uint32_t regval; + struct hal_soc *soc = (struct hal_soc *)hal_soc; + + addr = HWIO_TCL_R0_DSCP_TID_MAP_n_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET, id); + + index = dscp % HAL_TX_NUM_DSCP_PER_REGISTER; + addr += 4 * (dscp / HAL_TX_NUM_DSCP_PER_REGISTER); + value = tid << (HAL_TX_BITS_PER_TID * index); + + regval = HAL_REG_READ(soc, addr); + regval &= ~(HAL_TX_TID_BITS_MASK << (HAL_TX_BITS_PER_TID * index)); + regval |= value; + + HAL_REG_WRITE(soc, addr, (regval & HWIO_TCL_R0_DSCP_TID_MAP_n_RMSK)); +} + +/** + * hal_tx_desc_set_lmac_id_6750 - Set the lmac_id value + * @desc: Handle to Tx Descriptor + * @lmac_id: mac Id to ast matching + * b00 – mac 0 + * b01 – mac 1 + * b10 – mac 2 + * b11 – all macs (legacy HK way) + * + * Return: void + */ +static void hal_tx_desc_set_lmac_id_6750(void *desc, uint8_t lmac_id) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_4, LMAC_ID) |= + HAL_TX_SM(TCL_DATA_CMD_4, LMAC_ID, lmac_id); +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1.c b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1.c index 4be906748e2cb1bdcf707279336f25f191b0f561..2296029949a67cd38057f1c774977477001f1070 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1.c +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -104,6 +104,886 @@ #include #include +/** + * hal_get_window_address_8074(): Function to get hp/tp address + * @hal_soc: Pointer to hal_soc + * @addr: address offset of register + * + * Return: modified address offset of register + */ +static inline qdf_iomem_t hal_get_window_address_8074(struct hal_soc *hal_soc, + qdf_iomem_t addr) +{ + return addr; +} + +/** + * hal_rx_get_rx_fragment_number_8074v1(): Function to retrieve + * rx fragment number + * + * @nbuf: Network buffer + * Returns: rx fragment number + */ +static +uint8_t hal_rx_get_rx_fragment_number_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + /* Return first 4 bits as fragment number */ + return (HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info) & + DOT11_SEQ_FRAG_MASK); +} + +/** + * hal_rx_msdu_end_da_is_mcbc_get_8074v1(): API to check if + * pkt is MCBC from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_mcbc + */ +static uint8_t +hal_rx_msdu_end_da_is_mcbc_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_DA_IS_MCBC_GET(msdu_end); +} + +/** + * hal_rx_msdu_end_sa_is_valid_get_8074v1(): API to get_8074v1 the + * sa_is_valid bit from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_is_valid bit + */ +static uint8_t +hal_rx_msdu_end_sa_is_valid_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t sa_is_valid; + + sa_is_valid = HAL_RX_MSDU_END_SA_IS_VALID_GET(msdu_end); + + return sa_is_valid; +} + +/** + * hal_rx_msdu_end_sa_idx_get_8074v1(): API to get_8074v1 the + * sa_idx from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_idx (SA AST index) + */ +static uint16_t hal_rx_msdu_end_sa_idx_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint16_t sa_idx; + + sa_idx = HAL_RX_MSDU_END_SA_IDX_GET(msdu_end); + + return sa_idx; +} + +/** + * hal_rx_desc_is_first_msdu_8074v1() - Check if first msdu + * + * @hal_soc_hdl: hal_soc handle + * @hw_desc_addr: hardware descriptor address + * + * Return: 0 - success/ non-zero failure + */ +static uint32_t hal_rx_desc_is_first_msdu_8074v1(void *hw_desc_addr) +{ + struct rx_pkt_tlvs *rx_tlvs = (struct rx_pkt_tlvs *)hw_desc_addr; + struct rx_msdu_end *msdu_end = &rx_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_GET(msdu_end, RX_MSDU_END_5, FIRST_MSDU); +} + +/** + * hal_rx_msdu_end_l3_hdr_padding_get_8074v1(): API to get_8074v1 the + * l3_header padding from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: number of l3 header padding bytes + */ +static uint32_t hal_rx_msdu_end_l3_hdr_padding_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint32_t l3_header_padding; + + l3_header_padding = HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(msdu_end); + + return l3_header_padding; +} + +/* + * @ hal_rx_encryption_info_valid_8074v1: Returns encryption type. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: encryption type + */ +static uint32_t hal_rx_encryption_info_valid_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + uint32_t encryption_info = HAL_RX_MPDU_ENCRYPTION_INFO_VALID(mpdu_info); + + return encryption_info; +} + +/* + * @ hal_rx_print_pn_8074v1: Prints the PN of rx packet. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: void + */ +static void hal_rx_print_pn_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + uint32_t pn_31_0 = HAL_RX_MPDU_PN_31_0_GET(mpdu_info); + uint32_t pn_63_32 = HAL_RX_MPDU_PN_63_32_GET(mpdu_info); + uint32_t pn_95_64 = HAL_RX_MPDU_PN_95_64_GET(mpdu_info); + uint32_t pn_127_96 = HAL_RX_MPDU_PN_127_96_GET(mpdu_info); + + hal_debug("PN number pn_127_96 0x%x pn_95_64 0x%x pn_63_32 0x%x pn_31_0 0x%x ", + pn_127_96, pn_95_64, pn_63_32, pn_31_0); +} + +/** + * hal_rx_msdu_end_first_msdu_get_8074v1: API to get first msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: first_msdu + */ +static uint8_t +hal_rx_msdu_end_first_msdu_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t first_msdu; + + first_msdu = HAL_RX_MSDU_END_FIRST_MSDU_GET(msdu_end); + + return first_msdu; +} + +/** + * hal_rx_msdu_end_da_is_valid_get_8074v1: API to check if da is valid + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_valid + */ +static uint8_t hal_rx_msdu_end_da_is_valid_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t da_is_valid; + + da_is_valid = HAL_RX_MSDU_END_DA_IS_VALID_GET(msdu_end); + + return da_is_valid; +} + +/** + * hal_rx_msdu_end_last_msdu_get_8074v1: API to get last msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: last_msdu + */ +static uint8_t hal_rx_msdu_end_last_msdu_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t last_msdu; + + last_msdu = HAL_RX_MSDU_END_LAST_MSDU_GET(msdu_end); + + return last_msdu; +} + +/* + * hal_rx_get_mpdu_mac_ad4_valid_8074v1(): Retrieves if mpdu 4th addr is valid + * + * @nbuf: Network buffer + * Returns: value of mpdu 4th address valid field + */ +static bool hal_rx_get_mpdu_mac_ad4_valid_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + bool ad4_valid = 0; + + ad4_valid = HAL_RX_MPDU_GET_MAC_AD4_VALID(rx_mpdu_info); + + return ad4_valid; +} + +/** + * hal_rx_mpdu_start_sw_peer_id_get_8074v1: Retrieve sw peer_id + * @buf: network buffer + * + * Return: sw peer_id + */ +static uint32_t hal_rx_mpdu_start_sw_peer_id_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_SW_PEER_ID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/* + * hal_rx_mpdu_get_to_ds_8074v1(): API to get the tods info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(to_ds) + */ + +static uint32_t hal_rx_mpdu_get_to_ds_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_TODS(mpdu_info); +} + +/* + * hal_rx_mpdu_get_fr_ds_8074v1(): API to get the from ds info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(fr_ds) + */ +static uint32_t hal_rx_mpdu_get_fr_ds_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_FROMDS(mpdu_info); +} + +/* + * hal_rx_get_mpdu_frame_control_valid_8074v1(): Retrieves mpdu + * frame control valid + * + * @nbuf: Network buffer + * Returns: value of frame control valid field + */ +static uint8_t hal_rx_get_mpdu_frame_control_valid_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(rx_mpdu_info); +} + +/* + * hal_rx_mpdu_get_addr1_8074v1(): API to check get address1 of the mpdu + * + * @buf: pointer to the start of RX PKT TLV headera + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr1_8074v1(uint8_t *buf, + uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr1 { + uint32_t ad1_31_0; + uint16_t ad1_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr1 *addr = (struct hal_addr1 *)mac_addr; + uint32_t mac_addr_ad1_valid; + + mac_addr_ad1_valid = HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(mpdu_info); + + if (mac_addr_ad1_valid) { + addr->ad1_31_0 = HAL_RX_MPDU_AD1_31_0_GET(mpdu_info); + addr->ad1_47_32 = HAL_RX_MPDU_AD1_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr2_8074v1(): API to check get address2 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr2_8074v1(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr2 { + uint16_t ad2_15_0; + uint32_t ad2_47_16; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr2 *addr = (struct hal_addr2 *)mac_addr; + uint32_t mac_addr_ad2_valid; + + mac_addr_ad2_valid = HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(mpdu_info); + + if (mac_addr_ad2_valid) { + addr->ad2_15_0 = HAL_RX_MPDU_AD2_15_0_GET(mpdu_info); + addr->ad2_47_16 = HAL_RX_MPDU_AD2_47_16_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr3_8074v1(): API to get address3 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr3_8074v1(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr3 { + uint32_t ad3_31_0; + uint16_t ad3_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr3 *addr = (struct hal_addr3 *)mac_addr; + uint32_t mac_addr_ad3_valid; + + mac_addr_ad3_valid = HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(mpdu_info); + + if (mac_addr_ad3_valid) { + addr->ad3_31_0 = HAL_RX_MPDU_AD3_31_0_GET(mpdu_info); + addr->ad3_47_32 = HAL_RX_MPDU_AD3_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr4_8074v1(): API to get address4 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr4_8074v1(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr4 { + uint32_t ad4_31_0; + uint16_t ad4_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr4 *addr = (struct hal_addr4 *)mac_addr; + uint32_t mac_addr_ad4_valid; + + mac_addr_ad4_valid = HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(mpdu_info); + + if (mac_addr_ad4_valid) { + addr->ad4_31_0 = HAL_RX_MPDU_AD4_31_0_GET(mpdu_info); + addr->ad4_47_32 = HAL_RX_MPDU_AD4_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_get_mpdu_sequence_control_valid_8074v1(): Get mpdu + * sequence control valid + * + * @nbuf: Network buffer + * Returns: value of sequence control valid field + */ +static uint8_t hal_rx_get_mpdu_sequence_control_valid_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(rx_mpdu_info); +} + +/** + * hal_rx_is_unicast_8074v1: check packet is unicast frame or not. + * + * @ buf: pointer to rx pkt TLV. + * + * Return: true on unicast. + */ +static bool hal_rx_is_unicast_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint32_t grp_id; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + + grp_id = (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_OFFSET)), + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_MASK, + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_LSB)); + + return (HAL_MPDU_SW_FRAME_GROUP_UNICAST_DATA == grp_id) ? true : false; +} + +/** + * hal_rx_tid_get_8074v1: get tid based on qos control valid. + * + * @ buf: pointer to rx pkt TLV. + * + * Return: tid + */ +static uint32_t hal_rx_tid_get_8074v1(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + uint8_t qos_control_valid = + (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_OFFSET)), + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_MASK, + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_LSB)); + + if (qos_control_valid) + return hal_rx_mpdu_start_tid_get_8074(buf); + + return HAL_RX_NON_QOS_TID; +} + +/** + * hal_rx_hw_desc_get_ppduid_get_8074v1(): retrieve ppdu id + * @hw_desc_addr: hw addr + * + * Return: ppdu id + */ +static uint32_t hal_rx_hw_desc_get_ppduid_get_8074v1(void *hw_desc_addr) +{ + struct rx_mpdu_info *rx_mpdu_info; + struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + + rx_mpdu_info = + &rx_desc->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + + return HAL_RX_GET(rx_mpdu_info, RX_MPDU_INFO_0, PHY_PPDU_ID); +} + +/** + * hal_reo_status_get_header_8074v1 - Process reo desc info + * @d - Pointer to reo descriptior + * @b - tlv type info + * @h1 - Pointer to hal_reo_status_header where info to be stored + * + * Return - none. + * + */ +static void hal_reo_status_get_header_8074v1(uint32_t *d, int b, void *h1) +{ + uint32_t val1 = 0; + struct hal_reo_status_header *h = + (struct hal_reo_status_header *)h1; + + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->cmd_num = + HAL_GET_FIELD( + UNIFORM_REO_STATUS_HEADER_0, REO_STATUS_NUMBER, + val1); + h->exec_time = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + CMD_EXECUTION_TIME, val1); + h->status = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + REO_CMD_EXECUTION_STATUS, val1); + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->tstamp = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_1, TIMESTAMP, val1); +} + +/** + * hal_rx_mpdu_start_mpdu_qos_control_valid_get_8074v1(): + * Retrieve qos control valid bit from the tlv. + * @buf: pointer to rx pkt TLV. + * + * Return: qos control value. + */ +static inline uint32_t +hal_rx_mpdu_start_mpdu_qos_control_valid_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/** + * hal_rx_msdu_end_sa_sw_peer_id_get_8074v1(): API to get the + * sa_sw_peer_id from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: sa_sw_peer_id index + */ +static inline uint32_t +hal_rx_msdu_end_sa_sw_peer_id_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(msdu_end); +} + +/** + * hal_tx_desc_set_mesh_en_8074v1 - Set mesh_enable flag in Tx descriptor + * @desc: Handle to Tx Descriptor + * @en: For raw WiFi frames, this indicates transmission to a mesh STA, + * enabling the interpretation of the 'Mesh Control Present' bit + * (bit 8) of QoS Control (otherwise this bit is ignored), + * For native WiFi frames, this indicates that a 'Mesh Control' field + * is present between the header and the LLC. + * + * Return: void + */ +static inline +void hal_tx_desc_set_mesh_en_8074v1(void *desc, uint8_t en) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_4, MESH_ENABLE) |= + HAL_TX_SM(TCL_DATA_CMD_4, MESH_ENABLE, en); +} + +static +void *hal_rx_msdu0_buffer_addr_lsb_8074v1(void *link_desc_va) +{ + return (void *)HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va); +} + +static +void *hal_rx_msdu_desc_info_ptr_get_8074v1(void *msdu0) +{ + return (void *)HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0); +} + +static +void *hal_ent_mpdu_desc_info_8074v1(void *ent_ring_desc) +{ + return (void *)HAL_ENT_MPDU_DESC_INFO(ent_ring_desc); +} + +static +void *hal_dst_mpdu_desc_info_8074v1(void *dst_ring_desc) +{ + return (void *)HAL_DST_MPDU_DESC_INFO(dst_ring_desc); +} + +static +uint8_t hal_rx_get_fc_valid_8074v1(uint8_t *buf) +{ + return HAL_RX_GET_FC_VALID(buf); +} + +static uint8_t hal_rx_get_to_ds_flag_8074v1(uint8_t *buf) +{ + return HAL_RX_GET_TO_DS_FLAG(buf); +} + +static uint8_t hal_rx_get_mac_addr2_valid_8074v1(uint8_t *buf) +{ + return HAL_RX_GET_MAC_ADDR2_VALID(buf); +} + +static uint8_t hal_rx_get_filter_category_8074v1(uint8_t *buf) +{ + return HAL_RX_GET_FILTER_CATEGORY(buf); +} + +static uint32_t +hal_rx_get_ppdu_id_8074v1(uint8_t *buf) +{ + return HAL_RX_GET_PPDU_ID(buf); +} + +/** + * hal_reo_config_8074v1(): Set reo config parameters + * @soc: hal soc handle + * @reg_val: value to be set + * @reo_params: reo parameters + * + * Return: void + */ +static void +hal_reo_config_8074v1(struct hal_soc *soc, + uint32_t reg_val, + struct hal_reo_params *reo_params) +{ + HAL_REO_R0_CONFIG(soc, reg_val, reo_params); +} + +/** + * hal_rx_msdu_desc_info_get_ptr_8074v1() - Get msdu desc info ptr + * @msdu_details_ptr - Pointer to msdu_details_ptr + * + * Return - Pointer to rx_msdu_desc_info structure. + * + */ +static void *hal_rx_msdu_desc_info_get_ptr_8074v1(void *msdu_details_ptr) +{ + return HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr); +} + +/** + * hal_rx_link_desc_msdu0_ptr_8074v1 - Get pointer to rx_msdu details + * @link_desc - Pointer to link desc + * + * Return - Pointer to rx_msdu_details structure + * + */ +static void *hal_rx_link_desc_msdu0_ptr_8074v1(void *link_desc) +{ + return HAL_RX_LINK_DESC_MSDU0_PTR(link_desc); +} + +/** + * hal_rx_msdu_flow_idx_get_8074v1: API to get flow index + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index value from MSDU END TLV + */ +static inline uint32_t hal_rx_msdu_flow_idx_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_invalid_8074v1: API to get flow index invalid + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index invalid value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_invalid_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_timeout_8074v1: API to get flow index timeout + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index timeout value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_timeout_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); +} + +/** + * hal_rx_msdu_fse_metadata_get_8074v1: API to get FSE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: fse metadata value from MSDU END TLV + */ +static uint32_t hal_rx_msdu_fse_metadata_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FSE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_cce_metadata_get_8074v1: API to get CCE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: cce_metadata + */ +static uint16_t +hal_rx_msdu_cce_metadata_get_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_CCE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_get_flow_params_8074v1: API to get flow index, flow index invalid + * and flow index timeout from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * @flow_invalid: pointer to return value of flow_idx_valid + * @flow_timeout: pointer to return value of flow_idx_timeout + * @flow_index: pointer to return value of flow_idx + * + * Return: none + */ +static inline void +hal_rx_msdu_get_flow_params_8074v1(uint8_t *buf, + bool *flow_invalid, + bool *flow_timeout, + uint32_t *flow_index) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + *flow_invalid = HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); + *flow_timeout = HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); + *flow_index = HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_tlv_get_tcp_chksum_8074v1() - API to get tcp checksum + * @buf: rx_tlv_hdr + * + * Return: tcp checksum + */ +static uint16_t +hal_rx_tlv_get_tcp_chksum_8074v1(uint8_t *buf) +{ + return HAL_RX_TLV_GET_TCP_CHKSUM(buf); +} + +/** + * hal_rx_get_rx_sequence_8074v1(): Function to retrieve rx sequence number + * + * @nbuf: Network buffer + * Returns: rx sequence number + */ +static +uint16_t hal_rx_get_rx_sequence_8074v1(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info); +} struct hal_hw_txrx_ops qca8074_hal_hw_txrx_ops = { @@ -113,6 +993,7 @@ struct hal_hw_txrx_ops qca8074_hal_hw_txrx_ops = { hal_get_hw_hptp_generic, hal_reo_setup_generic, hal_setup_link_idle_list_generic, + hal_get_window_address_8074, NULL, /* tx */ @@ -123,9 +1004,11 @@ struct hal_hw_txrx_ops qca8074_hal_hw_txrx_ops = { hal_tx_desc_set_buf_addr_generic, hal_tx_desc_set_search_type_generic, hal_tx_desc_set_search_index_generic, + hal_tx_desc_set_cache_set_num_generic, hal_tx_comp_get_status_generic, hal_tx_comp_get_release_reason_generic, - + hal_get_wbm_internal_error_generic, + hal_tx_desc_set_mesh_en_8074v1, /* rx */ hal_rx_msdu_start_nss_get_8074, hal_rx_mon_hw_desc_get_mpdu_status_8074, @@ -137,9 +1020,9 @@ struct hal_hw_txrx_ops qca8074_hal_hw_txrx_ops = { hal_rx_mpdu_start_tid_get_8074, hal_rx_msdu_start_reception_type_get_8074, hal_rx_msdu_end_da_idx_get_8074, - hal_rx_msdu_desc_info_get_ptr_generic, - hal_rx_link_desc_msdu0_ptr_generic, - hal_reo_status_get_header_generic, + hal_rx_msdu_desc_info_get_ptr_8074v1, + hal_rx_link_desc_msdu0_ptr_8074v1, + hal_reo_status_get_header_8074v1, hal_rx_status_get_tlv_info_generic, hal_rx_wbm_err_info_get_generic, hal_rx_dump_mpdu_start_tlv_generic, @@ -147,6 +1030,60 @@ struct hal_hw_txrx_ops qca8074_hal_hw_txrx_ops = { hal_tx_set_pcp_tid_map_generic, hal_tx_update_pcp_tid_generic, hal_tx_update_tidmap_prty_generic, + hal_rx_get_rx_fragment_number_8074v1, + hal_rx_msdu_end_da_is_mcbc_get_8074v1, + hal_rx_msdu_end_sa_is_valid_get_8074v1, + hal_rx_msdu_end_sa_idx_get_8074v1, + hal_rx_desc_is_first_msdu_8074v1, + hal_rx_msdu_end_l3_hdr_padding_get_8074v1, + hal_rx_encryption_info_valid_8074v1, + hal_rx_print_pn_8074v1, + hal_rx_msdu_end_first_msdu_get_8074v1, + hal_rx_msdu_end_da_is_valid_get_8074v1, + hal_rx_msdu_end_last_msdu_get_8074v1, + hal_rx_get_mpdu_mac_ad4_valid_8074v1, + hal_rx_mpdu_start_sw_peer_id_get_8074v1, + hal_rx_mpdu_get_to_ds_8074v1, + hal_rx_mpdu_get_fr_ds_8074v1, + hal_rx_get_mpdu_frame_control_valid_8074v1, + hal_rx_mpdu_get_addr1_8074v1, + hal_rx_mpdu_get_addr2_8074v1, + hal_rx_mpdu_get_addr3_8074v1, + hal_rx_mpdu_get_addr4_8074v1, + hal_rx_get_mpdu_sequence_control_valid_8074v1, + hal_rx_is_unicast_8074v1, + hal_rx_tid_get_8074v1, + hal_rx_hw_desc_get_ppduid_get_8074v1, + hal_rx_mpdu_start_mpdu_qos_control_valid_get_8074v1, + hal_rx_msdu_end_sa_sw_peer_id_get_8074v1, + hal_rx_msdu0_buffer_addr_lsb_8074v1, + hal_rx_msdu_desc_info_ptr_get_8074v1, + hal_ent_mpdu_desc_info_8074v1, + hal_dst_mpdu_desc_info_8074v1, + hal_rx_get_fc_valid_8074v1, + hal_rx_get_to_ds_flag_8074v1, + hal_rx_get_mac_addr2_valid_8074v1, + hal_rx_get_filter_category_8074v1, + hal_rx_get_ppdu_id_8074v1, + hal_reo_config_8074v1, + hal_rx_msdu_flow_idx_get_8074v1, + hal_rx_msdu_flow_idx_invalid_8074v1, + hal_rx_msdu_flow_idx_timeout_8074v1, + hal_rx_msdu_fse_metadata_get_8074v1, + hal_rx_msdu_cce_metadata_get_8074v1, + hal_rx_msdu_get_flow_params_8074v1, + hal_rx_tlv_get_tcp_chksum_8074v1, + hal_rx_get_rx_sequence_8074v1, + NULL, + NULL, + /* rx - msdu fast path info fields */ + hal_rx_msdu_packet_metadata_get_generic, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; struct hal_hw_srng_config hw_srng_table_8074[] = { diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1_rx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1_rx.h index 597ab7b782c4a1c04939acf908b31224fba674b2..6df3e2d79928ab6328aafa2825c7d904a13c89e9 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1_rx.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1_rx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -24,6 +24,309 @@ #include "dp_types.h" #include "hal_api_mon.h" +#define HAL_RX_MPDU_GET_SEQUENCE_NUMBER(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_MASK, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_MCBC_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_DA_IS_MCBC_OFFSET)), \ + RX_MSDU_END_5_DA_IS_MCBC_MASK, \ + RX_MSDU_END_5_DA_IS_MCBC_LSB)) + +#define HAL_RX_MSDU_END_SA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_SA_IS_VALID_OFFSET)), \ + RX_MSDU_END_5_SA_IS_VALID_MASK, \ + RX_MSDU_END_5_SA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_13_SA_IDX_OFFSET)), \ + RX_MSDU_END_13_SA_IDX_MASK, \ + RX_MSDU_END_13_SA_IDX_LSB)) + +#define HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_L3_HEADER_PADDING_OFFSET)), \ + RX_MSDU_END_5_L3_HEADER_PADDING_MASK, \ + RX_MSDU_END_5_L3_HEADER_PADDING_LSB)) + +#define HAL_RX_MPDU_ENCRYPTION_INFO_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_OFFSET)), \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_MASK, \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_LSB)) + +#define HAL_RX_MPDU_PN_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_4_PN_31_0_OFFSET)), \ + RX_MPDU_INFO_4_PN_31_0_MASK, \ + RX_MPDU_INFO_4_PN_31_0_LSB)) + +#define HAL_RX_MPDU_PN_63_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_5_PN_63_32_OFFSET)), \ + RX_MPDU_INFO_5_PN_63_32_MASK, \ + RX_MPDU_INFO_5_PN_63_32_LSB)) + +#define HAL_RX_MPDU_PN_95_64_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_6_PN_95_64_OFFSET)), \ + RX_MPDU_INFO_6_PN_95_64_MASK, \ + RX_MPDU_INFO_6_PN_95_64_LSB)) + +#define HAL_RX_MPDU_PN_127_96_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_7_PN_127_96_OFFSET)), \ + RX_MPDU_INFO_7_PN_127_96_MASK, \ + RX_MPDU_INFO_7_PN_127_96_LSB)) + +#define HAL_RX_MSDU_END_FIRST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FIRST_MSDU_OFFSET)), \ + RX_MSDU_END_5_FIRST_MSDU_MASK, \ + RX_MSDU_END_5_FIRST_MSDU_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_DA_IS_VALID_OFFSET)), \ + RX_MSDU_END_5_DA_IS_VALID_MASK, \ + RX_MSDU_END_5_DA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_LAST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_LAST_MSDU_OFFSET)), \ + RX_MSDU_END_5_LAST_MSDU_MASK, \ + RX_MSDU_END_5_LAST_MSDU_LSB)) + +#define HAL_RX_MPDU_GET_MAC_AD4_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_SW_PEER_ID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_1_SW_PEER_ID_OFFSET)), \ + RX_MPDU_INFO_1_SW_PEER_ID_MASK, \ + RX_MPDU_INFO_1_SW_PEER_ID_LSB)) + +#define HAL_RX_MPDU_GET_TODS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_TO_DS_OFFSET)), \ + RX_MPDU_INFO_2_TO_DS_MASK, \ + RX_MPDU_INFO_2_TO_DS_LSB)) + +#define HAL_RX_MPDU_GET_FROMDS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_FR_DS_OFFSET)), \ + RX_MPDU_INFO_2_FR_DS_MASK, \ + RX_MPDU_INFO_2_FR_DS_LSB)) + +#define HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_LSB)) + +#define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_MASK, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_LSB)) + +#define HAL_RX_MPDU_AD1_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_LSB)) + +#define HAL_RX_MPDU_AD2_15_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_LSB)) + +#define HAL_RX_MPDU_AD2_47_16_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_OFFSET)), \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_MASK, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_LSB)) + +#define HAL_RX_MPDU_AD3_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_OFFSET)), \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_MASK, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_LSB)) + +#define HAL_RX_MPDU_AD3_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_OFFSET)), \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_MASK, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_AD4_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_OFFSET)), \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_MASK, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_LSB)) + +#define HAL_RX_MPDU_AD4_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_OFFSET)), \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_MASK, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_LSB)) + +#define HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_16_SA_SW_PEER_ID_OFFSET)), \ + RX_MSDU_END_16_SA_SW_PEER_ID_MASK, \ + RX_MSDU_END_16_SA_SW_PEER_ID_LSB)) + +#define HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va) \ + (uint8_t *)(link_desc_va) + \ + RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET + +#define HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0) \ + (uint8_t *)(msdu0) + \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET + +#define HAL_ENT_MPDU_DESC_INFO(ent_ring_desc) \ + (uint8_t *)(ent_ring_desc) + \ + RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET + +#define HAL_DST_MPDU_DESC_INFO(dst_ring_desc) \ + (uint8_t *)(dst_ring_desc) + \ + REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET + +#define HAL_RX_GET_FC_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MPDU_FRAME_CONTROL_VALID) + +#define HAL_RX_GET_TO_DS_FLAG(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, TO_DS) + +#define HAL_RX_GET_MAC_ADDR1_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MAC_ADDR_AD1_VALID) + +#define HAL_RX_GET_MAC_ADDR2_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MAC_ADDR_AD2_VALID) + +#define HAL_RX_GET_FILTER_CATEGORY(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, RXPCU_MPDU_FILTER_IN_CATEGORY) + +#define HAL_RX_GET_PPDU_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, PHY_PPDU_ID) + +#define HAL_RX_GET_SW_FRAME_GROUP_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, SW_FRAME_GROUP_ID) + +#define HAL_REO_R0_CONFIG(soc, reg_val, reo_params) \ + do { \ + reg_val &= \ + ~(HWIO_REO_R0_GENERAL_ENABLE_FRAGMENT_DEST_RING_BMSK |\ + HWIO_REO_R0_GENERAL_ENABLE_AGING_LIST_ENABLE_BMSK | \ + HWIO_REO_R0_GENERAL_ENABLE_AGING_FLUSH_ENABLE_BMSK); \ + reg_val |= \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + FRAGMENT_DEST_RING, \ + (reo_params)->frag_dst_ring) | \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_LIST_ENABLE, 1) |\ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_FLUSH_ENABLE, 1);\ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET),\ + (reg_val)); \ + } while (0) + +#define HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr) \ + ((struct rx_msdu_desc_info *) \ + _OFFSET_TO_BYTE_PTR((msdu_details_ptr), \ +UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET)) + +#define HAL_RX_LINK_DESC_MSDU0_PTR(link_desc) \ + ((struct rx_msdu_details *) \ + _OFFSET_TO_BYTE_PTR((link_desc),\ + UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET)) + +#define HAL_RX_MSDU_END_FLOW_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_14_FLOW_IDX_OFFSET)), \ + RX_MSDU_END_14_FLOW_IDX_MASK, \ + RX_MSDU_END_14_FLOW_IDX_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FLOW_IDX_INVALID_OFFSET)), \ + RX_MSDU_END_5_FLOW_IDX_INVALID_MASK, \ + RX_MSDU_END_5_FLOW_IDX_INVALID_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_OFFSET)), \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_MASK, \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_LSB)) + +#define HAL_RX_MSDU_END_FSE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_15_FSE_METADATA_OFFSET)), \ + RX_MSDU_END_15_FSE_METADATA_MASK, \ + RX_MSDU_END_15_FSE_METADATA_LSB)) + +#define HAL_RX_MSDU_END_CCE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_16_CCE_METADATA_OFFSET)), \ + RX_MSDU_END_16_CCE_METADATA_MASK, \ + RX_MSDU_END_16_CCE_METADATA_LSB)) + +#define HAL_RX_TLV_GET_TCP_CHKSUM(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_OFFSET)), \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_MASK, \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_LSB)) + /* * hal_rx_msdu_start_nss_get_8074(): API to get the NSS * Interval from rx_msdu_start diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1_tx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1_tx.h index 1ae1ef3d97c196acd9b18e30974f844a5afcdc49..b051e18c8bf352ea79f407cc1f15f714a2beaae2 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1_tx.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v1/hal_8074v1_tx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 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 @@ -54,15 +54,13 @@ static void hal_tx_desc_set_dscp_tid_table_id_8074(void *desc, uint8_t id) * * Return: none */ -static void hal_tx_set_dscp_tid_map_8074(void *hal_soc, uint8_t *map, +static void hal_tx_set_dscp_tid_map_8074(struct hal_soc *soc, uint8_t *map, uint8_t id) { int i; uint32_t addr; uint32_t value; - struct hal_soc *soc = (struct hal_soc *)hal_soc; - if (id == HAL_TX_DSCP_TID_MAP_TABLE_DEFAULT) { addr = HWIO_TCL_R0_DSCP_TID1_MAP_0_ADDR( SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET); @@ -102,7 +100,7 @@ static void hal_tx_set_dscp_tid_map_8074(void *hal_soc, uint8_t *map, * Return: void */ static -void hal_tx_update_dscp_tid_8074(void *hal_soc, uint8_t tid, +void hal_tx_update_dscp_tid_8074(struct hal_soc *soc, uint8_t tid, uint8_t id, uint8_t dscp) { int index; @@ -110,8 +108,6 @@ void hal_tx_update_dscp_tid_8074(void *hal_soc, uint8_t tid, uint32_t value; uint32_t regval; - struct hal_soc *soc = (struct hal_soc *)hal_soc; - if (id == HAL_TX_DSCP_TID_MAP_TABLE_DEFAULT) addr = HWIO_TCL_R0_DSCP_TID1_MAP_0_ADDR( SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET); diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2.c b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2.c index 0b107786b03a55229a5790b0580115eedb4eb809..0fa5fac63d8c9b061a5626502b069f39dc2c7399 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2.c +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -105,6 +105,884 @@ #include #include +/** + * hal_rx_get_rx_fragment_number_8074v2(): Function to retrieve + * rx fragment number + * + * @nbuf: Network buffer + * Returns: rx fragment number + */ +static +uint8_t hal_rx_get_rx_fragment_number_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + /* Return first 4 bits as fragment number */ + return HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info) & + DOT11_SEQ_FRAG_MASK; +} + +/** + * hal_rx_msdu_end_da_is_mcbc_get_8074v2: API to check if pkt is MCBC + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_mcbc + */ +static uint8_t +hal_rx_msdu_end_da_is_mcbc_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_DA_IS_MCBC_GET(msdu_end); +} + +/** + * hal_rx_msdu_end_sa_is_valid_get_8074v2(): API to get_8074v2 the + * sa_is_valid bit from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_is_valid bit + */ +static uint8_t +hal_rx_msdu_end_sa_is_valid_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t sa_is_valid; + + sa_is_valid = HAL_RX_MSDU_END_SA_IS_VALID_GET(msdu_end); + + return sa_is_valid; +} + +/** + * hal_rx_msdu_end_sa_idx_get_8074v2(): API to get_8074v2 the + * sa_idx from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_idx (SA AST index) + */ +static uint16_t hal_rx_msdu_end_sa_idx_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint16_t sa_idx; + + sa_idx = HAL_RX_MSDU_END_SA_IDX_GET(msdu_end); + + return sa_idx; +} + +/** + * hal_rx_desc_is_first_msdu_8074v2() - Check if first msdu + * + * @hal_soc_hdl: hal_soc handle + * @hw_desc_addr: hardware descriptor address + * + * Return: 0 - success/ non-zero failure + */ +static uint32_t hal_rx_desc_is_first_msdu_8074v2(void *hw_desc_addr) +{ + struct rx_pkt_tlvs *rx_tlvs = (struct rx_pkt_tlvs *)hw_desc_addr; + struct rx_msdu_end *msdu_end = &rx_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_GET(msdu_end, RX_MSDU_END_5, FIRST_MSDU); +} + +/** + * hal_rx_msdu_end_l3_hdr_padding_get_8074v2(): API to get_8074v2 the + * l3_header padding from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: number of l3 header padding bytes + */ +static uint32_t hal_rx_msdu_end_l3_hdr_padding_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint32_t l3_header_padding; + + l3_header_padding = HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(msdu_end); + + return l3_header_padding; +} + +/* + * @ hal_rx_encryption_info_valid_8074v2: Returns encryption type. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: encryption type + */ +static uint32_t hal_rx_encryption_info_valid_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + uint32_t encryption_info = HAL_RX_MPDU_ENCRYPTION_INFO_VALID(mpdu_info); + + return encryption_info; +} + +/* + * @ hal_rx_print_pn_8074v2: Prints the PN of rx packet. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: void + */ +static void hal_rx_print_pn_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + uint32_t pn_31_0 = HAL_RX_MPDU_PN_31_0_GET(mpdu_info); + uint32_t pn_63_32 = HAL_RX_MPDU_PN_63_32_GET(mpdu_info); + uint32_t pn_95_64 = HAL_RX_MPDU_PN_95_64_GET(mpdu_info); + uint32_t pn_127_96 = HAL_RX_MPDU_PN_127_96_GET(mpdu_info); + + hal_debug("PN number pn_127_96 0x%x pn_95_64 0x%x pn_63_32 0x%x pn_31_0 0x%x ", + pn_127_96, pn_95_64, pn_63_32, pn_31_0); +} + +/** + * hal_rx_msdu_end_first_msdu_get_8074v2: API to get first msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: first_msdu + */ +static uint8_t hal_rx_msdu_end_first_msdu_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t first_msdu; + + first_msdu = HAL_RX_MSDU_END_FIRST_MSDU_GET(msdu_end); + + return first_msdu; +} + +/** + * hal_rx_msdu_end_da_is_valid_get_8074v2: API to check if da is valid + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_valid + */ +static uint8_t hal_rx_msdu_end_da_is_valid_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t da_is_valid; + + da_is_valid = HAL_RX_MSDU_END_DA_IS_VALID_GET(msdu_end); + + return da_is_valid; +} + +/** + * hal_rx_msdu_end_last_msdu_get_8074v2: API to get last msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: last_msdu + */ +static uint8_t hal_rx_msdu_end_last_msdu_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t last_msdu; + + last_msdu = HAL_RX_MSDU_END_LAST_MSDU_GET(msdu_end); + + return last_msdu; +} + +/* + * hal_rx_get_mpdu_mac_ad4_valid_8074v2(): Retrieves if mpdu 4th addr is valid + * + * @nbuf: Network buffer + * Returns: value of mpdu 4th address valid field + */ +static bool hal_rx_get_mpdu_mac_ad4_valid_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + bool ad4_valid = 0; + + ad4_valid = HAL_RX_MPDU_GET_MAC_AD4_VALID(rx_mpdu_info); + + return ad4_valid; +} + +/** + * hal_rx_mpdu_start_sw_peer_id_get_8074v2: Retrieve sw peer_id + * @buf: network buffer + * + * Return: sw peer_id + */ +static uint32_t hal_rx_mpdu_start_sw_peer_id_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_SW_PEER_ID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/* + * hal_rx_mpdu_get_to_ds_8074v2(): API to get the tods info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(to_ds) + */ +static uint32_t hal_rx_mpdu_get_to_ds_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_TODS(mpdu_info); +} + +/* + * hal_rx_mpdu_get_fr_ds_8074v2(): API to get the from ds info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(fr_ds) + */ +static uint32_t hal_rx_mpdu_get_fr_ds_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_FROMDS(mpdu_info); +} + +/* + * hal_rx_get_mpdu_frame_control_valid_8074v2(): Retrieves mpdu + * frame control valid + * + * @nbuf: Network buffer + * Returns: value of frame control valid field + */ +static uint8_t hal_rx_get_mpdu_frame_control_valid_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(rx_mpdu_info); +} + +/* + * hal_rx_mpdu_get_addr1_8074v2(): API to check get address1 of the mpdu + * + * @buf: pointer to the start of RX PKT TLV headera + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr1_8074v2(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr1 { + uint32_t ad1_31_0; + uint16_t ad1_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr1 *addr = (struct hal_addr1 *)mac_addr; + uint32_t mac_addr_ad1_valid; + + mac_addr_ad1_valid = HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(mpdu_info); + + if (mac_addr_ad1_valid) { + addr->ad1_31_0 = HAL_RX_MPDU_AD1_31_0_GET(mpdu_info); + addr->ad1_47_32 = HAL_RX_MPDU_AD1_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr2_8074v2(): API to check get address2 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr2_8074v2(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr2 { + uint16_t ad2_15_0; + uint32_t ad2_47_16; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr2 *addr = (struct hal_addr2 *)mac_addr; + uint32_t mac_addr_ad2_valid; + + mac_addr_ad2_valid = HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(mpdu_info); + + if (mac_addr_ad2_valid) { + addr->ad2_15_0 = HAL_RX_MPDU_AD2_15_0_GET(mpdu_info); + addr->ad2_47_16 = HAL_RX_MPDU_AD2_47_16_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr3_8074v2(): API to get address3 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr3_8074v2(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr3 { + uint32_t ad3_31_0; + uint16_t ad3_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr3 *addr = (struct hal_addr3 *)mac_addr; + uint32_t mac_addr_ad3_valid; + + mac_addr_ad3_valid = HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(mpdu_info); + + if (mac_addr_ad3_valid) { + addr->ad3_31_0 = HAL_RX_MPDU_AD3_31_0_GET(mpdu_info); + addr->ad3_47_32 = HAL_RX_MPDU_AD3_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr4_8074v2(): API to get address4 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr4_8074v2(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr4 { + uint32_t ad4_31_0; + uint16_t ad4_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr4 *addr = (struct hal_addr4 *)mac_addr; + uint32_t mac_addr_ad4_valid; + + mac_addr_ad4_valid = HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(mpdu_info); + + if (mac_addr_ad4_valid) { + addr->ad4_31_0 = HAL_RX_MPDU_AD4_31_0_GET(mpdu_info); + addr->ad4_47_32 = HAL_RX_MPDU_AD4_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_get_mpdu_sequence_control_valid_8074v2(): Get mpdu + * sequence control valid + * + * @nbuf: Network buffer + * Returns: value of sequence control valid field + */ +static uint8_t hal_rx_get_mpdu_sequence_control_valid_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(rx_mpdu_info); +} + +/** + * hal_rx_is_unicast_8074v2: check packet is unicast frame or not. + * + * @ buf: pointer to rx pkt TLV. + * + * Return: true on unicast. + */ +static bool hal_rx_is_unicast_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint32_t grp_id; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + + grp_id = (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_OFFSET)), + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_MASK, + RX_MPDU_INFO_0_SW_FRAME_GROUP_ID_LSB)); + + return (HAL_MPDU_SW_FRAME_GROUP_UNICAST_DATA == grp_id) ? true : false; +} + +/** + * hal_rx_tid_get_8074v2: get tid based on qos control valid. + * @hal_soc_hdl: hal soc handle + * @buf: pointer to rx pkt TLV. + * + * Return: tid + */ +static uint32_t hal_rx_tid_get_8074v2(hal_soc_handle_t hal_soc_hdl, + uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + uint8_t qos_control_valid = + (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_OFFSET)), + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_MASK, + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_LSB)); + + if (qos_control_valid) + return hal_rx_mpdu_start_tid_get_8074v2(buf); + + return HAL_RX_NON_QOS_TID; +} + +/** + * hal_rx_hw_desc_get_ppduid_get_8074v2(): retrieve ppdu id + * @hw_desc_addr: hw addr + * + * Return: ppdu id + */ +static uint32_t hal_rx_hw_desc_get_ppduid_get_8074v2(void *hw_desc_addr) +{ + struct rx_mpdu_info *rx_mpdu_info; + struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + + rx_mpdu_info = + &rx_desc->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + + return HAL_RX_GET(rx_mpdu_info, RX_MPDU_INFO_0, PHY_PPDU_ID); +} + +/** + * hal_reo_status_get_header_8074v2 - Process reo desc info + * @d - Pointer to reo descriptior + * @b - tlv type info + * @h1 - Pointer to hal_reo_status_header where info to be stored + * + * Return - none. + * + */ +static void hal_reo_status_get_header_8074v2(uint32_t *d, int b, void *h1) +{ + uint32_t val1 = 0; + struct hal_reo_status_header *h = + (struct hal_reo_status_header *)h1; + + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->cmd_num = + HAL_GET_FIELD( + UNIFORM_REO_STATUS_HEADER_0, REO_STATUS_NUMBER, + val1); + h->exec_time = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + CMD_EXECUTION_TIME, val1); + h->status = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + REO_CMD_EXECUTION_STATUS, val1); + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->tstamp = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_1, TIMESTAMP, val1); +} + +/** + * hal_rx_mpdu_start_mpdu_qos_control_valid_get_8074v2(): + * Retrieve qos control valid bit from the tlv. + * @buf: pointer to rx pkt TLV. + * + * Return: qos control value. + */ +static inline uint32_t +hal_rx_mpdu_start_mpdu_qos_control_valid_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/** + * hal_rx_msdu_end_sa_sw_peer_id_get_8074v2(): API to get the + * sa_sw_peer_id from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: sa_sw_peer_id index + */ +static inline uint32_t +hal_rx_msdu_end_sa_sw_peer_id_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(msdu_end); +} + +/** + * hal_tx_desc_set_mesh_en_8074v2 - Set mesh_enable flag in Tx descriptor + * @desc: Handle to Tx Descriptor + * @en: For raw WiFi frames, this indicates transmission to a mesh STA, + * enabling the interpretation of the 'Mesh Control Present' bit + * (bit 8) of QoS Control (otherwise this bit is ignored), + * For native WiFi frames, this indicates that a 'Mesh Control' field + * is present between the header and the LLC. + * + * Return: void + */ +static inline +void hal_tx_desc_set_mesh_en_8074v2(void *desc, uint8_t en) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_4, MESH_ENABLE) |= + HAL_TX_SM(TCL_DATA_CMD_4, MESH_ENABLE, en); +} + +static +void *hal_rx_msdu0_buffer_addr_lsb_8074v2(void *link_desc_va) +{ + return (void *)HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va); +} + +static +void *hal_rx_msdu_desc_info_ptr_get_8074v2(void *msdu0) +{ + return (void *)HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0); +} + +static +void *hal_ent_mpdu_desc_info_8074v2(void *ent_ring_desc) +{ + return (void *)HAL_ENT_MPDU_DESC_INFO(ent_ring_desc); +} + +static +void *hal_dst_mpdu_desc_info_8074v2(void *dst_ring_desc) +{ + return (void *)HAL_DST_MPDU_DESC_INFO(dst_ring_desc); +} + +static +uint8_t hal_rx_get_fc_valid_8074v2(uint8_t *buf) +{ + return HAL_RX_GET_FC_VALID(buf); +} + +static uint8_t hal_rx_get_to_ds_flag_8074v2(uint8_t *buf) +{ + return HAL_RX_GET_TO_DS_FLAG(buf); +} + +static uint8_t hal_rx_get_mac_addr2_valid_8074v2(uint8_t *buf) +{ + return HAL_RX_GET_MAC_ADDR2_VALID(buf); +} + +static uint8_t hal_rx_get_filter_category_8074v2(uint8_t *buf) +{ + return HAL_RX_GET_FILTER_CATEGORY(buf); +} + +static uint32_t +hal_rx_get_ppdu_id_8074v2(uint8_t *buf) +{ + return HAL_RX_GET_PPDU_ID(buf); +} + +/** + * hal_reo_config_8074v2(): Set reo config parameters + * @soc: hal soc handle + * @reg_val: value to be set + * @reo_params: reo parameters + * + * Return: void + */ +static void +hal_reo_config_8074v2(struct hal_soc *soc, + uint32_t reg_val, + struct hal_reo_params *reo_params) +{ + HAL_REO_R0_CONFIG(soc, reg_val, reo_params); +} + +/** + * hal_rx_msdu_desc_info_get_ptr_8074v2() - Get msdu desc info ptr + * @msdu_details_ptr - Pointer to msdu_details_ptr + * + * Return - Pointer to rx_msdu_desc_info structure. + * + */ +static void *hal_rx_msdu_desc_info_get_ptr_8074v2(void *msdu_details_ptr) +{ + return HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr); +} + +/** + * hal_rx_link_desc_msdu0_ptr_8074v2 - Get pointer to rx_msdu details + * @link_desc - Pointer to link desc + * + * Return - Pointer to rx_msdu_details structure + * + */ +static void *hal_rx_link_desc_msdu0_ptr_8074v2(void *link_desc) +{ + return HAL_RX_LINK_DESC_MSDU0_PTR(link_desc); +} + +/** + * hal_rx_msdu_flow_idx_get_8074v2: API to get flow index + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index value from MSDU END TLV + */ +static inline uint32_t hal_rx_msdu_flow_idx_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_invalid_8074v2: API to get flow index invalid + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index invalid value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_invalid_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_timeout_8074v2: API to get flow index timeout + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index timeout value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_timeout_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); +} + +/** + * hal_rx_msdu_fse_metadata_get_8074v2: API to get FSE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: fse metadata value from MSDU END TLV + */ +static uint32_t hal_rx_msdu_fse_metadata_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FSE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_cce_metadata_get_8074v2: API to get CCE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: cce_metadata + */ +static uint16_t +hal_rx_msdu_cce_metadata_get_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_CCE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_get_flow_params_8074v2: API to get flow index, flow index invalid + * and flow index timeout from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * @flow_invalid: pointer to return value of flow_idx_valid + * @flow_timeout: pointer to return value of flow_idx_timeout + * @flow_index: pointer to return value of flow_idx + * + * Return: none + */ +static inline void +hal_rx_msdu_get_flow_params_8074v2(uint8_t *buf, + bool *flow_invalid, + bool *flow_timeout, + uint32_t *flow_index) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + *flow_invalid = HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); + *flow_timeout = HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); + *flow_index = HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_tlv_get_tcp_chksum_8074v2() - API to get tcp checksum + * @buf: rx_tlv_hdr + * + * Return: tcp checksum + */ +static uint16_t +hal_rx_tlv_get_tcp_chksum_8074v2(uint8_t *buf) +{ + return HAL_RX_TLV_GET_TCP_CHKSUM(buf); +} + +/** + * hal_rx_get_rx_sequence_8074v2(): Function to retrieve rx sequence number + * + * @nbuf: Network buffer + * Returns: rx sequence number + */ +static +uint16_t hal_rx_get_rx_sequence_8074v2(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info); +} + +/** + * hal_get_window_address_8074v2(): Function to get hp/tp address + * @hal_soc: Pointer to hal_soc + * @addr: address offset of register + * + * Return: modified address offset of register + */ +static inline qdf_iomem_t hal_get_window_address_8074v2(struct hal_soc *hal_soc, + qdf_iomem_t addr) +{ + return addr; +} + struct hal_hw_txrx_ops qca8074v2_hal_hw_txrx_ops = { /* init and setup */ @@ -113,6 +991,7 @@ struct hal_hw_txrx_ops qca8074v2_hal_hw_txrx_ops = { hal_get_hw_hptp_generic, hal_reo_setup_generic, hal_setup_link_idle_list_generic, + hal_get_window_address_8074v2, NULL, /* tx */ @@ -123,8 +1002,11 @@ struct hal_hw_txrx_ops qca8074v2_hal_hw_txrx_ops = { hal_tx_desc_set_buf_addr_generic, hal_tx_desc_set_search_type_generic, hal_tx_desc_set_search_index_generic, + hal_tx_desc_set_cache_set_num_generic, hal_tx_comp_get_status_generic, hal_tx_comp_get_release_reason_generic, + hal_get_wbm_internal_error_generic, + hal_tx_desc_set_mesh_en_8074v2, /* rx */ hal_rx_msdu_start_nss_get_8074v2, @@ -137,9 +1019,9 @@ struct hal_hw_txrx_ops qca8074v2_hal_hw_txrx_ops = { hal_rx_mpdu_start_tid_get_8074v2, hal_rx_msdu_start_reception_type_get_8074v2, hal_rx_msdu_end_da_idx_get_8074v2, - hal_rx_msdu_desc_info_get_ptr_generic, - hal_rx_link_desc_msdu0_ptr_generic, - hal_reo_status_get_header_generic, + hal_rx_msdu_desc_info_get_ptr_8074v2, + hal_rx_link_desc_msdu0_ptr_8074v2, + hal_reo_status_get_header_8074v2, hal_rx_status_get_tlv_info_generic, hal_rx_wbm_err_info_get_generic, hal_rx_dump_mpdu_start_tlv_generic, @@ -147,6 +1029,66 @@ struct hal_hw_txrx_ops qca8074v2_hal_hw_txrx_ops = { hal_tx_set_pcp_tid_map_generic, hal_tx_update_pcp_tid_generic, hal_tx_update_tidmap_prty_generic, + hal_rx_get_rx_fragment_number_8074v2, + hal_rx_msdu_end_da_is_mcbc_get_8074v2, + hal_rx_msdu_end_sa_is_valid_get_8074v2, + hal_rx_msdu_end_sa_idx_get_8074v2, + hal_rx_desc_is_first_msdu_8074v2, + hal_rx_msdu_end_l3_hdr_padding_get_8074v2, + hal_rx_encryption_info_valid_8074v2, + hal_rx_print_pn_8074v2, + hal_rx_msdu_end_first_msdu_get_8074v2, + hal_rx_msdu_end_da_is_valid_get_8074v2, + hal_rx_msdu_end_last_msdu_get_8074v2, + hal_rx_get_mpdu_mac_ad4_valid_8074v2, + hal_rx_mpdu_start_sw_peer_id_get_8074v2, + hal_rx_mpdu_get_to_ds_8074v2, + hal_rx_mpdu_get_fr_ds_8074v2, + hal_rx_get_mpdu_frame_control_valid_8074v2, + hal_rx_mpdu_get_addr1_8074v2, + hal_rx_mpdu_get_addr2_8074v2, + hal_rx_mpdu_get_addr3_8074v2, + hal_rx_mpdu_get_addr4_8074v2, + hal_rx_get_mpdu_sequence_control_valid_8074v2, + hal_rx_is_unicast_8074v2, + hal_rx_tid_get_8074v2, + hal_rx_hw_desc_get_ppduid_get_8074v2, + hal_rx_mpdu_start_mpdu_qos_control_valid_get_8074v2, + hal_rx_msdu_end_sa_sw_peer_id_get_8074v2, + hal_rx_msdu0_buffer_addr_lsb_8074v2, + hal_rx_msdu_desc_info_ptr_get_8074v2, + hal_ent_mpdu_desc_info_8074v2, + hal_dst_mpdu_desc_info_8074v2, + hal_rx_get_fc_valid_8074v2, + hal_rx_get_to_ds_flag_8074v2, + hal_rx_get_mac_addr2_valid_8074v2, + hal_rx_get_filter_category_8074v2, + hal_rx_get_ppdu_id_8074v2, + hal_reo_config_8074v2, + hal_rx_msdu_flow_idx_get_8074v2, + hal_rx_msdu_flow_idx_invalid_8074v2, + hal_rx_msdu_flow_idx_timeout_8074v2, + hal_rx_msdu_fse_metadata_get_8074v2, + hal_rx_msdu_cce_metadata_get_8074v2, + hal_rx_msdu_get_flow_params_8074v2, + hal_rx_tlv_get_tcp_chksum_8074v2, + hal_rx_get_rx_sequence_8074v2, +#if defined(QCA_WIFI_QCA6018) && defined(WLAN_CFR_ENABLE) && \ + defined(WLAN_ENH_CFR_ENABLE) + hal_rx_get_bb_info_8074v2, + hal_rx_get_rtt_info_8074v2, +#else + NULL, + NULL, +#endif + /* rx - msdu fast path info fields */ + hal_rx_msdu_packet_metadata_get_generic, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; struct hal_hw_srng_config hw_srng_table_8074v2[] = { @@ -603,6 +1545,3 @@ void hal_qca8074v2_attach(struct hal_soc *hal_soc) hal_soc->hal_hw_reg_offset = hal_hw_reg_offset_qca8074v2; hal_soc->ops = &qca8074v2_hal_hw_txrx_ops; } - - - diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2_rx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2_rx.h index a9bd0430300c225cbdb76edef07c5bd81eb925b5..8ceae38232775f6d6a8f646515f388737d7e2a09 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2_rx.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2_rx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -23,12 +23,319 @@ #include "hal_tx.h" #include "dp_types.h" #include "hal_api_mon.h" +#ifndef QCA_WIFI_QCA6018 +#include "phyrx_other_receive_info_su_evm_details.h" +#endif + +#define HAL_RX_MPDU_GET_SEQUENCE_NUMBER(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_MASK, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_NUMBER_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_MCBC_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_DA_IS_MCBC_OFFSET)), \ + RX_MSDU_END_5_DA_IS_MCBC_MASK, \ + RX_MSDU_END_5_DA_IS_MCBC_LSB)) + +#define HAL_RX_MSDU_END_SA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_SA_IS_VALID_OFFSET)), \ + RX_MSDU_END_5_SA_IS_VALID_MASK, \ + RX_MSDU_END_5_SA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_13_SA_IDX_OFFSET)), \ + RX_MSDU_END_13_SA_IDX_MASK, \ + RX_MSDU_END_13_SA_IDX_LSB)) + +#define HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_L3_HEADER_PADDING_OFFSET)), \ + RX_MSDU_END_5_L3_HEADER_PADDING_MASK, \ + RX_MSDU_END_5_L3_HEADER_PADDING_LSB)) + +#define HAL_RX_MPDU_ENCRYPTION_INFO_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_OFFSET)), \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_MASK, \ + RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_LSB)) + +#define HAL_RX_MPDU_PN_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_4_PN_31_0_OFFSET)), \ + RX_MPDU_INFO_4_PN_31_0_MASK, \ + RX_MPDU_INFO_4_PN_31_0_LSB)) + +#define HAL_RX_MPDU_PN_63_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_5_PN_63_32_OFFSET)), \ + RX_MPDU_INFO_5_PN_63_32_MASK, \ + RX_MPDU_INFO_5_PN_63_32_LSB)) + +#define HAL_RX_MPDU_PN_95_64_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_6_PN_95_64_OFFSET)), \ + RX_MPDU_INFO_6_PN_95_64_MASK, \ + RX_MPDU_INFO_6_PN_95_64_LSB)) + +#define HAL_RX_MPDU_PN_127_96_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_7_PN_127_96_OFFSET)), \ + RX_MPDU_INFO_7_PN_127_96_MASK, \ + RX_MPDU_INFO_7_PN_127_96_LSB)) + +#define HAL_RX_MSDU_END_FIRST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FIRST_MSDU_OFFSET)), \ + RX_MSDU_END_5_FIRST_MSDU_MASK, \ + RX_MSDU_END_5_FIRST_MSDU_LSB)) #define HAL_RX_MSDU_START_MIMO_SS_BITMAP(_rx_msdu_start)\ (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\ RX_MSDU_START_5_MIMO_SS_BITMAP_OFFSET)), \ RX_MSDU_START_5_MIMO_SS_BITMAP_MASK, \ RX_MSDU_START_5_MIMO_SS_BITMAP_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_DA_IS_VALID_OFFSET)), \ + RX_MSDU_END_5_DA_IS_VALID_MASK, \ + RX_MSDU_END_5_DA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_LAST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_LAST_MSDU_OFFSET)), \ + RX_MSDU_END_5_LAST_MSDU_MASK, \ + RX_MSDU_END_5_LAST_MSDU_LSB)) + +#define HAL_RX_MPDU_GET_MAC_AD4_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_SW_PEER_ID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_1_SW_PEER_ID_OFFSET)), \ + RX_MPDU_INFO_1_SW_PEER_ID_MASK, \ + RX_MPDU_INFO_1_SW_PEER_ID_LSB)) + +#define HAL_RX_MPDU_GET_TODS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_TO_DS_OFFSET)), \ + RX_MPDU_INFO_2_TO_DS_MASK, \ + RX_MPDU_INFO_2_TO_DS_LSB)) + +#define HAL_RX_MPDU_GET_FROMDS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_FR_DS_OFFSET)), \ + RX_MPDU_INFO_2_FR_DS_MASK, \ + RX_MPDU_INFO_2_FR_DS_LSB)) + +#define HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_FRAME_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD1_VALID_LSB)) + +#define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_MASK, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_LSB)) + +#define HAL_RX_MPDU_AD1_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_LSB)) + +#define HAL_RX_MPDU_AD2_15_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_LSB)) + +#define HAL_RX_MPDU_AD2_47_16_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_OFFSET)), \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_MASK, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_LSB)) + +#define HAL_RX_MPDU_AD3_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_OFFSET)), \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_MASK, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_LSB)) + +#define HAL_RX_MPDU_AD3_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_OFFSET)), \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_MASK, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_2_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_AD4_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_OFFSET)), \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_MASK, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_LSB)) + +#define HAL_RX_MPDU_AD4_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_OFFSET)), \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_MASK, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_LSB)) + +#define HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_SEQUENCE_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_2_MPDU_QOS_CONTROL_VALID_LSB)) + +#define HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_16_SA_SW_PEER_ID_OFFSET)), \ + RX_MSDU_END_16_SA_SW_PEER_ID_MASK, \ + RX_MSDU_END_16_SA_SW_PEER_ID_LSB)) + +#define HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va) \ + (uint8_t *)(link_desc_va) + \ + RX_MSDU_LINK_8_MSDU_0_BUFFER_ADDR_INFO_DETAILS_BUFFER_ADDR_31_0_OFFSET + +#define HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0) \ + (uint8_t *)(msdu0) + \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_DETAILS_FIRST_MSDU_IN_MPDU_FLAG_OFFSET + +#define HAL_ENT_MPDU_DESC_INFO(ent_ring_desc) \ + (uint8_t *)(ent_ring_desc) + \ + RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_DETAILS_MSDU_COUNT_OFFSET + +#define HAL_DST_MPDU_DESC_INFO(dst_ring_desc) \ + (uint8_t *)(dst_ring_desc) + \ + REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_DETAILS_MSDU_COUNT_OFFSET + +#define HAL_RX_GET_FC_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MPDU_FRAME_CONTROL_VALID) + +#define HAL_RX_GET_TO_DS_FLAG(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, TO_DS) + +#define HAL_RX_GET_MAC_ADDR1_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MAC_ADDR_AD1_VALID) + +#define HAL_RX_GET_MAC_ADDR2_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_2, MAC_ADDR_AD2_VALID) + +#define HAL_RX_GET_FILTER_CATEGORY(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, RXPCU_MPDU_FILTER_IN_CATEGORY) + +#define HAL_RX_GET_PPDU_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, PHY_PPDU_ID) + +#define HAL_RX_GET_SW_FRAME_GROUP_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_0, SW_FRAME_GROUP_ID) + +#define HAL_REO_R0_CONFIG(soc, reg_val, reo_params) \ + do { \ + reg_val &= \ + ~(HWIO_REO_R0_GENERAL_ENABLE_FRAGMENT_DEST_RING_BMSK |\ + HWIO_REO_R0_GENERAL_ENABLE_AGING_LIST_ENABLE_BMSK | \ + HWIO_REO_R0_GENERAL_ENABLE_AGING_FLUSH_ENABLE_BMSK); \ + reg_val |= \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + FRAGMENT_DEST_RING, \ + (reo_params)->frag_dst_ring) | \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_LIST_ENABLE, 1) |\ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_FLUSH_ENABLE, 1);\ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ + } while (0) + +#define HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr) \ + ((struct rx_msdu_desc_info *) \ + _OFFSET_TO_BYTE_PTR((msdu_details_ptr), \ +UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET)) + +#define HAL_RX_LINK_DESC_MSDU0_PTR(link_desc) \ + ((struct rx_msdu_details *) \ + _OFFSET_TO_BYTE_PTR((link_desc),\ + UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET)) + +#define HAL_RX_MSDU_END_FLOW_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_14_FLOW_IDX_OFFSET)), \ + RX_MSDU_END_14_FLOW_IDX_MASK, \ + RX_MSDU_END_14_FLOW_IDX_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FLOW_IDX_INVALID_OFFSET)), \ + RX_MSDU_END_5_FLOW_IDX_INVALID_MASK, \ + RX_MSDU_END_5_FLOW_IDX_INVALID_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_OFFSET)), \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_MASK, \ + RX_MSDU_END_5_FLOW_IDX_TIMEOUT_LSB)) + +#define HAL_RX_MSDU_END_FSE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_15_FSE_METADATA_OFFSET)), \ + RX_MSDU_END_15_FSE_METADATA_MASK, \ + RX_MSDU_END_15_FSE_METADATA_LSB)) + +#define HAL_RX_MSDU_END_CCE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_16_CCE_METADATA_OFFSET)), \ + RX_MSDU_END_16_CCE_METADATA_MASK, \ + RX_MSDU_END_16_CCE_METADATA_LSB)) + +#define HAL_RX_TLV_GET_TCP_CHKSUM(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_OFFSET)), \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_MASK, \ + RX_MSDU_END_1_TCP_UDP_CHKSUM_LSB)) + /* * hal_rx_msdu_start_nss_get_8074v2(): API to get the NSS * Interval from rx_msdu_start @@ -101,6 +408,52 @@ static uint8_t hal_rx_get_tlv_8074v2(void *rx_tlv) return HAL_RX_GET(rx_tlv, PHYRX_RSSI_LEGACY_0, RECEIVE_BANDWIDTH); } +#ifndef QCA_WIFI_QCA6018 +#define HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, evm, pilot) \ + (ppdu_info)->evm_info.pilot_evm[pilot] = HAL_RX_GET(rx_tlv, \ + PHYRX_OTHER_RECEIVE_INFO, \ + SU_EVM_DETAILS_##evm##_PILOT_##pilot##_EVM) + +static inline void +hal_rx_update_su_evm_info(void *rx_tlv, + void *ppdu_info_hdl) +{ + struct hal_rx_ppdu_info *ppdu_info = + (struct hal_rx_ppdu_info *)ppdu_info_hdl; + + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 1, 0); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 2, 1); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 3, 2); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 4, 3); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 5, 4); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 6, 5); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 7, 6); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 8, 7); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 9, 8); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 10, 9); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 11, 10); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 12, 11); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 13, 12); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 14, 13); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 15, 14); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 16, 15); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 17, 16); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 18, 17); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 19, 18); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 20, 19); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 21, 20); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 22, 21); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 23, 22); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 24, 23); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 25, 24); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 26, 25); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 27, 26); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 28, 27); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 29, 28); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 30, 29); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 31, 30); + HAL_RX_UPDATE_SU_EVM_INFO(rx_tlv, ppdu_info, 32, 31); +} /** * hal_rx_proc_phyrx_other_receive_info_tlv_8074v2() * -process other receive info TLV @@ -111,10 +464,89 @@ static uint8_t hal_rx_get_tlv_8074v2(void *rx_tlv) */ static void hal_rx_proc_phyrx_other_receive_info_tlv_8074v2(void *rx_tlv_hdr, - void *ppdu_info) + void *ppdu_info_hdl) { + uint16_t tlv_tag; + void *rx_tlv; + struct hal_rx_ppdu_info *ppdu_info = ppdu_info_hdl; + + /* Skip TLV_HDR for OTHER_RECEIVE_INFO and follows the + * embedded TLVs inside + */ + rx_tlv = (uint8_t *)rx_tlv_hdr + HAL_RX_TLV32_HDR_SIZE; + tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv); + + switch (tlv_tag) { + case WIFIPHYRX_OTHER_RECEIVE_INFO_SU_EVM_DETAILS_E: + + /* Skip TLV length to get TLV content */ + rx_tlv = (uint8_t *)rx_tlv + HAL_RX_TLV32_HDR_SIZE; + + ppdu_info->evm_info.number_of_symbols = HAL_RX_GET(rx_tlv, + PHYRX_OTHER_RECEIVE_INFO, + SU_EVM_DETAILS_0_NUMBER_OF_SYMBOLS); + ppdu_info->evm_info.pilot_count = HAL_RX_GET(rx_tlv, + PHYRX_OTHER_RECEIVE_INFO, + SU_EVM_DETAILS_0_PILOT_COUNT); + ppdu_info->evm_info.nss_count = HAL_RX_GET(rx_tlv, + PHYRX_OTHER_RECEIVE_INFO, + SU_EVM_DETAILS_0_NSS_COUNT); + hal_rx_update_su_evm_info(rx_tlv, ppdu_info_hdl); + break; + } +} +#else +static inline +void hal_rx_proc_phyrx_other_receive_info_tlv_8074v2(void *rx_tlv_hdr, + void *ppdu_info_hdl) +{ +} +#endif + +#if defined(QCA_WIFI_QCA6018) && defined(WLAN_CFR_ENABLE) && \ + defined(WLAN_ENH_CFR_ENABLE) +static inline +void hal_rx_get_bb_info_8074v2(void *rx_tlv, + void *ppdu_info_hdl) +{ + struct hal_rx_ppdu_info *ppdu_info = ppdu_info_hdl; + + ppdu_info->cfr_info.bb_captured_channel = + HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_3, BB_CAPTURED_CHANNEL); + + ppdu_info->cfr_info.bb_captured_timeout = + HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_3, BB_CAPTURED_TIMEOUT); + + ppdu_info->cfr_info.bb_captured_reason = + HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_3, BB_CAPTURED_REASON); } +static inline +void hal_rx_get_rtt_info_8074v2(void *rx_tlv, + void *ppdu_info_hdl) +{ + struct hal_rx_ppdu_info *ppdu_info = ppdu_info_hdl; + + ppdu_info->cfr_info.rx_location_info_valid = + HAL_RX_GET(rx_tlv, PHYRX_PKT_END_13_RX_PKT_END_DETAILS, + RX_LOCATION_INFO_DETAILS_RX_LOCATION_INFO_VALID); + + ppdu_info->cfr_info.rtt_che_buffer_pointer_low32 = + HAL_RX_GET(rx_tlv, + PHYRX_PKT_END_12_RX_PKT_END_DETAILS_RX_LOCATION_INFO_DETAILS, + RTT_CHE_BUFFER_POINTER_LOW32); + + ppdu_info->cfr_info.rtt_che_buffer_pointer_high8 = + HAL_RX_GET(rx_tlv, + PHYRX_PKT_END_11_RX_PKT_END_DETAILS_RX_LOCATION_INFO_DETAILS, + RTT_CHE_BUFFER_POINTER_HIGH8); + + ppdu_info->cfr_info.chan_capture_status = + HAL_RX_GET(rx_tlv, + PHYRX_PKT_END_13_RX_PKT_END_DETAILS_RX_LOCATION_INFO_DETAILS, + RESERVED_8); +} +#endif /** * hal_rx_dump_msdu_start_tlv_8074v2() : dump RX msdu_start TLV in structured @@ -368,4 +800,3 @@ static uint16_t hal_rx_msdu_end_da_idx_get_8074v2(uint8_t *buf) return da_idx; } - diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2_tx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2_tx.h index b95b4535f32781f7d4953d49e7933a889b6adb98..4cde5a5d1cae430c7aee13d1c2021b9520c1bd17 100644 --- a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2_tx.h +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qca8074v2/hal_8074v2_tx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 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 @@ -59,16 +59,15 @@ static void hal_tx_desc_set_dscp_tid_table_id_8074v2(void *desc, uint8_t id) * Return: none */ -static void hal_tx_set_dscp_tid_map_8074v2(void *hal_soc, uint8_t *map, - uint8_t id) +static void hal_tx_set_dscp_tid_map_8074v2(struct hal_soc *soc, + uint8_t *map, + uint8_t id) { int i; uint32_t addr, cmn_reg_addr; uint32_t value = 0, regval; uint8_t val[DSCP_TID_TABLE_SIZE], cnt = 0; - struct hal_soc *soc = (struct hal_soc *)hal_soc; - if (id >= HAL_MAX_HW_DSCP_TID_V2_MAPS) return; @@ -97,7 +96,7 @@ static void hal_tx_set_dscp_tid_map_8074v2(void *hal_soc, uint8_t *map, (map[i + 6] << 0x12) | (map[i + 7] << 0x15)); - qdf_mem_copy(&val[cnt], (void *)&value, 3); + qdf_mem_copy(&val[cnt], &value, 3); cnt += 3; } @@ -126,13 +125,12 @@ static void hal_tx_set_dscp_tid_map_8074v2(void *hal_soc, uint8_t *map, * * Return: void */ -static void hal_tx_update_dscp_tid_8074v2(void *hal_soc, uint8_t tid, - uint8_t id, uint8_t dscp) +static void hal_tx_update_dscp_tid_8074v2(struct hal_soc *soc, uint8_t tid, + uint8_t id, uint8_t dscp) { uint32_t addr, addr1, cmn_reg_addr; uint32_t start_value = 0, end_value = 0; uint32_t regval; - struct hal_soc *soc = (struct hal_soc *)hal_soc; uint8_t end_bits = 0; uint8_t start_bits = 0; uint32_t start_index, end_index; diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qcn9000/hal_9000.c b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qcn9000/hal_9000.c new file mode 100644 index 0000000000000000000000000000000000000000..41272e9b08177f644015efec91fa9fd0a7ad9001 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qcn9000/hal_9000.c @@ -0,0 +1,1927 @@ +/* + * Copyright (c) 2016-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +#include "hal_hw_headers.h" +#include "hal_internal.h" +#include "hal_api.h" +#include "target_type.h" +#include "wcss_version.h" +#include "qdf_module.h" +#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_OFFSET \ + RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_OFFSET +#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_MASK \ + RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_MASK +#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_LSB \ + RXPCU_PPDU_END_INFO_9_RX_PPDU_DURATION_LSB +#define UNIFIED_PHYRX_HT_SIG_0_HT_SIG_INFO_PHYRX_HT_SIG_INFO_DETAILS_OFFSET \ + PHYRX_HT_SIG_0_PHYRX_HT_SIG_INFO_DETAILS_MCS_OFFSET +#define UNIFIED_PHYRX_L_SIG_B_0_L_SIG_B_INFO_PHYRX_L_SIG_B_INFO_DETAILS_OFFSET \ + PHYRX_L_SIG_B_0_PHYRX_L_SIG_B_INFO_DETAILS_RATE_OFFSET +#define UNIFIED_PHYRX_L_SIG_A_0_L_SIG_A_INFO_PHYRX_L_SIG_A_INFO_DETAILS_OFFSET \ + PHYRX_L_SIG_A_0_PHYRX_L_SIG_A_INFO_DETAILS_RATE_OFFSET +#define UNIFIED_PHYRX_VHT_SIG_A_0_VHT_SIG_A_INFO_PHYRX_VHT_SIG_A_INFO_DETAILS_OFFSET \ + PHYRX_VHT_SIG_A_0_PHYRX_VHT_SIG_A_INFO_DETAILS_BANDWIDTH_OFFSET +#define UNIFIED_PHYRX_HE_SIG_A_SU_0_HE_SIG_A_SU_INFO_PHYRX_HE_SIG_A_SU_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_A_SU_0_PHYRX_HE_SIG_A_SU_INFO_DETAILS_FORMAT_INDICATION_OFFSET +#define UNIFIED_PHYRX_HE_SIG_A_MU_DL_0_HE_SIG_A_MU_DL_INFO_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_A_MU_DL_0_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS_DL_UL_FLAG_OFFSET +#define UNIFIED_PHYRX_HE_SIG_B1_MU_0_HE_SIG_B1_MU_INFO_PHYRX_HE_SIG_B1_MU_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_B1_MU_0_PHYRX_HE_SIG_B1_MU_INFO_DETAILS_RU_ALLOCATION_OFFSET +#define UNIFIED_PHYRX_HE_SIG_B2_MU_0_HE_SIG_B2_MU_INFO_PHYRX_HE_SIG_B2_MU_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_B2_MU_0_PHYRX_HE_SIG_B2_MU_INFO_DETAILS_STA_ID_OFFSET +#define UNIFIED_PHYRX_HE_SIG_B2_OFDMA_0_HE_SIG_B2_OFDMA_INFO_PHYRX_HE_SIG_B2_OFDMA_INFO_DETAILS_OFFSET \ + PHYRX_HE_SIG_B2_OFDMA_0_PHYRX_HE_SIG_B2_OFDMA_INFO_DETAILS_STA_ID_OFFSET +#define UNIFIED_PHYRX_RSSI_LEGACY_3_RECEIVE_RSSI_INFO_PRE_RSSI_INFO_DETAILS_OFFSET \ + PHYRX_RSSI_LEGACY_3_PRE_RSSI_INFO_DETAILS_RSSI_PRI20_CHAIN0_OFFSET +#define UNIFIED_PHYRX_RSSI_LEGACY_19_RECEIVE_RSSI_INFO_PREAMBLE_RSSI_INFO_DETAILS_OFFSET \ + PHYRX_RSSI_LEGACY_19_PREAMBLE_RSSI_INFO_DETAILS_RSSI_PRI20_CHAIN0_OFFSET +#define UNIFIED_RX_MPDU_START_0_RX_MPDU_INFO_RX_MPDU_INFO_DETAILS_OFFSET \ + RX_MPDU_START_9_RX_MPDU_INFO_DETAILS_RXPCU_MPDU_FILTER_IN_CATEGORY_OFFSET +#define UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET \ + RX_MSDU_LINK_8_MSDU_0_BUFFER_ADDR_INFO_DETAILS_BUFFER_ADDR_31_0_OFFSET +#define UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_DETAILS_FIRST_MSDU_IN_MPDU_FLAG_OFFSET +#define UNIFIED_RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET \ + RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_DETAILS_MSDU_COUNT_OFFSET +#define UNIFIED_REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET \ + REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_DETAILS_MSDU_COUNT_OFFSET +#define UNIFORM_REO_STATUS_HEADER_STATUS_HEADER \ + STATUS_HEADER_REO_STATUS_NUMBER +#define UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC \ + STATUS_HEADER_TIMESTAMP +#define UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_DETAILS_FIRST_MSDU_IN_MPDU_FLAG_OFFSET +#define UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET \ + RX_MSDU_LINK_8_MSDU_0_BUFFER_ADDR_INFO_DETAILS_BUFFER_ADDR_31_0_OFFSET +#define UNIFIED_TCL_DATA_CMD_0_BUFFER_ADDR_INFO_BUF_ADDR_INFO_OFFSET \ + TCL_DATA_CMD_0_BUF_ADDR_INFO_BUFFER_ADDR_31_0_OFFSET +#define UNIFIED_TCL_DATA_CMD_1_BUFFER_ADDR_INFO_BUF_ADDR_INFO_OFFSET \ + TCL_DATA_CMD_1_BUF_ADDR_INFO_BUFFER_ADDR_39_32_OFFSET +#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_OFFSET \ + TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_OFFSET +#define UNIFIED_BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_LSB \ + BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_LSB +#define UNIFIED_BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_MASK \ + BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_MASK +#define UNIFIED_BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_LSB \ + BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_LSB +#define UNIFIED_BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_MASK \ + BUFFER_ADDR_INFO_1_BUFFER_ADDR_39_32_MASK +#define UNIFIED_BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_LSB \ + BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_LSB +#define UNIFIED_BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_MASK \ + BUFFER_ADDR_INFO_1_RETURN_BUFFER_MANAGER_MASK +#define UNIFIED_BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_LSB \ + BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_LSB +#define UNIFIED_BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_MASK \ + BUFFER_ADDR_INFO_1_SW_BUFFER_COOKIE_MASK +#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_LSB \ + TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_LSB +#define UNIFIED_TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_MASK \ + TCL_DATA_CMD_2_BUF_OR_EXT_DESC_TYPE_MASK +#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_MASK \ + WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_MASK +#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_OFFSET \ + WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_OFFSET +#define UNIFIED_WBM_RELEASE_RING_6_TX_RATE_STATS_INFO_TX_RATE_STATS_LSB \ + WBM_RELEASE_RING_6_TX_RATE_STATS_PPDU_TRANSMISSION_TSF_LSB + +#define CE_WINDOW_ADDRESS_9000 \ + ((CE_WFSS_CE_REG_BASE >> WINDOW_SHIFT) & WINDOW_VALUE_MASK) + +#define UMAC_WINDOW_ADDRESS_9000 \ + ((SEQ_WCSS_UMAC_OFFSET >> WINDOW_SHIFT) & WINDOW_VALUE_MASK) + +#define WINDOW_CONFIGURATION_VALUE_9000 \ + ((CE_WINDOW_ADDRESS_9000 << 6) |\ + (UMAC_WINDOW_ADDRESS_9000 << 12) | \ + WINDOW_ENABLE_BIT) + +#include +#include +#include +#include + +/** + * hal_rx_msdu_start_nss_get_9000(): API to get the NSS + * Interval from rx_msdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(nss) + */ +static uint32_t hal_rx_msdu_start_nss_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_start *msdu_start = + &pkt_tlvs->msdu_start_tlv.rx_msdu_start; + uint8_t mimo_ss_bitmap; + + mimo_ss_bitmap = HAL_RX_MSDU_START_MIMO_SS_BITMAP(msdu_start); + + return qdf_get_hweight8(mimo_ss_bitmap); +} + +/** + * hal_rx_mon_hw_desc_get_mpdu_status_9000(): Retrieve MPDU status + * + * @ hw_desc_addr: Start address of Rx HW TLVs + * @ rs: Status for monitor mode + * + * Return: void + */ +static void hal_rx_mon_hw_desc_get_mpdu_status_9000(void *hw_desc_addr, + struct mon_rx_status *rs) +{ + struct rx_msdu_start *rx_msdu_start; + struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + uint32_t reg_value; + const uint32_t sgi_hw_to_cdp[] = { + CDP_SGI_0_8_US, + CDP_SGI_0_4_US, + CDP_SGI_1_6_US, + CDP_SGI_3_2_US, + }; + + rx_msdu_start = &rx_desc->msdu_start_tlv.rx_msdu_start; + + HAL_RX_GET_MSDU_AGGREGATION(rx_desc, rs); + + rs->ant_signal_db = HAL_RX_GET(rx_msdu_start, + RX_MSDU_START_5, USER_RSSI); + rs->is_stbc = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, STBC); + + reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, SGI); + rs->sgi = sgi_hw_to_cdp[reg_value]; + reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEPTION_TYPE); + rs->beamformed = (reg_value == HAL_RX_RECEPTION_TYPE_MU_MIMO) ? 1 : 0; + /* TODO: rs->beamformed should be set for SU beamforming also */ +} + +#define LINK_DESC_SIZE (NUM_OF_DWORDS_RX_MSDU_LINK << 2) +/** + * hal_get_link_desc_size_9000(): API to get the link desc size + * + * Return: uint32_t + */ +static uint32_t hal_get_link_desc_size_9000(void) +{ + return LINK_DESC_SIZE; +} + +/** + * hal_rx_get_tlv_9000(): API to get the tlv + * + * @rx_tlv: TLV data extracted from the rx packet + * Return: uint8_t + */ +static uint8_t hal_rx_get_tlv_9000(void *rx_tlv) +{ + return HAL_RX_GET(rx_tlv, PHYRX_RSSI_LEGACY_0, RECEIVE_BANDWIDTH); +} + +/** + * hal_rx_proc_phyrx_other_receive_info_tlv_9000(): API to get tlv info + * + * Return: uint32_t + */ +static inline +void hal_rx_proc_phyrx_other_receive_info_tlv_9000(void *rx_tlv_hdr, + void *ppdu_info_hdl) +{ +} + +/** + * hal_rx_dump_msdu_start_tlv_9000() : dump RX msdu_start TLV in structured + * human readable format. + * @ msdu_start: pointer the msdu_start TLV in pkt. + * @ dbg_level: log level. + * + * Return: void + */ +static void hal_rx_dump_msdu_start_tlv_9000(void *msdustart, + uint8_t dbg_level) +{ + struct rx_msdu_start *msdu_start = (struct rx_msdu_start *)msdustart; + + QDF_TRACE(QDF_MODULE_ID_DP, dbg_level, + "rx_msdu_start tlv - " + "rxpcu_mpdu_filter_in_category: %d " + "sw_frame_group_id: %d " + "phy_ppdu_id: %d " + "msdu_length: %d " + "ipsec_esp: %d " + "l3_offset: %d " + "ipsec_ah: %d " + "l4_offset: %d " + "msdu_number: %d " + "decap_format: %d " + "ipv4_proto: %d " + "ipv6_proto: %d " + "tcp_proto: %d " + "udp_proto: %d " + "ip_frag: %d " + "tcp_only_ack: %d " + "da_is_bcast_mcast: %d " + "ip4_protocol_ip6_next_header: %d " + "toeplitz_hash_2_or_4: %d " + "flow_id_toeplitz: %d " + "user_rssi: %d " + "pkt_type: %d " + "stbc: %d " + "sgi: %d " + "rate_mcs: %d " + "receive_bandwidth: %d " + "reception_type: %d " + "ppdu_start_timestamp: %d " + "sw_phy_meta_data: %d ", + msdu_start->rxpcu_mpdu_filter_in_category, + msdu_start->sw_frame_group_id, + msdu_start->phy_ppdu_id, + msdu_start->msdu_length, + msdu_start->ipsec_esp, + msdu_start->l3_offset, + msdu_start->ipsec_ah, + msdu_start->l4_offset, + msdu_start->msdu_number, + msdu_start->decap_format, + msdu_start->ipv4_proto, + msdu_start->ipv6_proto, + msdu_start->tcp_proto, + msdu_start->udp_proto, + msdu_start->ip_frag, + msdu_start->tcp_only_ack, + msdu_start->da_is_bcast_mcast, + msdu_start->ip4_protocol_ip6_next_header, + msdu_start->toeplitz_hash_2_or_4, + msdu_start->flow_id_toeplitz, + msdu_start->user_rssi, + msdu_start->pkt_type, + msdu_start->stbc, + msdu_start->sgi, + msdu_start->rate_mcs, + msdu_start->receive_bandwidth, + msdu_start->reception_type, + msdu_start->ppdu_start_timestamp, + msdu_start->sw_phy_meta_data); +} + +/** + * hal_rx_dump_msdu_end_tlv_9000: dump RX msdu_end TLV in structured + * human readable format. + * @ msdu_end: pointer the msdu_end TLV in pkt. + * @ dbg_level: log level. + * + * Return: void + */ +static void hal_rx_dump_msdu_end_tlv_9000(void *msduend, + uint8_t dbg_level) +{ + struct rx_msdu_end *msdu_end = (struct rx_msdu_end *)msduend; + + QDF_TRACE(QDF_MODULE_ID_DP, dbg_level, + "rx_msdu_end tlv - " + "rxpcu_mpdu_filter_in_category: %d " + "sw_frame_group_id: %d " + "phy_ppdu_id: %d " + "ip_hdr_chksum: %d " + "reported_mpdu_length: %d " + "key_id_octet: %d " + "cce_super_rule: %d " + "cce_classify_not_done_truncat: %d " + "cce_classify_not_done_cce_dis: %d " + "rule_indication_31_0: %d " + "rule_indication_63_32: %d " + "da_offset: %d " + "sa_offset: %d " + "da_offset_valid: %d " + "sa_offset_valid: %d " + "ipv6_options_crc: %d " + "tcp_seq_number: %d " + "tcp_ack_number: %d " + "tcp_flag: %d " + "lro_eligible: %d " + "window_size: %d " + "tcp_udp_chksum: %d " + "sa_idx_timeout: %d " + "da_idx_timeout: %d " + "msdu_limit_error: %d " + "flow_idx_timeout: %d " + "flow_idx_invalid: %d " + "wifi_parser_error: %d " + "amsdu_parser_error: %d " + "sa_is_valid: %d " + "da_is_valid: %d " + "da_is_mcbc: %d " + "l3_header_padding: %d " + "first_msdu: %d " + "last_msdu: %d " + "sa_idx: %d " + "msdu_drop: %d " + "reo_destination_indication: %d " + "flow_idx: %d " + "fse_metadata: %d " + "cce_metadata: %d " + "sa_sw_peer_id: %d ", + msdu_end->rxpcu_mpdu_filter_in_category, + msdu_end->sw_frame_group_id, + msdu_end->phy_ppdu_id, + msdu_end->ip_hdr_chksum, + msdu_end->reported_mpdu_length, + msdu_end->key_id_octet, + msdu_end->cce_super_rule, + msdu_end->cce_classify_not_done_truncate, + msdu_end->cce_classify_not_done_cce_dis, + msdu_end->rule_indication_31_0, + msdu_end->rule_indication_63_32, + msdu_end->da_offset, + msdu_end->sa_offset, + msdu_end->da_offset_valid, + msdu_end->sa_offset_valid, + msdu_end->ipv6_options_crc, + msdu_end->tcp_seq_number, + msdu_end->tcp_ack_number, + msdu_end->tcp_flag, + msdu_end->lro_eligible, + msdu_end->window_size, + msdu_end->tcp_udp_chksum, + msdu_end->sa_idx_timeout, + msdu_end->da_idx_timeout, + msdu_end->msdu_limit_error, + msdu_end->flow_idx_timeout, + msdu_end->flow_idx_invalid, + msdu_end->wifi_parser_error, + msdu_end->amsdu_parser_error, + msdu_end->sa_is_valid, + msdu_end->da_is_valid, + msdu_end->da_is_mcbc, + msdu_end->l3_header_padding, + msdu_end->first_msdu, + msdu_end->last_msdu, + msdu_end->sa_idx, + msdu_end->msdu_drop, + msdu_end->reo_destination_indication, + msdu_end->flow_idx, + msdu_end->fse_metadata, + msdu_end->cce_metadata, + msdu_end->sa_sw_peer_id); +} + +/** + * hal_rx_mpdu_start_tid_get_9000(): API to get tid + * from rx_msdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(tid value) + */ +static uint32_t hal_rx_mpdu_start_tid_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint32_t tid; + + tid = HAL_RX_MPDU_INFO_TID_GET(&mpdu_start->rx_mpdu_info_details); + + return tid; +} + +/** + * hal_rx_msdu_start_reception_type_get(): API to get the reception type + * Interval from rx_msdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(reception_type) + */ +static uint32_t hal_rx_msdu_start_reception_type_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_start *msdu_start = + &pkt_tlvs->msdu_start_tlv.rx_msdu_start; + uint32_t reception_type; + + reception_type = HAL_RX_MSDU_START_RECEPTION_TYPE_GET(msdu_start); + + return reception_type; +} + + /** + * hal_rx_msdu_end_da_idx_get_9000: API to get da_idx + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da index + */ +static uint16_t hal_rx_msdu_end_da_idx_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint16_t da_idx; + + da_idx = HAL_RX_MSDU_END_DA_IDX_GET(msdu_end); + + return da_idx; +} + +/** + * hal_rx_get_rx_fragment_number_9000(): Function to retrieve rx fragment number + * + * @nbuf: Network buffer + * Returns: rx fragment number + */ +static +uint8_t hal_rx_get_rx_fragment_number_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + /* Return first 4 bits as fragment number */ + return (HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info) & + DOT11_SEQ_FRAG_MASK); +} + +/** + * hal_rx_msdu_end_da_is_mcbc_get_9000(): API to check if pkt is MCBC + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_mcbc + */ +static uint8_t +hal_rx_msdu_end_da_is_mcbc_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_DA_IS_MCBC_GET(msdu_end); +} + +/** + * hal_rx_msdu_end_sa_is_valid_get_9000(): API to get_9000 the + * sa_is_valid bit from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_is_valid bit + */ +static uint8_t +hal_rx_msdu_end_sa_is_valid_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t sa_is_valid; + + sa_is_valid = HAL_RX_MSDU_END_SA_IS_VALID_GET(msdu_end); + + return sa_is_valid; +} + +/** + * hal_rx_msdu_end_sa_idx_get_9000(): API to get_9000 the + * sa_idx from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: sa_idx (SA AST index) + */ +static uint16_t hal_rx_msdu_end_sa_idx_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint16_t sa_idx; + + sa_idx = HAL_RX_MSDU_END_SA_IDX_GET(msdu_end); + + return sa_idx; +} + +/** + * hal_rx_desc_is_first_msdu_9000() - Check if first msdu + * + * @hal_soc_hdl: hal_soc handle + * @hw_desc_addr: hardware descriptor address + * + * Return: 0 - success/ non-zero failure + */ +static uint32_t hal_rx_desc_is_first_msdu_9000(void *hw_desc_addr) +{ + struct rx_pkt_tlvs *rx_tlvs = (struct rx_pkt_tlvs *)hw_desc_addr; + struct rx_msdu_end *msdu_end = &rx_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_GET(msdu_end, RX_MSDU_END_10, FIRST_MSDU); +} + +/** + * hal_rx_msdu_end_l3_hdr_padding_get_9000(): API to get_9000 the + * l3_header padding from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: number of l3 header padding bytes + */ +static uint32_t hal_rx_msdu_end_l3_hdr_padding_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint32_t l3_header_padding; + + l3_header_padding = HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(msdu_end); + + return l3_header_padding; +} + +/** + * @ hal_rx_encryption_info_valid_9000: Returns encryption type. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: encryption type + */ +inline uint32_t hal_rx_encryption_info_valid_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + uint32_t encryption_info = HAL_RX_MPDU_ENCRYPTION_INFO_VALID(mpdu_info); + + return encryption_info; +} + +/* + * @ hal_rx_print_pn_9000: Prints the PN of rx packet. + * + * @ buf: rx_tlv_hdr of the received packet + * @ Return: void + */ +static void hal_rx_print_pn_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + uint32_t pn_31_0 = HAL_RX_MPDU_PN_31_0_GET(mpdu_info); + uint32_t pn_63_32 = HAL_RX_MPDU_PN_63_32_GET(mpdu_info); + uint32_t pn_95_64 = HAL_RX_MPDU_PN_95_64_GET(mpdu_info); + uint32_t pn_127_96 = HAL_RX_MPDU_PN_127_96_GET(mpdu_info); + + hal_debug("PN number pn_127_96 0x%x pn_95_64 0x%x pn_63_32 0x%x pn_31_0 0x%x ", + pn_127_96, pn_95_64, pn_63_32, pn_31_0); +} + +/** + * hal_rx_msdu_end_first_msdu_get_9000: API to get first msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: first_msdu + */ +static uint8_t hal_rx_msdu_end_first_msdu_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t first_msdu; + + first_msdu = HAL_RX_MSDU_END_FIRST_MSDU_GET(msdu_end); + + return first_msdu; +} + +/** + * hal_rx_msdu_end_da_is_valid_get_9000: API to check if da is valid + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: da_is_valid + */ +static uint8_t hal_rx_msdu_end_da_is_valid_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t da_is_valid; + + da_is_valid = HAL_RX_MSDU_END_DA_IS_VALID_GET(msdu_end); + + return da_is_valid; +} + +/** + * hal_rx_msdu_end_last_msdu_get_9000: API to get last msdu status + * from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * Return: last_msdu + */ +static uint8_t hal_rx_msdu_end_last_msdu_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + uint8_t last_msdu; + + last_msdu = HAL_RX_MSDU_END_LAST_MSDU_GET(msdu_end); + + return last_msdu; +} + +/* + * hal_rx_get_mpdu_mac_ad4_valid(): Retrieves if mpdu 4th addr is valid + * + * @nbuf: Network buffer + * Returns: value of mpdu 4th address valid field + */ +inline bool hal_rx_get_mpdu_mac_ad4_valid_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + bool ad4_valid = 0; + + ad4_valid = HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(rx_mpdu_info); + + return ad4_valid; +} + +/** + * hal_rx_mpdu_start_sw_peer_id_get_9000: Retrieve sw peer_id + * @buf: network buffer + * + * Return: sw peer_id + */ +static uint32_t hal_rx_mpdu_start_sw_peer_id_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_SW_PEER_ID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/* + * hal_rx_mpdu_get_to_ds_9000(): API to get the tods info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(to_ds) + */ +static uint32_t hal_rx_mpdu_get_to_ds_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_TODS(mpdu_info); +} + +/* + * hal_rx_mpdu_get_fr_ds_9000(): API to get the from ds info + * from rx_mpdu_start + * + * @buf: pointer to the start of RX PKT TLV header + * Return: uint32_t(fr_ds) + */ +static uint32_t hal_rx_mpdu_get_fr_ds_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + + return HAL_RX_MPDU_GET_FROMDS(mpdu_info); +} + +/* + * hal_rx_get_mpdu_frame_control_valid_9000(): Retrieves mpdu + * frame control valid + * + * @nbuf: Network buffer + * Returns: value of frame control valid field + */ +static uint8_t hal_rx_get_mpdu_frame_control_valid_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(rx_mpdu_info); +} + +/* + * hal_rx_mpdu_get_addr1_9000(): API to check get address1 of the mpdu + * + * @buf: pointer to the start of RX PKT TLV headera + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr1_9000(uint8_t *buf, + uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr1 { + uint32_t ad1_31_0; + uint16_t ad1_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr1 *addr = (struct hal_addr1 *)mac_addr; + uint32_t mac_addr_ad1_valid; + + mac_addr_ad1_valid = HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(mpdu_info); + + if (mac_addr_ad1_valid) { + addr->ad1_31_0 = HAL_RX_MPDU_AD1_31_0_GET(mpdu_info); + addr->ad1_47_32 = HAL_RX_MPDU_AD1_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr2_9000(): API to check get address2 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr2_9000(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr2 { + uint16_t ad2_15_0; + uint32_t ad2_47_16; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr2 *addr = (struct hal_addr2 *)mac_addr; + uint32_t mac_addr_ad2_valid; + + mac_addr_ad2_valid = HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(mpdu_info); + + if (mac_addr_ad2_valid) { + addr->ad2_15_0 = HAL_RX_MPDU_AD2_15_0_GET(mpdu_info); + addr->ad2_47_16 = HAL_RX_MPDU_AD2_47_16_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr3_9000(): API to get address3 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr3_9000(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr3 { + uint32_t ad3_31_0; + uint16_t ad3_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr3 *addr = (struct hal_addr3 *)mac_addr; + uint32_t mac_addr_ad3_valid; + + mac_addr_ad3_valid = HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(mpdu_info); + + if (mac_addr_ad3_valid) { + addr->ad3_31_0 = HAL_RX_MPDU_AD3_31_0_GET(mpdu_info); + addr->ad3_47_32 = HAL_RX_MPDU_AD3_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_mpdu_get_addr4_9000(): API to get address4 of the mpdu + * in the packet + * + * @buf: pointer to the start of RX PKT TLV header + * @mac_addr: pointer to mac address + * Return: success/failure + */ +static QDF_STATUS hal_rx_mpdu_get_addr4_9000(uint8_t *buf, uint8_t *mac_addr) +{ + struct __attribute__((__packed__)) hal_addr4 { + uint32_t ad4_31_0; + uint16_t ad4_47_32; + }; + + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details; + struct hal_addr4 *addr = (struct hal_addr4 *)mac_addr; + uint32_t mac_addr_ad4_valid; + + mac_addr_ad4_valid = HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(mpdu_info); + + if (mac_addr_ad4_valid) { + addr->ad4_31_0 = HAL_RX_MPDU_AD4_31_0_GET(mpdu_info); + addr->ad4_47_32 = HAL_RX_MPDU_AD4_47_32_GET(mpdu_info); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_E_FAILURE; +} + +/* + * hal_rx_get_mpdu_sequence_control_valid_9000(): Get mpdu + * sequence control valid + * + * @nbuf: Network buffer + * Returns: value of sequence control valid field + */ +static uint8_t hal_rx_get_mpdu_sequence_control_valid_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(rx_mpdu_info); +} + +/** + * hal_rx_is_unicast_9000: check packet is unicast frame or not. + * + * @ buf: pointer to rx pkt TLV. + * + * Return: true on unicast. + */ +static bool hal_rx_is_unicast_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint32_t grp_id; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + + grp_id = (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_OFFSET)), + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_MASK, + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_LSB)); + + return (HAL_MPDU_SW_FRAME_GROUP_UNICAST_DATA == grp_id) ? true : false; +} + +/** + * hal_rx_tid_get_9000: get tid based on qos control valid. + * @hal_soc_hdl: hal soc handle + * @buf: pointer to rx pkt TLV. + * + * Return: tid + */ +static uint32_t hal_rx_tid_get_9000(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + uint8_t *rx_mpdu_info = (uint8_t *)&mpdu_start->rx_mpdu_info_details; + uint8_t qos_control_valid = + (_HAL_MS((*_OFFSET_TO_WORD_PTR((rx_mpdu_info), + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_OFFSET)), + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_MASK, + RX_MPDU_INFO_11_MPDU_QOS_CONTROL_VALID_LSB)); + + if (qos_control_valid) + return hal_rx_mpdu_start_tid_get_9000(buf); + + return HAL_RX_NON_QOS_TID; +} + +/** + * hal_rx_hw_desc_get_ppduid_get_9000(): retrieve ppdu id + * @hw_desc_addr: hw addr + * + * Return: ppdu id + */ +static uint32_t hal_rx_hw_desc_get_ppduid_get_9000(void *hw_desc_addr) +{ + struct rx_mpdu_info *rx_mpdu_info; + struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; + + rx_mpdu_info = + &rx_desc->mpdu_start_tlv.rx_mpdu_start.rx_mpdu_info_details; + + return HAL_RX_GET(rx_mpdu_info, RX_MPDU_INFO_9, PHY_PPDU_ID); +} + +/** + * hal_reo_status_get_header_9000 - Process reo desc info + * @d - Pointer to reo descriptior + * @b - tlv type info + * @h1 - Pointer to hal_reo_status_header where info to be stored + * + * Return - none. + * + */ +static void hal_reo_status_get_header_9000(uint32_t *d, int b, void *h1) +{ + uint32_t val1 = 0; + struct hal_reo_status_header *h = + (struct hal_reo_status_header *)h1; + + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_0, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->cmd_num = + HAL_GET_FIELD( + UNIFORM_REO_STATUS_HEADER_0, REO_STATUS_NUMBER, + val1); + h->exec_time = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + CMD_EXECUTION_TIME, val1); + h->status = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_0, + REO_CMD_EXECUTION_STATUS, val1); + switch (b) { + case HAL_REO_QUEUE_STATS_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_GET_QUEUE_STATS_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_FLUSH_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_QUEUE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_FLUSH_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_CACHE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_UNBLK_CACHE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UNBLOCK_CACHE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_TIMOUT_LIST_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_FLUSH_TIMEOUT_LIST_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_DESC_THRES_STATUS_TLV: + val1 = + d[HAL_OFFSET_DW(REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + case HAL_REO_UPDATE_RX_QUEUE_STATUS_TLV: + val1 = d[HAL_OFFSET_DW(REO_UPDATE_RX_REO_QUEUE_STATUS_1, + UNIFORM_REO_STATUS_HEADER_STATUS_HEADER_GENERIC)]; + break; + default: + qdf_nofl_err("ERROR: Unknown tlv\n"); + break; + } + h->tstamp = + HAL_GET_FIELD(UNIFORM_REO_STATUS_HEADER_1, TIMESTAMP, val1); +} + +/** + * hal_rx_mpdu_start_mpdu_qos_control_valid_get_9000(): + * Retrieve qos control valid bit from the tlv. + * @buf: pointer to rx pkt TLV. + * + * Return: qos control value. + */ +static inline uint32_t +hal_rx_mpdu_start_mpdu_qos_control_valid_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_mpdu_start *mpdu_start = + &pkt_tlvs->mpdu_start_tlv.rx_mpdu_start; + + return HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET( + &mpdu_start->rx_mpdu_info_details); +} + +/** + * hal_rx_msdu_end_sa_sw_peer_id_get_9000(): API to get the + * sa_sw_peer_id from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: sa_sw_peer_id index + */ +static inline uint32_t +hal_rx_msdu_end_sa_sw_peer_id_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(msdu_end); +} + +/** + * hal_tx_desc_set_mesh_en_9000 - Set mesh_enable flag in Tx descriptor + * @desc: Handle to Tx Descriptor + * @en: For raw WiFi frames, this indicates transmission to a mesh STA, + * enabling the interpretation of the 'Mesh Control Present' bit + * (bit 8) of QoS Control (otherwise this bit is ignored), + * For native WiFi frames, this indicates that a 'Mesh Control' field + * is present between the header and the LLC. + * + * Return: void + */ +static inline +void hal_tx_desc_set_mesh_en_9000(void *desc, uint8_t en) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_5, MESH_ENABLE) |= + HAL_TX_SM(TCL_DATA_CMD_5, MESH_ENABLE, en); +} + +static +void *hal_rx_msdu0_buffer_addr_lsb_9000(void *link_desc_va) +{ + return (void *)HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va); +} + +static +void *hal_rx_msdu_desc_info_ptr_get_9000(void *msdu0) +{ + return (void *)HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0); +} + +static +void *hal_ent_mpdu_desc_info_9000(void *ent_ring_desc) +{ + return (void *)HAL_ENT_MPDU_DESC_INFO(ent_ring_desc); +} + +static +void *hal_dst_mpdu_desc_info_9000(void *dst_ring_desc) +{ + return (void *)HAL_DST_MPDU_DESC_INFO(dst_ring_desc); +} + +static +uint8_t hal_rx_get_fc_valid_9000(uint8_t *buf) +{ + return HAL_RX_GET_FC_VALID(buf); +} + +static uint8_t hal_rx_get_to_ds_flag_9000(uint8_t *buf) +{ + return HAL_RX_GET_TO_DS_FLAG(buf); +} + +static uint8_t hal_rx_get_mac_addr2_valid_9000(uint8_t *buf) +{ + return HAL_RX_GET_MAC_ADDR2_VALID(buf); +} + +static uint8_t hal_rx_get_filter_category_9000(uint8_t *buf) +{ + return HAL_RX_GET_FILTER_CATEGORY(buf); +} + +static uint32_t +hal_rx_get_ppdu_id_9000(uint8_t *buf) +{ + return HAL_RX_GET_PPDU_ID(buf); +} + +/** + * hal_reo_config_9000(): Set reo config parameters + * @soc: hal soc handle + * @reg_val: value to be set + * @reo_params: reo parameters + * + * Return: void + */ +static void +hal_reo_config_9000(struct hal_soc *soc, + uint32_t reg_val, + struct hal_reo_params *reo_params) +{ + HAL_REO_R0_CONFIG(soc, reg_val, reo_params); +} + +/** + * hal_rx_msdu_desc_info_get_ptr_9000() - Get msdu desc info ptr + * @msdu_details_ptr - Pointer to msdu_details_ptr + * + * Return - Pointer to rx_msdu_desc_info structure. + * + */ +static void *hal_rx_msdu_desc_info_get_ptr_9000(void *msdu_details_ptr) +{ + return HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr); +} + +/** + * hal_rx_link_desc_msdu0_ptr_9000 - Get pointer to rx_msdu details + * @link_desc - Pointer to link desc + * + * Return - Pointer to rx_msdu_details structure + * + */ +static void *hal_rx_link_desc_msdu0_ptr_9000(void *link_desc) +{ + return HAL_RX_LINK_DESC_MSDU0_PTR(link_desc); +} + +/** + * hal_rx_msdu_flow_idx_get_9000: API to get flow index + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index value from MSDU END TLV + */ +static inline uint32_t hal_rx_msdu_flow_idx_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_invalid_9000: API to get flow index invalid + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index invalid value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_invalid_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); +} + +/** + * hal_rx_msdu_flow_idx_timeout_9000: API to get flow index timeout + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: flow index timeout value from MSDU END TLV + */ +static bool hal_rx_msdu_flow_idx_timeout_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); +} + +/** + * hal_rx_msdu_fse_metadata_get_9000: API to get FSE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: fse metadata value from MSDU END TLV + */ +static uint32_t hal_rx_msdu_fse_metadata_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_FSE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_cce_metadata_get_9000: API to get CCE metadata + * from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * + * Return: cce_metadata + */ +static uint16_t +hal_rx_msdu_cce_metadata_get_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_MSDU_END_CCE_METADATA_GET(msdu_end); +} + +/** + * hal_rx_msdu_get_flow_params_9000: API to get flow index, flow index invalid + * and flow index timeout from rx_msdu_end TLV + * @buf: pointer to the start of RX PKT TLV headers + * @flow_invalid: pointer to return value of flow_idx_valid + * @flow_timeout: pointer to return value of flow_idx_timeout + * @flow_index: pointer to return value of flow_idx + * + * Return: none + */ +static inline void +hal_rx_msdu_get_flow_params_9000(uint8_t *buf, + bool *flow_invalid, + bool *flow_timeout, + uint32_t *flow_index) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + + *flow_invalid = HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(msdu_end); + *flow_timeout = HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(msdu_end); + *flow_index = HAL_RX_MSDU_END_FLOW_IDX_GET(msdu_end); +} + +/** + * hal_rx_tlv_get_tcp_chksum_9000() - API to get tcp checksum + * @buf: rx_tlv_hdr + * + * Return: tcp checksum + */ +static uint16_t +hal_rx_tlv_get_tcp_chksum_9000(uint8_t *buf) +{ + return HAL_RX_TLV_GET_TCP_CHKSUM(buf); +} + +/** + * hal_rx_get_rx_sequence_9000(): Function to retrieve rx sequence number + * + * @nbuf: Network buffer + * Returns: rx sequence number + */ +static +uint16_t hal_rx_get_rx_sequence_9000(uint8_t *buf) +{ + struct rx_pkt_tlvs *pkt_tlvs = hal_rx_get_pkt_tlvs(buf); + struct rx_mpdu_info *rx_mpdu_info = hal_rx_get_mpdu_info(pkt_tlvs); + + return HAL_RX_MPDU_GET_SEQUENCE_NUMBER(rx_mpdu_info); +} + +/** + * hal_get_window_address_9000(): Function to get hp/tp address + * @hal_soc: Pointer to hal_soc + * @addr: address offset of register + * + * Return: modified address offset of register + */ +static inline qdf_iomem_t hal_get_window_address_9000(struct hal_soc *hal_soc, + qdf_iomem_t addr) +{ + uint32_t offset = addr - hal_soc->dev_base_addr; + qdf_iomem_t new_offset; + + /* + * If offset lies within DP register range, use 3rd window to write + * into DP region. + */ + if ((offset ^ SEQ_WCSS_UMAC_OFFSET) < WINDOW_RANGE_MASK) { + new_offset = (hal_soc->dev_base_addr + (3 * WINDOW_START) + + (offset & WINDOW_RANGE_MASK)); + /* + * If offset lies within CE register range, use 2nd window to write + * into CE region. + */ + } else if ((offset ^ CE_WFSS_CE_REG_BASE) < WINDOW_RANGE_MASK) { + new_offset = (hal_soc->dev_base_addr + (2 * WINDOW_START) + + (offset & WINDOW_RANGE_MASK)); + } else { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "%s: ERROR: Accessing Wrong register\n", __func__); + qdf_assert_always(0); + return 0; + } + return new_offset; +} + +static inline void hal_write_window_register(struct hal_soc *hal_soc) +{ + /* Write value into window configuration register */ + qdf_iowrite32(hal_soc->dev_base_addr + WINDOW_REG_ADDRESS, + WINDOW_CONFIGURATION_VALUE_9000); +} + +/** + * hal_rx_msdu_packet_metadata_get_9000(): API to get the + * msdu information from rx_msdu_end TLV + * + * @ buf: pointer to the start of RX PKT TLV headers + * @ hal_rx_msdu_metadata: pointer to the msdu info structure + */ +static void +hal_rx_msdu_packet_metadata_get_9000(uint8_t *buf, + void *msdu_pkt_metadata) +{ + struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf; + struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end; + struct hal_rx_msdu_metadata *msdu_metadata = + (struct hal_rx_msdu_metadata *)msdu_pkt_metadata; + + msdu_metadata->l3_hdr_pad = + HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(msdu_end); + msdu_metadata->sa_idx = HAL_RX_MSDU_END_SA_IDX_GET(msdu_end); + msdu_metadata->da_idx = HAL_RX_MSDU_END_DA_IDX_GET(msdu_end); + msdu_metadata->sa_sw_peer_id = + HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(msdu_end); +} + +struct hal_hw_txrx_ops qcn9000_hal_hw_txrx_ops = { + + /* init and setup */ + hal_srng_dst_hw_init_generic, + hal_srng_src_hw_init_generic, + hal_get_hw_hptp_generic, + hal_reo_setup_generic, + hal_setup_link_idle_list_generic, + hal_get_window_address_9000, + NULL, + + /* tx */ + hal_tx_desc_set_dscp_tid_table_id_9000, + hal_tx_set_dscp_tid_map_9000, + hal_tx_update_dscp_tid_9000, + hal_tx_desc_set_lmac_id_9000, + hal_tx_desc_set_buf_addr_generic, + hal_tx_desc_set_search_type_generic, + hal_tx_desc_set_search_index_generic, + hal_tx_desc_set_cache_set_num_generic, + hal_tx_comp_get_status_generic, + hal_tx_comp_get_release_reason_generic, + hal_get_wbm_internal_error_generic, + hal_tx_desc_set_mesh_en_9000, + + /* rx */ + hal_rx_msdu_start_nss_get_9000, + hal_rx_mon_hw_desc_get_mpdu_status_9000, + hal_rx_get_tlv_9000, + hal_rx_proc_phyrx_other_receive_info_tlv_9000, + hal_rx_dump_msdu_start_tlv_9000, + hal_rx_dump_msdu_end_tlv_9000, + hal_get_link_desc_size_9000, + hal_rx_mpdu_start_tid_get_9000, + hal_rx_msdu_start_reception_type_get_9000, + hal_rx_msdu_end_da_idx_get_9000, + hal_rx_msdu_desc_info_get_ptr_9000, + hal_rx_link_desc_msdu0_ptr_9000, + hal_reo_status_get_header_9000, + hal_rx_status_get_tlv_info_generic, + hal_rx_wbm_err_info_get_generic, + hal_rx_dump_mpdu_start_tlv_generic, + + hal_tx_set_pcp_tid_map_generic, + hal_tx_update_pcp_tid_generic, + hal_tx_update_tidmap_prty_generic, + hal_rx_get_rx_fragment_number_9000, + hal_rx_msdu_end_da_is_mcbc_get_9000, + hal_rx_msdu_end_sa_is_valid_get_9000, + hal_rx_msdu_end_sa_idx_get_9000, + hal_rx_desc_is_first_msdu_9000, + hal_rx_msdu_end_l3_hdr_padding_get_9000, + hal_rx_encryption_info_valid_9000, + hal_rx_print_pn_9000, + hal_rx_msdu_end_first_msdu_get_9000, + hal_rx_msdu_end_da_is_valid_get_9000, + hal_rx_msdu_end_last_msdu_get_9000, + hal_rx_get_mpdu_mac_ad4_valid_9000, + hal_rx_mpdu_start_sw_peer_id_get_9000, + hal_rx_mpdu_get_to_ds_9000, + hal_rx_mpdu_get_fr_ds_9000, + hal_rx_get_mpdu_frame_control_valid_9000, + hal_rx_mpdu_get_addr1_9000, + hal_rx_mpdu_get_addr2_9000, + hal_rx_mpdu_get_addr3_9000, + hal_rx_mpdu_get_addr4_9000, + hal_rx_get_mpdu_sequence_control_valid_9000, + hal_rx_is_unicast_9000, + hal_rx_tid_get_9000, + hal_rx_hw_desc_get_ppduid_get_9000, + hal_rx_mpdu_start_mpdu_qos_control_valid_get_9000, + hal_rx_msdu_end_sa_sw_peer_id_get_9000, + hal_rx_msdu0_buffer_addr_lsb_9000, + hal_rx_msdu_desc_info_ptr_get_9000, + hal_ent_mpdu_desc_info_9000, + hal_dst_mpdu_desc_info_9000, + hal_rx_get_fc_valid_9000, + hal_rx_get_to_ds_flag_9000, + hal_rx_get_mac_addr2_valid_9000, + hal_rx_get_filter_category_9000, + hal_rx_get_ppdu_id_9000, + hal_reo_config_9000, + hal_rx_msdu_flow_idx_get_9000, + hal_rx_msdu_flow_idx_invalid_9000, + hal_rx_msdu_flow_idx_timeout_9000, + hal_rx_msdu_fse_metadata_get_9000, + hal_rx_msdu_cce_metadata_get_9000, + hal_rx_msdu_get_flow_params_9000, + hal_rx_tlv_get_tcp_chksum_9000, + hal_rx_get_rx_sequence_9000, + NULL, + NULL, + /* rx - msdu fast path info fields */ + hal_rx_msdu_packet_metadata_get_9000, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +struct hal_hw_srng_config hw_srng_table_9000[] = { + /* TODO: max_rings can populated by querying HW capabilities */ + { /* REO_DST */ + .start_ring_id = HAL_SRNG_REO2SW1, + .max_rings = 4, + .entry_size = sizeof(struct reo_destination_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_REO_R0_REO2SW1_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO2SW1_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET) + }, + .reg_size = { + HWIO_REO_R0_REO2SW2_RING_BASE_LSB_ADDR(0) - + HWIO_REO_R0_REO2SW1_RING_BASE_LSB_ADDR(0), + HWIO_REO_R2_REO2SW2_RING_HP_ADDR(0) - + HWIO_REO_R2_REO2SW1_RING_HP_ADDR(0), + }, + .max_size = + HWIO_REO_R0_REO2SW1_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO2SW1_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_EXCEPTION */ + /* Designating REO2TCL ring as exception ring. This ring is + * similar to other REO2SW rings though it is named as REO2TCL. + * Any of theREO2SW rings can be used as exception ring. + */ + .start_ring_id = HAL_SRNG_REO2TCL, + .max_rings = 1, + .entry_size = sizeof(struct reo_destination_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_REO_R0_REO2TCL_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO2TCL_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET) + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_REO_R0_REO2TCL_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO2TCL_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_REINJECT */ + .start_ring_id = HAL_SRNG_SW2REO, + .max_rings = 1, + .entry_size = sizeof(struct reo_entrance_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_REO_R0_SW2REO_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_SW2REO_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET) + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = HWIO_REO_R0_SW2REO_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_SW2REO_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_CMD */ + .start_ring_id = HAL_SRNG_REO_CMD, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct reo_get_queue_stats)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_REO_R0_REO_CMD_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO_CMD_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = HWIO_REO_R0_REO_CMD_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO_CMD_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* REO_STATUS */ + .start_ring_id = HAL_SRNG_REO_STATUS, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct reo_get_queue_stats_status)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_REO_R0_REO_STATUS_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + HWIO_REO_R2_REO_STATUS_RING_HP_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_REO_R0_REO_STATUS_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_REO_R0_REO_STATUS_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* TCL_DATA */ + .start_ring_id = HAL_SRNG_SW2TCL1, + .max_rings = 3, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct tcl_data_cmd)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_TCL_R0_SW2TCL1_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + HWIO_TCL_R2_SW2TCL1_RING_HP_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + }, + .reg_size = { + HWIO_TCL_R0_SW2TCL2_RING_BASE_LSB_ADDR(0) - + HWIO_TCL_R0_SW2TCL1_RING_BASE_LSB_ADDR(0), + HWIO_TCL_R2_SW2TCL2_RING_HP_ADDR(0) - + HWIO_TCL_R2_SW2TCL1_RING_HP_ADDR(0), + }, + .max_size = + HWIO_TCL_R0_SW2TCL1_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_TCL_R0_SW2TCL1_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* TCL_CMD */ + .start_ring_id = HAL_SRNG_SW2TCL_CMD, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct tcl_gse_cmd)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_TCL_R0_SW2TCL_CREDIT_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + HWIO_TCL_R2_SW2TCL_CREDIT_RING_HP_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_TCL_R0_SW2TCL_CREDIT_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_TCL_R0_SW2TCL_CREDIT_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* TCL_STATUS */ + .start_ring_id = HAL_SRNG_TCL_STATUS, + .max_rings = 1, + .entry_size = (sizeof(struct tlv_32_hdr) + + sizeof(struct tcl_status_ring)) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_TCL_R0_TCL_STATUS1_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + HWIO_TCL_R2_TCL_STATUS1_RING_HP_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_TCL_R0_TCL_STATUS1_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_TCL_R0_TCL_STATUS1_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* CE_SRC */ + .start_ring_id = HAL_SRNG_CE_0_SRC, + .max_rings = 12, + .entry_size = sizeof(struct ce_src_desc) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET), + HWIO_WFSS_CE_CHANNEL_DST_R2_DEST_RING_HP_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET), + }, + .reg_size = { + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_SRC_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET, + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_SRC_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET, + }, + .max_size = + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* CE_DST */ + .start_ring_id = HAL_SRNG_CE_0_DST, + .max_rings = 12, + .entry_size = 8 >> 2, + /*TODO: entry_size above should actually be + * sizeof(struct ce_dst_desc) >> 2, but couldn't find definition + * of struct ce_dst_desc in HW header files + */ + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), + HWIO_WFSS_CE_CHANNEL_DST_R2_DEST_RING_HP_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), + }, + .reg_size = { + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, + }, + .max_size = + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* CE_DST_STATUS */ + .start_ring_id = HAL_SRNG_CE_0_DST_STATUS, + .max_rings = 12, + .entry_size = sizeof(struct ce_stat_desc) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_LSB_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), + HWIO_WFSS_CE_CHANNEL_DST_R2_STATUS_RING_HP_ADDR( + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), + }, + /* TODO: check destination status ring registers */ + .reg_size = { + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - + SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, + }, + .max_size = + HWIO_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* WBM_IDLE_LINK */ + .start_ring_id = HAL_SRNG_WBM_IDLE_LINK, + .max_rings = 1, + .entry_size = sizeof(struct wbm_link_descriptor_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_WBM_IDLE_LINK_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* SW2WBM_RELEASE */ + .start_ring_id = HAL_SRNG_WBM_SW_RELEASE, + .max_rings = 1, + .entry_size = sizeof(struct wbm_release_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_SRC_RING, + .reg_start = { + HWIO_WBM_R0_SW_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_SW_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + /* Single ring - provide ring size if multiple rings of this + * type are supported + */ + .reg_size = {}, + .max_size = + HWIO_WBM_R0_SW_RELEASE_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WBM_R0_SW_RELEASE_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* WBM2SW_RELEASE */ + .start_ring_id = HAL_SRNG_WBM2SW0_RELEASE, + .max_rings = 4, + .entry_size = sizeof(struct wbm_release_ring) >> 2, + .lmac_ring = FALSE, + .ring_dir = HAL_SRNG_DST_RING, + .reg_start = { + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_WBM2SW0_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + .reg_size = { + HWIO_WBM_R0_WBM2SW1_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET) - + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + HWIO_WBM_R2_WBM2SW1_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET) - + HWIO_WBM_R2_WBM2SW0_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), + }, + .max_size = + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_MSB_RING_SIZE_BMSK >> + HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_MSB_RING_SIZE_SHFT, + }, + { /* RXDMA_BUF */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA0_BUF0, +#ifdef IPA_OFFLOAD + .max_rings = 3, +#else + .max_rings = 2, +#endif + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_DST */ + .start_ring_id = HAL_SRNG_WMAC1_RXDMA2SW0, + .max_rings = 1, + .entry_size = sizeof(struct reo_entrance_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_DST_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_BUF */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA2_BUF, + .max_rings = 1, + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_STATUS */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA1_STATBUF, + .max_rings = 1, + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_DST */ + .start_ring_id = HAL_SRNG_WMAC1_RXDMA2SW1, + .max_rings = 1, + .entry_size = sizeof(struct reo_entrance_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_DST_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* RXDMA_MONITOR_DESC */ + .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA1_DESC, + .max_rings = 1, + .entry_size = sizeof(struct wbm_buffer_ring) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, + { /* DIR_BUF_RX_DMA_SRC */ + .start_ring_id = HAL_SRNG_DIR_BUF_RX_SRC_DMA_RING, + /* one ring for spectral and one ring for cfr */ + .max_rings = 2, + .entry_size = 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, +#ifdef WLAN_FEATURE_CIF_CFR + { /* WIFI_POS_SRC */ + .start_ring_id = HAL_SRNG_WIFI_POS_SRC_DMA_RING, + .max_rings = 1, + .entry_size = sizeof(wmi_oem_dma_buf_release_entry) >> 2, + .lmac_ring = TRUE, + .ring_dir = HAL_SRNG_SRC_RING, + /* reg_start is not set because LMAC rings are not accessed + * from host + */ + .reg_start = {}, + .reg_size = {}, + .max_size = HAL_RXDMA_MAX_RING_SIZE, + }, +#endif +}; + +int32_t hal_hw_reg_offset_qcn9000[] = { + /* dst */ + REG_OFFSET(DST, HP), + REG_OFFSET(DST, TP), + REG_OFFSET(DST, ID), + REG_OFFSET(DST, MISC), + REG_OFFSET(DST, HP_ADDR_LSB), + REG_OFFSET(DST, HP_ADDR_MSB), + REG_OFFSET(DST, MSI1_BASE_LSB), + REG_OFFSET(DST, MSI1_BASE_MSB), + REG_OFFSET(DST, MSI1_DATA), + REG_OFFSET(DST, BASE_LSB), + REG_OFFSET(DST, BASE_MSB), + REG_OFFSET(DST, PRODUCER_INT_SETUP), + /* src */ + REG_OFFSET(SRC, HP), + REG_OFFSET(SRC, TP), + REG_OFFSET(SRC, ID), + REG_OFFSET(SRC, MISC), + REG_OFFSET(SRC, TP_ADDR_LSB), + REG_OFFSET(SRC, TP_ADDR_MSB), + REG_OFFSET(SRC, MSI1_BASE_LSB), + REG_OFFSET(SRC, MSI1_BASE_MSB), + REG_OFFSET(SRC, MSI1_DATA), + REG_OFFSET(SRC, BASE_LSB), + REG_OFFSET(SRC, BASE_MSB), + REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX0), + REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX1), +}; + +/** + * hal_qcn9000_attach()- Attach 9000 target specific hal_soc ops, + * offset and srng table + * Return: void + */ +void hal_qcn9000_attach(struct hal_soc *hal_soc) +{ + hal_soc->hw_srng_table = hw_srng_table_9000; + hal_soc->hal_hw_reg_offset = hal_hw_reg_offset_qcn9000; + hal_soc->ops = &qcn9000_hal_hw_txrx_ops; + if (hal_soc->static_window_map) + hal_write_window_register(hal_soc); +} diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qcn9000/hal_9000_rx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qcn9000/hal_9000_rx.h new file mode 100644 index 0000000000000000000000000000000000000000..45528561301e4d30ccaa86511db482864ee714f7 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qcn9000/hal_9000_rx.h @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2016-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#define HAL_RX_MSDU0_BUFFER_ADDR_LSB(link_desc_va) \ + ((uint8_t *)(link_desc_va) + \ + RX_MSDU_LINK_8_MSDU_0_BUFFER_ADDR_INFO_DETAILS_BUFFER_ADDR_31_0_OFFSET) + +#define HAL_RX_MSDU_DESC_INFO_PTR_GET(msdu0) \ + ((uint8_t *)(msdu0) + \ + RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_DETAILS_FIRST_MSDU_IN_MPDU_FLAG_OFFSET) + +#define HAL_ENT_MPDU_DESC_INFO(ent_ring_desc) \ + ((uint8_t *)(ent_ring_desc) + \ + RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_DETAILS_MSDU_COUNT_OFFSET) + +#define HAL_DST_MPDU_DESC_INFO(dst_ring_desc) \ + ((uint8_t *)(dst_ring_desc) + \ + REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_DETAILS_MSDU_COUNT_OFFSET) + +#define HAL_RX_GET_FC_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, MPDU_FRAME_CONTROL_VALID) + +#define HAL_RX_GET_TO_DS_FLAG(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, TO_DS) + +#define HAL_RX_GET_MAC_ADDR1_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, MAC_ADDR_AD1_VALID) + +#define HAL_RX_GET_MAC_ADDR2_VALID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_11, MAC_ADDR_AD2_VALID) + +#define HAL_RX_GET_FILTER_CATEGORY(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_9, RXPCU_MPDU_FILTER_IN_CATEGORY) + +#define HAL_RX_GET_PPDU_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_9, PHY_PPDU_ID) + +#define HAL_RX_GET_SW_FRAME_GROUP_ID(rx_mpdu_start) \ + HAL_RX_GET(rx_mpdu_start, RX_MPDU_INFO_9, SW_FRAME_GROUP_ID) + +#define HAL_REO_R0_CONFIG(soc, reg_val, reo_params) \ + do { \ + reg_val &= \ + ~(HWIO_REO_R0_GENERAL_ENABLE_FRAGMENT_DEST_RING_BMSK |\ + HWIO_REO_R0_GENERAL_ENABLE_AGING_LIST_ENABLE_BMSK | \ + HWIO_REO_R0_GENERAL_ENABLE_AGING_FLUSH_ENABLE_BMSK); \ + reg_val |= \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + FRAGMENT_DEST_RING, \ + (reo_params)->frag_dst_ring) | \ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_LIST_ENABLE, 1) |\ + HAL_SM(HWIO_REO_R0_GENERAL_ENABLE, \ + AGING_FLUSH_ENABLE, 1);\ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ + } while (0) + +#define HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr) \ + ((struct rx_msdu_desc_info *) \ + _OFFSET_TO_BYTE_PTR((msdu_details_ptr), \ + UNIFIED_RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET)) + +#define HAL_RX_LINK_DESC_MSDU0_PTR(link_desc) \ + ((struct rx_msdu_details *) \ + _OFFSET_TO_BYTE_PTR((link_desc),\ + UNIFIED_RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET)) + +#define HAL_RX_TLV_GET_TCP_CHKSUM(buf) \ + (_HAL_MS( \ + (*_OFFSET_TO_WORD_PTR(&(((struct rx_pkt_tlvs *)(buf))->\ + msdu_end_tlv.rx_msdu_end), \ + RX_MSDU_END_10_TCP_UDP_CHKSUM_OFFSET)), \ + RX_MSDU_END_10_TCP_UDP_CHKSUM_MASK, \ + RX_MSDU_END_10_TCP_UDP_CHKSUM_LSB)) + +#define HAL_RX_MSDU_END_FIRST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_FIRST_MSDU_OFFSET)), \ + RX_MSDU_END_10_FIRST_MSDU_MASK, \ + RX_MSDU_END_10_FIRST_MSDU_LSB)) + +#define HAL_RX_MSDU_END_LAST_MSDU_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_LAST_MSDU_OFFSET)), \ + RX_MSDU_END_10_LAST_MSDU_MASK, \ + RX_MSDU_END_10_LAST_MSDU_LSB)) + +#define HAL_RX_MSDU_END_SA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_SA_IS_VALID_OFFSET)), \ + RX_MSDU_END_10_SA_IS_VALID_MASK, \ + RX_MSDU_END_10_SA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_VALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_DA_IS_VALID_OFFSET)), \ + RX_MSDU_END_10_DA_IS_VALID_MASK, \ + RX_MSDU_END_10_DA_IS_VALID_LSB)) + +#define HAL_RX_MSDU_END_DA_IS_MCBC_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_DA_IS_MCBC_OFFSET)), \ + RX_MSDU_END_10_DA_IS_MCBC_MASK, \ + RX_MSDU_END_10_DA_IS_MCBC_LSB)) + +#define HAL_RX_MSDU_END_L3_HEADER_PADDING_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_L3_HEADER_PADDING_OFFSET)), \ + RX_MSDU_END_10_L3_HEADER_PADDING_MASK, \ + RX_MSDU_END_10_L3_HEADER_PADDING_LSB)) + +#define HAL_RX_MSDU_END_SA_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_11_SA_IDX_OFFSET)), \ + RX_MSDU_END_11_SA_IDX_MASK, \ + RX_MSDU_END_11_SA_IDX_LSB)) + +#define HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_14_SA_SW_PEER_ID_OFFSET)), \ + RX_MSDU_END_14_SA_SW_PEER_ID_MASK, \ + RX_MSDU_END_14_SA_SW_PEER_ID_LSB)) + +#define HAL_RX_MSDU_END_CCE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_14_CCE_METADATA_OFFSET)), \ + RX_MSDU_END_14_CCE_METADATA_MASK, \ + RX_MSDU_END_14_CCE_METADATA_LSB)) + +#define HAL_RX_MSDU_END_DA_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_11_DA_IDX_OR_SW_PEER_ID_OFFSET)), \ + RX_MSDU_END_11_DA_IDX_OR_SW_PEER_ID_MASK, \ + RX_MSDU_END_11_DA_IDX_OR_SW_PEER_ID_LSB)) + +#define HAL_RX_MPDU_SW_FRAME_GROUP_ID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_OFFSET)), \ + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_MASK, \ + RX_MPDU_INFO_9_SW_FRAME_GROUP_ID_LSB)) \ + +#define HAL_RX_MPDU_INFO_SW_PEER_ID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_10_SW_PEER_ID_OFFSET)), \ + RX_MPDU_INFO_10_SW_PEER_ID_MASK, \ + RX_MPDU_INFO_10_SW_PEER_ID_LSB)) + +#define HAL_RX_MPDU_GET_FRAME_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MPDU_FRAME_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MPDU_FRAME_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_11_MPDU_FRAME_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD1_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD1_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD1_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD1_VALID_LSB)) + +#define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_MASK, \ + RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_LSB)) + +#define HAL_RX_MPDU_AD1_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD1_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD2_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD2_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD2_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD2_VALID_LSB)) + +#define HAL_RX_MPDU_AD2_15_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_OFFSET)), \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_MASK, \ + RX_MPDU_INFO_16_MAC_ADDR_AD2_15_0_LSB)) + +#define HAL_RX_MPDU_AD2_47_16_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_OFFSET)), \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_MASK, \ + RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD3_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD3_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD3_VALID_LSB)) + +#define HAL_RX_MPDU_AD3_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_OFFSET)), \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_MASK, \ + RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_LSB)) + +#define HAL_RX_MPDU_AD3_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_OFFSET)), \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_MASK, \ + RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_LSB)) + +#define HAL_RX_MPDU_MAC_ADDR_AD4_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_MASK, \ + RX_MPDU_INFO_11_MAC_ADDR_AD4_VALID_LSB)) + +#define HAL_RX_MPDU_AD4_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_OFFSET)), \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_MASK, \ + RX_MPDU_INFO_20_MAC_ADDR_AD4_31_0_LSB)) + +#define HAL_RX_MPDU_AD4_47_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_OFFSET)), \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_MASK, \ + RX_MPDU_INFO_21_MAC_ADDR_AD4_47_32_LSB)) + +#define HAL_RX_MPDU_GET_SEQUENCE_CONTROL_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_INFO_QOS_CONTROL_VALID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_OFFSET)), \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_MASK, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_CONTROL_VALID_LSB)) + +#define HAL_RX_MPDU_ENCRYPTION_INFO_VALID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_FRAME_ENCRYPTION_INFO_VALID_OFFSET)), \ + RX_MPDU_INFO_11_FRAME_ENCRYPTION_INFO_VALID_MASK, \ + RX_MPDU_INFO_11_FRAME_ENCRYPTION_INFO_VALID_LSB)) + +#define HAL_RX_MPDU_GET_FROMDS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_FR_DS_OFFSET)), \ + RX_MPDU_INFO_11_FR_DS_MASK, \ + RX_MPDU_INFO_11_FR_DS_LSB)) + +#define HAL_RX_MPDU_GET_TODS(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_TO_DS_OFFSET)), \ + RX_MPDU_INFO_11_TO_DS_MASK, \ + RX_MPDU_INFO_11_TO_DS_LSB)) + +#define HAL_RX_MPDU_GET_SEQUENCE_NUMBER(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_NUMBER_OFFSET)), \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_NUMBER_MASK, \ + RX_MPDU_INFO_11_MPDU_SEQUENCE_NUMBER_LSB)) + +#define HAL_RX_MPDU_PN_31_0_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_3_PN_31_0_OFFSET)), \ + RX_MPDU_INFO_3_PN_31_0_MASK, \ + RX_MPDU_INFO_3_PN_31_0_LSB)) + +#define HAL_RX_MPDU_PN_63_32_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_4_PN_63_32_OFFSET)), \ + RX_MPDU_INFO_4_PN_63_32_MASK, \ + RX_MPDU_INFO_4_PN_63_32_LSB)) + +#define HAL_RX_MPDU_PN_95_64_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_5_PN_95_64_OFFSET)), \ + RX_MPDU_INFO_5_PN_95_64_MASK, \ + RX_MPDU_INFO_5_PN_95_64_LSB)) + +#define HAL_RX_MPDU_PN_127_96_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ + RX_MPDU_INFO_6_PN_127_96_OFFSET)), \ + RX_MPDU_INFO_6_PN_127_96_MASK, \ + RX_MPDU_INFO_6_PN_127_96_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_TIMEOUT_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_FLOW_IDX_TIMEOUT_OFFSET)), \ + RX_MSDU_END_10_FLOW_IDX_TIMEOUT_MASK, \ + RX_MSDU_END_10_FLOW_IDX_TIMEOUT_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_INVALID_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_10_FLOW_IDX_INVALID_OFFSET)), \ + RX_MSDU_END_10_FLOW_IDX_INVALID_MASK, \ + RX_MSDU_END_10_FLOW_IDX_INVALID_LSB)) + +#define HAL_RX_MSDU_END_FLOW_IDX_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_12_FLOW_IDX_OFFSET)), \ + RX_MSDU_END_12_FLOW_IDX_MASK, \ + RX_MSDU_END_12_FLOW_IDX_LSB)) + +#define HAL_RX_MSDU_END_FSE_METADATA_GET(_rx_msdu_end) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ + RX_MSDU_END_13_FSE_METADATA_OFFSET)), \ + RX_MSDU_END_13_FSE_METADATA_MASK, \ + RX_MSDU_END_13_FSE_METADATA_LSB)) + +#define HAL_RX_MPDU_GET_PHY_PPDU_ID(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_9_PHY_PPDU_ID_OFFSET)), \ + RX_MPDU_INFO_9_PHY_PPDU_ID_MASK, \ + RX_MPDU_INFO_9_PHY_PPDU_ID_LSB)) \ + +#define HAL_RX_MSDU_START_MIMO_SS_BITMAP(_rx_msdu_start)\ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\ + RX_MSDU_START_5_MIMO_SS_BITMAP_OFFSET)), \ + RX_MSDU_START_5_MIMO_SS_BITMAP_MASK, \ + RX_MSDU_START_5_MIMO_SS_BITMAP_LSB)) + +#ifdef GET_MSDU_AGGREGATION +#define HAL_RX_GET_MSDU_AGGREGATION(rx_desc, rs)\ +{\ + struct rx_msdu_end *rx_msdu_end;\ + bool first_msdu, last_msdu; \ + rx_msdu_end = &rx_desc->msdu_end_tlv.rx_msdu_end;\ + first_msdu = HAL_RX_GET(rx_msdu_end, RX_MSDU_END_10, FIRST_MSDU);\ + last_msdu = HAL_RX_GET(rx_msdu_end, RX_MSDU_END_10, LAST_MSDU);\ + if (first_msdu && last_msdu)\ + rs->rs_flags &= (~IEEE80211_AMSDU_FLAG);\ + else\ + rs->rs_flags |= (IEEE80211_AMSDU_FLAG); \ +} \ + +#else +#define HAL_RX_GET_MSDU_AGGREGATION(rx_desc, rs) +#endif + +#define HAL_RX_MPDU_INFO_TID_GET(_rx_mpdu_info) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_mpdu_info), \ + RX_MPDU_INFO_7_TID_OFFSET)), \ + RX_MPDU_INFO_7_TID_MASK, \ + RX_MPDU_INFO_7_TID_LSB)) + +#define HAL_RX_MSDU_START_RECEPTION_TYPE_GET(_rx_msdu_start) \ + (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start), \ + RX_MSDU_START_5_RECEPTION_TYPE_OFFSET)), \ + RX_MSDU_START_5_RECEPTION_TYPE_MASK, \ + RX_MSDU_START_5_RECEPTION_TYPE_LSB)) diff --git a/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qcn9000/hal_9000_tx.h b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qcn9000/hal_9000_tx.h new file mode 100644 index 0000000000000000000000000000000000000000..c6c2856df85ea40c69d69e6e225807870d2530d0 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hal/wifi3.0/qcn9000/hal_9000_tx.h @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2016-2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +#include "hal_hw_headers.h" +#include "hal_internal.h" +#include "cdp_txrx_mon_struct.h" +#include "qdf_trace.h" +#include "hal_rx.h" +#include "hal_tx.h" +#include "dp_types.h" +#include "hal_api_mon.h" + +/** + * hal_tx_desc_set_dscp_tid_table_id_9000() - Sets DSCP to TID conversion + * table ID + * @desc: Handle to Tx Descriptor + * @id: DSCP to tid conversion table to be used for this frame + * + * Return: void + */ +static void hal_tx_desc_set_dscp_tid_table_id_9000(void *desc, uint8_t id) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_5, + DSCP_TID_TABLE_NUM) |= + HAL_TX_SM(TCL_DATA_CMD_5, DSCP_TID_TABLE_NUM, id); +} + +#define DSCP_TID_TABLE_SIZE 24 +#define NUM_WORDS_PER_DSCP_TID_TABLE (DSCP_TID_TABLE_SIZE / 4) +#define HAL_TX_NUM_DSCP_REGISTER_SIZE 32 + +/** + * hal_tx_set_dscp_tid_map_9000() - Configure default DSCP to TID map table + * @soc: HAL SoC context + * @map: DSCP-TID mapping table + * @id: mapping table ID - 0,1 + * + * DSCP are mapped to 8 TID values using TID values programmed + * in two set of mapping registers DSCP_TID1_MAP_<0 to 6> (id = 0) + * and DSCP_TID2_MAP_<0 to 6> (id = 1) + * Each mapping register has TID mapping for 10 DSCP values + * + * Return: none + */ +static void hal_tx_set_dscp_tid_map_9000(struct hal_soc *soc, + uint8_t *map, uint8_t id) +{ + int i; + uint32_t addr, cmn_reg_addr; + uint32_t value = 0, regval; + uint8_t val[DSCP_TID_TABLE_SIZE], cnt = 0; + + if (id >= HAL_MAX_HW_DSCP_TID_V2_MAPS) + return; + + cmn_reg_addr = HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET); + + addr = HWIO_TCL_R0_DSCP_TID_MAP_n_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET, + id * NUM_WORDS_PER_DSCP_TID_TABLE); + + /* Enable read/write access */ + regval = HAL_REG_READ(soc, cmn_reg_addr); + regval |= + (1 << HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_DSCP_TID_MAP_PROGRAM_EN_SHFT); + + HAL_REG_WRITE(soc, cmn_reg_addr, regval); + + /* Write 8 (24 bits) DSCP-TID mappings in each interation */ + for (i = 0; i < 64; i += 8) { + value = (map[i] | + (map[i + 1] << 0x3) | + (map[i + 2] << 0x6) | + (map[i + 3] << 0x9) | + (map[i + 4] << 0xc) | + (map[i + 5] << 0xf) | + (map[i + 6] << 0x12) | + (map[i + 7] << 0x15)); + + qdf_mem_copy(&val[cnt], &value, 3); + cnt += 3; + } + + for (i = 0; i < DSCP_TID_TABLE_SIZE; i += 4) { + regval = *(uint32_t *)(val + i); + HAL_REG_WRITE(soc, addr, + (regval & HWIO_TCL_R0_DSCP_TID_MAP_n_RMSK)); + addr += 4; + } + + /* Diasble read/write access */ + regval = HAL_REG_READ(soc, cmn_reg_addr); + regval &= + ~(HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_DSCP_TID_MAP_PROGRAM_EN_BMSK); + + HAL_REG_WRITE(soc, cmn_reg_addr, regval); +} + +/** + * hal_tx_update_dscp_tid_9000() - Update the dscp tid map table as + updated by user + * @soc: HAL SoC context + * @map: DSCP-TID mapping table + * @id : MAP ID + * @dscp: DSCP_TID map index + * + * Return: void + */ +static void hal_tx_update_dscp_tid_9000(struct hal_soc *soc, uint8_t tid, + uint8_t id, uint8_t dscp) +{ + uint32_t addr, addr1, cmn_reg_addr; + uint32_t start_value = 0, end_value = 0; + uint32_t regval; + uint8_t end_bits = 0; + uint8_t start_bits = 0; + uint32_t start_index, end_index; + + cmn_reg_addr = HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET); + + addr = HWIO_TCL_R0_DSCP_TID_MAP_n_ADDR( + SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET, + id * NUM_WORDS_PER_DSCP_TID_TABLE); + + start_index = dscp * HAL_TX_BITS_PER_TID; + end_index = (start_index + (HAL_TX_BITS_PER_TID - 1)) + % HAL_TX_NUM_DSCP_REGISTER_SIZE; + start_index = start_index % HAL_TX_NUM_DSCP_REGISTER_SIZE; + addr += (4 * ((dscp * HAL_TX_BITS_PER_TID) / + HAL_TX_NUM_DSCP_REGISTER_SIZE)); + + if (end_index < start_index) { + end_bits = end_index + 1; + start_bits = HAL_TX_BITS_PER_TID - end_bits; + start_value = tid << start_index; + end_value = tid >> start_bits; + addr1 = addr + 4; + } else { + start_bits = HAL_TX_BITS_PER_TID - end_bits; + start_value = tid << start_index; + addr1 = 0; + } + + /* Enable read/write access */ + regval = HAL_REG_READ(soc, cmn_reg_addr); + regval |= + (1 << HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_DSCP_TID_MAP_PROGRAM_EN_SHFT); + + HAL_REG_WRITE(soc, cmn_reg_addr, regval); + + regval = HAL_REG_READ(soc, addr); + + if (end_index < start_index) + regval &= (~0) >> start_bits; + else + regval &= ~(7 << start_index); + + regval |= start_value; + + HAL_REG_WRITE(soc, addr, (regval & HWIO_TCL_R0_DSCP_TID_MAP_n_RMSK)); + + if (addr1) { + regval = HAL_REG_READ(soc, addr1); + regval &= (~0) << end_bits; + regval |= end_value; + + HAL_REG_WRITE(soc, addr1, (regval & + HWIO_TCL_R0_DSCP_TID_MAP_n_RMSK)); + } + + /* Diasble read/write access */ + regval = HAL_REG_READ(soc, cmn_reg_addr); + regval &= + ~(HWIO_TCL_R0_CONS_RING_CMN_CTRL_REG_DSCP_TID_MAP_PROGRAM_EN_BMSK); + HAL_REG_WRITE(soc, cmn_reg_addr, regval); +} + +/** + * hal_tx_desc_set_lmac_id_9000 - Set the lmac_id value + * @desc: Handle to Tx Descriptor + * @lmac_id: mac Id to ast matching + * b00 – mac 0 + * b01 – mac 1 + * b10 – mac 2 + * b11 – all macs (legacy HK way) + * + * Return: void + */ +static void hal_tx_desc_set_lmac_id_9000(void *desc, uint8_t lmac_id) +{ + HAL_SET_FLD(desc, TCL_DATA_CMD_4, LMAC_ID) |= + HAL_TX_SM(TCL_DATA_CMD_4, LMAC_ID, lmac_id); +} diff --git a/drivers/staging/qca-wifi-host-cmn/hif/configs/ap_hif.config b/drivers/staging/qca-wifi-host-cmn/hif/configs/ap_hif.config deleted file mode 100644 index ac35e75eaba1ea056c8cad34304c58c91831c249..0000000000000000000000000000000000000000 --- a/drivers/staging/qca-wifi-host-cmn/hif/configs/ap_hif.config +++ /dev/null @@ -1 +0,0 @@ -EXTRA_CFLAGS += -DQCA_NAPI_DEF_SCALE_BIN_SHIFT=1 diff --git a/drivers/staging/qca-wifi-host-cmn/hif/inc/cfg_hif.h b/drivers/staging/qca-wifi-host-cmn/hif/inc/cfg_hif.h new file mode 100644 index 0000000000000000000000000000000000000000..41f0fd0bb77f6984e420e751a583908f9c520022 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/inc/cfg_hif.h @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _CFG_HIF_H_ +#define _CFG_HIF_H_ + +/* Min/Max/default CE status srng timer threshold */ +#define WLAN_CFG_CE_STATUS_RING_TIMER_THRESH_MIN 0 +#define WLAN_CFG_CE_STATUS_RING_TIMER_THRESH_MAX 4096 +#define WLAN_CFG_CE_STATUS_RING_TIMER_THRESH_DEFAULT 4096 + +/* Min/Max/default CE status srng batch count threshold */ +#define WLAN_CFG_CE_STATUS_RING_BATCH_COUNT_THRESH_MIN 0 +#define WLAN_CFG_CE_STATUS_RING_BATCH_COUNT_THRESH_MAX 512 +#define WLAN_CFG_CE_STATUS_RING_BATCH_COUNT_THRESH_DEFAULT 1 + +#ifdef WLAN_CE_INTERRUPT_THRESHOLD_CONFIG +/** + * + * ce_status_ring_timer_thresh - ce status srng timer threshold + * @Min: 0 + * @Max: 4096 + * @Default: 0 + * + * This ini specifies the timer threshold for CE status srng to + * indicate the interrupt to be fired whenever the timer threshold + * runs out. + * + * Supported Feature: interrupt threshold for CE status srng + * + * Usage: Internal + * + * + */ +#define CFG_CE_STATUS_RING_TIMER_THRESHOLD \ + CFG_INI_UINT("ce_status_ring_timer_threshold", \ + WLAN_CFG_CE_STATUS_RING_TIMER_THRESH_MIN, \ + WLAN_CFG_CE_STATUS_RING_TIMER_THRESH_MAX, \ + WLAN_CFG_CE_STATUS_RING_TIMER_THRESH_DEFAULT, \ + CFG_VALUE_OR_DEFAULT, \ + "CE Status ring timer threshold") + +/** + * + * ce_status_ring_batch_count_thresh - ce status srng batch count threshold + * @Min: 0 + * @Max: 512 + * @Default: 1 + * + * This ini specifies the batch count threshold for CE status srng to + * indicate the interrupt to be fired for a given number of packets in + * the ring. + * + * Supported Feature: interrupt threshold for CE status srng + * + * Usage: Internal + * + * + */ +#define CFG_CE_STATUS_RING_BATCH_COUNT_THRESHOLD \ + CFG_INI_UINT("ce_status_ring_batch_count_threshold", \ + WLAN_CFG_CE_STATUS_RING_BATCH_COUNT_THRESH_MIN, \ + WLAN_CFG_CE_STATUS_RING_BATCH_COUNT_THRESH_MAX, \ + WLAN_CFG_CE_STATUS_RING_BATCH_COUNT_THRESH_DEFAULT, \ + CFG_VALUE_OR_DEFAULT, \ + "CE Status ring batch count threshold") + +#define CFG_HIF \ + CFG(CFG_CE_STATUS_RING_TIMER_THRESHOLD) \ + CFG(CFG_CE_STATUS_RING_BATCH_COUNT_THRESHOLD) +#else +#define CFG_HIF +#endif /* WLAN_CE_INTERRUPT_THRESHOLD_CONFIG */ +#endif /* _CFG_HIF_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/inc/hif.h b/drivers/staging/qca-wifi-host-cmn/hif/inc/hif.h index 5cb23350f00ce06a22507192e5f0de547a3f0b9b..d29cf3bb59efe8f91f04e7e72d3ea7c452ef3163 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/inc/hif.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/inc/hif.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 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 @@ -38,6 +38,7 @@ extern "C" { #ifdef IPA_OFFLOAD #include #endif +#include "cfg_ucfg_api.h" #include "qdf_dev.h" #define ENABLE_MBOX_DUMMY_SPACE_FEATURE 1 @@ -63,6 +64,9 @@ typedef void *hif_handle_t; #define HIF_TYPE_QCA6390 18 #define HIF_TYPE_QCA8074V2 19 #define HIF_TYPE_QCA6018 20 +#define HIF_TYPE_QCN9000 21 +#define HIF_TYPE_QCA6490 22 +#define HIF_TYPE_QCA6750 23 #ifdef IPA_OFFLOAD #define DMA_COHERENT_MASK_IPA_VER_3_AND_ABOVE 37 @@ -115,18 +119,10 @@ struct CE_state; #define CE_COUNT_MAX 12 #define HIF_MAX_GRP_IRQ 16 -#ifdef CONFIG_WIN -#define HIF_MAX_GROUP 12 -#else +#ifndef HIF_MAX_GROUP #define HIF_MAX_GROUP 7 #endif -#ifdef CONFIG_SLUB_DEBUG_ON -#ifndef CONFIG_WIN -#define HIF_CONFIG_SLUB_DEBUG_ON -#endif -#endif - #ifndef NAPI_YIELD_BUDGET_BASED #ifndef QCA_NAPI_DEF_SCALE_BIN_SHIFT #define QCA_NAPI_DEF_SCALE_BIN_SHIFT 4 @@ -326,6 +322,23 @@ enum hif_event_type { HIF_EVENT_BH_SCHED, HIF_EVENT_SRNG_ACCESS_START, HIF_EVENT_SRNG_ACCESS_END, + /* Do check hif_hist_skip_event_record when adding new events */ +}; + +/** + * enum hif_system_pm_state - System PM state + * HIF_SYSTEM_PM_STATE_ON: System in active state + * HIF_SYSTEM_PM_STATE_BUS_RESUMING: bus resume in progress as part of + * system resume + * HIF_SYSTEM_PM_STATE_BUS_SUSPENDING: bus suspend in progress as part of + * system suspend + * HIF_SYSTEM_PM_STATE_BUS_SUSPENDED: bus suspended as part of system suspend + */ +enum hif_system_pm_state { + HIF_SYSTEM_PM_STATE_ON, + HIF_SYSTEM_PM_STATE_BUS_RESUMING, + HIF_SYSTEM_PM_STATE_BUS_SUSPENDING, + HIF_SYSTEM_PM_STATE_BUS_SUSPENDED, }; #ifdef WLAN_FEATURE_DP_EVENT_HISTORY @@ -356,6 +369,16 @@ struct hif_event_record { enum hif_event_type type; }; +/** + * struct hif_event_misc - history related misc info + * @last_irq_index: last irq event index in history + * @last_irq_ts: last irq timestamp + */ +struct hif_event_misc { + int32_t last_irq_index; + uint64_t last_irq_ts; +}; + /** * struct hif_event_history - history for one interrupt group * @index: index to store new event @@ -366,6 +389,7 @@ struct hif_event_record { */ struct hif_event_history { qdf_atomic_t index; + struct hif_event_misc misc; struct hif_event_record event[HIF_EVENT_HIST_MAX]; }; @@ -470,8 +494,8 @@ enum hif_disable_type { * enum hif_device_config_opcode: configure mode * * @HIF_DEVICE_POWER_STATE: device power state - * @HIF_DEVICE_GET_MBOX_BLOCK_SIZE: get mbox block size - * @HIF_DEVICE_GET_MBOX_ADDR: get mbox block address + * @HIF_DEVICE_GET_BLOCK_SIZE: get block size + * @HIF_DEVICE_GET_ADDR: get block address * @HIF_DEVICE_GET_PENDING_EVENTS_FUNC: get pending events functions * @HIF_DEVICE_GET_IRQ_PROC_MODE: get irq proc mode * @HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC: receive event function @@ -539,6 +563,8 @@ struct htc_callbacks { * @is_load_unload_in_progress: Query if driver state Load/Unload in Progress * @is_driver_unloading: Query if driver is unloading. * @get_bandwidth_level: Query current bandwidth level for the driver + * @prealloc_get_consistent_mem_unligned: get prealloc unaligned consistent mem + * @prealloc_put_consistent_mem_unligned: put unaligned consistent mem to pool * This Structure provides callback pointer for HIF to query hdd for driver * states. */ @@ -550,6 +576,12 @@ struct hif_driver_state_callbacks { bool (*is_driver_unloading)(void *context); bool (*is_target_ready)(void *context); int (*get_bandwidth_level)(void *context); +#ifdef DP_MEM_PRE_ALLOC + void *(*prealloc_get_consistent_mem_unaligned)(qdf_size_t size, + qdf_dma_addr_t *paddr, + uint32_t ring_type); + void (*prealloc_put_consistent_mem_unaligned)(void *vaddr); +#endif }; /* This API detaches the HTC layer from the HIF device */ @@ -676,6 +708,7 @@ struct hif_msg_callbacks { uint8_t pipeID); void (*txResourceAvailHandler)(void *context, uint8_t pipe); void (*fwEventHandler)(void *context, QDF_STATUS status); + void (*update_bundle_stats)(void *context, uint8_t no_of_pkt_in_bundle); }; enum hif_target_status { @@ -836,15 +869,35 @@ void hif_disable_isr(struct hif_opaque_softc *hif_ctx); void hif_reset_soc(struct hif_opaque_softc *hif_ctx); void hif_save_htc_htt_config_endpoint(struct hif_opaque_softc *hif_ctx, int htc_htt_tx_endpoint); -struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, uint32_t mode, + +/** + * hif_open() - Create hif handle + * @qdf_ctx: qdf context + * @mode: Driver Mode + * @bus_type: Bus Type + * @cbk: CDS Callbacks + * @psoc: psoc object manager + * + * API to open HIF Context + * + * Return: HIF Opaque Pointer + */ +struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, + uint32_t mode, enum qdf_bus_type bus_type, - struct hif_driver_state_callbacks *cbk); + struct hif_driver_state_callbacks *cbk, + struct wlan_objmgr_psoc *psoc); + void hif_close(struct hif_opaque_softc *hif_ctx); QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev, void *bdev, const struct hif_bus_id *bid, enum qdf_bus_type bus_type, enum hif_enable_type type); void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type); +#ifdef CE_TASKLET_DEBUG_ENABLE +void hif_enable_ce_latency_stats(struct hif_opaque_softc *hif_ctx, + uint8_t value); +#endif void hif_display_stats(struct hif_opaque_softc *hif_ctx); void hif_clear_stats(struct hif_opaque_softc *hif_ctx); @@ -908,8 +961,19 @@ static inline char *rtpm_string_from_dbgid(wlan_rtpm_dbgid id) return (char *)strings[id]; } +/** + * enum hif_pm_link_state - hif link state + * HIF_PM_LINK_STATE_DOWN: hif link state is down + * HIF_PM_LINK_STATE_UP: hif link state is up + */ +enum hif_pm_link_state { + HIF_PM_LINK_STATE_DOWN, + HIF_PM_LINK_STATE_UP +}; + #ifdef FEATURE_RUNTIME_PM struct hif_pm_runtime_lock; + void hif_fastpath_resume(struct hif_opaque_softc *hif_ctx); int hif_pm_runtime_get_sync(struct hif_opaque_softc *hif_ctx, wlan_rtpm_dbgid rtpm_dbgid); @@ -942,6 +1006,22 @@ void hif_pm_runtime_mark_dp_rx_busy(struct hif_opaque_softc *hif_ctx); int hif_pm_runtime_is_dp_rx_busy(struct hif_opaque_softc *hif_ctx); qdf_time_t hif_pm_runtime_get_dp_rx_busy_mark(struct hif_opaque_softc *hif_ctx); int hif_pm_runtime_sync_resume(struct hif_opaque_softc *hif_ctx); + +/** + * hif_pm_set_link_state() - set link state during RTPM + * @hif_sc: HIF Context + * + * Return: None + */ +void hif_pm_set_link_state(struct hif_opaque_softc *hif_handle, uint8_t val); + +/** + * hif_is_link_state_up() - Is link state up + * @hif_sc: HIF Context + * + * Return: 1 link is up, 0 link is down + */ +uint8_t hif_pm_get_link_state(struct hif_opaque_softc *hif_handle); #else struct hif_pm_runtime_lock { const char *name; @@ -1010,6 +1090,10 @@ hif_pm_runtime_get_dp_rx_busy_mark(struct hif_opaque_softc *hif_ctx) { return 0; } static inline int hif_pm_runtime_sync_resume(struct hif_opaque_softc *hif_ctx) { return 0; } +static inline +void hif_pm_set_link_state(struct hif_opaque_softc *hif_handle, uint8_t val) +{} + #endif void hif_enable_power_management(struct hif_opaque_softc *hif_ctx, @@ -1182,6 +1266,7 @@ int32_t hif_get_int_ctx_irq_num(struct hif_opaque_softc *softc, uint8_t id); uint32_t hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx); +void hif_deconfigure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx); uint32_t hif_register_ext_group(struct hif_opaque_softc *hif_ctx, uint32_t numirq, uint32_t irq[], ext_intr_handler handler, void *cb_ctx, const char *context_name, @@ -1214,6 +1299,50 @@ void hif_clear_napi_stats(struct hif_opaque_softc *hif_ctx); } #endif +#ifdef FORCE_WAKE +/** + * hif_force_wake_request() - Function to wake from power collapse + * @handle: HIF opaque handle + * + * Description: API to check if the device is awake or not before + * read/write to BAR + 4K registers. If device is awake return + * success otherwise write '1' to + * PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG which will interrupt + * the device and does wakeup the PCI and MHI within 50ms + * and then the device writes a value to + * PCIE_SOC_PCIE_REG_PCIE_SCRATCH_0_SOC_PCIE_REG to complete the + * handshake process to let the host know the device is awake. + * + * Return: zero - success/non-zero - failure + */ +int hif_force_wake_request(struct hif_opaque_softc *handle); + +/** + * hif_force_wake_release() - API to release/reset the SOC wake register + * from interrupting the device. + * @handle: HIF opaque handle + * + * Description: API to set the + * PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG to '0' + * to release the interrupt line. + * + * Return: zero - success/non-zero - failure + */ +int hif_force_wake_release(struct hif_opaque_softc *handle); +#else +static inline +int hif_force_wake_request(struct hif_opaque_softc *handle) +{ + return 0; +} + +static inline +int hif_force_wake_release(struct hif_opaque_softc *handle) +{ + return 0; +} +#endif /* FORCE_WAKE */ + #ifdef FEATURE_HAL_DELAYED_REG_WRITE /** * hif_prevent_link_low_power_states() - Prevent from going to low power states @@ -1308,7 +1437,8 @@ hif_get_ce_service_max_yield_time(struct hif_opaque_softc *hif); * Return: void */ void hif_set_ce_service_max_rx_ind_flush(struct hif_opaque_softc *hif, - uint8_t ce_service_max_rx_ind_flush); + uint8_t ce_service_max_rx_ind_flush); + #ifdef OL_ATH_SMART_LOGGING /* * hif_log_ce_dump() - Copy all the CE DEST ring to buf @@ -1329,6 +1459,39 @@ uint8_t *hif_log_dump_ce(struct hif_softc *scn, uint8_t *buf_cur, uint32_t ce, uint32_t skb_sz); #endif /* OL_ATH_SMART_LOGGING */ +/* + * hif_softc_to_hif_opaque_softc - API to convert hif_softc handle + * to hif_opaque_softc handle + * @hif_handle - hif_softc type + * + * Return: hif_opaque_softc type + */ +static inline struct hif_opaque_softc * +hif_softc_to_hif_opaque_softc(struct hif_softc *hif_handle) +{ + return (struct hif_opaque_softc *)hif_handle; +} + +#ifdef FORCE_WAKE +/** + * hif_srng_init_phase(): Indicate srng initialization phase + * to avoid force wake as UMAC power collapse is not yet + * enabled + * @hif_ctx: hif opaque handle + * @init_phase: initialization phase + * + * Return: None + */ +void hif_srng_init_phase(struct hif_opaque_softc *hif_ctx, + bool init_phase); +#else +static inline +void hif_srng_init_phase(struct hif_opaque_softc *hif_ctx, + bool init_phase) +{ +} +#endif /* FORCE_WAKE */ + #ifdef HIF_CPU_PERF_AFFINE_MASK /** * hif_config_irq_set_perf_affinity_hint() - API to set affinity @@ -1348,4 +1511,137 @@ static inline void hif_config_irq_set_perf_affinity_hint( { } #endif + +#ifdef HIF_CE_LOG_INFO +/** + * hif_log_ce_info() - API to log ce info + * @scn: hif handle + * @data: hang event data buffer + * @offset: offset at which data needs to be written + * + * Return: None + */ +void hif_log_ce_info(struct hif_softc *scn, uint8_t *data, + unsigned int *offset); +#else +static inline +void hif_log_ce_info(struct hif_softc *scn, uint8_t *data, + unsigned int *offset) +{ +} +#endif + +#ifdef SYSTEM_PM_CHECK +/** + * __hif_system_pm_set_state() - Set system pm state + * @hif: hif opaque handle + * @state: system state + * + * Return: None + */ +void __hif_system_pm_set_state(struct hif_opaque_softc *hif, + enum hif_system_pm_state state); + +/** + * hif_system_pm_set_state_on() - Set system pm state to ON + * @hif: hif opaque handle + * + * Return: None + */ +static inline +void hif_system_pm_set_state_on(struct hif_opaque_softc *hif) +{ + __hif_system_pm_set_state(hif, HIF_SYSTEM_PM_STATE_ON); +} + +/** + * hif_system_pm_set_state_resuming() - Set system pm state to resuming + * @hif: hif opaque handle + * + * Return: None + */ +static inline +void hif_system_pm_set_state_resuming(struct hif_opaque_softc *hif) +{ + __hif_system_pm_set_state(hif, HIF_SYSTEM_PM_STATE_BUS_RESUMING); +} + +/** + * hif_system_pm_set_state_suspending() - Set system pm state to suspending + * @hif: hif opaque handle + * + * Return: None + */ +static inline +void hif_system_pm_set_state_suspending(struct hif_opaque_softc *hif) +{ + __hif_system_pm_set_state(hif, HIF_SYSTEM_PM_STATE_BUS_SUSPENDING); +} + +/** + * hif_system_pm_set_state_suspended() - Set system pm state to suspended + * @hif: hif opaque handle + * + * Return: None + */ +static inline +void hif_system_pm_set_state_suspended(struct hif_opaque_softc *hif) +{ + __hif_system_pm_set_state(hif, HIF_SYSTEM_PM_STATE_BUS_SUSPENDED); +} + +/** + * hif_system_pm_get_state() - Get system pm state + * @hif: hif opaque handle + * + * Return: system state + */ +int32_t hif_system_pm_get_state(struct hif_opaque_softc *hif); + +/** + * hif_system_pm_state_check() - Check system state and trigger resume + * if required + * @hif: hif opaque handle + * + * Return: 0 if system is in on state else error code + */ +int hif_system_pm_state_check(struct hif_opaque_softc *hif); +#else +static inline +void __hif_system_pm_set_state(struct hif_opaque_softc *hif, + enum hif_system_pm_state state) +{ +} + +static inline +void hif_system_pm_set_state_on(struct hif_opaque_softc *hif) +{ +} + +static inline +void hif_system_pm_set_state_resuming(struct hif_opaque_softc *hif) +{ +} + +static inline +void hif_system_pm_set_state_suspending(struct hif_opaque_softc *hif) +{ +} + +static inline +void hif_system_pm_set_state_suspended(struct hif_opaque_softc *hif) +{ +} + +static inline +int32_t hif_system_pm_get_state(struct hif_opaque_softc *hif) +{ + return 0; +} + +static inline int hif_system_pm_state_check(struct hif_opaque_softc *hif) +{ + return 0; +} +#endif #endif /* _HIF_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/inc/hostdef.h b/drivers/staging/qca-wifi-host-cmn/hif/inc/hostdef.h index 9b0e4d1874dacb3d27ec23e5038ee76903e87bb5..a94df8efb53a7bd210fe29942a3875ea6000f83b 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/inc/hostdef.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/inc/hostdef.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016,2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016,2018-2020 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 @@ -35,11 +35,14 @@ extern struct hostdef_s *QCA9984_HOSTdef; extern struct hostdef_s *QCA9888_HOSTdef; extern struct hostdef_s *QCA6290_HOSTdef; extern struct hostdef_s *QCA6390_HOSTdef; +extern struct hostdef_s *QCA6490_HOSTdef; +extern struct hostdef_s *QCA6750_HOSTdef; + #ifdef ATH_AHB extern struct hostdef_s *IPQ4019_HOSTdef; #endif extern struct hostdef_s *QCA8074_HOSTdef; extern struct hostdef_s *QCA8074V2_HOSTDEF; extern struct hostdef_s *QCA6018_HOSTDEF; - +extern struct hostdef_s *QCN9000_HOSTDEF; #endif diff --git a/drivers/staging/qca-wifi-host-cmn/hif/inc/regtable.h b/drivers/staging/qca-wifi-host-cmn/hif/inc/regtable.h index 31cc83609cfe6d9b46ec6c4f492ee3a343d1f4bc..fb058bcfe1ae130b407b16b7c97ef9e5d05abe44 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/inc/regtable.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/inc/regtable.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016, 2020 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 @@ -32,4 +32,8 @@ #include "regtable_usb.h" #endif +#if defined(HIF_IPCI) +#include "reg_struct.h" +#include "regtable_ipcie.h" +#endif #endif diff --git a/drivers/staging/qca-wifi-host-cmn/hif/inc/regtable_ipcie.h b/drivers/staging/qca-wifi-host-cmn/hif/inc/regtable_ipcie.h new file mode 100644 index 0000000000000000000000000000000000000000..a19b417916a95b40d087d6fb50ec1cafaaf427ec --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/inc/regtable_ipcie.h @@ -0,0 +1,662 @@ +/* + * Copyright (c) 2011-2020 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 above + * copyright notice and this permission notice appear in all copies. + + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _REGTABLE_IPCIE_H_ +#define _REGTABLE_IPCIE_H_ + +#define MISSING 0 + +#define A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK \ + (scn->targetdef->d_A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK) +#define A_SOC_CORE_PCIE_INTR_CAUSE_GRP1 \ + (scn->targetdef->d_A_SOC_CORE_PCIE_INTR_CAUSE_GRP1) +#define A_SOC_CORE_SPARE_1_REGISTER \ + (scn->targetdef->d_A_SOC_CORE_SPARE_1_REGISTER) +#define A_SOC_CORE_PCIE_INTR_CLR_GRP1 \ + (scn->targetdef->d_A_SOC_CORE_PCIE_INTR_CLR_GRP1) +#define A_SOC_CORE_PCIE_INTR_ENABLE_GRP1 \ + (scn->targetdef->d_A_SOC_CORE_PCIE_INTR_ENABLE_GRP1) +#define A_SOC_PCIE_PCIE_SCRATCH_0 \ + (scn->targetdef->d_A_SOC_PCIE_PCIE_SCRATCH_0) +#define A_SOC_PCIE_PCIE_SCRATCH_1 \ + (scn->targetdef->d_A_SOC_PCIE_PCIE_SCRATCH_1) +#define A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA \ + (scn->targetdef->d_A_WIFI_APB_1_A_WFSS_CE_TARGET_HOST_DELTA) +#define A_SOC_PCIE_PCIE_SCRATCH_2 \ + (scn->targetdef->d_A_SOC_PCIE_PCIE_SCRATCH_2) +/* end Q6 iHelium emu registers */ + +#define PCIE_INTR_FIRMWARE_ROUTE_MASK \ + (scn->targetdef->d_PCIE_INTR_FIRMWARE_ROUTE_MASK) +#define A_SOC_CORE_SPARE_0_REGISTER \ + (scn->targetdef->d_A_SOC_CORE_SPARE_0_REGISTER) +#define A_SOC_CORE_SCRATCH_0_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_0_ADDRESS) +#define A_SOC_CORE_SCRATCH_1_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_1_ADDRESS) +#define A_SOC_CORE_SCRATCH_2_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_2_ADDRESS) +#define A_SOC_CORE_SCRATCH_3_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_3_ADDRESS) +#define A_SOC_CORE_SCRATCH_4_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_4_ADDRESS) +#define A_SOC_CORE_SCRATCH_5_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_5_ADDRESS) +#define A_SOC_CORE_SCRATCH_6_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_6_ADDRESS) +#define A_SOC_CORE_SCRATCH_7_ADDRESS \ + (scn->targetdef->d_A_SOC_CORE_SCRATCH_7_ADDRESS) +#define RTC_SOC_BASE_ADDRESS (scn->targetdef->d_RTC_SOC_BASE_ADDRESS) +#define RTC_WMAC_BASE_ADDRESS (scn->targetdef->d_RTC_WMAC_BASE_ADDRESS) +#define SYSTEM_SLEEP_OFFSET (scn->targetdef->d_SYSTEM_SLEEP_OFFSET) +#define WLAN_SYSTEM_SLEEP_OFFSET \ + (scn->targetdef->d_WLAN_SYSTEM_SLEEP_OFFSET) +#define WLAN_SYSTEM_SLEEP_DISABLE_LSB \ + (scn->targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_LSB) +#define WLAN_SYSTEM_SLEEP_DISABLE_MASK \ + (scn->targetdef->d_WLAN_SYSTEM_SLEEP_DISABLE_MASK) +#define CLOCK_CONTROL_OFFSET (scn->targetdef->d_CLOCK_CONTROL_OFFSET) +#define CLOCK_CONTROL_SI0_CLK_MASK \ + (scn->targetdef->d_CLOCK_CONTROL_SI0_CLK_MASK) +#define RESET_CONTROL_OFFSET (scn->targetdef->d_RESET_CONTROL_OFFSET) +#define RESET_CONTROL_MBOX_RST_MASK \ + (scn->targetdef->d_RESET_CONTROL_MBOX_RST_MASK) +#define RESET_CONTROL_SI0_RST_MASK \ + (scn->targetdef->d_RESET_CONTROL_SI0_RST_MASK) +#define WLAN_RESET_CONTROL_OFFSET \ + (scn->targetdef->d_WLAN_RESET_CONTROL_OFFSET) +#define WLAN_RESET_CONTROL_COLD_RST_MASK \ + (scn->targetdef->d_WLAN_RESET_CONTROL_COLD_RST_MASK) +#define WLAN_RESET_CONTROL_WARM_RST_MASK \ + (scn->targetdef->d_WLAN_RESET_CONTROL_WARM_RST_MASK) +#define GPIO_BASE_ADDRESS (scn->targetdef->d_GPIO_BASE_ADDRESS) +#define GPIO_PIN0_OFFSET (scn->targetdef->d_GPIO_PIN0_OFFSET) +#define GPIO_PIN1_OFFSET (scn->targetdef->d_GPIO_PIN1_OFFSET) +#define GPIO_PIN0_CONFIG_MASK (scn->targetdef->d_GPIO_PIN0_CONFIG_MASK) +#define GPIO_PIN1_CONFIG_MASK (scn->targetdef->d_GPIO_PIN1_CONFIG_MASK) +#define A_SOC_CORE_SCRATCH_0 (scn->targetdef->d_A_SOC_CORE_SCRATCH_0) +#define SI_CONFIG_BIDIR_OD_DATA_LSB \ + (scn->targetdef->d_SI_CONFIG_BIDIR_OD_DATA_LSB) +#define SI_CONFIG_BIDIR_OD_DATA_MASK \ + (scn->targetdef->d_SI_CONFIG_BIDIR_OD_DATA_MASK) +#define SI_CONFIG_I2C_LSB (scn->targetdef->d_SI_CONFIG_I2C_LSB) +#define SI_CONFIG_I2C_MASK \ + (scn->targetdef->d_SI_CONFIG_I2C_MASK) +#define SI_CONFIG_POS_SAMPLE_LSB \ + (scn->targetdef->d_SI_CONFIG_POS_SAMPLE_LSB) +#define SI_CONFIG_POS_SAMPLE_MASK \ + (scn->targetdef->d_SI_CONFIG_POS_SAMPLE_MASK) +#define SI_CONFIG_INACTIVE_CLK_LSB \ + (scn->targetdef->d_SI_CONFIG_INACTIVE_CLK_LSB) +#define SI_CONFIG_INACTIVE_CLK_MASK \ + (scn->targetdef->d_SI_CONFIG_INACTIVE_CLK_MASK) +#define SI_CONFIG_INACTIVE_DATA_LSB \ + (scn->targetdef->d_SI_CONFIG_INACTIVE_DATA_LSB) +#define SI_CONFIG_INACTIVE_DATA_MASK \ + (scn->targetdef->d_SI_CONFIG_INACTIVE_DATA_MASK) +#define SI_CONFIG_DIVIDER_LSB (scn->targetdef->d_SI_CONFIG_DIVIDER_LSB) +#define SI_CONFIG_DIVIDER_MASK (scn->targetdef->d_SI_CONFIG_DIVIDER_MASK) +#define SI_BASE_ADDRESS (scn->targetdef->d_SI_BASE_ADDRESS) +#define SI_CONFIG_OFFSET (scn->targetdef->d_SI_CONFIG_OFFSET) +#define SI_TX_DATA0_OFFSET (scn->targetdef->d_SI_TX_DATA0_OFFSET) +#define SI_TX_DATA1_OFFSET (scn->targetdef->d_SI_TX_DATA1_OFFSET) +#define SI_RX_DATA0_OFFSET (scn->targetdef->d_SI_RX_DATA0_OFFSET) +#define SI_RX_DATA1_OFFSET (scn->targetdef->d_SI_RX_DATA1_OFFSET) +#define SI_CS_OFFSET (scn->targetdef->d_SI_CS_OFFSET) +#define SI_CS_DONE_ERR_MASK (scn->targetdef->d_SI_CS_DONE_ERR_MASK) +#define SI_CS_DONE_INT_MASK (scn->targetdef->d_SI_CS_DONE_INT_MASK) +#define SI_CS_START_LSB (scn->targetdef->d_SI_CS_START_LSB) +#define SI_CS_START_MASK (scn->targetdef->d_SI_CS_START_MASK) +#define SI_CS_RX_CNT_LSB (scn->targetdef->d_SI_CS_RX_CNT_LSB) +#define SI_CS_RX_CNT_MASK (scn->targetdef->d_SI_CS_RX_CNT_MASK) +#define SI_CS_TX_CNT_LSB (scn->targetdef->d_SI_CS_TX_CNT_LSB) +#define SI_CS_TX_CNT_MASK (scn->targetdef->d_SI_CS_TX_CNT_MASK) +#define EEPROM_SZ (scn->targetdef->d_BOARD_DATA_SZ) +#define EEPROM_EXT_SZ (scn->targetdef->d_BOARD_EXT_DATA_SZ) +#define MBOX_BASE_ADDRESS (scn->targetdef->d_MBOX_BASE_ADDRESS) +#define LOCAL_SCRATCH_OFFSET (scn->targetdef->d_LOCAL_SCRATCH_OFFSET) +#define CPU_CLOCK_OFFSET (scn->targetdef->d_CPU_CLOCK_OFFSET) +#define LPO_CAL_OFFSET (scn->targetdef->d_LPO_CAL_OFFSET) +#define GPIO_PIN10_OFFSET (scn->targetdef->d_GPIO_PIN10_OFFSET) +#define GPIO_PIN11_OFFSET (scn->targetdef->d_GPIO_PIN11_OFFSET) +#define GPIO_PIN12_OFFSET (scn->targetdef->d_GPIO_PIN12_OFFSET) +#define GPIO_PIN13_OFFSET (scn->targetdef->d_GPIO_PIN13_OFFSET) +#define CLOCK_GPIO_OFFSET (scn->targetdef->d_CLOCK_GPIO_OFFSET) +#define CPU_CLOCK_STANDARD_LSB (scn->targetdef->d_CPU_CLOCK_STANDARD_LSB) +#define CPU_CLOCK_STANDARD_MASK (scn->targetdef->d_CPU_CLOCK_STANDARD_MASK) +#define LPO_CAL_ENABLE_LSB (scn->targetdef->d_LPO_CAL_ENABLE_LSB) +#define LPO_CAL_ENABLE_MASK (scn->targetdef->d_LPO_CAL_ENABLE_MASK) +#define CLOCK_GPIO_BT_CLK_OUT_EN_LSB \ + (scn->targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_LSB) +#define CLOCK_GPIO_BT_CLK_OUT_EN_MASK \ + (scn->targetdef->d_CLOCK_GPIO_BT_CLK_OUT_EN_MASK) +#define ANALOG_INTF_BASE_ADDRESS (scn->targetdef->d_ANALOG_INTF_BASE_ADDRESS) +#define WLAN_MAC_BASE_ADDRESS (scn->targetdef->d_WLAN_MAC_BASE_ADDRESS) +#define FW_INDICATOR_ADDRESS (scn->targetdef->d_FW_INDICATOR_ADDRESS) +#define DRAM_BASE_ADDRESS (scn->targetdef->d_DRAM_BASE_ADDRESS) +#define SOC_CORE_BASE_ADDRESS (scn->targetdef->d_SOC_CORE_BASE_ADDRESS) +#define CORE_CTRL_ADDRESS (scn->targetdef->d_CORE_CTRL_ADDRESS) +#define CE_COUNT (scn->targetdef->d_CE_COUNT) +#define PCIE_INTR_ENABLE_ADDRESS (scn->targetdef->d_PCIE_INTR_ENABLE_ADDRESS) +#define PCIE_INTR_CLR_ADDRESS (scn->targetdef->d_PCIE_INTR_CLR_ADDRESS) +#define PCIE_INTR_FIRMWARE_MASK (scn->targetdef->d_PCIE_INTR_FIRMWARE_MASK) +#define PCIE_INTR_CE_MASK_ALL (scn->targetdef->d_PCIE_INTR_CE_MASK_ALL) +#define CORE_CTRL_CPU_INTR_MASK (scn->targetdef->d_CORE_CTRL_CPU_INTR_MASK) +#define PCIE_INTR_CAUSE_ADDRESS (scn->targetdef->d_PCIE_INTR_CAUSE_ADDRESS) +#define SOC_RESET_CONTROL_ADDRESS (scn->targetdef->d_SOC_RESET_CONTROL_ADDRESS) +#define HOST_GROUP0_MASK (PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL | \ + A_SOC_CORE_PCIE_INTR_ENABLE_GRP0_Q6_MASK) +#define SOC_RESET_CONTROL_CE_RST_MASK \ + (scn->targetdef->d_SOC_RESET_CONTROL_CE_RST_MASK) +#define SOC_RESET_CONTROL_CPU_WARM_RST_MASK \ + (scn->targetdef->d_SOC_RESET_CONTROL_CPU_WARM_RST_MASK) +#define CPU_INTR_ADDRESS (scn->targetdef->d_CPU_INTR_ADDRESS) +#define SOC_LF_TIMER_CONTROL0_ADDRESS \ + (scn->targetdef->d_SOC_LF_TIMER_CONTROL0_ADDRESS) +#define SOC_LF_TIMER_CONTROL0_ENABLE_MASK \ + (scn->targetdef->d_SOC_LF_TIMER_CONTROL0_ENABLE_MASK) +#define SOC_LF_TIMER_STATUS0_ADDRESS \ + (scn->targetdef->d_SOC_LF_TIMER_STATUS0_ADDRESS) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB \ + (scn->targetdef->d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK \ + (scn->targetdef->d_SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) + +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_GET(x) \ + (((x) & SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) >> \ + SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) +#define SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_SET(x) \ + (((x) << SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_LSB) & \ + SOC_RESET_CONTROL_PCIE_RST_SHORT_OVRD_MASK) + +/* hif_ipci.c */ +#define CHIP_ID_ADDRESS (scn->targetdef->d_SOC_CHIP_ID_ADDRESS) +#define SOC_CHIP_ID_REVISION_MASK (scn->targetdef->d_SOC_CHIP_ID_REVISION_MASK) +#define SOC_CHIP_ID_REVISION_LSB (scn->targetdef->d_SOC_CHIP_ID_REVISION_LSB) +#define SOC_CHIP_ID_VERSION_MASK (scn->targetdef->d_SOC_CHIP_ID_VERSION_MASK) +#define SOC_CHIP_ID_VERSION_LSB (scn->targetdef->d_SOC_CHIP_ID_VERSION_LSB) +#define CHIP_ID_REVISION_GET(x) \ + (((x) & SOC_CHIP_ID_REVISION_MASK) >> SOC_CHIP_ID_REVISION_LSB) +#define CHIP_ID_VERSION_GET(x) \ + (((x) & SOC_CHIP_ID_VERSION_MASK) >> SOC_CHIP_ID_VERSION_LSB) +/* hif_ipci.c end */ + +/* misc */ +#define SR_WR_INDEX_ADDRESS (scn->targetdef->d_SR_WR_INDEX_ADDRESS) +#define DST_WATERMARK_ADDRESS (scn->targetdef->d_DST_WATERMARK_ADDRESS) +#define SOC_POWER_REG_OFFSET (scn->targetdef->d_SOC_POWER_REG_OFFSET) +/* end */ + +/* copy_engine.c */ +/* end */ +/* PLL start */ +#define EFUSE_OFFSET (scn->targetdef->d_EFUSE_OFFSET) +#define EFUSE_XTAL_SEL_MSB (scn->targetdef->d_EFUSE_XTAL_SEL_MSB) +#define EFUSE_XTAL_SEL_LSB (scn->targetdef->d_EFUSE_XTAL_SEL_LSB) +#define EFUSE_XTAL_SEL_MASK (scn->targetdef->d_EFUSE_XTAL_SEL_MASK) +#define BB_PLL_CONFIG_OFFSET (scn->targetdef->d_BB_PLL_CONFIG_OFFSET) +#define BB_PLL_CONFIG_OUTDIV_MSB (scn->targetdef->d_BB_PLL_CONFIG_OUTDIV_MSB) +#define BB_PLL_CONFIG_OUTDIV_LSB (scn->targetdef->d_BB_PLL_CONFIG_OUTDIV_LSB) +#define BB_PLL_CONFIG_OUTDIV_MASK (scn->targetdef->d_BB_PLL_CONFIG_OUTDIV_MASK) +#define BB_PLL_CONFIG_FRAC_MSB (scn->targetdef->d_BB_PLL_CONFIG_FRAC_MSB) +#define BB_PLL_CONFIG_FRAC_LSB (scn->targetdef->d_BB_PLL_CONFIG_FRAC_LSB) +#define BB_PLL_CONFIG_FRAC_MASK (scn->targetdef->d_BB_PLL_CONFIG_FRAC_MASK) +#define WLAN_PLL_SETTLE_TIME_MSB (scn->targetdef->d_WLAN_PLL_SETTLE_TIME_MSB) +#define WLAN_PLL_SETTLE_TIME_LSB (scn->targetdef->d_WLAN_PLL_SETTLE_TIME_LSB) +#define WLAN_PLL_SETTLE_TIME_MASK (scn->targetdef->d_WLAN_PLL_SETTLE_TIME_MASK) +#define WLAN_PLL_SETTLE_OFFSET (scn->targetdef->d_WLAN_PLL_SETTLE_OFFSET) +#define WLAN_PLL_SETTLE_SW_MASK (scn->targetdef->d_WLAN_PLL_SETTLE_SW_MASK) +#define WLAN_PLL_SETTLE_RSTMASK (scn->targetdef->d_WLAN_PLL_SETTLE_RSTMASK) +#define WLAN_PLL_SETTLE_RESET (scn->targetdef->d_WLAN_PLL_SETTLE_RESET) +#define WLAN_PLL_CONTROL_NOPWD_MSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_NOPWD_MSB) +#define WLAN_PLL_CONTROL_NOPWD_LSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_NOPWD_LSB) +#define WLAN_PLL_CONTROL_NOPWD_MASK \ + (scn->targetdef->d_WLAN_PLL_CONTROL_NOPWD_MASK) +#define WLAN_PLL_CONTROL_BYPASS_MSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_BYPASS_MSB) +#define WLAN_PLL_CONTROL_BYPASS_LSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_BYPASS_LSB) +#define WLAN_PLL_CONTROL_BYPASS_MASK \ + (scn->targetdef->d_WLAN_PLL_CONTROL_BYPASS_MASK) +#define WLAN_PLL_CONTROL_BYPASS_RESET \ + (scn->targetdef->d_WLAN_PLL_CONTROL_BYPASS_RESET) +#define WLAN_PLL_CONTROL_CLK_SEL_MSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_MSB) +#define WLAN_PLL_CONTROL_CLK_SEL_LSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_LSB) +#define WLAN_PLL_CONTROL_CLK_SEL_MASK \ + (scn->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_MASK) +#define WLAN_PLL_CONTROL_CLK_SEL_RESET \ + (scn->targetdef->d_WLAN_PLL_CONTROL_CLK_SEL_RESET) +#define WLAN_PLL_CONTROL_REFDIV_MSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_REFDIV_MSB) +#define WLAN_PLL_CONTROL_REFDIV_LSB \ + (scn->targetdef->d_WLAN_PLL_CONTROL_REFDIV_LSB) +#define WLAN_PLL_CONTROL_REFDIV_MASK \ + (scn->targetdef->d_WLAN_PLL_CONTROL_REFDIV_MASK) +#define WLAN_PLL_CONTROL_REFDIV_RESET \ + (scn->targetdef->d_WLAN_PLL_CONTROL_REFDIV_RESET) +#define WLAN_PLL_CONTROL_DIV_MSB (scn->targetdef->d_WLAN_PLL_CONTROL_DIV_MSB) +#define WLAN_PLL_CONTROL_DIV_LSB (scn->targetdef->d_WLAN_PLL_CONTROL_DIV_LSB) +#define WLAN_PLL_CONTROL_DIV_MASK (scn->targetdef->d_WLAN_PLL_CONTROL_DIV_MASK) +#define WLAN_PLL_CONTROL_DIV_RESET \ + (scn->targetdef->d_WLAN_PLL_CONTROL_DIV_RESET) +#define WLAN_PLL_CONTROL_OFFSET (scn->targetdef->d_WLAN_PLL_CONTROL_OFFSET) +#define WLAN_PLL_CONTROL_SW_MASK (scn->targetdef->d_WLAN_PLL_CONTROL_SW_MASK) +#define WLAN_PLL_CONTROL_RSTMASK (scn->targetdef->d_WLAN_PLL_CONTROL_RSTMASK) +#define WLAN_PLL_CONTROL_RESET (scn->targetdef->d_WLAN_PLL_CONTROL_RESET) +#define SOC_CORE_CLK_CTRL_OFFSET (scn->targetdef->d_SOC_CORE_CLK_CTRL_OFFSET) +#define SOC_CORE_CLK_CTRL_DIV_MSB (scn->targetdef->d_SOC_CORE_CLK_CTRL_DIV_MSB) +#define SOC_CORE_CLK_CTRL_DIV_LSB (scn->targetdef->d_SOC_CORE_CLK_CTRL_DIV_LSB) +#define SOC_CORE_CLK_CTRL_DIV_MASK \ + (scn->targetdef->d_SOC_CORE_CLK_CTRL_DIV_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_MSB \ + (scn->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_MSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_LSB \ + (scn->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_LSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_MASK \ + (scn->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_RESET \ + (scn->targetdef->d_RTC_SYNC_STATUS_PLL_CHANGING_RESET) +#define RTC_SYNC_STATUS_OFFSET (scn->targetdef->d_RTC_SYNC_STATUS_OFFSET) +#define SOC_CPU_CLOCK_OFFSET (scn->targetdef->d_SOC_CPU_CLOCK_OFFSET) +#define SOC_CPU_CLOCK_STANDARD_MSB \ + (scn->targetdef->d_SOC_CPU_CLOCK_STANDARD_MSB) +#define SOC_CPU_CLOCK_STANDARD_LSB \ + (scn->targetdef->d_SOC_CPU_CLOCK_STANDARD_LSB) +#define SOC_CPU_CLOCK_STANDARD_MASK \ + (scn->targetdef->d_SOC_CPU_CLOCK_STANDARD_MASK) +/* PLL end */ + +#define FW_CPU_PLL_CONFIG \ + (scn->targetdef->d_FW_CPU_PLL_CONFIG) + +#define WIFICMN_PCIE_BAR_REG_ADDRESS \ + (sc->targetdef->d_WIFICMN_PCIE_BAR_REG_ADDRESS) + + /* htt tx */ +#define MSDU_LINK_EXT_3_TCP_OVER_IPV4_CHECKSUM_EN_MASK \ + (pdev->targetdef->d_MSDU_LINK_EXT_3_TCP_OVER_IPV4_CHECKSUM_EN_MASK) +#define MSDU_LINK_EXT_3_TCP_OVER_IPV6_CHECKSUM_EN_MASK \ + (pdev->targetdef->d_MSDU_LINK_EXT_3_TCP_OVER_IPV6_CHECKSUM_EN_MASK) +#define MSDU_LINK_EXT_3_UDP_OVER_IPV4_CHECKSUM_EN_MASK \ + (pdev->targetdef->d_MSDU_LINK_EXT_3_UDP_OVER_IPV4_CHECKSUM_EN_MASK) +#define MSDU_LINK_EXT_3_UDP_OVER_IPV6_CHECKSUM_EN_MASK \ + (pdev->targetdef->d_MSDU_LINK_EXT_3_UDP_OVER_IPV6_CHECKSUM_EN_MASK) +#define MSDU_LINK_EXT_3_TCP_OVER_IPV4_CHECKSUM_EN_LSB \ + (pdev->targetdef->d_MSDU_LINK_EXT_3_TCP_OVER_IPV4_CHECKSUM_EN_LSB) +#define MSDU_LINK_EXT_3_TCP_OVER_IPV6_CHECKSUM_EN_LSB \ + (pdev->targetdef->d_MSDU_LINK_EXT_3_TCP_OVER_IPV6_CHECKSUM_EN_LSB) +#define MSDU_LINK_EXT_3_UDP_OVER_IPV4_CHECKSUM_EN_LSB \ + (pdev->targetdef->d_MSDU_LINK_EXT_3_UDP_OVER_IPV4_CHECKSUM_EN_LSB) +#define MSDU_LINK_EXT_3_UDP_OVER_IPV6_CHECKSUM_EN_LSB \ + (pdev->targetdef->d_MSDU_LINK_EXT_3_UDP_OVER_IPV6_CHECKSUM_EN_LSB) + +#define CE_CMD_ADDRESS \ + (scn->targetdef->d_CE_CMD_ADDRESS) +#define CE_CMD_HALT_MASK \ + (scn->targetdef->d_CE_CMD_HALT_MASK) +#define CE_CMD_HALT_STATUS_MASK \ + (scn->targetdef->d_CE_CMD_HALT_STATUS_MASK) +#define CE_CMD_HALT_STATUS_LSB \ + (scn->targetdef->d_CE_CMD_HALT_STATUS_LSB) + +#define SI_CONFIG_ERR_INT_MASK \ + (scn->targetdef->d_SI_CONFIG_ERR_INT_MASK) +#define SI_CONFIG_ERR_INT_LSB \ + (scn->targetdef->d_SI_CONFIG_ERR_INT_LSB) +#define GPIO_ENABLE_W1TS_LOW_ADDRESS \ + (scn->targetdef->d_GPIO_ENABLE_W1TS_LOW_ADDRESS) +#define GPIO_PIN0_CONFIG_LSB \ + (scn->targetdef->d_GPIO_PIN0_CONFIG_LSB) +#define GPIO_PIN0_PAD_PULL_LSB \ + (scn->targetdef->d_GPIO_PIN0_PAD_PULL_LSB) +#define GPIO_PIN0_PAD_PULL_MASK \ + (scn->targetdef->d_GPIO_PIN0_PAD_PULL_MASK) + +#define SOC_CHIP_ID_REVISION_MSB \ + (scn->targetdef->d_SOC_CHIP_ID_REVISION_MSB) + +#define FW_AXI_MSI_ADDR \ + (scn->targetdef->d_FW_AXI_MSI_ADDR) +#define FW_AXI_MSI_DATA \ + (scn->targetdef->d_FW_AXI_MSI_DATA) +#define WLAN_SUBSYSTEM_CORE_ID_ADDRESS \ + (scn->targetdef->d_WLAN_SUBSYSTEM_CORE_ID_ADDRESS) +#define FPGA_VERSION_ADDRESS \ + (scn->targetdef->d_FPGA_VERSION_ADDRESS) + +/* SET macros */ +#define WLAN_SYSTEM_SLEEP_DISABLE_SET(x) \ + (((x) << WLAN_SYSTEM_SLEEP_DISABLE_LSB) & \ + WLAN_SYSTEM_SLEEP_DISABLE_MASK) +#define SI_CONFIG_BIDIR_OD_DATA_SET(x) \ + (((x) << SI_CONFIG_BIDIR_OD_DATA_LSB) & SI_CONFIG_BIDIR_OD_DATA_MASK) +#define SI_CONFIG_I2C_SET(x) (((x) << SI_CONFIG_I2C_LSB) & SI_CONFIG_I2C_MASK) +#define SI_CONFIG_POS_SAMPLE_SET(x) \ + (((x) << SI_CONFIG_POS_SAMPLE_LSB) & SI_CONFIG_POS_SAMPLE_MASK) +#define SI_CONFIG_INACTIVE_CLK_SET(x) \ + (((x) << SI_CONFIG_INACTIVE_CLK_LSB) & SI_CONFIG_INACTIVE_CLK_MASK) +#define SI_CONFIG_INACTIVE_DATA_SET(x) \ + (((x) << SI_CONFIG_INACTIVE_DATA_LSB) & SI_CONFIG_INACTIVE_DATA_MASK) +#define SI_CONFIG_DIVIDER_SET(x) \ + (((x) << SI_CONFIG_DIVIDER_LSB) & SI_CONFIG_DIVIDER_MASK) +#define SI_CS_START_SET(x) (((x) << SI_CS_START_LSB) & SI_CS_START_MASK) +#define SI_CS_RX_CNT_SET(x) (((x) << SI_CS_RX_CNT_LSB) & SI_CS_RX_CNT_MASK) +#define SI_CS_TX_CNT_SET(x) (((x) << SI_CS_TX_CNT_LSB) & SI_CS_TX_CNT_MASK) +#define LPO_CAL_ENABLE_SET(x) \ + (((x) << LPO_CAL_ENABLE_LSB) & LPO_CAL_ENABLE_MASK) +#define CPU_CLOCK_STANDARD_SET(x) \ + (((x) << CPU_CLOCK_STANDARD_LSB) & CPU_CLOCK_STANDARD_MASK) +#define CLOCK_GPIO_BT_CLK_OUT_EN_SET(x) \ + (((x) << CLOCK_GPIO_BT_CLK_OUT_EN_LSB) & CLOCK_GPIO_BT_CLK_OUT_EN_MASK) +/* copy_engine.c */ +/* end */ +/* PLL start */ +#define EFUSE_XTAL_SEL_GET(x) \ + (((x) & EFUSE_XTAL_SEL_MASK) >> EFUSE_XTAL_SEL_LSB) +#define EFUSE_XTAL_SEL_SET(x) \ + (((x) << EFUSE_XTAL_SEL_LSB) & EFUSE_XTAL_SEL_MASK) +#define BB_PLL_CONFIG_OUTDIV_GET(x) \ + (((x) & BB_PLL_CONFIG_OUTDIV_MASK) >> BB_PLL_CONFIG_OUTDIV_LSB) +#define BB_PLL_CONFIG_OUTDIV_SET(x) \ + (((x) << BB_PLL_CONFIG_OUTDIV_LSB) & BB_PLL_CONFIG_OUTDIV_MASK) +#define BB_PLL_CONFIG_FRAC_GET(x) \ + (((x) & BB_PLL_CONFIG_FRAC_MASK) >> BB_PLL_CONFIG_FRAC_LSB) +#define BB_PLL_CONFIG_FRAC_SET(x) \ + (((x) << BB_PLL_CONFIG_FRAC_LSB) & BB_PLL_CONFIG_FRAC_MASK) +#define WLAN_PLL_SETTLE_TIME_GET(x) \ + (((x) & WLAN_PLL_SETTLE_TIME_MASK) >> WLAN_PLL_SETTLE_TIME_LSB) +#define WLAN_PLL_SETTLE_TIME_SET(x) \ + (((x) << WLAN_PLL_SETTLE_TIME_LSB) & WLAN_PLL_SETTLE_TIME_MASK) +#define WLAN_PLL_CONTROL_NOPWD_GET(x) \ + (((x) & WLAN_PLL_CONTROL_NOPWD_MASK) >> WLAN_PLL_CONTROL_NOPWD_LSB) +#define WLAN_PLL_CONTROL_NOPWD_SET(x) \ + (((x) << WLAN_PLL_CONTROL_NOPWD_LSB) & WLAN_PLL_CONTROL_NOPWD_MASK) +#define WLAN_PLL_CONTROL_BYPASS_GET(x) \ + (((x) & WLAN_PLL_CONTROL_BYPASS_MASK) >> WLAN_PLL_CONTROL_BYPASS_LSB) +#define WLAN_PLL_CONTROL_BYPASS_SET(x) \ + (((x) << WLAN_PLL_CONTROL_BYPASS_LSB) & WLAN_PLL_CONTROL_BYPASS_MASK) +#define WLAN_PLL_CONTROL_CLK_SEL_GET(x) \ + (((x) & WLAN_PLL_CONTROL_CLK_SEL_MASK) >> WLAN_PLL_CONTROL_CLK_SEL_LSB) +#define WLAN_PLL_CONTROL_CLK_SEL_SET(x) \ + (((x) << WLAN_PLL_CONTROL_CLK_SEL_LSB) & WLAN_PLL_CONTROL_CLK_SEL_MASK) +#define WLAN_PLL_CONTROL_REFDIV_GET(x) \ + (((x) & WLAN_PLL_CONTROL_REFDIV_MASK) >> WLAN_PLL_CONTROL_REFDIV_LSB) +#define WLAN_PLL_CONTROL_REFDIV_SET(x) \ + (((x) << WLAN_PLL_CONTROL_REFDIV_LSB) & WLAN_PLL_CONTROL_REFDIV_MASK) +#define WLAN_PLL_CONTROL_DIV_GET(x) \ + (((x) & WLAN_PLL_CONTROL_DIV_MASK) >> WLAN_PLL_CONTROL_DIV_LSB) +#define WLAN_PLL_CONTROL_DIV_SET(x) \ + (((x) << WLAN_PLL_CONTROL_DIV_LSB) & WLAN_PLL_CONTROL_DIV_MASK) +#define SOC_CORE_CLK_CTRL_DIV_GET(x) \ + (((x) & SOC_CORE_CLK_CTRL_DIV_MASK) >> SOC_CORE_CLK_CTRL_DIV_LSB) +#define SOC_CORE_CLK_CTRL_DIV_SET(x) \ + (((x) << SOC_CORE_CLK_CTRL_DIV_LSB) & SOC_CORE_CLK_CTRL_DIV_MASK) +#define RTC_SYNC_STATUS_PLL_CHANGING_GET(x) \ + (((x) & RTC_SYNC_STATUS_PLL_CHANGING_MASK) >> \ + RTC_SYNC_STATUS_PLL_CHANGING_LSB) +#define RTC_SYNC_STATUS_PLL_CHANGING_SET(x) \ + (((x) << RTC_SYNC_STATUS_PLL_CHANGING_LSB) & \ + RTC_SYNC_STATUS_PLL_CHANGING_MASK) +#define SOC_CPU_CLOCK_STANDARD_GET(x) \ + (((x) & SOC_CPU_CLOCK_STANDARD_MASK) >> SOC_CPU_CLOCK_STANDARD_LSB) +#define SOC_CPU_CLOCK_STANDARD_SET(x) \ + (((x) << SOC_CPU_CLOCK_STANDARD_LSB) & SOC_CPU_CLOCK_STANDARD_MASK) +/* PLL end */ +#define WLAN_GPIO_PIN0_CONFIG_SET(x) \ + (((x) << GPIO_PIN0_CONFIG_LSB) & GPIO_PIN0_CONFIG_MASK) +#define WLAN_GPIO_PIN0_PAD_PULL_SET(x) \ + (((x) << GPIO_PIN0_PAD_PULL_LSB) & GPIO_PIN0_PAD_PULL_MASK) +#define SI_CONFIG_ERR_INT_SET(x) \ + (((x) << SI_CONFIG_ERR_INT_LSB) & SI_CONFIG_ERR_INT_MASK) + +#ifdef QCA_WIFI_3_0_ADRASTEA +#define Q6_ENABLE_REGISTER_0 \ + (scn->targetdef->d_Q6_ENABLE_REGISTER_0) +#define Q6_ENABLE_REGISTER_1 \ + (scn->targetdef->d_Q6_ENABLE_REGISTER_1) +#define Q6_CAUSE_REGISTER_0 \ + (scn->targetdef->d_Q6_CAUSE_REGISTER_0) +#define Q6_CAUSE_REGISTER_1 \ + (scn->targetdef->d_Q6_CAUSE_REGISTER_1) +#define Q6_CLEAR_REGISTER_0 \ + (scn->targetdef->d_Q6_CLEAR_REGISTER_0) +#define Q6_CLEAR_REGISTER_1 \ + (scn->targetdef->d_Q6_CLEAR_REGISTER_1) +#endif + +#ifdef CONFIG_BYPASS_QMI +#define BYPASS_QMI_TEMP_REGISTER \ + (scn->targetdef->d_BYPASS_QMI_TEMP_REGISTER) +#endif + +#define A_SOC_PCIE_PCIE_BAR0_START (scn->hostdef->d_A_SOC_PCIE_PCIE_BAR0_START) +#define DESC_DATA_FLAG_MASK (scn->hostdef->d_DESC_DATA_FLAG_MASK) +#define MUX_ID_MASK (scn->hostdef->d_MUX_ID_MASK) +#define TRANSACTION_ID_MASK (scn->hostdef->d_TRANSACTION_ID_MASK) +#define HOST_CE_COUNT (scn->hostdef->d_HOST_CE_COUNT) +#define ENABLE_MSI (scn->hostdef->d_ENABLE_MSI) +#define INT_STATUS_ENABLE_ERROR_LSB \ + (scn->hostdef->d_INT_STATUS_ENABLE_ERROR_LSB) +#define INT_STATUS_ENABLE_ERROR_MASK \ + (scn->hostdef->d_INT_STATUS_ENABLE_ERROR_MASK) +#define INT_STATUS_ENABLE_CPU_LSB (scn->hostdef->d_INT_STATUS_ENABLE_CPU_LSB) +#define INT_STATUS_ENABLE_CPU_MASK (scn->hostdef->d_INT_STATUS_ENABLE_CPU_MASK) +#define INT_STATUS_ENABLE_COUNTER_LSB \ + (scn->hostdef->d_INT_STATUS_ENABLE_COUNTER_LSB) +#define INT_STATUS_ENABLE_COUNTER_MASK \ + (scn->hostdef->d_INT_STATUS_ENABLE_COUNTER_MASK) +#define INT_STATUS_ENABLE_MBOX_DATA_LSB \ + (scn->hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_LSB) +#define INT_STATUS_ENABLE_MBOX_DATA_MASK \ + (scn->hostdef->d_INT_STATUS_ENABLE_MBOX_DATA_MASK) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB \ + (scn->hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK \ + (scn->hostdef->d_ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB \ + (scn->hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK \ + (scn->hostdef->d_ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) +#define COUNTER_INT_STATUS_ENABLE_BIT_LSB \ + (scn->hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_LSB) +#define COUNTER_INT_STATUS_ENABLE_BIT_MASK \ + (scn->hostdef->d_COUNTER_INT_STATUS_ENABLE_BIT_MASK) +#define INT_STATUS_ENABLE_ADDRESS \ + (scn->hostdef->d_INT_STATUS_ENABLE_ADDRESS) +#define CPU_INT_STATUS_ENABLE_BIT_LSB \ + (scn->hostdef->d_CPU_INT_STATUS_ENABLE_BIT_LSB) +#define CPU_INT_STATUS_ENABLE_BIT_MASK \ + (scn->hostdef->d_CPU_INT_STATUS_ENABLE_BIT_MASK) +#define HOST_INT_STATUS_ADDRESS (scn->hostdef->d_HOST_INT_STATUS_ADDRESS) +#define CPU_INT_STATUS_ADDRESS (scn->hostdef->d_CPU_INT_STATUS_ADDRESS) +#define ERROR_INT_STATUS_ADDRESS (scn->hostdef->d_ERROR_INT_STATUS_ADDRESS) +#define ERROR_INT_STATUS_WAKEUP_MASK \ + (scn->hostdef->d_ERROR_INT_STATUS_WAKEUP_MASK) +#define ERROR_INT_STATUS_WAKEUP_LSB \ + (scn->hostdef->d_ERROR_INT_STATUS_WAKEUP_LSB) +#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK \ + (scn->hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_MASK) +#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB \ + (scn->hostdef->d_ERROR_INT_STATUS_RX_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_TX_OVERFLOW_MASK \ + (scn->hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_MASK) +#define ERROR_INT_STATUS_TX_OVERFLOW_LSB \ + (scn->hostdef->d_ERROR_INT_STATUS_TX_OVERFLOW_LSB) +#define COUNT_DEC_ADDRESS (scn->hostdef->d_COUNT_DEC_ADDRESS) +#define HOST_INT_STATUS_CPU_MASK (scn->hostdef->d_HOST_INT_STATUS_CPU_MASK) +#define HOST_INT_STATUS_CPU_LSB (scn->hostdef->d_HOST_INT_STATUS_CPU_LSB) +#define HOST_INT_STATUS_ERROR_MASK (scn->hostdef->d_HOST_INT_STATUS_ERROR_MASK) +#define HOST_INT_STATUS_ERROR_LSB (scn->hostdef->d_HOST_INT_STATUS_ERROR_LSB) +#define HOST_INT_STATUS_COUNTER_MASK \ + (scn->hostdef->d_HOST_INT_STATUS_COUNTER_MASK) +#define HOST_INT_STATUS_COUNTER_LSB \ + (scn->hostdef->d_HOST_INT_STATUS_COUNTER_LSB) +#define RX_LOOKAHEAD_VALID_ADDRESS (scn->hostdef->d_RX_LOOKAHEAD_VALID_ADDRESS) +#define WINDOW_DATA_ADDRESS (scn->hostdef->d_WINDOW_DATA_ADDRESS) +#define WINDOW_READ_ADDR_ADDRESS (scn->hostdef->d_WINDOW_READ_ADDR_ADDRESS) +#define WINDOW_WRITE_ADDR_ADDRESS (scn->hostdef->d_WINDOW_WRITE_ADDR_ADDRESS) +#define SOC_GLOBAL_RESET_ADDRESS (scn->hostdef->d_SOC_GLOBAL_RESET_ADDRESS) +#define RTC_STATE_ADDRESS (scn->hostdef->d_RTC_STATE_ADDRESS) +#define RTC_STATE_COLD_RESET_MASK (scn->hostdef->d_RTC_STATE_COLD_RESET_MASK) +#define PCIE_LOCAL_BASE_ADDRESS (scn->hostdef->d_PCIE_LOCAL_BASE_ADDRESS) +#define PCIE_SOC_WAKE_RESET (scn->hostdef->d_PCIE_SOC_WAKE_RESET) +#define PCIE_SOC_WAKE_ADDRESS (scn->hostdef->d_PCIE_SOC_WAKE_ADDRESS) +#define PCIE_SOC_WAKE_V_MASK (scn->hostdef->d_PCIE_SOC_WAKE_V_MASK) +#define RTC_STATE_V_MASK (scn->hostdef->d_RTC_STATE_V_MASK) +#define RTC_STATE_V_LSB (scn->hostdef->d_RTC_STATE_V_LSB) +#define FW_IND_EVENT_PENDING (scn->hostdef->d_FW_IND_EVENT_PENDING) +#define FW_IND_INITIALIZED (scn->hostdef->d_FW_IND_INITIALIZED) +#define FW_IND_HELPER (scn->hostdef->d_FW_IND_HELPER) +#define RTC_STATE_V_ON (scn->hostdef->d_RTC_STATE_V_ON) + +#define FW_IND_HOST_READY (scn->hostdef->d_FW_IND_HOST_READY) + +#if defined(SDIO_3_0) +#define HOST_INT_STATUS_MBOX_DATA_MASK \ + (scn->hostdef->d_HOST_INT_STATUS_MBOX_DATA_MASK) +#define HOST_INT_STATUS_MBOX_DATA_LSB \ + (scn->hostdef->d_HOST_INT_STATUS_MBOX_DATA_LSB) +#endif + +#if !defined(SOC_PCIE_BASE_ADDRESS) +#define SOC_PCIE_BASE_ADDRESS 0 +#endif + +#if !defined(PCIE_SOC_RDY_STATUS_ADDRESS) +#define PCIE_SOC_RDY_STATUS_ADDRESS 0 +#define PCIE_SOC_RDY_STATUS_BAR_MASK 0 +#endif + +#if !defined(MSI_MAGIC_ADR_ADDRESS) +#define MSI_MAGIC_ADR_ADDRESS 0 +#define MSI_MAGIC_ADDRESS 0 +#endif + +/* SET/GET macros */ +#define INT_STATUS_ENABLE_ERROR_SET(x) \ + (((x) << INT_STATUS_ENABLE_ERROR_LSB) & INT_STATUS_ENABLE_ERROR_MASK) +#define INT_STATUS_ENABLE_CPU_SET(x) \ + (((x) << INT_STATUS_ENABLE_CPU_LSB) & INT_STATUS_ENABLE_CPU_MASK) +#define INT_STATUS_ENABLE_COUNTER_SET(x) \ + (((x) << INT_STATUS_ENABLE_COUNTER_LSB) & \ + INT_STATUS_ENABLE_COUNTER_MASK) +#define INT_STATUS_ENABLE_MBOX_DATA_SET(x) \ + (((x) << INT_STATUS_ENABLE_MBOX_DATA_LSB) & \ + INT_STATUS_ENABLE_MBOX_DATA_MASK) +#define CPU_INT_STATUS_ENABLE_BIT_SET(x) \ + (((x) << CPU_INT_STATUS_ENABLE_BIT_LSB) & \ + CPU_INT_STATUS_ENABLE_BIT_MASK) +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(x) \ + (((x) << ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) & \ + ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(x) \ + (((x) << ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) & \ + ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) +#define COUNTER_INT_STATUS_ENABLE_BIT_SET(x) \ + (((x) << COUNTER_INT_STATUS_ENABLE_BIT_LSB) & \ + COUNTER_INT_STATUS_ENABLE_BIT_MASK) +#define ERROR_INT_STATUS_WAKEUP_GET(x) \ + (((x) & ERROR_INT_STATUS_WAKEUP_MASK) >> \ + ERROR_INT_STATUS_WAKEUP_LSB) +#define ERROR_INT_STATUS_RX_UNDERFLOW_GET(x) \ + (((x) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) >> \ + ERROR_INT_STATUS_RX_UNDERFLOW_LSB) +#define ERROR_INT_STATUS_TX_OVERFLOW_GET(x) \ + (((x) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) >> \ + ERROR_INT_STATUS_TX_OVERFLOW_LSB) +#define HOST_INT_STATUS_CPU_GET(x) \ + (((x) & HOST_INT_STATUS_CPU_MASK) >> HOST_INT_STATUS_CPU_LSB) +#define HOST_INT_STATUS_ERROR_GET(x) \ + (((x) & HOST_INT_STATUS_ERROR_MASK) >> HOST_INT_STATUS_ERROR_LSB) +#define HOST_INT_STATUS_COUNTER_GET(x) \ + (((x) & HOST_INT_STATUS_COUNTER_MASK) >> HOST_INT_STATUS_COUNTER_LSB) +#define RTC_STATE_V_GET(x) \ + (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB) +#if defined(SDIO_3_0) +#define HOST_INT_STATUS_MBOX_DATA_GET(x) \ + (((x) & HOST_INT_STATUS_MBOX_DATA_MASK) >> \ + HOST_INT_STATUS_MBOX_DATA_LSB) +#endif + +#define INVALID_REG_LOC_DUMMY_DATA 0xAA + +#define AR6320_CORE_CLK_DIV_ADDR 0x403fa8 +#define AR6320_CPU_PLL_INIT_DONE_ADDR 0x403fd0 +#define AR6320_CPU_SPEED_ADDR 0x403fa4 +#define AR6320V2_CORE_CLK_DIV_ADDR 0x403fd8 +#define AR6320V2_CPU_PLL_INIT_DONE_ADDR 0x403fd0 +#define AR6320V2_CPU_SPEED_ADDR 0x403fd4 +#define AR6320V3_CORE_CLK_DIV_ADDR 0x404028 +#define AR6320V3_CPU_PLL_INIT_DONE_ADDR 0x404020 +#define AR6320V3_CPU_SPEED_ADDR 0x404024 + +enum a_refclk_speed_t { + SOC_REFCLK_UNKNOWN = -1, /* Unsupported ref clock -- use PLL Bypass */ + SOC_REFCLK_48_MHZ = 0, + SOC_REFCLK_19_2_MHZ = 1, + SOC_REFCLK_24_MHZ = 2, + SOC_REFCLK_26_MHZ = 3, + SOC_REFCLK_37_4_MHZ = 4, + SOC_REFCLK_38_4_MHZ = 5, + SOC_REFCLK_40_MHZ = 6, + SOC_REFCLK_52_MHZ = 7, +}; + +#define A_REFCLK_UNKNOWN SOC_REFCLK_UNKNOWN +#define A_REFCLK_48_MHZ SOC_REFCLK_48_MHZ +#define A_REFCLK_19_2_MHZ SOC_REFCLK_19_2_MHZ +#define A_REFCLK_24_MHZ SOC_REFCLK_24_MHZ +#define A_REFCLK_26_MHZ SOC_REFCLK_26_MHZ +#define A_REFCLK_37_4_MHZ SOC_REFCLK_37_4_MHZ +#define A_REFCLK_38_4_MHZ SOC_REFCLK_38_4_MHZ +#define A_REFCLK_40_MHZ SOC_REFCLK_40_MHZ +#define A_REFCLK_52_MHZ SOC_REFCLK_52_MHZ + +#define TARGET_CPU_FREQ 176000000 + +struct wlan_pll_s { + uint32_t refdiv; + uint32_t div; + uint32_t rnfrac; + uint32_t outdiv; +}; + +struct cmnos_clock_s { + enum a_refclk_speed_t refclk_speed; + uint32_t refclk_hz; + uint32_t pll_settling_time; /* 50us */ + struct wlan_pll_s wlan_pll; +}; + +struct tgt_reg_section { + uint32_t start_addr; + uint32_t end_addr; +}; + +struct tgt_reg_table { + const struct tgt_reg_section *section; + uint32_t section_size; +}; + +struct hif_softc; +void hif_target_register_tbl_attach(struct hif_softc *scn, u32 target_type); +void hif_register_tbl_attach(struct hif_softc *scn, u32 hif_type); + +#endif /* _REGTABLE_IPCIE_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/inc/target_type.h b/drivers/staging/qca-wifi-host-cmn/hif/inc/target_type.h index 7aa3d0f0049e221a2accf530a69c372ac65436cf..8a5fc373e1ee54985e10096da16e8e21c8d3fc72 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/inc/target_type.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/inc/target_type.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 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 @@ -24,35 +24,12 @@ extern "C" { #endif /* __cplusplus */ /* Header files */ +#include "bmi_msg.h" /* TARGET definition needs to be abstracted in fw common * header files, below is the placeholder till WIN codebase * moved to latest copy of fw common header files. */ -#ifdef CONFIG_WIN -#define TARGET_TYPE_UNKNOWN 0 -#define TARGET_TYPE_AR6001 1 -#define TARGET_TYPE_AR6002 2 -#define TARGET_TYPE_AR6003 3 -#define TARGET_TYPE_AR6004 5 -#define TARGET_TYPE_AR6006 6 -#define TARGET_TYPE_AR9888 7 -#define TARGET_TYPE_AR900B 9 -#define TARGET_TYPE_QCA9984 10 -#define TARGET_TYPE_IPQ4019 11 -#define TARGET_TYPE_QCA9888 12 -/* For attach Peregrine 2.0 board target_reg_tbl only */ -#define TARGET_TYPE_AR9888V2 13 -/* For attach Rome1.0 target_reg_tbl only*/ -#define TARGET_TYPE_AR6320V1 14 -/* For Rome2.0/2.1 target_reg_tbl ID*/ -#define TARGET_TYPE_AR6320V2 15 -/* For Rome3.0 target_reg_tbl ID*/ -#define TARGET_TYPE_AR6320V3 16 -/* For Tufello1.0 target_reg_tbl ID*/ -#define TARGET_TYPE_QCA9377V1 17 -#endif /* CONFIG_WIN */ -#define TARGET_TYPE_AR6320 8 /* For Adrastea target */ #define TARGET_TYPE_ADRASTEA 19 #ifndef TARGET_TYPE_QCA8074 @@ -74,6 +51,26 @@ extern "C" { #ifndef TARGET_TYPE_QCA6018 #define TARGET_TYPE_QCA6018 25 #endif +#ifndef TARGET_TYPE_QCN9000 +#define TARGET_TYPE_QCN9000 26 +#endif +/* HastingsPrime */ +#ifndef TARGET_TYPE_QCA6490 +#define TARGET_TYPE_QCA6490 27 +#endif + +/* Moselle */ +#ifndef TARGET_TYPE_QCA6750 +#define TARGET_TYPE_QCA6750 28 +#endif + +#ifndef TARGET_TYPE_QCA5018 +#define TARGET_TYPE_QCA5018 29 +#endif + +#ifndef TARGET_TYPE_QCN6122 +#define TARGET_TYPE_QCN6122 30 +#endif #ifdef __cplusplus } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/inc/targetdef.h b/drivers/staging/qca-wifi-host-cmn/hif/inc/targetdef.h index 180ac8ab31f314f845df524c8eeb0c431c2a09fe..8bd957216bc19d8360282ceb839733216b83a38a 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/inc/targetdef.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/inc/targetdef.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016,2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016,2018-2020 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 @@ -35,12 +35,16 @@ extern struct targetdef_s *QCA9984_TARGETdef; extern struct targetdef_s *QCA9888_TARGETdef; extern struct targetdef_s *QCA6290_TARGETdef; extern struct targetdef_s *QCA6390_TARGETdef; +extern struct targetdef_s *QCA6490_TARGETdef; +extern struct targetdef_s *QCA6750_TARGETdef; + #ifdef ATH_AHB extern struct targetdef_s *IPQ4019_TARGETdef; #endif extern struct targetdef_s *QCA8074_TARGETdef; extern struct targetdef_s *QCA8074V2_TARGETDEF; extern struct targetdef_s *QCA6018_TARGETDEF; +extern struct targetdef_s *QCN9000_TARGETDEF; extern struct ce_reg_def *AR6002_CE_TARGETdef; extern struct ce_reg_def *AR6003_CE_TARGETdef; @@ -53,12 +57,15 @@ extern struct ce_reg_def *QCA9984_CE_TARGETdef; extern struct ce_reg_def *QCA9888_CE_TARGETdef; extern struct ce_reg_def *QCA6290_CE_TARGETdef; extern struct ce_reg_def *QCA6390_CE_TARGETdef; +extern struct ce_reg_def *QCA6490_CE_TARGETdef; +extern struct ce_reg_def *QCA6750_CE_TARGETdef; #ifdef ATH_AHB extern struct ce_reg_def *IPQ4019_CE_TARGETdef; #endif extern struct ce_reg_def *QCA8074_CE_TARGETdef; extern struct ce_reg_def *QCA8074V2_CE_TARGETDEF; extern struct ce_reg_def *QCA6018_CE_TARGETDEF; +extern struct ce_reg_def *QCN9000_CE_TARGETDEF; #endif diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ar6320def.h b/drivers/staging/qca-wifi-host-cmn/hif/src/ar6320def.h index 3014f6549b59561ff8e8f88fee2501a75a60b8f9..7fdfb3de2bf9747eed5f814d27f4b4dd5a3d3add 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ar6320def.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ar6320def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, 2020 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 @@ -97,7 +97,8 @@ #define AR6320_RX_MPDU_START_0_SEQ_NUM_MASK 0x0fff0000 #define AR6320_RX_MPDU_START_2_TID_LSB 28 #define AR6320_RX_MPDU_START_2_TID_MASK 0xf0000000 -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if (defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI)) #define AR6320_SOC_PCIE_BASE_ADDRESS 0x00038000 #define AR6320_CE_WRAPPER_BASE_ADDRESS 0x00034000 #define AR6320_CE0_BASE_ADDRESS 0x00034400 @@ -218,7 +219,8 @@ #define AR6320_SOC_CHIP_ID_VERSION_LSB 18 #define AR6320_SOC_CHIP_ID_REVISION_MASK 0x00000f00 #define AR6320_SOC_CHIP_ID_REVISION_LSB 8 -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if (defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI)) #define AR6320_SOC_POWER_REG_OFFSET 0x0000010c /* Copy Engine Debug */ #define AR6320_WLAN_DEBUG_INPUT_SEL_OFFSET 0x0000010c @@ -452,7 +454,8 @@ struct targetdef_s ar6320_targetdef = { .d_DRAM_BASE_ADDRESS = AR6320_DRAM_BASE_ADDRESS, .d_SOC_CORE_BASE_ADDRESS = AR6320_SOC_CORE_BASE_ADDRESS, .d_CORE_CTRL_ADDRESS = AR6320_CORE_CTRL_ADDRESS, -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if (defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI)) .d_MSI_NUM_REQUEST = MSI_NUM_REQUEST, .d_MSI_ASSIGN_FW = MSI_ASSIGN_FW, #endif @@ -513,7 +516,8 @@ struct targetdef_s ar6320_targetdef = { AR6320_RX_ATTENTION_0_MSDU_DONE_MASK, .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR6320_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if (defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI)) .d_CE_COUNT = AR6320_CE_COUNT, .d_MSI_ASSIGN_CE_INITIAL = MSI_ASSIGN_CE_INITIAL, .d_PCIE_INTR_ENABLE_ADDRESS = AR6320_PCIE_INTR_ENABLE_ADDRESS, @@ -696,7 +700,8 @@ struct hostdef_s ar6320_hostdef = { .d_SOC_GLOBAL_RESET_ADDRESS = AR6320_SOC_GLOBAL_RESET_ADDRESS, .d_RTC_STATE_ADDRESS = AR6320_RTC_STATE_ADDRESS, .d_RTC_STATE_COLD_RESET_MASK = AR6320_RTC_STATE_COLD_RESET_MASK, -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if (defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI)) .d_PCIE_LOCAL_BASE_ADDRESS = AR6320_PCIE_LOCAL_BASE_ADDRESS, .d_PCIE_SOC_WAKE_RESET = AR6320_PCIE_SOC_WAKE_RESET, .d_PCIE_SOC_WAKE_ADDRESS = AR6320_PCIE_SOC_WAKE_ADDRESS, @@ -725,7 +730,8 @@ struct hostdef_s ar6320_hostdef = { #endif }; -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI) struct ce_reg_def ar6320_ce_targetdef = { /* copy_engine.c */ .d_DST_WR_INDEX_ADDRESS = AR6320_DST_WR_INDEX_ADDRESS, diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ar6320v2def.h b/drivers/staging/qca-wifi-host-cmn/hif/src/ar6320v2def.h index fdb4e92ae3f4d2d6840dbad664f1d370a3c7f25c..0985ae6cfff0b0abc320df889e3a422f0a3d1eb5 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ar6320v2def.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ar6320v2def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2018, 2020 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 @@ -182,7 +182,8 @@ #if defined(HIF_SDIO) #define AR6320V2_FW_IND_HELPER 4 #endif -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI) #define AR6320V2_CE_WRAPPER_BASE_ADDRESS 0x00034000 #define AR6320V2_CE0_BASE_ADDRESS 0x00034400 #define AR6320V2_CE1_BASE_ADDRESS 0x00034800 @@ -459,7 +460,8 @@ struct targetdef_s ar6320v2_targetdef = { .d_DRAM_BASE_ADDRESS = AR6320V2_DRAM_BASE_ADDRESS, .d_SOC_CORE_BASE_ADDRESS = AR6320V2_SOC_CORE_BASE_ADDRESS, .d_CORE_CTRL_ADDRESS = AR6320V2_CORE_CTRL_ADDRESS, -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI) .d_MSI_NUM_REQUEST = MSI_NUM_REQUEST, .d_MSI_ASSIGN_FW = MSI_ASSIGN_FW, #endif @@ -526,7 +528,8 @@ struct targetdef_s ar6320v2_targetdef = { AR6320V2_RX_ATTENTION_0_MSDU_DONE_MASK, .d_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK = AR6320V2_RX_ATTENTION_0_TCP_UDP_CHKSUM_FAIL_MASK, -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI) .d_CE_COUNT = AR6320V2_CE_COUNT, .d_MSI_ASSIGN_CE_INITIAL = MSI_ASSIGN_CE_INITIAL, .d_PCIE_INTR_ENABLE_ADDRESS = AR6320V2_PCIE_INTR_ENABLE_ADDRESS, @@ -728,7 +731,8 @@ struct hostdef_s ar6320v2_hostdef = { .d_HOST_INT_STATUS_MBOX_DATA_LSB = AR6320V2_HOST_INT_STATUS_MBOX_DATA_LSB, #endif -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI) .d_FW_IND_HELPER = AR6320V2_FW_IND_HELPER, .d_MUX_ID_MASK = AR6320V2_MUX_ID_MASK, .d_TRANSACTION_ID_MASK = AR6320V2_TRANSACTION_ID_MASK, @@ -749,7 +753,8 @@ struct hostdef_s ar6320v2_hostdef = { #endif }; -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI) struct ce_reg_def ar6320v2_ce_targetdef = { /* copy_engine.c */ .d_DST_WR_INDEX_ADDRESS = AR6320V2_DST_WR_INDEX_ADDRESS, diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ath_procfs.c b/drivers/staging/qca-wifi-host-cmn/hif/src/ath_procfs.c index 16a707fd4ab46456b9bb88767b1232b6461dccc4..8e63dc8a7da86e759651717aeb8daa33a5f07811 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ath_procfs.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ath_procfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016-2020 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 @@ -83,9 +83,13 @@ static ssize_t ath_procfs_diag_read(struct file *file, char __user *buf, (scn->bus_type == QDF_BUS_TYPE_PCI && ((tgt_info->target_type == TARGET_TYPE_QCA6290) || (tgt_info->target_type == TARGET_TYPE_QCA6390) || + (tgt_info->target_type == TARGET_TYPE_QCA6490) || (tgt_info->target_type == TARGET_TYPE_QCA8074) || (tgt_info->target_type == TARGET_TYPE_QCA8074V2) || - (tgt_info->target_type == TARGET_TYPE_QCA6018)))) { + (tgt_info->target_type == TARGET_TYPE_QCN9000) || + (tgt_info->target_type == TARGET_TYPE_QCA6018))) || + (scn->bus_type == QDF_BUS_TYPE_IPCI && + (tgt_info->target_type == TARGET_TYPE_QCA6750))) { memtype = ((uint32_t)(*pos) & 0xff000000) >> 24; offset = (uint32_t)(*pos) & 0xffffff; HIF_DBG("%s: offset 0x%x memtype 0x%x, datalen %zu\n", @@ -158,9 +162,13 @@ static ssize_t ath_procfs_diag_write(struct file *file, ((scn->bus_type == QDF_BUS_TYPE_PCI) && ((tgt_info->target_type == TARGET_TYPE_QCA6290) || (tgt_info->target_type == TARGET_TYPE_QCA6390) || + (tgt_info->target_type == TARGET_TYPE_QCA6490) || (tgt_info->target_type == TARGET_TYPE_QCA8074) || (tgt_info->target_type == TARGET_TYPE_QCA8074V2) || - (tgt_info->target_type == TARGET_TYPE_QCA6018)))) { + (tgt_info->target_type == TARGET_TYPE_QCN9000) || + (tgt_info->target_type == TARGET_TYPE_QCA6018))) || + (scn->bus_type == QDF_BUS_TYPE_IPCI && + (tgt_info->target_type == TARGET_TYPE_QCA6750))) { memtype = ((uint32_t)(*pos) & 0xff000000) >> 24; offset = (uint32_t)(*pos) & 0xffffff; HIF_DBG("%s: offset 0x%x memtype 0x%x, datalen %zu\n", diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_api.h b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_api.h index 5ff48e0d16944ed8a13afa53b321ee2409f3eb3b..7b6b97be4814c4a7c1d61309993177777e41f6fe 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_api.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 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 @@ -546,6 +546,8 @@ struct ce_ops { void (*ce_prepare_shadow_register_v2_cfg)(struct hif_softc *scn, struct pld_shadow_reg_v2_cfg **shadow_config, int *num_shadow_registers_configured); + int (*ce_get_index_info)(struct hif_softc *scn, void *ce_state, + struct ce_index *info); }; int hif_ce_bus_early_suspend(struct hif_softc *scn); diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_assignment.h b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_assignment.h index 4f5b67f72e7995947df73c1c769291276ad91759..dce741cffa2531e371ca56ee5754b228bf365a92 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_assignment.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_assignment.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -63,7 +63,10 @@ static void hif_target_dump_access_log(void); /* Maximum number of Copy Engine's supported */ #define CE_HTT_H2T_MSG_SRC_NENTRIES 2048 +#define CE_HTT_H2T_MSG_SRC_NENTRIES_QCA6390 256 +#define CE_HTT_H2T_MSG_SRC_NENTRIES_QCA6490 256 #define CE_HTT_H2T_MSG_SRC_NENTRIES_AR900B 4096 +#define CE_HTT_H2T_MSG_SRC_NENTRIES_QCN7605 4096 #define EPPING_CE_FLAGS_POLL \ (CE_ATTR_DISABLE_INTR|CE_ATTR_ENABLE_POLL|CE_ATTR_FLAGS) @@ -85,7 +88,7 @@ static struct CE_attr host_ce_config_wlan_qcn7605[] = { { /* CE3 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,}, /* host->target HTT */ { /* CE4 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, - CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,}, + CE_HTT_H2T_MSG_SRC_NENTRIES_QCN7605, 256, 0, NULL,}, #ifdef IPA_OFFLOAD /* ipa_uc->target HTC control */ { /* CE5 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, @@ -676,7 +679,11 @@ static struct CE_attr host_ce_config_wlan_qca8074[] = { { /* CE4 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,}, /* target -> host PKTLOG */ +#ifdef REMOVE_PKT_LOG + { /* CE5 */ 0, 0, 0, 0, 0, NULL,}, +#else { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,}, +#endif /* Target autonomous HIF_memcpy */ { /* CE6 */ CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR, 0, 0, 0, 0, NULL,}, @@ -691,13 +698,18 @@ static struct CE_attr host_ce_config_wlan_qca8074[] = { { /* CE11 unused */ 0, 0, 0, 0, 0, NULL,}, }; +#if defined(QCA_LOWMEM_CONFIG) || defined(QCA_512M_CONFIG) +#define T2H_WMI_RING_SIZE 32 +#else +#define T2H_WMI_RING_SIZE 512 +#endif static struct CE_pipe_config target_ce_config_wlan_qca8074[] = { /* host->target HTC control and raw streams */ { /* CE0 */ 0, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, /* target->host HTT */ { /* CE1 */ 1, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, /* target->host WMI + HTC control */ - { /* CE2 */ 2, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + { /* CE2 */ 2, PIPEDIR_IN, T2H_WMI_RING_SIZE, 2048, CE_ATTR_FLAGS, 0,}, /* host->target WMI */ { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, /* host->target HTT */ @@ -705,7 +717,11 @@ static struct CE_pipe_config target_ce_config_wlan_qca8074[] = { (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, /* NB: 50% of src nentries, since tx has 2 frags */ /* Target -> host PKTLOG */ +#ifdef REMOVE_PKT_LOG + { /* CE5 */ 5, PIPEDIR_NONE, 0, 0, 0, 0,}, +#else { /* CE5 */ 5, PIPEDIR_IN, 32, 2048, 0, 0,}, +#endif /* Reserved for target autonomous HIF_memcpy */ { /* CE6 */ 6, PIPEDIR_INOUT, 32, 65535, 64, 0,}, /* CE7 used only by Host */ @@ -733,7 +749,11 @@ static struct CE_attr host_ce_config_wlan_qca8074_pci[] = { { /* CE4 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,}, /* target -> host PKTLOG */ +#ifdef REMOVE_PKT_LOG + { /* CE5 */ 0, 0, 0, 0, 0, NULL,}, +#else { /* CE5 */ EPPING_CE_FLAGS_POLL, 0, 0, 2048, 512, NULL,}, +#endif /* Target autonomous HIF_memcpy */ { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, /* host->target WMI (mac1) */ @@ -901,6 +921,58 @@ static struct CE_pipe_config target_ce_config_wlan_adrastea[] = { { /* CE11 */ 11, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, }; +#define QCN_9000_CE_COUNT 6 +/* QCN9000 enable polling mode */ +static struct CE_attr host_ce_config_wlan_qcn9000[] = { + /* host->target HTC control and raw streams */ + {/*CE0*/ (CE_ATTR_FLAGS), 0, 16, 2048, 0, NULL,}, + /* target->host HTT + HTC control */ + {/*CE1*/ (CE_ATTR_FLAGS), 0, 0, 2048, + 512, NULL,}, + /* target->host WMI */ + {/*CE2*/ (CE_ATTR_FLAGS), 0, 0, 2048, + 32, NULL,}, + /* host->target WMI */ + {/*CE3*/ (CE_ATTR_FLAGS), 0, 32, 2048, 0, NULL,}, + /* host->target HTT */ + {/*CE4*/ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, + CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,}, + /* target -> host PKTLOG */ + {/*CE5*/ (CE_ATTR_FLAGS), 0, 0, 2048, + 512, NULL,}, + /* Target autonomous HIF_memcpy */ + {/*CE6*/ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* host->target WMI (mac1) */ + {/*CE7*/ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL,}, + /* Reserved for target */ + {/*CE8*/ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* CE 9, 10, 11 belong to CoreBsp & MHI driver */ +}; + +static struct CE_pipe_config target_ce_config_wlan_qcn9000[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ 0, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host HTT */ + { /* CE1 */ 1, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host WMI + HTC control */ + { /* CE2 */ 2, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target WMI */ + { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target HTT */ + { /* CE4 */ 4, PIPEDIR_OUT, 256, 256, + (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, + /* Target -> host PKTLOG */ + { /* CE5 */ 5, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* Reserved for target autonomous HIF_memcpy */ + { /* CE6 */ 6, PIPEDIR_INOUT, 32, 16384, CE_ATTR_FLAGS, 0,}, + /* CE7 used only by Host */ + { /* CE7 */ 7, PIPEDIR_OUT, 32, 2048, + 8192, 0,}, + /* Reserved for target */ + { /* CE8 */ 8, PIPEDIR_INOUT, 32, 16384, CE_ATTR_FLAGS, 0,}, + /* CE 9, 10, 11 belong to CoreBsp & MHI driver */ +}; + #define QCA_6290_CE_COUNT 9 #ifdef QCA_6290_AP_MODE static struct CE_attr host_ce_config_wlan_qca6290[] = { @@ -1014,7 +1086,7 @@ static struct CE_attr host_ce_config_wlan_qca6390[] = { { /* CE3 */ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL,}, /* host->target HTT */ { /* CE4 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, - CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,}, + CE_HTT_H2T_MSG_SRC_NENTRIES_QCA6390, 256, 0, NULL,}, /* target -> host PKTLOG */ { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,}, /* Target autonomous HIF_memcpy */ @@ -1050,4 +1122,102 @@ static struct CE_pipe_config target_ce_config_wlan_qca6390[] = { { /* CE8 */ 8, PIPEDIR_INOUT, 32, 16384, CE_ATTR_FLAGS, 0,}, /* CE 9, 10, 11 belong to CoreBsp & MHI driver */ }; + +#define QCA_6490_CE_COUNT 9 +static struct CE_attr host_ce_config_wlan_qca6490[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 2048, 0, NULL,}, + /* target->host HTT + HTC control */ + { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,}, + /* target->host WMI */ + { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 4096, 64, NULL,}, + /* host->target WMI */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL,}, + /* host->target HTT */ + { /* CE4 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, + CE_HTT_H2T_MSG_SRC_NENTRIES_QCA6490, 256, 0, NULL,}, + /* target -> host PKTLOG */ + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,}, + /* Target autonomous HIF_memcpy */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* ce_diag, the Diagnostic Window */ + { /* CE7 */ (CE_ATTR_DIAG_FLAGS | CE_ATTR_DISABLE_INTR), 0, + 0, DIAG_TRANSFER_LIMIT, 0, NULL,}, + /* Reserved for target */ + { /* CE8 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* CE 9, 10, 11 belong to CoreBsp & MHI driver */ +}; + +static struct CE_pipe_config target_ce_config_wlan_qca6490[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ 0, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host HTT */ + { /* CE1 */ 1, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host WMI + HTC control */ + { /* CE2 */ 2, PIPEDIR_IN, 32, 4096, CE_ATTR_FLAGS, 0,}, + /* host->target WMI */ + { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target HTT */ + { /* CE4 */ 4, PIPEDIR_OUT, 256, 256, + (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, + /* Target -> host PKTLOG */ + { /* CE5 */ 5, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* Reserved for target autonomous HIF_memcpy */ + { /* CE6 */ 6, PIPEDIR_INOUT, 32, 16384, CE_ATTR_FLAGS, 0,}, + /* CE7 used only by Host */ + { /* CE7 */ 7, PIPEDIR_INOUT_H2H, 0, 0, + (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, + /* Reserved for target */ + { /* CE8 */ 8, PIPEDIR_INOUT, 32, 16384, CE_ATTR_FLAGS, 0,}, + /* CE 9, 10, 11 belong to CoreBsp & MHI driver */ +}; + +#define QCA_6750_CE_COUNT 9 +static struct CE_attr host_ce_config_wlan_qca6750[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 2048, 0, NULL,}, + /* target->host HTT + HTC control */ + { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,}, + /* target->host WMI */ + { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 32, NULL,}, + /* host->target WMI */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL,}, + /* host->target HTT */ + { /* CE4 */ (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0, + CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,}, + /* target -> host PKTLOG */ + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 2048, 512, NULL,}, + /* Target autonomous HIF_memcpy */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* ce_diag, the Diagnostic Window */ + { /* CE7 */ (CE_ATTR_DIAG_FLAGS | CE_ATTR_DISABLE_INTR), 0, + 0, DIAG_TRANSFER_LIMIT, 0, NULL,}, + /* Reserved for target */ + { /* CE8 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* CE 9, 10, 11 belong to CoreBsp & MHI driver */ +}; + +static struct CE_pipe_config target_ce_config_wlan_qca6750[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ 0, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host HTT */ + { /* CE1 */ 1, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* target->host WMI + HTC control */ + { /* CE2 */ 2, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target WMI */ + { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target HTT */ + { /* CE4 */ 4, PIPEDIR_OUT, 256, 256, + (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, + /* Target -> host PKTLOG */ + { /* CE5 */ 5, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* Reserved for target autonomous HIF_memcpy */ + { /* CE6 */ 6, PIPEDIR_INOUT, 32, 16384, CE_ATTR_FLAGS, 0,}, + /* CE7 used only by Host */ + { /* CE7 */ 7, PIPEDIR_INOUT_H2H, 0, 0, + (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, + /* Reserved for target */ + { /* CE8 */ 8, PIPEDIR_INOUT, 32, 16384, CE_ATTR_FLAGS, 0,}, + /* CE 9, 10, 11 belong to CoreBsp & MHI driver */ +}; #endif /* __HIF_PCI_INTERNAL_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_internal.h b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_internal.h index 1694e70015bb4e068a6f70a88b45b1c2a50846ab..94b148746e26962c854d3960ad7a5eee4e781ed9 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_internal.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 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 @@ -89,6 +89,12 @@ struct CE_ring_state { unsigned int high_water_mark_nentries; void *srng_ctx; void **per_transfer_context; + + /* HAL CE ring type */ + uint32_t hal_ring_type; + /* ring memory prealloc */ + uint8_t is_ring_prealloc; + OS_DMA_MEM_CONTEXT(ce_dmacontext); /* OS Specific DMA context */ }; @@ -468,6 +474,8 @@ enum hif_ce_event_type { HIF_RX_DESC_PRE_NBUF_ALLOC, HIF_RX_DESC_PRE_NBUF_MAP, HIF_RX_DESC_POST_NBUF_MAP, + + HIF_EVENT_TYPE_MAX, }; void ce_init_ce_desc_event_log(struct hif_softc *scn, int ce_id, int size); @@ -554,6 +562,7 @@ int hif_get_wake_ce_id(struct hif_softc *scn, uint8_t *ce_id); /** * struct hif_ce_desc_event - structure for detailing a ce event + * @index: location of the descriptor in the ce ring; * @type: what the event was * @time: when it happened * @current_hp: holds the current ring hp value @@ -563,7 +572,6 @@ int hif_get_wake_ce_id(struct hif_softc *scn, uint8_t *ce_id); * @dma_addr: physical/iova address based on smmu status * @dma_to_phy: physical address from iova address * @virt_to_phy: physical address from virtual address - * @index: location of the descriptor in the ce ring; * @actual_data_len: length of the data * @data: data pointed by descriptor */ @@ -571,6 +579,7 @@ struct hif_ce_desc_event { int index; enum hif_ce_event_type type; uint64_t time; + int cpu_id; #ifdef HELIUMPLUS union ce_desc descriptor; #else @@ -665,6 +674,7 @@ void hif_clear_ce_desc_debug_data(struct hif_ce_desc_event *event) * Return: */ void hif_ce_desc_data_record(struct hif_ce_desc_event *event, int len); + QDF_STATUS alloc_mem_ce_debug_hist_data(struct hif_softc *scn, uint32_t ce_id); void free_mem_ce_debug_hist_data(struct hif_softc *scn, uint32_t ce_id); #else diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_main.c b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_main.c index 5991690222310acbec5f078b1efbbdd2775a1d1b..ccf04ce52f13b66ed5e4e331135bd8d76d6ce90a 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_main.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 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 @@ -37,9 +37,6 @@ #include "ce_reg.h" #include "ce_assignment.h" #include "ce_tasklet.h" -#ifndef CONFIG_WIN -#include "qwlan_version.h" -#endif #include "qdf_module.h" #define CE_POLL_TIMEOUT 10 /* ms */ @@ -51,12 +48,19 @@ #define PCIE_ACCESS_DUMP 4 #endif #include "mp_dev.h" +#ifdef HIF_CE_LOG_INFO +#include "qdf_hang_event_notifier.h" +#endif #if (defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6290) || \ defined(QCA_WIFI_QCA6018)) && !defined(QCA_WIFI_SUPPORT_SRNG) #define QCA_WIFI_SUPPORT_SRNG #endif +#ifdef QCA_WIFI_SUPPORT_SRNG +#include +#endif + /* Forward references */ QDF_STATUS hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info); @@ -482,6 +486,33 @@ static struct service_to_pipe target_service_to_ce_map_qca6018[] = { }; #endif +#if (defined(QCA_WIFI_QCN9000)) +static struct service_to_pipe target_service_to_ce_map_qcn9000[] = { + { WMI_DATA_VO_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_VO_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_BK_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_BK_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_BE_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_BE_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_VI_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_VI_SVC, PIPEDIR_IN, 2, }, + { WMI_CONTROL_SVC, PIPEDIR_OUT, 3, }, + { WMI_CONTROL_SVC, PIPEDIR_IN, 2, }, + { HTC_CTRL_RSVD_SVC, PIPEDIR_OUT, 0, }, + { HTC_CTRL_RSVD_SVC, PIPEDIR_IN, 1, }, + { HTC_RAW_STREAMS_SVC, PIPEDIR_OUT, 0}, + { HTC_RAW_STREAMS_SVC, PIPEDIR_IN, 1 }, + { HTT_DATA_MSG_SVC, PIPEDIR_OUT, 4, }, + { HTT_DATA_MSG_SVC, PIPEDIR_IN, 1, }, + { PACKET_LOG_SVC, PIPEDIR_IN, 5, }, + /* (Additions here) */ + { 0, 0, 0, }, +}; +#else +static struct service_to_pipe target_service_to_ce_map_qcn9000[] = { +}; +#endif + /* PIPEDIR_OUT = HOST to Target */ /* PIPEDIR_IN = TARGET to HOST */ #ifdef QCN7605_SUPPORT @@ -587,6 +618,51 @@ static struct service_to_pipe target_service_to_ce_map_qca6390[] = { }; #endif +static struct service_to_pipe target_service_to_ce_map_qca6490[] = { + { WMI_DATA_VO_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_VO_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_BK_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_BK_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_BE_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_BE_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_VI_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_VI_SVC, PIPEDIR_IN, 2, }, + { WMI_CONTROL_SVC, PIPEDIR_OUT, 3, }, + { WMI_CONTROL_SVC, PIPEDIR_IN, 2, }, + { HTC_CTRL_RSVD_SVC, PIPEDIR_OUT, 0, }, + { HTC_CTRL_RSVD_SVC, PIPEDIR_IN, 2, }, + { HTT_DATA_MSG_SVC, PIPEDIR_OUT, 4, }, + { HTT_DATA_MSG_SVC, PIPEDIR_IN, 1, }, + { PACKET_LOG_SVC, PIPEDIR_IN, 5, }, + /* (Additions here) */ + { 0, 0, 0, }, +}; + +#if (defined(QCA_WIFI_QCA6750)) +static struct service_to_pipe target_service_to_ce_map_qca6750[] = { + { WMI_DATA_VO_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_VO_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_BK_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_BK_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_BE_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_BE_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_VI_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_VI_SVC, PIPEDIR_IN, 2, }, + { WMI_CONTROL_SVC, PIPEDIR_OUT, 3, }, + { WMI_CONTROL_SVC, PIPEDIR_IN, 2, }, + { HTC_CTRL_RSVD_SVC, PIPEDIR_OUT, 0, }, + { HTC_CTRL_RSVD_SVC, PIPEDIR_IN, 2, }, + { HTT_DATA_MSG_SVC, PIPEDIR_OUT, 4, }, + { HTT_DATA_MSG_SVC, PIPEDIR_IN, 1, }, + { PACKET_LOG_SVC, PIPEDIR_IN, 5, }, + /* (Additions here) */ + { 0, 0, 0, }, +}; +#else +static struct service_to_pipe target_service_to_ce_map_qca6750[] = { +}; +#endif + static struct service_to_pipe target_service_to_ce_map_ar900b[] = { { WMI_DATA_VO_SVC, @@ -778,6 +854,16 @@ static void hif_select_service_to_pipe_map(struct hif_softc *scn, *sz_tgt_svc_map_to_use = sizeof(target_service_to_ce_map_qca6390); break; + case TARGET_TYPE_QCA6490: + *tgt_svc_map_to_use = target_service_to_ce_map_qca6490; + *sz_tgt_svc_map_to_use = + sizeof(target_service_to_ce_map_qca6490); + break; + case TARGET_TYPE_QCA6750: + *tgt_svc_map_to_use = target_service_to_ce_map_qca6750; + *sz_tgt_svc_map_to_use = + sizeof(target_service_to_ce_map_qca6750); + break; case TARGET_TYPE_QCA8074: *tgt_svc_map_to_use = target_service_to_ce_map_qca8074; *sz_tgt_svc_map_to_use = @@ -795,6 +881,12 @@ static void hif_select_service_to_pipe_map(struct hif_softc *scn, *sz_tgt_svc_map_to_use = sizeof(target_service_to_ce_map_qca6018); break; + case TARGET_TYPE_QCN9000: + *tgt_svc_map_to_use = + target_service_to_ce_map_qcn9000; + *sz_tgt_svc_map_to_use = + sizeof(target_service_to_ce_map_qcn9000); + break; } } } @@ -895,11 +987,14 @@ static QDF_STATUS ce_alloc_desc_ring(struct hif_softc *scn, unsigned int CE_id, scn->ipa_ce_ring->vaddr; } else { ce_ring->base_addr_owner_space_unaligned = - qdf_mem_alloc_consistent(scn->qdf_dev, - scn->qdf_dev->dev, - (nentries * desc_size + - CE_DESC_RING_ALIGN), - base_addr); + hif_mem_alloc_consistent_unaligned + (scn, + (nentries * desc_size + + CE_DESC_RING_ALIGN), + base_addr, + ce_ring->hal_ring_type, + &ce_ring->is_ring_prealloc); + if (!ce_ring->base_addr_owner_space_unaligned) { HIF_ERROR("%s: Failed to allocate DMA memory for ce ring id : %u", __func__, CE_id); @@ -930,10 +1025,12 @@ static void ce_free_desc_ring(struct hif_softc *scn, unsigned int CE_id, } ce_ring->base_addr_owner_space_unaligned = NULL; } else { - qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, - ce_ring->nentries * desc_size + CE_DESC_RING_ALIGN, - ce_ring->base_addr_owner_space_unaligned, - ce_ring->base_addr_CE_space, 0); + hif_mem_free_consistent_unaligned + (scn, + ce_ring->nentries * desc_size + CE_DESC_RING_ALIGN, + ce_ring->base_addr_owner_space_unaligned, + ce_ring->base_addr_CE_space, 0, + ce_ring->is_ring_prealloc); ce_ring->base_addr_owner_space_unaligned = NULL; } } @@ -944,9 +1041,14 @@ static QDF_STATUS ce_alloc_desc_ring(struct hif_softc *scn, unsigned int CE_id, unsigned int nentries, uint32_t desc_size) { ce_ring->base_addr_owner_space_unaligned = - qdf_mem_alloc_consistent(scn->qdf_dev, scn->qdf_dev->dev, + hif_mem_alloc_consistent_unaligned + (scn, (nentries * desc_size + - CE_DESC_RING_ALIGN), base_addr); + CE_DESC_RING_ALIGN), + base_addr, + ce_ring->hal_ring_type, + &ce_ring->is_ring_prealloc); + if (!ce_ring->base_addr_owner_space_unaligned) { HIF_ERROR("%s: Failed to allocate DMA memory for ce ring id : %u", __func__, CE_id); @@ -958,10 +1060,12 @@ static QDF_STATUS ce_alloc_desc_ring(struct hif_softc *scn, unsigned int CE_id, static void ce_free_desc_ring(struct hif_softc *scn, unsigned int CE_id, struct CE_ring_state *ce_ring, uint32_t desc_size) { - qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, - ce_ring->nentries * desc_size + CE_DESC_RING_ALIGN, - ce_ring->base_addr_owner_space_unaligned, - ce_ring->base_addr_CE_space, 0); + hif_mem_free_consistent_unaligned + (scn, + ce_ring->nentries * desc_size + CE_DESC_RING_ALIGN, + ce_ring->base_addr_owner_space_unaligned, + ce_ring->base_addr_CE_space, 0, + ce_ring->is_ring_prealloc); ce_ring->base_addr_owner_space_unaligned = NULL; } #endif /* IPA_OFFLOAD */ @@ -1002,7 +1106,10 @@ bool ce_srng_based(struct hif_softc *scn) case TARGET_TYPE_QCA8074V2: case TARGET_TYPE_QCA6290: case TARGET_TYPE_QCA6390: + case TARGET_TYPE_QCA6490: + case TARGET_TYPE_QCA6750: case TARGET_TYPE_QCA6018: + case TARGET_TYPE_QCN9000: return true; default: return false; @@ -1054,7 +1161,26 @@ static inline uint32_t ce_get_desc_size(struct hif_softc *scn, return hif_state->ce_services->ce_get_desc_size(ring_type); } - +#ifdef QCA_WIFI_SUPPORT_SRNG +static inline int32_t ce_ring_type_to_hal_ring_type(uint32_t ce_ring_type) +{ + switch (ce_ring_type) { + case CE_RING_SRC: + return CE_SRC; + case CE_RING_DEST: + return CE_DST; + case CE_RING_STATUS: + return CE_DST_STATUS; + default: + return -EINVAL; + } +} +#else +static int32_t ce_ring_type_to_hal_ring_type(uint32_t ce_ring_type) +{ + return 0; +} +#endif static struct CE_ring_state *ce_alloc_ring_state(struct CE_state *CE_state, uint8_t ring_type, uint32_t nentries) { @@ -1079,6 +1205,7 @@ static struct CE_ring_state *ce_alloc_ring_state(struct CE_state *CE_state, ce_ring->low_water_mark_nentries = 0; ce_ring->high_water_mark_nentries = nentries; ce_ring->per_transfer_context = (void **)ptr; + ce_ring->hal_ring_type = ce_ring_type_to_hal_ring_type(ring_type); desc_size = ce_get_desc_size(scn, ring_type); @@ -1282,7 +1409,7 @@ void free_mem_ce_debug_hist_data(struct hif_softc *scn, uint32_t ce_id) } #endif /* HIF_CE_DEBUG_DATA_BUF */ -#if defined(CONFIG_MCL) +#ifndef HIF_CE_DEBUG_DATA_DYNAMIC_BUF #if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF) struct hif_ce_desc_event hif_ce_desc_history[CE_COUNT_MAX][HIF_CE_HISTORY_MAX]; @@ -1339,7 +1466,7 @@ alloc_mem_ce_debug_history(struct hif_softc *scn, unsigned int CE_id, static inline void free_mem_ce_debug_history(struct hif_softc *scn, unsigned int CE_id) { } #endif /* (HIF_CONFIG_SLUB_DEBUG_ON) || (HIF_CE_DEBUG_DATA_BUF) */ -#elif defined(CONFIG_WIN) +#else #if defined(HIF_CE_DEBUG_DATA_BUF) static QDF_STATUS @@ -1388,7 +1515,7 @@ alloc_mem_ce_debug_history(struct hif_softc *scn, unsigned int CE_id, static inline void free_mem_ce_debug_history(struct hif_softc *scn, unsigned int CE_id) { } #endif /* HIF_CE_DEBUG_DATA_BUF */ -#endif /* CONFIG_MCL */ +#endif /* HIF_CE_DEBUG_DATA_DYNAMIC_BUF */ #if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF) /** @@ -2328,7 +2455,9 @@ static void hif_post_recv_buffers_failure(struct HIF_CE_pipe_info *pipe_info, * there is no trigger to refill the ce and we will * eventually crash */ - if (bufs_needed_tmp == CE_state->dest_ring->nentries - 1) + if (bufs_needed_tmp == CE_state->dest_ring->nentries - 1 || + (ce_srng_based(scn) && + bufs_needed_tmp == CE_state->dest_ring->nentries - 2)) qdf_sched_work(scn->qdf_dev, &CE_state->oom_allocation_work); } @@ -2969,6 +3098,8 @@ int hif_wlan_enable(struct hif_softc *scn) mode = PLD_FTM; else if (QDF_GLOBAL_COLDBOOT_CALIB_MODE == con_mode) mode = PLD_COLDBOOT_CALIBRATION; + else if (QDF_GLOBAL_FTM_COLDBOOT_CALIB_MODE == con_mode) + mode = PLD_FTM_COLDBOOT_CALIBRATION; else if (QDF_IS_EPPING_ENABLED(con_mode)) mode = PLD_EPPING; else @@ -2977,8 +3108,7 @@ int hif_wlan_enable(struct hif_softc *scn) if (BYPASS_QMI) return 0; else - return pld_wlan_enable(scn->qdf_dev->dev, &cfg, - mode, QWLAN_VERSIONSTR); + return pld_wlan_enable(scn->qdf_dev->dev, &cfg, mode); } #ifdef WLAN_FEATURE_EPPING @@ -3131,6 +3261,14 @@ void hif_ce_prepare_config(struct hif_softc *scn) scn->ce_count = QCA_6290_CE_COUNT; break; + case TARGET_TYPE_QCN9000: + hif_state->host_ce_config = host_ce_config_wlan_qcn9000; + hif_state->target_ce_config = target_ce_config_wlan_qcn9000; + hif_state->target_ce_config_sz = + sizeof(target_ce_config_wlan_qcn9000); + scn->ce_count = QCN_9000_CE_COUNT; + scn->disable_wake_irq = 1; + break; case TARGET_TYPE_QCA6390: hif_state->host_ce_config = host_ce_config_wlan_qca6390; hif_state->target_ce_config = target_ce_config_wlan_qca6390; @@ -3139,6 +3277,22 @@ void hif_ce_prepare_config(struct hif_softc *scn) scn->ce_count = QCA_6390_CE_COUNT; break; + case TARGET_TYPE_QCA6490: + hif_state->host_ce_config = host_ce_config_wlan_qca6490; + hif_state->target_ce_config = target_ce_config_wlan_qca6490; + hif_state->target_ce_config_sz = + sizeof(target_ce_config_wlan_qca6490); + + scn->ce_count = QCA_6490_CE_COUNT; + break; + case TARGET_TYPE_QCA6750: + hif_state->host_ce_config = host_ce_config_wlan_qca6750; + hif_state->target_ce_config = target_ce_config_wlan_qca6750; + hif_state->target_ce_config_sz = + sizeof(target_ce_config_wlan_qca6750); + + scn->ce_count = QCA_6750_CE_COUNT; + break; case TARGET_TYPE_ADRASTEA: if (hif_is_attribute_set(scn, HIF_LOWDESC_CE_NO_PKTLOG_CFG)) { hif_state->host_ce_config = @@ -3235,7 +3389,6 @@ void hif_unconfig_ce(struct hif_softc *hif_sc) */ static void hif_post_static_buf_to_target(struct hif_softc *scn) { - void *target_va; phys_addr_t target_pa; struct ce_info *ce_info_ptr; uint32_t msi_data_start; @@ -3244,15 +3397,19 @@ static void hif_post_static_buf_to_target(struct hif_softc *scn) uint32_t i = 0; int ret; - target_va = qdf_mem_alloc_consistent(scn->qdf_dev, - scn->qdf_dev->dev, - FW_SHARED_MEM + - sizeof(struct ce_info), - &target_pa); - if (!target_va) + scn->vaddr_qmi_bypass = + (uint32_t *)qdf_mem_alloc_consistent(scn->qdf_dev, + scn->qdf_dev->dev, + FW_SHARED_MEM, + &target_pa); + if (!scn->vaddr_qmi_bypass) { + hif_err("Memory allocation failed could not post target buf"); return; + } - ce_info_ptr = (struct ce_info *)target_va; + scn->paddr_qmi_bypass = target_pa; + + ce_info_ptr = (struct ce_info *)scn->vaddr_qmi_bypass; if (scn->vaddr_rri_on_ddr) { ce_info_ptr->rri_over_ddr_low_paddr = @@ -3276,7 +3433,26 @@ static void hif_post_static_buf_to_target(struct hif_softc *scn) } hif_write32_mb(scn, scn->mem + BYPASS_QMI_TEMP_REGISTER, target_pa); - hif_info("target va %pK target pa %pa", target_va, &target_pa); + hif_info("target va %pK target pa %pa", scn->vaddr_qmi_bypass, + &target_pa); +} + +/** + * hif_cleanup_static_buf_to_target() - clean up static buffer to WLAN FW + * @scn: pointer to HIF structure + * + * + * Return: void + */ +void hif_cleanup_static_buf_to_target(struct hif_softc *scn) +{ + void *target_va = scn->vaddr_qmi_bypass; + phys_addr_t target_pa = scn->paddr_qmi_bypass; + + qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, + FW_SHARED_MEM, target_va, + target_pa, 0); + hif_write32_mb(scn, scn->mem + BYPASS_QMI_TEMP_REGISTER, 0); } #else /** @@ -3289,17 +3465,38 @@ static void hif_post_static_buf_to_target(struct hif_softc *scn) */ static void hif_post_static_buf_to_target(struct hif_softc *scn) { - void *target_va; - phys_addr_t target_pa; - - target_va = qdf_mem_alloc_consistent(scn->qdf_dev, scn->qdf_dev->dev, - FW_SHARED_MEM, &target_pa); - if (!target_va) { - HIF_TRACE("Memory allocation failed could not post target buf"); + qdf_dma_addr_t target_pa; + + scn->vaddr_qmi_bypass = + (uint32_t *)qdf_mem_alloc_consistent(scn->qdf_dev, + scn->qdf_dev->dev, + FW_SHARED_MEM, + &target_pa); + if (!scn->vaddr_qmi_bypass) { + hif_err("Memory allocation failed could not post target buf"); return; } + + scn->paddr_qmi_bypass = target_pa; hif_write32_mb(scn, scn->mem + BYPASS_QMI_TEMP_REGISTER, target_pa); - HIF_TRACE("target va %pK target pa %pa", target_va, &target_pa); +} + +/** + * hif_cleanup_static_buf_to_target() - clean up static buffer to WLAN FW + * @scn: pointer to HIF structure + * + * + * Return: void + */ +void hif_cleanup_static_buf_to_target(struct hif_softc *scn) +{ + void *target_va = scn->vaddr_qmi_bypass; + phys_addr_t target_pa = scn->paddr_qmi_bypass; + + qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, + FW_SHARED_MEM, target_va, + target_pa, 0); + hif_write32_mb(snc, scn->mem + BYPASS_QMI_TEMP_REGISTER, 0); } #endif @@ -3307,6 +3504,10 @@ static void hif_post_static_buf_to_target(struct hif_softc *scn) static inline void hif_post_static_buf_to_target(struct hif_softc *scn) { } + +void hif_cleanup_static_buf_to_target(struct hif_softc *scn) +{ +} #endif static int hif_srng_sleep_state_adjust(struct hif_softc *scn, bool sleep_ok, @@ -4043,3 +4244,61 @@ int hif_get_wake_ce_id(struct hif_softc *scn, uint8_t *ce_id) return 0; } + +#ifdef HIF_CE_LOG_INFO +/** + * ce_get_index_info(): Get CE index info + * @scn: HIF Context + * @ce_state: CE opaque handle + * @info: CE info + * + * Return: 0 for success and non zero for failure + */ +static +int ce_get_index_info(struct hif_softc *scn, void *ce_state, + struct ce_index *info) +{ + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + + return hif_state->ce_services->ce_get_index_info(scn, ce_state, info); +} + +void hif_log_ce_info(struct hif_softc *scn, uint8_t *data, + unsigned int *offset) +{ + struct hang_event_info info = {0}; + static uint32_t tracked_ce = BIT(CE_ID_1) | BIT(CE_ID_2) | + BIT(CE_ID_3) | BIT(CE_ID_4) | BIT(CE_ID_9) | BIT(CE_ID_10); + uint8_t curr_index = 0; + uint8_t i; + uint16_t size; + + info.active_tasklet_count = qdf_atomic_read(&scn->active_tasklet_cnt); + info.active_grp_tasklet_cnt = + qdf_atomic_read(&scn->active_grp_tasklet_cnt); + + for (i = 0; i < scn->ce_count; i++) { + if (!(tracked_ce & BIT(i)) || !scn->ce_id_to_state[i]) + continue; + + if (ce_get_index_info(scn, scn->ce_id_to_state[i], + &info.ce_info[curr_index])) + continue; + + curr_index++; + } + + info.ce_count = curr_index; + size = sizeof(info) - + (CE_COUNT_MAX - info.ce_count) * sizeof(struct ce_index); + + if (*offset + size > QDF_WLAN_HANG_FW_OFFSET) + return; + + QDF_HANG_EVT_SET_HDR(&info.tlv_header, HANG_EVT_TAG_CE_INFO, + size - QDF_HANG_EVENT_TLV_HDR_SIZE); + + qdf_mem_copy(data + *offset, &info, size); + *offset = *offset + size; +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_main.h b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_main.h index e54f04348d523683ff48ff07deada7138964fd72..d2875343644291a148ef480cb6b80d228bcde370 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_main.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_main.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 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 @@ -49,6 +49,7 @@ #define CE_USEFUL_SIZE 0x00000058 #define CE_ALL_BITMAP 0xFFFF +#define HIF_REQUESTED_EVENTS 20 /** * enum ce_id_type * @@ -70,16 +71,36 @@ enum ce_id_type { CE_ID_MAX }; +/** + * enum ce_buckets + * + * @ce_buckets: CE tasklet time buckets + * @CE_BUCKET_500_US: tasklet bucket to store 0-0.5ms + * @CE_BUCKET_1_MS: tasklet bucket to store 0.5-1ms + * @CE_BUCKET_2_MS: tasklet bucket to store 1-2ms + * @CE_BUCKET_5_MS: tasklet bucket to store 2-5ms + * @CE_BUCKET_10_MS: tasklet bucket to store 5-10ms + * @CE_BUCKET_BEYOND: tasklet bucket to store > 10ms + * @CE_BUCKET_MAX: enum max value + */ +#ifdef CE_TASKLET_DEBUG_ENABLE +enum ce_buckets { + CE_BUCKET_500_US, + CE_BUCKET_1_MS, + CE_BUCKET_2_MS, + CE_BUCKET_5_MS, + CE_BUCKET_10_MS, + CE_BUCKET_BEYOND, + CE_BUCKET_MAX, +}; +#endif + enum ce_target_type { CE_SVC_LEGACY, CE_SVC_SRNG, CE_MAX_TARGET_TYPE }; -#ifdef CONFIG_WIN -#define QWLAN_VERSIONSTR "WIN" -#endif - enum ol_ath_hif_pkt_ecodes { HIF_PIPE_NO_RESOURCE = 0 }; @@ -138,8 +159,33 @@ static inline bool hif_dummy_grp_done(struct hif_exec_context *grp_entry, int extern struct hif_execution_ops tasklet_sched_ops; extern struct hif_execution_ops napi_sched_ops; +/** + * struct ce_stats + * + * @ce_per_cpu: Stats of the CEs running per CPU + * @record_index: Current index to store in time record + * @tasklet_sched_entry_ts: Timestamp when tasklet is scheduled + * @tasklet_exec_entry_ts: Timestamp when tasklet is started execuiton + * @tasklet_exec_time_record: Last N number of tasklets execution time + * @tasklet_sched_time_record: Last N number of tasklets scheduled time + * @ce_tasklet_exec_bucket: Tasklet execution time buckets + * @ce_tasklet_sched_bucket: Tasklet time in queue buckets + * @ce_tasklet_exec_last_update: Latest timestamp when bucket is updated + * @ce_tasklet_sched_last_update: Latest timestamp when bucket is updated + */ struct ce_stats { uint32_t ce_per_cpu[CE_COUNT_MAX][QDF_MAX_AVAILABLE_CPU]; +#ifdef CE_TASKLET_DEBUG_ENABLE + uint32_t record_index[CE_COUNT_MAX]; + uint64_t tasklet_sched_entry_ts[CE_COUNT_MAX]; + uint64_t tasklet_exec_entry_ts[CE_COUNT_MAX]; + uint64_t tasklet_exec_time_record[CE_COUNT_MAX][HIF_REQUESTED_EVENTS]; + uint64_t tasklet_sched_time_record[CE_COUNT_MAX][HIF_REQUESTED_EVENTS]; + uint64_t ce_tasklet_exec_bucket[CE_COUNT_MAX][CE_BUCKET_MAX]; + uint64_t ce_tasklet_sched_bucket[CE_COUNT_MAX][CE_BUCKET_MAX]; + uint64_t ce_tasklet_exec_last_update[CE_COUNT_MAX][CE_BUCKET_MAX]; + uint64_t ce_tasklet_sched_last_update[CE_COUNT_MAX][CE_BUCKET_MAX]; +#endif }; struct HIF_CE_state { @@ -219,6 +265,49 @@ struct ce_info { #endif #endif +/** + * struct ce_index + * + * @id: CE id + * @sw_index: sw index + * @write_index: write index + * @hp: ring head pointer + * @tp: ring tail pointer + * @status_hp: status ring head pointer + * @status_tp: status ring tail pointer + */ +struct ce_index { + uint8_t id; + union { + struct { + uint16_t sw_index; + uint16_t write_index; + } legacy_info; + struct { + uint16_t hp; + uint16_t tp; + uint16_t status_hp; + uint16_t status_tp; + } srng_info; + } u; +} qdf_packed; + +/** + * struct hang_event_info + * + * @tlv_header: tlv header + * @active_tasklet_count: active tasklet count + * @active_grp_tasklet_cnt: active grp tasklet count + * @ce_info: CE info + */ +struct hang_event_info { + uint16_t tlv_header; + uint8_t active_tasklet_count; + uint8_t active_grp_tasklet_cnt; + uint8_t ce_count; + struct ce_index ce_info[CE_COUNT_MAX]; +} qdf_packed; + void hif_ce_stop(struct hif_softc *scn); int hif_dump_ce_registers(struct hif_softc *scn); void diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service.c b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service.c index 7731328a0453030071b9fe8a2ca3420e498f5396..4494e23d2fe1408cfeafbfa31d6ecd90326962f0 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service.c @@ -105,6 +105,8 @@ int get_next_record_index(qdf_atomic_t *table_index, int array_size) return record_index; } +qdf_export_symbol(get_next_record_index); + #ifdef HIF_CE_DEBUG_DATA_BUF void hif_ce_desc_data_record(struct hif_ce_desc_event *event, int len) { @@ -129,16 +131,22 @@ void hif_ce_desc_data_record(struct hif_ce_desc_event *event, int len) } } +qdf_export_symbol(hif_ce_desc_data_record); + void hif_clear_ce_desc_debug_data(struct hif_ce_desc_event *event) { qdf_mem_zero(event, offsetof(struct hif_ce_desc_event, data)); } + +qdf_export_symbol(hif_clear_ce_desc_debug_data); #else void hif_clear_ce_desc_debug_data(struct hif_ce_desc_event *event) { qdf_mem_zero(event, sizeof(struct hif_ce_desc_event)); } + +qdf_export_symbol(hif_clear_ce_desc_debug_data); #endif /* HIF_CE_DEBUG_DATA_BUF */ #if defined(HIF_RECORD_PADDR) @@ -202,6 +210,7 @@ void hif_record_ce_desc_event(struct hif_softc *scn, int ce_id, event->type = type; event->time = qdf_get_log_timestamp(); + event->cpu_id = qdf_get_cpu(); if (descriptor) qdf_mem_copy(&event->descriptor, descriptor, @@ -1637,13 +1646,13 @@ ssize_t hif_input_desc_trace_buf_index(struct hif_softc *scn, ce_hist = &scn->hif_ce_desc_hist; if (!size) { - pr_err("%s: Invalid input buffer.\n", __func__); + qdf_nofl_err("%s: Invalid input buffer.", __func__); return -EINVAL; } if (sscanf(buf, "%u %u", (unsigned int *)&ce_hist->hist_id, (unsigned int *)&ce_hist->hist_index) != 2) { - pr_err("%s: Invalid input value.\n", __func__); + qdf_nofl_err("%s: Invalid input value.", __func__); return -EINVAL; } if ((ce_hist->hist_id >= CE_COUNT_MAX) || @@ -1682,13 +1691,14 @@ ssize_t hif_ce_en_desc_hist(struct hif_softc *scn, const char *buf, size_t size) ce_hist = &scn->hif_ce_desc_hist; if (!size) { - pr_err("%s: Invalid input buffer.\n", __func__); + qdf_nofl_err("%s: Invalid input buffer.", __func__); return -EINVAL; } if (sscanf(buf, "%u %u", (unsigned int *)&ce_id, (unsigned int *)&cfg) != 2) { - pr_err("%s: Invalid input: Enter CE Id<1/0>.\n", __func__); + qdf_nofl_err("%s: Invalid input: Enter CE Id<1/0>.", + __func__); return -EINVAL; } if (ce_id >= CE_COUNT_MAX) { diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service_legacy.c b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service_legacy.c index 68faf5d4e45b58771fc6a8f2c2fbbc390d0243fe..366069e97a25567979b72ceb27fc4b8361bf71fd 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service_legacy.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service_legacy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 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 @@ -1267,6 +1267,34 @@ static bool ce_check_int_watermark(struct CE_state *CE_state, return false; } +#ifdef HIF_CE_LOG_INFO +/** + * ce_get_index_info_legacy(): Get CE index info + * @scn: HIF Context + * @ce_state: CE opaque handle + * @info: CE info + * + * Return: 0 for success and non zero for failure + */ +static +int ce_get_index_info_legacy(struct hif_softc *scn, void *ce_state, + struct ce_index *info) +{ + struct CE_state *state = (struct CE_state *)ce_state; + + info->id = state->id; + if (state->src_ring) { + info->u.legacy_info.sw_index = state->src_ring->sw_index; + info->u.legacy_info.write_index = state->src_ring->write_index; + } else if (state->dest_ring) { + info->u.legacy_info.sw_index = state->dest_ring->sw_index; + info->u.legacy_info.write_index = state->dest_ring->write_index; + } + + return 0; +} +#endif + struct ce_ops ce_service_legacy = { .ce_get_desc_size = ce_get_desc_size_legacy, .ce_ring_setup = ce_ring_setup_legacy, @@ -1283,6 +1311,10 @@ struct ce_ops ce_service_legacy = { .ce_send_entries_done_nolock = ce_send_entries_done_nolock_legacy, .ce_prepare_shadow_register_v2_cfg = ce_prepare_shadow_register_v2_cfg_legacy, +#ifdef HIF_CE_LOG_INFO + .ce_get_index_info = + ce_get_index_info_legacy, +#endif }; struct ce_ops *ce_services_legacy(void) diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service_srng.c b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service_srng.c index 102667ab82a10ae9f0e00ad8ef43b6af92f1ff84..013f7d98c61998185ae775426510b85b669ce868 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service_srng.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_service_srng.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -112,6 +112,7 @@ void hif_record_ce_srng_desc_event(struct hif_softc *scn, int ce_id, event->type = type; event->time = qdf_get_log_timestamp(); + event->cpu_id = qdf_get_cpu(); if (descriptor) qdf_mem_copy(&event->descriptor, descriptor, @@ -308,7 +309,7 @@ ce_recv_buf_enqueue_srng(struct CE_handle *copyeng, unsigned int sw_index; uint64_t dma_addr = buffer; struct hif_softc *scn = CE_state->scn; - struct ce_srng_dest_desc *dest_desc; + struct ce_srng_dest_desc *dest_desc = NULL; qdf_spin_lock_bh(&CE_state->ce_index_lock); write_index = dest_ring->write_index; @@ -739,8 +740,8 @@ static void ce_srng_msi_ring_params_setup(struct hif_softc *scn, uint32_t ce_id, } static void ce_srng_src_ring_setup(struct hif_softc *scn, uint32_t ce_id, - struct CE_ring_state *src_ring, - struct CE_attr *attr) + struct CE_ring_state *src_ring, + struct CE_attr *attr) { struct hal_srng_params ring_params = {0}; @@ -761,6 +762,7 @@ static void ce_srng_src_ring_setup(struct hif_softc *scn, uint32_t ce_id, ring_params.intr_timer_thres_us = 0; ring_params.intr_batch_cntr_thres_entries = 1; + ring_params.prefetch_timer = HAL_SRNG_PREFETCH_TIMER; } src_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_SRC, ce_id, 0, @@ -786,8 +788,9 @@ static void ce_srng_src_ring_setup(struct hif_softc *scn, uint32_t ce_id, * fails to post the last entry due to the race condition. */ static void ce_srng_initialize_dest_timer_interrupt_war( - struct CE_ring_state *dest_ring, - struct hal_srng_params *ring_params) { + struct CE_ring_state *dest_ring, + struct hal_srng_params *ring_params) +{ int num_buffers_when_fully_posted = dest_ring->nentries - 2; ring_params->low_threshold = num_buffers_when_fully_posted - 1; @@ -796,9 +799,10 @@ static void ce_srng_initialize_dest_timer_interrupt_war( ring_params->flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE; } -static void ce_srng_dest_ring_setup(struct hif_softc *scn, uint32_t ce_id, - struct CE_ring_state *dest_ring, - struct CE_attr *attr) +static void ce_srng_dest_ring_setup(struct hif_softc *scn, + uint32_t ce_id, + struct CE_ring_state *dest_ring, + struct CE_attr *attr) { struct hal_srng_params ring_params = {0}; bool status_ring_timer_thresh_work_arround = true; @@ -822,6 +826,7 @@ static void ce_srng_dest_ring_setup(struct hif_softc *scn, uint32_t ce_id, ring_params.intr_batch_cntr_thres_entries = 0; ring_params.flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE; } + ring_params.prefetch_timer = HAL_SRNG_PREFETCH_TIMER; } /*Dest ring is also source ring*/ @@ -829,6 +834,34 @@ static void ce_srng_dest_ring_setup(struct hif_softc *scn, uint32_t ce_id, &ring_params); } +#ifdef WLAN_CE_INTERRUPT_THRESHOLD_CONFIG +/** + * ce_status_ring_config_int_threshold() - configure ce status ring interrupt + * thresholds + * @scn: hif handle + * @ring_params: ce srng params + * + * Return: None + */ +static inline +void ce_status_ring_config_int_threshold(struct hif_softc *scn, + struct hal_srng_params *ring_params) +{ + ring_params->intr_timer_thres_us = + scn->ini_cfg.ce_status_ring_timer_threshold; + ring_params->intr_batch_cntr_thres_entries = + scn->ini_cfg.ce_status_ring_batch_count_threshold; +} +#else +static inline +void ce_status_ring_config_int_threshold(struct hif_softc *scn, + struct hal_srng_params *ring_params) +{ + ring_params->intr_timer_thres_us = 0x1000; + ring_params->intr_batch_cntr_thres_entries = 0x1; +} +#endif /* WLAN_CE_INTERRUPT_THRESHOLD_CONFIG */ + static void ce_srng_status_ring_setup(struct hif_softc *scn, uint32_t ce_id, struct CE_ring_state *status_ring, struct CE_attr *attr) @@ -844,8 +877,7 @@ static void ce_srng_status_ring_setup(struct hif_softc *scn, uint32_t ce_id, ring_params.num_entries = status_ring->nentries; if (!(CE_ATTR_DISABLE_INTR & attr->flags)) { - ring_params.intr_timer_thres_us = 0x1000; - ring_params.intr_batch_cntr_thres_entries = 0x1; + ce_status_ring_config_int_threshold(scn, &ring_params); } status_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_DST_STATUS, @@ -914,15 +946,52 @@ static void ce_prepare_shadow_register_v2_cfg_srng(struct hif_softc *scn, /* return with original configuration*/ return; } - - hal_construct_shadow_config(scn->hal_soc); + hal_construct_srng_shadow_regs(scn->hal_soc); ce_construct_shadow_config_srng(scn); - + hal_set_shadow_regs(scn->hal_soc); + hal_construct_shadow_regs(scn->hal_soc); /* get updated configuration */ hal_get_shadow_config(scn->hal_soc, shadow_config, num_shadow_registers_configured); } +#ifdef HIF_CE_LOG_INFO +/** + * ce_get_index_info_srng(): Get CE index info + * @scn: HIF Context + * @ce_state: CE opaque handle + * @info: CE info + * + * Return: 0 for success and non zero for failure + */ +static +int ce_get_index_info_srng(struct hif_softc *scn, void *ce_state, + struct ce_index *info) +{ + struct CE_state *CE_state = (struct CE_state *)ce_state; + uint32_t tp, hp; + + info->id = CE_state->id; + if (CE_state->src_ring) { + hal_get_sw_hptp(scn->hal_soc, CE_state->src_ring->srng_ctx, + &tp, &hp); + info->u.srng_info.tp = tp; + info->u.srng_info.hp = hp; + } else if (CE_state->dest_ring && CE_state->status_ring) { + hal_get_sw_hptp(scn->hal_soc, CE_state->status_ring->srng_ctx, + &tp, &hp); + info->u.srng_info.status_tp = tp; + info->u.srng_info.status_hp = hp; + hal_get_sw_hptp(scn->hal_soc, CE_state->dest_ring->srng_ctx, + &tp, &hp); + info->u.srng_info.tp = tp; + info->u.srng_info.hp = hp; + } + + return 0; +} +#endif + static struct ce_ops ce_service_srng = { .ce_get_desc_size = ce_get_desc_size_srng, .ce_ring_setup = ce_ring_setup_srng, @@ -939,9 +1008,13 @@ static struct ce_ops ce_service_srng = { .ce_send_entries_done_nolock = ce_send_entries_done_nolock_srng, .ce_prepare_shadow_register_v2_cfg = ce_prepare_shadow_register_v2_cfg_srng, +#ifdef HIF_CE_LOG_INFO + .ce_get_index_info = + ce_get_index_info_srng, +#endif }; -struct ce_ops *ce_services_srng() +struct ce_ops *ce_services_srng(void) { return &ce_service_srng; } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_tasklet.c b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_tasklet.c index 9a5b61599d498a3f0be503b54a36738cff1c3bd4..ced2765a91d058dcbaba123dd86c422e4aeff547 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_tasklet.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_tasklet.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 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 @@ -35,7 +35,6 @@ #include "hif_debug.h" #include "hif_napi.h" - /** * struct tasklet_work * @@ -139,6 +138,200 @@ static inline void ce_schedule_tasklet(struct ce_tasklet_entry *tasklet_entry) tasklet_schedule(&tasklet_entry->intr_tq); } +#ifdef CE_TASKLET_DEBUG_ENABLE +/** + * hif_record_tasklet_exec_entry_ts() - Record ce tasklet execution + * entry time + * @scn: hif_softc + * @ce_id: ce_id + * + * Return: None + */ +static inline void +hif_record_tasklet_exec_entry_ts(struct hif_softc *scn, uint8_t ce_id) +{ + struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(scn); + + hif_ce_state->stats.tasklet_exec_entry_ts[ce_id] = + qdf_get_log_timestamp_usecs(); +} + +/** + * hif_record_tasklet_sched_entry_ts() - Record ce tasklet scheduled + * entry time + * @scn: hif_softc + * @ce_id: ce_id + * + * Return: None + */ +static inline void +hif_record_tasklet_sched_entry_ts(struct hif_softc *scn, uint8_t ce_id) +{ + struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(scn); + + hif_ce_state->stats.tasklet_sched_entry_ts[ce_id] = + qdf_get_log_timestamp_usecs(); +} + +/** + * hif_ce_latency_stats() - Display ce latency information + * @hif_ctx: hif_softc struct + * + * Return: None + */ +static void +hif_ce_latency_stats(struct hif_softc *hif_ctx) +{ + uint8_t i, j; + uint32_t index, start_index; + static const char * const buck_str[] = {"0 - 0.5", "0.5 - 1", "1 - 2", + "2 - 5", "5 - 10", " > 10"}; + struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(hif_ctx); + struct ce_stats *stats = &hif_ce_state->stats; + + hif_err("\tCE TASKLET ARRIVAL AND EXECUTION STATS"); + for (i = 0; i < CE_COUNT_MAX; i++) { + hif_nofl_err("\n\t\tCE Ring %d Tasklet Execution Bucket", i); + for (j = 0; j < CE_BUCKET_MAX; j++) { + hif_nofl_err("\t Bucket %sms :%llu\t last update:%llu", + buck_str[j], + stats->ce_tasklet_exec_bucket[i][j], + stats->ce_tasklet_exec_last_update[i][j]); + } + + hif_nofl_err("\n\t\tCE Ring %d Tasklet Scheduled Bucket", i); + for (j = 0; j < CE_BUCKET_MAX; j++) { + hif_nofl_err("\t Bucket %sms :%llu\t last update :%lld", + buck_str[j], + stats->ce_tasklet_sched_bucket[i][j], + stats-> + ce_tasklet_sched_last_update[i][j]); + } + + hif_nofl_err("\n\t\t CE RING %d Last %d time records", + i, HIF_REQUESTED_EVENTS); + index = stats->record_index[i]; + start_index = stats->record_index[i]; + + for (j = 0; j < HIF_REQUESTED_EVENTS; j++) { + hif_nofl_err("\t Execuiton time: %luus Total Scheduled time: %luus", + stats->tasklet_exec_time_record[i][index], + stats-> + tasklet_sched_time_record[i][index]); + index = (index - 1) % HIF_REQUESTED_EVENTS; + if (index == start_index) + break; + } + } +} + +/** + * ce_tasklet_update_bucket() - update ce execution and scehduled time latency + * in corresponding time buckets + * @stats: struct ce_stats + * @ce_id: ce_id_type + * @entry_us: timestamp when tasklet is started to execute + * @exit_us: timestamp when tasklet is completed execution + * + * Return: N/A + */ +static void ce_tasklet_update_bucket(struct HIF_CE_state *hif_ce_state, + uint8_t ce_id) +{ + uint32_t index; + uint64_t exec_time, exec_ms; + uint64_t sched_time, sched_ms; + uint64_t curr_time = qdf_get_log_timestamp_usecs(); + struct ce_stats *stats = &hif_ce_state->stats; + + exec_time = curr_time - (stats->tasklet_exec_entry_ts[ce_id]); + sched_time = (stats->tasklet_exec_entry_ts[ce_id]) - + (stats->tasklet_sched_entry_ts[ce_id]); + + index = stats->record_index[ce_id]; + index = (index + 1) % HIF_REQUESTED_EVENTS; + + stats->tasklet_exec_time_record[ce_id][index] = exec_time; + stats->tasklet_sched_time_record[ce_id][index] = sched_time; + stats->record_index[ce_id] = index; + + exec_ms = qdf_do_div(exec_time, 1000); + sched_ms = qdf_do_div(sched_time, 1000); + + if (exec_ms > 10) { + stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_BEYOND]++; + stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_BEYOND] + = curr_time; + } else if (exec_ms > 5) { + stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_10_MS]++; + stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_10_MS] + = curr_time; + } else if (exec_ms > 2) { + stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_5_MS]++; + stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_5_MS] + = curr_time; + } else if (exec_ms > 1) { + stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_2_MS]++; + stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_2_MS] + = curr_time; + } else if (exec_time > 500) { + stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_1_MS]++; + stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_1_MS] + = curr_time; + } else { + stats->ce_tasklet_exec_bucket[ce_id][CE_BUCKET_500_US]++; + stats->ce_tasklet_exec_last_update[ce_id][CE_BUCKET_500_US] + = curr_time; + } + + if (sched_ms > 10) { + stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_BEYOND]++; + stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_BEYOND] + = curr_time; + } else if (sched_ms > 5) { + stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_10_MS]++; + stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_10_MS] + = curr_time; + } else if (sched_ms > 2) { + stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_5_MS]++; + stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_5_MS] + = curr_time; + } else if (sched_ms > 1) { + stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_2_MS]++; + stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_2_MS] + = curr_time; + } else if (sched_time > 500) { + stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_1_MS]++; + stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_1_MS] + = curr_time; + } else { + stats->ce_tasklet_sched_bucket[ce_id][CE_BUCKET_500_US]++; + stats->ce_tasklet_sched_last_update[ce_id][CE_BUCKET_500_US] + = curr_time; + } +} +#else +static inline void +hif_record_tasklet_exec_entry_ts(struct hif_softc *scn, uint8_t ce_id) +{ +} + +static void ce_tasklet_update_bucket(struct HIF_CE_state *hif_ce_state, + uint8_t ce_id) +{ +} + +static inline void +hif_record_tasklet_sched_entry_ts(struct hif_softc *scn, uint8_t ce_id) +{ +} + +static void +hif_ce_latency_stats(struct hif_softc *hif_ctx) +{ +} +#endif /*CE_TASKLET_DEBUG_ENABLE*/ + /** * ce_tasklet() - ce_tasklet * @data: data @@ -153,8 +346,11 @@ static void ce_tasklet(unsigned long data) struct hif_softc *scn = HIF_GET_SOFTC(hif_ce_state); struct CE_state *CE_state = scn->ce_id_to_state[tasklet_entry->ce_id]; + if (scn->ce_latency_stats) + hif_record_tasklet_exec_entry_ts(scn, tasklet_entry->ce_id); + hif_record_ce_desc_event(scn, tasklet_entry->ce_id, - HIF_CE_TASKLET_ENTRY, NULL, NULL, -1, 0); + HIF_CE_TASKLET_ENTRY, NULL, NULL, -1, 0); if (qdf_atomic_read(&scn->link_suspended)) { HIF_ERROR("%s: ce %d tasklet fired after link suspend.", @@ -183,6 +379,9 @@ static void ce_tasklet(unsigned long data) hif_record_ce_desc_event(scn, tasklet_entry->ce_id, HIF_CE_TASKLET_EXIT, NULL, NULL, -1, 0); + if (scn->ce_latency_stats) + ce_tasklet_update_bucket(hif_ce_state, tasklet_entry->ce_id); + qdf_atomic_dec(&scn->active_tasklet_cnt); } @@ -339,12 +538,13 @@ hif_ce_increment_interrupt_count(struct HIF_CE_state *hif_ce_state, int ce_id) * * Return: none */ -void hif_display_ce_stats(struct HIF_CE_state *hif_ce_state) +void hif_display_ce_stats(struct hif_softc *hif_ctx) { #define STR_SIZE 128 uint8_t i, j, pos; char str_buffer[STR_SIZE]; int size, ret; + struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(hif_ctx); qdf_debug("CE interrupt statistics:"); for (i = 0; i < CE_COUNT_MAX; i++) { @@ -352,7 +552,7 @@ void hif_display_ce_stats(struct HIF_CE_state *hif_ce_state) pos = 0; for (j = 0; j < QDF_MAX_AVAILABLE_CPU; j++) { ret = snprintf(str_buffer + pos, size, "[%d]:%d ", - j, hif_ce_state->stats.ce_per_cpu[i][j]); + j, hif_ce_state->stats.ce_per_cpu[i][j]); if (ret <= 0 || ret >= size) break; size -= ret; @@ -360,6 +560,9 @@ void hif_display_ce_stats(struct HIF_CE_state *hif_ce_state) } qdf_debug("CE id[%2d] - %s", i, str_buffer); } + + if (hif_ctx->ce_latency_stats) + hif_ce_latency_stats(hif_ctx); #undef STR_SIZE } @@ -393,6 +596,9 @@ static inline bool hif_tasklet_schedule(struct hif_opaque_softc *hif_ctx, } tasklet_schedule(&tasklet_entry->intr_tq); + if (scn->ce_latency_stats) + hif_record_tasklet_sched_entry_ts(scn, tasklet_entry->ce_id); + return true; } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_tasklet.h b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_tasklet.h index 05da16872781430932bba3edce11020403640b42..d5ab58cefb11be0e7016e0d916ba1e654d183654 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_tasklet.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ce/ce_tasklet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016,2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016,2018,2020 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 @@ -28,6 +28,6 @@ QDF_STATUS ce_register_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask); QDF_STATUS ce_unregister_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask); irqreturn_t ce_dispatch_interrupt(int irq, struct ce_tasklet_entry *tasklet_entry); -void hif_display_ce_stats(struct HIF_CE_state *hif_ce_state); +void hif_display_ce_stats(struct hif_softc *hif_ctx); void hif_clear_ce_stats(struct HIF_CE_state *hif_ce_state); #endif /* __CE_TASKLET_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/ahb_api.h b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/ahb_api.h index 103114b87e529c9c02a4b3830348ef3d87dcb620..c7fca4c195607ffd276063a9eccff92acca6ff8c 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/ahb_api.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/ahb_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2018,2020-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 @@ -49,5 +49,8 @@ int hif_ahb_enable_radio(struct hif_pci_softc *sc, int hif_ahb_configure_irq(struct hif_pci_softc *sc); int hif_ahb_configure_grp_irq(struct hif_softc *scn, struct hif_exec_context *hif_ext_grp); +void hif_ahb_deconfigure_grp_irq(struct hif_softc *scn); bool hif_ahb_needs_bmi(struct hif_softc *scn); +void hif_ahb_display_stats(struct hif_softc *scn); +void hif_ahb_clear_stats(struct hif_softc *scn); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/dummy.c b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/dummy.c index de0b195cb9429b2bf0e0fa91fa5ebc6377c8b021..f4d323dcd2c3987ce6709c4b10d694843ca96aea 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/dummy.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/dummy.c @@ -262,6 +262,16 @@ int hif_dummy_grp_irq_configure(struct hif_softc *hif_sc, return 0; } +/** + * hif_dummy_grp_irq_deconfigure - dummy call + * hif_sc: hif context + * + * Return: none + */ +void hif_dummy_grp_irq_deconfigure(struct hif_softc *hif_sc) +{ +} + /** * hif_dummy_dump_registers - dummy call * hif_sc: hif context @@ -377,3 +387,17 @@ int hif_dummy_addr_in_boundary(struct hif_softc *scn, uint32_t offset) void hif_dummy_config_irq_affinity(struct hif_softc *scn) { } + +/** + * hif_dummy_log_bus_info - dummy call + * @scn: hif context + * @data: hang event data buffer + * @offset: offset at which data needs to be written + * + * Return: bool + */ +bool hif_dummy_log_bus_info(struct hif_softc *scn, uint8_t *data, + unsigned int *offset) +{ + return false; +} diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/dummy.h b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/dummy.h index 99c440a937574a23d88684e60f61cea404db4c73..c048803d152a7736f1cba5aca5ba6105ed57709c 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/dummy.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/dummy.h @@ -44,6 +44,7 @@ void hif_dummy_grp_irq_enable(struct hif_softc *hif_sc, uint32_t grp_id); void hif_dummy_grp_irq_disable(struct hif_softc *hif_sc, uint32_t grp_id); int hif_dummy_grp_irq_configure(struct hif_softc *hif_sc, struct hif_exec_context *exec); +void hif_dummy_grp_irq_deconfigure(struct hif_softc *hif_sc); int hif_dummy_dump_registers(struct hif_softc *hif_sc); void hif_dummy_dump_target_memory(struct hif_softc *hif_sc, void *ramdump_base, uint32_t address, uint32_t size); @@ -60,3 +61,5 @@ int hif_dummy_bus_reset_resume(struct hif_softc *hif_ctx); int hif_dummy_map_ce_to_irq(struct hif_softc *scn, int ce_id); int hif_dummy_addr_in_boundary(struct hif_softc *scn, uint32_t offset); void hif_dummy_config_irq_affinity(struct hif_softc *scn); +bool hif_dummy_log_bus_info(struct hif_softc *scn, uint8_t *data, + unsigned int *offset); diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/ipci_api.h b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/ipci_api.h new file mode 100644 index 0000000000000000000000000000000000000000..17353428912c9f88eda4ac264c654533f2e24881 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/ipci_api.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2020 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 above + * copyright notice and this permission notice appear in all copies. + + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _IPCI_API_H_ +#define _IPCI_API_H_ +struct hif_exec_context; + +/** + * hif_ipci_open(): hif_bus_open + * @hif_ctx: hif context + * @bus_type: bus type + * + * Return: 0 for success or QDF_STATUS_E_NOMEM + */ +QDF_STATUS hif_ipci_open(struct hif_softc *hif_ctx, + enum qdf_bus_type bus_type); + +/** + * hif_ipci_close(): hif_bus_close + * @hif_ctx: hif context + * + * Return: n/a + */ +void hif_ipci_close(struct hif_softc *hif_ctx); + +/** + * hif_bus_prevent_linkdown(): allow or permit linkdown + * @scn: struct hif_softc + * @flag: true prevents linkdown, false allows + * + * Calls into the platform driver to vote against taking down the + * pcie link. + * + * Return: n/a + */ +void hif_ipci_prevent_linkdown(struct hif_softc *scn, bool flag); + +/** + * hif_ipci_bus_suspend(): prepare hif for suspend + * @scn: struct hif_softc + * + * Return: Errno + */ +int hif_ipci_bus_suspend(struct hif_softc *scn); + +/** + * hif_ipci_bus_suspend_noirq() - ensure there are no pending transactions + * @scn: hif context + * + * Ensure that if we received the wakeup message before the irq + * was disabled that the message is pocessed before suspending. + * + * Return: -EBUSY if we fail to flush the tasklets. + */ +int hif_ipci_bus_suspend_noirq(struct hif_softc *scn); + +/** + * hif_ipci_bus_resume(): prepare hif for resume + * @scn: struct hif_softc + * + * Return: Errno + */ +int hif_ipci_bus_resume(struct hif_softc *scn); + +/** + * hif_ipci_bus_resume_noirq() - ensure there are no pending transactions + * @scn: hif context + * + * Ensure that if we received the wakeup message before the irq + * was disabled that the message is pocessed before suspending. + * + * Return: -EBUSY if we fail to flush the tasklets. + */ +int hif_ipci_bus_resume_noirq(struct hif_softc *scn); + +/** + * hif_ipci_disable_isr(): disable interrupt + * @scn: struct hif_softc + * + * Return: n/a + */ +void hif_ipci_disable_isr(struct hif_softc *scn); + +/** + * hif_ipci_nointrs(): disable IRQ + * @scn: struct hif_softc + * + * This function stops interrupt(s) + * + * Return: none + */ +void hif_ipci_nointrs(struct hif_softc *scn); + +/** + * hif_ipci_dump_registers(): dump bus debug registers + * @scn: struct hif_opaque_softc + * + * This function dumps hif bus debug registers + * + * Return: 0 for success or error code + */ +int hif_ipci_dump_registers(struct hif_softc *scn); + +/** + * hif_ipci_enable_bus(): enable bus + * + * This function enables the bus + * + * @ol_sc: soft_sc struct + * @dev: device pointer + * @bdev: bus dev pointer + * bid: bus id pointer + * type: enum hif_enable_type such as HIF_ENABLE_TYPE_PROBE + * Return: QDF_STATUS + */ +QDF_STATUS hif_ipci_enable_bus( + struct hif_softc *scn, + struct device *dev, void *bdev, + const struct hif_bus_id *bid, + enum hif_enable_type type); + +/** + * hif_ipci_disable_bus(): hif_disable_bus + * + * This function disables the bus + * + * @scn: struct hif_softc + * + * Return: none + */ +void hif_ipci_disable_bus(struct hif_softc *scn); + +/** + * hif_ipci_bus_configure() - configure the pcie bus + * @hif_sc: pointer to the hif context. + * + * return: 0 for success. nonzero for failure. + */ +int hif_ipci_bus_configure(struct hif_softc *scn); + +/** + * hif_ipci_enable_power_management() - enable power management + * @hif_ctx: hif context + * @is_packet_log_enabled: pktlog enabled or disabled + * + * Return: none + */ +void hif_ipci_enable_power_management( + struct hif_softc *hif_ctx, + bool is_packet_log_enabled); + +/** + * hif_ipci_disable_power_management() - disable power management + * @hif_ctx: hif context + * + * Return: none + */ +void hif_ipci_disable_power_management(struct hif_softc *hif_ctx); + +/** + * hif_ipci_configure_grp_irq() - configure HW block irq + * @scn: hif context + * @exec: hif exec context + * + * Return:Errno + */ +int hif_ipci_configure_grp_irq( + struct hif_softc *scn, + struct hif_exec_context *exec); + +/** + * hif_ipci_deconfigure_grp_irq() - deconfigure HW block irq + * @scn: hif context + * + * Return: None + */ +void hif_ipci_deconfigure_grp_irq(struct hif_softc *scn); + +/** + * hif_ipci_display_stats() - display stats + * @hif_ctx: hif context + * + * Return: none + */ +void hif_ipci_display_stats(struct hif_softc *hif_ctx); + +/** + * hif_ipci_clear_stats() - clear stats + * @hif_ctx: hif context + * + * Return: none + */ +void hif_ipci_clear_stats(struct hif_softc *hif_ctx); + +/** + * hif_ipci_needs_bmi() - return true if the soc needs bmi through the driver + * @scn: hif context + * + * Return: true if soc needs driver bmi otherwise false + */ +bool hif_ipci_needs_bmi(struct hif_softc *scn); + +/** + * hif_ipci_get_irq_name() - get irqname + * This function gives irqnumber to irqname + * mapping. + * + * @irq_no: irq number + * + * Return: irq name + */ +const char *hif_ipci_get_irq_name(int irq_no); + +#endif /* _IPCI_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus.c b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus.c index 8c1dbbb273f9e03ca0d8ef1a9d9b85470c23e78d..aa80361d6a8456f46dae343e79adc2222ee11327 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, 2020 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 @@ -23,7 +23,8 @@ #include "hif_io32.h" #include "multibus.h" #include "dummy.h" -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI) #include "ce_main.h" #include "ce_api.h" #include "ce_internal.h" @@ -57,6 +58,7 @@ static void hif_initialize_default_ops(struct hif_softc *hif_sc) bus_ops->hif_bus_late_resume = &hif_dummy_bus_resume; bus_ops->hif_map_ce_to_irq = &hif_dummy_map_ce_to_irq; bus_ops->hif_grp_irq_configure = &hif_dummy_grp_irq_configure; + bus_ops->hif_grp_irq_deconfigure = &hif_dummy_grp_irq_deconfigure; bus_ops->hif_config_irq_affinity = &hif_dummy_config_irq_affinity; } @@ -98,6 +100,8 @@ int hif_bus_get_context_size(enum qdf_bus_type bus_type) switch (bus_type) { case QDF_BUS_TYPE_PCI: return hif_pci_get_context_size(); + case QDF_BUS_TYPE_IPCI: + return hif_ipci_get_context_size(); case QDF_BUS_TYPE_AHB: return hif_ahb_get_context_size(); case QDF_BUS_TYPE_SNOC: @@ -129,6 +133,9 @@ QDF_STATUS hif_bus_open(struct hif_softc *hif_sc, case QDF_BUS_TYPE_PCI: status = hif_initialize_pci_ops(hif_sc); break; + case QDF_BUS_TYPE_IPCI: + status = hif_initialize_ipci_ops(hif_sc); + break; case QDF_BUS_TYPE_SNOC: status = hif_initialize_snoc_ops(&hif_sc->bus_ops); break; @@ -325,6 +332,11 @@ int hif_grp_irq_configure(struct hif_softc *hif_sc, return hif_sc->bus_ops.hif_grp_irq_configure(hif_sc, hif_exec); } +void hif_grp_irq_deconfigure(struct hif_softc *hif_sc) +{ + hif_sc->bus_ops.hif_grp_irq_deconfigure(hif_sc); +} + int hif_dump_registers(struct hif_opaque_softc *hif_hdl) { struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl); @@ -526,3 +538,14 @@ void hif_config_irq_affinity(struct hif_softc *hif_sc) { hif_sc->bus_ops.hif_config_irq_affinity(hif_sc); } + +#ifdef HIF_BUS_LOG_INFO +bool hif_log_bus_info(struct hif_softc *hif_sc, uint8_t *data, + unsigned int *offset) +{ + if (hif_sc->bus_ops.hif_log_bus_info) + return hif_sc->bus_ops.hif_log_bus_info(hif_sc, data, offset); + + return false; +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus.h b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus.h index 53a04e46a98bb976baf7d55fa3e4c71c249cbfd5..104a7924bacff51dfa9bc2289810f4ad4d612fc1 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, 2020 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 @@ -60,6 +60,7 @@ struct hif_bus_ops { void (*hif_irq_enable)(struct hif_softc *hif_sc, int ce_id); int (*hif_grp_irq_configure)(struct hif_softc *hif_sc, struct hif_exec_context *exec); + void (*hif_grp_irq_deconfigure)(struct hif_softc *hif_sc); int (*hif_dump_registers)(struct hif_softc *hif_sc); void (*hif_dump_target_memory)(struct hif_softc *hif_sc, void *ramdump_base, @@ -81,6 +82,8 @@ struct hif_bus_ops { int (*hif_addr_in_boundary)(struct hif_softc *scn, uint32_t offset); bool (*hif_needs_bmi)(struct hif_softc *hif_sc); void (*hif_config_irq_affinity)(struct hif_softc *hif_sc); + bool (*hif_log_bus_info)(struct hif_softc *scn, uint8_t *data, + unsigned int *offset); }; #ifdef HIF_SNOC @@ -123,6 +126,39 @@ static inline int hif_pci_get_context_size(void) } #endif /* HIF_PCI */ +#ifdef HIF_IPCI +/** + * hif_initialize_ipci_ops() - initialize the pci ops + * @hif_sc: pointer to hif context + * + * Return: QDF_STATUS_SUCCESS + */ +QDF_STATUS hif_initialize_ipci_ops(struct hif_softc *hif_sc); + +/** + * hif_ipci_get_context_size() - return the size of the ipci context + * + * Return the size of the context. (0 for invalid bus) + */ +int hif_ipci_get_context_size(void); +#else +static inline QDF_STATUS hif_initialize_ipci_ops(struct hif_softc *hif_sc) +{ + HIF_ERROR("%s: not supported", __func__); + return QDF_STATUS_E_NOSUPPORT; +} + +/** + * hif_ipci_get_context_size() - dummy when ipci isn't supported + * + * Return: 0 as an invalid size to indicate no support + */ +static inline int hif_ipci_get_context_size(void) +{ + return 0; +} +#endif /* HIF_IPCI */ + #ifdef HIF_AHB QDF_STATUS hif_initialize_ahb_ops(struct hif_bus_ops *bus_ops); int hif_ahb_get_context_size(void); @@ -178,6 +214,7 @@ static inline int hif_sdio_get_context_size(void) int hif_grp_irq_configure(struct hif_softc *hif_sc, struct hif_exec_context *hif_exec); +void hif_grp_irq_deconfigure(struct hif_softc *hif_sc); #ifdef HIF_USB QDF_STATUS hif_initialize_usb_ops(struct hif_bus_ops *bus_ops); int hif_usb_get_context_size(void); @@ -208,4 +245,24 @@ static inline int hif_usb_get_context_size(void) * Return: None */ void hif_config_irq_affinity(struct hif_softc *hif_sc); + +#ifdef HIF_BUS_LOG_INFO +/** + * hif_log_bus_info() - API to log bus related info + * @scn: hif handle + * @data: hang event data buffer + * @offset: offset at which data needs to be written + * + * Return: true if bus_id is invalid else false + */ +bool hif_log_bus_info(struct hif_softc *scn, uint8_t *data, + unsigned int *offset); +#else +static inline +bool hif_log_bus_info(struct hif_softc *scn, uint8_t *data, + unsigned int *offset) +{ + return false; +} +#endif #endif /* _MULTIBUS_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_ahb.c b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_ahb.c index 7ab211e1296f77c5c10122a1641393de448e147d..e6fc2440024feebb5694949f3606573e91ea8dac 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_ahb.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_ahb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018,2020-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 @@ -67,10 +67,14 @@ QDF_STATUS hif_initialize_ahb_ops(struct hif_bus_ops *bus_ops) bus_ops->hif_disable_power_management = &hif_dummy_disable_power_management; bus_ops->hif_grp_irq_configure = &hif_ahb_configure_grp_irq; + bus_ops->hif_grp_irq_deconfigure = &hif_ahb_deconfigure_grp_irq; bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary; bus_ops->hif_needs_bmi = &hif_ahb_needs_bmi; + bus_ops->hif_display_stats = &hif_ahb_display_stats; + bus_ops->hif_clear_stats = &hif_ahb_clear_stats; bus_ops->hif_config_irq_affinity = &hif_dummy_config_irq_affinity; + bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info; return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_ipci.c b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_ipci.c new file mode 100644 index 0000000000000000000000000000000000000000..b67e5e382a41982b32ed83b2a73612e2c130cd72 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_ipci.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020 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 above + * copyright notice and this permission notice appear in all copies. + + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hif.h" +#include "hif_main.h" +#include "multibus.h" +#include "ipci_api.h" +#include "hif_io32.h" +#include "dummy.h" +#include "ce_api.h" + +/** + * hif_initialize_ipci_ops() - initialize the pci ops + * @bus_ops: hif_bus_ops table pointer to initialize + * + * Return: QDF_STATUS_SUCCESS + */ +QDF_STATUS hif_initialize_ipci_ops(struct hif_softc *hif_sc) +{ + struct hif_bus_ops *bus_ops = &hif_sc->bus_ops; + + bus_ops->hif_bus_open = &hif_ipci_open; + bus_ops->hif_bus_close = &hif_ipci_close; + bus_ops->hif_bus_prevent_linkdown = &hif_ipci_prevent_linkdown; + bus_ops->hif_reset_soc = &hif_dummy_reset_soc; + bus_ops->hif_bus_suspend = &hif_ipci_bus_suspend; + bus_ops->hif_bus_resume = &hif_ipci_bus_resume; + bus_ops->hif_bus_suspend_noirq = &hif_ipci_bus_suspend_noirq; + bus_ops->hif_bus_resume_noirq = &hif_ipci_bus_resume_noirq; + bus_ops->hif_target_sleep_state_adjust = + &hif_dummy_target_sleep_state_adjust; + bus_ops->hif_disable_isr = &hif_ipci_disable_isr; + bus_ops->hif_nointrs = &hif_ipci_nointrs; + bus_ops->hif_enable_bus = &hif_ipci_enable_bus; + bus_ops->hif_disable_bus = &hif_ipci_disable_bus; + bus_ops->hif_bus_configure = &hif_ipci_bus_configure; + bus_ops->hif_get_config_item = &hif_dummy_get_config_item; + bus_ops->hif_set_mailbox_swap = &hif_dummy_set_mailbox_swap; + bus_ops->hif_claim_device = &hif_dummy_claim_device; + bus_ops->hif_shutdown_device = &hif_ce_stop; + bus_ops->hif_stop = &hif_ce_stop; + bus_ops->hif_cancel_deferred_target_sleep = + &hif_dummy_cancel_deferred_target_sleep; + bus_ops->hif_irq_disable = &hif_dummy_irq_disable; + bus_ops->hif_irq_enable = &hif_dummy_irq_enable; + bus_ops->hif_dump_registers = &hif_ipci_dump_registers; + bus_ops->hif_dump_target_memory = &hif_ce_dump_target_memory; + bus_ops->hif_ipa_get_ce_resource = &hif_ce_ipa_get_ce_resource; + bus_ops->hif_mask_interrupt_call = &hif_dummy_mask_interrupt_call; + bus_ops->hif_enable_power_management = + &hif_ipci_enable_power_management; + bus_ops->hif_disable_power_management = + &hif_ipci_disable_power_management; + bus_ops->hif_grp_irq_configure = &hif_ipci_configure_grp_irq; + bus_ops->hif_grp_irq_deconfigure = &hif_ipci_deconfigure_grp_irq; + bus_ops->hif_display_stats = + &hif_ipci_display_stats; + bus_ops->hif_clear_stats = + &hif_ipci_clear_stats; + bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary; + bus_ops->hif_needs_bmi = &hif_ipci_needs_bmi; + bus_ops->hif_config_irq_affinity = + &hif_dummy_config_irq_affinity; + bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info; + + return QDF_STATUS_SUCCESS; +} + +/** + * hif_ipci_get_context_size() - return the size of the ipci context + * + * Return the size of the context. (0 for invalid bus) + */ +int hif_ipci_get_context_size(void) +{ + return sizeof(struct hif_ipci_softc); +} diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_pci.c b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_pci.c index f28053dd16b6f26da97f3801db0db2ba9d02b0de..35010a9f534c29cfe61ccc72a2639c7b6db08ee6 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_pci.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_pci.c @@ -75,6 +75,7 @@ QDF_STATUS hif_initialize_pci_ops(struct hif_softc *hif_sc) bus_ops->hif_disable_power_management = &hif_pci_disable_power_management; bus_ops->hif_grp_irq_configure = &hif_pci_configure_grp_irq; + bus_ops->hif_grp_irq_deconfigure = &hif_pci_deconfigure_grp_irq; bus_ops->hif_display_stats = &hif_pci_display_stats; bus_ops->hif_clear_stats = @@ -87,6 +88,8 @@ QDF_STATUS hif_initialize_pci_ops(struct hif_softc *hif_sc) bus_ops->hif_config_irq_affinity = &hif_pci_config_irq_affinity; + bus_ops->hif_log_bus_info = &hif_log_pcie_info; + return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_sdio.c b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_sdio.c index 3c220be0b42ad8d827a6e0bef192443227e802e4..97a3e194ebc40b89824c11e1a3235bc8a025d3ba 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_sdio.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_sdio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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,8 @@ #include "if_sdio.h" /** - * hif_initialize_sdio_ops() - initialize the pci ops - * @bus_ops: hif_bus_ops table pointer to initialize + * hif_initialize_sdio_ops() - initialize the sdio ops + * @hif_sc: hif soft context * * Return: QDF_STATUS_SUCCESS */ @@ -66,6 +66,7 @@ QDF_STATUS hif_initialize_sdio_ops(struct hif_softc *hif_sc) &hif_dummy_disable_power_management; bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary; bus_ops->hif_needs_bmi = &hif_sdio_needs_bmi; + bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info; return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_snoc.c b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_snoc.c index 3c0253ca060f38104ffa20142943d7a4a2519ef4..0834315a4005eb295fc049d30d43e316183066a8 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_snoc.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_snoc.c @@ -75,6 +75,7 @@ QDF_STATUS hif_initialize_snoc_ops(struct hif_bus_ops *bus_ops) bus_ops->hif_map_ce_to_irq = &hif_snoc_map_ce_to_irq; bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary; bus_ops->hif_needs_bmi = &hif_snoc_needs_bmi; + bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info; return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_usb.c b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_usb.c index e632a40134868060b6c1ca2a4b59be0dcecc7632..08b08ee15afc3bfae4e433b760adde27edb23eaa 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_usb.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/multibus_usb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018,2020 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 @@ -67,6 +67,7 @@ QDF_STATUS hif_initialize_usb_ops(struct hif_bus_ops *bus_ops) bus_ops->hif_bus_reset_resume = &hif_usb_bus_reset_resume; bus_ops->hif_map_ce_to_irq = &hif_dummy_map_ce_to_irq; bus_ops->hif_needs_bmi = &hif_usb_needs_bmi; + bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info; return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/pci_api.h b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/pci_api.h index 0fc67e1af0a054d29a5f5039e77c208052b27223..dddcedec779468dfc6da0f88a27d171b10f9b471 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/pci_api.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/dispatcher/pci_api.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 @@ -48,6 +48,7 @@ void hif_pci_enable_power_management(struct hif_softc *hif_ctx, void hif_pci_disable_power_management(struct hif_softc *hif_ctx); int hif_pci_configure_grp_irq(struct hif_softc *scn, struct hif_exec_context *exec); +void hif_pci_deconfigure_grp_irq(struct hif_softc *scn); void hif_pci_display_stats(struct hif_softc *hif_ctx); void hif_pci_clear_stats(struct hif_softc *hif_ctx); int hif_pci_legacy_map_ce_to_irq(struct hif_softc *scn, int ce_id); diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_exec.c b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_exec.c index 7d3117a1510714490ea37b32bb6eb44ae0f5449d..8f014ff8dd2d41cfc93ea140e3d6c0a1f12e7371 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_exec.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_exec.c @@ -43,6 +43,89 @@ int hif_get_next_record_index(qdf_atomic_t *table_index, return record_index & (array_size - 1); } +/** + * hif_hist_is_prev_record() - Check if index is the immediate + * previous record wrt curr_index + * @curr_index: curr index in the event history + * @index: index to be checked + * @hist_size: history size + * + * Return: true if index is immediately behind curr_index else false + */ +static inline +bool hif_hist_is_prev_record(int32_t curr_index, int32_t index, + uint32_t hist_size) +{ + return (((index + 1) & (hist_size - 1)) == curr_index) ? + true : false; +} + +/** + * hif_hist_skip_event_record() - Check if current event needs to be + * recorded or not + * @hist_ev: HIF event history + * @event: DP event entry + * + * Return: true if current event needs to be skipped else false + */ +static bool +hif_hist_skip_event_record(struct hif_event_history *hist_ev, + struct hif_event_record *event) +{ + struct hif_event_record *rec; + struct hif_event_record *last_irq_rec; + int32_t index; + + index = qdf_atomic_read(&hist_ev->index); + if (index < 0) + return false; + + index &= (HIF_EVENT_HIST_MAX - 1); + rec = &hist_ev->event[index]; + + switch (event->type) { + case HIF_EVENT_IRQ_TRIGGER: + /* + * The prev record check is to prevent skipping the IRQ event + * record in case where BH got re-scheduled due to force_break + * but there are no entries to be reaped in the rings. + */ + if (rec->type == HIF_EVENT_BH_SCHED && + hif_hist_is_prev_record(index, + hist_ev->misc.last_irq_index, + 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->cpu_id = qdf_get_cpu(); + last_irq_rec->hp++; + last_irq_rec->tp = last_irq_rec->timestamp - + hist_ev->misc.last_irq_ts; + return true; + } + break; + case HIF_EVENT_BH_SCHED: + if (rec->type == HIF_EVENT_BH_SCHED) { + rec->timestamp = qdf_get_log_timestamp(); + rec->cpu_id = qdf_get_cpu(); + return true; + } + break; + case HIF_EVENT_SRNG_ACCESS_START: + if (event->hp == event->tp) + return true; + break; + case HIF_EVENT_SRNG_ACCESS_END: + if (rec->type != HIF_EVENT_SRNG_ACCESS_START) + return true; + break; + default: + break; + } + + return false; +} + void hif_hist_record_event(struct hif_opaque_softc *hif_ctx, struct hif_event_record *event, uint8_t intr_grp_id) { @@ -67,11 +150,19 @@ void hif_hist_record_event(struct hif_opaque_softc *hif_ctx, hif_ext_group = hif_state->hif_ext_group[intr_grp_id]; hist_ev = hif_ext_group->evt_hist; + if (hif_hist_skip_event_record(hist_ev, event)) + return; + record_index = hif_get_next_record_index( &hist_ev->index, HIF_EVENT_HIST_MAX); record = &hist_ev->event[record_index]; + if (event->type == HIF_EVENT_IRQ_TRIGGER) { + hist_ev->misc.last_irq_index = record_index; + hist_ev->misc.last_irq_ts = qdf_get_log_timestamp(); + } + record->hal_ring_id = event->hal_ring_id; record->hp = event->hp; record->tp = event->tp; @@ -467,7 +558,8 @@ static void hif_latency_profile_measure(struct hif_exec_context *hif_ext_group) hif_ext_group->sched_latency_stats[7]++; } #else -static void hif_latency_profile_measure(struct hif_exec_context *hif_ext_group) +static inline +void hif_latency_profile_measure(struct hif_exec_context *hif_ext_group) { } #endif @@ -484,11 +576,13 @@ static void hif_latency_profile_start(struct hif_exec_context *hif_ext_group) hif_ext_group->tstamp = qdf_ktime_to_ms(qdf_ktime_get()); } #else -static void hif_latency_profile_start(struct hif_exec_context *hif_ext_group) +static inline +void hif_latency_profile_start(struct hif_exec_context *hif_ext_group) { } #endif +#ifdef FEATURE_NAPI /** * hif_exec_poll() - napi poll * napi: napi struct @@ -585,7 +679,6 @@ struct hif_execution_ops napi_sched_ops = { .kill = &hif_exec_napi_kill, }; -#ifdef FEATURE_NAPI /** * hif_exec_napi_create() - allocate and initialize a napi exec context * @scale: a binary shift factor to map NAPI budget from\to internal @@ -612,7 +705,7 @@ static struct hif_exec_context *hif_exec_napi_create(uint32_t scale) #else static struct hif_exec_context *hif_exec_napi_create(uint32_t scale) { - HIF_WARN("%s: FEATURE_NAPI not defined, making tasklet"); + HIF_WARN("%s: FEATURE_NAPI not defined, making tasklet", __func__); return hif_exec_tasklet_create(); } #endif @@ -738,6 +831,21 @@ uint32_t hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx) qdf_export_symbol(hif_configure_ext_group_interrupts); +void hif_deconfigure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + + if (!scn || !scn->ext_grp_irq_configured) { + hif_err("scn(%pk) is NULL or grp irq not configured", scn); + return; + } + + hif_grp_irq_deconfigure(scn); + scn->ext_grp_irq_configured = false; +} + +qdf_export_symbol(hif_deconfigure_ext_group_interrupts); + #ifdef WLAN_SUSPEND_RESUME_TEST /** * hif_check_and_trigger_ut_resume() - check if unit-test command was used to diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_exec.h b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_exec.h index 6a2b7868ed1ac8fb6073243d0488d980e10c587b..42756e81882700a92ef82561a0e65b4b940d6e97 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_exec.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_exec.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -155,6 +155,7 @@ void hif_exec_destroy(struct hif_exec_context *ctx); int hif_grp_irq_configure(struct hif_softc *scn, struct hif_exec_context *hif_exec); +void hif_grp_irq_deconfigure(struct hif_softc *scn); irqreturn_t hif_ext_group_interrupt_handler(int irq, void *context); struct hif_exec_context *hif_exec_get_ctx(struct hif_opaque_softc *hif, @@ -166,18 +167,47 @@ void hif_exec_kill(struct hif_opaque_softc *scn); * hif_pci_irq_set_affinity_hint() - API to set IRQ affinity * @hif_ext_group: hif_ext_group to extract the irq info * - * This function will set the IRQ affinity to the gold cores - * only for defconfig builds + * This function will set the WLAN IRQ affinity to the gold + * cores only for defconfig builds * * Return: none */ void hif_pci_irq_set_affinity_hint( struct hif_exec_context *hif_ext_group); + +/** + * hif_pci_ce_irq_set_affinity_hint() - API to set IRQ affinity + * + * This function will set the CE IRQ affinity to the gold cores + * only for defconfig builds + * + * @hif_softc: hif_softc to extract the CE irq info + * + * Return: none + */ +void hif_pci_ce_irq_set_affinity_hint( + struct hif_softc *scn); + +/** + * hif_pci_ce_irq_remove_affinity_hint() - remove affinity for the irq + * @irq: irq number to remove affinity from + */ +static inline void hif_pci_ce_irq_remove_affinity_hint(int irq) +{ + hif_irq_affinity_remove(irq); +} #else static inline void hif_pci_irq_set_affinity_hint( struct hif_exec_context *hif_ext_group) { } +static inline void hif_pci_ce_irq_set_affinity_hint( + struct hif_softc *scn) +{ +} +static inline void hif_pci_ce_irq_remove_affinity_hint(int irq) +{ +} #endif /* ifdef HIF_CPU_PERF_AFFINE_MASK */ #endif diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_io32.h b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_io32.h index 63674e26ffe5fd013e89f005bd01210634945a62..4a8f93a992a327e08b8f9fab9b891d5127dd3ea9 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_io32.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_io32.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 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 @@ -23,15 +23,15 @@ #include "hif.h" #include "hif_main.h" -#if defined(HIF_REG_WINDOW_SUPPORT) && defined(HIF_PCI) +#if defined(HIF_REG_WINDOW_SUPPORT) && (defined(HIF_PCI) || \ + defined(HIF_IPCI)) static inline void hif_write32_mb_reg_window(void *sc, void __iomem *addr, uint32_t value); - -static inline uint32_t hif_read32_mb_reg_window(void *sc, - void __iomem *addr); - +static inline +uint32_t hif_read32_mb_reg_window(void *sc, + void __iomem *addr); #define hif_read32_mb(scn, addr) \ hif_read32_mb_reg_window((void *)scn, \ (void __iomem *)addr) @@ -40,11 +40,9 @@ static inline uint32_t hif_read32_mb_reg_window(void *sc, (void __iomem *)addr, value) #else - #define hif_read32_mb(scn, addr) ioread32((void __iomem *)addr) #define hif_write32_mb(scn, addr, value) \ iowrite32((u32)(value), (void __iomem *)(addr)) - #endif #define Q_TARGET_ACCESS_BEGIN(scn) \ @@ -96,9 +94,14 @@ static inline uint32_t hif_read32_mb_reg_window(void *sc, #endif #ifdef HIF_SNOC #include "hif_io32_snoc.h" -#endif /* HIF_PCI */ +#endif +#ifdef HIF_IPCI +#include "hif_io32_ipci.h" +#endif + +#if defined(HIF_REG_WINDOW_SUPPORT) && (defined(HIF_PCI) || \ + defined(HIF_IPCI)) -#if defined(HIF_REG_WINDOW_SUPPORT) && defined(HIF_PCI) #include "qdf_lock.h" #include "qdf_util.h" diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.c b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.c index 10527e69743e53ab9dad808ea5fdf8a5df0991ab..45bd30103d8cbc7311b18d66fea09f6fda397d22 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 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 @@ -30,7 +30,8 @@ #include #include "hif_main.h" #include "hif_hw_version.h" -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if (defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI)) #include "ce_tasklet.h" #include "ce_api.h" #endif @@ -44,6 +45,10 @@ #include "hif_napi.h" #include "hif_unit_test_suspend_i.h" #include "qdf_module.h" +#ifdef HIF_CE_LOG_INFO +#include +#include +#endif void hif_dump(struct hif_opaque_softc *hif_ctx, uint8_t cmd_id, bool start) { @@ -77,6 +82,17 @@ void *hif_get_targetdef(struct hif_opaque_softc *hif_ctx) return scn->targetdef; } +#ifdef FORCE_WAKE +void hif_srng_init_phase(struct hif_opaque_softc *hif_ctx, + bool init_phase) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + + if (ce_srng_based(scn)) + hal_set_init_phase(scn->hal_soc, init_phase); +} +#endif /* FORCE_WAKE */ + /** * hif_vote_link_down(): unvote for link up * @@ -397,6 +413,35 @@ void *hif_get_dev_ba(struct hif_opaque_softc *hif_handle) } qdf_export_symbol(hif_get_dev_ba); +#ifdef WLAN_CE_INTERRUPT_THRESHOLD_CONFIG +/** + * hif_get_cfg_from_psoc() - Retrieve ini cfg from psoc + * @scn: hif context + * @psoc: psoc objmgr handle + * + * Return: None + */ +static inline +void hif_get_cfg_from_psoc(struct hif_softc *scn, + struct wlan_objmgr_psoc *psoc) +{ + if (psoc) { + scn->ini_cfg.ce_status_ring_timer_threshold = + cfg_get(psoc, + CFG_CE_STATUS_RING_TIMER_THRESHOLD); + scn->ini_cfg.ce_status_ring_batch_count_threshold = + cfg_get(psoc, + CFG_CE_STATUS_RING_BATCH_COUNT_THRESHOLD); + } +} +#else +static inline +void hif_get_cfg_from_psoc(struct hif_softc *scn, + struct wlan_objmgr_psoc *psoc) +{ +} +#endif /* WLAN_CE_INTERRUPT_THRESHOLD_CONFIG */ + #ifdef HIF_CPU_PERF_AFFINE_MASK /** * __hif_cpu_hotplug_notify() - CPU hotplug event handler @@ -484,20 +529,98 @@ static void hif_cpuhp_unregister(struct hif_softc *scn) } #endif /* ifdef HIF_CPU_PERF_AFFINE_MASK */ +#if defined(HIF_CE_LOG_INFO) || defined(HIF_BUS_LOG_INFO) /** - * hif_open(): hif_open - * @qdf_ctx: QDF Context - * @mode: Driver Mode - * @bus_type: Bus Type - * @cbk: CDS Callbacks + * hif_recovery_notifier_cb - Recovery notifier callback to log + * hang event data + * @block: notifier block + * @state: state + * @data: notifier data * - * API to open HIF Context + * Return: status + */ +static +int hif_recovery_notifier_cb(struct notifier_block *block, unsigned long state, + void *data) +{ + struct qdf_notifer_data *notif_data = data; + qdf_notif_block *notif_block; + struct hif_softc *hif_handle; + bool bus_id_invalid; + + if (!data || !block) + return -EINVAL; + + notif_block = qdf_container_of(block, qdf_notif_block, notif_block); + + hif_handle = notif_block->priv_data; + if (!hif_handle) + return -EINVAL; + + bus_id_invalid = hif_log_bus_info(hif_handle, notif_data->hang_data, + ¬if_data->offset); + if (bus_id_invalid) + return NOTIFY_STOP_MASK; + + hif_log_ce_info(hif_handle, notif_data->hang_data, + ¬if_data->offset); + + return 0; +} + +/** + * hif_register_recovery_notifier - Register hif recovery notifier + * @hif_handle: hif handle + * + * Return: status + */ +static +QDF_STATUS hif_register_recovery_notifier(struct hif_softc *hif_handle) +{ + qdf_notif_block *hif_notifier; + + if (!hif_handle) + return QDF_STATUS_E_FAILURE; + + hif_notifier = &hif_handle->hif_recovery_notifier; + + hif_notifier->notif_block.notifier_call = hif_recovery_notifier_cb; + hif_notifier->priv_data = hif_handle; + return qdf_hang_event_register_notifier(hif_notifier); +} + +/** + * hif_unregister_recovery_notifier - Un-register hif recovery notifier + * @hif_handle: hif handle * - * Return: HIF Opaque Pointer + * Return: status */ -struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, uint32_t mode, +static +QDF_STATUS hif_unregister_recovery_notifier(struct hif_softc *hif_handle) +{ + qdf_notif_block *hif_notifier = &hif_handle->hif_recovery_notifier; + + return qdf_hang_event_unregister_notifier(hif_notifier); +} +#else +static inline +QDF_STATUS hif_register_recovery_notifier(struct hif_softc *hif_handle) +{ + return QDF_STATUS_SUCCESS; +} + +static inline +QDF_STATUS hif_unregister_recovery_notifier(struct hif_softc *hif_handle) +{ + return QDF_STATUS_SUCCESS; +} +#endif + +struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, + uint32_t mode, enum qdf_bus_type bus_type, - struct hif_driver_state_callbacks *cbk) + struct hif_driver_state_callbacks *cbk, + struct wlan_objmgr_psoc *psoc) { struct hif_softc *scn; QDF_STATUS status = QDF_STATUS_SUCCESS; @@ -521,9 +644,14 @@ struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, uint32_t mode, qdf_atomic_init(&scn->active_grp_tasklet_cnt); qdf_atomic_init(&scn->link_suspended); qdf_atomic_init(&scn->tasklet_from_intr); + hif_system_pm_set_state_on(GET_HIF_OPAQUE_HDL(scn)); qdf_mem_copy(&scn->callbacks, cbk, sizeof(struct hif_driver_state_callbacks)); scn->bus_type = bus_type; + + hif_pm_set_link_state(GET_HIF_OPAQUE_HDL(scn), HIF_PM_LINK_STATE_DOWN); + hif_get_cfg_from_psoc(scn, psoc); + hif_set_event_hist_mask(GET_HIF_OPAQUE_HDL(scn)); status = hif_bus_open(scn, bus_type); if (status != QDF_STATUS_SUCCESS) { @@ -582,9 +710,11 @@ void hif_close(struct hif_opaque_softc *hif_ctx) } hif_uninit_rri_on_ddr(scn); + hif_cleanup_static_buf_to_target(scn); hif_cpuhp_unregister(scn); hif_bus_close(scn); + qdf_mem_free(scn); } @@ -656,12 +786,16 @@ QDF_STATUS hif_try_complete_tasks(struct hif_softc *scn) return QDF_STATUS_SUCCESS; } -#if defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \ - defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) +#if (defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \ + defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \ + defined(QCA_WIFI_QCN9000) || defined(QCA_WIFI_QCA6490) || \ + defined(QCA_WIFI_QCA6750)) static QDF_STATUS hif_hal_attach(struct hif_softc *scn) { if (ce_srng_based(scn)) { - scn->hal_soc = hal_attach(scn, scn->qdf_dev); + scn->hal_soc = hal_attach( + hif_softc_to_hif_opaque_softc(scn), + scn->qdf_dev); if (!scn->hal_soc) return QDF_STATUS_E_FAILURE; } @@ -722,6 +856,7 @@ QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev, return status; } + hif_pm_set_link_state(GET_HIF_OPAQUE_HDL(scn), HIF_PM_LINK_STATE_UP); status = hif_hal_attach(scn); if (status != QDF_STATUS_SUCCESS) { HIF_ERROR("%s: hal attach failed", __func__); @@ -735,6 +870,7 @@ QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev, } hif_ut_suspend_init(scn); + hif_register_recovery_notifier(scn); /* * Flag to avoid potential unallocated memory access from MSI @@ -764,6 +900,8 @@ void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type) if (!scn) return; + hif_unregister_recovery_notifier(scn); + hif_nointrs(scn); if (scn->hif_init_done == false) hif_shutdown_device(hif_ctx); @@ -772,6 +910,7 @@ void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type) hif_hal_detach(scn); + hif_pm_set_link_state(hif_ctx, HIF_PM_LINK_STATE_DOWN); hif_disable_bus(scn); hif_wlan_disable(scn); @@ -781,11 +920,25 @@ void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type) HIF_DBG("%s: X", __func__); } +#ifdef CE_TASKLET_DEBUG_ENABLE +void hif_enable_ce_latency_stats(struct hif_opaque_softc *hif_ctx, uint8_t val) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + + if (!scn) + return; + + scn->ce_latency_stats = val; +} +#endif + void hif_display_stats(struct hif_opaque_softc *hif_ctx) { hif_display_bus_stats(hif_ctx); } +qdf_export_symbol(hif_display_stats); + void hif_clear_stats(struct hif_opaque_softc *hif_ctx) { hif_clear_bus_stats(hif_ctx); @@ -982,9 +1135,17 @@ int hif_get_device_type(uint32_t device_id, HIF_INFO(" *********** QCA6290EMU *************\n"); break; + case QCN9000_DEVICE_ID: + *hif_type = HIF_TYPE_QCN9000; + *target_type = TARGET_TYPE_QCN9000; + HIF_INFO(" *********** QCN9000 *************\n"); + break; + case QCN7605_DEVICE_ID: case QCN7605_COMPOSITE: case QCN7605_STANDALONE: + case QCN7605_STANDALONE_V2: + case QCN7605_COMPOSITE_V2: *hif_type = HIF_TYPE_QCN7605; *target_type = TARGET_TYPE_QCN7605; HIF_INFO(" *********** QCN7605 *************\n"); @@ -997,6 +1158,20 @@ int hif_get_device_type(uint32_t device_id, HIF_INFO(" *********** QCA6390 *************\n"); break; + case QCA6490_DEVICE_ID: + case QCA6490_EMULATION_DEVICE_ID: + *hif_type = HIF_TYPE_QCA6490; + *target_type = TARGET_TYPE_QCA6490; + HIF_INFO(" *********** QCA6490 *************\n"); + break; + + case QCA6750_DEVICE_ID: + case QCA6750_EMULATION_DEVICE_ID: + *hif_type = HIF_TYPE_QCA6750; + *target_type = TARGET_TYPE_QCA6750; + HIF_INFO(" *********** QCA6750 *************\n"); + break; + case QCA8074V2_DEVICE_ID: *hif_type = HIF_TYPE_QCA8074V2; *target_type = TARGET_TYPE_QCA8074V2; @@ -1256,7 +1431,8 @@ bool hif_is_recovery_in_progress(struct hif_softc *scn) return false; } -#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) +#if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ + defined(HIF_IPCI) /** * hif_update_pipe_callback() - API to register pipe specific callbacks @@ -1323,6 +1499,64 @@ int hif_get_bandwidth_level(struct hif_opaque_softc *hif_handle) qdf_export_symbol(hif_get_bandwidth_level); +#ifdef DP_MEM_PRE_ALLOC +void *hif_mem_alloc_consistent_unaligned(struct hif_softc *scn, + qdf_size_t size, + qdf_dma_addr_t *paddr, + uint32_t ring_type, + uint8_t *is_mem_prealloc) +{ + void *vaddr = NULL; + struct hif_driver_state_callbacks *cbk = + hif_get_callbacks_handle(scn); + + *is_mem_prealloc = false; + if (cbk && cbk->prealloc_get_consistent_mem_unaligned) { + vaddr = cbk->prealloc_get_consistent_mem_unaligned(size, + paddr, + ring_type); + if (vaddr) { + *is_mem_prealloc = true; + goto end; + } + } + + vaddr = qdf_mem_alloc_consistent(scn->qdf_dev, + scn->qdf_dev->dev, + size, + paddr); +end: + dp_info("%s va_unaligned %pK pa_unaligned %pK size %d ring_type %d", + *is_mem_prealloc ? "pre-alloc" : "dynamic-alloc", vaddr, + (void *)*paddr, (int)size, ring_type); + + return vaddr; +} + +void hif_mem_free_consistent_unaligned(struct hif_softc *scn, + qdf_size_t size, + void *vaddr, + qdf_dma_addr_t paddr, + qdf_dma_context_t memctx, + uint8_t is_mem_prealloc) +{ + struct hif_driver_state_callbacks *cbk = + hif_get_callbacks_handle(scn); + + if (is_mem_prealloc) { + if (cbk && cbk->prealloc_put_consistent_mem_unaligned) { + cbk->prealloc_put_consistent_mem_unaligned(vaddr); + } else { + dp_warn("dp_prealloc_put_consistent_unligned NULL"); + QDF_BUG(0); + } + } else { + qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, + size, vaddr, paddr, memctx); + } +} +#endif + /** * hif_batch_send() - API to access hif specific function * ce_batch_send. @@ -1491,3 +1725,41 @@ void hif_set_ce_service_max_rx_ind_flush(struct hif_opaque_softc *hif, hif_ctx->ce_service_max_rx_ind_flush = ce_service_max_rx_ind_flush; } + +#ifdef SYSTEM_PM_CHECK +void __hif_system_pm_set_state(struct hif_opaque_softc *hif, + enum hif_system_pm_state state) +{ + struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); + + qdf_atomic_set(&hif_ctx->sys_pm_state, state); +} + +int32_t hif_system_pm_get_state(struct hif_opaque_softc *hif) +{ + struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); + + return qdf_atomic_read(&hif_ctx->sys_pm_state); +} + +int hif_system_pm_state_check(struct hif_opaque_softc *hif) +{ + struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); + int32_t sys_pm_state; + + if (!hif_ctx) { + hif_err("hif context is null"); + return -EFAULT; + } + + sys_pm_state = qdf_atomic_read(&hif_ctx->sys_pm_state); + if (sys_pm_state == HIF_SYSTEM_PM_STATE_BUS_SUSPENDING || + sys_pm_state == HIF_SYSTEM_PM_STATE_BUS_SUSPENDED) { + hif_info("Triggering system wakeup"); + qdf_pm_system_wakeup(); + return -EAGAIN; + } + + return 0; +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.h b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.h index eab38f9a8e0e7688e94041f08cb359f8ef076f5e..f6d5134d87d83dac08f8c569287bdcafd107bb44 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.h @@ -39,13 +39,20 @@ #include "hif.h" #include "multibus.h" #include "hif_unit_test_suspend_i.h" -#include "qdf_cpuhp.h" +#ifdef HIF_CE_LOG_INFO +#include "qdf_notifier.h" +#endif #define HIF_MIN_SLEEP_INACTIVITY_TIME_MS 50 #define HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS 60 #define HIF_MAX_BUDGET 0xFFFF +#define HIF_STATS_INC(_handle, _field, _delta) \ +{ \ + (_handle)->stats._field += _delta; \ +} + /* * This macro implementation is exposed for efficiency only. * The implementation may change and callers should @@ -81,8 +88,17 @@ #define AR6320_FW_3_2 (0x32) #define QCA6290_EMULATION_DEVICE_ID (0xabcd) #define QCA6290_DEVICE_ID (0x1100) +#define QCN9000_DEVICE_ID (0x1104) #define QCA6390_EMULATION_DEVICE_ID (0x0108) #define QCA6390_DEVICE_ID (0x1101) +/* TODO: change IDs for HastingsPrime */ +#define QCA6490_EMULATION_DEVICE_ID (0x010a) +#define QCA6490_DEVICE_ID (0x1103) + +/* TODO: change IDs for Moselle */ +#define QCA6750_EMULATION_DEVICE_ID (0x010c) +#define QCA6750_DEVICE_ID (0x1105) + #define ADRASTEA_DEVICE_ID_P2_E12 (0x7021) #define AR9887_DEVICE_ID (0x0050) #define AR900B_DEVICE_ID (0x0040) @@ -99,8 +115,10 @@ #define QCA6018_DEVICE_ID (0xfffd) /* Todo: replace this with actual number */ /* Genoa */ #define QCN7605_DEVICE_ID (0x1102) /* Genoa PCIe device ID*/ -#define QCN7605_COMPOSITE (0x9900) -#define QCN7605_STANDALONE (0x9901) +#define QCN7605_COMPOSITE (0x9901) +#define QCN7605_STANDALONE (0x9900) +#define QCN7605_STANDALONE_V2 (0x9902) +#define QCN7605_COMPOSITE_V2 (0x9903) #define RUMIM2M_DEVICE_ID_NODE0 0xabc0 #define RUMIM2M_DEVICE_ID_NODE1 0xabc1 @@ -110,6 +128,7 @@ #define RUMIM2M_DEVICE_ID_NODE5 0xaa11 #define HIF_GET_PCI_SOFTC(scn) ((struct hif_pci_softc *)scn) +#define HIF_GET_IPCI_SOFTC(scn) ((struct hif_ipci_softc *)scn) #define HIF_GET_CE_STATE(scn) ((struct HIF_CE_state *)scn) #define HIF_GET_SDIO_SOFTC(scn) ((struct hif_sdio_softc *)scn) #define HIF_GET_USB_SOFTC(scn) ((struct hif_usb_softc *)scn) @@ -138,6 +157,16 @@ struct ce_desc_hist { }; #endif /*defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)*/ +/** + * struct hif_cfg() - store ini config parameters in hif layer + * @ce_status_ring_timer_threshold: ce status ring timer threshold + * @ce_status_ring_batch_count_threshold: ce status ring batch count threshold + */ +struct hif_cfg { + uint16_t ce_status_ring_timer_threshold; + uint8_t ce_status_ring_batch_count_threshold; +}; + struct hif_softc { struct hif_opaque_softc osc; struct hif_config_info hif_config; @@ -150,6 +179,7 @@ struct hif_softc { bool hif_init_done; bool request_irq_done; bool ext_grp_irq_configured; + uint8_t ce_latency_stats; /* Packet statistics */ struct hif_ce_stats pkt_stats; enum hif_target_status target_status; @@ -171,6 +201,10 @@ struct hif_softc { atomic_t link_suspended; uint32_t *vaddr_rri_on_ddr; qdf_dma_addr_t paddr_rri_on_ddr; +#ifdef CONFIG_BYPASS_QMI + uint32_t *vaddr_qmi_bypass; + qdf_dma_addr_t paddr_qmi_bypass; +#endif int linkstate_vote; bool fastpath_mode_on; atomic_t tasklet_from_intr; @@ -192,6 +226,7 @@ struct hif_softc { struct hif_ut_suspend_context ut_suspend_ctx; uint32_t hif_attribute; int wake_irq; + int disable_wake_irq; void (*initial_wakeup_cb)(void *); void *initial_wakeup_priv; #ifdef REMOVE_PKT_LOG @@ -206,17 +241,28 @@ struct hif_softc { #if defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF) struct ce_desc_hist hif_ce_desc_hist; #endif /*defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)*/ - #ifdef IPA_OFFLOAD qdf_shared_mem_t *ipa_ce_ring; #endif + struct hif_cfg ini_cfg; #ifdef HIF_CPU_PERF_AFFINE_MASK /* The CPU hotplug event registration handle */ struct qdf_cpuhp_handler *cpuhp_event_handle; #endif +#ifdef HIF_CE_LOG_INFO + qdf_notif_block hif_recovery_notifier; +#endif +#ifdef FEATURE_RUNTIME_PM + /* Variable to track the link state change in RTPM */ + qdf_atomic_t pm_link_state; +#endif +#ifdef SYSTEM_PM_CHECK + qdf_atomic_t sys_pm_state; +#endif }; -static inline void *hif_get_hal_handle(void *hif_hdl) +static inline +void *hif_get_hal_handle(struct hif_opaque_softc *hif_hdl) { struct hif_softc *sc = (struct hif_softc *)hif_hdl; @@ -331,6 +377,47 @@ void hif_wlan_disable(struct hif_softc *scn); int hif_target_sleep_state_adjust(struct hif_softc *scn, bool sleep_ok, bool wait_for_it); + +#ifdef DP_MEM_PRE_ALLOC +void *hif_mem_alloc_consistent_unaligned(struct hif_softc *scn, + qdf_size_t size, + qdf_dma_addr_t *paddr, + uint32_t ring_type, + uint8_t *is_mem_prealloc); + +void hif_mem_free_consistent_unaligned(struct hif_softc *scn, + qdf_size_t size, + void *vaddr, + qdf_dma_addr_t paddr, + qdf_dma_context_t memctx, + uint8_t is_mem_prealloc); +#else +static inline +void *hif_mem_alloc_consistent_unaligned(struct hif_softc *scn, + qdf_size_t size, + qdf_dma_addr_t *paddr, + uint32_t ring_type, + uint8_t *is_mem_prealloc) +{ + return qdf_mem_alloc_consistent(scn->qdf_dev, + scn->qdf_dev->dev, + size, + paddr); +} + +static inline +void hif_mem_free_consistent_unaligned(struct hif_softc *scn, + qdf_size_t size, + void *vaddr, + qdf_dma_addr_t paddr, + qdf_dma_context_t memctx, + uint8_t is_mem_prealloc) +{ + return qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, + size, vaddr, paddr, memctx); +} +#endif + /** * hif_get_rx_ctx_id() - Returns NAPI instance ID based on CE ID * @ctx_id: Rx CE context ID @@ -373,4 +460,5 @@ void hif_uninit_rri_on_ddr(struct hif_softc *scn); static inline void hif_uninit_rri_on_ddr(struct hif_softc *scn) {} #endif +void hif_cleanup_static_buf_to_target(struct hif_softc *scn); #endif /* __HIF_MAIN_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_napi.h b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_napi.h index 0d164f155f7dd5145a5d5d61f8c9b9058e45e4ac..23084c001456d2fb94782051baaaddca34a07e33 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_napi.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_napi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2019 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 @@ -237,6 +237,10 @@ static inline struct qca_napi_data *hif_napi_get_all( struct hif_opaque_softc *hif) { return NULL; } +static inline struct qca_napi_info *hif_get_napi(int napi_id, + struct qca_napi_data *napid) +{ return NULL; } + static inline int hif_napi_event(struct hif_opaque_softc *hif, enum qca_napi_event event, void *data) diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ipcie/hif_io32_ipci.h b/drivers/staging/qca-wifi-host-cmn/hif/src/ipcie/hif_io32_ipci.h new file mode 100644 index 0000000000000000000000000000000000000000..d5fcb89c7a7de68690babdcc29e2419c08f80dd9 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ipcie/hif_io32_ipci.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020 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 above + * copyright notice and this permission notice appear in all copies. + + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __HIF_IO32_IPCI_H__ +#define __HIF_IO32_IPCI_H__ + +#ifdef HIF_IPCI + +#include "hif_main.h" +#include "regtable.h" +#include "ce_reg.h" +#include "qdf_atomic.h" +#include "if_ipci.h" +/* + * For maximum performance and no power management, set this to 1. + * For power management at the cost of performance, set this to 0. + */ +#ifndef CONFIG_ATH_IPCIE_MAX_PERF +#define CONFIG_ATH_IPCIE_MAX_PERF 0 +#endif + +/* + * PCIE_ACCESS_LOG_NUM specifies the number of + * read/write records to store + */ +#ifdef CONFIG_ATH_IPCIE_ACCESS_DEBUG +#define IPCIE_ACCESS_LOG_NUM 500 +#endif + +/* 64-bit MSI support */ +#define CONFIG_IPCIE_64BIT_MSI 0 + +/* AXI gating when L1, L2 to reduce power consumption */ +#define CONFIG_IPCIE_ENABLE_AXI_CLK_GATE 0 + +irqreturn_t hif_fw_interrupt_handler(int irq, void *arg); +#endif /* HIF_IPCI */ +#endif /* __HIF_IO32_IPCI_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ipcie/if_ipci.c b/drivers/staging/qca-wifi-host-cmn/hif/src/ipcie/if_ipci.c new file mode 100644 index 0000000000000000000000000000000000000000..4f52c7fab3b36fe288eefb738495c592fe708e24 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ipcie/if_ipci.c @@ -0,0 +1,792 @@ +/* + * Copyright (c) 2013-2020 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 above + * copyright notice and this permission notice appear in all copies. + + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#ifdef CONFIG_PCI_MSM +#include +#endif +#include "hif_io32.h" +#include "if_ipci.h" +#include "hif.h" +#include "target_type.h" +#include "hif_main.h" +#include "ce_main.h" +#include "ce_api.h" +#include "ce_internal.h" +#include "ce_reg.h" +#include "ce_bmi.h" +#include "regtable.h" +#include "hif_hw_version.h" +#include +#include +#include "qdf_status.h" +#include "qdf_atomic.h" +#include "pld_common.h" +#include "mp_dev.h" +#include "hif_debug.h" + +#include "ce_tasklet.h" +#include "targaddrs.h" +#include "hif_exec.h" + +#include "ipci_api.h" + +void hif_ipci_enable_power_management(struct hif_softc *hif_sc, + bool is_packet_log_enabled) +{ +} + +void hif_ipci_disable_power_management(struct hif_softc *hif_ctx) +{ +} + +void hif_ipci_display_stats(struct hif_softc *hif_ctx) +{ + hif_display_ce_stats(hif_ctx); +} + +void hif_ipci_clear_stats(struct hif_softc *hif_ctx) +{ + struct hif_ipci_softc *ipci_ctx = HIF_GET_IPCI_SOFTC(hif_ctx); + + if (!ipci_ctx) { + HIF_ERROR("%s, hif_ctx null", __func__); + return; + } + hif_clear_ce_stats(&ipci_ctx->ce_sc); +} + +QDF_STATUS hif_ipci_open(struct hif_softc *hif_ctx, enum qdf_bus_type bus_type) +{ + struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(hif_ctx); + + hif_ctx->bus_type = bus_type; + + qdf_spinlock_create(&sc->irq_lock); + + return hif_ce_open(hif_ctx); +} + +int hif_ipci_bus_configure(struct hif_softc *hif_sc) +{ + int status = 0; + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_sc); + + hif_ce_prepare_config(hif_sc); + + /* initialize sleep state adjust variables */ + hif_state->sleep_timer_init = true; + hif_state->keep_awake_count = 0; + hif_state->fake_sleep = false; + hif_state->sleep_ticks = 0; + + status = hif_wlan_enable(hif_sc); + if (status) { + HIF_ERROR("%s: hif_wlan_enable error = %d", + __func__, status); + goto timer_free; + } + + A_TARGET_ACCESS_LIKELY(hif_sc); + + status = hif_config_ce(hif_sc); + if (status) + goto disable_wlan; + + status = hif_configure_irq(hif_sc); + if (status < 0) + goto unconfig_ce; + + A_TARGET_ACCESS_UNLIKELY(hif_sc); + + return status; + +unconfig_ce: + hif_unconfig_ce(hif_sc); +disable_wlan: + A_TARGET_ACCESS_UNLIKELY(hif_sc); + hif_wlan_disable(hif_sc); + +timer_free: + qdf_timer_stop(&hif_state->sleep_timer); + qdf_timer_free(&hif_state->sleep_timer); + hif_state->sleep_timer_init = false; + + HIF_ERROR("%s: failed, status = %d", __func__, status); + return status; +} + +void hif_ipci_close(struct hif_softc *hif_sc) +{ + hif_ce_close(hif_sc); +} + +/** + * hif_ce_srng_msi_free_irq(): free CE msi IRQ + * @scn: struct hif_softc + * + * Return: ErrorNo + */ +static int hif_ce_srng_msi_free_irq(struct hif_softc *scn) +{ + int ret; + int ce_id, irq; + uint32_t msi_data_start; + uint32_t msi_data_count; + uint32_t msi_irq_start; + struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn); + + ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE", + &msi_data_count, &msi_data_start, + &msi_irq_start); + if (ret) + return ret; + + /* needs to match the ce_id -> irq data mapping + * used in the srng parameter configuration + */ + for (ce_id = 0; ce_id < scn->ce_count; ce_id++) { + unsigned int msi_data; + + if (!ce_sc->tasklets[ce_id].inited) + continue; + + msi_data = (ce_id % msi_data_count) + msi_irq_start; + irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data); + + hif_debug("%s: (ce_id %d, msi_data %d, irq %d)", __func__, + ce_id, msi_data, irq); + + free_irq(irq, &ce_sc->tasklets[ce_id]); + } + + return ret; +} + +/** + * hif_ipci_deconfigure_grp_irq(): deconfigure HW block IRQ + * @scn: struct hif_softc + * + * Return: none + */ +void hif_ipci_deconfigure_grp_irq(struct hif_softc *scn) +{ + int i, j, irq; + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct hif_exec_context *hif_ext_group; + + for (i = 0; i < hif_state->hif_num_extgroup; i++) { + hif_ext_group = hif_state->hif_ext_group[i]; + if (hif_ext_group->irq_requested) { + hif_ext_group->irq_requested = false; + for (j = 0; j < hif_ext_group->numirq; j++) { + irq = hif_ext_group->os_irq[j]; + free_irq(irq, hif_ext_group); + } + hif_ext_group->numirq = 0; + } + } +} + +void hif_ipci_nointrs(struct hif_softc *scn) +{ + int ret; + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + + ce_unregister_irq(hif_state, CE_ALL_BITMAP); + + if (scn->request_irq_done == false) + return; + + hif_ipci_deconfigure_grp_irq(scn); + + ret = hif_ce_srng_msi_free_irq(scn); + if (ret != -EINVAL) { + /* ce irqs freed in hif_ce_srng_msi_free_irq */ + + if (scn->wake_irq) + free_irq(scn->wake_irq, scn); + scn->wake_irq = 0; + } + + scn->request_irq_done = false; +} + +void hif_ipci_disable_bus(struct hif_softc *scn) +{ + struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn); + void __iomem *mem; + + /* Attach did not succeed, all resources have been + * freed in error handler + */ + if (!sc) + return; + + mem = (void __iomem *)sc->mem; + if (mem) { + hif_dump_pipe_debug_count(scn); + if (scn->athdiag_procfs_inited) { + athdiag_procfs_remove(); + scn->athdiag_procfs_inited = false; + } + scn->mem = NULL; + } + HIF_INFO("%s: X", __func__); +} + +#if defined(CONFIG_PCI_MSM) +void hif_ipci_prevent_linkdown(struct hif_softc *scn, bool flag) +{ + int errno; + + HIF_INFO("wlan: %s pcie power collapse", flag ? "disable" : "enable"); + + errno = pld_wlan_pm_control(scn->qdf_dev->dev, flag); + if (errno) + HIF_ERROR("%s: Failed pld_wlan_pm_control; errno %d", + __func__, errno); +} +#else +void hif_ipci_prevent_linkdown(struct hif_softc *scn, bool flag) +{ + HIF_INFO("wlan: %s pcie power collapse", (flag ? "disable" : "enable")); +} +#endif + +int hif_ipci_bus_suspend(struct hif_softc *scn) +{ + QDF_STATUS ret; + + hif_apps_irqs_disable(GET_HIF_OPAQUE_HDL(scn)); + + ret = hif_try_complete_tasks(scn); + if (QDF_IS_STATUS_ERROR(ret)) { + hif_apps_irqs_enable(GET_HIF_OPAQUE_HDL(scn)); + return -EBUSY; + } + + return 0; +} + +int hif_ipci_bus_resume(struct hif_softc *scn) +{ + hif_apps_irqs_enable(GET_HIF_OPAQUE_HDL(scn)); + + return 0; +} + +int hif_ipci_bus_suspend_noirq(struct hif_softc *scn) +{ + if (hif_can_suspend_link(GET_HIF_OPAQUE_HDL(scn))) + qdf_atomic_set(&scn->link_suspended, 1); + + hif_apps_wake_irq_enable(GET_HIF_OPAQUE_HDL(scn)); + + return 0; +} + +int hif_ipci_bus_resume_noirq(struct hif_softc *scn) +{ + hif_apps_wake_irq_disable(GET_HIF_OPAQUE_HDL(scn)); + + if (hif_can_suspend_link(GET_HIF_OPAQUE_HDL(scn))) + qdf_atomic_set(&scn->link_suspended, 0); + + return 0; +} + +void hif_ipci_disable_isr(struct hif_softc *scn) +{ + struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn); + + hif_exec_kill(&scn->osc); + hif_nointrs(scn); + /* Cancel the pending tasklet */ + ce_tasklet_kill(scn); + tasklet_kill(&sc->intr_tq); + qdf_atomic_set(&scn->active_tasklet_cnt, 0); + qdf_atomic_set(&scn->active_grp_tasklet_cnt, 0); +} + +int hif_ipci_dump_registers(struct hif_softc *hif_ctx) +{ + int status; + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + + status = hif_dump_ce_registers(scn); + + if (status) + HIF_ERROR("%s: Dump CE Registers Failed", __func__); + + return 0; +} + +/** + * hif_ce_interrupt_handler() - interrupt handler for copy engine + * @irq: irq number + * @context: tasklet context + * + * Return: irqreturn_t + */ +static irqreturn_t hif_ce_interrupt_handler(int irq, void *context) +{ + struct ce_tasklet_entry *tasklet_entry = context; + + return ce_dispatch_interrupt(tasklet_entry->ce_id, tasklet_entry); +} + +extern const char *ce_name[]; + +/** + * hif_ce_msi_map_ce_to_irq() - map CE to IRQ + * @scn: hif context + * @ce_id: CE Id + * + * Return: IRQ number + */ +static int hif_ce_msi_map_ce_to_irq(struct hif_softc *scn, int ce_id) +{ + struct hif_ipci_softc *ipci_scn = HIF_GET_IPCI_SOFTC(scn); + + return ipci_scn->ce_msi_irq_num[ce_id]; +} + +/* hif_ce_srng_msi_irq_disable() - disable the irq for msi + * @hif_sc: hif context + * @ce_id: which ce to disable copy complete interrupts for + * + * @Return: none + */ +static void hif_ce_srng_msi_irq_disable(struct hif_softc *hif_sc, int ce_id) +{ + disable_irq_nosync(hif_ce_msi_map_ce_to_irq(hif_sc, ce_id)); +} + +/* hif_ce_srng_msi_irq_enable() - enable the irq for msi + * @hif_sc: hif context + * @ce_id: which ce to enable copy complete interrupts for + * + * @Return: none + */ +static void hif_ce_srng_msi_irq_enable(struct hif_softc *hif_sc, int ce_id) +{ + enable_irq(hif_ce_msi_map_ce_to_irq(hif_sc, ce_id)); +} + +/* hif_ce_msi_configure_irq() - configure the irq + * @scn: hif context + * + * @Return: none + */ +static int hif_ce_msi_configure_irq(struct hif_softc *scn) +{ + int ret; + int ce_id, irq; + uint32_t msi_data_start; + uint32_t msi_data_count; + uint32_t msi_irq_start; + struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn); + struct hif_ipci_softc *ipci_sc = HIF_GET_IPCI_SOFTC(scn); + + /* do wake irq assignment */ + ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "WAKE", + &msi_data_count, &msi_data_start, + &msi_irq_start); + if (ret) + return ret; + + scn->wake_irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_irq_start); + ret = request_irq(scn->wake_irq, hif_wake_interrupt_handler, + IRQF_NO_SUSPEND, "wlan_wake_irq", scn); + if (ret) + return ret; + + /* do ce irq assignments */ + ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE", + &msi_data_count, &msi_data_start, + &msi_irq_start); + if (ret) + goto free_wake_irq; + + scn->bus_ops.hif_irq_disable = &hif_ce_srng_msi_irq_disable; + scn->bus_ops.hif_irq_enable = &hif_ce_srng_msi_irq_enable; + scn->bus_ops.hif_map_ce_to_irq = &hif_ce_msi_map_ce_to_irq; + + /* needs to match the ce_id -> irq data mapping + * used in the srng parameter configuration + */ + for (ce_id = 0; ce_id < scn->ce_count; ce_id++) { + unsigned int msi_data = (ce_id % msi_data_count) + + msi_irq_start; + irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data); + HIF_DBG("%s: (ce_id %d, msi_data %d, irq %d tasklet %pK)", + __func__, ce_id, msi_data, irq, + &ce_sc->tasklets[ce_id]); + + /* implies the ce is also initialized */ + if (!ce_sc->tasklets[ce_id].inited) + continue; + + ipci_sc->ce_msi_irq_num[ce_id] = irq; + ret = request_irq(irq, hif_ce_interrupt_handler, + IRQF_SHARED, + ce_name[ce_id], + &ce_sc->tasklets[ce_id]); + if (ret) + goto free_irq; + } + + return ret; + +free_irq: + /* the request_irq for the last ce_id failed so skip it. */ + while (ce_id > 0 && ce_id < scn->ce_count) { + unsigned int msi_data; + + ce_id--; + msi_data = (ce_id % msi_data_count) + msi_irq_start; + irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data); + free_irq(irq, &ce_sc->tasklets[ce_id]); + } + +free_wake_irq: + free_irq(scn->wake_irq, scn->qdf_dev->dev); + scn->wake_irq = 0; + + return ret; +} + +/** + * hif_exec_grp_irq_disable() - disable the irq for group + * @hif_ext_group: hif exec context + * + * Return: none + */ +static void hif_exec_grp_irq_disable(struct hif_exec_context *hif_ext_group) +{ + int i; + + for (i = 0; i < hif_ext_group->numirq; i++) + disable_irq_nosync(hif_ext_group->os_irq[i]); +} + +/** + * hif_exec_grp_irq_enable() - enable the irq for group + * @hif_ext_group: hif exec context + * + * Return: none + */ +static void hif_exec_grp_irq_enable(struct hif_exec_context *hif_ext_group) +{ + int i; + + for (i = 0; i < hif_ext_group->numirq; i++) + enable_irq(hif_ext_group->os_irq[i]); +} + +const char *hif_ipci_get_irq_name(int irq_no) +{ + return "pci-dummy"; +} + +int hif_ipci_configure_grp_irq(struct hif_softc *scn, + struct hif_exec_context *hif_ext_group) +{ + int ret = 0; + int irq = 0; + int j; + + hif_ext_group->irq_enable = &hif_exec_grp_irq_enable; + hif_ext_group->irq_disable = &hif_exec_grp_irq_disable; + hif_ext_group->irq_name = &hif_ipci_get_irq_name; + hif_ext_group->work_complete = &hif_dummy_grp_done; + + for (j = 0; j < hif_ext_group->numirq; j++) { + irq = hif_ext_group->irq[j]; + + hif_info("request_irq = %d for grp %d", + irq, hif_ext_group->grp_id); + ret = request_irq(irq, + hif_ext_group_interrupt_handler, + IRQF_SHARED | IRQF_NO_SUSPEND, + "wlan_EXT_GRP", + hif_ext_group); + if (ret) { + HIF_ERROR("%s: request_irq failed ret = %d", + __func__, ret); + return -EFAULT; + } + hif_ext_group->os_irq[j] = irq; + } + hif_ext_group->irq_requested = true; + return 0; +} + +int hif_configure_irq(struct hif_softc *scn) +{ + int ret = 0; + + HIF_TRACE("%s: E", __func__); + + if (hif_is_polled_mode_enabled(GET_HIF_OPAQUE_HDL(scn))) { + scn->request_irq_done = false; + return 0; + } + + ret = hif_ce_msi_configure_irq(scn); + if (ret == 0) + goto end; + + if (ret < 0) { + HIF_ERROR("%s: hif_ipci_configure_irq error = %d", + __func__, ret); + return ret; + } +end: + scn->request_irq_done = true; + return 0; +} + +/** + * hif_ipci_get_soc_info_pld() - get soc info for ipcie bus from pld target + * @sc: ipci context + * @dev: device structure + * + * Return: none + */ +static void hif_ipci_get_soc_info_pld(struct hif_ipci_softc *sc, + struct device *dev) +{ + struct pld_soc_info info; + + pld_get_soc_info(dev, &info); + sc->mem = info.v_addr; + sc->ce_sc.ol_sc.mem = info.v_addr; + sc->ce_sc.ol_sc.mem_pa = info.p_addr; +} + +/** + * hif_ipci_get_soc_info_nopld() - get soc info for ipcie bus for non pld target + * @sc: ipci context + * @dev: device structure + * + * Return: none + */ +static void hif_ipci_get_soc_info_nopld(struct hif_ipci_softc *sc, + struct device *dev) +{} + +/** + * hif_is_pld_based_target() - verify if the target is pld based + * @sc: ipci context + * @device_id: device id + * + * Return: none + */ +static bool hif_is_pld_based_target(struct hif_ipci_softc *sc, + int device_id) +{ + if (!pld_have_platform_driver_support(sc->dev)) + return false; + + switch (device_id) { +#ifdef QCA_WIFI_QCA6750 + case QCA6750_DEVICE_ID: +#endif + return true; + } + return false; +} + +/** + * hif_ipci_init_deinit_ops_attach() - attach ops for ipci + * @sc: ipci context + * @device_id: device id + * + * Return: none + */ +static void hif_ipci_init_deinit_ops_attach(struct hif_ipci_softc *sc, + int device_id) +{ + if (hif_is_pld_based_target(sc, device_id)) + sc->hif_ipci_get_soc_info = hif_ipci_get_soc_info_pld; + else + sc->hif_ipci_get_soc_info = hif_ipci_get_soc_info_nopld; +} + +QDF_STATUS hif_ipci_enable_bus(struct hif_softc *ol_sc, + struct device *dev, void *bdev, + const struct hif_bus_id *bid, + enum hif_enable_type type) +{ + int ret = 0; + uint32_t hif_type, target_type; + struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(ol_sc); + struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(ol_sc); + uint16_t revision_id = 0; + struct pci_dev *pdev = bdev; + struct hif_target_info *tgt_info; + int device_id = QCA6750_DEVICE_ID; + + if (!ol_sc) { + HIF_ERROR("%s: hif_ctx is NULL", __func__); + return QDF_STATUS_E_NOMEM; + } + + sc->dev = dev; + tgt_info = hif_get_target_info_handle(hif_hdl); + hif_ipci_init_deinit_ops_attach(sc, device_id); + sc->hif_ipci_get_soc_info(sc, dev); + HIF_TRACE("%s: hif_enable_pci done", __func__); + + device_disable_async_suspend(&pdev->dev); + + ret = hif_get_device_type(device_id, revision_id, + &hif_type, &target_type); + if (ret < 0) { + HIF_ERROR("%s: invalid device id/revision_id", __func__); + return QDF_STATUS_E_ABORTED; + } + HIF_TRACE("%s: hif_type = 0x%x, target_type = 0x%x", + __func__, hif_type, target_type); + + hif_register_tbl_attach(ol_sc, hif_type); + hif_target_register_tbl_attach(ol_sc, target_type); + sc->use_register_windowing = false; + tgt_info->target_type = target_type; + + if (!ol_sc->mem_pa) { + HIF_ERROR("%s: ERROR - BAR0 uninitialized", __func__); + ret = -EIO; + return QDF_STATUS_E_ABORTED; + } + + return 0; +} + +bool hif_ipci_needs_bmi(struct hif_softc *scn) +{ + return !ce_srng_based(scn); +} + +#ifdef FORCE_WAKE +int hif_force_wake_request(struct hif_opaque_softc *hif_handle) +{ + uint32_t timeout = 0, value; + struct hif_softc *scn = (struct hif_softc *)hif_handle; + struct hif_ipci_softc *ipci_scn = HIF_GET_IPCI_SOFTC(scn); + + if (pld_force_wake_request(scn->qdf_dev->dev)) { + hif_err("force wake request send failed"); + return -EINVAL; + } + + HIF_STATS_INC(ipci_scn, mhi_force_wake_request_vote, 1); + while (!pld_is_device_awake(scn->qdf_dev->dev) && + timeout <= FORCE_WAKE_DELAY_TIMEOUT_MS) { + qdf_mdelay(FORCE_WAKE_DELAY_MS); + timeout += FORCE_WAKE_DELAY_MS; + } + + if (pld_is_device_awake(scn->qdf_dev->dev) <= 0) { + hif_err("Unable to wake up mhi"); + HIF_STATS_INC(ipci_scn, mhi_force_wake_failure, 1); + return -EINVAL; + } + HIF_STATS_INC(ipci_scn, mhi_force_wake_success, 1); + hif_write32_mb(scn, + scn->mem + + PCIE_SOC_PCIE_REG_PCIE_SCRATCH_0_SOC_PCIE_REG, + 0); + hif_write32_mb(scn, + scn->mem + + PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG, + 1); + + HIF_STATS_INC(ipci_scn, soc_force_wake_register_write_success, 1); + /* + * do not reset the timeout + * total_wake_time = MHI_WAKE_TIME + PCI_WAKE_TIME < 50 ms + */ + do { + value = + hif_read32_mb(scn, + scn->mem + + PCIE_SOC_PCIE_REG_PCIE_SCRATCH_0_SOC_PCIE_REG); + if (value) + break; + qdf_mdelay(FORCE_WAKE_DELAY_MS); + timeout += FORCE_WAKE_DELAY_MS; + } while (timeout <= FORCE_WAKE_DELAY_TIMEOUT_MS); + + if (!value) { + hif_err("failed handshake mechanism"); + HIF_STATS_INC(ipci_scn, soc_force_wake_failure, 1); + return -ETIMEDOUT; + } + + HIF_STATS_INC(ipci_scn, soc_force_wake_success, 1); + + return 0; +} + +int hif_force_wake_release(struct hif_opaque_softc *hif_handle) +{ + int ret; + struct hif_softc *scn = (struct hif_softc *)hif_handle; + struct hif_ipci_softc *ipci_scn = HIF_GET_IPCI_SOFTC(scn); + + ret = pld_force_wake_release(scn->qdf_dev->dev); + if (ret) { + hif_err("force wake release failure"); + HIF_STATS_INC(ipci_scn, mhi_force_wake_release_failure, 1); + return ret; + } + + HIF_STATS_INC(ipci_scn, mhi_force_wake_release_success, 1); + hif_write32_mb(scn, + scn->mem + + PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG, + 0); + HIF_STATS_INC(ipci_scn, soc_force_wake_release_success, 1); + return 0; +} + +void hif_print_ipci_stats(struct hif_ipci_softc *ipci_handle) +{ + hif_debug("mhi_force_wake_request_vote: %d", + ipci_handle->stats.mhi_force_wake_request_vote); + hif_debug("mhi_force_wake_failure: %d", + ipci_handle->stats.mhi_force_wake_failure); + hif_debug("mhi_force_wake_success: %d", + ipci_handle->stats.mhi_force_wake_success); + hif_debug("soc_force_wake_register_write_success: %d", + ipci_handle->stats.soc_force_wake_register_write_success); + hif_debug("soc_force_wake_failure: %d", + ipci_handle->stats.soc_force_wake_failure); + hif_debug("soc_force_wake_success: %d", + ipci_handle->stats.soc_force_wake_success); + hif_debug("mhi_force_wake_release_failure: %d", + ipci_handle->stats.mhi_force_wake_release_failure); + hif_debug("mhi_force_wake_release_success: %d", + ipci_handle->stats.mhi_force_wake_release_success); + hif_debug("oc_force_wake_release_success: %d", + ipci_handle->stats.soc_force_wake_release_success); +} +#endif /* FORCE_WAKE */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/ipcie/if_ipci.h b/drivers/staging/qca-wifi-host-cmn/hif/src/ipcie/if_ipci.h new file mode 100644 index 0000000000000000000000000000000000000000..b7464b5beb78af63a89ffb7dfd84bd4d2caa7d09 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/ipcie/if_ipci.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2020 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 above + * copyright notice and this permission notice appear in all copies. + + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __ATH_IPCI_H__ +#define __ATH_IPCI_H__ + +#include +#include +#include + +#define ATH_DBG_DEFAULT 0 +#define DRAM_SIZE 0x000a8000 +#include "hif.h" +#include "cepci.h" +#include "ce_main.h" + +#ifdef FORCE_WAKE +/** + * struct hif_pci_stats - Account for hif pci based statistics + * @mhi_force_wake_request_vote: vote for mhi + * @mhi_force_wake_failure: mhi force wake failure + * @mhi_force_wake_success: mhi force wake success + * @soc_force_wake_register_write_success: write to soc wake + * @soc_force_wake_failure: soc force wake failure + * @soc_force_wake_success: soc force wake success + * @mhi_force_wake_release_success: mhi force wake release success + * @soc_force_wake_release_success: soc force wake release + */ +struct hif_ipci_stats { + uint32_t mhi_force_wake_request_vote; + uint32_t mhi_force_wake_failure; + uint32_t mhi_force_wake_success; + uint32_t soc_force_wake_register_write_success; + uint32_t soc_force_wake_failure; + uint32_t soc_force_wake_success; + uint32_t mhi_force_wake_release_failure; + uint32_t mhi_force_wake_release_success; + uint32_t soc_force_wake_release_success; +}; + +/* Register to wake the UMAC from power collapse */ +#define PCIE_SOC_PCIE_REG_PCIE_SCRATCH_0_SOC_PCIE_REG (0x01E04000 + 0x40) +/* Register used for handshake mechanism to validate UMAC is awake */ +#define PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG (0x01E00000 + 0x3004) +/* Timeout duration to validate UMAC wake status */ +#ifdef HAL_CONFIG_SLUB_DEBUG_ON +#define FORCE_WAKE_DELAY_TIMEOUT_MS 500 +#else +#define FORCE_WAKE_DELAY_TIMEOUT_MS 50 +#endif /* HAL_CONFIG_SLUB_DEBUG_ON */ +/* Validate UMAC status every 5ms */ +#define FORCE_WAKE_DELAY_MS 5 +#endif /* FORCE_WAKE */ + +struct hif_ipci_softc { + struct HIF_CE_state ce_sc; + void __iomem *mem; /* PCI address. */ + + struct device *dev; /* For efficiency, should be first in struct */ + struct tasklet_struct intr_tq; /* tasklet */ + int ce_msi_irq_num[CE_COUNT_MAX]; + bool use_register_windowing; + uint32_t register_window; + qdf_spinlock_t register_access_lock; + qdf_spinlock_t irq_lock; + + void (*hif_ipci_get_soc_info)(struct hif_ipci_softc *sc, + struct device *dev); +#ifdef FORCE_WAKE + struct hif_ipci_stats stats; +#endif +}; + +int hif_configure_irq(struct hif_softc *sc); + +/* + * There may be some pending tx frames during platform suspend. + * Suspend operation should be delayed until those tx frames are + * transferred from the host to target. This macro specifies how + * long suspend thread has to sleep before checking pending tx + * frame count. + */ +#define OL_ATH_TX_DRAIN_WAIT_DELAY 50 /* ms */ + +#ifdef FORCE_WAKE +/** + * hif_print_ipci_stats() - Display HIF IPCI stats + * @ipci_scn - HIF ipci handle + * + * Return: None + */ +void hif_print_ipci_stats(struct hif_ipci_softc *ipci_scn); +#else +static inline +void hif_print_ipci_stats(struct hif_ipci_softc *ipci_scn) +{ +} +#endif /* FORCE_WAKE */ + +#endif /* __IATH_PCI_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/pcie/if_pci.c b/drivers/staging/qca-wifi-host-cmn/hif/src/pcie/if_pci.c index b32293ec6c5a7c8074e5d4c2a8ca80461f6d8c99..76d167684e6821799193ee1772d9afa03d5daa0a 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/pcie/if_pci.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/pcie/if_pci.c @@ -50,6 +50,7 @@ #include "pci_api.h" #include "ahb_api.h" +#include "qdf_hang_event_notifier.h" #include "qdf_platform.h" /* Maximum ms timeout for host to wake up target */ @@ -881,7 +882,7 @@ void wlan_tasklet(unsigned long data) goto end; if (!ADRASTEA_BU) { - (irqreturn_t) hif_fw_interrupt_handler(sc->irq_event, scn); + hif_fw_interrupt_handler(sc->irq_event, scn); if (scn->target_status == TARGET_STATUS_RESET) goto end; } @@ -993,7 +994,7 @@ static void hif_pci_runtime_pm_warn(struct hif_pci_softc *sc, const char *msg) return; } - QDF_DEBUG_PANIC("hif_pci_runtime_pm_warn"); + QDF_ASSERT(0); } /** @@ -1479,7 +1480,9 @@ void hif_pci_display_stats(struct hif_softc *hif_ctx) HIF_ERROR("%s, hif_ctx null", __func__); return; } - hif_display_ce_stats(&pci_ctx->ce_sc); + hif_display_ce_stats(hif_ctx); + + hif_print_pci_stats(pci_ctx); } void hif_pci_clear_stats(struct hif_softc *hif_ctx) @@ -1577,10 +1580,11 @@ static void hif_sleep_entry(void *arg) return; qdf_spin_lock_irqsave(&hif_state->keep_awake_lock); - if (hif_state->verified_awake == false) { + if (hif_state->fake_sleep) { idle_ms = qdf_system_ticks_to_msecs(qdf_system_ticks() - hif_state->sleep_ticks); - if (idle_ms >= HIF_MIN_SLEEP_INACTIVITY_TIME_MS) { + if (!hif_state->verified_awake && + idle_ms >= HIF_MIN_SLEEP_INACTIVITY_TIME_MS) { if (!qdf_atomic_read(&scn->link_suspended)) { soc_wake_reset(scn); hif_state->fake_sleep = false; @@ -1588,12 +1592,8 @@ static void hif_sleep_entry(void *arg) } else { qdf_timer_stop(&hif_state->sleep_timer); qdf_timer_start(&hif_state->sleep_timer, - HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS); - } - } else { - qdf_timer_stop(&hif_state->sleep_timer); - qdf_timer_start(&hif_state->sleep_timer, HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS); + } } qdf_spin_unlock_irqrestore(&hif_state->keep_awake_lock); } @@ -2098,7 +2098,6 @@ int hif_pci_bus_configure(struct hif_softc *hif_sc) if (status) goto disable_wlan; - /* QCA_WIFI_QCA8074_VP:Should not be executed on 8074 VP platform */ if (hif_needs_bmi(hif_osc)) { status = hif_set_hia(hif_sc); if (status) @@ -2429,6 +2428,7 @@ static int hif_ce_srng_msi_free_irq(struct hif_softc *scn) uint32_t msi_data_count; uint32_t msi_irq_start; struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn); + struct CE_attr *host_ce_conf = ce_sc->host_ce_config; ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE", &msi_data_count, &msi_data_start, @@ -2442,12 +2442,17 @@ static int hif_ce_srng_msi_free_irq(struct hif_softc *scn) for (ce_id = 0; ce_id < scn->ce_count; ce_id++) { unsigned int msi_data; + if (host_ce_conf[ce_id].flags & CE_ATTR_DISABLE_INTR) + continue; + if (!ce_sc->tasklets[ce_id].inited) continue; msi_data = (ce_id % msi_data_count) + msi_irq_start; irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data); + hif_pci_ce_irq_remove_affinity_hint(irq); + hif_debug("%s: (ce_id %d, msi_data %d, irq %d)", __func__, ce_id, msi_data, irq); @@ -2457,7 +2462,7 @@ static int hif_ce_srng_msi_free_irq(struct hif_softc *scn) return ret; } -static void hif_pci_deconfigure_grp_irq(struct hif_softc *scn) +void hif_pci_deconfigure_grp_irq(struct hif_softc *scn) { int i, j, irq; struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); @@ -2477,6 +2482,41 @@ static void hif_pci_deconfigure_grp_irq(struct hif_softc *scn) } } +#ifdef HIF_BUS_LOG_INFO +bool hif_log_pcie_info(struct hif_softc *scn, uint8_t *data, + unsigned int *offset) +{ + struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn); + struct hang_event_bus_info info = {0}; + size_t size; + + if (!sc) { + hif_err("HIF Bus Context is Invalid"); + return false; + } + + pfrm_read_config_word(sc->pdev, PCI_DEVICE_ID, &info.dev_id); + + size = sizeof(info); + QDF_HANG_EVT_SET_HDR(&info.tlv_header, HANG_EVT_TAG_BUS_INFO, + size - QDF_HANG_EVENT_TLV_HDR_SIZE); + + if (*offset + size > QDF_WLAN_HANG_FW_OFFSET) + return false; + + qdf_mem_copy(data + *offset, &info, size); + *offset = *offset + size; + + if (info.dev_id == sc->devid) + return false; + + qdf_recovery_reason_update(QCA_HANG_BUS_FAILURE); + qdf_get_bus_reg_dump(scn->qdf_dev->dev, data, + (QDF_WLAN_HANG_FW_OFFSET - size)); + return true; +} +#endif + /** * hif_nointrs(): disable IRQ * @@ -2656,6 +2696,7 @@ int hif_pci_bus_suspend(struct hif_softc *scn) return 0; } +#ifdef PCI_LINK_STATUS_SANITY /** * __hif_check_link_status() - API to check if PCIe link is active/not * @scn: HIF Context @@ -2694,6 +2735,13 @@ static int __hif_check_link_status(struct hif_softc *scn) pld_is_pci_link_down(sc->dev); return -EACCES; } +#else +static inline int __hif_check_link_status(struct hif_softc *scn) +{ + return 0; +} +#endif + /** * hif_pci_bus_resume(): prepare hif for resume @@ -2728,6 +2776,7 @@ int hif_pci_bus_suspend_noirq(struct hif_softc *scn) qdf_atomic_set(&scn->link_suspended, 1); hif_apps_wake_irq_enable(GET_HIF_OPAQUE_HDL(scn)); + return 0; } @@ -3013,9 +3062,14 @@ void hif_fastpath_resume(struct hif_opaque_softc *hif_ctx) */ int hif_runtime_resume(struct hif_opaque_softc *hif_ctx) { + int errno; + QDF_BUG(!hif_bus_resume_noirq(hif_ctx)); - QDF_BUG(!hif_bus_resume(hif_ctx)); - return 0; + errno = hif_bus_resume(hif_ctx); + if (errno) + HIF_ERROR("%s: failed runtime resume: %d", __func__, errno); + + return errno; } #endif /* #ifdef FEATURE_RUNTIME_PM */ @@ -3421,6 +3475,9 @@ static void hif_ce_srng_msi_irq_disable(struct hif_softc *hif_sc, int ce_id) static void hif_ce_srng_msi_irq_enable(struct hif_softc *hif_sc, int ce_id) { + if (__hif_check_link_status(hif_sc)) + return; + pfrm_enable_irq(hif_sc->qdf_dev->dev, hif_ce_msi_map_ce_to_irq(hif_sc, ce_id)); } @@ -3444,20 +3501,27 @@ static int hif_ce_msi_configure_irq(struct hif_softc *scn) uint32_t msi_irq_start; struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn); struct hif_pci_softc *pci_sc = HIF_GET_PCI_SOFTC(scn); + struct CE_attr *host_ce_conf = ce_sc->host_ce_config; + + if (!scn->disable_wake_irq) { + /* do wake irq assignment */ + ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "WAKE", + &msi_data_count, + &msi_data_start, + &msi_irq_start); + if (ret) + return ret; - /* do wake irq assignment */ - ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "WAKE", - &msi_data_count, &msi_data_start, - &msi_irq_start); - if (ret) - return ret; + scn->wake_irq = pld_get_msi_irq(scn->qdf_dev->dev, + msi_irq_start); - scn->wake_irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_irq_start); - ret = pfrm_request_irq(scn->qdf_dev->dev, scn->wake_irq, - hif_wake_interrupt_handler, - IRQF_NO_SUSPEND, "wlan_wake_irq", scn); - if (ret) - return ret; + ret = pfrm_request_irq(scn->qdf_dev->dev, scn->wake_irq, + hif_wake_interrupt_handler, + IRQF_NO_SUSPEND, "wlan_wake_irq", scn); + + if (ret) + return ret; + } /* do ce irq assignments */ ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE", @@ -3482,6 +3546,8 @@ static int hif_ce_msi_configure_irq(struct hif_softc *scn) for (ce_id = 0; ce_id < scn->ce_count; ce_id++) { unsigned int msi_data = (ce_id % msi_data_count) + msi_irq_start; + if (host_ce_conf[ce_id].flags & CE_ATTR_DISABLE_INTR) + continue; irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data); HIF_DBG("%s: (ce_id %d, msi_data %d, irq %d tasklet %pK)", __func__, ce_id, msi_data, irq, @@ -3516,9 +3582,11 @@ static int hif_ce_msi_configure_irq(struct hif_softc *scn) } free_wake_irq: - pfrm_free_irq(scn->qdf_dev->dev, - scn->wake_irq, scn->qdf_dev->dev); - scn->wake_irq = 0; + if (!scn->disable_wake_irq) { + pfrm_free_irq(scn->qdf_dev->dev, + scn->wake_irq, scn->qdf_dev->dev); + scn->wake_irq = 0; + } return ret; } @@ -3561,8 +3629,8 @@ const char *hif_pci_get_irq_name(int irq_no) * hif_pci_irq_set_affinity_hint() - API to set IRQ affinity * @hif_ext_group: hif_ext_group to extract the irq info * - * This function will set the IRQ affinity to the gold cores - * only for defconfig builds + * This function will set the WLAN DP IRQ affinity to the gold + * cores only for defconfig builds * * @hif_ext_group: hif_ext_group to extract the irq info * @@ -3615,6 +3683,61 @@ void hif_pci_irq_set_affinity_hint( } } } + +void hif_pci_ce_irq_set_affinity_hint( + struct hif_softc *scn) +{ + int ret; + unsigned int cpus; + struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn); + struct hif_pci_softc *pci_sc = HIF_GET_PCI_SOFTC(scn); + struct CE_attr *host_ce_conf; + int ce_id; + qdf_cpu_mask ce_cpu_mask; + + host_ce_conf = ce_sc->host_ce_config; + qdf_cpumask_clear(&ce_cpu_mask); + + qdf_for_each_online_cpu(cpus) { + if (qdf_topology_physical_package_id(cpus) == + CPU_CLUSTER_TYPE_PERF) { + qdf_cpumask_set_cpu(cpus, + &ce_cpu_mask); + } else { + hif_err_rl("Unable to set cpu mask for offline CPU %d" + , cpus); + } + } + if (qdf_cpumask_empty(&ce_cpu_mask)) { + hif_err_rl("Empty cpu_mask, unable to set CE IRQ affinity"); + return; + } + for (ce_id = 0; ce_id < scn->ce_count; ce_id++) { + if (host_ce_conf[ce_id].flags & CE_ATTR_DISABLE_INTR) + continue; + qdf_cpumask_clear(&pci_sc->ce_irq_cpu_mask[ce_id]); + qdf_cpumask_copy(&pci_sc->ce_irq_cpu_mask[ce_id], + &ce_cpu_mask); + qdf_dev_modify_irq_status(pci_sc->ce_msi_irq_num[ce_id], + IRQ_NO_BALANCING, 0); + ret = + qdf_dev_set_irq_affinity(pci_sc->ce_msi_irq_num[ce_id], + (struct qdf_cpu_mask *) + &pci_sc->ce_irq_cpu_mask[ce_id]); + qdf_dev_modify_irq_status(pci_sc->ce_msi_irq_num[ce_id], + 0, IRQ_NO_BALANCING); + if (ret) + hif_err_rl("Set affinity %*pbl fails for CE IRQ %d", + qdf_cpumask_pr_args( + &pci_sc->ce_irq_cpu_mask[ce_id]), + pci_sc->ce_msi_irq_num[ce_id]); + else + hif_debug_rl("Set affinity %*pbl for CE IRQ: %d", + qdf_cpumask_pr_args( + &pci_sc->ce_irq_cpu_mask[ce_id]), + pci_sc->ce_msi_irq_num[ce_id]); + } +} #endif /* #ifdef HIF_CPU_PERF_AFFINE_MASK */ void hif_pci_config_irq_affinity(struct hif_softc *scn) @@ -3624,10 +3747,13 @@ void hif_pci_config_irq_affinity(struct hif_softc *scn) struct hif_exec_context *hif_ext_group; hif_core_ctl_set_boost(true); + /* Set IRQ affinity for WLAN DP interrupts*/ for (i = 0; i < hif_state->hif_num_extgroup; i++) { hif_ext_group = hif_state->hif_ext_group[i]; hif_pci_irq_set_affinity_hint(hif_ext_group); } + /* Set IRQ affinity for CE interrupts*/ + hif_pci_ce_irq_set_affinity_hint(scn); } int hif_pci_configure_grp_irq(struct hif_softc *scn, @@ -3642,8 +3768,7 @@ int hif_pci_configure_grp_irq(struct hif_softc *scn, hif_ext_group->irq_name = &hif_pci_get_irq_name; hif_ext_group->work_complete = &hif_dummy_grp_done; - for (j = 0; j < hif_ext_group->numirq; j++) - { + for (j = 0; j < hif_ext_group->numirq; j++) { irq = hif_ext_group->irq[j]; hif_debug("request_irq = %d for grp %d", @@ -3827,14 +3952,18 @@ static void hif_pci_get_soc_info_nopld(struct hif_pci_softc *sc, struct device *dev) {} -static bool hif_is_pld_based_target(int device_id) +static bool hif_is_pld_based_target(struct hif_pci_softc *sc, + int device_id) { + if (!pld_have_platform_driver_support(sc->dev)) + return false; + switch (device_id) { case QCA6290_DEVICE_ID: + case QCN9000_DEVICE_ID: case QCA6290_EMULATION_DEVICE_ID: -#ifdef QCA_WIFI_QCA6390 case QCA6390_DEVICE_ID: -#endif + case QCA6490_DEVICE_ID: case AR6320_DEVICE_ID: case QCN7605_DEVICE_ID: return true; @@ -3845,7 +3974,7 @@ static bool hif_is_pld_based_target(int device_id) static void hif_pci_init_deinit_ops_attach(struct hif_pci_softc *sc, int device_id) { - if (hif_is_pld_based_target(device_id)) { + if (hif_is_pld_based_target(sc, device_id)) { sc->hif_enable_pci = hif_enable_pci_pld; sc->hif_pci_deinit = hif_pci_deinit_pld; sc->hif_pci_get_soc_info = hif_pci_get_soc_info_pld; @@ -3896,7 +4025,8 @@ QDF_STATUS hif_pci_enable_bus(struct hif_softc *ol_sc, enum hif_enable_type type) { int ret = 0; - uint32_t hif_type, target_type; + uint32_t hif_type; + uint32_t target_type = TARGET_TYPE_UNKNOWN; struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(ol_sc); struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(ol_sc); uint16_t revision_id = 0; @@ -4869,6 +4999,19 @@ qdf_time_t hif_pm_runtime_get_dp_rx_busy_mark(struct hif_opaque_softc *hif_ctx) return sc->dp_last_busy_timestamp; } +void hif_pm_set_link_state(struct hif_opaque_softc *hif_handle, uint8_t val) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_handle); + + qdf_atomic_set(&scn->pm_link_state, val); +} + +uint8_t hif_pm_get_link_state(struct hif_opaque_softc *hif_handle) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_handle); + + return qdf_atomic_read(&scn->pm_link_state); +} #endif /* FEATURE_RUNTIME_PM */ int hif_pci_legacy_map_ce_to_irq(struct hif_softc *scn, int ce_id) @@ -4888,6 +5031,7 @@ int hif_pci_addr_in_boundary(struct hif_softc *scn, uint32_t offset) if (tgt_info->target_type == TARGET_TYPE_QCA6290 || tgt_info->target_type == TARGET_TYPE_QCA6390 || + tgt_info->target_type == TARGET_TYPE_QCA6490 || tgt_info->target_type == TARGET_TYPE_QCA8074) { /* * Need to consider offset's memtype for QCA6290/QCA8074, @@ -4920,6 +5064,171 @@ bool hif_pci_needs_bmi(struct hif_softc *scn) return !ce_srng_based(scn); } +#ifdef FORCE_WAKE +#ifdef DEVICE_FORCE_WAKE_ENABLE +int hif_force_wake_request(struct hif_opaque_softc *hif_handle) +{ + uint32_t timeout, value; + struct hif_softc *scn = (struct hif_softc *)hif_handle; + struct hif_pci_softc *pci_scn = HIF_GET_PCI_SOFTC(scn); + + HIF_STATS_INC(pci_scn, mhi_force_wake_request_vote, 1); + + if (qdf_in_interrupt()) + timeout = FORCE_WAKE_DELAY_TIMEOUT_MS * 1000; + else + timeout = 0; + + if (pld_force_wake_request_sync(scn->qdf_dev->dev, timeout)) { + hif_err("force wake request send failed"); + HIF_STATS_INC(pci_scn, mhi_force_wake_failure, 1); + return -EINVAL; + } + + /* If device's M1 state-change event races here, it can be ignored, + * as the device is expected to immediately move from M2 to M0 + * without entering low power state. + */ + if (!pld_is_device_awake(scn->qdf_dev->dev)) + HIF_INFO("%s: state-change event races, ignore", __func__); + + HIF_STATS_INC(pci_scn, mhi_force_wake_success, 1); + hif_write32_mb(scn, + scn->mem + + PCIE_SOC_PCIE_REG_PCIE_SCRATCH_0_SOC_PCIE_REG, + 0); + hif_write32_mb(scn, + scn->mem + + PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG, + 1); + + HIF_STATS_INC(pci_scn, soc_force_wake_register_write_success, 1); + /* + * do not reset the timeout + * total_wake_time = MHI_WAKE_TIME + PCI_WAKE_TIME < 50 ms + */ + timeout = 0; + do { + value = + hif_read32_mb(scn, + scn->mem + + PCIE_SOC_PCIE_REG_PCIE_SCRATCH_0_SOC_PCIE_REG); + if (value) + break; + qdf_mdelay(FORCE_WAKE_DELAY_MS); + timeout += FORCE_WAKE_DELAY_MS; + } while (timeout <= FORCE_WAKE_DELAY_TIMEOUT_MS); + + if (!value) { + hif_err("failed handshake mechanism"); + HIF_STATS_INC(pci_scn, soc_force_wake_failure, 1); + return -ETIMEDOUT; + } + + HIF_STATS_INC(pci_scn, soc_force_wake_success, 1); + return 0; +} + +int hif_force_wake_release(struct hif_opaque_softc *hif_handle) +{ + int ret; + struct hif_softc *scn = (struct hif_softc *)hif_handle; + struct hif_pci_softc *pci_scn = HIF_GET_PCI_SOFTC(scn); + + ret = pld_force_wake_release(scn->qdf_dev->dev); + if (ret) { + hif_err("force wake release failure"); + HIF_STATS_INC(pci_scn, mhi_force_wake_release_failure, 1); + return ret; + } + + HIF_STATS_INC(pci_scn, mhi_force_wake_release_success, 1); + hif_write32_mb(scn, + scn->mem + + PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG, + 0); + HIF_STATS_INC(pci_scn, soc_force_wake_release_success, 1); + return 0; +} + +#else /* DEVICE_FORCE_WAKE_ENABLE */ +/** hif_force_wake_request() - Disable the PCIE scratch register + * write/read + * + * Return: 0 + */ +int hif_force_wake_request(struct hif_opaque_softc *hif_handle) +{ + struct hif_softc *scn = (struct hif_softc *)hif_handle; + struct hif_pci_softc *pci_scn = HIF_GET_PCI_SOFTC(scn); + uint32_t timeout; + + HIF_STATS_INC(pci_scn, mhi_force_wake_request_vote, 1); + + if (qdf_in_interrupt()) + timeout = FORCE_WAKE_DELAY_TIMEOUT_MS * 1000; + else + timeout = 0; + + if (pld_force_wake_request_sync(scn->qdf_dev->dev, timeout)) { + hif_err("force wake request send failed"); + HIF_STATS_INC(pci_scn, mhi_force_wake_failure, 1); + return -EINVAL; + } + + /* If device's M1 state-change event races here, it can be ignored, + * as the device is expected to immediately move from M2 to M0 + * without entering low power state. + */ + if (!pld_is_device_awake(scn->qdf_dev->dev)) + HIF_INFO("%s: state-change event races, ignore", __func__); + + HIF_STATS_INC(pci_scn, mhi_force_wake_success, 1); + + return 0; +} + +int hif_force_wake_release(struct hif_opaque_softc *hif_handle) +{ + int ret; + struct hif_softc *scn = (struct hif_softc *)hif_handle; + struct hif_pci_softc *pci_scn = HIF_GET_PCI_SOFTC(scn); + + ret = pld_force_wake_release(scn->qdf_dev->dev); + if (ret) { + hif_err("force wake release failure"); + HIF_STATS_INC(pci_scn, mhi_force_wake_release_failure, 1); + return ret; + } + + HIF_STATS_INC(pci_scn, mhi_force_wake_release_success, 1); + return 0; +} +#endif /* DEVICE_FORCE_WAKE_ENABLE */ + +void hif_print_pci_stats(struct hif_pci_softc *pci_handle) +{ + hif_debug("mhi_force_wake_request_vote: %d", + pci_handle->stats.mhi_force_wake_request_vote); + hif_debug("mhi_force_wake_failure: %d", + pci_handle->stats.mhi_force_wake_failure); + hif_debug("mhi_force_wake_success: %d", + pci_handle->stats.mhi_force_wake_success); + hif_debug("soc_force_wake_register_write_success: %d", + pci_handle->stats.soc_force_wake_register_write_success); + hif_debug("soc_force_wake_failure: %d", + pci_handle->stats.soc_force_wake_failure); + hif_debug("soc_force_wake_success: %d", + pci_handle->stats.soc_force_wake_success); + hif_debug("mhi_force_wake_release_failure: %d", + pci_handle->stats.mhi_force_wake_release_failure); + hif_debug("mhi_force_wake_release_success: %d", + pci_handle->stats.mhi_force_wake_release_success); + hif_debug("oc_force_wake_release_success: %d", + pci_handle->stats.soc_force_wake_release_success); +} +#endif /* FORCE_WAKE */ + #ifdef FEATURE_HAL_DELAYED_REG_WRITE int hif_prevent_link_low_power_states(struct hif_opaque_softc *hif) { diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/pcie/if_pci.h b/drivers/staging/qca-wifi-host-cmn/hif/src/pcie/if_pci.h index f3858ef4057125e9d589ff6b54ae9fc134f5cc5c..cdcb558eea1c29d22f6d3dabc00a4573a5eb06c9 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/pcie/if_pci.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/pcie/if_pci.h @@ -28,7 +28,21 @@ #include "hif.h" #include "cepci.h" #include "ce_main.h" -#include + +#ifdef FORCE_WAKE +/* Register to wake the UMAC from power collapse */ +#define PCIE_SOC_PCIE_REG_PCIE_SCRATCH_0_SOC_PCIE_REG (0x01E04000 + 0x40) +/* Register used for handshake mechanism to validate UMAC is awake */ +#define PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG (0x01E00000 + 0x3004) +/* Timeout duration to validate UMAC wake status */ +#ifdef HAL_CONFIG_SLUB_DEBUG_ON +#define FORCE_WAKE_DELAY_TIMEOUT_MS 500 +#else +#define FORCE_WAKE_DELAY_TIMEOUT_MS 50 +#endif /* HAL_CONFIG_SLUB_DEBUG_ON */ +/* Validate UMAC status every 5ms */ +#define FORCE_WAKE_DELAY_MS 5 +#endif /* FORCE_WAKE */ #ifdef QCA_HIF_HIA_EXTND extern int32_t frac, intval, ar900b_20_targ_clk, qca9888_20_targ_clk; @@ -42,6 +56,11 @@ struct hif_tasklet_entry { void *hif_handler; /* struct hif_pci_softc */ }; +struct hang_event_bus_info { + uint16_t tlv_header; + uint16_t dev_id; +} qdf_packed; + /** * enum hif_pm_runtime_state - Driver States for Runtime Power Management * HIF_PM_RUNTIME_STATE_NONE: runtime pm is off @@ -111,6 +130,29 @@ struct hif_msi_info { OS_DMA_MEM_CONTEXT(dmacontext); }; +/** + * struct hif_pci_stats - Account for hif pci based statistics + * @mhi_force_wake_request_vote: vote for mhi + * @mhi_force_wake_failure: mhi force wake failure + * @mhi_force_wake_success: mhi force wake success + * @soc_force_wake_register_write_success: write to soc wake + * @soc_force_wake_failure: soc force wake failure + * @soc_force_wake_success: soc force wake success + * @mhi_force_wake_release_success: mhi force wake release success + * @soc_force_wake_release_success: soc force wake release + */ +struct hif_pci_stats { + uint32_t mhi_force_wake_request_vote; + uint32_t mhi_force_wake_failure; + uint32_t mhi_force_wake_success; + uint32_t soc_force_wake_register_write_success; + uint32_t soc_force_wake_failure; + uint32_t soc_force_wake_success; + uint32_t mhi_force_wake_release_failure; + uint32_t mhi_force_wake_release_success; + uint32_t soc_force_wake_release_success; +}; + struct hif_pci_softc { struct HIF_CE_state ce_sc; void __iomem *mem; /* PCI address. */ @@ -157,6 +199,11 @@ struct hif_pci_softc { void (*hif_pci_deinit)(struct hif_pci_softc *sc); void (*hif_pci_get_soc_info)(struct hif_pci_softc *sc, struct device *dev); + struct hif_pci_stats stats; +#ifdef HIF_CPU_PERF_AFFINE_MASK + /* Stores the affinity hint mask for each CE IRQ */ + qdf_cpu_mask ce_irq_cpu_mask[CE_COUNT_MAX]; +#endif }; bool hif_pci_targ_is_present(struct hif_softc *scn, void *__iomem *mem); @@ -201,6 +248,21 @@ int hif_pci_addr_in_boundary(struct hif_softc *scn, uint32_t offset); #define OL_ATH_TX_DRAIN_WAIT_CNT 60 #endif +#ifdef FORCE_WAKE +/** + * hif_print_pci_stats() - Display HIF PCI stats + * @hif_ctx - HIF pci handle + * + * Return: None + */ +void hif_print_pci_stats(struct hif_pci_softc *pci_scn); +#else +static inline +void hif_print_pci_stats(struct hif_pci_softc *pci_scn) +{ +} +#endif /* FORCE_WAKE */ + #ifdef FEATURE_RUNTIME_PM #include @@ -220,4 +282,16 @@ static inline int hif_pm_runtime_put_auto(struct device *dev) } #endif /* FEATURE_RUNTIME_PM */ + +#ifdef HIF_BUS_LOG_INFO +bool hif_log_pcie_info(struct hif_softc *scn, uint8_t *data, + unsigned int *offset); +#else +static inline +bool hif_log_pcie_info(struct hif_softc *scn, uint8_t *data, + unsigned int *offset) +{ + return false; +} +#endif #endif /* __ATH_PCI_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/qca6290def.c b/drivers/staging/qca-wifi-host-cmn/hif/src/qca6290def.c index e755ced1297ad2994a5e69ab345516dc8e301ff2..4070b10ad4ce3a3bd64d3b430cdf01be96233900 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/qca6290def.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/qca6290def.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 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 @@ -152,15 +152,8 @@ #define CE_DDR_ADDRESS_FOR_RRI_LOW MISSING #define CE_DDR_ADDRESS_FOR_RRI_HIGH MISSING -#if defined(WCSS_VERSION) && \ - ((defined(CONFIG_WIN) && (WCSS_VERSION > 81)) || \ - (defined(CONFIG_MCL) && (WCSS_VERSION >= 72))) #define HOST_IE_ADDRESS UMAC_CE_COMMON_WFSS_CE_COMMON_R0_CE_HOST_IE_0 #define HOST_IE_ADDRESS_2 UMAC_CE_COMMON_WFSS_CE_COMMON_R0_CE_HOST_IE_1 -#else /* WCSS_VERSION < 72 */ -#define HOST_IE_ADDRESS UMAC_CE_COMMON_CE_HOST_IE_0 -#define HOST_IE_ADDRESS_2 UMAC_CE_COMMON_CE_HOST_IE_1 -#endif /* WCSS_VERSION */ #define HOST_IE_COPY_COMPLETE_MASK MISSING #define SR_BA_ADDRESS MISSING diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/qca6390def.c b/drivers/staging/qca-wifi-host-cmn/hif/src/qca6390def.c index ffdcb17f08c04ef8180de405762474e5be6522c5..59fc7d56290a755db3d0a5de8b1d949c0c20391e 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/qca6390def.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/qca6390def.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 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 @@ -152,15 +152,8 @@ #define CE_DDR_ADDRESS_FOR_RRI_LOW MISSING #define CE_DDR_ADDRESS_FOR_RRI_HIGH MISSING -#if defined(WCSS_VERSION) && \ - ((defined(CONFIG_WIN) && (WCSS_VERSION > 81)) || \ - (defined(CONFIG_MCL) && (WCSS_VERSION >= 72))) #define HOST_IE_ADDRESS UMAC_CE_COMMON_WFSS_CE_COMMON_R0_CE_HOST_IE_0 #define HOST_IE_ADDRESS_2 UMAC_CE_COMMON_WFSS_CE_COMMON_R0_CE_HOST_IE_1 -#else /* WCSS_VERSION < 72 */ -#define HOST_IE_ADDRESS UMAC_CE_COMMON_CE_HOST_IE_0 -#define HOST_IE_ADDRESS_2 UMAC_CE_COMMON_CE_HOST_IE_1 -#endif /* WCSS_VERSION */ #define HOST_IE_COPY_COMPLETE_MASK MISSING #define SR_BA_ADDRESS MISSING diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/qca6490def.c b/drivers/staging/qca-wifi-host-cmn/hif/src/qca6490def.c new file mode 100644 index 0000000000000000000000000000000000000000..1dc1ec2a99475ea431e54acd504be7af5d5ae29a --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/qca6490def.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#if defined(QCA6490_HEADERS_DEF) + +#undef UMAC +#define WLAN_HEADERS 1 + +#include "lithium_top_reg.h" +#include "wcss_version.h" + +#define MISSING 0 + +#define SOC_RESET_CONTROL_OFFSET MISSING +#define GPIO_PIN0_OFFSET MISSING +#define GPIO_PIN1_OFFSET MISSING +#define GPIO_PIN0_CONFIG_MASK MISSING +#define GPIO_PIN1_CONFIG_MASK MISSING +#define LOCAL_SCRATCH_OFFSET 0x18 +#define GPIO_PIN10_OFFSET MISSING +#define GPIO_PIN11_OFFSET MISSING +#define GPIO_PIN12_OFFSET MISSING +#define GPIO_PIN13_OFFSET MISSING +#define MBOX_BASE_ADDRESS MISSING +#define INT_STATUS_ENABLE_ERROR_LSB MISSING +#define INT_STATUS_ENABLE_ERROR_MASK MISSING +#define INT_STATUS_ENABLE_CPU_LSB MISSING +#define INT_STATUS_ENABLE_CPU_MASK MISSING +#define INT_STATUS_ENABLE_COUNTER_LSB MISSING +#define INT_STATUS_ENABLE_COUNTER_MASK MISSING +#define INT_STATUS_ENABLE_MBOX_DATA_LSB MISSING +#define INT_STATUS_ENABLE_MBOX_DATA_MASK MISSING +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB MISSING +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK MISSING +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB MISSING +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK MISSING +#define COUNTER_INT_STATUS_ENABLE_BIT_LSB MISSING +#define COUNTER_INT_STATUS_ENABLE_BIT_MASK MISSING +#define INT_STATUS_ENABLE_ADDRESS MISSING +#define CPU_INT_STATUS_ENABLE_BIT_LSB MISSING +#define CPU_INT_STATUS_ENABLE_BIT_MASK MISSING +#define HOST_INT_STATUS_ADDRESS MISSING +#define CPU_INT_STATUS_ADDRESS MISSING +#define ERROR_INT_STATUS_ADDRESS MISSING +#define ERROR_INT_STATUS_WAKEUP_MASK MISSING +#define ERROR_INT_STATUS_WAKEUP_LSB MISSING +#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK MISSING +#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB MISSING +#define ERROR_INT_STATUS_TX_OVERFLOW_MASK MISSING +#define ERROR_INT_STATUS_TX_OVERFLOW_LSB MISSING +#define COUNT_DEC_ADDRESS MISSING +#define HOST_INT_STATUS_CPU_MASK MISSING +#define HOST_INT_STATUS_CPU_LSB MISSING +#define HOST_INT_STATUS_ERROR_MASK MISSING +#define HOST_INT_STATUS_ERROR_LSB MISSING +#define HOST_INT_STATUS_COUNTER_MASK MISSING +#define HOST_INT_STATUS_COUNTER_LSB MISSING +#define RX_LOOKAHEAD_VALID_ADDRESS MISSING +#define WINDOW_DATA_ADDRESS MISSING +#define WINDOW_READ_ADDR_ADDRESS MISSING +#define WINDOW_WRITE_ADDR_ADDRESS MISSING +/* GPIO Register */ +#define GPIO_ENABLE_W1TS_LOW_ADDRESS MISSING +#define GPIO_PIN0_CONFIG_LSB MISSING +#define GPIO_PIN0_PAD_PULL_LSB MISSING +#define GPIO_PIN0_PAD_PULL_MASK MISSING +/* SI reg */ +#define SI_CONFIG_ERR_INT_MASK MISSING +#define SI_CONFIG_ERR_INT_LSB MISSING + +#define RTC_SOC_BASE_ADDRESS MISSING +#define RTC_WMAC_BASE_ADDRESS MISSING +#define SOC_CORE_BASE_ADDRESS MISSING +#define WLAN_MAC_BASE_ADDRESS MISSING +#define GPIO_BASE_ADDRESS MISSING +#define ANALOG_INTF_BASE_ADDRESS MISSING +#define CE0_BASE_ADDRESS MISSING +#define CE1_BASE_ADDRESS MISSING +#define CE_COUNT 12 +#define CE_WRAPPER_BASE_ADDRESS MISSING +#define SI_BASE_ADDRESS MISSING +#define DRAM_BASE_ADDRESS MISSING + +#define WLAN_SYSTEM_SLEEP_DISABLE_LSB MISSING +#define WLAN_SYSTEM_SLEEP_DISABLE_MASK MISSING +#define CLOCK_CONTROL_OFFSET MISSING +#define CLOCK_CONTROL_SI0_CLK_MASK MISSING +#define RESET_CONTROL_SI0_RST_MASK MISSING +#define WLAN_RESET_CONTROL_OFFSET MISSING +#define WLAN_RESET_CONTROL_COLD_RST_MASK MISSING +#define WLAN_RESET_CONTROL_WARM_RST_MASK MISSING +#define CPU_CLOCK_OFFSET MISSING + +#define CPU_CLOCK_STANDARD_LSB MISSING +#define CPU_CLOCK_STANDARD_MASK MISSING +#define LPO_CAL_ENABLE_LSB MISSING +#define LPO_CAL_ENABLE_MASK MISSING +#define WLAN_SYSTEM_SLEEP_OFFSET MISSING + +#define SOC_CHIP_ID_ADDRESS MISSING +#define SOC_CHIP_ID_REVISION_MASK MISSING +#define SOC_CHIP_ID_REVISION_LSB MISSING +#define SOC_CHIP_ID_REVISION_MSB MISSING + +#define FW_IND_EVENT_PENDING MISSING +#define FW_IND_INITIALIZED MISSING + +#define MSDU_LINK_EXT_3_TCP_OVER_IPV4_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_TCP_OVER_IPV6_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV4_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV6_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_TCP_OVER_IPV4_CHECKSUM_EN_LSB MISSING +#define MSDU_LINK_EXT_3_TCP_OVER_IPV6_CHECKSUM_EN_LSB MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV4_CHECKSUM_EN_LSB MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV6_CHECKSUM_EN_LSB MISSING + +#define SR_WR_INDEX_ADDRESS MISSING +#define DST_WATERMARK_ADDRESS MISSING + +#define DST_WR_INDEX_ADDRESS MISSING +#define SRC_WATERMARK_ADDRESS MISSING +#define SRC_WATERMARK_LOW_MASK MISSING +#define SRC_WATERMARK_HIGH_MASK MISSING +#define DST_WATERMARK_LOW_MASK MISSING +#define DST_WATERMARK_HIGH_MASK MISSING +#define CURRENT_SRRI_ADDRESS MISSING +#define CURRENT_DRRI_ADDRESS MISSING +#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK MISSING +#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK MISSING +#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK MISSING +#define HOST_IS_DST_RING_LOW_WATERMARK_MASK MISSING +#define HOST_IS_ADDRESS MISSING +#define MISC_IS_ADDRESS MISSING +#define HOST_IS_COPY_COMPLETE_MASK MISSING +#define CE_WRAPPER_BASE_ADDRESS MISSING +#define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS MISSING +#define CE_DDR_ADDRESS_FOR_RRI_LOW MISSING +#define CE_DDR_ADDRESS_FOR_RRI_HIGH MISSING + +#if (defined(WCSS_VERSION) && (WCSS_VERSION >= 72)) +#define HOST_IE_ADDRESS UMAC_CE_COMMON_WFSS_CE_COMMON_R0_CE_HOST_IE_0 +#define HOST_IE_ADDRESS_2 UMAC_CE_COMMON_WFSS_CE_COMMON_R0_CE_HOST_IE_1 +#else /* WCSS_VERSION < 72 */ +#define HOST_IE_ADDRESS UMAC_CE_COMMON_CE_HOST_IE_0 +#define HOST_IE_ADDRESS_2 UMAC_CE_COMMON_CE_HOST_IE_1 +#endif /* WCSS_VERSION */ + +#define HOST_IE_COPY_COMPLETE_MASK MISSING +#define SR_BA_ADDRESS MISSING +#define SR_BA_ADDRESS_HIGH MISSING +#define SR_SIZE_ADDRESS MISSING +#define CE_CTRL1_ADDRESS MISSING +#define CE_CTRL1_DMAX_LENGTH_MASK MISSING +#define DR_BA_ADDRESS MISSING +#define DR_BA_ADDRESS_HIGH MISSING +#define DR_SIZE_ADDRESS MISSING +#define CE_CMD_REGISTER MISSING +#define CE_MSI_ADDRESS MISSING +#define CE_MSI_ADDRESS_HIGH MISSING +#define CE_MSI_DATA MISSING +#define CE_MSI_ENABLE_BIT MISSING +#define MISC_IE_ADDRESS MISSING +#define MISC_IS_AXI_ERR_MASK MISSING +#define MISC_IS_DST_ADDR_ERR_MASK MISSING +#define MISC_IS_SRC_LEN_ERR_MASK MISSING +#define MISC_IS_DST_MAX_LEN_VIO_MASK MISSING +#define MISC_IS_DST_RING_OVERFLOW_MASK MISSING +#define MISC_IS_SRC_RING_OVERFLOW_MASK MISSING +#define SRC_WATERMARK_LOW_LSB MISSING +#define SRC_WATERMARK_HIGH_LSB MISSING +#define DST_WATERMARK_LOW_LSB MISSING +#define DST_WATERMARK_HIGH_LSB MISSING +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK MISSING +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB MISSING +#define CE_CTRL1_DMAX_LENGTH_LSB MISSING +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK MISSING +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK MISSING +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB MISSING +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB MISSING +#define CE_CTRL1_IDX_UPD_EN_MASK MISSING +#define CE_WRAPPER_DEBUG_OFFSET MISSING +#define CE_WRAPPER_DEBUG_SEL_MSB MISSING +#define CE_WRAPPER_DEBUG_SEL_LSB MISSING +#define CE_WRAPPER_DEBUG_SEL_MASK MISSING +#define CE_DEBUG_OFFSET MISSING +#define CE_DEBUG_SEL_MSB MISSING +#define CE_DEBUG_SEL_LSB MISSING +#define CE_DEBUG_SEL_MASK MISSING +#define CE0_BASE_ADDRESS MISSING +#define CE1_BASE_ADDRESS MISSING +#define A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES MISSING +#define A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_STATUS MISSING + +#define QCA6490_BOARD_DATA_SZ MISSING +#define QCA6490_BOARD_EXT_DATA_SZ MISSING + +#define MY_TARGET_DEF QCA6490_TARGETdef +#define MY_HOST_DEF QCA6490_HOSTdef +#define MY_CEREG_DEF QCA6490_CE_TARGETdef +#define MY_TARGET_BOARD_DATA_SZ QCA6490_BOARD_DATA_SZ +#define MY_TARGET_BOARD_EXT_DATA_SZ QCA6490_BOARD_EXT_DATA_SZ +#include "targetdef.h" +#include "hostdef.h" +#else +#include "common_drv.h" +#include "targetdef.h" +#include "hostdef.h" +struct targetdef_s *QCA6490_TARGETdef; +struct hostdef_s *QCA6490_HOSTdef; +#endif /*QCA6490_HEADERS_DEF */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/qca6750def.c b/drivers/staging/qca-wifi-host-cmn/hif/src/qca6750def.c new file mode 100644 index 0000000000000000000000000000000000000000..6ec562ff6c28bfc54e69d328c479c7b2025e4a81 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/qca6750def.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2020 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 above + * copyright notice and this permission notice appear in all copies. + + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if defined(QCA6750_HEADERS_DEF) + +#undef UMAC +#define WLAN_HEADERS 1 +#include "lithium_top_reg.h" +#include "wfss_ce_reg_seq_hwioreg.h" +#include "wcss_version.h" + +#define MISSING 0 + +#define SOC_RESET_CONTROL_OFFSET MISSING +#define GPIO_PIN0_OFFSET MISSING +#define GPIO_PIN1_OFFSET MISSING +#define GPIO_PIN0_CONFIG_MASK MISSING +#define GPIO_PIN1_CONFIG_MASK MISSING +#define LOCAL_SCRATCH_OFFSET 0x18 +#define GPIO_PIN10_OFFSET MISSING +#define GPIO_PIN11_OFFSET MISSING +#define GPIO_PIN12_OFFSET MISSING +#define GPIO_PIN13_OFFSET MISSING +#define MBOX_BASE_ADDRESS MISSING +#define INT_STATUS_ENABLE_ERROR_LSB MISSING +#define INT_STATUS_ENABLE_ERROR_MASK MISSING +#define INT_STATUS_ENABLE_CPU_LSB MISSING +#define INT_STATUS_ENABLE_CPU_MASK MISSING +#define INT_STATUS_ENABLE_COUNTER_LSB MISSING +#define INT_STATUS_ENABLE_COUNTER_MASK MISSING +#define INT_STATUS_ENABLE_MBOX_DATA_LSB MISSING +#define INT_STATUS_ENABLE_MBOX_DATA_MASK MISSING +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB MISSING +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK MISSING +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB MISSING +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK MISSING +#define COUNTER_INT_STATUS_ENABLE_BIT_LSB MISSING +#define COUNTER_INT_STATUS_ENABLE_BIT_MASK MISSING +#define INT_STATUS_ENABLE_ADDRESS MISSING +#define CPU_INT_STATUS_ENABLE_BIT_LSB MISSING +#define CPU_INT_STATUS_ENABLE_BIT_MASK MISSING +#define HOST_INT_STATUS_ADDRESS MISSING +#define CPU_INT_STATUS_ADDRESS MISSING +#define ERROR_INT_STATUS_ADDRESS MISSING +#define ERROR_INT_STATUS_WAKEUP_MASK MISSING +#define ERROR_INT_STATUS_WAKEUP_LSB MISSING +#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK MISSING +#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB MISSING +#define ERROR_INT_STATUS_TX_OVERFLOW_MASK MISSING +#define ERROR_INT_STATUS_TX_OVERFLOW_LSB MISSING +#define COUNT_DEC_ADDRESS MISSING +#define HOST_INT_STATUS_CPU_MASK MISSING +#define HOST_INT_STATUS_CPU_LSB MISSING +#define HOST_INT_STATUS_ERROR_MASK MISSING +#define HOST_INT_STATUS_ERROR_LSB MISSING +#define HOST_INT_STATUS_COUNTER_MASK MISSING +#define HOST_INT_STATUS_COUNTER_LSB MISSING +#define RX_LOOKAHEAD_VALID_ADDRESS MISSING +#define WINDOW_DATA_ADDRESS MISSING +#define WINDOW_READ_ADDR_ADDRESS MISSING +#define WINDOW_WRITE_ADDR_ADDRESS MISSING +/* GPIO Register */ +#define GPIO_ENABLE_W1TS_LOW_ADDRESS MISSING +#define GPIO_PIN0_CONFIG_LSB MISSING +#define GPIO_PIN0_PAD_PULL_LSB MISSING +#define GPIO_PIN0_PAD_PULL_MASK MISSING +/* SI reg */ +#define SI_CONFIG_ERR_INT_MASK MISSING +#define SI_CONFIG_ERR_INT_LSB MISSING + +#define RTC_SOC_BASE_ADDRESS MISSING +#define RTC_WMAC_BASE_ADDRESS MISSING +#define SOC_CORE_BASE_ADDRESS MISSING +#define WLAN_MAC_BASE_ADDRESS MISSING +#define GPIO_BASE_ADDRESS MISSING +#define ANALOG_INTF_BASE_ADDRESS MISSING +#define CE0_BASE_ADDRESS MISSING +#define CE1_BASE_ADDRESS MISSING +#define CE_COUNT 12 +#define CE_WRAPPER_BASE_ADDRESS MISSING +#define SI_BASE_ADDRESS MISSING +#define DRAM_BASE_ADDRESS MISSING + +#define WLAN_SYSTEM_SLEEP_DISABLE_LSB MISSING +#define WLAN_SYSTEM_SLEEP_DISABLE_MASK MISSING +#define CLOCK_CONTROL_OFFSET MISSING +#define CLOCK_CONTROL_SI0_CLK_MASK MISSING +#define RESET_CONTROL_SI0_RST_MASK MISSING +#define WLAN_RESET_CONTROL_OFFSET MISSING +#define WLAN_RESET_CONTROL_COLD_RST_MASK MISSING +#define WLAN_RESET_CONTROL_WARM_RST_MASK MISSING +#define CPU_CLOCK_OFFSET MISSING + +#define CPU_CLOCK_STANDARD_LSB MISSING +#define CPU_CLOCK_STANDARD_MASK MISSING +#define LPO_CAL_ENABLE_LSB MISSING +#define LPO_CAL_ENABLE_MASK MISSING +#define WLAN_SYSTEM_SLEEP_OFFSET MISSING + +#define SOC_CHIP_ID_ADDRESS MISSING +#define SOC_CHIP_ID_REVISION_MASK MISSING +#define SOC_CHIP_ID_REVISION_LSB MISSING +#define SOC_CHIP_ID_REVISION_MSB MISSING + +#define FW_IND_EVENT_PENDING MISSING +#define FW_IND_INITIALIZED MISSING + +#define MSDU_LINK_EXT_3_TCP_OVER_IPV4_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_TCP_OVER_IPV6_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV4_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV6_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_TCP_OVER_IPV4_CHECKSUM_EN_LSB MISSING +#define MSDU_LINK_EXT_3_TCP_OVER_IPV6_CHECKSUM_EN_LSB MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV4_CHECKSUM_EN_LSB MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV6_CHECKSUM_EN_LSB MISSING + +#define SR_WR_INDEX_ADDRESS MISSING +#define DST_WATERMARK_ADDRESS MISSING + +#define DST_WR_INDEX_ADDRESS MISSING +#define SRC_WATERMARK_ADDRESS MISSING +#define SRC_WATERMARK_LOW_MASK MISSING +#define SRC_WATERMARK_HIGH_MASK MISSING +#define DST_WATERMARK_LOW_MASK MISSING +#define DST_WATERMARK_HIGH_MASK MISSING +#define CURRENT_SRRI_ADDRESS MISSING +#define CURRENT_DRRI_ADDRESS MISSING +#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK MISSING +#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK MISSING +#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK MISSING +#define HOST_IS_DST_RING_LOW_WATERMARK_MASK MISSING +#define HOST_IS_ADDRESS MISSING +#define MISC_IS_ADDRESS MISSING +#define HOST_IS_COPY_COMPLETE_MASK MISSING +#define CE_WRAPPER_BASE_ADDRESS MISSING +#define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS MISSING +#define CE_DDR_ADDRESS_FOR_RRI_LOW MISSING +#define CE_DDR_ADDRESS_FOR_RRI_HIGH MISSING + +#define HOST_IE_ADDRESS HWIO_SOC_CE_COMMON_WFSS_CE_COMMON_R0_CE_HOST_IE_0_ADDR +#define HOST_IE_ADDRESS_2 HWIO_SOC_CE_COMMON_WFSS_CE_COMMON_R0_CE_HOST_IE_1_ADDR + +#define HOST_IE_COPY_COMPLETE_MASK MISSING +#define SR_BA_ADDRESS MISSING +#define SR_BA_ADDRESS_HIGH MISSING +#define SR_SIZE_ADDRESS MISSING +#define CE_CTRL1_ADDRESS MISSING +#define CE_CTRL1_DMAX_LENGTH_MASK MISSING +#define DR_BA_ADDRESS MISSING +#define DR_BA_ADDRESS_HIGH MISSING +#define DR_SIZE_ADDRESS MISSING +#define CE_CMD_REGISTER MISSING +#define CE_MSI_ADDRESS MISSING +#define CE_MSI_ADDRESS_HIGH MISSING +#define CE_MSI_DATA MISSING +#define CE_MSI_ENABLE_BIT MISSING +#define MISC_IE_ADDRESS MISSING +#define MISC_IS_AXI_ERR_MASK MISSING +#define MISC_IS_DST_ADDR_ERR_MASK MISSING +#define MISC_IS_SRC_LEN_ERR_MASK MISSING +#define MISC_IS_DST_MAX_LEN_VIO_MASK MISSING +#define MISC_IS_DST_RING_OVERFLOW_MASK MISSING +#define MISC_IS_SRC_RING_OVERFLOW_MASK MISSING +#define SRC_WATERMARK_LOW_LSB MISSING +#define SRC_WATERMARK_HIGH_LSB MISSING +#define DST_WATERMARK_LOW_LSB MISSING +#define DST_WATERMARK_HIGH_LSB MISSING +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK MISSING +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB MISSING +#define CE_CTRL1_DMAX_LENGTH_LSB MISSING +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK MISSING +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK MISSING +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB MISSING +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB MISSING +#define CE_CTRL1_IDX_UPD_EN_MASK MISSING +#define CE_WRAPPER_DEBUG_OFFSET MISSING +#define CE_WRAPPER_DEBUG_SEL_MSB MISSING +#define CE_WRAPPER_DEBUG_SEL_LSB MISSING +#define CE_WRAPPER_DEBUG_SEL_MASK MISSING +#define CE_DEBUG_OFFSET MISSING +#define CE_DEBUG_SEL_MSB MISSING +#define CE_DEBUG_SEL_LSB MISSING +#define CE_DEBUG_SEL_MASK MISSING +#define CE0_BASE_ADDRESS MISSING +#define CE1_BASE_ADDRESS MISSING +#define A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES MISSING +#define A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_STATUS MISSING + +#define QCA6750_BOARD_DATA_SZ MISSING +#define QCA6750_BOARD_EXT_DATA_SZ MISSING + +#define MY_TARGET_DEF QCA6750_TARGETdef +#define MY_HOST_DEF QCA6750_HOSTdef +#define MY_CEREG_DEF QCA6750_CE_TARGETdef +#define MY_TARGET_BOARD_DATA_SZ QCA6750_BOARD_DATA_SZ +#define MY_TARGET_BOARD_EXT_DATA_SZ QCA6750_BOARD_EXT_DATA_SZ +#include "targetdef.h" +#include "hostdef.h" +#else +#include "common_drv.h" +#include "targetdef.h" +#include "hostdef.h" +struct targetdef_s *QCA6750_TARGETdef; +struct hostdef_s *QCA6750_HOSTdef; +#endif /*QCA6750_HEADERS_DEF */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/qcn9000def.c b/drivers/staging/qca-wifi-host-cmn/hif/src/qcn9000def.c new file mode 100644 index 0000000000000000000000000000000000000000..8a9527c49441398cd2049c999f00fb49a73ffed4 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/qcn9000def.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2018-2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "qdf_module.h" + +#if defined(QCN9000_HEADERS_DEF) + +#undef UMAC +#define WLAN_HEADERS 1 + +#include "wcss_version.h" +#include "wcss_seq_hwiobase.h" +#include "wfss_ce_reg_seq_hwioreg.h" + +#define MISSING 0 + +#define SOC_RESET_CONTROL_OFFSET MISSING +#define GPIO_PIN0_OFFSET MISSING +#define GPIO_PIN1_OFFSET MISSING +#define GPIO_PIN0_CONFIG_MASK MISSING +#define GPIO_PIN1_CONFIG_MASK MISSING +#define LOCAL_SCRATCH_OFFSET 0x18 +#define GPIO_PIN10_OFFSET MISSING +#define GPIO_PIN11_OFFSET MISSING +#define GPIO_PIN12_OFFSET MISSING +#define GPIO_PIN13_OFFSET MISSING +#define MBOX_BASE_ADDRESS MISSING +#define INT_STATUS_ENABLE_ERROR_LSB MISSING +#define INT_STATUS_ENABLE_ERROR_MASK MISSING +#define INT_STATUS_ENABLE_CPU_LSB MISSING +#define INT_STATUS_ENABLE_CPU_MASK MISSING +#define INT_STATUS_ENABLE_COUNTER_LSB MISSING +#define INT_STATUS_ENABLE_COUNTER_MASK MISSING +#define INT_STATUS_ENABLE_MBOX_DATA_LSB MISSING +#define INT_STATUS_ENABLE_MBOX_DATA_MASK MISSING +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB MISSING +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK MISSING +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB MISSING +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK MISSING +#define COUNTER_INT_STATUS_ENABLE_BIT_LSB MISSING +#define COUNTER_INT_STATUS_ENABLE_BIT_MASK MISSING +#define INT_STATUS_ENABLE_ADDRESS MISSING +#define CPU_INT_STATUS_ENABLE_BIT_LSB MISSING +#define CPU_INT_STATUS_ENABLE_BIT_MASK MISSING +#define HOST_INT_STATUS_ADDRESS MISSING +#define CPU_INT_STATUS_ADDRESS MISSING +#define ERROR_INT_STATUS_ADDRESS MISSING +#define ERROR_INT_STATUS_WAKEUP_MASK MISSING +#define ERROR_INT_STATUS_WAKEUP_LSB MISSING +#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK MISSING +#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB MISSING +#define ERROR_INT_STATUS_TX_OVERFLOW_MASK MISSING +#define ERROR_INT_STATUS_TX_OVERFLOW_LSB MISSING +#define COUNT_DEC_ADDRESS MISSING +#define HOST_INT_STATUS_CPU_MASK MISSING +#define HOST_INT_STATUS_CPU_LSB MISSING +#define HOST_INT_STATUS_ERROR_MASK MISSING +#define HOST_INT_STATUS_ERROR_LSB MISSING +#define HOST_INT_STATUS_COUNTER_MASK MISSING +#define HOST_INT_STATUS_COUNTER_LSB MISSING +#define RX_LOOKAHEAD_VALID_ADDRESS MISSING +#define WINDOW_DATA_ADDRESS MISSING +#define WINDOW_READ_ADDR_ADDRESS MISSING +#define WINDOW_WRITE_ADDR_ADDRESS MISSING +/* GPIO Register */ +#define GPIO_ENABLE_W1TS_LOW_ADDRESS MISSING +#define GPIO_PIN0_CONFIG_LSB MISSING +#define GPIO_PIN0_PAD_PULL_LSB MISSING +#define GPIO_PIN0_PAD_PULL_MASK MISSING +/* SI reg */ +#define SI_CONFIG_ERR_INT_MASK MISSING +#define SI_CONFIG_ERR_INT_LSB MISSING + +#define RTC_SOC_BASE_ADDRESS MISSING +#define RTC_WMAC_BASE_ADDRESS MISSING +#define SOC_CORE_BASE_ADDRESS MISSING +#define WLAN_MAC_BASE_ADDRESS MISSING +#define GPIO_BASE_ADDRESS MISSING +#define ANALOG_INTF_BASE_ADDRESS MISSING +#define CE0_BASE_ADDRESS MISSING +#define CE1_BASE_ADDRESS MISSING +#define CE_COUNT 12 +#define CE_WRAPPER_BASE_ADDRESS MISSING +#define SI_BASE_ADDRESS MISSING +#define DRAM_BASE_ADDRESS MISSING + +#define WLAN_SYSTEM_SLEEP_DISABLE_LSB MISSING +#define WLAN_SYSTEM_SLEEP_DISABLE_MASK MISSING +#define CLOCK_CONTROL_OFFSET MISSING +#define CLOCK_CONTROL_SI0_CLK_MASK MISSING +#define RESET_CONTROL_SI0_RST_MASK MISSING +#define WLAN_RESET_CONTROL_OFFSET MISSING +#define WLAN_RESET_CONTROL_COLD_RST_MASK MISSING +#define WLAN_RESET_CONTROL_WARM_RST_MASK MISSING +#define CPU_CLOCK_OFFSET MISSING + +#define CPU_CLOCK_STANDARD_LSB MISSING +#define CPU_CLOCK_STANDARD_MASK MISSING +#define LPO_CAL_ENABLE_LSB MISSING +#define LPO_CAL_ENABLE_MASK MISSING +#define WLAN_SYSTEM_SLEEP_OFFSET MISSING + +#define SOC_CHIP_ID_ADDRESS MISSING +#define SOC_CHIP_ID_REVISION_MASK MISSING +#define SOC_CHIP_ID_REVISION_LSB MISSING +#define SOC_CHIP_ID_REVISION_MSB MISSING + +#define FW_IND_EVENT_PENDING MISSING +#define FW_IND_INITIALIZED MISSING + +#define MSDU_LINK_EXT_3_TCP_OVER_IPV4_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_TCP_OVER_IPV6_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV4_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV6_CHECKSUM_EN_MASK MISSING +#define MSDU_LINK_EXT_3_TCP_OVER_IPV4_CHECKSUM_EN_LSB MISSING +#define MSDU_LINK_EXT_3_TCP_OVER_IPV6_CHECKSUM_EN_LSB MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV4_CHECKSUM_EN_LSB MISSING +#define MSDU_LINK_EXT_3_UDP_OVER_IPV6_CHECKSUM_EN_LSB MISSING + +#define SR_WR_INDEX_ADDRESS MISSING +#define DST_WATERMARK_ADDRESS MISSING + +#define DST_WR_INDEX_ADDRESS MISSING +#define SRC_WATERMARK_ADDRESS MISSING +#define SRC_WATERMARK_LOW_MASK MISSING +#define SRC_WATERMARK_HIGH_MASK MISSING +#define DST_WATERMARK_LOW_MASK MISSING +#define DST_WATERMARK_HIGH_MASK MISSING +#define CURRENT_SRRI_ADDRESS MISSING +#define CURRENT_DRRI_ADDRESS MISSING +#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK MISSING +#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK MISSING +#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK MISSING +#define HOST_IS_DST_RING_LOW_WATERMARK_MASK MISSING +#define HOST_IS_ADDRESS MISSING +#define MISC_IS_ADDRESS MISSING +#define HOST_IS_COPY_COMPLETE_MASK MISSING +#define CE_WRAPPER_BASE_ADDRESS MISSING +#define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS MISSING +#define CE_DDR_ADDRESS_FOR_RRI_LOW MISSING +#define CE_DDR_ADDRESS_FOR_RRI_HIGH MISSING + +#define HOST_IE_ADDRESS \ + HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_ADDR(\ + WFSS_CE_COMMON_REG_REG_BASE) +#define HOST_IE_REG1_CE_LSB HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_SRC_RING_IE_SHFT +#define HOST_IE_ADDRESS_2 \ + HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_1_ADDR(\ + WFSS_CE_COMMON_REG_REG_BASE) +#define HOST_IE_REG2_CE_LSB HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_1_STS_RING_IE_SHFT +#define HOST_IE_ADDRESS_3 \ + HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_ADDR(\ + WFSS_CE_COMMON_REG_REG_BASE) +#define HOST_IE_REG3_CE_LSB HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_DST_RING_IE_SHFT + +#define HOST_IE_COPY_COMPLETE_MASK MISSING +#define SR_BA_ADDRESS MISSING +#define SR_BA_ADDRESS_HIGH MISSING +#define SR_SIZE_ADDRESS MISSING +#define CE_CTRL1_ADDRESS MISSING +#define CE_CTRL1_DMAX_LENGTH_MASK MISSING +#define DR_BA_ADDRESS MISSING +#define DR_BA_ADDRESS_HIGH MISSING +#define DR_SIZE_ADDRESS MISSING +#define CE_CMD_REGISTER MISSING +#define CE_MSI_ADDRESS MISSING +#define CE_MSI_ADDRESS_HIGH MISSING +#define CE_MSI_DATA MISSING +#define CE_MSI_ENABLE_BIT MISSING +#define MISC_IE_ADDRESS MISSING +#define MISC_IS_AXI_ERR_MASK MISSING +#define MISC_IS_DST_ADDR_ERR_MASK MISSING +#define MISC_IS_SRC_LEN_ERR_MASK MISSING +#define MISC_IS_DST_MAX_LEN_VIO_MASK MISSING +#define MISC_IS_DST_RING_OVERFLOW_MASK MISSING +#define MISC_IS_SRC_RING_OVERFLOW_MASK MISSING +#define SRC_WATERMARK_LOW_LSB MISSING +#define SRC_WATERMARK_HIGH_LSB MISSING +#define DST_WATERMARK_LOW_LSB MISSING +#define DST_WATERMARK_HIGH_LSB MISSING +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK MISSING +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB MISSING +#define CE_CTRL1_DMAX_LENGTH_LSB MISSING +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK MISSING +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK MISSING +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB MISSING +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB MISSING +#define CE_CTRL1_IDX_UPD_EN_MASK MISSING +#define CE_WRAPPER_DEBUG_OFFSET MISSING +#define CE_WRAPPER_DEBUG_SEL_MSB MISSING +#define CE_WRAPPER_DEBUG_SEL_LSB MISSING +#define CE_WRAPPER_DEBUG_SEL_MASK MISSING +#define CE_DEBUG_OFFSET MISSING +#define CE_DEBUG_SEL_MSB MISSING +#define CE_DEBUG_SEL_LSB MISSING +#define CE_DEBUG_SEL_MASK MISSING +#define CE0_BASE_ADDRESS MISSING +#define CE1_BASE_ADDRESS MISSING +#define A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES MISSING +#define A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_STATUS MISSING + +#define QCN9000_BOARD_DATA_SZ MISSING +#define QCN9000_BOARD_EXT_DATA_SZ MISSING + +#define MY_TARGET_DEF QCN9000_TARGETDEF +#define MY_HOST_DEF QCN9000_HOSTDEF +#define MY_CEREG_DEF QCN9000_CE_TARGETDEF +#define MY_TARGET_BOARD_DATA_SZ QCN9000_BOARD_DATA_SZ +#define MY_TARGET_BOARD_EXT_DATA_SZ QCN9000_BOARD_EXT_DATA_SZ +#include "targetdef.h" +#include "hostdef.h" +qdf_export_symbol(QCN9000_CE_TARGETDEF); +#else +#include "common_drv.h" +#include "targetdef.h" +#include "hostdef.h" +struct targetdef_s *QCN9000_TARGETDEF; +struct hostdef_s *QCN9000_HOSTDEF; +#endif /*QCN9000_HEADERS_DEF */ +qdf_export_symbol(QCN9000_TARGETDEF); +qdf_export_symbol(QCN9000_HOSTDEF); diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/regtable.c b/drivers/staging/qca-wifi-host-cmn/hif/src/regtable.c index 82d2feae11c288151856c07e2072d987bf99ff73..a6496b1cab0c0870314b303d5cb772b17e5b5d12 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/regtable.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/regtable.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 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 @@ -126,6 +126,14 @@ void hif_target_register_tbl_attach(struct hif_softc *scn, u32 target_type) break; #endif +#if defined(QCN9000_HEADERS_DEF) + case TARGET_TYPE_QCN9000: + scn->targetdef = QCN9000_TARGETDEF; + scn->target_ce_def = QCN9000_CE_TARGETDEF; + HIF_TRACE("%s: TARGET_TYPE_QCN9000", __func__); + break; +#endif + #if defined(QCA6390_HEADERS_DEF) case TARGET_TYPE_QCA6390: scn->targetdef = QCA6390_TARGETdef; @@ -134,6 +142,21 @@ void hif_target_register_tbl_attach(struct hif_softc *scn, u32 target_type) break; #endif /* QCA6390_HEADERS_DEF */ +#if defined(QCA6490_HEADERS_DEF) + case TARGET_TYPE_QCA6490: + scn->targetdef = QCA6490_TARGETdef; + scn->target_ce_def = QCA6490_CE_TARGETdef; + HIF_TRACE("%s: TARGET_TYPE_QCA6490", __func__); + break; +#endif /* QCA6490_HEADERS_DEF */ + +#if defined(QCA6750_HEADERS_DEF) + case TARGET_TYPE_QCA6750: + scn->targetdef = QCA6750_TARGETdef; + scn->target_ce_def = QCA6750_CE_TARGETdef; + HIF_TRACE("%s: TARGET_TYPE_QCA6750", __func__); + break; +#endif /* QCA6750_HEADERS_DEF */ default: break; } @@ -222,6 +245,11 @@ void hif_register_tbl_attach(struct hif_softc *scn, u32 hif_type) scn->hostdef = QCA6290_HOSTdef; break; #endif +#if defined(QCN9000_HEADERS_DEF) + case HIF_TYPE_QCN9000: + scn->hostdef = QCN9000_HOSTDEF; + break; +#endif #if defined(QCA6390_HEADERS_DEF) case HIF_TYPE_QCA6390: @@ -230,6 +258,19 @@ void hif_register_tbl_attach(struct hif_softc *scn, u32 hif_type) break; #endif /* QCA6390_HEADERS_DEF */ +#if defined(QCA6490_HEADERS_DEF) + case HIF_TYPE_QCA6490: + scn->hostdef = QCA6490_HOSTdef; + HIF_TRACE("%s: HIF_TYPE_QCA6490", __func__); + break; +#endif /* QCA6490_HEADERS_DEF */ + +#if defined(QCA6750_HEADERS_DEF) + case TARGET_TYPE_QCA6750: + scn->hostdef = QCA6750_HOSTdef; + HIF_TRACE("%s: TARGET_TYPE_QCA6750", __func__); + break; +#endif /* QCA6750_HEADERS_DEF */ default: break; } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_bmi_reg_access.c b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_bmi_reg_access.c index d274d841588afe6bcd9ea2df1e094a8a30c42ad2..ada36b00f665b5f05ab6e3ef9964e6b8ae61d073 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_bmi_reg_access.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_bmi_reg_access.c @@ -25,6 +25,7 @@ #include "htc_api.h" #include "if_sdio.h" #include "regtable_sdio.h" +#include "hif_sdio_dev.h" #define BMI_COMMUNICATION_TIMEOUT 100000 diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_diag_reg_access.c b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_diag_reg_access.c index 0f4d50c83abb402efc57e908694f638b684dfd86..30e363552fd5d6556f2dd014f527f3eccc68acce 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_diag_reg_access.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_diag_reg_access.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -26,7 +26,7 @@ #include "hif.h" #include "if_sdio.h" #include "regtable_sdio.h" - +#include "hif_sdio_dev.h" #include "qdf_module.h" #define CPU_DBG_SEL_ADDRESS 0x00000483 diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio.c b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio.c index 39aaf8e7399c41c92c4448284c619c252dead8dc..5636c4702af864cf5df96d49414740ec84520179 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio.c @@ -37,6 +37,7 @@ #include "hif_sdio_dev.h" #include "if_sdio.h" #include "regtable_sdio.h" +#include #define ATH_MODULE_NAME hif_sdio @@ -53,8 +54,16 @@ uint32_t hif_start(struct hif_opaque_softc *hif_ctx) struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); struct hif_sdio_dev *hif_device = scn->hif_handle; struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device); + struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx); + int ret = 0; HIF_ENTER(); + ret = hif_sdio_bus_configure(hif_sc); + if (ret) { + HIF_ERROR("%s: hif_sdio_bus_configure failed", __func__); + return QDF_STATUS_E_FAILURE; + } + hif_dev_enable_interrupts(htc_sdio_device); HIF_EXIT(); return QDF_STATUS_SUCCESS; diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_common.h b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_common.h index dc0900da898803f1220a4fbfc0732a145898c93d..21977f2a7045be40c0ef5dd5bd237d32100079f0 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_common.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -26,11 +26,13 @@ #define MANUFACTURER_ID_AR6320_BASE 0x500 #define MANUFACTURER_ID_QCA9377_BASE 0x700 #define MANUFACTURER_ID_QCA9379_BASE 0x800 -#define MANUFACTURER_ID_QCN7605_BASE 0x0000 /*TODO - GenoaSDIO */ +#define MANUFACTURER_ID_QCN7605 0x400B +#define MANUFACTURER_ID_QCN7605_BASE 0x4000 #define MANUFACTURER_ID_AR6K_BASE_MASK 0xFF00 #define MANUFACTURER_ID_AR6K_REV_MASK 0x00FF #define FUNCTION_CLASS 0x0 -#define MANUFACTURER_CODE 0x271 +#define MANUFACTURER_CODE 0x271 /* Atheros Manufacturer ID */ +#define MANUFACTURER_QC_CODE 0x70 /* QC Manufacturer ID */ #endif /* _HIF_SDIO_COMMON_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_dev.c b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_dev.c index 253cf2768080813a013132557b82e8b21ffb0754..ba2277a3bb866b4d3ca351a4bde53c64ae79794e 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_dev.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_dev.c @@ -208,127 +208,6 @@ QDF_STATUS hif_dev_enable_interrupts(struct hif_sdio_device *pdev) return status; } -#define DEV_CHECK_RECV_YIELD(pdev) \ - ((pdev)->CurrentDSRRecvCount >= \ - (pdev)->HifIRQYieldParams.recv_packet_yield_count) - -/** - * hif_dev_dsr_handler() - Synchronous interrupt handler - * - * @context: hif send context - * - * Return: 0 for success and non-zero for failure - */ -QDF_STATUS hif_dev_dsr_handler(void *context) -{ - struct hif_sdio_device *pdev = (struct hif_sdio_device *)context; - QDF_STATUS status = QDF_STATUS_SUCCESS; - bool done = false; - bool async_proc = false; - - HIF_ENTER(); - - /* reset the recv counter that tracks when we need - * to yield from the DSR - */ - pdev->CurrentDSRRecvCount = 0; - /* reset counter used to flag a re-scan of IRQ - * status registers on the target - */ - pdev->RecheckIRQStatusCnt = 0; - - while (!done) { - status = hif_dev_process_pending_irqs(pdev, &done, &async_proc); - if (QDF_IS_STATUS_ERROR(status)) - break; - - if (pdev->HifIRQProcessingMode == HIF_DEVICE_IRQ_SYNC_ONLY) { - /* the HIF layer does not allow async IRQ processing, - * override the asyncProc flag - */ - async_proc = false; - /* this will cause us to re-enter ProcessPendingIRQ() - * and re-read interrupt status registers. - * This has a nice side effect of blocking us until all - * async read requests are completed. This behavior is - * required as we do not allow ASYNC processing - * in interrupt handlers (like Windows CE) - */ - - if (pdev->DSRCanYield && DEV_CHECK_RECV_YIELD(pdev)) - /* ProcessPendingIRQs() pulled enough recv - * messages to satisfy the yield count, stop - * checking for more messages and return - */ - break; - } - - if (async_proc) { - /* the function does some async I/O for performance, - * we need to exit the ISR immediately, the check below - * will prevent the interrupt from being - * Ack'd while we handle it asynchronously - */ - break; - } - } - - if (QDF_IS_STATUS_SUCCESS(status) && !async_proc) { - /* Ack the interrupt only if : - * 1. we did not get any errors in processing interrupts - * 2. there are no outstanding async processing requests - */ - if (pdev->DSRCanYield) { - /* if the DSR can yield do not ACK the interrupt, there - * could be more pending messages. The HIF layer - * must ACK the interrupt on behalf of HTC - */ - HIF_INFO("%s: Yield (RX count: %d)", - __func__, pdev->CurrentDSRRecvCount); - } else { - HIF_INFO("%s: Ack interrupt", __func__); - hif_ack_interrupt(pdev->HIFDevice); - } - } - - HIF_EXIT(); - return status; -} - -/** hif_dev_set_mailbox_swap() - Set the mailbox swap from firmware - * @pdev : The HIF layer object - * - * Return: none - */ -void hif_dev_set_mailbox_swap(struct hif_sdio_dev *pdev) -{ - struct hif_sdio_device *hif_device = hif_dev_from_hif(pdev); - - HIF_ENTER(); - - hif_device->swap_mailbox = true; - - HIF_EXIT(); -} - -/** hif_dev_get_mailbox_swap() - Get the mailbox swap setting - * @pdev : The HIF layer object - * - * Return: none - */ -bool hif_dev_get_mailbox_swap(struct hif_sdio_dev *pdev) -{ - struct hif_sdio_device *hif_device; - - HIF_ENTER(); - - hif_device = hif_dev_from_hif(pdev); - - HIF_EXIT(); - - return hif_device->swap_mailbox; -} - /** * hif_dev_setup() - set up sdio device. * @pDev: sdio device context @@ -346,7 +225,6 @@ QDF_STATUS hif_dev_setup(struct hif_sdio_device *pdev) status = hif_dev_setup_device(pdev); - if (status != QDF_STATUS_SUCCESS) { HIF_ERROR("%s: device specific setup failed", __func__); return QDF_STATUS_E_INVAL; diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_dev.h b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_dev.h index 5dbe6820c9d39787b61f6c85bec3c2dc3f9dad3c..7ee6582e6aa80beb29bae570c427c80cb6059f19 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_dev.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_dev.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2016, 2018-2019 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 @@ -26,6 +26,7 @@ #include #include "athstartpack.h" #include "hif_internal.h" +#include "if_sdio.h" struct hif_sdio_device *hif_dev_from_hif(struct hif_sdio_dev *hif_device); @@ -47,7 +48,7 @@ QDF_STATUS hif_dev_send_buffer(struct hif_sdio_device *htc_sdio_device, QDF_STATUS hif_dev_process_pending_irqs(struct hif_sdio_device *pdev, bool *done, - bool *async_processing); + bool *async_processing); void hif_dev_mask_interrupts(struct hif_sdio_device *pdev); @@ -60,9 +61,9 @@ void hif_dev_unmask_interrupts(struct hif_sdio_device *pdev); int hif_dev_setup_device(struct hif_sdio_device *pdev); -QDF_STATUS hif_dev_get_fifo_address(struct hif_sdio_dev *pdev, - struct hif_device_mbox_info *config, - uint32_t config_len); +int hif_dev_get_fifo_address(struct hif_sdio_dev *pdev, + void *config, + uint32_t config_len); void hif_dev_get_block_size(void *config); @@ -70,8 +71,93 @@ void hif_dev_set_mailbox_swap(struct hif_sdio_dev *pdev); bool hif_dev_get_mailbox_swap(struct hif_sdio_dev *pdev); -int hif_sdio_set_drvdata(struct sdio_func *func, - struct hif_sdio_dev *hifdevice); - -struct hif_sdio_dev *get_hif_device(struct sdio_func *func); +QDF_STATUS hif_read_write(struct hif_sdio_dev *device, unsigned long address, + char *buffer, uint32_t length, uint32_t request, + void *context); + +#ifdef CONFIG_SDIO_TRANSFER_MAILBOX +static inline struct hif_sdio_dev *get_hif_device(struct hif_softc *hif_ctx, + struct sdio_func *func) +{ + qdf_assert(func); + return (struct hif_sdio_dev *)sdio_get_drvdata(func); +} + +/** + * hif_sdio_set_drvdata() - set wlan driver data into upper layer private + * @hif_ctx: HIF object + * @func: pointer to sdio function + * @hifdevice: pointer to hif device + * + * Return: zero for success. + */ +static inline int hif_sdio_set_drvdata(struct hif_softc *hif_ctx, + struct sdio_func *func, + struct hif_sdio_dev *hifdevice) +{ + sdio_set_drvdata(func, hifdevice); + return 0; +} + +static inline int hif_dev_configure_pipes(struct hif_sdio_dev *pdev, + struct sdio_func *func) +{ + return 0; +} + +static inline int hif_dev_register_channels(struct hif_sdio_dev *dev, + struct sdio_func *func) +{ + return 0; +} + +static inline void hif_dev_unregister_channels(struct hif_sdio_dev *dev, + struct sdio_func *func) +{ +} +#else +static inline struct hif_sdio_dev *get_hif_device(struct hif_softc *hif_ctx, + struct sdio_func *func) +{ + struct hif_sdio_softc *scn = (struct hif_sdio_softc *)hif_ctx; + + return (struct hif_sdio_dev *)scn->hif_handle; +} + +/** + * hif_sdio_set_drvdata() - set wlan driver data into upper layer private + * @hif_ctx: HIF object + * @func: pointer to sdio function + * @hifdevice: pointer to hif device + * + * Return: zero for success. + */ +static inline int hif_sdio_set_drvdata(struct hif_softc *hif_ctx, + struct sdio_func *func, + struct hif_sdio_dev *hifdevice) +{ + struct hif_sdio_softc *sc = (struct hif_sdio_softc *)hif_ctx; + + sc->hif_handle = hifdevice; + + return 0; +} + +int hif_dev_configure_pipes(struct hif_sdio_dev *pdev, + struct sdio_func *func); + +int hif_dev_register_channels(struct hif_sdio_dev *dev, + struct sdio_func *func); + +void hif_dev_unregister_channels(struct hif_sdio_dev *dev, + struct sdio_func *func); +#endif /* SDIO_TRANSFER */ +QDF_STATUS hif_enable_func(struct hif_softc *ol_sc, struct hif_sdio_dev *device, + struct sdio_func *func, bool resume); +QDF_STATUS hif_disable_func(struct hif_sdio_dev *device, + struct sdio_func *func, + bool reset); +A_STATUS hif_sdio_probe(struct hif_softc *ol_sc, + struct sdio_func *func, + struct hif_sdio_dev *device); #endif /* HIF_SDIO_DEV_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_internal.h b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_internal.h index 67c8ebfab7f189077cccd61a39965deb31623b0e..b378575d085489bdb07b65752ba077cbba309036 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_internal.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/hif_sdio_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016-2019 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 @@ -28,7 +28,7 @@ #if defined(CONFIG_SDIO_TRANSFER_MAILBOX) #include #elif defined(CONFIG_SDIO_TRANSFER_ADMA) -#error "Error - Not implemented yet" +#include #else #error "Error - Invalid transfer method" #endif @@ -54,7 +54,6 @@ struct hif_sdio_device { qdf_spinlock_t TxLock; qdf_spinlock_t RxLock; struct hif_msg_callbacks hif_callbacks; - struct hif_device_mbox_info MailBoxInfo; uint32_t BlockSize; uint32_t BlockMask; enum hif_device_irq_mode HifIRQProcessingMode; @@ -65,8 +64,11 @@ struct hif_sdio_device { int RecheckIRQStatusCnt; uint32_t RecvStateFlags; void *pTarget; - bool swap_mailbox; struct devRegisters devRegisters; +#ifdef CONFIG_SDIO_TRANSFER_MAILBOX + bool swap_mailbox; + struct hif_device_mbox_info MailBoxInfo; +#endif }; #define LOCK_HIF_DEV(device) qdf_spin_lock(&(device)->Lock) diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/if_sdio.c b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/if_sdio.c index 0b98d0baf5d8b08b88a4b5fcd67dacbc0400b9a2..102b84d09fff387d8e53f46ada087622e5493c32 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/if_sdio.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/if_sdio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -181,7 +181,7 @@ void hif_sdio_disable_bus(struct hif_softc *hif_sc) { struct sdio_func *func = dev_to_sdio_func(hif_sc->qdf_dev->dev); - hif_sdio_device_removed(func); + hif_sdio_device_removed(hif_sc, func); } /** diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/if_sdio.h b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/if_sdio.h index 1891c8b3e939ded30c7f8b66070ee82be81cc71b..191ea615ec237863b037d0798c4476bea9709904 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/if_sdio.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/if_sdio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -83,7 +83,7 @@ int hif_sdio_device_inserted(struct hif_softc *ol_sc, const struct sdio_device_id *id); void hif_sdio_stop(struct hif_softc *hif_ctx); void hif_sdio_shutdown(struct hif_softc *hif_ctx); -void hif_sdio_device_removed(struct sdio_func *func); +void hif_sdio_device_removed(struct hif_softc *hif_ctx, struct sdio_func *func); int hif_device_suspend(struct hif_softc *ol_sc, struct device *dev); int hif_device_resume(struct hif_softc *ol_sc, struct device *dev); void hif_register_tbl_attach(struct hif_softc *scn, diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/include/hif_internal.h b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/include/hif_internal.h index 8f2719a22802615f5810b96dd5ce2e8739fe75d7..41001c848ae984d2183361516ade24ef4ece9e96 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/include/hif_internal.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/include/hif_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -35,6 +35,7 @@ #include #include #include +#include #include "hif.h" #include "hif_debug.h" #include "hif_sdio_common.h" @@ -167,7 +168,7 @@ struct bus_request { struct bus_request *next; /* link list of available requests */ struct bus_request *inusenext; /* link list of in use requests */ struct semaphore sem_req; - uint32_t address; /* request data */ + unsigned long address; /* request data */ char *buffer; uint32_t length; uint32_t request; @@ -176,6 +177,14 @@ struct bus_request { struct HIF_SCATTER_REQ_PRIV *scatter_req; }; +#define HIF_ADMA_MAX_CHANS 2 +#ifdef CONFIG_SDIO_TRANSFER_ADMA +struct rx_q_entry { + qdf_list_node_t entry; + qdf_nbuf_t nbuf; +}; +#endif + struct hif_sdio_dev { struct sdio_func *func; qdf_spinlock_t asynclock; @@ -201,6 +210,15 @@ struct hif_sdio_dev { const struct sdio_device_id *id; struct mmc_host *host; void *htc_context; +#ifdef CONFIG_SDIO_TRANSFER_ADMA + struct sdio_al_client_handle *al_client; + struct sdio_al_channel_handle *al_chan[HIF_ADMA_MAX_CHANS]; + uint8_t adma_chans_used; + qdf_list_t rx_q; + qdf_spinlock_t rx_q_lock; + qdf_work_t rx_q_alloc_work; + bool rx_q_alloc_work_scheduled; +#endif }; struct HIF_DEVICE_OS_DEVICE_INFO { @@ -270,18 +288,13 @@ QDF_STATUS hif_configure_device(struct hif_softc *ol_sc, QDF_STATUS hif_attach_htc(struct hif_sdio_dev *device, struct htc_callbacks *callbacks); -QDF_STATUS hif_read_write(struct hif_sdio_dev *device, - uint32_t address, - char *buffer, - uint32_t length, uint32_t request, void *context); - void hif_ack_interrupt(struct hif_sdio_dev *device); void hif_mask_interrupt(struct hif_sdio_dev *device); void hif_un_mask_interrupt(struct hif_sdio_dev *device); -void hif_sdio_configure_pipes(struct hif_sdio_dev *dev, struct sdio_func *func); +int hif_sdio_configure_pipes(struct hif_sdio_dev *dev, struct sdio_func *func); struct _HIF_SCATTER_ITEM { u_int8_t *buffer; /* CPU accessible address of buffer */ @@ -400,14 +413,14 @@ static inline QDF_STATUS do_hif_read_write_scatter(struct hif_sdio_dev *device, #define SDIO_SET_CMD52_WRITE_ARG(arg, func, address, value) \ SDIO_SET_CMD52_ARG(arg, 1, (func), 0, address, value) -void hif_sdio_quirk_force_drive_strength(struct sdio_func *func); -void hif_sdio_quirk_write_cccr(struct sdio_func *func); -int hif_sdio_quirk_mod_strength(struct sdio_func *func); -int hif_sdio_quirk_async_intr(struct sdio_func *func); -int hif_sdio_set_bus_speed(struct sdio_func *func); -int hif_sdio_set_bus_width(struct sdio_func *func); -int hif_sdio_func_enable(struct hif_sdio_dev *device, - struct sdio_func *func); +void hif_sdio_quirk_force_drive_strength(struct hif_softc *ol_sc, + struct sdio_func *func); +void hif_sdio_quirk_write_cccr(struct hif_softc *ol_sc, struct sdio_func *func); +int hif_sdio_quirk_mod_strength(struct hif_softc *ol_sc, + struct sdio_func *func); +int hif_sdio_quirk_async_intr(struct hif_softc *ol_sc, struct sdio_func *func); +int hif_sdio_set_bus_speed(struct hif_softc *ol_sc, struct sdio_func *func); +int hif_sdio_set_bus_width(struct hif_softc *ol_sc, struct sdio_func *func); QDF_STATUS hif_sdio_func_disable(struct hif_sdio_dev *device, struct sdio_func *func, bool reset); diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/src/dev_quirks.c b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/src/dev_quirks.c index b84f1ab8b7e0ef3da87c8d3c5efe17a37ff01b7b..7c7e63ba01185d2c75f436bba67bbaaec01d425e 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/src/dev_quirks.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/src/dev_quirks.c @@ -1,8 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. - * - * - * + * Copyright (c) 2013-2019 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 @@ -91,8 +88,10 @@ module_param(brokenirq, uint, 0644); MODULE_PARM_DESC(brokenirq, "Set as 1 to use polling method instead of interrupt mode"); +#ifdef CONFIG_SDIO_TRANSFER_MAILBOX /** * hif_sdio_force_drive_strength() - Set SDIO drive strength + * @ol_sc: softc instance * @func: pointer to sdio_func * * This function forces the driver strength of the SDIO @@ -100,61 +99,156 @@ MODULE_PARM_DESC(brokenirq, * * Return: none. */ -void hif_sdio_quirk_force_drive_strength(struct sdio_func *func) +void hif_sdio_quirk_force_drive_strength(struct hif_softc *ol_sc, + struct sdio_func *func) { int err = 0; unsigned char value = 0; uint32_t mask = 0, addr = SDIO_CCCR_DRIVE_STRENGTH; - struct hif_sdio_dev *device = sdio_get_drvdata(func); - uint16_t manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; + err = func0_cmd52_read_byte(func->card, addr, &value); + if (err) { + HIF_ERROR("%s: read driver strength 0x%02X fail %d\n", + __func__, addr, err); + return; + } + + mask = (SDIO_DRIVE_DTSx_MASK << SDIO_DRIVE_DTSx_SHIFT); + value = (value & ~mask) | SDIO_DTSx_SET_TYPE_D; + err = func0_cmd52_write_byte(func->card, addr, value); + if (err) { + HIF_ERROR("%s: write driver strength failed", __func__); + HIF_ERROR("%s: 0x%02X to 0x%02X failed: %d\n", __func__, + (uint32_t)value, addr, err); + return; + } + + value = 0; + addr = CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR; + err = func0_cmd52_read_byte(func->card, addr, &value); + if (err) { + HIF_ERROR("%s Read CCCR 0x%02X failed: %d\n", + __func__, addr, err); + return; + } + + mask = CCCR_SDIO_DRIVER_STRENGTH_ENABLE_MASK; + value = (value & ~mask) | CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A | + CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C | + CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D; + err = func0_cmd52_write_byte(func->card, addr, value); + if (err) + HIF_ERROR("%s Write CCCR 0x%02X to 0x%02X failed: %d\n", + __func__, addr, value, err); +} + +/** + * hif_sdio_quirk_async_intr() - Set asynchronous interrupt settings + * @ol_sc: softc instance + * @func: pointer to sdio_func + * + * The values are taken from the module parameter asyncintdelay + * Call this with the sdhci host claimed + * + * Return: none. + */ +int hif_sdio_quirk_async_intr(struct hif_softc *ol_sc, struct sdio_func *func) +{ + uint8_t data; + uint16_t manfid; + int set_async_irq = 0, ret = 0; + struct hif_sdio_dev *device = get_hif_device(ol_sc, func); + + manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; switch (manfid) { - case MANUFACTURER_ID_QCN7605_BASE: + case MANUFACTURER_ID_AR6003_BASE: + set_async_irq = 1; + ret = + func0_cmd52_write_byte(func->card, + CCCR_SDIO_IRQ_MODE_REG_AR6003, + SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6003); + if (ret) + return ret; break; - default: - err = func0_cmd52_read_byte(func->card, addr, &value); - if (err) { - HIF_ERROR("%s: read driver strength 0x%02X fail %d\n", - __func__, addr, err); - break; - } + case MANUFACTURER_ID_AR6320_BASE: + case MANUFACTURER_ID_QCA9377_BASE: + case MANUFACTURER_ID_QCA9379_BASE: + set_async_irq = 1; + ret = func0_cmd52_read_byte(func->card, + CCCR_SDIO_IRQ_MODE_REG_AR6320, + &data); + if (ret) + return ret; - mask = (SDIO_DRIVE_DTSx_MASK << SDIO_DRIVE_DTSx_SHIFT); - value = (value & ~mask) | SDIO_DTSx_SET_TYPE_D; - err = func0_cmd52_write_byte(func->card, addr, value); - if (err) { - HIF_ERROR("%s: write driver strength failed", __func__); - HIF_ERROR("%s: 0x%02X to 0x%02X failed: %d\n", __func__, - (uint32_t)value, addr, err); - break; - } + data |= SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6320; + ret = func0_cmd52_write_byte(func->card, + CCCR_SDIO_IRQ_MODE_REG_AR6320, + data); + if (ret) + return ret; + break; + } - value = 0; - addr = CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR; - err = func0_cmd52_read_byte(func->card, addr, &value); - if (err) { - HIF_ERROR("%s Read CCCR 0x%02X failed: %d\n", - __func__, addr, err); - break; - } + if (asyncintdelay) { + /* Set CCCR 0xF0[7:6] to increase async interrupt delay clock + * to fix interrupt missing issue on dell 8460p + */ - mask = CCCR_SDIO_DRIVER_STRENGTH_ENABLE_MASK; - value = (value & ~mask) | - CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A | - CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C | - CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D; - err = func0_cmd52_write_byte(func->card, addr, value); - if (err) - HIF_ERROR("%s Write CCCR 0x%02X to 0x%02X failed: %d\n", - __func__, addr, value, err); + ret = func0_cmd52_read_byte(func->card, + CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS, + &data); + if (ret) + return ret; - break; + data = (data & ~CCCR_SDIO_ASYNC_INT_DELAY_MASK) | + ((asyncintdelay << CCCR_SDIO_ASYNC_INT_DELAY_LSB) & + CCCR_SDIO_ASYNC_INT_DELAY_MASK); + + ret = func0_cmd52_write_byte(func->card, + CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS, + data); + if (ret) + return ret; } + + return ret; +} +#else +/** + * hif_sdio_force_drive_strength() - Set SDIO drive strength + * @ol_sc: softc instance + * @func: pointer to sdio_func + * + * This function forces the driver strength of the SDIO + * Call this with the sdhci host claimed + * + * Return: none. + */ +void hif_sdio_quirk_force_drive_strength(struct hif_softc *ol_sc, + struct sdio_func *func) +{ } +/** + * hif_sdio_quirk_async_intr() - Set asynchronous interrupt settings + * @ol_sc: softc instance + * @func: pointer to sdio_func + * + * The values are taken from the module parameter asyncintdelay + * Call this with the sdhci host claimed + * + * Return: none. + */ +int hif_sdio_quirk_async_intr(struct hif_softc *ol_sc, struct sdio_func *func) +{ + return 0; +} +#endif + /** * hif_sdio_quirk_write_cccr() - write a desired CCCR register + * @ol_sc: softc instance * @func: pointer to sdio_func * * The values are taken from the module parameter writecccr @@ -162,7 +256,7 @@ void hif_sdio_quirk_force_drive_strength(struct sdio_func *func) * * Return: none. */ -void hif_sdio_quirk_write_cccr(struct sdio_func *func) +void hif_sdio_quirk_write_cccr(struct hif_softc *ol_sc, struct sdio_func *func) { int32_t err; @@ -231,6 +325,7 @@ void hif_sdio_quirk_write_cccr(struct sdio_func *func) /** * hif_sdio_quirk_mod_strength() - write a desired CCCR register + * @ol_sc: softc instance * @func: pointer to sdio_func * * The values are taken from the module parameter writecccr @@ -238,11 +333,11 @@ void hif_sdio_quirk_write_cccr(struct sdio_func *func) * * Return: none. */ -int hif_sdio_quirk_mod_strength(struct sdio_func *func) +int hif_sdio_quirk_mod_strength(struct hif_softc *ol_sc, struct sdio_func *func) { int ret = 0; uint32_t addr, value; - struct hif_sdio_dev *device = sdio_get_drvdata(func); + struct hif_sdio_dev *device = get_hif_device(ol_sc, func); uint16_t manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; if (!modstrength) /* TODO: Dont set this : scn is not popolated yet */ @@ -287,82 +382,6 @@ int hif_sdio_quirk_mod_strength(struct sdio_func *func) return ret; } -/** - * hif_sdio_quirk_async_intr() - Set asynchronous interrupt settings - * @func: pointer to sdio_func - * - * The values are taken from the module parameter asyncintdelay - * Call this with the sdhci host claimed - * - * Return: none. - */ -int hif_sdio_quirk_async_intr(struct sdio_func *func) -{ - uint8_t data; - uint16_t manfid; - int set_async_irq = 0, ret = 0; - struct hif_sdio_dev *device = sdio_get_drvdata(func); - - manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; - - switch (manfid) { - case MANUFACTURER_ID_AR6003_BASE: - set_async_irq = 1; - ret = - func0_cmd52_write_byte(func->card, - CCCR_SDIO_IRQ_MODE_REG_AR6003, - SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6003); - if (ret) - return ret; - break; - case MANUFACTURER_ID_AR6320_BASE: - case MANUFACTURER_ID_QCA9377_BASE: - case MANUFACTURER_ID_QCA9379_BASE: - set_async_irq = 1; - ret = func0_cmd52_read_byte(func->card, - CCCR_SDIO_IRQ_MODE_REG_AR6320, - &data); - if (ret) - return ret; - - data |= SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_AR6320; - ret = func0_cmd52_write_byte(func->card, - CCCR_SDIO_IRQ_MODE_REG_AR6320, - data); - if (ret) - return ret; - break; - case MANUFACTURER_ID_QCN7605_BASE: - /* No async intr delay settings */ - asyncintdelay = 0; - return ret; - } - - if (asyncintdelay) { - /* Set CCCR 0xF0[7:6] to increase async interrupt delay clock - * to fix interrupt missing issue on dell 8460p - */ - - ret = func0_cmd52_read_byte(func->card, - CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS, - &data); - if (ret) - return ret; - - data = (data & ~CCCR_SDIO_ASYNC_INT_DELAY_MASK) | - ((asyncintdelay << CCCR_SDIO_ASYNC_INT_DELAY_LSB) & - CCCR_SDIO_ASYNC_INT_DELAY_MASK); - - ret = func0_cmd52_write_byte(func->card, - CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS, - data); - if (ret) - return ret; - } - - return ret; -} - #if KERNEL_VERSION(3, 4, 0) <= LINUX_VERSION_CODE #ifdef SDIO_BUS_WIDTH_8BIT static int hif_cmd52_write_byte_8bit(struct sdio_func *func) @@ -381,14 +400,15 @@ static int hif_cmd52_write_byte_8bit(struct sdio_func *func) /** * hif_sdio_set_bus_speed() - Set the sdio bus speed + * @ol_sc: softc instance * @func: pointer to sdio_func * * Return: 0 on success, error number otherwise. */ -int hif_sdio_set_bus_speed(struct sdio_func *func) +int hif_sdio_set_bus_speed(struct hif_softc *ol_sc, struct sdio_func *func) { uint32_t clock, clock_set = 12500000; - struct hif_sdio_dev *device = get_hif_device(func); + struct hif_sdio_dev *device = get_hif_device(ol_sc, func); uint16_t manfid; manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; @@ -427,16 +447,17 @@ int hif_sdio_set_bus_speed(struct sdio_func *func) /** * hif_set_bus_width() - Set the sdio bus width + * @ol_sc: softc instance * @func: pointer to sdio_func * * Return: 0 on success, error number otherwise. */ -int hif_sdio_set_bus_width(struct sdio_func *func) +int hif_sdio_set_bus_width(struct hif_softc *ol_sc, struct sdio_func *func) { int ret = 0; uint16_t manfid; uint8_t data = 0; - struct hif_sdio_dev *device = get_hif_device(func); + struct hif_sdio_dev *device = get_hif_device(ol_sc, func); manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; @@ -491,66 +512,6 @@ int hif_sdio_set_bus_width(struct sdio_func *func) return ret; } -/** - * hif_sdio_func_enable() - Handle device enabling as per device - * @device: HIF device object - * @func: function pointer - * - * Return success or failure - */ -int hif_sdio_func_enable(struct hif_sdio_dev *device, - struct sdio_func *func) -{ - uint16_t manfid; - - manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK; - - if (manfid == MANUFACTURER_ID_QCN7605_BASE) - return 0; - - if (device->is_disabled) { - int ret = 0; - - sdio_claim_host(func); - - ret = hif_sdio_quirk_async_intr(func); - if (ret) { - HIF_ERROR("%s: Error setting async intr:%d", - __func__, ret); - sdio_release_host(func); - return QDF_STATUS_E_FAILURE; - } - - func->enable_timeout = 100; - ret = sdio_enable_func(func); - if (ret) { - HIF_ERROR("%s: Unable to enable function: %d", - __func__, ret); - sdio_release_host(func); - return QDF_STATUS_E_FAILURE; - } - - ret = sdio_set_block_size(func, HIF_BLOCK_SIZE); - if (ret) { - HIF_ERROR("%s: Unable to set block size 0x%X : %d\n", - __func__, HIF_BLOCK_SIZE, ret); - sdio_release_host(func); - return QDF_STATUS_E_FAILURE; - } - - ret = hif_sdio_quirk_mod_strength(func); - if (ret) { - HIF_ERROR("%s: Error setting mod strength : %d\n", - __func__, ret); - sdio_release_host(func); - return QDF_STATUS_E_FAILURE; - } - - sdio_release_host(func); - } - - return 0; -} /** * hif_mask_interrupt() - Disable hif device irq @@ -594,11 +555,7 @@ void hif_mask_interrupt(struct hif_sdio_dev *device) */ static void hif_irq_handler(struct sdio_func *func) { - struct hif_sdio_dev *device; - - HIF_ENTER(); - - device = get_hif_device(func); + struct hif_sdio_dev *device = get_hif_device(NULL, func); atomic_set(&device->irq_handling, 1); /* release the host during intr so we can use * it when we process cmds @@ -607,8 +564,6 @@ static void hif_irq_handler(struct sdio_func *func) device->htc_callbacks.dsr_handler(device->htc_callbacks.context); sdio_claim_host(device->func); atomic_set(&device->irq_handling, 0); - - HIF_EXIT(); } /** diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/src/hif.c b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/src/hif.c index 926067c3ca27deb7ce1a6af3add0d91067b7c7af..7100baf1d616e981760ec4352f21f586195d91db 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/src/hif.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/native_sdio/src/hif.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -38,26 +37,10 @@ #include "hif_internal.h" #include -/* by default setup a bounce buffer for the data packets, - * if the underlying host controller driver - * does not use DMA you may be able to skip this step - * and save the memory allocation and transfer time - */ #define HIF_USE_DMA_BOUNCE_BUFFER 1 #define ATH_MODULE_NAME hif #include "a_debug.h" -#if HIF_USE_DMA_BOUNCE_BUFFER -/* macro to check if DMA buffer is WORD-aligned and DMA-able. - * Most host controllers assume the - * buffer is DMA'able and will bug-check otherwise (i.e. buffers on the stack). - * virt_addr_valid check fails on stack memory. - */ -#define BUFFER_NEEDS_BOUNCE(buffer) (((unsigned long)(buffer) & 0x3) || \ - !virt_addr_valid((buffer))) -#else -#define BUFFER_NEEDS_BOUNCE(buffer) (false) -#endif #define MAX_HIF_DEVICES 2 #ifdef HIF_MBOX_SLEEP_WAR #define HIF_MIN_SLEEP_INACTIVITY_TIME_MS 50 @@ -83,7 +66,8 @@ MODULE_PARM_DESC(debugcccr, "Output this cccr values"); #define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) #define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) -static struct hif_sdio_dev *add_hif_device(struct sdio_func *func); +static struct hif_sdio_dev *add_hif_device(struct hif_softc *hif_ctx, + struct sdio_func *func); static void del_hif_device(struct hif_sdio_dev *device); int reset_sdio_on_unload; @@ -171,186 +155,6 @@ ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, ATH_DEBUG_MASK_DEFAULTS, 0, NULL); #endif -/** - * __hif_read_write() - sdio read/write wrapper - * @device: pointer to hif device structure - * @address: address to read - * @buffer: buffer to hold read/write data - * @length: length to read/write - * @request: read/write/sync/async request - * @context: pointer to hold calling context - * - * Return: 0 on success, error number otherwise. - */ -static QDF_STATUS -__hif_read_write(struct hif_sdio_dev *device, - uint32_t address, char *buffer, - uint32_t length, uint32_t request, void *context) -{ - uint8_t opcode; - QDF_STATUS status = QDF_STATUS_SUCCESS; - int ret = A_OK; - uint8_t *tbuffer; - bool bounced = false; - - if (!device) { - HIF_ERROR("%s: device null!", __func__); - return QDF_STATUS_E_INVAL; - } - - if (!device->func) { - HIF_ERROR("%s: func null!", __func__); - return QDF_STATUS_E_INVAL; - } - - HIF_INFO_HI("%s: addr:0X%06X, len:%08d, %s, %s", __func__, - address, length, - request & HIF_SDIO_READ ? "Read " : "Write", - request & HIF_ASYNCHRONOUS ? "Async" : "Sync "); - - do { - if (request & HIF_EXTENDED_IO) { - HIF_INFO_HI("%s: Command type: CMD53\n", __func__); - } else { - HIF_ERROR("%s: Invalid command type: 0x%08x\n", - __func__, request); - status = QDF_STATUS_E_INVAL; - break; - } - - if (request & HIF_BLOCK_BASIS) { - /* round to whole block length size */ - length = - (length / HIF_BLOCK_SIZE) * - HIF_BLOCK_SIZE; - HIF_INFO_HI("%s: Block mode (BlockLen: %d)\n", - __func__, length); - } else if (request & HIF_BYTE_BASIS) { - HIF_INFO_HI("%s: Byte mode (BlockLen: %d)\n", - __func__, length); - } else { - HIF_ERROR("%s: Invalid data mode: 0x%08x\n", - __func__, request); - status = QDF_STATUS_E_INVAL; - break; - } - if (request & HIF_SDIO_WRITE) { - hif_fixup_write_param(device, request, - &length, &address); - - HIF_INFO_HI("addr:%08X, len:0x%08X, dummy:0x%04X\n", - address, length, - (request & HIF_DUMMY_SPACE_MASK) >> 16); - } - - if (request & HIF_FIXED_ADDRESS) { - opcode = CMD53_FIXED_ADDRESS; - HIF_INFO_HI("%s: Addr mode: fixed 0x%X\n", - __func__, address); - } else if (request & HIF_INCREMENTAL_ADDRESS) { - opcode = CMD53_INCR_ADDRESS; - HIF_INFO_HI("%s: Address mode: Incremental 0x%X\n", - __func__, address); - } else { - HIF_ERROR("%s: Invalid address mode: 0x%08x\n", - __func__, request); - status = QDF_STATUS_E_INVAL; - break; - } - - if (request & HIF_SDIO_WRITE) { -#if HIF_USE_DMA_BOUNCE_BUFFER - if (BUFFER_NEEDS_BOUNCE(buffer)) { - AR_DEBUG_ASSERT(device->dma_buffer); - tbuffer = device->dma_buffer; - /* copy the write data to the dma buffer */ - AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); - if (length > HIF_DMA_BUFFER_SIZE) { - HIF_ERROR("%s: Invalid write len: %d\n", - __func__, length); - status = QDF_STATUS_E_INVAL; - break; - } - memcpy(tbuffer, buffer, length); - bounced = true; - } else { - tbuffer = buffer; - } -#else - tbuffer = buffer; -#endif - if (opcode == CMD53_FIXED_ADDRESS && tbuffer) { - ret = sdio_writesb(device->func, address, - tbuffer, length); - HIF_INFO_HI("%s:r=%d addr:0x%X, len:%d, 0x%X\n", - __func__, ret, address, length, - *(int *)tbuffer); - } else if (tbuffer) { - ret = sdio_memcpy_toio(device->func, address, - tbuffer, length); - HIF_INFO_HI("%s:r=%d addr:0x%X, len:%d, 0x%X\n", - __func__, ret, address, length, - *(int *)tbuffer); - } - } else if (request & HIF_SDIO_READ) { -#if HIF_USE_DMA_BOUNCE_BUFFER - if (BUFFER_NEEDS_BOUNCE(buffer)) { - AR_DEBUG_ASSERT(device->dma_buffer); - AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); - if (length > HIF_DMA_BUFFER_SIZE) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("%s: Invalid read length: %d\n", - __func__, length)); - status = QDF_STATUS_E_INVAL; - break; - } - tbuffer = device->dma_buffer; - bounced = true; - } else { - tbuffer = buffer; - } -#else - tbuffer = buffer; -#endif - if (opcode == CMD53_FIXED_ADDRESS && tbuffer) { - ret = sdio_readsb(device->func, tbuffer, - address, length); - HIF_INFO_HI("%s:r=%d addr:0x%X, len:%d, 0x%X\n", - __func__, ret, address, length, - *(int *)tbuffer); - } else if (tbuffer) { - ret = sdio_memcpy_fromio(device->func, - tbuffer, address, - length); - HIF_INFO_HI("%s:r=%d addr:0x%X, len:%d, 0x%X\n", - __func__, ret, address, length, - *(int *)tbuffer); - } -#if HIF_USE_DMA_BOUNCE_BUFFER - if (bounced && tbuffer) - memcpy(buffer, tbuffer, length); -#endif - } else { - HIF_ERROR("%s: Invalid dir: 0x%08x", __func__, request); - status = QDF_STATUS_E_INVAL; - return status; - } - - if (ret) { - HIF_ERROR("%s: SDIO bus operation failed!", __func__); - HIF_ERROR("%s: MMC stack returned : %d", __func__, ret); - HIF_ERROR("%s: addr:0X%06X, len:%08d, %s, %s", - __func__, address, length, - request & HIF_SDIO_READ ? "Read " : "Write", - request & HIF_ASYNCHRONOUS ? - "Async" : "Sync"); - status = QDF_STATUS_E_FAILURE; - } - } while (false); - - return status; -} - /** * add_to_async_list() - add bus reqest to async task list * @device: pointer to hif device @@ -380,222 +184,6 @@ void add_to_async_list(struct hif_sdio_dev *device, qdf_spin_unlock_irqrestore(&device->asynclock); } -/** - * hif_read_write() - queue a read/write request - * @device: pointer to hif device structure - * @address: address to read - * @buffer: buffer to hold read/write data - * @length: length to read/write - * @request: read/write/sync/async request - * @context: pointer to hold calling context - * - * Return: 0 on success, error number otherwise. - */ -QDF_STATUS -hif_read_write(struct hif_sdio_dev *device, - uint32_t address, - char *buffer, uint32_t length, - uint32_t request, void *context) -{ - QDF_STATUS status = QDF_STATUS_SUCCESS; - struct bus_request *busrequest; - - AR_DEBUG_ASSERT(device); - AR_DEBUG_ASSERT(device->func); - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: device 0x%pK addr 0x%X buffer 0x%pK len %d req 0x%X context 0x%pK", - __func__, device, address, buffer, - length, request, context)); - - /*sdio r/w action is not needed when suspend, so just return */ - if ((device->is_suspend == true) - && (device->power_config == HIF_DEVICE_POWER_CUT)) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("skip io when suspending\n")); - return QDF_STATUS_SUCCESS; - } - do { - if ((request & HIF_ASYNCHRONOUS) || - (request & HIF_SYNCHRONOUS)) { - /* serialize all requests through the async thread */ - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: Execution mode: %s\n", __func__, - (request & HIF_ASYNCHRONOUS) ? "Async" - : "Synch")); - busrequest = hif_allocate_bus_request(device); - if (!busrequest) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("no async bus requests available (%s, addr:0x%X, len:%d)\n", - request & HIF_SDIO_READ ? "READ" : - "WRITE", address, length)); - return QDF_STATUS_E_FAILURE; - } - busrequest->address = address; - busrequest->buffer = buffer; - busrequest->length = length; - busrequest->request = request; - busrequest->context = context; - - add_to_async_list(device, busrequest); - - if (request & HIF_SYNCHRONOUS) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: queued sync req: 0x%lX\n", - __func__, (unsigned long)busrequest)); - - /* wait for completion */ - up(&device->sem_async); - if (down_interruptible(&busrequest->sem_req) != - 0) { - /* interrupted, exit */ - return QDF_STATUS_E_FAILURE; - } else { - QDF_STATUS status = busrequest->status; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: sync return freeing 0x%lX: 0x%X\n", - __func__, - (unsigned long) - busrequest, - busrequest->status)); - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: freeing req: 0x%X\n", - __func__, - (unsigned int) - request)); - hif_free_bus_request(device, - busrequest); - return status; - } - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: queued async req: 0x%lX\n", - __func__, - (unsigned long)busrequest)); - up(&device->sem_async); - return QDF_STATUS_E_PENDING; - } - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("%s: Invalid execution mode: 0x%08x\n", - __func__, - (unsigned int)request)); - status = QDF_STATUS_E_INVAL; - break; - } - } while (0); - - return status; -} - -/** - * async_task() - thread function to serialize all bus requests - * @param: pointer to hif device - * - * thread function to serialize all requests, both sync and async - * Return: 0 on success, error number otherwise. - */ -static int async_task(void *param) -{ - struct hif_sdio_dev *device; - struct bus_request *request; - QDF_STATUS status; - bool claimed = false; - - device = (struct hif_sdio_dev *) param; - set_current_state(TASK_INTERRUPTIBLE); - while (!device->async_shutdown) { - /* wait for work */ - if (down_interruptible(&device->sem_async) != 0) { - /* interrupted, exit */ - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: async task interrupted\n", - __func__)); - break; - } - if (device->async_shutdown) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: async task stopping\n", - __func__)); - break; - } - /* we want to hold the host over multiple cmds - * if possible, but holding the host blocks - * card interrupts - */ - qdf_spin_lock_irqsave(&device->asynclock); - /* pull the request to work on */ - while (device->asyncreq) { - request = device->asyncreq; - if (request->inusenext) - device->asyncreq = request->inusenext; - else - device->asyncreq = NULL; - qdf_spin_unlock_irqrestore(&device->asynclock); - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: async_task processing req: 0x%lX\n", - __func__, (unsigned long)request)); - - if (!claimed) { - sdio_claim_host(device->func); - claimed = true; - } - if (request->scatter_req) { - A_ASSERT(device->scatter_enabled); - /* pass the request to scatter routine which - * executes it synchronously, note, no need - * to free the request since scatter requests - * are maintained on a separate list - */ - status = do_hif_read_write_scatter(device, - request); - } else { - /* call hif_read_write in sync mode */ - status = - __hif_read_write(device, - request->address, - request->buffer, - request->length, - request-> - request & - ~HIF_SYNCHRONOUS, - NULL); - if (request->request & HIF_ASYNCHRONOUS) { - void *context = request->context; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: freeing req: 0x%lX\n", - __func__, (unsigned long) - request)); - hif_free_bus_request(device, request); - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: async_task completion req 0x%lX\n", - __func__, (unsigned long) - request)); - device->htc_callbacks. - rw_compl_handler(context, status); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("%s: async_task upping req: 0x%lX\n", - __func__, (unsigned long) - request)); - request->status = status; - up(&request->sem_req); - } - } - qdf_spin_lock_irqsave(&device->asynclock); - } - qdf_spin_unlock_irqrestore(&device->asynclock); - if (claimed) { - sdio_release_host(device->func); - claimed = false; - } - } - - complete_and_exit(&device->async_completion, 0); - - return 0; -} - /* * Setup IRQ mode for deep sleep and WoW * Switch back to 1 bits mode when we suspend for @@ -603,6 +191,7 @@ static int async_task(void *param) * Re-enable async 4-bit irq mode for some host controllers * after resume. */ +#ifdef CONFIG_SDIO_TRANSFER_MAILBOX static int sdio_enable4bits(struct hif_sdio_dev *device, int enable) { int ret = 0; @@ -675,34 +264,12 @@ static int sdio_enable4bits(struct hif_sdio_dev *device, int enable) return ret; } - -static QDF_STATUS hif_disable_func(struct hif_sdio_dev *device, - struct sdio_func *func, - bool reset) +#else +static int sdio_enable4bits(struct hif_sdio_dev *device, int enable) { - QDF_STATUS status = QDF_STATUS_SUCCESS; - - HIF_ENTER(); - device = get_hif_device(func); - if (!IS_ERR(device->async_task)) { - init_completion(&device->async_completion); - device->async_shutdown = 1; - up(&device->sem_async); - wait_for_completion(&device->async_completion); - device->async_task = NULL; - sema_init(&device->sem_async, 0); - } - - status = hif_sdio_func_disable(device, func, reset); - if (status == QDF_STATUS_SUCCESS) - device->is_disabled = true; - - cleanup_hif_scatter_resources(device); - - HIF_EXIT(); - - return status; + return 0; } +#endif /** * hif_sdio_probe() - configure sdio device @@ -712,9 +279,9 @@ static QDF_STATUS hif_disable_func(struct hif_sdio_dev *device, * * Return: 0 for success and non-zero for failure */ -static A_STATUS hif_sdio_probe(struct hif_softc *ol_sc, - struct sdio_func *func, - struct hif_sdio_dev *device) +A_STATUS hif_sdio_probe(struct hif_softc *ol_sc, + struct sdio_func *func, + struct hif_sdio_dev *device) { int ret = 0; const struct sdio_device_id *id; @@ -794,7 +361,9 @@ static A_STATUS hif_sdio_probe(struct hif_softc *ol_sc, goto err_attach1; } - return 0; + ret = hif_dev_register_channels(device, func); + + return ret; err_attach1: if (scn->ramdump_base) @@ -803,48 +372,9 @@ static A_STATUS hif_sdio_probe(struct hif_softc *ol_sc, return ret; } -static QDF_STATUS hif_enable_func(struct hif_softc *ol_sc, - struct hif_sdio_dev *device, - struct sdio_func *func, - bool resume) -{ - int ret = QDF_STATUS_SUCCESS; - - HIF_ENTER(); - - if (!device) { - HIF_ERROR("%s: HIF device is NULL", __func__); - return QDF_STATUS_E_INVAL; - } - - if (hif_sdio_func_enable(device, func)) - return QDF_STATUS_E_FAILURE; - - /* create async I/O thread */ - if (!device->async_task && device->is_disabled) { - device->async_shutdown = 0; - device->async_task = kthread_create(async_task, - (void *)device, - "AR6K Async"); - if (IS_ERR(device->async_task)) { - HIF_ERROR("%s: Error creating async task", - __func__); - return QDF_STATUS_E_FAILURE; - } - device->is_disabled = false; - wake_up_process(device->async_task); - } - - if (resume == false) - ret = hif_sdio_probe(ol_sc, func, device); - - HIF_EXIT(); - - return ret; -} - /** * power_state_change_notify() - SDIO bus power notification handler + * @ol_sc: HIF device context * @config: hif device power change type * * Return: 0 on success, error number otherwise. @@ -910,6 +440,7 @@ power_state_change_notify(struct hif_softc *ol_sc, /** * hif_configure_device() - configure sdio device + * @ol_sc: HIF device context * @device: pointer to hif device structure * @opcode: configuration type * @config: configuration value to set @@ -1032,6 +563,7 @@ void hif_sdio_shutdown(struct hif_softc *hif_ctx) /** * hif_device_inserted() - hif-sdio driver probe handler + * @ol_sc: HIF device context * @func: pointer to sdio_func * @id: pointer to sdio_device_id * @@ -1057,10 +589,10 @@ static int hif_device_inserted(struct hif_softc *ol_sc, if (hifdevice && hifdevice->power_config == HIF_DEVICE_POWER_CUT && hifdevice->host == func->card->host) { - device = get_hif_device(func); + device = get_hif_device(ol_sc, func); hifdevice->func = func; hifdevice->power_config = HIF_DEVICE_POWER_UP; - hif_sdio_set_drvdata(func, hifdevice); + hif_sdio_set_drvdata(ol_sc, func, hifdevice); if (device->is_suspend) { HIF_INFO("%s: Resume from suspend", __func__); @@ -1072,9 +604,10 @@ static int hif_device_inserted(struct hif_softc *ol_sc, /* If device not found, then it is a new insertion, alloc and add it */ if (!device) { - if (add_hif_device(func) == NULL) + if (!add_hif_device(ol_sc, func)) return QDF_STATUS_E_FAILURE; - device = get_hif_device(func); + + device = get_hif_device(ol_sc, func); for (i = 0; i < MAX_HIF_DEVICES; ++i) { if (!hif_devices[i]) { @@ -1095,13 +628,13 @@ static int hif_device_inserted(struct hif_softc *ol_sc, */ sdio_claim_host(func); - hif_sdio_quirk_force_drive_strength(func); + hif_sdio_quirk_force_drive_strength(ol_sc, func); - hif_sdio_quirk_write_cccr(func); + hif_sdio_quirk_write_cccr(ol_sc, func); - ret = hif_sdio_set_bus_speed(func); + ret = hif_sdio_set_bus_speed(ol_sc, func); - ret = hif_sdio_set_bus_width(func); + ret = hif_sdio_set_bus_width(ol_sc, func); if (debugcccr) hif_dump_cccr(device); @@ -1174,11 +707,11 @@ void hif_ack_interrupt(struct hif_sdio_dev *device) * @pdev - HIF layer object * @func - SDIO bus function object * - * Return - NONE + * Return - error in case of failure to configure, else success */ -void hif_sdio_configure_pipes(struct hif_sdio_dev *dev, struct sdio_func *func) +int hif_sdio_configure_pipes(struct hif_sdio_dev *dev, struct sdio_func *func) { - /* ADMA-TODO */ + return hif_dev_configure_pipes(dev, func); } /** @@ -1233,7 +766,7 @@ void hif_free_bus_request(struct hif_sdio_dev *device, int hif_device_suspend(struct hif_softc *ol_sc, struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); - struct hif_sdio_dev *device = get_hif_device(func); + struct hif_sdio_dev *device = get_hif_device(ol_sc, func); mmc_pm_flag_t pm_flag = 0; enum HIF_DEVICE_POWER_CHANGE_TYPE config; struct mmc_host *host = func->card->host; @@ -1314,7 +847,7 @@ int hif_device_resume(struct hif_softc *ol_sc, struct device *dev) enum HIF_DEVICE_POWER_CHANGE_TYPE config; struct hif_sdio_dev *device; - device = get_hif_device(func); + device = get_hif_device(ol_sc, func); if (!device) { HIF_ERROR("%s: hif object is null", __func__); return -EINVAL; @@ -1367,7 +900,8 @@ static A_STATUS hif_sdio_remove(void *context, void *hif_handle) return 0; } -static void hif_device_removed(struct sdio_func *func) + +static void hif_device_removed(struct hif_softc *ol_sc, struct sdio_func *func) { QDF_STATUS status = QDF_STATUS_SUCCESS; struct hif_sdio_dev *device; @@ -1375,7 +909,7 @@ static void hif_device_removed(struct sdio_func *func) AR_DEBUG_ASSERT(func); HIF_ENTER(); - device = get_hif_device(func); + device = get_hif_device(ol_sc, func); if (device->power_config == HIF_DEVICE_POWER_CUT) { device->func = NULL; /* func will be free by mmc stack */ @@ -1406,7 +940,8 @@ static void hif_device_removed(struct sdio_func *func) HIF_EXIT(); } -static struct hif_sdio_dev *add_hif_device(struct sdio_func *func) +static struct hif_sdio_dev *add_hif_device(struct hif_softc *ol_sc, + struct sdio_func *func) { struct hif_sdio_dev *hifdevice = NULL; int ret = 0; @@ -1430,8 +965,8 @@ static struct hif_sdio_dev *add_hif_device(struct sdio_func *func) hifdevice->func = func; hifdevice->power_config = HIF_DEVICE_POWER_UP; hifdevice->device_state = HIF_DEVICE_STATE_ON; - ret = hif_sdio_set_drvdata(func, hifdevice); - hif_info("status %d", ret); + ret = hif_sdio_set_drvdata(ol_sc, func, hifdevice); + HIF_INFO("status %d", ret); return hifdevice; } @@ -1552,12 +1087,12 @@ int hif_sdio_device_inserted(struct hif_softc *ol_sc, HIF_ERROR("%s: Enter", __func__); status = hif_device_inserted(ol_sc, func, id); - HIF_ERROR("%s: Exit", __func__); + HIF_ERROR("%s: Exit: status:%d", __func__, status); return status; } -void hif_sdio_device_removed(struct sdio_func *func) +void hif_sdio_device_removed(struct hif_softc *ol_sc, struct sdio_func *func) { - hif_device_removed(func); + hif_device_removed(ol_sc, func); } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/adma.c b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/adma.c new file mode 100644 index 0000000000000000000000000000000000000000..bce8c52bdff4f18cda9bb7dff247b6f1acef07ce --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/adma.c @@ -0,0 +1,862 @@ +/* + * Copyright (c) 2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include "adma.h" +#include "hif_sdio_internal.h" +#include "pld_sdio.h" +#include "if_sdio.h" + +/** + * hif_dev_get_fifo_address() - get the fifo addresses for dma + * @pdev: SDIO HIF object + * @c : FIFO address config pointer + * + * Return : 0 for success, non-zero for error + */ +int hif_dev_get_fifo_address(struct hif_sdio_dev *pdev, + void *c, + uint32_t config_len) +{ + /* SDIO AL handles DMA Addresses */ + return 0; +} + +/** + * hif_dev_get_block_size() - get the adma block size for dma + * @config : block size config pointer + * + * Return : NONE + */ +void hif_dev_get_block_size(void *config) +{ + /* TODO Get block size used by AL Layer in Mission ROM Mode */ + *((uint32_t *)config) = HIF_BLOCK_SIZE; /* QCN_SDIO_MROM_BLK_SZ TODO */ +} + +/** + * hif_dev_configure_pipes() - configure pipes + * @pdev: SDIO HIF object + * @func: sdio function object + * + * Return : 0 for success, non-zero for error + */ +int hif_dev_configure_pipes(struct hif_sdio_dev *pdev, struct sdio_func *func) +{ + /* SDIO AL Configures SDIO Channels */ + return 0; +} + +/** hif_dev_set_mailbox_swap() - Set the mailbox swap + * @pdev : The HIF layer object + * + * Return: none + */ +void hif_dev_set_mailbox_swap(struct hif_sdio_dev *pdev) +{ + /* SDIO AL doesn't use mailbox architecture */ +} + +/** hif_dev_get_mailbox_swap() - Get the mailbox swap setting + * @pdev : The HIF layer object + * + * Return: true or false + */ +bool hif_dev_get_mailbox_swap(struct hif_sdio_dev *pdev) +{ + /* SDIO AL doesn't use mailbox architecture */ + return false; +} + +/** + * hif_dev_dsr_handler() - Synchronous interrupt handler + * + * @context: hif send context + * + * Return: 0 for success and non-zero for failure + */ +QDF_STATUS hif_dev_dsr_handler(void *context) +{ + /* SDIO AL handles interrupts */ + return QDF_STATUS_SUCCESS; +} + +/** + * hif_dev_map_service_to_pipe() - maps ul/dl pipe to service id. + * @pDev: SDIO HIF object + * @ServiceId: sevice index + * @ULPipe: uplink pipe id + * @DLPipe: down-linklink pipe id + * + * Return: 0 on success, error value on invalid map + */ +QDF_STATUS hif_dev_map_service_to_pipe(struct hif_sdio_dev *pdev, uint16_t svc, + uint8_t *ul_pipe, uint8_t *dl_pipe) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + switch (svc) { + case HTT_DATA_MSG_SVC: + *dl_pipe = 2; + *ul_pipe = 3; + break; + + case HTC_CTRL_RSVD_SVC: + case HTC_RAW_STREAMS_SVC: + *dl_pipe = 0; + *ul_pipe = 1; + break; + + case WMI_DATA_BE_SVC: + case WMI_DATA_BK_SVC: + case WMI_DATA_VI_SVC: + case WMI_DATA_VO_SVC: + *dl_pipe = 2; + *ul_pipe = 3; + break; + + case WMI_CONTROL_SVC: + *dl_pipe = 0; + *ul_pipe = 1; + break; + + default: + HIF_ERROR("%s: Err : Invalid service (%d)", + __func__, svc); + status = QDF_STATUS_E_INVAL; + break; + } + return status; +} + +/** + * hif_bus_configure() - configure the bus + * @hif_sc: pointer to the hif context. + * + * return: 0 for success. nonzero for failure. + */ +int hif_sdio_bus_configure(struct hif_softc *hif_sc) +{ + struct pld_wlan_enable_cfg cfg; + enum pld_driver_mode mode; + uint32_t con_mode = hif_get_conparam(hif_sc); + + if (con_mode == QDF_GLOBAL_FTM_MODE) + mode = PLD_FTM; + else if (con_mode == QDF_GLOBAL_COLDBOOT_CALIB_MODE) + mode = PLD_COLDBOOT_CALIBRATION; + else if (QDF_IS_EPPING_ENABLED(con_mode)) + mode = PLD_EPPING; + else + mode = PLD_MISSION; + + return pld_wlan_enable(hif_sc->qdf_dev->dev, &cfg, mode); +} + +/** hif_dev_setup_device() - Setup device specific stuff here required for hif + * @pdev : HIF layer object + * + * return 0 on success, error otherwise + */ +int hif_dev_setup_device(struct hif_sdio_device *pdev) +{ + hif_dev_get_block_size(&pdev->BlockSize); + + return 0; +} + +/** hif_dev_mask_interrupts() - Disable the interrupts in the device + * @pdev SDIO HIF Object + * + * Return: NONE + */ +void hif_dev_mask_interrupts(struct hif_sdio_device *pdev) +{ + /* SDIO AL Handles Interrupts */ +} + +/** hif_dev_unmask_interrupts() - Enable the interrupts in the device + * @pdev SDIO HIF Object + * + * Return: NONE + */ +void hif_dev_unmask_interrupts(struct hif_sdio_device *pdev) +{ + /* SDIO AL Handles Interrupts */ +} + +/** + * hif_dev_map_pipe_to_adma_chan() - maps pipe id to adma chan + * @pdev: The pointer to the hif device object + * @pipeid: pipe index + * + * Return: adma channel handle + */ +struct sdio_al_channel_handle *hif_dev_map_pipe_to_adma_chan +( +struct hif_sdio_device *dev, +uint8_t pipeid +) +{ + struct hif_sdio_dev *pdev = dev->HIFDevice; + + HIF_ENTER(); + + if ((pipeid == 0) || (pipeid == 1)) + return pdev->al_chan[0]; + else if ((pipeid == 2) || (pipeid == 3)) + return pdev->al_chan[1]; + else + return NULL; +} + +/** + * hif_dev_map_adma_chan_to_pipe() - map adma chan to htc pipe + * @pdev: The pointer to the hif device object + * @chan: channel number + * @upload: boolean to decide upload or download + * + * Return: Invalid pipe index + */ +uint8_t hif_dev_map_adma_chan_to_pipe(struct hif_sdio_device *pdev, + uint8_t chan, bool upload) +{ + HIF_INFO("%s: chan: %u, %s", __func__, chan, + upload ? "Upload" : "Download"); + + if (chan == 0) /* chan 0 is mapped to HTT */ + return upload ? 1 : 0; + else if (chan == 1) /* chan 1 is mapped to WMI */ + return upload ? 3 : 2; + + return (uint8_t)-1; /* invalid channel id */ +} + +/** + * hif_get_send_address() - Get the transfer pipe address + * @pdev: The pointer to the hif device object + * @pipe: The pipe identifier + * + * Return 0 for success and non-zero for failure to map + */ +int hif_get_send_address(struct hif_sdio_device *pdev, + uint8_t pipe, unsigned long *addr) +{ + struct sdio_al_channel_handle *chan = NULL; + + if (!addr) + return -EINVAL; + + *addr = 0; + chan = hif_dev_map_pipe_to_adma_chan(pdev, pipe); + + if (!chan) + return -EINVAL; + + *addr = (unsigned long)chan; + + return 0; +} + +/** + * hif_fixup_write_param() - Tweak the address and length parameters + * @pdev: The pointer to the hif device object + * @length: The length pointer + * @addr: The addr pointer + * + * Return: None + */ +void hif_fixup_write_param(struct hif_sdio_dev *pdev, uint32_t req, + uint32_t *length, uint32_t *addr) +{ + HIF_ENTER(); + HIF_EXIT(); +} + +#define HIF_MAX_RX_Q_ALLOC 0 /* TODO */ +#define HIF_RX_Q_ALLOC_THRESHOLD 100 +QDF_STATUS hif_disable_func(struct hif_sdio_dev *device, + struct sdio_func *func, + bool reset) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; +#if HIF_MAX_RX_Q_ALLOC + qdf_list_node_t *node; + struct rx_q_entry *rx_q_elem; +#endif + HIF_ENTER(); + +#if HIF_MAX_RX_Q_ALLOC + qdf_spin_lock_irqsave(&device->rx_q_lock); + + for (; device->rx_q.count; ) { + qdf_list_remove_back(&device->rx_q, &node); + rx_q_elem = container_of(node, struct rx_q_entry, entry); + if (rx_q_elem) { + if (rx_q_elem->nbuf) + qdf_nbuf_free(rx_q_elem->nbuf); + qdf_mem_free(rx_q_elem); + } + } + qdf_destroy_work(0, &device->rx_q_alloc_work); + + qdf_spin_unlock_irqrestore(&device->rx_q_lock); + + qdf_spinlock_destroy(&device->rx_q_lock); +#endif + + status = hif_sdio_func_disable(device, func, reset); + if (status == QDF_STATUS_SUCCESS) + device->is_disabled = true; + + cleanup_hif_scatter_resources(device); + + HIF_EXIT(); + + return status; +} + +/** + * hif_enable_func() - Enable SDIO function + * + * @ol_sc: HIF object pointer + * @device: HIF device pointer + * @sdio_func: SDIO function pointer + * @resume: If this is called from resume or probe + * + * Return: 0 in case of success, else error value + */ +QDF_STATUS hif_enable_func(struct hif_softc *ol_sc, struct hif_sdio_dev *device, + struct sdio_func *func, bool resume) +{ + int ret = QDF_STATUS_SUCCESS; + + if (!device) { + HIF_ERROR("%s: HIF device is NULL", __func__); + return QDF_STATUS_E_INVAL; + } + + if (!resume) + ret = hif_sdio_probe(ol_sc, func, device); + +#if HIF_MAX_RX_Q_ALLOC + if (!ret) { + qdf_list_create(&device->rx_q, HIF_MAX_RX_Q_ALLOC); + qdf_spinlock_create(&device->rx_q_lock); + qdf_create_work(0, &device->rx_q_alloc_work, + hif_sdio_rx_q_alloc, (void *)device); + device->rx_q_alloc_work_scheduled = true; + qdf_sched_work(0, &device->rx_q_alloc_work); + } +#endif + return ret; +} + +/** + * hif_sdio_get_net_buf() - Get a network buffer from the rx q + * @dev - HIF device object + * + * Return - NULL if out of buffers, else qdf_nbuf_t + */ +#if HIF_MAX_RX_Q_ALLOC +static qdf_nbuf_t hif_sdio_get_nbuf(struct hif_sdio_dev *dev, uint16_t buf_len) +{ + qdf_list_node_t *node; + qdf_nbuf_t nbuf = NULL; + qdf_list_t *q = &dev->rx_q; + struct rx_q_entry *elem = NULL; + + /* TODO - Alloc nbuf based on buf_len */ + qdf_spin_lock_irqsave(&dev->rx_q_lock); + + if (q->count) { + qdf_list_remove_front(q, &node); + elem = qdf_container_of(node, struct rx_q_entry, entry); + nbuf = elem->nbuf; + } else { + HIF_ERROR("%s: no rx q elements", __func__); + } + + if (q->count <= HIF_RX_Q_ALLOC_THRESHOLD && + !dev->rx_q_alloc_work_scheduled) { + dev->rx_q_alloc_work_scheduled = true; + qdf_sched_work(0, &dev->rx_q_alloc_work); + } + + qdf_spin_unlock_irqrestore(&dev->rx_q_lock); + + qdf_mem_free(elem); + + return nbuf; +} +#else +static qdf_nbuf_t hif_sdio_get_nbuf(struct hif_sdio_dev *dev, uint16_t buf_len) +{ + qdf_nbuf_t nbuf; + + if (!buf_len) + buf_len = HIF_SDIO_RX_BUFFER_SIZE; + + nbuf = qdf_nbuf_alloc(NULL, buf_len, 0, 4, false); + + return nbuf; +} +#endif +/** + * hif_sdio_rx_q_alloc() - Deferred work for pre-alloc rx q + * @ctx - Pointer to context object + * + * Return NONE + */ +#if HIF_MAX_RX_Q_ALLOC +void hif_sdio_rx_q_alloc(void *ctx) +{ + struct rx_q_entry *rx_q_elem; + struct hif_sdio_dev *dev = (struct hif_sdio_dev *)ctx; + unsigned int rx_q_count = dev->rx_q.count; + + HIF_ENTER(); + qdf_spin_lock_irqsave(&dev->rx_q_lock); + + for (; rx_q_count < dev->rx_q.max_size; rx_q_count++) { + rx_q_elem = qdf_mem_malloc(sizeof(struct rx_q_entry)); + if (!rx_q_elem) { + HIF_ERROR("%s: failed to alloc rx q elem", __func__); + break; + } + + /* TODO - Alloc nbuf based on payload_len in HTC Header */ + rx_q_elem->nbuf = qdf_nbuf_alloc(NULL, HIF_SDIO_RX_BUFFER_SIZE, + 0, 4, false); + if (!rx_q_elem->nbuf) { + HIF_ERROR("%s: failed to alloc nbuf for rx", __func__); + qdf_mem_free(rx_q_elem); + break; + } + + qdf_list_insert_back(&dev->rx_q, &rx_q_elem->entry); + } + dev->rx_q_alloc_work_scheduled = false; + + qdf_spin_unlock_irqrestore(&dev->rx_q_lock); + HIF_EXIT(); +} +#else +void hif_sdio_rx_q_alloc(void *ctx) +{ +} +#endif + +#include + +struct sdio_al_channel_data qcn7605_chan[HIF_SDIO_MAX_AL_CHANNELS] = { + { + .name = "SDIO_AL_WLAN_CH0", /* HTT */ + .client_data = NULL, /* populate from client handle */ + .ul_xfer_cb = ul_xfer_cb, + .dl_xfer_cb = dl_xfer_cb, + .dl_data_avail_cb = dl_data_avail_cb, + .dl_meta_data_cb = NULL + }, + { + .name = "SDIO_AL_WLAN_CH1", /* WMI */ + .client_data = NULL, /* populate from client handle */ + .ul_xfer_cb = ul_xfer_cb, + .dl_xfer_cb = dl_xfer_cb, + .dl_data_avail_cb = dl_data_avail_cb, + .dl_meta_data_cb = NULL + } +}; + +/** + * hif_dev_register_channels()- Register transport layer channels + * @dev : HIF device object + * @func : SDIO function pointer + * + * Return : success on configuration, else failure + */ +int hif_dev_register_channels(struct hif_sdio_dev *dev, struct sdio_func *func) +{ + int ret = 0; + unsigned int chan; + struct sdio_al_channel_data *chan_data[HIF_ADMA_MAX_CHANS]; + + HIF_ENTER(); + + dev->al_client = pld_sdio_get_sdio_al_client_handle(func); + if (ret || !dev->al_client) { + HIF_ERROR("%s: Failed to get get sdio al handle", __func__); + return ret; + } + + if ((func->device & MANUFACTURER_ID_AR6K_BASE_MASK) == + MANUFACTURER_ID_QCN7605_BASE) { + dev->adma_chans_used = 2; + qcn7605_chan[0].client_data = dev->al_client->client_data; + qcn7605_chan[1].client_data = dev->al_client->client_data; + chan_data[0] = &qcn7605_chan[0]; + chan_data[1] = &qcn7605_chan[1]; + } else { + dev->adma_chans_used = 0; + } + + for (chan = 0; chan < dev->adma_chans_used; chan++) { + dev->al_chan[chan] = + pld_sdio_register_sdio_al_channel(dev->al_client, + chan_data[chan]); + if (!dev->al_chan[chan] || IS_ERR(dev->al_chan[chan])) { + ret = -EINVAL; + HIF_ERROR("%s: Channel registration failed", __func__); + } else { + dev->al_chan[chan]->priv = (void *)dev; + HIF_INFO("%s: chan %s : id : %u", __func__, + chan_data[chan]->name, + dev->al_chan[chan]->channel_id); + } + } + + HIF_EXIT(); + + return ret; +} + +/** + * hif_dev_unregister_channels()- Register transport layer channels + * @dev : HIF device object + * @func : SDIO Function pointer + * + * Return : None + */ +void hif_dev_unregister_channels(struct hif_sdio_dev *dev, + struct sdio_func *func) +{ + unsigned int chan; + + if (!dev) { + HIF_ERROR("%s: hif_sdio_dev is null", __func__); + return; + } + + for (chan = 0; chan < dev->adma_chans_used; chan++) { + dev->al_chan[chan]->priv = NULL; + pld_sdio_unregister_sdio_al_channel(dev->al_chan[chan]); + } +} + +/** + * hif_read_write() - queue a read/write request + * @dev: pointer to hif device structure + * @address: address to read, actually channel pointer + * @buffer: buffer to hold read/write data + * @length: length to read/write + * @request: read/write/sync/async request + * @context: pointer to hold calling context + * + * Return: 0, pending on success, error number otherwise. + */ +QDF_STATUS +hif_read_write(struct hif_sdio_dev *dev, + unsigned long sdio_al_ch_handle, + char *cbuffer, uint32_t length, + uint32_t request, void *context) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct sdio_al_channel_handle *ch; + struct bus_request *bus_req; + enum sdio_al_dma_direction dir; + struct hif_sdio_device *device; + QDF_STATUS (*rx_comp)(void *, qdf_nbuf_t, uint8_t); + qdf_nbuf_t nbuf; + int ret = 0, payload_len = 0; + unsigned char *buffer = (unsigned char *)cbuffer; + + if (!dev || !sdio_al_ch_handle) { + HIF_ERROR("%s: device = %pK, addr = %lu", __func__, + dev, sdio_al_ch_handle); + return QDF_STATUS_E_INVAL; + } + + if (!(request & HIF_ASYNCHRONOUS) && + !(request & HIF_SYNCHRONOUS)) { + HIF_ERROR("%s: Invalid request mode", __func__); + return QDF_STATUS_E_INVAL; + } + + /*sdio r/w action is not needed when suspend, so just return */ + if ((dev->is_suspend) && + (dev->power_config == HIF_DEVICE_POWER_CUT)) { + HIF_INFO("%s: skip in suspend", __func__); + return QDF_STATUS_SUCCESS; + } + + ch = (struct sdio_al_channel_handle *)sdio_al_ch_handle; + + bus_req = hif_allocate_bus_request(dev); + if (!bus_req) { + HIF_ERROR("%s: Bus alloc failed", __func__); + return QDF_STATUS_E_FAILURE; + } + + bus_req->address = sdio_al_ch_handle; + bus_req->length = length; + bus_req->request = request; + bus_req->context = context; + bus_req->buffer = buffer; + + /* Request SDIO AL to do transfer */ + dir = (request & HIF_SDIO_WRITE) ? SDIO_AL_TX : SDIO_AL_RX; + + if (request & HIF_SYNCHRONOUS) { + ret = sdio_al_queue_transfer(ch, + dir, + bus_req->buffer, + bus_req->length, + 1); /* higher priority */ + if (ret) { + status = QDF_STATUS_E_FAILURE; + HIF_ERROR("%s: SYNC REQ failed ret=%d", __func__, ret); + } else { + status = QDF_STATUS_SUCCESS; + } + + hif_free_bus_request(dev, bus_req); + + if ((status == QDF_STATUS_SUCCESS) && (dir == SDIO_AL_RX)) { + nbuf = (qdf_nbuf_t)context; + payload_len = HTC_GET_FIELD(bus_req->buffer, + HTC_FRAME_HDR, + PAYLOADLEN); + qdf_nbuf_set_pktlen(nbuf, payload_len + HTC_HDR_LENGTH); + device = (struct hif_sdio_device *)dev->htc_context; + rx_comp = device->hif_callbacks.rxCompletionHandler; + rx_comp(device->hif_callbacks.Context, nbuf, 0); + } + } else { + ret = sdio_al_queue_transfer_async(ch, + dir, + bus_req->buffer, + bus_req->length, + 1, /* higher priority */ + (void *)bus_req); + if (ret) { + status = QDF_STATUS_E_FAILURE; + HIF_ERROR("%s: ASYNC REQ fail ret=%d for len=%d ch=%d", + __func__, ret, length, ch->channel_id); + hif_free_bus_request(dev, bus_req); + } else { + status = QDF_STATUS_E_PENDING; + } + } + return status; +} + +/** + * ul_xfer_cb() - Completion call back for asynchronous transfer + * @ch_handle: The sdio al channel handle + * @result: The result of the operation + * @context: pointer to request context + * + * Return: None + */ +void ul_xfer_cb(struct sdio_al_channel_handle *ch_handle, + struct sdio_al_xfer_result *result, + void *ctx) +{ + struct bus_request *req = (struct bus_request *)ctx; + struct hif_sdio_dev *dev; + + if (!ch_handle || !result) { + HIF_ERROR("%s: Invalid args", __func__); + qdf_assert_always(0); + return; + } + + dev = (struct hif_sdio_dev *)ch_handle->priv; + + if (result->xfer_status) { + req->status = QDF_STATUS_E_FAILURE; + HIF_ERROR("%s: ASYNC Tx failed status=%d", __func__, + result->xfer_status); + } else { + req->status = QDF_STATUS_SUCCESS; + } + + dev->htc_callbacks.rw_compl_handler(req->context, req->status); + + hif_free_bus_request(dev, req); +} + +/** + * dl_data_avail_cb() - Called when data is available on a channel + * @ch_handle: The sdio al channel handle + * @len: The len of data available to download + * + * Return: None + */ +/* Use the asynchronous method of transfer. This will help in + * completing READ in the transfer done callback later which + * runs in sdio al thread context. If we do the syncronous + * transfer here, the thread context won't be available and + * perhaps a new thread may be required here. + */ +void dl_data_avail_cb(struct sdio_al_channel_handle *ch_handle, + unsigned int len) +{ + struct hif_sdio_dev *dev; + unsigned int chan; + qdf_nbuf_t nbuf; + + if (!ch_handle || !len) { + HIF_ERROR("%s: Invalid args %u", __func__, len); + qdf_assert_always(0); + return; + } + + dev = (struct hif_sdio_dev *)ch_handle->priv; + chan = ch_handle->channel_id; + + if (chan > HIF_SDIO_MAX_AL_CHANNELS) { + HIF_ERROR("%s: Invalid Ch ID %d", __func__, chan); + return; + } + + /* allocate a buffer for reading the data from the chip. + * Note that this is raw, unparsed buffer and will be + * processed in the transfer done callback. + */ + /* TODO, use global buffer instead of runtime allocations */ + nbuf = qdf_nbuf_alloc(NULL, len, 0, 4, false); + + if (!nbuf) { + HIF_ERROR("%s: Unable to alloc netbuf %u bytes", __func__, len); + return; + } + + hif_read_write(dev, (unsigned long)ch_handle, nbuf->data, len, + HIF_RD_ASYNC_BLOCK_FIX, nbuf); +} + +#define is_pad_block(buf) (*((uint32_t *)buf) == 0xbabababa) +uint16_t g_dbg_payload_len; + +/** + * dl_xfer_cb() - Call from lower layer after transfer is completed + * @ch_handle: The sdio al channel handle + * @result: The xfer result + * @ctx: Context passed in the transfer queuing + * + * Return: None + */ +void dl_xfer_cb(struct sdio_al_channel_handle *ch_handle, + struct sdio_al_xfer_result *result, + void *ctx) +{ + unsigned char *buf; + qdf_nbuf_t nbuf; + uint32_t len; + uint16_t payload_len = 0; + struct hif_sdio_dev *dev; + struct hif_sdio_device *device; + struct bus_request *bus_req = (struct bus_request *)ctx; + QDF_STATUS (*rx_completion)(void *, qdf_nbuf_t, uint8_t); + + if (!bus_req) { + HIF_ERROR("%s: Bus Req NULL!!!", __func__); + qdf_assert_always(0); + return; + } + + if (!ch_handle || !result) { + HIF_ERROR("%s: Invalid args %pK %pK", __func__, + ch_handle, result); + qdf_assert_always(0); + return; + } + + dev = (struct hif_sdio_dev *)ch_handle->priv; + if (result->xfer_status) { + HIF_ERROR("%s: ASYNC Rx failed %d", __func__, + result->xfer_status); + qdf_nbuf_free((qdf_nbuf_t)bus_req->context); + hif_free_bus_request(dev, bus_req); + return; + } + + device = (struct hif_sdio_device *)dev->htc_context; + rx_completion = device->hif_callbacks.rxCompletionHandler; + + buf = (unsigned char *)result->buf_addr; + len = (unsigned int)result->xfer_len; + + while (len >= sizeof(HTC_FRAME_HDR)) { + if (is_pad_block(buf)) { + /* End of Rx Buffer */ + break; + } + + if (HTC_GET_FIELD(buf, HTC_FRAME_HDR, ENDPOINTID) >= + ENDPOINT_MAX) { + HIF_ERROR("%s: invalid endpoint id: %u", __func__, + HTC_GET_FIELD(buf, HTC_FRAME_HDR, + ENDPOINTID)); + break; + } + + /* Copy the HTC frame to the alloc'd packet buffer */ + payload_len = HTC_GET_FIELD(buf, HTC_FRAME_HDR, PAYLOADLEN); + payload_len = qdf_le16_to_cpu(payload_len); + if (!payload_len) { + HIF_ERROR("%s:Invalid Payload len %d bytes", __func__, + payload_len); + break; + } + if (payload_len > g_dbg_payload_len) { + g_dbg_payload_len = payload_len; + HIF_ERROR("Max Rx HTC Payload = %d", g_dbg_payload_len); + } + + nbuf = hif_sdio_get_nbuf(dev, payload_len + HTC_HEADER_LEN); + if (!nbuf) { + HIF_ERROR("%s: failed to alloc rx buffer", __func__); + break; + } + + /* Check if payload fits in skb */ + if (qdf_nbuf_tailroom(nbuf) < payload_len + HTC_HEADER_LEN) { + HIF_ERROR("%s: Payload + HTC_HDR %d > skb tailroom %d", + __func__, (payload_len + 8), + qdf_nbuf_tailroom(nbuf)); + qdf_nbuf_free(nbuf); + break; + } + + qdf_mem_copy((uint8_t *)qdf_nbuf_data(nbuf), buf, + payload_len + HTC_HEADER_LEN); + + qdf_nbuf_put_tail(nbuf, payload_len + HTC_HDR_LENGTH); + + rx_completion(device->hif_callbacks.Context, nbuf, + 0); /* don't care, not used */ + + len -= payload_len + HTC_HDR_LENGTH; + buf += payload_len + HTC_HDR_LENGTH; + } + + qdf_nbuf_free((qdf_nbuf_t)bus_req->context); + hif_free_bus_request(dev, bus_req); +} diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/adma.h b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/adma.h new file mode 100644 index 0000000000000000000000000000000000000000..cfda66db25deb143a2bb73cb0738da06f8943010 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/adma.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _ADMA_H_ +#define _ADMA_H_ + +#include "hif_sdio_dev.h" +#include "htc_packet.h" +#include "htc_api.h" +#include "hif_internal.h" + +/* This should align with the underlying transport layer */ +#define HIF_DEFAULT_IO_BLOCK_SIZE 512 +#define HIF_BLOCK_SIZE HIF_DEFAULT_IO_BLOCK_SIZE +#define HIF_DUMMY_SPACE_MASK 0x0FFFFFFF + +#define HIF_SDIO_MAX_AL_CHANNELS 2 + +struct devRegisters { + uint32_t dummy; +}; + +#include "transfer.h" +#define DEV_REGISTERS_SIZE sizeof(struct devRegisters) + +uint8_t hif_dev_map_adma_chan_to_pipe(struct hif_sdio_device *pdev, + uint8_t chan, bool upload); + +struct sdio_al_channel_handle *hif_dev_map_pipe_to_adma_chan +( +struct hif_sdio_device *pdev, +uint8_t pipeid +); + +void dl_xfer_cb(struct sdio_al_channel_handle *ch_handle, + struct sdio_al_xfer_result *result, + void *ctx); +void ul_xfer_cb(struct sdio_al_channel_handle *ch_handle, + struct sdio_al_xfer_result *result, + void *ctx); + +void dl_data_avail_cb(struct sdio_al_channel_handle *ch_handle, + unsigned int len); + +void hif_sdio_rx_q_alloc(void *ctx); +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/mailbox.c b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/mailbox.c index 84a0a690eeab42bd391c87b92153a9223b041484..91ad93f4cd1de610ae305433475c85c752503494 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/mailbox.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/mailbox.c @@ -1,7 +1,6 @@ /* * Copyright (c) 2013-2019 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 * above copyright notice and this permission notice appear in all @@ -19,6 +18,7 @@ #ifdef CONFIG_SDIO_TRANSFER_MAILBOX #define ATH_MODULE_NAME hif +#include #include #include #include @@ -44,6 +44,24 @@ #include "regtable.h" #include "transfer.h" +/* by default setup a bounce buffer for the data packets, + * if the underlying host controller driver + * does not use DMA you may be able to skip this step + * and save the memory allocation and transfer time + */ +#define HIF_USE_DMA_BOUNCE_BUFFER 1 +#if HIF_USE_DMA_BOUNCE_BUFFER +/* macro to check if DMA buffer is WORD-aligned and DMA-able. + * Most host controllers assume the + * buffer is DMA'able and will bug-check otherwise (i.e. buffers on the stack). + * virt_addr_valid check fails on stack memory. + */ +#define BUFFER_NEEDS_BOUNCE(buffer) (((unsigned long)(buffer) & 0x3) || \ + !virt_addr_valid((buffer))) +#else +#define BUFFER_NEEDS_BOUNCE(buffer) (false) +#endif + #ifdef SDIO_3_0 /** * set_extended_mbox_size() - set extended MBOX size @@ -170,6 +188,40 @@ static void set_extended_mbox_window_info(uint16_t manf_id, } } +/** hif_dev_set_mailbox_swap() - Set the mailbox swap from firmware + * @pdev : The HIF layer object + * + * Return: none + */ +void hif_dev_set_mailbox_swap(struct hif_sdio_dev *pdev) +{ + struct hif_sdio_device *hif_device = hif_dev_from_hif(pdev); + + HIF_ENTER(); + + hif_device->swap_mailbox = true; + + HIF_EXIT(); +} + +/** hif_dev_get_mailbox_swap() - Get the mailbox swap setting + * @pdev : The HIF layer object + * + * Return: true or false + */ +bool hif_dev_get_mailbox_swap(struct hif_sdio_dev *pdev) +{ + struct hif_sdio_device *hif_device; + + HIF_ENTER(); + + hif_device = hif_dev_from_hif(pdev); + + HIF_EXIT(); + + return hif_device->swap_mailbox; +} + /** * hif_dev_get_fifo_address() - get the fifo addresses for dma * @pdev: SDIO HIF object @@ -177,22 +229,24 @@ static void set_extended_mbox_window_info(uint16_t manf_id, * * Return : 0 for success, non-zero for error */ -QDF_STATUS hif_dev_get_fifo_address(struct hif_sdio_dev *pdev, - struct hif_device_mbox_info *config, - uint32_t config_len) +int hif_dev_get_fifo_address(struct hif_sdio_dev *pdev, + void *config, + uint32_t config_len) { uint32_t count; + struct hif_device_mbox_info *cfg = + (struct hif_device_mbox_info *)config; for (count = 0; count < 4; count++) - config->mbox_addresses[count] = HIF_MBOX_START_ADDR(count); + cfg->mbox_addresses[count] = HIF_MBOX_START_ADDR(count); if (config_len >= sizeof(struct hif_device_mbox_info)) { set_extended_mbox_window_info((uint16_t)pdev->func->device, - config); - return QDF_STATUS_SUCCESS; + cfg); + return 0; } - return QDF_STATUS_E_INVAL; + return -EINVAL; } /** @@ -259,8 +313,8 @@ QDF_STATUS hif_dev_map_service_to_pipe(struct hif_sdio_dev *pdev, uint16_t svc, break; default: - HIF_ERROR("%s: Err : Invalid service (%d)", - __func__, svc); + hif_err("%s: Err : Invalid service (%d)", + __func__, svc); status = QDF_STATUS_E_INVAL; break; } @@ -283,13 +337,13 @@ int hif_dev_setup_device(struct hif_sdio_device *pdev) sizeof(pdev->MailBoxInfo)); if (status != QDF_STATUS_SUCCESS) - HIF_ERROR("%s: HIF_DEVICE_GET_MBOX_ADDR failed", __func__); + hif_err("%s: HIF_DEVICE_GET_MBOX_ADDR failed", __func__); status = hif_configure_device(NULL, pdev->HIFDevice, HIF_DEVICE_GET_BLOCK_SIZE, blocksizes, sizeof(blocksizes)); if (status != QDF_STATUS_SUCCESS) - HIF_ERROR("%s: HIF_DEVICE_GET_MBOX_BLOCK_SIZE fail", __func__); + hif_err("%s: HIF_DEVICE_GET_MBOX_BLOCK_SIZE fail", __func__); pdev->BlockSize = blocksizes[MAILBOX_FOR_BLOCK_SIZE]; @@ -322,7 +376,7 @@ void hif_dev_mask_interrupts(struct hif_sdio_device *pdev) HIF_WR_SYNC_BYTE_INC, NULL); if (status != QDF_STATUS_SUCCESS) - HIF_ERROR("%s: Err updating intr reg: %d", __func__, status); + hif_err("%s: Err updating intr reg: %d", __func__, status); } /** hif_dev_unmask_interrupts() - Enable the interrupts in the device @@ -378,7 +432,7 @@ void hif_dev_unmask_interrupts(struct hif_sdio_device *pdev) NULL); if (status != QDF_STATUS_SUCCESS) - HIF_ERROR("%s: Err updating intr reg: %d", __func__, status); + hif_err("%s: Err updating intr reg: %d", __func__, status); } void hif_dev_dump_registers(struct hif_sdio_device *pdev, @@ -388,37 +442,38 @@ void hif_dev_dump_registers(struct hif_sdio_device *pdev, { int i = 0; - HIF_DBG("%s: Mailbox registers:", __func__); + hif_debug("%s: Mailbox registers:", __func__); if (irq_proc) { - HIF_DBG("HostIntStatus: 0x%x ", irq_proc->host_int_status); - HIF_DBG("CPUIntStatus: 0x%x ", irq_proc->cpu_int_status); - HIF_DBG("ErrorIntStatus: 0x%x ", irq_proc->error_int_status); - HIF_DBG("CounterIntStat: 0x%x ", irq_proc->counter_int_status); - HIF_DBG("MboxFrame: 0x%x ", irq_proc->mbox_frame); - HIF_DBG("RxLKAValid: 0x%x ", irq_proc->rx_lookahead_valid); - HIF_DBG("RxLKA0: 0x%x", irq_proc->rx_lookahead[0]); - HIF_DBG("RxLKA1: 0x%x ", irq_proc->rx_lookahead[1]); - HIF_DBG("RxLKA2: 0x%x ", irq_proc->rx_lookahead[2]); - HIF_DBG("RxLKA3: 0x%x", irq_proc->rx_lookahead[3]); + hif_debug("HostIntStatus: 0x%x ", irq_proc->host_int_status); + hif_debug("CPUIntStatus: 0x%x ", irq_proc->cpu_int_status); + hif_debug("ErrorIntStatus: 0x%x ", irq_proc->error_int_status); + hif_debug("CounterIntStat: 0x%x ", + irq_proc->counter_int_status); + hif_debug("MboxFrame: 0x%x ", irq_proc->mbox_frame); + hif_debug("RxLKAValid: 0x%x ", irq_proc->rx_lookahead_valid); + hif_debug("RxLKA0: 0x%x", irq_proc->rx_lookahead[0]); + hif_debug("RxLKA1: 0x%x ", irq_proc->rx_lookahead[1]); + hif_debug("RxLKA2: 0x%x ", irq_proc->rx_lookahead[2]); + hif_debug("RxLKA3: 0x%x", irq_proc->rx_lookahead[3]); if (pdev->MailBoxInfo.gmbox_address != 0) { - HIF_DBG("GMBOX-HostIntStatus2: 0x%x ", - irq_proc->host_int_status2); - HIF_DBG("GMBOX-RX-Avail: 0x%x ", - irq_proc->gmbox_rx_avail); + hif_debug("GMBOX-HostIntStatus2: 0x%x ", + irq_proc->host_int_status2); + hif_debug("GMBOX-RX-Avail: 0x%x ", + irq_proc->gmbox_rx_avail); } } if (irq_en) { - HIF_DBG("IntStatusEnable: 0x%x\n", - irq_en->int_status_enable); - HIF_DBG("CounterIntStatus: 0x%x\n", - irq_en->counter_int_status_enable); + hif_debug("IntStatusEnable: 0x%x\n", + irq_en->int_status_enable); + hif_debug("CounterIntStatus: 0x%x\n", + irq_en->counter_int_status_enable); } for (i = 0; mbox_regs && i < 4; i++) - HIF_DBG("Counter[%d]: 0x%x\n", i, mbox_regs->counter[i]); + hif_debug("Counter[%d]: 0x%x\n", i, mbox_regs->counter[i]); } /* under HL SDIO, with Interface Memory support, we have @@ -449,7 +504,7 @@ static uint8_t hif_dev_map_pipe_to_mail_box(struct hif_sdio_device *pdev, else if (0 == pipeid || 1 == pipeid) return 0; - HIF_ERROR("%s: pipeid=%d invalid", __func__, pipeid); + hif_err("%s: pipeid=%d invalid", __func__, pipeid); qdf_assert(0); @@ -472,8 +527,8 @@ static uint8_t hif_dev_map_mail_box_to_pipe(struct hif_sdio_device *pdev, else if (mbox_index == 1) return upload ? 3 : 2; - HIF_ERROR("%s: mbox_index=%d, upload=%d invalid", - __func__, mbox_index, upload); + hif_err("%s: mbox_index=%d, upload=%d invalid", + __func__, mbox_index, upload); qdf_assert(0); @@ -488,7 +543,7 @@ static uint8_t hif_dev_map_mail_box_to_pipe(struct hif_sdio_device *pdev, * Return 0 for success and non-zero for failure to map */ int hif_get_send_address(struct hif_sdio_device *pdev, - uint8_t pipe, uint32_t *addr) + uint8_t pipe, unsigned long *addr) { uint8_t mbox_index = INVALID_MAILBOX_NUMBER; @@ -535,14 +590,14 @@ void hif_fixup_write_param(struct hif_sdio_dev *pdev, uint32_t req, } else if (taddr == mboxinfo.mbox_prop[1].extended_address) { mboxlen = mboxinfo.mbox_prop[1].extended_size; } else { - HIF_ERROR("%s: Invalid write addr: 0x%08x\n", __func__, taddr); + hif_err("%s: Invalid write addr: 0x%08x\n", __func__, taddr); return; } if (mboxlen != 0) { if (*length > mboxlen) { - HIF_ERROR("%s: Error (%u > %u)", - __func__, *length, mboxlen); + hif_err("%s: Error (%u > %u)", + __func__, *length, mboxlen); return; } @@ -575,9 +630,9 @@ static QDF_STATUS hif_dev_recv_packet(struct hif_sdio_device *pdev, padded_length = DEV_CALC_RECV_PADDED_LEN(pdev, recv_length); if (padded_length > packet->BufferLength) { - HIF_ERROR("%s: No space for padlen:%d recvlen:%d bufferlen:%d", - __func__, padded_length, - recv_length, packet->BufferLength); + hif_err("%s: No space for padlen:%d recvlen:%d bufferlen:%d", + __func__, padded_length, + recv_length, packet->BufferLength); if (packet->Completion) { COMPLETE_HTC_PACKET(packet, QDF_STATUS_E_INVAL); return QDF_STATUS_SUCCESS; @@ -586,9 +641,9 @@ static QDF_STATUS hif_dev_recv_packet(struct hif_sdio_device *pdev, } /* mailbox index is saved in Endpoint member */ - HIF_INFO("%s : hdr:0x%x, len:%d, padded length: %d Mbox:0x%x", - __func__, packet->PktInfo.AsRx.ExpectedHdr, recv_length, - padded_length, mbox_index); + hif_debug("%s : hdr:0x%x, len:%d, padded length: %d Mbox:0x%x", + __func__, packet->PktInfo.AsRx.ExpectedHdr, recv_length, + padded_length, mbox_index); status = hif_read_write(pdev->HIFDevice, pdev->MailBoxInfo.mbox_addresses[mbox_index], @@ -597,18 +652,18 @@ static QDF_STATUS hif_dev_recv_packet(struct hif_sdio_device *pdev, req, sync ? NULL : packet); if (status != QDF_STATUS_SUCCESS && status != QDF_STATUS_E_PENDING) - HIF_ERROR("%s : Failed %d", __func__, status); + hif_err("%s : Failed %d", __func__, status); if (sync) { packet->Status = status; if (status == QDF_STATUS_SUCCESS) { HTC_FRAME_HDR *hdr = (HTC_FRAME_HDR *) packet->pBuffer; - HIF_INFO("%s: EP:%d,Len:%d,Flag:%d,CB:0x%02X,0x%02X\n", - __func__, - hdr->EndpointID, hdr->PayloadLen, - hdr->Flags, hdr->ControlBytes0, - hdr->ControlBytes1); + hif_debug("%s:EP:%d,Len:%d,Flg:%d,CB:0x%02X,0x%02X\n", + __func__, + hdr->EndpointID, hdr->PayloadLen, + hdr->Flags, hdr->ControlBytes0, + hdr->ControlBytes1); } } @@ -638,7 +693,7 @@ static QDF_STATUS hif_dev_issue_recv_packet_bundle if ((HTC_PACKET_QUEUE_DEPTH(recv_pkt_queue) - HTC_MAX_MSG_PER_BUNDLE_RX) > 0) { partial_bundle = true; - HIF_WARN("%s, partial bundle detected num: %d, %d\n", + hif_warn("%s, partial bundle detected num: %d, %d\n", __func__, HTC_PACKET_QUEUE_DEPTH(recv_pkt_queue), HTC_MAX_MSG_PER_BUNDLE_RX); @@ -648,7 +703,7 @@ static QDF_STATUS hif_dev_issue_recv_packet_bundle HTC_MAX_MSG_PER_BUNDLE_RX * target->TargetCreditSize; packet_rx_bundle = allocate_htc_bundle_packet(target); if (!packet_rx_bundle) { - HIF_ERROR("%s: packet_rx_bundle is NULL\n", __func__); + hif_err("%s: packet_rx_bundle is NULL\n", __func__); qdf_sleep(NBUF_ALLOC_FAIL_WAIT_TIME); /* 100 msec sleep */ return QDF_STATUS_E_NOMEM; } @@ -699,8 +754,8 @@ static QDF_STATUS hif_dev_issue_recv_packet_bundle HIF_RD_SYNC_BLOCK_FIX, NULL); if (status != QDF_STATUS_SUCCESS) { - HIF_ERROR("%s, hif_send Failed status:%d\n", - __func__, status); + hif_err("%s, hif_send Failed status:%d\n", + __func__, status); } else { unsigned char *buffer = bundle_buffer; *num_packets_fetched = i; @@ -745,7 +800,7 @@ QDF_STATUS hif_dev_recv_message_pending_handler(struct hif_sdio_device *pdev, HTC_PACKET_QUEUE recv_q, sync_comp_q; QDF_STATUS (*rxCompletion)(void *, qdf_nbuf_t, uint8_t); - HIF_INFO("%s: NumLookAheads: %d\n", __func__, num_look_aheads); + hif_debug("%s: NumLookAheads: %d\n", __func__, num_look_aheads); if (num_pkts_fetched) *num_pkts_fetched = 0; @@ -787,8 +842,8 @@ QDF_STATUS hif_dev_recv_message_pending_handler(struct hif_sdio_device *pdev, id = ((HTC_FRAME_HDR *)&look_aheads[0])->EndpointID; if (id >= ENDPOINT_MAX) { - HIF_ERROR("%s: Invalid Endpoint in lookahead: %d\n", - __func__, id); + hif_err("%s: Invalid Endpoint in lookahead: %d\n", + __func__, id); status = QDF_STATUS_E_PROTO; break; } @@ -974,7 +1029,7 @@ static QDF_STATUS hif_dev_service_cpu_interrupt(struct hif_sdio_device *pdev) cpu_int_status = mboxProcRegs(pdev).cpu_int_status & mboxEnaRegs(pdev).cpu_int_status_enable; - HIF_ERROR("%s: 0x%x", __func__, (uint32_t)cpu_int_status); + hif_err("%s: 0x%x", __func__, (uint32_t)cpu_int_status); /* Clear the interrupt */ mboxProcRegs(pdev).cpu_int_status &= ~cpu_int_status; @@ -1010,7 +1065,7 @@ static QDF_STATUS hif_dev_service_cpu_interrupt(struct hif_sdio_device *pdev) pdev->hif_callbacks.Context, QDF_STATUS_E_FAILURE); } else { - HIF_ERROR("%s: Unrecognized CPU event", __func__); + hif_err("%s: Unrecognized CPU event", __func__); } return status; @@ -1031,16 +1086,16 @@ static QDF_STATUS hif_dev_service_error_interrupt(struct hif_sdio_device *pdev) uint8_t error_int_status = 0; error_int_status = mboxProcRegs(pdev).error_int_status & 0x0F; - HIF_ERROR("%s: 0x%x", __func__, error_int_status); + hif_err("%s: 0x%x", __func__, error_int_status); if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) - HIF_ERROR("%s: Error : Wakeup", __func__); + hif_err("%s: Error : Wakeup", __func__); if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) - HIF_ERROR("%s: Error : Rx Underflow", __func__); + hif_err("%s: Error : Rx Underflow", __func__); if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) - HIF_ERROR("%s: Error : Tx Overflow", __func__); + hif_err("%s: Error : Tx Overflow", __func__); /* Clear the interrupt */ mboxProcRegs(pdev).error_int_status &= ~error_int_status; @@ -1080,7 +1135,7 @@ static QDF_STATUS hif_dev_service_debug_interrupt(struct hif_sdio_device *pdev) QDF_STATUS status; /* Send a target failure event to the application */ - HIF_ERROR("%s: Target debug interrupt", __func__); + hif_err("%s: Target debug interrupt", __func__); /* clear the interrupt , the debug error interrupt is counter 0 * read counter to clear interrupt @@ -1321,33 +1376,603 @@ QDF_STATUS hif_dev_process_pending_irqs(struct hif_sdio_device *pdev, return status; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)) && \ - !defined(WITH_BACKPORTS) +#define DEV_CHECK_RECV_YIELD(pdev) \ + ((pdev)->CurrentDSRRecvCount >= \ + (pdev)->HifIRQYieldParams.recv_packet_yield_count) /** - * hif_sdio_set_drvdata() - set wlan driver data into upper layer private - * @func: pointer to sdio function - * @hifdevice: pointer to hif device + * hif_dev_dsr_handler() - Synchronous interrupt handler + * + * @context: hif send context * - * Return: non zero for success. + * Return: 0 for success and non-zero for failure */ -int hif_sdio_set_drvdata(struct sdio_func *func, - struct hif_sdio_dev *hifdevice) +QDF_STATUS hif_dev_dsr_handler(void *context) { - return sdio_set_drvdata(func, hifdevice); + struct hif_sdio_device *pdev = (struct hif_sdio_device *)context; + QDF_STATUS status = QDF_STATUS_SUCCESS; + bool done = false; + bool async_proc = false; + + /* reset the recv counter that tracks when we need + * to yield from the DSR + */ + pdev->CurrentDSRRecvCount = 0; + /* reset counter used to flag a re-scan of IRQ + * status registers on the target + */ + pdev->RecheckIRQStatusCnt = 0; + + while (!done) { + status = hif_dev_process_pending_irqs(pdev, &done, &async_proc); + if (QDF_IS_STATUS_ERROR(status)) + break; + + if (pdev->HifIRQProcessingMode == HIF_DEVICE_IRQ_SYNC_ONLY) { + /* the HIF layer does not allow async IRQ processing, + * override the asyncProc flag + */ + async_proc = false; + /* this will cause us to re-enter ProcessPendingIRQ() + * and re-read interrupt status registers. + * This has a nice side effect of blocking us until all + * async read requests are completed. This behavior is + * required as we do not allow ASYNC processing + * in interrupt handlers (like Windows CE) + */ + + if (pdev->DSRCanYield && DEV_CHECK_RECV_YIELD(pdev)) + /* ProcessPendingIRQs() pulled enough recv + * messages to satisfy the yield count, stop + * checking for more messages and return + */ + break; + } + + if (async_proc) { + /* the function does some async I/O for performance, + * we need to exit the ISR immediately, the check below + * will prevent the interrupt from being + * Ack'd while we handle it asynchronously + */ + break; + } + } + + if (QDF_IS_STATUS_SUCCESS(status) && !async_proc) { + /* Ack the interrupt only if : + * 1. we did not get any errors in processing interrupts + * 2. there are no outstanding async processing requests + */ + if (pdev->DSRCanYield) { + /* if the DSR can yield do not ACK the interrupt, there + * could be more pending messages. The HIF layer + * must ACK the interrupt on behalf of HTC + */ + hif_info("%s: Yield (RX count: %d)", + __func__, pdev->CurrentDSRRecvCount); + } else { + hif_ack_interrupt(pdev->HIFDevice); + } + } + + return status; +} + +/** + * hif_read_write() - queue a read/write request + * @device: pointer to hif device structure + * @address: address to read + * @buffer: buffer to hold read/write data + * @length: length to read/write + * @request: read/write/sync/async request + * @context: pointer to hold calling context + * + * Return: 0 on success, error number otherwise. + */ +QDF_STATUS +hif_read_write(struct hif_sdio_dev *device, + unsigned long address, + char *buffer, uint32_t length, + uint32_t request, void *context) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct bus_request *busrequest; + + AR_DEBUG_ASSERT(device); + AR_DEBUG_ASSERT(device->func); + hif_debug("%s: device 0x%pK addr 0x%lX buffer 0x%pK", + __func__, device, address, buffer); + hif_debug("%s: len %d req 0x%X context 0x%pK", + __func__, length, request, context); + + /*sdio r/w action is not needed when suspend, so just return */ + if ((device->is_suspend) && + (device->power_config == HIF_DEVICE_POWER_CUT)) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("skip io when suspending\n")); + return QDF_STATUS_SUCCESS; + } + do { + if ((request & HIF_ASYNCHRONOUS) || + (request & HIF_SYNCHRONOUS)) { + /* serialize all requests through the async thread */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("%s: Execution mode: %s\n", __func__, + (request & HIF_ASYNCHRONOUS) ? "Async" + : "Synch")); + busrequest = hif_allocate_bus_request(device); + if (!busrequest) { + hif_err("%s:bus requests unavail", __func__); + hif_err("%s, addr:0x%lX, len:%d", + request & HIF_SDIO_READ ? "READ" : + "WRITE", address, length); + return QDF_STATUS_E_FAILURE; + } + busrequest->address = address; + busrequest->buffer = buffer; + busrequest->length = length; + busrequest->request = request; + busrequest->context = context; + + add_to_async_list(device, busrequest); + + if (request & HIF_SYNCHRONOUS) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("%s: queued sync req: 0x%lX\n", + __func__, + (unsigned long)busrequest)); + + /* wait for completion */ + up(&device->sem_async); + if (down_interruptible(&busrequest->sem_req) == + 0) { + QDF_STATUS status = busrequest->status; + + hif_debug("%s: sync freeing 0x%lX:0x%X", + __func__, + (unsigned long)busrequest, + busrequest->status); + hif_debug("%s: freeing req: 0x%X", + __func__, + (unsigned int)request); + hif_free_bus_request(device, + busrequest); + return status; + } else { + /* interrupted, exit */ + return QDF_STATUS_E_FAILURE; + } + } else { + hif_debug("%s: queued async req: 0x%lX", + __func__, (unsigned long)busrequest); + up(&device->sem_async); + return QDF_STATUS_E_PENDING; + } + } else { + hif_err("%s: Invalid execution mode: 0x%08x", + __func__, (unsigned int)request); + status = QDF_STATUS_E_INVAL; + break; + } + } while (0); + + return status; +} + +/** + * hif_sdio_func_enable() - Handle device enabling as per device + * @device: HIF device object + * @func: function pointer + * + * Return success or failure + */ +static int hif_sdio_func_enable(struct hif_softc *ol_sc, + struct sdio_func *func) +{ + struct hif_sdio_dev *device = get_hif_device(ol_sc, func); + + if (device->is_disabled) { + int ret = 0; + + sdio_claim_host(func); + + ret = hif_sdio_quirk_async_intr(ol_sc, func); + if (ret) { + hif_err("%s: Error setting async intr:%d", + __func__, ret); + sdio_release_host(func); + return QDF_STATUS_E_FAILURE; + } + + func->enable_timeout = 100; + ret = sdio_enable_func(func); + if (ret) { + hif_err("%s: Unable to enable function: %d", + __func__, ret); + sdio_release_host(func); + return QDF_STATUS_E_FAILURE; + } + + ret = sdio_set_block_size(func, HIF_BLOCK_SIZE); + if (ret) { + hif_err("%s: Unable to set block size 0x%X : %d\n", + __func__, HIF_BLOCK_SIZE, ret); + sdio_release_host(func); + return QDF_STATUS_E_FAILURE; + } + + ret = hif_sdio_quirk_mod_strength(ol_sc, func); + if (ret) { + hif_err("%s: Error setting mod strength : %d\n", + __func__, ret); + sdio_release_host(func); + return QDF_STATUS_E_FAILURE; + } + + sdio_release_host(func); + } + + return 0; } + +/** + * __hif_read_write() - sdio read/write wrapper + * @device: pointer to hif device structure + * @address: address to read + * @buffer: buffer to hold read/write data + * @length: length to read/write + * @request: read/write/sync/async request + * @context: pointer to hold calling context + * + * Return: 0 on success, error number otherwise. + */ +static QDF_STATUS +__hif_read_write(struct hif_sdio_dev *device, + uint32_t address, char *buffer, + uint32_t length, uint32_t request, void *context) +{ + uint8_t opcode; + QDF_STATUS status = QDF_STATUS_SUCCESS; + int ret = A_OK; + uint8_t *tbuffer; + bool bounced = false; + + if (!device) { + hif_err("%s: device null!", __func__); + return QDF_STATUS_E_INVAL; + } + + if (!device->func) { + hif_err("%s: func null!", __func__); + return QDF_STATUS_E_INVAL; + } + + hif_debug("%s: addr:0X%06X, len:%08d, %s, %s", __func__, + address, length, + request & HIF_SDIO_READ ? "Read " : "Write", + request & HIF_ASYNCHRONOUS ? "Async" : "Sync "); + + do { + if (request & HIF_EXTENDED_IO) { + //HIF_INFO_HI("%s: Command type: CMD53\n", __func__); + } else { + hif_err("%s: Invalid command type: 0x%08x\n", + __func__, request); + status = QDF_STATUS_E_INVAL; + break; + } + + if (request & HIF_BLOCK_BASIS) { + /* round to whole block length size */ + length = + (length / HIF_BLOCK_SIZE) * + HIF_BLOCK_SIZE; + hif_debug("%s: Block mode (BlockLen: %d)\n", + __func__, length); + } else if (request & HIF_BYTE_BASIS) { + hif_debug("%s: Byte mode (BlockLen: %d)\n", + __func__, length); + } else { + hif_err("%s: Invalid data mode: 0x%08x\n", + __func__, request); + status = QDF_STATUS_E_INVAL; + break; + } + if (request & HIF_SDIO_WRITE) { + hif_fixup_write_param(device, request, + &length, &address); + + hif_debug("addr:%08X, len:0x%08X, dummy:0x%04X\n", + address, length, + (request & HIF_DUMMY_SPACE_MASK) >> 16); + } + + if (request & HIF_FIXED_ADDRESS) { + opcode = CMD53_FIXED_ADDRESS; + hif_debug("%s: Addr mode: fixed 0x%X\n", + __func__, address); + } else if (request & HIF_INCREMENTAL_ADDRESS) { + opcode = CMD53_INCR_ADDRESS; + hif_debug("%s: Address mode: Incremental 0x%X\n", + __func__, address); + } else { + hif_err("%s: Invalid address mode: 0x%08x\n", + __func__, request); + status = QDF_STATUS_E_INVAL; + break; + } + + if (request & HIF_SDIO_WRITE) { +#if HIF_USE_DMA_BOUNCE_BUFFER + if (BUFFER_NEEDS_BOUNCE(buffer)) { + AR_DEBUG_ASSERT(device->dma_buffer); + tbuffer = device->dma_buffer; + /* copy the write data to the dma buffer */ + AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); + if (length > HIF_DMA_BUFFER_SIZE) { + hif_err("%s: Invalid write len: %d\n", + __func__, length); + status = QDF_STATUS_E_INVAL; + break; + } + memcpy(tbuffer, buffer, length); + bounced = true; + } else { + tbuffer = buffer; + } +#else + tbuffer = buffer; +#endif + if (opcode == CMD53_FIXED_ADDRESS && tbuffer) { + ret = sdio_writesb(device->func, address, + tbuffer, length); + hif_debug("%s:r=%d addr:0x%X, len:%d, 0x%X\n", + __func__, ret, address, length, + *(int *)tbuffer); + } else if (tbuffer) { + ret = sdio_memcpy_toio(device->func, address, + tbuffer, length); + hif_debug("%s:r=%d addr:0x%X, len:%d, 0x%X\n", + __func__, ret, address, length, + *(int *)tbuffer); + } + } else if (request & HIF_SDIO_READ) { +#if HIF_USE_DMA_BOUNCE_BUFFER + if (BUFFER_NEEDS_BOUNCE(buffer)) { + AR_DEBUG_ASSERT(device->dma_buffer); + AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE); + if (length > HIF_DMA_BUFFER_SIZE) { + hif_err("%s: Invalid read len: %d\n", + __func__, length); + status = QDF_STATUS_E_INVAL; + break; + } + tbuffer = device->dma_buffer; + bounced = true; + } else { + tbuffer = buffer; + } #else -int hif_sdio_set_drvdata(struct sdio_func *func, - struct hif_sdio_dev *hifdevice) + tbuffer = buffer; +#endif + if (opcode == CMD53_FIXED_ADDRESS && tbuffer) { + ret = sdio_readsb(device->func, tbuffer, + address, length); + hif_debug("%s:r=%d addr:0x%X, len:%d, 0x%X\n", + __func__, ret, address, length, + *(int *)tbuffer); + } else if (tbuffer) { + ret = sdio_memcpy_fromio(device->func, + tbuffer, address, + length); + hif_debug("%s:r=%d addr:0x%X, len:%d, 0x%X\n", + __func__, ret, address, length, + *(int *)tbuffer); + } +#if HIF_USE_DMA_BOUNCE_BUFFER + if (bounced && tbuffer) + memcpy(buffer, tbuffer, length); +#endif + } else { + hif_err("%s: Invalid dir: 0x%08x", __func__, request); + status = QDF_STATUS_E_INVAL; + return status; + } + + if (ret) { + hif_err("%s: SDIO bus operation failed!", __func__); + hif_err("%s: MMC stack returned : %d", __func__, ret); + hif_err("%s: addr:0X%06X, len:%08d, %s, %s", + __func__, address, length, + request & HIF_SDIO_READ ? "Read " : "Write", + request & HIF_ASYNCHRONOUS ? + "Async" : "Sync"); + status = QDF_STATUS_E_FAILURE; + } + } while (false); + + return status; +} + +/** + * async_task() - thread function to serialize all bus requests + * @param: pointer to hif device + * + * thread function to serialize all requests, both sync and async + * Return: 0 on success, error number otherwise. + */ +static int async_task(void *param) { - sdio_set_drvdata(func, hifdevice); + struct hif_sdio_dev *device; + struct bus_request *request; + QDF_STATUS status; + bool claimed = false; + + device = (struct hif_sdio_dev *)param; + set_current_state(TASK_INTERRUPTIBLE); + while (!device->async_shutdown) { + /* wait for work */ + if (down_interruptible(&device->sem_async) != 0) { + /* interrupted, exit */ + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("%s: async task interrupted\n", + __func__)); + break; + } + if (device->async_shutdown) { + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, + ("%s: async task stopping\n", + __func__)); + break; + } + /* we want to hold the host over multiple cmds + * if possible, but holding the host blocks + * card interrupts + */ + qdf_spin_lock_irqsave(&device->asynclock); + /* pull the request to work on */ + while (device->asyncreq) { + request = device->asyncreq; + if (request->inusenext) + device->asyncreq = request->inusenext; + else + device->asyncreq = NULL; + qdf_spin_unlock_irqrestore(&device->asynclock); + hif_debug("%s: processing req: 0x%lX", + __func__, (unsigned long)request); + + if (!claimed) { + sdio_claim_host(device->func); + claimed = true; + } + if (request->scatter_req) { + A_ASSERT(device->scatter_enabled); + /* pass the request to scatter routine which + * executes it synchronously, note, no need + * to free the request since scatter requests + * are maintained on a separate list + */ + status = do_hif_read_write_scatter(device, + request); + } else { + /* call hif_read_write in sync mode */ + status = + __hif_read_write(device, + request->address, + request->buffer, + request->length, + request-> + request & + ~HIF_SYNCHRONOUS, + NULL); + if (request->request & HIF_ASYNCHRONOUS) { + void *context = request->context; + + hif_free_bus_request(device, request); + device->htc_callbacks. + rw_compl_handler(context, status); + } else { + hif_debug("%s: upping req: 0x%lX", + __func__, + (unsigned long)request); + request->status = status; + up(&request->sem_req); + } + } + qdf_spin_lock_irqsave(&device->asynclock); + } + qdf_spin_unlock_irqrestore(&device->asynclock); + if (claimed) { + sdio_release_host(device->func); + claimed = false; + } + } + + complete_and_exit(&device->async_completion, 0); + return 0; } -#endif /* LINUX VERSION */ -struct hif_sdio_dev *get_hif_device(struct sdio_func *func) +/** + * hif_disable_func() - Disable SDIO function + * + * @device: HIF device pointer + * @func: SDIO function pointer + * @reset: If this is called from resume or probe + * + * Return: 0 in case of success, else error value + */ +QDF_STATUS hif_disable_func(struct hif_sdio_dev *device, + struct sdio_func *func, + bool reset) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + HIF_ENTER(); + if (!IS_ERR(device->async_task)) { + init_completion(&device->async_completion); + device->async_shutdown = 1; + up(&device->sem_async); + wait_for_completion(&device->async_completion); + device->async_task = NULL; + sema_init(&device->sem_async, 0); + } + + status = hif_sdio_func_disable(device, func, reset); + if (status == QDF_STATUS_SUCCESS) + device->is_disabled = true; + + cleanup_hif_scatter_resources(device); + + HIF_EXIT(); + + return status; +} + +/** + * hif_enable_func() - Enable SDIO function + * + * @ol_sc: HIF object pointer + * @device: HIF device pointer + * @sdio_func: SDIO function pointer + * @resume: If this is called from resume or probe + * + * Return: 0 in case of success, else error value + */ +QDF_STATUS hif_enable_func(struct hif_softc *ol_sc, struct hif_sdio_dev *device, + struct sdio_func *func, bool resume) { - qdf_assert(func); + int ret = QDF_STATUS_SUCCESS; + + HIF_ENTER(); + + if (!device) { + hif_err("%s: HIF device is NULL", __func__); + return QDF_STATUS_E_INVAL; + } + + if (hif_sdio_func_enable(ol_sc, func)) + return QDF_STATUS_E_FAILURE; + + /* create async I/O thread */ + if (!device->async_task && device->is_disabled) { + device->async_shutdown = 0; + device->async_task = kthread_create(async_task, + (void *)device, + "AR6K Async"); + if (IS_ERR(device->async_task)) { + hif_err("%s: Error creating async task", + __func__); + return QDF_STATUS_E_FAILURE; + } + device->is_disabled = false; + wake_up_process(device->async_task); + } + + if (!resume) + ret = hif_sdio_probe(ol_sc, func, device); + + HIF_EXIT(); - return (struct hif_sdio_dev *)sdio_get_drvdata(func); + return ret; } #endif /* CONFIG_SDIO_TRANSFER_MAILBOX */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/mailbox.h b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/mailbox.h index 9123d872e76d74ffbb816da9917041d8ad6e7b94..3e5913215241fec47eda0b056a0960562efd20d0 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/mailbox.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/mailbox.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016-2019 The Linux Foundation. All rights reserved. * * * @@ -146,11 +146,6 @@ */ #define HIF_DUMMY_SPACE_MASK 0xFFFF0000 -/* - * data written into the dummy space will not put into the final mbox FIFO - */ -#define HIF_DUMMY_SPACE_MASK 0xFFFF0000 - PREPACK struct MBOX_IRQ_PROC_REGISTERS { uint8_t host_int_status; uint8_t cpu_int_status; @@ -190,4 +185,9 @@ struct devRegisters { #define DEV_REGISTERS_SIZE (sizeof(struct MBOX_IRQ_PROC_REGISTERS) + \ sizeof(struct MBOX_IRQ_ENABLE_REGISTERS) + \ sizeof(struct MBOX_COUNTER_REGISTERS)) + +void hif_dev_dump_registers(struct hif_sdio_device *pdev, + struct MBOX_IRQ_PROC_REGISTERS *irq_proc, + struct MBOX_IRQ_ENABLE_REGISTERS *irq_en, + struct MBOX_COUNTER_REGISTERS *mbox_regs); #endif /* _MAILBOX_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/transfer.c b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/transfer.c index 07ebf52b9509d6bade4f1c70e91578aa6d69e9b0..f75680ce06a8ddc5d852e39b539db5667dfe2f53 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/transfer.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/transfer.c @@ -91,12 +91,13 @@ QDF_STATUS hif_dev_send_buffer(struct hif_sdio_device *pdev, uint32_t xfer_id, unsigned char *pData; struct hif_sendContext *sctx; uint32_t request = hif_get_send_buffer_flags(pdev); - uint32_t padded_length, addr = 0; + uint32_t padded_length; + unsigned long addr = 0; int frag_count = 0, i, count, head_len; if (hif_get_send_address(pdev, pipe, &addr)) { - HIF_ERROR("%s: Invalid address map for pipe 0x%x", - __func__, pipe); + hif_err("%s: Invalid address map for pipe 0x%x", + __func__, pipe); return QDF_STATUS_E_INVAL; } @@ -216,17 +217,17 @@ QDF_STATUS hif_dev_alloc_and_prepare_rx_packets(struct hif_sdio_device *pdev, for (i = 0; i < messages; i++) { hdr = (HTC_FRAME_HDR *)&look_aheads[i]; if (hdr->EndpointID >= ENDPOINT_MAX) { - HIF_ERROR("%s: Invalid Endpoint:%d\n", - __func__, hdr->EndpointID); + hif_err("%s: Invalid Endpoint:%d\n", + __func__, hdr->EndpointID); status = QDF_STATUS_E_INVAL; break; } if (hdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) { - HIF_ERROR("%s: Payload length %d exceeds max HTC : %u", - __func__, - hdr->PayloadLen, - (uint32_t)HTC_MAX_PAYLOAD_LENGTH); + hif_err("%s: Payload length %d exceeds max HTC : %u", + __func__, + hdr->PayloadLen, + (uint32_t)HTC_MAX_PAYLOAD_LENGTH); status = QDF_STATUS_E_INVAL; break; } @@ -245,7 +246,7 @@ QDF_STATUS hif_dev_alloc_and_prepare_rx_packets(struct hif_sdio_device *pdev, */ num_messages++; - HIF_INFO("%s: HTC header : %u messages in bundle", + hif_info("%s: HTC header : %u messages in bundle", __func__, num_messages); } @@ -299,12 +300,12 @@ QDF_STATUS hif_dev_alloc_and_prepare_rx_packets(struct hif_sdio_device *pdev, /* make sure message can fit in the endpoint buffer */ if (full_length > packet->BufferLength) { - HIF_ERROR("%s: Payload Length Error", __func__); - HIF_ERROR("%s: header reports payload: %u(%u)", - __func__, hdr->PayloadLen, - full_length); - HIF_ERROR("%s: endpoint buffer size: %d\n", - __func__, packet->BufferLength); + hif_err("%s: Payload Length Error", __func__); + hif_err("%s: header reports payload: %u(%u)", + __func__, hdr->PayloadLen, + full_length); + hif_err("%s: endpoint buffer size: %d\n", + __func__, packet->BufferLength); status = QDF_STATUS_E_INVAL; break; } @@ -381,7 +382,7 @@ QDF_STATUS hif_dev_process_trailer(struct hif_sdio_device *pdev, HTC_RECORD_HDR *record; HTC_LOOKAHEAD_REPORT *look_ahead; - HIF_INFO("%s: length:%d", __func__, length); + hif_debug("%s: length:%d", __func__, length); orig_buffer = buffer; orig_length = length; @@ -399,11 +400,11 @@ QDF_STATUS hif_dev_process_trailer(struct hif_sdio_device *pdev, if (record->Length > length) { /* no room left in buffer for record */ - HIF_ERROR("%s: invalid record len: (%u, %u)", - __func__, record->Length, - record->RecordID); - HIF_ERROR("%s: buffer has %d bytes left", - __func__, length); + hif_err("%s: invalid record len: (%u, %u)", + __func__, record->Length, + record->RecordID); + hif_err("%s: buffer has %d bytes left", + __func__, length); status = QDF_STATUS_E_PROTO; break; } @@ -420,13 +421,13 @@ QDF_STATUS hif_dev_process_trailer(struct hif_sdio_device *pdev, if ((look_ahead->PreValid == ((~look_ahead->PostValid) & 0xFF)) && next_look_aheads) { - HIF_INFO_HI("%s: look_ahead Report", __func__); - HIF_INFO_HI("%s:prevalid:0x%x, postvalid:0x%x", - __func__, look_ahead->PreValid, - look_ahead->PostValid); - HIF_INFO_HI("%s:from endpoint %d : %u", - __func__, from_endpoint, - look_ahead->LookAhead0); + hif_debug("%s: look_ahead Report", __func__); + hif_debug("%s:prevalid:0x%x, postvalid:0x%x", + __func__, look_ahead->PreValid, + look_ahead->PostValid); + hif_debug("%s:from endpoint %d : %u", + __func__, from_endpoint, + look_ahead->LookAhead0); /* look ahead bytes are valid, copy them over */ ((uint8_t *)(&next_look_aheads[0]))[0] = look_ahead->LookAhead0; @@ -498,8 +499,8 @@ QDF_STATUS hif_dev_process_trailer(struct hif_sdio_device *pdev, } break; default: - HIF_ERROR("%s: HIF unhandled record: id:%u length:%u", - __func__, record->RecordID, record->Length); + hif_err("%s: HIF unhandled record: id:%u length:%u", + __func__, record->RecordID, record->Length); break; } @@ -515,7 +516,7 @@ QDF_STATUS hif_dev_process_trailer(struct hif_sdio_device *pdev, debug_dump_bytes(orig_buffer, orig_length, "BAD Recv Trailer"); - HIF_INFO("%s: status = %d", __func__, status); + hif_debug("%s: status = %d", __func__, status); return status; } @@ -572,10 +573,10 @@ QDF_STATUS hif_dev_process_recv_header(struct hif_sdio_device *pdev, /* validate the actual header that was refreshed */ if (packet->ActualLength > packet->BufferLength) { - HIF_ERROR("%s: Bundled RECV Look ahead: 0x%X", - __func__, look_ahead); - HIF_ERROR("%s: Invalid HDR payload length(%d)", - __func__, payloadLen); + hif_err("%s: Bundled RECV Look ahead: 0x%X", + __func__, look_ahead); + hif_err("%s: Invalid HDR payload length(%d)", + __func__, payloadLen); /* limit this to max buffer just to print out * some of the buffer */ @@ -588,12 +589,12 @@ QDF_STATUS hif_dev_process_recv_header(struct hif_sdio_device *pdev, if (packet->Endpoint != HTC_GET_FIELD(buf, HTC_FRAME_HDR, ENDPOINTID)) { - HIF_ERROR("%s: Refreshed HDR EP (%d)", - __func__, - HTC_GET_FIELD(buf, HTC_FRAME_HDR, - ENDPOINTID)); - HIF_ERROR("%s: doesn't match expected EP (%d)", - __func__, packet->Endpoint); + hif_err("%s: Refreshed HDR EP (%d)", + __func__, + HTC_GET_FIELD(buf, HTC_FRAME_HDR, + ENDPOINTID)); + hif_err("%s: doesn't match expected EP (%d)", + __func__, packet->Endpoint); status = QDF_STATUS_E_PROTO; break; } @@ -604,13 +605,13 @@ QDF_STATUS hif_dev_process_recv_header(struct hif_sdio_device *pdev, * length did not reflect the actual header * in the pending message */ - HIF_ERROR("%s: lookahead mismatch!", __func__); - HIF_ERROR("%s: pPkt:0x%lX flags:0x%X", - __func__, (unsigned long)packet, - packet->PktInfo.AsRx.HTCRxFlags); - HIF_ERROR("%s: look_ahead 0x%08X != 0x%08X", - __func__, look_ahead, - packet->PktInfo.AsRx.ExpectedHdr); + hif_err("%s: lookahead mismatch!", __func__); + hif_err("%s: pPkt:0x%lX flags:0x%X", + __func__, (unsigned long)packet, + packet->PktInfo.AsRx.HTCRxFlags); + hif_err("%s: look_ahead 0x%08X != 0x%08X", + __func__, look_ahead, + packet->PktInfo.AsRx.ExpectedHdr); #ifdef ATH_DEBUG_MODULE debug_dump_bytes((uint8_t *)&packet->PktInfo.AsRx. ExpectedHdr, 4, @@ -642,12 +643,12 @@ QDF_STATUS hif_dev_process_recv_header(struct hif_sdio_device *pdev, if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) { - HIF_ERROR("%s: invalid header", - __func__); - HIF_ERROR("%s: payloadlength should be :%d", - __func__, payloadLen); - HIF_ERROR("%s: But control bytes is :%d)", - __func__, temp); + hif_err("%s: invalid header", + __func__); + hif_err("%s: payloadlength should be :%d", + __func__, payloadLen); + hif_err("%s: But control bytes is :%d)", + __func__, temp); status = QDF_STATUS_E_PROTO; break; } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/transfer.h b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/transfer.h index 4a728385134a1abb8182eb77f10e02f48456a173..31950bfeb1a2158eb5fb133cf1d05b4315241308 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/transfer.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/sdio/transfer/transfer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. * * * @@ -65,13 +65,8 @@ struct hif_sendContext { unsigned int head_data_len; }; -void hif_dev_dump_registers(struct hif_sdio_device *pdev, - struct MBOX_IRQ_PROC_REGISTERS *irq_proc, - struct MBOX_IRQ_ENABLE_REGISTERS *irq_en, - struct MBOX_COUNTER_REGISTERS *mbox_regs); - int hif_get_send_address(struct hif_sdio_device *pdev, - uint8_t pipe, uint32_t *addr); + uint8_t pipe, unsigned long *addr); QDF_STATUS hif_dev_alloc_and_prepare_rx_packets(struct hif_sdio_device *pdev, uint32_t look_aheads[], @@ -103,8 +98,20 @@ static inline uint32_t hif_get_send_buffer_flags(struct hif_sdio_device *pdev) return 0; } + +static inline int hif_sdio_bus_configure(struct hif_softc *hif_sc) +{ + return 0; +} + #elif defined(CONFIG_SDIO_TRANSFER_ADMA) -#error "Error - Not implemented yet" +static inline uint32_t hif_get_send_buffer_flags(struct hif_sdio_device *pdev) +{ + /* ADAM-TODO */ + return (uint32_t)HIF_WR_ASYNC_BLOCK_FIX; +} + +int hif_sdio_bus_configure(struct hif_softc *hif_sc); #endif #endif /* __TRANSFER_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/snoc/if_ahb.c b/drivers/staging/qca-wifi-host-cmn/hif/src/snoc/if_ahb.c index 1abc3ac733667ef7df5889ed8d4cf56ba24c2470..49672a5b8a9997fa35da169265a3507706c50b05 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/snoc/if_ahb.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/snoc/if_ahb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 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 @@ -233,14 +233,14 @@ int hif_ahb_configure_legacy_irq(struct hif_pci_softc *sc) qal_vbus_get_irq((struct qdf_pfm_hndl *)pdev, "legacy", &irq); if (irq < 0) { dev_err(&pdev->dev, "Unable to get irq\n"); - ret = -1; + ret = -EFAULT; goto end; } ret = request_irq(irq, hif_pci_legacy_ce_interrupt_handler, IRQF_DISABLED, "wlan_ahb", sc); if (ret) { dev_err(&pdev->dev, "ath_request_irq failed\n"); - ret = -1; + ret = -EFAULT; goto end; } sc->irq = irq; @@ -271,16 +271,24 @@ int hif_ahb_configure_irq(struct hif_pci_softc *sc) for (i = 0; i < scn->ce_count; i++) { if (host_ce_conf[i].flags & CE_ATTR_DISABLE_INTR) continue; - qal_vbus_get_irq((struct qdf_pfm_hndl *)pdev, - ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i], &irq); + ret = pfrm_get_irq(&pdev->dev, (struct qdf_pfm_hndl *)pdev, + ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i], + HIF_IC_CE0_IRQ_OFFSET + i, &irq); + if (ret) { + dev_err(&pdev->dev, "get irq failed\n"); + ret = -EFAULT; + goto end; + } + ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i] = irq; - ret = request_irq(irq , - hif_ahb_interrupt_handler, - IRQF_TRIGGER_RISING, ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i], - &hif_state->tasklets[i]); + ret = pfrm_request_irq(&pdev->dev, irq, + hif_ahb_interrupt_handler, + IRQF_TRIGGER_RISING, + ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i], + &hif_state->tasklets[i]); if (ret) { dev_err(&pdev->dev, "ath_request_irq failed\n"); - ret = -1; + ret = -EFAULT; goto end; } hif_ahb_irq_enable(scn, i); @@ -305,25 +313,34 @@ int hif_ahb_configure_grp_irq(struct hif_softc *scn, hif_ext_group->irq_name = &hif_ahb_get_irq_name; hif_ext_group->work_complete = &hif_dummy_grp_done; + for (j = 0; j < hif_ext_group->numirq; j++) { + ret = pfrm_get_irq(&pdev->dev, (struct qdf_pfm_hndl *)pdev, + ic_irqname[hif_ext_group->irq[j]], + hif_ext_group->irq[j], &irq); + if (ret) { + dev_err(&pdev->dev, "get irq failed\n"); + ret = -EFAULT; + goto end; + } + ic_irqnum[hif_ext_group->irq[j]] = irq; + hif_ext_group->os_irq[j] = irq; + } + qdf_spin_lock_irqsave(&hif_ext_group->irq_lock); for (j = 0; j < hif_ext_group->numirq; j++) { - qal_vbus_get_irq((struct qdf_pfm_hndl *)pdev, - ic_irqname[hif_ext_group->irq[j]], &irq); - - ic_irqnum[hif_ext_group->irq[j]] = irq; + irq = hif_ext_group->os_irq[j]; irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY); - ret = request_irq(irq, hif_ext_group_interrupt_handler, - IRQF_TRIGGER_RISING, - ic_irqname[hif_ext_group->irq[j]], - hif_ext_group); + ret = pfrm_request_irq(scn->qdf_dev->dev, + irq, hif_ext_group_interrupt_handler, + IRQF_TRIGGER_RISING, + ic_irqname[hif_ext_group->irq[j]], + hif_ext_group); if (ret) { - dev_err(&pdev->dev, - "ath_request_irq failed\n"); - ret = -1; + dev_err(&pdev->dev, "ath_request_irq failed\n"); + ret = -EFAULT; goto end; } - hif_ext_group->os_irq[j] = irq; } qdf_spin_unlock_irqrestore(&hif_ext_group->irq_lock); @@ -350,11 +367,22 @@ void hif_ahb_deconfigure_grp_irq(struct hif_softc *scn) hif_ext_group->irq_requested = false; for (j = 0; j < hif_ext_group->numirq; j++) { irq = hif_ext_group->os_irq[j]; + hif_ext_group->irq_enabled = false; irq_clear_status_flags(irq, IRQ_DISABLE_UNLAZY); - free_irq(irq, hif_ext_group); } qdf_spin_unlock_irqrestore(&hif_ext_group->irq_lock); + + /* Avoid holding the irq_lock while freeing the irq + * as the same lock is being held by the irq handler + * while disabling the irq. This causes a deadlock + * between free_irq and irq_handler. + */ + for (j = 0; j < hif_ext_group->numirq; j++) { + irq = hif_ext_group->os_irq[j]; + pfrm_free_irq(scn->qdf_dev->dev, + irq, hif_ext_group); + } } } } @@ -440,19 +468,23 @@ void hif_ahb_disable_bus(struct hif_softc *scn) int mem_pa_size = 0; struct hif_target_info *tgt_info = NULL; struct qdf_vbus_resource *vmres = NULL; + QDF_STATUS status; tgt_info = &scn->target_info; /*Disable WIFI clock input*/ if (sc->mem) { - qal_vbus_get_resource((struct qdf_pfm_hndl *)pdev, &vmres, - IORESOURCE_MEM, 0); - memres = (struct resource *)vmres; - if (!memres) { + status = pfrm_platform_get_resource( + scn->qdf_dev->dev, + (struct qdf_pfm_hndl *)pdev, &vmres, + IORESOURCE_MEM, 0); + if (QDF_IS_STATUS_ERROR(status)) { HIF_INFO("%s: Failed to get IORESOURCE_MEM\n", - __func__); + __func__); return; } - mem_pa_size = memres->end - memres->start + 1; + memres = (struct resource *)vmres; + if (memres) + mem_pa_size = memres->end - memres->start + 1; /* Should not be executed on 8074 platform */ if ((tgt_info->target_type != TARGET_TYPE_QCA8074) && @@ -464,9 +496,9 @@ void hif_ahb_disable_bus(struct hif_softc *scn) } mem = (void __iomem *)sc->mem; if (mem) { - devm_iounmap(&pdev->dev, mem); - devm_release_mem_region(&pdev->dev, scn->mem_pa, - mem_pa_size); + pfrm_devm_iounmap(&pdev->dev, mem); + pfrm_devm_release_mem_region(&pdev->dev, scn->mem_pa, + mem_pa_size); sc->mem = NULL; } } @@ -500,6 +532,8 @@ QDF_STATUS hif_ahb_enable_bus(struct hif_softc *ol_sc, void __iomem *mem = NULL; uint32_t revision_id = 0; struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(ol_sc); + QDF_STATUS status; + struct qdf_vbus_resource *vmres = NULL; sc->pdev = (struct pci_dev *)pdev; sc->dev = &pdev->dev; @@ -513,22 +547,30 @@ QDF_STATUS hif_ahb_enable_bus(struct hif_softc *ol_sc, return QDF_STATUS_E_FAILURE; } - memres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + status = pfrm_platform_get_resource(&pdev->dev, + (struct qdf_pfm_hndl *)pdev, + &vmres, + IORESOURCE_MEM, 0); + if (QDF_IS_STATUS_ERROR(status)) { + HIF_INFO("%s: Failed to get IORESOURCE_MEM\n", __func__); + return -EIO; + } + memres = (struct resource *)vmres; if (!memres) { HIF_INFO("%s: Failed to get IORESOURCE_MEM\n", __func__); return -EIO; } - ret = dma_set_mask(dev, DMA_BIT_MASK(32)); + ret = pfrm_dma_set_mask(dev, 32); if (ret) { HIF_INFO("ath: 32-bit DMA not available\n"); goto err_cleanup1; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) - ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + ret = pfrm_dma_set_mask_and_coherent(dev, 32); #else - ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); + ret = pfrm_dma_set_coherent_mask(dev, 32); #endif if (ret) { HIF_ERROR("%s: failed to set dma mask error = %d", @@ -538,11 +580,16 @@ QDF_STATUS hif_ahb_enable_bus(struct hif_softc *ol_sc, /* Arrange for access to Target SoC registers. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) - mem = devm_ioremap_resource(&pdev->dev, memres); + status = pfrm_devm_ioremap_resource(dev, + (struct qdf_vbus_resource *)memres, + &mem); #else - mem = devm_request_and_ioremap(&pdev->dev, memres); + status = pfrm_devm_request_and_ioremap( + dev, + (struct qdf_vbus_resource *)memres, + &mem); #endif - if (IS_ERR(mem)) { + if (QDF_IS_STATUS_ERROR(status)) { HIF_INFO("ath: ioremap error\n"); ret = PTR_ERR(mem); goto err_cleanup1; @@ -558,7 +605,6 @@ QDF_STATUS hif_ahb_enable_bus(struct hif_softc *ol_sc, hif_register_tbl_attach(ol_sc, hif_type); hif_target_register_tbl_attach(ol_sc, target_type); - /* QCA_WIFI_QCA8074_VP:Should not be executed on 8074 VP platform */ if ((tgt_info->target_type != TARGET_TYPE_QCA8074) && (tgt_info->target_type != TARGET_TYPE_QCA8074V2) && (tgt_info->target_type != TARGET_TYPE_QCA6018)) { @@ -577,7 +623,6 @@ QDF_STATUS hif_ahb_enable_bus(struct hif_softc *ol_sc, return QDF_STATUS_SUCCESS; err_target_sync: - /* QCA_WIFI_QCA8074_VP:Should not be executed on 8074 VP platform */ if ((tgt_info->target_type != TARGET_TYPE_QCA8074) && (tgt_info->target_type != TARGET_TYPE_QCA8074V2) && (tgt_info->target_type != TARGET_TYPE_QCA6018)) { @@ -630,20 +675,22 @@ void hif_ahb_nointrs(struct hif_softc *scn) if (sc->num_msi_intrs > 0) { /* MSI interrupt(s) */ for (i = 0; i < sc->num_msi_intrs; i++) { - free_irq(sc->irq + i, sc); + pfrm_free_irq(scn->qdf_dev->dev, sc->irq + i, sc); } sc->num_msi_intrs = 0; } else { if (!scn->per_ce_irq) { - free_irq(sc->irq, sc); + pfrm_free_irq(scn->qdf_dev->dev, sc->irq, sc); } else { for (i = 0; i < scn->ce_count; i++) { if (host_ce_conf[i].flags & CE_ATTR_DISABLE_INTR) continue; - free_irq(ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i], - &hif_state->tasklets[i]); + pfrm_free_irq( + scn->qdf_dev->dev, + ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i], + &hif_state->tasklets[i]); } hif_ahb_deconfigure_grp_irq(scn); } @@ -771,7 +818,7 @@ void hif_ahb_exec_grp_irq_enable(struct hif_exec_context *hif_ext_group) int i; qdf_spin_lock_irqsave(&hif_ext_group->irq_lock); - if (!hif_ext_group->irq_enabled) { + if (hif_ext_group->irq_requested && !hif_ext_group->irq_enabled) { for (i = 0; i < hif_ext_group->numirq; i++) { enable_irq(hif_ext_group->os_irq[i]); } @@ -790,3 +837,23 @@ bool hif_ahb_needs_bmi(struct hif_softc *scn) { return !ce_srng_based(scn); } + +void hif_ahb_display_stats(struct hif_softc *scn) +{ + if (!scn) { + HIF_ERROR("%s, hif_scn null", __func__); + return; + } + hif_display_ce_stats(scn); +} + +void hif_ahb_clear_stats(struct hif_softc *scn) +{ + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + + if (!hif_state) { + HIF_ERROR("%s, hif_state null", __func__); + return; + } + hif_clear_ce_stats(hif_state); +} diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/snoc/if_snoc.c b/drivers/staging/qca-wifi-host-cmn/hif/src/snoc/if_snoc.c index 119db8af3b395ba6971097b60d35954e8627b8f6..51350887fecceb656e97ebc012902ea4d98a5f44 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/snoc/if_snoc.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/snoc/if_snoc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 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 @@ -78,13 +78,11 @@ int hif_snoc_dump_registers(struct hif_softc *hif_ctx) void hif_snoc_display_stats(struct hif_softc *hif_ctx) { - struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx); - - if (!hif_state) { + if (!hif_ctx) { HIF_ERROR("%s, hif_ctx null", __func__); return; } - hif_display_ce_stats(hif_state); + hif_display_ce_stats(hif_ctx); } void hif_snoc_clear_stats(struct hif_softc *hif_ctx) diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/usb/hif_usb.c b/drivers/staging/qca-wifi-host-cmn/hif/src/usb/hif_usb.c index 4a129e3c5c75483cc13e43d4492c234d7a0548fc..8ed33841763e4952619265d7b8bbca6e1f532267 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/usb/hif_usb.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/usb/hif_usb.c @@ -298,8 +298,14 @@ uint16_t hif_get_free_queue_number(struct hif_opaque_softc *scn, uint8_t pipe_id) { struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); + struct HIF_USB_PIPE *pipe = &device->pipes[pipe_id]; + u16 urb_cnt; + + qdf_spin_lock_irqsave(&pipe->device->cs_lock); + urb_cnt = pipe->urb_cnt; + qdf_spin_unlock_irqrestore(&pipe->device->cs_lock); - return device->pipes[pipe_id].urb_cnt; + return urb_cnt; } /** @@ -378,6 +384,7 @@ QDF_STATUS hif_usb_device_init(struct hif_usb_softc *sc) qdf_spinlock_create(&(device->cs_lock)); qdf_spinlock_create(&(device->rx_lock)); qdf_spinlock_create(&(device->tx_lock)); + qdf_spinlock_create(&device->rx_prestart_lock); device->udev = dev; device->interface = interface; diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/usb/hif_usb_internal.h b/drivers/staging/qca-wifi-host-cmn/hif/src/usb/hif_usb_internal.h index ddf8cc22546be5c1dd025864d495f1a56c984e87..3f3a91eafe952481595b8c1ac6f3bcd5b23aea21 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/usb/hif_usb_internal.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/usb/hif_usb_internal.h @@ -51,7 +51,8 @@ #define HIF_USB_FLUSH_WORK(pipe) flush_work(&pipe->io_complete_work) #else -#define HIF_USB_SCHEDULE_WORK(pipe) schedule_work(&pipe->io_complete_work) +#define HIF_USB_SCHEDULE_WORK(pipe) queue_work(system_highpri_wq,\ + &(pipe)->io_complete_work) #define HIF_USB_INIT_WORK(pipe)\ INIT_WORK(&pipe->io_complete_work,\ usb_hif_io_comp_work) diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/usb/if_usb.c b/drivers/staging/qca-wifi-host-cmn/hif/src/usb/if_usb.c index fd6da656f951c0712bd38e612e765f1731cbd4df..7917380e060b6a7ffabdebb9027f56bd5349c4d1 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/usb/if_usb.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/usb/if_usb.c @@ -26,7 +26,6 @@ #include "hif_debug.h" #include "epping_main.h" #include "hif_main.h" -#include "qwlan_version.h" #include "usb_api.h" #define DELAY_FOR_TARGET_READY 200 /* 200ms */ @@ -195,8 +194,6 @@ QDF_STATUS hif_usb_enable_bus(struct hif_softc *scn, u32 hif_type; u32 target_type; - usb_get_dev(usbdev); - if (!scn) { HIF_ERROR("%s: hif_ctx is NULL", __func__); goto err_usb; @@ -230,6 +227,7 @@ QDF_STATUS hif_usb_enable_bus(struct hif_softc *scn, * by CNSS driver. */ if (target_type != TARGET_TYPE_QCN7605) { + usb_get_dev(usbdev); if ((usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), USB_REQ_SET_CONFIGURATION, 0, 1, 0, NULL, 0, HZ)) < 0) { @@ -272,7 +270,8 @@ QDF_STATUS hif_usb_enable_bus(struct hif_softc *scn, unregister_reboot_notifier(&sc->reboot_notifier); err_usb: ret = QDF_STATUS_E_FAILURE; - usb_put_dev(usbdev); + if (target_type != TARGET_TYPE_QCN7605) + usb_put_dev(usbdev); return ret; } @@ -306,7 +305,8 @@ void hif_usb_disable_bus(struct hif_softc *hif_ctx) /* disable lpm to avoid following cold reset will * cause xHCI U1/U2 timeout */ - usb_disable_lpm(udev); + if (tgt_info->target_type != TARGET_TYPE_QCN7605) + usb_disable_lpm(udev); /* wait for disable lpm */ set_current_state(TASK_INTERRUPTIBLE); @@ -319,10 +319,10 @@ void hif_usb_disable_bus(struct hif_softc *hif_ctx) if (g_usb_sc->suspend_state) hif_bus_resume(GET_HIF_OPAQUE_HDL(hif_ctx)); - if (tgt_info->target_type != TARGET_TYPE_QCN7605) + if (tgt_info->target_type != TARGET_TYPE_QCN7605) { unregister_reboot_notifier(&sc->reboot_notifier); - - usb_put_dev(interface_to_usbdev(interface)); + usb_put_dev(udev); + } hif_usb_device_deinit(sc); @@ -532,8 +532,7 @@ int hif_usb_bus_configure(struct hif_softc *scn) else mode = PLD_MISSION; - return pld_wlan_enable(scn->qdf_dev->dev, &cfg, - mode, QWLAN_VERSIONSTR); + return pld_wlan_enable(scn->qdf_dev->dev, &cfg, mode); } #else /** @@ -706,7 +705,6 @@ void hif_usb_ramdump_handler(struct hif_opaque_softc *scn) if (pattern == FW_ASSERT_PATTERN) { HIF_ERROR("Firmware crash detected...\n"); - HIF_ERROR("Host SW version: %s\n", QWLAN_VERSIONSTR); HIF_ERROR("target_type: %d.target_version %d. target_revision%d.", tgt_info->target_type, tgt_info->target_version, @@ -722,7 +720,7 @@ void hif_usb_ramdump_handler(struct hif_opaque_softc *scn) reg = (uint32_t *) (data + 4); start_addr = *reg++; if (sc->fw_ram_dumping == 0) { - pr_err("Firmware stack dump:"); + qdf_nofl_err("Firmware stack dump:"); sc->fw_ram_dumping = 1; fw_stack_addr = start_addr; } @@ -731,13 +729,13 @@ void hif_usb_ramdump_handler(struct hif_opaque_softc *scn) for (i = 0; i < (len - 8); i += 16) { if ((*reg == FW_REG_END_PATTERN) && (i == len - 12)) { sc->fw_ram_dumping = 0; - pr_err("Stack start address = %#08x\n", - fw_stack_addr); + qdf_nofl_err("Stack start address = %#08x", + fw_stack_addr); break; } hex_dump_to_buffer(reg, remaining, 16, 4, str_buf, sizeof(str_buf), false); - pr_err("%#08x: %s\n", start_addr + i, str_buf); + qdf_nofl_err("%#08x: %s", start_addr + i, str_buf); remaining -= 16; reg += 4; } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/usb/if_usb.h b/drivers/staging/qca-wifi-host-cmn/hif/src/usb/if_usb.h index 35d83af601d7f49ec3fd360a863e6fd9353fba7b..1dd3840559446f3ceb10c02ab6f45c973cca0b59 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/usb/if_usb.h +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/usb/if_usb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -117,6 +117,7 @@ struct HIF_DEVICE_USB { qdf_spinlock_t cs_lock; qdf_spinlock_t tx_lock; qdf_spinlock_t rx_lock; + qdf_spinlock_t rx_prestart_lock; struct hif_msg_callbacks htc_callbacks; struct usb_device *udev; struct usb_interface *interface; diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/usb/usbdrv.c b/drivers/staging/qca-wifi-host-cmn/hif/src/usb/usbdrv.c index 13ccace19b53f0e3aa73cf0b577d06aeb0491df2..c56aa3152825ec261910f4872cc79ce76705e46c 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/usb/usbdrv.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/usb/usbdrv.c @@ -546,6 +546,7 @@ static void usb_hif_usb_recv_prestart_complete QDF_STATUS status = QDF_STATUS_SUCCESS; qdf_nbuf_t buf = NULL; struct HIF_USB_PIPE *pipe = urb_context->pipe; + struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device); HIF_DBG("+%s: recv pipe: %d, stat:%d,len:%d urb:0x%pK", __func__, @@ -601,8 +602,10 @@ static void usb_hif_usb_recv_prestart_complete usb_hif_cleanup_recv_urb(urb_context); /* Prestart URBs runs out and now start working receive pipe. */ - if (--pipe->urb_prestart_cnt == 0) + qdf_spin_lock_irqsave(&pipe->device->rx_prestart_lock); + if ((--pipe->urb_prestart_cnt == 0) && !sc->suspend_state) usb_hif_start_recv_pipes(pipe->device); + qdf_spin_unlock_irqrestore(&pipe->device->rx_prestart_lock); HIF_DBG("-%s", __func__); } @@ -676,6 +679,11 @@ static void usb_hif_usb_recv_complete(struct urb *urb) } /* note: queue implements a lock */ skb_queue_tail(&pipe->io_comp_queue, buf); + + if (pipe->device->htc_callbacks.update_bundle_stats) + pipe->device->htc_callbacks.update_bundle_stats + (pipe->device->htc_callbacks.Context, 1); + HIF_USB_SCHEDULE_WORK(pipe); } while (false); @@ -719,6 +727,7 @@ static void usb_hif_usb_recv_bundle_complete(struct urb *urb) HTC_FRAME_HDR *HtcHdr; uint16_t payloadLen; qdf_nbuf_t new_skb = NULL; + uint8_t no_of_pkt_in_bundle; HIF_DBG("+%s: recv pipe: %d, stat:%d,len:%d urb:0x%pK", __func__, @@ -766,6 +775,7 @@ static void usb_hif_usb_recv_bundle_complete(struct urb *urb) qdf_nbuf_peek_header(buf, &netdata, &netlen); netlen = urb->actual_length; + no_of_pkt_in_bundle = 0; do { uint16_t frame_len; @@ -815,7 +825,14 @@ static void usb_hif_usb_recv_bundle_complete(struct urb *urb) new_skb = NULL; netdata += frame_len; netlen -= frame_len; + no_of_pkt_in_bundle++; } while (netlen); + + if (pipe->device->htc_callbacks.update_bundle_stats) + pipe->device->htc_callbacks.update_bundle_stats + (pipe->device->htc_callbacks.Context, + no_of_pkt_in_bundle); + HIF_USB_SCHEDULE_WORK(pipe); } while (false); @@ -854,6 +871,7 @@ static void usb_hif_post_recv_prestart_transfers(struct HIF_USB_PIPE *recv_pipe, HIF_TRACE("+%s", __func__); + qdf_spin_lock_irqsave(&recv_pipe->device->rx_prestart_lock); for (i = 0; i < prestart_urb; i++) { urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe); if (!urb_context) @@ -885,7 +903,6 @@ static void usb_hif_post_recv_prestart_transfers(struct HIF_USB_PIPE *recv_pipe, urb_context->buf); usb_hif_enqueue_pending_transfer(recv_pipe, urb_context); - usb_status = usb_submit_urb(urb, GFP_ATOMIC); if (usb_status) { @@ -897,6 +914,7 @@ static void usb_hif_post_recv_prestart_transfers(struct HIF_USB_PIPE *recv_pipe, } recv_pipe->urb_prestart_cnt++; } + qdf_spin_unlock_irqrestore(&recv_pipe->device->rx_prestart_lock); HIF_TRACE("-%s", __func__); } @@ -1070,8 +1088,9 @@ void usb_hif_start_recv_pipes(struct HIF_DEVICE_USB *device) pipe = &device->pipes[HIF_RX_DATA_PIPE]; pipe->urb_cnt_thresh = pipe->urb_alloc / 2; - HIF_TRACE("Post URBs to RX_DATA_PIPE: %d", - device->pipes[HIF_RX_DATA_PIPE].urb_cnt); + HIF_TRACE("Post URBs to RX_DATA_PIPE: %d is_bundle %d", + device->pipes[HIF_RX_DATA_PIPE].urb_cnt, + device->is_bundle_enabled); if (device->is_bundle_enabled) { usb_hif_post_recv_bundle_transfers(pipe, pipe->device->rx_bundle_buf_len); diff --git a/drivers/staging/qca-wifi-host-cmn/htc/htc.c b/drivers/staging/qca-wifi-host-cmn/htc/htc.c index c7b7d927cd333020dd2731a9d06752771959de08..f2d420cdc72e321b6014d47b5a8c3f6274b3a72a 100644 --- a/drivers/staging/qca-wifi-host-cmn/htc/htc.c +++ b/drivers/staging/qca-wifi-host-cmn/htc/htc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 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 @@ -19,6 +19,7 @@ #include "htc_debug.h" #include "htc_internal.h" #include "htc_credit_history.h" +#include "htc_hang_event.h" #include #include /* qdf_nbuf_t */ #include /* qdf_print */ @@ -45,7 +46,7 @@ ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc, #endif -#if (defined(CONFIG_MCL) || defined(QCA_WIFI_QCA8074) || \ +#if (defined(WMI_MULTI_MAC_SVC) || defined(QCA_WIFI_QCA8074) || \ defined(QCA_WIFI_QCA6018)) static const uint32_t svc_id[] = {WMI_CONTROL_SVC, WMI_CONTROL_SVC_WMAC1, WMI_CONTROL_SVC_WMAC2}; @@ -134,6 +135,16 @@ void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start) hif_dump(target->hif_dev, CmdId, start); } +void htc_ce_tasklet_debug_dump(HTC_HANDLE htc_handle) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); + + if (!target->hif_dev) + return; + + hif_display_stats(target->hif_dev); +} + /* cleanup the HTC instance */ static void htc_cleanup(HTC_TARGET *target) { @@ -143,6 +154,9 @@ static void htc_cleanup(HTC_TARGET *target) HTC_PACKET_QUEUE *pkt_queue; qdf_nbuf_t netbuf; + while (htc_dec_return_runtime_cnt((void *)target) >= 0) + hif_pm_runtime_put(target->hif_dev, RTPM_ID_HTC); + if (target->hif_dev) { hif_detach_htc(target->hif_dev); hif_mask_interrupt_call(target->hif_dev); @@ -260,9 +274,49 @@ static void htc_runtime_pm_deinit(HTC_TARGET *target) qdf_destroy_work(0, &target->queue_kicker); } +int32_t htc_dec_return_runtime_cnt(HTC_HANDLE htc) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc); + + return qdf_atomic_dec_return(&target->htc_runtime_cnt); +} + +/** + * htc_init_runtime_cnt: Initialize htc runtime count + * @htc: HTC handle + * + * Return: None + */ +static inline +void htc_init_runtime_cnt(HTC_TARGET *target) +{ + qdf_atomic_init(&target->htc_runtime_cnt); +} #else static inline void htc_runtime_pm_init(HTC_TARGET *target) { } static inline void htc_runtime_pm_deinit(HTC_TARGET *target) { } + +static inline +void htc_init_runtime_cnt(HTC_TARGET *target) +{ +} +#endif + +#if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) +static +void htc_update_rx_bundle_stats(void *ctx, uint8_t no_of_pkt_in_bundle) +{ + HTC_TARGET *target = (HTC_TARGET *)ctx; + + no_of_pkt_in_bundle--; + if (target && (no_of_pkt_in_bundle < HTC_MAX_MSG_PER_BUNDLE_RX)) + target->rx_bundle_stats[no_of_pkt_in_bundle]++; +} +#else +static +void htc_update_rx_bundle_stats(void *ctx, uint8_t no_of_pkt_in_bundle) +{ +} #endif /* registered target arrival callback from the HIF layer */ @@ -334,6 +388,7 @@ HTC_HANDLE htc_create(void *ol_sc, struct htc_init_info *pInfo, htcCallbacks.txResourceAvailHandler = htc_tx_resource_avail_handler; htcCallbacks.fwEventHandler = htc_fw_event_handler; + htcCallbacks.update_bundle_stats = htc_update_rx_bundle_stats; target->hif_dev = ol_sc; /* Get HIF default pipe for HTC message exchange */ @@ -349,9 +404,12 @@ HTC_HANDLE htc_create(void *ol_sc, struct htc_init_info *pInfo, } while (false); htc_recv_init(target); + htc_init_runtime_cnt(target); HTC_TRACE("-htc_create: (0x%pK)", target); + htc_hang_event_notifier_register(target); + return (HTC_HANDLE) target; } @@ -361,6 +419,7 @@ void htc_destroy(HTC_HANDLE HTCHandle) AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_destroy .. Destroying :0x%pK\n", target)); + htc_hang_event_notifier_unregister(); hif_stop(htc_get_hif_device(HTCHandle)); if (target) htc_cleanup(target); diff --git a/drivers/staging/qca-wifi-host-cmn/htc/htc_api.h b/drivers/staging/qca-wifi-host-cmn/htc/htc_api.h index b4eeb33a8c8f6c5657696716662fd80fc0c58477..5ed879821a3045097152af611568df28d1afa67d 100644 --- a/drivers/staging/qca-wifi-host-cmn/htc/htc_api.h +++ b/drivers/staging/qca-wifi-host-cmn/htc/htc_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 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 @@ -38,7 +38,13 @@ extern "C" { #define HTC_HTT_TRANSFER_HDRSIZE 24 -typedef void *HTC_HANDLE; +/* + * NOTE WELL: struct opaque_htc_handle is not defined anywhere. This + * reference is used to help ensure that a HTC_HANDLE is never used + * where a different handle type is expected + */ +struct opaque_htc_handle; +typedef struct opaque_htc_handle *HTC_HANDLE; typedef uint16_t HTC_SERVICE_ID; @@ -63,6 +69,8 @@ struct ol_ath_htc_stats { /* To resume HTT Tx queue during runtime resume */ typedef void (*HTC_EP_RESUME_TX_QUEUE)(void *); +typedef int (*HTC_EP_PADDING_CREDIT_UPDATE) (void *, int); + /* per service connection send completion */ typedef void (*HTC_EP_SEND_PKT_COMPLETE)(void *, HTC_PACKET *); /* per service connection callback when a plurality of packets have been sent @@ -169,6 +177,8 @@ struct htc_ep_callbacks { HTC_EP_SEND_PKT_COMP_MULTIPLE EpTxCompleteMultiple; HTC_EP_RESUME_TX_QUEUE ep_resume_tx_queue; + + HTC_EP_PADDING_CREDIT_UPDATE ep_padding_credit_update; /* if EpRecvAllocThresh is non-NULL, HTC will compare the * threshold value to the current recv packet length and invoke * the EpRecvAllocThresh callback to acquire a packet buffer @@ -471,6 +481,15 @@ QDF_STATUS htc_connect_service(HTC_HANDLE HTCHandle, */ void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start); +/** + * htc_ce_taklet_debug_dump - Dump ce tasklet rings debug data + * @HTCHandle - HTC handle + * + * Debug logs will be printed. + * Return: None + */ +void htc_ce_tasklet_debug_dump(HTC_HANDLE htc_handle); + /** * htc_send_pkt - Send an HTC packet * @HTCHandle - HTC handle @@ -697,7 +716,7 @@ struct ol_ath_htc_stats *ieee80211_ioctl_get_htc_stats(HTC_HANDLE * * Return: htc_handle tx queue depth */ -int htc_get_tx_queue_depth(HTC_HANDLE *htc_handle, HTC_ENDPOINT_ID endpoint_id); +int htc_get_tx_queue_depth(HTC_HANDLE htc_handle, HTC_ENDPOINT_ID endpoint_id); #ifdef WLAN_FEATURE_FASTPATH void htc_ctrl_msg_cmpl(HTC_HANDLE htc_pdev, HTC_ENDPOINT_ID htc_ep_id); @@ -762,9 +781,23 @@ void htc_clear_bundle_stats(HTC_HANDLE HTCHandle); #ifdef FEATURE_RUNTIME_PM int htc_pm_runtime_get(HTC_HANDLE htc_handle); int htc_pm_runtime_put(HTC_HANDLE htc_handle); + +/** + * htc_dec_return_runtime_cnt: Decrement htc runtime count + * @htc: HTC handle + * + * Return: value of runtime count after decrement + */ +int32_t htc_dec_return_runtime_cnt(HTC_HANDLE htc); #else static inline int htc_pm_runtime_get(HTC_HANDLE htc_handle) { return 0; } static inline int htc_pm_runtime_put(HTC_HANDLE htc_handle) { return 0; } + +static inline +int32_t htc_dec_return_runtime_cnt(HTC_HANDLE htc) +{ + return -1; +} #endif /** @@ -818,4 +851,19 @@ void htc_print_credit_history(HTC_HANDLE htc, uint32_t count, print(print_priv, "HTC Credit History Feature is disabled"); } #endif + +#ifdef SYSTEM_PM_CHECK +/** + * htc_system_resume() - Send out any pending WMI/HTT + * messages pending in htc queues on system resume. + * @htc: HTC handle + * + * Return: None + */ +void htc_system_resume(HTC_HANDLE htc); +#else +static inline void htc_system_resume(HTC_HANDLE htc) +{ +} +#endif #endif /* _HTC_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/htc/htc_credit_history.c b/drivers/staging/qca-wifi-host-cmn/htc/htc_credit_history.c index 4e067201232714b2a4cba15a102a91d3d0afb0c5..becfd4e3ced3cc5765c349d75b0091b1e7b6e1eb 100644 --- a/drivers/staging/qca-wifi-host-cmn/htc/htc_credit_history.c +++ b/drivers/staging/qca-wifi-host-cmn/htc/htc_credit_history.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018,2020 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 @@ -20,6 +20,8 @@ #include "htc_internal.h" #include "htc_credit_history.h" #include +#include +#include struct HTC_CREDIT_HISTORY { enum htc_credit_exchange_type type; @@ -28,6 +30,11 @@ struct HTC_CREDIT_HISTORY { uint32_t htc_tx_queue_depth; }; +struct htc_hang_data_fixed_param { + uint16_t tlv_header; + struct HTC_CREDIT_HISTORY credit_hist; +} qdf_packed; + static qdf_spinlock_t g_htc_credit_lock; static uint32_t g_htc_credit_history_idx; static uint32_t g_htc_credit_history_length; @@ -135,3 +142,57 @@ void htc_print_credit_history(HTC_HANDLE htc, uint32_t count, qdf_spin_unlock_bh(&g_htc_credit_lock); } + +#ifdef WLAN_HANG_EVENT +void htc_log_hang_credit_history(struct notifier_block *block, void *data) +{ + qdf_notif_block *notif_block = qdf_container_of(block, qdf_notif_block, + notif_block); + struct qdf_notifer_data *htc_hang_data = data; + uint32_t count = 1, idx, total_len; + HTC_HANDLE htc; + struct htc_hang_data_fixed_param *cmd; + uint8_t *htc_buf_ptr; + + htc = notif_block->priv_data; + + if (!htc) + return; + + if (!htc_hang_data) + return; + + total_len = sizeof(struct htc_hang_data_fixed_param); + qdf_spin_lock_bh(&g_htc_credit_lock); + + if (count > HTC_CREDIT_HISTORY_MAX) + count = HTC_CREDIT_HISTORY_MAX; + if (count > g_htc_credit_history_length) + count = g_htc_credit_history_length; + + idx = HTC_CREDIT_HISTORY_MAX + g_htc_credit_history_idx - count; + idx %= HTC_CREDIT_HISTORY_MAX; + + qdf_spin_unlock_bh(&g_htc_credit_lock); + + while (count) { + struct HTC_CREDIT_HISTORY *hist = + &htc_credit_history_buffer[idx]; + htc_buf_ptr = htc_hang_data->hang_data + htc_hang_data->offset; + cmd = (struct htc_hang_data_fixed_param *)htc_buf_ptr; + + if (htc_hang_data->offset + total_len > QDF_WLAN_HANG_FW_OFFSET) + return; + + QDF_HANG_EVT_SET_HDR(&cmd->tlv_header, + HANG_EVT_TAG_HTC_CREDIT_HIST, + QDF_HANG_GET_STRUCT_TLVLEN(struct htc_hang_data_fixed_param)); + qdf_mem_copy(&cmd->credit_hist, hist, sizeof(*hist)); + --count; + ++idx; + if (idx >= HTC_CREDIT_HISTORY_MAX) + idx = 0; + htc_hang_data->offset += total_len; + } +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/htc/htc_credit_history.h b/drivers/staging/qca-wifi-host-cmn/htc/htc_credit_history.h index 78b284eaac3e470611045c390a3f3395fc096a31..bd02c998a154b588d62577c5df91f1a05a0da5f5 100644 --- a/drivers/staging/qca-wifi-host-cmn/htc/htc_credit_history.h +++ b/drivers/staging/qca-wifi-host-cmn/htc/htc_credit_history.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018,2020 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 @@ -32,7 +32,24 @@ void htc_credit_history_init(void); void htc_credit_record(enum htc_credit_exchange_type type, uint32_t tx_credit, uint32_t htc_tx_queue_depth); - +#ifdef WLAN_HANG_EVENT +/** + * htc_log_hang_credit_history: Log the credit history into a buffer + * @block: Notifier block + * @data: Private data of the block. + * + * HTC hang event notifier callback inovked when the recovery is triggered + * to log the credit information to understand the reason for recovery. + * + * Return: none + */ +void htc_log_hang_credit_history(struct notifier_block *block, void *data); +#else +static inline +void htc_log_hang_credit_history(struct notifier_block *block, void *data) +{ +} +#endif #else /* FEATURE_HTC_CREDIT_HISTORY */ static inline diff --git a/drivers/staging/qca-wifi-host-cmn/htc/htc_hang_event.c b/drivers/staging/qca-wifi-host-cmn/htc/htc_hang_event.c new file mode 100644 index 0000000000000000000000000000000000000000..b6b75760dce7f684484dbab407515bb93b2b47d0 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/htc/htc_hang_event.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include "htc_hang_event.h" +#include "htc_internal.h" +#include "htc_credit_history.h" + +static int htc_recovery_notifier_call(struct notifier_block *block, + unsigned long state, + void *data) +{ + htc_log_hang_credit_history(block, data); + + return NOTIFY_OK; +} + +static qdf_notif_block htc_recovery_notifier = { + .notif_block.notifier_call = htc_recovery_notifier_call, +}; + +QDF_STATUS htc_hang_event_notifier_register(HTC_TARGET *target) +{ + htc_recovery_notifier.priv_data = target; + return qdf_hang_event_register_notifier(&htc_recovery_notifier); +} + +QDF_STATUS htc_hang_event_notifier_unregister(void) +{ + return qdf_hang_event_unregister_notifier(&htc_recovery_notifier); +} diff --git a/drivers/staging/qca-wifi-host-cmn/htc/htc_hang_event.h b/drivers/staging/qca-wifi-host-cmn/htc/htc_hang_event.h new file mode 100644 index 0000000000000000000000000000000000000000..3304541bca93d02d60296af08cf7e23441daaf90 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/htc/htc_hang_event.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef HTC_HANG_EVENT_H +#define HTC_HANG_EVENT_H + +#include "htc_internal.h" + +#ifdef WLAN_HANG_EVENT +/** + * htc_hang_event_notifier_register() - HTC hang event notifier register + * @target: Target specific htc hangle + * + * This function registers htc layer notifier for the hang event notifier chain. + * + * Return: QDF_STATUS + */ +QDF_STATUS htc_hang_event_notifier_register(HTC_TARGET *target); + +/** + * htc_hang_event_notifier_unregister() - htc hang event notifier unregister + * + * This function unregisters htc layer notifier for the hang event notifier + * chain. + * + * Return: QDF_STATUS + */ +QDF_STATUS htc_hang_event_notifier_unregister(void); +#else +static inline QDF_STATUS htc_hang_event_notifier_register(HTC_TARGET *target) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS htc_hang_event_notifier_unregister(void) +{ + return QDF_STATUS_SUCCESS; +} +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/htc/htc_internal.h b/drivers/staging/qca-wifi-host-cmn/htc/htc_internal.h index 32b527821fee14eb88eb498d1e4bc70902e7f5b0..a51e910a59460bc13de664844124ece2f7b6c9f0 100644 --- a/drivers/staging/qca-wifi-host-cmn/htc/htc_internal.h +++ b/drivers/staging/qca-wifi-host-cmn/htc/htc_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -39,9 +39,15 @@ extern "C" { #define HTC_TARGET_DEBUG_INTR_MASK 0x01 #define HTC_TARGET_CREDIT_INTR_MASK 0xF0 #define HTC_MIN_MSG_PER_BUNDLE 2 + #if defined(HIF_USB) + #define HTC_MAX_MSG_PER_BUNDLE_RX 11 -#define HTC_MAX_MSG_PER_BUNDLE_TX 8 +#if defined(CFG_HTC_MAX_MSG_PER_BUNDLE_TX) +#define HTC_MAX_MSG_PER_BUNDLE_TX CFG_HTC_MAX_MSG_PER_BUNDLE_TX +#else +#define HTC_MAX_MSG_PER_BUNDLE_TX 8 +#endif /* CFG_HTC_MAX_MSG_PER_BUNDLE_TX */ #else #define HTC_MAX_MSG_PER_BUNDLE_RX 64 #define HTC_MAX_MSG_PER_BUNDLE 16 @@ -242,6 +248,11 @@ typedef struct _HTC_TARGET { uint8_t wmi_ep_count; /* Flag to indicate whether htc header length check is required */ bool htc_hdr_length_check; + +#ifdef FEATURE_RUNTIME_PM + /* Runtime count for H2T msg with response */ + qdf_atomic_t htc_runtime_cnt; +#endif } HTC_TARGET; diff --git a/drivers/staging/qca-wifi-host-cmn/htc/htc_packet.h b/drivers/staging/qca-wifi-host-cmn/htc/htc_packet.h index 8ac7db432caf99693cf57cb71120a8c73ce27836..78e0a3b95bb6bfe0b87b9ff7f4f281f9d907a070 100644 --- a/drivers/staging/qca-wifi-host-cmn/htc/htc_packet.h +++ b/drivers/staging/qca-wifi-host-cmn/htc/htc_packet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, 2016-2017, 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016-2017, 2019-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 @@ -76,8 +76,14 @@ struct htc_tx_packet_info { /* Tag packet for runtime put after sending */ #define HTC_TX_PACKET_TAG_RUNTIME_PUT (HTC_TX_PACKET_TAG_USER_DEFINED + 3) +/*Tag packet for runtime put in response or cleanup */ +#define HTC_TX_PACKET_TAG_RTPM_PUT_RC (HTC_TX_PACKET_TAG_USER_DEFINED + 4) + +#define HTC_TX_PACKET_SYSTEM_SUSPEND (HTC_TX_PACKET_TAG_USER_DEFINED + 5) +#define HTC_TX_PACKET_SYSTEM_RESUME (HTC_TX_PACKET_TAG_USER_DEFINED + 6) #define HTC_TX_PACKET_FLAG_FIXUP_NETBUF (1 << 0) +#define HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA (1 << 1) /** * struct htc_rx_packet_info - HTC RX Packet information diff --git a/drivers/staging/qca-wifi-host-cmn/htc/htc_recv.c b/drivers/staging/qca-wifi-host-cmn/htc/htc_recv.c index ce09ee0296eaec82603bb752362522f1f07b363e..2d6047da83efd86b91630b43a39cb5e91052ef45 100644 --- a/drivers/staging/qca-wifi-host-cmn/htc/htc_recv.c +++ b/drivers/staging/qca-wifi-host-cmn/htc/htc_recv.c @@ -229,10 +229,6 @@ qdf_nbuf_t rx_sg_to_single_netbuf(HTC_TARGET *target) } #endif -#ifdef CONFIG_WIN -#define HTC_MSG_NACK_SUSPEND 7 -#endif - QDF_STATUS htc_rx_completion_handler(void *Context, qdf_nbuf_t netbuf, uint8_t pipeID) { diff --git a/drivers/staging/qca-wifi-host-cmn/htc/htc_send.c b/drivers/staging/qca-wifi-host-cmn/htc/htc_send.c index b86c7c478b9bb858e26318fe440c67a3ae550db1..89170c47df806162344fb0ba861cd7b863bf2e84 100644 --- a/drivers/staging/qca-wifi-host-cmn/htc/htc_send.c +++ b/drivers/staging/qca-wifi-host-cmn/htc/htc_send.c @@ -71,7 +71,7 @@ void htc_dump_counter_info(HTC_HANDLE HTCHandle) __func__, target->ce_send_cnt, target->TX_comp_cnt)); } -int htc_get_tx_queue_depth(HTC_HANDLE *htc_handle, HTC_ENDPOINT_ID endpoint_id) +int htc_get_tx_queue_depth(HTC_HANDLE htc_handle, HTC_ENDPOINT_ID endpoint_id) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); HTC_ENDPOINT *endpoint = &target->endpoint[endpoint_id]; @@ -112,8 +112,10 @@ static inline void restore_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket) qdf_nbuf_unmap(target->osdev, netbuf, QDF_DMA_TO_DEVICE); pPacket->PktInfo.AsTx.Flags &= ~HTC_TX_PACKET_FLAG_FIXUP_NETBUF; } - - qdf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR)); + if (pPacket->PktInfo.AsTx.Flags & + HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA) { + qdf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR)); + } } static void send_packet_completion(HTC_TARGET *target, HTC_PACKET *pPacket) @@ -168,10 +170,27 @@ static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket) qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR)); } } + +/** + * htc_inc_runtime_cnt: Increment htc runtime count + * @target: handle of HTC context + * + * Return: None + */ +static inline +void htc_inc_runtime_cnt(HTC_TARGET *target) +{ + qdf_atomic_inc(&target->htc_runtime_cnt); +} #else static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket) { } + +static inline +void htc_inc_runtime_cnt(HTC_TARGET *target) +{ +} #endif void htc_send_complete_check_cleanup(void *context) @@ -302,8 +321,10 @@ htc_send_update_tx_bundle_stats(HTC_TARGET *target, qdf_size_t data_len, int TxCreditSize) { - if ((data_len / TxCreditSize) <= HTC_MAX_MSG_PER_BUNDLE_TX) - target->tx_bundle_stats[(data_len / TxCreditSize) - 1]++; + int index = ((data_len + TxCreditSize - 1) / TxCreditSize) - 1; + + if (index < HTC_MAX_MSG_PER_BUNDLE_TX) + target->tx_bundle_stats[index]++; } /** @@ -371,13 +392,137 @@ static QDF_STATUS htc_send_bundled_netbuf(HTC_TARGET *target, pEndpoint->UL_PipeID, pEndpoint->Id, data_len, bundleBuf, data_attr); - if (status != QDF_STATUS_SUCCESS) { - qdf_print("%s:hif_send_head failed(len=%zu).", __func__, - data_len); + if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) { + HTC_PACKET_QUEUE requeue; + + qdf_print("hif_send_head failed(len=%zu).", data_len); + INIT_HTC_PACKET_QUEUE(&requeue); + LOCK_HTC_TX(target); + pEndpoint->ul_outstanding_cnt--; + HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacketTx); + + if (pPacketTx->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) { + HTC_PACKET *temp_packet; + HTC_PACKET_QUEUE *packet_queue = + (HTC_PACKET_QUEUE *)pPacketTx->pContext; + + HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(packet_queue, + temp_packet) { + HTC_PACKET_ENQUEUE(&requeue, temp_packet); + } HTC_PACKET_QUEUE_ITERATE_END; + + UNLOCK_HTC_TX(target); + free_htc_bundle_packet(target, pPacketTx); + LOCK_HTC_TX(target); + + } else { + HTC_PACKET_ENQUEUE(&requeue, pPacketTx); + } + + HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue, + &requeue); + UNLOCK_HTC_TX(target); } return status; } +#ifdef QCA_TX_PADDING_CREDIT_SUPPORT +#define SDIO_BLOCK_SIZE 512 +static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep) +{ + int ret = 0; + + if (!ep || !ep->EpCallBacks.pContext || + !ep->EpCallBacks.ep_padding_credit_update) + return 1; + + ret = ep->EpCallBacks.ep_padding_credit_update(ep->EpCallBacks.pContext, + 0); + + if (ret < 2) + AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s ret %d\n", __func__, ret)); + + return ret; +} + +static bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep, + HTC_PACKET *p_last_htc_pkt, + unsigned char *p_last_pkt_bundle_buffer, + unsigned char **p_bundle_buffer, + int tot_data_len) +{ + bool extra_tx_credit = FALSE; + HTC_FRAME_HDR *p_htc_hdr; + int first_buf_bundled_len = 0, last_buf_len = 0; + int sdio_pad = 0, free_space = 0; + int (*update_ep_padding_credit)(void *, int); + + update_ep_padding_credit = ep->EpCallBacks.ep_padding_credit_update; + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("%s Tot data_len = %d\n", __func__, tot_data_len)); + + if (!p_last_htc_pkt) + return extra_tx_credit; + + last_buf_len = (p_last_htc_pkt->ActualLength + HTC_HDR_LENGTH); + if (tot_data_len != last_buf_len) { + first_buf_bundled_len = tot_data_len - ep->TxCreditSize; + free_space = tot_data_len - + (first_buf_bundled_len + last_buf_len); + } else { + free_space = ep->TxCreditSize - tot_data_len; + } + + sdio_pad = SDIO_BLOCK_SIZE - ((first_buf_bundled_len + last_buf_len) % + SDIO_BLOCK_SIZE); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("%s first_buf_bundled_len = %d last_buf_len = %d\n", + __func__, first_buf_bundled_len, last_buf_len)); + + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("%s sdio_pad = %d free_space = %d\n", __func__, + sdio_pad, free_space)); + + if (sdio_pad <= free_space) { + if (p_bundle_buffer && *p_bundle_buffer) { + /* Align Tx bundled buf to avoid a extra Padding buf */ + *p_bundle_buffer -= (free_space - sdio_pad); + } + } else { + /* Extra Padding Buffer needed, consume extra tx credit */ + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, + ("%s Used a Tx credit for Padding Buffer\n", + __func__)); + p_htc_hdr = (HTC_FRAME_HDR *)(p_last_pkt_bundle_buffer); + p_htc_hdr->Flags |= HTC_FLAGS_PADDING_CHECK; + extra_tx_credit = TRUE; + if (ep->EpCallBacks.ep_padding_credit_update) { + /* Decrement 1 credit at host, + * due to extra tx credit consumed by padding buffer + */ + update_ep_padding_credit(ep->EpCallBacks.pContext, -1); + } + } + return extra_tx_credit; +} +#else +static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep) +{ + return 1; +} + +static bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep, + HTC_PACKET *p_last_htc_pkt, + unsigned char *p_last_pkt_bundle_buffer, + unsigned char **p_bundle_buffer, + int tot_data_len) +{ + return FALSE; +} +#endif + /** * htc_issue_packets_bundle() - HTC function to send bundle packets from a queue * @target: HTC target on which packets need to be sent @@ -399,6 +544,8 @@ static void htc_issue_packets_bundle(HTC_TARGET *target, int creditPad, creditRemainder, transferLength, bundlesSpaceRemaining = 0; HTC_PACKET_QUEUE *pQueueSave = NULL; + HTC_PACKET *p_last_htc_pkt = NULL; + unsigned char *p_last_pkt_bundle_buffer = NULL; bundlesSpaceRemaining = target->MaxMsgsPerHTCBundle * pEndpoint->TxCreditSize; @@ -414,6 +561,10 @@ static void htc_issue_packets_bundle(HTC_TARGET *target, pBundleBuffer = qdf_nbuf_data(bundleBuf); pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext; while (1) { + if (pEndpoint->EpCallBacks.ep_padding_credit_update) { + if (htc_tx_pad_credit_avail(pEndpoint) < 1) + break; + } pPacket = htc_packet_dequeue(pPktQueue); if (!pPacket) break; @@ -431,6 +582,12 @@ static void htc_issue_packets_bundle(HTC_TARGET *target, } if (bundlesSpaceRemaining < transferLength) { + htc_handle_extra_tx_credit(pEndpoint, p_last_htc_pkt, + p_last_pkt_bundle_buffer, + &pBundleBuffer, + pBundleBuffer - + qdf_nbuf_data(bundleBuf)); + /* send out previous buffer */ htc_send_bundled_netbuf(target, pEndpoint, pBundleBuffer - last_credit_pad, @@ -460,6 +617,9 @@ static void htc_issue_packets_bundle(HTC_TARGET *target, pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext; } + p_last_htc_pkt = pPacket; + p_last_pkt_bundle_buffer = pBundleBuffer; + bundlesSpaceRemaining -= transferLength; netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); @@ -500,15 +660,41 @@ static void htc_issue_packets_bundle(HTC_TARGET *target, last_credit_pad = creditPad; } /* send out remaining buffer */ - if (pBundleBuffer != qdf_nbuf_data(bundleBuf)) + if (pBundleBuffer != qdf_nbuf_data(bundleBuf)) { + htc_handle_extra_tx_credit(pEndpoint, p_last_htc_pkt, + p_last_pkt_bundle_buffer, + &pBundleBuffer, + pBundleBuffer - + qdf_nbuf_data(bundleBuf)); + htc_send_bundled_netbuf(target, pEndpoint, pBundleBuffer - last_credit_pad, pPacketTx); - else + } else { free_htc_bundle_packet(target, pPacketTx); + } } #endif /* ENABLE_BUNDLE_TX */ #else +static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep) +{ + return 1; +} + +bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep, + HTC_PACKET *p_last_htc_pkt, + unsigned char *p_last_pkt_bundle_buffer, + unsigned char **p_bundle_buffer, + int tot_data_len); +bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep, + HTC_PACKET *p_last_htc_pkt, + unsigned char *p_last_pkt_bundle_buffer, + unsigned char **p_bundle_buffer, + int tot_data_len) +{ + return FALSE; +} + static void htc_issue_packets_bundle(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_PACKET_QUEUE *pPktQueue) @@ -537,6 +723,15 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target, enum qdf_bus_type bus_type; QDF_STATUS ret; bool rt_put = false; + bool used_extra_tx_credit = false; + uint8_t *buf = NULL; + int (*update_ep_padding_credit)(void *, int); + void *ctx = NULL; + bool rt_put_in_resp; + int32_t sys_state = HIF_SYSTEM_PM_STATE_ON; + + update_ep_padding_credit = + pEndpoint->EpCallBacks.ep_padding_credit_update; bus_type = hif_get_bus_type(target->hif_dev); @@ -544,6 +739,7 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target, ("+htc_issue_packets: Queue: %pK, Pkts %d\n", pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue))); while (true) { + rt_put_in_resp = false; if (HTC_TX_BUNDLE_ENABLED(target) && HTC_PACKET_QUEUE_DEPTH(pPktQueue) >= HTC_MIN_MSG_PER_BUNDLE) { @@ -551,6 +747,11 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target, case QDF_BUS_TYPE_SDIO: if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) break; + if (update_ep_padding_credit) { + if (htc_tx_pad_credit_avail + (pEndpoint) < 1) + break; + } case QDF_BUS_TYPE_USB: htc_issue_packets_bundle(target, pEndpoint, @@ -563,6 +764,13 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target, /* if not bundling or there was a packet that could not be * placed in a bundle, and send it by normal way */ + if (pEndpoint->EpCallBacks.ep_padding_credit_update) { + if (htc_tx_pad_credit_avail(pEndpoint) < 1) { + status = QDF_STATUS_E_FAILURE; + break; + } + } + pPacket = htc_packet_dequeue(pPktQueue); if (!pPacket) { /* local queue is fully drained */ @@ -635,6 +843,11 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target, pEndpoint->UL_PipeID, false); } + if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_SYSTEM_SUSPEND) { + sys_state = hif_system_pm_get_state(target->hif_dev); + hif_system_pm_set_state_suspending(target->hif_dev); + } + htc_packet_set_magic_cookie(pPacket, HTC_PACKET_MAGIC_COOKIE); /* * For HTT messages without a response from fw, @@ -643,17 +856,46 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target, */ if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_RUNTIME_PUT) rt_put = true; + else if (pPacket->PktInfo.AsTx.Tag == + HTC_TX_PACKET_TAG_RTPM_PUT_RC) { + rt_put_in_resp = true; + htc_inc_runtime_cnt(target); + } + #if DEBUG_BUNDLE qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.", pEndpoint->Id, pEndpoint->TxCreditSize, HTC_HDR_LENGTH + pPacket->ActualLength); #endif + buf = (uint8_t *)qdf_nbuf_get_frag_vaddr(netbuf, 0); + used_extra_tx_credit = + htc_handle_extra_tx_credit(pEndpoint, pPacket, buf, + NULL, pPacket->ActualLength + + HTC_HDR_LENGTH); + status = hif_send_head(target->hif_dev, pEndpoint->UL_PipeID, pEndpoint->Id, HTC_HDR_LENGTH + pPacket->ActualLength, netbuf, data_attr); + if (status != QDF_STATUS_SUCCESS) { + if (rt_put_in_resp) + htc_dec_return_runtime_cnt((void *)target); + + if (pPacket->PktInfo.AsTx.Tag == + HTC_TX_PACKET_SYSTEM_SUSPEND) + __hif_system_pm_set_state(target->hif_dev, + sys_state); + + if (pEndpoint->EpCallBacks.ep_padding_credit_update) { + if (used_extra_tx_credit) { + ctx = pEndpoint->EpCallBacks.pContext; + update_ep_padding_credit(ctx, 1); + } + } + } + htc_issue_tx_bundle_stats_inc(target); target->ce_send_cnt++; @@ -803,6 +1045,41 @@ htc_send_pkts_rtpm_dbgid_get(HTC_SERVICE_ID service_id) return rtpm_dbgid; } +#ifdef SYSTEM_PM_CHECK +/** + * extract_htc_system_resume_pkts(): Move system pm resume packets from endpoint + * into queue + * @endpoint: which enpoint to extract packets from + * @queue: a queue to store extracted packets in. + * + * Remove pm packets from the endpoint's tx queue and enqueue + * them into a queue + */ +static void extract_htc_system_resume_pkts(HTC_ENDPOINT *endpoint, + HTC_PACKET_QUEUE *queue) +{ + HTC_PACKET *packet; + + /* only WMI endpoint has power management packets */ + if (endpoint->service_id != WMI_CONTROL_SVC) + return; + + ITERATE_OVER_LIST_ALLOW_REMOVE(&endpoint->TxQueue.QueueHead, packet, + HTC_PACKET, ListLink) { + if (packet->PktInfo.AsTx.Tag == HTC_TX_PACKET_SYSTEM_RESUME) { + HTC_PACKET_REMOVE(&endpoint->TxQueue, packet); + HTC_PACKET_ENQUEUE(queue, packet); + } + } ITERATE_END +} +#else +static inline +void extract_htc_system_resume_pkts(HTC_ENDPOINT *endpoint, + HTC_PACKET_QUEUE *queue) +{ +} +#endif + /** * get_htc_send_packets_credit_based() - get packets based on available credits * @target: HTC target on which packets need to be sent @@ -828,6 +1105,8 @@ static void get_htc_send_packets_credit_based(HTC_TARGET *target, bool do_pm_get = false; wlan_rtpm_dbgid rtpm_dbgid = 0; int ret; + HTC_PACKET_QUEUE sys_pm_queue; + bool sys_pm_check = false; /*** NOTE : the TX lock is held when this function is called ***/ AR_DEBUG_PRINTF(ATH_DEBUG_SEND, @@ -836,8 +1115,16 @@ static void get_htc_send_packets_credit_based(HTC_TARGET *target, INIT_HTC_PACKET_QUEUE(&pm_queue); extract_htc_pm_packets(pEndpoint, &pm_queue); if (HTC_QUEUE_EMPTY(&pm_queue)) { - tx_queue = &pEndpoint->TxQueue; do_pm_get = true; + + INIT_HTC_PACKET_QUEUE(&sys_pm_queue); + extract_htc_system_resume_pkts(pEndpoint, &sys_pm_queue); + if (HTC_QUEUE_EMPTY(&sys_pm_queue)) { + tx_queue = &pEndpoint->TxQueue; + sys_pm_check = true; + } else { + tx_queue = &sys_pm_queue; + } } else { tx_queue = &pm_queue; } @@ -873,6 +1160,13 @@ static void get_htc_send_packets_credit_based(HTC_TARGET *target, break; } + if (sys_pm_check && + hif_system_pm_state_check(target->hif_dev)) { + if (do_pm_get) + hif_pm_runtime_put(target->hif_dev, rtpm_dbgid); + break; + } + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Got head packet:%pK , Queue Depth: %d\n", pPacket, @@ -1012,12 +1306,20 @@ static void get_htc_send_packets(HTC_TARGET *target, } } + ret = hif_system_pm_state_check(target->hif_dev); + if (ret) { + if (do_pm_get) + hif_pm_runtime_put(target->hif_dev, rtpm_dbgid); + break; + } + pPacket = htc_packet_dequeue(tx_queue); if (!pPacket) { if (do_pm_get) hif_pm_runtime_put(target->hif_dev, rtpm_dbgid); break; } + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Got packet:%pK , New Queue Depth: %d\n", pPacket, @@ -1215,14 +1517,6 @@ static enum HTC_SEND_QUEUE_RESULT htc_try_send(HTC_TARGET *target, return result; } - if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { - tx_resources = - hif_get_free_queue_number(target->hif_dev, - pEndpoint->UL_PipeID); - } else { - tx_resources = 0; - } - LOCK_HTC_TX(target); if (!HTC_QUEUE_EMPTY(&sendQueue)) { @@ -1261,6 +1555,14 @@ static enum HTC_SEND_QUEUE_RESULT htc_try_send(HTC_TARGET *target, /* now drain the endpoint TX queue for transmission as long as we have * enough transmit resources */ + if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { + tx_resources = + hif_get_free_queue_number(target->hif_dev, + pEndpoint->UL_PipeID); + } else { + tx_resources = 0; + } + while (true) { if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0) @@ -1518,6 +1820,8 @@ static inline QDF_STATUS __htc_send_pkt(HTC_HANDLE HTCHandle, return QDF_STATUS_E_INVAL; qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR)); + pPacket->PktInfo.AsTx.Flags |= + HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA; /* setup HTC frame header */ htc_hdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0); AR_DEBUG_ASSERT(htc_hdr); @@ -1715,6 +2019,7 @@ QDF_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket, int tx_resources; QDF_STATUS status = QDF_STATUS_SUCCESS; uint32_t data_attr = 0; + bool used_extra_tx_credit = false; if (pPacket) { if ((pPacket->Endpoint >= ENDPOINT_MAX) || @@ -1859,12 +2164,41 @@ QDF_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket, HTC_MIN_MSG_PER_BUNDLE) && (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_SDIO || hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB)) { + if (pEndpoint->EpCallBacks.ep_padding_credit_update) { + if (htc_tx_pad_credit_avail(pEndpoint) < 1) { + status = QDF_STATUS_E_RESOURCES; + /* put the sendQueue back at the front + * of pEndpoint->TxQueue + */ + LOCK_HTC_TX(target); + HTC_PACKET_QUEUE_TRANSFER_TO_HEAD( + &pEndpoint->TxQueue, + &sendQueue); + UNLOCK_HTC_TX(target); + break; + } + } htc_issue_packets_bundle(target, pEndpoint, &sendQueue); } + if (pEndpoint->EpCallBacks.ep_padding_credit_update) { + if (htc_tx_pad_credit_avail(pEndpoint) < 1) { + status = QDF_STATUS_E_RESOURCES; + /* put the sendQueue back at the front + * of pEndpoint->TxQueue + */ + LOCK_HTC_TX(target); + HTC_PACKET_QUEUE_TRANSFER_TO_HEAD( + &pEndpoint->TxQueue, + &sendQueue); + UNLOCK_HTC_TX(target); + break; + } + } pPacket = htc_packet_dequeue(&sendQueue); if (!pPacket) break; netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); + pHtcHdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0); LOCK_HTC_TX(target); /* store in look up queue to match completions */ @@ -1873,11 +2207,27 @@ QDF_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket, pEndpoint->ul_outstanding_cnt++; UNLOCK_HTC_TX(target); + used_extra_tx_credit = + htc_handle_extra_tx_credit(pEndpoint, pPacket, + (uint8_t *)pHtcHdr, + NULL, + pPacket->ActualLength + + HTC_HDR_LENGTH); + status = hif_send_head(target->hif_dev, pEndpoint->UL_PipeID, pEndpoint->Id, HTC_HDR_LENGTH + pPacket->ActualLength, netbuf, data_attr); + if (status != QDF_STATUS_SUCCESS) { + if (pEndpoint->EpCallBacks.ep_padding_credit_update) { + if (used_extra_tx_credit) { + pEndpoint->EpCallBacks. + ep_padding_credit_update + (pEndpoint->EpCallBacks.pContext, 1); + } + } + } #if DEBUG_BUNDLE qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.", pEndpoint->Id, @@ -2349,7 +2699,7 @@ void htc_process_credit_rpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, htc_try_send(target, pEndpoint, NULL); #else if (pEndpoint->service_id == HTT_DATA_MSG_SVC) - htc_send_data_pkt(target, NULL, 0); + htc_send_data_pkt((HTC_HANDLE)target, NULL, 0); else htc_try_send(target, pEndpoint, NULL); #endif @@ -2374,3 +2724,24 @@ struct ol_ath_htc_stats *ieee80211_ioctl_get_htc_stats(HTC_HANDLE HTCHandle) return &(target->htc_pkt_stats); } + +#ifdef SYSTEM_PM_CHECK +void htc_system_resume(HTC_HANDLE htc) +{ + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc); + HTC_ENDPOINT *endpoint = NULL; + int i; + + if (!target) + return; + + for (i = 0; i < ENDPOINT_MAX; i++) { + endpoint = &target->endpoint[i]; + + if (endpoint->service_id == 0) + continue; + + htc_try_send(target, endpoint, NULL); + } +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/init_deinit/dispatcher/src/dispatcher_init_deinit.c b/drivers/staging/qca-wifi-host-cmn/init_deinit/dispatcher/src/dispatcher_init_deinit.c index 2c7f972c92612f9ca6d7124427b4633a2e1fbdf0..b06da00f509a49930e2aef3a572f357faf4a1f12 100644 --- a/drivers/staging/qca-wifi-host-cmn/init_deinit/dispatcher/src/dispatcher_init_deinit.c +++ b/drivers/staging/qca-wifi-host-cmn/init_deinit/dispatcher/src/dispatcher_init_deinit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 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 above @@ -72,6 +72,12 @@ #include #endif +#ifdef FEATURE_COEX +#include +#endif + +#include + /** * DOC: This file provides various init/deinit trigger point for new * components. @@ -252,12 +258,6 @@ static QDF_STATUS dispatcher_regulatory_psoc_close(struct wlan_objmgr_psoc return regulatory_psoc_close(psoc); } -static QDF_STATUS dispatcher_regulatory_pdev_open(struct wlan_objmgr_pdev - *pdev) -{ - return regulatory_pdev_open(pdev); -} - #if defined(WLAN_CONV_SPECTRAL_ENABLE) && defined(SPECTRAL_MODULIZED_ENABLE) QDF_STATUS dispatcher_register_spectral_pdev_open_handler( spectral_pdev_open_handler handler) @@ -291,6 +291,12 @@ static QDF_STATUS dispatcher_spectral_pdev_close(struct wlan_objmgr_pdev *pdev) } #endif +static QDF_STATUS dispatcher_regulatory_pdev_open(struct wlan_objmgr_pdev + *pdev) +{ + return regulatory_pdev_open(pdev); +} + static QDF_STATUS dispatcher_regulatory_pdev_close(struct wlan_objmgr_pdev *pdev) { @@ -412,6 +418,16 @@ static QDF_STATUS dispatcher_deinit_crypto(void) { return wlan_crypto_deinit(); } + +static QDF_STATUS dispatcher_crypto_psoc_enable(struct wlan_objmgr_psoc *psoc) +{ + return wlan_crypto_psoc_enable(psoc); +} + +static QDF_STATUS dispatcher_crypto_psoc_disable(struct wlan_objmgr_psoc *psoc) +{ + return wlan_crypto_psoc_disable(psoc); +} #else static QDF_STATUS dispatcher_init_crypto(void) { @@ -422,6 +438,16 @@ static QDF_STATUS dispatcher_deinit_crypto(void) { return QDF_STATUS_SUCCESS; } + +static QDF_STATUS dispatcher_crypto_psoc_enable(struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS dispatcher_crypto_psoc_disable(struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_SUCCESS; +} #endif /* END of WLAN_CONV_CRYPTO_SUPPORTED */ #ifdef WIFI_POS_CONVERGED @@ -707,6 +733,50 @@ static QDF_STATUS fd_psoc_disable(struct wlan_objmgr_psoc *psoc) } #endif /* WLAN_SUPPORT_FILS */ +#ifdef FEATURE_COEX +static QDF_STATUS dispatcher_coex_init(void) +{ + return wlan_coex_init(); +} + +static QDF_STATUS dispatcher_coex_deinit(void) +{ + return wlan_coex_deinit(); +} + +static QDF_STATUS dispatcher_coex_psoc_open(struct wlan_objmgr_psoc *psoc) +{ + return wlan_coex_psoc_open(psoc); +} + +static QDF_STATUS dispatcher_coex_psoc_close(struct wlan_objmgr_psoc *psoc) +{ + return wlan_coex_psoc_close(psoc); +} +#else +static inline QDF_STATUS dispatcher_coex_init(void) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS dispatcher_coex_deinit(void) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS +dispatcher_coex_psoc_open(struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS +dispatcher_coex_psoc_close(struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* FEATURE_COEX */ + QDF_STATUS dispatcher_init(void) { if (QDF_STATUS_SUCCESS != wlan_objmgr_global_obj_init()) @@ -772,6 +842,12 @@ QDF_STATUS dispatcher_init(void) if (QDF_STATUS_SUCCESS != dispatcher_init_cfr()) goto cfr_init_fail; + if (QDF_STATUS_SUCCESS != dispatcher_coex_init()) + goto coex_init_fail; + + if (QDF_STATUS_SUCCESS != wlan_gpio_init()) + goto gpio_init_fail; + /* * scheduler INIT has to be the last as each component's * initialization has to happen first and then at the end @@ -783,6 +859,10 @@ QDF_STATUS dispatcher_init(void) return QDF_STATUS_SUCCESS; scheduler_init_fail: + wlan_gpio_deinit(); +gpio_init_fail: + dispatcher_coex_deinit(); +coex_init_fail: dispatcher_deinit_cfr(); cfr_init_fail: wlan_cmn_mlme_deinit(); @@ -836,6 +916,10 @@ QDF_STATUS dispatcher_deinit(void) QDF_BUG(QDF_STATUS_SUCCESS == scheduler_deinit()); + QDF_BUG(QDF_STATUS_SUCCESS == wlan_gpio_deinit()); + + QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_coex_deinit()); + QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_deinit_cfr()); QDF_BUG(QDF_STATUS_SUCCESS == wlan_cmn_mlme_deinit()); @@ -924,8 +1008,13 @@ QDF_STATUS dispatcher_psoc_open(struct wlan_objmgr_psoc *psoc) if (QDF_STATUS_SUCCESS != dispatcher_ftm_psoc_open(psoc)) goto ftm_psoc_open_fail; + if (QDF_STATUS_SUCCESS != dispatcher_coex_psoc_open(psoc)) + goto coex_psoc_open_fail; + return QDF_STATUS_SUCCESS; +coex_psoc_open_fail: + dispatcher_ftm_psoc_close(psoc); ftm_psoc_open_fail: son_psoc_close(psoc); psoc_son_fail: @@ -946,6 +1035,8 @@ qdf_export_symbol(dispatcher_psoc_open); QDF_STATUS dispatcher_psoc_close(struct wlan_objmgr_psoc *psoc) { + QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_coex_psoc_close(psoc)); + QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_ftm_psoc_close(psoc)); QDF_BUG(QDF_STATUS_SUCCESS == son_psoc_close(psoc)); @@ -993,12 +1084,17 @@ QDF_STATUS dispatcher_psoc_enable(struct wlan_objmgr_psoc *psoc) if (QDF_STATUS_SUCCESS != dispatcher_dbr_psoc_enable(psoc)) goto dbr_psoc_enable_fail; + if (QDF_STATUS_SUCCESS != dispatcher_crypto_psoc_enable(psoc)) + goto crypto_psoc_enable_fail; + if (QDF_STATUS_SUCCESS != wlan_mlme_psoc_enable(psoc)) goto mlme_psoc_enable_fail; return QDF_STATUS_SUCCESS; mlme_psoc_enable_fail: + dispatcher_crypto_psoc_disable(psoc); +crypto_psoc_enable_fail: dispatcher_dbr_psoc_disable(psoc); dbr_psoc_enable_fail: fd_psoc_disable(psoc); @@ -1025,6 +1121,8 @@ QDF_STATUS dispatcher_psoc_disable(struct wlan_objmgr_psoc *psoc) { QDF_BUG(QDF_STATUS_SUCCESS == wlan_mlme_psoc_disable(psoc)); + QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_crypto_psoc_disable(psoc)); + QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_dbr_psoc_disable(psoc)); QDF_BUG(QDF_STATUS_SUCCESS == fd_psoc_disable(psoc)); @@ -1078,6 +1176,7 @@ QDF_STATUS dispatcher_pdev_open(struct wlan_objmgr_pdev *pdev) spectral_pdev_open_fail: dispatcher_regulatory_pdev_close(pdev); regulatory_pdev_open_fail: + return QDF_STATUS_E_FAILURE; } qdf_export_symbol(dispatcher_pdev_open); diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/coex/inc/wlan_cfg80211_coex.h b/drivers/staging/qca-wifi-host-cmn/os_if/linux/coex/inc/wlan_cfg80211_coex.h new file mode 100644 index 0000000000000000000000000000000000000000..cd3e6bd43240249608e994fdd3dda8edcc310701 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/coex/inc/wlan_cfg80211_coex.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: declares driver functions interfacing with linux kernel + */ + +#ifndef _WLAN_CFG80211_COEX_H_ +#define _WLAN_CFG80211_COEX_H_ +#include +#include + +#ifdef FEATURE_COEX +int wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev, + const void *data, int data_len); +#else +static inline int +wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev, + const void *data, int data_len) +{ + return -ENOTSUPP; +} +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/coex/src/wlan_cfg80211_coex.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/coex/src/wlan_cfg80211_coex.c new file mode 100644 index 0000000000000000000000000000000000000000..754b16796e48947850d595d64e169ab0042b783e --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/coex/src/wlan_cfg80211_coex.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: defines driver functions interfacing with linux kernel + */ +#include +#include +#include +#include +#include +#include +#include + +static const struct nla_policy +btc_chain_mode_policy[QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX + 1] = { + [QCA_VENDOR_ATTR_BTC_CHAIN_MODE] = {.type = NLA_U32}, + [QCA_VENDOR_ATTR_BTC_CHAIN_MODE_RESTART] = {.type = NLA_FLAG}, +}; + +static int +__wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev, + uint8_t mode, bool do_restart) +{ + QDF_STATUS status; + uint8_t cur_mode; + int err; + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_vdev *vdev_tmp; + int vdev_id; + struct coex_psoc_obj *coex_obj; + + if (!vdev) { + coex_err("Null vdev"); + return -EINVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + coex_err("NULL psoc"); + return -EINVAL; + } + + coex_obj = wlan_psoc_get_coex_obj(psoc); + if (!coex_obj) + return -EINVAL; + + status = ucfg_coex_psoc_get_btc_chain_mode(psoc, &cur_mode); + if (QDF_IS_STATUS_ERROR(status)) { + coex_err("failed to get cur BTC chain mode, status %d", status); + return -EFAULT; + } + + if (cur_mode == mode) + return -EALREADY; + + status = ucfg_coex_psoc_set_btc_chain_mode(psoc, mode); + if (!QDF_IS_STATUS_SUCCESS(status)) { + coex_err("unable to set BTC chain mode to %d", mode); + return -EFAULT; + } + + wlan_objmgr_for_each_psoc_vdev(psoc, vdev_id, vdev_tmp) { + status = ucfg_coex_send_btc_chain_mode(vdev, mode); + err = qdf_status_to_os_return(status); + if (err) { + coex_err("Failed to set btc chain mode to %d for vdev %d", + mode, vdev_id); + return err; + } + coex_debug("Set btc chain mode to %d for vdev %d", + mode, vdev_id); + + if (!do_restart) + continue; + + wlan_coex_config_updated(vdev, COEX_CONFIG_BTC_CHAIN_MODE); + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_set_btc_chain_mode() - set btc chain mode + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: pointer to btc chain mode command parameters. + * @data_len: the length in byte of btc chain mode command parameters. + * + * Return: An error code or 0 on success. + */ +int wlan_cfg80211_coex_set_btc_chain_mode(struct wlan_objmgr_vdev *vdev, + const void *data, int data_len) +{ + struct nlattr *tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX + 1]; + uint32_t mode; + bool restart; + + if (wlan_cfg80211_nla_parse(tb, QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX, + data, data_len, btc_chain_mode_policy)) { + coex_err("Invalid btc chain mode ATTR"); + return -EINVAL; + } + + if (!tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE]) { + coex_err("btc chain mode - no attr mode"); + return -EINVAL; + } + + mode = nla_get_u32(tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE]); + if (mode < QCA_BTC_CHAIN_SHARED || mode > QCA_BTC_CHAIN_SEPARATED) { + coex_err("Invalid btc chain mode %d", mode); + return -EINVAL; + } + + restart = nla_get_flag(tb[QCA_VENDOR_ATTR_BTC_CHAIN_MODE_RESTART]); + + coex_debug("vdev_id %u mode %u restart %u", + wlan_vdev_get_id(vdev), mode, restart); + + return __wlan_cfg80211_coex_set_btc_chain_mode(vdev, mode, restart); +} diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/inc/wlan_cfg80211_mc_cp_stats.h b/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/inc/wlan_cfg80211_mc_cp_stats.h index 23d370d023095d31318251e04e67be675ca61e61..9b44112c80e4a76799c1e3762da25420f2519508 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/inc/wlan_cfg80211_mc_cp_stats.h +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/inc/wlan_cfg80211_mc_cp_stats.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2019 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 @@ -52,6 +52,21 @@ int wlan_cfg80211_mc_cp_stats_get_wakelock_stats(struct wlan_objmgr_psoc *psoc, */ int wlan_cfg80211_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev, int *dbm); +#ifdef WLAN_FEATURE_MIB_STATS +/** + * wlan_cfg80211_mc_cp_stats_get_mib_stats() - API to get mib stats + * statistics from firmware + * @vdev: Pointer to vdev + * @errno: error type in case of failure + * + * Callers of this API must call wlan_cfg80211_mc_cp_stats_free_stats_event + * API. + * Return: stats buffer on success, Null on failure + */ +struct stats_event * +wlan_cfg80211_mc_cp_stats_get_mib_stats(struct wlan_objmgr_vdev *vdev, + int *errno); +#endif /** * wlan_cfg80211_mc_cp_stats_get_station_stats() - API to get station diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/src/wlan_cfg80211_ic_cp_stats.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/src/wlan_cfg80211_ic_cp_stats.c index 4dcc0d5c8cdcb65189691e5617dc3c2959e27f92..df38bb1ad8f7b90b1cb689e6ab482a2acee4e704 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/src/wlan_cfg80211_ic_cp_stats.c +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/src/wlan_cfg80211_ic_cp_stats.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 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 @@ -32,19 +32,19 @@ int wlan_cfg80211_get_peer_cp_stats(struct wlan_objmgr_peer *peer_obj, QDF_STATUS status; if (!peer_obj) { - cfg80211_err("Invalid input, peer obj NULL"); + osif_err("Invalid input, peer obj NULL"); return -EINVAL; } if (!peer_cp_stats) { - cfg80211_err("Invalid input, peer cp obj is NULL"); + osif_err("Invalid input, peer cp obj is NULL"); return -EINVAL; } status = wlan_ucfg_get_peer_cp_stats(peer_obj, peer_cp_stats); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("wlan_cfg80211_get_peer_cp_stats status: %d", - status); + osif_err("wlan_cfg80211_get_peer_cp_stats status: %d", + status); } return qdf_status_to_os_return(status); @@ -56,19 +56,19 @@ int wlan_cfg80211_get_vdev_cp_stats(struct wlan_objmgr_vdev *vdev_obj, QDF_STATUS status; if (!vdev_obj) { - cfg80211_err("Invalid input, vdev obj is NULL"); + osif_err("Invalid input, vdev obj is NULL"); return -EINVAL; } if (!vdev_cp_stats) { - cfg80211_err("Invalid input, vdev cp obj is NULL"); + osif_err("Invalid input, vdev cp obj is NULL"); return -EINVAL; } status = wlan_ucfg_get_vdev_cp_stats(vdev_obj, vdev_cp_stats); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("wlan_cfg80211_get_vdev_cp_stats status: %d", - status); + osif_err("wlan_cfg80211_get_vdev_cp_stats status: %d", + status); } return qdf_status_to_os_return(status); @@ -80,19 +80,19 @@ int wlan_cfg80211_get_pdev_cp_stats(struct wlan_objmgr_pdev *pdev_obj, QDF_STATUS status; if (!pdev_obj) { - cfg80211_err("Invalid input, pdev obj is NULL"); + osif_err("Invalid input, pdev obj is NULL"); return -EINVAL; } if (!pdev_cp_stats) { - cfg80211_err("Invalid input, pdev cp obj is NULL"); + osif_err("Invalid input, pdev cp obj is NULL"); return -EINVAL; } status = wlan_ucfg_get_pdev_cp_stats(pdev_obj, pdev_cp_stats); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("wlan_cfg80211_get_pdev_cp_stats status: %d", - status); + osif_err("wlan_cfg80211_get_pdev_cp_stats status: %d", + status); } return qdf_status_to_os_return(status); @@ -108,19 +108,19 @@ wlan_cfg80211_get_atf_peer_cp_stats(struct wlan_objmgr_peer *peer_obj, QDF_STATUS status; if (!peer_obj) { - cfg80211_err("Invalid input, peer obj is NULL"); + osif_err("Invalid input, peer obj is NULL"); return -EINVAL; } if (!atf_cp_stats) { - cfg80211_err("Invalid input, ATF peer cp obj is NULL!"); + osif_err("Invalid input, ATF peer cp obj is NULL!"); return -EINVAL; } status = wlan_ucfg_get_atf_peer_cp_stats(peer_obj, atf_cp_stats); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("wlan_cfg80211_get_atf_peer_cp_stats status: %d", - status); + osif_err("wlan_cfg80211_get_atf_peer_cp_stats status: %d", + status); } return qdf_status_to_os_return(status); @@ -134,25 +134,25 @@ int wlan_cfg80211_get_atf_peer_cp_stats_from_mac( QDF_STATUS status; if (!vdev_obj) { - cfg80211_err("Invalid input, vdev obj is NULL"); + osif_err("Invalid input, vdev obj is NULL"); return -EINVAL; } if (!mac) { - cfg80211_err("Invalid input, peer mac is NULL"); + osif_err("Invalid input, peer mac is NULL"); return -EINVAL; } if (!atf_cp_stats) { - cfg80211_err("Invalid input, ATF peer cp stats obj is NULL"); + osif_err("Invalid input, ATF peer cp stats obj is NULL"); return -EINVAL; } status = wlan_ucfg_get_atf_peer_cp_stats_from_mac(vdev_obj, mac, atf_cp_stats); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("wlan_cfg80211_get_cp_stats_from_mac status: %d", - status); + osif_err("wlan_cfg80211_get_cp_stats_from_mac status: %d", + status); } return qdf_status_to_os_return(status); @@ -166,19 +166,19 @@ wlan_cfg80211_get_dcs_pdev_cp_stats(struct wlan_objmgr_pdev *pdev_obj, QDF_STATUS status; if (!pdev_obj) { - cfg80211_err("Invalid input, pdev obj is NULL"); + osif_err("Invalid input, pdev obj is NULL"); return -EINVAL; } if (!dcs_chan_stats) { - cfg80211_err("Invalid input, dcs chan stats is NULL"); + osif_err("Invalid input, dcs chan stats is NULL"); return -EINVAL; } status = wlan_ucfg_get_dcs_chan_stats(pdev_obj, dcs_chan_stats); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("wlan_cfg80211_get_dcs_pdev_cp_stats status: %d", - status); + osif_err("wlan_cfg80211_get_dcs_pdev_cp_stats status: %d", + status); } return qdf_status_to_os_return(status); diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c index 4d94947b1eca8f2623315d137f828389f4f60ea7..81eb1efd6aa97bcef47ebd0b5621f4e3824e348c 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020 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 @@ -32,6 +32,24 @@ /* max time in ms, caller may wait for stats request get serviced */ #define CP_STATS_WAIT_TIME_STAT 800 +#ifdef WLAN_FEATURE_MIB_STATS +/** + * wlan_free_mib_stats() - free allocations for mib stats + * @stats: Pointer to stats event statucture + * + * Return: None + */ +static void wlan_free_mib_stats(struct stats_event *stats) +{ + qdf_mem_free(stats->mib_stats); + stats->mib_stats = NULL; +} +#else +static void wlan_free_mib_stats(struct stats_event *stats) +{ +} +#endif + /** * wlan_cfg80211_mc_cp_stats_dealloc() - callback to free priv * allocations for stats @@ -44,7 +62,7 @@ static void wlan_cfg80211_mc_cp_stats_dealloc(void *priv) struct stats_event *stats = priv; if (!stats) { - cfg80211_err("stats is NULL"); + osif_err("stats is NULL"); return; } @@ -54,6 +72,7 @@ static void wlan_cfg80211_mc_cp_stats_dealloc(void *priv) qdf_mem_free(stats->vdev_summary_stats); qdf_mem_free(stats->vdev_chain_rssi); qdf_mem_free(stats->peer_adv_stats); + wlan_free_mib_stats(stats); } /** @@ -76,41 +95,41 @@ static int wlan_cfg80211_mc_cp_stats_send_wake_lock_stats(struct wiphy *wiphy, nl_buf_len += QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX * (NLMSG_HDRLEN + sizeof(uint32_t)); - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len); + skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len); if (!skb) { - cfg80211_err("cfg80211_vendor_cmd_alloc_reply_skb failed"); + osif_err("cfg80211_vendor_cmd_alloc_reply_skb failed"); return -ENOMEM; } - cfg80211_debug("wow_ucast_wake_up_count %d", - stats->ucast_wake_up_count); - cfg80211_debug("wow_bcast_wake_up_count %d", - stats->bcast_wake_up_count); - cfg80211_debug("wow_ipv4_mcast_wake_up_count %d", - stats->ipv4_mcast_wake_up_count); - cfg80211_debug("wow_ipv6_mcast_wake_up_count %d", - stats->ipv6_mcast_wake_up_count); - cfg80211_debug("wow_ipv6_mcast_ra_stats %d", - stats->ipv6_mcast_ra_stats); - cfg80211_debug("wow_ipv6_mcast_ns_stats %d", - stats->ipv6_mcast_ns_stats); - cfg80211_debug("wow_ipv6_mcast_na_stats %d", - stats->ipv6_mcast_na_stats); - cfg80211_debug("wow_icmpv4_count %d", - stats->icmpv4_count); - cfg80211_debug("wow_icmpv6_count %d", - stats->icmpv6_count); - cfg80211_debug("wow_rssi_breach_wake_up_count %d", - stats->rssi_breach_wake_up_count); - cfg80211_debug("wow_low_rssi_wake_up_count %d", - stats->low_rssi_wake_up_count); - cfg80211_debug("wow_gscan_wake_up_count %d", - stats->gscan_wake_up_count); - cfg80211_debug("wow_pno_complete_wake_up_count %d", - stats->pno_complete_wake_up_count); - cfg80211_debug("wow_pno_match_wake_up_count %d", - stats->pno_match_wake_up_count); + osif_debug("wow_ucast_wake_up_count %d", + stats->ucast_wake_up_count); + osif_debug("wow_bcast_wake_up_count %d", + stats->bcast_wake_up_count); + osif_debug("wow_ipv4_mcast_wake_up_count %d", + stats->ipv4_mcast_wake_up_count); + osif_debug("wow_ipv6_mcast_wake_up_count %d", + stats->ipv6_mcast_wake_up_count); + osif_debug("wow_ipv6_mcast_ra_stats %d", + stats->ipv6_mcast_ra_stats); + osif_debug("wow_ipv6_mcast_ns_stats %d", + stats->ipv6_mcast_ns_stats); + osif_debug("wow_ipv6_mcast_na_stats %d", + stats->ipv6_mcast_na_stats); + osif_debug("wow_icmpv4_count %d", + stats->icmpv4_count); + osif_debug("wow_icmpv6_count %d", + stats->icmpv6_count); + osif_debug("wow_rssi_breach_wake_up_count %d", + stats->rssi_breach_wake_up_count); + osif_debug("wow_low_rssi_wake_up_count %d", + stats->low_rssi_wake_up_count); + osif_debug("wow_gscan_wake_up_count %d", + stats->gscan_wake_up_count); + osif_debug("wow_pno_complete_wake_up_count %d", + stats->pno_complete_wake_up_count); + osif_debug("wow_pno_match_wake_up_count %d", + stats->pno_match_wake_up_count); ipv6_rx_multicast_addr_cnt = stats->ipv6_mcast_wake_up_count; icmpv6_cnt = stats->icmpv6_count; @@ -176,15 +195,15 @@ static int wlan_cfg80211_mc_cp_stats_send_wake_lock_stats(struct wiphy *wiphy, nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT, stats->pno_match_wake_up_count)) { - cfg80211_err("nla put fail"); + osif_err("nla put fail"); goto nla_put_failure; } - cfg80211_vendor_cmd_reply(skb); + wlan_cfg80211_vendor_cmd_reply(skb); return 0; nla_put_failure: - kfree_skb(skb); + wlan_cfg80211_vendor_free_skb(skb); return -EINVAL; } @@ -220,7 +239,7 @@ static void get_tx_power_cb(int tx_power, void *cookie) request = osif_request_get(cookie); if (!request) { - cfg80211_err("Obsolete request"); + osif_err("Obsolete request"); return; } @@ -247,7 +266,7 @@ int wlan_cfg80211_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev, request = osif_request_alloc(¶ms); if (!request) { - cfg80211_err("Request allocation failure, return cached value"); + osif_err("Request allocation failure, return cached value"); goto fetch_tx_power; } @@ -269,13 +288,13 @@ int wlan_cfg80211_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev, TYPE_CONNECTION_TX_POWER, &info); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("wlan_mc_cp_stats_request_tx_power status: %d", - status); + osif_err("wlan_mc_cp_stats_request_tx_power status: %d", + status); ret = qdf_status_to_os_return(status); } else { ret = osif_request_wait_for_response(request); if (ret) - cfg80211_err("wait failed or timed out ret: %d", ret); + osif_err("wait failed or timed out ret: %d", ret); else priv = osif_request_priv(request); } @@ -286,8 +305,8 @@ int wlan_cfg80211_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev, } else { status = ucfg_mc_cp_stats_get_tx_power(vdev, dbm); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("ucfg_mc_cp_stats_get_tx_power status: %d", - status); + osif_err("ucfg_mc_cp_stats_get_tx_power status: %d", + status); ret = qdf_status_to_os_return(status); } } @@ -319,14 +338,14 @@ static void get_peer_rssi_cb(struct stats_event *ev, void *cookie) request = osif_request_get(cookie); if (!request) { - cfg80211_err("Obsolete request"); + osif_err("Obsolete request"); return; } priv = osif_request_priv(request); rssi_size = sizeof(*ev->peer_stats) * ev->num_peer_stats; if (rssi_size == 0) { - cfg80211_err("Invalid rssi stats"); + osif_err("Invalid rssi stats"); goto get_peer_rssi_cb_fail; } @@ -366,7 +385,7 @@ wlan_cfg80211_mc_cp_stats_get_peer_rssi(struct wlan_objmgr_vdev *vdev, request = osif_request_alloc(¶ms); if (!request) { - cfg80211_err("Request allocation failure, return cached value"); + osif_err("Request allocation failure, return cached value"); *errno = -ENOMEM; qdf_mem_free(out); return NULL; @@ -382,20 +401,20 @@ wlan_cfg80211_mc_cp_stats_get_peer_rssi(struct wlan_objmgr_vdev *vdev, status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_PEER_STATS, &info); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("stats req failed: %d", status); + osif_err("stats req failed: %d", status); *errno = qdf_status_to_os_return(status); goto get_peer_rssi_fail; } *errno = osif_request_wait_for_response(request); if (*errno) { - cfg80211_err("wait failed or timed out ret: %d", *errno); + osif_err("wait failed or timed out ret: %d", *errno); goto get_peer_rssi_fail; } if (!priv->peer_stats || priv->num_peer_stats == 0) { - cfg80211_err("Invalid peer stats, count %d, data %pK", - priv->num_peer_stats, priv->peer_stats); + osif_err("Invalid peer stats, count %d, data %pK", + priv->num_peer_stats, priv->peer_stats); *errno = -EINVAL; goto get_peer_rssi_fail; } @@ -428,7 +447,7 @@ static void get_station_stats_cb(struct stats_event *ev, void *cookie) request = osif_request_get(cookie); if (!request) { - cfg80211_err("Obsolete request"); + osif_err("Obsolete request"); return; } @@ -438,8 +457,14 @@ static void get_station_stats_cb(struct stats_event *ev, void *cookie) peer_adv_size = sizeof(*ev->peer_adv_stats) * ev->num_peer_adv_stats; if (summary_size == 0 || rssi_size == 0) { - cfg80211_err("Invalid stats, summary %d rssi %d", - summary_size, rssi_size); + osif_err("Invalid stats, summary %d rssi %d", + summary_size, rssi_size); + goto station_stats_cb_fail; + } + if (priv->vdev_summary_stats || priv->vdev_chain_rssi || + priv->peer_adv_stats) { + osif_err("invalid context cookie %pK request %pK", + cookie, request); goto station_stats_cb_fail; } @@ -491,7 +516,7 @@ wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev *vdev, .dealloc = wlan_cfg80211_mc_cp_stats_dealloc, }; - cfg80211_debug("Enter"); + osif_debug("Enter"); out = qdf_mem_malloc(sizeof(*out)); if (!out) { @@ -514,7 +539,7 @@ wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev *vdev, info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)); peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID); if (!peer) { - cfg80211_err("peer is null"); + osif_err("peer is null"); *errno = -EINVAL; goto get_station_stats_fail; } @@ -525,23 +550,23 @@ wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev *vdev, status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_STATION_STATS, &info); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("Failed to send stats request status: %d", status); + osif_err("Failed to send stats request status: %d", status); *errno = qdf_status_to_os_return(status); goto get_station_stats_fail; } *errno = osif_request_wait_for_response(request); if (*errno) { - cfg80211_err("wait failed or timed out ret: %d", *errno); + osif_err("wait failed or timed out ret: %d", *errno); goto get_station_stats_fail; } if (!priv->vdev_summary_stats || !priv->vdev_chain_rssi || priv->num_summary_stats == 0 || priv->num_chain_rssi_stats == 0) { - cfg80211_err("Invalid stats"); - cfg80211_err("summary %d:%pK, rssi %d:%pK", - priv->num_summary_stats, priv->vdev_summary_stats, - priv->num_chain_rssi_stats, priv->vdev_chain_rssi); + osif_err("Invalid stats"); + osif_err("summary %d:%pK, rssi %d:%pK", + priv->num_summary_stats, priv->vdev_summary_stats, + priv->num_chain_rssi_stats, priv->vdev_chain_rssi); *errno = -EINVAL; goto get_station_stats_fail; } @@ -561,7 +586,7 @@ wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev *vdev, priv->peer_adv_stats = NULL; osif_request_put(request); - cfg80211_debug("Exit"); + osif_debug("Exit"); return out; @@ -569,10 +594,129 @@ wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev *vdev, osif_request_put(request); wlan_cfg80211_mc_cp_stats_free_stats_event(out); - cfg80211_debug("Exit"); + osif_debug("Exit"); + + return NULL; +} + +#ifdef WLAN_FEATURE_MIB_STATS +/** + * get_mib_stats_cb() - get mib stats from fw callback function + * @ev: mib stats buffer + * @cookie: a cookie for the request context + * + * Return: None + */ +static void get_mib_stats_cb(struct stats_event *ev, void *cookie) +{ + struct stats_event *priv; + struct osif_request *request; + + request = osif_request_get(cookie); + if (!request) { + osif_err("Obsolete request"); + return; + } + + priv = osif_request_priv(request); + + priv->mib_stats = qdf_mem_malloc(sizeof(*ev->mib_stats)); + if (!priv->mib_stats) + goto get_mib_stats_cb_fail; + + priv->num_mib_stats = ev->num_mib_stats; + qdf_mem_copy(priv->mib_stats, ev->mib_stats, sizeof(*ev->mib_stats)); + +get_mib_stats_cb_fail: + osif_request_complete(request); + osif_request_put(request); +} + +struct stats_event * +wlan_cfg80211_mc_cp_stats_get_mib_stats(struct wlan_objmgr_vdev *vdev, + int *errno) +{ + void *cookie; + QDF_STATUS status; + struct stats_event *priv, *out; + struct wlan_objmgr_peer *peer; + struct osif_request *request; + struct request_info info = {0}; + static const struct osif_request_params params = { + .priv_size = sizeof(*priv), + .timeout_ms = 2 * CP_STATS_WAIT_TIME_STAT, + .dealloc = wlan_cfg80211_mc_cp_stats_dealloc, + }; + + out = qdf_mem_malloc(sizeof(*out)); + if (!out) { + *errno = -ENOMEM; + return NULL; + } + + request = osif_request_alloc(¶ms); + if (!request) { + qdf_mem_free(out); + *errno = -ENOMEM; + return NULL; + } + + cookie = osif_request_cookie(request); + priv = osif_request_priv(request); + info.cookie = cookie; + info.u.get_mib_stats_cb = get_mib_stats_cb; + info.vdev_id = wlan_vdev_get_id(vdev); + info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)); + peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID); + if (!peer) { + osif_err("peer is null"); + *errno = -EINVAL; + goto get_mib_stats_fail; + } + qdf_mem_copy(info.peer_mac_addr, peer->macaddr, QDF_MAC_ADDR_SIZE); + + osif_debug("vdev id %d, pdev id %d, peer " QDF_MAC_ADDR_FMT, + info.vdev_id, info.pdev_id, + QDF_MAC_ADDR_REF(info.peer_mac_addr)); + + wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); + + status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_MIB_STATS, + &info); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("Failed to send stats request status: %d", status); + *errno = qdf_status_to_os_return(status); + goto get_mib_stats_fail; + } + + *errno = osif_request_wait_for_response(request); + if (*errno) { + osif_err("wait failed or timed out ret: %d", *errno); + goto get_mib_stats_fail; + } + + if (!priv->mib_stats || priv->num_mib_stats == 0 ) { + osif_err("Invalid mib stats %d:%pK", + priv->num_mib_stats, priv->mib_stats); + *errno = -EINVAL; + goto get_mib_stats_fail; + } + + out->num_mib_stats = priv->num_mib_stats; + out->mib_stats = priv->mib_stats; + priv->mib_stats = NULL; + + osif_request_put(request); + + return out; + +get_mib_stats_fail: + osif_request_put(request); + wlan_cfg80211_mc_cp_stats_free_stats_event(out); return NULL; } +#endif void wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event *stats) { @@ -585,5 +729,6 @@ void wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event *stats) qdf_mem_free(stats->vdev_summary_stats); qdf_mem_free(stats->vdev_chain_rssi); qdf_mem_free(stats->peer_adv_stats); + wlan_free_mib_stats(stats); qdf_mem_free(stats); } diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/inc/wlan_cfg80211_crypto.h b/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/inc/wlan_cfg80211_crypto.h index 1f4e8df2a253f3eedb2f119dcf2231fc5d636a4f..18ad13aa8e7fec52d0b77a7f1f7249edd27f3542 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/inc/wlan_cfg80211_crypto.h +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/inc/wlan_cfg80211_crypto.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019,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 @@ -65,10 +65,12 @@ int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev, * @vdev: vdev object * @key_type: denotes if the add key request is for pairwise or group key * @key_index: Index of the key that needs to be added + * @sync: flag to indicate whether or not to add key synchronously. + * DO NOT set to true if it's in scheduler context. * * Return: Zero on Success, negative value on failure */ int wlan_cfg80211_crypto_add_key(struct wlan_objmgr_vdev *vdev, enum wlan_crypto_key_type key_type, - uint8_t key_index); + uint8_t key_index, bool sync); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/inc/wlan_nl_to_crypto_params.h b/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/inc/wlan_nl_to_crypto_params.h index 58e44c21f44aa748ddeb7bfd78b6fd046d653591..c557394256311ce81471fc7f0a13319ed7de5796 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/inc/wlan_nl_to_crypto_params.h +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/inc/wlan_nl_to_crypto_params.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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 @@ -30,9 +30,10 @@ * set the crypto auth type for corresponding auth type received * from NL * - * Return: crypto auth type, negative value for failure + * Return: crypto auth type */ -int osif_nl_to_crypto_auth_type(enum nl80211_auth_type auth_type); +wlan_crypto_auth_mode +osif_nl_to_crypto_auth_type(enum nl80211_auth_type auth_type); /** * osif_nl_to_crypto_akm_type() - populate akm type for crypto @@ -41,9 +42,9 @@ int osif_nl_to_crypto_auth_type(enum nl80211_auth_type auth_type); * set the crypto akm type for corresponding akm type received * from NL * - * Return: crypto akm type, negative value for failure + * Return: crypto akm type */ -int osif_nl_to_crypto_akm_type(u32 key_mgmt); +wlan_crypto_key_mgmt osif_nl_to_crypto_akm_type(u32 key_mgmt); /** * osif_nl_to_crypto_cipher_type() - populate cipher type for crypto diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/src/wlan_cfg80211_crypto.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/src/wlan_cfg80211_crypto.c index c059cf146e93334df593b57dec5e077dd684a357..02085d287726e647ce30e614ea86bbdb7604c07a 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/src/wlan_cfg80211_crypto.c +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/src/wlan_cfg80211_crypto.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-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 @@ -23,10 +23,15 @@ #include #include #include +#include +#include +#include +#include #include #include #include "wlan_cfg80211_crypto.h" #include +#include static void wlan_cfg80211_translate_key(struct wlan_objmgr_vdev *vdev, uint8_t key_index, @@ -38,9 +43,9 @@ static void wlan_cfg80211_translate_key(struct wlan_objmgr_vdev *vdev, qdf_mem_zero(crypto_key, sizeof(*crypto_key)); crypto_key->keylen = params->key_len; crypto_key->keyix = key_index; - cfg80211_debug("key_type %d, opmode %d, key_len %d, seq_len %d", - key_type, vdev->vdev_mlme.vdev_opmode, - params->key_len, params->seq_len); + osif_debug("key_type %d, opmode %d, key_len %d, seq_len %d", + key_type, vdev->vdev_mlme.vdev_opmode, + params->key_len, params->seq_len); qdf_mem_copy(&crypto_key->keyval[0], params->key, params->key_len); qdf_mem_copy(&crypto_key->keyrsc[0], params->seq, params->seq_len); @@ -52,7 +57,7 @@ static void wlan_cfg80211_translate_key(struct wlan_objmgr_vdev *vdev, * but since we did not connect yet, so we do not know the peer * address yet. */ - cfg80211_debug("No Mac Address to copy"); + osif_debug("No Mac Address to copy"); return; } if (key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) { @@ -67,7 +72,8 @@ static void wlan_cfg80211_translate_key(struct wlan_objmgr_vdev *vdev, vdev->vdev_mlme.macaddr, QDF_MAC_ADDR_SIZE); } - cfg80211_debug("mac %pM", crypto_key->macaddr); + osif_debug("mac "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(crypto_key->macaddr)); } int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev, @@ -81,24 +87,24 @@ int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev, QDF_STATUS status; if (!vdev) { - cfg80211_err("vdev is NULL"); + osif_err("vdev is NULL"); return -EINVAL; } if (!params) { - cfg80211_err("Key params is NULL"); + osif_err("Key params is NULL"); return -EINVAL; } cipher_len = osif_nl_to_crypto_cipher_len(params->cipher); if (cipher_len < 0 || params->key_len < cipher_len) { - cfg80211_err("cipher length %d less than reqd len %d", - params->key_len, cipher_len); + osif_err("cipher length %d less than reqd len %d", + params->key_len, cipher_len); return -EINVAL; } cipher = osif_nl_to_crypto_cipher_type(params->cipher); if (!IS_WEP_CIPHER(cipher)) { if ((key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) && !mac_addr) { - cfg80211_err("mac_addr is NULL for pairwise Key"); + osif_err("mac_addr is NULL for pairwise Key"); return -EINVAL; } } @@ -106,7 +112,7 @@ int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev, params->key_len, params->seq_len); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("Invalid key params"); + osif_err("Invalid key params"); return -EINVAL; } @@ -119,33 +125,97 @@ int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev, crypto_key = qdf_mem_malloc(sizeof(*crypto_key)); if (!crypto_key) return -EINVAL; - status = wlan_crypto_save_key(vdev, key_index, crypto_key); - if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("Failed to save key"); - qdf_mem_free(crypto_key); - return -EINVAL; - } } wlan_cfg80211_translate_key(vdev, key_index, key_type, mac_addr, params, crypto_key); + status = wlan_crypto_save_key(vdev, key_index, crypto_key); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("Failed to save key"); + qdf_mem_free(crypto_key); + return -EINVAL; + } return 0; } +#define WLAN_WAIT_TIME_ADD_KEY 100 + +static void +wlan_cfg80211_crypto_add_key_cb(void *context, + struct crypto_add_key_result *result) +{ + struct osif_request *request; + struct crypto_add_key_result *priv; + + request = osif_request_get(context); + if (!request) { + osif_err("Obsolete request"); + return; + } + + priv = osif_request_priv(request); + qdf_mem_copy(priv, result, sizeof(*priv)); + osif_request_complete(request); + osif_request_put(request); +} + int wlan_cfg80211_crypto_add_key(struct wlan_objmgr_vdev *vdev, enum wlan_crypto_key_type key_type, - uint8_t key_index) + uint8_t key_index, bool sync) { struct wlan_crypto_key *crypto_key; QDF_STATUS status; + struct osif_request *request; + struct crypto_add_key_result *result; + struct wlan_crypto_comp_priv *priv; + int ret; + static const struct osif_request_params params = { + .priv_size = sizeof(*result), + .timeout_ms = WLAN_WAIT_TIME_ADD_KEY, + }; crypto_key = wlan_crypto_get_key(vdev, key_index); if (!crypto_key) { - cfg80211_err("Crypto KEY is NULL"); + osif_err("Crypto KEY is NULL"); return -EINVAL; } - status = ucfg_crypto_set_key_req(vdev, crypto_key, key_type); + + if (sync) { + priv = wlan_get_vdev_crypto_obj(vdev); + if (!priv) { + osif_err("Invalid crypto_priv"); + return -EINVAL; + } + + request = osif_request_alloc(¶ms); + if (!request) { + osif_err("Request allocation failure"); + return -ENOMEM; + } + + priv->add_key_ctx = osif_request_cookie(request);; + priv->add_key_cb = wlan_cfg80211_crypto_add_key_cb; + + status = ucfg_crypto_set_key_req(vdev, crypto_key, key_type); + if (QDF_IS_STATUS_SUCCESS(status)) { + ret = osif_request_wait_for_response(request); + if (ret) { + osif_err("Target response timed out"); + } else { + result = osif_request_priv(request); + osif_debug("complete, vdev_id %u, ix: %u, flags: %u, status: %u", + result->vdev_id, result->key_ix, + result->key_flags, result->status); + } + } + + priv->add_key_ctx = NULL; + priv->add_key_cb = NULL; + osif_request_put(request); + } else { + status = ucfg_crypto_set_key_req(vdev, crypto_key, key_type); + } return qdf_status_to_os_return(status); } diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/src/wlan_nl_to_crypto_params.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/src/wlan_nl_to_crypto_params.c index 2ecf276048a9a2132af68cb3bacb6e193d4440a6..3e8430d5e884b03d5c588dc1fdde31831ae585f2 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/src/wlan_nl_to_crypto_params.c +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/crypto/src/wlan_nl_to_crypto_params.c @@ -276,7 +276,8 @@ static const struct osif_cipher_crypto_mapping #endif }; -int osif_nl_to_crypto_auth_type(enum nl80211_auth_type auth_type) +wlan_crypto_auth_mode +osif_nl_to_crypto_auth_type(enum nl80211_auth_type auth_type) { wlan_crypto_auth_mode crypto_auth_type = WLAN_CRYPTO_AUTH_NONE; @@ -284,15 +285,17 @@ int osif_nl_to_crypto_auth_type(enum nl80211_auth_type auth_type) auth_type >= QDF_ARRAY_SIZE(osif_auth_type_crypto_mapping)) { QDF_TRACE_ERROR(QDF_MODULE_ID_OS_IF, "Unknown type: %d", auth_type); - return -EINVAL; + return crypto_auth_type; } + + crypto_auth_type = osif_auth_type_crypto_mapping[auth_type]; QDF_TRACE_DEBUG(QDF_MODULE_ID_OS_IF, "Auth type, NL: %d, crypto: %d", - auth_type, osif_auth_type_crypto_mapping[auth_type]); + auth_type, crypto_auth_type); return crypto_auth_type; } -int osif_nl_to_crypto_akm_type(u32 key_mgmt) +wlan_crypto_key_mgmt osif_nl_to_crypto_akm_type(u32 key_mgmt) { uint8_t index; wlan_crypto_key_mgmt crypto_akm_type = WLAN_CRYPTO_KEY_MGMT_NONE; @@ -307,13 +310,12 @@ int osif_nl_to_crypto_akm_type(u32 key_mgmt) break; } } - if (!akm_type_crypto_exist) { + if (!akm_type_crypto_exist) QDF_TRACE_ERROR(QDF_MODULE_ID_OS_IF, "Unknown type: %d", key_mgmt); - return -EINVAL; - } - QDF_TRACE_DEBUG(QDF_MODULE_ID_OS_IF, "Akm suite, NL: %d, crypto: %d", - key_mgmt, crypto_akm_type); + else + QDF_TRACE_DEBUG(QDF_MODULE_ID_OS_IF, "Akm suite, NL: %d, crypto: %d", + key_mgmt, crypto_akm_type); return crypto_akm_type; } diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/gpio/inc/wlan_cfg80211_gpio.h b/drivers/staging/qca-wifi-host-cmn/os_if/linux/gpio/inc/wlan_cfg80211_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..924c290eec615ddab706ea312060fbbcf229f3fd --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/gpio/inc/wlan_cfg80211_gpio.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_cfg80211_gpio.h + * + * This Header file provide declaration for cfg80211 command handler API + */ + +#ifndef __WLAN_CFG80211_GPIO_CFG_H__ +#define __WLAN_CFG80211_GPIO_CFG_H__ + +#include +#include +#include +#include + +#ifdef WLAN_FEATURE_GPIO_CFG + +extern const struct nla_policy + wlan_cfg80211_gpio_config_policy + [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX + 1]; + +/** + * wlan_cfg80211_start_gpio_config() - set GPIO config + * @psoc: pointer to psoc common object + * @data: Pointer to the data to be passed via vendor interface + * @data_len: Length of the data to be passed + * + * Return: Return the Success or Failure code + */ +int wlan_cfg80211_start_gpio_config(struct wiphy *wiphy, + struct wlan_objmgr_psoc *psoc, + const void *data, int data_len); +#else +static inline +int wlan_cfg80211_start_gpio_config(struct wiphy *wiphy, + struct wlan_objmgr_psoc *psoc, + const void *data, int data_len) +{ + return 0; +} +#endif /* WLAN_FEATURE_GPIO_CFG */ +#endif /* __WLAN_CFG80211_GPIO_CFG_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/gpio/src/wlan_cfg80211_gpio.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/gpio/src/wlan_cfg80211_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..b99898353a70e18408a42fc26420b08e7323af8a --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/gpio/src/wlan_cfg80211_gpio.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: defines driver functions interfacing with linux kernel + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "qdf_module.h" + +const struct nla_policy +wlan_cfg80211_gpio_config_policy[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND] = { + .type = NLA_U32, + .len = sizeof(uint32_t) }, + [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM] = { + .type = NLA_U32, + .len = sizeof(uint32_t) }, + [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE] = { + .type = NLA_U32, + .len = sizeof(uint32_t) }, + [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE] = { + .type = NLA_U32, + .len = sizeof(uint32_t) }, + [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE] = { + .type = NLA_U32, + .len = sizeof(uint32_t) }, + [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR] = { + .type = NLA_U32, + .len = sizeof(uint32_t) }, + [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG] = { + .type = NLA_U32, + .len = sizeof(uint32_t) }, + [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE] = { + .type = NLA_U32, + .len = sizeof(uint32_t) }, + [QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG] = { + .type = NLA_U32, + .len = sizeof(uint32_t) }, +}; + +/** + * convert_vendor_gpio_direction() - Function to convert vendor gpio direction + * @dir: pointer to enum qca_gpio_direction + * + * Convert the vendor gpio direction to wmi unified gpio direction + * + * Return: wmi unified gpio direction + */ +static enum gpio_direction +convert_vendor_gpio_direction(enum qca_gpio_direction dir) +{ + switch (dir) { + case QCA_WLAN_GPIO_INPUT: + return WMI_HOST_GPIO_INPUT; + case QCA_WLAN_GPIO_OUTPUT: + return WMI_HOST_GPIO_OUTPUT; + default: + return WMI_HOST_GPIO_INPUT; + } +} + +/** + * convert_vendor_gpio_pull_type() - Function to convert vendor pull type + * @pull_type: pointer to enum qca_gpio_pull_type + * + * Convert the vendor pull type to wmi unified pull type + * + * Return: wmi unified gpio pull type + */ +static enum gpio_pull_type +convert_vendor_gpio_pull_type(enum qca_gpio_pull_type pull_type) +{ + switch (pull_type) { + case QCA_WLAN_GPIO_PULL_NONE: + return WMI_HOST_GPIO_PULL_NONE; + case QCA_WLAN_GPIO_PULL_UP: + return WMI_HOST_GPIO_PULL_UP; + case QCA_WLAN_GPIO_PULL_DOWN: + return WMI_HOST_GPIO_PULL_DOWN; + default: + return WMI_HOST_GPIO_PULL_NONE; + } +} + +/** + * convert_vendor_gpio_interrupt_mode() - Function to convert + * vendor interrupt mode + * @intr_mode: pointer to enum qca_gpio_interrupt_mode + * + * Convert the vendor interrupt mode to wmi unified interrupt mode + * + * Return: wmi unified gpio interrupt mode + */ +static enum gpio_interrupt_mode +convert_vendor_gpio_interrupt_mode(enum qca_gpio_interrupt_mode intr_mode) +{ + switch (intr_mode) { + case QCA_WLAN_GPIO_INTMODE_DISABLE: + return WMI_HOST_GPIO_INTMODE_DISABLE; + case QCA_WLAN_GPIO_INTMODE_RISING_EDGE: + return WMI_HOST_GPIO_INTMODE_RISING_EDGE; + case QCA_WLAN_GPIO_INTMODE_FALLING_EDGE: + return WMI_HOST_GPIO_INTMODE_FALLING_EDGE; + case QCA_WLAN_GPIO_INTMODE_BOTH_EDGE: + return WMI_HOST_GPIO_INTMODE_BOTH_EDGE; + case QCA_WLAN_GPIO_INTMODE_LEVEL_LOW: + return WMI_HOST_GPIO_INTMODE_LEVEL_LOW; + case QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH: + return WMI_HOST_GPIO_INTMODE_LEVEL_HIGH; + default: + return WMI_HOST_GPIO_INTMODE_DISABLE; + } +} + +/** + * convert_vendor_gpio_output_value() - Function to convert vendor + * gpio output value + * @value: pointer to enum qca_gpio_value + * + * Convert the vendor gpio value to wmi unified gpio output value + * + * Return: wmi unified gpio output value + */ +static enum gpio_value +convert_vendor_gpio_output_value(enum qca_gpio_value value) +{ + switch (value) { + case QCA_WLAN_GPIO_LEVEL_LOW: + return WMI_HOST_GPIO_LEVEL_LOW; + case QCA_WLAN_GPIO_LEVEL_HIGH: + return WMI_HOST_GPIO_LEVEL_HIGH; + default: + return WMI_HOST_GPIO_LEVEL_LOW; + } +} + +/** + * convert_vendor_gpio_drive() - Function to convert vendor + * gpio drive + * @drive: value of enum gpio_drive + * + * Convert the vendor gpio drive to wmi unified gpio output drive + * + * Return: wmi unified gpio output drive config + */ +static enum gpio_drive +convert_vendor_gpio_drive(enum qca_gpio_drive drive) +{ + switch (drive) { + case QCA_WLAN_GPIO_DRIVE_2MA: + return WMI_HOST_GPIO_DRIVE_2MA; + case QCA_WLAN_GPIO_DRIVE_4MA: + return WMI_HOST_GPIO_DRIVE_4MA; + case QCA_WLAN_GPIO_DRIVE_6MA: + return WMI_HOST_GPIO_DRIVE_6MA; + case QCA_WLAN_GPIO_DRIVE_8MA: + return WMI_HOST_GPIO_DRIVE_8MA; + case QCA_WLAN_GPIO_DRIVE_10MA: + return WMI_HOST_GPIO_DRIVE_10MA; + case QCA_WLAN_GPIO_DRIVE_12MA: + return WMI_HOST_GPIO_DRIVE_12MA; + case QCA_WLAN_GPIO_DRIVE_14MA: + return WMI_HOST_GPIO_DRIVE_14MA; + case QCA_WLAN_GPIO_DRIVE_16MA: + return WMI_HOST_GPIO_DRIVE_16MA; + default: + return WMI_HOST_GPIO_DRIVE_2MA; + } +} + +/** + * convert_vendor_gpio_init_enable() - Function to convert vendor + * gpio init_enable + * @internal_config: Param to decide whether to use internal config + * + * Convert the vendor internal_config to wmi unified gpio output init_enable + * + * Return: wmi unified gpio output init_enable config + */ +static enum gpio_init_enable +convert_vendor_gpio_init_enable(uint32_t internal_config) +{ + if(internal_config) + return WMI_HOST_GPIO_INIT_DISABLE; + else + return WMI_HOST_GPIO_INIT_ENABLE; +} + +/** + * wlan_set_gpio_config() - set the gpio configuration info + * @psoc: the pointer of wlan_objmgr_psoc + * @attr: list of attributes + * + * Return: 0 on success; errno on failure + */ +static int +wlan_set_gpio_config(struct wlan_objmgr_psoc *psoc, + struct nlattr **attr) +{ + struct gpio_config_params cfg_param; + struct nlattr *gpio_attr; + enum qca_gpio_direction pin_dir; + enum qca_gpio_pull_type pull_type; + enum qca_gpio_interrupt_mode intr_mode; + enum qca_gpio_drive drive; + uint32_t internal_config; + QDF_STATUS status; + + gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM]; + if (!gpio_attr) { + osif_err_rl("attr gpio number failed"); + return -EINVAL; + } + cfg_param.pin_num = nla_get_u32(gpio_attr); + + gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR]; + if (!gpio_attr) { + osif_err_rl("attr gpio dir failed"); + return -EINVAL; + } + pin_dir = nla_get_u32(gpio_attr); + if (pin_dir >= QCA_WLAN_GPIO_DIR_MAX) { + osif_err_rl("attr gpio direction invalid"); + return -EINVAL; + } + cfg_param.pin_dir = convert_vendor_gpio_direction(pin_dir); + + gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE]; + if (!gpio_attr) { + osif_err_rl("attr gpio pull failed"); + return -EINVAL; + } + pull_type = nla_get_u32(gpio_attr); + if (pull_type >= QCA_WLAN_GPIO_PULL_MAX) { + osif_err_rl("attr gpio pull type invalid"); + return -EINVAL; + } + cfg_param.pin_pull_type = convert_vendor_gpio_pull_type(pull_type); + + gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE]; + if (!gpio_attr) { + osif_err_rl("attr gpio interrupt mode failed"); + return -EINVAL; + } + intr_mode = nla_get_u32(gpio_attr); + if (intr_mode >= QCA_WLAN_GPIO_INTMODE_MAX) { + osif_err_rl("attr gpio interrupt mode invalid"); + return -EINVAL; + } + cfg_param.pin_intr_mode = convert_vendor_gpio_interrupt_mode(intr_mode); + + /* Below are optional parameters. Initialize to zero */ + cfg_param.mux_config_val = WMI_HOST_GPIO_MUX_DEFAULT; + cfg_param.drive = WMI_HOST_GPIO_DRIVE_2MA; + cfg_param.init_enable = WMI_HOST_GPIO_INIT_DISABLE; + + gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG]; + if (gpio_attr) { + cfg_param.mux_config_val = nla_get_u32(gpio_attr); + } + + gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE]; + if (gpio_attr) { + drive = nla_get_u32(gpio_attr); + if (drive >= QCA_WLAN_GPIO_DRIVE_MAX) { + osif_err_rl("attr gpio drive invalid"); + return -EINVAL; + } + cfg_param.drive = convert_vendor_gpio_drive(drive); + } + + gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG]; + if (gpio_attr) { + internal_config = nla_get_u32(gpio_attr); + cfg_param.init_enable = + convert_vendor_gpio_init_enable(internal_config); + } + + status = ucfg_set_gpio_config(psoc, &cfg_param); + return status; +} + +/** + * wlan_set_gpio_output() - set the gpio output info + * @psoc: the pointer of wlan_objmgr_psoc + * @attr: list of attributes + * + * Return: 0 on success; errno on failure + */ +static int +wlan_set_gpio_output(struct wlan_objmgr_psoc *psoc, + struct nlattr **attr) +{ + struct gpio_output_params out_param; + struct nlattr *gpio_attr; + enum qca_gpio_value pin_set; + QDF_STATUS status; + + gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM]; + if (!gpio_attr) { + osif_err_rl("attr gpio number failed"); + return -EINVAL; + } + out_param.pin_num = nla_get_u32(gpio_attr); + + gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE]; + if (!gpio_attr) { + osif_err_rl("attr gpio value failed"); + return -EINVAL; + } + pin_set = nla_get_u32(gpio_attr); + if (pin_set >= QCA_WLAN_GPIO_LEVEL_MAX) { + osif_err_rl("attr gpio level invalid"); + return -EINVAL; + } + out_param.pin_set = convert_vendor_gpio_output_value(pin_set); + + status = ucfg_set_gpio_output(psoc, &out_param); + return status; +} + +/** + * wlan_cfg80211_start_gpio_config - Set the gpio configuration + * @wiphy: pointer to wiphy + * @psoc: the pointer of wlan_objmgr_psoc + * @data: pointer to data + * @data_len: data length + * + * __wlan_cfg80211_set_gpio_config will forward the GPIO setting to FW by + * WMI_GPIO_CONFIG/OUTPUT_CMDID + * + * Return: 0 on success; errno on failure + */ +int +wlan_cfg80211_start_gpio_config(struct wiphy *wiphy, + struct wlan_objmgr_psoc *psoc, + const void *data, + int data_len) +{ + uint32_t command; + struct nlattr *attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX + 1]; + int ret; + + if (wlan_cfg80211_nla_parse(attr, QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX, + data, data_len, + wlan_cfg80211_gpio_config_policy)) { + return -EINVAL; + } + + if (attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND]) { + command = nla_get_u32( + attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND]); + + if (command == QCA_WLAN_VENDOR_GPIO_CONFIG) { + ret = wlan_set_gpio_config(psoc, attr); + } else if (command == QCA_WLAN_VENDOR_GPIO_OUTPUT) { + ret = wlan_set_gpio_output(psoc, attr); + } else { + osif_err_rl("Invalid command"); + return -EINVAL; + } + } else { + osif_err_rl("Invalid command"); + return -EINVAL; + } + + return ret; +} +qdf_export_symbol(wlan_cfg80211_start_gpio_config); + diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/mlme/src/wlan_cfg80211_vdev_mlme.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/mlme/src/wlan_cfg80211_vdev_mlme.c index 54eecf585527612c9931542f5bab0bea8133bae9..16a6a0cd8568d10eb5e988b612dc33addcaddc57 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/mlme/src/wlan_cfg80211_vdev_mlme.c +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/mlme/src/wlan_cfg80211_vdev_mlme.c @@ -31,7 +31,7 @@ wlan_cfg80211_vdev_mlme_get_param_ssid(struct wlan_objmgr_vdev *vdev, uint8_t *ssid_len) { if (!vdev) { - cfg80211_err("VDEV is NULL!!!!"); + osif_err("VDEV is NULL!!!!"); return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); } @@ -44,7 +44,7 @@ wlan_cfg80211_vdev_mlme_get_trans_bssid(struct wlan_objmgr_vdev *vdev, uint8_t *addr) { if (!vdev) { - cfg80211_err("VDEV is NULL!!!!"); + osif_err("VDEV is NULL!!!!"); return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); } @@ -58,7 +58,7 @@ wlan_cfg80211_vdev_mlme_set_param(struct wlan_objmgr_vdev *vdev, struct wlan_vdev_mgr_cfg mlme_cfg) { if (!vdev) { - cfg80211_err("VDEV is NULL!!!!"); + osif_err("VDEV is NULL!!!!"); return; } @@ -71,7 +71,7 @@ wlan_cfg80211_vdev_mlme_get_param(struct wlan_objmgr_vdev *vdev, uint32_t *value) { if (!vdev) { - cfg80211_err("VDEV is NULL!!!!"); + osif_err("VDEV is NULL!!!!"); return; } diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/qca_vendor.h b/drivers/staging/qca-wifi-host-cmn/os_if/linux/qca_vendor.h index 8a81c4b731f27906002ff3f199c233c7b29bfa6e..16d1466222d79afbf141cfaa803d487ab1ba0188 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/qca_vendor.h +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/qca_vendor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -34,6 +34,10 @@ #define QCA_NL80211_VENDOR_ID 0x001374 +#ifndef BIT +#define BIT(x) (1U << (x)) +#endif + /** * enum qca_nl80211_vendor_subcmds: NL 80211 vendor sub command * @@ -98,7 +102,11 @@ * @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH: After roaming, send the * roaming and auth information. * @QCA_NL80211_VENDOR_SUBCMD_OCB_SET_SCHED: Set OCB schedule - * @QCA_NL80211_VENDOR_SUBCMD_DO_ACS: ACS offload flag + * + * @QCA_NL80211_VENDOR_SUBCMD_DO_ACS: ACS command/event which is used to + * invoke the ACS function in device and pass selected channels to + * hostapd. Uses enum qca_wlan_vendor_attr_acs_offload attributes. + * * @QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES: Get the supported features by the * driver. * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED: Indicate that driver @@ -136,7 +144,20 @@ * @QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST: get preferred channel list * @QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL: channel hint - * @QCA_NL80211_VENDOR_SUBCMD_SETBAND: vendor setband command + * @QCA_NL80211_VENDOR_SUBCMD_SETBAND: Command to configure the band + * to the host driver. This command sets the band through either + * the attribute QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE or + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE + * refers enum qca_set_band as unsigned integer values and + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK refers it as 32 bit unsigned BitMask + * values. Also, the acceptable values for + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE are only till QCA_SETBAND_2G. Further + * values/bitmask's are valid for QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. The + * attribute QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE is deprecated and the + * recommendation is to use the QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. If the + * implementations configure using both the attributes, the configurations + * through QCA_WLAN_VENDOR_ATTR_SETBAND_MASK shall always take the + * precedence. * @QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN: venodr scan command * @QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE: vendor scan complete * @QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN: vendor abort scan @@ -276,6 +297,10 @@ * legacy blob encapsulated within an attribute and can be extended with * additional vendor attributes that can enhance the NAN command * interface. + * @QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG: This command is used to + * configure parameters per peer to capture Channel Frequency Response + * (CFR) and enable Periodic CFR capture. The attributes for this command + * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr. * @QCA_NL80211_VENDOR_SUBCMD_GET_FW_STATE: Sub command to get firmware state. * The returned firmware state is specified in the attribute * QCA_WLAN_VENDOR_ATTR_FW_STATE. @@ -352,6 +377,27 @@ * binary blobs from application/service to firmware. The attributes * defined in enum qca_wlan_vendor_attr_oem_data_params are used to * deliver the parameters. + * @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT: This command/event is used + * to send/receive avoid frequency data using + * enum qca_wlan_vendor_attr_avoid_frequency_ext. + * This new command is alternative to existing command + * QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY since existing command/event + * is using stream of bytes instead of structured data using vendor + * attributes. + * @QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: This vendor subcommand is used to + * add the STA node details in driver/firmware. Attributes for this event + * are specified in enum qca_wlan_vendor_attr_add_sta_node_params. + * @QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE: This command is used to set BT + * coex chain mode from application/service. + * The attributes defined in enum qca_vendor_attr_btc_chain_mode are used + * to deliver the parameters. + * @QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO: This vendor subcommand is used to + * get information of a station from driver to userspace. This command can + * be used in both STA and AP modes. For STA mode, it provides information + * of the current association when in connected state or the last + * association when in disconnected state. For AP mode, only information + * of the currently connected stations is available. This command uses + * attributes defined in enum qca_wlan_vendor_attr_get_sta_info. * @QCA_NL80211_VENDOR_SUBCMD_REQUEST_SAR_LIMITS_EVENT: This acts as an event. * Host drivers can request the user space entity to set the SAR power * limits with this event. Accordingly, the user space entity is expected @@ -375,6 +421,14 @@ * code immediately prior to triggering cfg80211_disconnected(). The * attributes used with this event are defined in enum * qca_wlan_vendor_attr_driver_disconnect_reason. + * + * @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT: Vendor subcommand to configure TWT. + * Uses attributes defined in enum qca_wlan_vendor_attr_config_twt. + * + * @QCA_NL80211_VENDOR_SUBCMD_GETBAND: Command to get the configured band from + * the host driver. The band configurations obtained are referred through + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. + * */ enum qca_nl80211_vendor_subcmds { @@ -583,6 +637,7 @@ enum qca_nl80211_vendor_subcmds { /* Wi-Fi test configuration subcommand */ QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION = 169, QCA_NL80211_VENDOR_SUBCMD_NAN_EXT = 171, + QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG = 173, QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT = 174, QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG = 175, QCA_NL80211_VENDOR_SUBCMD_GET_FW_STATE = 177, @@ -591,9 +646,15 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING = 180, QCA_NL80211_VENDOR_SUBCMD_INTEROP_ISSUES_AP = 181, QCA_NL80211_VENDOR_SUBCMD_OEM_DATA = 182, + QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT = 183, + QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE = 184, + QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE = 185, + QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO = 186, QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS_EVENT = 187, QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO = 188, QCA_NL80211_VENDOR_SUBCMD_DRIVER_DISCONNECT_REASON = 189, + QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT = 191, + QCA_NL80211_VENDOR_SUBCMD_GETBAND = 192, }; enum qca_wlan_vendor_tos { @@ -647,6 +708,47 @@ enum qca_wlan_vendor_hang_reason { QCA_WLAN_HANG_DXE_FAILURE = 12, /* WMI pending commands exceed the maximum count */ QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS = 13, + /* Timeout for peer STA connection accept command's response from the + * FW in AP mode. This command is triggered when a STA (peer) connects + * to AP (DUT). + */ + QCA_WLAN_HANG_AP_STA_CONNECT_REQ_TIMEOUT = 14, + /* Timeout for the AP connection accept command's response from the FW + * in STA mode. This command is triggered when the STA (DUT) connects + * to an AP (peer). + */ + QCA_WLAN_HANG_STA_AP_CONNECT_REQ_TIMEOUT = 15, + /* Timeout waiting for the response to the MAC HW mode change command + * sent to FW as a part of MAC mode switch among DBS (Dual Band + * Simultaneous), SCC (Single Channel Concurrency), and MCC (Multi + * Channel Concurrency) mode. + */ + QCA_WLAN_HANG_MAC_HW_MODE_CHANGE_TIMEOUT = 16, + /* Timeout waiting for the response from FW to configure the MAC HW's + * mode. This operation is to configure the single/two MACs in either + * SCC/MCC/DBS mode. + */ + QCA_WLAN_HANG_MAC_HW_MODE_CONFIG_TIMEOUT = 17, + /* Timeout waiting for response of VDEV start command from the FW */ + QCA_WLAN_HANG_VDEV_START_RESPONSE_TIMED_OUT = 18, + /* Timeout waiting for response of VDEV restart command from the FW */ + QCA_WLAN_HANG_VDEV_RESTART_RESPONSE_TIMED_OUT = 19, + /* Timeout waiting for response of VDEV stop command from the FW */ + QCA_WLAN_HANG_VDEV_STOP_RESPONSE_TIMED_OUT = 20, + /* Timeout waiting for response of VDEV delete command from the FW */ + QCA_WLAN_HANG_VDEV_DELETE_RESPONSE_TIMED_OUT = 21, + /* Timeout waiting for response of peer all delete request command to + * the FW on a specific VDEV. + */ + QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT = 22, + /* WMI sequence mismatch between WMI command and Tx completion */ + QCA_WLAN_HANG_WMI_BUF_SEQUENCE_MISMATCH = 23, + /* Write to Device HAL register failed */ + QCA_WLAN_HANG_REG_WRITE_FAILURE = 24, + /* No credit left to send the wow_wakeup_from_sleep to firmware */ + QCA_WLAN_HANG_SUSPEND_NO_CREDIT = 25, + /* Bus failure */ + QCA_WLAN_HANG_BUS_FAILURE = 26, }; /** @@ -660,7 +762,12 @@ enum qca_wlan_vendor_attr_hang { * qca_wlan_vendor_hang_reason. */ QCA_WLAN_VENDOR_ATTR_HANG_REASON = 1, - + /* The binary blob data associated with the hang reason specified by + * QCA_WLAN_VENDOR_ATTR_HANG_REASON. This binary data is expected to + * contain the required dump to analyze the reason for the hang. + * NLA_BINARY attribute, the max size is 1024 bytes. + */ + QCA_WLAN_VENDOR_ATTR_HANG_REASON_DATA = 2, QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_HANG_MAX = QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST - 1, @@ -747,6 +854,7 @@ enum qca_wlan_vendor_attr_update_sta_info { * @QCA_WLAN_802_11_MODE_11N: mode N * @QCA_WLAN_802_11_MODE_11A: mode A * @QCA_WLAN_802_11_MODE_11AC: mode AC + * @QCA_WLAN_802_11_MODE_11AX: mode AX * @QCA_WLAN_802_11_MODE_INVALID: Invalid dot11 mode */ enum qca_wlan_802_11_mode { @@ -755,6 +863,7 @@ enum qca_wlan_802_11_mode { QCA_WLAN_802_11_MODE_11N, QCA_WLAN_802_11_MODE_11A, QCA_WLAN_802_11_MODE_11AC, + QCA_WLAN_802_11_MODE_11AX, QCA_WLAN_802_11_MODE_INVALID, }; @@ -831,8 +940,7 @@ enum qca_wlan_auth_type { * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_MAX_PHY_RATE: * Max phy rate of remote station * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_PACKETS: - * Unsigned 32 bit value. Represent the number of all frames from host to - * firmware. + * TX packets to remote station * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_BYTES: * TX bytes to remote station * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_PACKETS: @@ -858,39 +966,6 @@ enum qca_wlan_auth_type { * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SGI_ENABLE: * Remote station short GI enable/disable * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_PAD: Attribute type for padding - * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_RETRY_COUNT: - * Unsigned 32 bit value. Represents the number of retried frames received - * from remote station. - * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BC_MC_COUNT: - * Unsigned 32 bit value. Represents the number of broadcast and multicast - * frames received from remote station. - * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_FAILURE: - * Unsigned 32 bit value. Represents the number of frames which is failed to - * be transmitted. - * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_AVG_RSSI_PER_CHAIN: - * An array of CHAINS x signed 32 bit value. Represents the average value of - * RSSI per chain calculated for the remote station. - * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_RETRY_SUCCEED: - * Unsigned 32 bit value. Represents the number of frames retried but - * successfully transmitted to remote station. - * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_LAST_PKT_RSSI: - * Signed 32 bit value. Represents the RSSI calculated by last packet received - * from remote station. - * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_RETRY: - * Unsigned 32 bit value. Represent the number of retried frames from host - * to firmware. - * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_RETRY_EXHAUST: - * Unsigned 32 bit value. Represent the number of frames retried but finally - * failed from host to firmware. - * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_TOTAL_FW: - * Unsigned 32 bit value. Represent the number of all frames from firmware - * to remote station. - * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_RETRY_FW: - * Unsigned 32 bit value. Represent the number of retried frames from - * firmware to remote station. - * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_RETRY_EXHAUST_FW: - * Unsigned 32 bit value. Represent the number of frames retried but finally - * failed from firmware to remote station. * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_BEACON_IES: Binary attribute * containing the raw information elements from Beacon frames. Represents * the Beacon frames of the current BSS in the connected state. When queried @@ -906,6 +981,8 @@ enum qca_wlan_auth_type { * mac address of peer station when it disconnects. Host driver sends * assoc request frame of the given station. Host driver doesn't provide * the IEs when the peer station is still in connected state. + * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HE_OPERATION: Attribute type for + * sending HE operation info. * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AFTER_LAST: After last */ enum qca_wlan_vendor_attr_get_station_info { @@ -948,6 +1025,7 @@ enum qca_wlan_vendor_attr_get_station_info { QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_BEACON_IES, QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_DRIVER_DISCONNECT_REASON, QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_REQ_IES, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HE_OPERATION, /* keep last */ QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AFTER_LAST, @@ -1292,7 +1370,13 @@ enum qca_wlan_vendor_attr { QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND = 10, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND = 11, - /* Unsigned 32-bit value from enum qca_set_band. */ + /* Unsigned 32-bit value from enum qca_set_band. Also, the acceptable + * value for this attribute are only till QCA_SETBAND_2G. This attribute + * is deprecated. Recommendation is to use + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK instead. If the band is configured + * using both the attributes, the ones configured through + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK take the precedence. + */ QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE = 12, /* Dummy (NOP) attribute for 64 bit padding */ QCA_WLAN_VENDOR_ATTR_PAD = 13, @@ -1479,9 +1563,18 @@ enum qca_wlan_vendor_attr { */ QCA_WLAN_VENDOR_ATTR_FW_STATE = 42, + /* Unsigned 32-bitmask value from enum qca_set_band. Substitutes the + * attribute QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE for which only the + * integer values of enum qca_set_band till QCA_SETBAND_2G are valid. + * This attribute shall consider the bitmask combinations to define + * the respective Band combinations and always takes precedence over + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE. + */ + QCA_WLAN_VENDOR_ATTR_SETBAND_MASK = 43, + /* keep last */ QCA_WLAN_VENDOR_ATTR_AFTER_LAST, - QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1 + QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1 }; enum qca_wlan_vendor_attr_extscan_config_params { @@ -2312,6 +2405,10 @@ enum qca_wlan_vendor_attr_ll_stats_results { QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_SUCC_CNT = 81, QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_FAIL_CNT = 82, + /* u8 value representing the time slicing duty cycle percentage. + * Possible values are 0-100. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_TS_DUTY_CYCLE = 87, /* keep last */ QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX = @@ -3618,27 +3715,29 @@ enum qca_wlan_vendor_attr_nd_offload { }; /** - * enum qca_wlan_vendor_features - vendor device/driver features + * enum qca_wlan_vendor_features - Vendor device/driver feature flags + * * @QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD: Device supports key - * management offload, a mechanism where the station's firmware - * does the exchange with the AP to establish the temporal keys - * after roaming, rather than having the supplicant do it. + * management offload, a mechanism where the station's firmware + * does the exchange with the AP to establish the temporal keys + * after roaming, rather than having the user space wpa_supplicant do it. + * @QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY: Device supports automatic + * band selection based on channel selection results. * @QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS: Device supports - * simultaneous off-channel operations. - * @QQCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD: Device supports P2P - * Listen offload; a mechanism where the station's firmware - * takes care of responding to incoming Probe Request frames received - * from other P2P devices whilst in Listen state, rather than having the - * user space wpa_supplicant do it. Information from received P2P - * Requests are forwarded from firmware to host whenever the APPS - * processor exits power collapse state. + * simultaneous off-channel operations. + * @QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD: Device supports P2P + * Listen offload; a mechanism where the station's firmware takes care of + * responding to incoming Probe Request frames received from other P2P + * Devices whilst in Listen state, rather than having the user space + * wpa_supplicant do it. Information from received P2P requests are + * forwarded from firmware to host whenever the host processor wakes up. * @QCA_WLAN_VENDOR_FEATURE_OCE_STA: Device supports all OCE non-AP STA - * specific features + * specific features. * @QCA_WLAN_VENDOR_FEATURE_OCE_AP: Device supports all OCE AP specific * features. * @QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON: Device supports OCE STA-CFON * specific features only. If a Device sets this bit but not the - * QCA_WLAN_VENDOR_FEATURE_OCE_AP, the userspace shall assume that + * %QCA_WLAN_VENDOR_FEATURE_OCE_AP, the userspace shall assume that * this Device may not support all OCE AP functionalities but can support * only OCE STA-CFON functionalities. * @QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY: Device supports self @@ -3651,13 +3750,17 @@ enum qca_wlan_vendor_attr_nd_offload { * %QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL and * %QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW attributes from * userspace. + * @QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS: Device supports + * concurrent network sessions on different Wi-Fi Bands. This feature + * capability is attributed to the hardware's capability to support + * the same (e.g., DBS). * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits */ enum qca_wlan_vendor_features { QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0, QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1, QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2, - QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD = 3, + QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD = 3, QCA_WLAN_VENDOR_FEATURE_OCE_STA = 4, QCA_WLAN_VENDOR_FEATURE_OCE_AP = 5, QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON = 6, @@ -3666,9 +3769,9 @@ enum qca_wlan_vendor_features { QCA_WLAN_VENDOR_FEATURE_11AX = 9, QCA_WLAN_VENDOR_FEATURE_6GHZ_SUPPORT = 10, QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG = 11, + QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS = 13, - /* Additional features need to be added above this */ - NUM_QCA_WLAN_VENDOR_FEATURES + NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */ }; /** @@ -3716,41 +3819,155 @@ enum wifi_logger_supported_features { WIFI_LOGGER_DRIVER_DUMP_SUPPORTED = (1 << (7)), WIFI_LOGGER_PACKET_FATE_SUPPORTED = (1 << (8)) }; + /** - * enum qca_wlan_vendor_attr_acs_offload - * - * @QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL: ACS selected primary channel - * @QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL: ACS selected secondary channel - * @QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE: hw_mode for ACS - * @QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED: indicate if HT capability is enabled - * @QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED: indicate HT capability + * enum qca_wlan_vendor_attr_acs_offload - Defines attributes to be used with + * vendor command/event QCA_NL80211_VENDOR_SUBCMD_DO_ACS. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL: Required (u8). + * Used with event to notify the primary channel number selected in ACS + * operation. + * Note: If both the driver and user-space application supports the 6 GHz band, + * QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL is deprecated; use + * QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY instead. + * To maintain backward compatibility, QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL + * is still used if either of the driver or user space application doesn't + * support the 6 GHz band. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL: Required (u8). + * Used with event to notify the secondary channel number selected in ACS + * operation. + * Note: If both the driver and user-space application supports the 6 GHz band, + * QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL is deprecated; use + * QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY instead. + * To maintain backward compatibility, + * QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL is still used if either of + * the driver or user space application doesn't support 6 GHz band. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE: Required (u8). + * (a) Used with command to configure hw_mode from + * enum qca_wlan_vendor_acs_hw_mode for ACS operation. + * (b) Also used with event to notify the hw_mode of selected primary channel + * in ACS operation. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED: Flag attribute. + * Used with command to configure ACS operation for HT mode. + * Disable (flag attribute not present) - HT disabled and + * Enable (flag attribute present) - HT enabled. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED: Flag attribute. + * Used with command to configure ACS operation for HT40 mode. + * Disable (flag attribute not present) - HT40 disabled and + * Enable (flag attribute present) - HT40 enabled. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED: Flag attribute. + * Used with command to configure ACS operation for VHT mode. + * Disable (flag attribute not present) - VHT disabled and + * Enable (flag attribute present) - VHT enabled. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH: Optional (u16) with command and + * mandatory with event. + * If specified in command path, ACS operation is configured with the given + * channel width (in MHz). + * In event path, specifies the channel width of the primary channel selected. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST: Required and type is NLA_UNSPEC. + * Used with command to configure channel list using an array of + * channel numbers (u8). + * Note: If both the driver and user-space application supports the 6 GHz band, + * the driver mandates use of QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST whereas + * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is optional. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL: Required (u8). + * Used with event to notify the VHT segment 0 center channel number selected in + * ACS operation. + * Note: If both the driver and user-space application supports the 6 GHz band, + * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL is deprecated; use + * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY instead. + * To maintain backward compatibility, + * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL is still used if either of + * the driver or user space application doesn't support the 6 GHz band. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL: Required (u8). + * Used with event to notify the VHT segment 1 center channel number selected in + * ACS operation. + * Note: If both the driver and user-space application supports the 6 GHz band, + * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL is deprecated; use + * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY instead. + * To maintain backward compatibility, + * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL is still used if either of + * the driver or user space application doesn't support the 6 GHz band. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST: Required and type is NLA_UNSPEC. + * Used with command to configure the channel list using an array of channel + * center frequencies in MHz (u32). + * Note: If both the driver and user-space application supports the 6 GHz band, + * the driver first parses the frequency list and if it fails to get a frequency + * list, parses the channel list specified using + * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST (considers only 2 GHz and 5 GHz channels in + * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST). + * + * @QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY: Required (u32). + * Used with event to notify the primary channel center frequency (MHz) selected + * in ACS operation. + * Note: If the driver supports the 6 GHz band, the event sent from the driver + * includes this attribute along with QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY: Required (u32). + * Used with event to notify the secondary channel center frequency (MHz) + * selected in ACS operation. + * Note: If the driver supports the 6 GHz band, the event sent from the driver + * includes this attribute along with + * QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY: Required (u32). + * Used with event to notify the VHT segment 0 center channel frequency (MHz) + * selected in ACS operation. + * Note: If the driver supports the 6 GHz band, the event sent from the driver + * includes this attribute along with + * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY: Required (u32). + * Used with event to notify the VHT segment 1 center channel frequency (MHz) + * selected in ACS operation. + * Note: If the driver supports the 6 GHz band, the event sent from the driver + * includes this attribute along with + * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL. */ enum qca_wlan_vendor_attr_acs_offload { QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0, - QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL, - QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL, - QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE, - QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED, - QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED, - QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED, - QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH, - QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST, - QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL, - QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, - QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST, + QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL = 1, + QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL = 2, + QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE = 3, + QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED = 4, + QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED = 5, + QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED = 6, + QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH = 7, + QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST = 8, + QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL = 9, + QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL = 10, + QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST = 11, + QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY = 12, + QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY = 13, + QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY = 14, + QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY = 15, + /* keep last */ QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ACS_MAX = - QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST - 1 + QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST - 1 }; /** - * enum qca_wlan_vendor_acs_hw_mode + * enum qca_wlan_vendor_acs_hw_mode - Defines HW mode to be used with the + * vendor command/event QCA_NL80211_VENDOR_SUBCMD_DO_ACS. * - * @QCA_ACS_MODE_IEEE80211B: 11b mode - * @QCA_ACS_MODE_IEEE80211G: 11g mode - * @QCA_ACS_MODE_IEEE80211A: 11a mode - * @QCA_ACS_MODE_IEEE80211AD: 11ad mode + * @QCA_ACS_MODE_IEEE80211B: 802.11b mode + * @QCA_ACS_MODE_IEEE80211G: 802.11g mode + * @QCA_ACS_MODE_IEEE80211A: 802.11a mode + * @QCA_ACS_MODE_IEEE80211AD: 802.11ad mode + * @QCA_ACS_MODE_IEEE80211ANY: all modes + * @QCA_ACS_MODE_IEEE80211AX: 802.11ax mode */ enum qca_wlan_vendor_acs_hw_mode { QCA_ACS_MODE_IEEE80211B, @@ -3758,6 +3975,7 @@ enum qca_wlan_vendor_acs_hw_mode { QCA_ACS_MODE_IEEE80211A, QCA_ACS_MODE_IEEE80211AD, QCA_ACS_MODE_IEEE80211ANY, + QCA_ACS_MODE_IEEE80211AX, }; /** @@ -3797,6 +4015,12 @@ enum qca_ignore_assoc_disallowed { * QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION and * QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION subcommands. */ +#define QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES\ + QCA_WLAN_VENDOR_ATTR_CONFIG_DISCONNECT_IES +#define QCA_WLAN_VENDOR_ATTR_BEACON_REPORT_FAIL\ + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL +#define QCA_WLAN_VENDOR_ATTR_ROAM_REASON\ + QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON enum qca_wlan_vendor_attr_config { QCA_WLAN_VENDOR_ATTR_CONFIG_INVALID = 0, /* @@ -3929,7 +4153,10 @@ enum qca_wlan_vendor_attr_config { * wiphy. */ QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX = 24, - /* 8-bit unsigned value to trigger QPower: 1-Enable, 0-Disable */ + /* + * 8-bit unsigned value to trigger QPower: + * 1-Enable, 0-Disable + */ QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER = 25, /* * 8-bit unsigned value to configure the driver and below layers to @@ -4111,13 +4338,96 @@ enum qca_wlan_vendor_attr_config { * take the union of IEs from both of these interfaces and send in * further disassoc/deauth frames. */ - QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES = 58, + QCA_WLAN_VENDOR_ATTR_CONFIG_DISCONNECT_IES = 58, /* 8-bit unsigned value for ELNA bypass. * 1-Enable, 0-Disable */ QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS = 59, + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL = 60, + + /* 8-bit unsigned value. This attribute enables/disables the host driver + * to send roam reason information in the reassociation request to the + * AP. 1-Enable, 0-Disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON = 61, + + /* + * 8-bit unsigned value to trigger Optimized Power Management: + * 1-Enable, 0-Disable + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT = 71, + + /* 8-bit unsigned value. This attribute takes the QOS/access category + * value represented by the enum qca_wlan_ac_type and expects the driver + * to upgrade the UDP frames to this QOS. The value of QCA_WLAN_AC_ALL + * is invalid for this attribute. This will override the DSCP value + * configured in the frame with the intention to only upgrade the QOS. + * That said, it is not intended to downgrade the QOS for the frames. + * Set the value to 0 ( corresponding to BE ) if the QOS upgrade needs + * to disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE = 72, + + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of chains to be used for transmitting data. This + * configuration is allowed only when in connected state and will be + * effective until disconnected. The driver rejects this configuration + * if the number of spatial streams being used in the current connection + * cannot be supported by this configuration. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS = 73, + + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of chains to be used for receiving data. This + * configuration is allowed only when in connected state and will be + * effective until disconnected. The driver rejects this configuration + * if the number of spatial streams being used in the current connection + * cannot be supported by this configuration. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS = 74, + + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of spatial streams used for transmitting the data. When + * configured in the disconnected state, the configured value will + * be considered for the following connection attempt. + * If the NSS is updated after the connection, the updated NSS value + * is notified to the peer using the Operating Mode Notification/Spatial + * Multiplexing Power Save frame. + * The TX NSS value configured after the connection shall not be greater + * than the value negotiated during the connection. Any such higher + * value configuration shall be treated as invalid configuration by + * the driver. This attribute shall be configured along with + * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute to define the symmetric + * configuration (such as 2X2 or 1X1) or the asymmetric + * configuration (such as 1X2). + * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along + * with this QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute the driver + * will update the TX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS = 77, + + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of spatial streams used for receiving the data. When + * configured in the disconnected state, the configured value will + * be considered for the following connection attempt. + * If the NSS is updated after the connection, the updated NSS value + * is notified to the peer using the Operating Mode Notification/Spatial + * Multiplexing Power Save frame. + * The RX NSS value configured after the connection shall not be greater + * than the value negotiated during the connection. Any such higher + * value configuration shall be treated as invalid configuration by + * the driver. This attribute shall be configured along with + * QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute to define the symmetric + * configuration (such as 2X2 or 1X1) or the asymmetric + * configuration (such as 1X2). + * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along + * with this QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute the driver + * will update the RX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS = 78, + /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = @@ -4422,6 +4732,10 @@ enum qca_wlan_ndp_sub_cmd { * antenna gain in dbm * @QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0: vht segment 0 * @QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1: vht segment 1 + * @QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0: vht + * segment 0 in center freq in MHz. + * @QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1: vht + * segment 1 in center freq in MHz. * */ enum qca_wlan_vendor_external_acs_event_chan_info_attr { @@ -4443,6 +4757,46 @@ enum qca_wlan_vendor_external_acs_event_chan_info_attr { */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS_2 = 11, + /* + * VHT segment 0 in MHz (u32) and the attribute is mandatory. + * Note: Event QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS includes + * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 + * along with + * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0. + * + * If both the driver and user-space application supports the 6 GHz + * band, QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0 + * is deprecated and + * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 + * should be used. + * + * To maintain backward compatibility, + * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 + * is still used if either of the driver or user space application + * doesn't support the 6 GHz band. + */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 = 12, + + /* + * VHT segment 1 in MHz (u32) and the attribute is mandatory. + * Note: Event QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS includes + * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 + * along with + * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1. + * + * If both the driver and user-space application supports the 6 GHz + * band, QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1 + * is deprecated and + * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 + * should be considered. + * + * To maintain backward compatibility, + * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 + * is still used if either of the driver or user space application + * doesn't support the 6 GHz band. + */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 = 13, + /* keep last */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST, QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX = @@ -4537,9 +4891,10 @@ enum qca_wlan_vendor_attr_pcl_config { }; enum qca_set_band { - QCA_SETBAND_AUTO, - QCA_SETBAND_5G, - QCA_SETBAND_2G, + QCA_SETBAND_AUTO = 0, + QCA_SETBAND_5G = BIT(0), + QCA_SETBAND_2G = BIT(1), + QCA_SETBAND_6G = BIT(2), }; /** @@ -5020,22 +5375,35 @@ enum dfs_mode { }; /** - * enum qca_wlan_vendor_attr_acs_config - Config params for ACS - * @QCA_WLAN_VENDOR_ATTR_ACS_MODE_INVALID: Invalid - * @QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE: Dfs mode for ACS - * QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT: channel_hint for ACS - * QCA_WLAN_VENDOR_ATTR_ACS_DFS_AFTER_LAST: after_last - * QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX: max attribute + * enum qca_wlan_vendor_attr_acs_config - Defines Configuration attributes + * used by the vendor command QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE: Required (u8) + * DFS mode for ACS operation from enum qca_acs_dfs_mode. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT: Required (u8) + * channel number hint for ACS operation, if valid channel is specified then + * ACS operation gives priority to this channel. + * Note: If both the driver and user space application supports the 6 GHz band, + * this attribute is deprecated and QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT + * should be used. + * To maintain backward compatibility, QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT + * is still used if either of the driver or user space application doesn't + * support the 6 GHz band. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT: Required (u32). + * Channel center frequency (MHz) hint for ACS operation, if a valid center + * frequency is specified, ACS operation gives priority to this channel. */ enum qca_wlan_vendor_attr_acs_config { QCA_WLAN_VENDOR_ATTR_ACS_MODE_INVALID = 0, - QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE, - QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT, + QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE = 1, + QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT = 2, + QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT = 3, QCA_WLAN_VENDOR_ATTR_ACS_DFS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX = QCA_WLAN_VENDOR_ATTR_ACS_DFS_AFTER_LAST - 1, - }; /** @@ -5152,22 +5520,34 @@ enum qca_wlan_vendor_attr_loc_capa_flags { }; /** - * enum qca_wlan_vendor_attr_sap_config - config params for sap configuration - * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_INVALID: invalid - * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL: Channel on which SAP should start - * @QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST: List of frequencies on - * which AP is expected to operate. This is irrespective of ACS configuration. - * This list is a priority based one and is looked for before the AP is created - * to ensure the best concurrency sessions (avoid MCC and use DBS/SCC) co-exist - * in the system. - * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST: after last - * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX: max attribute + * enum qca_wlan_vendor_attr_sap_config - Parameters for AP configuration + * + * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL: Optional (u8) + * Channel number on which Access Point should restart. + * Note: If both the driver and user space application supports the 6 GHz band, + * this attribute is deprecated and QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY + * should be used. + * To maintain backward compatibility, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL + * is still used if either of the driver or user space application doesn't + * support the 6 GHz band. + * + * @QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST: Required + * Nested attribute to hold list of center frequencies on which AP is + * expected to operate. This is irrespective of ACS configuration. + * This list is a priority based one and is looked for before the AP is + * created to ensure the best concurrency sessions (avoid MCC and use DBS/SCC) + * co-exist in the system. + * + * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY: Optional (u32) + * Channel center frequency (MHz) on which the access point should restart. */ enum qca_wlan_vendor_attr_sap_config { QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_INVALID = 0, - QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL, + QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL = 1, QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST = 2, - /* keep last */ + QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY = 3, + + /* Keep last */ QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX = QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST - 1, @@ -6076,39 +6456,136 @@ enum qca_wlan_vendor_attr_ll_stats_ext { }; /** - * qca_wlan_vendor_attr_external_acs_channels: attribute to vendor subcmd - * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This carry a list of channels - * in priority order as decided after acs operation in userspace. - * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON: One of reason code from - * qca_wlan_vendor_acs_select_reason. - * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT: Number of channels in - * this list - * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST: Array of nested values - * for each channel with following attributes: + * enum qca_wlan_vendor_attr_external_acs_channels: Attributes to vendor subcmd + * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This carries a list of channels + * in priority order as decided after ACS operation in userspace. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON: Required (u8). + * One of reason code from enum qca_wlan_vendor_acs_select_reason. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST: Required + * Array of nested values for each channel with following attributes: * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH - * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY: Primary channel (u8) - * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY: Secondary channel (u8) - * required only for 160 / 80 + 80 - * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0: VHT seg0 channel (u8) - * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1: VHT seg1 channel (u8) - * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH:channel width (u8) + * Note: If both the driver and user-space application supports the 6 GHz band, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST is deprecated and use + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_LIST. + * To maintain backward compatibility, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST + * is still used if either of the driver or user space application doesn't + * support the 6 GHz band. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY: Required (u8). + * Primary channel number + * Note: If both the driver and user-space application supports the 6 GHz band, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY is deprecated and use + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY. + * To maintain backward compatibility, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY + * is still used if either of the driver or user space application doesn't + * support the 6 GHz band. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY: Required (u8). + * Secondary channel number, required only for 160 and 80+80 MHz bandwidths. + * Note: If both the driver and user-space application supports the 6 GHz band, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY is deprecated and use + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY. + * To maintain backward compatibility, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY + * is still used if either of the driver or user space application + * doesn't support the 6 GHz band. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0: Required (u8). + * VHT seg0 channel number + * Note: If both the driver and user-space application supports the 6 GHz band, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0 is deprecated and use + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0. + * To maintain backward compatibility, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0 + * is still used if either of the driver or user space application + * doesn't support the 6 GHz band. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1: Required (u8). + * VHT seg1 channel number + * Note: If both the driver and user-space application supports the 6 GHz band, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1 is deprecated and use + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1. + * To maintain backward compatibility, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1 + * is still used if either of the driver or user space application + * doesn't support the 6 GHz band. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH: Required (u8). + * Takes one of enum nl80211_chan_width values. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_LIST: Required + * Array of nested values for each channel with following attributes: + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY in MHz (u32), + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY in MHz (u32), + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0 in MHz (u32), + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1 in MHz (u32), + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH + * Note: If user-space application has no support of the 6 GHz band, this + * attribute is optional. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY: Required (u32) + * Primary channel frequency in MHz + * Note: If user-space application has no support of the 6 GHz band, this + * attribute is optional. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY: Required (u32) + * Secondary channel frequency in MHz used for HT 40 MHz channels. + * Note: If user-space application has no support of the 6 GHz band, this + * attribute is optional. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0: Required (u32) + * VHT seg0 channel frequency in MHz + * Note: If user-space application has no support of the 6GHz band, this + * attribute is optional. + * + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1: Required (u32) + * VHT seg1 channel frequency in MHz + * Note: If user-space application has no support of the 6 GHz band, this + * attribute is optional. */ enum qca_wlan_vendor_attr_external_acs_channels { QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_INVALID = 0, + /* One of reason code (u8) from enum qca_wlan_vendor_acs_select_reason + */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON = 1, + + /* Array of nested values for each channel with following attributes: + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH + */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST = 2, + /* This (u8) will hold values of one of enum nl80211_bands */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND = 3, + /* Primary channel (u8) */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY = 4, + /* Secondary channel (u8) used for HT 40 MHz channels */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY = 5, + /* VHT seg0 channel (u8) */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0 = 6, + /* VHT seg1 channel (u8) */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1 = 7, + /* Channel width (u8). Takes one of enum nl80211_chan_width values. */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH = 8, + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_LIST = 9, + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY = 10, + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY = 11, + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0 = 12, + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1 = 13, + /* keep last */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LAST, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX = @@ -6117,37 +6594,140 @@ enum qca_wlan_vendor_attr_external_acs_channels { /** * qca_wlan_vendor_acs_select_reason: This represents the different reasons why - * the ACS has to be triggered. These parameters are used by + * the ACS has to be triggered. These values are used by * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON and - * QCA_NL80211_VENDOR_SUBCMD_ACS_SET_CHANNELS - * @QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT: Represents the reason that the - * ACS triggered during the AP start - * @QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS: Represents the reason that - * DFS found with current channel - * @QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX: Represents the reason that - * LTE CO-Exist in current band + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON */ enum qca_wlan_vendor_acs_select_reason { + /* Represents the reason that the ACS triggered during the AP start */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT, + /* Represents the reason that DFS found with the current channel */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS, + /* Represents the reason that LTE co-exist in the current band. */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX, + /* Represents the reason that generic, uncategorized interference has + * been found in the current channel. + */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_GENERIC_INTERFERENCE, + /* Represents the reason that excessive 802.11 interference has been + * found in the current channel. + */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_80211_INTERFERENCE, + /* Represents the reason that generic Continuous Wave (CW) interference + * has been found in the current channel. + */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_CW_INTERFERENCE, + /* Represents the reason that Microwave Oven (MWO) interference has been + * found in the current channel. + */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_MWO_INTERFERENCE, + /* Represents the reason that generic Frequency-Hopping Spread Spectrum + * (FHSS) interference has been found in the current channel. This may + * include 802.11 waveforms. + */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_FHSS_INTERFERENCE, + /* Represents the reason that non-802.11 generic Frequency-Hopping + * Spread Spectrum (FHSS) interference has been found in the current + * channel. + */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_NON_80211_FHSS_INTERFERENCE, + /* Represents the reason that generic Wideband (WB) interference has + * been found in the current channel. This may include 802.11 waveforms. + */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_WB_INTERFERENCE, + /* Represents the reason that non-802.11 generic Wideband (WB) + * interference has been found in the current channel. + */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_NON_80211_WB_INTERFERENCE, + /* Represents the reason that Jammer interference has been found in the + * current channel. + */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_JAMMER_INTERFERENCE, }; /** * enum qca_wlan_gpio_attr - Parameters for GPIO configuration + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND: Required (u32) + * value to specify the gpio command, please refer to enum qca_gpio_cmd_type + * to get the available value that this item can use. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM: Required (u32) + * value to specify the gpio number. + * Required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG or %.QCA_WLAN_VENDOR_GPIO_OUTPUT. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE: Required (u32) + * value to specify the gpio output level, please refer to enum qca_gpio_value + * to get the available value that this item can use. + * Required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_OUTPUT. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Optional (u32) + * value to specify the gpio pull type, please refer to enum qca_gpio_pull_type + * to get the available value that this item can use. + * Required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG and + * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG + * attribute is present. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Optional (u32) + * value to specify the gpio interrupt mode, please refer to enum + * qca_gpio_interrupt_mode to get the available value that this item can use. + * Required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG and + * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG + * attribute is present. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Optional (u32) + * value to specify the gpio direction, please refer to enum qca_gpio_direction + * to get the available value that this item can use. + * Required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG and + * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG + * attribute is present. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG: Optional (u32) + * Value to specify the mux config. Meaning of a given value is dependent + * on the target chipset and gpio pin. Must be of the range 0-15. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to 0. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE: Optional (u32) + * Value to specify the drive, Refer to enum qca_gpio_drive. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to QCA_WLAN_GPIO_DRIVE_2MA(0). + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG: Optional (flag) + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. When present this attribute signals that all + * other parameters for the given GPIO will be obtained from internal + * configuration. Only %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM must be + * specified to indicate the GPIO pin being configured. */ enum qca_wlan_gpio_attr { QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INVALID = 0, /* Unsigned 32-bit attribute for GPIO command */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND = 1, /* Unsigned 32-bit attribute for GPIO PIN number to configure */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM = 2, /* Unsigned 32-bit attribute for GPIO value to configure */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE = 3, /* Unsigned 32-bit attribute for GPIO pull type */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE = 4, /* Unsigned 32-bit attribute for GPIO interrupt mode */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE = 5, + /* Unsigned 32-bit attribute for GPIO direction to configure */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR = 6, + /* Unsigned 32-bit attribute for GPIO mux config */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG = 7, + /* Unsigned 32-bit attribute for GPIO drive */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE = 8, + /* Flag attribute for using internal gpio configuration */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG = 9, /* keep last */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST, @@ -6155,6 +6735,97 @@ enum qca_wlan_gpio_attr { QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST - 1, }; +/** + * enum gpio_cmd_type - GPIO configuration command type + * @QCA_WLAN_VENDOR_GPIO_CONFIG: set gpio configuration info + * @QCA_WLAN_VENDOR_GPIO_OUTPUT: set gpio output level + */ +enum qca_gpio_cmd_type { + QCA_WLAN_VENDOR_GPIO_CONFIG = 0, + QCA_WLAN_VENDOR_GPIO_OUTPUT = 1, +}; + +/** + * enum qca_gpio_pull_type - GPIO pull type + * @QCA_WLAN_GPIO_PULL_NONE: set gpio pull type to none + * @QCA_WLAN_GPIO_PULL_UP: set gpio pull up + * @QCA_WLAN_GPIO_PULL_DOWN: set gpio pull down + */ +enum qca_gpio_pull_type { + QCA_WLAN_GPIO_PULL_NONE = 0, + QCA_WLAN_GPIO_PULL_UP = 1, + QCA_WLAN_GPIO_PULL_DOWN = 2, + QCA_WLAN_GPIO_PULL_MAX, +}; + +/** + * enum qca_gpio_direction - GPIO direction + * @QCA_WLAN_GPIO_INPUT: set gpio as input mode + * @QCA_WLAN_GPIO_OUTPUT: set gpio as output mode + * @QCA_WLAN_GPIO_VALUE_MAX: invalid value + */ +enum qca_gpio_direction { + QCA_WLAN_GPIO_INPUT = 0, + QCA_WLAN_GPIO_OUTPUT = 1, + QCA_WLAN_GPIO_DIR_MAX, +}; + +/** + * enum qca_gpio_value - GPIO Value + * @QCA_WLAN_GPIO_LEVEL_LOW: set gpio output level to low + * @QCA_WLAN_GPIO_LEVEL_HIGH: set gpio output level to high + * @QCA_WLAN_GPIO_LEVEL_MAX: invalid value + */ +enum qca_gpio_value { + QCA_WLAN_GPIO_LEVEL_LOW = 0, + QCA_WLAN_GPIO_LEVEL_HIGH = 1, + QCA_WLAN_GPIO_LEVEL_MAX, +}; + +/** + * enum gpio_interrupt_mode - GPIO interrupt mode + * @QCA_WLAN_GPIO_INTMODE_DISABLE: disable interrupt trigger + * @QCA_WLAN_GPIO_INTMODE_RISING_EDGE: interrupt with gpio rising edge trigger + * @QCA_WLAN_GPIO_INTMODE_FALLING_EDGE: interrupt with gpio falling edge trigger + * @QCA_WLAN_GPIO_INTMODE_BOTH_EDGE: interrupt with gpio both edge trigger + * @QCA_WLAN_GPIO_INTMODE_LEVEL_LOW: interrupt with gpio level low trigger + * @QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH: interrupt with gpio level high trigger + * @QCA_WLAN_GPIO_INTMODE_MAX: invalid value + */ +enum qca_gpio_interrupt_mode { + QCA_WLAN_GPIO_INTMODE_DISABLE = 0, + QCA_WLAN_GPIO_INTMODE_RISING_EDGE = 1, + QCA_WLAN_GPIO_INTMODE_FALLING_EDGE = 2, + QCA_WLAN_GPIO_INTMODE_BOTH_EDGE = 3, + QCA_WLAN_GPIO_INTMODE_LEVEL_LOW = 4, + QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH = 5, + QCA_WLAN_GPIO_INTMODE_MAX, +}; + +/** + * enum gpio_drive - GPIO drive + * @QCA_WLAN_GPIO_DRIVE_2MA: drive 2MA + * @QCA_WLAN_GPIO_DRIVE_4MA: drive 4MA + * @QCA_WLAN_GPIO_DRIVE_6MA: drive 6MA + * @QCA_WLAN_GPIO_DRIVE_8MA: drive 8MA + * @QCA_WLAN_GPIO_DRIVE_10MA: drive 10MA + * @QCA_WLAN_GPIO_DRIVE_12MA: drive 12MA + * @QCA_WLAN_GPIO_DRIVE_14MA: drive 14MA + * @QCA_WLAN_GPIO_DRIVE_16MA: drive 16MA + * @QCA_WLAN_GPIO_DRIVE_MAX: invalid gpio drive + */ +enum qca_gpio_drive { + QCA_WLAN_GPIO_DRIVE_2MA = 0, + QCA_WLAN_GPIO_DRIVE_4MA = 1, + QCA_WLAN_GPIO_DRIVE_6MA = 2, + QCA_WLAN_GPIO_DRIVE_8MA = 3, + QCA_WLAN_GPIO_DRIVE_10MA = 4, + QCA_WLAN_GPIO_DRIVE_12MA = 5, + QCA_WLAN_GPIO_DRIVE_14MA = 6, + QCA_WLAN_GPIO_DRIVE_16MA = 7, + QCA_WLAN_GPIO_DRIVE_MAX, +}; + /** * qca_wlan_set_qdepth_thresh_attr - Parameters for setting * MSDUQ depth threshold per peer per tid in the target @@ -6356,6 +7027,16 @@ enum qca_wlan_vendor_attr_spectral_scan { * This attribute is included only in failure scenarios. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE = 26, + /* 8-bit unsigned value to enable/disable debug of the + * Spectral DMA ring. + * 1-enable, 0-disable + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG = 27, + /* 8-bit unsigned value to enable/disable debug of the + * Spectral DMA buffers. + * 1-enable, 0-disable + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG = 28, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX = @@ -6434,8 +7115,18 @@ enum qca_wlan_vendor_attr_spectral_cap { * u8 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_DEFAULT_AGC_MAX_GAIN = 10, - /* Flag attribute to indicate agile spectral scan capability */ + /* Flag attribute to indicate agile spectral scan capability + * for 20/40/80 MHz modes. + */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL = 11, + /* Flag attribute to indicate agile spectral scan capability + * for 160 MHz mode. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_160 = 12, + /* Flag attribute to indicate agile spectral scan capability + * for 80+80 MHz mode. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_80_80 = 13, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX = @@ -6644,12 +7335,22 @@ enum qca_wlan_vendor_attr_rrop_info { enum qca_wlan_vendor_attr_rtplinst { QCA_WLAN_VENDOR_ATTR_RTPLINST_INVALID = 0, - /* Primary channel number (u8) */ + /* Primary channel number (u8). + * Note: If both the driver and user space application support the + * 6 GHz band, this attribute is deprecated and + * QCA_WLAN_VENDOR_ATTR_RTPLINST_PRIMARY_FREQUENCY should be used. To + * maintain backward compatibility, + * QCA_WLAN_VENDOR_ATTR_RTPLINST_PRIMARY is still used if either the + * driver or user space application or both do not support the 6 GHz + * band. + */ QCA_WLAN_VENDOR_ATTR_RTPLINST_PRIMARY = 1, /* Representative Tx power in dBm (s32) with emphasis on throughput. */ QCA_WLAN_VENDOR_ATTR_RTPLINST_TXPOWER_THROUGHPUT = 2, /* Representative Tx power in dBm (s32) with emphasis on range. */ QCA_WLAN_VENDOR_ATTR_RTPLINST_TXPOWER_RANGE = 3, + /* Primary channel center frequency (u32) in MHz */ + QCA_WLAN_VENDOR_ATTR_RTPLINST_PRIMARY_FREQUENCY = 4, QCA_WLAN_VENDOR_ATTR_RTPLINST_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_RTPLINST_MAX = @@ -7245,11 +7946,67 @@ enum qca_wlan_vendor_attr_wifi_test_config { QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST - 1, }; +/** + * enum qca_wlan_twt_operation - Operation of the config TWT request + * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION. + * + * @QCA_WLAN_TWT_SET: Setup a TWT session. Required parameters are configured + * through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_setup. + * + * @QCA_WLAN_TWT_GET: Get the configured TWT parameters. Required parameters are + * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_setup. + * + * @QCA_WLAN_TWT_TERMINATE: Terminate the TWT session. Does not carry any + * parameters. Valid only after the TWT session is setup. + * + * @QCA_WLAN_TWT_SUSPEND: Terminate the TWT session. Does not carry any + * parameters. Valid only after the TWT session is setup. + * + * @QCA_WLAN_TWT_RESUME: Resume the TWT session. Required parameters are + * configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_resume. + */ +enum qca_wlan_twt_operation { + QCA_WLAN_TWT_SET = 0, + QCA_WLAN_TWT_GET = 1, + QCA_WLAN_TWT_TERMINATE = 2, + QCA_WLAN_TWT_SUSPEND = 3, + QCA_WLAN_TWT_RESUME = 4, +}; + +/* enum qca_wlan_vendor_attr_config_twt: Defines attributes used by + * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION: + * u8 attribute. Specify the TWT operation of this request. Possible values + * are defined in enum qca_wlan_twt_operation. The parameters for the + * respective operation is specified through + * QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS: Nested attribute representing the + * parameters configured for TWT. These parameters are represented by + * enum qca_wlan_vendor_attr_twt_setup or enum qca_wlan_vendor_attr_twt_resume + * based on the operation. + */ +enum qca_wlan_vendor_attr_config_twt { + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION = 1, + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX = + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_AFTER_LAST - 1, +}; + /** * enum qca_wlan_vendor_attr_twt_setup: Represents attributes for * TWT (Target Wake Time) setup request. These attributes are sent as part of * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP and - * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. + * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. Also used by + * attributes through %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST: Flag attribute. * Disable (flag attribute not present) - Individual TWT @@ -7328,7 +8085,8 @@ enum qca_wlan_vendor_attr_twt_setup { * enum qca_wlan_vendor_attr_twt_resume: Represents attributes for * TWT (Target Wake Time) resume request. These attributes are sent as part of * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME and - * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. + * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. Also used by + * attributes through %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT: Optional (u8) * This attribute is used as the SP offset which is the offset from @@ -7484,6 +8242,238 @@ enum qca_wlan_vendor_attr_nan_params { QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_AFTER_LAST - 1 }; +/** + * enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by + * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor + * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG. + * @QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL: CFR method using QOS Null frame. + * @QCA_WLAN_VENDOR_CFR_QOS_NULL_WITH_PHASE: CFR method using QOS Null frame + * with phase + * @QCA_WLAN_VENDOR_CFR_PROBE_RESPONSE: CFR method using probe response frame + */ +enum qca_wlan_vendor_cfr_method { + QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL = 0, + QCA_WLAN_VENDOR_CFR_QOS_NULL_WITH_PHASE = 1, + QCA_WLAN_VENDOR_CFR_PROBE_RESPONSE = 2, +}; + +/** + * enum qca_wlan_vendor_cfr_capture_type - QCA vendor CFR capture type used by + * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE. + * @QCA_WLAN_VENDOR_CFR_DIRECT_FTM: Filter directed FTM ACK frames. + * @QCA_WLAN_VENDOR_CFR_ALL_FTM_ACK: Filter all FTM ACK frames. + * @QCA_WLAN_VENDOR_CFR_DIRECT_NDPA_NDP: Filter NDPA NDP directed frames. + * @QCA_WLAN_VENDOR_CFR_TA_RA: Filter frames based on TA/RA/Subtype which + * is provided by one or more of below attributes: + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER + * @QCA_WLAN_CFR_ALL_PACKET: Filter all packets. + * @QCA_WLAN_VENDOR_CFR_NDPA_NDP_ALL: Filter all NDPA NDP frames. + */ +enum qca_wlan_vendor_cfr_capture_type { + QCA_WLAN_VENDOR_CFR_DIRECT_FTM = 0, + QCA_WLAN_VENDOR_CFR_ALL_FTM_ACK = 1, + QCA_WLAN_VENDOR_CFR_DIRECT_NDPA_NDP = 2, + QCA_WLAN_VENDOR_CFR_TA_RA = 3, + QCA_WLAN_VENDOR_CFR_ALL_PACKET = 4, + QCA_WLAN_VENDOR_CFR_NDPA_NDP_ALL = 5, +}; + +/** + * enum qca_wlan_vendor_peer_cfr_capture_attr - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG to configure peer + * Channel Frequency Response capture parameters and enable periodic CFR + * capture. + * + * @QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR: Optional (6-byte MAC address) + * MAC address of peer. This is for CFR version 1 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE: Required (flag) + * Enable peer CFR Capture. This attribute is mandatory to + * enable peer CFR capture. If this attribute is not present, + * peer CFR capture is disabled. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH: Optional (u8) + * BW of measurement, attribute uses the values in enum nl80211_chan_width + * Supported values: 20, 40, 80, 80+80, 160. + * Note that all targets may not support all bandwidths. + * This attribute is mandatory for version 1 if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY: Optional (u32) + * Periodicity of CFR measurement in msec. + * Periodicity should be a multiple of Base timer. + * Current Base timer value supported is 10 msecs (default). + * 0 for one shot capture. + * This attribute is mandatory for version 1 if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD: Optional (u8) + * Method used to capture Channel Frequency Response. + * Attribute uses the values defined in enum qca_wlan_vendor_cfr_method. + * This attribute is mandatory for version 1 if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + * + * @QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE: Optional (flag) + * Enable periodic CFR capture. + * This attribute is mandatory for version 1 to enable Periodic CFR capture. + * If this attribute is not present, periodic CFR capture is disabled. + * + * @QCA_WLAN_VENDOR_ATTR_CFR_VERSION: Optional (u8) + * Value is 1 or 2 since there are two versions of CFR capture. Two versions + * can't be enabled at same time. This attribute is mandatory if target + * support both versions and use one of them. + * + * @QCA_WLAN_VENDOR_ATTR_CFR_ENABLE_GROUP_BITMAP: Optional (u32) + * This attribute is mandatory for version 2 if + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY is used. + * Bits 15:0 Bit fields indicating which group to be enabled. + * Bits 31:16 Reserved for future use. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION: Optional (u32) + * CFR capture duration in microsecond. This attribute is mandatory for + * version 2 if attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL: Optional (u32) + * CFR capture interval in microsecond. This attribute is mandatory for + * version 2 if attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE: Optional (u32) + * CFR capture type is defined in enum qca_wlan_vendor_cfr_capture_type. + * This attribute is mandatory for version 2. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK: Optional (u64) + * Bit fields indicating which user in the current UL MU + * transmissions are enabled for CFR capture. Bits 36 to 0 indicating + * user indexes for 37 users in a UL MU transmission. If bit 0 is set, + * then the CFR capture will happen for user index 0 in the current + * UL MU transmission. If bits 0,2 are set, then CFR capture for UL MU + * TX corresponds to user indices 0 and 2. Bits 63:37 Reserved for future use. + * This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT: Optional (u32) + * Indicates the number of consecutive Rx packets to be skipped + * before CFR capture is enabled again. + * This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE: Nested attribute containing + * one or more %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY attributes. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY: Nested attribute containing + * the following GROUP attributes: + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER: Optional (u32) + * Target support multiple groups for some configurations. Group number could be + * any value between 0 and 15. This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA: Optional (6-byte MAC address) + * Transmitter address which is used to filter packets, this MAC address takes + * effect with QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK. + * This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA: Optional (6-byte MAC address) + * Receiver address which is used to filter packets, this MAC address takes + * effect with QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK. + * This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK: Optional (6-byte MAC address) + * Mask of transmitter address which is used to filter packets. + * This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK: Optional (6-byte MAC address) + * Mask of receiver address which is used to filter packets. + * This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS: Optional (u32) + * Indicates packets with a specific NSS will be filtered for CFR capture. + * This is for CFR version 2 only. This is a bitmask. Bits 7:0, CFR capture will + * be done for packets matching the NSS specified within this bitmask. + * Bits 31:8 Reserved for future use. Bits 7:0 map to NSS: + * bit 0 : NSS 1 + * bit 1 : NSS 2 + * ... + * bit 7 : NSS 8 + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW: Optional (u32) + * Indicates packets with a specific BW will be filtered for CFR capture. + * This is for CFR version 2 only. This is a bitmask. Bits 4:0, CFR capture + * will be done for packets matching the bandwidths specified within this + * bitmask. Bits 31:5 Reserved for future use. Bits 4:0 map to bandwidth + * numerated in enum nl80211_band (although not all bands may be supported + * by a given device). + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER: Optional (u32) + * Management packets matching the subtype filter categories will be + * filtered in by MAC for CFR capture. This is a bitmask, in which each bit + * represents the corresponding mgmt subtype value as per + * IEEE 802.11(2016) 9.2.4.1.3 Type and Subtype subfields. + * For example, beacon frame control type is 8, its value is 1<<8 = 0x100. + * This is for CFR version 2 only + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER: Optional (u32) + * Control packets matching the subtype filter categories will be + * filtered in by MAC for CFR capture. This is a bitmask, in which each bit + * represents the corresponding control subtype value as per + * IEEE 802.11(2016) 9.2.4.1.3 Type and Subtype subfields. + * This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER: Optional (u32) + * Data packets matching the subtype filter categories will be + * filtered in by MAC for CFR capture. This is a bitmask, in which each bit + * represents the corresponding data subtype value as per + * IEEE 802.11(2016) 9.2.4.1.3 Type and Subtype subfields. + * This is for CFR version 2 only. + * + */ +enum qca_wlan_vendor_peer_cfr_capture_attr { + QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR = 1, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE = 2, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH = 3, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY = 4, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD = 5, + QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE = 6, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION = 7, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP = 8, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION = 9, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL = 10, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE = 11, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK = 12, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT = 13, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE = 14, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY = 15, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER = 16, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA = 17, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA = 18, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK = 19, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK = 20, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS = 21, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW = 22, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER = 23, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER = 24, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER = 25, + + /* Keep last */ + QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX = + QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST - 1, +}; + /** * enum qca_coex_config_profiles - This enum defines different types of * traffic streams that can be prioritized one over the other during coex @@ -7958,14 +8948,23 @@ enum qca_wlan_vendor_attr_beacon_reporting_params { * enum qca_wlan_vendor_attr_oem_data_params - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_OEM_DATA. * - * @QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA: The binary blob for the vendor - * command QCA_NL80211_VENDOR_SUBCMD_OEM_DATA are carried through this - * attribute. - * NLA_BINARY attribute, the max size is 1024 bytes. + * @QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA: This NLA_BINARY attribute is + * used to set/query the data to/from the firmware. On query, the same + * attribute is used to carry the respective data in the reply sent by the + * driver to userspace. The request to set/query the data and the format of the + * respective data from the firmware are embedded in the attribute. The + * maximum size of the attribute payload is 1024 bytes. + * Userspace has to set the QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED + * attribute when the data is queried from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED: This NLA_FLAG attribute + * is set when the userspace queries data from the firmware. This attribute + * should not be set when userspace sets the OEM data to the firmware. */ enum qca_wlan_vendor_attr_oem_data_params { QCA_WLAN_VENDOR_ATTR_OEM_DATA_INVALID = 0, QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA = 1, + QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_AFTER_LAST, @@ -7973,6 +8972,394 @@ enum qca_wlan_vendor_attr_oem_data_params { QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_AFTER_LAST - 1 }; +/** + * enum qca_wlan_vendor_attr_avoid_frequency_ext - Defines attributes to be + * used with vendor command/event QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT. + * + * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE: Required + * Nested attribute containing multiple ranges with following attributes: + * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and + * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END. + * + * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START: Required (u32) + * Starting center frequency in MHz. + * + * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END: Required (u32) + * Ending center frequency in MHz. + */ +enum qca_wlan_vendor_attr_avoid_frequency_ext { + QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE = 1, + QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START = 2, + QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END = 3, + + QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_MAX = + QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST - 1 +}; + +/* + * enum qca_wlan_vendor_attr_add_sta_node_params - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE. + */ +enum qca_wlan_vendor_attr_add_sta_node_params { + QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_INVALID = 0, + /* 6 byte MAC address of STA */ + QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_MAC_ADDR = 1, + /* Authentication algorithm used by the station of size u16; + * defined in enum nl80211_auth_type. + */ + QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_AUTH_ALGO = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_PARAM_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_PARAM_MAX = + QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_PARAM_AFTER_LAST - 1 +}; + +/** + * enum qca_btc_chain_mode - Specifies BT coex chain mode. + * This enum defines the valid set of values of BT coex chain mode. + * These values are used by attribute %QCA_VENDOR_ATTR_BTC_CHAIN_MODE of + * %QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE. + * + * @QCA_BTC_CHAIN_SHARED: chains of BT and WLAN 2.4G are shared. + * @QCA_BTC_CHAIN_SEPARATED: chains of BT and WLAN 2.4G are separated. + */ +enum qca_btc_chain_mode { + QCA_BTC_CHAIN_SHARED = 0, + QCA_BTC_CHAIN_SEPARATED = 1, +}; + +/** + * enum qca_vendor_attr_btc_chain_mode - Specifies attributes for BT coex + * chain mode. + * Attributes for data used by QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE. + * + * @QCA_VENDOR_ATTR_COEX_BTC_CHAIN_MODE: u32 attribute. + * Indicates the BT coex chain mode, are 32-bit values from + * enum qca_btc_chain_mode. This attribute is mandatory. + * + * @QCA_VENDOR_ATTR_COEX_BTC_CHAIN_MODE_RESTART: flag attribute. + * If set, vdev should be restarted when BT coex chain mode is updated. + * This attribute is optional. + */ +enum qca_vendor_attr_btc_chain_mode { + QCA_VENDOR_ATTR_BTC_CHAIN_MODE_INVALID = 0, + QCA_VENDOR_ATTR_BTC_CHAIN_MODE = 1, + QCA_VENDOR_ATTR_BTC_CHAIN_MODE_RESTART = 2, + + /* Keep last */ + QCA_VENDOR_ATTR_BTC_CHAIN_MODE_LAST, + QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX = + QCA_VENDOR_ATTR_BTC_CHAIN_MODE_LAST - 1, +}; + +/** + * enum qca_vendor_wlan_sta_flags - Station feature flags + * Bits will be set to 1 if the corresponding features are enabled. + * @QCA_VENDOR_WLAN_STA_FLAG_AMPDU: AMPDU is enabled for the station + * @QCA_VENDOR_WLAN_STA_FLAG_TX_STBC: TX Space-time block coding is enabled + for the station + * @QCA_VENDOR_WLAN_STA_FLAG_RX_STBC: RX Space-time block coding is enabled + for the station + */ +enum qca_vendor_wlan_sta_flags { + QCA_VENDOR_WLAN_STA_FLAG_AMPDU = BIT(0), + QCA_VENDOR_WLAN_STA_FLAG_TX_STBC = BIT(1), + QCA_VENDOR_WLAN_STA_FLAG_RX_STBC = BIT(2), +}; + +/** + * enum qca_vendor_wlan_sta_guard_interval - Station guard interval + * @QCA_VENDOR_WLAN_STA_GI_800_NS: Legacy normal guard interval + * @QCA_VENDOR_WLAN_STA_GI_400_NS: Legacy short guard interval + * @QCA_VENDOR_WLAN_STA_GI_1600_NS: Guard interval used by HE + * @QCA_VENDOR_WLAN_STA_GI_3200_NS: Guard interval used by HE + */ +enum qca_vendor_wlan_sta_guard_interval { + QCA_VENDOR_WLAN_STA_GI_800_NS = 0, + QCA_VENDOR_WLAN_STA_GI_400_NS = 1, + QCA_VENDOR_WLAN_STA_GI_1600_NS = 2, + QCA_VENDOR_WLAN_STA_GI_3200_NS = 3, +}; + +/** + * enum qca_wlan_vendor_attr_get_sta_info - Defines attributes + * used by QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC: + * Required attribute in request for AP mode only, 6-byte MAC address, + * corresponding to the station's MAC address for which information is + * requested. For STA mode this is not required as the info always correspond + * to the self STA and the current/last association. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_FLAGS: + * Optionally used in response, u32 attribute, contains a bitmap of different + * fields defined in enum qca_vendor_wlan_sta_flags, used in AP mode only. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_GUARD_INTERVAL: + * Optionally used in response, u32 attribute, possible values are defined in + * enum qca_vendor_wlan_sta_guard_interval, used in AP mode only. + * Guard interval used by the station. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_RETRY_COUNT: + * Optionally used in response, u32 attribute, used in AP mode only. + * Value indicates the number of data frames received from station with retry + * bit set to 1 in FC. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BC_MC_COUNT: + * Optionally used in response, u32 attribute, used in AP mode only. + * Counter for number of data frames with broadcast or multicast address in + * the destination address received from the station. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_SUCCEED: + * Optionally used in response, u32 attribute, used in both STA and AP modes. + * Value indicates the number of data frames successfully transmitted only + * after retrying the packets and for which the TX status has been updated + * back to host from target. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_EXHAUSTED: + * Optionally used in response, u32 attribute, used in both STA and AP mode. + * Value indicates the number of data frames not transmitted successfully even + * after retrying the packets for the number of times equal to the total number + * of retries allowed for that packet and for which the TX status has been + * updated back to host from target. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_TOTAL: + * Optionally used in response, u32 attribute, used in AP mode only. + * Counter in the target for the number of data frames successfully transmitted + * to the station. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY: + * Optionally used in response, u32 attribute, used in AP mode only. + * Value indicates the number of data frames successfully transmitted only + * after retrying the packets. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED: + * Optionally used in response, u32 attribute, used in both STA & AP mode. + * Value indicates the number of data frames not transmitted successfully even + * after retrying the packets for the number of times equal to the total number + * of retries allowed for that packet. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_PROBE_REQ_BMISS_COUNT: u32, used in + * the STA mode only. Represent the number of probe requests sent by the STA + * while attempting to roam on missing certain number of beacons from the + * connected AP. If queried in the disconnected state, this represents the + * count for the last connected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_PROBE_RESP_BMISS_COUNT: u32, used in + * the STA mode. Represent the number of probe responses received by the station + * while attempting to roam on missing certain number of beacons from the + * connected AP. When queried in the disconnected state, this represents the + * count when in last connected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_ALL_COUNT: u32, used in the + * STA mode only. Represents the total number of frames sent out by STA + * including Data, ACK, RTS, CTS, Control Management. This data is maintained + * only for the connect session. Represents the count of last connected session, + * when queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RTS_COUNT: u32, used in the STA mode. + * Total number of RTS sent out by the STA. This data is maintained per connect + * session. Represents the count of last connected session, when queried in the + * disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RTS_RETRY_FAIL_COUNT: u32, used in the + * STA mode.Represent the number of RTS transmission failure that reach retry + * limit. This data is maintained per connect session. Represents the count of + * last connected session, when queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_DATA_NON_AGGREGATED_COUNT: u32, used in + * the STA mode. Represent the total number of non aggregated frames transmitted + * by the STA. This data is maintained per connect session. Represents the count + * of last connected session, when queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_DATA_AGGREGATED_COUNT: u32, used in the + * STA mode. Represent the total number of aggregated frames transmitted by the + * STA. This data is maintained per connect session. Represents the count of + * last connected session, when queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_GOOD_PLCP_COUNT: u32, used in + * the STA mode. Represents the number of received frames with a good PLCP. This + * data is maintained per connect session. Represents the count of last + * connected session, when queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_INVALID_DELIMITER_COUNT: u32, + * used in the STA mode. Represents the number of occasions that no valid + * delimiter is detected by A-MPDU parser. This data is maintained per connect + * session. Represents the count of last connected session, when queried in the + * disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_CRC_FAIL_COUNT: u32, used in the + * STA mode. Represents the number of frames for which CRC check failed in the + * MAC. This data is maintained per connect session. Represents the count of + * last connected session, when queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_ACKS_GOOD_FCS_COUNT: u32, used in the + * STA mode. Represents the number of unicast ACKs received with good FCS. This + * data is maintained per connect session. Represents the count of last + * connected session, when queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BLOCKACK_COUNT: u32, used in the STA + * mode. Represents the number of received Block Acks. This data is maintained + * per connect session. Represents the count of last connected session, when + * queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BEACON_COUNT: u32, used in the STA + * mode. Represents the number of beacons received from the connected BSS. This + * data is maintained per connect session. Represents the count of last + * connected session, when queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_OTHER_BEACON_COUNT: u32, used in the + * STA mode. Represents the number of beacons received by the other BSS when in + * connected state (through the probes done by the STA). This data is maintained + * per connect session. Represents the count of last connected session, when + * queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_UCAST_DATA_GOOD_FCS_COUNT: u64, used in + * the STA mode. Represents the number of received DATA frames with good FCS and + * matching Receiver Address when in connected state. This data is maintained + * per connect session. Represents the count of last connected session, when + * queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_DATA_BC_MC_DROP_COUNT: u32, used in the + * STA mode. Represents the number of RX Data multicast frames dropped by the HW + * when in the connected state. This data is maintained per connect session. + * Represents the count of last connected session, when queried in the + * disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_1MBPS: u32, used in the + * STA mode. This represents the target power in dBm for the transmissions done + * to the AP in 2.4 GHz at 1 Mbps (DSSS) rate. This data is maintained per + * connect session. Represents the count of last connected session, when + * queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_6MBPS: u32, used in the + * STA mode. This represents the Target power in dBm for transmissions done to + * the AP in 2.4 GHz at 6 Mbps (OFDM) rate. This data is maintained per connect + * session. Represents the count of last connected session, when queried in the + * disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_MCS0: u32, used in the + * STA mode. This represents the Target power in dBm for transmissions done to + * the AP in 2.4 GHz at MCS0 rate. This data is maintained per connect session. + * Represents the count of last connected session, when queried in the + * disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_5G_6MBPS: u32, used in the + * STA mode. This represents the Target power in dBm for transmissions done to + * the AP in 5 GHz at 6 Mbps (OFDM) rate. This data is maintained per connect + * session. Represents the count of last connected session, when queried in + * the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_5G_MCS0: u32, used in the + * STA mode. This represents the Target power in dBm for for transmissions done + * to the AP in 5 GHz at MCS0 rate. This data is maintained per connect session. + * Represents the count of last connected session, when queried in the + * disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_HW_BUFFERS_OVERFLOW_COUNT: u32, used + * in the STA mode. This represents the Nested attribute representing the + * overflow counts of each receive buffer allocated to the hardware during the + * STA's connection. The number of hw buffers might vary for each WLAN + * solution and hence this attribute represents the nested array of all such + * HW buffer count. This data is maintained per connect session. Represents + * the count of last connected session, when queried in the disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX_TX_POWER: u32, Max TX power (dBm) + * allowed as per the regulatory requirements for the current or last connected + * session. Used in the STA mode. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_POWER: u32, Latest TX power + * (dBm) used by the station in its latest unicast frame while communicating + * to the AP in the connected state. When queried in the disconnected state, + * this represents the TX power used by the STA with last AP communication + * when in connected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ANI_LEVEL: u32, Adaptive noise immunity + * level used to adjust the RX sensitivity. Represents the current ANI level + * when queried in the connected state. When queried in the disconnected + * state, this corresponds to the latest ANI level at the instance of + * disconnection. + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_MIC_ERROR_COUNT: u32, used in STA mode + * only. This represents the number of group addressed robust management frames + * received from this station with an invalid MIC or a missing MME when PMF is + * enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT: u32, used in STA mode + * only. This represents the number of group addressed robust management frames + * received from this station with the packet number less than or equal to the + * last received packet number when PMF is enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT: u32, used in STA + * mode only. This represents the number of Beacon frames received from this + * station with an invalid MIC or a missing MME when beacon protection is + * enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT: u32, used in STA mode + * only. This represents number of Beacon frames received from this station with + * the packet number less than or equal to the last received packet number when + * beacon protection is enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE: u32, used in + * STA mode only. Driver uses this attribute to populate the connection failure + * reason codes and the values are defined in + * enum qca_sta_connect_fail_reason_codes. Userspace applications can send + * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command after receiving + * connection failure from driver. The driver shall not include this attribute + * in response to QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO command if there is no + * connection failure observed in the last attempted connection. + */ +enum qca_wlan_vendor_attr_get_sta_info { + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC = 1, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_FLAGS = 2, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_GUARD_INTERVAL = 3, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_RETRY_COUNT = 4, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BC_MC_COUNT = 5, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_SUCCEED = 6, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_EXHAUSTED = 7, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_TOTAL = 8, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY = 9, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED = 10, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_PROBE_REQ_BMISS_COUNT = 11, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_PROBE_RESP_BMISS_COUNT = 12, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_ALL_COUNT = 13, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RTS_COUNT = 14, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RTS_RETRY_FAIL_COUNT = 15, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_DATA_NON_AGGREGATED_COUNT = 16, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_DATA_AGGREGATED_COUNT = 17, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_GOOD_PLCP_COUNT = 18, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_INVALID_DELIMITER_COUNT = 19, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_CRC_FAIL_COUNT = 20, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_ACKS_GOOD_FCS_COUNT = 21, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BLOCKACK_COUNT = 22, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BEACON_COUNT = 23, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_OTHER_BEACON_COUNT = 24, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_UCAST_DATA_GOOD_FCS_COUNT = 25, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_DATA_BC_MC_DROP_COUNT = 26, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_1MBPS = 27, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_6MBPS = 28, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_MCS0 = 29, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_5G_6MBPS = 30, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_5G_MCS0 = 31, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_HW_BUFFERS_OVERFLOW_COUNT = 32, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX_TX_POWER = 33, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_POWER = 34, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ANI_LEVEL = 35, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_MIC_ERROR_COUNT = 39, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT = 40, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT = 41, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT = 42, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE = 43, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX = + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST - 1, +}; + /** * enum qca_disconnect_reason_codes - Specifies driver disconnect reason codes. * Used when the driver triggers the STA to disconnect from the AP. @@ -8053,6 +9440,34 @@ enum qca_disconnect_reason_codes { QCA_DISCONNECT_REASON_USER_TRIGGERED = 16, }; +/** + * enum qca_sta_connect_fail_reason_codes - Defines values carried + * by QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE vendor + * attribute. + * @QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: No probe response frame received + * for unicast probe request. + * @QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: STA failed to send auth request. + * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: AP didn't send ACK for + * ath request. + * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: Auth response is not + * received from AP. + * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: STA failed to send assoc + * request. + * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: AP didn't send ACK for + * assoc request. + * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: Assoc response is not + * received from AP. + */ +enum qca_sta_connect_fail_reason_codes { + QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND = 1, + QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL = 2, + QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED = 3, + QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED = 4, + QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL = 5, + QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED = 6, + QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7, +}; + /** * enum qca_wlan_vendor_attr_driver_disconnect_reason - Defines attributes * used by %QCA_NL80211_VENDOR_SUBCMD_DRIVER_DISCONNECT_REASON vendor command. diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/scan/inc/wlan_cfg80211_scan.h b/drivers/staging/qca-wifi-host-cmn/os_if/linux/scan/inc/wlan_cfg80211_scan.h index aee2d3b5ef902344d1f58e7c9870051c335a6e41..7d7aecd2c93cb54aa9483a6ef085e9994927278c 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/scan/inc/wlan_cfg80211_scan.h +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/scan/inc/wlan_cfg80211_scan.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -108,6 +108,7 @@ enum scan_source { * @scan_id: scan identifier used across host layers which is generated at WMI * @source: scan request originator (NL/Vendor scan) * @dev: net device (same as what is in scan_request) + * @scan_start_timestamp: scan start time * * Scan request linked list element */ @@ -117,6 +118,7 @@ struct scan_req { uint32_t scan_id; uint8_t source; struct net_device *dev; + qdf_time_t scan_start_timestamp; }; /** @@ -128,6 +130,14 @@ struct scan_req { * @half_rate: Half rate flag * @quarter_rate: Quarter rate flag * @strict_pscan: strict passive scan flag + * @dwell_time_active: Active dwell time. Ignored if zero or inapplicable. + * @dwell_time_active_2g: 2.4 GHz specific active dwell time. Ignored if zero or + * inapplicable. + * @dwell_time_passive: Passive dwell time. Ignored if zero or inapplicable. + * @dwell_time_active_6g: 6 GHz specific active dwell time. Ignored if zero or + * inapplicable. + * @dwell_time_passive_6g: 6 GHz specific passive dwell time. Ignored if zero or + * inapplicable. */ struct scan_params { uint8_t source; @@ -137,6 +147,11 @@ struct scan_params { bool half_rate; bool quarter_rate; bool strict_pscan; + uint32_t dwell_time_active; + uint32_t dwell_time_active_2g; + uint32_t dwell_time_passive; + uint32_t dwell_time_active_6g; + uint32_t dwell_time_passive_6g; }; /** diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/scan/src/wlan_cfg80211_scan.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/scan/src/wlan_cfg80211_scan.c index 855124cabc7a76e2103c5b16f3a47d35d5f48308..199feba31c5076357d7b84095f46d7f19696e5ff 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/scan/src/wlan_cfg80211_scan.c +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/scan/src/wlan_cfg80211_scan.c @@ -1,6 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -23,6 +22,7 @@ #include #include +#include #include #include #include @@ -86,8 +86,8 @@ static void wlan_fill_scan_rand_attrs(struct wlan_objmgr_vdev *vdev, *randomize = true; memcpy(addr, mac_addr, QDF_MAC_ADDR_SIZE); memcpy(mask, mac_addr_mask, QDF_MAC_ADDR_SIZE); - cfg80211_debug("Random mac addr: %pM and Random mac mask: %pM", - addr, mask); + osif_debug("Random mac addr: "QDF_MAC_ADDR_FMT" and Random mac mask: "QDF_FULL_MAC_FMT, + QDF_MAC_ADDR_REF(addr), QDF_FULL_MAC_REF(mask)); } /** @@ -150,39 +150,42 @@ static void wlan_scan_rand_attrs(struct wlan_objmgr_vdev *vdev, * Return: None */ static void -wlan_config_sched_scan_plan(struct pno_scan_req_params *pno_req, +wlan_config_sched_scan_plan(struct wlan_objmgr_psoc *psoc, + struct pno_scan_req_params *pno_req, struct cfg80211_sched_scan_request *request) { + if (!ucfg_scan_get_user_config_sched_scan_plan(psoc) || + request->n_scan_plans == 1) { + pno_req->fast_scan_period = + request->scan_plans[0].interval * MSEC_PER_SEC; + /* + * if only one scan plan is configured from framework + * then both fast and slow scan should be configured with the + * same value that is why fast scan cycles are hardcoded to one + */ + pno_req->fast_scan_max_cycles = 1; + pno_req->slow_scan_period = + request->scan_plans[0].interval * MSEC_PER_SEC; + } /* * As of now max 2 scan plans were supported by firmware * if number of scan plan supported by firmware increased below logic * must change. */ - if (request->n_scan_plans == SCAN_PNO_MAX_PLAN_REQUEST) { + else if (request->n_scan_plans == SCAN_PNO_MAX_PLAN_REQUEST) { pno_req->fast_scan_period = request->scan_plans[0].interval * MSEC_PER_SEC; pno_req->fast_scan_max_cycles = request->scan_plans[0].iterations; pno_req->slow_scan_period = request->scan_plans[1].interval * MSEC_PER_SEC; - } else if (request->n_scan_plans == 1) { - pno_req->fast_scan_period = - request->scan_plans[0].interval * MSEC_PER_SEC; - /* - * if only one scan plan is configured from framework - * then both fast and slow scan should be configured with the - * same value that is why fast scan cycles are hardcoded to one - */ - pno_req->fast_scan_max_cycles = 1; - pno_req->slow_scan_period = - request->scan_plans[0].interval * MSEC_PER_SEC; } else { - cfg80211_err("Invalid number of scan plans %d !!", - request->n_scan_plans); + osif_err("Invalid number of scan plans %d !!", + request->n_scan_plans); } } #else -#define wlan_config_sched_scan_plan(pno_req, request) \ +#define wlan_config_sched_scan_plan(psoc, pno_req, request) \ __wlan_config_sched_scan_plan(pno_req, request, psoc) static void @@ -235,17 +238,17 @@ static void wlan_cfg80211_pno_callback(struct wlan_objmgr_vdev *vdev, if (event->type != SCAN_EVENT_TYPE_NLO_COMPLETE) return; - cfg80211_debug("vdev id = %d", event->vdev_id); + osif_debug("vdev id = %d", event->vdev_id); pdev = wlan_vdev_get_pdev(vdev); if (!pdev) { - cfg80211_err("pdev is NULL"); + osif_err("pdev is NULL"); return; } pdev_ospriv = wlan_pdev_get_ospriv(pdev); if (!pdev_ospriv) { - cfg80211_err("pdev_ospriv is NULL"); + osif_err("pdev_ospriv is NULL"); return; } wlan_cfg80211_sched_scan_results(pdev_ospriv->wiphy, 0); @@ -264,12 +267,13 @@ static bool wlan_cfg80211_is_ap_go_present(struct wlan_objmgr_psoc *psoc) static QDF_STATUS wlan_cfg80211_is_chan_ok_for_dnbs( struct wlan_objmgr_psoc *psoc, - u8 channel, bool *ok) + u16 chan_freq, bool *ok) { - QDF_STATUS status = policy_mgr_is_chan_ok_for_dnbs(psoc, channel, ok); + QDF_STATUS status = policy_mgr_is_chan_ok_for_dnbs( + psoc, chan_freq, ok); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("DNBS check failed"); + osif_err("DNBS check failed"); return status; } @@ -283,7 +287,7 @@ static bool wlan_cfg80211_is_ap_go_present(struct wlan_objmgr_psoc *psoc) static QDF_STATUS wlan_cfg80211_is_chan_ok_for_dnbs( struct wlan_objmgr_psoc *psoc, - u8 channel, + u16 chan_freq, bool *ok) { if (!ok) @@ -394,14 +398,15 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev *vdev, struct pno_scan_req_params *req; int i, j, ret = 0; QDF_STATUS status; - uint8_t num_chan = 0, channel; + uint8_t num_chan = 0; + uint16_t chan_freq; struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); struct wlan_objmgr_psoc *psoc; uint32_t valid_ch[SCAN_PNO_MAX_NETW_CHANNELS_EX] = {0}; bool enable_dfs_pno_chnl_scan; if (ucfg_scan_get_pno_in_progress(vdev)) { - cfg80211_debug("pno is already in progress"); + osif_debug("pno is already in progress"); return -EBUSY; } @@ -427,15 +432,15 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev *vdev, if ((!req->networks_cnt) || (req->networks_cnt > SCAN_PNO_MAX_SUPP_NETWORKS)) { - cfg80211_err("Network input is not correct %d", - req->networks_cnt); + osif_err("Network input is not correct %d", + req->networks_cnt); ret = -EINVAL; goto error; } if (request->n_channels > SCAN_PNO_MAX_NETW_CHANNELS_EX) { - cfg80211_err("Incorrect number of channels %d", - request->n_channels); + osif_err("Incorrect number of channels %d", + request->n_channels); ret = -EINVAL; goto error; } @@ -454,14 +459,14 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev *vdev, goto error; } for (i = 0; i < request->n_channels; i++) { - channel = request->channels[i]->hw_value; + chan_freq = request->channels[i]->center_freq; if ((!enable_dfs_pno_chnl_scan) && - (wlan_reg_is_dfs_ch(pdev, channel))) { - cfg80211_debug("Dropping DFS channel :%d", - channel); + (wlan_reg_is_dfs_for_freq(pdev, chan_freq))) { + osif_debug("Dropping DFS channel freq :%d", + chan_freq); continue; } - if (wlan_reg_is_dsrc_chan(pdev, channel)) + if (wlan_reg_is_dsrc_freq(chan_freq)) continue; if (ap_or_go_present) { @@ -469,10 +474,10 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev *vdev, status = wlan_cfg80211_is_chan_ok_for_dnbs(psoc, - channel, + chan_freq, &ok); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("DNBS check failed"); + osif_err("DNBS check failed"); qdf_mem_free(chl); chl = NULL; ret = -EINVAL; @@ -481,17 +486,17 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev *vdev, if (!ok) continue; } - len += qdf_scnprintf(chl + len, buff_len - len, " %d", channel); - valid_ch[num_chan++] = wlan_chan_to_freq(channel); + len += qdf_scnprintf(chl + len, buff_len - len, " %d", chan_freq); + valid_ch[num_chan++] = chan_freq; } - cfg80211_debug("Channel-List[%d]:%s", num_chan, chl); + osif_debug("Channel-List[%d]:%s", num_chan, chl); qdf_mem_free(chl); chl = NULL; /* If all channels are DFS and dropped, * then ignore the PNO request */ if (!num_chan) { - cfg80211_notice("Channel list empty due to filtering of DSRC"); + osif_notice("Channel list empty due to filtering of DSRC"); ret = -EINVAL; goto error; } @@ -504,8 +509,8 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev *vdev, if ((!req->networks_list[i].ssid.length) || (req->networks_list[i].ssid.length > WLAN_SSID_MAX_LEN)) { - cfg80211_err(" SSID Len %d is not correct for network %d", - req->networks_list[i].ssid.length, i); + osif_err(" SSID Len %d is not correct for network %d", + req->networks_list[i].ssid.length, i); ret = -EINVAL; goto error; } @@ -564,9 +569,10 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev *vdev, * switches slow_scan_period. This is less frequent scans and firmware * shall be in slow_scan_period mode until next PNO Start. */ - wlan_config_sched_scan_plan(req, request); + wlan_config_sched_scan_plan(psoc, req, request); req->delay_start_time = wlan_config_sched_scan_start_delay(request); req->scan_backoff_multiplier = scan_backoff_multiplier; + wlan_hdd_sched_scan_update_relative_rssi(req, request); psoc = wlan_pdev_get_psoc(pdev); @@ -580,22 +586,22 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_vdev *vdev, if (ucfg_ie_whitelist_enabled(psoc, vdev)) ucfg_copy_ie_whitelist_attrs(psoc, &req->ie_whitelist); - cfg80211_debug("Network count %d n_ssids %d fast_scan_period: %d msec slow_scan_period: %d msec, fast_scan_max_cycles: %d, relative_rssi %d band_pref %d, rssi_pref %d", - req->networks_cnt, request->n_ssids, - req->fast_scan_period, req->slow_scan_period, - req->fast_scan_max_cycles, req->relative_rssi, - req->band_rssi_pref.band, req->band_rssi_pref.rssi); + osif_debug("Network count %d n_ssids %d fast_scan_period: %d msec slow_scan_period: %d msec, fast_scan_max_cycles: %d, relative_rssi %d band_pref %d, rssi_pref %d", + req->networks_cnt, request->n_ssids, req->fast_scan_period, + req->slow_scan_period, req->fast_scan_max_cycles, + req->relative_rssi, req->band_rssi_pref.band, + req->band_rssi_pref.rssi); for (i = 0; i < req->networks_cnt; i++) - cfg80211_debug("[%d] ssid: %.*s, RSSI th %d bc NW type %u", - i, req->networks_list[i].ssid.length, - req->networks_list[i].ssid.ssid, - req->networks_list[i].rssi_thresh, - req->networks_list[i].bc_new_type); + osif_debug("[%d] ssid: %.*s, RSSI th %d bc NW type %u", + i, req->networks_list[i].ssid.length, + req->networks_list[i].ssid.ssid, + req->networks_list[i].rssi_thresh, + req->networks_list[i].bc_new_type); status = ucfg_scan_pno_start(vdev, req); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("Failed to enable PNO"); + osif_err("Failed to enable PNO"); ret = -EINVAL; goto error; } @@ -611,7 +617,7 @@ int wlan_cfg80211_sched_scan_stop(struct wlan_objmgr_vdev *vdev) status = ucfg_scan_pno_stop(vdev); if (QDF_IS_STATUS_ERROR(status)) - cfg80211_debug("Failed to disable PNO"); + osif_debug("Failed to disable PNO"); return 0; } @@ -681,6 +687,7 @@ wlan_schedule_scan_start_request(struct wlan_objmgr_pdev *pdev, scan_req->source = source; scan_req->scan_id = scan_start_req->scan_req.scan_id; scan_req->dev = req->wdev->netdev; + scan_req->scan_start_timestamp = qdf_get_time_of_the_day_ms(); qdf_mutex_acquire(&osif_scan->scan_req_q_lock); if (qdf_list_size(&osif_scan->scan_req_q) < WLAN_MAX_SCAN_COUNT) { @@ -689,9 +696,9 @@ wlan_schedule_scan_start_request(struct wlan_objmgr_pdev *pdev, qdf_list_insert_back(&osif_scan->scan_req_q, &scan_req->node); } else { - cfg80211_err("scan req failed with error %d", status); + osif_err("scan req failed with error %d", status); if (status == QDF_STATUS_E_RESOURCES) - cfg80211_err("HO is in progress.So defer the scan by informing busy"); + osif_err("HO is in progress.So defer the scan by informing busy"); } } else { ucfg_scm_scan_free_scan_request_mem(scan_start_req); @@ -700,8 +707,8 @@ wlan_schedule_scan_start_request(struct wlan_objmgr_pdev *pdev, qdf_mutex_release(&osif_scan->scan_req_q_lock); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_debug_rl("Failed to enqueue Scan Req as max scan %d already queued", - qdf_list_size(&osif_scan->scan_req_q)); + osif_rl_debug("Failed to enqueue Scan Req as max scan %d already queued", + qdf_list_size(&osif_scan->scan_req_q)); qdf_mem_free(scan_req); } @@ -721,7 +728,8 @@ wlan_schedule_scan_start_request(struct wlan_objmgr_pdev *pdev, static QDF_STATUS wlan_scan_request_dequeue( struct wlan_objmgr_pdev *pdev, uint32_t scan_id, struct cfg80211_scan_request **req, - uint8_t *source, struct net_device **dev) + uint8_t *source, struct net_device **dev, + qdf_time_t *scan_start_timestamp) { QDF_STATUS status = QDF_STATUS_E_FAILURE; struct scan_req *scan_req; @@ -730,21 +738,21 @@ static QDF_STATUS wlan_scan_request_dequeue( struct osif_scan_pdev *scan_priv; if ((!source) || (!req)) { - cfg80211_err("source or request is NULL"); + osif_err("source or request is NULL"); return QDF_STATUS_E_NULL_VALUE; } /* Get NL global context from objmgr*/ osif_ctx = wlan_pdev_get_ospriv(pdev); if (!osif_ctx) { - cfg80211_err("Failed to retrieve osif context"); + osif_err("Failed to retrieve osif context"); return status; } scan_priv = osif_ctx->osif_scan; qdf_mutex_acquire(&scan_priv->scan_req_q_lock); if (qdf_list_empty(&scan_priv->scan_req_q)) { - cfg80211_info("Scan List is empty"); + osif_info("Scan List is empty"); qdf_mutex_release(&scan_priv->scan_req_q_lock); return QDF_STATUS_E_FAILURE; } @@ -752,40 +760,40 @@ static QDF_STATUS wlan_scan_request_dequeue( if (QDF_STATUS_SUCCESS != qdf_list_peek_front(&scan_priv->scan_req_q, &next_node)) { qdf_mutex_release(&scan_priv->scan_req_q_lock); - cfg80211_err("Failed to remove Scan Req from queue"); + osif_err("Failed to remove Scan Req from queue"); return QDF_STATUS_E_FAILURE; } do { node = next_node; - scan_req = qdf_container_of(node, struct scan_req, - node); + scan_req = qdf_container_of(node, struct scan_req, node); if (scan_req->scan_id == scan_id) { status = qdf_list_remove_node(&scan_priv->scan_req_q, - node); + node); if (status == QDF_STATUS_SUCCESS) { *req = scan_req->scan_request; *source = scan_req->source; *dev = scan_req->dev; + *scan_start_timestamp = + scan_req->scan_start_timestamp; qdf_mem_free(scan_req); qdf_mutex_release(&scan_priv->scan_req_q_lock); - cfg80211_debug("removed Scan id: %d, req = %pK, pending scans %d", - scan_id, req, - qdf_list_size(&scan_priv-> - scan_req_q)); + osif_debug("removed Scan id: %d, req = %pK, pending scans %d", + scan_id, req, + qdf_list_size(&scan_priv->scan_req_q)); return QDF_STATUS_SUCCESS; } else { qdf_mutex_release(&scan_priv->scan_req_q_lock); - cfg80211_err("Failed to remove scan id %d, pending scans %d", - scan_id, - qdf_list_size(&scan_priv->scan_req_q)); + osif_err("Failed to remove scan id %d, pending scans %d", + scan_id, + qdf_list_size(&scan_priv->scan_req_q)); return status; } } } while (QDF_STATUS_SUCCESS == qdf_list_peek_next(&scan_priv->scan_req_q, node, &next_node)); qdf_mutex_release(&scan_priv->scan_req_q_lock); - cfg80211_debug("Failed to find scan id %d", scan_id); + osif_debug("Failed to find scan id %d", scan_id); return status; } @@ -850,14 +858,16 @@ static void wlan_vendor_scan_callback(struct cfg80211_scan_request *req, int i; uint8_t scan_status; uint64_t cookie; + int index = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX; - skb = cfg80211_vendor_event_alloc(req->wdev->wiphy, req->wdev, - SCAN_DONE_EVENT_BUF_SIZE + 4 + NLMSG_HDRLEN, - QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX, - GFP_ATOMIC); + skb = wlan_cfg80211_vendor_event_alloc(req->wdev->wiphy, req->wdev, + SCAN_DONE_EVENT_BUF_SIZE + 4 + + NLMSG_HDRLEN, + index, + GFP_ATOMIC); if (!skb) { - cfg80211_err("skb alloc failed"); + osif_err("skb alloc failed"); qdf_mem_free(req); return; } @@ -900,13 +910,13 @@ static void wlan_vendor_scan_callback(struct cfg80211_scan_request *req, if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SCAN_STATUS, scan_status)) goto nla_put_failure; - cfg80211_vendor_event(skb, GFP_ATOMIC); + wlan_cfg80211_vendor_event(skb, GFP_ATOMIC); qdf_mem_free(req); return; nla_put_failure: - kfree_skb(skb); + wlan_cfg80211_vendor_free_skb(skb); qdf_mem_free(req); } @@ -963,6 +973,36 @@ void wlan_scan_release_wake_lock(struct wlan_objmgr_psoc *psoc, } #endif +static +uint32_t wlan_scan_get_bss_count_for_scan(struct wlan_objmgr_pdev *pdev, + qdf_time_t scan_start_ts) +{ + struct scan_filter *filter; + qdf_list_t *list = NULL; + uint32_t count = 0; + + if (!scan_start_ts) + return count; + + filter = qdf_mem_malloc(sizeof(*filter)); + if (!filter) + return count; + + filter->ignore_auth_enc_type = true; + filter->age_threshold = qdf_get_time_of_the_day_ms() - scan_start_ts; + + list = ucfg_scan_get_result(pdev, filter); + + qdf_mem_free(filter); + + if (list) { + count = qdf_list_size(list); + ucfg_scan_purge_results(list); + } + + return count; +} + /** * wlan_cfg80211_scan_done_callback() - scan done callback function called after * scan is finished @@ -979,44 +1019,49 @@ static void wlan_cfg80211_scan_done_callback( { struct cfg80211_scan_request *req = NULL; bool success = false; - uint32_t scan_id = event->scan_id; + uint32_t scan_id; uint8_t source = NL_SCAN; struct wlan_objmgr_pdev *pdev; struct pdev_osif_priv *osif_priv; struct net_device *netdev = NULL; QDF_STATUS status; + qdf_time_t scan_start_timestamp = 0; + uint32_t unique_bss_count = 0; + + if (!event) { + osif_nofl_err("Invalid scan event received"); + return; + } + + scan_id = event->scan_id; qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_OS_IF, event->type, - event->vdev_id, event->scan_id); + event->vdev_id, scan_id); + + if (event->type == SCAN_EVENT_TYPE_STARTED) + osif_nofl_info("scan start scan id %d", scan_id); if (!util_is_scan_completed(event, &success)) return; - cfg80211_debug("vdev %d, scan id %d type %s(%d) reason %s(%d)", - event->vdev_id, scan_id, - util_scan_get_ev_type_name(event->type), event->type, - util_scan_get_ev_reason_name(event->reason), - event->reason); - pdev = wlan_vdev_get_pdev(vdev); status = wlan_scan_request_dequeue( - pdev, scan_id, &req, &source, &netdev); + pdev, scan_id, &req, &source, &netdev, + &scan_start_timestamp); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("Dequeue of scan request failed ID: %d", scan_id); + osif_err("Dequeue of scan request failed ID: %d", scan_id); goto allow_suspend; } if (!netdev) { - cfg80211_err("net dev is NULL,Drop scan event Id: %d", - scan_id); + osif_err("net dev is NULL,Drop scan event Id: %d", scan_id); goto allow_suspend; } /* Make sure vdev is active */ status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_OSIF_ID); if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("Failed to get vdev reference: scan Id: %d", - scan_id); + osif_err("Failed to get vdev reference: scan Id: %d", scan_id); goto allow_suspend; } @@ -1033,6 +1078,14 @@ static void wlan_cfg80211_scan_done_callback( wlan_vendor_scan_callback(req, !success); wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID); + + unique_bss_count = wlan_scan_get_bss_count_for_scan(pdev, + scan_start_timestamp); + osif_nofl_info("vdev %d, scan id %d type %s(%d) reason %s(%d) scan found %d bss", + event->vdev_id, scan_id, + util_scan_get_ev_type_name(event->type), event->type, + util_scan_get_ev_reason_name(event->reason), + event->reason, unique_bss_count); allow_suspend: osif_priv = wlan_pdev_get_ospriv(pdev); qdf_mutex_acquire(&osif_priv->osif_scan->scan_req_q_lock); @@ -1059,6 +1112,7 @@ static void wlan_cfg80211_scan_done_callback( } else { qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock); } + } QDF_STATUS wlan_scan_runtime_pm_init(struct wlan_objmgr_pdev *pdev) @@ -1189,7 +1243,7 @@ wlan_cfg80211_enqueue_for_cleanup(qdf_list_t *scan_cleanup_q, qdf_list_remove_node(&scan_priv->scan_req_q, node)) { qdf_mutex_release(&scan_priv->scan_req_q_lock); - cfg80211_err("Failed to remove scan request"); + osif_err("Failed to remove scan request"); return; } qdf_mem_free(scan_req); @@ -1212,7 +1266,7 @@ void wlan_cfg80211_cleanup_scan_queue(struct wlan_objmgr_pdev *pdev, qdf_list_node_t *node = NULL; if (!pdev) { - cfg80211_err("pdev is Null"); + osif_err("pdev is Null"); return; } @@ -1230,7 +1284,7 @@ void wlan_cfg80211_cleanup_scan_queue(struct wlan_objmgr_pdev *pdev, while (!qdf_list_empty(&scan_cleanup_q)) { if (QDF_STATUS_SUCCESS != qdf_list_remove_front(&scan_cleanup_q, &node)) { - cfg80211_err("Failed to remove scan request"); + osif_err("Failed to remove scan request"); return; } scan_req = container_of(node, struct scan_req, node); @@ -1299,7 +1353,7 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, struct wlan_ssid *pssid; uint8_t i; int ret = 0; - uint8_t num_chan = 0, channel; + uint8_t num_chan = 0; uint32_t c_freq; struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); wlan_scan_requester req_id; @@ -1314,18 +1368,18 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, psoc = wlan_pdev_get_psoc(pdev); if (!psoc) { - cfg80211_err("Invalid psoc object"); + osif_err("Invalid psoc object"); return -EINVAL; } opmode = wlan_vdev_mlme_get_opmode(vdev); - cfg80211_debug("%s(vdev%d): mode %d", request->wdev->netdev->name, - wlan_vdev_get_id(vdev), opmode); + osif_debug("%s(vdev%d): mode %d", request->wdev->netdev->name, + wlan_vdev_get_id(vdev), opmode); /* Get NL global context from objmgr*/ osif_priv = wlan_pdev_get_ospriv(pdev); if (!osif_priv) { - cfg80211_err("Invalid osif priv object"); + osif_err("Invalid osif priv object"); return -EINVAL; } @@ -1339,7 +1393,7 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, !qdf_list_empty(&osif_priv->osif_scan->scan_req_q) && opmode != QDF_SAP_MODE) { qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock); - cfg80211_err("Simultaneous scan disabled, reject scan"); + osif_err("Simultaneous scan disabled, reject scan"); return -EBUSY; } qdf_mutex_release(&osif_priv->osif_scan->scan_req_q_lock); @@ -1354,7 +1408,7 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, req_id = osif_priv->osif_scan->req_id; scan_id = ucfg_scan_get_scan_id(psoc); if (!scan_id) { - cfg80211_err("Invalid scan id"); + osif_err("Invalid scan id"); qdf_mem_free(req); return -EINVAL; } @@ -1383,9 +1437,9 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, req->scan_req.num_ssids = request->n_ssids; if (req->scan_req.num_ssids > WLAN_SCAN_MAX_NUM_SSID) { - cfg80211_info("number of ssid %d greater than MAX %d", - req->scan_req.num_ssids, - WLAN_SCAN_MAX_NUM_SSID); + osif_info("number of ssid %d greater than MAX %d", + req->scan_req.num_ssids, + WLAN_SCAN_MAX_NUM_SSID); req->scan_req.num_ssids = WLAN_SCAN_MAX_NUM_SSID; } /* copy all the ssid's and their length */ @@ -1419,6 +1473,24 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, if (is_p2p_scan && request->no_cck) req->scan_req.scan_type = SCAN_TYPE_P2P_SEARCH; + if (params->dwell_time_active) + req->scan_req.dwell_time_active = params->dwell_time_active; + + if (params->dwell_time_active_2g) + req->scan_req.dwell_time_active_2g = + params->dwell_time_active_2g; + + if (params->dwell_time_passive) + req->scan_req.dwell_time_passive = params->dwell_time_passive; + + if (params->dwell_time_active_6g) + req->scan_req.dwell_time_active_6g = + params->dwell_time_active_6g; + + if (params->dwell_time_passive_6g) + req->scan_req.dwell_time_passive_6g = + params->dwell_time_passive_6g; + /* Set dwell time mode according to scan policy type flags */ if (ucfg_scan_cfg_honour_nl_scan_policy_flags(psoc)) { if (req->scan_req.scan_policy_high_accuracy) @@ -1449,21 +1521,18 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, psoc, PM_P2P_GO_MODE, NULL); #endif for (i = 0; i < request->n_channels; i++) { - channel = request->channels[i]->hw_value; - c_freq = wlan_reg_chan_to_freq(pdev, channel); - if (wlan_reg_is_dsrc_chan(pdev, channel)) + c_freq = request->channels[i]->center_freq; + if (wlan_reg_is_dsrc_freq(c_freq)) continue; #ifdef WLAN_POLICY_MGR_ENABLE if (ap_or_go_present) { bool ok; - qdf_status = - policy_mgr_is_chan_ok_for_dnbs(psoc, - channel, - &ok); + qdf_status = policy_mgr_is_chan_ok_for_dnbs( + psoc, c_freq, &ok); if (QDF_IS_STATUS_ERROR(qdf_status)) { - cfg80211_err("DNBS check failed"); + osif_err("DNBS check failed"); ret = -EINVAL; goto err; } @@ -1480,12 +1549,12 @@ int wlan_cfg80211_scan(struct wlan_objmgr_vdev *vdev, req->scan_req.chan_list.chan[num_chan].phymode = SCAN_PHY_MODE_11A; num_chan++; - if (num_chan >= WLAN_SCAN_MAX_NUM_CHANNELS) + if (num_chan >= NUM_CHANNELS) break; } } if (!num_chan) { - cfg80211_err("Received zero non-dsrc channels"); + osif_err("Received zero non-dsrc channels"); ret = -EINVAL; goto err; } @@ -1607,14 +1676,14 @@ static int wlan_get_scanid(struct wlan_objmgr_pdev *pdev, /* Get NL global context from objmgr*/ osif_ctx = wlan_pdev_get_ospriv(pdev); if (!osif_ctx) { - cfg80211_err("Failed to retrieve osif context"); + osif_err("Failed to retrieve osif context"); return ret; } scan_priv = osif_ctx->osif_scan; qdf_mutex_acquire(&scan_priv->scan_req_q_lock); if (qdf_list_empty(&scan_priv->scan_req_q)) { qdf_mutex_release(&scan_priv->scan_req_q_lock); - cfg80211_err("Failed to retrieve scan id"); + osif_err("Failed to retrieve scan id"); return ret; } @@ -1660,7 +1729,7 @@ QDF_STATUS wlan_abort_scan(struct wlan_objmgr_pdev *pdev, /* Get NL global context from objmgr*/ osif_ctx = wlan_pdev_get_ospriv(pdev); if (!osif_ctx) { - cfg80211_err("Failed to retrieve osif context"); + osif_err("Failed to retrieve osif context"); qdf_mem_free(req); return QDF_STATUS_E_FAILURE; } @@ -1689,22 +1758,24 @@ QDF_STATUS wlan_abort_scan(struct wlan_objmgr_pdev *pdev, else req->cancel_req.req_type = WLAN_SCAN_CANCEL_VDEV_ALL; - cfg80211_debug("Type %d Vdev %d pdev %d scan id %d sync %d", - req->cancel_req.req_type, req->cancel_req.vdev_id, - req->cancel_req.pdev_id, req->cancel_req.scan_id, sync); + osif_debug("Type %d Vdev %d pdev %d scan id %d sync %d", + req->cancel_req.req_type, req->cancel_req.vdev_id, + req->cancel_req.pdev_id, req->cancel_req.scan_id, sync); if (sync) status = ucfg_scan_cancel_sync(req); else status = ucfg_scan_cancel(req); if (QDF_IS_STATUS_ERROR(status)) - cfg80211_err("Cancel scan request failed"); + osif_err("Cancel scan request failed"); wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID); return status; } +qdf_export_symbol(wlan_abort_scan); + int wlan_cfg80211_abort_scan(struct wlan_objmgr_pdev *pdev) { uint8_t pdev_id; @@ -1731,7 +1802,7 @@ int wlan_vendor_abort_scan(struct wlan_objmgr_pdev *pdev, pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SCAN_MAX, data, data_len, scan_policy)) { - cfg80211_err("Invalid ATTR"); + osif_err("Invalid ATTR"); return ret; } @@ -1752,16 +1823,13 @@ int wlan_vendor_abort_scan(struct wlan_objmgr_pdev *pdev, static inline struct ieee80211_channel * wlan_get_ieee80211_channel(struct wiphy *wiphy, struct wlan_objmgr_pdev *pdev, - int chan_no) + int chan_freq) { - unsigned int freq; struct ieee80211_channel *chan; - freq = wlan_reg_chan_to_freq(pdev, chan_no); - chan = ieee80211_get_channel(wiphy, freq); + chan = ieee80211_get_channel(wiphy, chan_freq); if (!chan) - cfg80211_err("chan is NULL, chan_no: %d freq: %d", - chan_no, freq); + osif_err("chan is NULL, freq: %d", chan_freq); return chan; } @@ -1832,7 +1900,7 @@ static void wlan_fill_per_chain_rssi(struct cfg80211_inform_bss *data, uint32_t i; if (!bss || !data) { - cfg80211_err("Received bss is NULL"); + osif_err("Received bss is NULL"); return; } for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++) { @@ -1858,7 +1926,7 @@ wlan_cfg80211_inform_bss_frame_data(struct wiphy *wiphy, struct cfg80211_inform_bss data = {0}; if (!bss) { - cfg80211_err("bss is null"); + osif_err("bss is null"); return NULL; } wlan_fill_per_chain_rssi(&data, bss); @@ -1904,7 +1972,7 @@ void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev, struct wlan_cfg80211_inform_bss bss_data = {0}; if (!pdev_ospriv) { - cfg80211_err("os_priv is NULL"); + osif_err("os_priv is NULL"); return; } @@ -1913,8 +1981,8 @@ void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev, bss_data.frame_len = wlan_get_frame_len(scan_params); bss_data.mgmt = qdf_mem_malloc_atomic(bss_data.frame_len); if (!bss_data.mgmt) { - cfg80211_err("mem alloc failed for bss %pM seq %d", - bss_data.mgmt->bssid, scan_params->seq_num); + osif_err("bss mem alloc failed for seq %d", + scan_params->seq_num); return; } qdf_mem_copy(bss_data.mgmt, @@ -1933,11 +2001,12 @@ void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev, bss_data.rssi = scan_params->rssi_raw; bss_data.chan = wlan_get_ieee80211_channel(wiphy, pdev, - scan_params->channel.chan_idx); + scan_params->channel.chan_freq); if (!bss_data.chan) { - cfg80211_err("Channel not found for bss %pM seq %d chan %d", - bss_data.mgmt->bssid, scan_params->seq_num, - scan_params->channel.chan_idx); + osif_err("Channel not found for bss "QDF_MAC_ADDR_FMT" seq %d chan_freq %d", + QDF_MAC_ADDR_REF(bss_data.mgmt->bssid), + scan_params->seq_num, + scan_params->channel.chan_freq); qdf_mem_free(bss_data.mgmt); return; } @@ -1955,8 +2024,9 @@ void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev, bss = wlan_cfg80211_inform_bss_frame_data(wiphy, &bss_data); if (!bss) - cfg80211_err("failed to inform bss %pM seq %d", - bss_data.mgmt->bssid, scan_params->seq_num); + osif_err("failed to inform bss "QDF_MAC_ADDR_FMT" seq %d", + QDF_MAC_ADDR_REF(bss_data.mgmt->bssid), + scan_params->seq_num); else wlan_cfg80211_put_bss(wiphy, bss); @@ -1996,10 +2066,11 @@ void __wlan_cfg80211_unlink_bss_list(struct wiphy *wiphy, uint8_t *bssid, bss = wlan_cfg80211_get_bss(wiphy, NULL, bssid, ssid, ssid_len); if (!bss) { - cfg80211_info("BSS %pM not found", bssid); + osif_info("BSS "QDF_MAC_ADDR_FMT" not found", + QDF_MAC_ADDR_REF(bssid)); } else { - cfg80211_debug("unlink entry for ssid:%.*s and BSSID %pM", - ssid_len, ssid, bssid); + osif_debug("unlink entry for ssid:%.*s and BSSID "QDF_MAC_ADDR_FMT, + ssid_len, ssid, QDF_MAC_ADDR_REF(bssid)); cfg80211_unlink_bss(wiphy, bss); wlan_cfg80211_put_bss(wiphy, bss); } @@ -2015,11 +2086,11 @@ void __wlan_cfg80211_unlink_bss_list(struct wiphy *wiphy, uint8_t *bssid, */ bss = wlan_cfg80211_get_bss(wiphy, NULL, bssid, NULL, 0); if (!bss) { - cfg80211_debug("Hidden bss not found for Ssid:%.*s BSSID: %pM sid_len %d", - ssid_len, ssid, bssid, ssid_len); + osif_debug("Hidden bss not found for Ssid:%.*s BSSID: "QDF_MAC_ADDR_FMT" sid_len %d", + ssid_len, ssid, QDF_MAC_ADDR_REF(bssid), ssid_len); } else { - cfg80211_debug("unlink entry for Hidden ssid:%.*s and BSSID %pM", - ssid_len, ssid, bssid); + osif_debug("unlink entry for Hidden ssid:%.*s and BSSID "QDF_MAC_ADDR_FMT, + ssid_len, ssid, QDF_MAC_ADDR_REF(bssid)); cfg80211_unlink_bss(wiphy, bss); /* cfg80211_get_bss get bss with ref count so release it */ @@ -2033,7 +2104,7 @@ void wlan_cfg80211_unlink_bss_list(struct wlan_objmgr_pdev *pdev, struct wiphy *wiphy; if (!pdev_ospriv) { - cfg80211_err("os_priv is NULL"); + osif_err("os_priv is NULL"); return; } diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/inc/os_if_spectral_netlink.h b/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/inc/os_if_spectral_netlink.h index 156eaac00bacc9e02036bf587c73c78600abb093..9028654621d5ec13da0239dc6de44451769b9325 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/inc/os_if_spectral_netlink.h +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/inc/os_if_spectral_netlink.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2017-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -36,7 +36,7 @@ void os_if_spectral_nl_data_ready(struct sk_buff *skb); #ifndef SPECTRAL_NETLINK #define SPECTRAL_NETLINK (NETLINK_GENERIC + 1) #endif -#define MAX_SPECTRAL_PAYLOAD 1500 +#define MAX_SPECTRAL_PAYLOAD (2004) /* Init's network namespace */ extern struct net init_net; diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/inc/wlan_cfg80211_spectral.h b/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/inc/wlan_cfg80211_spectral.h index 39bae6fae644ec20eec95e9dadb0929431bf23b0..ec5081c1ea50be9e9d4f03aa2dbba216a77bb983 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/inc/wlan_cfg80211_spectral.h +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/inc/wlan_cfg80211_spectral.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017, 2019 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 @@ -135,4 +135,17 @@ int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy, struct wlan_objmgr_pdev *pdev, const void *data, int data_len); + +/** + * wlan_cfg80211_spectral_scan_dma_debug_config() - configure DMA debug + * @pdev: Pointer to pdev + * @tb: Pointer to Spectral Scan config attribute + * @sscan_mode: Spectral scan mode + * + * Return QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure + */ +QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config( + struct wlan_objmgr_pdev *pdev, + struct nlattr **tb, + enum spectral_scan_mode sscan_mode); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/src/os_if_spectral_netlink.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/src/os_if_spectral_netlink.c index 9ec2d155f26698f6e993e902c0a142a5b649e274..748a078e4d81599982be83c431da9fc9de986097 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/src/os_if_spectral_netlink.c +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/src/os_if_spectral_netlink.c @@ -162,14 +162,14 @@ os_if_spectral_init_nl(struct wlan_objmgr_pdev *pdev) memset(&cfg, 0, sizeof(cfg)); if (!pdev) { - cfg80211_err("PDEV is NULL!"); + osif_err("PDEV is NULL!"); return -EINVAL; } ps = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_SPECTRAL); if (!ps) { - cfg80211_err("PDEV SPECTRAL object is NULL!"); + osif_err("PDEV SPECTRAL object is NULL!"); return -EINVAL; } os_if_spectral_init_nl_cfg(&cfg); @@ -178,14 +178,14 @@ os_if_spectral_init_nl(struct wlan_objmgr_pdev *pdev) os_if_spectral_create_nl_sock(&cfg); if (!os_if_spectral_nl_sock) { - cfg80211_err("NETLINK_KERNEL_CREATE FAILED"); + osif_err("NETLINK_KERNEL_CREATE FAILED"); return -ENODEV; } } ps->spectral_sock = os_if_spectral_nl_sock; if (!ps->spectral_sock) { - cfg80211_err("ps->spectral_sock is NULL"); + osif_err("ps->spectral_sock is NULL"); return -ENODEV; } atomic_inc(&spectral_nl_users); @@ -206,14 +206,14 @@ os_if_spectral_destroy_netlink(struct wlan_objmgr_pdev *pdev) struct pdev_spectral *ps = NULL; if (!pdev) { - cfg80211_err("PDEV is NULL!"); + osif_err("PDEV is NULL!"); return -EINVAL; } ps = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_SPECTRAL); if (!ps) { - cfg80211_err("PDEV SPECTRAL object is NULL!"); + osif_err("PDEV SPECTRAL object is NULL!"); return -EINVAL; } ps->spectral_sock = NULL; @@ -248,17 +248,17 @@ os_if_spectral_prep_skb(struct wlan_objmgr_pdev *pdev, void *buf = NULL; if (!pdev) { - cfg80211_err("PDEV is NULL!"); + osif_err("PDEV is NULL!"); return NULL; } if (smsg_type >= SPECTRAL_MSG_TYPE_MAX) { - cfg80211_err("Invalid Spectral message type %u", smsg_type); + osif_err("Invalid Spectral message type %u", smsg_type); return NULL; } if (buf_type >= SPECTRAL_MSG_BUF_TYPE_MAX) { - cfg80211_err("Invalid Spectral message buffer type %u", + osif_err("Invalid Spectral message buffer type %u", buf_type); return NULL; } @@ -267,7 +267,7 @@ os_if_spectral_prep_skb(struct wlan_objmgr_pdev *pdev, WLAN_UMAC_COMP_SPECTRAL); if (!ps) { - cfg80211_err("PDEV SPECTRAL object is NULL!"); + osif_err("PDEV SPECTRAL object is NULL!"); return NULL; } @@ -278,7 +278,7 @@ os_if_spectral_prep_skb(struct wlan_objmgr_pdev *pdev, 0, 0, false); if (!ps->skb[smsg_type]) { - cfg80211_err("alloc skb (len=%u, msg_type=%u) failed", + osif_err("alloc skb (len=%u, msg_type=%u) failed", MAX_SPECTRAL_PAYLOAD, smsg_type); return NULL; } @@ -307,7 +307,7 @@ os_if_spectral_prep_skb(struct wlan_objmgr_pdev *pdev, spectral_nlh = (struct nlmsghdr *)ps->skb[smsg_type]->data; buf = NLMSG_DATA(spectral_nlh); } else { - cfg80211_err("Failed to get spectral report buffer"); + osif_err("Failed to get spectral report buffer"); buf = NULL; } @@ -364,29 +364,29 @@ os_if_spectral_nl_unicast_msg(struct wlan_objmgr_pdev *pdev, int status; if (!pdev) { - cfg80211_err("PDEV is NULL!"); + osif_err("PDEV is NULL!"); return -EINVAL; } if (smsg_type >= SPECTRAL_MSG_TYPE_MAX) { - cfg80211_err("Invalid Spectral message type %u", smsg_type); + osif_err("Invalid Spectral message type %u", smsg_type); return -EINVAL; } ps = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_SPECTRAL); if (!ps) { - cfg80211_err("PDEV SPECTRAL object is NULL!"); + osif_err("PDEV SPECTRAL object is NULL!"); return -EINVAL; } if (!ps->skb[smsg_type]) { - cfg80211_err("Socket buffer is null, msg_type= %u", smsg_type); + osif_err("Socket buffer is null, msg_type= %u", smsg_type); return -EINVAL; } if (!ps->spectral_sock) { - cfg80211_err("Spectral Socket is invalid, msg_type= %u", + osif_err("Spectral Socket is invalid, msg_type= %u", smsg_type); qdf_nbuf_free(ps->skb[smsg_type]); ps->skb[smsg_type] = NULL; @@ -421,24 +421,24 @@ os_if_spectral_nl_unicast_msg(struct wlan_objmgr_pdev *pdev, int status; if (!pdev) { - cfg80211_err("PDEV is NULL!"); + osif_err("PDEV is NULL!"); return -EINVAL; } if (smsg_type >= SPECTRAL_MSG_TYPE_MAX) { - cfg80211_err("Invalid Spectral message type %u", smsg_type); + osif_err("Invalid Spectral message type %u", smsg_type); return -EINVAL; } ps = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_SPECTRAL); if (!ps) { - cfg80211_err("PDEV SPECTRAL object is NULL!"); + osif_err("PDEV SPECTRAL object is NULL!"); return -EINVAL; } if (!ps->skb[smsg_type]) { - cfg80211_err("Socket buffer is null, msg_type= %u", smsg_type); + osif_err("Socket buffer is null, msg_type= %u", smsg_type); return -EINVAL; } @@ -449,7 +449,7 @@ os_if_spectral_nl_unicast_msg(struct wlan_objmgr_pdev *pdev, MSG_DONTWAIT, WLAN_NL_MSG_SPECTRAL_SCAN, CLD80211_MCGRP_OEM_MSGS); if (status < 0) - cfg80211_err("failed to send to spectral scan app"); + osif_err("failed to send to spectral scan app"); /* clear the local copy, free would be done by netlink layer */ ps->skb[smsg_type] = NULL; @@ -482,12 +482,12 @@ os_if_spectral_nl_bcast_msg(struct wlan_objmgr_pdev *pdev, #endif if (!pdev) { - cfg80211_err("PDEV is NULL!"); + osif_err("PDEV is NULL!"); return -EINVAL; } if (smsg_type >= SPECTRAL_MSG_TYPE_MAX) { - cfg80211_err("Invalid Spectral message type %u", smsg_type); + osif_err("Invalid Spectral message type %u", smsg_type); return -EINVAL; } @@ -495,12 +495,12 @@ os_if_spectral_nl_bcast_msg(struct wlan_objmgr_pdev *pdev, WLAN_UMAC_COMP_SPECTRAL); if (!ps) { - cfg80211_err("PDEV SPECTRAL object is NULL!"); + osif_err("PDEV SPECTRAL object is NULL!"); return -EINVAL; } if (!ps->skb[smsg_type]) { - cfg80211_err("Socket buffer is null, msg_type= %u", smsg_type); + osif_err("Socket buffer is null, msg_type= %u", smsg_type); return -EINVAL; } @@ -537,12 +537,12 @@ os_if_spectral_free_skb(struct wlan_objmgr_pdev *pdev, struct pdev_spectral *ps = NULL; if (!pdev) { - cfg80211_err("PDEV is NULL!"); + osif_err("PDEV is NULL!"); return; } if (smsg_type >= SPECTRAL_MSG_TYPE_MAX) { - cfg80211_err("Invalid Spectral message type %u", smsg_type); + osif_err("Invalid Spectral message type %u", smsg_type); return; } @@ -550,12 +550,12 @@ os_if_spectral_free_skb(struct wlan_objmgr_pdev *pdev, WLAN_UMAC_COMP_SPECTRAL); if (!ps) { - cfg80211_err("PDEV SPECTRAL object is NULL!"); + osif_err("PDEV SPECTRAL object is NULL!"); return; } if (!ps->skb[smsg_type]) { - cfg80211_info("Socket buffer is null, msg_type= %u", smsg_type); + osif_info("Socket buffer is null, msg_type= %u", smsg_type); return; } @@ -575,14 +575,14 @@ os_if_spectral_netlink_init(struct wlan_objmgr_pdev *pdev) struct spectral_context *sptrl_ctx; if (!pdev) { - cfg80211_err("PDEV is NULL!"); + osif_err("PDEV is NULL!"); return; } sptrl_ctx = spectral_get_spectral_ctx_from_pdev(pdev); if (!sptrl_ctx) { - cfg80211_err("Spectral context is NULL!"); + osif_err("Spectral context is NULL!"); return; } @@ -605,14 +605,14 @@ void os_if_spectral_netlink_deinit(struct wlan_objmgr_pdev *pdev) enum spectral_msg_type msg_type = SPECTRAL_MSG_NORMAL_MODE; if (!pdev) { - cfg80211_err("PDEV is NULL!"); + osif_err("PDEV is NULL!"); return; } sptrl_ctx = spectral_get_spectral_ctx_from_pdev(pdev); if (!sptrl_ctx) { - cfg80211_err("Spectral context is NULL!"); + osif_err("Spectral context is NULL!"); return; } diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/src/wlan_cfg80211_spectral.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/src/wlan_cfg80211_spectral.c index 1008d119512d281107fa058ba89cdb97d28d629c..b45efef147a7dde04d841918ecb8600762485026 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/src/wlan_cfg80211_spectral.c +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/spectral/src/wlan_cfg80211_spectral.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -31,7 +31,6 @@ #include #include #include -#include "qal_devcfg.h" static const struct nla_policy spectral_scan_policy[ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1] = { @@ -84,7 +83,11 @@ static const struct nla_policy spectral_scan_policy[ [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY] = { .type = NLA_U32}, [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE] = { - .type = NLA_U32}, + .type = NLA_U32}, + [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG] = { + .type = NLA_U8}, + [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG] = { + .type = NLA_U8}, }; static void wlan_spectral_intit_config(struct spectral_config *config_req) @@ -134,13 +137,105 @@ convert_spectral_mode_nl_to_internal break; default: - cfg80211_err("Invalid spectral mode %u", nl_spectral_mode); + osif_err("Invalid spectral mode %u", nl_spectral_mode); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * convert_spectral_err_code_internal_to_nl() - Get Spectral error code + * @spectral_err_code: Spectral error code used internally + * @nl_err_code: Spectral error code for cfg80211 + * + * Return: QDF_STATUS_SUCCESS on success, else QDF_STATUS_E_FAILURE + */ +static QDF_STATUS +convert_spectral_err_code_internal_to_nl + (enum spectral_cp_error_code spectral_err_code, + enum qca_wlan_vendor_spectral_scan_error_code *nl_err_code) +{ + switch (spectral_err_code) { + case SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED: + *nl_err_code = + QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED; + break; + + case SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED: + *nl_err_code = + QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; + break; + + case SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE: + *nl_err_code = + QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; + break; + + case SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED: + *nl_err_code = + QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED; + break; + + default: + osif_err("Invalid spectral error code %u", spectral_err_code); return QDF_STATUS_E_FAILURE; } return QDF_STATUS_SUCCESS; } +#ifdef DIRECT_BUF_RX_DEBUG +QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config( + struct wlan_objmgr_pdev *pdev, + struct nlattr **tb, + enum spectral_scan_mode sscan_mode) +{ + struct spectral_cp_request sscan_req; + uint8_t dma_debug_enable; + QDF_STATUS status; + + if (!tb || !pdev) + return QDF_STATUS_E_FAILURE; + + if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG]) { + dma_debug_enable = nla_get_u8(tb[ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG]); + sscan_req.ss_mode = sscan_mode; + sscan_req.dma_debug_req.dma_debug_enable = !!dma_debug_enable; + sscan_req.dma_debug_req.dma_debug_type = + SPECTRAL_DMA_RING_DEBUG; + sscan_req.req_id = SPECTRAL_SET_DMA_DEBUG; + status = ucfg_spectral_control(pdev, &sscan_req); + if (status != QDF_STATUS_SUCCESS) { + osif_err("Could not configure dma ring debug"); + return QDF_STATUS_E_FAILURE; + } + } + + if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG]) { + dma_debug_enable = nla_get_u8(tb[ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG]); + sscan_req.ss_mode = sscan_mode; + sscan_req.dma_debug_req.dma_debug_enable = !!dma_debug_enable; + sscan_req.dma_debug_req.dma_debug_type = + SPECTRAL_DMA_BUFFER_DEBUG; + sscan_req.req_id = SPECTRAL_SET_DMA_DEBUG; + return ucfg_spectral_control(pdev, &sscan_req); + } + + return QDF_STATUS_SUCCESS; +} +#else +QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config( + struct wlan_objmgr_pdev *pdev, + struct nlattr **tb, + enum spectral_scan_mode sscan_mode) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* DIRECT_BUF_RX_DEBUG */ + int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy, struct wlan_objmgr_pdev *pdev, const void *data, @@ -155,6 +250,7 @@ int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy, uint32_t scan_req_type = 0; struct spectral_cp_request sscan_req; enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL; + uint16_t skb_len; if (wlan_cfg80211_nla_parse( tb, @@ -162,7 +258,7 @@ int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy, data, data_len, spectral_scan_policy)) { - cfg80211_err("Invalid Spectral Scan config ATTR"); + osif_err("Invalid Spectral Scan config ATTR"); return -EINVAL; } @@ -275,6 +371,25 @@ int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy, scan_req_type = nla_get_u32(tb [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE]); + skb_len = NLMSG_HDRLEN; + /* QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE */ + skb_len += NLA_HDRLEN + sizeof(u32); + /* QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE */ + skb_len += NLA_HDRLEN + sizeof(u64); + skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len); + + if (!skb) { + osif_err(" reply skb alloc failed"); + return -ENOMEM; + } + + status = wlan_cfg80211_spectral_scan_dma_debug_config( + pdev, tb, sscan_mode); + if (QDF_IS_STATUS_ERROR(status)) { + status = QDF_STATUS_E_INVAL; + goto free_skb_return_os_status; + } + if (CONFIG_REQUESTED(scan_req_type)) { sscan_req.ss_mode = sscan_mode; sscan_req.req_id = SPECTRAL_SET_CONFIG; @@ -282,36 +397,77 @@ int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy, qdf_min(sizeof(sscan_req.config_req.sscan_config), sizeof(config_req))); status = ucfg_spectral_control(pdev, &sscan_req); - if (QDF_IS_STATUS_ERROR(status)) - return -EINVAL; + if (QDF_IS_STATUS_ERROR(status)) { + enum qca_wlan_vendor_spectral_scan_error_code + spectral_nl_err_code; + + /* No error reasons populated, just return error */ + if (sscan_req.config_req.sscan_err_code == + SPECTRAL_SCAN_ERR_INVALID) + goto free_skb_return_os_status; + + status = convert_spectral_err_code_internal_to_nl + (sscan_req.config_req.sscan_err_code, + &spectral_nl_err_code); + if (QDF_IS_STATUS_ERROR(status)) { + status = QDF_STATUS_E_INVAL; + goto free_skb_return_os_status; + } + + if (nla_put_u32 + (skb, + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE, + spectral_nl_err_code)) { + status = QDF_STATUS_E_INVAL; + goto free_skb_return_os_status; + } + } } if (SCAN_REQUESTED(scan_req_type)) { sscan_req.ss_mode = sscan_mode; sscan_req.req_id = SPECTRAL_ACTIVATE_SCAN; status = ucfg_spectral_control(pdev, &sscan_req); - if (QDF_IS_STATUS_ERROR(status)) - return -EINVAL; - } - - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u64) + - NLA_HDRLEN + NLMSG_HDRLEN); - if (!skb) { - cfg80211_err(" reply skb alloc failed"); - return -ENOMEM; + if (QDF_IS_STATUS_ERROR(status)) { + enum qca_wlan_vendor_spectral_scan_error_code + spectral_nl_err_code; + + /* No error reasons populated, just return error */ + if (sscan_req.action_req.sscan_err_code == + SPECTRAL_SCAN_ERR_INVALID) + goto free_skb_return_os_status; + + status = convert_spectral_err_code_internal_to_nl + (sscan_req.action_req.sscan_err_code, + &spectral_nl_err_code); + if (QDF_IS_STATUS_ERROR(status)) { + status = QDF_STATUS_E_INVAL; + goto free_skb_return_os_status; + } + + if (nla_put_u32 + (skb, + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE, + spectral_nl_err_code)) { + status = QDF_STATUS_E_INVAL; + goto free_skb_return_os_status; + } + } } cookie = 0; if (wlan_cfg80211_nla_put_u64(skb, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE, cookie)) { - kfree_skb(skb); - return -EINVAL; + status = QDF_STATUS_E_INVAL; + goto free_skb_return_os_status; } - qal_devcfg_send_response((qdf_nbuf_t)skb); - + wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); return 0; +free_skb_return_os_status: + wlan_cfg80211_vendor_free_skb(skb); + return qdf_status_to_os_return(status); } int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy, @@ -323,6 +479,7 @@ int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy, QDF_STATUS status; struct spectral_cp_request sscan_req; enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL; + struct sk_buff *skb; if (wlan_cfg80211_nla_parse( tb, @@ -330,7 +487,7 @@ int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy, data, data_len, spectral_scan_policy)) { - cfg80211_err("Invalid Spectral Scan stop ATTR"); + osif_err("Invalid Spectral Scan stop ATTR"); return -EINVAL; } @@ -345,8 +502,38 @@ int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy, sscan_req.ss_mode = sscan_mode; sscan_req.req_id = SPECTRAL_STOP_SCAN; status = ucfg_spectral_control(pdev, &sscan_req); - if (QDF_IS_STATUS_ERROR(status)) - return -EINVAL; + if (QDF_IS_STATUS_ERROR(status)) { + enum qca_wlan_vendor_spectral_scan_error_code + spectral_nl_err_code; + + /* No error reasons populated, just return error */ + if (sscan_req.action_req.sscan_err_code == + SPECTRAL_SCAN_ERR_INVALID) + return qdf_status_to_os_return(status); + + status = convert_spectral_err_code_internal_to_nl + (sscan_req.action_req.sscan_err_code, + &spectral_nl_err_code); + if (QDF_IS_STATUS_ERROR(status)) + return -EINVAL; + + skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + NLMSG_HDRLEN + sizeof(u32) + NLA_HDRLEN); + + if (!skb) { + osif_err(" reply skb alloc failed"); + return -ENOMEM; + } + + if (nla_put_u32 + (skb, + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE, + spectral_nl_err_code)) { + wlan_cfg80211_vendor_free_skb(skb); + return -EINVAL; + } + wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); + } return 0; } @@ -370,7 +557,7 @@ int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy, data, data_len, spectral_scan_policy)) { - cfg80211_err("Invalid Spectral Scan config ATTR"); + osif_err("Invalid Spectral Scan config ATTR"); return -EINVAL; } @@ -382,11 +569,12 @@ int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy, return -EINVAL; } - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (sizeof(u32) + + skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + (sizeof(u32) + NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + NLMSG_HDRLEN); if (!skb) { - cfg80211_err(" reply skb alloc failed"); + osif_err(" reply skb alloc failed"); return -ENOMEM; } @@ -457,10 +645,8 @@ int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy, sconfig->ss_short_report) || nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY, - sconfig->ss_frequency)) { - kfree_skb(skb); - return -EINVAL; - } + sconfig->ss_frequency)) + goto fail; sscan_req.ss_mode = sscan_mode; sscan_req.req_id = SPECTRAL_GET_DEBUG_LEVEL; @@ -468,13 +654,14 @@ int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy, spectral_dbg_level = sscan_req.debug_req.spectral_dbg_level; if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL, - spectral_dbg_level)) { - kfree_skb(skb); - return -EINVAL; - } - qal_devcfg_send_response((qdf_nbuf_t)skb); + spectral_dbg_level)) + goto fail; + wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); return 0; +fail: + wlan_cfg80211_vendor_free_skb(skb); + return -EINVAL; } int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy, @@ -491,11 +678,12 @@ int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy, status = ucfg_spectral_control(pdev, &sscan_req); scaps = &sscan_req.caps_req.sscan_caps; - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (sizeof(u32) + + skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + (sizeof(u32) + NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX + NLMSG_HDRLEN); if (!skb) { - cfg80211_err(" reply skb alloc failed"); + osif_err(" reply skb alloc failed"); return -ENOMEM; } @@ -568,12 +756,31 @@ int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy, if (ret) goto fail; } - qal_devcfg_send_response((qdf_nbuf_t)skb); + + if (scaps->agile_spectral_cap_160) { + int ret; + + ret = nla_put_flag + (skb, + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_160); + if (ret) + goto fail; + } + if (scaps->agile_spectral_cap_80p80) { + int ret; + + ret = nla_put_flag + (skb, + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_80_80); + if (ret) + goto fail; + } + wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); return 0; fail: - kfree_skb(skb); + wlan_cfg80211_vendor_free_skb(skb); return -EINVAL; } @@ -591,11 +798,12 @@ int wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy, status = ucfg_spectral_control(pdev, &sscan_req); spetcral_diag = &sscan_req.diag_req.sscan_diag; - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (sizeof(u64) + - NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_MAX + + skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + (sizeof(u64) + NLA_HDRLEN) * + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_MAX + NLMSG_HDRLEN); if (!skb) { - cfg80211_err(" reply skb alloc failed"); + osif_err(" reply skb alloc failed"); return -ENOMEM; } @@ -619,10 +827,10 @@ int wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy, skb, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH, spetcral_diag->spectral_vhtseg2id_mismatch)) { - kfree_skb(skb); + wlan_cfg80211_vendor_free_skb(skb); return -EINVAL; } - qal_devcfg_send_response((qdf_nbuf_t)skb); + wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); return 0; } @@ -645,7 +853,7 @@ int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy, data, data_len, NULL)) { - cfg80211_err("Invalid Spectral Scan config ATTR"); + osif_err("Invalid Spectral Scan config ATTR"); return -EINVAL; } @@ -668,10 +876,10 @@ int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy, status = ucfg_spectral_control(pdev, &sscan_req); sscan_state.is_enabled = sscan_req.status_req.is_enabled; - skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 2 * (sizeof(u32) + - NLA_HDRLEN) + NLMSG_HDRLEN); + skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + 2 * (sizeof(u32) + NLA_HDRLEN) + NLMSG_HDRLEN); if (!skb) { - cfg80211_err(" reply skb alloc failed"); + osif_err(" reply skb alloc failed"); return -ENOMEM; } @@ -686,10 +894,10 @@ int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy, skb, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE)) goto fail; - qal_devcfg_send_response((qdf_nbuf_t)skb); + wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb); return 0; fail: - kfree_skb(skb); + wlan_cfg80211_vendor_free_skb(skb); return -EINVAL; } diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/wifi_pos/inc/os_if_wifi_pos.h b/drivers/staging/qca-wifi-host-cmn/os_if/linux/wifi_pos/inc/os_if_wifi_pos.h index 26db59415482c9632697510652054b3ed809465e..cc6616d8cfbd05967496bdc295f6cae8c6b7dcec 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/wifi_pos/inc/os_if_wifi_pos.h +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/wifi_pos/inc/os_if_wifi_pos.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, 2020 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 @@ -105,4 +105,182 @@ static inline int os_if_wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, } #endif +#ifdef CNSS_GENL +/** + * enum cld80211_vendor_sub_cmds + * @CLD80211_VENDOR_SUB_CMD_INVALID: invalid cmd type + * @CLD80211_VENDOR_SUB_CMD_REGISTRATION: app registration + * @CLD80211_VENDOR_SUB_CMD_SET_CAPS: set driver capabilities + * @CLD80211_VENDOR_SUB_CMD_GET_CAPS: get driver capabilities + * @CLD80211_VENDOR_SUB_CMD_GET_CH_INFO: get channel info + * @CLD80211_VENDOR_SUB_CMD_OEM_DATA: oem data req/rsp + * @CLD80211_VENDOR_SUB_CMD_OEM_ERROR: oem error rsp + * @CLD80211_VENDOR_SUB_CMD_PEER_STATUS_IND: peer status indication + * @CLD80211_VENDOR_SUB_CMD_MAX: Max cld80211 vendor sub cmds + */ +enum cld80211_vendor_sub_cmds { + CLD80211_VENDOR_SUB_CMD_INVALID = 0, + CLD80211_VENDOR_SUB_CMD_REGISTRATION = 1, + CLD80211_VENDOR_SUB_CMD_SET_CAPS = 2, + CLD80211_VENDOR_SUB_CMD_GET_CAPS = 3, + CLD80211_VENDOR_SUB_CMD_GET_CH_INFO = 4, + CLD80211_VENDOR_SUB_CMD_OEM_DATA = 5, + CLD80211_VENDOR_SUB_CMD_OEM_ERROR = 6, + CLD80211_VENDOR_SUB_CMD_PEER_STATUS_IND = 7, + /* keep last */ + CLD80211_VENDOR_SUB_CMD__AFTER_LAST, + CLD80211_VENDOR_SUB_CMD_MAX = + CLD80211_VENDOR_SUB_CMD__AFTER_LAST - 1 +}; + +/** + * enum cld80211_sub_attr_cap_rsp - Capability response sub attribute + * @CLD80211_SUB_ATTR_CAPS_INVALID: Invalid capability + * @CLD80211_SUB_ATTR_CAPS_OEM_TARGET_SIGNATURE: OEM target signature + * @CLD80211_SUB_ATTR_CAPS_OEM_TARGET_TYPE: OEM target type + * @CLD80211_SUB_ATTR_CAPS_OEM_FW_VERSION: OEM firmware version + * @CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MAJOR: Driver version major + * @CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MINOR: Driver version minor + * @CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_PATCH: Driver version patch + * @CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_BUILD: Driver version build + * @CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MIN: Allowed dwell time min + * @CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MAX: Allowed dwell time max + * @CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MIN: Current dwell time min + * @CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MAX: Current dwell time max + * @CLD80211_SUB_ATTR_CAPS_SUPPORTED_BANDS: Supported bands + * @CLD80211_SUB_ATTR_CAPS_USER_DEFINED_CAPS: User defined capabilities + * @CLD80211_SUB_ATTR_CAPS_MAX: Max number for CAP sub attribute + * + */ +enum cld80211_sub_attr_cap_rsp { + CLD80211_SUB_ATTR_CAPS_INVALID = 0, + CLD80211_SUB_ATTR_CAPS_OEM_TARGET_SIGNATURE = 1, + CLD80211_SUB_ATTR_CAPS_OEM_TARGET_TYPE = 2, + CLD80211_SUB_ATTR_CAPS_OEM_FW_VERSION = 3, + CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MAJOR = 4, + CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MINOR = 5, + CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_PATCH = 6, + CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_BUILD = 7, + CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MIN = 8, + CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MAX = 9, + CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MIN = 10, + CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MAX = 11, + CLD80211_SUB_ATTR_CAPS_SUPPORTED_BANDS = 12, + CLD80211_SUB_ATTR_CAPS_USER_DEFINED_CAPS = 13, + + /* keep last */ + CLD80211_SUB_ATTR_CAPS_AFTER_LAST, + CLD80211_SUB_ATTR_CAPS_MAX = + CLD80211_SUB_ATTR_CAPS_AFTER_LAST - 1 +}; + +/** + * enum cld80211_sub_attr_channel_rsp - Chan info response sub attribute + * @CLD80211_SUB_ATTR_CH_RESP_INVALID: Invalid channel resp + * @CLD80211_SUB_ATTR_CH_MORE_DATA: More date sub attr for frag response + * @CLD80211_SUB_ATTR_CHANNEL_NUM_CHAN: Number of channels in response + * @CLD80211_SUB_ATTR_CHANNEL_LIST: Channel list nesting + * @CLD80211_SUB_ATTR_CH_CHAN_ID: Channel number + * @CLD80211_SUB_ATTR_CH_MHZ: Channel frequency + * @CLD80211_SUB_ATTR_CH_BAND_CF_1: Center frequency 1 + * @CLD80211_SUB_ATTR_CH_BAND_CF_2: Center frequency 2 + * @CLD80211_SUB_ATTR_CH_INFO: channel info + * @CLD80211_SUB_ATTR_CH_REG_INFO_1: regulatory info field 1 + * @CLD80211_SUB_ATTR_CH_REG_INFO_2: regulatory info field 2 + * @CLD80211_SUB_ATTR_CAPS_MAX: Max number for CHAN Info sub attribute + * + */ +enum cld80211_sub_attr_channel_rsp { + CLD80211_SUB_ATTR_CH_RESP_INVALID = 0, + CLD80211_SUB_ATTR_CH_MORE_DATA = 1, + CLD80211_SUB_ATTR_CHANNEL_NUM_CHAN = 2, + CLD80211_SUB_ATTR_CH_LIST = 3, + /* CH_* belongs to CH_LIST */ + CLD80211_SUB_ATTR_CH_CHAN_ID = 4, + CLD80211_SUB_ATTR_CH_MHZ = 5, + CLD80211_SUB_ATTR_CH_BAND_CF_1 = 6, + CLD80211_SUB_ATTR_CH_BAND_CF_2 = 7, + CLD80211_SUB_ATTR_CH_INFO = 8, + CLD80211_SUB_ATTR_CH_REG_INFO_1 = 9, + CLD80211_SUB_ATTR_CH_REG_INFO_2 = 10, + + /* keep last */ + CLD80211_SUB_ATTR_CH_AFTER_LAST, + CLD80211_SUB_ATTR_CH_MAX = + CLD80211_SUB_ATTR_CH_AFTER_LAST - 1 + +}; + +/** + * enum cld80211_sub_attr_oem_data_req - OEM data req sub attribute + * @CLD80211_SUB_ATTR_MSG_OEM_DATA_INVALID: Invalid OEM data request + * @CLD80211_SUB_ATTR_MSG_OEM_DATA_FW: Data to Firmware + * @CLD80211_SUB_ATTR_MSG_OEM_DATA_DRIVER: Data to driver + * @CLD80211_SUB_ATTR_MSG_OEM_DATA_REQ_MAX: Max number for OEM data req sub + * attribute + * + * OEM data request sub attributes are NLA attributes in NLA type OEM data + * request. + * + */ +enum cld80211_sub_attr_oem_data_req { + CLD80211_SUB_ATTR_MSG_OEM_DATA_INVALID = 0, + CLD80211_SUB_ATTR_MSG_OEM_DATA_FW = 1, + CLD80211_SUB_ATTR_MSG_OEM_DATA_DRIVER = 2, + + /* keep last */ + CLD80211_SUB_ATTR_MSG_OEM_DATA_REQ_AFTER_LAST, + CLD80211_SUB_ATTR_MSG_OEM_DATA_REQ_MAX = + CLD80211_SUB_ATTR_MSG_OEM_DATA_REQ_AFTER_LAST - 1 +}; + +/** + * enum cld80211_sub_attr_oem_data_resp - OEM message sub attribute + * @CLD80211_SUB_ATTR_OEM_DATA_INVALID: Invalid oem data resp + * @CLD80211_SUB_ATTR_OEM_MORE_DATA: more date sub attribute + * @CLD80211_SUB_ATTR_BINARY_DATA: Binary data sub attribute + * @CLD80211_SUB_ATTR_OEM_DATA_RESP_MAX: Max number for OEM data resp + * sub attribute + * + * OEM message sub attributes are interface between apps and driver to + * process NLA type request and response messages. + * + */ +enum cld80211_sub_attr_oem_data_resp { + CLD80211_SUB_ATTR_OEM_DATA_INVALID = 0, + CLD80211_SUB_ATTR_OEM_MORE_DATA = 1, + CLD80211_SUB_ATTR_BINARY_DATA = 2, + + /* keep last */ + CLD80211_SUB_ATTR_OEM_DATA_RESP_AFTER_LAST, + CLD80211_SUB_ATTR_OEM_DATA_RESP_MAX = + CLD80211_SUB_ATTR_OEM_DATA_RESP_AFTER_LAST - 1 +}; + +/** + * enum cld80211_sub_attr_peer_info - peer info sub attribute + * @CLD80211_SUB_ATTR_PEER_INVALID: Invalid peer info + * @CLD80211_SUB_ATTR_PEER_MAC_ADDR: peer mac address + * @CLD80211_SUB_ATTR_PEER_STATUS: peer status + * @CLD80211_SUB_ATTR_PEER_VDEV_ID: peer vdevid + * @CLD80211_SUB_ATTR_PEER_CAPABILITY: peer capabilities + * @CLD80211_SUB_ATTR_PEER_RESERVED: reserved bytes + * @CLD80211_SUB_ATTR_PEER_CHAN_INFO: peer channel info + * + */ +enum cld80211_sub_attr_peer_info { + CLD80211_SUB_ATTR_PEER_INVALID = 0, + CLD80211_SUB_ATTR_PEER_MAC_ADDR = 1, + CLD80211_SUB_ATTR_PEER_STATUS = 2, + CLD80211_SUB_ATTR_PEER_VDEV_ID = 3, + CLD80211_SUB_ATTR_PEER_CAPABILITY = 4, + CLD80211_SUB_ATTR_PEER_RESERVED = 5, + CLD80211_SUB_ATTR_PEER_CHAN_INFO = 6, + + /* keep last */ + CLD80211_SUB_ATTR_PEER_AFTER_LAST, + CLD80211_SUB_ATTR_PEER_MAX = + CLD80211_SUB_ATTR_PEER_AFTER_LAST - 1 +}; +#endif #endif /* _OS_IF_WIFI_POS_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/wifi_pos/src/os_if_wifi_pos.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/wifi_pos/src/os_if_wifi_pos.c index 189b67bd555ad0fae38e09647d49cc13db36aec2..d85a23ce0ca9aa7b05109ec9b45511239b02a741 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/wifi_pos/src/os_if_wifi_pos.c +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/wifi_pos/src/os_if_wifi_pos.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 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 @@ -23,6 +23,7 @@ */ #include "qdf_platform.h" +#include "qdf_module.h" #include "wlan_nlink_srv.h" #include "wlan_ptt_sock_svc.h" #include "wlan_nlink_common.h" @@ -32,6 +33,535 @@ #include "wlan_objmgr_psoc_obj.h" #ifdef CNSS_GENL #include +#include "linux/genetlink.h" +#include "wifi_pos_utils_pub.h" +#endif + +#ifdef CNSS_GENL +#define WLAN_CLD80211_MAX_SIZE SKB_WITH_OVERHEAD(8192UL) + +#define CLD80211_ATTR_CMD 4 +#define CLD80211_ATTR_CMD_TAG_DATA 5 +#define CLD80211_ATTR_MAX 5 + +static const uint32_t +cap_resp_sub_attr_len[CLD80211_SUB_ATTR_CAPS_MAX + 1] = { + [CLD80211_SUB_ATTR_CAPS_OEM_TARGET_SIGNATURE] = + OEM_TARGET_SIGNATURE_LEN, + [CLD80211_SUB_ATTR_CAPS_OEM_TARGET_TYPE] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_CAPS_OEM_FW_VERSION] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MAJOR] = sizeof(uint8_t), + [CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MINOR] = sizeof(uint8_t), + [CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_PATCH] = sizeof(uint8_t), + [CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_BUILD] = sizeof(uint8_t), + [CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MIN] = sizeof(uint16_t), + [CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MAX] = sizeof(uint16_t), + [CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MIN] = sizeof(uint16_t), + [CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MAX] = sizeof(uint16_t), + [CLD80211_SUB_ATTR_CAPS_SUPPORTED_BANDS] = sizeof(uint16_t), + [CLD80211_SUB_ATTR_CAPS_USER_DEFINED_CAPS] = + sizeof(struct wifi_pos_user_defined_caps), +}; + +static const uint32_t +peer_status_sub_attr_len[CLD80211_SUB_ATTR_PEER_MAX + 1] = { + [CLD80211_SUB_ATTR_PEER_MAC_ADDR] = ETH_ALEN, + [CLD80211_SUB_ATTR_PEER_STATUS] = sizeof(uint8_t), + [CLD80211_SUB_ATTR_PEER_VDEV_ID] = sizeof(uint8_t), + [CLD80211_SUB_ATTR_PEER_CAPABILITY] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_PEER_RESERVED] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_PEER_CHAN_INFO] = + sizeof(struct wifi_pos_ch_info_rsp), +}; + +static const uint32_t +ch_resp_sub_attr_len[CLD80211_SUB_ATTR_CH_MAX + 1] = { + [CLD80211_SUB_ATTR_CHANNEL_NUM_CHAN] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_CH_LIST] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_CH_CHAN_ID] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_CH_MHZ] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_CH_BAND_CF_1] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_CH_BAND_CF_2] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_CH_INFO] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_CH_REG_INFO_1] = sizeof(uint32_t), + [CLD80211_SUB_ATTR_CH_REG_INFO_2] = sizeof(uint32_t), +}; +#endif + +static int map_wifi_pos_cmd_to_ani_msg_rsp( + enum wifi_pos_cmd_ids cmd) +{ + switch (cmd) { + case WIFI_POS_CMD_REGISTRATION: + return ANI_MSG_APP_REG_RSP; + case WIFI_POS_CMD_SET_CAPS: + return ANI_MSG_SET_OEM_CAP_RSP; + case WIFI_POS_CMD_GET_CAPS: + return ANI_MSG_GET_OEM_CAP_RSP; + case WIFI_POS_CMD_GET_CH_INFO: + return ANI_MSG_CHANNEL_INFO_RSP; + case WIFI_POS_CMD_OEM_DATA: + return ANI_MSG_OEM_DATA_RSP; + case WIFI_POS_CMD_ERROR: + return ANI_MSG_OEM_ERROR; + case WIFI_POS_PEER_STATUS_IND: + return ANI_MSG_PEER_STATUS_IND; + default: + osif_err("response message is invalid :%d", cmd); + return -EINVAL; + } +} + +static enum wifi_pos_cmd_ids +map_ani_msg_req_to_wifi_pos_cmd(uint32_t cmd) +{ + switch (cmd) { + case ANI_MSG_APP_REG_REQ: + return WIFI_POS_CMD_REGISTRATION; + case ANI_MSG_SET_OEM_CAP_REQ: + return WIFI_POS_CMD_SET_CAPS; + case ANI_MSG_GET_OEM_CAP_REQ: + return WIFI_POS_CMD_GET_CAPS; + case ANI_MSG_CHANNEL_INFO_REQ: + return WIFI_POS_CMD_GET_CH_INFO; + case ANI_MSG_OEM_DATA_REQ: + return WIFI_POS_CMD_OEM_DATA; + default: + osif_err("ani req is invalid :%d", cmd); + return WIFI_POS_CMD_INVALID; + } +} + +#ifdef CNSS_GENL +static enum wifi_pos_cmd_ids +map_cld_vendor_sub_cmd_to_wifi_pos_cmd( + enum cld80211_vendor_sub_cmds cmd) +{ + switch (cmd) { + case CLD80211_VENDOR_SUB_CMD_REGISTRATION: + return WIFI_POS_CMD_REGISTRATION; + case CLD80211_VENDOR_SUB_CMD_SET_CAPS: + return WIFI_POS_CMD_SET_CAPS; + case CLD80211_VENDOR_SUB_CMD_GET_CAPS: + return WIFI_POS_CMD_GET_CAPS; + case CLD80211_VENDOR_SUB_CMD_GET_CH_INFO: + return WIFI_POS_CMD_GET_CH_INFO; + case CLD80211_VENDOR_SUB_CMD_OEM_DATA: + return WIFI_POS_CMD_OEM_DATA; + default: + osif_err("cld vendor subcmd is invalid :%d", cmd); + return WIFI_POS_CMD_INVALID; + } +} + +static enum cld80211_vendor_sub_cmds +map_wifi_pos_cmd_to_cld_vendor_sub_cmd( + enum wifi_pos_cmd_ids cmd) +{ + switch (cmd) { + case WIFI_POS_CMD_REGISTRATION: + return CLD80211_VENDOR_SUB_CMD_REGISTRATION; + case WIFI_POS_CMD_SET_CAPS: + return CLD80211_VENDOR_SUB_CMD_SET_CAPS; + case WIFI_POS_CMD_GET_CAPS: + return CLD80211_VENDOR_SUB_CMD_GET_CAPS; + case WIFI_POS_CMD_GET_CH_INFO: + return CLD80211_VENDOR_SUB_CMD_GET_CH_INFO; + case WIFI_POS_CMD_OEM_DATA: + return CLD80211_VENDOR_SUB_CMD_OEM_DATA; + case WIFI_POS_CMD_ERROR: + return ANI_MSG_OEM_ERROR; + case WIFI_POS_PEER_STATUS_IND: + return ANI_MSG_PEER_STATUS_IND; + default: + osif_err("response message is invalid :%d", cmd); + return CLD80211_VENDOR_SUB_CMD_INVALID; + } +} + +static void os_if_wifi_pos_send_peer_nl_status(uint32_t pid, uint8_t *buf) +{ + void *hdr; + int flags = GFP_KERNEL; + struct sk_buff *msg = NULL; + struct nlattr *nest1, *nest2, *nest3; + struct wifi_pos_peer_status_info *peer_info; + struct wifi_pos_ch_info_rsp *chan_info; + + msg = cld80211_oem_rsp_alloc_skb(pid, &hdr, &nest1, &flags); + if (!msg) { + osif_err("alloc_skb failed"); + return; + } + + peer_info = (struct wifi_pos_peer_status_info *)buf; + chan_info = &peer_info->peer_chan_info; + + nla_put_u32(msg, CLD80211_ATTR_CMD, + CLD80211_VENDOR_SUB_CMD_PEER_STATUS_IND); + nest2 = nla_nest_start(msg, CLD80211_ATTR_CMD_TAG_DATA); + if (!nest2) { + osif_err("nla_nest_start failed"); + dev_kfree_skb(msg); + return; + } + + nla_put(msg, CLD80211_SUB_ATTR_PEER_MAC_ADDR, + ETH_ALEN, peer_info->peer_mac_addr); + nla_put_u8(msg, CLD80211_SUB_ATTR_PEER_STATUS, + peer_info->peer_status); + nla_put_u8(msg, CLD80211_SUB_ATTR_PEER_VDEV_ID, + peer_info->vdev_id); + nla_put_u32(msg, CLD80211_SUB_ATTR_PEER_CAPABILITY, + peer_info->peer_capability); + nla_put_u32(msg, CLD80211_SUB_ATTR_PEER_RESERVED, + peer_info->reserved0); + nest3 = nla_nest_start(msg, CLD80211_SUB_ATTR_PEER_CHAN_INFO); + if (!nest3) { + osif_err("nla_nest_start failed"); + dev_kfree_skb(msg); + return; + } + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_CHAN_ID, + chan_info->chan_id); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_MHZ, chan_info->mhz); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_BAND_CF_1, + chan_info->band_center_freq1); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_BAND_CF_2, + chan_info->band_center_freq2); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_INFO, chan_info->info); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_REG_INFO_1, + chan_info->reg_info_1); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_REG_INFO_2, + chan_info->reg_info_2); + + nla_nest_end(msg, nest3); + nla_nest_end(msg, nest2); + + osif_debug("sending oem rsp: type: %d to pid (%d)", + CLD80211_VENDOR_SUB_CMD_PEER_STATUS_IND, pid); + + cld80211_oem_send_reply(msg, hdr, nest1, flags); +} + +static void os_if_send_cap_nl_resp(uint32_t pid, uint8_t *buf) +{ + void *hdr; + int flags = GFP_KERNEL; + struct sk_buff *msg = NULL; + struct nlattr *nest1, *nest2; + struct wifi_pos_oem_get_cap_rsp *cap_rsp; + + msg = cld80211_oem_rsp_alloc_skb(pid, &hdr, &nest1, &flags); + if (!msg) { + osif_err("alloc_skb failed"); + return; + } + + nla_put_u32(msg, CLD80211_ATTR_CMD, + map_wifi_pos_cmd_to_cld_vendor_sub_cmd(WIFI_POS_CMD_GET_CAPS)); + + cap_rsp = (struct wifi_pos_oem_get_cap_rsp *)(buf); + nest2 = nla_nest_start(msg, CLD80211_ATTR_CMD_TAG_DATA); + + if (!nest2) { + osif_err("nla_nest_start failed"); + dev_kfree_skb(msg); + return; + } + + nla_put(msg, CLD80211_SUB_ATTR_CAPS_OEM_TARGET_SIGNATURE, + OEM_TARGET_SIGNATURE_LEN, OEM_TARGET_SIGNATURE); + nla_put_u32(msg, CLD80211_SUB_ATTR_CAPS_OEM_TARGET_TYPE, + cap_rsp->driver_cap.oem_target_type); + nla_put_u32(msg, CLD80211_SUB_ATTR_CAPS_OEM_FW_VERSION, + cap_rsp->driver_cap.oem_fw_version); + nla_put_u8(msg, CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MAJOR, + cap_rsp->driver_cap.driver_version.major); + nla_put_u8(msg, CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_MINOR, + cap_rsp->driver_cap.driver_version.minor); + nla_put_u8(msg, CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_PATCH, + cap_rsp->driver_cap.driver_version.patch); + nla_put_u8(msg, CLD80211_SUB_ATTR_CAPS_DRIVER_VERSION_BUILD, + cap_rsp->driver_cap.driver_version.build); + nla_put_u16(msg, CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MIN, + cap_rsp->driver_cap.allowed_dwell_time_min); + nla_put_u16(msg, CLD80211_SUB_ATTR_CAPS_ALLOWED_DWELL_TIME_MAX, + cap_rsp->driver_cap.allowed_dwell_time_max); + nla_put_u16(msg, CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MIN, + cap_rsp->driver_cap.curr_dwell_time_min); + nla_put_u16(msg, CLD80211_SUB_ATTR_CAPS_CURRENT_DWELL_TIME_MAX, + cap_rsp->driver_cap.curr_dwell_time_max); + nla_put_u16(msg, CLD80211_SUB_ATTR_CAPS_SUPPORTED_BANDS, + cap_rsp->driver_cap.supported_bands); + nla_put(msg, CLD80211_SUB_ATTR_CAPS_USER_DEFINED_CAPS, + sizeof(struct wifi_pos_user_defined_caps), + &cap_rsp->user_defined_cap); + nla_nest_end(msg, nest2); + + osif_debug("sending oem rsp: type: %d to pid (%d)", + CLD80211_VENDOR_SUB_CMD_GET_CAPS, pid); + + cld80211_oem_send_reply(msg, hdr, nest1, flags); +} + +static void +os_if_get_chan_nl_resp_len(uint32_t *chan_info, uint32_t *attr_headers) +{ + uint32_t i; + struct nlattr more_data; + struct nlattr attr_tag_data; + struct nlattr cld80211_subattr_ch_list; + struct nlattr chan_iter; + + *attr_headers = NLA_ALIGN(sizeof(attr_tag_data)); + *attr_headers += NLA_ALIGN(sizeof(more_data)); + *attr_headers += nla_total_size( + ch_resp_sub_attr_len[CLD80211_SUB_ATTR_CHANNEL_NUM_CHAN]); + *attr_headers += sizeof(cld80211_subattr_ch_list); + + *chan_info = NLA_ALIGN(sizeof(chan_iter)); + i = CLD80211_SUB_ATTR_CH_LIST; + for (; i <= CLD80211_SUB_ATTR_CH_MAX; i++) + *chan_info += nla_total_size(ch_resp_sub_attr_len[i]); +} + +static uint8_t os_if_get_max_chan_nl_resp(uint8_t chan_num) +{ + struct nlattr vendor_data; + struct nlattr attr_cmd; + uint32_t chan_info = 0, attr_headers = 0; + uint32_t chan_info_msg_len, chan_allow = 0; + + os_if_get_chan_nl_resp_len(&chan_info, &attr_headers); + attr_headers += NLA_ALIGN(sizeof(vendor_data)); + attr_headers += NLA_ALIGN(sizeof(attr_cmd)); + + chan_info_msg_len = WLAN_CLD80211_MAX_SIZE; + chan_info_msg_len -= WIFIPOS_RESERVE_BYTES; + chan_info_msg_len -= attr_headers; + + chan_allow = chan_info_msg_len / chan_info; + + if (chan_num > chan_allow) + return chan_allow; + else + return chan_num; +} + +static int +os_if_create_ch_nl_resp(uint32_t pid, uint8_t *buf, uint16_t num_chan, + bool is_frag) +{ + void *hdr; + int i; + int flags = GFP_KERNEL; + struct sk_buff *msg = NULL; + struct nlattr *nest1, *nest2; + struct nlattr *nest3, *nest4; + struct wifi_pos_ch_info_rsp *channel_rsp; + + channel_rsp = (struct wifi_pos_ch_info_rsp *)buf; + + msg = cld80211_oem_rsp_alloc_skb(pid, &hdr, &nest1, &flags); + if (!msg) { + osif_err("alloc_skb failed"); + return -EPERM; + } + + nla_put_u32(msg, CLD80211_ATTR_CMD, + CLD80211_VENDOR_SUB_CMD_GET_CH_INFO); + + nest2 = nla_nest_start(msg, CLD80211_ATTR_CMD_TAG_DATA); + if (!nest2) + goto fail; + + if (is_frag) + nla_put_flag(msg, CLD80211_SUB_ATTR_CH_MORE_DATA); + + nla_put_u32(msg, CLD80211_SUB_ATTR_CHANNEL_NUM_CHAN, num_chan); + + nest3 = nla_nest_start(msg, CLD80211_SUB_ATTR_CH_LIST); + if (!nest3) + goto fail; + for (i = 0; i < num_chan; i++) { + nest4 = nla_nest_start(msg, i); + if (!nest4) + goto fail; + + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_CHAN_ID, + channel_rsp->chan_id); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_MHZ, channel_rsp->mhz); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_BAND_CF_1, + channel_rsp->band_center_freq1); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_BAND_CF_2, + channel_rsp->band_center_freq2); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_INFO, channel_rsp->info); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_REG_INFO_1, + channel_rsp->reg_info_1); + nla_put_u32(msg, CLD80211_SUB_ATTR_CH_REG_INFO_2, + channel_rsp->reg_info_2); + nla_nest_end(msg, nest4); + channel_rsp++; + } + + nla_nest_end(msg, nest3); + nla_nest_end(msg, nest2); + + osif_debug("sending oem rsp: type: %d to pid (%d)", + CLD80211_VENDOR_SUB_CMD_GET_CH_INFO, pid); + + cld80211_oem_send_reply(msg, hdr, nest1, flags); + return 0; + +fail: + osif_err("failed to fill CHAN_RESP attributes"); + dev_kfree_skb(msg); + return -EPERM; +} + +static void os_if_send_chan_nl_resp(uint32_t pid, uint8_t *buf) +{ + int err; + uint8_t check_chans = 0; + uint8_t *chnk_ptr, chan_allow = 0; + bool resp_frag = false; + + check_chans = buf[0]; + chnk_ptr = &buf[1]; + + do { + chan_allow = os_if_get_max_chan_nl_resp(check_chans); + + if (check_chans > chan_allow) + resp_frag = true; + else + resp_frag = false; + check_chans -= chan_allow; + + err = os_if_create_ch_nl_resp(pid, chnk_ptr, + chan_allow, resp_frag); + if (err) { + osif_err("failed to alloc memory for ch_nl_resp"); + return; + } + chnk_ptr += (sizeof(struct wifi_pos_ch_info_rsp) * + chan_allow); + } while (resp_frag); +} + +static int +os_if_create_oemdata_resp(uint32_t pid, uint8_t *buf, bool frag_resp, + uint32_t chnk_len) +{ + void *hdr; + int flags = GFP_KERNEL; + struct sk_buff *msg = NULL; + struct nlattr *nest1, *nest2; + + msg = cld80211_oem_rsp_alloc_skb(pid, &hdr, &nest1, &flags); + if (!msg) { + osif_err("alloc_skb failed"); + return -EPERM; + } + + nla_put_u32(msg, CLD80211_ATTR_CMD, CLD80211_VENDOR_SUB_CMD_OEM_DATA); + + nest2 = nla_nest_start(msg, CLD80211_ATTR_CMD_TAG_DATA); + if (!nest2) + goto fail; + + if (frag_resp) + nla_put_flag(msg, CLD80211_SUB_ATTR_OEM_MORE_DATA); + + nla_put(msg, CLD80211_SUB_ATTR_BINARY_DATA, chnk_len, buf); + + nla_nest_end(msg, nest2); + osif_debug("sending oem rsp: type: %d to pid (%d)", + CLD80211_VENDOR_SUB_CMD_OEM_DATA, pid); + cld80211_oem_send_reply(msg, hdr, nest1, flags); + return 0; + +fail: + osif_err("failed to fill CHAN_RESP attributes"); + dev_kfree_skb(msg); + return -EPERM; +} + +static void +os_if_send_oem_data_nl_resp(uint32_t pid, uint8_t *buf, + uint32_t buf_len) +{ + int err; + uint32_t attr_len; + uint32_t chnk_len, remain_len; + uint8_t *chnk_ptr; + bool frag_resp = false; + + struct nlattr vendor_data; + struct nlattr attr_cmd; + struct nlattr attr_tag_data; + struct nlattr cld80211_subattr_bindata; + struct nlattr more_data; + + attr_len = WIFIPOS_RESERVE_BYTES; + attr_len += NLMSG_ALIGN(sizeof(vendor_data)); + attr_len += NLMSG_ALIGN(sizeof(attr_cmd)); + attr_len += NLMSG_ALIGN(sizeof(attr_tag_data)); + attr_len += NLMSG_ALIGN(sizeof(more_data)); + + chnk_ptr = buf; + chnk_len = buf_len; + remain_len = buf_len; + do { + if (attr_len + nla_total_size(chnk_len) > + WLAN_CLD80211_MAX_SIZE) { + frag_resp = true; + + chnk_len = WLAN_CLD80211_MAX_SIZE - (attr_len + + sizeof(cld80211_subattr_bindata)); + } else { + frag_resp = false; + } + + remain_len -= chnk_len; + + err = os_if_create_oemdata_resp(pid, chnk_ptr, + frag_resp, chnk_len); + if (err) { + osif_err("failed to alloc memory for oem_nl_resp"); + return; + } + chnk_ptr += chnk_len; + chnk_len = remain_len; + } while (frag_resp); +} + +static void os_if_send_nl_resp(uint32_t pid, uint8_t *buf, + enum wifi_pos_cmd_ids cmd, uint32_t len) +{ + switch (cmd) { + case WIFI_POS_CMD_GET_CAPS: + os_if_send_cap_nl_resp(pid, buf); + break; + case WIFI_POS_CMD_GET_CH_INFO: + os_if_send_chan_nl_resp(pid, buf); + break; + case WIFI_POS_CMD_OEM_DATA: + os_if_send_oem_data_nl_resp(pid, buf, len); + break; + case WIFI_POS_PEER_STATUS_IND: + os_if_wifi_pos_send_peer_nl_status(pid, buf); + break; + default: + osif_err("response message is invalid :%d", cmd); + } +} +#else +static void os_if_send_nl_resp(uint32_t pid, uint8_t *buf, + enum wifi_pos_cmd_ids cmd, uint32_t len) +{ +} #endif /** @@ -41,74 +571,139 @@ * * Return: none */ -static void os_if_wifi_pos_send_rsp(uint32_t pid, uint32_t rsp_msg_type, +static void os_if_wifi_pos_send_rsp(uint32_t pid, enum wifi_pos_cmd_ids cmd, uint32_t buf_len, uint8_t *buf) { tAniMsgHdr *aniHdr; - struct sk_buff *skb; + struct sk_buff *skb = NULL; struct nlmsghdr *nlh; + struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc(); /* OEM msg is always to a specific process and cannot be a broadcast */ if (pid == 0) { - cfg80211_err("invalid dest pid"); + osif_err("invalid dest pid"); return; } - skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + buf_len), GFP_ATOMIC); - if (!skb) { - cfg80211_alert("alloc_skb failed"); - return; + if (ucfg_wifi_pos_is_nl_rsp(psoc)) { + os_if_send_nl_resp(pid, buf, cmd, buf_len); + } else { + skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + buf_len), + GFP_ATOMIC); + if (!skb) { + osif_alert("alloc_skb failed"); + return; + } + + nlh = (struct nlmsghdr *)skb->data; + nlh->nlmsg_pid = 0; /* from kernel */ + nlh->nlmsg_flags = 0; + nlh->nlmsg_seq = 0; + nlh->nlmsg_type = WLAN_NL_MSG_OEM; + nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + buf_len); + + aniHdr = NLMSG_DATA(nlh); + aniHdr->type = map_wifi_pos_cmd_to_ani_msg_rsp(cmd); + qdf_mem_copy(&aniHdr[1], buf, buf_len); + aniHdr->length = buf_len; + + skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + buf_len)); + osif_debug("sending oem rsp: type: %d len(%d) to pid (%d)", + aniHdr->type, buf_len, pid); + nl_srv_ucast_oem(skb, pid, MSG_DONTWAIT); } - - nlh = (struct nlmsghdr *)skb->data; - nlh->nlmsg_pid = 0; /* from kernel */ - nlh->nlmsg_flags = 0; - nlh->nlmsg_seq = 0; - nlh->nlmsg_type = WLAN_NL_MSG_OEM; - nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + buf_len); - - aniHdr = NLMSG_DATA(nlh); - aniHdr->type = rsp_msg_type; - qdf_mem_copy(&aniHdr[1], buf, buf_len); - aniHdr->length = buf_len; - - skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + buf_len)); - cfg80211_debug("sending oem rsp: type: %d len(%d) to pid (%d)", - rsp_msg_type, buf_len, pid); - nl_srv_ucast_oem(skb, pid, MSG_DONTWAIT); } #ifdef CNSS_GENL -static int wifi_pos_parse_req(const void *data, int len, int pid, +static int +wifi_pos_parse_nla_oemdata_req(uint32_t len, uint8_t *buf, + struct wifi_pos_req_msg *req) +{ + struct nlattr *tb_oem_data[CLD80211_SUB_ATTR_MSG_OEM_DATA_REQ_MAX + 1]; + + if (wlan_cfg80211_nla_parse(tb_oem_data, + CLD80211_SUB_ATTR_MSG_OEM_DATA_REQ_MAX, + (struct nlattr *)buf, len, NULL)) { + osif_err("invalid data in request"); + return OEM_ERR_INVALID_MESSAGE_TYPE; + } + + if (!tb_oem_data[CLD80211_SUB_ATTR_MSG_OEM_DATA_FW]) { + osif_err("CLD80211_SUB_ATTR_MSG_OEM_DATA_FW not present"); + return OEM_ERR_INVALID_MESSAGE_TYPE; + } + req->buf_len = nla_len( + tb_oem_data[CLD80211_SUB_ATTR_MSG_OEM_DATA_FW]); + req->buf = nla_data( + tb_oem_data[CLD80211_SUB_ATTR_MSG_OEM_DATA_FW]); + + return 0; +} + +static int wifi_pos_parse_nla_req(const void *data, int len, int pid, struct wifi_pos_req_msg *req) { - tAniMsgHdr *msg_hdr; + uint8_t *msg; struct nlattr *tb[CLD80211_ATTR_MAX + 1]; - uint32_t msg_len, id, nl_field_info_size, expected_field_info_size; - struct wifi_pos_field_info *field_info; + uint32_t msg_len; if (wlan_cfg80211_nla_parse(tb, CLD80211_ATTR_MAX, data, len, NULL)) { - cfg80211_err("invalid data in request"); + osif_err("invalid data in request"); return OEM_ERR_INVALID_MESSAGE_TYPE; } - if (!tb[CLD80211_ATTR_DATA]) { - cfg80211_err("CLD80211_ATTR_DATA not present"); + req->pid = pid; + req->msg_type = map_cld_vendor_sub_cmd_to_wifi_pos_cmd( + nla_get_u32(tb[CLD80211_ATTR_CMD])); + req->rsp_version = WIFI_POS_RSP_V2_NL; + + if (tb[CLD80211_ATTR_CMD_TAG_DATA]) { + msg_len = nla_len(tb[CLD80211_ATTR_CMD_TAG_DATA]); + msg = nla_data(tb[CLD80211_ATTR_CMD_TAG_DATA]); + + if (req->msg_type == WIFI_POS_CMD_OEM_DATA) { + if (wifi_pos_parse_nla_oemdata_req(msg_len, msg, req)) { + osif_err("parsing oemdata req failed"); + return OEM_ERR_INVALID_MESSAGE_LENGTH; + } + } else { + req->buf_len = msg_len; + req->buf = msg; + } + } + if (tb[CLD80211_ATTR_META_DATA]) + osif_err("meta data dropped. Apps can use CLD80211_ATTR_CMD_TAG_DATA sub attrs"); + + return 0; +} + +static int wifi_pos_parse_ani_req(const void *data, int len, int pid, + struct wifi_pos_req_msg *req) +{ + tAniMsgHdr *msg_hdr; + struct nlattr *tb[CLD80211_ATTR_MAX + 1]; + uint32_t msg_len, id, nl_field_info_size, expected_field_info_size; + struct wifi_pos_field_info *field_info; + + if (wlan_cfg80211_nla_parse(tb, CLD80211_ATTR_MAX, data, len, NULL)) { + osif_err("invalid data in request"); return OEM_ERR_INVALID_MESSAGE_TYPE; } msg_len = nla_len(tb[CLD80211_ATTR_DATA]); if (msg_len < sizeof(*msg_hdr)) { - cfg80211_err("Insufficient length for msg_hdr: %u", msg_len); + osif_err("Insufficient length for msg_hdr: %u", msg_len); return OEM_ERR_INVALID_MESSAGE_LENGTH; } msg_hdr = nla_data(tb[CLD80211_ATTR_DATA]); - req->msg_type = msg_hdr->type; + req->msg_type = map_ani_msg_req_to_wifi_pos_cmd( + (uint32_t)msg_hdr->type); + req->rsp_version = WIFI_POS_RSP_V1_FLAT_MEMORY; if (msg_len < sizeof(*msg_hdr) + msg_hdr->length) { - cfg80211_err("Insufficient length for msg_hdr buffer: %u", - msg_len); + osif_err("Insufficient length for msg_hdr buffer: %u", + msg_len); return OEM_ERR_INVALID_MESSAGE_LENGTH; } @@ -122,14 +717,14 @@ static int wifi_pos_parse_req(const void *data, int len, int pid, nl_field_info_size = nla_len(tb[id]); if (nl_field_info_size < sizeof(*field_info)) { - cfg80211_err("Insufficient length for field_info_buf: %u", - nl_field_info_size); + osif_err("Insufficient length for field_info_buf: %u", + nl_field_info_size); return OEM_ERR_INVALID_MESSAGE_LENGTH; } field_info = nla_data(tb[id]); if (!field_info->count) { - cfg80211_debug("field_info->count is zero, ignoring META_DATA"); + osif_debug("field_info->count is zero, ignoring META_DATA"); return 0; } @@ -137,8 +732,8 @@ static int wifi_pos_parse_req(const void *data, int len, int pid, (field_info->count - 1) * sizeof(struct wifi_pos_field); if (nl_field_info_size < expected_field_info_size) { - cfg80211_err("Insufficient len for total no.of %u fields", - field_info->count); + osif_err("Insufficient len for total no.of %u fields", + field_info->count); return OEM_ERR_INVALID_MESSAGE_LENGTH; } @@ -147,6 +742,29 @@ static int wifi_pos_parse_req(const void *data, int len, int pid, return 0; } + + +static int wifi_pos_parse_req(const void *data, int len, int pid, + struct wifi_pos_req_msg *req) +{ + int status = 0; + struct nlattr *tb[CLD80211_ATTR_MAX + 1]; + + if (wlan_cfg80211_nla_parse(tb, CLD80211_ATTR_MAX, data, len, NULL)) { + osif_err("invalid data in request"); + return OEM_ERR_INVALID_MESSAGE_TYPE; + } + + if (tb[CLD80211_ATTR_DATA]) { + status = wifi_pos_parse_ani_req(data, len, pid, req); + } else if (tb[CLD80211_ATTR_CMD]) { + status = wifi_pos_parse_nla_req(data, len, pid, req); + } else { + osif_err("Valid CLD80211 ATTR not present"); + return OEM_ERR_INVALID_MESSAGE_TYPE; + } + return status; +} #else static int wifi_pos_parse_req(struct sk_buff *skb, struct wifi_pos_req_msg *req) { @@ -154,35 +772,47 @@ static int wifi_pos_parse_req(struct sk_buff *skb, struct wifi_pos_req_msg *req) /* NLMSG_DATA(nlh) contains ANI msg */ struct nlmsghdr *nlh; tAniMsgHdr *msg_hdr; + size_t field_info_len; nlh = (struct nlmsghdr *)skb->data; if (!nlh) { - cfg80211_err("Netlink header null"); + osif_err("Netlink header null"); return OEM_ERR_NULL_MESSAGE_HEADER; } if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*msg_hdr))) { - cfg80211_err("nlmsg_len(%d) and msg_hdr_size(%zu) mis-match", - nlh->nlmsg_len, sizeof(*msg_hdr)); + osif_err("nlmsg_len(%d) and msg_hdr_size(%zu) mis-match", + nlh->nlmsg_len, sizeof(*msg_hdr)); return OEM_ERR_INVALID_MESSAGE_LENGTH; } msg_hdr = NLMSG_DATA(nlh); if (!msg_hdr) { - cfg80211_err("Message header null"); + osif_err("Message header null"); return OEM_ERR_NULL_MESSAGE_HEADER; } if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*msg_hdr) + msg_hdr->length)) { - cfg80211_err("nlmsg_len(%d) and animsg_len(%d) mis-match", - nlh->nlmsg_len, msg_hdr->length); + osif_err("nlmsg_len(%d) and animsg_len(%d) mis-match", + nlh->nlmsg_len, msg_hdr->length); return OEM_ERR_INVALID_MESSAGE_LENGTH; } - req->msg_type = msg_hdr->type; + req->msg_type = map_ani_msg_req_to_wifi_pos_cmd( + (uint32_t)msg_hdr->type); + req->rsp_version = WIFI_POS_RSP_V1_FLAT_MEMORY; req->buf_len = msg_hdr->length; req->buf = (uint8_t *)&msg_hdr[1]; req->pid = nlh->nlmsg_pid; + req->field_info_buf = NULL; + + field_info_len = nlh->nlmsg_len - + (NLMSG_LENGTH(sizeof(*msg_hdr) + msg_hdr->length)); + if (field_info_len) { + req->field_info_buf = (struct wifi_pos_field_info *) + (req->buf + req->buf_len); + req->field_info_buf_len = field_info_len; + } return 0; } @@ -204,9 +834,9 @@ static void __os_if_wifi_pos_callback(const void *data, int data_len, struct wifi_pos_req_msg req = {0}; struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc(); - cfg80211_debug("enter: pid %d", pid); + osif_debug("enter: pid %d", pid); if (!psoc) { - cfg80211_err("global psoc object not registered yet."); + osif_err("global psoc object not registered yet."); return; } @@ -214,15 +844,15 @@ static void __os_if_wifi_pos_callback(const void *data, int data_len, err = wifi_pos_parse_req(data, data_len, pid, &req); if (err) { os_if_wifi_pos_send_rsp(wifi_pos_get_app_pid(psoc), - ANI_MSG_OEM_ERROR, sizeof(err), &err); + WIFI_POS_CMD_ERROR, sizeof(err), &err); status = QDF_STATUS_E_INVAL; goto release_psoc_ref; } status = ucfg_wifi_pos_process_req(psoc, &req, os_if_wifi_pos_send_rsp); if (QDF_IS_STATUS_ERROR(status)) - cfg80211_err("ucfg_wifi_pos_process_req failed. status: %d", - status); + osif_err("ucfg_wifi_pos_process_req failed. status: %d", + status); release_psoc_ref: wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_OSIF_ID); @@ -247,9 +877,9 @@ static int __os_if_wifi_pos_callback(struct sk_buff *skb) struct wifi_pos_req_msg req = {0}; struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc(); - cfg80211_debug("enter"); + osif_debug("enter"); if (!psoc) { - cfg80211_err("global psoc object not registered yet."); + osif_err("global psoc object not registered yet."); return -EINVAL; } @@ -257,15 +887,15 @@ static int __os_if_wifi_pos_callback(struct sk_buff *skb) err = wifi_pos_parse_req(skb, &req); if (err) { os_if_wifi_pos_send_rsp(wifi_pos_get_app_pid(psoc), - ANI_MSG_OEM_ERROR, sizeof(err), &err); + WIFI_POS_CMD_ERROR, sizeof(err), &err); status = QDF_STATUS_E_INVAL; goto release_psoc_ref; } status = ucfg_wifi_pos_process_req(psoc, &req, os_if_wifi_pos_send_rsp); if (QDF_IS_STATUS_ERROR(status)) - cfg80211_err("ucfg_wifi_pos_process_req failed. status: %d", - status); + osif_err("ucfg_wifi_pos_process_req failed. status: %d", + status); release_psoc_ref: wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_OSIF_ID); @@ -294,7 +924,7 @@ int os_if_wifi_pos_register_nl(void) int ret = register_cld_cmd_cb(WLAN_NL_MSG_OEM, os_if_wifi_pos_callback, NULL); if (ret) - cfg80211_err("register_cld_cmd_cb failed"); + osif_err("register_cld_cmd_cb failed"); return ret; } @@ -304,13 +934,14 @@ int os_if_wifi_pos_register_nl(void) return nl_srv_register(WLAN_NL_MSG_OEM, os_if_wifi_pos_callback); } #endif /* CNSS_GENL */ +qdf_export_symbol(os_if_wifi_pos_register_nl); #ifdef CNSS_GENL int os_if_wifi_pos_deregister_nl(void) { int ret = deregister_cld_cmd_cb(WLAN_NL_MSG_OEM); if (ret) - cfg80211_err("deregister_cld_cmd_cb failed"); + osif_err("deregister_cld_cmd_cb failed"); return ret; } @@ -329,16 +960,16 @@ void os_if_wifi_pos_send_peer_status(struct qdf_mac_addr *peer_mac, enum QDF_OPMODE dev_mode) { struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc(); - struct wmi_pos_peer_status_info *peer_info; + struct wifi_pos_peer_status_info *peer_info; if (!psoc) { - cfg80211_err("global wifi_pos psoc object not registered"); + osif_err("global wifi_pos psoc object not registered"); return; } if (!wifi_pos_is_app_registered(psoc) || wifi_pos_get_app_pid(psoc) == 0) { - cfg80211_debug("app is not registered or pid is invalid"); + osif_debug("app is not registered or pid is invalid"); return; } @@ -370,7 +1001,7 @@ void os_if_wifi_pos_send_peer_status(struct qdf_mac_addr *peer_mac, } os_if_wifi_pos_send_rsp(wifi_pos_get_app_pid(psoc), - ANI_MSG_PEER_STATUS_IND, + WIFI_POS_PEER_STATUS_IND, sizeof(*peer_info), (uint8_t *)peer_info); qdf_mem_free(peer_info); } @@ -379,7 +1010,7 @@ int os_if_wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, struct wifi_pos_driver_caps *caps) { if (!psoc || !caps) { - cfg80211_err("psoc or caps buffer is null"); + osif_err("psoc or caps buffer is null"); return -EINVAL; } diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/wlan_cfg80211.h b/drivers/staging/qca-wifi-host-cmn/os_if/linux/wlan_cfg80211.h index 4debaa4613fec11f2655a856e16506b30826c3ca..52f21045018d8cf2962b4c8dc9a9adeb22da597f 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/wlan_cfg80211.h +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/wlan_cfg80211.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -29,37 +29,133 @@ #include #include #include +#include +#include "qal_devcfg.h" -#define cfg80211_alert(params...) \ +#define osif_alert(params...) \ QDF_TRACE_FATAL(QDF_MODULE_ID_OS_IF, params) -#define cfg80211_err(params...) \ +#define osif_err(params...) \ QDF_TRACE_ERROR(QDF_MODULE_ID_OS_IF, params) -#define cfg80211_warn(params...) \ +#define osif_warn(params...) \ QDF_TRACE_WARN(QDF_MODULE_ID_OS_IF, params) -#define cfg80211_notice(params...) \ +#define osif_notice(params...) \ QDF_TRACE_INFO(QDF_MODULE_ID_OS_IF, params) -#define cfg80211_info(params...) \ +#define osif_info(params...) \ QDF_TRACE_INFO(QDF_MODULE_ID_OS_IF, params) -#define cfg80211_debug(params...) \ +#define osif_debug(params...) \ QDF_TRACE_DEBUG(QDF_MODULE_ID_OS_IF, params) -#define cfg80211_debug_rl(params...) \ +#define osif_rl_debug(params...) \ QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_OS_IF, params) +#define osif_err_rl(params...) \ + QDF_TRACE_ERROR_RL(QDF_MODULE_ID_OS_IF, params) -#define COMMON_VENDOR_COMMANDS \ -{ \ - .info.vendor_id = OUI_QCA, \ - .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,\ - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | \ - WIPHY_VENDOR_CMD_NEED_NETDEV, \ - .doit = NULL \ -}, \ -{ \ - .info.vendor_id = OUI_QCA, \ - .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION,\ - .flags = WIPHY_VENDOR_CMD_NEED_WDEV | \ - WIPHY_VENDOR_CMD_NEED_NETDEV, \ - .doit = NULL \ -}, +#define osif_nofl_alert(params...) \ + QDF_TRACE_FATAL_NO_FL(QDF_MODULE_ID_OS_IF, params) +#define osif_nofl_err(params...) \ + QDF_TRACE_ERROR_NO_FL(QDF_MODULE_ID_OS_IF, params) +#define osif_nofl_warn(params...) \ + QDF_TRACE_WARN_NO_FL(QDF_MODULE_ID_OS_IF, params) +#define osif_nofl_info(params...) \ + QDF_TRACE_INFO_NO_FL(QDF_MODULE_ID_OS_IF, params) +#define osif_nofl_debug(params...) \ + QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_OS_IF, params) + +/* For kernel version >= 5.2, driver needs to provide policy */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +#define vendor_command_policy(__policy, __maxattr) \ + .policy = __policy, \ + .maxattr = __maxattr +#else +#define vendor_command_policy(__policy, __maxattr) +#endif /*End of (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */ + +#if defined(NBUF_MEMORY_DEBUG) && defined(NETLINK_BUF_TRACK) +#define wlan_cfg80211_vendor_free_skb(skb) \ + qdf_nbuf_free(skb) + +#define wlan_cfg80211_vendor_event(skb, gfp) \ +{ \ + qdf_nbuf_count_dec(skb); \ + qdf_net_buf_debug_release_skb(skb); \ + cfg80211_vendor_event(skb, gfp); \ +} + +#define wlan_cfg80211_vendor_cmd_reply(skb) \ +{ \ + qdf_nbuf_count_dec(skb); \ + qdf_net_buf_debug_release_skb(skb); \ + cfg80211_vendor_cmd_reply(skb); \ +} + +static inline QDF_STATUS wlan_cfg80211_qal_devcfg_send_response(qdf_nbuf_t skb) +{ + qdf_nbuf_count_dec(skb); + qdf_net_buf_debug_release_skb(skb); + return qal_devcfg_send_response(skb); +} + +static inline struct sk_buff * +__cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int len, + const char *func, uint32_t line) +{ + struct sk_buff *skb; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len); + if (skb) { + qdf_nbuf_count_inc(skb); + qdf_net_buf_debug_acquire_skb(skb, func, line); + } + return skb; +} +#define wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \ + __cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len, __func__, __LINE__) + +static inline struct sk_buff * +__cfg80211_vendor_event_alloc(struct wiphy *wiphy, + struct wireless_dev *wdev, + int approxlen, + int event_idx, + gfp_t gfp, + const char *func, + uint32_t line) +{ + struct sk_buff *skb; + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, + approxlen, + event_idx, + gfp); + if (skb) { + qdf_nbuf_count_inc(skb); + qdf_net_buf_debug_acquire_skb(skb, func, line); + } + return skb; +} +#define wlan_cfg80211_vendor_event_alloc(wiphy, wdev, len, idx, gfp) \ + __cfg80211_vendor_event_alloc(wiphy, wdev, len, \ + idx, gfp, \ + __func__, __LINE__) +#else /* NBUF_MEMORY_DEBUG && NETLINK_BUF_TRACK */ +#define wlan_cfg80211_vendor_free_skb(skb) \ + kfree_skb(skb) + +#define wlan_cfg80211_vendor_event(skb, gfp) \ + cfg80211_vendor_event(skb, gfp) + +#define wlan_cfg80211_vendor_cmd_reply(skb) \ + cfg80211_vendor_cmd_reply(skb) + +#define wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \ + cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) + +#define wlan_cfg80211_vendor_event_alloc(wiphy, wdev, len, idx, gfp) \ + cfg80211_vendor_event_alloc(wiphy, wdev, len, idx, gfp) + +static inline QDF_STATUS wlan_cfg80211_qal_devcfg_send_response( qdf_nbuf_t skb) +{ + return qal_devcfg_send_response(skb); +} +#endif /* NBUF_MEMORY_DEBUG && NETLINK_BUF_TRACK */ #undef nla_parse #undef nla_parse_nested @@ -116,5 +212,4 @@ wlan_cfg80211_nla_put_u64(struct sk_buff *skb, int attrtype, u64 value) return nla_put_u64_64bit(skb, attrtype, value, NL80211_ATTR_PAD); } #endif - #endif diff --git a/drivers/staging/qca-wifi-host-cmn/os_if/linux/wlan_osif_request_manager.c b/drivers/staging/qca-wifi-host-cmn/os_if/linux/wlan_osif_request_manager.c index 719200dca01145799e5d5f140358245d6dacdc1a..52cb1a54f1c614a95727dc4ea4aba6d5afa72e3b 100644 --- a/drivers/staging/qca-wifi-host-cmn/os_if/linux/wlan_osif_request_manager.c +++ b/drivers/staging/qca-wifi-host-cmn/os_if/linux/wlan_osif_request_manager.c @@ -83,7 +83,7 @@ struct osif_request *osif_request_alloc(const struct osif_request_params *params struct osif_request *request; if (!is_initialized) { - cfg80211_err("invoked when not initialized"); + osif_err("invoked when not initialized"); return NULL; } @@ -119,7 +119,7 @@ struct osif_request *osif_request_get(void *cookie) struct osif_request *request; if (!is_initialized) { - cfg80211_err("invoked when not initialized"); + osif_err("invoked when not initialized"); return NULL; } qdf_spin_lock_bh(&spinlock); diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/Kbuild b/drivers/staging/qca-wifi-host-cmn/qdf/Kbuild index 0d46466d82cc8d968df7bc8b03e09e27f9438a46..85f1b10faefacab7ec745935bbf14c1e5fee229a 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/Kbuild +++ b/drivers/staging/qca-wifi-host-cmn/qdf/Kbuild @@ -17,6 +17,7 @@ INCS += -Inbuf/linux -Inet/linux -Ios/linux INCS += -I$(WLAN_TOP)/../../include INCS += -I$(WLAN_TOP)/cmn_dev/qdf/inc INCS += -I$(WLAN_TOP)/cmn_dev/qal/inc +INCS += -I$(WLAN_TOP)/cmn_dev/utils/sys INCS += -I$(WLAN_TOP)/component_dev/qal/inc INCS += -I$(WLAN_TOP)/cmn_dev/qal/linux/src INCS += -I$(WLAN_TOP)/cmn_dev/qdf/linux/src diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/i_qdf_nbuf_api_m.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/i_qdf_nbuf_api_m.h index 150e40bb9b9c5ab4cb9c578099afada08073b8d4..da6cbd22693f2d223e042d9c41c670f3215730a3 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/i_qdf_nbuf_api_m.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/i_qdf_nbuf_api_m.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017,2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017,2019-2020 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 @@ -58,20 +58,113 @@ static inline void qdf_nbuf_ipa_priv_set(qdf_nbuf_t buf, uint32_t priv) /** * qdf_nbuf_set_rx_protocol_tag() * @buf: Network buffer - * @val: Value to be set - * Return: void + * @val: Value to be set in the nbuf + * Return: None */ -static inline void qdf_nbuf_set_rx_protocol_tag(qdf_nbuf_t buf, uint32_t val) +static inline void qdf_nbuf_set_rx_protocol_tag(qdf_nbuf_t buf, uint16_t val) { } /** * qdf_nbuf_get_rx_protocol_tag() * @buf: Network buffer - * Return: void + * Return: Value of rx protocol tag, here 0 */ -static inline int qdf_nbuf_get_rx_protocol_tag(qdf_nbuf_t buf) +static inline uint16_t qdf_nbuf_get_rx_protocol_tag(qdf_nbuf_t buf) { return 0; } + +/** + * qdf_nbuf_set_rx_flow_tag() - set given value in flow tag field + * of buf(skb->cb) + * @buf: Network buffer + * @val: Rx Flow Tag to be set in the nbuf + * Return: None + */ +static inline void qdf_nbuf_set_rx_flow_tag(qdf_nbuf_t buf, uint16_t val) +{ +} + +/** + * qdf_nbuf_get_rx_flow_tag() - Get the value of flow_tag + * field of buf(skb->cb) + * @buf: Network buffer + * Return: Value of rx flow tag, here 0 + */ +static inline uint16_t qdf_nbuf_get_rx_flow_tag(qdf_nbuf_t buf) +{ + return 0; +} + +/** + * qdf_nbuf_set_exc_frame() - set exception frame flag + * @buf: Network buffer whose cb is to set exception frame flag + * @value: exception frame flag, value 0 or 1. + * + * Return: none + */ +static inline void qdf_nbuf_set_exc_frame(qdf_nbuf_t buf, uint8_t value) +{ + QDF_NBUF_CB_RX_PACKET_EXC_FRAME(buf) = value; +} + +/** + * qdf_nbuf_is_exc_frame() - check exception frame flag bit + * @buf: Network buffer to get exception flag + * + * Return: 0 or 1 + */ +static inline uint8_t qdf_nbuf_is_exc_frame(qdf_nbuf_t buf) +{ + return QDF_NBUF_CB_RX_PACKET_EXC_FRAME(buf); +} + +/** + * qdf_nbuf_set_rx_reo_dest_ind() - set reo destination indication + * @buf: Network buffer + * @value: reo destination indication value to set + * + * Return: none + */ +static inline void qdf_nbuf_set_rx_reo_dest_ind(qdf_nbuf_t buf, + uint8_t value) +{ + QDF_NBUF_CB_RX_PACKET_REO_DEST_IND(buf) = value; +} + +/** + * qdf_nbuf_get_rx_reo_dest_ind() - get reo destination indication + * @buf: Network buffer + * + * Return reo destination indication value (0 ~ 31) + */ +static inline uint8_t qdf_nbuf_get_rx_reo_dest_ind(qdf_nbuf_t buf) +{ + return QDF_NBUF_CB_RX_PACKET_REO_DEST_IND(buf); +} + +/** + * qdf_nbuf_set_rx_ipa_smmu_map() - set ipa smmu mapped flag + * @buf: Network buffer + * @value: 1 - ipa smmu mapped, 0 - ipa smmu unmapped + * + * Return: none + */ +static inline void qdf_nbuf_set_rx_ipa_smmu_map(qdf_nbuf_t buf, + uint8_t value) +{ + QDF_NBUF_CB_RX_PACKET_IPA_SMMU_MAP(buf) = value; +} + +/** + * qdf_nbuf_is_rx_ipa_smmu_map() - check ipa smmu map flag + * @buf: Network buffer + * + * Return 0 or 1 + */ +static inline uint8_t qdf_nbuf_is_rx_ipa_smmu_map(qdf_nbuf_t buf) +{ + return QDF_NBUF_CB_RX_PACKET_IPA_SMMU_MAP(buf); +} #endif /* _QDF_NBUF_M_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/i_qdf_nbuf_api_w.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/i_qdf_nbuf_api_w.h index b9ce5e005d7027503e06d9555cb52b11bd77dd04..04be21b63cd20072187132eea60b4b05ac6de586 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/i_qdf_nbuf_api_w.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/i_qdf_nbuf_api_w.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017,2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017,2019-2020 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 @@ -68,10 +68,10 @@ qdf_nbuf_set_ext_cb(qdf_nbuf_t buf, void *ref) * qdf_nbuf_set_rx_protocol_tag() - set given value in protocol_tag * field of buf(skb->cb) * @buf: Network buffer - * @val: Value to be set - * Return: void + * @val: Value to be set in the nbuf + * Return: None */ -static inline void qdf_nbuf_set_rx_protocol_tag(qdf_nbuf_t buf, uint32_t val) +static inline void qdf_nbuf_set_rx_protocol_tag(qdf_nbuf_t buf, uint16_t val) { __qdf_nbuf_set_rx_protocol_tag(buf, val); } @@ -80,10 +80,79 @@ static inline void qdf_nbuf_set_rx_protocol_tag(qdf_nbuf_t buf, uint32_t val) * qdf_nbuf_get_rx_protocol_tag() - Get the value of protocol_tag * field of buf(skb->cb) * @buf: Network buffer - * Return: void + * Return: Value of Rx protocol tag in the nbuf */ -static inline int qdf_nbuf_get_rx_protocol_tag(qdf_nbuf_t buf) +static inline uint16_t qdf_nbuf_get_rx_protocol_tag(qdf_nbuf_t buf) { return __qdf_nbuf_get_rx_protocol_tag(buf); } + +/** + * qdf_nbuf_set_rx_flow_tag() - set given value in flow tag field + * of buf(skb->cb) + * @buf: Network buffer + * @val: Value of Rx flow tag to be set in the nbuf + * Return: None + */ +static inline void qdf_nbuf_set_rx_flow_tag(qdf_nbuf_t buf, uint16_t val) +{ + __qdf_nbuf_set_rx_flow_tag(buf, val); +} + +/** + * qdf_nbuf_get_rx_flow_tag() - Get the value of flow_tag + * field of buf(skb->cb) + * @buf: Network buffer + * Return: Value of the Rx flow tag in the nbuf + */ +static inline uint16_t qdf_nbuf_get_rx_flow_tag(qdf_nbuf_t buf) +{ + return __qdf_nbuf_get_rx_flow_tag(buf); +} + +/** + * qdf_nbuf_set_exc_frame() - set exception frame flag + * @buf: Network buffer whose cb is to set exception frame flag + * @value: exception frame flag, value 0 or 1. + * + * Return: none + */ +static inline void qdf_nbuf_set_exc_frame(qdf_nbuf_t buf, uint8_t value) +{ +} + +/** + * qdf_nbuf_set_rx_reo_dest_ind() - set reo destination indication + * @buf: Network buffer + * @value: reo destination indication value to set + * + * Return: none + */ +static inline void qdf_nbuf_set_rx_reo_dest_ind(qdf_nbuf_t buf, + uint8_t value) +{ +} + +/** +* qdf_nbuf_set_rx_ipa_smmu_map() - set ipa smmu mapped flag + * @buf: Network buffer + * @value: 1 - ipa smmu mapped, 0 - ipa smmu unmapped + * + * Return: none + */ +static inline void qdf_nbuf_set_rx_ipa_smmu_map(qdf_nbuf_t buf, + uint8_t value) +{ +} + +/** + * qdf_nbuf_is_rx_ipa_smmu_map() - check ipa smmu map flag + * @buf: Network buffer + * + * Return 0 or 1 + */ +static inline uint8_t qdf_nbuf_is_rx_ipa_smmu_map(qdf_nbuf_t buf) +{ + return 0; +} #endif /* _QDF_NBUF_W_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_atomic.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_atomic.h index 57f66d3ead37f1642f558f8f25a09cef6a95f4e3..3b888c388f32a9e1d130787c897cb49061e234ff 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_atomic.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_atomic.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -154,6 +154,17 @@ static inline int32_t qdf_atomic_dec_return(qdf_atomic_t *v) return __qdf_atomic_dec_return(v); } +/** + * qdf_atomic_inc_not_zero() - increment if not zero + * @v: A pointer to an opaque atomic variable + * + * Return: Returns non-zero on successful increment and zero otherwise + */ +static inline int32_t qdf_atomic_inc_not_zero(qdf_atomic_t *v) +{ + return __qdf_atomic_inc_not_zero(v); +} + /** * qdf_atomic_set_bit - Atomically set a bit in memory * @nr: bit to set diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_debugfs.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_debugfs.h index 62200b30fdaec8c6365c5a91d18ebf00c8981911..46dc3a945a5ae2cc89d24747966a4965c3fd4f59 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_debugfs.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_debugfs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 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 @@ -240,6 +240,43 @@ void qdf_debugfs_remove_dir(qdf_dentry_t d); */ void qdf_debugfs_remove_file(qdf_dentry_t d); +/** + * qdf_debugfs_create_file_simplified() - Create a simple debugfs file + * where a single function call produces all the desired output + * @name: name of the file + * @mode: qdf file mode + * @parent: parent node. If NULL, defaults to base 'qdf_debugfs_root' + * @fops: file operations { .show, .write , .priv... } + * + * Users just have to define the show() function and pass it via @fops.show() + * argument. When the output time comes, the show() will be called once. + * The show() function must do everything that is needed to write the data, + * all in one function call. + * This is useful either for writing small amounts of data to debugfs or + * for cases in which the output is not iterative. + * The private data can be passed via @fops.priv, which will be available + * inside the show() function as the 'private' filed of the qdf_debugfs_file_t. + * + * Return: dentry structure pointer in case of success, otherwise NULL. + * + */ + +qdf_dentry_t qdf_debugfs_create_file_simplified(const char *name, uint16_t mode, + qdf_dentry_t parent, + struct qdf_debugfs_fops *fops); + +/** + * qdf_debugfs_printer() - Print formated string into debugfs file + * @priv: The private data + * @fmt: Format string + * @...: arguments for the format string + * + * This function prints a new line character after printing the formatted + * string into the debugfs file. + * This function can be passed when the argument is of type qdf_abstract_print + */ +int qdf_debugfs_printer(void *priv, const char *fmt, ...); + #else /* WLAN_DEBUGFS */ static inline QDF_STATUS qdf_debugfs_init(void) @@ -333,5 +370,18 @@ static inline void qdf_debugfs_remove_dir_recursive(qdf_dentry_t d) {} static inline void qdf_debugfs_remove_dir(qdf_dentry_t d) {} static inline void qdf_debugfs_remove_file(qdf_dentry_t d) {} +static inline +qdf_dentry_t qdf_debugfs_create_file_simplified(const char *name, uint16_t mode, + qdf_dentry_t parent, + struct qdf_debugfs_fops *fops) +{ + return NULL; +} + +static inline +int qdf_debugfs_printer(void *priv, const char *fmt, ...) +{ + return 0; +} #endif /* WLAN_DEBUGFS */ #endif /* _QDF_DEBUGFS_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_hang_event_notifier.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_hang_event_notifier.h new file mode 100644 index 0000000000000000000000000000000000000000..532ea47ca0e2e20a0bb5df111b0871ba2dbdacea --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_hang_event_notifier.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + /** + * DOC: qdf_hang_event_notifier + * This file provides OS dependent QDF notifier call for hang event + */ + +#ifndef QDF_HANG_EVENT_NOTIFIER_H +#define QDF_HANG_EVENT_NOTIFIER_H + +#include + +#define QDF_HANG_EVENT_VERSION "1" +/* Max hang event buffer size */ +#define QDF_HANG_EVENT_DATA_SIZE 390 +/* Max offset which host can write */ +#define QDF_WLAN_MAX_HOST_OFFSET 194 +/* Start of the Firmware Data offset */ +#define QDF_WLAN_HANG_FW_OFFSET 195 + +/** + * hang_event_tag: Hang event tag for various modules + * @HANG_EVT_TAG_CDS: CDS module hang event tag + * @HANG_EVT_TAG_OS_IF: OS interface module hang event tag + * @HANG_EVT_TAG_OS_IF_SCAN: scan module hang event tag + * @HANG_EVT_TAG_LEGACY_MAC: Legacy mac module hang event tag + * @HANG_EVT_TAG_WMI_EVT_HIST: WMI event history hang event tag + * @HANG_EVT_TAG_WMI_CMD_HIST: WMI command history hang event tag + * @HANG_EVT_TAG_WMI_CMD_HIST: HTC event tag wmi command history hang event tag + * @HANG_EVT_TAG_DP_PEER_INFO: DP peer info hang event tag + * @HANG_EVT_TAG_CE_INFO: Copy Engine hang event tag + * @HANG_EVT_TAG_BUS_INFO: Bus hang event tag + */ +enum hang_event_tag { + HANG_EVT_TAG_CDS, + HANG_EVT_TAG_OS_IF, + HANG_EVT_TAG_OS_IF_SCAN, + HANG_EVT_TAG_LEGACY_MAC, + HANG_EVT_TAG_WMI_EVT_HIST, + HANG_EVT_TAG_WMI_CMD_HIST, + HANG_EVT_TAG_HTC_CREDIT_HIST, + HANG_EVT_TAG_DP_PEER_INFO, + HANG_EVT_TAG_CE_INFO, + HANG_EVT_TAG_BUS_INFO +}; + +#define QDF_HANG_EVENT_TLV_HDR_SIZE (sizeof(uint16_t)) + +#define QDF_HANG_EVT_SET_HDR(tlv_buf, tag, len) \ + (((uint16_t *)(tlv_buf))[0]) = (((tag) << 8) | ((len) & 0x000000FF)) + +#define QDF_HANG_GET_STRUCT_TLVLEN(tlv_struct) \ + ((uint16_t)(sizeof(tlv_struct) - QDF_HANG_EVENT_TLV_HDR_SIZE)) + +/** + * qdf_notifier_data - Private data for notifier data + * @hang_data: Data filled by notifier + * @offset: Current offset of the hang data buffer + */ +struct qdf_notifer_data { + uint8_t *hang_data; + unsigned int offset; +}; + +#ifdef WLAN_HANG_EVENT +/** + * qdf_hang_event_register_notifier() - Hang data notifier register + * @nb: Notifier block + * + * This function registers notifier block for the hang data notifier chain + * the registered function will be invoked when the hang data notifier call + * is invoked. + * + * Return: QDF_STATUS + */ +QDF_STATUS qdf_hang_event_register_notifier(qdf_notif_block *nb); + +/** + * qdf_hang_event_unregister_notifier() - Hang data notifier unregister + * @nb: Notifier block + * + * This function unregisters notifier block for the hang data notifier chain. + * + * Return: QDF_STATUS + */ +QDF_STATUS qdf_hang_event_unregister_notifier(qdf_notif_block *nb); + +/** + * qdf_hang_event_notifier_call() - Hang data notifier register + * @v: state + * @data: Private data for this notifier chain + * + * This function when invoked will call the functions registered with this + * notifier chain. + * + * Return: QDF_STATUS + */ +QDF_STATUS qdf_hang_event_notifier_call(unsigned long v, void *data); +#else +static inline +QDF_STATUS qdf_hang_event_register_notifier(qdf_notif_block *nb) +{ + return QDF_STATUS_SUCCESS; +} + +static inline +QDF_STATUS qdf_hang_event_unregister_notifier(qdf_notif_block *nb) +{ + return QDF_STATUS_SUCCESS; +} + +static inline +QDF_STATUS qdf_hang_event_notifier_call(unsigned long v, void *data) +{ + return QDF_STATUS_SUCCESS; +} +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_hashtable.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_hashtable.h index 098ee3961c9b1c1a3e36108b56698cf9c73f2959..7bb09b4fd8b15c9daf210afbb749f94c1d6a98ff 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_hashtable.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_hashtable.h @@ -96,6 +96,18 @@ #define qdf_ht_for_each(table, i, cursor, entry_field) \ __qdf_ht_for_each(table, i, cursor, entry_field) +/** + * qdf_ht_for_each_safe() - iterate all entries in @table safe against removal + * of hash entry. + * @table: a non-pointer qdf_ht instance to iterate + * @i: int type cursor populated with the bucket index + * @tmp: a &struct used for temporary storage + * @cursor: container struct pointer populated with each iteration + * @entry_field: name of the entry field in the entry container struct + */ +#define qdf_ht_for_each_safe(table, i, tmp, cursor, entry_field) \ + __qdf_ht_for_each_safe(table, i, tmp, cursor, entry_field) + /** * qdf_ht_for_each_in_bucket() - iterate entries in the bucket for @key * @table: a non-pointer qdf_ht instance to iterate diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_ipa.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_ipa.h index 75c0fa68c12e9f7b56b70e320cde8b97307368de..6d13de7d69a6497a2f6ca853ef49a7a51bbe636b 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_ipa.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_ipa.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, 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 above @@ -214,8 +214,24 @@ typedef __qdf_ipa_gsi_ep_config_t qdf_ipa_gsi_ep_config_t; typedef __qdf_ipa_dp_evt_type_t qdf_ipa_dp_evt_type_t; #ifdef WDI3_STATS_UPDATE +/** + * qdf_ipa_wdi_tx_info_t - WLAN embedded TX bytes information + * + * WLAN host fills this structure to update IPA driver about + * embedded TX information. + */ typedef __qdf_ipa_wdi_tx_info_t qdf_ipa_wdi_tx_info_t; + +/** + * qdf_ipa_wdi_bw_info_t - BW threshold levels to be monitored + * by IPA uC + */ typedef __qdf_ipa_wdi_bw_info_t qdf_ipa_wdi_bw_info_t; + +/** + * qdf_ipa_inform_wlan_bw_t - BW information given by IPA driver + * whenever uC detects threshold level reached + */ typedef __qdf_ipa_inform_wlan_bw_t qdf_ipa_inform_wlan_bw_t; #endif @@ -649,5 +665,22 @@ static inline bool qdf_get_ipa_smmu_enabled(void) } #endif +#ifdef IPA_LAN_RX_NAPI_SUPPORT +/** + * qdf_ipa_get_lan_rx_napi() - Check if NAPI is enabled in LAN + * RX DP + * + * Returns: true if enabled, false otherwise + */ +static inline bool qdf_ipa_get_lan_rx_napi(void) +{ + return __qdf_ipa_get_lan_rx_napi(); +} +#else +static inline bool qdf_ipa_get_lan_rx_napi(void) +{ + return false; +} +#endif /* IPA_LAN_RX_NAPI_SUPPORT */ #endif /* IPA_OFFLOAD */ #endif /* _QDF_IPA_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_ipa_wdi3.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_ipa_wdi3.h index 729e7d304e16f2df19d087ce719a9e5df2a4935f..cdb133e262985be5e50f74374878644bc09ef89f 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_ipa_wdi3.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_ipa_wdi3.h @@ -400,9 +400,9 @@ static inline int qdf_ipa_wdi_release_smmu_mapping(uint32_t num_buffers, #ifdef WDI3_STATS_UPDATE /** - * qdf_ipa_wdi_wlan_stats() - send embedded Tx in bytes to IPA - * - * @tx_stats: tx stats in bytes on sta and sap interface + * qdf_ipa_wdi_wlan_stats() - Client should call this function to + * send Tx byte counts to IPA driver + * @tx_count: number of Tx bytes * * Returns: 0 on success, negative on failure */ @@ -412,7 +412,7 @@ static inline int qdf_ipa_wdi_wlan_stats(qdf_ipa_wdi_tx_info_t *tx_stats) } /** - * ipa_uc_bw_monitor() - start/stop uc bw monitoring + * qdf_ipa_uc_bw_monitor() - start/stop uc bw monitoring * @bw_info: set bw info levels to monitor * * Returns: 0 on success, negative on failure diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_lock.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_lock.h index 3950c564c3176b8ab2eee94ba2e6fe1dc01da29e..91f8948f723fded7f48ad9ced091eba5b8f7379f 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_lock.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_lock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-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 @@ -44,9 +44,14 @@ /* Max hold time in micro seconds, 0 to disable detection*/ #define QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK_IRQ 10000 -#define QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK_BH 1000000 #define QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK 0 +#if QDF_LOCK_STATS +#define QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK_BH 2000000 +#else +#define QDF_MAX_HOLD_TIME_ALOWED_SPINLOCK_BH 1000000 +#endif + #if !QDF_LOCK_STATS struct lock_stats {}; #define BEFORE_LOCK(x...) do {} while (0) @@ -85,13 +90,13 @@ do { \ uint64_t BEFORE_LOCK_time; \ uint64_t AFTER_LOCK_time; \ bool BEFORE_LOCK_is_locked = was_locked; \ - BEFORE_LOCK_time = qdf_get_log_timestamp(); \ + BEFORE_LOCK_time = qdf_get_log_timestamp_lightweight(); \ do {} while (0) #define AFTER_LOCK(lock, func) \ lock->stats.acquired_by = func; \ - AFTER_LOCK_time = qdf_get_log_timestamp(); \ + AFTER_LOCK_time = qdf_get_log_timestamp_lightweight(); \ lock->stats.acquired++; \ lock->stats.last_acquired = AFTER_LOCK_time; \ if (BEFORE_LOCK_is_locked) { \ @@ -116,11 +121,11 @@ do { \ do { \ uint64_t BEFORE_LOCK_time; \ uint64_t AFTER_LOCK_time; \ - BEFORE_LOCK_time = qdf_get_log_timestamp(); \ + BEFORE_LOCK_time = qdf_get_log_timestamp_lightweight(); \ do {} while (0) #define AFTER_TRYLOCK(lock, trylock_return, func) \ - AFTER_LOCK_time = qdf_get_log_timestamp(); \ + AFTER_LOCK_time = qdf_get_log_timestamp_lightweight(); \ if (trylock_return) { \ lock->stats.acquired++; \ lock->stats.last_acquired = AFTER_LOCK_time; \ @@ -133,8 +138,15 @@ do { \ /* max_hold_time in US */ #define BEFORE_UNLOCK(lock, max_hold_time) \ do {\ - uint64_t held_time = qdf_get_log_timestamp() - \ - lock->stats.last_acquired; \ + uint64_t BEFORE_UNLOCK_time; \ + uint64_t held_time; \ + BEFORE_UNLOCK_time = qdf_get_log_timestamp_lightweight(); \ +\ + if (unlikely(BEFORE_UNLOCK_time < lock->stats.last_acquired)) \ + held_time = 0; \ + else \ + held_time = BEFORE_UNLOCK_time - lock->stats.last_acquired; \ +\ lock->stats.held_time += held_time; \ \ if (held_time > lock->stats.max_held_time) \ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_mem.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_mem.h index 69ba990b38a87fa8a2fa6ae5cd3a79fa9a7a0ae0..56c3c498008caf1d1417ffd6c8be29782791c704 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_mem.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_mem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -27,6 +27,7 @@ /* Include Files */ #include #include +#include #define QDF_CACHE_LINE_SZ __qdf_cache_line_sz @@ -38,6 +39,7 @@ * Return: aligned value. */ #define qdf_align(a, align_size) __qdf_align(a, align_size) +#define qdf_page_size __page_size /** * struct qdf_mem_dma_page_t - Allocated dmaable page @@ -57,12 +59,17 @@ struct qdf_mem_dma_page_t { * @num_pages: Number of allocation needed pages * @dma_pages: page information storage in case of coherent memory * @cacheable_pages: page information storage in case of cacheable memory + * @is_mem_prealloc: flag for multiple pages pre-alloc or not */ struct qdf_mem_multi_page_t { uint16_t num_element_per_page; uint16_t num_pages; struct qdf_mem_dma_page_t *dma_pages; void **cacheable_pages; + qdf_size_t page_size; +#ifdef DP_MEM_PRE_ALLOC + uint8_t is_mem_prealloc; +#endif }; @@ -89,6 +96,13 @@ void qdf_mem_exit(void); #define QDF_MEM_FUNC_NAME_SIZE 48 #ifdef MEMORY_DEBUG +/** + * qdf_mem_debug_config_get() - Get the user configuration of mem_debug_disabled + * + * Return: value of mem_debug_disabled qdf module argument + */ +bool qdf_mem_debug_config_get(void); + /** * qdf_mem_malloc_debug() - debug version of QDF memory allocation API * @size: Number of bytes of memory to allocate. @@ -128,6 +142,28 @@ void qdf_mem_free_debug(void *ptr, const char *file, uint32_t line); #define qdf_mem_free(ptr) \ qdf_mem_free_debug(ptr, __func__, __LINE__) +void qdf_mem_multi_pages_alloc_debug(qdf_device_t osdev, + struct qdf_mem_multi_page_t *pages, + size_t element_size, uint16_t element_num, + qdf_dma_context_t memctxt, bool cacheable, + const char *func, uint32_t line, + void *caller); + +#define qdf_mem_multi_pages_alloc(osdev, pages, element_size, element_num,\ + memctxt, cacheable) \ + qdf_mem_multi_pages_alloc_debug(osdev, pages, element_size, \ + element_num, memctxt, cacheable, \ + __func__, __LINE__, QDF_RET_IP) + +void qdf_mem_multi_pages_free_debug(qdf_device_t osdev, + struct qdf_mem_multi_page_t *pages, + qdf_dma_context_t memctxt, bool cacheable, + const char *func, uint32_t line); + +#define qdf_mem_multi_pages_free(osdev, pages, memctxt, cacheable) \ + qdf_mem_multi_pages_free_debug(osdev, pages, memctxt, cacheable, \ + __func__, __LINE__) + /** * qdf_mem_check_for_leaks() - Assert that the current memory domain is empty * @@ -203,6 +239,10 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev, qdf_mem_free_consistent_debug(osdev, dev, size, vaddr, paddr, memctx, \ __func__, __LINE__) #else +static inline bool qdf_mem_debug_config_get(void) +{ + return false; +} /** * qdf_mem_malloc() - allocation QDF memory @@ -217,9 +257,10 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev, * specified (for any reason) it returns NULL. */ #define qdf_mem_malloc(size) \ - qdf_mem_malloc_fl(size, __func__, __LINE__) + __qdf_mem_malloc(size, __func__, __LINE__) -void *qdf_mem_malloc_fl(qdf_size_t size, const char *func, uint32_t line); +#define qdf_mem_malloc_fl(size, func, line) \ + __qdf_mem_malloc(size, func, line) /** * qdf_mem_malloc_atomic() - allocation QDF memory atomically @@ -240,25 +281,40 @@ void *qdf_mem_malloc_atomic_fl(qdf_size_t size, const char *func, uint32_t line); -/** - * qdf_mem_free() - free QDF memory - * @ptr: Pointer to the starting address of the memory to be freed. - * - * Return: None - */ -void qdf_mem_free(void *ptr); +#define qdf_mem_free(ptr) \ + __qdf_mem_free(ptr) static inline void qdf_mem_check_for_leaks(void) { } -void *qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev, - qdf_size_t size, qdf_dma_addr_t *paddr); +#define qdf_mem_alloc_consistent(osdev, dev, size, paddr) \ + __qdf_mem_alloc_consistent(osdev, dev, size, paddr, __func__, __LINE__) + +#define qdf_mem_free_consistent(osdev, dev, size, vaddr, paddr, memctx) \ + __qdf_mem_free_consistent(osdev, dev, size, vaddr, paddr, memctx) -void qdf_mem_free_consistent(qdf_device_t osdev, void *dev, - qdf_size_t size, void *vaddr, - qdf_dma_addr_t paddr, qdf_dma_context_t memctx); +void qdf_mem_multi_pages_alloc(qdf_device_t osdev, + struct qdf_mem_multi_page_t *pages, + size_t element_size, uint16_t element_num, + qdf_dma_context_t memctxt, bool cacheable); + +void qdf_mem_multi_pages_free(qdf_device_t osdev, + struct qdf_mem_multi_page_t *pages, + qdf_dma_context_t memctxt, bool cacheable); #endif /* MEMORY_DEBUG */ +/** + * qdf_mem_multi_pages_zero() - zero out each page memory + * @pages: Multi page information storage + * @cacheable: Coherent memory or cacheable memory + * + * This function will zero out each page memory + * + * Return: None + */ +void qdf_mem_multi_pages_zero(struct qdf_mem_multi_page_t *pages, + bool cacheable); + /** * qdf_aligned_malloc() - allocates aligned QDF memory. * @size: Size to be allocated @@ -415,7 +471,7 @@ static inline uint32_t qdf_mem_map_nbytes_single(qdf_device_t osdev, void *buf, qdf_dma_dir_t dir, int nbytes, qdf_dma_addr_t *phy_addr) { -#if defined(HIF_PCI) +#if defined(HIF_PCI) || defined(HIF_IPCI) return __qdf_mem_map_nbytes_single(osdev, buf, dir, nbytes, phy_addr); #else return 0; @@ -444,7 +500,7 @@ static inline void qdf_mem_unmap_nbytes_single(qdf_device_t osdev, qdf_dma_dir_t dir, int nbytes) { -#if defined(HIF_PCI) +#if defined(HIF_PCI) || defined(HIF_IPCI) __qdf_mem_unmap_nbytes_single(osdev, phy_addr, dir, nbytes); #endif } @@ -511,13 +567,6 @@ void qdf_mem_dma_sync_single_for_cpu(qdf_device_t osdev, qdf_size_t size, __dma_data_direction direction); -void qdf_mem_multi_pages_alloc(qdf_device_t osdev, - struct qdf_mem_multi_page_t *pages, - size_t element_size, uint16_t element_num, - qdf_dma_context_t memctxt, bool cacheable); -void qdf_mem_multi_pages_free(qdf_device_t osdev, - struct qdf_mem_multi_page_t *pages, - qdf_dma_context_t memctxt, bool cacheable); int qdf_mem_multi_page_link(qdf_device_t osdev, struct qdf_mem_multi_page_t *pages, uint32_t elem_size, uint32_t elem_count, uint8_t cacheable); @@ -597,7 +646,7 @@ static inline void qdf_update_mem_map_table(qdf_device_t osdev, uint32_t mem_size) { if (!mem_info) { - __qdf_print("%s: NULL mem_info\n", __func__); + qdf_nofl_err("%s: NULL mem_info", __func__); return; } @@ -794,8 +843,8 @@ static inline void qdf_mem_shared_mem_free(qdf_device_t osdev, qdf_shared_mem_t *shared_mem) { if (!shared_mem) { - __qdf_print("%s: NULL shared mem struct passed\n", - __func__); + qdf_nofl_err("%s: NULL shared mem struct passed", + __func__); return; } diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_nbuf.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_nbuf.h index b91f754c58e7a2934c868c4506df5017d6bd269e..e4aa99db54f8b0ba990ead38814726e9655e1690 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_nbuf.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_nbuf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -39,6 +39,7 @@ #define QDF_NBUF_PKT_TRAC_TYPE_ARP 0x10 #define QDF_NBUF_PKT_TRAC_TYPE_ICMP 0x20 #define QDF_NBUF_PKT_TRAC_TYPE_ICMPv6 0x40 +#define QDF_HL_CREDIT_TRACKING 0x80 #define QDF_NBUF_PKT_TRAC_MAX_STRING 12 #define QDF_NBUF_PKT_TRAC_PROTO_STRING 4 @@ -50,6 +51,8 @@ #define QDF_NBUF_TRAC_DHCP_SRV_PORT 67 #define QDF_NBUF_TRAC_DHCP_CLI_PORT 68 #define QDF_NBUF_TRAC_ETH_TYPE_OFFSET 12 +#define QDF_NBUF_TRAC_VLAN_ETH_TYPE_OFFSET 16 +#define QDF_NBUF_TRAC_DOUBLE_VLAN_ETH_TYPE_OFFSET 20 #define QDF_NBUF_TRAC_EAPOL_ETH_TYPE 0x888E #define QDF_NBUF_TRAC_WAPI_ETH_TYPE 0x88b4 #define QDF_NBUF_TRAC_ARP_ETH_TYPE 0x0806 @@ -83,7 +86,11 @@ #define QDF_NBUF_TRAC_DHCP6_SRV_PORT 547 #define QDF_NBUF_TRAC_DHCP6_CLI_PORT 546 #define QDF_NBUF_TRAC_MDNS_SRC_N_DST_PORT 5353 - +#define QDF_NBUF_TRAC_IP_OFFSET 14 +#define QDF_NBUF_TRAC_VLAN_IP_OFFSET 18 +#define QDF_NBUF_TRAC_DOUBLE_VLAN_IP_OFFSET 22 +/* One dword for IPv4 header size unit */ +#define QDF_NBUF_IPV4_HDR_SIZE_UNIT 4 /* EAPOL Related MASK */ #define EAPOL_PACKET_TYPE_OFFSET 15 @@ -166,6 +173,7 @@ #endif #define MAX_CHAIN 8 +#define QDF_MON_STATUS_MPDU_FCS_BMAP_NWORDS 8 /** * struct mon_rx_status - This will have monitor mode rx_status extracted from @@ -239,15 +247,13 @@ * @first_data_seq_ctrl: Sequence ctrl field of first data frame * @rxpcu_filter_pass: Flag which indicates whether RX packets are received in * BSS mode(not in promisc mode) - * @tx_status: packet tx status - * @tx_retry_cnt: tx retry count - * @tx_retry_cnt: tx retry count + * @rssi_chain: Rssi chain per nss per bw */ struct mon_rx_status { uint64_t tsft; uint32_t ppdu_timestamp; uint32_t preamble_type; - uint16_t chan_freq; + qdf_freq_t chan_freq; uint16_t chan_num; uint16_t chan_flags; uint16_t ht_flags; @@ -321,26 +327,71 @@ struct mon_rx_status { uint16_t first_data_seq_ctrl; uint8_t ltf_size; uint8_t rxpcu_filter_pass; - uint8_t tx_status; - uint8_t tx_retry_cnt; - bool add_rtap_ext; + int8_t rssi_chain[8][8]; + uint32_t rx_antenna; }; /** - * struct mon_rx_status - This will have monitor mode per user rx_status + * struct mon_rx_user_status - This will have monitor mode per user rx_status * extracted from hardware TLV. * @mcs: MCS index of Rx frame * @nss: Number of spatial streams - * @ofdma_info_valid: OFDMA info below is valid - * @dl_ofdma_ru_start_index: OFDMA RU start index - * @dl_ofdma_ru_width: OFDMA total RU width + * @mu_ul_info_valid: MU UL info below is valid + * @ofdma_ru_start_index: OFDMA RU start index + * @ofdma_ru_width: OFDMA total RU width + * @ofdma_ru_size: OFDMA RU size index + * @mu_ul_user_v0_word0: MU UL user info word 0 + * @mu_ul_user_v0_word1: MU UL user info word 1 + * @ast_index: AST table hash index + * @tid: QoS traffic tid number + * @tcp_msdu_count: tcp protocol msdu count + * @udp_msdu_count: udp protocol msdu count + * @other_msdu_count: other protocol msdu count + * @frame_control: frame control field + * @frame_control_info_valid: field indicates if fc value is valid + * @data_sequence_control_info_valid: field to indicate validity of seq control + * @first_data_seq_ctrl: Sequence ctrl field of first data frame + * @preamble_type: Preamble type in radio header + * @ht_flags: HT flags, only present for HT frames. + * @vht_flags: VHT flags, only present for VHT frames. + * @he_flags: HE (11ax) flags, only present in HE frames + * @rtap_flags: Bit map of available fields in the radiotap + * @rs_flags: Flags to indicate AMPDU or AMSDU aggregation + * @mpdu_cnt_fcs_ok: mpdu count received with fcs ok + * @mpdu_cnt_fcs_err: mpdu count received with fcs ok bitmap + * @mpdu_fcs_ok_bitmap: mpdu with fcs ok bitmap + * @mpdu_ok_byte_count: mpdu byte count with fcs ok + * @mpdu_err_byte_count: mpdu byte count with fcs err */ struct mon_rx_user_status { uint32_t mcs:4, nss:3, - ofdma_info_valid:1, - dl_ofdma_ru_start_index:7, - dl_ofdma_ru_width:7; + mu_ul_info_valid:1, + ofdma_ru_start_index:7, + ofdma_ru_width:7, + ofdma_ru_size:8; + uint32_t mu_ul_user_v0_word0; + uint32_t mu_ul_user_v0_word1; + uint32_t ast_index; + uint32_t tid; + uint16_t tcp_msdu_count; + uint16_t udp_msdu_count; + uint16_t other_msdu_count; + uint16_t frame_control; + uint8_t frame_control_info_valid; + uint8_t data_sequence_control_info_valid; + uint16_t first_data_seq_ctrl; + uint32_t preamble_type; + uint16_t ht_flags; + uint16_t vht_flags; + uint16_t he_flags; + uint8_t rtap_flags; + uint8_t rs_flags; + uint32_t mpdu_cnt_fcs_ok; + uint32_t mpdu_cnt_fcs_err; + uint32_t mpdu_fcs_ok_bitmap[QDF_MON_STATUS_MPDU_FCS_BMAP_NWORDS]; + uint32_t mpdu_ok_byte_count; + uint32_t mpdu_err_byte_count; }; /** @@ -1495,6 +1546,24 @@ qdf_nbuf_t qdf_nbuf_clone_debug(qdf_nbuf_t buf, const char *func, */ qdf_nbuf_t qdf_nbuf_copy_debug(qdf_nbuf_t buf, const char *func, uint32_t line); +#define qdf_nbuf_copy_expand(buf, headroom, tailroom) \ + qdf_nbuf_copy_expand_debug(buf, headroom, tailroom, __func__, __LINE__) + +/** + * qdf_nbuf_copy_expand_debug() - copy and expand nbuf + * @buf: Network buf instance + * @headroom: Additional headroom to be added + * @tailroom: Additional tailroom to be added + * @func: name of the calling function + * @line: line number of the callsite + * + * Return: New nbuf that is a copy of buf, with additional head and tailroom + * or NULL if there is no memory + */ +qdf_nbuf_t +qdf_nbuf_copy_expand_debug(qdf_nbuf_t buf, int headroom, int tailroom, + const char *func, uint32_t line); + #else /* NBUF_MEMORY_DEBUG */ static inline void qdf_net_buf_debug_init(void) {} @@ -1575,6 +1644,20 @@ static inline qdf_nbuf_t qdf_nbuf_copy(qdf_nbuf_t buf) return __qdf_nbuf_copy(buf); } +/** + * qdf_nbuf_copy_expand() - copy and expand nbuf + * @buf: Network buf instance + * @headroom: Additional headroom to be added + * @tailroom: Additional tailroom to be added + * + * Return: New nbuf that is a copy of buf, with additional head and tailroom + * or NULL if there is no memory + */ +static inline qdf_nbuf_t qdf_nbuf_copy_expand(qdf_nbuf_t buf, int headroom, + int tailroom) +{ + return __qdf_nbuf_copy_expand(buf, headroom, tailroom); +} #endif /* NBUF_MEMORY_DEBUG */ #ifdef WLAN_FEATURE_FASTPATH @@ -3116,6 +3199,17 @@ static inline void qdf_nbuf_unmap_tso_segment(qdf_device_t osdev, return __qdf_nbuf_unmap_tso_segment(osdev, tso_seg, is_last_seg); } +/** + * qdf_nbuf_get_tcp_payload_len() - function to return the tso payload len + * @nbuf: network buffer + * + * Return: size of the tso packet + */ +static inline size_t qdf_nbuf_get_tcp_payload_len(qdf_nbuf_t nbuf) +{ + return __qdf_nbuf_get_tcp_payload_len(nbuf); +} + /** * qdf_nbuf_get_tso_num_seg() - function to calculate the number * of TCP segments within the TSO jumbo packet @@ -3235,8 +3329,9 @@ qdf_nbuf_unshare_debug(qdf_nbuf_t buf, const char *func_name, uint32_t line_num) if (qdf_likely(buf != unshared_buf)) { qdf_net_buf_debug_delete_node(buf); - qdf_net_buf_debug_add_node(unshared_buf, 0, - func_name, line_num); + if (unshared_buf) + qdf_net_buf_debug_add_node(unshared_buf, 0, + func_name, line_num); } return unshared_buf; @@ -3530,7 +3625,7 @@ static inline void qdf_nbuf_orphan(qdf_nbuf_t buf) return __qdf_nbuf_orphan(buf); } -#ifdef CONFIG_WIN +#ifdef CONFIG_NBUF_AP_PLATFORM #include #else #include diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_net_types.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_net_types.h index 1772bdf0d8972e2aa0829b92daacbdf15b5808e2..c3a60736bbdac77cce89fced2bd2adbeebe207b9 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_net_types.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_net_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -61,6 +61,7 @@ typedef __in6_addr_t in6_addr_t; #define QDF_ETH_TYPE_IPV4 0x0800 /* IPV4 */ #define QDF_ETH_TYPE_IPV6 0x86dd /* IPV6 */ #define QDF_ETH_TYPE_8021Q 0x8100 /* 802.1Q vlan protocol */ +#define QDF_ETH_TYPE_8021AD 0x88a8 /* 802.1AD vlan protocol */ #define QDF_IEEE80211_4ADDR_HDR_LEN 30 #define QDF_IEEE80211_3ADDR_HDR_LEN 24 #define QDF_IEEE80211_FC0_SUBTYPE_QOS 0x80 @@ -74,6 +75,9 @@ typedef __in6_addr_t in6_addr_t; #define QDF_IEEE80211_FC0_SUBTYPE_DATA 0x00 #define QDF_IEEE80211_FC0_SUBTYPE_QOS 0x80 +#define QDF_IEEE80211_FC0_SUBTYPE_QOS_NULL 0xC0 +#define QDF_IEEE80211_FC0_SUBTYPE_NODATA 0x40 + #define QDF_IEEE80211_FC0_TYPE_CTL 0x04 #define QDF_IEEE80211_FC0_SUBTYPE_BEAM_REPORT_POLL 0x40 #define QDF_IEEE80211_FC0_SUBTYPE_VHT_NDP_AN 0x50 diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_notifier.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_notifier.h new file mode 100644 index 0000000000000000000000000000000000000000..1d090e01766c1da4b67df75bde1c26da65a4e7b5 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_notifier.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * @file qdf_notifier.h + * This file abstracts notifier chain call operations. + */ + +#ifndef _QDF_NOTIFIER_H +#define _QDF_NOTIFIER_H + +#include +#include + +/* + * qdf_notif_block - qdf notifier block + * @__qdf_notifier_block: OS specific notifier block + * @priv_data: private data of the notifier block + */ +typedef struct { + __qdf_notifier_block notif_block; + void *priv_data; +} qdf_notif_block; + +typedef __qdf_blocking_notif_head qdf_blocking_notif_head; +typedef __qdf_atomic_notif_head qdf_atomic_notif_head; +typedef __qdf_notifier_block qdf_notifier_block; + +#ifdef WLAN_HANG_EVENT + +/** + * qdf_register_blocking_notifier_chain() - Register for blocking notifier chain + * @qdf_blocking_notif_head: Head of blocking notifier chain + * @qdf_notif_block: Notifier Block to be registered for this head chain + * + * This function is invoked to add a notifier block for the specific notifier + * head chain. + * + * Return: QDF_STATUS + */ + +QDF_STATUS qdf_register_blocking_notifier_chain(qdf_blocking_notif_head *head, + qdf_notif_block *qnb); +/** + * qdf_unregister_blocking_notifier_chain() - Unregister for blocking notifier + * chain + * @qdf_blocking_notif_head: Head of blocking notifier chain + * @qdf_notif_block: Notifier Block to be registered for this head chain + * + * This function is invoked to remove a notifier block for the specific notifier + * head chain. + * + * Return: QDF_STATUS + */ + +QDF_STATUS qdf_unregister_blocking_notifier_chain(qdf_blocking_notif_head *head, + qdf_notif_block *qnb); +/** + * qdf_blocking_notfier_call() - Invoke the function in the blocking chain + * @qdf_blocking_notif_head: Head of blocking notifier chain + * @state: state passed during the invoking of the notifier + * @data: Private data to be passed to all the notifier functions + * + * This function is called to invoke all the notifier blocks for the specific + * notifier chain with state and private data. + * when success the notifier reply with NOTIFY_OK. + * + * Return: QDF_STATUS + */ + +QDF_STATUS qdf_blocking_notfier_call(qdf_blocking_notif_head *head, + unsigned long state, void *data); + +/** + * qdf_register_atomic_notifier_chain() - Register for atomic notifier chain + * @qdf_blocking_notif_head: Head of atomic notifier chain + * @qdf_notif_block: Notifier Block to be registered for this head chain + * + * This function is invoked to add a notifier block for the specific atomic + * notifier head chain. + * + * Return: QDF_STATUS + */ + +QDF_STATUS qdf_register_atomic_notifier_chain(qdf_atomic_notif_head *head, + qdf_notif_block *qnb); +/** + * qdf_unregister_atmoic_notifier_chain() - Unregister for atomic notifier + * chain + * @qdf_blocking_notif_head: Head of blocking notifier chain + * @qdf_notif_block: Notifier Block to be registered for this head chain + * + * This function is invoked to remove a notifier block for the specific notifier + * head chain. + * + * Return: QDF_STATUS + */ + +QDF_STATUS qdf_unregister_atomic_notifier_chain(qdf_atomic_notif_head *head, + qdf_notif_block *qnb); +/** + * qdf_blocking_notfier_call() - Invoke the function in the blocking chain + * @qdf_blocking_notif_head: Head of blocking notifier chain + * @v: Generally state passed during the invoking of the notifier + * @data: Private data to be passed to all the notifier functions + * + * This function is invoke a notifier block for the specific notifier head chain + * with state and private data. when success the notifier reply with NOTIFY_OK. + * + * Return: QDF_STATUS + */ + +QDF_STATUS qdf_atomic_notfier_call(qdf_atomic_notif_head *head, + unsigned long v, void *data); +#else + +static inline QDF_STATUS qdf_register_blocking_notifier_chain( + qdf_blocking_notif_head *head, + qdf_notif_block *qnb) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS qdf_unregister_blocking_notifier_chain( + qdf_blocking_notif_head *head, + qdf_notif_block *qnb) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS qdf_blocking_notfier_call( + qdf_blocking_notif_head *head, + unsigned long v, void *data) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS qdf_register_atomic_notifier_chain( + qdf_atomic_notif_head *head, + qdf_notif_block *qnb) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS qdf_unregister_atomic_notifier_chain( + qdf_atomic_notif_head *head, + qdf_notif_block *qnb) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS qdf_atomic_notfier_call(qdf_atomic_notif_head *head, + unsigned long v, void *data) +{ + return QDF_STATUS_SUCCESS; +} +#endif + +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_platform.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_platform.h index 9833002b372194a346f884a4c23a36ced2fa12ef..36e738eb004f4bc88706127e339d64378c6fc632 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_platform.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_platform.h @@ -28,13 +28,15 @@ /** * qdf_self_recovery_callback() - callback for self recovery + * @psoc: pointer to the posc object * @reason: the reason for the recovery request * @func: the caller's function name * @line: the line number of the callsite * * Return: none */ -typedef void (*qdf_self_recovery_callback)(enum qdf_hang_reason reason, +typedef void (*qdf_self_recovery_callback)(void *psoc, + enum qdf_hang_reason reason, const char *func, const uint32_t line); @@ -133,6 +135,7 @@ void qdf_register_self_recovery_callback(qdf_self_recovery_callback callback); /** * qdf_trigger_self_recovery () - trigger self recovery + * @psoc: the psoc at which the recovery is being triggered * @reason: the reason for the recovery request * * Call API only in case of fatal error, @@ -141,9 +144,9 @@ void qdf_register_self_recovery_callback(qdf_self_recovery_callback callback); * * Return: None */ -#define qdf_trigger_self_recovery(reason) \ - __qdf_trigger_self_recovery(reason, __func__, __LINE__) -void __qdf_trigger_self_recovery(enum qdf_hang_reason reason, +#define qdf_trigger_self_recovery(psoc, reason) \ + __qdf_trigger_self_recovery(psoc, reason, __func__, __LINE__) +void __qdf_trigger_self_recovery(void *psoc, enum qdf_hang_reason reason, const char *func, const uint32_t line); /** @@ -252,5 +255,81 @@ void qdf_register_drv_connected_callback(qdf_is_drv_connected_callback */ void qdf_check_state_before_panic(void); -#endif /*_QDF_PLATFORM_H*/ +/** + * qdf_is_drv_supported_callback() - callback to query if drv is supported + * + * Return: true if drv is supported else false + */ +typedef bool (*qdf_is_drv_supported_callback)(void); + +/** + * qdf_is_drv_supported_callback() - API to check if drv is supported or not + * + * DRV is dynamic request voting using which fw can do page fault and + * bring in page back without apps wake up + * + * Return: true: if drv is supported + * false: if drv is not supported + */ +bool qdf_is_drv_supported(void); + +/** + * qdf_register_drv_supported_callback() - API to register drv supported cb + * @is_drv_supported: callback to query if drv is supported or not + * + * Return: none + */ +void qdf_register_drv_supported_callback(qdf_is_drv_supported_callback + is_drv_supported); + +typedef void (*qdf_recovery_reason_update_callback)(enum qdf_hang_reason + reason); + +/** + * qdf_register_recovery_reason_update() - Register callback to update recovery + * reason + * @qdf_recovery_reason_update_callback: callback to update recovery reason + * + * Return: none + */ +void qdf_register_recovery_reason_update(qdf_recovery_reason_update_callback + callback); + +/** + * qdf_recovery_reason_update() - update recovery reason + * @reason: recovery reason + * + * Return: none + */ +void qdf_recovery_reason_update(enum qdf_hang_reason reason); + +/** + * qdf_bus_reg_dump() - callback for getting bus specific register dump + * @dev: Bus specific device + * @buf: Hang event buffer in which the data will be populated + * @len: length of data to be populated in the hang event buffer + * + * Return: none + */ +typedef void (*qdf_bus_reg_dump)(struct device *dev, uint8_t *buf, + uint32_t len); +/** + * qdf_register_get_bus_reg_dump() - Register callback to update bus register + * dump + * @qdf_bus_reg_dump: callback to update bus register dump + * + * Return: none + */ +void qdf_register_get_bus_reg_dump(qdf_bus_reg_dump callback); + +/** + * qdf_get_bus_reg_dump() - Get the register dump for the bus + * @dev: device + * @buffer: buffer for hang data + * @len: len of hang data + * + * Return: none + */ +void qdf_get_bus_reg_dump(struct device *dev, uint8_t *buf, uint32_t len); +#endif /*_QDF_PLATFORM_H*/ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_str.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_str.h index 7864a4412e3a6a73ffed019e6fb181d2d40cda9c..5c04baa5bd485902b36502c305194fbbcdba35b0 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_str.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_str.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 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 @@ -154,4 +154,20 @@ static inline qdf_size_t qdf_str_nlen(const char *str, qdf_size_t limit) return __qdf_str_nlen(str, limit); } +/** + * qdf_str_ncmp - Compare two strings + * @str1: First string + * @str2: Second string + * @limit: the maximum number of characters to check + * Return: + * 0 - strings are equal + * <0 - str1 sorts lexicographically before str2 + * >0 - str1 sorts lexicographically after str2 + */ +static inline int32_t +qdf_str_ncmp(const char *str1, const char *str2, qdf_size_t limit) +{ + return __qdf_str_ncmp(str1, str2, limit); +} + #endif /* __QDF_STR_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_streamfs.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_streamfs.h new file mode 100644 index 0000000000000000000000000000000000000000..f6449cbe4745c898ed4d8ede27d17c373ef1d5f2 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_streamfs.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2018, 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: qdf_streamfs.h + * This file provides OS abstraction for stream filesystem APIs. + */ + +#ifndef _QDF_STREAMFS_H +#define _QDF_STREAMFS_H + +#include +#include +#include + +typedef __qdf_streamfs_chan_t qdf_streamfs_chan_t; +typedef __qdf_streamfs_chan_buf_t qdf_streamfs_chan_buf_t; + +#ifdef WLAN_STREAMFS +/** + * qdf_streamfs_create_dir() - wrapper to create a debugfs directory + * @name: name of the new directory + * @parent: parent node. If NULL, defaults to base qdf_debugfs_root + * + * Return: dentry structure pointer in case of success, otherwise NULL. + * + */ +static inline qdf_dentry_t qdf_streamfs_create_dir( + const char *name, qdf_dentry_t parent) +{ + return qdf_debugfs_create_dir(name, parent); +} + +/** + * qdf_streamfs_remove_file() - wrapper to remove streamfs file + * @d: streamfs node + * + */ +static inline void qdf_streamfs_remove_file(qdf_dentry_t d) +{ + qdf_debugfs_remove_file(d); +} + +/** + * qdf_debugfs_remove_dir_recursive() - wrapper to remove directory recursively + * @d: debugfs node + * + * This function will recursively remove a directory in streamfs that was + * previously created with a call to qdf_debugfs_create_file() or it's + * variant functions. + */ +static inline void qdf_streamfs_remove_dir_recursive(qdf_dentry_t d) +{ + qdf_debugfs_remove_dir_recursive(d); +} + +/** + * qdf_streamfs_create_file() - Create streamfs chan buffer file + * @name: base name of file to create + * @mode: filemode + * @parent: dentry of parent directory, NULL for root directory + * @buf: pointer to chan buffer + * + * Returns file dentry pointer if successful, NULL otherwise. + */ +qdf_dentry_t qdf_streamfs_create_file(const char *name, uint16_t mode, + qdf_dentry_t parent, + qdf_streamfs_chan_buf_t buf); + +/** + * qdf_streamfs_open() - Create streamfs channel for data trasfer + * @base_filename: base name of files to create, %NULL for buffering only + * @parent: dentry of parent directory, %NULL for root directory + * @subbuf_size: size of sub-buffers + * @n_subbufs: number of sub-buffers + * @private_data: user-defined data + * + * Returns channel pointer if successful, %NULL otherwise. + */ +qdf_streamfs_chan_t qdf_streamfs_open(const char *base_filename, + qdf_dentry_t parent, + size_t subbuf_size, size_t n_subbufs, + void *private_data); + +/** + * qdf_streamfs_close() - Closes all channel buffers and frees the channel. + * @chan: pointer to qdf_streamfs_chan. + * + * Returns NONE + */ +void qdf_streamfs_close(qdf_streamfs_chan_t chan); + +/** + * qdf_streamfs_flush() - Flushes all channel buffers. + * @chan: pointer to qdf_streamfs_chan. + * + * Returns NONE + */ +void qdf_streamfs_flush(qdf_streamfs_chan_t chan); + +/** + * qdf_streamfs_reset() - Reset streamfs channel + * @chan: pointer to qdf_streamfs_chan. + * + * This erases data from all channel buffers and restarting the channel + * in its initial state. The buffers are not freed, so any mappings are + * still in effect. + * + * Returns NONE + */ +void qdf_streamfs_reset(qdf_streamfs_chan_t chan); + +/** + * qdf_streamfs_subbufs_consumed() - update the buffer's sub-buffers-consumed + * count + * @chan: pointer to qdf_streamfs_chan. + * @cpu: the cpu associated with the channel buffer to update + * @subbufs_consumed: number of sub-buffers to add to current buf's count + * + * Returns NONE + */ +void qdf_streamfs_subbufs_consumed(qdf_streamfs_chan_t chan, + unsigned int cpu, + size_t consumed); + +/** + * qdf_streamfs_write() - write data into the channel + * @chan: relay channel + * @data: data to be written + * @length: number of bytes to write + * + * Writes data into the current cpu's channel buffer. + */ +void qdf_streamfs_write(qdf_streamfs_chan_t chan, const void *data, + size_t length); +#else +static inline qdf_dentry_t qdf_streamfs_create_dir( + const char *name, qdf_dentry_t parent) +{ + return NULL; +} + +static inline void qdf_streamfs_remove_file(qdf_dentry_t d) +{ +} + +static inline void qdf_streamfs_remove_dir_recursive(qdf_dentry_t d) +{ +} + +static inline +qdf_dentry_t qdf_streamfs_create_file(const char *name, uint16_t mode, + qdf_dentry_t parent, + qdf_streamfs_chan_buf_t buf) +{ + return NULL; +} + +static inline +qdf_streamfs_chan_t qdf_streamfs_open(const char *base_filename, + qdf_dentry_t parent, + size_t subbuf_size, size_t n_subbufs, + void *private_data) +{ + return NULL; +} + +static inline void qdf_streamfs_close(qdf_streamfs_chan_t chan) +{ +} + +static inline void qdf_streamfs_flush(qdf_streamfs_chan_t chan) +{ +} + +static inline void qdf_streamfs_reset(qdf_streamfs_chan_t chan) +{ +} + +static inline void +qdf_streamfs_subbufs_consumed(qdf_streamfs_chan_t chan, + unsigned int cpu, size_t consumed) +{ +} + +static inline void +qdf_streamfs_write(qdf_streamfs_chan_t chan, const void *data, + size_t length) +{ +} +#endif /* WLAN_STREAMFS */ +#endif /* _QDF_STREAMFS_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_threads.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_threads.h index fcb28c8bea0a7fad5b0efa3121eb21bc5347a50e..17c8fe467462ff6c4f7ce512dce490d704be5b84 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_threads.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_threads.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -168,4 +168,24 @@ void qdf_cpumask_set_cpu(unsigned int cpu, qdf_cpu_mask *dstp); * Return: None */ void qdf_cpumask_setall(qdf_cpu_mask *dstp); + +/** + * qdf_cpumask_empty - Check if cpu_mask is empty + * @srcp: cpumask pointer + * + * Return: true or false + * + */ +bool qdf_cpumask_empty(const struct cpumask *srcp); + +/** + * qdf_cpumask_copy - Copy srcp cpumask to dstp + * @srcp: source cpumask pointer + * @dstp: destination cpumask pointer + * + * Return: None + * + */ +void qdf_cpumask_copy(struct cpumask *dstp, + const struct cpumask *srcp); #endif /* __QDF_THREADS_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_time.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_time.h index 32cfeba0068e2ed67556c6ccb71b546d00ba13e5..575e851bd41061da2d2fcf004c036e061af0eb65 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_time.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_time.h @@ -270,6 +270,21 @@ static inline uint64_t qdf_log_timestamp_to_usecs(uint64_t time) return time; } + +/** + * qdf_get_log_timestamp_lightweight - get time stamp for logging + * For adrastea this API returns QTIMER tick which is needed to synchronize + * host and fw log timestamps + * For ROME and other discrete solution this API returns system boot time stamp + * + * Return: + * QTIMER ticks(19.2MHz) for adrastea + * System tick for rome and other 3rd party platform solutions + */ +static inline uint64_t qdf_get_log_timestamp_lightweight(void) +{ + return __qdf_get_log_timestamp(); +} #else #define QDF_LOG_TIMESTAMP_UNIT KERNEL_LOG #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 10 @@ -279,6 +294,22 @@ static inline uint64_t qdf_log_timestamp_to_usecs(uint64_t time) /* timestamps are already in micro seconds */ return time; } + +static inline uint64_t qdf_get_log_timestamp_lightweight(void) +{ + uint64_t timestamp_us; + + /* explicitly change to uint64_t, otherwise it will assign + * uint32_t to timestamp_us, which lose high 32bits. + * on 64bit platform, it will only use low 32bits jiffies in + * jiffies_to_msecs. + * eg: HZ=250, it will overflow every (0xffff ffff<<2==0x3fff ffff) + * ticks. it is 1193 hours. + */ + timestamp_us = + (uint64_t)__qdf_system_ticks_to_msecs(qdf_system_ticks()) * 1000; + return timestamp_us; +} #endif /* end of MSM_PLATFORM */ static inline void qdf_log_timestamp_to_secs(uint64_t time, uint64_t *secs, diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_trace.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_trace.h index 2ecbdb5fffaf03d686a21bad3ba21de151cf2ded..cfc389c12460fa04fc5e573cb9fef5eb905982d4 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_trace.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_trace.h @@ -54,10 +54,7 @@ */ #define QDF_WMI_MTRACE_CMD_ID(message_id) ((message_id) & 0x7F) -#ifdef CONFIG_MCL -#define QDF_DEFAULT_TRACE_LEVEL \ - ((1 << QDF_TRACE_LEVEL_FATAL) | (1 << QDF_TRACE_LEVEL_ERROR)) -#else +#ifdef QDF_TRACE_PRINT_ENABLE #define QDF_DEFAULT_TRACE_LEVEL (1 << QDF_TRACE_LEVEL_INFO) #endif @@ -207,6 +204,7 @@ typedef struct s_qdf_trace_data { * @QDF_DP_TRACE_ICMPv6_PACKET_RECORD - record ICMPv6 packet * @QDF_DP_TRACE_HDD_TX_TIMEOUT - HDD tx timeout * @QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT- SOFTAP HDD tx timeout + * @QDF_DP_TRACE_TX_CREDIT_RECORD - credit update record * @QDF_DP_TRACE_ULTRA_LOW_VERBOSITY - Below this is not logged for >4PPS * @QDF_DP_TRACE_TX_PACKET_RECORD - record 32 bytes of tx pkt at any layer * @QDF_DP_TRACE_RX_PACKET_RECORD - record 32 bytes of rx pkt at any layer @@ -253,6 +251,7 @@ enum QDF_DP_TRACE_ID { QDF_DP_TRACE_ICMPv6_PACKET_RECORD, QDF_DP_TRACE_HDD_TX_TIMEOUT, QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT, + QDF_DP_TRACE_TX_CREDIT_RECORD, QDF_DP_TRACE_ULTRA_LOW_VERBOSITY, QDF_DP_TRACE_TX_PACKET_RECORD, QDF_DP_TRACE_RX_PACKET_RECORD, @@ -297,6 +296,36 @@ enum qdf_proto_dir { QDF_NA }; +/** + * QDF_CREDIT_UPDATE_SOURCE - source of credit record + * @QDF_TX_SCHED: Tx scheduler + * @QDF_TX_COMP: TX completion + * @QDF_TX_CREDIT_UPDATE: credit update indication + * @QDF_HTT_ATTACH: HTT attach + * @QDF_TX_HTT_MSG: HTT TX message + */ +enum QDF_CREDIT_UPDATE_SOURCE { + QDF_TX_SCHED, + QDF_TX_COMP, + QDF_TX_CREDIT_UPDATE, + QDF_HTT_ATTACH, + QDF_TX_HTT_MSG +}; + +/** + * QDF_CREDIT_OPERATION - operation on credit + * @QDF_CREDIT_INC: credit increment + * @QDF_CREDIT_DEC: credit decrement + * @QDF_CREDIT_ABS: Abosolute credit + * @QDF_OP_NA: Not applicable + */ +enum QDF_CREDIT_OPERATION { + QDF_CREDIT_INC, + QDF_CREDIT_DEC, + QDF_CREDIT_ABS, + QDF_OP_NA +}; + /** * struct qdf_dp_trace_ptr_buf - pointer record buffer * @cookie: cookie value @@ -339,6 +368,24 @@ struct qdf_dp_trace_mgmt_buf { uint8_t subtype; }; +/** + * struct qdf_dp_trace_credit_record - tx credit record + * @source: credit record source + * @operation: credit operation + * @delta: delta of credit + * @total_credits: total credit + * @g0_credit: group 0 credit + * @g1_credit: group 1 credit + */ +struct qdf_dp_trace_credit_record { + enum QDF_CREDIT_UPDATE_SOURCE source; + enum QDF_CREDIT_OPERATION operation; + int delta; + int total_credits; + int g0_credit; + int g1_credit; +}; + /** * struct qdf_dp_trace_event_buf - event buffer * @vdev_id : vdev id @@ -429,7 +476,7 @@ struct s_qdf_dp_trace_data { uint32_t head; uint32_t tail; uint32_t num; - uint8_t proto_bitmap; + uint32_t proto_bitmap; uint8_t no_of_record; uint16_t num_records_to_dump; uint16_t dump_counter; @@ -624,11 +671,11 @@ bool qdf_dp_trace_log_pkt(uint8_t vdev_id, struct sk_buff *skb, void qdf_dp_trace_init(bool live_mode_config, uint8_t thresh, uint16_t time_limit, uint8_t verbosity, - uint8_t proto_bitmap); + uint32_t proto_bitmap); void qdf_dp_trace_deinit(void); void qdf_dp_trace_spin_lock_init(void); -void qdf_dp_trace_set_value(uint8_t proto_bitmap, uint8_t no_of_records, - uint8_t verbosity); +void qdf_dp_trace_set_value(uint32_t proto_bitmap, uint8_t no_of_records, + uint8_t verbosity); void qdf_dp_trace_set_track(qdf_nbuf_t nbuf, enum qdf_proto_dir dir); void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, uint8_t pdev_id, uint8_t *data, uint8_t size, enum qdf_proto_dir dir); @@ -753,7 +800,7 @@ void qdf_dp_trace_data_pkt(qdf_nbuf_t nbuf, uint8_t pdev_id, enum QDF_DP_TRACE_ID code, uint16_t msdu_id, enum qdf_proto_dir dir); -uint8_t qdf_dp_get_proto_bitmap(void); +uint32_t qdf_dp_get_proto_bitmap(void); uint8_t qdf_dp_get_verbosity(void); uint8_t qdf_dp_get_no_of_record(void); @@ -794,6 +841,20 @@ void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id, uint8_t pdev_id, enum qdf_proto_type type, enum qdf_proto_subtype subtype); +/** + * qdf_dp_trace_credit_record() - record credit update + * @source: source of record + * @operation: credit operation + * @delta: credit delta + * @total_credits: total credit + * @g0_credit: group 0 credit + * @g1_credit: group 1 credit + */ +void qdf_dp_trace_credit_record(enum QDF_CREDIT_UPDATE_SOURCE source, + enum QDF_CREDIT_OPERATION operation, + int delta, int total_credits, + int g0_credit, int g1_credit); + /** * qdf_dp_display_mgmt_pkt() - display proto packet * @record: dptrace record @@ -806,6 +867,17 @@ void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id, void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record, uint16_t index, uint8_t pdev_id, uint8_t info); +/** + * qdf_dp_display_credit_record() - display credit record + * @record: dptrace record + * @index: index + * @pdev_id: pdev id + * @info: metadeta info + */ +void qdf_dp_display_credit_record(struct qdf_dp_trace_record_s *record, + uint16_t index, uint8_t pdev_id, + uint8_t info); + /** * qdf_dp_display_event_record() - display event records * @record: dptrace record @@ -870,7 +942,7 @@ bool qdf_dp_trace_log_pkt(uint8_t vdev_id, struct sk_buff *skb, static inline void qdf_dp_trace_init(bool live_mode_config, uint8_t thresh, uint16_t time_limit, uint8_t verbosity, - uint8_t proto_bitmap) + uint32_t proto_bitmap) { } @@ -884,8 +956,8 @@ void qdf_dp_trace_set_track(qdf_nbuf_t nbuf, enum qdf_proto_dir dir) { } static inline -void qdf_dp_trace_set_value(uint8_t proto_bitmap, uint8_t no_of_records, - uint8_t verbosity) +void qdf_dp_trace_set_value(uint32_t proto_bitmap, uint8_t no_of_records, + uint8_t verbosity) { } @@ -1093,9 +1165,40 @@ qdf_tso_seg_dbg_zero(struct qdf_tso_seg_elem_t *tsoseg) #endif /* TSOSEG_DEBUG */ +/** + * qdf_trace_hex_dump() - externally called hex dump function + * @module: Module identifier a member of the QDF_MODULE_ID enumeration that + * identifies the module issuing the trace message. + * @level: Trace level a member of the QDF_TRACE_LEVEL enumeration indicating + * the severity of the condition causing the trace message to be + * issued. More severe conditions are more likely to be logged. + * @data: The base address of the buffer to be logged. + * @buf_len: The size of the buffer to be logged. + * + * Checks the level of severity and accordingly prints the trace messages + * + * Return: None + */ void qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, void *data, int buf_len); +/** + * qdf_trace_hex_ascii_dump() - externally called hex and ascii dump function + * @module: Module identifier a member of the QDF_MODULE_ID enumeration that + * identifies the module issuing the trace message. + * @level: Trace level a member of the QDF_TRACE_LEVEL enumeration indicating + * the severity of the condition causing the trace message to be + * issued. More severe conditions are more likely to be logged. + * @data: The base address of the buffer to be logged. + * @buf_len: The size of the buffer to be logged. + * + * Checks the level of severity and accordingly prints the trace messages + * + * Return: None + */ +void qdf_trace_hex_ascii_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, + void *data, int buf_len); + #define ERROR_CODE -1 #define QDF_MAX_NAME_SIZE 32 #define MAX_PRINT_CONFIG_SUPPORTED 32 @@ -1406,4 +1509,14 @@ void qdf_minidump_log(void *start_addr, size_t size, const char *name) __qdf_minidump_log(start_addr, size, name); } +/** + * qdf_minidump_remove() - Remove memory address from minidump + * @addr: Start address of the memory previously added + */ +static inline +void qdf_minidump_remove(void *addr) +{ + __qdf_minidump_remove(addr); +} + #endif /* __QDF_TRACE_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_types.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_types.h index 5eebbdd1e7ffb58a99eeb9f0901f6fbce8829a8a..87cf7569553f57c77305fc115ffbc3b0d86682ab 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_types.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_types.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -24,12 +25,6 @@ #if !defined(__QDF_TYPES_H) #define __QDF_TYPES_H -#ifndef CONFIG_MCL -#if !defined(__printf) -#define __printf(a, b) -#endif -#endif - #define qdf_must_check __qdf_must_check /* Include Files */ @@ -113,6 +108,15 @@ typedef void *qdf_pm_t; */ typedef void *qdf_handle_t; +/** + * typedef qdf_freq_t - define frequency as a 16 bit/32 bit + * unsigned integer depending on the requirement + */ +#ifdef CONFIG_16_BIT_FREQ_TYPE +typedef uint16_t qdf_freq_t; +#else +typedef uint32_t qdf_freq_t; +#endif /** * typedef qdf_device_t - Platform/bus generic handle. * Used for bus specific functions. @@ -199,7 +203,7 @@ typedef struct qdf_shared_mem { qdf_dma_mem_context(memctx); } qdf_shared_mem_t; -#define qdf_iomem_t __qdf_iomem_t; +#define qdf_iomem_t __qdf_iomem_t /** * typedef enum QDF_TIMER_TYPE - QDF timer type @@ -375,7 +379,13 @@ typedef bool (*qdf_irqlocked_func_t)(void *); * @QDF_MODULE_ID_TX_CAPTURE: Tx capture enhancement feature ID * @QDF_MODULE_ID_INTEROP_ISSUES_AP: interop issues ap module ID * @QDF_MODULE_ID_BLACKLIST_MGR: Blacklist Manager module + * @QDF_MODULE_ID_QLD: QCA Live Debug module ID + * @QDF_MODULE_ID_DYNAMIC_MODE_CHG: Dynamic mode change module ID + * @QDF_MODULE_ID_COEX: Coex related config module ID + * @QDF_MODULE_ID_FTM_TIME_SYNC: FTM Time sync module ID * @QDF_MODULE_ID_PKT_CAPTURE: PACKET CAPTURE module ID + * @QDF_MODULE_ID_MON_FILTER: Monitor filter related config module ID + * @QDF_MODULE_ID_GPIO: GPIO configuration module ID * @QDF_MODULE_ID_ANY: anything * @QDF_MODULE_ID_MAX: Max place holder module ID */ @@ -492,7 +502,13 @@ typedef enum { QDF_MODULE_ID_TX_CAPTURE, QDF_MODULE_ID_INTEROP_ISSUES_AP, QDF_MODULE_ID_BLACKLIST_MGR, + QDF_MODULE_ID_QLD, + QDF_MODULE_ID_DYNAMIC_MODE_CHG, + QDF_MODULE_ID_COEX, + QDF_MODULE_ID_FTM_TIME_SYNC, QDF_MODULE_ID_PKT_CAPTURE, + QDF_MODULE_ID_MON_FILTER, + QDF_MODULE_ID_GPIO = 123, QDF_MODULE_ID_ANY, QDF_MODULE_ID_MAX, } QDF_MODULE_ID; @@ -596,11 +612,14 @@ const char *qdf_opmode_str(const enum QDF_OPMODE opmode); * enum QDF_GLOBAL_MODE - global mode when driver is loaded. * * @QDF_GLOBAL_MISSION_MODE: mission mode (STA, SAP...) + * @QDF_GLOBAL_WALTEST_MODE: WAL Test Mode * @QDF_GLOBAL_MONITOR_MODE: Monitor Mode * @QDF_GLOBAL_FTM_MODE: FTM mode * @QDF_GLOBAL_IBSS_MODE: IBSS mode + * @QDF_GLOBAL_COLDBOOT_CALIB_MODEL: Cold Boot Calibration Mode * @QDF_GLOBAL_EPPING_MODE: EPPING mode * @QDF_GLOBAL_QVIT_MODE: QVIT global mode + * @QDF_GLOBAL_FTM_COLDBOOT_CALIB_MODE: Cold Boot Calibration in FTM Mode * @QDF_GLOBAL_MAX_MODE: Max place holder */ enum QDF_GLOBAL_MODE { @@ -612,44 +631,12 @@ enum QDF_GLOBAL_MODE { QDF_GLOBAL_COLDBOOT_CALIB_MODE = 7, QDF_GLOBAL_EPPING_MODE = 8, QDF_GLOBAL_QVIT_MODE = 9, + QDF_GLOBAL_FTM_COLDBOOT_CALIB_MODE = 10, QDF_GLOBAL_MAX_MODE }; #define QDF_IS_EPPING_ENABLED(mode) (mode == QDF_GLOBAL_EPPING_MODE) -/** - * qdf_trace_msg()- logging API - * @module: Module identifier. A member of the QDF_MODULE_ID enumeration that - * identifies the module issuing the trace message. - * @level: Trace level. A member of the QDF_TRACE_LEVEL enumeration indicating - * the severity of the condition causing the trace message to be issued. - * More severe conditions are more likely to be logged. - * @str_format: Format string. The message to be logged. This format string - * contains printf-like replacement parameters, which follow this - * parameter in the variable argument list. - * - * Users wishing to add tracing information to their code should use - * QDF_TRACE. QDF_TRACE() will compile into a call to qdf_trace_msg() when - * tracing is enabled. - * - * Return: nothing - * - * implemented in qdf_trace.c - */ -void __printf(3, 4) qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, - const char *str_format, ...); -/** - * qdf_vtrace_msg() - the va_list version of qdf_trace_msg - * @module: the calling module's Id - * @level: the logging level to log using - * @str_format: the log format string - * @val: the va_list containing the values to format according to str_format - * - * Return: None - */ -void qdf_vtrace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, - const char *str_format, va_list val); - #ifdef QDF_TRACE_PRINT_ENABLE #define qdf_print(args...) QDF_TRACE_INFO(QDF_MODULE_ID_ANY, ## args) #define qdf_alert(args...) QDF_TRACE_FATAL(QDF_MODULE_ID_ANY, ## args) @@ -709,7 +696,6 @@ void qdf_vtrace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, #define qdf_rl_nofl_debug(params...) \ QDF_TRACE_DEBUG_RL_NO_FL(QDF_MODULE_ID_QDF, ## params) -#define qdf_vprint __qdf_vprint #define qdf_snprint __qdf_snprint #define qdf_kstrtoint __qdf_kstrtoint @@ -830,8 +816,43 @@ QDF_STATUS qdf_int64_parse(const char *int_str, int64_t *out_int); QDF_STATUS qdf_uint64_parse(const char *int_str, uint64_t *out_int); #define QDF_MAC_ADDR_SIZE 6 -#define QDF_MAC_ADDR_STR "%02x:%02x:%02x:%02x:%02x:%02x" -#define QDF_MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] + +/** + * If the feature CONFIG_WLAN_TRACE_HIDE_MAC_ADDRESS is enabled, + * then the requirement is to hide 2nd, 3rd and 4th octet of the + * MAC address in the kernel logs and driver logs. + * But other management interfaces like ioctl, debugfs, sysfs, + * wext, unit test code or non-production simulator sw (iot_sim) + * should continue to log the full mac address. + * + * Developers must use QDF_FULL_MAC_FMT instead of "%pM", + * as this macro helps avoid accidentally breaking the feature + * CONFIG_WLAN_TRACE_HIDE_MAC_ADDRESS if enabled and code auditing + * becomes easy. + */ +#define QDF_FULL_MAC_FMT "%pM" +#define QDF_FULL_MAC_REF(a) (a) + +#if defined(WLAN_TRACE_HIDE_MAC_ADDRESS) +#define QDF_MAC_ADDR_FMT "%02x:**:**:**:%02x:%02x" + +/* + * The input data type for QDF_MAC_ADDR_REF can be pointer or an array. + * In case of array, compiler was throwing following warning + * 'address of array will always evaluate as ‘true’ + * and if the pointer is NULL, zero is passed to the format specifier + * which results in zero mac address (00:**:**:**:00:00) + * For this reason, input data type is typecasted to (uintptr_t). + */ +#define QDF_MAC_ADDR_REF(a) \ + (((uintptr_t)NULL != (uintptr_t)(a)) ? (a)[0] : 0), \ + (((uintptr_t)NULL != (uintptr_t)(a)) ? (a)[4] : 0), \ + (((uintptr_t)NULL != (uintptr_t)(a)) ? (a)[5] : 0) +#else +#define QDF_MAC_ADDR_FMT "%pM" +#define QDF_MAC_ADDR_REF(a) (a) +#endif /* WLAN_TRACE_HIDE_MAC_ADDRESS */ + #define QDF_MAC_ADDR_BCAST_INIT { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } #define QDF_MAC_ADDR_ZERO_INIT { { 0, 0, 0, 0, 0, 0 } } @@ -1018,6 +1039,22 @@ struct qdf_ipv6_addr { */ QDF_STATUS qdf_ipv6_parse(const char *ipv6_str, struct qdf_ipv6_addr *out_addr); +/** + * qdf_uint32_array_parse() - parse the given string as uint32 array + * @in_str: the input string to parse + * @out_array: the output uint32 array, populated on success + * @array_size: size of the array + * @out_size: size of the populated array + * + * This API is called to convert string (each value separated by + * a comma) into an uint32 array + * + * Return: QDF_STATUS + */ + +QDF_STATUS qdf_uint32_array_parse(const char *in_str, uint32_t *out_array, + qdf_size_t array_size, qdf_size_t *out_size); + /** * qdf_uint16_array_parse() - parse the given string as uint16 array * @in_str: the input string to parse @@ -1049,8 +1086,6 @@ QDF_STATUS qdf_uint16_array_parse(const char *in_str, uint16_t *out_array, QDF_STATUS qdf_uint8_array_parse(const char *in_str, uint8_t *out_array, qdf_size_t array_size, qdf_size_t *out_size); -#define QDF_MAX_NUM_CHAN (128) - #define QDF_BCAST_MAC_ADDR (0xFF) #define QDF_MCAST_IPV4_MAC_ADDR (0x01) #define QDF_MCAST_IPV6_MAC_ADDR (0x33) @@ -1286,19 +1321,45 @@ enum qdf_suspend_type { * @QDF_SUSPEND_TIMEOUT: Timeout for an ACK from FW for suspend request * @QDF_RESUME_TIMEOUT: Timeout for an ACK from FW for resume request * @QDF_WMI_EXCEED_MAX_PENDING_CMDS: wmi exceed max pending cmd + * @QDF_AP_STA_CONNECT_REQ_TIMEOUT: SAP peer assoc timeout from FW + * @QDF_STA_AP_CONNECT_REQ_TIMEOUT: STA peer assoc timeout from FW + * @QDF_MAC_HW_MODE_CHANGE_TIMEOUT: HW mode change timeout from FW + * @QDF_MAC_HW_MODE_CONFIG_TIMEOUT: HW dual mac cfg timeout from FW + * @QDF_VDEV_START_RESPONSE_TIMED_OUT: Start response timeout from FW + * @QDF_VDEV_RESTART_RESPONSE_TIMED_OUT: Restart response timeout from FW + * @QDF_VDEV_STOP_RESPONSE_TIMED_OUT: Stop response timeout from FW + * @QDF_VDEV_DELETE_RESPONSE_TIMED_OUT: Delete response timeout from FW + * @QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT: Peer delete all resp timeout + * @QDF_WMI_BUF_SEQUENCE_MISMATCH: WMI Tx completion buffer sequence mismatch + * @QDF_HAL_REG_WRITE_FAILURE: HAL register writing failures + * @QDF_SUSPEND_NO_CREDIT: host lack of credit after suspend + * @QCA_HANG_BUS_FAILURE: Bus failure */ enum qdf_hang_reason { - QDF_REASON_UNSPECIFIED = 0, - QDF_RX_HASH_NO_ENTRY_FOUND = 1, - QDF_PEER_DELETION_TIMEDOUT = 2, - QDF_PEER_UNMAP_TIMEDOUT = 3, - QDF_SCAN_REQ_EXPIRED = 4, - QDF_SCAN_ATTEMPT_FAILURES = 5, - QDF_GET_MSG_BUFF_FAILURE = 6, - QDF_ACTIVE_LIST_TIMEOUT = 7, - QDF_SUSPEND_TIMEOUT = 8, - QDF_RESUME_TIMEOUT = 9, - QDF_WMI_EXCEED_MAX_PENDING_CMDS = 10, + QDF_REASON_UNSPECIFIED, + QDF_RX_HASH_NO_ENTRY_FOUND, + QDF_PEER_DELETION_TIMEDOUT, + QDF_PEER_UNMAP_TIMEDOUT, + QDF_SCAN_REQ_EXPIRED, + QDF_SCAN_ATTEMPT_FAILURES, + QDF_GET_MSG_BUFF_FAILURE, + QDF_ACTIVE_LIST_TIMEOUT, + QDF_SUSPEND_TIMEOUT, + QDF_RESUME_TIMEOUT, + QDF_WMI_EXCEED_MAX_PENDING_CMDS, + QDF_AP_STA_CONNECT_REQ_TIMEOUT, + QDF_STA_AP_CONNECT_REQ_TIMEOUT, + QDF_MAC_HW_MODE_CHANGE_TIMEOUT, + QDF_MAC_HW_MODE_CONFIG_TIMEOUT, + QDF_VDEV_START_RESPONSE_TIMED_OUT, + QDF_VDEV_RESTART_RESPONSE_TIMED_OUT, + QDF_VDEV_STOP_RESPONSE_TIMED_OUT, + QDF_VDEV_DELETE_RESPONSE_TIMED_OUT, + QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT, + QDF_WMI_BUF_SEQUENCE_MISMATCH, + QDF_HAL_REG_WRITE_FAILURE, + QDF_SUSPEND_NO_CREDIT, + QCA_HANG_BUS_FAILURE, }; /** diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_util.h b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_util.h index d0e4077487bfd2d42060da3b71c9c031f7773226..2710afefcdf6004dff9e5c9878d7fee0460a8734 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_util.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/inc/qdf_util.h @@ -51,6 +51,11 @@ typedef __qdf_wait_queue_head_t qdf_wait_queue_head_t; */ #define qdf_wmb() __qdf_wmb() +/** + * qdf_rmb - read memory barrier. + */ +#define qdf_rmb() __qdf_rmb() + /** * qdf_mb - read + write memory barrier. */ @@ -766,4 +771,17 @@ int qdf_hex_str_to_binary(u8 *dst, const char *src, size_t count) return __qdf_hex_str_to_binary(dst, src, count); } +/** + * qdf_fls() - find last set bit in a given 32 bit input + * @x: 32 bit mask + * + * Return: zero if the input is zero, otherwise returns the bit + * position of the last set bit, where the LSB is 1 and MSB is 32. + */ +static inline +int qdf_fls(uint32_t x) +{ + return __qdf_fls(x); +} + #endif /*_QDF_UTIL_H*/ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_osdep.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_osdep.h index 9b80428defc5cbb4fa92a0eb54b2d67af27d5377..877f43f757f2fa848f11db957d7a83b610611ce1 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_osdep.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_osdep.h @@ -24,11 +24,7 @@ #ifndef _I_OSDEP_H #define _I_OSDEP_H -#ifdef CONFIG_MCL -#include -#else -#include -#endif +#include "queue.h" /* * Byte Order stuff @@ -54,8 +50,8 @@ do { \ if (!spin_is_locked(x)) { \ WARN_ON(1); \ - printk(KERN_EMERG " %s:%d unlock addr=%pK, %s \n", __func__, __LINE__, x, \ - !spin_is_locked(x) ? "Not locked" : ""); \ + qdf_info("unlock addr=%pK, %s", x, \ + !spin_is_locked(x) ? "Not locked" : ""); \ } \ spin_unlock_bh(x); \ } while (0) diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_atomic.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_atomic.h index 1af747d6aa86a728a47d319f961294220d523791..1d2cb2b30a879d72883684e065ff672f30c632ba 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_atomic.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_atomic.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -147,6 +147,17 @@ static inline int32_t __qdf_atomic_dec_return(__qdf_atomic_t *v) return atomic_dec_return(v); } +/** + * __qdf_atomic_inc_not_zero() - increment if not zero + * @v: A pointer to an opaque atomic variable + * + * Return: Returns non-zero on successful increment and zero otherwise + */ +static inline int32_t __qdf_atomic_inc_not_zero(__qdf_atomic_t *v) +{ + return atomic_inc_not_zero(v); +} + /** * __qdf_atomic_set_bit - Atomically set a bit in memory * @nr: bit to set diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_hashtable.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_hashtable.h index f1806cbf1d763d2bf0ba8b8d6f682649600820bb..f9ad3806e71b257d5853e515d5bddf6eebf4638e 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_hashtable.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_hashtable.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 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 @@ -47,4 +47,7 @@ do { \ break; \ } while (false) +#define __qdf_ht_for_each_safe(table, i, tmp, cursor, entry_field) \ + hash_for_each_safe(table, i, tmp, cursor, entry_field) + #endif /* __I_QDF_HASHTABLE_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_hrtimer.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_hrtimer.h index d72db5700bb4de5b8abecf8ab178e29d4f5f23d3..00055036f9411949c5f2303c80dbb5e868441dc8 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_hrtimer.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_hrtimer.h @@ -34,7 +34,9 @@ typedef struct { union { struct hrtimer hrtimer; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) struct tasklet_hrtimer tasklet_hrtimer; +#endif } u; enum qdf_context_mode ctx; } __qdf_hrtimer_data_t; @@ -63,6 +65,16 @@ enum hrtimer_mode __qdf_hrtimer_get_mode(enum qdf_hrtimer_mode mode) * * Return: void */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static inline +void __qdf_hrtimer_start(__qdf_hrtimer_data_t *timer, ktime_t interval, + enum qdf_hrtimer_mode mode) +{ + enum hrtimer_mode hrt_mode = __qdf_hrtimer_get_mode(mode); + + hrtimer_start(&timer->u.hrtimer, interval, hrt_mode); +} +#else static inline void __qdf_hrtimer_start(__qdf_hrtimer_data_t *timer, ktime_t interval, enum qdf_hrtimer_mode mode) @@ -75,6 +87,7 @@ void __qdf_hrtimer_start(__qdf_hrtimer_data_t *timer, ktime_t interval, tasklet_hrtimer_start(&timer->u.tasklet_hrtimer, interval, hrt_mode); } +#endif /** * __qdf_hrtimer_cancel() - cancels hrtimer in given context @@ -84,6 +97,16 @@ void __qdf_hrtimer_start(__qdf_hrtimer_data_t *timer, ktime_t interval, * * Return: int */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static inline +int __qdf_hrtimer_cancel(__qdf_hrtimer_data_t *timer) +{ + if (timer->ctx == QDF_CONTEXT_HARDWARE) + return hrtimer_cancel(&timer->u.hrtimer); + + return 0; +} +#else static inline int __qdf_hrtimer_cancel(__qdf_hrtimer_data_t *timer) { @@ -94,6 +117,7 @@ int __qdf_hrtimer_cancel(__qdf_hrtimer_data_t *timer) return 0; } +#endif /** * __qdf_hrtimer_init() - init hrtimer in a given context @@ -106,6 +130,26 @@ int __qdf_hrtimer_cancel(__qdf_hrtimer_data_t *timer) * * Return: void */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static inline void __qdf_hrtimer_init(__qdf_hrtimer_data_t *timer, + void *cback, + enum qdf_clock_id clock, + enum qdf_hrtimer_mode mode, + enum qdf_context_mode ctx) +{ + struct hrtimer *hrtimer = &timer->u.hrtimer; + enum hrtimer_mode hrt_mode = __qdf_hrtimer_get_mode(mode); + + timer->ctx = ctx; + + if (timer->ctx == QDF_CONTEXT_HARDWARE) { + hrtimer_init(hrtimer, clock, hrt_mode); + hrtimer->function = cback; + } else if (timer->ctx == QDF_CONTEXT_TASKLET) { + QDF_BUG(0); + } +} +#else static inline void __qdf_hrtimer_init(__qdf_hrtimer_data_t *timer, void *cback, enum qdf_clock_id clock, @@ -125,6 +169,7 @@ static inline void __qdf_hrtimer_init(__qdf_hrtimer_data_t *timer, tasklet_hrtimer_init(tasklet_hrtimer, cback, clock, hrt_mode); } } +#endif /** * __qdf_hrtimer_kill() - kills hrtimer in given context @@ -134,6 +179,13 @@ static inline void __qdf_hrtimer_init(__qdf_hrtimer_data_t *timer, * * Return: void */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static inline +void __qdf_hrtimer_kill(__qdf_hrtimer_data_t *timer) +{ + hrtimer_cancel(&timer->u.hrtimer); +} +#else static inline void __qdf_hrtimer_kill(__qdf_hrtimer_data_t *timer) { @@ -142,6 +194,7 @@ void __qdf_hrtimer_kill(__qdf_hrtimer_data_t *timer) else if (timer->ctx == QDF_CONTEXT_TASKLET) tasklet_hrtimer_cancel(&timer->u.tasklet_hrtimer); } +#endif /** * __qdf_hrtimer_get_remaining() - check remaining time in the timer @@ -151,6 +204,14 @@ void __qdf_hrtimer_kill(__qdf_hrtimer_data_t *timer) * * Return: remaining time as ktime object */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static inline ktime_t __qdf_hrtimer_get_remaining(__qdf_hrtimer_data_t *timer) +{ + struct hrtimer *hrtimer = &timer->u.hrtimer; + + return hrtimer_get_remaining(hrtimer); +} +#else static inline ktime_t __qdf_hrtimer_get_remaining(__qdf_hrtimer_data_t *timer) { struct hrtimer *hrtimer = &timer->u.hrtimer; @@ -161,6 +222,7 @@ static inline ktime_t __qdf_hrtimer_get_remaining(__qdf_hrtimer_data_t *timer) else return hrtimer_get_remaining(&tasklet_hrtimer->timer); } +#endif /** * __qdf_hrtimer_is_queued() - check whether the timer is on one of the queues @@ -171,6 +233,14 @@ static inline ktime_t __qdf_hrtimer_get_remaining(__qdf_hrtimer_data_t *timer) * Return: false when the timer was not in queue * true when the timer was in queue */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static inline bool __qdf_hrtimer_is_queued(__qdf_hrtimer_data_t *timer) +{ + struct hrtimer *hrtimer = &timer->u.hrtimer; + + return hrtimer_is_queued(hrtimer); +} +#else static inline bool __qdf_hrtimer_is_queued(__qdf_hrtimer_data_t *timer) { struct hrtimer *hrtimer = &timer->u.hrtimer; @@ -181,6 +251,7 @@ static inline bool __qdf_hrtimer_is_queued(__qdf_hrtimer_data_t *timer) else return hrtimer_is_queued(&tasklet_hrtimer->timer); } +#endif /** * __qdf_hrtimer_callback_running() - check if callback is running @@ -191,6 +262,14 @@ static inline bool __qdf_hrtimer_is_queued(__qdf_hrtimer_data_t *timer) * Return: false when callback is not running * true when callback is running */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static inline bool __qdf_hrtimer_callback_running(__qdf_hrtimer_data_t *timer) +{ + struct hrtimer *hrtimer = &timer->u.hrtimer; + + return hrtimer_callback_running(hrtimer); +} +#else static inline bool __qdf_hrtimer_callback_running(__qdf_hrtimer_data_t *timer) { struct hrtimer *hrtimer = &timer->u.hrtimer; @@ -201,6 +280,7 @@ static inline bool __qdf_hrtimer_callback_running(__qdf_hrtimer_data_t *timer) else return hrtimer_callback_running(&tasklet_hrtimer->timer); } +#endif /** * __qdf_hrtimer_active() - check if timer is active @@ -212,6 +292,14 @@ static inline bool __qdf_hrtimer_callback_running(__qdf_hrtimer_data_t *timer) * Return: false if timer is not active * true if timer is active */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static inline bool __qdf_hrtimer_active(__qdf_hrtimer_data_t *timer) +{ + struct hrtimer *hrtimer = &timer->u.hrtimer; + + return hrtimer_active(hrtimer); +} +#else static inline bool __qdf_hrtimer_active(__qdf_hrtimer_data_t *timer) { struct hrtimer *hrtimer = &timer->u.hrtimer; @@ -222,6 +310,7 @@ static inline bool __qdf_hrtimer_active(__qdf_hrtimer_data_t *timer) else return hrtimer_active(&tasklet_hrtimer->timer); } +#endif /** * __qdf_hrtimer_cb_get_time() - get remaining time in callback @@ -231,6 +320,14 @@ static inline bool __qdf_hrtimer_active(__qdf_hrtimer_data_t *timer) * * Return: time remaining as ktime object */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static inline ktime_t __qdf_hrtimer_cb_get_time(__qdf_hrtimer_data_t *timer) +{ + struct hrtimer *hrtimer = &timer->u.hrtimer; + + return hrtimer_cb_get_time(hrtimer); +} +#else static inline ktime_t __qdf_hrtimer_cb_get_time(__qdf_hrtimer_data_t *timer) { struct hrtimer *hrtimer = &timer->u.hrtimer; @@ -241,6 +338,7 @@ static inline ktime_t __qdf_hrtimer_cb_get_time(__qdf_hrtimer_data_t *timer) else return hrtimer_cb_get_time(&tasklet_hrtimer->timer); } +#endif /** * __qdf_hrtimer_forward() - forward the hrtimer @@ -252,6 +350,16 @@ static inline ktime_t __qdf_hrtimer_cb_get_time(__qdf_hrtimer_data_t *timer) * * Return:the number of overruns */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static inline uint64_t __qdf_hrtimer_forward(__qdf_hrtimer_data_t *timer, + ktime_t now, + ktime_t interval) +{ + struct hrtimer *hrtimer = &timer->u.hrtimer; + + return hrtimer_forward(hrtimer, now, interval); +} +#else static inline uint64_t __qdf_hrtimer_forward(__qdf_hrtimer_data_t *timer, ktime_t now, ktime_t interval) @@ -264,5 +372,6 @@ static inline uint64_t __qdf_hrtimer_forward(__qdf_hrtimer_data_t *timer, else return hrtimer_forward(&tasklet_hrtimer->timer, now, interval); } +#endif #endif /* _I_QDF_HRTIMER_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_ipa.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_ipa.h index 0b3628896f6bbd0303d359bd4bd0f42b608312f4..273f5a3748ccfe92a874a80a2a06372b87601820 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_ipa.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_ipa.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, 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 above @@ -20,6 +20,7 @@ #ifdef IPA_OFFLOAD #include +#include /** * __qdf_ipa_wdi_meter_evt_type_t - type of event client callback is @@ -378,10 +379,40 @@ typedef struct ipa_wdi_buffer_info __qdf_ipa_wdi_buffer_info_t; typedef struct ipa_gsi_ep_config __qdf_ipa_gsi_ep_config_t; #ifdef WDI3_STATS_UPDATE +/** + * __qdf_ipa_wdi_tx_info_t - WLAN embedded TX information + */ typedef struct ipa_wdi_tx_info __qdf_ipa_wdi_tx_info_t; + +#define QDF_IPA_WDI_TX_INFO_STA_TX_BYTES(stats_info) \ + (((struct ipa_wdi_tx_info *)stats_info)->sta_tx) +#define QDF_IPA_WDI_TX_INFO_SAP_TX_BYTES(stats_info) \ + (((struct ipa_wdi_tx_info *)stats_info)->ap_tx) +/** + * __qdf_ipa_wdi_bw_info_t - BW levels to be monitored by uC + */ typedef struct ipa_wdi_bw_info __qdf_ipa_wdi_bw_info_t; + +#define QDF_IPA_WDI_BW_INFO_THRESHOLD_LEVEL_1(bw_info) \ + (((struct ipa_wdi_bw_info *)bw_info)->threshold[0]) +#define QDF_IPA_WDI_BW_INFO_THRESHOLD_LEVEL_2(bw_info) \ + (((struct ipa_wdi_bw_info *)bw_info)->threshold[1]) +#define QDF_IPA_WDI_BW_INFO_THRESHOLD_LEVEL_3(bw_info) \ + (((struct ipa_wdi_bw_info *)bw_info)->threshold[2]) +#define QDF_IPA_WDI_BW_INFO_START_STOP(bw_info) \ + (((struct ipa_wdi_bw_info *)bw_info)->stop) + +/** + * __qdf_ipa_inform_wlan_bw_t - BW information given by IPA driver + */ typedef struct ipa_inform_wlan_bw __qdf_ipa_inform_wlan_bw_t; -#endif + +#define QDF_IPA_INFORM_WLAN_BW_INDEX(bw_inform) \ + (((struct ipa_inform_wlan_bw*)bw_inform)->index) +#define QDF_IPA_INFORM_WLAN_BW_THROUGHPUT(bw_inform) \ + (((struct ipa_inform_wlan_bw*)bw_inform)->throughput) + +#endif /* WDI3_STATS_UPDATE */ /** * __qdf_ipa_dp_evt_type_t - type of event client callback is @@ -524,6 +555,10 @@ typedef struct ipa_wlan_hdr_attrib_val __qdf_ipa_wlan_hdr_attrib_val_t; #define __QDF_IPA_CLIENT_WLAN3_CONS IPA_CLIENT_WLAN3_CONS #define __QDF_IPA_CLIENT_WLAN4_CONS IPA_CLIENT_WLAN4_CONS +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) +#define IPA_LAN_RX_NAPI_SUPPORT +#endif + /* * Resume / Suspend */ @@ -937,5 +972,16 @@ static bool __qdf_get_ipa_smmu_enabled(void) } #endif +#ifdef IPA_LAN_RX_NAPI_SUPPORT +/** + * ipa_get_lan_rx_napi() - Check if NAPI is enabled in LAN RX DP + * + * Returns: true if enabled, false otherwise + */ +static inline bool __qdf_ipa_get_lan_rx_napi(void) +{ + return ipa_get_lan_rx_napi(); +} +#endif /* IPA_LAN_RX_NAPI_SUPPORT */ #endif /* IPA_OFFLOAD */ #endif /* _I_QDF_IPA_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_mem.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_mem.h index 95590d986c3df638d8fe271ba8d512c8db8c95cb..cdb5b3e8f870723adfd4ced1cc6390f6d1ad85d8 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_mem.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_mem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -39,11 +39,8 @@ #include /* L1_CACHE_BYTES */ #define __qdf_cache_line_sz L1_CACHE_BYTES -#if defined(CONFIG_MCL) -#include -#else -#include -#endif +#include "queue.h" + #else /* * Provide dummy defs for kernel data types, functions, and enums @@ -63,7 +60,9 @@ #if IS_ENABLED(CONFIG_ARM_SMMU) #include +#ifdef ENABLE_SMMU_S1_TRANSLATION #include +#endif #include #endif @@ -99,8 +98,19 @@ typedef struct __qdf_mempool_ctxt { #endif /* __KERNEL__ */ +#define __page_size ((size_t)PAGE_SIZE) #define __qdf_align(a, mask) ALIGN(a, mask) +#ifdef DISABLE_MEMDEBUG_PANIC +#define QDF_MEMDEBUG_PANIC(reason_fmt, args...) \ + do { \ + /* no-op */ \ + } while (false) +#else +#define QDF_MEMDEBUG_PANIC(reason_fmt, args...) \ + QDF_DEBUG_PANIC(reason_fmt, ## args) +#endif + /* typedef for dma_data_direction */ typedef enum dma_data_direction __dma_data_direction; @@ -210,7 +220,7 @@ static inline bool __qdf_mem_smmu_s1_enabled(qdf_device_t osdev) return osdev->smmu_s1_enabled; } -#if IS_ENABLED(CONFIG_ARM_SMMU) +#if IS_ENABLED(CONFIG_ARM_SMMU) && defined(ENABLE_SMMU_S1_TRANSLATION) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) /** * __qdf_dev_get_domain() - get iommu domain from osdev @@ -441,4 +451,61 @@ __qdf_mem_set_dma_pa(qdf_device_t osdev, { mem_info->pa = dma_pa; } + +/** + * __qdf_mem_alloc_consistent() - allocates consistent qdf memory + * @osdev: OS device handle + * @dev: Pointer to device handle + * @size: Size to be allocated + * @paddr: Physical address + * @func: Function name of the call site + * @line: line numbe rof the call site + * + * Return: pointer of allocated memory or null if memory alloc fails + */ +void *__qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev, + qdf_size_t size, qdf_dma_addr_t *paddr, + const char *func, uint32_t line); + +/** + * __qdf_mem_malloc() - allocates QDF memory + * @size: Number of bytes of memory to allocate. + * + * @func: Function name of the call site + * @line: line numbe rof the call site + * + * This function will dynamicallly allocate the specified number of bytes of + * memory. + * + * Return: + * Upon successful allocate, returns a non-NULL pointer to the allocated + * memory. If this function is unable to allocate the amount of memory + * specified (for any reason) it returns NULL. + */ +void *__qdf_mem_malloc(qdf_size_t size, const char *func, uint32_t line); + +/** + * __qdf_mem_free() - free QDF memory + * @ptr: Pointer to the starting address of the memory to be freed. + * + * This function will free the memory pointed to by 'ptr'. + * Return: None + */ +void __qdf_mem_free(void *ptr); + +/** + * __qdf_mem_free_consistent() - free consistent qdf memory + * @osdev: OS device handle + * @dev: Pointer to device handle + * @size: Size to be allocated + * @vaddr: virtual address + * @paddr: Physical address + * @memctx: Pointer to DMA context + * + * Return: none + */ +void __qdf_mem_free_consistent(qdf_device_t osdev, void *dev, + qdf_size_t size, void *vaddr, + qdf_dma_addr_t paddr, qdf_dma_context_t memctx); + #endif /* __I_QDF_MEM_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf.h index d1a81b932f1a45ad9d09adeab0d0b22390f5022f..5d6dc425abb43756abc0dab2746fae215244978d 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -101,29 +101,31 @@ typedef union { * @rx.dev.priv_cb_w.fctx: ctx to handle special pkts defined by ftype * @rx.dev.priv_cb_w.msdu_len: length of RX packet * @rx.dev.priv_cb_w.peer_id: peer_id for RX packet - * @rx.dev.priv_cb_w.protocol_tag: protocol tag set by application for - * received packet type - * @rx.dev.priv_cb_w.reserved1: reserved for flow tag set by application - * for 5 tuples received - * + * @rx.dev.priv_cb_w.protocol_tag: protocol tag set by app for rcvd packet type + * @rx.dev.priv_cb_w.flow_tag: flow tag set by application for 5 tuples rcvd + * + * @rx.dev.priv_cb_m.peer_cached_buf_frm: peer cached buffer + * @rx.dev.priv_cb_m.flush_ind: flush indication + * @rx.dev.priv_cb_m.packet_buf_pool: packet buff bool + * @rx.dev.priv_cb_m.l3_hdr_pad: L3 header padding offset + * @rx.dev.priv_cb_m.exc_frm: exception frame + * @rx.dev.priv_cb_m.reo_dest_ind: reo destination indication + * @rx.dev.priv_cb_m.ipa_smmu_map: do IPA smmu map * @rx.dev.priv_cb_m.tcp_seq_num: TCP sequence number * @rx.dev.priv_cb_m.tcp_ack_num: TCP ACK number * @rx.dev.priv_cb_m.lro_ctx: LRO context * @rx.dev.priv_cb_m.dp.wifi3.msdu_len: length of RX packet * @rx.dev.priv_cb_m.dp.wifi3.peer_id: peer_id for RX packet * @rx.dev.priv_cb_m.dp.wifi2.map_index: - * @rx.dev.priv_cb_m.vdev_id: vdev_id for RX pkt * @rx.dev.priv_cb_m.ipa_owned: packet owned by IPA * * @rx.lro_eligible: flag to indicate whether the MSDU is LRO eligible - * @rx.peer_cached_buf_frm: peer cached buffer * @rx.tcp_proto: L4 protocol is TCP * @rx.tcp_pure_ack: A TCP ACK packet with no payload * @rx.ipv6_proto: L3 protocol is IPV6 * @rx.ip_offset: offset to IP header * @rx.tcp_offset: offset to TCP header * @rx_ctx_id: Rx context id - * @flush_ind: flush indication * @num_elements_in_list: number of elements in the nbuf list * * @rx.tcp_udp_chksum: L4 payload checksum @@ -134,7 +136,7 @@ typedef union { * @rx.flag_chfrag_start: first MSDU in an AMSDU * @rx.flag_chfrag_cont: middle or part of MSDU in an AMSDU * @rx.flag_chfrag_end: last MSDU in an AMSDU - * @rx.packet_buff_pool: indicate packet from pre-allocated pool for Rx ring + * @rx.flag_retry: flag to indicate MSDU is retried * @rx.flag_da_mcbc: flag to indicate mulicast or broadcast packets * @rx.flag_da_valid: flag to indicate DA is valid for RX packet * @rx.flag_sa_valid: flag to indicate SA is valid for RX packet @@ -148,12 +150,12 @@ typedef union { * @rx.trace.packet_track: RX_DATA packet * @rx.trace.rsrvd: enable packet logging * - * @rx.ftype: mcast2ucast, TSO, SG, MESH + * @rx.vdev_id: vdev_id for RX pkt * @rx.is_raw_frame: RAW frame * @rx.fcs_err: FCS error * @rx.tid_val: tid value - * @rx.flag_retry: flag to indicate MSDU is retried * @rx.reserved: reserved + * @rx.ftype: mcast2ucast, TSO, SG, MESH * * @tx.dev.priv_cb_w.fctx: ctx to handle special pkts defined by ftype * @tx.dev.priv_cb_w.ext_cb_ptr: extended cb pointer @@ -213,7 +215,7 @@ struct qdf_nbuf_cb { uint16_t msdu_len; uint16_t peer_id; uint16_t protocol_tag; - uint16_t reserved1; + uint16_t flow_tag; } priv_cb_w; struct { /* ipa_owned bit is common between rx @@ -221,9 +223,16 @@ struct qdf_nbuf_cb { * Do not change location of this bit. */ uint32_t ipa_owned:1, - reserved:15, - vdev_id:8, - reserved1:8; + peer_cached_buf_frm:1, + flush_ind:1, + packet_buf_pool:1, + reserved:4, + l3_hdr_pad:8, + /* exception frame flag */ + exc_frm:1, + reo_dest_ind:5, + ipa_smmu_map:1, + reserved1:9; uint32_t tcp_seq_num; uint32_t tcp_ack_num; union { @@ -239,14 +248,14 @@ struct qdf_nbuf_cb { } priv_cb_m; } dev; uint32_t lro_eligible:1, - peer_cached_buf_frm:1, tcp_proto:1, tcp_pure_ack:1, ipv6_proto:1, ip_offset:7, tcp_offset:7, rx_ctx_id:4, - flush_ind:1, + fcs_err:1, + is_raw_frame:1, num_elements_in_list:8; uint32_t tcp_udp_chksum:16, tcp_win:16; @@ -254,7 +263,7 @@ struct qdf_nbuf_cb { uint8_t flag_chfrag_start:1, flag_chfrag_cont:1, flag_chfrag_end:1, - packet_buff_pool:1, + flag_retry:1, flag_da_mcbc:1, flag_da_valid:1, flag_sa_valid:1, @@ -265,12 +274,9 @@ struct qdf_nbuf_cb { packet_track:4, rsrvd:3; } trace; - uint8_t ftype; - uint8_t is_raw_frame:1, - fcs_err:1, - tid_val:4, - flag_retry:1, - reserved:1; + uint16_t vdev_id:8, + tid_val:4, + ftype:4; } rx; /* Note: MAX: 40 bytes */ @@ -349,8 +355,6 @@ QDF_COMPILE_TIME_ASSERT(qdf_nbuf_cb_size, #define QDF_NBUF_CB_RX_LRO_ELIGIBLE(skb) \ (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.lro_eligible) -#define QDF_NBUF_CB_RX_PEER_CACHED_FRM(skb) \ - (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.peer_cached_buf_frm) #define QDF_NBUF_CB_RX_TCP_PROTO(skb) \ (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.tcp_proto) #define QDF_NBUF_CB_RX_TCP_PURE_ACK(skb) \ @@ -363,8 +367,6 @@ QDF_COMPILE_TIME_ASSERT(qdf_nbuf_cb_size, (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.tcp_offset) #define QDF_NBUF_CB_RX_CTX_ID(skb) \ (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.rx_ctx_id) -#define QDF_NBUF_CB_RX_FLUSH_IND(skb) \ - (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.flush_ind) #define QDF_NBUF_CB_RX_NUM_ELEMENTS_IN_LIST(skb) \ (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.num_elements_in_list) @@ -384,6 +386,9 @@ QDF_COMPILE_TIME_ASSERT(qdf_nbuf_cb_size, #define QDF_NBUF_CB_RX_FTYPE(skb) \ (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.ftype) +#define QDF_NBUF_CB_RX_VDEV_ID(skb) \ + (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.vdev_id) + #define QDF_NBUF_CB_RX_CHFRAG_START(skb) \ (((struct qdf_nbuf_cb *) \ ((skb)->cb))->u.rx.flag_chfrag_start) @@ -393,9 +398,6 @@ QDF_COMPILE_TIME_ASSERT(qdf_nbuf_cb_size, #define QDF_NBUF_CB_RX_CHFRAG_END(skb) \ (((struct qdf_nbuf_cb *) \ ((skb)->cb))->u.rx.flag_chfrag_end) -#define QDF_NBUF_CB_RX_PACKET_BUFF_POOL(skb) \ - (((struct qdf_nbuf_cb *) \ - ((skb)->cb))->u.rx.packet_buff_pool) #define QDF_NBUF_CB_RX_DA_MCBC(skb) \ (((struct qdf_nbuf_cb *) \ @@ -1474,9 +1476,23 @@ void __qdf_nbuf_unmap_tso_segment(qdf_device_t osdev, bool is_last_seg); #ifdef FEATURE_TSO +/** + * __qdf_nbuf_get_tcp_payload_len() - function to return the tcp + * payload len + * @skb: buffer + * + * Return: size + */ +size_t __qdf_nbuf_get_tcp_payload_len(struct sk_buff *skb); uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb); #else +static inline +size_t __qdf_nbuf_get_tcp_payload_len(struct sk_buff *skb) +{ + return 0; +} + static inline uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb) { return 0; @@ -1903,6 +1919,21 @@ __qdf_nbuf_expand(struct sk_buff *skb, uint32_t headroom, uint32_t tailroom) return NULL; } +/** + * __qdf_nbuf_copy_expand() - copy and expand nbuf + * @buf: Network buf instance + * @headroom: Additional headroom to be added + * @tailroom: Additional tailroom to be added + * + * Return: New nbuf that is a copy of buf, with additional head and tailroom + * or NULL if there is no memory + */ +static inline struct sk_buff * +__qdf_nbuf_copy_expand(struct sk_buff *buf, int headroom, int tailroom) +{ + return skb_copy_expand(buf, headroom, tailroom, GFP_ATOMIC); +} + /** * __qdf_nbuf_tx_cksum_info() - tx checksum info * @@ -2235,7 +2266,7 @@ void __qdf_nbuf_queue_head_unlock(struct sk_buff_head *skb_queue_head) spin_unlock_bh(&skb_queue_head->lock); } -#ifdef CONFIG_WIN +#ifdef CONFIG_NBUF_AP_PLATFORM #include #else #include diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf_m.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf_m.h index 296494c8aca95108fddc24a8df88573b1a979c15..69f594883c380d98deb3695f90c760aaf9167e48 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf_m.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf_m.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -34,9 +34,6 @@ #define QDF_NBUF_CB_RX_LRO_CTX(skb) \ (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.dev.priv_cb_m.lro_ctx) -#define QDF_NBUF_CB_RX_VDEV_ID(skb) \ - (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.dev.priv_cb_m.vdev_id) - #define QDF_NBUF_CB_TX_IPA_OWNED(skb) \ (((struct qdf_nbuf_cb *)((skb)->cb))->u.tx.dev.priv_cb_m.ipa.owned) #define QDF_NBUF_CB_TX_IPA_PRIV(skb) \ @@ -61,6 +58,33 @@ (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.dev.priv_cb_m.dp. \ wifi2.map_index) +#define QDF_NBUF_CB_RX_PEER_CACHED_FRM(skb) \ + (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.dev.priv_cb_m. \ + peer_cached_buf_frm) + +#define QDF_NBUF_CB_RX_FLUSH_IND(skb) \ + (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.dev.priv_cb_m.flush_ind) + +#define QDF_NBUF_CB_RX_PACKET_BUFF_POOL(skb) \ + (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.dev.priv_cb_m. \ + packet_buf_pool) + +#define QDF_NBUF_CB_RX_PACKET_L3_HDR_PAD(skb) \ + (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.dev.priv_cb_m. \ + l3_hdr_pad) + +#define QDF_NBUF_CB_RX_PACKET_EXC_FRAME(skb) \ + (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.dev.priv_cb_m. \ + exc_frm) + +#define QDF_NBUF_CB_RX_PACKET_REO_DEST_IND(skb) \ + (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.dev.priv_cb_m. \ + reo_dest_ind) + +#define QDF_NBUF_CB_RX_PACKET_IPA_SMMU_MAP(skb) \ + (((struct qdf_nbuf_cb *)((skb)->cb))->u.rx.dev.priv_cb_m. \ + ipa_smmu_map) + #define __qdf_nbuf_ipa_owned_get(skb) \ QDF_NBUF_CB_TX_IPA_OWNED(skb) diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf_w.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf_w.h index 893c86d2908f0e1650ca7525ad2fab176ea1413f..4657186c71584fd38c009931db63df97d23fe97e 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf_w.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_nbuf_w.h @@ -82,6 +82,16 @@ #define __qdf_nbuf_get_rx_protocol_tag(skb) \ (QDF_NBUF_CB_RX_PROTOCOL_TAG((skb))) +#define QDF_NBUF_CB_RX_FLOW_TAG(skb) \ + (((struct qdf_nbuf_cb *) \ + ((skb)->cb))->u.rx.dev.priv_cb_w.flow_tag) + +#define __qdf_nbuf_set_rx_flow_tag(skb, val) \ + ((QDF_NBUF_CB_RX_FLOW_TAG((skb))) = val) + +#define __qdf_nbuf_get_rx_flow_tag(skb) \ + (QDF_NBUF_CB_RX_FLOW_TAG((skb))) + /** * qdf_nbuf_cb_update_vdev_id() - update vdev id in skb cb * @skb: skb pointer whose cb is updated with vdev id information diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_notifier.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_notifier.h new file mode 100644 index 0000000000000000000000000000000000000000..331bfffb485e9ab8413fab9d0cecacd3439cd3ce --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_notifier.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + /** + * DOC: i_qdf_notifier.h + * + * Linux-specific definitions for use by QDF notifier APIs + */ + +#ifndef __I_QDF_NOTIFIER_H +#define __I_QDF_NOTIFIER_H + +#include + +typedef struct blocking_notifier_head __qdf_blocking_notif_head; +typedef struct atomic_notifier_head __qdf_atomic_notif_head; +typedef struct notifier_block __qdf_notifier_block; +#define qdf_blocking_notifier_init(p) BLOCKING_NOTIFIER_HEAD(p); +#define qdf_atomic_notifier_init(p) ATOMIC_NOTIFIER_HEAD(p); + +static inline int +__qdf_register_blocking_notifier_chain(__qdf_blocking_notif_head *head, + __qdf_notifier_block *qnb) +{ + return blocking_notifier_chain_register(head, qnb); +} + +static inline int +__qdf_unregister_blocking_notifier_chain(__qdf_blocking_notif_head *head, + __qdf_notifier_block *qnb) +{ + return blocking_notifier_chain_unregister(head, qnb); +} + +static inline int +__qdf_blocking_notfier_call(__qdf_blocking_notif_head *head, + unsigned long v, void *data) +{ + return blocking_notifier_call_chain(head, v, data); +} + +static inline int +__qdf_register_atomic_notifier_chain(__qdf_atomic_notif_head *head, + __qdf_notifier_block *qnb) +{ + return atomic_notifier_chain_register(head, qnb); +} + +static inline int +__qdf_unregister_atomic_notifier_chain(__qdf_atomic_notif_head *head, + __qdf_notifier_block *qnb) +{ + return atomic_notifier_chain_unregister(head, qnb); +} + +static inline int +__qdf_atomic_notifier_call(__qdf_atomic_notif_head *head, + unsigned long v, void *data) +{ + return atomic_notifier_call_chain(head, v, data); +} + +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_str.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_str.h index 0f54196c36e5261244fbfa8b66f3edbbd1b30a87..53378e12ba0028e1053fb7f40bfc44fd25ae7527 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_str.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_str.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 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 @@ -33,5 +33,6 @@ #define __qdf_str_len(str) strlen(str) #define __qdf_str_trim(str) strim(str) #define __qdf_str_nlen(str, limit) strnlen(str, limit) +#define __qdf_str_ncmp(left, right, limit) strncmp(left, right, limit) #endif /* __I_QDF_STR_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_streamfs.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_streamfs.h new file mode 100644 index 0000000000000000000000000000000000000000..d4b6e2edc1389ff922f245ca183e5559e7a10c34 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_streamfs.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: i_qdf_streamfs.h + * Linux specific implementation for stream filesystem APIs. + */ + +#ifndef _I_QDF_STREAMFS_H +#define _I_QDF_STREAMFS_H + +#include + +typedef struct rchan *__qdf_streamfs_chan_t; +typedef struct rchan_buf *__qdf_streamfs_chan_buf_t; + +#endif /* _I_QDF_STREAMFS_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_talloc.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_talloc.h index 7965d93ee22ee89d9d97eee4bcbce7c3099ae4bc..3bc402dcbd43092eba1c7f418cf6da6ae2a08223 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_talloc.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_talloc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 @@ -33,16 +33,14 @@ #define __can_sleep() \ (!in_interrupt() && !irqs_disabled() && !in_atomic()) -#define __zalloc_sleeps(size) kmalloc(size, GFP_KERNEL) -#define __zalloc_atomic(size) kmalloc(size, GFP_ATOMIC) +#define __zalloc_sleeps(size) kzalloc(size, GFP_KERNEL) +#define __zalloc_atomic(size) kzalloc(size, GFP_ATOMIC) #define __zalloc_auto(size) \ - kmalloc(size, __can_sleep() ? GFP_KERNEL : GFP_ATOMIC) + kzalloc(size, __can_sleep() ? GFP_KERNEL : GFP_ATOMIC) #define __free(ptr) kfree(ptr) #define __alloc_size(ptr) ksize(ptr) -#define __page_size ((size_t)PAGE_SIZE) - #endif /* __I_QDF_TALLOC_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_time.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_time.h index 539df213ba8973b8f66a06fd402c93efa031783f..30d98860a755c6874a6737bd0406209c5a313b60 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_time.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_time.h @@ -249,11 +249,7 @@ static inline bool __qdf_system_time_after_eq(__qdf_time_t a, __qdf_time_t b) */ static inline uint64_t __qdf_get_monotonic_boottime(void) { - struct timespec ts; - - get_monotonic_boottime(&ts); - - return ((uint64_t) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); + return (uint64_t)ktime_to_us(ktime_get_boottime()); } #if defined (MSM_PLATFORM) @@ -266,7 +262,12 @@ static inline uint64_t __qdf_get_monotonic_boottime(void) * * Return: QTIMER(19.2 MHz) clock ticks */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static inline uint64_t __qdf_get_log_timestamp(void) +{ + return __arch_counter_get_cntvct(); +} +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) static inline uint64_t __qdf_get_log_timestamp(void) { return arch_counter_get_cntvct(); @@ -305,7 +306,13 @@ static inline uint64_t __qdf_get_log_timestamp(void) * The time since system booted in nanoseconds */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) +static inline uint64_t __qdf_get_bootbased_boottime_ns(void) +{ + return ktime_get_boottime_ns(); +} + +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) static inline uint64_t __qdf_get_bootbased_boottime_ns(void) { return ktime_get_boot_ns(); diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_trace.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_trace.h index 3223905e10b240f3c19e953c5251f30c7b31132b..ea0b7fda1fbf1605c67538a5f8b4f929c3892e88 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_trace.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_trace.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2019 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 @@ -121,7 +121,8 @@ #define __QDF_TRACE_HEX_DUMP_RL(log_level, module_id, args...) \ __QDF_TRACE_HEX_DUMP_RATE_LIMITED(module_id, log_level, ## args) -static inline void __qdf_trace_noop(QDF_MODULE_ID module, char *format, ...) { } +static inline void __qdf_trace_noop(QDF_MODULE_ID module, + const char *format, ...) { } static inline void __qdf_trace_dummy(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, const char *format, ...) { } @@ -132,6 +133,7 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, void *data, int buf_len) { } + #ifdef WLAN_LOG_FATAL #define QDF_TRACE_FATAL(params...) \ __QDF_TRACE_FL(QDF_TRACE_LEVEL_FATAL, ## params) @@ -141,6 +143,8 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, __QDF_TRACE_RL(QDF_TRACE_LEVEL_FATAL, ## params) #define QDF_TRACE_FATAL_RL_NO_FL(params...) \ __QDF_TRACE_RL_NO_FL(QDF_TRACE_LEVEL_FATAL, ## params) +#define QDF_VTRACE_FATAL(module_id, fmt, args) \ + QDF_VTRACE(module_id, QDF_TRACE_LEVEL_FATAL, fmt, args) #define QDF_TRACE_HEX_DUMP_FATAL_RL(params...) \ __QDF_TRACE_HEX_DUMP_RL(QDF_TRACE_LEVEL_FATAL, ## params) #else @@ -148,6 +152,7 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, #define QDF_TRACE_FATAL_NO_FL(params...) __qdf_trace_noop(params) #define QDF_TRACE_FATAL_RL(params...) __qdf_trace_noop(params) #define QDF_TRACE_FATAL_RL_NO_FL(params...) __qdf_trace_noop(params) +#define QDF_VTRACE_FATAL(params...) __qdf_trace_noop(params) #define QDF_TRACE_HEX_DUMP_FATAL_RL(params...) __qdf_trace_noop(params) #endif @@ -160,6 +165,8 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, __QDF_TRACE_RL(QDF_TRACE_LEVEL_ERROR, ## params) #define QDF_TRACE_ERROR_RL_NO_FL(params...) \ __QDF_TRACE_RL_NO_FL(QDF_TRACE_LEVEL_ERROR, ## params) +#define QDF_VTRACE_ERROR(module_id, fmt, args) \ + QDF_VTRACE(module_id, QDF_TRACE_LEVEL_ERROR, fmt, args) #define QDF_TRACE_HEX_DUMP_ERROR_RL(params...) \ __QDF_TRACE_HEX_DUMP_RL(QDF_TRACE_LEVEL_ERROR, ## params) #else @@ -167,6 +174,7 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, #define QDF_TRACE_ERROR_NO_FL(params...) __qdf_trace_noop(params) #define QDF_TRACE_ERROR_RL(params...) __qdf_trace_noop(params) #define QDF_TRACE_ERROR_RL_NO_FL(params...) __qdf_trace_noop(params) +#define QDF_VTRACE_ERROR(params...) __qdf_trace_noop(params) #define QDF_TRACE_HEX_DUMP_ERROR_RL(params...) __qdf_trace_noop(params) #endif @@ -179,6 +187,8 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, __QDF_TRACE_RL(QDF_TRACE_LEVEL_WARN, ## params) #define QDF_TRACE_WARN_RL_NO_FL(params...) \ __QDF_TRACE_RL_NO_FL(QDF_TRACE_LEVEL_WARN, ## params) +#define QDF_VTRACE_WARN(module_id, fmt, args) \ + QDF_VTRACE(module_id, QDF_TRACE_LEVEL_WARN, fmt, args) #define QDF_TRACE_HEX_DUMP_WARN_RL(params...) \ __QDF_TRACE_HEX_DUMP_RL(QDF_TRACE_LEVEL_WARN, ## params) #else @@ -186,6 +196,7 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, #define QDF_TRACE_WARN_NO_FL(params...) __qdf_trace_noop(params) #define QDF_TRACE_WARN_RL(params...) __qdf_trace_noop(params) #define QDF_TRACE_WARN_RL_NO_FL(params...) __qdf_trace_noop(params) +#define QDF_VTRACE_WARN(params...) __qdf_trace_noop(params) #define QDF_TRACE_HEX_DUMP_WARN_RL(params...) __qdf_trace_noop(params) #endif @@ -198,6 +209,8 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, __QDF_TRACE_RL(QDF_TRACE_LEVEL_INFO, ## params) #define QDF_TRACE_INFO_RL_NO_FL(params...) \ __QDF_TRACE_RL_NO_FL(QDF_TRACE_LEVEL_INFO, ## params) +#define QDF_VTRACE_INFO(module_id, fmt, args) \ + QDF_VTRACE(module_id, QDF_TRACE_LEVEL_INFO, fmt, args) #define QDF_TRACE_HEX_DUMP_INFO_RL(params...) \ __QDF_TRACE_HEX_DUMP_RL(QDF_TRACE_LEVEL_INFO, ## params) #else @@ -205,6 +218,7 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, #define QDF_TRACE_INFO_NO_FL(params...) __qdf_trace_noop(params) #define QDF_TRACE_INFO_RL(params...) __qdf_trace_noop(params) #define QDF_TRACE_INFO_RL_NO_FL(params...) __qdf_trace_noop(params) +#define QDF_VTRACE_INFO(params...) __qdf_trace_noop(params) #define QDF_TRACE_HEX_DUMP_INFO_RL(params...) __qdf_trace_noop(params) #endif @@ -217,6 +231,8 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, __QDF_TRACE_RL(QDF_TRACE_LEVEL_DEBUG, ## params) #define QDF_TRACE_DEBUG_RL_NO_FL(params...) \ __QDF_TRACE_RL_NO_FL(QDF_TRACE_LEVEL_DEBUG, ## params) +#define QDF_VTRACE_DEBUG(module_id, fmt, args) \ + QDF_VTRACE(module_id, QDF_TRACE_LEVEL_DEBUG, fmt, args) #define QDF_TRACE_HEX_DUMP_DEBUG_RL(params...) \ __QDF_TRACE_HEX_DUMP_RL(QDF_TRACE_LEVEL_DEBUG, ## params) #else @@ -224,6 +240,7 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, #define QDF_TRACE_DEBUG_NO_FL(params...) __qdf_trace_noop(params) #define QDF_TRACE_DEBUG_RL(params...) __qdf_trace_noop(params) #define QDF_TRACE_DEBUG_RL_NO_FL(params...) __qdf_trace_noop(params) +#define QDF_VTRACE_DEBUG(params...) __qdf_trace_noop(params) #define QDF_TRACE_HEX_DUMP_DEBUG_RL(params...) __qdf_trace_noop(params) #endif @@ -263,6 +280,39 @@ static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, } \ } while (0) #endif /* WLAN_WARN_ON_ASSERT */ +/** + * qdf_trace_msg()- logging API + * @module: Module identifier. A member of the QDF_MODULE_ID enumeration that + * identifies the module issuing the trace message. + * @level: Trace level. A member of the QDF_TRACE_LEVEL enumeration indicating + * the severity of the condition causing the trace message to be issued. + * More severe conditions are more likely to be logged. + * @str_format: Format string. The message to be logged. This format string + * contains printf-like replacement parameters, which follow this + * parameter in the variable argument list. + * + * Users wishing to add tracing information to their code should use + * QDF_TRACE. QDF_TRACE() will compile into a call to qdf_trace_msg() when + * tracing is enabled. + * + * Return: nothing + * + * implemented in qdf_trace.c + */ +void __printf(3, 4) qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, + const char *str_format, ...); + +/** + * qdf_vtrace_msg() - the va_list version of qdf_trace_msg + * @module: the calling module's Id + * @level: the logging level to log using + * @str_format: the log format string + * @val: the va_list containing the values to format according to str_format + * + * Return: None + */ +void qdf_vtrace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, + const char *str_format, va_list val); #else @@ -277,6 +327,18 @@ static inline void qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, #endif +#ifdef QDF_TRACE_PRINT_ENABLE +static inline void qdf_vprint(const char *fmt, va_list args) +{ + QDF_VTRACE_INFO(QDF_MODULE_ID_ANY, fmt, args); +} +#else /* QDF_TRACE_PRINT_ENABLE */ +static inline void qdf_vprint(const char *fmt, va_list args) +{ + QDF_VTRACE_ERROR(QDF_MODULE_ID_QDF, fmt, args); +} +#endif + #ifdef PANIC_ON_BUG #ifdef CONFIG_SLUB_DEBUG /** @@ -389,8 +451,16 @@ __qdf_minidump_log(void *start_addr, size_t size, const char *name) "%s: failed to log %pK (%s)\n", __func__, start_addr, name); } + +static inline void +__qdf_minidump_remove(void *addr) +{ + remove_minidump_segments((uintptr_t)addr); +} #else static inline void __qdf_minidump_log(void *start_addr, size_t size, const char *name) {} +static inline void +__qdf_minidump_remove(void *addr) {} #endif #endif /* __I_QDF_TRACE_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_types.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_types.h index 2c68abfa335cd655e6302303ca1099e5a1a9ae66..b43f6c0ccb42dc1dd91240d9343a5106763df0ed 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_types.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -98,11 +98,26 @@ typedef unsigned long dma_addr_t; typedef unsigned long phys_addr_t; typedef unsigned long __sgtable_t; +#ifndef SIOCGIWAP #define SIOCGIWAP 0 +#endif + +#ifndef IWEVCUSTOM #define IWEVCUSTOM 0 +#endif + +#ifndef IWEVREGISTERED #define IWEVREGISTERED 0 +#endif + +#ifndef IWEVEXPIRED #define IWEVEXPIRED 0 +#endif + +#ifndef SIOCGIWSCAN #define SIOCGIWSCAN 0 +#endif + #define DMA_TO_DEVICE 0 #define DMA_BIDIRECTIONAL 0 #define DMA_FROM_DEVICE 0 @@ -209,6 +224,7 @@ struct __qdf_mempool_ctxt; * @QDF_BUS_TYPE_SNOC: SNOC Bus * @QDF_BUS_TYPE_SIM: Simulator * @QDF_BUS_TYPE_USB: USB Bus + * @QDF_BUS_TYPE_IPCI: IPCI Bus */ enum qdf_bus_type { QDF_BUS_TYPE_NONE = -1, @@ -217,7 +233,8 @@ enum qdf_bus_type { QDF_BUS_TYPE_SNOC, QDF_BUS_TYPE_SIM, QDF_BUS_TYPE_SDIO, - QDF_BUS_TYPE_USB + QDF_BUS_TYPE_USB, + QDF_BUS_TYPE_IPCI }; /** @@ -250,14 +267,16 @@ struct __qdf_device { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) struct iommu_domain *domain; #else +#ifdef ENABLE_SMMU_S1_TRANSLATION struct dma_iommu_mapping *iommu_mapping; #endif +#endif }; typedef struct __qdf_device *__qdf_device_t; typedef size_t __qdf_size_t; typedef off_t __qdf_off_t; -typedef uint8_t __iomem *__qdf_iomem_t; +typedef void __iomem* __qdf_iomem_t; typedef uint32_t ath_dma_addr_t; @@ -312,8 +331,6 @@ enum __qdf_net_wireless_evcode { __QDF_CUSTOM_PUSH_BUTTON = IWEVCUSTOM, }; -#define __qdf_print printk -#define __qdf_vprint vprintk #define __qdf_snprint snprintf #define __qdf_vsnprint vsnprintf #define __qdf_toupper toupper diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_util.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_util.h index 469320e6e02c50d9849a8a9c6ab4db89e71fd100..67469c355e0917fedf5f9e6f73dccaae956f652a 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_util.h +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/i_qdf_util.h @@ -472,4 +472,17 @@ int __qdf_hex_str_to_binary(u8 *dst, const char *src, size_t count) return hex2bin(dst, src, count); } +/** + * __qdf_fls() - find last set bit in a given 32 bit input + * @x: 32 bit mask + * + * Return: zero if the input is zero, otherwise returns the bit + * position of the last set bit, where the LSB is 1 and MSB is 32. + */ +static inline +int __qdf_fls(uint32_t x) +{ + return fls(x); +} + #endif /*_I_QDF_UTIL_H*/ diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_crypto.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_crypto.c index a3bcf10e0526d9baf67834e5fa8727e453bad46d..766221a20a50d80c990f1fc763054db7faf2edcc 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_crypto.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_crypto.c @@ -95,6 +95,27 @@ void qdf_update_dbl(uint8_t *d) d[AES_BLOCK_SIZE - 1] ^= 0x87; } +/** + * set_desc_flags() - set flags variable in the shash_desc struct + * @desc: pointer to shash_desc struct + * @tfm: pointer to crypto_shash struct + * + * Set the flags variable in the shash_desc struct by getting the flag + * from the crypto_hash struct. The flag is not actually used, prompting + * its removal from kernel code in versions 5.2 and above. Thus, for + * versions 5.2 and above, do not set the flag variable of shash_desc. + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) +static void set_desc_flags(struct shash_desc *desc, struct crypto_shash *tfm) +{ + desc->flags = crypto_shash_get_flags(tfm); +} +#else +static void set_desc_flags(struct shash_desc *desc, struct crypto_shash *tfm) +{ +} +#endif + int qdf_get_keyed_hash(const char *alg, const uint8_t *key, unsigned int key_len, const uint8_t *src[], size_t *src_len, size_t num_elements, uint8_t *out) @@ -124,7 +145,7 @@ int qdf_get_keyed_hash(const char *alg, const uint8_t *key, do { SHASH_DESC_ON_STACK(desc, tfm); desc->tfm = tfm; - desc->flags = crypto_shash_get_flags(tfm); + set_desc_flags(desc, tfm); ret = crypto_shash_init(desc); if (ret) { diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_debugfs.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_debugfs.c index f590a87508b645044788d15218da836e0cb4de7d..da98bb0bbe889d919925b6c26df2ed7a099436ee 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_debugfs.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_debugfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 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 @@ -165,6 +165,8 @@ void qdf_debugfs_printf(qdf_debugfs_file_t file, const char *f, ...) va_end(args); } +qdf_export_symbol(qdf_debugfs_printf); + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) void qdf_debugfs_hexdump(qdf_debugfs_file_t file, const uint8_t *buf, @@ -466,3 +468,70 @@ void qdf_debugfs_remove_file(qdf_dentry_t d) debugfs_remove(d); } qdf_export_symbol(qdf_debugfs_remove_file); + +static int qdf_debugfs_single_show(struct seq_file *seq, void *v) +{ + struct qdf_debugfs_fops *fops = seq->private; + + if (fops && fops->show) + fops->show(seq, fops->priv); + + return 0; +} + +/* .open() */ +static int qdf_debugfs_single_open(struct inode *inode, struct file *file) +{ + return single_open(file, qdf_debugfs_single_show, + inode->i_private); +} + +/* File operations for the simplified version */ +static const struct file_operations qdf_debugfs_fops_simple = { + .owner = THIS_MODULE, + .open = qdf_debugfs_single_open, + .release = single_release, + .read = seq_read, + .llseek = seq_lseek, +}; + +qdf_dentry_t qdf_debugfs_create_file_simplified( + const char *name, uint16_t mode, + qdf_dentry_t parent, struct qdf_debugfs_fops *fops) +{ + qdf_dentry_t file; + umode_t filemode; + + if (!name || !fops) + return NULL; + + if (!parent) + parent = qdf_debugfs_get_root(); + + filemode = qdf_debugfs_get_filemode(mode); + file = debugfs_create_file(name, filemode, parent, fops, + &qdf_debugfs_fops_simple); + + if (IS_ERR_OR_NULL(file)) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s creation failed 0x%pK", name, file); + file = NULL; + } + + return file; +} +qdf_export_symbol(qdf_debugfs_create_file_simplified); + +int qdf_debugfs_printer(void *priv, const char *fmt, ...) +{ + struct seq_file *file = priv; + va_list args; + + va_start(args, fmt); + seq_vprintf(file, fmt, args); + seq_puts(file, "\n"); + va_end(args); + + return 0; +} +qdf_export_symbol(qdf_debugfs_printer); diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_func_tracker.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_func_tracker.c new file mode 100644 index 0000000000000000000000000000000000000000..43fa3b44ee522c8262e0ac97ce7c7acfa1a4cf5d --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_func_tracker.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#ifdef FUNC_CALL_MAP +char qdf_func_call_map_buf[QDF_FUNCTION_CALL_MAP_BUF_LEN] = {0}; + +void cc_func(unsigned int track) +{ + unsigned int index = 0; + unsigned int bit = 0; + + index = track / 8; + bit = track % 8; + qdf_func_call_map_buf[index] |= (char)(1 << bit); +} + +void qdf_get_func_call_map(char *data) +{ + qdf_mem_copy(data, qdf_func_call_map_buf, + QDF_FUNCTION_CALL_MAP_BUF_LEN); +} + +void qdf_clear_func_call_map(void) +{ + qdf_mem_zero(qdf_func_call_map_buf, QDF_FUNCTION_CALL_MAP_BUF_LEN); +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_func_tracker.h b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_func_tracker.h new file mode 100644 index 0000000000000000000000000000000000000000..5f4fb25dedd73eef3f34a3cc554ca49096ba2716 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_func_tracker.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef QDF_FUNC_TRACKER_H +#define QDF_FUNC_TRACKER_H + +#ifdef FUNC_CALL_MAP + +#define QDF_FUNCTION_CALL_MAP_BUF_LEN 4096 + +/** + * cc_func() - Inserts the function Id into the global + * function map + * @track: Function Id which needs to be inserted into the + * Global function map. + * + * Return: None + */ +void cc_func(unsigned int track); + +/** + * qdf_get_func_call_map() - Copies the global function call + * map into the given buffer + * @data: Buffer in which the function call map needs to be + * copied + * + * Return: None + */ +void qdf_get_func_call_map(char *data); + +/** + * qdf_clear_func_call_map() - Clears the global function + * call map + * + * Return: None + */ +void qdf_clear_func_call_map(void); +#else +static inline void cc_func(unsigned int track) +{ +} + +static inline void qdf_get_func_call_map(char *data) +{ +} + +static inline void qdf_clear_func_call_map(void) +{ +} + +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_lock.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_lock.c index 710553e3be1471df5356f262541d6b86d8c916fa..48deb01e93ea15571f10669488d43f8a5320c9bf 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_lock.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_lock.c @@ -23,7 +23,7 @@ #include #include -#ifdef CONFIG_MCL +#ifdef FEATURE_RUNTIME_PM #include #include #endif @@ -582,10 +582,6 @@ qdf_export_symbol(__qdf_runtime_lock_init); void qdf_runtime_lock_deinit(qdf_runtime_lock_t *lock) { void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF); - - if (!lock) - return; - hif_runtime_lock_deinit(hif_ctx, lock->lock); } qdf_export_symbol(qdf_runtime_lock_deinit); @@ -827,6 +823,7 @@ void qdf_lock_stats_deinit(void) __func__, lock_cookies[i].u.cookie.func, lock_cookies[i].u.cookie.line); } + lock_cookie_freelist = NULL; } /* allocated separate memory in case the lock memory is freed without diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_mc_timer.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_mc_timer.c index 163e7b1edd471fd5a202b21b386f87f515b6bfe8..b2591b32e957ddd9a3ec1e81552b8ac0d199a7d9 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_mc_timer.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_mc_timer.c @@ -30,6 +30,7 @@ #include "qdf_mem.h" #include #include "qdf_timer.h" +#include /* Preprocessor definitions and constants */ #define LINUX_TIMER_COOKIE 0x12341234 @@ -824,6 +825,17 @@ qdf_export_symbol(qdf_mc_timer_get_system_ticks); * Return: * The current system time in milliseconds */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) +unsigned long qdf_mc_timer_get_system_time(void) +{ + struct timespec64 tv; + + ktime_get_real_ts64(&tv); + return tv.tv_sec * 1000 + tv.tv_nsec / 1000000; +} +qdf_export_symbol(qdf_mc_timer_get_system_time); + +#else unsigned long qdf_mc_timer_get_system_time(void) { struct timeval tv; @@ -832,17 +844,32 @@ unsigned long qdf_mc_timer_get_system_time(void) return tv.tv_sec * 1000 + tv.tv_usec / 1000; } qdf_export_symbol(qdf_mc_timer_get_system_time); +#endif s64 qdf_get_monotonic_boottime_ns(void) { - struct timespec ts; + return ktime_to_ns(ktime_get_boottime()); +} +qdf_export_symbol(qdf_get_monotonic_boottime_ns); - get_monotonic_boottime(&ts); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) +qdf_time_t qdf_get_time_of_the_day_ms(void) +{ + struct timespec64 tv; + qdf_time_t local_time; + struct rtc_time tm; - return timespec_to_ns(&ts); + ktime_get_real_ts64(&tv); + local_time = (qdf_time_t)(tv.tv_sec - (sys_tz.tz_minuteswest * 60)); + rtc_time_to_tm(local_time, &tm); + + return (tm.tm_hour * 60 * 60 * 1000) + + (tm.tm_min * 60 * 1000) + (tm.tm_sec * 1000) + + (tv.tv_nsec / 1000000); } -qdf_export_symbol(qdf_get_monotonic_boottime_ns); +qdf_export_symbol(qdf_get_time_of_the_day_ms); +#else qdf_time_t qdf_get_time_of_the_day_ms(void) { struct timeval tv; @@ -858,6 +885,7 @@ qdf_time_t qdf_get_time_of_the_day_ms(void) (tv.tv_usec / 1000); } qdf_export_symbol(qdf_get_time_of_the_day_ms); +#endif /** * qdf_timer_module_deinit() - Deinitializes a QDF timer module. @@ -873,6 +901,25 @@ void qdf_timer_module_deinit(void) } qdf_export_symbol(qdf_timer_module_deinit); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) +void qdf_get_time_of_the_day_in_hr_min_sec_usec(char *tbuf, int len) +{ + struct timespec64 tv; + struct rtc_time tm; + unsigned long local_time; + + /* Format the Log time R#: [hr:min:sec.microsec] */ + ktime_get_real_ts64(&tv); + /* Convert rtc to local time */ + local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60)); + rtc_time_to_tm(local_time, &tm); + scnprintf(tbuf, len, + "[%02d:%02d:%02d.%06lu]", + tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_nsec / 1000); +} +qdf_export_symbol(qdf_get_time_of_the_day_in_hr_min_sec_usec); + +#else void qdf_get_time_of_the_day_in_hr_min_sec_usec(char *tbuf, int len) { struct timeval tv; @@ -889,3 +936,4 @@ void qdf_get_time_of_the_day_in_hr_min_sec_usec(char *tbuf, int len) tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec); } qdf_export_symbol(qdf_get_time_of_the_day_in_hr_min_sec_usec); +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_mem.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_mem.c index e967f212f4f4d53706d3f8d7d4b5588a0c3e4c19..21576d9878412a3acd3b8b511cd965a60d740cd5 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_mem.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_mem.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-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 @@ -34,19 +34,57 @@ #include #include #include -#include #if IS_ENABLED(CONFIG_WCNSS_MEM_PRE_ALLOC) #include #endif +#if defined(MEMORY_DEBUG) || defined(NBUF_MEMORY_DEBUG) +static bool mem_debug_disabled; +qdf_declare_param(mem_debug_disabled, bool); +qdf_export_symbol(mem_debug_disabled); +static bool is_initial_mem_debug_disabled; +#endif + /* Preprocessor Definitions and Constants */ #define QDF_MEM_MAX_MALLOC (4096 * 1024) /* 4 Mega Bytes */ #define QDF_MEM_WARN_THRESHOLD 300 /* ms */ #define QDF_DEBUG_STRING_SIZE 512 +/** + * struct __qdf_mem_stat - qdf memory statistics + * @kmalloc: total kmalloc allocations + * @dma: total dma allocations + * @skb: total skb allocations + */ +static struct __qdf_mem_stat { + qdf_atomic_t kmalloc; + qdf_atomic_t dma; + qdf_atomic_t skb; +} qdf_mem_stat; + #ifdef MEMORY_DEBUG #include "qdf_debug_domain.h" +#include + +enum list_type { + LIST_TYPE_MEM = 0, + LIST_TYPE_DMA = 1, + LIST_TYPE_MAX, +}; + +/** + * major_alloc_priv: private data registered to debugfs entry created to list + * the list major allocations + * @type: type of the list to be parsed + * @threshold: configured by user by overwriting the respective debugfs + * sys entry. This is to list the functions which requested + * memory/dma allocations more than threshold nubmer of times. + */ +struct major_alloc_priv { + enum list_type type; + uint32_t threshold; +}; static qdf_list_t qdf_mem_domains[QDF_DEBUG_DOMAIN_COUNT]; static qdf_spinlock_t qdf_mem_list_lock; @@ -237,13 +275,18 @@ qdf_mem_header_assert_valid(struct qdf_mem_header *header, qdf_debug_domain_name(header->domain), header->domain, qdf_debug_domain_name(current_domain), current_domain); - QDF_DEBUG_PANIC("Fatal memory error detected @ %s:%d", func, line); + QDF_MEMDEBUG_PANIC("Fatal memory error detected @ %s:%d", func, line); } -#endif /* MEMORY_DEBUG */ -u_int8_t prealloc_disabled = 1; -qdf_declare_param(prealloc_disabled, byte); -qdf_export_symbol(prealloc_disabled); +void qdf_mem_skb_inc(qdf_size_t size) +{ + qdf_atomic_add(size, &qdf_mem_stat.skb); +} + +void qdf_mem_skb_dec(qdf_size_t size) +{ + qdf_atomic_sub(size, &qdf_mem_stat.skb); +} /** * struct __qdf_mem_info - memory statistics @@ -263,80 +306,6 @@ struct __qdf_mem_info { uint64_t time; }; -static struct __qdf_mem_stat { - qdf_atomic_t kmalloc; - qdf_atomic_t dma; - qdf_atomic_t skb; -} qdf_mem_stat; - -void qdf_mem_skb_inc(qdf_size_t size) -{ - qdf_atomic_add(size, &qdf_mem_stat.skb); -} - -void qdf_mem_skb_dec(qdf_size_t size) -{ - qdf_atomic_sub(size, &qdf_mem_stat.skb); -} - -#if defined WLAN_DEBUGFS - -/* Debugfs root directory for qdf_mem */ -static struct dentry *qdf_mem_debugfs_root; - -/** - * struct __qdf_mem_stat - qdf memory statistics - * @kmalloc: total kmalloc allocations - * @dma: total dma allocations - * @skb: total skb allocations - */ - -void qdf_mem_kmalloc_inc(qdf_size_t size) -{ - qdf_atomic_add(size, &qdf_mem_stat.kmalloc); -} - -void qdf_mem_kmalloc_dec(qdf_size_t size) -{ - qdf_atomic_sub(size, &qdf_mem_stat.kmalloc); -} - -static void qdf_mem_dma_inc(qdf_size_t size) -{ - qdf_atomic_add(size, &qdf_mem_stat.dma); -} - -static inline void qdf_mem_dma_dec(qdf_size_t size) -{ - qdf_atomic_sub(size, &qdf_mem_stat.dma); -} - - -#ifdef MEMORY_DEBUG -static int qdf_err_printer(void *priv, const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - QDF_VTRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, (char *)fmt, args); - va_end(args); - - return 0; -} - -static int seq_printf_printer(void *priv, const char *fmt, ...) -{ - struct seq_file *file = priv; - va_list args; - - va_start(args, fmt); - seq_vprintf(file, fmt, args); - seq_puts(file, "\n"); - va_end(args); - - return 0; -} - /* * The table depth defines the de-duplication proximity scope. * A deeper table takes more time, so choose any optimum value. @@ -344,15 +313,20 @@ static int seq_printf_printer(void *priv, const char *fmt, ...) #define QDF_MEM_STAT_TABLE_SIZE 8 /** - * qdf_mem_domain_print_header() - memory domain header print logic + * qdf_mem_debug_print_header() - memory debug header print logic * @print: the print adapter function * @print_priv: the private data to be consumed by @print + * @threshold: the threshold value set by user to list top allocations * * Return: None */ -static void qdf_mem_domain_print_header(qdf_abstract_print print, - void *print_priv) +static void qdf_mem_debug_print_header(qdf_abstract_print print, + void *print_priv, + uint32_t threshold) { + if (threshold) + print(print_priv, "APIs requested allocations >= %u no of time", + threshold); print(print_priv, "--------------------------------------------------------------"); print(print_priv, @@ -361,48 +335,6 @@ static void qdf_mem_domain_print_header(qdf_abstract_print print, "--------------------------------------------------------------"); } -/** - * qdf_mem_meta_table_print() - memory metadata table print logic - * @table: the memory metadata table to print - * @print: the print adapter function - * @print_priv: the private data to be consumed by @print - * - * Return: None - */ -static void qdf_mem_meta_table_print(struct __qdf_mem_info *table, - qdf_abstract_print print, - void *print_priv) -{ - int i; - char debug_str[QDF_DEBUG_STRING_SIZE]; - size_t len = 0; - char *debug_prefix = "WLAN_BUG_RCA: memory leak detected"; - - len += qdf_scnprintf(debug_str, sizeof(debug_str) - len, - "%s", debug_prefix); - - for (i = 0; i < QDF_MEM_STAT_TABLE_SIZE; i++) { - if (!table[i].count) - break; - - print(print_priv, - "%6u x %5u = %7uB @ %s:%u %pS %llu", - table[i].count, - table[i].size, - table[i].count * table[i].size, - table[i].func, - table[i].line, table[i].caller, - table[i].time); - len += qdf_scnprintf(debug_str + len, - sizeof(debug_str) - len, - " @ %s:%u %pS", - table[i].func, - table[i].line, - table[i].caller); - } - print(print_priv, "%s", debug_str); -} - /** * qdf_mem_meta_table_insert() - insert memory metadata into the given table * @table: the memory metadata table to insert into @@ -445,19 +377,25 @@ static bool qdf_mem_meta_table_insert(struct __qdf_mem_info *table, * @domain: the memory domain to print * @print: the print adapter function * @print_priv: the private data to be consumed by @print + * @threshold: the threshold value set by uset to list top allocations + * @mem_print: pointer to function which prints the memory allocation data * * Return: None */ static void qdf_mem_domain_print(qdf_list_t *domain, qdf_abstract_print print, - void *print_priv) + void *print_priv, + uint32_t threshold, + void (*mem_print)(struct __qdf_mem_info *, + qdf_abstract_print, + void *, uint32_t)) { QDF_STATUS status; struct __qdf_mem_info table[QDF_MEM_STAT_TABLE_SIZE]; qdf_list_node_t *node; qdf_mem_zero(table, sizeof(table)); - qdf_mem_domain_print_header(print, print_priv); + qdf_mem_debug_print_header(print, print_priv, threshold); /* hold lock while inserting to avoid use-after free of the metadata */ qdf_spin_lock(&qdf_mem_list_lock); @@ -469,7 +407,7 @@ static void qdf_mem_domain_print(qdf_list_t *domain, qdf_spin_unlock(&qdf_mem_list_lock); if (is_full) { - qdf_mem_meta_table_print(table, print, print_priv); + (*mem_print)(table, print, print_priv, threshold); qdf_mem_zero(table, sizeof(table)); } @@ -478,7 +416,128 @@ static void qdf_mem_domain_print(qdf_list_t *domain, } qdf_spin_unlock(&qdf_mem_list_lock); - qdf_mem_meta_table_print(table, print, print_priv); + (*mem_print)(table, print, print_priv, threshold); +} + +/** + * qdf_mem_meta_table_print() - memory metadata table print logic + * @table: the memory metadata table to print + * @print: the print adapter function + * @print_priv: the private data to be consumed by @print + * @threshold: the threshold value set by user to list top allocations + * + * Return: None + */ +static void qdf_mem_meta_table_print(struct __qdf_mem_info *table, + qdf_abstract_print print, + void *print_priv, + uint32_t threshold) +{ + int i; + char debug_str[QDF_DEBUG_STRING_SIZE]; + size_t len = 0; + char *debug_prefix = "WLAN_BUG_RCA: memory leak detected"; + + len += qdf_scnprintf(debug_str, sizeof(debug_str) - len, + "%s", debug_prefix); + + for (i = 0; i < QDF_MEM_STAT_TABLE_SIZE; i++) { + if (!table[i].count) + break; + + print(print_priv, + "%6u x %5u = %7uB @ %s:%u %pS %llu", + table[i].count, + table[i].size, + table[i].count * table[i].size, + table[i].func, + table[i].line, table[i].caller, + table[i].time); + len += qdf_scnprintf(debug_str + len, + sizeof(debug_str) - len, + " @ %s:%u %pS", + table[i].func, + table[i].line, + table[i].caller); + } + print(print_priv, "%s", debug_str); +} + +static int qdf_err_printer(void *priv, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + QDF_VTRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, (char *)fmt, args); + va_end(args); + + return 0; +} + +#endif /* MEMORY_DEBUG */ + +u_int8_t prealloc_disabled = 1; +qdf_declare_param(prealloc_disabled, byte); +qdf_export_symbol(prealloc_disabled); + +#if defined WLAN_DEBUGFS + +void qdf_mem_kmalloc_inc(qdf_size_t size) +{ + qdf_atomic_add(size, &qdf_mem_stat.kmalloc); +} + +void qdf_mem_kmalloc_dec(qdf_size_t size) +{ + qdf_atomic_sub(size, &qdf_mem_stat.kmalloc); +} + +/* Debugfs root directory for qdf_mem */ +static struct dentry *qdf_mem_debugfs_root; + +#ifdef MEMORY_DEBUG +static int seq_printf_printer(void *priv, const char *fmt, ...) +{ + struct seq_file *file = priv; + va_list args; + + va_start(args, fmt); + seq_vprintf(file, fmt, args); + seq_puts(file, "\n"); + va_end(args); + + return 0; +} + +/** + * qdf_print_major_alloc() - memory metadata table print logic + * @table: the memory metadata table to print + * @print: the print adapter function + * @print_priv: the private data to be consumed by @print + * @threshold: the threshold value set by uset to list top allocations + * + * Return: None + */ +static void qdf_print_major_alloc(struct __qdf_mem_info *table, + qdf_abstract_print print, + void *print_priv, + uint32_t threshold) +{ + int i; + + for (i = 0; i < QDF_MEM_STAT_TABLE_SIZE; i++) { + if (!table[i].count) + break; + if (table[i].count >= threshold) + print(print_priv, + "%6u x %5u = %7uB @ %s:%u %pS %llu", + table[i].count, + table[i].size, + table[i].count * table[i].size, + table[i].func, + table[i].line, table[i].caller, + table[i].time); + } } /** @@ -539,7 +598,10 @@ static int qdf_mem_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "\n%s Memory Domain (Id %d)\n", qdf_debug_domain_name(domain_id), domain_id); qdf_mem_domain_print(qdf_mem_list_get(domain_id), - seq_printf_printer, seq); + seq_printf_printer, + seq, + 0, + qdf_mem_meta_table_print); return 0; } @@ -558,6 +620,99 @@ static int qdf_mem_debugfs_open(struct inode *inode, struct file *file) return seq_open(file, &qdf_mem_seq_ops); } +/** + * qdf_major_alloc_show() - print sequential callback + * @seq: seq_file handle + * @v: current iterator + * + * Return: 0 - success + */ +static int qdf_major_alloc_show(struct seq_file *seq, void *v) +{ + enum qdf_debug_domain domain_id = *(enum qdf_debug_domain *)v; + struct major_alloc_priv *priv; + qdf_list_t *list; + + priv = (struct major_alloc_priv *)seq->private; + seq_printf(seq, "\n%s Memory Domain (Id %d)\n", + qdf_debug_domain_name(domain_id), domain_id); + + switch (priv->type) { + case LIST_TYPE_MEM: + list = qdf_mem_list_get(domain_id); + break; + case LIST_TYPE_DMA: + list = qdf_mem_dma_list(domain_id); + break; + default: + list = NULL; + break; + } + + if (list) + qdf_mem_domain_print(list, + seq_printf_printer, + seq, + priv->threshold, + qdf_print_major_alloc); + + return 0; +} + +/* sequential file operation table created to track major allocs */ +static const struct seq_operations qdf_major_allocs_seq_ops = { + .start = qdf_mem_seq_start, + .next = qdf_mem_seq_next, + .stop = qdf_mem_seq_stop, + .show = qdf_major_alloc_show, +}; + +static int qdf_major_allocs_open(struct inode *inode, struct file *file) +{ + void *private = inode->i_private; + struct seq_file *seq; + int rc; + + rc = seq_open(file, &qdf_major_allocs_seq_ops); + if (rc == 0) { + seq = file->private_data; + seq->private = private; + } + return rc; +} + +static ssize_t qdf_major_alloc_set_threshold(struct file *file, + const char __user *user_buf, + size_t count, + loff_t *pos) +{ + char buf[32]; + ssize_t buf_size; + uint32_t threshold; + struct seq_file *seq = file->private_data; + struct major_alloc_priv *priv = (struct major_alloc_priv *)seq->private; + + buf_size = min(count, (sizeof(buf) - 1)); + if (buf_size <= 0) + return 0; + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + buf[buf_size] = '\0'; + if (!kstrtou32(buf, 10, &threshold)) + priv->threshold = threshold; + return buf_size; +} + +/* file operation table for listing major allocs */ +static const struct file_operations fops_qdf_major_allocs = { + .owner = THIS_MODULE, + .open = qdf_major_allocs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, + .write = qdf_major_alloc_set_threshold, +}; + /* debugfs file operation table */ static const struct file_operations fops_qdf_mem_debugfs = { .owner = THIS_MODULE, @@ -567,8 +722,25 @@ static const struct file_operations fops_qdf_mem_debugfs = { .release = seq_release, }; +static struct major_alloc_priv mem_priv = { + /* List type set to mem */ + LIST_TYPE_MEM, + /* initial threshold to list APIs which allocates mem >= 50 times */ + 50 +}; + +static struct major_alloc_priv dma_priv = { + /* List type set to DMA */ + LIST_TYPE_DMA, + /* initial threshold to list APIs which allocates dma >= 50 times */ + 50 +}; + static QDF_STATUS qdf_mem_debug_debugfs_init(void) { + if (is_initial_mem_debug_disabled) + return QDF_STATUS_SUCCESS; + if (!qdf_mem_debugfs_root) return QDF_STATUS_E_FAILURE; @@ -578,6 +750,18 @@ static QDF_STATUS qdf_mem_debug_debugfs_init(void) NULL, &fops_qdf_mem_debugfs); + debugfs_create_file("major_mem_allocs", + 0600, + qdf_mem_debugfs_root, + &mem_priv, + &fops_qdf_major_allocs); + + debugfs_create_file("major_dma_allocs", + 0600, + qdf_mem_debugfs_root, + &dma_priv, + &fops_qdf_major_allocs); + return QDF_STATUS_SUCCESS; } @@ -640,13 +824,6 @@ static QDF_STATUS qdf_mem_debugfs_init(void) #else /* WLAN_DEBUGFS */ -static inline void qdf_mem_dma_inc(qdf_size_t size) {} -static inline void qdf_mem_dma_dec(qdf_size_t size) {} -static -inline void qdf_mem_domain_print(qdf_list_t *domain, - qdf_abstract_print print, - void *print_priv) {} - static QDF_STATUS qdf_mem_debugfs_init(void) { return QDF_STATUS_E_NOSUPPORT; @@ -666,6 +843,16 @@ static QDF_STATUS qdf_mem_debug_debugfs_exit(void) #endif /* WLAN_DEBUGFS */ +static void qdf_mem_dma_inc(qdf_size_t size) +{ + qdf_atomic_add(size, &qdf_mem_stat.dma); +} + +static inline void qdf_mem_dma_dec(qdf_size_t size) +{ + qdf_atomic_sub(size, &qdf_mem_stat.dma); +} + /** * __qdf_mempool_init() - Create and initialize memory pool * @@ -895,6 +1082,23 @@ static int qdf_mem_malloc_flags(void) /* External Function implementation */ #ifdef MEMORY_DEBUG +/** + * qdf_mem_debug_config_get() - Get the user configuration of mem_debug_disabled + * + * Return: value of mem_debug_disabled qdf module argument + */ +#ifdef DISABLE_MEM_DBG_LOAD_CONFIG +bool qdf_mem_debug_config_get(void) +{ + /* Return false if DISABLE_LOAD_MEM_DBG_CONFIG flag is enabled */ + return false; +} +#else +bool qdf_mem_debug_config_get(void) +{ + return mem_debug_disabled; +} +#endif /* DISABLE_MEM_DBG_LOAD_CONFIG */ /** * qdf_mem_debug_init() - initialize qdf memory debug functionality @@ -905,6 +1109,11 @@ static void qdf_mem_debug_init(void) { int i; + is_initial_mem_debug_disabled = qdf_mem_debug_config_get(); + + if (is_initial_mem_debug_disabled) + return; + /* Initalizing the list with maximum size of 60000 */ for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i) qdf_list_create(&qdf_mem_domains[i], 60000); @@ -920,12 +1129,19 @@ static uint32_t qdf_mem_domain_check_for_leaks(enum qdf_debug_domain domain, qdf_list_t *mem_list) { + if (is_initial_mem_debug_disabled) + return 0; + if (qdf_list_empty(mem_list)) return 0; qdf_err("Memory leaks detected in %s domain!", qdf_debug_domain_name(domain)); - qdf_mem_domain_print(mem_list, qdf_err_printer, NULL); + qdf_mem_domain_print(mem_list, + qdf_err_printer, + NULL, + 0, + qdf_mem_meta_table_print); return mem_list->count; } @@ -935,13 +1151,16 @@ static void qdf_mem_domain_set_check_for_leaks(qdf_list_t *domains) uint32_t leak_count = 0; int i; + if (is_initial_mem_debug_disabled) + return; + /* detect and print leaks */ for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i) leak_count += qdf_mem_domain_check_for_leaks(i, domains + i); if (leak_count) - QDF_DEBUG_PANIC("%u fatal memory leaks detected!", - leak_count); + QDF_MEMDEBUG_PANIC("%u fatal memory leaks detected!", + leak_count); } /** @@ -953,6 +1172,9 @@ static void qdf_mem_debug_exit(void) { int i; + if (is_initial_mem_debug_disabled) + return; + /* mem */ qdf_mem_domain_set_check_for_leaks(qdf_mem_domains); for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i) @@ -977,6 +1199,9 @@ void *qdf_mem_malloc_debug(size_t size, const char *func, uint32_t line, void *ptr; unsigned long start, duration; + if (is_initial_mem_debug_disabled) + return __qdf_mem_malloc(size, func, line); + if (!size || size > QDF_MEM_MAX_MALLOC) { qdf_err("Cannot malloc %zu bytes @ %s:%d", size, func, line); return NULL; @@ -1024,6 +1249,11 @@ void qdf_mem_free_debug(void *ptr, const char *func, uint32_t line) struct qdf_mem_header *header; enum qdf_mem_validation_bitmap error_bitmap; + if (is_initial_mem_debug_disabled) { + __qdf_mem_free(ptr); + return; + } + /* freeing a null pointer is valid */ if (qdf_unlikely(!ptr)) return; @@ -1032,8 +1262,8 @@ void qdf_mem_free_debug(void *ptr, const char *func, uint32_t line) return; if (qdf_unlikely((qdf_size_t)ptr <= sizeof(*header))) - QDF_DEBUG_PANIC("Failed to free invalid memory location %pK", - ptr); + QDF_MEMDEBUG_PANIC("Failed to free invalid memory location %pK", + ptr); qdf_talloc_assert_no_children_fl(ptr, func, line); @@ -1064,45 +1294,184 @@ void qdf_mem_check_for_leaks(void) qdf_list_t *dma_list = qdf_mem_dma_list(current_domain); uint32_t leaks_count = 0; + if (is_initial_mem_debug_disabled) + return; + leaks_count += qdf_mem_domain_check_for_leaks(current_domain, mem_list); leaks_count += qdf_mem_domain_check_for_leaks(current_domain, dma_list); if (leaks_count) - QDF_DEBUG_PANIC("%u fatal memory leaks detected!", - leaks_count); + QDF_MEMDEBUG_PANIC("%u fatal memory leaks detected!", + leaks_count); } -#else -static void qdf_mem_debug_init(void) {} +/** + * qdf_mem_multi_pages_alloc_debug() - Debug version of + * qdf_mem_multi_pages_alloc + * @osdev: OS device handle pointer + * @pages: Multi page information storage + * @element_size: Each element size + * @element_num: Total number of elements should be allocated + * @memctxt: Memory context + * @cacheable: Coherent memory or cacheable memory + * @func: Caller of this allocator + * @line: Line number of the caller + * @caller: Return address of the caller + * + * This function will allocate large size of memory over multiple pages. + * Large size of contiguous memory allocation will fail frequently, then + * instead of allocate large memory by one shot, allocate through multiple, non + * contiguous memory and combine pages when actual usage + * + * Return: None + */ +void qdf_mem_multi_pages_alloc_debug(qdf_device_t osdev, + struct qdf_mem_multi_page_t *pages, + size_t element_size, uint16_t element_num, + qdf_dma_context_t memctxt, bool cacheable, + const char *func, uint32_t line, + void *caller) +{ + uint16_t page_idx; + struct qdf_mem_dma_page_t *dma_pages; + void **cacheable_pages = NULL; + uint16_t i; + + if (!pages->page_size) + pages->page_size = qdf_page_size; + + pages->num_element_per_page = pages->page_size / element_size; + if (!pages->num_element_per_page) { + qdf_print("Invalid page %d or element size %d", + (int)pages->page_size, (int)element_size); + goto out_fail; + } + + pages->num_pages = element_num / pages->num_element_per_page; + if (element_num % pages->num_element_per_page) + pages->num_pages++; + + if (cacheable) { + /* Pages information storage */ + pages->cacheable_pages = qdf_mem_malloc_debug( + pages->num_pages * sizeof(pages->cacheable_pages), + func, line, caller, 0); + if (!pages->cacheable_pages) + goto out_fail; + + cacheable_pages = pages->cacheable_pages; + for (page_idx = 0; page_idx < pages->num_pages; page_idx++) { + cacheable_pages[page_idx] = qdf_mem_malloc_debug( + pages->page_size, func, line, caller, 0); + if (!cacheable_pages[page_idx]) + goto page_alloc_fail; + } + pages->dma_pages = NULL; + } else { + pages->dma_pages = qdf_mem_malloc_debug( + pages->num_pages * sizeof(struct qdf_mem_dma_page_t), + func, line, caller, 0); + if (!pages->dma_pages) + goto out_fail; + + dma_pages = pages->dma_pages; + for (page_idx = 0; page_idx < pages->num_pages; page_idx++) { + dma_pages->page_v_addr_start = + qdf_mem_alloc_consistent_debug( + osdev, osdev->dev, pages->page_size, + &dma_pages->page_p_addr, + func, line, caller); + if (!dma_pages->page_v_addr_start) { + qdf_print("dmaable page alloc fail pi %d", + page_idx); + goto page_alloc_fail; + } + dma_pages->page_v_addr_end = + dma_pages->page_v_addr_start + pages->page_size; + dma_pages++; + } + pages->cacheable_pages = NULL; + } + return; + +page_alloc_fail: + if (cacheable) { + for (i = 0; i < page_idx; i++) + qdf_mem_free_debug(pages->cacheable_pages[i], + func, line); + qdf_mem_free_debug(pages->cacheable_pages, func, line); + } else { + dma_pages = pages->dma_pages; + for (i = 0; i < page_idx; i++) { + qdf_mem_free_consistent_debug( + osdev, osdev->dev, + pages->page_size, dma_pages->page_v_addr_start, + dma_pages->page_p_addr, memctxt, func, line); + dma_pages++; + } + qdf_mem_free_debug(pages->dma_pages, func, line); + } + +out_fail: + pages->cacheable_pages = NULL; + pages->dma_pages = NULL; + pages->num_pages = 0; +} -static void qdf_mem_debug_exit(void) {} +qdf_export_symbol(qdf_mem_multi_pages_alloc_debug); -void *qdf_mem_malloc_fl(size_t size, const char *func, uint32_t line) +/** + * qdf_mem_multi_pages_free_debug() - Debug version of qdf_mem_multi_pages_free + * @osdev: OS device handle pointer + * @pages: Multi page information storage + * @memctxt: Memory context + * @cacheable: Coherent memory or cacheable memory + * @func: Caller of this allocator + * @line: Line number of the caller + * + * This function will free large size of memory over multiple pages. + * + * Return: None + */ +void qdf_mem_multi_pages_free_debug(qdf_device_t osdev, + struct qdf_mem_multi_page_t *pages, + qdf_dma_context_t memctxt, bool cacheable, + const char *func, uint32_t line) { - void *ptr; + unsigned int page_idx; + struct qdf_mem_dma_page_t *dma_pages; - if (!size || size > QDF_MEM_MAX_MALLOC) { - qdf_nofl_err("Cannot malloc %zu bytes @ %s:%d", size, func, - line); - return NULL; + if (!pages->page_size) + pages->page_size = qdf_page_size; + + if (cacheable) { + for (page_idx = 0; page_idx < pages->num_pages; page_idx++) + qdf_mem_free_debug(pages->cacheable_pages[page_idx], + func, line); + qdf_mem_free_debug(pages->cacheable_pages, func, line); + } else { + dma_pages = pages->dma_pages; + for (page_idx = 0; page_idx < pages->num_pages; page_idx++) { + qdf_mem_free_consistent_debug( + osdev, osdev->dev, pages->page_size, + dma_pages->page_v_addr_start, + dma_pages->page_p_addr, memctxt, func, line); + dma_pages++; + } + qdf_mem_free_debug(pages->dma_pages, func, line); } - ptr = qdf_mem_prealloc_get(size); - if (ptr) - return ptr; + pages->cacheable_pages = NULL; + pages->dma_pages = NULL; + pages->num_pages = 0; +} - ptr = kzalloc(size, qdf_mem_malloc_flags()); - if (!ptr) { - qdf_nofl_err("Failed to malloc %zuB @ %s:%d", - size, func, line); - return NULL; - } +qdf_export_symbol(qdf_mem_multi_pages_free_debug); - qdf_mem_kmalloc_inc(ksize(ptr)); +#else +static void qdf_mem_debug_init(void) {} - return ptr; -} -qdf_export_symbol(qdf_mem_malloc_fl); +static void qdf_mem_debug_exit(void) {} void *qdf_mem_malloc_atomic_fl(size_t size, const char *func, uint32_t line) { @@ -1125,85 +1494,6 @@ void *qdf_mem_malloc_atomic_fl(size_t size, const char *func, uint32_t line) } qdf_export_symbol(qdf_mem_malloc_atomic_fl); -/** - * qdf_mem_free() - free QDF memory - * @ptr: Pointer to the starting address of the memory to be free'd. - * - * This function will free the memory pointed to by 'ptr'. - * - * Return: None - */ -void qdf_mem_free(void *ptr) -{ - if (!ptr) - return; - - if (qdf_mem_prealloc_put(ptr)) - return; - - qdf_mem_kmalloc_dec(ksize(ptr)); - - kfree(ptr); -} - -qdf_export_symbol(qdf_mem_free); -#endif - -void *qdf_aligned_malloc_fl(uint32_t *size, - void **vaddr_unaligned, - qdf_dma_addr_t *paddr_unaligned, - qdf_dma_addr_t *paddr_aligned, - uint32_t align, - const char *func, uint32_t line) -{ - void *vaddr_aligned; - uint32_t align_alloc_size; - - *vaddr_unaligned = qdf_mem_malloc_fl((qdf_size_t)*size, func, - line); - if (!*vaddr_unaligned) { - qdf_warn("Failed to alloc %uB @ %s:%d", *size, func, line); - return NULL; - } - - *paddr_unaligned = qdf_mem_virt_to_phys(*vaddr_unaligned); - - /* Re-allocate additional bytes to align base address only if - * above allocation returns unaligned address. Reason for - * trying exact size allocation above is, OS tries to allocate - * blocks of size power-of-2 pages and then free extra pages. - * e.g., of a ring size of 1MB, the allocation below will - * request 1MB plus 7 bytes for alignment, which will cause a - * 2MB block allocation,and that is failing sometimes due to - * memory fragmentation. - */ - if ((unsigned long)(*paddr_unaligned) & (align - 1)) { - align_alloc_size = *size + align - 1; - - qdf_mem_free(*vaddr_unaligned); - *vaddr_unaligned = qdf_mem_malloc_fl( - (qdf_size_t)align_alloc_size, func, line); - if (!*vaddr_unaligned) { - qdf_warn("Failed to alloc %uB @ %s:%d", - align_alloc_size, func, line); - return NULL; - } - - *paddr_unaligned = qdf_mem_virt_to_phys( - *vaddr_unaligned); - *size = align_alloc_size; - } - - *paddr_aligned = (qdf_dma_addr_t)qdf_align - ((unsigned long)(*paddr_unaligned), align); - - vaddr_aligned = (void *)((unsigned long)(*vaddr_unaligned) + - ((unsigned long)(*paddr_aligned) - - (unsigned long)(*paddr_unaligned))); - - return vaddr_aligned; -} - /** * qdf_mem_multi_pages_alloc() - allocate large size of kernel memory * @osdev: OS device handle pointer @@ -1230,10 +1520,13 @@ void qdf_mem_multi_pages_alloc(qdf_device_t osdev, void **cacheable_pages = NULL; uint16_t i; - pages->num_element_per_page = PAGE_SIZE / element_size; + if (!pages->page_size) + pages->page_size = qdf_page_size; + + pages->num_element_per_page = pages->page_size / element_size; if (!pages->num_element_per_page) { qdf_print("Invalid page %d or element size %d", - (int)PAGE_SIZE, (int)element_size); + (int)pages->page_size, (int)element_size); goto out_fail; } @@ -1250,7 +1543,8 @@ void qdf_mem_multi_pages_alloc(qdf_device_t osdev, cacheable_pages = pages->cacheable_pages; for (page_idx = 0; page_idx < pages->num_pages; page_idx++) { - cacheable_pages[page_idx] = qdf_mem_malloc(PAGE_SIZE); + cacheable_pages[page_idx] = + qdf_mem_malloc(pages->page_size); if (!cacheable_pages[page_idx]) goto page_alloc_fail; } @@ -1265,7 +1559,7 @@ void qdf_mem_multi_pages_alloc(qdf_device_t osdev, for (page_idx = 0; page_idx < pages->num_pages; page_idx++) { dma_pages->page_v_addr_start = qdf_mem_alloc_consistent(osdev, osdev->dev, - PAGE_SIZE, + pages->page_size, &dma_pages->page_p_addr); if (!dma_pages->page_v_addr_start) { qdf_print("dmaable page alloc fail pi %d", @@ -1273,7 +1567,7 @@ void qdf_mem_multi_pages_alloc(qdf_device_t osdev, goto page_alloc_fail; } dma_pages->page_v_addr_end = - dma_pages->page_v_addr_start + PAGE_SIZE; + dma_pages->page_v_addr_start + pages->page_size; dma_pages++; } pages->cacheable_pages = NULL; @@ -1288,7 +1582,8 @@ void qdf_mem_multi_pages_alloc(qdf_device_t osdev, } else { dma_pages = pages->dma_pages; for (i = 0; i < page_idx; i++) { - qdf_mem_free_consistent(osdev, osdev->dev, PAGE_SIZE, + qdf_mem_free_consistent( + osdev, osdev->dev, pages->page_size, dma_pages->page_v_addr_start, dma_pages->page_p_addr, memctxt); dma_pages++; @@ -1322,6 +1617,9 @@ void qdf_mem_multi_pages_free(qdf_device_t osdev, unsigned int page_idx; struct qdf_mem_dma_page_t *dma_pages; + if (!pages->page_size) + pages->page_size = qdf_page_size; + if (cacheable) { for (page_idx = 0; page_idx < pages->num_pages; page_idx++) qdf_mem_free(pages->cacheable_pages[page_idx]); @@ -1329,7 +1627,8 @@ void qdf_mem_multi_pages_free(qdf_device_t osdev, } else { dma_pages = pages->dma_pages; for (page_idx = 0; page_idx < pages->num_pages; page_idx++) { - qdf_mem_free_consistent(osdev, osdev->dev, PAGE_SIZE, + qdf_mem_free_consistent( + osdev, osdev->dev, pages->page_size, dma_pages->page_v_addr_start, dma_pages->page_p_addr, memctxt); dma_pages++; @@ -1343,6 +1642,129 @@ void qdf_mem_multi_pages_free(qdf_device_t osdev, return; } qdf_export_symbol(qdf_mem_multi_pages_free); +#endif + +void qdf_mem_multi_pages_zero(struct qdf_mem_multi_page_t *pages, + bool cacheable) +{ + unsigned int page_idx; + struct qdf_mem_dma_page_t *dma_pages; + + if (!pages->page_size) + pages->page_size = qdf_page_size; + + if (cacheable) { + for (page_idx = 0; page_idx < pages->num_pages; page_idx++) + qdf_mem_zero(pages->cacheable_pages[page_idx], + pages->page_size); + } else { + dma_pages = pages->dma_pages; + for (page_idx = 0; page_idx < pages->num_pages; page_idx++) { + qdf_mem_zero(dma_pages->page_v_addr_start, + pages->page_size); + dma_pages++; + } + } +} + +qdf_export_symbol(qdf_mem_multi_pages_zero); + +void __qdf_mem_free(void *ptr) +{ + if (!ptr) + return; + + if (qdf_mem_prealloc_put(ptr)) + return; + + qdf_mem_kmalloc_dec(ksize(ptr)); + + kfree(ptr); +} + +qdf_export_symbol(__qdf_mem_free); + +void *__qdf_mem_malloc(size_t size, const char *func, uint32_t line) +{ + void *ptr; + + if (!size || size > QDF_MEM_MAX_MALLOC) { + qdf_nofl_err("Cannot malloc %zu bytes @ %s:%d", size, func, + line); + return NULL; + } + + ptr = qdf_mem_prealloc_get(size); + if (ptr) + return ptr; + + ptr = kzalloc(size, qdf_mem_malloc_flags()); + if (!ptr) + return NULL; + + qdf_mem_kmalloc_inc(ksize(ptr)); + + return ptr; +} + +qdf_export_symbol(__qdf_mem_malloc); + +void *qdf_aligned_malloc_fl(uint32_t *size, + void **vaddr_unaligned, + qdf_dma_addr_t *paddr_unaligned, + qdf_dma_addr_t *paddr_aligned, + uint32_t align, + const char *func, uint32_t line) +{ + void *vaddr_aligned; + uint32_t align_alloc_size; + + *vaddr_unaligned = qdf_mem_malloc_fl((qdf_size_t)*size, func, + line); + if (!*vaddr_unaligned) { + qdf_warn("Failed to alloc %uB @ %s:%d", *size, func, line); + return NULL; + } + + *paddr_unaligned = qdf_mem_virt_to_phys(*vaddr_unaligned); + + /* Re-allocate additional bytes to align base address only if + * above allocation returns unaligned address. Reason for + * trying exact size allocation above is, OS tries to allocate + * blocks of size power-of-2 pages and then free extra pages. + * e.g., of a ring size of 1MB, the allocation below will + * request 1MB plus 7 bytes for alignment, which will cause a + * 2MB block allocation,and that is failing sometimes due to + * memory fragmentation. + */ + if ((unsigned long)(*paddr_unaligned) & (align - 1)) { + align_alloc_size = *size + align - 1; + + qdf_mem_free(*vaddr_unaligned); + *vaddr_unaligned = qdf_mem_malloc_fl( + (qdf_size_t)align_alloc_size, func, line); + if (!*vaddr_unaligned) { + qdf_warn("Failed to alloc %uB @ %s:%d", + align_alloc_size, func, line); + return NULL; + } + + *paddr_unaligned = qdf_mem_virt_to_phys( + *vaddr_unaligned); + *size = align_alloc_size; + } + + *paddr_aligned = (qdf_dma_addr_t)qdf_align + ((unsigned long)(*paddr_unaligned), align); + + vaddr_aligned = (void *)((unsigned long)(*vaddr_unaligned) + + ((unsigned long)(*paddr_aligned) - + (unsigned long)(*paddr_unaligned))); + + return vaddr_aligned; +} + +qdf_export_symbol(qdf_aligned_malloc_fl); /** * qdf_mem_multi_page_link() - Make links for multi page elements @@ -1574,7 +1996,9 @@ static inline void *qdf_mem_dma_alloc(qdf_device_t osdev, void *dev, return vaddr; } -#elif defined(QCA_WIFI_QCA8074_VP) && defined(BUILD_X86) +#elif defined(CONFIG_WIFI_EMULATION_WIFI_3_0) && defined(BUILD_X86) && \ + !defined(QCA_WIFI_QCN9000) + #define QCA8074_RAM_BASE 0x50000000 #define QDF_MEM_ALLOC_X86_MAX_RETRIES 10 void *qdf_mem_dma_alloc(qdf_device_t osdev, void *dev, qdf_size_t size, @@ -1638,6 +2062,11 @@ void *qdf_mem_alloc_consistent_debug(qdf_device_t osdev, void *dev, struct qdf_mem_header *header; void *vaddr; + if (is_initial_mem_debug_disabled) + return __qdf_mem_alloc_consistent(osdev, dev, + size, paddr, + func, line); + if (!size || size > QDF_MEM_MAX_MALLOC) { qdf_err("Cannot malloc %zu bytes @ %s:%d", size, func, line); return NULL; @@ -1681,6 +2110,14 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev, struct qdf_mem_header *header; enum qdf_mem_validation_bitmap error_bitmap; + if (is_initial_mem_debug_disabled) { + __qdf_mem_free_consistent( + osdev, dev, + size, vaddr, + paddr, memctx); + return; + } + /* freeing a null pointer is valid */ if (qdf_unlikely(!vaddr)) return; @@ -1708,31 +2145,39 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev, qdf_mem_dma_free(dev, size + QDF_DMA_MEM_DEBUG_SIZE, vaddr, paddr); } qdf_export_symbol(qdf_mem_free_consistent_debug); +#endif /* MEMORY_DEBUG */ -#else +void __qdf_mem_free_consistent(qdf_device_t osdev, void *dev, + qdf_size_t size, void *vaddr, + qdf_dma_addr_t paddr, qdf_dma_context_t memctx) +{ + qdf_mem_dma_dec(size); + qdf_mem_dma_free(dev, size, vaddr, paddr); +} -void *qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev, - qdf_size_t size, qdf_dma_addr_t *paddr) +qdf_export_symbol(__qdf_mem_free_consistent); + +void *__qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev, + qdf_size_t size, qdf_dma_addr_t *paddr, + const char *func, uint32_t line) { - void *vaddr = qdf_mem_dma_alloc(osdev, dev, size, paddr); + void *vaddr; + + if (!size || size > QDF_MEM_MAX_MALLOC) { + qdf_nofl_err("Cannot malloc %zu bytes @ %s:%d", + size, func, line); + return NULL; + } + + vaddr = qdf_mem_dma_alloc(osdev, dev, size, paddr); if (vaddr) qdf_mem_dma_inc(size); return vaddr; } -qdf_export_symbol(qdf_mem_alloc_consistent); - -void qdf_mem_free_consistent(qdf_device_t osdev, void *dev, - qdf_size_t size, void *vaddr, - qdf_dma_addr_t paddr, qdf_dma_context_t memctx) -{ - qdf_mem_dma_dec(size); - qdf_mem_dma_free(dev, size, vaddr, paddr); -} -qdf_export_symbol(qdf_mem_free_consistent); -#endif /* MEMORY_DEBUG */ +qdf_export_symbol(__qdf_mem_alloc_consistent); void *qdf_aligned_mem_alloc_consistent_fl( qdf_device_t osdev, uint32_t *size, diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_module.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_module.c index 92dff158c343b3ab8e298f9cd879a6f0d3f78fef..9c1529206c050373d7d05a22b5d82abfa13fe9c6 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_module.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_module.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, 2020 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 @@ -42,8 +42,11 @@ MODULE_LICENSE("Dual BSD/GPL"); * * Return: int */ -static int __init -qdf_mod_init(void) +#ifndef QCA_SINGLE_WIFI_3_0 +static int __init qdf_mod_init(void) +#else +int qdf_mod_init(void) +#endif { qdf_shared_print_ctrl_init(); qdf_debugfs_init(); @@ -56,15 +59,20 @@ qdf_mod_init(void) return 0; } -module_init(qdf_mod_init); +#ifndef QCA_SINGLE_WIFI_3_0 +module_init(qdf_mod_init); +#endif /** * qdf_mod_exit() - module remove * * Return: int */ -static void __exit -qdf_mod_exit(void) +#ifndef QCA_SINGLE_WIFI_3_0 +static void __exit qdf_mod_exit(void) +#else +void qdf_mod_exit(void) +#endif { qdf_event_list_destroy(); qdf_nbuf_mod_exit(); @@ -75,5 +83,7 @@ qdf_mod_exit(void) qdf_debugfs_exit(); qdf_shared_print_ctrl_cleanup(); } -module_exit(qdf_mod_exit); +#ifndef QCA_SINGLE_WIFI_3_0 +module_exit(qdf_mod_exit); +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_nbuf.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_nbuf.c index 6bddb719e314204d1491b921c0c77888529534f3..0ee852ee732791a22f4307ae751d2a82bcd313a6 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_nbuf.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_nbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -84,6 +84,7 @@ #define CHANNEL_FREQ_2512 2512 #define CHANNEL_FREQ_5000 5000 #define CHANNEL_FREQ_4000 4000 +#define CHANNEL_FREQ_5150 5150 #define FREQ_MULTIPLIER_CONST_5MHZ 5 #define FREQ_MULTIPLIER_CONST_20MHZ 20 #define RADIOTAP_5G_SPECTRUM_CHANNEL 0x0100 @@ -113,6 +114,65 @@ static uint32_t nbuf_tx_data[QDF_NBUF_TX_PKT_STATE_MAX]; static qdf_atomic_t nbuf_count; #endif +#if defined(NBUF_MEMORY_DEBUG) +static bool is_initial_mem_debug_disabled; +#endif + +/** + * __qdf_nbuf_get_ip_offset - Get IPV4/V6 header offset + * @data: Pointer to network data buffer + * + * Get the IP header offset in case of 8021Q and 8021AD + * tag is present in L2 header. + * + * Return: IP header offset + */ +static inline uint8_t __qdf_nbuf_get_ip_offset(uint8_t *data) +{ + uint16_t ether_type; + + ether_type = *(uint16_t *)(data + + QDF_NBUF_TRAC_ETH_TYPE_OFFSET); + + if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021Q))) + return QDF_NBUF_TRAC_VLAN_IP_OFFSET; + else if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021AD))) + return QDF_NBUF_TRAC_DOUBLE_VLAN_IP_OFFSET; + + return QDF_NBUF_TRAC_IP_OFFSET; +} + +qdf_export_symbol(__qdf_nbuf_get_ip_offset); + +/** + * __qdf_nbuf_get_ether_type - Get the ether type + * @data: Pointer to network data buffer + * + * Get the ether type in case of 8021Q and 8021AD tag + * is present in L2 header, e.g for the returned ether type + * value, if IPV4 data ether type 0x0800, return 0x0008. + * + * Return ether type. + */ +static inline uint16_t __qdf_nbuf_get_ether_type(uint8_t *data) +{ + uint16_t ether_type; + + ether_type = *(uint16_t *)(data + + QDF_NBUF_TRAC_ETH_TYPE_OFFSET); + + if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021Q))) + ether_type = *(uint16_t *)(data + + QDF_NBUF_TRAC_VLAN_ETH_TYPE_OFFSET); + else if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021AD))) + ether_type = *(uint16_t *)(data + + QDF_NBUF_TRAC_DOUBLE_VLAN_ETH_TYPE_OFFSET); + + return ether_type; +} + +qdf_export_symbol(__qdf_nbuf_get_ether_type); + /** * qdf_nbuf_tx_desc_count_display() - Displays the packet counter * @@ -334,7 +394,16 @@ qdf_export_symbol(__qdf_nbuf_count_get); */ void __qdf_nbuf_count_inc(qdf_nbuf_t nbuf) { - qdf_atomic_inc(&nbuf_count); + int num_nbuf = 1; + qdf_nbuf_t ext_list = qdf_nbuf_get_ext_list(nbuf); + + /* Take care to account for frag_list */ + while (ext_list) { + ++num_nbuf; + ext_list = qdf_nbuf_queue_next(ext_list); + } + + qdf_atomic_add(num_nbuf, &nbuf_count); } qdf_export_symbol(__qdf_nbuf_count_inc); @@ -347,12 +416,29 @@ qdf_export_symbol(__qdf_nbuf_count_inc); */ void __qdf_nbuf_count_dec(__qdf_nbuf_t nbuf) { - qdf_atomic_dec(&nbuf_count); + qdf_nbuf_t ext_list; + int num_nbuf; + + if (qdf_nbuf_get_users(nbuf) > 1) + return; + + num_nbuf = 1; + + /* Take care to account for frag_list */ + ext_list = qdf_nbuf_get_ext_list(nbuf); + while (ext_list) { + if (qdf_nbuf_get_users(ext_list) == 1) + ++num_nbuf; + ext_list = qdf_nbuf_queue_next(ext_list); + } + + qdf_atomic_sub(num_nbuf, &nbuf_count); } qdf_export_symbol(__qdf_nbuf_count_dec); #endif -#if defined(QCA_WIFI_QCA8074_VP) && defined(BUILD_X86) +#if defined(CONFIG_WIFI_EMULATION_WIFI_3_0) && defined(BUILD_X86) && \ + !defined(QCA_WIFI_QCN9000) struct sk_buff *__qdf_nbuf_alloc(qdf_device_t osdev, size_t size, int reserve, int align, int prio, const char *func, uint32_t line) @@ -529,6 +615,7 @@ enum qdf_nbuf_event_type { QDF_NBUF_FREE, QDF_NBUF_MAP, QDF_NBUF_UNMAP, + QDF_NBUF_ALLOC_COPY_EXPAND, }; struct qdf_nbuf_event { @@ -589,6 +676,9 @@ qdf_nbuf_track_map(qdf_nbuf_t nbuf, const char *func, uint32_t line) { QDF_STATUS status; + if (is_initial_mem_debug_disabled) + return QDF_STATUS_SUCCESS; + status = qdf_tracker_track(&qdf_nbuf_map_tracker, nbuf, func, line); if (QDF_IS_STATUS_ERROR(status)) return status; @@ -601,6 +691,9 @@ qdf_nbuf_track_map(qdf_nbuf_t nbuf, const char *func, uint32_t line) static void qdf_nbuf_untrack_map(qdf_nbuf_t nbuf, const char *func, uint32_t line) { + if (is_initial_mem_debug_disabled) + return; + qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_UNMAP); qdf_tracker_untrack(&qdf_nbuf_map_tracker, nbuf, func, line); } @@ -769,8 +862,8 @@ static void qdf_nbuf_panic_on_free_if_mapped(qdf_nbuf_t nbuf, &map_func, &map_line)) return; - QDF_DEBUG_PANIC("Nbuf freed @ %s:%u while mapped from %s:%u", - func, line, map_func, map_line); + QDF_MEMDEBUG_PANIC("Nbuf freed @ %s:%u while mapped from %s:%u", + func, line, map_func, map_line); } #else static inline void qdf_nbuf_map_tracking_init(void) @@ -1284,12 +1377,21 @@ bool __qdf_nbuf_data_is_ipv4_dhcp_pkt(uint8_t *data) { uint16_t sport; uint16_t dport; + uint8_t ipv4_offset; + uint8_t ipv4_hdr_len; + struct iphdr *iphdr; + + if (__qdf_nbuf_get_ether_type(data) != + QDF_SWAP_U16(QDF_NBUF_TRAC_IPV4_ETH_TYPE)) + return false; + + ipv4_offset = __qdf_nbuf_get_ip_offset(data); + iphdr = (struct iphdr *)(data + ipv4_offset); + ipv4_hdr_len = iphdr->ihl * QDF_NBUF_IPV4_HDR_SIZE_UNIT; - sport = (uint16_t)(*(uint16_t *)(data + QDF_NBUF_TRAC_IPV4_OFFSET + - QDF_NBUF_TRAC_IPV4_HEADER_SIZE)); - dport = (uint16_t)(*(uint16_t *)(data + QDF_NBUF_TRAC_IPV4_OFFSET + - QDF_NBUF_TRAC_IPV4_HEADER_SIZE + - sizeof(uint16_t))); + sport = *(uint16_t *)(data + ipv4_offset + ipv4_hdr_len); + dport = *(uint16_t *)(data + ipv4_offset + ipv4_hdr_len + + sizeof(uint16_t)); if (((sport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_SRV_PORT)) && (dport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_CLI_PORT))) || @@ -1314,8 +1416,7 @@ bool __qdf_nbuf_data_is_ipv4_eapol_pkt(uint8_t *data) { uint16_t ether_type; - ether_type = (uint16_t)(*(uint16_t *)(data + - QDF_NBUF_TRAC_ETH_TYPE_OFFSET)); + ether_type = __qdf_nbuf_get_ether_type(data); if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_EAPOL_ETH_TYPE)) return true; @@ -1383,8 +1484,7 @@ bool __qdf_nbuf_data_is_ipv4_arp_pkt(uint8_t *data) { uint16_t ether_type; - ether_type = (uint16_t)(*(uint16_t *)(data + - QDF_NBUF_TRAC_ETH_TYPE_OFFSET)); + ether_type = __qdf_nbuf_get_ether_type(data); if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_ARP_ETH_TYPE)) return true; @@ -1759,12 +1859,14 @@ bool __qdf_nbuf_data_is_ipv6_dhcp_pkt(uint8_t *data) { uint16_t sport; uint16_t dport; + uint8_t ipv6_offset; - sport = *(uint16_t *)(data + QDF_NBUF_TRAC_IPV6_OFFSET + - QDF_NBUF_TRAC_IPV6_HEADER_SIZE); - dport = *(uint16_t *)(data + QDF_NBUF_TRAC_IPV6_OFFSET + - QDF_NBUF_TRAC_IPV6_HEADER_SIZE + - sizeof(uint16_t)); + ipv6_offset = __qdf_nbuf_get_ip_offset(data); + sport = *(uint16_t *)(data + ipv6_offset + + QDF_NBUF_TRAC_IPV6_HEADER_SIZE); + dport = *(uint16_t *)(data + ipv6_offset + + QDF_NBUF_TRAC_IPV6_HEADER_SIZE + + sizeof(uint16_t)); if (((sport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP6_SRV_PORT)) && (dport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP6_CLI_PORT))) || @@ -1888,6 +1990,8 @@ bool __qdf_nbuf_data_is_icmp_pkt(uint8_t *data) return false; } +qdf_export_symbol(__qdf_nbuf_data_is_icmp_pkt); + /** * __qdf_nbuf_data_is_icmpv6_pkt() - check if it is IPV6 ICMPV6 packet. * @data: Pointer to IPV6 ICMPV6 packet data buffer @@ -2320,6 +2424,11 @@ void qdf_net_buf_debug_init(void) { uint32_t i; + is_initial_mem_debug_disabled = qdf_mem_debug_config_get(); + + if (is_initial_mem_debug_disabled) + return; + qdf_atomic_set(&qdf_nbuf_history_index, -1); qdf_nbuf_map_tracking_init(); @@ -2349,6 +2458,9 @@ void qdf_net_buf_debug_exit(void) QDF_NBUF_TRACK *p_node; QDF_NBUF_TRACK *p_prev; + if (is_initial_mem_debug_disabled) + return; + for (i = 0; i < QDF_NET_BUF_TRACK_MAX_SIZE; i++) { spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag); p_node = gp_qdf_net_buf_track_tbl[i]; @@ -2435,6 +2547,9 @@ void qdf_net_buf_debug_add_node(qdf_nbuf_t net_buf, size_t size, QDF_NBUF_TRACK *p_node; QDF_NBUF_TRACK *new_node; + if (is_initial_mem_debug_disabled) + return; + new_node = qdf_nbuf_track_alloc(); i = qdf_net_buf_debug_hash(net_buf); @@ -2475,6 +2590,9 @@ void qdf_net_buf_debug_update_node(qdf_nbuf_t net_buf, const char *func_name, unsigned long irq_flag; QDF_NBUF_TRACK *p_node; + if (is_initial_mem_debug_disabled) + return; + i = qdf_net_buf_debug_hash(net_buf); spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag); @@ -2499,6 +2617,9 @@ void qdf_net_buf_debug_update_map_node(qdf_nbuf_t net_buf, unsigned long irq_flag; QDF_NBUF_TRACK *p_node; + if (is_initial_mem_debug_disabled) + return; + i = qdf_net_buf_debug_hash(net_buf); spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag); @@ -2513,6 +2634,8 @@ void qdf_net_buf_debug_update_map_node(qdf_nbuf_t net_buf, spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag); } +qdf_export_symbol(qdf_net_buf_debug_update_map_node); + void qdf_net_buf_debug_update_unmap_node(qdf_nbuf_t net_buf, const char *func_name, uint32_t line_num) @@ -2521,6 +2644,9 @@ void qdf_net_buf_debug_update_unmap_node(qdf_nbuf_t net_buf, unsigned long irq_flag; QDF_NBUF_TRACK *p_node; + if (is_initial_mem_debug_disabled) + return; + i = qdf_net_buf_debug_hash(net_buf); spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag); @@ -2535,6 +2661,8 @@ void qdf_net_buf_debug_update_unmap_node(qdf_nbuf_t net_buf, spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag); } +qdf_export_symbol(qdf_net_buf_debug_update_unmap_node); + /** * qdf_net_buf_debug_delete_node() - remove skb from debug hash table * @@ -2548,6 +2676,9 @@ void qdf_net_buf_debug_delete_node(qdf_nbuf_t net_buf) unsigned long irq_flag; QDF_NBUF_TRACK *p_prev; + if (is_initial_mem_debug_disabled) + return; + i = qdf_net_buf_debug_hash(net_buf); spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag); @@ -2593,6 +2724,9 @@ void qdf_net_buf_debug_acquire_skb(qdf_nbuf_t net_buf, { qdf_nbuf_t ext_list = qdf_nbuf_get_ext_list(net_buf); + if (is_initial_mem_debug_disabled) + return; + while (ext_list) { /* * Take care to add if it is Jumbo packet connected using @@ -2622,6 +2756,9 @@ void qdf_net_buf_debug_release_skb(qdf_nbuf_t net_buf) { qdf_nbuf_t ext_list = qdf_nbuf_get_ext_list(net_buf); + if (is_initial_mem_debug_disabled) + return; + while (ext_list) { /* * Take care to free if it is Jumbo packet connected using @@ -2653,6 +2790,11 @@ qdf_nbuf_t qdf_nbuf_alloc_debug(qdf_device_t osdev, qdf_size_t size, { qdf_nbuf_t nbuf; + if (is_initial_mem_debug_disabled) + return __qdf_nbuf_alloc(osdev, size, + reserve, align, + prio, func, line); + nbuf = __qdf_nbuf_alloc(osdev, size, reserve, align, prio, func, line); /* Store SKB in internal QDF tracking table */ @@ -2674,6 +2816,9 @@ void qdf_nbuf_free_debug(qdf_nbuf_t nbuf, const char *func, uint32_t line) if (qdf_unlikely(!nbuf)) return; + if (is_initial_mem_debug_disabled) + goto free_buf; + if (qdf_nbuf_get_users(nbuf) > 1) goto free_buf; @@ -2702,6 +2847,9 @@ qdf_nbuf_t qdf_nbuf_clone_debug(qdf_nbuf_t buf, const char *func, uint32_t line) { qdf_nbuf_t cloned_buf = __qdf_nbuf_clone(buf); + if (is_initial_mem_debug_disabled) + return cloned_buf; + if (qdf_unlikely(!cloned_buf)) return NULL; @@ -2717,6 +2865,9 @@ qdf_nbuf_t qdf_nbuf_copy_debug(qdf_nbuf_t buf, const char *func, uint32_t line) { qdf_nbuf_t copied_buf = __qdf_nbuf_copy(buf); + if (is_initial_mem_debug_disabled) + return copied_buf; + if (qdf_unlikely(!copied_buf)) return NULL; @@ -2728,6 +2879,28 @@ qdf_nbuf_t qdf_nbuf_copy_debug(qdf_nbuf_t buf, const char *func, uint32_t line) } qdf_export_symbol(qdf_nbuf_copy_debug); +qdf_nbuf_t +qdf_nbuf_copy_expand_debug(qdf_nbuf_t buf, int headroom, int tailroom, + const char *func, uint32_t line) +{ + qdf_nbuf_t copied_buf = __qdf_nbuf_copy_expand(buf, headroom, tailroom); + + if (qdf_unlikely(!copied_buf)) + return NULL; + + if (is_initial_mem_debug_disabled) + return copied_buf; + + /* Store SKB in internal QDF tracking table */ + qdf_net_buf_debug_add_node(copied_buf, 0, func, line); + qdf_nbuf_history_add(copied_buf, func, line, + QDF_NBUF_ALLOC_COPY_EXPAND); + + return copied_buf; +} + +qdf_export_symbol(qdf_nbuf_copy_expand_debug); + #endif /* NBUF_MEMORY_DEBUG */ #if defined(FEATURE_TSO) @@ -2766,6 +2939,51 @@ struct qdf_tso_cmn_seg_info_t { uint32_t tcp_seq_num; }; +/** + * qdf_nbuf_adj_tso_frag() - adjustment for buffer address of tso fragment + * + * @skb: network buffer + * + * Return: byte offset length of 8 bytes aligned. + */ +#ifdef FIX_TXDMA_LIMITATION +static uint8_t qdf_nbuf_adj_tso_frag(struct sk_buff *skb) +{ + uint32_t eit_hdr_len; + uint8_t *eit_hdr; + uint8_t byte_8_align_offset; + + eit_hdr = skb->data; + eit_hdr_len = (skb_transport_header(skb) + - skb_mac_header(skb)) + tcp_hdrlen(skb); + byte_8_align_offset = ((unsigned long)(eit_hdr) + eit_hdr_len) & 0x7L; + if (qdf_unlikely(byte_8_align_offset)) { + TSO_DEBUG("%pK,Len %d %d", + eit_hdr, eit_hdr_len, byte_8_align_offset); + if (unlikely(skb_headroom(skb) < byte_8_align_offset)) { + TSO_DEBUG("[%d]Insufficient headroom,[%pK],[%pK],[%d]", + __LINE__, skb->head, skb->data, + byte_8_align_offset); + return 0; + } + qdf_nbuf_push_head(skb, byte_8_align_offset); + qdf_mem_move(skb->data, + skb->data + byte_8_align_offset, + eit_hdr_len); + skb->len -= byte_8_align_offset; + skb->mac_header -= byte_8_align_offset; + skb->network_header -= byte_8_align_offset; + skb->transport_header -= byte_8_align_offset; + } + return byte_8_align_offset; +} +#else +static uint8_t qdf_nbuf_adj_tso_frag(struct sk_buff *skb) +{ + return 0; +} +#endif + /** * __qdf_nbuf_get_tso_cmn_seg_info() - get TSO common * information @@ -2930,18 +3148,21 @@ uint32_t __qdf_nbuf_get_tso_info(qdf_device_t osdev, struct sk_buff *skb, uint32_t num_seg = 0; struct qdf_tso_seg_elem_t *curr_seg; struct qdf_tso_num_seg_elem_t *total_num_seg; - struct skb_frag_struct *frag = NULL; + skb_frag_t *frag = NULL; uint32_t tso_frag_len = 0; /* tso segment's fragment length*/ uint32_t skb_frag_len = 0; /* skb's fragment length (contiguous memory)*/ uint32_t skb_proc = skb->len; /* bytes of skb pending processing */ uint32_t tso_seg_size = skb_shinfo(skb)->gso_size; int j = 0; /* skb fragment index */ + uint8_t byte_8_align_offset; memset(&tso_cmn_info, 0x0, sizeof(tso_cmn_info)); total_num_seg = tso_info->tso_num_seg_list; curr_seg = tso_info->tso_seg_list; total_num_seg->num_seg.tso_cmn_num_seg = 0; + byte_8_align_offset = qdf_nbuf_adj_tso_frag(skb); + if (qdf_unlikely(__qdf_nbuf_get_tso_cmn_seg_info(osdev, skb, &tso_cmn_info))) { qdf_warn("TSO: error getting common segment info"); @@ -2957,7 +3178,9 @@ uint32_t __qdf_nbuf_get_tso_info(qdf_device_t osdev, struct sk_buff *skb, skb_proc -= tso_cmn_info.eit_hdr_len; /* get the address to the next tso fragment */ - tso_frag_vaddr = skb->data + tso_cmn_info.eit_hdr_len; + tso_frag_vaddr = skb->data + + tso_cmn_info.eit_hdr_len + + byte_8_align_offset; /* get the length of the next tso fragment */ tso_frag_len = min(skb_frag_len, tso_seg_size); @@ -3185,6 +3408,19 @@ void __qdf_nbuf_unmap_tso_segment(qdf_device_t osdev, } qdf_export_symbol(__qdf_nbuf_unmap_tso_segment); +size_t __qdf_nbuf_get_tcp_payload_len(struct sk_buff *skb) +{ + size_t packet_len; + + packet_len = skb->len - + ((skb_transport_header(skb) - skb_mac_header(skb)) + + tcp_hdrlen(skb)); + + return packet_len; +} + +qdf_export_symbol(__qdf_nbuf_get_tcp_payload_len); + /** * __qdf_nbuf_get_tso_num_seg() - function to divide a TSO nbuf * into segments @@ -3208,7 +3444,7 @@ uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb) uint32_t skb_frag_len = 0; uint32_t eit_hdr_len = (skb_transport_header(skb) - skb_mac_header(skb)) + tcp_hdrlen(skb); - struct skb_frag_struct *frag = NULL; + skb_frag_t *frag = NULL; int j = 0; uint32_t temp_num_seg = 0; @@ -3290,11 +3526,11 @@ uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb) return num_segs; } -#else +#elif !defined(QCA_WIFI_QCN9000) uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb) { uint32_t i, gso_size, tmp_len, num_segs = 0; - struct skb_frag_struct *frag = NULL; + skb_frag_t *frag = NULL; /* * Check if the head SKB or any of frags are allocated in < 0x50000000 @@ -3319,6 +3555,42 @@ uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb) } + gso_size = skb_shinfo(skb)->gso_size; + tmp_len = skb->len - ((skb_transport_header(skb) - skb_mac_header(skb)) + + tcp_hdrlen(skb)); + while (tmp_len) { + num_segs++; + if (tmp_len > gso_size) + tmp_len -= gso_size; + else + break; + } + + return num_segs; + + /* + * Do not free this frame, just do socket level accounting + * so that this is not reused. + */ +fail: + if (skb->sk) + atomic_sub(skb->truesize, &(skb->sk->sk_wmem_alloc)); + + return 0; +} +#else +uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb) +{ + uint32_t i, gso_size, tmp_len, num_segs = 0; + skb_frag_t *frag = NULL; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + + if (!frag) + goto fail; + } + gso_size = skb_shinfo(skb)->gso_size; tmp_len = skb->len - ((skb_transport_header(skb) - skb_mac_header(skb)) + tcp_hdrlen(skb)); @@ -3984,8 +4256,6 @@ qdf_nbuf_update_radiotap_he_mu_other_flags(struct mon_rx_status *rx_status, return rtap_len; } -#define IEEE80211_RADIOTAP_TX_STATUS 0 -#define IEEE80211_RADIOTAP_RETRY_COUNT 1 /** * This is the length for radiotap, combined length @@ -4004,11 +4274,6 @@ qdf_nbuf_update_radiotap_he_mu_other_flags(struct mon_rx_status *rx_status, #define RADIOTAP_AMPDU_STATUS_LEN (8 + 3) #define RADIOTAP_VENDOR_NS_LEN \ (sizeof(struct qdf_radiotap_vendor_ns_ath) + 1) -/* This is Radio Tap Header Extension Length. - * 4 Bytes for Extended it_present bit map + - * 4 bytes padding for alignment - */ -#define RADIOTAP_HEADER_EXT_LEN (2 * sizeof(uint32_t)) #define RADIOTAP_HEADER_LEN (sizeof(struct ieee80211_radiotap_header) + \ RADIOTAP_FIXED_HEADER_LEN + \ RADIOTAP_HT_FLAGS_LEN + \ @@ -4017,42 +4282,13 @@ qdf_nbuf_update_radiotap_he_mu_other_flags(struct mon_rx_status *rx_status, RADIOTAP_HE_FLAGS_LEN + \ RADIOTAP_HE_MU_FLAGS_LEN + \ RADIOTAP_HE_MU_OTHER_FLAGS_LEN + \ - RADIOTAP_VENDOR_NS_LEN + \ - RADIOTAP_HEADER_EXT_LEN) + RADIOTAP_VENDOR_NS_LEN) #define IEEE80211_RADIOTAP_HE 23 #define IEEE80211_RADIOTAP_HE_MU 24 #define IEEE80211_RADIOTAP_HE_MU_OTHER 25 uint8_t ATH_OUI[] = {0x00, 0x03, 0x7f}; /* Atheros OUI */ -/** - * radiotap_num_to_freq() - Get frequency from chan number - * @chan_num - Input channel number - * - * Return - Channel frequency in Mhz - */ -static uint16_t radiotap_num_to_freq (uint16_t chan_num) -{ - if (chan_num == CHANNEL_NUM_14) - return CHANNEL_FREQ_2484; - if (chan_num < CHANNEL_NUM_14) - return CHANNEL_FREQ_2407 + - (chan_num * FREQ_MULTIPLIER_CONST_5MHZ); - - if (chan_num < CHANNEL_NUM_27) - return CHANNEL_FREQ_2512 + - ((chan_num - CHANNEL_NUM_15) * - FREQ_MULTIPLIER_CONST_20MHZ); - - if (chan_num > CHANNEL_NUM_182 && - chan_num < CHANNEL_NUM_197) - return ((chan_num * FREQ_MULTIPLIER_CONST_5MHZ) + - CHANNEL_FREQ_4000); - - return CHANNEL_FREQ_5000 + - (chan_num * FREQ_MULTIPLIER_CONST_5MHZ); -} - /** * qdf_nbuf_update_radiotap_ampdu_flags() - Update radiotap header ampdu flags * @rx_status: Pointer to rx_status. @@ -4105,14 +4341,6 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status, uint32_t rtap_len = rtap_hdr_len; uint8_t length = rtap_len; struct qdf_radiotap_vendor_ns_ath *radiotap_vendor_ns_ath; - uint32_t *rtap_ext = NULL; - - /* Adding Extended Header space */ - if (rx_status->add_rtap_ext) { - rtap_hdr_len += RADIOTAP_HEADER_EXT_LEN; - rtap_len = rtap_hdr_len; - } - length = rtap_len; /* IEEE80211_RADIOTAP_TSFT __le64 microseconds*/ rthdr->it_present = (1 << IEEE80211_RADIOTAP_TSFT); @@ -4139,11 +4367,10 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status, /* IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap */ rthdr->it_present |= (1 << IEEE80211_RADIOTAP_CHANNEL); - rx_status->chan_freq = radiotap_num_to_freq(rx_status->chan_num); put_unaligned_le16(rx_status->chan_freq, &rtap_buf[rtap_len]); rtap_len += 2; /* Channel flags. */ - if (rx_status->chan_num > CHANNEL_NUM_35) + if (rx_status->chan_freq > CHANNEL_FREQ_5150) rx_status->chan_flags = RADIOTAP_5G_SPECTRUM_CHANNEL; else rx_status->chan_flags = RADIOTAP_2G_SPECTRUM_CHANNEL; @@ -4297,20 +4524,6 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status, cpu_to_le32(rx_status->ppdu_timestamp); rtap_len += sizeof(*radiotap_vendor_ns_ath); - /* Add Extension to Radiotap Header & corresponding data */ - if (rx_status->add_rtap_ext) { - rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_EXT); - rtap_ext = (uint32_t *)&rthdr->it_present; - rtap_ext++; - *rtap_ext = cpu_to_le32(1 << IEEE80211_RADIOTAP_TX_STATUS); - *rtap_ext |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RETRY_COUNT); - - rtap_buf[rtap_len] = rx_status->tx_status; - rtap_len += 1; - rtap_buf[rtap_len] = rx_status->tx_retry_cnt; - rtap_len += 1; - } - rthdr->it_len = cpu_to_le16(rtap_len); rthdr->it_present = cpu_to_le32(rthdr->it_present); diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_periodic_work.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_periodic_work.c index 15aeb3435e1c7283b3cd591dd1b0d0210a212cbf..a845ed18ea3a4e892f3cad335738c71ca05c1406 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_periodic_work.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_periodic_work.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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 @@ -97,7 +97,7 @@ QDF_STATUS __qdf_periodic_work_create(struct qdf_periodic_work *pwork, if (QDF_IS_STATUS_ERROR(status)) return status; - INIT_DELAYED_WORK(&pwork->dwork, __qdf_periodic_work_handler); + INIT_DEFERRABLE_WORK(&pwork->dwork, __qdf_periodic_work_handler); pwork->callback = callback; pwork->context = context; pwork->msec = 0; diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_streamfs.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_streamfs.c new file mode 100644 index 0000000000000000000000000000000000000000..25f58a33235aa60dad7fbc4dd9aae03a54da2a84 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_streamfs.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2018, 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: qdf_streamfs + * This file provides QDF stream file system APIs + */ + +#include +#include +#include +#include + +/** + * qdf_create_buf_file_handler() - Create streamfs buffer file + * @filename: base name of files to create, NULL for buffering only + * @parent: dentry of parent directory, NULL for root directory + * @mode: filemode + * @buf: streamfs channel buf + * @is_global: pointer to set whether this buf file is global or not. + * + * Returns dentry if successful, NULL otherwise. + */ +static qdf_dentry_t +qdf_create_buf_file_handler(const char *filename, qdf_dentry_t parent, + uint16_t mode, qdf_streamfs_chan_buf_t buf, + int32_t *is_global) +{ + qdf_dentry_t buf_file; + *is_global = 1; + buf_file = qdf_streamfs_create_file(filename, mode, parent, buf); + + if (!buf_file) + return NULL; + + return buf_file; +} + +/** + * qdf_remove_buf_file_handler() - Remove streamfs buffer file + * @dentry:dentry + */ +static int qdf_remove_buf_file_handler(qdf_dentry_t dentry) +{ + qdf_streamfs_remove_file(dentry); + + return 0; +} + +static struct rchan_callbacks g_qdf_streamfs_cb = { + .create_buf_file = qdf_create_buf_file_handler, + .remove_buf_file = qdf_remove_buf_file_handler, +}; + +qdf_dentry_t +qdf_streamfs_create_file(const char *name, uint16_t mode, + qdf_dentry_t parent, + qdf_streamfs_chan_buf_t buf) +{ + qdf_dentry_t file = NULL; + + if (!name) + return NULL; + + file = debugfs_create_file(name, mode, + (struct dentry *)parent, + buf, &relay_file_operations); + + return file; +} + +qdf_export_symbol(qdf_streamfs_create_file); + +qdf_streamfs_chan_t +qdf_streamfs_open(const char *base_filename, qdf_dentry_t parent, + size_t subbuf_size, size_t n_subbufs, + void *private_data) +{ + qdf_streamfs_chan_t channel_ptr = NULL; + + channel_ptr = relay_open(base_filename, + (struct dentry *)parent, + subbuf_size, n_subbufs, + &g_qdf_streamfs_cb, + private_data); + + return channel_ptr; +} + +qdf_export_symbol(qdf_streamfs_open); + +void qdf_streamfs_close(qdf_streamfs_chan_t chan) +{ + if (chan) + relay_close(chan); +} + +qdf_export_symbol(qdf_streamfs_close); + +void qdf_streamfs_flush(qdf_streamfs_chan_t chan) +{ + if (chan) + relay_flush(chan); +} + +qdf_export_symbol(qdf_streamfs_flush); + +void qdf_streamfs_reset(qdf_streamfs_chan_t chan) +{ + if (chan) + relay_reset(chan); +} + +qdf_export_symbol(qdf_streamfs_reset); + +void qdf_streamfs_subbufs_consumed(qdf_streamfs_chan_t chan, + unsigned int cpu, + size_t consumed) +{ + if (chan) + relay_subbufs_consumed(chan, cpu, consumed); +} + +qdf_export_symbol(qdf_streamfs_subbufs_consumed); + +void qdf_streamfs_write(qdf_streamfs_chan_t chan, + const void *data, + size_t length) +{ + if (chan) + relay_write(chan, data, length); +} + +qdf_export_symbol(qdf_streamfs_write); diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_threads.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_threads.c index 8ec0963b0036057917b23d923667a30eb3fb2d5f..2e6463e737133db456387eba84e2d8d3789e1a14 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_threads.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_threads.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -106,7 +106,7 @@ void qdf_busy_wait(uint32_t us_interval) } qdf_export_symbol(qdf_busy_wait); -#ifdef MSM_PLATFORM +#ifdef PF_WAKE_UP_IDLE void qdf_set_wake_up_idle(bool idle) { set_wake_up_idle(idle); @@ -115,7 +115,7 @@ void qdf_set_wake_up_idle(bool idle) void qdf_set_wake_up_idle(bool idle) { } -#endif /* MSM_PLATFORM */ +#endif /* PF_WAKE_UP_IDLE */ qdf_export_symbol(qdf_set_wake_up_idle); @@ -187,10 +187,29 @@ qdf_export_symbol(qdf_wake_up_process); * 2) arm architectures in kernel versions >=4.14 * 3) backported kernels defining BACKPORTED_EXPORT_SAVE_STACK_TRACE_TSK_ARM */ -#if (defined(WLAN_HOST_ARCH_ARM) && !WLAN_HOST_ARCH_ARM) || \ +#if ((defined(WLAN_HOST_ARCH_ARM) && !WLAN_HOST_ARCH_ARM) || \ LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) || \ - defined(BACKPORTED_EXPORT_SAVE_STACK_TRACE_TSK_ARM) + defined(BACKPORTED_EXPORT_SAVE_STACK_TRACE_TSK_ARM)) && \ + defined(CONFIG_STACKTRACE) && !defined(CONFIG_ARCH_STACKWALK) #define QDF_PRINT_TRACE_COUNT 32 + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +void qdf_print_thread_trace(qdf_thread_t *thread) +{ + const int spaces = 4; + struct task_struct *task = thread; + unsigned long entries[QDF_PRINT_TRACE_COUNT] = {0}; + struct stack_trace trace = { + .nr_entries = 0, + .skip = 0, + .entries = &entries[0], + .max_entries = QDF_PRINT_TRACE_COUNT, + }; + + save_stack_trace_tsk(task, &trace); + stack_trace_print(entries, trace.nr_entries, spaces); +} +#else void qdf_print_thread_trace(qdf_thread_t *thread) { const int spaces = 4; @@ -206,6 +225,8 @@ void qdf_print_thread_trace(qdf_thread_t *thread) save_stack_trace_tsk(task, &trace); print_stack_trace(&trace, spaces); } +#endif + #else void qdf_print_thread_trace(qdf_thread_t *thread) { } #endif /* KERNEL_VERSION(4, 14, 0) */ @@ -257,3 +278,18 @@ void qdf_cpumask_setall(qdf_cpu_mask *dstp) } qdf_export_symbol(qdf_cpumask_setall); + +bool qdf_cpumask_empty(const struct cpumask *srcp) +{ + return cpumask_empty(srcp); +} + +qdf_export_symbol(qdf_cpumask_empty); + +void qdf_cpumask_copy(struct cpumask *dstp, + const struct cpumask *srcp) +{ + return cpumask_copy(dstp, srcp); +} + +qdf_export_symbol(qdf_cpumask_copy); diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_trace.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_trace.c index e6f5323683624e9cca000e87adddd44182b523f6..681046ad804ac9e249605d85d3f99cf84512ea12 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_trace.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_trace.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-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 @@ -157,22 +157,8 @@ qdf_export_symbol(qdf_vtrace_msg); /* Buffer size = data bytes(2 hex chars plus space) + NULL */ #define BUFFER_SIZE ((QDF_DP_TRACE_RECORD_SIZE * 3) + 1) -/** - * qdf_trace_hex_dump() - externally called hex dump function - * @module: Module identifier a member of the QDF_MODULE_ID enumeration that - * identifies the module issuing the trace message. - * @level: Trace level a member of the QDF_TRACE_LEVEL enumeration indicating - * the severity of the condition causing the trace message to be - * issued. More severe conditions are more likely to be logged. - * @data: The base address of the buffer to be logged. - * @buf_len: The size of the buffer to be logged. - * - * Checks the level of severity and accordingly prints the trace messages - * - * Return: None - */ -void qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, - void *data, int buf_len) +static void __qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, + void *data, int buf_len, bool print_ascii) { const u8 *ptr = data; int i = 0; @@ -187,15 +173,30 @@ void qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, buf_len -= ROW_SIZE; hex_dump_to_buffer(ptr, linelen, ROW_SIZE, 1, - linebuf, sizeof(linebuf), false); + linebuf, sizeof(linebuf), print_ascii); qdf_trace_msg(module, level, "%.8x: %s", i, linebuf); ptr += ROW_SIZE; i += ROW_SIZE; } } + +void qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, + void *data, int buf_len) +{ + __qdf_trace_hex_dump(module, level, data, buf_len, false); +} + qdf_export_symbol(qdf_trace_hex_dump); +void qdf_trace_hex_ascii_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, + void *data, int buf_len) +{ + __qdf_trace_hex_dump(module, level, data, buf_len, true); +} + +qdf_export_symbol(qdf_trace_hex_ascii_dump); + #endif #ifdef TRACE_RECORD @@ -692,7 +693,7 @@ static void qdf_dp_unused(struct qdf_dp_trace_record_s *record, */ void qdf_dp_trace_init(bool live_mode_config, uint8_t thresh, uint16_t time_limit, uint8_t verbosity, - uint8_t proto_bitmap) + uint32_t proto_bitmap) { uint8_t i; @@ -739,6 +740,8 @@ void qdf_dp_trace_init(bool live_mode_config, uint8_t thresh, qdf_dp_display_proto_pkt; qdf_dp_trace_cb_table[QDF_DP_TRACE_MGMT_PACKET_RECORD] = qdf_dp_display_mgmt_pkt; + qdf_dp_trace_cb_table[QDF_DP_TRACE_TX_CREDIT_RECORD] = + qdf_dp_display_credit_record; qdf_dp_trace_cb_table[QDF_DP_TRACE_EVENT_RECORD] = qdf_dp_display_event_record; @@ -765,7 +768,7 @@ void qdf_dp_trace_deinit(void) * * Return: None */ -void qdf_dp_trace_set_value(uint8_t proto_bitmap, uint8_t no_of_record, +void qdf_dp_trace_set_value(uint32_t proto_bitmap, uint8_t no_of_record, uint8_t verbosity) { g_qdf_dp_trace_data.proto_bitmap = proto_bitmap; @@ -891,7 +894,7 @@ static bool qdf_dp_trace_verbosity_check(enum QDF_DP_TRACE_ID code) * * Return: proto bitmap */ -uint8_t qdf_dp_get_proto_bitmap(void) +uint32_t qdf_dp_get_proto_bitmap(void) { if (g_qdf_dp_trace_data.enable) return g_qdf_dp_trace_data.proto_bitmap; @@ -992,6 +995,8 @@ const char *qdf_dp_code_to_string(enum QDF_DP_TRACE_ID code) return "ICMPv6:"; case QDF_DP_TRACE_MGMT_PACKET_RECORD: return "MGMT:"; + case QDF_DP_TRACE_TX_CREDIT_RECORD: + return "CREDIT:"; case QDF_DP_TRACE_EVENT_RECORD: return "EVENT:"; case QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD: @@ -1068,6 +1073,39 @@ static const char *qdf_dp_dir_to_str(enum qdf_proto_dir dir) } } +static const char *qdf_dp_credit_source_to_str( + enum QDF_CREDIT_UPDATE_SOURCE source) +{ + switch (source) { + case QDF_TX_SCHED: + return "TX SCHED"; + case QDF_TX_COMP: + return "TX COMP"; + case QDF_TX_CREDIT_UPDATE: + return "CREDIT UP"; + case QDF_TX_HTT_MSG: + return "HTT TX MSG"; + case QDF_HTT_ATTACH: + return "HTT ATTACH"; + default: + return "invalid"; + } +} + +static const char *qdf_dp_operation_to_str(enum QDF_CREDIT_OPERATION op) +{ + switch (op) { + case QDF_CREDIT_INC: + return "+"; + case QDF_CREDIT_DEC: + return "-"; + case QDF_CREDIT_ABS: + return "ABS"; + default: + return "invalid"; + } +} + /** * qdf_dp_type_to_str() - convert packet type to string * @type: type @@ -1519,13 +1557,15 @@ void qdf_dp_log_proto_pkt_info(uint8_t *sa, uint8_t *da, uint8_t type, last_ticks_rx[subtype] = curr_ticks; if (status == QDF_TX_RX_STATUS_INVALID) - qdf_nofl_info("%s %s: SA:%pM DA:%pM", + qdf_nofl_info("%s %s: SA:" QDF_MAC_ADDR_FMT " DA:" QDF_MAC_ADDR_FMT, qdf_get_pkt_type_string(type, subtype), - dir ? "RX":"TX", sa, da); + dir ? "RX" : "TX", QDF_MAC_ADDR_REF(sa), + QDF_MAC_ADDR_REF(da)); else - qdf_nofl_info("%s %s: SA:%pM DA:%pM msdu_id:%d status: %s", + qdf_nofl_info("%s %s: SA:" QDF_MAC_ADDR_FMT " DA:" QDF_MAC_ADDR_FMT " msdu_id:%d status: %s", qdf_get_pkt_type_string(type, subtype), - dir ? "RX":"TX", sa, da, msdu_id, + dir ? "RX" : "TX", QDF_MAC_ADDR_REF(sa), + QDF_MAC_ADDR_REF(da), msdu_id, qdf_get_pkt_status_string(status)); } @@ -1898,6 +1938,91 @@ void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id, } qdf_export_symbol(qdf_dp_trace_mgmt_pkt); +static void +qdf_dpt_display_credit_record_debugfs(qdf_debugfs_file_t file, + struct qdf_dp_trace_record_s *record, + uint32_t index) +{ + int loc; + char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; + struct qdf_dp_trace_credit_record *buf = + (struct qdf_dp_trace_credit_record *)record->data; + + loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), + index, 0, record); + if (buf->operation == QDF_OP_NA) + qdf_debugfs_printf(file, "%s [%s] [T: %d G0: %d G1: %d]\n", + prepend_str, + qdf_dp_credit_source_to_str(buf->source), + buf->total_credits, buf->g0_credit, + buf->g1_credit); + else + qdf_debugfs_printf(file, + "%s [%s] [T: %d G0: %d G1: %d] [%s %d]\n", + prepend_str, + qdf_dp_credit_source_to_str(buf->source), + buf->total_credits, buf->g0_credit, + buf->g1_credit, + qdf_dp_operation_to_str(buf->operation), + buf->delta); +} + +void qdf_dp_display_credit_record(struct qdf_dp_trace_record_s *record, + uint16_t index, uint8_t pdev_id, uint8_t info) +{ + int loc; + char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; + struct qdf_dp_trace_credit_record *buf = + (struct qdf_dp_trace_credit_record *)record->data; + + loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), + index, info, record); + if (buf->operation == QDF_OP_NA) + DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d]", + prepend_str, + qdf_dp_credit_source_to_str(buf->source), + buf->total_credits, buf->g0_credit, + buf->g1_credit); + else + DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d] [%s %d]", + prepend_str, + qdf_dp_credit_source_to_str(buf->source), + buf->total_credits, buf->g0_credit, + buf->g1_credit, + qdf_dp_operation_to_str(buf->operation), + buf->delta); +} + +void qdf_dp_trace_credit_record(enum QDF_CREDIT_UPDATE_SOURCE source, + enum QDF_CREDIT_OPERATION operation, + int delta, int total_credits, + int g0_credit, int g1_credit) +{ + struct qdf_dp_trace_credit_record buf; + int buf_size = sizeof(struct qdf_dp_trace_credit_record); + enum QDF_DP_TRACE_ID code = QDF_DP_TRACE_TX_CREDIT_RECORD; + + if (qdf_dp_enable_check(NULL, code, QDF_NA) == false) + return; + + if (!(qdf_dp_get_proto_bitmap() & QDF_HL_CREDIT_TRACKING)) + return; + + if (buf_size > QDF_DP_TRACE_RECORD_SIZE) + QDF_BUG(0); + + buf.source = source; + buf.operation = operation; + buf.delta = delta; + buf.total_credits = total_credits; + buf.g0_credit = g0_credit; + buf.g1_credit = g1_credit; + + qdf_dp_add_record(code, QDF_TRACE_DEFAULT_PDEV_ID, (uint8_t *)&buf, + buf_size, NULL, 0, false); +} +qdf_export_symbol(qdf_dp_trace_credit_record); + void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record, uint16_t index, uint8_t pdev_id, uint8_t info) { @@ -1961,14 +2086,14 @@ void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record, loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), index, info, record); DPTRACE_PRINT("%s [%d] [%s] SA: " - QDF_MAC_ADDR_STR " %s DA: " - QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_FMT " %s DA: " + QDF_MAC_ADDR_FMT, prepend_str, buf->vdev_id, qdf_dp_subtype_to_str(buf->subtype), - QDF_MAC_ADDR_ARRAY(buf->sa.bytes), + QDF_MAC_ADDR_REF(buf->sa.bytes), qdf_dp_dir_to_str(buf->dir), - QDF_MAC_ADDR_ARRAY(buf->da.bytes)); + QDF_MAC_ADDR_REF(buf->da.bytes)); } qdf_export_symbol(qdf_dp_display_proto_pkt); @@ -2423,14 +2548,14 @@ static void qdf_dpt_display_proto_pkt_debugfs(qdf_debugfs_file_t file, loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), index, 0, record); qdf_debugfs_printf(file, "%s [%d] [%s] SA: " - QDF_MAC_ADDR_STR " %s DA: " - QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_FMT " %s DA: " + QDF_MAC_ADDR_FMT, prepend_str, buf->vdev_id, qdf_dp_subtype_to_str(buf->subtype), - QDF_MAC_ADDR_ARRAY(buf->sa.bytes), + QDF_MAC_ADDR_REF(buf->sa.bytes), qdf_dp_dir_to_str(buf->dir), - QDF_MAC_ADDR_ARRAY(buf->da.bytes)); + QDF_MAC_ADDR_REF(buf->da.bytes)); qdf_debugfs_printf(file, "\n"); } @@ -2685,6 +2810,11 @@ QDF_STATUS qdf_dpt_dump_stats_debugfs(qdf_debugfs_file_t file, qdf_dpt_display_proto_pkt_debugfs(file, &p_record, i); break; + case QDF_DP_TRACE_TX_CREDIT_RECORD: + qdf_dpt_display_credit_record_debugfs(file, &p_record, + i); + break; + case QDF_DP_TRACE_MGMT_PACKET_RECORD: qdf_dpt_display_mgmt_pkt_debugfs(file, &p_record, i); break; @@ -3026,8 +3156,13 @@ struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = { [QDF_MODULE_ID_TX_CAPTURE] = {"TX_CAPTURE_ENHANCE"}, [QDF_MODULE_ID_INTEROP_ISSUES_AP] = {"INTEROP_ISSUES_AP"}, [QDF_MODULE_ID_BLACKLIST_MGR] = {"blm"}, - [QDF_MODULE_ID_PKT_CAPTURE] = {"pkt_capture"}, + [QDF_MODULE_ID_QLD] = {"QLD"}, + [QDF_MODULE_ID_DYNAMIC_MODE_CHG] = {"Dynamic Mode Change"}, + [QDF_MODULE_ID_COEX] = {"COEX"}, + [QDF_MODULE_ID_MON_FILTER] = {"Monitor Filter"}, [QDF_MODULE_ID_ANY] = {"ANY"}, + [QDF_MODULE_ID_PKT_CAPTURE] = {"pkt_capture"}, + [QDF_MODULE_ID_GPIO] = {"GPIO_CFG"}, }; qdf_export_symbol(g_qdf_category_name); @@ -3265,8 +3400,6 @@ int qdf_print_ctrl_register(const struct category_info *cinfo, } } - pr_info("%s: Allocated print control object %d\n", - __func__, idx); return idx; } qdf_export_symbol(qdf_print_ctrl_register); @@ -3282,7 +3415,7 @@ qdf_export_symbol(qdf_shared_print_ctrl_cleanup); * Set this to invalid value to differentiate with user-provided * value. */ -int qdf_dbg_mask = 0; +int qdf_dbg_mask = QDF_TRACE_LEVEL_MAX; qdf_export_symbol(qdf_dbg_mask); qdf_declare_param(qdf_dbg_mask, int); @@ -3449,7 +3582,7 @@ static void set_default_trace_levels(struct category_info *cinfo) [QDF_MODULE_ID_SOC] = QDF_TRACE_LEVEL_NONE, [QDF_MODULE_ID_OS_IF] = QDF_TRACE_LEVEL_NONE, [QDF_MODULE_ID_TARGET_IF] = QDF_TRACE_LEVEL_INFO, - [QDF_MODULE_ID_SCHEDULER] = QDF_TRACE_LEVEL_NONE, + [QDF_MODULE_ID_SCHEDULER] = QDF_TRACE_LEVEL_FATAL, [QDF_MODULE_ID_MGMT_TXRX] = QDF_TRACE_LEVEL_NONE, [QDF_MODULE_ID_SERIALIZATION] = QDF_TRACE_LEVEL_ERROR, [QDF_MODULE_ID_PMO] = QDF_TRACE_LEVEL_NONE, @@ -3485,8 +3618,13 @@ static void set_default_trace_levels(struct category_info *cinfo) [QDF_MODULE_ID_TX_CAPTURE] = QDF_TRACE_LEVEL_NONE, [QDF_MODULE_ID_INTEROP_ISSUES_AP] = QDF_TRACE_LEVEL_NONE, [QDF_MODULE_ID_BLACKLIST_MGR] = QDF_TRACE_LEVEL_NONE, - [QDF_MODULE_ID_PKT_CAPTURE] = QDF_TRACE_LEVEL_NONE, + [QDF_MODULE_ID_QLD] = QDF_TRACE_LEVEL_ERROR, + [QDF_MODULE_ID_DYNAMIC_MODE_CHG] = QDF_TRACE_LEVEL_INFO, + [QDF_MODULE_ID_COEX] = QDF_TRACE_LEVEL_ERROR, + [QDF_MODULE_ID_MON_FILTER] = QDF_TRACE_LEVEL_INFO, [QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_INFO, + [QDF_MODULE_ID_PKT_CAPTURE] = QDF_TRACE_LEVEL_NONE, + [QDF_MODULE_ID_GPIO] = QDF_TRACE_LEVEL_NONE, }; for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { @@ -3505,14 +3643,14 @@ void qdf_shared_print_ctrl_init(void) /* * User specified across-module single debug level */ - if ((qdf_dbg_mask > 0) && (qdf_dbg_mask <= QDF_TRACE_LEVEL_MAX)) { + if ((qdf_dbg_mask >= 0) && (qdf_dbg_mask < QDF_TRACE_LEVEL_MAX)) { pr_info("User specified module debug level of %d\n", qdf_dbg_mask); for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { cinfo[i].category_verbose_mask = set_cumulative_verbose_mask(qdf_dbg_mask); } - } else { + } else if (qdf_dbg_mask != QDF_TRACE_LEVEL_MAX) { pr_info("qdf_dbg_mask value is invalid\n"); pr_info("Using the default module debug levels instead\n"); } @@ -3766,7 +3904,7 @@ qdf_export_symbol(QDF_PRINT_INFO); void qdf_logging_init(void) { wlan_logging_sock_init_svc(); - nl_srv_init(NULL); + nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY); wlan_logging_set_flush_timer(qdf_log_flush_timer_period); } @@ -3792,7 +3930,7 @@ void qdf_logging_flush_logs(void) #else void qdf_logging_init(void) { - nl_srv_init(NULL); + nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY); } void qdf_logging_exit(void) diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_hang_event_notifier.c b/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_hang_event_notifier.c new file mode 100644 index 0000000000000000000000000000000000000000..09b1761b65179b47fc63bd3b27bfe2cd6011fb86 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_hang_event_notifier.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + /** + * DOC: qdf_hang_event_notifier + * This file provides OS dependent QDF notifier call for hang event + */ + +#include +#include +#include + +static qdf_atomic_notifier_init(qdf_hang_event_notif_head) + +QDF_STATUS qdf_hang_event_register_notifier(qdf_notif_block *nb) +{ + return qdf_register_atomic_notifier_chain(&qdf_hang_event_notif_head, + nb); +} + +QDF_STATUS qdf_hang_event_unregister_notifier(qdf_notif_block *nb) +{ + return qdf_unregister_atomic_notifier_chain(&qdf_hang_event_notif_head, + nb); +} + +QDF_STATUS qdf_hang_event_notifier_call(unsigned long v, void *data) +{ + return qdf_atomic_notfier_call(&qdf_hang_event_notif_head, + v, data); +} diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_notifier.c b/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_notifier.c new file mode 100644 index 0000000000000000000000000000000000000000..6351831e98ff24d8baa06679d4bbd2e6686797bd --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_notifier.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include + +QDF_STATUS qdf_register_blocking_notifier_chain(qdf_blocking_notif_head *head, + qdf_notif_block *qnb) +{ + int ret; + + ret = __qdf_register_blocking_notifier_chain(head, &qnb->notif_block); + + return qdf_status_from_os_return(ret); +} + +QDF_STATUS qdf_unregister_blocking_notifier_chain(qdf_blocking_notif_head *head, + qdf_notif_block *qnb) +{ + int ret; + + ret = __qdf_unregister_blocking_notifier_chain(head, + &qnb->notif_block); + + return qdf_status_from_os_return(ret); +} + +QDF_STATUS qdf_blocking_notfier_call(qdf_blocking_notif_head *head, + unsigned long state, void *data) +{ + int ret; + + ret = __qdf_blocking_notfier_call(head, state, data); + + return qdf_status_from_os_return(ret); +} + +QDF_STATUS qdf_register_atomic_notifier_chain(qdf_atomic_notif_head *head, + qdf_notif_block *qnb) +{ + int ret; + + ret = __qdf_register_atomic_notifier_chain(head, &qnb->notif_block); + + return qdf_status_from_os_return(ret); +} + +QDF_STATUS qdf_unregister_atomic_notifier_chain(qdf_atomic_notif_head *head, + qdf_notif_block *qnb) +{ + int ret; + + ret = __qdf_unregister_atomic_notifier_chain(head, &qnb->notif_block); + + return qdf_status_from_os_return(ret); +} + +QDF_STATUS qdf_atomic_notfier_call(qdf_atomic_notif_head *head, + unsigned long v, void *data) +{ + int ret; + + ret = __qdf_atomic_notifier_call(head, v, data); + + return qdf_status_from_os_return(ret); +} diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_parse.c b/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_parse.c index 577f8eedaea575d4fe17744554e201fe7359ef07..469d59a4fdf10ce4feedecd0e657fe51d9bd0a0c 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_parse.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_parse.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 @@ -30,6 +30,7 @@ QDF_STATUS qdf_ini_parse(const char *ini_path, void *context, QDF_STATUS status; char *fbuf; char *cursor; + int ini_read_count = 0; status = qdf_file_read(ini_path, &fbuf); if (QDF_IS_STATUS_ERROR(status)) { @@ -99,6 +100,8 @@ QDF_STATUS qdf_ini_parse(const char *ini_path, void *context, status = item_cb(context, key, value); if (QDF_IS_STATUS_ERROR(status)) goto free_fbuf; + else + ini_read_count++; } else if (key[0] == '[') { qdf_size_t len = qdf_str_len(key); @@ -119,7 +122,11 @@ QDF_STATUS qdf_ini_parse(const char *ini_path, void *context, cursor++; } - status = QDF_STATUS_SUCCESS; + qdf_debug("INI values read: %d", ini_read_count); + if (ini_read_count != 0) + status = QDF_STATUS_SUCCESS; + else + status = QDF_STATUS_E_FAILURE; free_fbuf: qdf_file_buf_free(fbuf); diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_platform.c b/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_platform.c index 2a9bf2c769cd89b9fb1d209cbab063fe53327398..f1e486da74203a9c7e22fe70b9a22583eaed748b 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_platform.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_platform.c @@ -30,6 +30,11 @@ static qdf_is_driver_unloading_callback is_driver_unloading_cb; static qdf_is_recovering_callback is_recovering_cb; static qdf_is_drv_connected_callback is_drv_connected_cb; static qdf_wmi_send_over_qmi_callback _wmi_send_recv_qmi_cb; +static qdf_is_drv_supported_callback is_drv_supported_cb; +static qdf_recovery_reason_update_callback update_recovery_reason_cb; +static qdf_bus_reg_dump get_bus_reg_dump; + + void qdf_register_fw_down_callback(qdf_is_fw_down_callback is_fw_down) { @@ -87,11 +92,11 @@ void qdf_register_self_recovery_callback(qdf_self_recovery_callback callback) qdf_export_symbol(qdf_register_self_recovery_callback); -void __qdf_trigger_self_recovery(enum qdf_hang_reason reason, +void __qdf_trigger_self_recovery(void *psoc, enum qdf_hang_reason reason, const char *func, const uint32_t line) { if (self_recovery_cb) - self_recovery_cb(reason, func, line); + self_recovery_cb(psoc, reason, func, line); else QDF_DEBUG_PANIC_FL(func, line, ""); } @@ -175,3 +180,57 @@ void qdf_check_state_before_panic(void) qdf_export_symbol(qdf_check_state_before_panic); +void qdf_register_drv_supported_callback(qdf_is_drv_supported_callback + is_drv_supported) +{ + is_drv_supported_cb = is_drv_supported; +} + +qdf_export_symbol(qdf_register_drv_supported_callback); + +bool qdf_is_drv_supported(void) +{ + if (!is_drv_supported_cb) { + qdf_err("drv supported callback is not registered"); + return false; + } + + return is_drv_supported_cb(); +} + +qdf_export_symbol(qdf_is_drv_supported); + +void qdf_register_recovery_reason_update(qdf_recovery_reason_update_callback + callback) +{ + update_recovery_reason_cb = callback; +} + +qdf_export_symbol(qdf_register_recovery_reason_update); + +void qdf_recovery_reason_update(enum qdf_hang_reason reason) +{ + if (!update_recovery_reason_cb) + return; + + update_recovery_reason_cb(reason); +} + +qdf_export_symbol(qdf_recovery_reason_update); + +void qdf_register_get_bus_reg_dump(qdf_bus_reg_dump callback) +{ + get_bus_reg_dump = callback; +} + +qdf_export_symbol(qdf_register_get_bus_reg_dump); + +void qdf_get_bus_reg_dump(struct device *dev, uint8_t *buf, uint32_t len) +{ + if (!get_bus_reg_dump) + return; + + get_bus_reg_dump(dev, buf, len); +} + +qdf_export_symbol(qdf_get_bus_reg_dump); diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_types.c b/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_types.c index 8f645c74f347a3d926b55dadd7668fd5e99e48a7..86325250d25e8bd533676dfefd36316a358d7c30 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_types.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/src/qdf_types.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -616,6 +617,55 @@ QDF_STATUS qdf_ipv6_parse(const char *ipv6_str, struct qdf_ipv6_addr *out_addr) } qdf_export_symbol(qdf_ipv6_parse); +QDF_STATUS qdf_uint32_array_parse(const char *in_str, uint32_t *out_array, + qdf_size_t array_size, qdf_size_t *out_size) +{ + QDF_STATUS status; + bool negate; + qdf_size_t size = 0; + uint64_t value; + + QDF_BUG(in_str); + if (!in_str) + return QDF_STATUS_E_INVAL; + + QDF_BUG(out_array); + if (!out_array) + return QDF_STATUS_E_INVAL; + + QDF_BUG(out_size); + if (!out_size) + return QDF_STATUS_E_INVAL; + + while (size < array_size) { + status = __qdf_int_parse_lazy(&in_str, &value, &negate); + if (QDF_IS_STATUS_ERROR(status)) + return status; + + if ((uint32_t)value != value || negate) + return QDF_STATUS_E_RANGE; + + in_str = qdf_str_left_trim(in_str); + + switch (in_str[0]) { + case ',': + out_array[size++] = value; + in_str++; + break; + case '\0': + out_array[size++] = value; + *out_size = size; + return QDF_STATUS_SUCCESS; + default: + return QDF_STATUS_E_FAILURE; + } + } + + return QDF_STATUS_E_FAILURE; +} + +qdf_export_symbol(qdf_uint32_array_parse); + QDF_STATUS qdf_uint16_array_parse(const char *in_str, uint16_t *out_array, qdf_size_t array_size, qdf_size_t *out_size) { diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/test/qdf_types_test.c b/drivers/staging/qca-wifi-host-cmn/qdf/test/qdf_types_test.c index c19393ad318ab49a98fb010ca6a43b80d3a0b645..d833a76e6515128d9fdaedc71af7663ffb804387 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/test/qdf_types_test.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/test/qdf_types_test.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -161,6 +162,153 @@ static uint32_t qdf_types_ut_int64_parse(void) return errors; } +#define ut_uint16_array_pass(str, max_size, exp_arr, exp_arr_size) \ +__ut_uint16_array(str, QDF_STATUS_SUCCESS, max_size, exp_arr, exp_arr_size) + +#define ut_uint16_array_fail(str, max_size, exp_status, exp_arr, exp_arr_size)\ +__ut_uint16_array(str, exp_status, max_size, exp_arr, exp_arr_size) + +static uint32_t +__ut_uint16_array(const char *str, QDF_STATUS exp_status, + uint8_t max_array_size, uint16_t *exp_array, + uint8_t exp_array_size) +{ + uint16_t parsed_array[10]; + qdf_size_t parsed_array_size; + QDF_STATUS status; + uint8_t i; + + status = qdf_uint16_array_parse(str, parsed_array, max_array_size, + &parsed_array_size); + + if (status != exp_status) { + qdf_nofl_alert("FAIL: qdf_uint16_array_parse(\"%s\") -> status %d; expected status %d", + str, status, exp_status); + return 1; + } + + if (QDF_IS_STATUS_ERROR(status)) + return 0; + + if (parsed_array_size != exp_array_size) { + qdf_nofl_alert("FAIL: qdf_uint16_array_parse(\"%s\") -> parsed_array_size %zu; exp_array_size %d", + str, parsed_array_size, exp_array_size); + return 1; + } + + for (i = 0; i < exp_array_size; i++) + if (parsed_array[i] != exp_array[i]) { + qdf_nofl_alert("FAIL: qdf_uint16_array_parse(\"%s\") -> parsed_array[%d] %d; exp_array[%d] %d", + str, i, parsed_array[i], i, + exp_array[i]); + return 1; + } + + return 0; +} + +static uint32_t qdf_types_ut_uint16_array_parse(void) +{ + uint32_t errors = 0; + uint16_t exp_array_value[10] = { + 1, 10, 2412, 2417, 100, 65535, 0, 5486, 5180, 9999}; + + errors += ut_uint16_array_pass( + "1, 10, 2412, 2417, 100, 65535, 0, 5486, 5180, 9999", + 10, exp_array_value, 10); + errors += ut_uint16_array_pass( + "+1, +10, +2412, +2417, +100, +65535, 0, +5486, +5180, +9999", + 10, exp_array_value, 10); + errors += ut_uint16_array_fail("1;", 10, QDF_STATUS_E_FAILURE, + exp_array_value, 0); + /* Out of range test where 65536 is out of range */ + errors += ut_uint16_array_fail( + "1, 10, 2412, 2417, 100, 65536, 0, 5486, 5180, 9999", + 10, QDF_STATUS_E_RANGE, exp_array_value, 0); + errors += ut_uint16_array_fail( + "-1, -10, -2412, -2417, -100, -65535, 0, -5486, -5180, -9999", + 10, QDF_STATUS_E_RANGE, exp_array_value, 0); + errors += ut_uint16_array_fail( + "1, 10, 2412, 2417, 100, 日本, 0, 5486, 5180, 9999", + 10, QDF_STATUS_E_FAILURE, exp_array_value, 0); + + return errors; +} + +#define ut_uint32_array_pass(str, max_size, exp_arr, exp_arr_size) \ +__ut_uint32_array(str, QDF_STATUS_SUCCESS, max_size, exp_arr, exp_arr_size) + +#define ut_uint32_array_fail(str, max_size, exp_status, exp_arr, exp_arr_size)\ +__ut_uint32_array(str, exp_status, max_size, exp_arr, exp_arr_size) + +static uint32_t +__ut_uint32_array(const char *str, QDF_STATUS exp_status, + uint8_t max_array_size, uint32_t *exp_array, + uint8_t exp_array_size) +{ + uint32_t parsed_array[10]; + qdf_size_t parsed_array_size; + QDF_STATUS status; + uint8_t i; + + status = qdf_uint32_array_parse(str, parsed_array, max_array_size, + &parsed_array_size); + + if (status != exp_status) { + qdf_nofl_alert("FAIL: qdf_uint32_array_parse(\"%s\") -> status %d; expected status %d", + str, status, exp_status); + return 1; + } + + if (QDF_IS_STATUS_ERROR(status)) + return 0; + + if (parsed_array_size != exp_array_size) { + qdf_nofl_alert("FAIL: qdf_uint32_array_parse(\"%s\") -> parsed_array_size %zu; exp_array_size %d", + str, parsed_array_size, exp_array_size); + return 1; + } + + for (i = 0; i < exp_array_size; i++) + if (parsed_array[i] != exp_array[i]) { + qdf_nofl_alert("FAIL: qdf_uint32_array_parse(\"%s\") -> parsed_array[%d] %d; exp_array[%d] %d", + str, i, parsed_array[i], i, + exp_array[i]); + return 1; + } + + return 0; +} + +static uint32_t qdf_types_ut_uint32_array_parse(void) +{ + uint32_t errors = 0; + uint32_t exp_array_value[10] = { 1, 100, 9997, 899965, 65536, 0, + 4294967295, 268435456, + 2164184149, 999999999}; + + errors += ut_uint32_array_pass( + "1, 100, 9997, 899965, 65536, 0, 4294967295, 268435456, 2164184149, 999999999", + 10, exp_array_value, 10); + errors += ut_uint32_array_pass( + "+1, +100, +9997, +899965, +65536, 0, +4294967295, +268435456, +2164184149, +999999999", + 10, exp_array_value, 10); + errors += ut_uint32_array_fail("1;", 10, QDF_STATUS_E_FAILURE, + exp_array_value, 0); + /* Out of range test where 4294967296 is out of range */ + errors += ut_uint32_array_fail( + "1, 100, 9997, 899965, 65536, 0, 4294967296, 268435456, 2164184149, 999999999", + 10, QDF_STATUS_E_RANGE, exp_array_value, 0); + errors += ut_uint32_array_fail( + "-1, -100, -9997, -899965, -65536, 0, -4294967295, -268435456, -2164184149, -999999999", + 10, QDF_STATUS_E_RANGE, exp_array_value, 0); + errors += ut_uint32_array_fail( + "1, 100, 9997, 899965, 65536, 日本, 0, 4294967295, 268435456, 999999999", + 10, QDF_STATUS_E_FAILURE, exp_array_value, 0); + + return errors; +} + #define ut_uint32_pass(str, exp) __ut_uint32(str, QDF_STATUS_SUCCESS, exp) #define ut_uint32_fail(str, exp_status) __ut_uint32(str, exp_status, 0) @@ -287,11 +435,11 @@ __ut_mac(const char *str, const char *display_str, QDF_STATUS exp_status, return 0; if (qdf_mem_cmp(&value, exp_value, sizeof(value))) { - qdf_nofl_alert("FAIL: qdf_mac_parse(%s) -> " QDF_MAC_ADDR_STR - "; expected " QDF_MAC_ADDR_STR, + qdf_nofl_alert("FAIL: qdf_mac_parse(%s) -> " QDF_FULL_MAC_FMT + "; expected " QDF_FULL_MAC_FMT, display_str, - QDF_MAC_ADDR_ARRAY(value.bytes), - QDF_MAC_ADDR_ARRAY(exp_value->bytes)); + QDF_FULL_MAC_REF(value.bytes), + QDF_FULL_MAC_REF(exp_value->bytes)); return 1; } @@ -507,6 +655,8 @@ uint32_t qdf_types_unit_test(void) errors += qdf_types_ut_mac_parse(); errors += qdf_types_ut_ipv4_parse(); errors += qdf_types_ut_ipv6_parse(); + errors += qdf_types_ut_uint16_array_parse(); + errors += qdf_types_ut_uint32_array_parse(); return errors; } diff --git a/drivers/staging/qca-wifi-host-cmn/scheduler/inc/scheduler_core.h b/drivers/staging/qca-wifi-host-cmn/scheduler/inc/scheduler_core.h index 680ac2094f05e0f7e1b3aa821f03175e4669d42e..0fe8d4867562d3cf0aed93d4b946eb35ef98fded 100644 --- a/drivers/staging/qca-wifi-host-cmn/scheduler/inc/scheduler_core.h +++ b/drivers/staging/qca-wifi-host-cmn/scheduler/inc/scheduler_core.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -95,11 +95,11 @@ struct scheduler_mq_ctx { * @resume_sch_event: scheduler resume wait event * @sch_thread_lock: scheduler thread lock * @sch_last_qidx: scheduler last qidx allocation + * @watchdog_msg_type: 'type' of the current msg being processed * @hdd_callback: os if suspend callback * @legacy_wma_handler: legacy wma message handler * @legacy_sys_handler: legacy sys message handler * @watchdog_timer: timer for triggering a scheduler watchdog bite - * @watchdog_msg_type: 'type' of the current msg being processed * @watchdog_callback: the callback of the current msg being processed */ struct scheduler_ctx { @@ -112,11 +112,11 @@ struct scheduler_ctx { qdf_event_t resume_sch_event; qdf_spinlock_t sch_thread_lock; uint8_t sch_last_qidx; + uint16_t watchdog_msg_type; hdd_suspend_callback hdd_callback; scheduler_msg_process_fn_t legacy_wma_handler; scheduler_msg_process_fn_t legacy_sys_handler; qdf_timer_t watchdog_timer; - uint16_t watchdog_msg_type; void *watchdog_callback; }; diff --git a/drivers/staging/qca-wifi-host-cmn/scheduler/src/scheduler_api.c b/drivers/staging/qca-wifi-host-cmn/scheduler/src/scheduler_api.c index 02e25ab2e504251eb0002df30dc85aa3daad452a..d50a88ac63aa597008a9ba84eec2428058eeb5ae 100644 --- a/drivers/staging/qca-wifi-host-cmn/scheduler/src/scheduler_api.c +++ b/drivers/staging/qca-wifi-host-cmn/scheduler/src/scheduler_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -19,6 +19,8 @@ #include #include #include +#include +#include QDF_STATUS scheduler_disable(void) { @@ -53,16 +55,21 @@ static inline void scheduler_watchdog_notify(struct scheduler_ctx *sched) if (sched->watchdog_callback) qdf_sprint_symbol(symbol, sched->watchdog_callback); - sched_err("WLAN_BUG_RCA: Callback %s (type 0x%x) exceeded its allotted time of %ds", - sched->watchdog_callback ? symbol : "", - sched->watchdog_msg_type, SCHEDULER_WATCHDOG_TIMEOUT / 1000); + sched_fatal("Callback %s (type 0x%x) exceeded its allotted time of %ds", + sched->watchdog_callback ? symbol : "", + sched->watchdog_msg_type, + SCHEDULER_WATCHDOG_TIMEOUT / 1000); } -#ifdef CONFIG_SLUB_DEBUG_ON static void scheduler_watchdog_timeout(void *arg) { struct scheduler_ctx *sched = arg; + if (qdf_is_recovering()) { + sched_debug("Recovery is in progress ignore timeout"); + return; + } + scheduler_watchdog_notify(sched); if (sched->sch_thread) qdf_print_thread_trace(sched->sch_thread); @@ -73,12 +80,6 @@ static void scheduler_watchdog_timeout(void *arg) QDF_DEBUG_PANIC("Going down for Scheduler Watchdog Bite!"); } -#else -static void scheduler_watchdog_timeout(void *arg) -{ - scheduler_watchdog_notify((struct scheduler_ctx *)arg); -} -#endif QDF_STATUS scheduler_enable(void) { @@ -100,7 +101,7 @@ QDF_STATUS scheduler_enable(void) sched_ctx->sch_thread = qdf_create_thread(scheduler_thread, sched_ctx, "scheduler_thread"); if (!sched_ctx->sch_thread) { - sched_err("Failed to create scheduler thread"); + sched_fatal("Failed to create scheduler thread"); return QDF_STATUS_E_RESOURCES; } @@ -124,7 +125,7 @@ QDF_STATUS scheduler_init(void) status = scheduler_create_ctx(); if (QDF_IS_STATUS_ERROR(status)) { - sched_err("Failed to create context; status:%d", status); + sched_fatal("Failed to create context; status:%d", status); return status; } @@ -137,25 +138,26 @@ QDF_STATUS scheduler_init(void) status = scheduler_queues_init(sched_ctx); if (QDF_IS_STATUS_ERROR(status)) { - sched_err("Failed to init queues; status:%d", status); + sched_fatal("Failed to init queues; status:%d", status); goto ctx_destroy; } status = qdf_event_create(&sched_ctx->sch_start_event); if (QDF_IS_STATUS_ERROR(status)) { - sched_err("Failed to create start event; status:%d", status); + sched_fatal("Failed to create start event; status:%d", status); goto queues_deinit; } status = qdf_event_create(&sched_ctx->sch_shutdown); if (QDF_IS_STATUS_ERROR(status)) { - sched_err("Failed to create shutdown event; status:%d", status); + sched_fatal("Failed to create shutdown event; status:%d", + status); goto start_event_destroy; } status = qdf_event_create(&sched_ctx->resume_sch_event); if (QDF_IS_STATUS_ERROR(status)) { - sched_err("Failed to create resume event; status:%d", status); + sched_fatal("Failed to create resume event; status:%d", status); goto shutdown_event_destroy; } @@ -698,3 +700,5 @@ QDF_STATUS scheduler_post_message_debug(QDF_MODULE_ID src_id, return status; } + +qdf_export_symbol(scheduler_post_message_debug); diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/Kbuild b/drivers/staging/qca-wifi-host-cmn/spectral/Kbuild index af0f7fd2a5d7caa1e98d82c01a8127015892f317..117fc4f4ce248aab09a9690db24fac14487a14ef 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/Kbuild +++ b/drivers/staging/qca-wifi-host-cmn/spectral/Kbuild @@ -189,7 +189,7 @@ endif ifeq ($(QCA_CFR_SUPPORT), 1) ccflags-y+= -DWLAN_CFR_ENABLE=1 -INCS += -I$(obj)/$(DEPTH)/component_dev/umac/cfr/dispatcher/inc +INCS += -I$(obj)/$(DEPTH)/cmn_dev/umac/cfr/dispatcher/inc INCS += -I$(obj)/$(DEPTH)/component_dev/qal/inc endif diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_common.c b/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_common.c index c955dca798b0e6ac77e2e842c46c273432e0dfd2..a460635da4d4883b80911085f4f1c8572a1c0d86 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_common.c +++ b/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_common.c @@ -425,11 +425,16 @@ spectral_control_cmn(struct wlan_objmgr_pdev *pdev, case SPECTRAL_ACTIVATE_SCAN: err = &sscan_req->action_req.sscan_err_code; - sc->sptrlc_start_spectral_scan(pdev, smode, err); + ret = sc->sptrlc_start_spectral_scan(pdev, smode, err); + if (QDF_IS_STATUS_ERROR(ret)) + goto bad; break; case SPECTRAL_STOP_SCAN: - sc->sptrlc_stop_spectral_scan(pdev, smode); + err = &sscan_req->action_req.sscan_err_code; + ret = sc->sptrlc_stop_spectral_scan(pdev, smode, err); + if (QDF_IS_STATUS_ERROR(ret)) + goto bad; break; case SPECTRAL_GET_CAPABILITY_INFO: @@ -466,6 +471,14 @@ spectral_control_cmn(struct wlan_objmgr_pdev *pdev, } break; + case SPECTRAL_SET_DMA_DEBUG: + if (sc->sptrlc_set_dma_debug) + sc->sptrlc_set_dma_debug( + pdev, + sscan_req->dma_debug_req.dma_debug_type, + sscan_req->dma_debug_req.dma_debug_enable); + break; + default: goto bad; break; diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_defs_i.h b/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_defs_i.h index 52abd90ff73bd471edd5c19838ef4ea4c623e91c..716807d5afac9d3468df25d08048f468b062fdfd 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_defs_i.h +++ b/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_defs_i.h @@ -118,6 +118,7 @@ struct wmi_spectral_cmd_ops; * @sptrlc_use_nl_bcast: Check whether to use Netlink broadcast/unicast * @sptrlc_deregister_netlink_cb: De-register Netlink callbacks * @sptrlc_process_spectral_report: Process spectral report + * @sptrlc_set_dma_debug: Set DMA debug */ struct spectral_context { struct wlan_objmgr_psoc *psoc_obj; @@ -143,8 +144,10 @@ struct spectral_context { (struct wlan_objmgr_pdev *pdev, const enum spectral_scan_mode smode, enum spectral_cp_error_code *err); - QDF_STATUS (*sptrlc_stop_spectral_scan)(struct wlan_objmgr_pdev *pdev, - enum spectral_scan_mode smode); + QDF_STATUS (*sptrlc_stop_spectral_scan) + (struct wlan_objmgr_pdev *pdev, + enum spectral_scan_mode smode, + enum spectral_cp_error_code *err); bool (*sptrlc_is_spectral_active)(struct wlan_objmgr_pdev *pdev, enum spectral_scan_mode smode); bool (*sptrlc_is_spectral_enabled)(struct wlan_objmgr_pdev *pdev, @@ -161,13 +164,17 @@ struct spectral_context { struct wlan_objmgr_pdev *pdev, struct wmi_spectral_cmd_ops *cmd_ops); void (*sptrlc_register_netlink_cb)( - struct wlan_objmgr_pdev *pdev, - struct spectral_nl_cb *nl_cb); + struct wlan_objmgr_pdev *pdev, + struct spectral_nl_cb *nl_cb); bool (*sptrlc_use_nl_bcast)(struct wlan_objmgr_pdev *pdev); void (*sptrlc_deregister_netlink_cb)(struct wlan_objmgr_pdev *pdev); int (*sptrlc_process_spectral_report)( - struct wlan_objmgr_pdev *pdev, - void *payload); + struct wlan_objmgr_pdev *pdev, + void *payload); + QDF_STATUS (*sptrlc_set_dma_debug)( + struct wlan_objmgr_pdev *pdev, + enum spectral_dma_debug dma_debug_type, + bool dma_debug_enable); }; -#endif /* _SPECTRAL_DEFS_I_H_ */ +#endif /* _SPECTRAL_DEFS_I_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_module.c b/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_module.c index 0f946e7e89c0b347a788a340fe1e75df584f5dc3..eabff65f6b36b536b584a551b050e1e1cdfe2a3c 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_module.c +++ b/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_module.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011,2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011,2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -31,8 +31,12 @@ MODULE_LICENSE("Dual BSD/GPL"); * * Return: None */ -static int __init -spectral_init_module(void) + +#ifndef QCA_SINGLE_WIFI_3_0 +static int __init spectral_init_module(void) +#else +int spectral_init_module(void) +#endif { spectral_info("qca_spectral module loaded"); wlan_spectral_init(); @@ -51,12 +55,17 @@ spectral_init_module(void) * * Return: None */ -static void __exit -spectral_exit_module(void) +#ifndef QCA_SINGLE_WIFI_3_0 +static void __exit spectral_exit_module(void) +#else +void spectral_exit_module(void) +#endif { wlan_spectral_deinit(); spectral_info("qca_spectral module unloaded"); } +#ifndef QCA_SINGLE_WIFI_3_0 module_init(spectral_init_module); module_exit(spectral_exit_module); +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_offload.c b/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_offload.c index b07c7a7fc20f2dc9b87c18a44abcfc6328e4193e..7db9dd3861735521fed7fcf562c00bec2248ec4f 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_offload.c +++ b/drivers/staging/qca-wifi-host-cmn/spectral/core/spectral_offload.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -21,6 +21,23 @@ #include "spectral_ol_api_i.h" #include "../dispatcher/inc/wlan_spectral_tgt_api.h" +#ifdef DIRECT_BUF_RX_DEBUG +static void +spectral_ctx_init_ol_dma_debug(struct spectral_context *sc) +{ + if (!sc) { + spectral_err("spectral context is null!"); + return; + } + sc->sptrlc_set_dma_debug = tgt_set_spectral_dma_debug; +} +#else +static void +spectral_ctx_init_ol_dma_debug(struct spectral_context *sc) +{ +} +#endif + void spectral_ctx_init_ol(struct spectral_context *sc) { @@ -47,4 +64,5 @@ spectral_ctx_init_ol(struct spectral_context *sc) sc->sptrlc_use_nl_bcast = tgt_spectral_use_nl_bcast; sc->sptrlc_deregister_netlink_cb = tgt_spectral_deregister_nl_cb; sc->sptrlc_process_spectral_report = tgt_spectral_process_report; + spectral_ctx_init_ol_dma_debug(sc); } diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/cfg_spectral.h b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/cfg_spectral.h index b997cd9641bbaac1b17d33f9a7bf79656902c804..175d743b53a66fcc74eb05796b6fec6e13d1e3be 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/cfg_spectral.h +++ b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/cfg_spectral.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 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 @@ -43,7 +43,29 @@ CFG_INI_BOOL("spectral_disable", false, \ "Spectral disable") +/* + * + * poison_spectral_bufs - enable poisoning of spectral buffers + * @Min: 0 + * @Max: 1 + * @Default: 0 + * + * This ini is used to enable the poisoning of spectral buffers. + * + * Related: None + * + * Supported Feature: Spectral + * + * Usage: Internal + * + * + */ +#define CFG_SPECTRAL_POISON_BUFS \ + CFG_INI_BOOL("poison_spectral_bufs", false, \ + "Enable spectral bufs poison at init") + #define CFG_SPECTRAL_ALL \ - CFG(CFG_SPECTRAL_DISABLE) + CFG(CFG_SPECTRAL_DISABLE) \ + CFG(CFG_SPECTRAL_POISON_BUFS) #endif diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/spectral_ioctl.h b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/spectral_ioctl.h index 2f24c6baf6c441daeb1a93e272af9febbaaea23d..4f99495f1ad5dd2c87e40f81fd0d3aca0c2e4bb4 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/spectral_ioctl.h +++ b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/spectral_ioctl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2017-2020 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 @@ -51,12 +51,13 @@ #define SPECTRAL_SET_ICM_ACTIVE (DFS_LAST_IOCTL + 21) #define SPECTRAL_GET_NOMINAL_NOISEFLOOR (DFS_LAST_IOCTL + 22) #define SPECTRAL_GET_DEBUG_LEVEL (DFS_LAST_IOCTL + 23) +#define SPECTRAL_SET_DMA_DEBUG (DFS_LAST_IOCTL + 24) /* * ioctl parameter types */ enum spectral_params { - SPECTRAL_PARAM_FFT_PERIOD = 1, + SPECTRAL_PARAM_FFT_PERIOD, SPECTRAL_PARAM_SCAN_PERIOD, SPECTRAL_PARAM_SCAN_COUNT, SPECTRAL_PARAM_SHORT_REPORT, @@ -80,8 +81,9 @@ enum spectral_params { SPECTRAL_PARAM_STOP, SPECTRAL_PARAM_ENABLE, SPECTRAL_PARAM_FREQUENCY, - SPECTRAL_PARAM_AFTER_LAST, - SPECTRAL_PARAM_MAX = SPECTRAL_PARAM_AFTER_LAST - 1, + SPECTRAL_PARAM_CHAN_FREQUENCY, + SPECTRAL_PARAM_CHAN_WIDTH, + SPECTRAL_PARAM_MAX, }; /** @@ -225,7 +227,9 @@ struct spectral_config { * @high_level_offset: high_level_offset * @rssi_thr: rssi_thr * @default_agc_max_gain: default_agc_max_gain - * @agile_spectral_cap: agile Spectral capability + * @agile_spectral_cap: agile Spectral capability for 20/40/80 + * @agile_spectral_cap_160: agile Spectral capability for 160 MHz + * @agile_spectral_cap_80p80: agile Spectral capability for 80p80 */ struct spectral_caps { uint8_t phydiag_cap; @@ -240,12 +244,16 @@ struct spectral_caps { int16_t rssi_thr; uint8_t default_agc_max_gain; bool agile_spectral_cap; + bool agile_spectral_cap_160; + bool agile_spectral_cap_80p80; }; #define SPECTRAL_IOCTL_PARAM_NOVAL (65535) -#define MAX_SPECTRAL_CHAINS 3 -#define MAX_NUM_BINS 520 +#define MAX_SPECTRAL_CHAINS (3) +#define MAX_NUM_BINS (1024) +#define MAX_NUM_BINS_PRI80 (1024) +#define MAX_NUM_BINS_SEC80 (520) /* 5 categories x (lower + upper) bands */ #define MAX_INTERF 10 @@ -343,6 +351,36 @@ struct spectral_classifier_params { * segment * @ch_width: Channel width 20/40/80/160 MHz * @spectral_mode: Spectral scan mode + * @spectral_pri80ind: Indication from hardware that the sample was + * received on the primary 80 MHz segment. If this + * is set when smode = SPECTRAL_SCAN_MODE_AGILE, it + * indicates that Spectral was carried out on pri80 + * instead of the Agile frequency due to a + * channel switch - Software may choose + * to ignore the sample in this case. + * @spectral_pri80ind_sec80: Indication from hardware that the sample was + * received on the primary 80 MHz segment instead of + * the secondary 80 MHz segment due to a channel + * switch - Software may choose to ignore the sample + * if this is set. Applicable only if smode = + * SPECTRAL_SCAN_MODE_NORMAL and for 160/80+80 MHz + * Spectral operation. + * @last_raw_timestamp: Previous FFT report's raw timestamp. In case of + * 160Mhz it will be primary 80 segment's timestamp + * as both primary & secondary segment's timestamp + * are expected to be almost equal. + * @timestamp_war_offset: Offset calculated based on reset_delay and + * last_raw_timestamp. It will be added to + * raw_timestamp to get spectral_tstamp. + * @raw_timestamp: Actual FFT timestamp reported by HW on primary + * segment. + * @raw_timestamp_sec80: Actual FFT timestamp reported by HW on sec80 MHz + * segment. + * @reset_delay: Time gap between the last spectral report before + * reset and the end of reset. It is provided by FW + * via direct DMA framework. + * @target_reset_count: Indicates the number of times target went through + * reset routine after spectral was enabled. */ struct spectral_samp_data { int16_t spectral_data_len; @@ -389,8 +427,8 @@ struct spectral_samp_data { uint8_t lb_edge_extrabins; uint8_t rb_edge_extrabins; uint16_t bin_pwr_count_sec80; - uint8_t bin_pwr[MAX_NUM_BINS]; - uint8_t bin_pwr_sec80[MAX_NUM_BINS]; + uint8_t bin_pwr[MAX_NUM_BINS_PRI80]; + uint8_t bin_pwr_sec80[MAX_NUM_BINS_SEC80]; struct interf_src_rsp interf_list; int16_t noise_floor; int16_t noise_floor_sec80; @@ -400,6 +438,15 @@ struct spectral_samp_data { uint8_t spectral_gainchange; uint8_t spectral_gainchange_sec80; enum spectral_scan_mode spectral_mode; + uint8_t spectral_pri80ind; + uint8_t spectral_pri80ind_sec80; + uint32_t last_raw_timestamp; + uint32_t timestamp_war_offset; + uint32_t raw_timestamp; + uint32_t raw_timestamp_sec80; + uint32_t reset_delay; + uint32_t target_reset_count; + uint32_t agile_ch_width; } __packed; /** @@ -408,6 +455,9 @@ struct spectral_samp_data { * @freq: Operating frequency in MHz * @vhtop_ch_freq_seg1: VHT Segment 1 centre frequency in MHz * @vhtop_ch_freq_seg2: VHT Segment 2 centre frequency in MHz + * @agile_freq: Center frequency in MHz of the entire span across which + * Agile Spectral is carried out. Applicable only for Agile + * Spectral samples. * @freq_loading: How busy was the channel * @dcs_enabled: Whether DCS is enabled * @int_type: Interference type indicated by DCS @@ -419,6 +469,7 @@ struct spectral_samp_msg { uint16_t freq; uint16_t vhtop_ch_freq_seg1; uint16_t vhtop_ch_freq_seg2; + uint16_t agile_freq; uint16_t freq_loading; uint16_t dcs_enabled; enum dcs_int_type int_type; diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_public_structs.h b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_public_structs.h index 4096eb4bea3ec6151be5e368f8d8de52fe7c5786..34cc4b1bc80ccee51a09bb5f5b61372af36ad28b 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_public_structs.h +++ b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_public_structs.h @@ -218,18 +218,30 @@ enum spectral_capability_type { /** * enum spectral_cp_error_code - Spectral control path response code + * @SPECTRAL_SCAN_RESP_ERR_INVALID: Invalid error identifier * @SPECTRAL_SCAN_RESP_ERR_PARAM_UNSUPPORTED: parameter unsupported * @SPECTRAL_SCAN_RESP_ERR_MODE_UNSUPPORTED: mode unsupported * @SPECTRAL_SCAN_RESP_ERR_PARAM_INVALID_VALUE: invalid parameter value * @SPECTRAL_SCAN_RESP_ERR_PARAM_NOT_INITIALIZED: parameter uninitialized */ enum spectral_cp_error_code { + SPECTRAL_SCAN_ERR_INVALID, SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED, SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED, SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE, SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED, }; +/** + * enum spectral_dma_debug - Spectral DMA debug + * @SPECTRAL_DMA_RING_DEBUG: Spectral DMA ring debug + * @SPECTRAL_DMA_BUFFER_DEBUG: Spectral DMA buffer debug + */ +enum spectral_dma_debug { + SPECTRAL_DMA_RING_DEBUG, + SPECTRAL_DMA_BUFFER_DEBUG, +}; + /** * struct spectral_chan_stats - channel status info * @cycle_count: Cycle count @@ -376,12 +388,25 @@ struct spectral_scan_debug_request { enum spectral_cp_error_code sscan_err_code; }; +/** + * struct spectral_scan_dma_debug_request - DMA debug request + * @dma_debug_enable: Enable/disable @dma_debug_type + * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug + * @sscan_err_code: Spectral scan error code + */ +struct spectral_scan_dma_debug_request { + bool dma_debug_enable; + enum spectral_dma_debug dma_debug_type; + enum spectral_cp_error_code sscan_err_code; +}; + /** * struct spectral_cp_request - Spectral control path request * Creating request and extracting response has to * be atomic. * @ss_mode: Spectral scan mode * @req_id: Request identifier + * @dma_debug_req: Spectral DMA debug request */ struct spectral_cp_request { enum spectral_scan_mode ss_mode; @@ -394,6 +419,7 @@ struct spectral_cp_request { struct spectral_scan_get_chan_width_request chan_width_req; struct spectral_scan_get_status_request status_req; struct spectral_scan_debug_request debug_req; + struct spectral_scan_dma_debug_request dma_debug_req; }; }; diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_tgt_api.h b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_tgt_api.h index 4a1ee4dbbda6992f54af37dda2f6ea8cd948a66f..264ab28dc8617a31fb067f9babe3c78b1a2c4131 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_tgt_api.h +++ b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_tgt_api.h @@ -102,7 +102,7 @@ QDF_STATUS tgt_get_spectral_config(struct wlan_objmgr_pdev *pdev, * tgt_start_spectral_scan() - Start spectral scan * @pdev: Pointer to pdev object * @smode: Spectral scan mode - * @res: Spectral control path error code + * @err: Spectral control path error code * * Implementation for starting spectral scan * @@ -116,13 +116,15 @@ QDF_STATUS tgt_start_spectral_scan(struct wlan_objmgr_pdev *pdev, * tgt_stop_spectral_scan() - Stop spectral scan * @pdev: Pointer to pdev object * @smode: Spectral scan mode + * @err: Spectral control path error code * * Implementation for stop spectral scan * * Return: QDF_STATUS_SUCCESS on success, else QDF_STATUS_E_FAILURE */ QDF_STATUS tgt_stop_spectral_scan(struct wlan_objmgr_pdev *pdev, - enum spectral_scan_mode smode); + enum spectral_scan_mode smode, + enum spectral_cp_error_code *err); /** * tgt_is_spectral_active() - Get whether Spectral is active @@ -271,4 +273,16 @@ tgt_spectral_unregister_to_dbr(struct wlan_objmgr_pdev *pdev); */ uint32_t tgt_spectral_get_target_type(struct wlan_objmgr_psoc *psoc); + +/** + * tgt_set_spectral_dma_debug() - Set DMA debug for Spectral + * @pdev: Pointer to pdev object + * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug + * @dma_debug_enable: Value to be set for @dma_debug_type + * + * Return: QDF_STATUS of operation + */ +QDF_STATUS tgt_set_spectral_dma_debug(struct wlan_objmgr_pdev *pdev, + enum spectral_dma_debug dma_debug_type, + bool dma_debug_enable); #endif /* _WLAN_SPECTRAL_TGT_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_utils_api.h b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_utils_api.h index 9453dcc2f799d58c7eb76360fe748d68bbc04b30..3d1b159e82179aa0aae79f52d3fa1b623b6b2b93 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_utils_api.h +++ b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/inc/wlan_spectral_utils_api.h @@ -88,11 +88,13 @@ wlan_register_wmi_spectral_cmd_ops(struct wlan_objmgr_pdev *pdev, /** * struct spectral_legacy_cbacks - Spectral legacy callbacks * @vdev_get_chan_freq: Get channel frequency + * @vdev_get_chan_freq_seg2: Get secondary 80 center frequency * @vdev_get_ch_width: Get channel width * @vdev_get_sec20chan_freq_mhz: Get seconadry 20 frequency */ struct spectral_legacy_cbacks { int16_t (*vdev_get_chan_freq)(struct wlan_objmgr_vdev *vdev); + int16_t (*vdev_get_chan_freq_seg2)(struct wlan_objmgr_vdev *vdev); enum phy_ch_width (*vdev_get_ch_width)(struct wlan_objmgr_vdev *vdev); int (*vdev_get_sec20chan_freq_mhz)(struct wlan_objmgr_vdev *vdev, uint16_t *sec20chan_freq); @@ -106,6 +108,14 @@ struct spectral_legacy_cbacks { */ int16_t spectral_vdev_get_chan_freq(struct wlan_objmgr_vdev *vdev); +/** + * spectral_vdev_get_chan_freq_seg2 - Get vdev's secondary 80 center frequency + * @vdev: vdev object + * + * Return: vdev secondary 80 center frequency + */ +int16_t spectral_vdev_get_chan_freq_seg2(struct wlan_objmgr_vdev *vdev); + /** * spectral_vdev_get_sec20chan_freq_mhz - Get vdev secondary channel frequency * @vdev: vdev object diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/src/wlan_spectral_tgt_api.c b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/src/wlan_spectral_tgt_api.c index 0195ae2d0b47d382681dd9bcb9c085c375aff126..f416b47e9c325cc0ae53ef4a1fcc35ad22253fc5 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/src/wlan_spectral_tgt_api.c +++ b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/src/wlan_spectral_tgt_api.c @@ -125,13 +125,14 @@ tgt_start_spectral_scan(struct wlan_objmgr_pdev *pdev, QDF_STATUS tgt_stop_spectral_scan(struct wlan_objmgr_pdev *pdev, - enum spectral_scan_mode smode) + enum spectral_scan_mode smode, + enum spectral_cp_error_code *err) { - struct wlan_objmgr_psoc *psoc = NULL; + struct wlan_objmgr_psoc *psoc; psoc = wlan_pdev_get_psoc(pdev); return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_stop_spectral_scan( - pdev, smode); + pdev, smode, err); } bool @@ -297,23 +298,26 @@ tgt_spectral_register_to_dbr(struct wlan_objmgr_pdev *pdev) { struct wlan_objmgr_psoc *psoc; struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL; + struct wlan_lmac_if_sptrl_tx_ops *sptrl_tx_ops = NULL; struct dbr_module_config dbr_config = {0}; - uint32_t target_type; psoc = wlan_pdev_get_psoc(pdev); dbr_tx_ops = &psoc->soc_cb.tx_ops.dbr_tx_ops; + sptrl_tx_ops = &psoc->soc_cb.tx_ops.sptrl_tx_ops; dbr_config.num_resp_per_event = DBR_NUM_RESP_PER_EVENT_SPECTRAL; dbr_config.event_timeout_in_ms = DBR_EVENT_TIMEOUT_IN_MS_SPECTRAL; - target_type = tgt_spectral_get_target_type(psoc); - if ((target_type == TARGET_TYPE_QCA8074) || - (target_type == TARGET_TYPE_QCA8074V2) || - (target_type == TARGET_TYPE_QCA6018) || - (target_type == TARGET_TYPE_QCA6390)) + if ((sptrl_tx_ops->sptrlto_direct_dma_support) && + (sptrl_tx_ops->sptrlto_direct_dma_support(pdev))) { + if (sptrl_tx_ops->sptrlto_check_and_do_dbr_buff_debug) + sptrl_tx_ops->sptrlto_check_and_do_dbr_buff_debug(pdev); if (dbr_tx_ops->direct_buf_rx_module_register) - return dbr_tx_ops->direct_buf_rx_module_register + dbr_tx_ops->direct_buf_rx_module_register (pdev, 0, &dbr_config, spectral_dbr_event_handler); + if (sptrl_tx_ops->sptrlto_check_and_do_dbr_ring_debug) + sptrl_tx_ops->sptrlto_check_and_do_dbr_ring_debug(pdev); + } return QDF_STATUS_SUCCESS; } @@ -323,17 +327,29 @@ tgt_spectral_unregister_to_dbr(struct wlan_objmgr_pdev *pdev) { struct wlan_objmgr_psoc *psoc; struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL; + struct wlan_lmac_if_sptrl_tx_ops *sptrl_tx_ops = NULL; psoc = wlan_pdev_get_psoc(pdev); dbr_tx_ops = &psoc->soc_cb.tx_ops.dbr_tx_ops; + sptrl_tx_ops = &psoc->soc_cb.tx_ops.sptrl_tx_ops; + + if ((sptrl_tx_ops->sptrlto_direct_dma_support) && + (sptrl_tx_ops->sptrlto_direct_dma_support(pdev))) { + /* Stop DBR debug as the buffers itself are freed now */ + if (dbr_tx_ops->direct_buf_rx_stop_ring_debug) + dbr_tx_ops->direct_buf_rx_stop_ring_debug(pdev, 0); - if ((tgt_spectral_get_target_type(psoc) == TARGET_TYPE_QCA8074) || - (tgt_spectral_get_target_type(psoc) == TARGET_TYPE_QCA8074V2) || - (tgt_spectral_get_target_type(psoc) == TARGET_TYPE_QCA6018)) + /*No need to zero-out as buffers are anyway getting freed*/ + if (dbr_tx_ops->direct_buf_rx_stop_buffer_poisoning) + dbr_tx_ops->direct_buf_rx_stop_buffer_poisoning + (pdev, 0); if (dbr_tx_ops->direct_buf_rx_module_unregister) - return dbr_tx_ops->direct_buf_rx_module_unregister + dbr_tx_ops->direct_buf_rx_module_unregister (pdev, 0); + return QDF_STATUS_SUCCESS; + } + return QDF_STATUS_E_FAILURE; } #else @@ -348,4 +364,32 @@ tgt_spectral_unregister_to_dbr(struct wlan_objmgr_pdev *pdev) { return QDF_STATUS_SUCCESS; } +#endif /* DIRECT_BUF_RX_ENABLE */ + +#ifdef DIRECT_BUF_RX_DEBUG +QDF_STATUS tgt_set_spectral_dma_debug(struct wlan_objmgr_pdev *pdev, + enum spectral_dma_debug dma_debug_type, + bool dma_debug_enable) +{ + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_pdev_get_psoc(pdev); + + if (!psoc) { + spectral_err("psoc is NULL!"); + return QDF_STATUS_E_FAILURE; + } + + return psoc->soc_cb.tx_ops.sptrl_tx_ops.sptrlto_set_dma_debug( + pdev, + dma_debug_type, + dma_debug_enable); +} +#else +QDF_STATUS tgt_set_spectral_dma_debug(struct wlan_objmgr_pdev *pdev, + enum spectral_dma_debug dma_debug_type, + bool dma_debug_enable) +{ + return QDF_STATUS_SUCCESS; +} #endif diff --git a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/src/wlan_spectral_utils_api.c b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/src/wlan_spectral_utils_api.c index 18b7c8201806d88f0fffd5a7f9295ecc1cf267ce..8a58ad65437880615b39860c6a5d5a0374cdc08b 100644 --- a/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/src/wlan_spectral_utils_api.c +++ b/drivers/staging/qca-wifi-host-cmn/spectral/dispatcher/src/wlan_spectral_utils_api.c @@ -119,6 +119,8 @@ spectral_register_legacy_cb(struct wlan_objmgr_psoc *psoc, sc->legacy_cbacks.vdev_get_chan_freq = legacy_cbacks->vdev_get_chan_freq; + sc->legacy_cbacks.vdev_get_chan_freq_seg2 = + legacy_cbacks->vdev_get_chan_freq_seg2; sc->legacy_cbacks.vdev_get_ch_width = legacy_cbacks->vdev_get_ch_width; sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz = legacy_cbacks->vdev_get_sec20chan_freq_mhz; @@ -138,9 +140,33 @@ spectral_vdev_get_chan_freq(struct wlan_objmgr_vdev *vdev) return -EINVAL; } + if (!sc->legacy_cbacks.vdev_get_chan_freq) { + spectral_err("vdev_get_chan_freq is not supported"); + return -ENOTSUPP; + } + return sc->legacy_cbacks.vdev_get_chan_freq(vdev); } +int16_t +spectral_vdev_get_chan_freq_seg2(struct wlan_objmgr_vdev *vdev) +{ + struct spectral_context *sc; + + sc = spectral_get_spectral_ctx_from_vdev(vdev); + if (!sc) { + spectral_err("spectral context is null"); + return -EINVAL; + } + + if (!sc->legacy_cbacks.vdev_get_chan_freq_seg2) { + spectral_err("vdev_get_chan_freq_seg2 is not supported"); + return -ENOTSUPP; + } + + return sc->legacy_cbacks.vdev_get_chan_freq_seg2(vdev); +} + enum phy_ch_width spectral_vdev_get_ch_width(struct wlan_objmgr_vdev *vdev) { @@ -152,6 +178,11 @@ spectral_vdev_get_ch_width(struct wlan_objmgr_vdev *vdev) return CH_WIDTH_INVALID; } + if (!sc->legacy_cbacks.vdev_get_ch_width) { + spectral_err("vdev_get_ch_width is not supported"); + return -ENOTSUPP; + } + return sc->legacy_cbacks.vdev_get_ch_width(vdev); } @@ -167,6 +198,11 @@ spectral_vdev_get_sec20chan_freq_mhz(struct wlan_objmgr_vdev *vdev, return -EINVAL; } + if (!sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz) { + spectral_err("vdev_get_sec20chan_freq_mhz is not supported"); + return -ENOTSUPP; + } + return sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz(vdev, sec20chan_freq); } @@ -179,6 +215,8 @@ wlan_lmac_if_sptrl_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) /* Spectral rx ops */ sptrl_rx_ops->sptrlro_get_target_handle = tgt_get_target_handle; sptrl_rx_ops->sptrlro_vdev_get_chan_freq = spectral_vdev_get_chan_freq; + sptrl_rx_ops->sptrlro_vdev_get_chan_freq_seg2 = + spectral_vdev_get_chan_freq_seg2; sptrl_rx_ops->sptrlro_vdev_get_ch_width = spectral_vdev_get_ch_width; sptrl_rx_ops->sptrlro_vdev_get_sec20chan_freq_mhz = spectral_vdev_get_sec20chan_freq_mhz; @@ -231,13 +269,19 @@ bool spectral_dbr_event_handler(struct wlan_objmgr_pdev *pdev, QDF_STATUS spectral_pdev_open(struct wlan_objmgr_pdev *pdev) { + struct wlan_objmgr_psoc *psoc; QDF_STATUS status; - if (wlan_spectral_is_feature_disabled(wlan_pdev_get_psoc(pdev))) { + psoc = wlan_pdev_get_psoc(pdev); + + if (wlan_spectral_is_feature_disabled(psoc)) { spectral_info("Spectral is disabled"); return QDF_STATUS_COMP_DISABLED; } + if (cfg_get(psoc, CFG_SPECTRAL_POISON_BUFS)) + tgt_set_spectral_dma_debug(pdev, SPECTRAL_DMA_BUFFER_DEBUG, 1); + status = tgt_spectral_register_to_dbr(pdev); return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/cfr/inc/target_if_cfr.h b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/inc/target_if_cfr.h new file mode 100644 index 0000000000000000000000000000000000000000..77d3c69bee7de2f84fa35cb9d2920a4b5f481465 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/inc/target_if_cfr.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _TARGET_IF_CFR_H_ +#define _TARGET_IF_CFR_H_ + +#include +#include +#include +#include +#include + +#include "wmi_unified_cfr_api.h" +#include "wmi_unified_param.h" +#include "wmi_unified_cfr_param.h" +#define PEER_CFR_CAPTURE_ENABLE 1 +#define PEER_CFR_CAPTURE_DISABLE 0 + +#define PEER_CFR_CAPTURE_EVT_STATUS_MASK 0x80000000 +#define PEER_CFR_CAPTURE_EVT_PS_STATUS_MASK 0x40000000 +#define CFR_TX_EVT_STATUS_MASK 0x00000003 + +/* Status codes used by correlate and relay function */ +#define STATUS_STREAM_AND_RELEASE 0 +#define STATUS_HOLD 1 +#define STATUS_ERROR -1 + +/* Module IDs using corrlation function */ +#define CORRELATE_DBR_MODULE_ID 0 +/* + * HKV2 - Tx completion event for one-shot capture + * Cypress - Tx completion event for one-shot capture (or) RXTLV event for RCC + */ +#define CORRELATE_TX_EV_MODULE_ID 1 + +/** + * target_if_cfr_init_pdev() - Inits cfr pdev and registers necessary handlers. + * @psoc: pointer to psoc object + * @pdev: pointer to pdev object + * + * Return: Registration status for necessary handlers + */ +int target_if_cfr_init_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev); + +/** + * target_if_cfr_deinit_pdev() - De-inits corresponding pdev and handlers. + * @psoc: pointer to psoc object + * @pdev: pointer to pdev object + * + * Return: De-registration status for necessary handlers + */ +int target_if_cfr_deinit_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev); + +/** + * target_if_cfr_tx_ops_register() - Registers tx ops for cfr module + * @tx_ops - pointer to tx_ops structure. + */ +void target_if_cfr_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops); + +/** + * target_if_cfr_enable_cfr_timer() - Enables cfr timer + * @pdev: pointer to pdev object + * @cfr_timer: Amount of time this timer has to run + * + * Return: status of timer + */ +int target_if_cfr_enable_cfr_timer(struct wlan_objmgr_pdev *pdev, + uint32_t cfr_timer); + +/** + * target_if_cfr_pdev_set_param() - Function to set params for cfr config + * @pdev: pointer to pdev object + * @param_id: param id which has to be set + * @param_value: value of param being set + * + * Return: success/failure of setting param + */ +int target_if_cfr_pdev_set_param(struct wlan_objmgr_pdev *pdev, + uint32_t param_id, uint32_t param_value); +/** + * target_if_cfr_start_capture() - Function to start cfr capture for a peer + * @pdev: pointer to pdev object + * @peer: pointer to peer object + * @cfr_params: capture parameters for this peer + * + * Return: success/failure status of start capture + */ +int target_if_cfr_start_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer, + struct cfr_capture_params *cfr_params); +/** + * target_if_cfr_stop_capture() - Function to stop cfr capture for a peer + * @pdev: pointer to pdev object + * @peer: pointer to peer object + * + * Return: success/failure status of stop capture + */ +int target_if_cfr_stop_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer); + +/** + * target_if_cfr_get_target_type() - Function to get target type + * @psoc: pointer to psoc object + * + * Return: target type of target + */ +int target_if_cfr_get_target_type(struct wlan_objmgr_psoc *psoc); + +/** + * target_if_cfr_set_cfr_support() - Function to set cfr support + * @psoc: pointer to psoc object + * @value: value to be set + */ +void target_if_cfr_set_cfr_support(struct wlan_objmgr_psoc *psoc, + uint8_t value); + +/** + * target_if_cfr_info_send() - Function to send cfr info to upper layers + * @pdev: pointer to pdev object + * @head: pointer to cfr info head + * @hlen: head len + * @data: pointer to cfr info data + * @dlen: data len + * @tail: pointer to cfr info tail + * @tlen: tail len + */ +void target_if_cfr_info_send(struct wlan_objmgr_pdev *pdev, void *head, + size_t hlen, void *data, size_t dlen, void *tail, + size_t tlen); + +/** + * cfr_wifi2_0_init_pdev() - Function to init legacy pdev + * @psoc: pointer to psoc object + * @pdev: pointer to pdev object + * + * Return: success/failure status of init + */ +QDF_STATUS cfr_wifi2_0_init_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev); + +/** + * cfr_wifi2_0_deinit_pdev() - Function to deinit legacy pdev + * @psoc: pointer to psoc object + * @pdev: pointer to pdev object + * + * Return: success/failure status of deinit + */ +QDF_STATUS cfr_wifi2_0_deinit_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev); +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/cfr/inc/target_if_cfr_6018.h b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/inc/target_if_cfr_6018.h new file mode 100644 index 0000000000000000000000000000000000000000..4255f85acac9e2a1fd03c5e2d6ba863d3dc58ce2 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/inc/target_if_cfr_6018.h @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _TARGET_IF_CFR_6018_H_ +#define _TARGET_IF_CFR_6018_H_ + +#ifdef WLAN_ENH_CFR_ENABLE +/* + * Memory requirements : + * + * 1. DMA header : + * + * Legacy DMA header(QCA8074V2) : 2 words (length = 8 bytes) + * Enhanced DMA header(QCA6018) : Upto 16 words depending on no. of MU users + * in UL-MU-PPDU (Max length = 64 bytes) + * + * Fixed 4 words for whal_cfir_enhanced_hdr + freeze TLV + * + uplink_user_info TLV (MAX 4) + * + * mu_rx_num_users -> No. of words in CFR DMA header + * 0 -> 12 = 4 + 7(freeze TLV) + 1(for 64-bit alignment) + * 1 -> 12 = 4 + 7(freeze TLV) + 1(user1) + * 2 -> 14 = 4 + 7(freeze TLV) + 2(users 1,2) + 1(for 64-bit alignment) + * 3 -> 14 = 4 + 7(freeze TLV) + 3(users 1,2,3) + * 4 -> 16 = 4 + 7(freeze TLV) + 4(users 1,2,3,4) + 1(for 64-bit alignment) + * + * + * 2. CFR data size for max BW/Nss/Nrx + * + * Cypress : Max BW = 80 MHz + * NSS = 2 + * Nrx = 2 + * Size of one tone = 4 bytes + * + * a. RTT-H - 2048 bytes + * + * b. Debug-H (MIMO CFR) - 16016 bytes + * + * c. RTT-H + CIR - 10240 bytes = 2048(RTT-H) + 8192(CIR) + */ + +/* Max 4 users in MU case */ +#define CYP_CFR_MU_USERS 4 + +#define CYP_MAX_HEADER_LENGTH_WORDS 16 + +/* payload_len = Max(2048, 16016, 10240) = 16064 (64-bit alignment) */ +#define CYP_MAX_DATA_LENGTH_BYTES 16064 + +/* in ms */ +#define LUT_AGE_TIMER 3000 +#define LUT_AGE_THRESHOLD 3000 +#define NUM_LUT_ENTRIES 136 + +/* Max size : + * 16173 = 93 bytes(csi header) + 64 bytes(cfr header) + 16016 bytes(cfr + * payload) + */ +#define STREAMFS_MAX_SUBBUF_CYP 16173 + +#define STREAMFS_NUM_SUBBUF_CYP 255 + +/* + * @tag: ucode fills this with 0xBA + * + * @length: length of CFR header in words (32-bit) + * + * @upload_done: ucode sets this to 1 to indicate DMA completion + * + * @capture_type: + * + * 0 - None + * 1 - RTT-H (Nss = 1, Nrx) + * 2 - Debug-H (Nss, Nrx) + * 3 - Reserved + * 5 - RTT-H + CIR(Nss, Nrx) + * + * @preamble_type: + * + * 0 - Legacy + * 1 - HT + * 2 - VHT + * 3 - HE + * + * @nss: + * + * 0 - 1-stream + * 1 - 2-stream + * .. .. + * 7 - 8-stream + * + *@num_chains: + * + * 0 - 1-chain + * 1 - 2-chain + * .. .. + * 7 - 8-chain + * + *@upload_bw_pkt: + * + * 0 - 20 MHz + * 1 - 40 MHz + * 2 - 80 MHz + * 3 - 160 MHz + * + * @sw_peer_id_valid: Indicates whether sw_peer_id field is valid or not, + * sent from MAC to PHY via the MACRX_FREEZE_CAPTURE_CHANNEL TLV + * + * @sw_peer_id: Indicates peer id based on AST search, sent from MAC to PHY + * via the MACRX_FREEZE_CAPTURE_CHANNEL TLV + * + * @phy_ppdu_id: sent from PHY to MAC, copied to MACRX_FREEZE_CAPTURE_CHANNEL + * TLV + * + * @total_bytes: Total size of CFR payload (FFT bins) + * + * @header_version: + * + * 1 - HKV2/Hastings + * 2 - Cypress + * + * @target_id: + * + * 1 - Hastings + * 2 - Cypress + * 3 - Hastings Prime + * 4 - Pine + * + * @cfr_fmt: + * + * 0 - raw (32-bit format) + * 1 - compressed (24-bit format) + * + * @mu_rx_data_incl: Indicates whether CFR header contains UL-MU-MIMO info + * + * @freeze_data_incl: Indicates whether CFR header contains + * MACRX_FREEZE_CAPTURE_CHANNEL TLV + * + * @decimation_factor: FFT bins decimation + * @mu_rx_num_users: Number of users in UL-MU-PPDU + */ +struct whal_cfir_enhanced_hdr { + uint16_t tag : 8, + length : 6, + rsvd1 : 2; + + uint16_t upload_done : 1, + capture_type : 3, + preamble_type : 2, + nss : 3, + num_chains : 3, + upload_pkt_bw : 3, + sw_peer_id_valid : 1; + + uint16_t sw_peer_id : 16; + + uint16_t phy_ppdu_id : 16; + + uint16_t total_bytes; + + uint16_t header_version :4, + target_id :4, + cfr_fmt :1, + rsvd2 :1, + mu_rx_data_incl :1, + freeze_data_incl:1, + rsvd3 :4; + + uint16_t mu_rx_num_users :8, + decimation_factor :4, + rsvd4 :4; + + uint16_t rsvd5; +}; + +struct macrx_freeze_capture_channel { + uint16_t freeze : 1, //[0] + capture_reason : 3, //[3:1] + packet_type : 2, //[5:4] + packet_sub_type : 4, //[9:6] + reserved : 5, //[14:10] + sw_peer_id_valid : 1; //[15] + uint16_t sw_peer_id : 16; //[15:0] + uint16_t phy_ppdu_id : 16; //[15:0] + uint16_t packet_ta_lower_16 : 16; //[15:0] + uint16_t packet_ta_mid_16 : 16; //[15:0] + uint16_t packet_ta_upper_16 : 16; //[15:0] + uint16_t packet_ra_lower_16 : 16; //[15:0] + uint16_t packet_ra_mid_16 : 16; //[15:0] + uint16_t packet_ra_upper_16 : 16; //[15:0] + uint16_t tsf_timestamp_15_0 : 16; //[15:0] + uint16_t tsf_timestamp_31_16 : 16; //[15:0] + uint16_t tsf_timestamp_47_32 : 16; //[15:0] + uint16_t tsf_timestamp_63_48 : 16; //[15:0] + uint16_t user_index : 6, //[5:0] + directed : 1, //[6] + reserved_13 : 9; //[15:7] +}; + +struct uplink_user_setup_info { + uint32_t bw_info_valid : 1, //[0] + uplink_receive_type : 2, //[2:1] + reserved_0a : 1, //[3] + uplink_11ax_mcs : 4, //[7:4] + ru_width : 7, //[14:8] + reserved_0b : 1, //[15] + nss : 3, //[18:16] + stream_offset : 3, //[21:19] + sta_dcm : 1, //[22] + sta_coding : 1, //[23] + ru_start_index : 7, //[30:24] + reserved_0c : 1; //[31] +}; + +/** + * cfr_6018_init_pdev() - Inits cfr pdev and registers necessary handlers. + * @psoc: pointer to psoc object + * @pdev: pointer to pdev object + * + * Return: Registration status for necessary handlers + */ +QDF_STATUS cfr_6018_init_pdev( + struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev); + +/** + * cfr_6018_deinit_pdev() - De-inits corresponding pdev and handlers. + * @psoc: pointer to psoc object + * @pdev: pointer to pdev object + * + * Return: De-registration status for necessary handlers + */ +QDF_STATUS cfr_6018_deinit_pdev( + struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev); + +/** + * target_if_cfr_start_lut_age_timer() - Start timer to flush aged-out LUT + * entries + * @pdev: pointer to pdev object + * + * Return: None + */ +void target_if_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev); + +/** + * target_if_cfr_stop_lut_age_timer() - Stop timer to flush aged-out LUT + * entries + * @pdev: pointer to pdev object + * + * Return: None + */ +void target_if_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev); + +/** + * target_if_cfr_dump_lut_enh() - Dump all valid LUT entries + * @pdev: objmgr PDEV + * + * Return: none + */ +void target_if_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev); + +/** + * target_if_cfr_config_rcc() - Start repetitive channel capture + * @pdev: pointer to pdev object + * @rcc_param: rcc configurations + * + * Return: Success/Failure status + */ +QDF_STATUS target_if_cfr_config_rcc(struct wlan_objmgr_pdev *pdev, + struct cfr_rcc_param *rcc_param); + +/** + * target_if_cfr_default_ta_ra_config() - Configure default values to all + * params(BW/NSS/TA/RA) in TA_RA mode + * @rcc_param: rcc configurations + * @allvalid: Indicates whether all TA_RA params are valid or not. + * It could be either 0 or 1. + * 1: should be sent to FW during CFR initialization + * 0: should be set, after a successful commit session. + * @reset_cfg: This bitmap is being used to determine which groups' + * parameters are needed to be reset to its default state. + */ +void target_if_cfr_default_ta_ra_config(struct cfr_rcc_param *rcc_param, + bool allvalid, uint16_t reset_cfg); + +/** + * target_if_cfr_rx_tlv_process() - Process PPDU status TLVs and store info in + * lookup table + * @pdev: PDEV object + * @nbuf: ppdu info + * + * Return: none + */ +void target_if_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf); + +/** + * target_if_cfr_update_global_cfg() - Update global config after a successful + * commit + * @pdev: pointer to pdev object + * + * Return: None + */ +void target_if_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev); +#else +static QDF_STATUS cfr_6018_init_pdev( + struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS cfr_6018_deinit_pdev( + struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + return QDF_STATUS_SUCCESS; +} +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/cfr/inc/target_if_cfr_6490.h b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/inc/target_if_cfr_6490.h new file mode 100644 index 0000000000000000000000000000000000000000..94b149c84a7a6eee23bd6bf0e4cfac691d62ed6b --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/inc/target_if_cfr_6490.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC : target_if_cfr_6490.h + * + * Target interface of CFR for QCA6490 implementation + * + */ + +#ifndef _TARGET_IF_CFR_6490_H +#define _TARGET_IF_CFR_6490_H + +#ifdef QCA_WIFI_QCA6490 +#define CFR_MAC_ID_24G 1 +#define CFR_MAC_ID_5G 0 +#endif /* QCA_WIFI_QCA6490 */ + +/** + * target_if_cfr_subscribe_ppdu_desc() - subscribe ppdu description + * for CFR component + * + * @pdev: pointer to pdev object + * @is_subscribe: subscribe or unsubscribe + * + * Return: QDF_STATUS + */ +QDF_STATUS +target_if_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev, + bool is_subscribe); + +/** + * cfr_6490_init_pdev() - Init pdev cfr for QCA6490 + * @psoc: pointer to psoc object + * @pdev: pointer to pdev object + * + * Registers to DBR component and init pdev cfr parameters + * + * Return: QDF status + */ +QDF_STATUS cfr_6490_init_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev); + +/** + * cfr_6490_deinit_pdev() - De-inits pdev cfr for QCA6490 + * @pdev: pointer to pdev object + * + * Unregister to DBR and deinit pdev cfr parameters + * + * Return: QDF status + */ +QDF_STATUS cfr_6490_deinit_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev); + +#endif /* _TARGET_IF_CFR_6490_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/cfr/src/target_if_cfr.c b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/src/target_if_cfr.c new file mode 100644 index 0000000000000000000000000000000000000000..11e1c59062b43c3ba73900e550cd3423a5ce08b2 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/src/target_if_cfr.c @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CFR_USE_FIXED_FOLDER +#include "target_if_cfr_6490.h" +#include "wlan_reg_services_api.h" +#else +#include +#endif + +int target_if_cfr_stop_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer) +{ + struct peer_cfr *pe; + struct peer_cfr_params param = {0}; + struct wmi_unified *pdev_wmi_handle = NULL; + struct wlan_objmgr_vdev *vdev = {0}; + struct pdev_cfr *pdev_cfrobj; + int retv = 0; + + pe = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_CFR); + if (pe == NULL) + return -EINVAL; + + pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); + if (!pdev_wmi_handle) { + cfr_err("pdev wmi handle NULL"); + return -EINVAL; + } + vdev = wlan_peer_get_vdev(peer); + + qdf_mem_set(¶m, sizeof(param), 0); + + param.request = PEER_CFR_CAPTURE_DISABLE; + param.macaddr = wlan_peer_get_macaddr(peer); + param.vdev_id = wlan_vdev_get_id(vdev); + + param.periodicity = pe->period; + param.bandwidth = pe->bandwidth; + param.capture_method = pe->capture_method; + + retv = wmi_unified_send_peer_cfr_capture_cmd(pdev_wmi_handle, ¶m); + + pdev_cfrobj = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + if (!pdev_cfrobj) { + cfr_err("pdev object for CFR is null"); + return -EINVAL; + } + cfr_err("CFR capture stats for this capture:"); + cfr_err("DBR event count = %llu, Tx event count = %llu " + "Release count = %llu", + pdev_cfrobj->dbr_evt_cnt, pdev_cfrobj->tx_evt_cnt, + pdev_cfrobj->release_cnt); + + pdev_cfrobj->dbr_evt_cnt = 0; + pdev_cfrobj->tx_evt_cnt = 0; + pdev_cfrobj->release_cnt = 0; + + return retv; +} + +int target_if_cfr_start_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer, + struct cfr_capture_params *cfr_params) +{ + struct peer_cfr_params param = {0}; + struct wmi_unified *pdev_wmi_handle = NULL; + struct wlan_objmgr_vdev *vdev; + int retv = 0; + + pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); + if (!pdev_wmi_handle) { + cfr_err("pdev wmi handle NULL"); + return -EINVAL; + } + vdev = wlan_peer_get_vdev(peer); + qdf_mem_set(¶m, sizeof(param), 0); + + param.request = PEER_CFR_CAPTURE_ENABLE; + param.macaddr = wlan_peer_get_macaddr(peer); + param.vdev_id = wlan_vdev_get_id(vdev); + + param.periodicity = cfr_params->period; + param.bandwidth = cfr_params->bandwidth; + param.capture_method = cfr_params->method; + + retv = wmi_unified_send_peer_cfr_capture_cmd(pdev_wmi_handle, ¶m); + return retv; +} + +int target_if_cfr_pdev_set_param(struct wlan_objmgr_pdev *pdev, + uint32_t param_id, uint32_t param_value) +{ + struct pdev_params pparam; + uint32_t pdev_id; + struct wmi_unified *pdev_wmi_handle = NULL; + + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + if (pdev_id < 0) + return -EINVAL; + + pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); + if (!pdev_wmi_handle) { + cfr_err("pdev wmi handle NULL"); + return -EINVAL; + } + qdf_mem_set(&pparam, sizeof(pparam), 0); + pparam.param_id = param_id; + pparam.param_value = param_value; + + return wmi_unified_pdev_param_send(pdev_wmi_handle, + &pparam, pdev_id); +} + +int target_if_cfr_enable_cfr_timer(struct wlan_objmgr_pdev *pdev, + uint32_t cfr_timer) +{ + struct pdev_cfr *pa; + int retval; + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (pa == NULL) + return QDF_STATUS_E_FAILURE; + + if (!cfr_timer) { + /* disable periodic cfr capture */ + retval = + target_if_cfr_pdev_set_param(pdev, + wmi_pdev_param_per_peer_prd_cfr_enable, + WMI_HOST_PEER_CFR_TIMER_DISABLE); + + if (retval == QDF_STATUS_SUCCESS) + pa->cfr_timer_enable = 0; + } else { + /* enable periodic cfr capture (default base timer is 10ms ) */ + retval = + target_if_cfr_pdev_set_param(pdev, + wmi_pdev_param_per_peer_prd_cfr_enable, + WMI_HOST_PEER_CFR_TIMER_ENABLE); + + if (retval == QDF_STATUS_SUCCESS) + pa->cfr_timer_enable = 1; + } + + return retval; +} + +int target_if_cfr_get_target_type(struct wlan_objmgr_psoc *psoc) +{ + uint32_t target_type = 0; + struct wlan_lmac_if_target_tx_ops *target_type_tx_ops; + + target_type_tx_ops = &psoc->soc_cb.tx_ops.target_tx_ops; + + if (target_type_tx_ops->tgt_get_tgt_type) + target_type = target_type_tx_ops->tgt_get_tgt_type(psoc); + + return target_type; +} + +#ifdef CFR_USE_FIXED_FOLDER +int target_if_cfr_init_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + uint32_t target_type; + QDF_STATUS status; + + target_type = target_if_cfr_get_target_type(psoc); + + if (target_type == TARGET_TYPE_QCA6490) { + status = cfr_6490_init_pdev(psoc, pdev); + } else { + cfr_info("unsupport chip"); + status = QDF_STATUS_SUCCESS; + } + + return qdf_status_to_os_return(status); +} + +int target_if_cfr_deinit_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + uint32_t target_type; + QDF_STATUS status; + + target_type = target_if_cfr_get_target_type(psoc); + + if (target_type == TARGET_TYPE_QCA6490) { + status = cfr_6490_deinit_pdev(psoc, pdev); + } else { + cfr_info("unsupport chip"); + status = QDF_STATUS_SUCCESS; + } + + return qdf_status_to_os_return(status); +} +#else +int target_if_cfr_init_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + uint32_t target_type; + struct pdev_cfr *pa; + struct psoc_cfr *cfr_sc; + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (pa == NULL) + return QDF_STATUS_E_FAILURE; + + /* Reset unassociated entries for every init */ + qdf_mem_zero(&pa->unassoc_pool[0], MAX_CFR_ENABLED_CLIENTS * + sizeof(struct unassoc_pool_entry)); + + cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_CFR); + + if (cfr_sc == NULL) + return QDF_STATUS_E_FAILURE; + + target_type = target_if_cfr_get_target_type(psoc); + + if (target_type == TARGET_TYPE_QCA8074V2) { + pa->is_cfr_capable = cfr_sc->is_cfr_capable; + return cfr_8074v2_init_pdev(psoc, pdev); + } else if ((target_type == TARGET_TYPE_IPQ4019) || + (target_type == TARGET_TYPE_QCA9984) || + (target_type == TARGET_TYPE_QCA9888)) { + + pa->is_cfr_capable = cfr_sc->is_cfr_capable; + + return cfr_wifi2_0_init_pdev(psoc, pdev); + } else if (target_type == TARGET_TYPE_QCA6018) { + pa->is_cfr_capable = cfr_sc->is_cfr_capable; + return cfr_6018_init_pdev(psoc, pdev); + } else + return QDF_STATUS_E_NOSUPPORT; +} + +int target_if_cfr_deinit_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + uint32_t target_type; + + target_type = target_if_cfr_get_target_type(psoc); + + if (target_type == TARGET_TYPE_QCA8074V2) { + return cfr_8074v2_deinit_pdev(psoc, pdev); + } else if ((target_type == TARGET_TYPE_IPQ4019) || + (target_type == TARGET_TYPE_QCA9984) || + (target_type == TARGET_TYPE_QCA9888)) { + + return cfr_wifi2_0_deinit_pdev(psoc, pdev); + } else if (target_type == TARGET_TYPE_QCA6018) { + return cfr_6018_deinit_pdev(psoc, pdev); + } else + return QDF_STATUS_E_NOSUPPORT; +} +#endif + +#ifdef WLAN_ENH_CFR_ENABLE +#ifdef QCA_WIFI_QCA6490 +static uint8_t target_if_cfr_get_mac_id(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_vdev *vdev; + struct wlan_channel *bss_chan; + struct pdev_cfr *pcfr; + uint8_t mac_id = 0; + + if (!pdev) { + cfr_err("null pdev"); + return mac_id; + } + + mac_id = wlan_objmgr_pdev_get_pdev_id(pdev); + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (!pcfr) { + cfr_err("null pcfr"); + return mac_id; + } + + if (pcfr->rcc_param.vdev_id == CFR_INVALID_VDEV_ID) + return mac_id; + + vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, + pcfr->rcc_param.vdev_id, + WLAN_CFR_ID); + if (!vdev) { + cfr_err("null vdev"); + return mac_id; + } + + bss_chan = wlan_vdev_mlme_get_bss_chan(vdev); + if (!bss_chan) { + cfr_info("null bss chan"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); + return mac_id; + } + + cfr_debug("bss freq %d", bss_chan->ch_freq); + if (wlan_reg_is_24ghz_ch_freq(bss_chan->ch_freq)) + mac_id = CFR_MAC_ID_24G; + else + mac_id = CFR_MAC_ID_5G; + + pcfr->rcc_param.srng_id = mac_id; + wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); + + return mac_id; +} + +static uint8_t target_if_cfr_get_pdev_id(struct wlan_objmgr_pdev *pdev) +{ + return target_if_cfr_get_mac_id(pdev); +} +#else +static uint8_t target_if_cfr_get_pdev_id(struct wlan_objmgr_pdev *pdev) +{ + return wlan_objmgr_pdev_get_pdev_id(pdev); +} +#endif /* QCA_WIFI_QCA6490 */ + +QDF_STATUS target_if_cfr_config_rcc(struct wlan_objmgr_pdev *pdev, + struct cfr_rcc_param *rcc_info) +{ + QDF_STATUS status; + struct wmi_unified *pdev_wmi_handle = NULL; + + pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); + if (!pdev_wmi_handle) { + cfr_err("pdev_wmi_handle is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + rcc_info->pdev_id = target_if_cfr_get_pdev_id(pdev); + rcc_info->num_grp_tlvs = + count_set_bits(rcc_info->modified_in_curr_session); + + status = wmi_unified_send_cfr_rcc_cmd(pdev_wmi_handle, rcc_info); + return status; +} + +void target_if_cfr_default_ta_ra_config(struct cfr_rcc_param *rcc_info, + bool allvalid, uint16_t reset_cfg) +{ + struct ta_ra_cfr_cfg *curr_cfg = NULL; + int grp_id; + unsigned long bitmap = reset_cfg; + uint8_t def_mac[QDF_MAC_ADDR_SIZE] = {0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF}; + uint8_t null_mac[QDF_MAC_ADDR_SIZE] = {0, 0, 0, 0, 0, 0}; + + for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) { + if (qdf_test_bit(grp_id, &bitmap)) { + curr_cfg = &rcc_info->curr[grp_id]; + qdf_mem_copy(curr_cfg->tx_addr, + def_mac, QDF_MAC_ADDR_SIZE); + qdf_mem_copy(curr_cfg->tx_addr_mask, + null_mac, QDF_MAC_ADDR_SIZE); + qdf_mem_copy(curr_cfg->rx_addr, + def_mac, QDF_MAC_ADDR_SIZE); + qdf_mem_copy(curr_cfg->rx_addr_mask, + null_mac, QDF_MAC_ADDR_SIZE); + curr_cfg->bw = 0xf; + curr_cfg->nss = 0xff; + curr_cfg->mgmt_subtype_filter = 0xffff; + curr_cfg->ctrl_subtype_filter = 0xffff; + curr_cfg->data_subtype_filter = 0xffff; + if (!allvalid) { + curr_cfg->valid_ta = 0; + curr_cfg->valid_ta_mask = 0; + curr_cfg->valid_ra = 0; + curr_cfg->valid_ra_mask = 0; + curr_cfg->valid_bw_mask = 0; + curr_cfg->valid_nss_mask = 0; + curr_cfg->valid_mgmt_subtype = 0; + curr_cfg->valid_ctrl_subtype = 0; + curr_cfg->valid_data_subtype = 0; + } else { + curr_cfg->valid_ta = 1; + curr_cfg->valid_ta_mask = 1; + curr_cfg->valid_ra = 1; + curr_cfg->valid_ra_mask = 1; + curr_cfg->valid_bw_mask = 1; + curr_cfg->valid_nss_mask = 1; + curr_cfg->valid_mgmt_subtype = 1; + curr_cfg->valid_ctrl_subtype = 1; + curr_cfg->valid_data_subtype = 1; + } + } + } +} +#endif + +#ifdef WLAN_ENH_CFR_ENABLE +#ifdef CFR_USE_FIXED_FOLDER +static void target_if_enh_cfr_add_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + tx_ops->cfr_tx_ops.cfr_subscribe_ppdu_desc = + target_if_cfr_subscribe_ppdu_desc; +} +#else +static void target_if_enh_cfr_add_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ +} +#endif /* CFR_USE_FIXED_FOLDER */ +static void target_if_enh_cfr_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + tx_ops->cfr_tx_ops.cfr_config_rcc = + target_if_cfr_config_rcc; + tx_ops->cfr_tx_ops.cfr_start_lut_timer = + target_if_cfr_start_lut_age_timer; + tx_ops->cfr_tx_ops.cfr_stop_lut_timer = + target_if_cfr_stop_lut_age_timer; + tx_ops->cfr_tx_ops.cfr_default_ta_ra_cfg = + target_if_cfr_default_ta_ra_config; + tx_ops->cfr_tx_ops.cfr_dump_lut_enh = + target_if_cfr_dump_lut_enh; + tx_ops->cfr_tx_ops.cfr_rx_tlv_process = + target_if_cfr_rx_tlv_process; + tx_ops->cfr_tx_ops.cfr_update_global_cfg = + target_if_cfr_update_global_cfg; + target_if_enh_cfr_add_ops(tx_ops); +} +#else +static void target_if_enh_cfr_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ +} +#endif + +void target_if_cfr_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) +{ + tx_ops->cfr_tx_ops.cfr_init_pdev = + target_if_cfr_init_pdev; + tx_ops->cfr_tx_ops.cfr_deinit_pdev = + target_if_cfr_deinit_pdev; + tx_ops->cfr_tx_ops.cfr_enable_cfr_timer = + target_if_cfr_enable_cfr_timer; + tx_ops->cfr_tx_ops.cfr_start_capture = + target_if_cfr_start_capture; + tx_ops->cfr_tx_ops.cfr_stop_capture = + target_if_cfr_stop_capture; + target_if_enh_cfr_tx_ops(tx_ops); +} + +void target_if_cfr_set_cfr_support(struct wlan_objmgr_psoc *psoc, + uint8_t value) +{ + if (psoc->soc_cb.rx_ops.cfr_rx_ops.cfr_support_set) + psoc->soc_cb.rx_ops.cfr_rx_ops.cfr_support_set(psoc, value); +} + +void target_if_cfr_info_send(struct wlan_objmgr_pdev *pdev, void *head, + size_t hlen, void *data, size_t dlen, void *tail, + size_t tlen) +{ + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_pdev_get_psoc(pdev); + + if (psoc->soc_cb.rx_ops.cfr_rx_ops.cfr_info_send) + psoc->soc_cb.rx_ops.cfr_rx_ops.cfr_info_send(pdev, head, hlen, + data, dlen, tail, + tlen); +} diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/cfr/src/target_if_cfr_6018.c b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/src/target_if_cfr_6018.c new file mode 100644 index 0000000000000000000000000000000000000000..de491aa41e2ca1f8f3a97e5e999ec51eccd88787 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/src/target_if_cfr_6018.c @@ -0,0 +1,1638 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef DIRECT_BUF_RX_ENABLE +#include +#endif +#include +#include "cdp_txrx_ctrl.h" + +#define NUM_CHAINS_FW_TO_HOST(n) ((1 << ((n) + 1)) - 1) + +static u_int32_t end_magic = 0xBEAFDEAD; +/** + * get_lut_entry() - Retrieve LUT entry using cookie number + * @pcfr: PDEV CFR object + * @offset: cookie number + * + * Return: look up table entry + */ +static struct look_up_table *get_lut_entry(struct pdev_cfr *pcfr, + int offset) +{ + if (offset >= pcfr->lut_num) { + cfr_err("Invalid offset %d, lut_num %d", + offset, pcfr->lut_num); + return NULL; + } + + return pcfr->lut[offset]; +} + +/** + * release_lut_entry_enh() - Clear all params in an LUT entry + * @pdev: objmgr PDEV + * @lut: pointer to LUT + * + * Return: status + */ +static int release_lut_entry_enh(struct wlan_objmgr_pdev *pdev, + struct look_up_table *lut) +{ + lut->dbr_recv = false; + lut->tx_recv = false; + lut->data = NULL; + lut->data_len = 0; + lut->dbr_ppdu_id = 0; + lut->tx_ppdu_id = 0; + lut->dbr_tstamp = 0; + lut->txrx_tstamp = 0; + lut->tx_address1 = 0; + lut->tx_address2 = 0; + lut->dbr_address = 0; + qdf_mem_zero(&lut->header, sizeof(struct csi_cfr_header)); + + return 0; +} + +/** + * target_if_cfr_dump_lut_enh() - dump all valid lut entries + * @pdev: objmgr pdev + * + * return: none + */ +void target_if_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev) +{ + struct pdev_cfr *pcfr; + struct look_up_table *lut = NULL; + int i = 0; + uint64_t diff; + QDF_STATUS retval = 0; + + retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID); + if (retval != QDF_STATUS_SUCCESS) { + cfr_err("failed to get pdev reference"); + return; + } + + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + if (!pcfr) { + cfr_err("pdev object for CFR is null"); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + return; + } + + for (i = 0; i < pcfr->lut_num; i++) { + lut = get_lut_entry(pcfr, i); + if (!lut) + continue; + if (lut->dbr_recv ^ lut->tx_recv) { + diff = (lut->dbr_tstamp > lut->txrx_tstamp) ? + (lut->dbr_tstamp - lut->txrx_tstamp) : + (lut->txrx_tstamp - lut->dbr_tstamp); + cfr_err("idx:%d dbrevnt: %d txrxevent: %d " + "dbrppdu:0x%x txrxppdu:0x%x dbr_tstamp: %llu " + "txrx_tstamp: %llu diff: %llu\n", + i, lut->dbr_recv, lut->tx_recv, + lut->dbr_ppdu_id, lut->tx_ppdu_id, + lut->dbr_tstamp, lut->txrx_tstamp, diff); + } + + } + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); +} + +/** + * cfr_free_pending_dbr_events() - Flush all pending DBR events. This is useful + * in cases where for RXTLV drops in host monitor status ring is huge. + * @pdev: objmgr pdev + * + * return: none + */ +static void cfr_free_pending_dbr_events(struct wlan_objmgr_pdev *pdev) +{ + struct pdev_cfr *pcfr; + struct look_up_table *lut = NULL; + int i = 0; + QDF_STATUS retval = 0; + + retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID); + if (retval != QDF_STATUS_SUCCESS) { + cfr_err("failed to get pdev reference"); + return; + } + + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + if (!pcfr) { + cfr_err("pdev object for CFR is null"); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + return; + } + + for (i = 0; i < pcfr->lut_num; i++) { + lut = get_lut_entry(pcfr, i); + if (!lut) + continue; + + if (lut->dbr_recv && !lut->tx_recv && + (lut->dbr_tstamp < pcfr->last_success_tstamp)) { + target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, + lut->dbr_address, + i, 0); + pcfr->flush_dbr_cnt++; + release_lut_entry_enh(pdev, lut); + } + } + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); +} + +/** + * dump_freeze_tlv() - Dump freeze TLV sent in enhanced DMA header + * @freeze_tlv: Freeze TLV sent from MAC to PHY + * @cookie: Index into lookup table + * + * Return: none + */ +static void dump_freeze_tlv(void *freeze_tlv, uint32_t cookie) +{ + struct macrx_freeze_capture_channel *freeze = + (struct macrx_freeze_capture_channel *)freeze_tlv; + + cfr_debug("<%u>\n" + "freeze: %d capture_reason: %d packet_type: 0x%x\n" + "packet_subtype: 0x%x sw_peer_id_valid: %d sw_peer_id: %d\n" + "phy_ppdu_id: 0x%04x packet_ta_upper_16: 0x%04x\n" + "packet_ta_mid_16: 0x%04x packet_ta_lower_16: 0x%04x\n" + "packet_ra_upper_16: 0x%04x packet_ra_mid_16: 0x%04x\n" + "packet_ra_lower_16: 0x%04x tsf_timestamp_63_48: 0x%04x\n" + "tsf_timestamp_47_32: 0x%04x tsf_timestamp_31_16: 0x%04x\n" + "tsf_timestamp_15_0: 0x%04x user_index: %d directed: %d\n", + cookie, + freeze->freeze, + freeze->capture_reason, + freeze->packet_type, + freeze->packet_sub_type, + freeze->sw_peer_id_valid, + freeze->sw_peer_id, + freeze->phy_ppdu_id, + freeze->packet_ta_upper_16, + freeze->packet_ta_mid_16, + freeze->packet_ta_lower_16, + freeze->packet_ra_upper_16, + freeze->packet_ra_mid_16, + freeze->packet_ra_lower_16, + freeze->tsf_timestamp_63_48, + freeze->tsf_timestamp_47_32, + freeze->tsf_timestamp_31_16, + freeze->tsf_timestamp_15_0, + freeze->user_index, + freeze->directed); +} + +/** + * dump_mu_rx_info() - Dump MU info in enhanced DMA header + * @mu_rx_user_info: MU info sent by ucode + * @mu_rx_num_users: Number of MU users in UL-MU-PPDU + * @cookie: Index into lookup table + * + * Return: none + */ +static void dump_mu_rx_info(void *mu_rx_user_info, + uint8_t mu_rx_num_users, + uint32_t cookie) +{ + uint8_t i; + struct uplink_user_setup_info *ul_mu_user_info = + (struct uplink_user_setup_info *) mu_rx_user_info; + + for (i = 0 ; i < mu_rx_num_users; i++) { + cfr_debug("<%u>\n" + "\n" + "bw_info_valid = %d\n" + "uplink_receive_type = %d\n" + "uplink_11ax_mcs = %d\n" + "ru_width = %d\n" + "nss = %d\n" + "stream_offset = %d\n" + "sta_dcm = %d\n" + "sta_coding = %d\n" + "ru_start_index = %d\n", + cookie, + i, + ul_mu_user_info->bw_info_valid, + ul_mu_user_info->uplink_receive_type, + ul_mu_user_info->uplink_11ax_mcs, + ul_mu_user_info->ru_width, + ul_mu_user_info->nss, + ul_mu_user_info->stream_offset, + ul_mu_user_info->sta_dcm, + ul_mu_user_info->sta_coding, + ul_mu_user_info->ru_start_index); + ul_mu_user_info += sizeof(struct uplink_user_setup_info); + } +} + +static void dump_metadata(struct csi_cfr_header *header, uint32_t cookie) +{ + uint8_t user_id, chain_id; + struct cfr_metadata_version_3 *meta = &header->u.meta_v3; + uint8_t *usermac = NULL; + + cfr_debug("<%u>\n" + "start_magic_num = 0x%x\n" + "vendorid = 0x%x\n" + "cfr_metadata_version = %d\n" + "cfr_data_version = %d\n" + "chip_type = %d\n" + "platform_type = %d\n" + "status = %d\n" + "capture_bw = %d\n" + "channel_bw = %d\n" + "phy_mode = %d\n" + "prim20_chan = %d\n" + "center_freq1 = %d\n" + "center_freq2 = %d\n" + "ack_capture_mode = %d\n" + "cfr_capture_type = %d\n" + "sts_count = %d\n" + "num_rx_chain = %d\n" + "timestamp = %llu\n" + "length = %d\n" + "is_mu_ppdu = %d\n" + "num_users = %d\n", + cookie, + header->start_magic_num, + header->vendorid, + header->cfr_metadata_version, + header->cfr_data_version, + header->chip_type, + header->pltform_type, + meta->status, + meta->capture_bw, + meta->channel_bw, + meta->phy_mode, + meta->prim20_chan, + meta->center_freq1, + meta->center_freq2, + meta->capture_mode, + meta->capture_type, + meta->sts_count, + meta->num_rx_chain, + meta->timestamp, + meta->length, + meta->is_mu_ppdu, + meta->num_mu_users); + + if (meta->is_mu_ppdu) { + for (user_id = 0; user_id < meta->num_mu_users; user_id++) { + usermac = meta->peer_addr.mu_peer_addr[user_id]; + cfr_debug("peermac[%d]: " QDF_MAC_ADDR_FMT, + user_id, QDF_MAC_ADDR_REF(usermac)); + } + } else { + cfr_debug("peermac: " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(meta->peer_addr.su_peer_addr)); + } + + for (chain_id = 0; chain_id < HOST_MAX_CHAINS; chain_id++) { + cfr_debug("chain_rssi[%d] = %d\n", + chain_id, + meta->chain_rssi[chain_id]); + } + + for (chain_id = 0; chain_id < HOST_MAX_CHAINS; chain_id++) { + cfr_debug("chain_phase[%d] = %d\n", + chain_id, + meta->chain_phase[chain_id]); + } +} +/** + * dump_enh_dma_hdr() - Dump enhanced DMA header populated by ucode + * @dma_hdr: pointer to enhanced DMA header + * @freeze_tlv: pointer to MACRX_FREEZE_CAPTURE_CHANNEL TLV + * @mu_rx_user_info: UPLINK_USER_SETUP_INFO TLV + * @header: pointer to metadata passed to userspace + * @error: Indicates whether it is an error + * @cookie: Index into lookup table + * + * Return: none + */ +static void dump_enh_dma_hdr(struct whal_cfir_enhanced_hdr *dma_hdr, + void *freeze_tlv, void *mu_rx_user_info, + struct csi_cfr_header *header, int error, + uint32_t cookie) +{ + if (!error) { + cfr_debug("<%u>\n" + "Tag: 0x%02x Length: %d udone: %d\n" + "ctype: %d preamble: %d Nss: %d\n" + "num_chains: %d bw: %d peervalid: %d\n" + "peer_id: %d ppdu_id: 0x%04x total_bytes: %d\n" + "header_version: %d target_id: %d cfr_fmt: %d\n" + "mu_rx_data_incl: %d freeze_data_incl: %d\n" + "mu_rx_num_users: %d decimation_factor: %d\n", + cookie, + dma_hdr->tag, + dma_hdr->length, + dma_hdr->upload_done, + dma_hdr->capture_type, + dma_hdr->preamble_type, + dma_hdr->nss, + dma_hdr->num_chains, + dma_hdr->upload_pkt_bw, + dma_hdr->sw_peer_id_valid, + dma_hdr->sw_peer_id, + dma_hdr->phy_ppdu_id, + dma_hdr->total_bytes, + dma_hdr->header_version, + dma_hdr->target_id, + dma_hdr->cfr_fmt, + dma_hdr->mu_rx_data_incl, + dma_hdr->freeze_data_incl, + dma_hdr->mu_rx_num_users, + dma_hdr->decimation_factor); + + if (dma_hdr->freeze_data_incl) + dump_freeze_tlv(freeze_tlv, cookie); + + if (dma_hdr->mu_rx_data_incl) + dump_mu_rx_info(mu_rx_user_info, + dma_hdr->mu_rx_num_users, + cookie); + } else { + cfr_err("<%u>\n" + "Tag: 0x%02x Length: %d udone: %d\n" + "ctype: %d preamble: %d Nss: %d\n" + "num_chains: %d bw: %d peervalid: %d\n" + "peer_id: %d ppdu_id: 0x%04x total_bytes: %d\n" + "header_version: %d target_id: %d cfr_fmt: %d\n" + "mu_rx_data_incl: %d freeze_data_incl: %d\n" + "mu_rx_num_users: %d decimation_factor: %d\n", + cookie, + dma_hdr->tag, + dma_hdr->length, + dma_hdr->upload_done, + dma_hdr->capture_type, + dma_hdr->preamble_type, + dma_hdr->nss, + dma_hdr->num_chains, + dma_hdr->upload_pkt_bw, + dma_hdr->sw_peer_id_valid, + dma_hdr->sw_peer_id, + dma_hdr->phy_ppdu_id, + dma_hdr->total_bytes, + dma_hdr->header_version, + dma_hdr->target_id, + dma_hdr->cfr_fmt, + dma_hdr->mu_rx_data_incl, + dma_hdr->freeze_data_incl, + dma_hdr->mu_rx_num_users, + dma_hdr->decimation_factor); + } +} + + +/** + * extract_peer_mac_from_freeze_tlv() - extract macaddr from freeze tlv + * @freeze_tlv: Freeze TLV sent from MAC to PHY + * @peermac: macaddr of the peer + * + * Return: none + */ +static void +extract_peer_mac_from_freeze_tlv(void *freeze_tlv, uint8_t *peermac) +{ + struct macrx_freeze_capture_channel *freeze = + (struct macrx_freeze_capture_channel *)freeze_tlv; + + peermac[0] = freeze->packet_ta_lower_16 & 0x00FF; + peermac[1] = (freeze->packet_ta_lower_16 & 0xFF00) >> 8; + peermac[2] = freeze->packet_ta_mid_16 & 0x00FF; + peermac[3] = (freeze->packet_ta_mid_16 & 0xFF00) >> 8; + peermac[4] = freeze->packet_ta_upper_16 & 0x00FF; + peermac[5] = (freeze->packet_ta_upper_16 & 0xFF00) >> 8; +} + +/** + * check_dma_length() - Sanity check DMA header and payload length + * @dma_hdr: pointer to enhanced DMA header + * + * Return: QDF_STATUS + */ +static QDF_STATUS check_dma_length(struct look_up_table *lut) +{ + if (lut->header_length <= CYP_MAX_HEADER_LENGTH_WORDS && + lut->payload_length <= CYP_MAX_DATA_LENGTH_BYTES) { + return QDF_STATUS_SUCCESS; + } else { + return QDF_STATUS_E_FAILURE; + } +} + +/** + * correlate_and_relay_enh() - Correlate TXRX and DBR events and stream CFR + * data to userspace + * @pdev: objmgr PDEV + * @cookie: Index into lookup table + * @lut: pointer to lookup table + * @module_id: ID of the event received + * 0 - DBR event + * 1 - TXRX event + * + * Return: + * - STATUS_ERROR + * - STATUS_HOLD + * - STATUS_STREAM_AND_RELEASE + */ +static int correlate_and_relay_enh(struct wlan_objmgr_pdev *pdev, + uint32_t cookie, + struct look_up_table *lut, + uint8_t module_id) +{ + struct pdev_cfr *pcfr; + uint64_t diff; + int status = STATUS_ERROR; + + if (module_id > 1) { + cfr_err("Received request with invalid mod id. Investigate!!"); + QDF_ASSERT(0); + status = STATUS_ERROR; + goto done; + } + + + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + + if (module_id == CORRELATE_TX_EV_MODULE_ID) { + if (lut->tx_recv) + pcfr->cfr_dma_aborts++; + lut->tx_recv = true; + } else if (module_id == CORRELATE_DBR_MODULE_ID) { + pcfr->dbr_evt_cnt++; + lut->dbr_recv = true; + } + + if ((lut->dbr_recv == true) && (lut->tx_recv == true)) { + if (lut->dbr_ppdu_id == lut->tx_ppdu_id) { + + pcfr->last_success_tstamp = lut->dbr_tstamp; + if (lut->dbr_tstamp > lut->txrx_tstamp) { + diff = lut->dbr_tstamp - lut->txrx_tstamp; + cfr_debug("<%u>: " + "TXRX evt -> DBR evt" + "(delay = %llu ms)\n", cookie, diff); + } else if (lut->txrx_tstamp > lut->dbr_tstamp) { + diff = lut->txrx_tstamp - lut->dbr_tstamp; + cfr_debug("<%u>: " + "DBR evt -> TXRX evt" + "(delay = %llu ms)\n", cookie, diff); + } + + /* + * Flush pending dbr events, if newer PPDU TLV is + * received + */ + cfr_free_pending_dbr_events(pdev); + + if (check_dma_length(lut) == QDF_STATUS_SUCCESS) { + pcfr->release_cnt++; + cfr_debug("<%u>:Stream and release " + "CFR data for " + "ppdu_id:0x%04x\n", cookie, + lut->tx_ppdu_id); + status = STATUS_STREAM_AND_RELEASE; + goto done; + } else { + pcfr->invalid_dma_length_cnt++; + cfr_err("<%u>:CFR buffers " + "received with invalid length " + "header_length_words = %d " + "cfr_payload_length_bytes = %d " + "ppdu_id:0x%04x\n", + cookie, + lut->header_length, + lut->payload_length, + lut->tx_ppdu_id); + /* + * Assert here as length exceeding the allowed + * limit would anyway manifest as random crash + */ + QDF_ASSERT(0); + status = STATUS_ERROR; + goto done; + } + } else { + /* + * When there is a ppdu id mismatch, discard the TXRX + * event since multiple PPDUs are likely to have same + * dma addr, due to ucode aborts + */ + cfr_debug("Received new dbr event for same " + "cookie %u", + cookie); + lut->tx_recv = false; + lut->tx_ppdu_id = 0; + pcfr->clear_txrx_event++; + pcfr->cfr_dma_aborts++; + status = STATUS_HOLD; + } + } else { + status = STATUS_HOLD; + } +done: + return status; +} + +/** + * target_if_cfr_rx_tlv_process() - Process PPDU status TLVs and store info in + * lookup table + * @pdev_obj: PDEV object + * @nbuf: ppdu info + * + * Return: none + */ +void target_if_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf) +{ + struct cdp_rx_indication_ppdu *cdp_rx_ppdu; + struct cdp_rx_stats_ppdu_user *rx_stats_peruser; + struct cdp_rx_ppdu_cfr_info *cfr_info; + qdf_dma_addr_t buf_addr = 0, buf_addr_extn = 0; + struct pdev_cfr *pcfr; + struct look_up_table *lut = NULL; + struct csi_cfr_header *header = NULL; + uint32_t cookie; + struct wlan_objmgr_psoc *psoc; + struct wlan_channel *bss_chan; + enum wlan_phymode ch_phymode; + uint16_t ch_freq; + uint32_t ch_cfreq1; + uint32_t ch_cfreq2; + struct wlan_objmgr_vdev *vdev = NULL; + int i, status = 0; + QDF_STATUS retval = 0; + struct wlan_lmac_if_cfr_rx_ops *cfr_rx_ops = NULL; + struct cfr_metadata_version_3 *meta = NULL; + uint8_t srng_id = 0; + + if (qdf_unlikely(!pdev)) { + cfr_err("pdev is null\n"); + qdf_nbuf_free(nbuf); + return; + } + + retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID); + if (qdf_unlikely(retval != QDF_STATUS_SUCCESS)) { + cfr_err("failed to get pdev reference"); + qdf_nbuf_free(nbuf); + return; + } + + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + if (qdf_unlikely(!pcfr)) { + cfr_err("pdev object for CFR is NULL"); + goto done; + } + + cdp_rx_ppdu = (struct cdp_rx_indication_ppdu *)qdf_nbuf_data(nbuf); + cfr_info = &cdp_rx_ppdu->cfr_info; + + if (!cfr_info->bb_captured_channel) + goto done; + + psoc = wlan_pdev_get_psoc(pdev); + if (qdf_unlikely(!psoc)) { + cfr_err("psoc is null\n"); + goto done; + } + + cfr_rx_ops = &psoc->soc_cb.rx_ops.cfr_rx_ops; + buf_addr_extn = cfr_info->rtt_che_buffer_pointer_high8 & 0xF; + buf_addr = (cfr_info->rtt_che_buffer_pointer_low32 | + ((uint64_t)buf_addr_extn << 32)); + + srng_id = pcfr->rcc_param.srng_id; + if (target_if_dbr_cookie_lookup(pdev, DBR_MODULE_CFR, buf_addr, + &cookie, srng_id)) { + cfr_debug("Cookie lookup failure for addr: 0x%pK", + (void *)((uintptr_t)buf_addr)); + goto done; + } + + cfr_debug("<%u>:buffer address: 0x%pK \n" + " ppdu_id: 0x%04x\n" + " BB_CAPTURED_CHANNEL = %d\n" + " RX_LOCATION_INFO_VALID = %d\n" + " RTT_CHE_BUFFER_POINTER_LOW32 = %x\n" + " RTT_CHE_BUFFER_POINTER_HIGH8 = %x\n" + " CHAN_CAPTURE_STATUS = %d\n", + cookie, + (void *)((uintptr_t)buf_addr), + cdp_rx_ppdu->ppdu_id, + cfr_info->bb_captured_channel, + cfr_info->rx_location_info_valid, + cfr_info->rtt_che_buffer_pointer_low32, + cfr_info->rtt_che_buffer_pointer_high8, + cfr_info->chan_capture_status); + + lut = get_lut_entry(pcfr, cookie); + if (qdf_unlikely(!lut)) { + cfr_err("lut is NULL"); + goto done; + } + + if (pcfr->rcc_param.vdev_id == CFR_INVALID_VDEV_ID) + vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_CFR_ID); + else + vdev = wlan_objmgr_get_vdev_by_id_from_pdev( + pdev, pcfr->rcc_param.vdev_id, WLAN_CFR_ID); + if (qdf_unlikely(!vdev)) { + cfr_debug("vdev is null\n"); + goto done; + } + + bss_chan = wlan_vdev_mlme_get_bss_chan(vdev); + ch_freq = bss_chan->ch_freq; + ch_cfreq1 = bss_chan->ch_cfreq1; + ch_cfreq2 = bss_chan->ch_cfreq2; + ch_phymode = bss_chan->ch_phymode; + wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); + + pcfr->rx_tlv_evt_cnt++; + lut->tx_ppdu_id = cdp_rx_ppdu->ppdu_id; + lut->tx_address1 = cfr_info->rtt_che_buffer_pointer_low32; + lut->tx_address2 = cfr_info->rtt_che_buffer_pointer_high8; + lut->txrx_tstamp = qdf_ktime_to_ms(qdf_ktime_get()); + header = &lut->header; + meta = &header->u.meta_v3; + + header->start_magic_num = 0xDEADBEAF; + header->vendorid = 0x8cfdf0; + header->cfr_metadata_version = CFR_META_VERSION_3; + header->cfr_data_version = CFR_DATA_VERSION_1; + header->chip_type = pcfr->chip_type; + header->pltform_type = CFR_PLATFORM_TYPE_ARM; + header->Reserved = 0; + + meta->status = 1; + meta->phy_mode = ch_phymode; + meta->prim20_chan = ch_freq; + meta->center_freq1 = ch_cfreq1; + meta->center_freq2 = ch_cfreq2; + meta->capture_mode = 0; + + meta->timestamp = cdp_rx_ppdu->timestamp; + meta->is_mu_ppdu = (cdp_rx_ppdu->u.ppdu_type == CDP_RX_TYPE_SU) ? 0 : 1; + meta->num_mu_users = (meta->is_mu_ppdu) ? (cdp_rx_ppdu->num_users) : 0; + + if (meta->num_mu_users > CYP_CFR_MU_USERS) + meta->num_mu_users = CYP_CFR_MU_USERS; + + for (i = 0; i < MAX_CHAIN; i++) + meta->chain_rssi[i] = cdp_rx_ppdu->per_chain_rssi[i]; + + if (cdp_rx_ppdu->u.ppdu_type == CDP_RX_TYPE_SU) { + qdf_mem_copy(meta->peer_addr.su_peer_addr, + cdp_rx_ppdu->mac_addr, + QDF_MAC_ADDR_SIZE); + } else { + for (i = 0 ; i < meta->num_mu_users; i++) { + rx_stats_peruser = &cdp_rx_ppdu->user[i]; + qdf_mem_copy(meta->peer_addr.mu_peer_addr[i], + rx_stats_peruser->mac_addr, + QDF_MAC_ADDR_SIZE); + } + } + status = correlate_and_relay_enh(pdev, cookie, lut, + CORRELATE_TX_EV_MODULE_ID); + if (status == STATUS_STREAM_AND_RELEASE) { + if (cfr_rx_ops->cfr_info_send) + status = cfr_rx_ops->cfr_info_send(pdev, + &lut->header, + sizeof(struct + csi_cfr_header), + lut->data, + lut->data_len, + &end_magic, 4); + dump_metadata(header, cookie); + release_lut_entry_enh(pdev, lut); + target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, buf_addr, + cookie, srng_id); + cfr_debug("Data sent to upper layers, release look up table"); + } else if (status == STATUS_HOLD) { + cfr_debug("HOLD for buffer address: 0x%pK cookie: %u", + (void *)((uintptr_t)buf_addr), cookie); + } else { + cfr_err("Correlation returned invalid status!!"); + } +done: + qdf_nbuf_free(nbuf); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); +} + +/** + * freeze_reason_to_capture_type() - Convert capture type enum in freeze tlv + * to the cfr type enum shared with userspace + * @freeze_tlv: pointer to MACRX_FREEZE_CAPTURE_CHANNEL TLV + * + * Return: cfr type enum + */ +static uint8_t freeze_reason_to_capture_type(void *freeze_tlv) +{ + struct macrx_freeze_capture_channel *freeze = + (struct macrx_freeze_capture_channel *)freeze_tlv; + + switch (freeze->capture_reason) { + case FREEZE_REASON_TM: + return CFR_TYPE_METHOD_TM; + case FREEZE_REASON_FTM: + return CFR_TYPE_METHOD_FTM; + case FREEZE_REASON_TA_RA_TYPE_FILTER: + return CFR_TYPE_METHOD_TA_RA_TYPE_FILTER; + case FREEZE_REASON_NDPA_NDP: + return CFR_TYPE_METHOD_NDPA_NDP; + case FREEZE_REASON_ALL_PACKET: + return CFR_TYPE_METHOD_ALL_PACKET; + case FREEZE_REASON_ACK_RESP_TO_TM_FTM: + return CFR_TYPE_METHOD_ACK_RESP_TO_TM_FTM; + default: + return CFR_TYPE_METHOD_AUTO; + } + return CFR_TYPE_METHOD_AUTO; +} + +#ifdef DIRECT_BUF_RX_ENABLE +/** + * enh_cfr_dbr_event_handler() - Process DBR event for CFR data DMA completion + * @pdev: PDEV object + * @payload: pointer to CFR data + * + * Return: status + */ +static bool enh_cfr_dbr_event_handler(struct wlan_objmgr_pdev *pdev, + struct direct_buf_rx_data *payload) +{ + uint8_t *data = NULL; + uint32_t cookie = 0; + struct whal_cfir_enhanced_hdr dma_hdr = {0}; + int length, status = 0; + struct wlan_objmgr_psoc *psoc; + struct pdev_cfr *pcfr; + struct look_up_table *lut = NULL; + struct csi_cfr_header *header = NULL; + void *mu_rx_user_info = NULL, *freeze_tlv = NULL; + uint8_t capture_type = CFR_TYPE_METHOD_AUTO; + uint8_t *peer_macaddr = NULL; + struct wlan_lmac_if_cfr_rx_ops *cfr_rx_ops = NULL; + struct cfr_metadata_version_3 *meta = NULL; + + if ((!pdev) || (!payload)) { + cfr_err("pdev or payload is null"); + return true; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + cfr_err("psoc is null"); + return true; + } + + cfr_rx_ops = &psoc->soc_cb.rx_ops.cfr_rx_ops; + + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + if (!pcfr) { + cfr_err("pdev object for CFR is null"); + return true; + } + + data = payload->vaddr; + cookie = payload->cookie; + + cfr_debug("<%u>:bufferaddr: 0x%pK cookie: %u\n", cookie, + (void *)((uintptr_t)payload->paddr), cookie); + + qdf_mem_copy(&dma_hdr, &data[0], + sizeof(struct whal_cfir_enhanced_hdr)); + + if (dma_hdr.freeze_data_incl) { + freeze_tlv = data + sizeof(struct whal_cfir_enhanced_hdr); + capture_type = freeze_reason_to_capture_type(freeze_tlv); + } + + if (dma_hdr.mu_rx_data_incl) { + mu_rx_user_info = data + + sizeof(struct whal_cfir_enhanced_hdr) + + (dma_hdr.freeze_data_incl ? + sizeof(struct macrx_freeze_capture_channel) : 0); + } + + + length = dma_hdr.length * 4; + length += dma_hdr.total_bytes; /* size of cfr data */ + + lut = get_lut_entry(pcfr, cookie); + if (!lut) { + cfr_err("lut is NULL"); + return true; + } + + lut->data = data; + lut->data_len = length; + lut->dbr_ppdu_id = dma_hdr.phy_ppdu_id; + lut->dbr_address = payload->paddr; + lut->dbr_tstamp = qdf_ktime_to_ms(qdf_ktime_get()); + lut->header_length = dma_hdr.length; + lut->payload_length = dma_hdr.total_bytes; + qdf_mem_copy(&lut->dma_hdr, &dma_hdr, + sizeof(struct whal_cfir_dma_hdr)); + + header = &lut->header; + meta = &header->u.meta_v3; + meta->channel_bw = dma_hdr.upload_pkt_bw; + meta->num_rx_chain = NUM_CHAINS_FW_TO_HOST(dma_hdr.num_chains); + meta->length = length; + /* For Tx based captures, capture type is sent from FW */ + if (capture_type != CFR_TYPE_METHOD_ACK_RESP_TO_TM_FTM) { + meta->capture_type = capture_type; + meta->sts_count = (dma_hdr.nss + 1); + if (!dma_hdr.mu_rx_data_incl) { + /* extract peer addr from freeze tlv */ + peer_macaddr = meta->peer_addr.su_peer_addr; + if (dma_hdr.freeze_data_incl) { + extract_peer_mac_from_freeze_tlv(freeze_tlv, + peer_macaddr); + } + } + } + + if (dma_hdr.freeze_data_incl) { + dump_enh_dma_hdr(&dma_hdr, freeze_tlv, mu_rx_user_info, + header, 0, cookie); + } + + status = correlate_and_relay_enh(pdev, cookie, lut, + CORRELATE_DBR_MODULE_ID); + if (status == STATUS_STREAM_AND_RELEASE) { + /* + * Message format + * Meta data Header + actual payload + trailer + */ + if (cfr_rx_ops->cfr_info_send) + status = cfr_rx_ops->cfr_info_send(pdev, + &lut->header, + sizeof(struct + csi_cfr_header), + lut->data, + lut->data_len, + &end_magic, 4); + dump_metadata(header, cookie); + release_lut_entry_enh(pdev, lut); + cfr_debug("Data sent to upper layers, released look up table"); + status = true; + } else if (status == STATUS_HOLD) { + cfr_debug("TxRx event not received yet. " + "Buffer is not released"); + status = false; + } else { + cfr_err("Correlation returned invalid status!!"); + status = true; + } + + return status; +} + +/** + * target_if_register_to_dbr_enh() - Initialize DBR ring and register callback + * for DBR events + * @pdev: PDEV object + * + * Return: status + */ +static QDF_STATUS +target_if_register_to_dbr_enh(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL; + struct dbr_module_config dbr_config; + + psoc = wlan_pdev_get_psoc(pdev); + dbr_tx_ops = &psoc->soc_cb.tx_ops.dbr_tx_ops; + dbr_config.num_resp_per_event = DBR_NUM_RESP_PER_EVENT_CFR; + dbr_config.event_timeout_in_ms = DBR_EVENT_TIMEOUT_IN_MS_CFR; + if (dbr_tx_ops->direct_buf_rx_module_register) { + return dbr_tx_ops->direct_buf_rx_module_register + (pdev, DBR_MODULE_CFR, &dbr_config, + enh_cfr_dbr_event_handler); + } + + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_unregister_to_dbr_enh() - Unregister callback for DBR events + * @pdev: PDEV object + * + * Return: status + */ +static QDF_STATUS +target_if_unregister_to_dbr_enh(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_direct_buf_rx_tx_ops *dbr_tx_ops = NULL; + + psoc = wlan_pdev_get_psoc(pdev); + dbr_tx_ops = &psoc->soc_cb.tx_ops.dbr_tx_ops; + if (dbr_tx_ops->direct_buf_rx_module_unregister) { + return dbr_tx_ops->direct_buf_rx_module_unregister + (pdev, DBR_MODULE_CFR); + } + + return QDF_STATUS_SUCCESS; +} +#endif + +/** + * dump_cfr_peer_tx_event_enh() - Dump TX completion event + * @event: ptr to WMI TX completion event for QOS frames sent during + * one-shot capture + * @cookie: Index into lookup table + * + * Return: none + */ +static void dump_cfr_peer_tx_event_enh(wmi_cfr_peer_tx_event_param *event, + uint32_t cookie) +{ + cfr_debug("<%u>CFR capture method: %d vdev_id: %d mac: " + QDF_MAC_ADDR_FMT, cookie, + event->capture_method, event->vdev_id, + QDF_MAC_ADDR_REF(event->peer_mac_addr.bytes)); + + cfr_debug("<%u>Chan: %d bw: %d phymode: %d cfreq1: %d cfrq2: %d " + "nss: %d\n", + cookie, + event->primary_20mhz_chan, event->bandwidth, + event->phy_mode, event->band_center_freq1, + event->band_center_freq2, event->spatial_streams); + + cfr_debug("<%u>Correlation_info1: 0x%08x " + "Correlation_info2: 0x%08x\n", + cookie, + event->correlation_info_1, event->correlation_info_2); + + cfr_debug("<%u>status: 0x%x ts: %d counter: %d rssi0: 0x%08x\n", + cookie, + event->status, event->timestamp_us, event->counter, + event->chain_rssi[0]); +} + +#ifdef DIRECT_BUF_RX_ENABLE +/** + * enh_prepare_cfr_header_txstatus() - Prepare CFR metadata for TX failures + * @tx_evt_param: ptr to WMI TX completion event + * @header: pointer to metadata + * + * Return: none + */ +static void enh_prepare_cfr_header_txstatus(wmi_cfr_peer_tx_event_param + *tx_evt_param, + struct csi_cfr_header *header) +{ + header->start_magic_num = 0xDEADBEAF; + header->vendorid = 0x8cfdf0; + header->cfr_metadata_version = CFR_META_VERSION_3; + header->cfr_data_version = CFR_DATA_VERSION_1; + header->chip_type = CFR_CAPTURE_RADIO_CYP; + header->pltform_type = CFR_PLATFORM_TYPE_ARM; + header->Reserved = 0; + header->u.meta_v3.status = 0; /* failure */ + header->u.meta_v3.length = 0; + + qdf_mem_copy(&header->u.meta_v2.peer_addr[0], + &tx_evt_param->peer_mac_addr.bytes[0], QDF_MAC_ADDR_SIZE); + +} + +/** + * target_if_peer_capture_event() - WMI TX completion event for one-shot + * capture + * @sc: pointer to offload soc object + * @data: WMI TX completion event buffer + * @datalen: WMI Tx completion event buffer length + * + * Return: status + */ +static int +target_if_peer_capture_event(ol_scn_t sc, uint8_t *data, uint32_t datalen) +{ + QDF_STATUS retval = 0; + struct wmi_unified *wmi_handle; + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + struct wlan_objmgr_vdev *vdev; + uint32_t cookie; + struct pdev_cfr *pcfr; + struct look_up_table *lut = NULL; + struct csi_cfr_header *header = NULL; + struct csi_cfr_header header_error = {0}; + wmi_cfr_peer_tx_event_param tx_evt_param = {0}; + qdf_dma_addr_t buf_addr = 0, buf_addr_temp = 0; + int status; + struct wlan_channel *bss_chan; + struct wlan_lmac_if_cfr_rx_ops *cfr_rx_ops = NULL; + + if (!sc || !data) { + cfr_err("sc or data is null"); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(sc); + if (!psoc) { + cfr_err("psoc is null"); + return -EINVAL; + } + + cfr_rx_ops = &psoc->soc_cb.rx_ops.cfr_rx_ops; + + retval = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_CFR_ID); + if (QDF_IS_STATUS_ERROR(retval)) { + cfr_err("unable to get psoc reference"); + return -EINVAL; + } + + wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); + if (!wmi_handle) { + cfr_err("wmi_handle is null"); + wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); + return -EINVAL; + } + + + retval = wmi_extract_cfr_peer_tx_event_param(wmi_handle, data, + &tx_evt_param); + + if (retval != QDF_STATUS_SUCCESS) { + cfr_err("Failed to extract cfr tx event param"); + wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); + return -EINVAL; + } + + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, tx_evt_param.vdev_id, + WLAN_CFR_ID); + if (!vdev) { + cfr_err("vdev is null"); + wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); + return -EINVAL; + } + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) { + cfr_err("pdev is null"); + wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); + return -EINVAL; + } + + retval = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID); + if (retval != QDF_STATUS_SUCCESS) { + cfr_err("failed to get pdev reference"); + wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); + return -EINVAL; + } + + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + if (!pcfr) { + cfr_err("pdev object for CFR is NULL"); + retval = -EINVAL; + goto end; + } + + if ((tx_evt_param.status & PEER_CFR_CAPTURE_EVT_PS_STATUS_MASK) == 1) { + cfr_err("CFR capture failed as peer is in powersave: " + QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(tx_evt_param.peer_mac_addr.bytes)); + + enh_prepare_cfr_header_txstatus(&tx_evt_param, &header_error); + if (cfr_rx_ops->cfr_info_send) + cfr_rx_ops->cfr_info_send(pdev, + &header_error, + sizeof(struct + csi_cfr_header), + NULL, 0, &end_magic, 4); + + retval = -EINVAL; + goto end; + } + + if ((tx_evt_param.status & PEER_CFR_CAPTURE_EVT_STATUS_MASK) == 0) { + cfr_debug("CFR capture failed for peer: " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(tx_evt_param.peer_mac_addr.bytes)); + retval = -EINVAL; + goto end; + } + + if (tx_evt_param.status & CFR_TX_EVT_STATUS_MASK) { + cfr_debug("TX packet returned status %d for peer: " + QDF_MAC_ADDR_FMT, + tx_evt_param.status & CFR_TX_EVT_STATUS_MASK, + QDF_MAC_ADDR_REF(tx_evt_param.peer_mac_addr.bytes)); + retval = -EINVAL; + goto end; + } + + buf_addr_temp = (tx_evt_param.correlation_info_2 & 0x0f); + buf_addr = (tx_evt_param.correlation_info_1 | + ((uint64_t)buf_addr_temp << 32)); + + if (target_if_dbr_cookie_lookup(pdev, DBR_MODULE_CFR, buf_addr, + &cookie, 0)) { + cfr_debug("Cookie lookup failure for addr: 0x%pK status: 0x%x", + (void *)((uintptr_t)buf_addr), tx_evt_param.status); + retval = -EINVAL; + goto end; + } + + cfr_debug("buffer address: 0x%pK cookie: %u", + (void *)((uintptr_t)buf_addr), cookie); + + dump_cfr_peer_tx_event_enh(&tx_evt_param, cookie); + + lut = get_lut_entry(pcfr, cookie); + if (!lut) { + cfr_err("lut is NULL\n"); + retval = -EINVAL; + goto end; + } + + pcfr->tx_evt_cnt++; + pcfr->total_tx_evt_cnt++; + + lut->tx_ppdu_id = (tx_evt_param.correlation_info_2 >> 16); + lut->tx_address1 = tx_evt_param.correlation_info_1; + lut->tx_address2 = tx_evt_param.correlation_info_2; + lut->txrx_tstamp = qdf_ktime_to_ms(qdf_ktime_get()); + + header = &lut->header; + header->start_magic_num = 0xDEADBEAF; + header->vendorid = 0x8cfdf0; + header->cfr_metadata_version = CFR_META_VERSION_3; + header->cfr_data_version = CFR_DATA_VERSION_1; + header->chip_type = CFR_CAPTURE_RADIO_CYP; + header->pltform_type = CFR_PLATFORM_TYPE_ARM; + header->Reserved = 0; + header->u.meta_v3.status = (tx_evt_param.status & + PEER_CFR_CAPTURE_EVT_STATUS_MASK) ? + 1 : 0; + header->u.meta_v3.capture_bw = tx_evt_param.bandwidth; + + bss_chan = wlan_vdev_mlme_get_bss_chan(vdev); + header->u.meta_v3.phy_mode = bss_chan->ch_phymode; + + header->u.meta_v3.prim20_chan = tx_evt_param.primary_20mhz_chan; + header->u.meta_v3.center_freq1 = tx_evt_param.band_center_freq1; + header->u.meta_v3.center_freq2 = tx_evt_param.band_center_freq2; + + /* Currently CFR data is captured on ACK of a Qos NULL frame. + * For 20 MHz, ACK is Legacy and for 40/80/160, ACK is DUP Legacy. + */ + header->u.meta_v3.capture_mode = tx_evt_param.bandwidth ? + CFR_DUP_LEGACY_ACK : CFR_LEGACY_ACK; + header->u.meta_v3.capture_type = tx_evt_param.capture_method; + header->u.meta_v3.num_rx_chain = wlan_vdev_mlme_get_rxchainmask(vdev); + header->u.meta_v3.sts_count = tx_evt_param.spatial_streams; + header->u.meta_v3.timestamp = tx_evt_param.timestamp_us; + + qdf_mem_copy(&header->u.meta_v3.peer_addr.su_peer_addr[0], + &tx_evt_param.peer_mac_addr.bytes[0], QDF_MAC_ADDR_SIZE); + qdf_mem_copy(&header->u.meta_v3.chain_rssi[0], + &tx_evt_param.chain_rssi[0], + HOST_MAX_CHAINS * sizeof(tx_evt_param.chain_rssi[0])); + qdf_mem_copy(&header->u.meta_v3.chain_phase[0], + &tx_evt_param.chain_phase[0], + HOST_MAX_CHAINS * sizeof(tx_evt_param.chain_phase[0])); + + status = correlate_and_relay_enh(pdev, cookie, lut, + CORRELATE_TX_EV_MODULE_ID); + if (status == STATUS_STREAM_AND_RELEASE) { + if (cfr_rx_ops->cfr_info_send) + status = cfr_rx_ops->cfr_info_send(pdev, + &lut->header, + sizeof( + struct + csi_cfr_header), + lut->data, + lut->data_len, + &end_magic, 4); + dump_metadata(header, cookie); + release_lut_entry_enh(pdev, lut); + target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, buf_addr, + cookie, 0); + cfr_debug("Data sent to upper layers, " + "releasing look up table"); + } else if (status == STATUS_HOLD) { + cfr_debug("HOLD for buffer address: 0x%pK cookie: %u", + (void *)((uintptr_t)buf_addr), cookie); + } else { + cfr_err("Correlation returned invalid status!!"); + retval = -EINVAL; + goto end; + } + +end: + + wlan_objmgr_psoc_release_ref(psoc, WLAN_CFR_ID); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return retval; +} +#else +static int +target_if_peer_capture_event(ol_scn_t sc, uint8_t *data, uint32_t datalen) +{ + return 0; +} +#endif + +/** + * target_if_register_tx_completion_enh_event_handler() - Register callback for + * WMI TX completion event + * @psoc: PSOC object + * + * Return: Success/Failure status + */ +static int +target_if_register_tx_completion_enh_event_handler(struct wlan_objmgr_psoc + *psoc) +{ + /* Register completion handler here */ + wmi_unified_t wmi_hdl; + int ret = 0; + + wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_hdl) { + cfr_err("Unable to get wmi handle"); + return -EINVAL; + } + + ret = wmi_unified_register_event_handler(wmi_hdl, + wmi_peer_cfr_capture_event_id, + target_if_peer_capture_event, + WMI_RX_UMAC_CTX); + /* + * Event registration is called per pdev + * Ignore erorr if event is alreday registred. + */ + if (ret == QDF_STATUS_E_FAILURE) + ret = QDF_STATUS_SUCCESS; + + return ret; +} + +/** + * target_if_unregister_tx_completion_enh_event_handler() - Unregister callback + * for WMI TX completion event + * @psoc: PSOC object + * + * Return: Success/Failure status + */ +static int +target_if_unregister_tx_completion_enh_event_handler(struct wlan_objmgr_psoc + *psoc) +{ + /* Unregister completion handler here */ + wmi_unified_t wmi_hdl; + int status = 0; + + wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_hdl) { + cfr_err("Unable to get wmi handle"); + return -EINVAL; + } + + status = wmi_unified_unregister_event(wmi_hdl, + wmi_peer_cfr_capture_event_id); + return status; +} + +/** + * lut_ageout_timer_task() - Timer to flush pending TXRX/DBR events + * + * Return: none + */ +static os_timer_func(lut_ageout_timer_task) +{ + int i = 0; + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + struct look_up_table *lut = NULL; + uint64_t diff, cur_tstamp; + uint8_t srng_id = 0; + + OS_GET_TIMER_ARG(pcfr, struct pdev_cfr*); + + if (!pcfr) { + cfr_err("pdev object for CFR is null"); + return; + } + + pdev = pcfr->pdev_obj; + if (!pdev) { + cfr_err("pdev is null"); + return; + } + + srng_id = pcfr->rcc_param.srng_id; + if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID) + != QDF_STATUS_SUCCESS) { + cfr_err("failed to get pdev reference"); + return; + } + + cur_tstamp = qdf_ktime_to_ms(qdf_ktime_get()); + + for (i = 0; i < pcfr->lut_num; i++) { + lut = get_lut_entry(pcfr, i); + if (!lut) + continue; + + if (lut->dbr_recv && !lut->tx_recv) { + diff = cur_tstamp - lut->dbr_tstamp; + if (diff > LUT_AGE_THRESHOLD) { + cfr_debug("<%d>TXRX event not received for " + "%llu ms, release lut entry : " + "dma_addr = 0x%pK\n", i, diff, + (void *)((uintptr_t)lut->dbr_address)); + target_if_dbr_buf_release(pdev, DBR_MODULE_CFR, + lut->dbr_address, + i, srng_id); + pcfr->flush_timeout_dbr_cnt++; + release_lut_entry_enh(pdev, lut); + } + } + } + + if (pcfr->lut_timer_init) + qdf_timer_mod(&pcfr->lut_age_timer, LUT_AGE_TIMER); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); +} + +/** + * target_if_cfr_start_lut_age_timer() - Start timer to flush aged-out LUT + * entries + * @pdev: pointer to pdev object + * + * Return: None + */ +void target_if_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev) +{ + struct pdev_cfr *pcfr; + + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + if (pcfr->lut_timer_init) + qdf_timer_mod(&pcfr->lut_age_timer, LUT_AGE_TIMER); +} + +/** + * target_if_cfr_stop_lut_age_timer() - Stop timer to flush aged-out LUT + * entries + * @pdev: pointer to pdev object + * + * Return: None + */ +void target_if_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev) +{ + struct pdev_cfr *pcfr; + + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + if (pcfr->lut_timer_init) + qdf_timer_stop(&pcfr->lut_age_timer); +} + +/** + * target_if_cfr_update_global_cfg() - Update global config after a successful + * commit + * @pdev: pointer to pdev object + * + * Return: None + */ +void target_if_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev) +{ + int grp_id; + struct pdev_cfr *pcfr; + struct ta_ra_cfr_cfg *curr_cfg = NULL; + struct ta_ra_cfr_cfg *glbl_cfg = NULL; + unsigned long *modified_in_this_session; + + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + modified_in_this_session = + (unsigned long *)&pcfr->rcc_param.modified_in_curr_session; + + for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) { + if (qdf_test_bit(grp_id, modified_in_this_session)) { + /* Populating global config based on user's input */ + glbl_cfg = &pcfr->global[grp_id]; + curr_cfg = &pcfr->rcc_param.curr[grp_id]; + + if (curr_cfg->valid_ta) + qdf_mem_copy(glbl_cfg->tx_addr, + curr_cfg->tx_addr, + QDF_MAC_ADDR_SIZE); + + if (curr_cfg->valid_ra) + qdf_mem_copy(glbl_cfg->rx_addr, + curr_cfg->rx_addr, + QDF_MAC_ADDR_SIZE); + + if (curr_cfg->valid_ta_mask) + qdf_mem_copy(glbl_cfg->tx_addr_mask, + curr_cfg->tx_addr_mask, + QDF_MAC_ADDR_SIZE); + + if (curr_cfg->valid_ra_mask) + qdf_mem_copy(glbl_cfg->rx_addr_mask, + curr_cfg->rx_addr_mask, + QDF_MAC_ADDR_SIZE); + + if (curr_cfg->valid_bw_mask) + glbl_cfg->bw = curr_cfg->bw; + + if (curr_cfg->valid_nss_mask) + glbl_cfg->nss = curr_cfg->nss; + + if (curr_cfg->valid_mgmt_subtype) + glbl_cfg->mgmt_subtype_filter = + curr_cfg->mgmt_subtype_filter; + + if (curr_cfg->valid_ctrl_subtype) + glbl_cfg->ctrl_subtype_filter = + curr_cfg->ctrl_subtype_filter; + + if (curr_cfg->valid_data_subtype) + glbl_cfg->data_subtype_filter = + curr_cfg->data_subtype_filter; + } + } +} + +/** + * cfr_6018_init_pdev() - Inits cfr pdev and registers necessary handlers. + * @psoc: pointer to psoc object + * @pdev: pointer to pdev object + * + * Return: Registration status for necessary handlers + */ +QDF_STATUS cfr_6018_init_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct pdev_cfr *pcfr; + + if (!pdev) { + cfr_err("PDEV is NULL!"); + return QDF_STATUS_E_NULL_VALUE; + } + + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + if (!pcfr) { + cfr_err("pcfr is NULL!"); + return QDF_STATUS_E_NULL_VALUE; + } + +#if DIRECT_BUF_RX_ENABLE + status = target_if_register_to_dbr_enh(pdev); + if (status != QDF_STATUS_SUCCESS) { + cfr_err("Failed to register with dbr"); + return status; + } +#endif + + status = target_if_register_tx_completion_enh_event_handler(psoc); + if (status != QDF_STATUS_SUCCESS) { + cfr_err("Failed to register with tx event handler"); + return status; + } + + pcfr->is_cfr_rcc_capable = 1; + pcfr->rcc_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + pcfr->rcc_param.modified_in_curr_session = MAX_RESET_CFG_ENTRY; + pcfr->rcc_param.num_grp_tlvs = MAX_TA_RA_ENTRIES; + pcfr->rcc_param.vdev_id = CFR_INVALID_VDEV_ID; + pcfr->rcc_param.srng_id = 0; + + target_if_cfr_default_ta_ra_config(&pcfr->rcc_param, + true, MAX_RESET_CFG_ENTRY); + + status = target_if_cfr_config_rcc(pdev, &pcfr->rcc_param); + if (status == QDF_STATUS_SUCCESS) { + /* Update global configuration */ + target_if_cfr_update_global_cfg(pdev); + } else { + cfr_err("Sending WMI to configure default has failed\n"); + return status; + } + + pcfr->rcc_param.modified_in_curr_session = 0; + + pcfr->cfr_max_sta_count = MAX_CFR_ENABLED_CLIENTS; + pcfr->subbuf_size = STREAMFS_MAX_SUBBUF_CYP; + pcfr->num_subbufs = STREAMFS_NUM_SUBBUF_CYP; + pcfr->chip_type = CFR_CAPTURE_RADIO_CYP; + + if (!pcfr->lut_timer_init) { + qdf_timer_init(NULL, + &(pcfr->lut_age_timer), + lut_ageout_timer_task, (void *)pcfr, + QDF_TIMER_TYPE_WAKE_APPS); + pcfr->lut_timer_init = 1; + } + + return status; +} + +/** + * cfr_6018_deinit_pdev() - De-inits corresponding pdev and handlers. + * @psoc: pointer to psoc object + * @pdev: pointer to pdev object + * + * Return: De-registration status for necessary handlers + */ +QDF_STATUS cfr_6018_deinit_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + int status; + struct pdev_cfr *pcfr; + + pcfr = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + if (!pcfr) { + cfr_err("pcfr is NULL"); + return -EINVAL; + } + + if (pcfr->lut_timer_init) { + qdf_timer_stop(&pcfr->lut_age_timer); + qdf_timer_free(&(pcfr->lut_age_timer)); + pcfr->lut_timer_init = 0; + } + + pcfr->tx_evt_cnt = 0; + pcfr->dbr_evt_cnt = 0; + pcfr->release_cnt = 0; + pcfr->total_tx_evt_cnt = 0; + pcfr->rx_tlv_evt_cnt = 0; + pcfr->flush_dbr_cnt = 0; + pcfr->flush_timeout_dbr_cnt = 0; + pcfr->invalid_dma_length_cnt = 0; + pcfr->clear_txrx_event = 0; + pcfr->cfr_dma_aborts = 0; + qdf_mem_zero(&pcfr->rcc_param, sizeof(struct cfr_rcc_param)); + qdf_mem_zero(&pcfr->global, (sizeof(struct ta_ra_cfr_cfg) * + MAX_TA_RA_ENTRIES)); + +#ifdef DIRECT_BUF_RX_ENABLE + status = target_if_unregister_to_dbr_enh(pdev); + if (status != QDF_STATUS_SUCCESS) + cfr_err("Failed to register with dbr"); +#endif + + status = target_if_unregister_tx_completion_enh_event_handler(psoc); + if (status != QDF_STATUS_SUCCESS) + cfr_err("Failed to register with dbr"); + + return status; +} diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/cfr/src/target_if_cfr_6490.c b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/src/target_if_cfr_6490.c new file mode 100644 index 0000000000000000000000000000000000000000..0e25aff300ecfcb829e0ed450e6f94779a0d49b4 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/cfr/src/target_if_cfr_6490.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC : target_if_cfr_6490.c + * + * Target interface of CFR for QCA6490 implementation + * + */ + +#include +#include "target_if_cfr.h" +#include +#include "wlan_cfr_utils_api.h" +#include "target_if_cfr_6490.h" +#include "target_if_cfr_6018.h" +#include "init_deinit_lmac.h" +#include "cfg_ucfg_api.h" +#include "cfr_cfg.h" + +static wdi_event_subscribe g_cfr_subscribe; + +static void target_cfr_callback(void *pdev_obj, enum WDI_EVENT event, + void *data, u_int16_t peer_id, + uint32_t status) +{ + struct wlan_objmgr_pdev *pdev; + qdf_nbuf_t nbuf = (qdf_nbuf_t)data; + qdf_nbuf_t data_clone; + + pdev = (struct wlan_objmgr_pdev *)pdev_obj; + if (qdf_unlikely((!pdev || !data))) { + cfr_err("Invalid pdev %pK or data %pK for event %d", + pdev, data, event); + qdf_nbuf_free(nbuf); + return; + } + + if (event != WDI_EVENT_RX_PPDU_DESC) { + cfr_debug("event is %d", event); + qdf_nbuf_free(nbuf); + return; + } + + data_clone = qdf_nbuf_clone(nbuf); + if (data_clone) + wlan_cfr_rx_tlv_process(pdev, (void *)data_clone); + + qdf_nbuf_free(nbuf); +} + +QDF_STATUS +target_if_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev, + bool is_subscribe) +{ + ol_txrx_soc_handle soc; + struct wlan_objmgr_psoc *psoc; + struct pdev_cfr *pcfr; + + if (!pdev) { + cfr_err("Null pdev"); + return QDF_STATUS_E_INVAL; + } + + pcfr = wlan_objmgr_pdev_get_comp_private_obj( + pdev, WLAN_UMAC_COMP_CFR); + if (!pcfr) { + cfr_err("pcfr is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + cfr_err("Null psoc"); + return QDF_STATUS_E_INVAL; + } + + soc = wlan_psoc_get_dp_handle(psoc); + if (!soc) { + cfr_err("Null soc"); + return QDF_STATUS_E_INVAL; + } + + g_cfr_subscribe.callback = target_cfr_callback; + g_cfr_subscribe.context = pdev; + cdp_set_cfr_rcc(soc, 0, is_subscribe); + cdp_enable_mon_reap_timer(soc, 0, is_subscribe); + if (is_subscribe) { + if (cdp_wdi_event_sub(soc, 0, &g_cfr_subscribe, + WDI_EVENT_RX_PPDU_DESC)) { + cfr_err("wdi event sub fail"); + return QDF_STATUS_E_FAILURE; + } + } else { + if (cdp_wdi_event_unsub(soc, 0, &g_cfr_subscribe, + WDI_EVENT_RX_PPDU_DESC)) { + cfr_err("wdi event unsub fail"); + return QDF_STATUS_E_FAILURE; + } + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS cfr_6490_init_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + struct pdev_cfr *cfr_pdev; + struct psoc_cfr *cfr_psoc; + struct wmi_unified *wmi_handle = NULL; + bool is_cfr_disabled; + bool cfr_capable; + QDF_STATUS status; + + if (!psoc || !pdev) { + cfr_err("null pdev or psoc"); + return QDF_STATUS_E_FAILURE; + } + + cfr_pdev = wlan_objmgr_pdev_get_comp_private_obj( + pdev, WLAN_UMAC_COMP_CFR); + if (!cfr_pdev) { + cfr_err("null pdev cfr"); + return QDF_STATUS_E_FAILURE; + } + + cfr_psoc = wlan_objmgr_psoc_get_comp_private_obj( + psoc, WLAN_UMAC_COMP_CFR); + + if (!cfr_psoc) { + cfr_err("null psoc cfr"); + return QDF_STATUS_E_FAILURE; + } + + wmi_handle = lmac_get_pdev_wmi_handle(pdev); + if (!wmi_handle) { + cfr_err("null wmi handle"); + return QDF_STATUS_E_FAILURE; + } + + is_cfr_disabled = cfg_get(psoc, CFG_CFR_DISABLE); + if (is_cfr_disabled) { + cfr_pdev->is_cfr_capable = 0; + cfr_psoc->is_cfr_capable = 0; + cfr_info("cfr disabled"); + return QDF_STATUS_SUCCESS; + } + + cfr_capable = wmi_service_enabled(wmi_handle, + wmi_service_cfr_capture_support); + cfr_pdev->is_cfr_capable = cfr_capable; + cfr_psoc->is_cfr_capable = cfr_capable; + if (!cfr_capable) { + cfr_err("FW doesn't support CFR"); + return QDF_STATUS_SUCCESS; + } + + status = cfr_6018_init_pdev(psoc, pdev); + cfr_pdev->chip_type = CFR_CAPTURE_RADIO_HSP; + + return status; +} + +QDF_STATUS cfr_6490_deinit_pdev(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + struct pdev_cfr *pcfr; + + if (!psoc || !pdev) { + cfr_err("null pdev or psoc"); + return QDF_STATUS_E_FAILURE; + } + + pcfr = wlan_objmgr_pdev_get_comp_private_obj( + pdev, WLAN_UMAC_COMP_CFR); + if (!pcfr) { + cfr_err("null pdev cfr"); + return QDF_STATUS_E_FAILURE; + } + + if (!pcfr->is_cfr_capable) { + cfr_info("cfr disabled or FW not support"); + return QDF_STATUS_SUCCESS; + } + + return cfr_6018_deinit_pdev(psoc, pdev); +} diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/coex/inc/target_if_coex.h b/drivers/staging/qca-wifi-host-cmn/target_if/coex/inc/target_if_coex.h new file mode 100644 index 0000000000000000000000000000000000000000..d496efaa78ea7b371c5ad808ffec1f5839253b86 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/coex/inc/target_if_coex.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: contains coex target if declarations + */ +#ifndef __TARGET_IF_COEX_H__ +#define __TARGET_IF_COEX_H__ + +#include + +/** + * target_if_coex_register_tx_ops() - Register coex target_if tx ops + * @tx_ops: pointer to target if tx ops + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +target_if_coex_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/coex/src/target_if_coex.c b/drivers/staging/qca-wifi-host-cmn/target_if/coex/src/target_if_coex.c new file mode 100644 index 0000000000000000000000000000000000000000..6dd3c70b8092fc07d776aa9f57b540a597c56c5e --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/coex/src/target_if_coex.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: contains coex target if functions + */ +#include +#include + +static QDF_STATUS +target_if_coex_config_send(struct wlan_objmgr_pdev *pdev, + struct coex_config_params *param) +{ + wmi_unified_t pdev_wmi_handle; + + pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev); + if (!pdev_wmi_handle) { + coex_err("Invalid PDEV WMI handle"); + return QDF_STATUS_E_FAILURE; + } + + return wmi_unified_send_coex_config_cmd(pdev_wmi_handle, param); +} + +QDF_STATUS +target_if_coex_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + struct wlan_lmac_if_coex_tx_ops *coex_ops; + + if (!tx_ops) { + coex_err("target if tx ops is NULL!"); + return QDF_STATUS_E_INVAL; + } + + coex_ops = &tx_ops->coex_ops; + coex_ops->coex_config_send = target_if_coex_config_send; + + return QDF_STATUS_SUCCESS; +} diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/core/inc/target_if.h b/drivers/staging/qca-wifi-host-cmn/target_if/core/inc/target_if.h index ea21539ef27e1c4e8b1951b31531d08244ff51f1..3f229597393c4e015a86a8b94aa40d12fe0155cb 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/core/inc/target_if.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/core/inc/target_if.h @@ -64,14 +64,6 @@ #define targetif_nofl_debug(params...) \ QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_TARGET_IF, params) -#ifdef CONFIG_MCL -#define TARGET_TYPE_AR900B 9 /* Beeliner */ -#define TARGET_TYPE_QCA9984 15 /* cascade */ -#define TARGET_TYPE_IPQ4019 16 /* dakota */ -#define TARGET_TYPE_QCA9888 17 /* besra */ -#define TARGET_TYPE_AR9888 7 /* Peregrine */ -#endif - typedef struct wlan_objmgr_psoc *(*get_psoc_handle_callback)( void *scn_handle); @@ -118,9 +110,6 @@ struct host_fw_ver { }; struct common_dbglog_handle; -struct common_hif_handle; -struct common_htc_handle; -struct common_wmi_handle; struct common_accelerator_handle; /** @@ -133,9 +122,9 @@ struct common_accelerator_handle; * @dbglog_hdl: Debug log handle */ struct comp_hdls { - struct common_hif_handle *hif_hdl; - struct common_htc_handle *htc_hdl; - struct common_wmi_handle *wmi_hdl; + struct hif_opaque_softc *hif_hdl; + HTC_HANDLE htc_hdl; + struct wmi_unified *wmi_hdl; struct common_accelerator_handle *accelerator_hdl; struct common_dbglog_handle *dbglog_hdl; }; @@ -187,6 +176,7 @@ struct target_version_info { * @service_ext2_param: service ready ext2 event params * @service_ext_param: ext service params * @mac_phy_cap: phy caps array + * @dbr_ring_cap: dbr_ring capability info * @reg_cap: regulatory caps array * @scaling_params: Spectral bin scaling parameters * @num_mem_chunks: number of mem chunks allocated @@ -243,6 +233,7 @@ struct tgt_info { * @sw_version_check: Checks the SW version * @smart_log_enable: Enable Smart Logs feature * @cfr_support_enable: CFR support enable + * @set_pktlog_checksum: Set the pktlog checksum from FW ready event to pl_dev */ struct target_ops { QDF_STATUS (*ext_resource_config_enable) @@ -303,6 +294,8 @@ struct target_ops { void (*cfr_support_enable) (struct wlan_objmgr_psoc *psoc, struct target_psoc_info *tgt_info, uint8_t *event); + void (*set_pktlog_checksum) + (struct wlan_objmgr_pdev *pdev, uint32_t checksum); }; @@ -330,7 +323,7 @@ struct target_psoc_info { * @feature_ptr: stores legacy pointer or few driver specific structures */ struct target_pdev_info { - struct common_wmi_handle *wmi_handle; + struct wmi_unified *wmi_handle; struct common_accelerator_handle *accelerator_hdl; int32_t pdev_idx; int32_t phy_idx; @@ -501,6 +494,14 @@ bool target_is_tgt_type_qca9984(uint32_t target_type); */ bool target_is_tgt_type_qca9888(uint32_t target_type); +/** + * target_is_tgt_type_adrastea() - Check if the target type is QCS40X + * @target_type: target type to be checked. + * + * Return: true if the target_type is QCS40X, else false. + */ +bool target_is_tgt_type_adrastea(uint32_t target_type); + /** * target_psoc_set_wlan_init_status() - set info wlan_init_status @@ -828,6 +829,35 @@ static inline uint8_t target_psoc_get_num_radios return psoc_info->info.num_radios; } +/** + * target_psoc_get_num_radios_for_mode() - get number of radios for a hw-mode + * @psoc_info: pointer to structure target_psoc_info + * + * API to get number_of_radios for a HW mode + * + * Return: number of radios + */ + +static inline uint8_t target_psoc_get_num_radios_for_mode + (struct target_psoc_info *psoc_info, uint8_t mode) +{ + uint8_t mac_phy_count; + uint8_t num_radios = 0; + struct tgt_info *info = &psoc_info->info; + + if (!psoc_info) + return 0; + + for (mac_phy_count = 0; + mac_phy_count < target_psoc_get_total_mac_phy_cnt(psoc_info); + mac_phy_count++) { + num_radios += + (info->mac_phy_cap[mac_phy_count].hw_mode_id == mode); + } + + return num_radios; +} + /** * target_psoc_set_service_bitmap() - set service_bitmap * @psoc_info: pointer to structure target_psoc_info @@ -902,7 +932,7 @@ static inline uint32_t target_psoc_get_num_mem_chunks */ static inline void target_psoc_set_hif_hdl (struct target_psoc_info *psoc_info, - struct common_hif_handle *hif_hdl) + struct hif_opaque_softc *hif_hdl) { if (!psoc_info) return; @@ -918,7 +948,7 @@ static inline void target_psoc_set_hif_hdl * * Return: hif_hdl */ -static inline struct common_hif_handle *target_psoc_get_hif_hdl +static inline struct hif_opaque_softc *target_psoc_get_hif_hdl (struct target_psoc_info *psoc_info) { if (!psoc_info) @@ -936,9 +966,9 @@ static inline struct common_hif_handle *target_psoc_get_hif_hdl * * Return: void */ -static inline void target_psoc_set_htc_hdl - (struct target_psoc_info *psoc_info, - struct common_htc_handle *htc_hdl) +static inline void target_psoc_set_htc_hdl( + struct target_psoc_info *psoc_info, + HTC_HANDLE htc_hdl) { if (!psoc_info) return; @@ -954,7 +984,7 @@ static inline void target_psoc_set_htc_hdl * * Return: htc_hdl */ -static inline struct common_htc_handle *target_psoc_get_htc_hdl +static inline HTC_HANDLE target_psoc_get_htc_hdl (struct target_psoc_info *psoc_info) { if (!psoc_info) @@ -973,7 +1003,7 @@ static inline struct common_htc_handle *target_psoc_get_htc_hdl */ static inline void target_psoc_set_wmi_hdl (struct target_psoc_info *psoc_info, - struct common_wmi_handle *wmi_hdl) + struct wmi_unified *wmi_hdl) { if (!psoc_info) return; @@ -989,7 +1019,7 @@ static inline void target_psoc_set_wmi_hdl * * Return: wmi_hdl */ -static inline struct common_wmi_handle *target_psoc_get_wmi_hdl +static inline struct wmi_unified *target_psoc_get_wmi_hdl (struct target_psoc_info *psoc_info) { if (!psoc_info) @@ -1270,6 +1300,56 @@ static inline struct wlan_psoc_host_service_ext_param return &psoc_info->info.service_ext_param; } +/** + * target_psoc_get_num_dbr_ring_caps() - get no of dbr_ring_caps + * @psoc_info: pointer to structure target_psoc_info + * + * API to get num_dbr_ring_caps + * + * Return: no of dbr_ring_caps + */ +static inline uint32_t target_psoc_get_num_dbr_ring_caps + (struct target_psoc_info *psoc_info) +{ + if (!psoc_info) + return 0; + + if (psoc_info->info.service_ext_param.num_dbr_ring_caps) + return psoc_info->info.service_ext_param.num_dbr_ring_caps; + + return psoc_info->info.service_ext2_param.num_dbr_ring_caps; +} + +/** + * target_psoc_get_mac_phy_cap_for_mode() - get mac_phy_cap for a hw-mode + * @psoc_info: pointer to structure target_psoc_info + * + * API to get mac_phy_cap for a specified hw-mode + * + * Return: structure pointer to wlan_psoc_host_mac_phy_caps + */ + +static inline struct wlan_psoc_host_mac_phy_caps + *target_psoc_get_mac_phy_cap_for_mode + (struct target_psoc_info *psoc_info, uint8_t mode) +{ + uint8_t mac_phy_idx; + struct tgt_info *info = &psoc_info->info; + + if (!psoc_info) + return NULL; + + for (mac_phy_idx = 0; + mac_phy_idx < PSOC_MAX_MAC_PHY_CAP; + mac_phy_idx++) + if (info->mac_phy_cap[mac_phy_idx].hw_mode_id == mode) + break; + + if (mac_phy_idx == PSOC_MAX_MAC_PHY_CAP) + return NULL; + + return &info->mac_phy_cap[mac_phy_idx]; +} /** * target_psoc_get_mac_phy_cap() - get mac_phy_cap @@ -1282,10 +1362,24 @@ static inline struct wlan_psoc_host_service_ext_param static inline struct wlan_psoc_host_mac_phy_caps *target_psoc_get_mac_phy_cap (struct target_psoc_info *psoc_info) { + uint32_t preferred_hw_mode; + struct wlan_psoc_host_mac_phy_caps *mac_phy_cap; + if (!psoc_info) return NULL; - return psoc_info->info.mac_phy_cap; + preferred_hw_mode = + target_psoc_get_preferred_hw_mode(psoc_info); + + if (preferred_hw_mode < WMI_HOST_HW_MODE_MAX) { + mac_phy_cap = + target_psoc_get_mac_phy_cap_for_mode + (psoc_info, preferred_hw_mode); + } else { + mac_phy_cap = psoc_info->info.mac_phy_cap; + } + + return mac_phy_cap; } /** @@ -1403,7 +1497,7 @@ static inline void *target_pdev_get_feature_ptr */ static inline void target_pdev_set_wmi_handle (struct target_pdev_info *pdev_info, - struct common_wmi_handle *wmi_handle) + struct wmi_unified *wmi_handle) { if (!pdev_info) return; @@ -1419,7 +1513,7 @@ static inline void target_pdev_set_wmi_handle * * Return: wmi_handle */ -static inline struct common_wmi_handle *target_pdev_get_wmi_handle +static inline struct wmi_unified *target_pdev_get_wmi_handle (struct target_pdev_info *pdev_info) { if (!pdev_info) @@ -1543,17 +1637,16 @@ static inline int32_t target_pdev_get_phy_idx * Return: wmi_handle on success * if tgt handle is not initialized, it returns NULL */ -static inline struct common_wmi_handle *GET_WMI_HDL_FROM_PSOC( +static inline struct wmi_unified *GET_WMI_HDL_FROM_PSOC( struct wlan_objmgr_psoc *psoc) { - void *tgt_if_handle; + struct target_psoc_info *tgt_if_handle; if (psoc) { tgt_if_handle = psoc->tgt_if_handle; if (tgt_if_handle) - return (target_psoc_get_wmi_hdl( - (struct target_psoc_info *)tgt_if_handle)); + return target_psoc_get_wmi_hdl(tgt_if_handle); else return NULL; } @@ -1570,10 +1663,10 @@ static inline struct common_wmi_handle *GET_WMI_HDL_FROM_PSOC( * Return: wmi_handle on success * if tgt handle is not initialized, it returns NULL */ -static inline struct common_wmi_handle *GET_WMI_HDL_FROM_PDEV( +static inline struct wmi_unified *GET_WMI_HDL_FROM_PDEV( struct wlan_objmgr_pdev *pdev) { - void *tgt_if_handle; + struct target_pdev_info *tgt_if_handle; if (pdev) { tgt_if_handle = pdev->tgt_if_handle; @@ -1726,6 +1819,24 @@ static inline void target_if_cfr_support_enable(struct wlan_objmgr_psoc *psoc, tgt_hdl->tif_ops->cfr_support_enable(psoc, tgt_hdl, evt_buf); } +/** + * target_if_set_pktlog_checksum - Set pktlog checksum + * @pdev: pdev object + * @tgt_hdl: target_psoc_info pointer + * @checksum: checksum received from FW + * + * API to set pktlog checksum + * + * Return: none + */ +static inline void target_if_set_pktlog_checksum(struct wlan_objmgr_pdev *pdev, + struct target_psoc_info *tgt_hdl, uint32_t checksum) +{ + if ((tgt_hdl->tif_ops) && + (tgt_hdl->tif_ops->set_pktlog_checksum)) + tgt_hdl->tif_ops->set_pktlog_checksum(pdev, checksum); +} + /** * target_if_atf_cfg_enable - Enable ATF config * @psoc: psoc object diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/core/src/target_if_main.c b/drivers/staging/qca-wifi-host-cmn/target_if/core/src/target_if_main.c index c29dc9679bbac0817c0fe972314351cb3f7bcae9..a565aab1d547719106fd24b8301812a4f9b9fee0 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/core/src/target_if_main.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/core/src/target_if_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -78,11 +78,14 @@ #ifdef CRYPTO_SET_KEY_CONVERGED #include #endif - -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE #include + +#ifdef FEATURE_COEX +#include #endif +#include + static struct target_if_ctx *g_target_if_ctx; struct target_if_ctx *target_if_get_ctx(void) @@ -341,6 +344,20 @@ static inline void target_if_crypto_tx_ops_register( } #endif +#ifdef FEATURE_COEX +static QDF_STATUS +target_if_coex_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) +{ + return target_if_coex_register_tx_ops(tx_ops); +} +#else +static inline QDF_STATUS +target_if_coex_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) +{ + return QDF_STATUS_SUCCESS; +} +#endif + static void target_if_target_tx_ops_register( struct wlan_lmac_if_tx_ops *tx_ops) { @@ -365,6 +382,9 @@ static void target_if_target_tx_ops_register( target_tx_ops->tgt_is_tgt_type_qca9888 = target_is_tgt_type_qca9888; + target_tx_ops->tgt_is_tgt_type_adrastea = + target_is_tgt_type_adrastea; + target_tx_ops->tgt_get_tgt_type = lmac_get_tgt_type; @@ -381,19 +401,11 @@ target_if_cp_stats_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) return target_if_cp_stats_register_tx_ops(tx_ops); } -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE static QDF_STATUS target_if_vdev_mgr_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) { return target_if_vdev_mgr_register_tx_ops(tx_ops); } -#else -static QDF_STATUS -target_if_vdev_mgr_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) -{ - return QDF_STATUS_SUCCESS; -} -#endif #ifdef QCA_WIFI_FTM static @@ -407,6 +419,20 @@ void target_if_ftm_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) { } #endif + +#ifdef WLAN_FEATURE_GPIO_CFG +static +void target_if_gpio_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) +{ + target_if_gpio_register_tx_ops(tx_ops); +} +#else +static +void target_if_gpio_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) +{ +} +#endif + static QDF_STATUS target_if_register_umac_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) { @@ -449,6 +475,10 @@ QDF_STATUS target_if_register_umac_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) target_if_vdev_mgr_tx_ops_register(tx_ops); + target_if_coex_tx_ops_register(tx_ops); + + target_if_gpio_tx_ops_register(tx_ops); + /* Converged UMAC components to register their TX-ops here */ return QDF_STATUS_SUCCESS; } @@ -577,7 +607,6 @@ QDF_STATUS target_if_free_psoc_tgt_info(struct wlan_objmgr_psoc *psoc) return QDF_STATUS_E_INVAL; } init_deinit_chainmask_table_free(ext_param); - init_deinit_rf_characterization_entries_free(ext_param); init_deinit_dbr_ring_cap_free(tgt_psoc_info); init_deinit_spectral_scaling_params_free(tgt_psoc_info); @@ -609,3 +638,8 @@ bool target_is_tgt_type_qca9888(uint32_t target_type) { return target_type == TARGET_TYPE_QCA9888; } + +bool target_is_tgt_type_adrastea(uint32_t target_type) +{ + return target_type == TARGET_TYPE_ADRASTEA; +} diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/cp_stats/src/target_if_mc_cp_stats.c b/drivers/staging/qca-wifi-host-cmn/target_if/cp_stats/src/target_if_mc_cp_stats.c index 200a9320a2ffdaef945fbbb9708e81f3cddc4857..df77875133087d9ece2c6d1cfb2166629d3e6b84 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/cp_stats/src/target_if_mc_cp_stats.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/cp_stats/src/target_if_mc_cp_stats.c @@ -37,10 +37,20 @@ #include #include #include -#include #include #include +#ifdef WLAN_FEATURE_MIB_STATS +static void target_if_cp_stats_free_mib_stats(struct stats_event *ev) +{ + qdf_mem_free(ev->mib_stats); + ev->mib_stats = NULL; +} +#else +static void target_if_cp_stats_free_mib_stats(struct stats_event *ev) +{ +} +#endif static void target_if_cp_stats_free_stats_event(struct stats_event *ev) { qdf_mem_free(ev->pdev_stats); @@ -57,6 +67,7 @@ static void target_if_cp_stats_free_stats_event(struct stats_event *ev) ev->vdev_summary_stats = NULL; qdf_mem_free(ev->vdev_chain_rssi); ev->vdev_chain_rssi = NULL; + target_if_cp_stats_free_mib_stats(ev); } static QDF_STATUS target_if_cp_stats_extract_pdev_stats( @@ -105,10 +116,7 @@ static void target_if_cp_stats_extract_peer_extd_stats( uint32_t i; wmi_host_peer_extd_stats peer_extd_stats; void *soc = cds_get_context(QDF_MODULE_ID_SOC); - struct cdp_pdev *txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX); struct cdp_peer_stats *peer_stats; - struct cdp_peer *peer; - uint8_t peer_id; if (!stats_param->num_peer_extd_stats) return; @@ -134,17 +142,19 @@ static void target_if_cp_stats_extract_peer_extd_stats( ev->peer_extended_stats[i].rx_mc_bc_cnt = peer_extd_stats.rx_mc_bc_cnt; - peer = cdp_peer_find_by_addr(soc, txrx_pdev, - ev->peer_extended_stats[i].peer_macaddr, - &peer_id); - if (!peer) + peer_stats = qdf_mem_malloc(sizeof(*peer_stats)); + if (!peer_stats) continue; - peer_stats = cdp_host_get_peer_stats(soc, peer); - if (peer_stats) + status = cdp_host_get_peer_stats(soc, VDEV_ALL, + ev->peer_extended_stats[i].peer_macaddr, + peer_stats); + if (status == QDF_STATUS_SUCCESS) ev->peer_extended_stats[i].rx_mc_bc_cnt = peer_stats->rx.multicast.num + peer_stats->rx.bcast.num; + + qdf_mem_free(peer_stats); } } @@ -252,6 +262,50 @@ static QDF_STATUS target_if_cp_stats_extract_cca_stats( return QDF_STATUS_SUCCESS; } +#ifdef WLAN_FEATURE_MIB_STATS +static QDF_STATUS target_if_cp_stats_extract_mib_stats( + struct wmi_unified *wmi_hdl, + wmi_host_stats_event *stats_param, + struct stats_event *ev, uint8_t *data) +{ + QDF_STATUS status; + + if (!stats_param->num_mib_stats) + return QDF_STATUS_SUCCESS; + + if (stats_param->num_mib_stats != MAX_MIB_STATS || + (stats_param->num_mib_extd_stats && + stats_param->num_mib_extd_stats != MAX_MIB_STATS)) { + cp_stats_err("number of mib stats wrong, num_mib_stats %d, num_mib_extd_stats %d", + stats_param->num_mib_stats, + stats_param->num_mib_extd_stats); + return QDF_STATUS_E_INVAL; + } + + ev->num_mib_stats = stats_param->num_mib_stats; + + ev->mib_stats = qdf_mem_malloc(sizeof(*ev->mib_stats)); + if (!ev->mib_stats) + return QDF_STATUS_E_NOMEM; + + status = wmi_extract_mib_stats(wmi_hdl, data, ev->mib_stats); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("wmi_extract_mib_stats failed"); + return status; + } + + return QDF_STATUS_SUCCESS; +} +#else +static QDF_STATUS target_if_cp_stats_extract_mib_stats( + struct wmi_unified *wmi_hdl, + wmi_host_stats_event *stats_param, + struct stats_event *ev, uint8_t *data) +{ + return QDF_STATUS_SUCCESS; +} +#endif + static QDF_STATUS target_if_cp_stats_extract_vdev_summary_stats( struct wmi_unified *wmi_hdl, wmi_host_stats_event *stats_param, @@ -382,11 +436,23 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl, cp_stats_err("stats param extract failed: %d", status); return status; } - cp_stats_nofl_debug("num: pdev: %d, vdev: %d, peer: %d, rssi: %d", + cp_stats_nofl_debug("num: pdev: %d, pdev_extd: %d, vdev: %d, peer: %d," + "peer_extd: %d rssi: %d, mib %d, mib_extd %d, " + "bcnflt: %d, channel: %d, bcn: %d, peer_extd2: %d," + "last_event: %x", stats_param.num_pdev_stats, + stats_param.num_pdev_ext_stats, stats_param.num_vdev_stats, stats_param.num_peer_stats, - stats_param.num_rssi_stats); + stats_param.num_peer_extd_stats, + stats_param.num_rssi_stats, + stats_param.num_mib_stats, + stats_param.num_mib_extd_stats, + stats_param.num_bcnflt_stats, + stats_param.num_chan_stats, + stats_param.num_bcn_stats, + stats_param.num_peer_adv_stats, stats_param.last_event); + ev->last_event = stats_param.last_event; status = target_if_cp_stats_extract_pdev_stats(wmi_hdl, &stats_param, ev, data); @@ -415,6 +481,12 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl, if (QDF_IS_STATUS_ERROR(status)) return status; + status = target_if_cp_stats_extract_mib_stats(wmi_hdl, + &stats_param, + ev, data); + if (QDF_IS_STATUS_ERROR(status)) + return status; + return QDF_STATUS_SUCCESS; } @@ -616,6 +688,8 @@ static uint32_t get_stats_id(enum stats_req_type type) WMI_REQUEST_PDEV_STAT | WMI_REQUEST_PEER_EXTD2_STAT | WMI_REQUEST_RSSI_PER_CHAIN_STAT); + case TYPE_MIB_STATS: + return (WMI_REQUEST_MIB_STAT | WMI_REQUEST_MIB_EXTD_STAT); } return 0; diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/crypto/src/target_if_crypto.c b/drivers/staging/qca-wifi-host-cmn/target_if/crypto/src/target_if_crypto.c index c09d073533bc636fe1c8caeb1a0e495b619561b2..53fc94a5f2515e45da3ea7ecde531c4a599949a6 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/crypto/src/target_if_crypto.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/crypto/src/target_if_crypto.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-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 @@ -34,9 +34,56 @@ #include #include #include +#include #include +#include +#include +#include "wlan_crypto_def_i.h" +#include "wlan_crypto_obj_mgr_i.h" #ifdef FEATURE_WLAN_WAPI +#ifdef FEATURE_WAPI_BIG_ENDIAN +/* + * All lithium firmware expects WAPI in big endian + * format , whereas helium firmware's expect otherwise + */ + +static void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev, + bool pairwise, + enum wlan_crypto_cipher_type cipher_type, + struct set_key_params *params) +{ + static const unsigned char tx_iv[16] = {0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x36, 0x5c, 0x36, 0x5c, 0x36, + 0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x36}; + + static const unsigned char rx_iv[16] = {0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x36, 0x5c, 0x36, 0x5c, 0x36, + 0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x37}; + + if (cipher_type != WLAN_CRYPTO_CIPHER_WAPI_SMS4 && + cipher_type != WLAN_CRYPTO_CIPHER_WAPI_GCM4) + return; + + if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE || + vdev->vdev_mlme.vdev_opmode == QDF_P2P_GO_MODE) { + qdf_mem_copy(¶ms->rx_iv, &tx_iv, + WLAN_CRYPTO_WAPI_IV_SIZE); + qdf_mem_copy(params->tx_iv, &rx_iv, + WLAN_CRYPTO_WAPI_IV_SIZE); + } else { + qdf_mem_copy(params->rx_iv, &rx_iv, + WLAN_CRYPTO_WAPI_IV_SIZE); + qdf_mem_copy(params->tx_iv, &tx_iv, + WLAN_CRYPTO_WAPI_IV_SIZE); + } + + params->key_txmic_len = WLAN_CRYPTO_MIC_LEN; + params->key_rxmic_len = WLAN_CRYPTO_MIC_LEN; +} +#else static void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev, bool pairwise, enum wlan_crypto_cipher_type cipher_type, @@ -74,6 +121,7 @@ static void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev, params->key_txmic_len = WLAN_CRYPTO_MIC_LEN; params->key_rxmic_len = WLAN_CRYPTO_MIC_LEN; } +#endif /* FEATURE_WAPI_BIG_ENDIAN */ #else static inline void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev, bool pairwise, @@ -112,13 +160,10 @@ QDF_STATUS target_if_crypto_set_key(struct wlan_objmgr_vdev *vdev, struct wlan_objmgr_pdev *pdev; enum cdp_sec_type sec_type = cdp_sec_type_none; void *soc = cds_get_context(QDF_MODULE_ID_SOC); - struct cdp_pdev *txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX); - struct cdp_vdev *txrx_vdev; uint32_t pn[4] = {0, 0, 0, 0}; - struct cdp_peer *peer = NULL; - uint8_t peer_id; + bool peer_exist = false; uint8_t def_tx_idx; - void *pdev_wmi_handle; + wmi_unified_t pdev_wmi_handle; bool pairwise; QDF_STATUS status; @@ -157,21 +202,15 @@ QDF_STATUS target_if_crypto_set_key(struct wlan_objmgr_vdev *vdev, } qdf_mem_copy(¶ms.key_rsc_ctr, &req->keyrsc[0], sizeof(uint64_t)); - txrx_vdev = (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc, - (struct cdp_pdev *)txrx_pdev, params.vdev_id); - peer = cdp_peer_find_by_addr(soc, txrx_pdev, req->macaddr, &peer_id); - - if (!txrx_vdev) { - target_if_err("Invalid txrx vdev"); - return QDF_STATUS_E_FAILURE; - } + peer_exist = cdp_find_peer_exist(soc, pdev->pdev_objmgr.wlan_pdev_id, + req->macaddr); target_if_debug("key_type %d, mac: %02x:%02x:%02x:%02x:%02x:%02x", key_type, req->macaddr[0], req->macaddr[1], req->macaddr[2], req->macaddr[3], req->macaddr[4], req->macaddr[5]); - if ((key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) && !peer) { + if ((key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) && !peer_exist) { target_if_err("Invalid peer"); return QDF_STATUS_E_FAILURE; } @@ -203,27 +242,152 @@ QDF_STATUS target_if_crypto_set_key(struct wlan_objmgr_vdev *vdev, &req->keyval[0], req->keylen); params.key_len = req->keylen; - if (peer) { - /* Set PN check & security type in data path */ - qdf_mem_copy(&pn[0], ¶ms.key_rsc_ctr, sizeof(pn)); - cdp_set_pn_check(soc, txrx_vdev, peer, sec_type, pn); - cdp_set_key_sec_type(soc, txrx_vdev, peer, sec_type, pairwise); - cdp_set_key(soc, peer, pairwise, (uint32_t *)(req->keyval + - WLAN_CRYPTO_IV_SIZE + WLAN_CRYPTO_MIC_LEN)); - } else { - target_if_info("peer not found"); - } + + /* Set PN check & security type in data path */ + qdf_mem_copy(&pn[0], ¶ms.key_rsc_ctr, sizeof(pn)); + cdp_set_pn_check(soc, vdev->vdev_objmgr.vdev_id, req->macaddr, + sec_type, pn); + + cdp_set_key_sec_type(soc, vdev->vdev_objmgr.vdev_id, req->macaddr, + sec_type, pairwise); + + cdp_set_key(soc, vdev->vdev_objmgr.vdev_id, req->macaddr, pairwise, + (uint32_t *)(req->keyval + WLAN_CRYPTO_IV_SIZE + + WLAN_CRYPTO_MIC_LEN)); target_if_debug("vdev_id:%d, key: idx:%d,len:%d", params.vdev_id, params.key_idx, params.key_len); - target_if_debug("peer mac %pM", params.peer_mac); + target_if_debug("peer mac "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(params.peer_mac)); QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_DEBUG, ¶ms.key_rsc_ctr, sizeof(uint64_t)); status = wmi_unified_setup_install_key_cmd(pdev_wmi_handle, ¶ms); + /* Zero-out local key variables */ + qdf_mem_zero(¶ms, sizeof(struct set_key_params)); + return status; } +/** + * target_if_crypto_install_key_comp_evt_handler() - install key complete + * handler + * @handle: wma handle + * @event: event data + * @len: data length + * + * This event is sent by fw once WPA/WPA2 keys are installed in fw. + * + * Return: 0 for success or error code + */ +static int +target_if_crypto_install_key_comp_evt_handler(void *handle, uint8_t *event, + uint32_t len) +{ + struct wlan_crypto_comp_priv *priv_obj; + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_vdev *vdev; + struct wmi_install_key_comp_event params; + QDF_STATUS status; + wmi_unified_t wmi_handle; + struct crypto_add_key_result result; + + if (!event || !handle) { + target_if_err("invalid param"); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(handle); + if (!psoc) { + target_if_err("psoc is null"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("invalid wmi handle"); + return -EINVAL; + } + + status = wmi_extract_install_key_comp_event(wmi_handle, event, + len, ¶ms); + if (QDF_IS_STATUS_ERROR(status)) { + target_if_err("received invalid buf from target"); + return -EINVAL; + } + + target_if_debug("vdev %d mac " QDF_MAC_ADDR_FMT " ix %x flags %x status %d", + params.vdev_id, + QDF_MAC_ADDR_REF(params.peer_macaddr), + params.key_ix, params.key_flags, params.status); + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, params.vdev_id, + WLAN_CRYPTO_ID); + if (!vdev) { + target_if_err("vdev %d is null", params.vdev_id); + return -EINVAL; + } + + priv_obj = wlan_get_vdev_crypto_obj(vdev); + if (!priv_obj) { + target_if_err("priv_obj is null"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID); + return -EINVAL; + } + + result.vdev_id = params.vdev_id; + result.key_ix = params.key_ix; + result.key_flags = params.key_flags; + result.status = params.status; + qdf_mem_copy(result.peer_macaddr, params.peer_macaddr, + QDF_MAC_ADDR_SIZE); + + if (priv_obj->add_key_cb) + priv_obj->add_key_cb(priv_obj->add_key_ctx, &result); + + wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID); + + return 0; +} + +static QDF_STATUS +target_if_crypto_register_events(struct wlan_objmgr_psoc *psoc) +{ + QDF_STATUS status; + + if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { + target_if_err("psoc or psoc->tgt_if_handle is null"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_register_event_handler( + get_wmi_unified_hdl_from_psoc(psoc), + wmi_vdev_install_key_complete_event_id, + target_if_crypto_install_key_comp_evt_handler, + WMI_RX_WORK_CTX); + if (QDF_IS_STATUS_ERROR(status)) { + target_if_err("register_event_handler failed: err %d", status); + return status; + } + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS +target_if_crypto_deregister_events(struct wlan_objmgr_psoc *psoc) +{ + if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) { + target_if_err("psoc or psoc->tgt_if_handle is null"); + return QDF_STATUS_E_INVAL; + } + + wmi_unified_unregister_event_handler( + get_wmi_unified_hdl_from_psoc(psoc), + wmi_vdev_install_key_complete_event_id); + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS target_if_crypto_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) { struct wlan_lmac_if_crypto_tx_ops *crypto; @@ -235,6 +399,8 @@ QDF_STATUS target_if_crypto_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) crypto = &tx_ops->crypto_tx_ops; crypto->set_key = target_if_crypto_set_key; + crypto->register_events = target_if_crypto_register_events; + crypto->deregister_events = target_if_crypto_deregister_events; return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/dfs/inc/target_if_dfs_full_offload.h b/drivers/staging/qca-wifi-host-cmn/target_if/dfs/inc/target_if_dfs_full_offload.h index 624aaf57b244ce157d6f2a3a5645ac716f9eda85..513b8413d9873c696d3a1a9fc244beb20daab493 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/dfs/inc/target_if_dfs_full_offload.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/dfs/inc/target_if_dfs_full_offload.h @@ -70,14 +70,16 @@ static QDF_STATUS target_process_bang_radar_cmd(struct wlan_objmgr_pdev *pdev, */ QDF_STATUS target_send_ocac_abort_cmd(struct wlan_objmgr_pdev *pdev); /** - * target_send_agile_ch_cfg_cmd() - Send agile channel to target for + * target_send_agile_ch_cfg_cmd() - Send agile channel parameters to target for * off channel precac. * @pdev: Pointer to DFS pdev object. + * @adfs_param: Agile-DFS CAC parameters. * * Return: QDF_STATUS */ -QDF_STATUS target_send_agile_ch_cfg_cmd(struct wlan_objmgr_pdev *pdev, - uint8_t *ch_freq); +QDF_STATUS +target_send_agile_ch_cfg_cmd(struct wlan_objmgr_pdev *pdev, + struct dfs_agile_cac_params *adfs_param); #else static inline QDF_STATUS target_send_ocac_abort_cmd(struct wlan_objmgr_pdev *pdev) @@ -87,7 +89,7 @@ target_send_ocac_abort_cmd(struct wlan_objmgr_pdev *pdev) static inline QDF_STATUS target_send_agile_ch_cfg_cmd(struct wlan_objmgr_pdev *pdev, - uint8_t *ch_freq) + struct dfs_agile_cac_params *adfs_param) { return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/dfs/src/target_if_dfs.c b/drivers/staging/qca-wifi-host-cmn/target_if/dfs/src/target_if_dfs.c index f4be0611537fdb642b1bc16d10063e42fa2947b5..e040aea2bcecf8020ab724f3e0e2d1baa26091c0 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/dfs/src/target_if_dfs.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/dfs/src/target_if_dfs.c @@ -213,6 +213,27 @@ static bool target_if_dfs_offload(struct wlan_objmgr_psoc *psoc) wmi_service_dfs_phyerr_offload); } +static QDF_STATUS target_if_dfs_get_target_type(struct wlan_objmgr_pdev *pdev, + uint32_t *target_type) +{ + struct wlan_objmgr_psoc *psoc; + struct target_psoc_info *tgt_psoc_info; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + target_if_err("null psoc"); + return QDF_STATUS_E_FAILURE; + } + + tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); + if (!tgt_psoc_info) { + target_if_err("null tgt_psoc_info"); + return QDF_STATUS_E_FAILURE; + } + *target_type = target_psoc_get_target_type(tgt_psoc_info); + return QDF_STATUS_SUCCESS; +} + static QDF_STATUS target_if_dfs_register_event_handler( struct wlan_objmgr_psoc *psoc) { @@ -285,7 +306,7 @@ static QDF_STATUS target_if_dfs_set_phyerr_filter_offload( bool dfs_phyerr_filter_offload) { QDF_STATUS status; - void *wmi_handle; + wmi_unified_t wmi_handle; if (!pdev) { target_if_err("null pdev"); @@ -386,5 +407,6 @@ QDF_STATUS target_if_register_dfs_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) &target_send_usenol_pdev_param; dfs_tx_ops->dfs_send_subchan_marking_pdev_param = &target_send_subchan_marking_pdev_param; + dfs_tx_ops->dfs_get_target_type = &target_if_dfs_get_target_type; return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/dfs/src/target_if_dfs_full_offload.c b/drivers/staging/qca-wifi-host-cmn/target_if/dfs/src/target_if_dfs_full_offload.c index eab31e2d2f409e185bddd91788d2b9a3a48e31ea..9c29ce31cb02cd6f71deeb9a30e4d8ac5107d6ac 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/dfs/src/target_if_dfs_full_offload.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/dfs/src/target_if_dfs_full_offload.c @@ -344,7 +344,7 @@ QDF_STATUS target_send_ocac_abort_cmd(struct wlan_objmgr_pdev *pdev) } QDF_STATUS target_send_agile_ch_cfg_cmd(struct wlan_objmgr_pdev *pdev, - uint8_t *ch_freq) + struct dfs_agile_cac_params *adfs_param) { wmi_unified_t wmi_handle; struct vdev_adfs_ch_cfg_params param; @@ -373,11 +373,11 @@ QDF_STATUS target_send_agile_ch_cfg_cmd(struct wlan_objmgr_pdev *pdev, qdf_mem_set(¶m, sizeof(param), 0); param.vdev_id = wlan_vdev_get_id(vdev); param.ocac_mode = QUICK_OCAC_MODE; - param.min_duration_ms = 60000; - param.max_duration_ms = 0; - param.chan_freq = *ch_freq; - param.chan_width = wlan_vdev_get_ch_width(vdev); - param.center_freq = *ch_freq; + param.min_duration_ms = adfs_param->min_precac_timeout; + param.max_duration_ms = adfs_param->max_precac_timeout; + param.chan_freq = adfs_param->precac_chan; + param.chan_width = adfs_param->precac_chwidth; + param.center_freq = adfs_param->precac_chan; status = wmi_unified_send_vdev_adfs_ch_cfg_cmd(wmi_handle, ¶m); if (QDF_IS_STATUS_ERROR(status)) @@ -390,7 +390,7 @@ QDF_STATUS target_send_agile_ch_cfg_cmd(struct wlan_objmgr_pdev *pdev, } #endif -#if (defined(CONFIG_MCL) || defined(QCA_WIFI_QCA8074) || \ +#if (defined(WLAN_DFS_FULL_OFFLOAD) || defined(QCA_WIFI_QCA8074) || \ defined(QCA_WIFI_QCA6018)) QDF_STATUS target_process_bang_radar_cmd( struct wlan_objmgr_pdev *pdev, diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/inc/target_if_direct_buf_rx_api.h b/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/inc/target_if_direct_buf_rx_api.h index 6df48d23d5e4adf4de21d247dfc692c90982b248..10882f2f2c2c0e99384ccb923d9631a3858e07b7 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/inc/target_if_direct_buf_rx_api.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/inc/target_if_direct_buf_rx_api.h @@ -23,6 +23,13 @@ #include "qdf_atomic.h" #include "wmi_unified_api.h" +#ifdef WLAN_DEBUGFS +#ifdef DIRECT_BUF_RX_DEBUG +/* Base debugfs entry for DBR module */ +extern qdf_dentry_t dbr_debugfs_entry; +#endif /* DIRECT_BUF_RX_DEBUG */ +#endif /* WLAN_DEBUGFS */ + #define direct_buf_rx_alert(params...) \ QDF_TRACE_FATAL(QDF_MODULE_ID_DIRECT_BUF_RX, params) #define direct_buf_rx_err(params...) \ diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_api.c b/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_api.c index 0a882c617c40543a3526f035ce06f3c902866abf..cf9e7eabf233e643347292d11ad8cca6675aff51 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_api.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_api.c @@ -25,6 +25,39 @@ #include "target_if_direct_buf_rx_main.h" #include +#if defined(WLAN_DEBUGFS) && defined(DIRECT_BUF_RX_DEBUG) +/* Base debugfs entry for DBR module */ +qdf_dentry_t dbr_debugfs_entry; + +static inline void +target_if_direct_buf_rx_debugfs_init(void) +{ + dbr_debugfs_entry = qdf_debugfs_create_dir("dbr_ring_debug", NULL); + + if (!dbr_debugfs_entry) + direct_buf_rx_err("error while creating direct_buf rx debugfs dir"); +} + +static inline void +target_if_direct_buf_rx_debugfs_deinit(void) +{ + if (dbr_debugfs_entry) { + qdf_debugfs_remove_dir_recursive(dbr_debugfs_entry); + dbr_debugfs_entry = NULL; + } +} +#else +static inline void +target_if_direct_buf_rx_debugfs_init(void) +{ +} + +static inline void +target_if_direct_buf_rx_debugfs_deinit(void) +{ +} +#endif /* WLAN_DEBUGFS && DIRECT_BUF_RX_DEBUG */ + QDF_STATUS direct_buf_rx_init(void) { QDF_STATUS status; @@ -69,6 +102,8 @@ QDF_STATUS direct_buf_rx_init(void) goto dbr_unreg_pdev_create; } + target_if_direct_buf_rx_debugfs_init(); + direct_buf_rx_info("Direct Buffer RX pdev,psoc create and destroy handlers registered"); return QDF_STATUS_SUCCESS; @@ -99,6 +134,8 @@ QDF_STATUS direct_buf_rx_deinit(void) { QDF_STATUS status; + target_if_direct_buf_rx_debugfs_deinit(); + status = wlan_objmgr_unregister_pdev_destroy_handler( WLAN_TARGET_IF_COMP_DIRECT_BUF_RX, target_if_direct_buf_rx_pdev_destroy_handler, @@ -163,6 +200,28 @@ QDF_STATUS direct_buf_rx_target_attach(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +#ifdef DIRECT_BUF_RX_DEBUG +static inline void +target_if_direct_buf_rx_debug_register_tx_ops( + struct wlan_lmac_if_tx_ops *tx_ops) +{ + tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug = + target_if_dbr_start_ring_debug; + tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug = + target_if_dbr_stop_ring_debug; + tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning = + target_if_dbr_start_buffer_poisoning; + tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning = + target_if_dbr_stop_buffer_poisoning; +} +#else +static inline void +target_if_direct_buf_rx_debug_register_tx_ops( + struct wlan_lmac_if_tx_ops *tx_ops) +{ +} +#endif /* DIRECT_BUF_RX_DEBUG */ + void target_if_direct_buf_rx_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) { tx_ops->dbr_tx_ops.direct_buf_rx_module_register = @@ -177,5 +236,6 @@ void target_if_direct_buf_rx_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) target_if_direct_buf_rx_print_ring_stat; tx_ops->dbr_tx_ops.direct_buf_rx_get_ring_params = target_if_direct_buf_rx_get_ring_params; + target_if_direct_buf_rx_debug_register_tx_ops(tx_ops); } qdf_export_symbol(target_if_direct_buf_rx_register_tx_ops); diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c b/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c index c0b0f5da63edfc34353ad78a0d417ef27b1490b7..516f4b3002d2af1f5e961eb46d43d324538cf343 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -43,7 +43,6 @@ static uint8_t get_num_dbr_modules_per_pdev(struct wlan_objmgr_pdev *pdev) struct wlan_psoc_host_dbr_ring_caps *dbr_ring_cap; uint8_t num_dbr_ring_caps, cap_idx, pdev_id, num_modules; struct target_psoc_info *tgt_psoc_info; - struct wlan_psoc_host_service_ext_param *ext_svc_param; psoc = wlan_pdev_get_psoc(pdev); @@ -57,8 +56,7 @@ static uint8_t get_num_dbr_modules_per_pdev(struct wlan_objmgr_pdev *pdev) direct_buf_rx_err("target_psoc_info is null"); return 0; } - ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); - num_dbr_ring_caps = ext_svc_param->num_dbr_ring_caps; + num_dbr_ring_caps = target_psoc_get_num_dbr_ring_caps(tgt_psoc_info); dbr_ring_cap = target_psoc_get_dbr_ring_caps(tgt_psoc_info); pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); num_modules = 0; @@ -81,7 +79,6 @@ static QDF_STATUS populate_dbr_cap_mod_param(struct wlan_objmgr_pdev *pdev, enum DBR_MODULE mod_id = mod_param->mod_id; uint32_t num_dbr_ring_caps, pdev_id; struct target_psoc_info *tgt_psoc_info; - struct wlan_psoc_host_service_ext_param *ext_svc_param; psoc = wlan_pdev_get_psoc(pdev); @@ -96,8 +93,7 @@ static QDF_STATUS populate_dbr_cap_mod_param(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_E_INVAL; } - ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); - num_dbr_ring_caps = ext_svc_param->num_dbr_ring_caps; + num_dbr_ring_caps = target_psoc_get_num_dbr_ring_caps(tgt_psoc_info); dbr_ring_cap = target_psoc_get_dbr_ring_caps(tgt_psoc_info); pdev_id = mod_param->pdev_id; @@ -123,11 +119,242 @@ static QDF_STATUS populate_dbr_cap_mod_param(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } +#ifdef DIRECT_BUF_RX_DEBUG +static inline struct direct_buf_rx_module_debug * +target_if_get_dbr_mod_debug_from_dbr_pdev_obj( + struct direct_buf_rx_pdev_obj *dbr_pdev_obj, + uint8_t mod_id) +{ + if (!dbr_pdev_obj) { + direct_buf_rx_err("dir buf rx object is null"); + return NULL; + } + + if (mod_id >= DBR_MODULE_MAX) { + direct_buf_rx_err("Invalid module id"); + return NULL; + } + + if (!dbr_pdev_obj->dbr_mod_debug) { + direct_buf_rx_err("dbr_pdev_obj->dbr_mod_debug is NULL"); + return NULL; + } + + if (mod_id >= dbr_pdev_obj->num_modules) { + direct_buf_rx_err("Module %d not supported in target", mod_id); + return NULL; + } + return &dbr_pdev_obj->dbr_mod_debug[mod_id]; +} + +static inline struct direct_buf_rx_module_debug * +target_if_get_dbr_mod_debug_from_pdev( + struct wlan_objmgr_pdev *pdev, + uint8_t mod_id) +{ + struct direct_buf_rx_pdev_obj *dbr_pdev_obj; + + if (!pdev) { + direct_buf_rx_err("pdev is null"); + return NULL; + } + + dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj( + pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); + + return target_if_get_dbr_mod_debug_from_dbr_pdev_obj( + dbr_pdev_obj, mod_id); +} +#endif + +#ifdef DIRECT_BUF_RX_DEBUG +#define RING_DEBUG_EVENT_NAME_SIZE 12 +static const unsigned char +g_dbr_ring_debug_event[DBR_RING_DEBUG_EVENT_MAX][RING_DEBUG_EVENT_NAME_SIZE] = { + [DBR_RING_DEBUG_EVENT_RX] = "Rx", + [DBR_RING_DEBUG_EVENT_REPLENISH_RING] = "Replenish", +}; + +/** + * target_if_dbr_print_ring_debug_entries() - Print ring debug entries + * @print: The print adapter function + * @print_priv: The private data to be consumed by @print + * @dbr_pdev_obj: Pdev object of the DBR module + * @mod_id: Module ID + * + * Print ring debug entries of the ring identified by @dbr_pdev_obj and @mod_id + * using the given print adapter function + * + * Return: QDF_STATUS of operation + */ +static QDF_STATUS target_if_dbr_print_ring_debug_entries( + qdf_abstract_print print, void *print_priv, + struct direct_buf_rx_pdev_obj *dbr_pdev_obj, + uint8_t mod_id, uint8_t srng_id) +{ + struct direct_buf_rx_module_debug *mod_debug; + struct direct_buf_rx_ring_debug *ring_debug; + int idx; + + mod_debug = target_if_get_dbr_mod_debug_from_dbr_pdev_obj(dbr_pdev_obj, + mod_id); + if (!mod_debug) + return QDF_STATUS_E_INVAL; + + mod_debug = &dbr_pdev_obj->dbr_mod_debug[mod_id]; + ring_debug = &mod_debug->dbr_ring_debug[srng_id]; + + if (ring_debug->entries) { + print(print_priv, "Current debug entry is %d", + ring_debug->ring_debug_idx); + print(print_priv, "---------------------------------------------------------"); + print(print_priv, "| Number | Head Idx | Tail Idx | Timestamp | event |"); + print(print_priv, "---------------------------------------------------------"); + for (idx = 0; idx < ring_debug->num_ring_debug_entries; ++idx) { + print(print_priv, "|%8u|%10u|%10u|%11llu|%12s|", idx, + ring_debug->entries[idx].head_idx, + ring_debug->entries[idx].tail_idx, + ring_debug->entries[idx].timestamp, + g_dbr_ring_debug_event[ + ring_debug->entries[idx].event]); + } + print(print_priv, "---------------------------------------------------------"); + } + + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_dbr_qdf_err_printer() - QDF error level printer for DBR module + * @print_priv: The private data + * @fmt: Format string + * + * This function should be passed in place of the 'print' argument to + * target_if_dbr_print_ring_debug_entries function for the logs that should be + * printed via QDF trace + * + * Return: QDF_STATUS of operation + */ +static int target_if_dbr_qdf_err_printer(void *priv, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + QDF_VTRACE(QDF_MODULE_ID_DIRECT_BUF_RX, QDF_TRACE_LEVEL_ERROR, + (char *)fmt, args); + va_end(args); + + return 0; +} + +static inline void target_if_direct_buf_rx_free_mod_debug( + struct direct_buf_rx_pdev_obj *dbr_pdev_obj) +{ + if (!dbr_pdev_obj) { + direct_buf_rx_err("dir buf rx object is null"); + return; + } + /* Free the debug data structures of all modules */ + if (dbr_pdev_obj->dbr_mod_debug) { + qdf_mem_free(dbr_pdev_obj->dbr_mod_debug); + dbr_pdev_obj->dbr_mod_debug = NULL; + } +} + +static inline QDF_STATUS target_if_direct_buf_rx_alloc_mod_debug( + struct direct_buf_rx_pdev_obj *dbr_pdev_obj) +{ + if (!dbr_pdev_obj) { + direct_buf_rx_err("dir buf rx object is null"); + return QDF_STATUS_E_FAILURE; + } + /* Allocate the debug data structure for each module */ + dbr_pdev_obj->dbr_mod_debug = qdf_mem_malloc( + dbr_pdev_obj->num_modules * + sizeof(struct direct_buf_rx_module_debug)); + + if (!dbr_pdev_obj->dbr_mod_debug) + return QDF_STATUS_E_NOMEM; + + return QDF_STATUS_SUCCESS; +} +#else +static inline QDF_STATUS target_if_direct_buf_rx_alloc_mod_debug( + struct direct_buf_rx_pdev_obj *dbr_pdev_obj) +{ + return QDF_STATUS_SUCCESS; +} + +static inline void target_if_direct_buf_rx_free_mod_debug( + struct direct_buf_rx_pdev_obj *dbr_pdev_obj) +{ +} +#endif + +#if defined(WLAN_DEBUGFS) && defined(DIRECT_BUF_RX_DEBUG) +static inline void target_if_direct_buf_pdev_debugfs_init( + struct wlan_objmgr_pdev *pdev) +{ + char dir_name[32]; + struct wlan_objmgr_psoc *psoc; + struct direct_buf_rx_pdev_obj *dbr_pdev_obj; + + if (!pdev) { + direct_buf_rx_err("pdev is null"); + return; + } + + psoc = wlan_pdev_get_psoc(pdev); + dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj( + pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); + + if (!dbr_pdev_obj) { + direct_buf_rx_err("dir buf rx object is null"); + return; + } + + qdf_snprintf(dir_name, sizeof(dir_name), "SOC%u_PDEV%u", + wlan_psoc_get_id(psoc), + wlan_objmgr_pdev_get_pdev_id(pdev)); + + /* Create debugfs entry for this radio */ + dbr_pdev_obj->debugfs_entry = qdf_debugfs_create_dir( + dir_name, dbr_debugfs_entry); + + if (!dbr_pdev_obj->debugfs_entry) + direct_buf_rx_err("error while creating direct_buf debugfs dir"); +} + +static inline void target_if_direct_buf_pdev_debugfs_deinit( + struct direct_buf_rx_pdev_obj *dbr_pdev_obj) +{ + if (!dbr_pdev_obj) { + direct_buf_rx_err("dir buf rx object is null"); + return; + } + /* Remove the debugfs entry of the radio */ + if (dbr_pdev_obj->debugfs_entry) { + qdf_debugfs_remove_dir_recursive(dbr_pdev_obj->debugfs_entry); + dbr_pdev_obj->debugfs_entry = NULL; + } +} +#else +static inline void target_if_direct_buf_pdev_debugfs_init( + struct wlan_objmgr_pdev *pdev) +{ +} + +static inline void target_if_direct_buf_pdev_debugfs_deinit( + struct direct_buf_rx_pdev_obj *dbr_pdev_obj) +{ +} +#endif /* WLAN_DEBUGFS && DIRECT_BUF_RX_DEBUG */ QDF_STATUS target_if_direct_buf_rx_pdev_create_handler( struct wlan_objmgr_pdev *pdev, void *data) { struct direct_buf_rx_pdev_obj *dbr_pdev_obj; + struct direct_buf_rx_psoc_obj *dbr_psoc_obj; struct wlan_objmgr_psoc *psoc; uint8_t num_modules; QDF_STATUS status; @@ -146,13 +373,20 @@ QDF_STATUS target_if_direct_buf_rx_pdev_create_handler( return QDF_STATUS_E_INVAL; } + dbr_psoc_obj = + wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); + + if (!dbr_psoc_obj) { + direct_buf_rx_err("dir buf rx psoc object is null"); + return QDF_STATUS_E_FAILURE; + } + dbr_pdev_obj = qdf_mem_malloc(sizeof(*dbr_pdev_obj)); if (!dbr_pdev_obj) return QDF_STATUS_E_NOMEM; - direct_buf_rx_info("Dbr pdev obj %pK", dbr_pdev_obj); - status = wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX, dbr_pdev_obj, QDF_STATUS_SUCCESS); @@ -164,6 +398,9 @@ QDF_STATUS target_if_direct_buf_rx_pdev_create_handler( return status; } + dbr_psoc_obj->dbr_pdev_obj[wlan_objmgr_pdev_get_pdev_id(pdev)] = + dbr_pdev_obj; + num_modules = get_num_dbr_modules_per_pdev(pdev); direct_buf_rx_debug("Number of modules = %d pdev %d DBR pdev obj %pK", num_modules, wlan_objmgr_pdev_get_pdev_id(pdev), @@ -181,15 +418,28 @@ QDF_STATUS target_if_direct_buf_rx_pdev_create_handler( sizeof(struct direct_buf_rx_module_param)); if (!dbr_pdev_obj->dbr_mod_param) { - direct_buf_rx_err("alloc dbr mod param fail"); - wlan_objmgr_pdev_component_obj_detach(pdev, - WLAN_TARGET_IF_COMP_DIRECT_BUF_RX, - dbr_pdev_obj); - qdf_mem_free(dbr_pdev_obj); - return QDF_STATUS_E_NOMEM; + direct_buf_rx_err("alloc dbr mod param fail"); + goto dbr_mod_param_fail; } + if (target_if_direct_buf_rx_alloc_mod_debug(dbr_pdev_obj) != + QDF_STATUS_SUCCESS) + goto dbr_mod_debug_fail; + + target_if_direct_buf_pdev_debugfs_init(pdev); + return QDF_STATUS_SUCCESS; + +dbr_mod_debug_fail: + qdf_mem_free(dbr_pdev_obj->dbr_mod_param); + +dbr_mod_param_fail: + wlan_objmgr_pdev_component_obj_detach( + pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX, + dbr_pdev_obj); + qdf_mem_free(dbr_pdev_obj); + + return QDF_STATUS_E_NOMEM; } QDF_STATUS target_if_direct_buf_rx_pdev_destroy_handler( @@ -214,11 +464,19 @@ QDF_STATUS target_if_direct_buf_rx_pdev_destroy_handler( num_modules = dbr_pdev_obj->num_modules; for (mod_idx = 0; mod_idx < num_modules; mod_idx++) { + /* + * If the module didn't stop the ring debug by this time, + * it will result in memory leak of its ring debug entries. + * So, stop the ring debug + */ + target_if_dbr_stop_ring_debug(pdev, mod_idx); for (srng_id = 0; srng_id < DBR_SRNG_NUM; srng_id++) target_if_deinit_dbr_ring(pdev, dbr_pdev_obj, mod_idx, srng_id); } + target_if_direct_buf_pdev_debugfs_deinit(dbr_pdev_obj); + target_if_direct_buf_rx_free_mod_debug(dbr_pdev_obj); qdf_mem_free(dbr_pdev_obj->dbr_mod_param); dbr_pdev_obj->dbr_mod_param = NULL; @@ -304,6 +562,442 @@ QDF_STATUS target_if_direct_buf_rx_psoc_destroy_handler( return status; } +#if defined(WLAN_DEBUGFS) && defined(DIRECT_BUF_RX_DEBUG) +/** + * target_if_dbr_debugfs_show_ring_debug() - Function to display ring debug + * entries in debugfs + * @file: qdf debugfs file handler + * @arg: pointer to DBR debugfs private object + * + * Return: QDF_STATUS of operation + */ +static QDF_STATUS target_if_dbr_debugfs_show_ring_debug( + qdf_debugfs_file_t file, void *arg) +{ + struct dbr_debugfs_priv *priv = arg; + + return target_if_dbr_print_ring_debug_entries(qdf_debugfs_printer, + file, priv->dbr_pdev_obj, + priv->mod_id, + priv->srng_id); +} + +/** + * target_if_dbr_mod_debugfs_init() - Init debugfs for a given module + * @dbr_pdev_obj: Pointer to the pdev obj of Direct buffer rx module + * @mod_id: Module ID corresponding to this ring + * + * Return: QDF_STATUS of operation + */ +static QDF_STATUS target_if_dbr_mod_debugfs_init( + struct direct_buf_rx_pdev_obj *dbr_pdev_obj, + enum DBR_MODULE mod_id) +{ + struct direct_buf_rx_module_debug *mod_debug; + + mod_debug = target_if_get_dbr_mod_debug_from_dbr_pdev_obj(dbr_pdev_obj, + mod_id); + + if (!mod_debug) + return QDF_STATUS_E_INVAL; + + if (mod_debug->debugfs_entry) { + direct_buf_rx_err("debugfs mod entry was already created for %s module", + g_dbr_module_name[mod_id].module_name_str); + return QDF_STATUS_SUCCESS; + } + + mod_debug->debugfs_entry = + qdf_debugfs_create_dir(g_dbr_module_name[mod_id].module_name_str, + dbr_pdev_obj->debugfs_entry); + + if (!mod_debug->debugfs_entry) { + direct_buf_rx_err("error while creating direct_buf debugfs entry for %s module", + g_dbr_module_name[mod_id].module_name_str); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_dbr_ring_debugfs_init() - Init debugfs for a given ring + * @dbr_pdev_obj: Pointer to the pdev obj of Direct buffer rx module + * @mod_id: Module ID corresponding to this ring + * @srng_id: srng ID corresponding to this ring + * + * Return: QDF_STATUS of operation + */ +static QDF_STATUS target_if_dbr_ring_debugfs_init( + struct direct_buf_rx_pdev_obj *dbr_pdev_obj, + enum DBR_MODULE mod_id, uint8_t srng_id) +{ + struct direct_buf_rx_module_debug *mod_debug; + struct direct_buf_rx_ring_debug *ring_debug; + struct dbr_debugfs_priv *priv; + char debug_file_name[32]; + + mod_debug = target_if_get_dbr_mod_debug_from_dbr_pdev_obj(dbr_pdev_obj, + mod_id); + + if (!mod_debug) + return QDF_STATUS_E_INVAL; + + ring_debug = &mod_debug->dbr_ring_debug[srng_id]; + + if (!mod_debug->debugfs_entry) { + direct_buf_rx_err("error mod_debug->debugfs_entry not created"); + return QDF_STATUS_E_FAILURE; + } + + if (ring_debug->debugfs_entry) { + direct_buf_rx_err("debugfs file for %d ring under %s module already created", + srng_id, + g_dbr_module_name[mod_id].module_name_str); + return QDF_STATUS_SUCCESS; + } + + qdf_snprintf(debug_file_name, sizeof(debug_file_name), + "ring_%d", srng_id); + + // Allocate debugfs ops + ring_debug->debugfs_fops = + qdf_mem_malloc(sizeof(*ring_debug->debugfs_fops)); + if (!ring_debug->debugfs_fops) { + direct_buf_rx_err("error in allocating debugfs ops"); + return QDF_STATUS_E_NOMEM; + } + + // Allocate private data + priv = qdf_mem_malloc(sizeof(*priv)); + if (!priv) { + direct_buf_rx_err("error in creating debugfs private data"); + goto priv_alloc_fail; + } + priv->dbr_pdev_obj = dbr_pdev_obj; + priv->mod_id = mod_id; + priv->srng_id = srng_id; + + /* Fill in the debugfs ops for this ring. + * When the output time comes, the 'show' function will be + * called with 'priv' as an argument. + */ + ring_debug->debugfs_fops->show = target_if_dbr_debugfs_show_ring_debug; + ring_debug->debugfs_fops->priv = priv; + + ring_debug->debugfs_entry = + qdf_debugfs_create_file_simplified( + debug_file_name, + (QDF_FILE_USR_READ | QDF_FILE_GRP_READ | + QDF_FILE_OTH_READ), + mod_debug->debugfs_entry, + ring_debug->debugfs_fops); + + if (!ring_debug->debugfs_entry) { + direct_buf_rx_err("error while creating direct_buf debugfs file for %d ring under %s module", + srng_id, + g_dbr_module_name[mod_id].module_name_str); + goto file_creation_fail; + } + + return QDF_STATUS_SUCCESS; + +file_creation_fail: + qdf_mem_free(ring_debug->debugfs_fops->priv); + +priv_alloc_fail: + qdf_mem_free(ring_debug->debugfs_fops); + ring_debug->debugfs_fops = NULL; + return QDF_STATUS_E_NOMEM; +} + +/** + * target_if_dbr_mod_debugfs_deinit() - De-init debugfs for a given module + * @mod_debug: Pointer to direct_buf_rx_module_debug structure + * + * Return: void + */ +static void target_if_dbr_mod_debugfs_deinit( + struct direct_buf_rx_module_debug *mod_debug) +{ + if (!mod_debug) { + direct_buf_rx_err("mod_debug is null"); + return; + } + + if (mod_debug->debugfs_entry) { + qdf_debugfs_remove_file(mod_debug->debugfs_entry); + mod_debug->debugfs_entry = NULL; + } +} + +/** + * target_if_dbr_ring_debugfs_deinit() - De-init debugfs for a given ring + * @ring_debug: Pointer to direct_buf_rx_ring_debug structure + * + * Return: void + */ +static void target_if_dbr_ring_debugfs_deinit( + struct direct_buf_rx_ring_debug *ring_debug) +{ + if (!ring_debug) { + direct_buf_rx_err("ring_debug is null"); + return; + } + + if (ring_debug->debugfs_entry) { + qdf_debugfs_remove_file(ring_debug->debugfs_entry); + ring_debug->debugfs_entry = NULL; + } + + // Free the private data and debugfs ops of this ring + if (ring_debug->debugfs_fops) { + qdf_mem_free(ring_debug->debugfs_fops->priv); + qdf_mem_free(ring_debug->debugfs_fops); + ring_debug->debugfs_fops = NULL; + } +} +#endif /* WLAN_DEBUGFS && DIRECT_BUF_RX_DEBUG */ + +#ifdef DIRECT_BUF_RX_DEBUG +QDF_STATUS target_if_dbr_stop_ring_debug(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id) +{ + struct direct_buf_rx_module_debug *mod_debug; + struct direct_buf_rx_ring_debug *ring_debug; + uint8_t srng_id; + + mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id); + if (!mod_debug) + return QDF_STATUS_E_INVAL; + + for (srng_id = 0; srng_id < DBR_SRNG_NUM; srng_id++) { + ring_debug = &mod_debug->dbr_ring_debug[srng_id]; + if (!ring_debug->entries) { + direct_buf_rx_debug("DBR ring debug for module %d srng %d was already disabled", + mod_id, srng_id); + continue; + } + /* De-init debugsfs for this ring */ + target_if_dbr_ring_debugfs_deinit(ring_debug); + qdf_mem_free(ring_debug->entries); + ring_debug->entries = NULL; + ring_debug->ring_debug_idx = 0; + ring_debug->num_ring_debug_entries = 0; + direct_buf_rx_info("DBR ring debug for module %d srng %d is now stopped", + mod_id, srng_id); + } + target_if_dbr_mod_debugfs_deinit(mod_debug); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS target_if_dbr_start_ring_debug(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, + uint32_t num_ring_debug_entries) +{ + struct direct_buf_rx_pdev_obj *dbr_pdev_obj; + struct direct_buf_rx_module_debug *mod_debug; + struct direct_buf_rx_ring_debug *ring_debug; + uint8_t srng_id; + + mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id); + + if (!mod_debug) + return QDF_STATUS_E_INVAL; + + if (num_ring_debug_entries > DIRECT_BUF_RX_MAX_RING_DEBUG_ENTRIES) { + direct_buf_rx_err("Requested number of ring debug entries(%d) exceed the maximum entries allowed(%d)", + num_ring_debug_entries, + DIRECT_BUF_RX_MAX_RING_DEBUG_ENTRIES); + + return QDF_STATUS_E_FAILURE; + } + + dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj( + pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); + + target_if_dbr_mod_debugfs_init(dbr_pdev_obj, mod_id); + + for (srng_id = 0; srng_id < DBR_SRNG_NUM; srng_id++) { + ring_debug = &mod_debug->dbr_ring_debug[srng_id]; + + if (ring_debug->entries) { + direct_buf_rx_err("DBR ring debug for module %d srng %d was already enabled", + mod_id, srng_id); + continue; + } + + ring_debug->entries = qdf_mem_malloc( + num_ring_debug_entries * + sizeof(*ring_debug->entries)); + + if (!ring_debug->entries) + return QDF_STATUS_E_NOMEM; + + ring_debug->ring_debug_idx = 0; + ring_debug->num_ring_debug_entries = num_ring_debug_entries; + /* Init debugsfs for this ring */ + target_if_dbr_ring_debugfs_init( + dbr_pdev_obj, + mod_id, srng_id); + direct_buf_rx_info("DBR ring debug for module %d srng %d is now started", + mod_id, srng_id); + } + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS target_if_dbr_start_buffer_poisoning(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, uint32_t value) +{ + struct direct_buf_rx_module_debug *mod_debug; + + mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id); + + if (!mod_debug) + return QDF_STATUS_E_INVAL; + + mod_debug->poisoning_enabled = true; + mod_debug->poison_value = value; /* Save the poison value */ + + direct_buf_rx_debug("DBR buffer poisoning for module %d is now started", + mod_id); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS target_if_dbr_stop_buffer_poisoning( + struct wlan_objmgr_pdev *pdev, + uint8_t mod_id) +{ + struct direct_buf_rx_module_debug *mod_debug; + + mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id); + + if (!mod_debug) + return QDF_STATUS_E_INVAL; + + mod_debug->poisoning_enabled = false; + mod_debug->poison_value = 0; + + direct_buf_rx_debug("DBR buffer poisoning for module %d is now stopped", + mod_id); + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_dbr_fill_buffer_u32() - Fill buffer with an unsigned 32-bit value + * @buffer: pointer to the buffer + * @num_bytes: Size of the destination buffer in bytes + * @value: Unsigned 32-bit value to be copied + * + * Return : void + */ +static void +target_if_dbr_fill_buffer_u32(uint8_t *buffer, uint32_t num_bytes, + uint32_t value) +{ + uint32_t *bufp; + uint32_t idx; + uint32_t size = (num_bytes >> 2); + + if (!buffer) { + direct_buf_rx_err("buffer empty"); + return; + } + + bufp = (uint32_t *)buffer; + + for (idx = 0; idx < size; ++idx) { + *bufp = value; + ++bufp; + } +} + +/** + * target_if_dbr_debug_poison_buffer() - Poison a given DBR buffer + * @pdev: pointer to pdev object + * @mod_id: Module ID of the owner of the buffer + * @aligned_vaddr: Virtual address(aligned) of the buffer + * @size: Size of the buffer + * + * Value with which the buffers will be poisoned would have been saved + * while starting the buffer poisoning for the module, use that value. + * + * Return : QDF status of operation + */ +static QDF_STATUS target_if_dbr_debug_poison_buffer( + struct wlan_objmgr_pdev *pdev, + uint32_t mod_id, void *aligned_vaddr, uint32_t size) +{ + struct direct_buf_rx_module_debug *mod_debug; + + mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id); + + if (!mod_debug) + return QDF_STATUS_E_INVAL; + + if (mod_debug->poisoning_enabled) { + target_if_dbr_fill_buffer_u32(aligned_vaddr, size, + mod_debug->poison_value); + } + + return QDF_STATUS_SUCCESS; +} + +static inline void target_if_dbr_qdf_show_ring_debug( + struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, uint8_t srng_id) +{ + struct direct_buf_rx_pdev_obj *dbr_pdev_obj = + wlan_objmgr_pdev_get_comp_private_obj( + pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); + + target_if_dbr_print_ring_debug_entries( + target_if_dbr_qdf_err_printer, + NULL, dbr_pdev_obj, + mod_id, srng_id); +} +#else +QDF_STATUS target_if_dbr_stop_ring_debug(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS target_if_dbr_start_ring_debug(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, + uint32_t num_ring_debug_entries) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS target_if_dbr_start_buffer_poisoning(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, uint32_t value) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS target_if_dbr_stop_buffer_poisoning( + struct wlan_objmgr_pdev *pdev, + uint8_t mod_id) +{ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS target_if_dbr_debug_poison_buffer( + struct wlan_objmgr_pdev *pdev, + uint32_t mod_id, void *aligned_vaddr, uint32_t size) +{ + return QDF_STATUS_SUCCESS; +} + +static inline void target_if_dbr_qdf_show_ring_debug( + struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, uint8_t srng_id) +{ +} +#endif /* DIRECT_BUF_RX_DEBUG */ + static QDF_STATUS target_if_dbr_replenish_ring(struct wlan_objmgr_pdev *pdev, struct direct_buf_rx_module_param *mod_param, void *aligned_vaddr, uint32_t cookie) @@ -349,6 +1043,10 @@ static QDF_STATUS target_if_dbr_replenish_ring(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } + target_if_dbr_debug_poison_buffer( + pdev, mod_param->mod_id, aligned_vaddr, + dbr_ring_cap->min_buf_size); + map_status = qdf_mem_map_nbytes_single(dbr_psoc_obj->osdev, aligned_vaddr, QDF_DMA_FROM_DEVICE, @@ -364,7 +1062,13 @@ static QDF_STATUS target_if_dbr_replenish_ring(struct wlan_objmgr_pdev *pdev, hal_srng_access_start(hal_soc, srng); ring_entry = hal_srng_src_get_next(hal_soc, srng); - QDF_ASSERT(ring_entry); + + if (!ring_entry) { + target_if_dbr_qdf_show_ring_debug(pdev, mod_param->mod_id, + mod_param->srng_id); + QDF_BUG(0); + } + dw_lo = (uint64_t)paddr & 0xFFFFFFFF; WMI_HOST_DBR_RING_ADDR_HI_SET(dw_hi, (uint64_t)paddr >> 32); WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_SET(dw_hi, cookie); @@ -572,7 +1276,7 @@ static QDF_STATUS target_if_dbr_cfg_tgt(struct wlan_objmgr_pdev *pdev, { QDF_STATUS status; struct wlan_objmgr_psoc *psoc; - void *wmi_hdl; + wmi_unified_t wmi_hdl; struct direct_buf_rx_cfg_req dbr_cfg_req = {0}; struct direct_buf_rx_ring_cfg *dbr_ring_cfg; struct direct_buf_rx_ring_cap *dbr_ring_cap; @@ -589,7 +1293,7 @@ static QDF_STATUS target_if_dbr_cfg_tgt(struct wlan_objmgr_pdev *pdev, dbr_ring_cfg = mod_param->dbr_ring_cfg; dbr_ring_cap = mod_param->dbr_ring_cap; dbr_config = &mod_param->dbr_config; - wmi_hdl = get_wmi_unified_hdl_from_psoc(psoc); + wmi_hdl = lmac_get_pdev_wmi_handle(pdev); if (!wmi_hdl) { direct_buf_rx_err("WMI handle null. Can't send WMI CMD"); return QDF_STATUS_E_INVAL; @@ -599,18 +1303,18 @@ static QDF_STATUS target_if_dbr_cfg_tgt(struct wlan_objmgr_pdev *pdev, dbr_cfg_req.pdev_id = mod_param->pdev_id; /* Module ID numbering starts from 1 in FW. need to fix it */ dbr_cfg_req.mod_id = mod_param->mod_id; - dbr_cfg_req.base_paddr_lo = (uint64_t)dbr_ring_cfg->base_paddr_aligned - & 0xFFFFFFFF; - dbr_cfg_req.base_paddr_hi = (uint64_t)dbr_ring_cfg->base_paddr_aligned - & 0xFFFFFFFF00000000; - dbr_cfg_req.head_idx_paddr_lo = (uint64_t)dbr_ring_cfg->head_idx_addr - & 0xFFFFFFFF; - dbr_cfg_req.head_idx_paddr_hi = (uint64_t)dbr_ring_cfg->head_idx_addr - & 0xFFFFFFFF00000000; - dbr_cfg_req.tail_idx_paddr_lo = (uint64_t)dbr_ring_cfg->tail_idx_addr - & 0xFFFFFFFF; - dbr_cfg_req.tail_idx_paddr_hi = (uint64_t)dbr_ring_cfg->tail_idx_addr - & 0xFFFFFFFF00000000; + dbr_cfg_req.base_paddr_lo = + qdf_get_lower_32_bits(dbr_ring_cfg->base_paddr_aligned); + dbr_cfg_req.base_paddr_hi = + qdf_get_upper_32_bits(dbr_ring_cfg->base_paddr_aligned); + dbr_cfg_req.head_idx_paddr_lo = + qdf_get_lower_32_bits(dbr_ring_cfg->head_idx_addr); + dbr_cfg_req.head_idx_paddr_hi = + qdf_get_upper_32_bits(dbr_ring_cfg->head_idx_addr); + dbr_cfg_req.tail_idx_paddr_lo = + qdf_get_lower_32_bits(dbr_ring_cfg->tail_idx_addr); + dbr_cfg_req.tail_idx_paddr_hi = + qdf_get_upper_32_bits(dbr_ring_cfg->tail_idx_addr); dbr_cfg_req.num_elems = dbr_ring_cap->ring_elems_min; dbr_cfg_req.buf_size = dbr_ring_cap->min_buf_size; dbr_cfg_req.num_resp_per_event = dbr_config->num_resp_per_event; @@ -662,6 +1366,7 @@ static QDF_STATUS target_if_init_dbr_ring(struct wlan_objmgr_pdev *pdev, mod_param->mod_id = mod_id; mod_param->pdev_id = dbr_get_pdev_id( srng_id, wlan_objmgr_pdev_get_pdev_id(pdev)); + mod_param->srng_id = srng_id; /* Initialize DMA ring now */ status = target_if_dbr_init_srng(pdev, mod_param); @@ -813,8 +1518,10 @@ static void *target_if_dbr_vaddr_lookup( return dbr_buf_pool[cookie].vaddr + dbr_buf_pool[cookie].offset; } + direct_buf_rx_debug("Invalid paddr, cookie %d, pool paddr %pK, paddr %pK", + cookie, (void *)dbr_buf_pool[cookie].paddr, + (void *)paddr); - direct_buf_rx_debug("Incorrect paddr found on cookie slot"); return NULL; } @@ -925,6 +1632,14 @@ static QDF_STATUS target_if_get_dbr_data(struct wlan_objmgr_pdev *pdev, *cookie = WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_GET( dbr_rsp->dbr_entries[idx].paddr_hi); dbr_data->vaddr = target_if_dbr_vaddr_lookup(mod_param, paddr, *cookie); + + if (!dbr_data->vaddr) { + direct_buf_rx_debug("dbr vaddr lookup failed, cookie %d, hi %x, lo %x", + *cookie, dbr_rsp->dbr_entries[idx].paddr_hi, + dbr_rsp->dbr_entries[idx].paddr_lo); + return QDF_STATUS_E_FAILURE; + } + dbr_data->cookie = *cookie; dbr_data->paddr = paddr; direct_buf_rx_debug("Cookie = %d Vaddr look up = %pK", @@ -981,6 +1696,90 @@ dbr_get_pdev_and_srng_id(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, } #endif +#ifdef DIRECT_BUF_RX_DEBUG +/** + * target_if_dbr_add_ring_debug_entry() - Add a DBR ring debug entry + * @pdev: pointer to pdev object + * @mod_id: Module ID + * @event: ring debug event + * + * Log the given event, head and tail pointers of DBR ring of the given module + * into its ring debug data structure. + * Also, log the timestamp at the time of logging. + */ +static void target_if_dbr_add_ring_debug_entry( + struct wlan_objmgr_pdev *pdev, + uint32_t mod_id, + enum DBR_RING_DEBUG_EVENT event, + uint8_t srng_id) +{ + struct wlan_objmgr_psoc *psoc; + void *hal_soc, *srng; + uint32_t hp = 0, tp = 0; + struct direct_buf_rx_psoc_obj *dbr_psoc_obj; + struct direct_buf_rx_pdev_obj *dbr_pdev_obj; + struct direct_buf_rx_ring_cfg *dbr_ring_cfg; + struct direct_buf_rx_module_debug *mod_debug; + struct direct_buf_rx_module_param *mod_param; + struct direct_buf_rx_ring_debug *ring_debug; + struct direct_buf_rx_ring_debug_entry *entry; + + mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id); + + if (!mod_debug) + return; + + psoc = wlan_pdev_get_psoc(pdev); + + dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj( + pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); + + dbr_psoc_obj = wlan_objmgr_psoc_get_comp_private_obj( + psoc, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX); + + mod_param = &dbr_pdev_obj->dbr_mod_param[mod_id][srng_id]; + if (!mod_param) { + direct_buf_rx_err("dir buf rx module param is null"); + return; + } + + hal_soc = dbr_psoc_obj->hal_soc; + dbr_ring_cfg = mod_param->dbr_ring_cfg; + srng = dbr_ring_cfg->srng; + ring_debug = &mod_debug->dbr_ring_debug[srng_id]; + + if (ring_debug->entries) { + if (hal_srng_access_start(hal_soc, srng)) { + direct_buf_rx_err("module %d - HAL srng access failed", + mod_id); + return; + } + hal_get_sw_hptp(hal_soc, srng, &tp, &hp); + hal_srng_access_end(hal_soc, srng); + entry = &ring_debug->entries[ring_debug->ring_debug_idx]; + + entry->head_idx = hp; + entry->tail_idx = tp; + entry->timestamp = qdf_get_log_timestamp(); + entry->event = event; + + ring_debug->ring_debug_idx++; + if (ring_debug->ring_debug_idx == + ring_debug->num_ring_debug_entries) + ring_debug->ring_debug_idx = 0; + } +} + +#else +static void target_if_dbr_add_ring_debug_entry( + struct wlan_objmgr_pdev *pdev, + uint32_t mod_id, + enum DBR_RING_DEBUG_EVENT event, + uint8_t srng_id) +{ +} +#endif /* DIRECT_BUF_RX_DEBUG */ + static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, uint8_t *data_buf, uint32_t data_len) @@ -996,7 +1795,7 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, struct direct_buf_rx_buf_info *dbr_buf_pool; struct direct_buf_rx_pdev_obj *dbr_pdev_obj; struct direct_buf_rx_module_param *mod_param; - struct common_wmi_handle *wmi_handle; + struct wmi_unified *wmi_handle; wlan_objmgr_ref_dbgid dbr_mod_id = WLAN_DIRECT_BUF_RX_ID; uint8_t srng_id = 0; @@ -1095,10 +1894,20 @@ static int target_if_direct_buf_rx_rsp_event_handler(ol_scn_t scn, &dbr_data.meta_data) == QDF_STATUS_SUCCESS) dbr_data.meta_data_valid = true; } + + target_if_dbr_add_ring_debug_entry(pdev, dbr_rsp.mod_id, + DBR_RING_DEBUG_EVENT_RX, + srng_id); if (mod_param->dbr_rsp_handler(pdev, &dbr_data)) { status = target_if_dbr_replenish_ring(pdev, mod_param, dbr_data.vaddr, cookie); + + target_if_dbr_add_ring_debug_entry( + pdev, dbr_rsp.mod_id, + DBR_RING_DEBUG_EVENT_REPLENISH_RING, + srng_id); + if (QDF_IS_STATUS_ERROR(status)) { direct_buf_rx_err("Ring replenish failed"); qdf_mem_free(dbr_rsp.dbr_entries); diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h b/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h index 5e8e56637a380e2e0fb4db093db380e460a52d0f..a06375f9cc40fb9dbdca0aca2e5f13c686d04c82 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/direct_buf_rx/src/target_if_direct_buf_rx_main.h @@ -88,6 +88,84 @@ struct direct_buf_rx_ring_cap { uint32_t min_buf_align; }; +/** + * enum DBR_RING_DEBUG_EVENT - DMA ring debug event + * @DBR_RING_DEBUG_EVENT_NONE: Not a real value, just a place holder for + * no entry + * @DBR_RING_DEBUG_EVENT_RX: DBR Rx event + * @DBR_RING_DEBUG_EVENT_REPLENISH_RING: DBR replenish event + * @DBR_RING_DEBUG_EVENT_MAX: Not a real value, just a place holder for max + */ +enum DBR_RING_DEBUG_EVENT { + DBR_RING_DEBUG_EVENT_NONE = 0, + DBR_RING_DEBUG_EVENT_RX, + DBR_RING_DEBUG_EVENT_REPLENISH_RING, + DBR_RING_DEBUG_EVENT_MAX, +}; + +#define DIRECT_BUF_RX_MAX_RING_DEBUG_ENTRIES (1024) +/** + * struct direct_buf_rx_ring_debug_entry - DBR ring debug entry + * @head_idx: Head index of the DMA ring + * @tail_idx: Tail index of the DMA ring + * @timestamp: Timestamp at the time of logging + * @event: Name of the event + */ +struct direct_buf_rx_ring_debug_entry { + uint32_t head_idx; + uint32_t tail_idx; + uint64_t timestamp; + enum DBR_RING_DEBUG_EVENT event; +}; + +#ifdef WLAN_DEBUGFS +/** + * struct dbr_debugfs_priv - Private data for DBR ring debugfs + * @dbr_pdev_obj: Pointer to the pdev obj of Direct buffer rx module + * @mod_id: Pointer to the registered module ID + * @srng_id: srng ID + */ +struct dbr_debugfs_priv { + struct direct_buf_rx_pdev_obj *dbr_pdev_obj; + enum DBR_MODULE mod_id; + uint8_t srng_id; +}; +#endif + +/** + * struct direct_buf_rx_ring_debug - DMA ring debug of a module + * @entries: Pointer to the array of ring debug entries + * @ring_debug_idx: Current index in the array of ring debug entries + * @num_ring_debug_entries: Total ring debug entries + * @debugfs_entry: Debugfs entry for this ring + * @debugfs_priv: Debugfs ops for this ring + */ +struct direct_buf_rx_ring_debug { + struct direct_buf_rx_ring_debug_entry *entries; + uint32_t ring_debug_idx; + uint32_t num_ring_debug_entries; +#ifdef WLAN_DEBUGFS + qdf_dentry_t debugfs_entry; + struct qdf_debugfs_fops *debugfs_fops; +#endif +}; + +/** + * struct direct_buf_rx_module_debug - Debug of a module subscribed to DBR + * @dbr_ring_debug: Array of ring debug structers corresponding to each srng + * @poisoning_enabled: Whether buffer poisoning is enabled for this module + * @poison_value: Value with which buffers should be poisoned + * @debugfs_entry: Debugfs entry for this module + */ +struct direct_buf_rx_module_debug { + struct direct_buf_rx_ring_debug dbr_ring_debug[DBR_SRNG_NUM]; + bool poisoning_enabled; + uint32_t poison_value; +#ifdef WLAN_DEBUGFS + qdf_dentry_t debugfs_entry; +#endif +}; + /** * struct direct_buf_rx_module_param - DMA module param * @mod_id: Module ID @@ -101,6 +179,7 @@ struct direct_buf_rx_ring_cap { struct direct_buf_rx_module_param { enum DBR_MODULE mod_id; uint8_t pdev_id; + uint8_t srng_id; struct dbr_module_config dbr_config; struct direct_buf_rx_ring_cap *dbr_ring_cap; struct direct_buf_rx_ring_cfg *dbr_ring_cfg; @@ -113,20 +192,30 @@ struct direct_buf_rx_module_param { * struct direct_buf_rx_pdev_obj - Direct Buf RX pdev object struct * @num_modules: Number of modules registered to DBR for the pdev * @dbr_mod_param: Pointer to direct buf rx module param struct + * @dbr_mod_debug: Pointer to the array of DBR module debug structures + * @debugfs_entry: DBR debugfs entry of this radio */ struct direct_buf_rx_pdev_obj { uint32_t num_modules; struct direct_buf_rx_module_param (*dbr_mod_param)[DBR_SRNG_NUM]; +#ifdef DIRECT_BUF_RX_DEBUG + struct direct_buf_rx_module_debug *dbr_mod_debug; +#ifdef WLAN_DEBUGFS + qdf_dentry_t debugfs_entry; +#endif +#endif }; /** * struct direct_buf_rx_psoc_obj - Direct Buf RX psoc object struct * @hal_soc: Opaque HAL SOC handle * @osdev: QDF os device handle + * @dbr_pdev_objs: array of DBR pdev objects */ struct direct_buf_rx_psoc_obj { void *hal_soc; qdf_device_t osdev; + struct direct_buf_rx_pdev_obj *dbr_pdev_obj[WLAN_UMAC_MAX_PDEVS]; }; /** @@ -271,4 +360,44 @@ target_if_direct_buf_rx_get_ring_params(struct wlan_objmgr_pdev *pdev, struct module_ring_params *param, uint8_t mod_id, uint8_t srng_id); +/** + * target_if_dbr_start_ring_debug() - Start DBR ring debug + * @pdev: pointer to pdev object + * @mod_id: module ID indicating the module using direct buffer rx framework + * @num_ring_debug_entries: Size of the ring debug entries + */ +QDF_STATUS target_if_dbr_start_ring_debug(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, + uint32_t num_ring_debug_entries); + +/** + * target_if_dbr_stop_ring_debug() - Stop DBR ring debug + * @pdev: pointer to pdev object + * @mod_id: module ID indicating the module using direct buffer rx framework + */ +QDF_STATUS target_if_dbr_stop_ring_debug(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id); + +/** + * target_if_dbr_start_buffer_poisoning() - Start DBR buffer poisoning + * @pdev: pointer to pdev object + * @mod_id: module ID indicating the module using direct buffer rx framework + * @value: Value with which buffers should be poisoned + * + * Only those buffers which are going to be mapped to the device after this + * API call are guaranteed to be poisoned. If user wants all the buffers in + * the ring to be poisoned from their creation time then this API should be + * called before module's registration to the DBR. + * + */ +QDF_STATUS target_if_dbr_start_buffer_poisoning(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id, uint32_t value); + +/** + * target_if_dbr_stop_buffer_poisoning() - Stop DBR buffer poisoning + * @pdev: pointer to pdev object + * @mod_id: module ID indicating the module using direct buffer rx framework + */ +QDF_STATUS target_if_dbr_stop_buffer_poisoning(struct wlan_objmgr_pdev *pdev, + uint8_t mod_id); #endif /* _TARGET_IF_DIRECT_BUF_RX_MAIN_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/dispatcher/inc/target_if_pub.h b/drivers/staging/qca-wifi-host-cmn/target_if/dispatcher/inc/target_if_pub.h new file mode 100644 index 0000000000000000000000000000000000000000..84a24b7c264dcb4d51f2116e59d3ef8143cbb7d8 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/dispatcher/inc/target_if_pub.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016-2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file contains the structure definitions of target interface + * used for the abstraction across various layers. + */ + +#ifndef _TARGET_IF_PUB_H_ +#define _TARGET_IF_PUB_H_ + +/** + * typedef target_pdev_info_t - Opaque definition of target pdev + * information structure + */ +struct target_pdev_info; +typedef struct target_pdev_info target_pdev_info_t; + +/** + * typedef target_psoc_info_t - Opaque definition of target psoc + * information structure + */ +struct target_psoc_info; +typedef struct target_psoc_info target_psoc_info_t; +#endif /* _TARGET_IF_PUB_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/dp/inc/target_if_dp.h b/drivers/staging/qca-wifi-host-cmn/target_if/dp/inc/target_if_dp.h index 3bae0e202603e4a99627f9c2ef9c92b514cd3898..dcb6327b425b251375686edf030b12f23e4a2223 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/dp/inc/target_if_dp.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/dp/inc/target_if_dp.h @@ -33,8 +33,9 @@ /** * struct reorder_q_setup - reorder queue setup params - * @pdev: pdev + * @psoc: psoc * @vdev_id: vdev id + * @pdev_id: pdev id * @peer_macaddr: peer mac address * @hw_qdesc: hw queue descriptor * @tid: tid number @@ -43,8 +44,9 @@ * @ba_window_size: BA window size */ struct reorder_q_setup { - struct cdp_ctrl_objmgr_pdev *pdev; + struct cdp_ctrl_objmgr_psoc *psoc; uint8_t vdev_id; + uint8_t pdev_id; uint8_t peer_mac[QDF_MAC_ADDR_SIZE]; qdf_dma_addr_t hw_qdesc_paddr; uint8_t tid; @@ -55,7 +57,8 @@ struct reorder_q_setup { /** * target_if_peer_set_default_routing() - set peer default routing - * @pdev: pdev pointer + * @psoc: psoc pointer + * @pdev_id: pdev id * @peer_macaddr: peer mac address * @vdev_id: vdev id * @hash_based: hash based routing @@ -64,13 +67,14 @@ struct reorder_q_setup { * return: void */ void -target_if_peer_set_default_routing(struct cdp_ctrl_objmgr_pdev *pdev, +target_if_peer_set_default_routing(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, uint8_t *peer_macaddr, uint8_t vdev_id, bool hash_based, uint8_t ring_num); - /** * target_if_peer_rx_reorder_queue_setup() - setup rx reorder queue * @pdev: pdev pointer + * @pdev_id: pdev id * @vdev_id: vdev id * @peer_macaddr: peer mac address * @hw_qdesc: hw queue descriptor @@ -82,7 +86,8 @@ target_if_peer_set_default_routing(struct cdp_ctrl_objmgr_pdev *pdev, * return: QDF_STATUS_SUCCESS for success or error code */ QDF_STATUS -target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_pdev *pdev, +target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, uint8_t vdev_id, uint8_t *peer_macaddr, qdf_dma_addr_t hw_qdesc, int tid, uint16_t queue_no, @@ -91,7 +96,8 @@ target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_pdev *pdev, /** * target_if_peer_rx_reorder_queue_remove() - remove rx reorder queue - * @pdev: pdev pointer + * @psoc: psoc pointer + * @pdev_id: pdev id * @vdev_id: vdev id * @peer_macaddr: peer mac address * @peer_tid_bitmap: peer tid bitmap @@ -99,7 +105,8 @@ target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_pdev *pdev, * return: QDF_STATUS_SUCCESS for success or error code */ QDF_STATUS -target_if_peer_rx_reorder_queue_remove(struct cdp_ctrl_objmgr_pdev *pdev, +target_if_peer_rx_reorder_queue_remove(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, uint8_t vdev_id, uint8_t *peer_macaddr, uint32_t peer_tid_bitmap); @@ -111,7 +118,7 @@ target_if_peer_rx_reorder_queue_remove(struct cdp_ctrl_objmgr_pdev *pdev, * return: QDF_STATUS_SUCCESS for success or error code */ QDF_STATUS -target_if_lro_hash_config(struct cdp_ctrl_objmgr_pdev *pdev, +target_if_lro_hash_config(struct cdp_ctrl_objmgr_psoc *psoc, uint8_t pdev_id, struct cdp_lro_hash_config *lro_hash_cfg); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/dp/src/target_if_dp.c b/drivers/staging/qca-wifi-host-cmn/target_if/dp/src/target_if_dp.c index fb7a25370c81274462aca88a2c0f804b98f7e2fb..e45352f887ec4b0e3274cfadebbccc303a6b4fc7 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/dp/src/target_if_dp.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/dp/src/target_if_dp.c @@ -25,17 +25,26 @@ #include void -target_if_peer_set_default_routing(struct cdp_ctrl_objmgr_pdev *pdev, - uint8_t *peer_macaddr, uint8_t vdev_id, +target_if_peer_set_default_routing(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, uint8_t *peer_macaddr, + uint8_t vdev_id, bool hash_based, uint8_t ring_num) { uint32_t value; struct peer_set_params param; - struct common_wmi_handle *pdev_wmi_handle; + struct wmi_unified *pdev_wmi_handle; + struct wlan_objmgr_pdev *pdev = + wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, + pdev_id, WLAN_PDEV_TARGET_IF_ID); - pdev_wmi_handle = - lmac_get_pdev_wmi_handle((struct wlan_objmgr_pdev *)pdev); + if (!pdev) { + target_if_err("pdev with id %d is NULL", pdev_id); + return; + } + + pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); if (!pdev_wmi_handle) { + wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); target_if_err("pdev wmi handle NULL"); return; } @@ -53,9 +62,10 @@ target_if_peer_set_default_routing(struct cdp_ctrl_objmgr_pdev *pdev, if (wmi_set_peer_param_send(pdev_wmi_handle, peer_macaddr, ¶m)) { target_if_err("Unable to set default routing for peer " - QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(peer_macaddr)); + QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(peer_macaddr)); } + wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); } #ifdef SERIALIZE_QUEUE_SETUP @@ -63,10 +73,11 @@ static QDF_STATUS target_if_rx_reorder_queue_setup(struct scheduler_msg *msg) { struct rx_reorder_queue_setup_params param; - struct common_wmi_handle *pdev_wmi_handle; + struct wmi_unified *pdev_wmi_handle; struct reorder_q_setup *q_params; - struct cdp_ctrl_objmgr_pdev *pdev; QDF_STATUS status; + struct wlan_objmgr_pdev *pdev; + struct wlan_objmgr_psoc *psoc; if (!(msg->bodyptr)) { target_if_err("rx_reorder: Invalid message body"); @@ -74,9 +85,17 @@ target_if_rx_reorder_queue_setup(struct scheduler_msg *msg) } q_params = msg->bodyptr; - pdev = q_params->pdev; - pdev_wmi_handle = - lmac_get_pdev_wmi_handle((struct wlan_objmgr_pdev *)pdev); + psoc = (struct wlan_objmgr_psoc *)q_params->psoc; + + pdev = wlan_objmgr_get_pdev_by_id(psoc, q_params->pdev_id, + WLAN_PDEV_TARGET_IF_ID); + + if (!pdev) { + target_if_err("pdev with id %d is NULL", q_params->pdev_id); + return QDF_STATUS_E_INVAL; + } + + pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); if (!pdev_wmi_handle) { target_if_err("pdev wmi handle NULL"); status = QDF_STATUS_E_FAILURE; @@ -95,13 +114,15 @@ target_if_rx_reorder_queue_setup(struct scheduler_msg *msg) status = wmi_unified_peer_rx_reorder_queue_setup_send(pdev_wmi_handle, ¶m); out: + wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); qdf_mem_free(q_params); return status; } QDF_STATUS -target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_pdev *pdev, +target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, uint8_t vdev_id, uint8_t *peer_macaddr, qdf_dma_addr_t hw_qdesc, int tid, uint16_t queue_no, @@ -116,8 +137,9 @@ target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_pdev *pdev, if (!q_params) return QDF_STATUS_E_NOMEM; - q_params->pdev = pdev; + q_params->psoc = psoc; q_params->vdev_id = vdev_id; + q_params->pdev_id = pdev_id; q_params->hw_qdesc_paddr = hw_qdesc; q_params->tid = tid; q_params->queue_no = queue_no; @@ -140,7 +162,8 @@ target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_pdev *pdev, #else QDF_STATUS -target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_pdev *pdev, +target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, uint8_t vdev_id, uint8_t *peer_macaddr, qdf_dma_addr_t hw_qdesc, int tid, uint16_t queue_no, @@ -148,11 +171,20 @@ target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_pdev *pdev, uint16_t ba_window_size) { struct rx_reorder_queue_setup_params param; - struct common_wmi_handle *pdev_wmi_handle; + struct wmi_unified *pdev_wmi_handle; + QDF_STATUS status; + struct wlan_objmgr_pdev *pdev = + wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, + pdev_id, WLAN_PDEV_TARGET_IF_ID); - pdev_wmi_handle = - lmac_get_pdev_wmi_handle((struct wlan_objmgr_pdev *)pdev); + if (!pdev) { + target_if_err("pdev with id %d is NULL", pdev_id); + return QDF_STATUS_E_INVAL; + } + + pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); if (!pdev_wmi_handle) { + wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); target_if_err("pdev wmi handle NULL"); return QDF_STATUS_E_FAILURE; } @@ -165,42 +197,67 @@ target_if_peer_rx_reorder_queue_setup(struct cdp_ctrl_objmgr_pdev *pdev, param.ba_window_size_valid = ba_window_size_valid; param.ba_window_size = ba_window_size; - return wmi_unified_peer_rx_reorder_queue_setup_send(pdev_wmi_handle, - ¶m); + status = wmi_unified_peer_rx_reorder_queue_setup_send(pdev_wmi_handle, + ¶m); + wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); + + return status; } #endif QDF_STATUS -target_if_peer_rx_reorder_queue_remove(struct cdp_ctrl_objmgr_pdev *pdev, +target_if_peer_rx_reorder_queue_remove(struct cdp_ctrl_objmgr_psoc *psoc, + uint8_t pdev_id, uint8_t vdev_id, uint8_t *peer_macaddr, uint32_t peer_tid_bitmap) { struct rx_reorder_queue_remove_params param; - struct common_wmi_handle *pdev_wmi_handle; + struct wmi_unified *pdev_wmi_handle; + QDF_STATUS status; + struct wlan_objmgr_pdev *pdev = + wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, + pdev_id, WLAN_PDEV_TARGET_IF_ID); - pdev_wmi_handle = - lmac_get_pdev_wmi_handle((struct wlan_objmgr_pdev *)pdev); + if (!pdev) { + target_if_err("pdev with id %d is NULL", pdev_id); + return QDF_STATUS_E_INVAL; + } + + pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); if (!pdev_wmi_handle) { + wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); target_if_err("pdev wmi handle NULL"); return QDF_STATUS_E_FAILURE; } param.vdev_id = vdev_id; param.peer_macaddr = peer_macaddr; param.peer_tid_bitmap = peer_tid_bitmap; - return wmi_unified_peer_rx_reorder_queue_remove_send(pdev_wmi_handle, - ¶m); + status = wmi_unified_peer_rx_reorder_queue_remove_send(pdev_wmi_handle, + ¶m); + wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); + + return status; } QDF_STATUS -target_if_lro_hash_config(struct cdp_ctrl_objmgr_pdev *pdev, +target_if_lro_hash_config(struct cdp_ctrl_objmgr_psoc *psoc, uint8_t pdev_id, struct cdp_lro_hash_config *lro_hash_cfg) { struct wmi_lro_config_cmd_t wmi_lro_cmd = {0}; - struct common_wmi_handle *pdev_wmi_handle; + struct wmi_unified *pdev_wmi_handle; + QDF_STATUS status; + struct wlan_objmgr_pdev *pdev = + wlan_objmgr_get_pdev_by_id((struct wlan_objmgr_psoc *)psoc, + pdev_id, WLAN_PDEV_TARGET_IF_ID); - pdev_wmi_handle = - lmac_get_pdev_wmi_handle((struct wlan_objmgr_pdev *)pdev); + if (!pdev) { + target_if_err("pdev with id %d is NULL", pdev_id); + return QDF_STATUS_E_INVAL; + } + + pdev_wmi_handle = lmac_get_pdev_wmi_handle(pdev); if (!lro_hash_cfg || !pdev_wmi_handle) { + wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); target_if_err("wmi_handle: 0x%pK, lro_hash_cfg: 0x%pK", pdev_wmi_handle, lro_hash_cfg); return QDF_STATUS_E_FAILURE; @@ -209,8 +266,7 @@ target_if_lro_hash_config(struct cdp_ctrl_objmgr_pdev *pdev, wmi_lro_cmd.lro_enable = lro_hash_cfg->lro_enable; wmi_lro_cmd.tcp_flag = lro_hash_cfg->tcp_flag; wmi_lro_cmd.tcp_flag_mask = lro_hash_cfg->tcp_flag_mask; - wmi_lro_cmd.pdev_id = - lmac_get_pdev_idx((struct wlan_objmgr_pdev *)pdev); + wmi_lro_cmd.pdev_id = pdev_id; qdf_mem_copy(wmi_lro_cmd.toeplitz_hash_ipv4, lro_hash_cfg->toeplitz_hash_ipv4, @@ -220,6 +276,9 @@ target_if_lro_hash_config(struct cdp_ctrl_objmgr_pdev *pdev, lro_hash_cfg->toeplitz_hash_ipv6, LRO_IPV6_SEED_ARR_SZ * sizeof(uint32_t)); - return wmi_unified_lro_config_cmd(pdev_wmi_handle, - &wmi_lro_cmd); + status = wmi_unified_lro_config_cmd(pdev_wmi_handle, + &wmi_lro_cmd); + wlan_objmgr_pdev_release_ref(pdev, WLAN_PDEV_TARGET_IF_ID); + + return status; } diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/gpio/target_if_gpio.c b/drivers/staging/qca-wifi-host-cmn/target_if/gpio/target_if_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..0b2cb5050645c2f8211bdfe2342626335b3d8578 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/gpio/target_if_gpio.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: target_if_gpio.c + * + * This file provide definition for APIs registered through lmac Tx Ops + */ + +#include +#include +#include +#include +#include + +/** + * target_if_set_gpio_config() - API to send gpio config request to wmi + * @psoc: pointer to psoc object + * @param: pointer to gpio info + * + * Return: status of operation. + */ +static QDF_STATUS +target_if_set_gpio_config(struct wlan_objmgr_psoc *psoc, + struct gpio_config_params *param) +{ + struct wmi_unified *wmi_handle; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("wmi_handle is null."); + return QDF_STATUS_E_NULL_VALUE; + } + + return wmi_unified_gpio_config_cmd_send(wmi_handle, param); +} + +/** + * target_if_set_gpio_output() - API to send gpio output request to wmi + * @psoc: pointer to psoc object + * @param: pointer to gpio info + * + * Return: status of operation. + */ +static QDF_STATUS +target_if_set_gpio_output(struct wlan_objmgr_psoc *psoc, + struct gpio_output_params *param) +{ + struct wmi_unified *wmi_handle; + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("wmi_handle is null."); + return QDF_STATUS_E_NULL_VALUE; + } + + return wmi_unified_gpio_output_cmd_send(wmi_handle, param); +} + +QDF_STATUS +target_if_gpio_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + struct wlan_lmac_if_gpio_tx_ops *gpio_ops; + + if (!tx_ops) { + target_if_err("tx ops is NULL!"); + return QDF_STATUS_E_INVAL; + } + gpio_ops = &tx_ops->gpio_ops; + + gpio_ops->set_gpio_config = target_if_set_gpio_config; + gpio_ops->set_gpio_output = target_if_set_gpio_output; + + return QDF_STATUS_SUCCESS; +} + diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/gpio/target_if_gpio.h b/drivers/staging/qca-wifi-host-cmn/target_if/gpio/target_if_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..f0993511c645959beb6a3ca974b655295643ad28 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/gpio/target_if_gpio.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: offload lmac interface APIs for gpio cfg + */ +#ifndef __TARGET_IF_GPIO_CFG_H__ +#define __TARGET_IF_GPIO_CFG_H__ + +#ifdef WLAN_FEATURE_GPIO_CFG +#include +struct wlan_lmac_if_tx_ops; + +/** + * target_if_gpio_register_tx_ops() - register tx ops funcs + * @tx_ops: pointer to gpio tx ops + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +target_if_gpio_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); + +#endif /* WLAN_FEATURE_GPIO_CFG */ +#endif /* __TARGET_IF_GPIO_CFG_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/green_ap/src/target_if_green_ap.c b/drivers/staging/qca-wifi-host-cmn/target_if/green_ap/src/target_if_green_ap.c index 3ecf935c678c710f40dcc5d780d8f423b14edea8..56b70dbceeef4c20fa9dc70ae49782d5c03ec97d 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/green_ap/src/target_if_green_ap.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/green_ap/src/target_if_green_ap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 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 @@ -140,7 +140,7 @@ QDF_STATUS target_if_green_ap_enable_egap( struct wlan_green_ap_egap_params *egap_params) { struct wlan_pdev_green_ap_ctx *green_ap_ctx; - void *wmi_hdl; + wmi_unified_t wmi_hdl; if (!pdev) { green_ap_err("pdev context passed is NULL"); @@ -175,7 +175,7 @@ QDF_STATUS target_if_green_ap_enable_egap( QDF_STATUS target_if_green_ap_set_ps_on_off(struct wlan_objmgr_pdev *pdev, bool value, uint8_t pdev_id) { - void *wmi_hdl; + wmi_unified_t wmi_hdl; if (!pdev) { green_ap_err("pdev context passed is NULL"); diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/init_cmd_api.h b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/init_cmd_api.h index e96d3802c54b0c28a89a9be3ff81b08f3b46aa15..a7c9adf1efc640d8c6e40f80a625335db6bbb998 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/init_cmd_api.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/init_cmd_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018, 2020 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 @@ -33,18 +33,6 @@ #define TXBF_CV_POOL2 4 #define HOST_CONTIGUOUS_MEM_CHUNK_REQUIRED 0x8 -/** - * enum wlan_fw_mem_prio - defines FW Memory requirement type - * @FW_MEM_HIGH_PRIORITY: Memory requires contiguous memory allocation - * @FW_MEM_LOW_PRIORITY: Memory can be fragmented - * @FW_PRIORITY_MAX: Invalid type - */ -enum wlan_fw_mem_prio { - FW_MEM_HIGH_PRIORITY = 0, - FW_MEM_LOW_PRIORITY, - FW_PRIORITY_MAX -}; - /** * init_deinit_handle_host_mem_req() - handle host memory request * @psoc: PSOC object diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/init_deinit_lmac.h b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/init_deinit_lmac.h index bf1b43cb0b879ad28c2745414d03ee46639c915d..7d3b7104186255082dba560d5565a6914e45fb9f 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/init_deinit_lmac.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/init_deinit_lmac.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 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 @@ -117,7 +117,7 @@ bool lmac_is_target_ar900b(struct wlan_objmgr_psoc *psoc); * * Return: wmi handler */ -struct common_wmi_handle *lmac_get_wmi_hdl(struct wlan_objmgr_psoc *psoc); +struct wmi_unified *lmac_get_wmi_hdl(struct wlan_objmgr_psoc *psoc); /** * lmac_get_wmi_unified_hdl() - get wmi handle @@ -137,7 +137,7 @@ wmi_unified_t lmac_get_wmi_unified_hdl(struct wlan_objmgr_psoc *psoc); * * Return: htc handler */ -struct common_htc_handle *lmac_get_htc_hdl(struct wlan_objmgr_psoc *psoc); +HTC_HANDLE lmac_get_htc_hdl(struct wlan_objmgr_psoc *psoc); /** * lmac_set_htc_hdl() - set htc handle @@ -149,7 +149,7 @@ struct common_htc_handle *lmac_get_htc_hdl(struct wlan_objmgr_psoc *psoc); * Return: void */ void lmac_set_htc_hdl(struct wlan_objmgr_psoc *psoc, - struct common_htc_handle *htc_hdl); + HTC_HANDLE htc_hdl); /** * lmac_get_hif_hdl() - get hif handle @@ -159,7 +159,7 @@ void lmac_set_htc_hdl(struct wlan_objmgr_psoc *psoc, * * Return: hif handler */ -struct common_hif_handle *lmac_get_hif_hdl(struct wlan_objmgr_psoc *psoc); +struct hif_opaque_softc *lmac_get_hif_hdl(struct wlan_objmgr_psoc *psoc); /** * lmac_get_ol_hif_hdl() - get hif handle @@ -179,7 +179,7 @@ struct hif_opaque_softc *lmac_get_ol_hif_hdl(struct wlan_objmgr_psoc *psoc); * * Return: wmi handle */ -struct common_wmi_handle *lmac_get_pdev_wmi_handle( +struct wmi_unified *lmac_get_pdev_wmi_handle( struct wlan_objmgr_pdev *pdev); /** diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/service_ready_param.h b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/service_ready_param.h index 4073156b1a265a54c77fad958dd6f51542bf0169..3a0f9986aebecd78fcd0d3a499feff67893994eb 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/service_ready_param.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/service_ready_param.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -109,6 +109,23 @@ struct wlan_psoc_host_ppe_threshold { uint32_t ppet16_ppet8_ru3_ru0[PSOC_HOST_MAX_NUM_SS]; }; +/** + * struct wlan_psoc_host_hal_reg_cap_ext - extended regulatory capabilities + * recvd in EXT service + * @wireless_modes: REGDMN MODE + * @low_2ghz_chan: lower 2.4GHz channels + * @high_2ghz_chan: higher 2.4 GHz channels + * @low_5ghz_chan: lower 5 GHz channels + * @high_5ghz_chan: higher 5 GHz channels + */ +struct wlan_psoc_host_hal_reg_cap_ext { + uint32_t wireless_modes; + uint32_t low_2ghz_chan; + uint32_t high_2ghz_chan; + uint32_t low_5ghz_chan; + uint32_t high_5ghz_chan; +}; + /** * struct wlan_psoc_host_mac_phy_caps - Phy caps recvd in EXT service * @hw_mode_id: identify a particular set of HW characteristics, @@ -161,6 +178,11 @@ struct wlan_psoc_host_ppe_threshold { * @he_ppet5G: 5G HE PPET info * @chainmask_table_id: chain mask table id * @lmac_id: hw mac id + * @reg_cap_ext: extended regulatory capabilities + * @tgt_pdev_id: target pdev id assigned and used by firmware + * @nss_ratio_enabled: This flag is set if nss ratio is received from FW as part + * of service ready ext event. + * @nss_ratio: nss ratio is used to calculate the NSS value for 160MHz. */ struct wlan_psoc_host_mac_phy_caps { uint32_t hw_mode_id; @@ -198,6 +220,10 @@ struct wlan_psoc_host_mac_phy_caps { struct wlan_psoc_host_ppe_threshold he_ppet5G; uint32_t chainmask_table_id; uint32_t lmac_id; + struct wlan_psoc_host_hal_reg_cap_ext reg_cap_ext; + uint32_t tgt_pdev_id; + bool nss_ratio_enabled; + uint8_t nss_ratio_info; }; /** @@ -255,6 +281,9 @@ struct wlan_psoc_host_spectral_scaling_params { * @supports_chan_width_80: channel width 80 support for this chain mask. * @supports_chan_width_160: channel width 160 support for this chain mask. * @supports_chan_width_80P80: channel width 80P80 support for this chain mask. + * @supports_aSpectral: Agile Spectral support for this chain mask. + * @supports_aSpectral_160: Agile Spectral support in 160 MHz. + * @supports_aDFS_160: Agile DFS support in 160 MHz for this chain mask. * @chain_mask_2G: 2G support for this chain mask. * @chain_mask_5G: 5G support for this chain mask. * @chain_mask_tx: Tx support for this chain mask. @@ -268,7 +297,10 @@ struct wlan_psoc_host_chainmask_capabilities { supports_chan_width_80:1, supports_chan_width_160:1, supports_chan_width_80P80:1, - reserved:22, + supports_aSpectral:1, + supports_aSpectral_160:1, + supports_aDFS_160:1, + reserved:19, chain_mask_2G:1, chain_mask_5G:1, chain_mask_tx:1, @@ -289,20 +321,6 @@ struct wlan_psoc_host_chainmask_table { struct wlan_psoc_host_chainmask_capabilities *cap_list; }; -#ifdef WLAN_SUPPORT_RF_CHARACTERIZATION -/** - * struct wlan_psoc_host_rf_characterization_entry - rf characterization table - * @freq: center frequency of primary channel - * @bw: bandwidth of primary channel - * @chan_metric: primary channel-specific metric - */ -struct wlan_psoc_host_rf_characterization_entry { - uint16_t freq; - wmi_host_channel_width bw; - uint8_t chan_metric; -}; -#endif - /** * struct wlan_psoc_host_service_ext_param - EXT service base params in event * @default_conc_scan_config_bits: Default concurrenct scan config @@ -322,8 +340,6 @@ struct wlan_psoc_host_rf_characterization_entry { * @max_bssid_indicator: Maximum number of VAPs in MBSS IE * @num_bin_scaling_params: Number of Spectral bin scaling parameters * @chainmask_table: Available chain mask tables. - * @num_rf_characterization_entries: Number of RF characterization info entries - * @rf_characterization_entries: Channel RF characterization information entries * @sar_version: SAR version info */ struct wlan_psoc_host_service_ext_param { @@ -342,11 +358,6 @@ struct wlan_psoc_host_service_ext_param { uint32_t num_bin_scaling_params; struct wlan_psoc_host_chainmask_table chainmask_table[PSOC_MAX_CHAINMASK_TABLES]; -#ifdef WLAN_SUPPORT_RF_CHARACTERIZATION - uint32_t num_rf_characterization_entries; - struct wlan_psoc_host_rf_characterization_entry - *rf_characterization_entries; -#endif uint32_t sar_version; }; @@ -356,13 +367,16 @@ struct wlan_psoc_host_service_ext_param { * reg_db_version_minor: REG DB version minor number * bdf_reg_db_version_major: BDF REG DB version major number * bdf_reg_db_version_minor: BDF REG DB version minor number + * @num_dbr_ring_caps: Number of direct buf rx ring capabilities + * @max_ndp_sessions: Max number of ndp session fw supports */ struct wlan_psoc_host_service_ext2_param { uint8_t reg_db_version_major; uint8_t reg_db_version_minor; uint8_t bdf_reg_db_version_major; uint8_t bdf_reg_db_version_minor; - + uint32_t num_dbr_ring_caps; + uint32_t max_ndp_sessions; }; #endif /* _SERVICE_READY_PARAM_H_*/ diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/service_ready_util.h b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/service_ready_util.h index dd32a5b217cb7e243ee962a6f9ec23e0ca1ba3af..e78fa79ff6a130c9f756b7e1910551bae4b4b05c 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/service_ready_util.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/inc/service_ready_util.h @@ -27,50 +27,6 @@ #include "service_ready_param.h" #include "target_if.h" -#ifdef WLAN_SUPPORT_RF_CHARACTERIZATION -/** - * init_deinit_populate_rf_characterization_entries() - * - allocates space for and populates the RF characterization information - * @handle: WMI handle pointer - * @evt: event buffer received from FW - * @service_ext_param: pointer to server ext param - * - * Allocates space for and populates the RF characterization information - * - * Return: QDF Status - */ -QDF_STATUS init_deinit_populate_rf_characterization_entries(void *handle, - uint8_t *evt, - struct wlan_psoc_host_service_ext_param *service_ext_par); - -/** - * init_deinit_rf_characterization_entries_free() - * - free RF characterization information - * @service_ext_param: pointer to server ext param - * - * Frees RF characterization information - * - * Return: QDF Status - */ -QDF_STATUS init_deinit_rf_characterization_entries_free( - struct wlan_psoc_host_service_ext_param *service_ext_par); -#else -static inline -QDF_STATUS init_deinit_populate_rf_characterization_entries(void *handle, - uint8_t *evt, - struct wlan_psoc_host_service_ext_param *ser_ext_par) -{ - return QDF_STATUS_SUCCESS; -} - -static inline -QDF_STATUS init_deinit_rf_characterization_entries_free( - struct wlan_psoc_host_service_ext_param *ser_ext_par) -{ - return QDF_STATUS_SUCCESS; -} -#endif - /** * init_deinit_chainmask_table_alloc() * - allocate chainmask table capability list. @@ -105,8 +61,9 @@ QDF_STATUS init_deinit_chainmask_table_free( * * Return: zero on successful population of service bitmap or failure flag */ -int init_deinit_populate_service_bitmap(void *wmi_handle, uint8_t *event, - uint32_t *service_bitmap); +int init_deinit_populate_service_bitmap( + wmi_unified_t wmi_handle, uint8_t *event, + uint32_t *service_bitmap); /** * init_deinit_populate_fw_version_cmd() - populate FW version @@ -117,7 +74,8 @@ int init_deinit_populate_service_bitmap(void *wmi_handle, uint8_t *event, * * Return: zero on successful population of fw_version command or failure flag */ -int init_deinit_populate_fw_version_cmd(void *wmi_handle, uint8_t *event); +int +init_deinit_populate_fw_version_cmd(wmi_unified_t wmi_handle, uint8_t *event); /** * init_deinit_populate_target_cap() - populate target cap @@ -129,8 +87,9 @@ int init_deinit_populate_fw_version_cmd(void *wmi_handle, uint8_t *event); * * Return: zero on successful population of target cap or failure flag */ -int init_deinit_populate_target_cap(void *wmi_handle, uint8_t *event, - struct wlan_psoc_target_capability_info *cap); +int init_deinit_populate_target_cap( + wmi_unified_t wmi_handle, uint8_t *event, + struct wlan_psoc_target_capability_info *cap); /** * init_deinit_populate_service_ready_ext_param() - populate service ready ext @@ -143,8 +102,9 @@ int init_deinit_populate_target_cap(void *wmi_handle, uint8_t *event, * * Return: zero on successful parsing of service ready ext parameter or failure */ -int init_deinit_populate_service_ready_ext_param(void *handle, uint8_t *evt, - struct wlan_psoc_host_service_ext_param *param); +int init_deinit_populate_service_ready_ext_param( + wmi_unified_t handle, uint8_t *evt, + struct wlan_psoc_host_service_ext_param *param); /** * init_deinit_populate_service_ready_ext2_param() - populate service ready ext2 @@ -158,7 +118,7 @@ int init_deinit_populate_service_ready_ext_param(void *handle, uint8_t *evt, * Return: zero on successful parsing of service ready ext parameter or failure */ int init_deinit_populate_service_ready_ext2_param( - void *handle, uint8_t *evt, + wmi_unified_t handle, uint8_t *evt, struct tgt_info *info); /** @@ -171,7 +131,8 @@ int init_deinit_populate_service_ready_ext2_param( * * Return: zero on successful parsing of chainmaks tables or failure flag */ -int init_deinit_populate_chainmask_tables(void *handle, uint8_t *evt, +int init_deinit_populate_chainmask_tables( + wmi_unified_t handle, uint8_t *evt, struct wlan_psoc_host_chainmask_table *param); /** @@ -185,7 +146,8 @@ int init_deinit_populate_chainmask_tables(void *handle, uint8_t *evt, * * Return: zero on successful population of mac physical capability or failure */ -int init_deinit_populate_mac_phy_capability(void *handle, uint8_t *evt, +int init_deinit_populate_mac_phy_capability( + wmi_unified_t handle, uint8_t *evt, struct wlan_psoc_host_hw_mode_caps *hw_cap, struct tgt_info *info); /** @@ -198,7 +160,8 @@ int init_deinit_populate_mac_phy_capability(void *handle, uint8_t *evt, * * Return: zero on successful parsing of hw mode capability or failure */ -int init_deinit_populate_hw_mode_capability(void *wmi_handle, +int init_deinit_populate_hw_mode_capability( + wmi_unified_t wmi_handle, uint8_t *event, struct target_psoc_info *tgt_hdl); /** @@ -213,8 +176,24 @@ int init_deinit_populate_hw_mode_capability(void *wmi_handle, * Return: zero on successful parsing of dbr ring capability or failure */ int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc, - void *handle, uint8_t *event, - struct tgt_info *info); + wmi_unified_t handle, uint8_t *event, + struct tgt_info *info); + +/** + * init_deinit_populate_dbr_ring_cap_ext2() - populate dbr ring capability + * from ext2 event + * @psoc: PSOC object + * @handle: WMI handle pointer + * @event: event buffer received from FW + * @info: tgt_info object + * + * API to populate dbr ring capability + * + * Return: zero on successful parsing of dbr ring capability or failure + */ +int init_deinit_populate_dbr_ring_cap_ext2(struct wlan_objmgr_psoc *psoc, + wmi_unified_t handle, uint8_t *event, + struct tgt_info *info); /** * init_deinit_populate_spectral_bin_scale_params() - populate Spectral scaling @@ -229,7 +208,7 @@ int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc, */ int init_deinit_populate_spectral_bin_scale_params( struct wlan_objmgr_psoc *psoc, - void *handle, uint8_t *event, + wmi_unified_t handle, uint8_t *event, struct tgt_info *info); /** @@ -267,8 +246,9 @@ QDF_STATUS init_deinit_spectral_scaling_params_free( * Return: zero on successful parsing of physical reg capability or failure flag */ int init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc *psoc, - void *wmi_handle, uint8_t *event, - struct tgt_info *info, bool service_ready); + wmi_unified_t wmi_handle, uint8_t *event, + struct tgt_info *info, + bool service_ready); /** * init_deinit_validate_160_80p80_fw_caps() - validate 160 80p80 fw caps diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_cmd_api.c b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_cmd_api.c index ee7db77e2fd46a37a24d31a45b303af594c62da4..ebc0b3b7c8ab2739e8ce0dffb25085908bfd1d45 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_cmd_api.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_cmd_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -182,98 +181,6 @@ static QDF_STATUS init_deinit_alloc_host_mem(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } -/** - * init_deinit_alloc_num_units() - allocates num units requested by FW. - * @psoc: PSOC object - * @tgt_hdl: Target PSOC info - * @mem_reqs: pointer to mem req - * @num_units: Number - * @i: FW priority - * @idx: Index - * - * API to allocate num units of host memory requested by FW - * - * Return: QDF_STATUS_SUCCESS on successful allocation - * QDF_STATUS_E_FAILURE on failure - */ -static QDF_STATUS init_deinit_alloc_num_units(struct wlan_objmgr_psoc *psoc, - struct target_psoc_info *tgt_hdl, - host_mem_req *mem_reqs, uint16_t fw_prio, - uint16_t idx) -{ - struct tgt_info *info; - uint32_t num_units; - QDF_STATUS status; - - if (!tgt_hdl || !mem_reqs) { - target_if_err("Invalid parameters, tgt_hdl: %pK, mem_reqs: %pK", - tgt_hdl, mem_reqs); - return QDF_STATUS_E_INVAL; - } - - info = (&tgt_hdl->info); - - if (((fw_prio == FW_MEM_HIGH_PRIORITY) && - (mem_reqs[idx].num_unit_info & - HOST_CONTIGUOUS_MEM_CHUNK_REQUIRED)) || - ((fw_prio == FW_MEM_LOW_PRIORITY) && - (!(mem_reqs[idx].num_unit_info & - HOST_CONTIGUOUS_MEM_CHUNK_REQUIRED)))) { - /* First allocate the memory that requires contiguous memory */ - num_units = mem_reqs[idx].num_units; - if (mem_reqs[idx].num_unit_info) { - if (mem_reqs[idx].num_unit_info & - NUM_UNITS_IS_NUM_PEERS) { - /* - * number of units allocated is equal to number - * of peers, 1 extra for self peer on target. - * this needs to be fixed, host and target can - * get out of sync - */ - num_units = info->wlan_res_cfg.num_peers + 1; - } - if (mem_reqs[idx].num_unit_info & - NUM_UNITS_IS_NUM_ACTIVE_PEERS) { - /* - * Requesting allocation of memory using - * num_active_peers in qcache. if qcache is - * disabled in host, then it should allocate - * memory for num_peers instead of - * num_active_peers. - */ - if (info->wlan_res_cfg.num_active_peers) - num_units = - info->wlan_res_cfg.num_active_peers + 1; - else - num_units = - info->wlan_res_cfg.num_peers + 1; - } - } - - target_if_debug("idx %d req %d num_units %d num_unit_info %d unit size %d actual units %d", - idx, mem_reqs[idx].req_id, - mem_reqs[idx].num_units, - mem_reqs[idx].num_unit_info, - mem_reqs[idx].unit_size, num_units); - - status = init_deinit_alloc_host_mem(psoc, tgt_hdl, - mem_reqs[idx].req_id, num_units, - mem_reqs[idx].unit_size, - mem_reqs[idx].num_unit_info); - if (status == QDF_STATUS_E_FAILURE) { - target_if_err( - "psoc:(%pK) num_mem_chunk exceeds supp number", - psoc); - return QDF_STATUS_E_FAILURE; - } else if (status == QDF_STATUS_E_NOMEM) { - target_if_err("soc:(%pK) mem alloc failure", psoc); - return QDF_STATUS_E_NOMEM; - } - } - - return QDF_STATUS_SUCCESS; -} - QDF_STATUS init_deinit_free_num_units(struct wlan_objmgr_psoc *psoc, struct target_psoc_info *tgt_hdl) { @@ -300,12 +207,12 @@ QDF_STATUS init_deinit_free_num_units(struct wlan_objmgr_psoc *psoc, info = (&tgt_hdl->info); for (idx = 0; idx < info->num_mem_chunks; idx++) { qdf_mem_free_consistent( - qdf_dev, qdf_dev->dev, - info->mem_chunks[idx].len, - info->mem_chunks[idx].vaddr, - info->mem_chunks[idx].paddr, - qdf_get_dma_mem_context( - (&(info->mem_chunks[idx])), memctx)); + qdf_dev, qdf_dev->dev, + info->mem_chunks[idx].len, + info->mem_chunks[idx].vaddr, + info->mem_chunks[idx].paddr, + qdf_get_dma_mem_context( + (&info->mem_chunks[idx]), memctx)); info->mem_chunks[idx].vaddr = NULL; info->mem_chunks[idx].paddr = 0; @@ -319,15 +226,15 @@ QDF_STATUS init_deinit_free_num_units(struct wlan_objmgr_psoc *psoc, } QDF_STATUS init_deinit_handle_host_mem_req( - struct wlan_objmgr_psoc *psoc, - struct target_psoc_info *tgt_hdl, uint8_t *event) + struct wlan_objmgr_psoc *psoc, + struct target_psoc_info *tgt_hdl, uint8_t *event) { - uint8_t num_mem_reqs; - host_mem_req *mem_reqs; + uint32_t num_mem_reqs; + host_mem_req mem_reqs; uint32_t i; uint32_t idx; QDF_STATUS status = QDF_STATUS_SUCCESS; - struct common_wmi_handle *wmi_handle; + struct wmi_unified *wmi_handle; struct tgt_info *info; if (!tgt_hdl) { @@ -338,21 +245,38 @@ QDF_STATUS init_deinit_handle_host_mem_req( wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl); info = (&tgt_hdl->info); - mem_reqs = wmi_extract_host_mem_req_from_service_ready( - wmi_handle, event, &num_mem_reqs); + num_mem_reqs = wmi_extract_num_mem_reqs_from_service_ready( + wmi_handle, event); if (!num_mem_reqs) return QDF_STATUS_SUCCESS; if (num_mem_reqs > MAX_MEM_CHUNKS) { target_if_err_rl("num_mem_reqs:%u is out of bounds", - num_mem_reqs); + num_mem_reqs); return QDF_STATUS_E_FAILURE; } - for (i = 0; i < FW_PRIORITY_MAX; i++) { + for (i = 0; i < WMI_FW_PRIORITY_MAX; i++) { for (idx = 0; idx < num_mem_reqs; idx++) { - status = init_deinit_alloc_num_units(psoc, tgt_hdl, - mem_reqs, i, idx); + status = wmi_extract_host_mem_req_from_service_ready( + wmi_handle, event, &mem_reqs, + info->wlan_res_cfg.num_active_peers, + info->wlan_res_cfg.num_peers, i, idx); + if (mem_reqs.tgt_num_units) { + status = init_deinit_alloc_host_mem( + psoc, + tgt_hdl, + mem_reqs.req_id, + mem_reqs.tgt_num_units, + mem_reqs.unit_size, + mem_reqs.num_unit_info); + if (status == QDF_STATUS_E_FAILURE) { + target_if_err("num_mem_chunk exceeds supp number"); + } else if (status == QDF_STATUS_E_NOMEM) { + target_if_err("mem alloc failure"); + } + } + if (status != QDF_STATUS_SUCCESS) return status; } @@ -384,8 +308,12 @@ void init_deinit_derive_band_to_mac_param( return; } + mac_phy_cap = target_psoc_get_mac_phy_cap(tgt_hdl); + if (!mac_phy_cap) { + target_if_err("mac_phy_cap is NULL"); + return; + } for (i = 0; i < target_psoc_get_num_radios(tgt_hdl); i++) { - mac_phy_cap = &info->mac_phy_cap[i]; if (mac_phy_cap->supported_bands == (WMI_HOST_WLAN_5G_CAPABILITY | WMI_HOST_WLAN_2G_CAPABILITY)) { @@ -409,9 +337,9 @@ void init_deinit_derive_band_to_mac_param( reg_cap[mac_phy_cap->phy_id].high_5ghz_chan = 0; target_if_debug("2G radio - pdev_id = %d start_freq = %d end_freq= %d", - band_to_mac[i].pdev_id, - band_to_mac[i].start_freq, - band_to_mac[i].end_freq); + band_to_mac[i].pdev_id, + band_to_mac[i].start_freq, + band_to_mac[i].end_freq); } else if (mac_phy_cap->supported_bands == WMI_HOST_WLAN_5G_CAPABILITY) { @@ -425,10 +353,11 @@ void init_deinit_derive_band_to_mac_param( reg_cap[mac_phy_cap->phy_id].high_2ghz_chan = 0; target_if_debug("5G radio -pdev_id = %d start_freq = %d end_freq =%d\n", - band_to_mac[i].pdev_id, - band_to_mac[i].start_freq, - band_to_mac[i].end_freq); + band_to_mac[i].pdev_id, + band_to_mac[i].start_freq, + band_to_mac[i].end_freq); } + mac_phy_cap++; } } @@ -438,7 +367,7 @@ void init_deinit_prepare_send_init_cmd( { struct wmi_init_cmd_param init_param = {0}; struct tgt_info *info; - struct common_wmi_handle *wmi_handle; + struct wmi_unified *wmi_handle; QDF_STATUS ret_val; if (!tgt_hdl) { @@ -483,6 +412,10 @@ void init_deinit_prepare_send_init_cmd( if (ret_val != QDF_STATUS_SUCCESS) return; + info->wlan_res_cfg.max_ndp_sessions = + QDF_MIN(info->wlan_res_cfg.max_ndp_sessions, + info->service_ext2_param.max_ndp_sessions); + target_if_debug("FW version 0x%x ", info->target_caps.fw_version); if (init_deinit_is_service_ext_msg(psoc, tgt_hdl) == QDF_STATUS_SUCCESS) target_if_debug("0x%x\n", diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_deinit_lmac.c b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_deinit_lmac.c index 282934ac231c6ed3e38a9f79b73a6516f46a8c5d..4da2a989350f1d144f35412dd972ae4d466ef9b3 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_deinit_lmac.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_deinit_lmac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 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 @@ -68,20 +68,12 @@ target_resource_config *lmac_get_tgt_res_cfg(struct wlan_objmgr_psoc *psoc) int32_t lmac_get_pdev_idx(struct wlan_objmgr_pdev *pdev) { - struct target_pdev_info *tgt_hdl; - if (!pdev) { target_if_err("pdev is null"); return 0xffffffff; } - tgt_hdl = wlan_pdev_get_tgt_if_handle(pdev); - if (!tgt_hdl) { - target_if_err("target_pdev_info is null"); - return 0xffffffff; - } - - return target_pdev_get_pdev_idx(tgt_hdl); + return wlan_objmgr_pdev_get_pdev_id(pdev); } uint32_t lmac_get_tgt_type(struct wlan_objmgr_psoc *psoc) @@ -187,7 +179,7 @@ bool lmac_is_target_ar900b(struct wlan_objmgr_psoc *psoc) } qdf_export_symbol(lmac_is_target_ar900b); -struct common_wmi_handle *lmac_get_wmi_hdl(struct wlan_objmgr_psoc *psoc) +struct wmi_unified *lmac_get_wmi_hdl(struct wlan_objmgr_psoc *psoc) { struct target_psoc_info *tgt_hdl; @@ -212,7 +204,7 @@ wmi_unified_t lmac_get_wmi_unified_hdl(struct wlan_objmgr_psoc *psoc) } qdf_export_symbol(lmac_get_wmi_unified_hdl); -struct common_htc_handle *lmac_get_htc_hdl(struct wlan_objmgr_psoc *psoc) +HTC_HANDLE lmac_get_htc_hdl(struct wlan_objmgr_psoc *psoc) { struct target_psoc_info *tgt_hdl; @@ -232,7 +224,7 @@ struct common_htc_handle *lmac_get_htc_hdl(struct wlan_objmgr_psoc *psoc) qdf_export_symbol(lmac_get_htc_hdl); void lmac_set_htc_hdl(struct wlan_objmgr_psoc *psoc, - struct common_htc_handle *htc_hdl) + HTC_HANDLE htc_hdl) { struct target_psoc_info *tgt_hdl; @@ -240,7 +232,7 @@ void lmac_set_htc_hdl(struct wlan_objmgr_psoc *psoc, target_if_err("psoc is null"); return; } - tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle(psoc); + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); if (!tgt_hdl) { target_if_err("target_psoc_info is null"); return; @@ -249,7 +241,7 @@ void lmac_set_htc_hdl(struct wlan_objmgr_psoc *psoc, target_psoc_set_htc_hdl(tgt_hdl, htc_hdl); } -struct common_hif_handle *lmac_get_hif_hdl(struct wlan_objmgr_psoc *psoc) +struct hif_opaque_softc *lmac_get_hif_hdl(struct wlan_objmgr_psoc *psoc) { struct target_psoc_info *tgt_hdl; @@ -274,7 +266,7 @@ struct hif_opaque_softc *lmac_get_ol_hif_hdl(struct wlan_objmgr_psoc *psoc) } qdf_export_symbol(lmac_get_ol_hif_hdl); -struct common_wmi_handle *lmac_get_pdev_wmi_handle( +struct wmi_unified *lmac_get_pdev_wmi_handle( struct wlan_objmgr_pdev *pdev) { struct target_pdev_info *tgt_hdl; diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_event_handler.c b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_event_handler.c index cad714de81a9358023f89fca4c1419da130ea804..5868c1a84d05a1e137cacffc3a6f92242a45deae 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_event_handler.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/init_event_handler.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 @@ -49,7 +49,7 @@ static int init_deinit_service_ready_event_handler(ol_scn_t scn_handle, struct wlan_objmgr_psoc *psoc; struct target_psoc_info *tgt_hdl; wmi_legacy_service_ready_callback legacy_callback; - struct common_wmi_handle *wmi_handle; + struct wmi_unified *wmi_handle; QDF_STATUS ret_val; if (!scn_handle) { @@ -63,8 +63,7 @@ static int init_deinit_service_ready_event_handler(ol_scn_t scn_handle, return -EINVAL; } - tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( - psoc); + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); if (!tgt_hdl) { target_if_err("target_psoc_info is null in service ready ev"); return -EINVAL; @@ -124,6 +123,18 @@ static int init_deinit_service_ready_event_handler(ol_scn_t scn_handle, if (wmi_service_enabled(wmi_handle, wmi_service_infra_mbssid)) wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_MBSS_IE); + if (wmi_service_enabled(wmi_handle, wmi_service_dynamic_hw_mode)) + wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_DYNAMIC_HW_MODE); + + if (wmi_service_enabled(wmi_handle, wmi_service_bw_165mhz_support)) + wlan_psoc_nif_fw_ext_cap_set(psoc, + WLAN_SOC_RESTRICTED_80P80_SUPPORT); + + if (wmi_service_enabled(wmi_handle, + wmi_service_nss_ratio_to_host_support)) + wlan_psoc_nif_fw_ext_cap_set( + psoc, WLAN_SOC_NSS_RATIO_TO_HOST_SUPPORT); + target_if_debug(" TT support %d, Wide BW Scan %d, SW cal %d", wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_TT_SUPPORT), wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_WIDEBAND_SCAN), @@ -146,6 +157,10 @@ static int init_deinit_service_ready_event_handler(ol_scn_t scn_handle, target_if_lteu_cfg_enable(psoc, tgt_hdl, event); + if (wmi_service_enabled(wmi_handle, wmi_service_rx_fse_support)) + wlan_psoc_nif_fw_ext_cap_set(psoc, + WLAN_SOC_CEXT_RX_FSE_SUPPORT); + /* override derived value, if it exceeds max peer count */ if ((wlan_psoc_get_max_peer_count(psoc) > tgt_hdl->info.wlan_res_cfg.num_active_peers) && @@ -201,7 +216,7 @@ static int init_deinit_service_ext2_ready_event_handler(ol_scn_t scn_handle, int err_code = 0; struct wlan_objmgr_psoc *psoc; struct target_psoc_info *tgt_hdl; - struct common_wmi_handle *wmi_handle; + struct wmi_unified *wmi_handle; struct tgt_info *info; if (!scn_handle) { @@ -229,6 +244,15 @@ static int init_deinit_service_ext2_ready_event_handler(ol_scn_t scn_handle, if (err_code) goto exit; + /* dbr_ring_caps could have already come as part of EXT event */ + if (info->service_ext2_param.num_dbr_ring_caps) { + err_code = init_deinit_populate_dbr_ring_cap_ext2(psoc, + wmi_handle, + event, info); + if (err_code) + goto exit; + } + /* send init command */ init_deinit_set_send_init_cmd(psoc, tgt_hdl); @@ -241,9 +265,10 @@ static int init_deinit_service_ext_ready_event_handler(ol_scn_t scn_handle, uint32_t data_len) { int err_code; + uint8_t num_radios; struct wlan_objmgr_psoc *psoc; struct target_psoc_info *tgt_hdl; - struct common_wmi_handle *wmi_handle; + struct wmi_unified *wmi_handle; struct tgt_info *info; wmi_legacy_service_ready_callback legacy_callback; @@ -258,8 +283,7 @@ static int init_deinit_service_ext_ready_event_handler(ol_scn_t scn_handle, return -EINVAL; } - tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( - psoc); + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); if (!tgt_hdl) { target_if_err("target_psoc_info is null in service ready ev"); return -EINVAL; @@ -286,20 +310,11 @@ static int init_deinit_service_ext_ready_event_handler(ol_scn_t scn_handle, return -EINVAL; } - if (info->preferred_hw_mode != WMI_HOST_HW_MODE_MAX) { - struct wlan_psoc_host_hw_mode_caps *hw_cap = &info->hw_mode_cap; - /* prune info mac_phy cap to preferred/selected mode caps */ - info->total_mac_phy_cnt = 0; - err_code = init_deinit_populate_mac_phy_capability(wmi_handle, - event, - hw_cap, - info); - if (err_code) - goto exit; + num_radios = target_psoc_get_num_radios_for_mode(tgt_hdl, + info->preferred_hw_mode); - info->num_radios = info->total_mac_phy_cnt; - target_if_debug("num radios is %d\n", info->num_radios); - } + /* set number of radios based on current mode */ + target_psoc_set_num_radios(tgt_hdl, num_radios); target_if_print_service_ready_ext_param(psoc, tgt_hdl); @@ -320,17 +335,13 @@ static int init_deinit_service_ext_ready_event_handler(ol_scn_t scn_handle, goto exit; } - err_code = init_deinit_populate_rf_characterization_entries( - wmi_handle, - event, - &info->service_ext_param); - if (err_code) - goto exit; - - err_code = init_deinit_populate_dbr_ring_cap(psoc, wmi_handle, - event, info); - if (err_code) - goto exit; + /* dbr_ring_caps can be absent if enough space is not available */ + if (info->service_ext_param.num_dbr_ring_caps) { + err_code = init_deinit_populate_dbr_ring_cap(psoc, wmi_handle, + event, info); + if (err_code) + goto exit; + } err_code = init_deinit_populate_spectral_bin_scale_params(psoc, wmi_handle, @@ -347,11 +358,6 @@ static int init_deinit_service_ext_ready_event_handler(ol_scn_t scn_handle, target_if_set_twt_ap_pdev_count(info, tgt_hdl); - info->wlan_res_cfg.num_vdevs = (target_psoc_get_num_radios(tgt_hdl) * - info->wlan_res_cfg.num_vdevs); - info->wlan_res_cfg.beacon_tx_offload_max_vdev = - (target_psoc_get_num_radios(tgt_hdl) * - info->wlan_res_cfg.beacon_tx_offload_max_vdev); info->wlan_res_cfg.max_bssid_indicator = info->service_ext_param.max_bssid_indicator; @@ -372,7 +378,7 @@ static int init_deinit_service_available_handler(ol_scn_t scn_handle, { struct wlan_objmgr_psoc *psoc; struct target_psoc_info *tgt_hdl; - struct common_wmi_handle *wmi_handle; + struct wmi_unified *wmi_handle; if (!scn_handle) { target_if_err("scn handle NULL"); @@ -385,8 +391,7 @@ static int init_deinit_service_available_handler(ol_scn_t scn_handle, return -EINVAL; } - tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( - psoc); + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); if (!tgt_hdl) { target_if_err("target_psoc_info is null"); return -EINVAL; @@ -413,7 +418,7 @@ static int init_deinit_ready_event_handler(ol_scn_t scn_handle, struct wlan_objmgr_psoc *psoc; struct wlan_objmgr_pdev *pdev; struct target_psoc_info *tgt_hdl; - struct common_wmi_handle *wmi_handle; + struct wmi_unified *wmi_handle; struct wmi_host_fw_abi_ver fw_ver; uint8_t myaddr[QDF_MAC_ADDR_SIZE]; struct tgt_info *info; @@ -435,8 +440,7 @@ static int init_deinit_ready_event_handler(ol_scn_t scn_handle, return -EINVAL; } - tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( - psoc); + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); if (!tgt_hdl) { target_if_err("target_psoc_info is null"); return -EINVAL; @@ -467,8 +471,26 @@ static int init_deinit_ready_event_handler(ol_scn_t scn_handle, else info->wlan_res_cfg.agile_capability = ready_ev.agile_capability; + /* Indicate to the waiting thread that the ready + * event was received + */ + info->wlan_init_status = wmi_ready_extract_init_status( + wmi_handle, event); + + legacy_callback = target_if_get_psoc_legacy_service_ready_cb(); + if (legacy_callback) + if (legacy_callback(wmi_ready_event_id, + scn_handle, event, data_len)) { + target_if_err("Legacy callback returned error!"); + tgt_hdl->info.wmi_ready = FALSE; + goto exit; + } + + num_radios = target_psoc_get_num_radios(tgt_hdl); + if ((ready_ev.num_total_peer != 0) && (info->wlan_res_cfg.num_peers != ready_ev.num_total_peer)) { + uint16_t num_peers = 0; /* FW allocated number of peers is different than host * requested. Update host max with FW reported value. */ @@ -476,6 +498,22 @@ static int init_deinit_ready_event_handler(ol_scn_t scn_handle, info->wlan_res_cfg.num_peers, ready_ev.num_total_peer); info->wlan_res_cfg.num_peers = ready_ev.num_total_peer; + num_peers = info->wlan_res_cfg.num_peers / num_radios; + + for (i = 0; i < num_radios; i++) { + pdev = wlan_objmgr_get_pdev_by_id(psoc, i, + WLAN_INIT_DEINIT_ID); + if (!pdev) { + target_if_err(" PDEV %d is NULL", i); + return -EINVAL; + } + + wlan_pdev_set_max_peer_count(pdev, num_peers); + wlan_objmgr_pdev_release_ref(pdev, WLAN_INIT_DEINIT_ID); + } + + wlan_psoc_set_max_peer_count(psoc, + info->wlan_res_cfg.num_peers); } /* for non legacy num_total_peer will be non zero @@ -495,22 +533,22 @@ static int init_deinit_ready_event_handler(ol_scn_t scn_handle, } } - /* Indicate to the waiting thread that the ready - * event was received - */ - info->wlan_init_status = wmi_ready_extract_init_status( - wmi_handle, event); - legacy_callback = target_if_get_psoc_legacy_service_ready_cb(); - if (legacy_callback) - if (legacy_callback(wmi_ready_event_id, - scn_handle, event, data_len)) { - target_if_err("Legacy callback returned error!"); - tgt_hdl->info.wmi_ready = FALSE; - goto exit; + if (ready_ev.pktlog_defs_checksum) { + for (i = 0; i < num_radios; i++) { + pdev = wlan_objmgr_get_pdev_by_id(psoc, i, + WLAN_INIT_DEINIT_ID); + if (!pdev) { + target_if_err(" PDEV %d is NULL", i); + return -EINVAL; + } + target_if_set_pktlog_checksum(pdev, tgt_hdl, + ready_ev. + pktlog_defs_checksum); + wlan_objmgr_pdev_release_ref(pdev, WLAN_INIT_DEINIT_ID); } + } - num_radios = target_psoc_get_num_radios(tgt_hdl); /* * For non-legacy HW, MAC addr list is extracted. */ @@ -587,8 +625,7 @@ QDF_STATUS init_deinit_register_tgt_psoc_ev_handlers( return QDF_STATUS_E_FAILURE; } - tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( - psoc); + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); if (!tgt_hdl) { target_if_err("target_psoc_info null in register wmi hadler"); return QDF_STATUS_E_FAILURE; diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/service_ready_util.c b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/service_ready_util.c index 0a6b4534b4859715c7e1e372cc476a7ab78047d8..21bc668947b8dbfaf7f43256c2715f28236aa2a8 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/service_ready_util.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/init_deinit/src/service_ready_util.c @@ -26,51 +26,6 @@ #include #include -#ifdef WLAN_SUPPORT_RF_CHARACTERIZATION -QDF_STATUS init_deinit_populate_rf_characterization_entries(void *handle, - uint8_t *evt, - struct wlan_psoc_host_service_ext_param *ser_ext_par) -{ - uint32_t alloc_size; - QDF_STATUS status = QDF_STATUS_SUCCESS; - - if (ser_ext_par->num_rf_characterization_entries == 0) - return QDF_STATUS_SUCCESS; - - alloc_size = (sizeof(struct wlan_psoc_host_rf_characterization_entry) * - ser_ext_par->num_rf_characterization_entries); - - ser_ext_par->rf_characterization_entries = qdf_mem_malloc(alloc_size); - if (!ser_ext_par->rf_characterization_entries) { - init_deinit_rf_characterization_entries_free(ser_ext_par); - return QDF_STATUS_E_NOMEM; - } - - status = wmi_extract_rf_characterization_entries(handle, evt, - ser_ext_par->rf_characterization_entries); - if (QDF_IS_STATUS_ERROR(status)) { - target_if_err("failed to parse wmi service ready ext param"); - init_deinit_rf_characterization_entries_free(ser_ext_par); - } - - return status; -} - -qdf_export_symbol(init_deinit_populate_rf_characterization_entries); - -QDF_STATUS init_deinit_rf_characterization_entries_free( - struct wlan_psoc_host_service_ext_param *ser_ext_par) -{ - qdf_mem_free(ser_ext_par->rf_characterization_entries); - ser_ext_par->rf_characterization_entries = NULL; - ser_ext_par->num_rf_characterization_entries = 0; - - return QDF_STATUS_SUCCESS; -} - -qdf_export_symbol(init_deinit_rf_characterization_entries_free); -#endif - QDF_STATUS init_deinit_chainmask_table_alloc( struct wlan_psoc_host_service_ext_param *ser_ext_par) { @@ -128,8 +83,9 @@ QDF_STATUS init_deinit_chainmask_table_free( qdf_export_symbol(init_deinit_chainmask_table_free); -int init_deinit_populate_service_bitmap(void *wmi_handle, uint8_t *event, - uint32_t *service_bitmap) +int init_deinit_populate_service_bitmap( + wmi_unified_t wmi_handle, uint8_t *event, + uint32_t *service_bitmap) { QDF_STATUS status; @@ -142,7 +98,8 @@ int init_deinit_populate_service_bitmap(void *wmi_handle, uint8_t *event, return 0; } -int init_deinit_populate_fw_version_cmd(void *wmi_handle, uint8_t *event) +int init_deinit_populate_fw_version_cmd(wmi_unified_t wmi_handle, + uint8_t *event) { QDF_STATUS status; @@ -153,8 +110,9 @@ int init_deinit_populate_fw_version_cmd(void *wmi_handle, uint8_t *event) return 0; } -int init_deinit_populate_target_cap(void *wmi_handle, uint8_t *event, - struct wlan_psoc_target_capability_info *cap) +int init_deinit_populate_target_cap( + wmi_unified_t wmi_handle, uint8_t *event, + struct wlan_psoc_target_capability_info *cap) { QDF_STATUS status; @@ -167,8 +125,9 @@ int init_deinit_populate_target_cap(void *wmi_handle, uint8_t *event, return 0; } -int init_deinit_populate_service_ready_ext_param(void *handle, uint8_t *evt, - struct wlan_psoc_host_service_ext_param *param) +int init_deinit_populate_service_ready_ext_param( + wmi_unified_t handle, uint8_t *evt, + struct wlan_psoc_host_service_ext_param *param) { QDF_STATUS status; @@ -182,7 +141,7 @@ int init_deinit_populate_service_ready_ext_param(void *handle, uint8_t *evt, } int init_deinit_populate_service_ready_ext2_param( - void *handle, uint8_t *evt, + wmi_unified_t handle, uint8_t *evt, struct tgt_info *info) { QDF_STATUS status; @@ -197,7 +156,8 @@ int init_deinit_populate_service_ready_ext2_param( return 0; } -int init_deinit_populate_chainmask_tables(void *handle, uint8_t *evt, +int init_deinit_populate_chainmask_tables( + wmi_unified_t handle, uint8_t *evt, struct wlan_psoc_host_chainmask_table *param) { QDF_STATUS status; @@ -211,7 +171,8 @@ int init_deinit_populate_chainmask_tables(void *handle, uint8_t *evt, return 0; } -int init_deinit_populate_mac_phy_capability(void *handle, uint8_t *evt, +int init_deinit_populate_mac_phy_capability( + wmi_unified_t handle, uint8_t *evt, struct wlan_psoc_host_hw_mode_caps *hw_cap, struct tgt_info *info) { QDF_STATUS status; @@ -250,8 +211,8 @@ int init_deinit_populate_mac_phy_capability(void *handle, uint8_t *evt, return 0; } -static int get_hw_mode(void *handle, uint8_t *evt, uint8_t hw_idx, - struct wlan_psoc_host_hw_mode_caps *cap) +static int get_hw_mode(wmi_unified_t handle, uint8_t *evt, uint8_t hw_idx, + struct wlan_psoc_host_hw_mode_caps *cap) { QDF_STATUS status; @@ -265,7 +226,7 @@ static int get_hw_mode(void *handle, uint8_t *evt, uint8_t hw_idx, return 0; } -static int get_sar_version(void *handle, uint8_t *evt, +static int get_sar_version(wmi_unified_t handle, uint8_t *evt, struct wlan_psoc_host_service_ext_param *ext_param) { QDF_STATUS status; @@ -349,8 +310,9 @@ select_preferred_hw_mode(struct target_psoc_info *tgt_hdl, return selected_mode; } -int init_deinit_populate_hw_mode_capability(void *wmi_handle, - uint8_t *event, struct target_psoc_info *tgt_hdl) +int init_deinit_populate_hw_mode_capability( + wmi_unified_t wmi_handle, uint8_t *event, + struct target_psoc_info *tgt_hdl) { QDF_STATUS status = QDF_STATUS_SUCCESS; uint8_t hw_idx; @@ -408,7 +370,8 @@ int init_deinit_populate_hw_mode_capability(void *wmi_handle, } int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc, - void *handle, uint8_t *event, struct tgt_info *info) + wmi_unified_t handle, uint8_t *event, + struct tgt_info *info) { uint8_t cap_idx; @@ -416,7 +379,6 @@ int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc, QDF_STATUS status = QDF_STATUS_SUCCESS; num_dbr_ring_caps = info->service_ext_param.num_dbr_ring_caps; - target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps); if (!num_dbr_ring_caps) @@ -448,8 +410,62 @@ int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc, return qdf_status_to_os_return(status); } +int init_deinit_populate_dbr_ring_cap_ext2(struct wlan_objmgr_psoc *psoc, + wmi_unified_t handle, uint8_t *event, + struct tgt_info *info) + +{ + uint8_t cap_idx; + uint32_t num_dbr_ring_caps; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct wlan_psoc_host_dbr_ring_caps *param; + + /* + * If FW had already sent this info as part of EXT event, + * we need to discard the same and use the info from EXT2. + */ + if (info->service_ext_param.num_dbr_ring_caps) { + target_if_debug("dbr_ring_caps already populated"); + info->service_ext_param.num_dbr_ring_caps = 0; + qdf_mem_free(info->dbr_ring_cap); + info->dbr_ring_cap = NULL; + } + + num_dbr_ring_caps = info->service_ext2_param.num_dbr_ring_caps; + target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps); + + if (!num_dbr_ring_caps) + return 0; + + info->dbr_ring_cap = qdf_mem_malloc( + sizeof(struct wlan_psoc_host_dbr_ring_caps) * + num_dbr_ring_caps); + + if (!info->dbr_ring_cap) + return -EINVAL; + + for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) { + param = &info->dbr_ring_cap[cap_idx]; + status = wmi_extract_dbr_ring_cap_service_ready_ext2(handle, + event, + cap_idx, + param); + if (QDF_IS_STATUS_ERROR(status)) { + target_if_err("Extraction of DMA cap failed"); + goto free_and_return; + } + } + + return 0; + +free_and_return: + qdf_mem_free(info->dbr_ring_cap); + info->dbr_ring_cap = NULL; + + return qdf_status_to_os_return(status); +} int init_deinit_populate_spectral_bin_scale_params( - struct wlan_objmgr_psoc *psoc, void *handle, + struct wlan_objmgr_psoc *psoc, wmi_unified_t handle, uint8_t *event, struct tgt_info *info) { @@ -521,9 +537,70 @@ QDF_STATUS init_deinit_spectral_scaling_params_free( qdf_export_symbol(init_deinit_spectral_scaling_params_free); +#ifdef DBS_SBS_BAND_LIMITATION_WAR +#define phy0 0 +#define phy2 2 +#define NUM_RF_MODES 2 /* (DBS + DBS_SBS) */ +/** + * init_deinit_update_phy_reg_cap() - Update the low/high frequency for phy0. + * @psoc: PSOC common object + * @info: FW or lower layer related info + * @wlan_psoc_host_hal_reg_capabilities_ext: Reg caps per PHY + * + * For the DBS_SBS capable board, update the low or high frequency + * for phy0 by leveraging the frequency populated for phy2 + * depending on whether it is mapped to upper or lower 5G band by + * FW/HAL-PHY. + */ +static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc, + struct tgt_info *info, + struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap) +{ + struct target_psoc_info *tgt_hdl; + enum wmi_host_hw_mode_config_type mode; + uint32_t num_hw_modes; + uint8_t idx; + + tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( + psoc); + if (!tgt_hdl) { + target_if_err("target_psoc_info is null in service ready ev"); + return; + } + + mode = target_psoc_get_preferred_hw_mode(tgt_hdl); + + num_hw_modes = info->hw_modes.num_modes; + + if ((mode != WMI_HOST_HW_MODE_DBS) || (num_hw_modes < NUM_RF_MODES)) + return; + + for (idx = 0; idx < num_hw_modes; idx++) + if (info->hw_modes.hw_mode_ids[idx] == + WMI_HOST_HW_MODE_DBS_SBS) { + if (reg_cap[phy0].low_5ghz_chan > + reg_cap[phy2].low_5ghz_chan) + reg_cap[phy0].low_5ghz_chan = + reg_cap[phy2].low_5ghz_chan; + else if (reg_cap[phy0].high_5ghz_chan < + reg_cap[phy2].high_5ghz_chan) + reg_cap[phy0].high_5ghz_chan = + reg_cap[phy2].high_5ghz_chan; + break; + } +} +#else +static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc, + struct tgt_info *info, + struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap) +{ +} +#endif + int init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc *psoc, - void *handle, uint8_t *event, - struct tgt_info *info, bool service_ready) + wmi_unified_t handle, uint8_t *event, + struct tgt_info *info, + bool service_ready) { uint8_t reg_idx; uint32_t num_phy_reg_cap; @@ -564,6 +641,7 @@ int init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc *psoc, } } + init_deinit_update_phy_reg_cap(psoc, info, reg_cap); status = ucfg_reg_set_hal_reg_cap(psoc, reg_cap, num_phy_reg_cap); return qdf_status_to_os_return(status); @@ -609,7 +687,7 @@ QDF_STATUS init_deinit_validate_160_80p80_fw_caps( bool vhtcap_160mhz_sgi = false; bool valid = false; struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap; - struct common_wmi_handle *wmi_handle; + struct wmi_unified *wmi_handle; if (!tgt_hdl) { target_if_err( @@ -724,7 +802,7 @@ QDF_STATUS init_deinit_is_service_ext_msg( struct wlan_objmgr_psoc *psoc, struct target_psoc_info *tgt_hdl) { - struct common_wmi_handle *wmi_handle; + struct wmi_unified *wmi_handle; if (!tgt_hdl) { target_if_err( @@ -758,6 +836,15 @@ bool init_deinit_is_preferred_hw_mode_supported( if (info->preferred_hw_mode == WMI_HOST_HW_MODE_MAX) return TRUE; + if (wlan_psoc_nif_feat_cap_get(psoc, WLAN_SOC_F_DYNAMIC_HW_MODE)) { + if (!wlan_psoc_nif_fw_ext_cap_get(psoc, + WLAN_SOC_CEXT_DYNAMIC_HW_MODE)) { + target_if_err( + "WMI service bit for DYNAMIC HW mode is not set!"); + return FALSE; + } + } + for (i = 0; i < target_psoc_get_total_mac_phy_cnt(tgt_hdl); i++) { if (info->mac_phy_cap[i].hw_mode_id == info->preferred_hw_mode) return TRUE; diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/inc/target_if_psoc_timer_tx_ops.h b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/inc/target_if_psoc_timer_tx_ops.h new file mode 100644 index 0000000000000000000000000000000000000000..ad781db7fb60fd90a152db1f52ce527df8a7cb30 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/inc/target_if_psoc_timer_tx_ops.h @@ -0,0 +1,94 @@ + +/* + * Copyright (c) 2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: target_if_psoc_timer_tx_ops.h + * + * This file provide declaration for APIs registered through lmac Tx Ops + */ + +#ifndef __TARGET_IF_PSOC_TIMER_TX_OPS_H__ +#define __TARGET_IF_PSOC_TIMER_TX_OPS_H__ + +/** + * target_if_psoc_vdev_rsp_timer_inuse() - API to check if the response timer + * for vdev is inuse + * @psoc: Psoc object + * @vdev_id: Vdev object id + * + * Return: QDF_STATUS_E_ALREADY in case the timer is inuse or QDF_STATUS_SUCCESS + */ +QDF_STATUS target_if_psoc_vdev_rsp_timer_inuse(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); + +/** + * target_if_flush_psoc_vdev_timers() - API to flush target_if response timers + * for vdev + * @psoc: pointer to psoc object + * + * This API is used to flush target_if response timer. This API used while + * wlan driver shutdown. + * + * Return: none + */ +void target_if_flush_psoc_vdev_timers(struct wlan_objmgr_psoc *psoc); + +/** + * target_if_psoc_vdev_rsp_timer_init() - API to initialize response timers for + * vdev from psoc + * @psoc: pointer to psoc object + * @vdev_id: vdev id for which response timer to be retrieved + * + * This API is used to initialize vdev response timer for vdev-id. + * + * Return: QDF_STATUS + */ +QDF_STATUS target_if_psoc_vdev_rsp_timer_init(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); + +/** + * target_if_psoc_vdev_rsp_timer_deinit() - API to de-initialize response timers + * for vdev from psoc + * @psoc: pointer to psoc object + * @vdev_id: vdev id for which response timer to be retrieved + * + * This API is used to de-initialize vdev response timer from vdev-id. + * + * Return: none + */ +void target_if_psoc_vdev_rsp_timer_deinit(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); + +/** + * target_if_vdev_mgr_rsp_timer_mod() - API to modify time of response timers + * for vdev from psoc + * @psoc: pointer to psoc object + * @vdev_id: vdev id for which response timer to be retrieved + * @mseconds: milli seconds + * + * This API is used to modify vdev response timer for vdev-id. + * + * Return: none + */ +QDF_STATUS target_if_vdev_mgr_rsp_timer_mod( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + int mseconds); + +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/inc/target_if_psoc_wake_lock.h b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/inc/target_if_psoc_wake_lock.h new file mode 100644 index 0000000000000000000000000000000000000000..7451dd5cb5646a0d686b3296c493141151d7e9d2 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/inc/target_if_psoc_wake_lock.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2013-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: target_if_psoc_wake_lock.h + * + * This file provides declaration for wakelock APIs + */ + +#ifndef __TARGET_IF_PSOC_WAKE_LOCK_H__ +#define __TARGET_IF_PSOC_WAKE_LOCK_H__ + +#include +#include + +#ifdef FEATURE_VDEV_RSP_WAKELOCK +/** + * struct wlan_vdev_wakelock - vdev wake lock sub structure + * @start_wakelock: wakelock for vdev start + * @stop_wakelock: wakelock for vdev stop + * @delete_wakelock: wakelock for vdev delete + * @wmi_cmd_rsp_runtime_lock: run time lock + */ +struct psoc_mlme_wakelock { + qdf_wake_lock_t start_wakelock; + qdf_wake_lock_t stop_wakelock; + qdf_wake_lock_t delete_wakelock; + qdf_runtime_lock_t wmi_cmd_rsp_runtime_lock; +}; +#endif + +enum wakelock_mode { + START_WAKELOCK, + STOP_WAKELOCK, + DELETE_WAKELOCK +}; + +#ifdef FEATURE_VDEV_RSP_WAKELOCK + +/** + * target_if_wake_lock_init() - API to initialize + wakelocks:start, + stop and delete. + * @psoc: pointer to psoc + * + * This also initialize the runtime lock + * + * Return: None + */ +void target_if_wake_lock_init(struct wlan_objmgr_psoc *psoc); + +/** + * target_if_wake_lock_deinit() - API to destroy + wakelocks:start, stop and delete. + * @psoc: pointer to psoc + * + * This also destroy the runtime lock + * + * Return: None + */ +void target_if_wake_lock_deinit(struct wlan_objmgr_psoc *psoc); + +/** + * target_if_start_wake_lock_timeout_acquire() - acquire the + vdev start wakelock + * @psoc: pointer to psoc + * + * This also acquires the target_if runtime pm lock. + * + * Return: Success/Failure + */ +QDF_STATUS target_if_wake_lock_timeout_acquire(struct wlan_objmgr_psoc *psoc, + enum wakelock_mode mode); +/** + * target_if_start_wake_lock_timeout_release() - release the + start wakelock + * @psoc: pointer to psoc + * + * This also release the target_if runtime pm lock. + * + * Return: Success/Failure + */ +QDF_STATUS target_if_wake_lock_timeout_release(struct wlan_objmgr_psoc *psoc, + enum wakelock_mode mode); +#else +static inline void target_if_wake_lock_init(struct wlan_objmgr_psoc *psoc) +{ +} + +static inline void target_if_wake_lock_deinit(struct wlan_objmgr_psoc *psoc) +{ +} + +static inline QDF_STATUS target_if_wake_lock_timeout_acquire( + struct wlan_objmgr_psoc *psoc, + enum wakelock_mode mode) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS target_if_wake_lock_timeout_release( + struct wlan_objmgr_psoc *psoc, + enum wakelock_mode mode) +{ + return QDF_STATUS_SUCCESS; +} +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/src/target_if_psoc_timer_tx_ops.c b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/src/target_if_psoc_timer_tx_ops.c new file mode 100644 index 0000000000000000000000000000000000000000..7936e1f83415b3c5cb28905ce8a1cee00dab1dac --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/src/target_if_psoc_timer_tx_ops.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: target_if_psoc_timer_tx_ops.c + * + * This file provide definition for APIs registered through lmac Tx Ops + */ + +#include +#include +#include +#include +#include +#include + +QDF_STATUS target_if_psoc_vdev_rsp_timer_inuse(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ + struct vdev_response_timer *vdev_rsp; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + + if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) { + mlme_err("Invalid vdev id passed VDEV_%d", vdev_id); + return QDF_STATUS_E_INVAL; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops && !rx_ops->psoc_get_vdev_response_timer_info) { + mlme_err("VDEV_%d PSOC_%d No Rx Ops", vdev_id, + wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; + } + + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); + if (!vdev_rsp) { + mlme_err("vdev response is NULL for VDEV_%d PSOC_%d", + vdev_id, wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; + } + + if (qdf_atomic_read(&vdev_rsp->rsp_timer_inuse)) { + mlme_err("vdev response timer still inuse VDEV_%d PSOC_%d", + vdev_id, wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_ALREADY; + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS target_if_psoc_vdev_rsp_timer_init(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ + struct vdev_response_timer *vdev_rsp; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + + if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) { + mlme_err("Invalid vdev id passed VDEV_%d PSOC_%d", vdev_id, + wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops && !rx_ops->psoc_get_vdev_response_timer_info) { + mlme_err("VDEV_%d PSOC_%d No Rx Ops", vdev_id, + wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; + } + + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); + if (!vdev_rsp) { + mlme_err("vdev response is NULL for VDEV_%d PSOC_%d", + vdev_id, wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; + } + + vdev_rsp->psoc = psoc; + vdev_rsp->vdev_id = vdev_id; + qdf_timer_init(NULL, &vdev_rsp->rsp_timer, + target_if_vdev_mgr_rsp_timer_mgmt_cb, + vdev_rsp, QDF_TIMER_TYPE_WAKE_APPS); + qdf_atomic_init(&vdev_rsp->rsp_timer_inuse); + + return QDF_STATUS_SUCCESS; +} + +void target_if_psoc_vdev_rsp_timer_deinit(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ + struct vdev_response_timer *vdev_rsp; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + + if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) { + mlme_err("Invalid vdev id passed VDEV_%d PSOC_%d", vdev_id, + wlan_psoc_get_id(psoc)); + return; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops && !rx_ops->psoc_get_vdev_response_timer_info) { + mlme_err("VDEV_%d PSOC_%d No Rx Ops", vdev_id, + wlan_psoc_get_id(psoc)); + return; + } + + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); + if (!vdev_rsp) { + mlme_err("vdev response is NULL for VDEV_%d PSOC_%d", + vdev_id, wlan_psoc_get_id(psoc)); + return; + } + + qdf_timer_free(&vdev_rsp->rsp_timer); + qdf_atomic_set(&vdev_rsp->rsp_timer_inuse, 0); + vdev_rsp->psoc = NULL; +} + +void target_if_flush_psoc_vdev_timers(struct wlan_objmgr_psoc *psoc) +{ + struct vdev_response_timer *vdev_rsp; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + int i; + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops && !rx_ops->psoc_get_vdev_response_timer_info) { + mlme_err("PSOC_%d No Rx Ops", wlan_psoc_get_id(psoc)); + return; + } + + for (i = 0; i < WLAN_UMAC_PSOC_MAX_VDEVS; i++) { + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, + i); + if (vdev_rsp && qdf_timer_sync_cancel(&vdev_rsp->rsp_timer)) + target_if_vdev_mgr_rsp_timer_cb(vdev_rsp); + } +} + +QDF_STATUS target_if_vdev_mgr_rsp_timer_mod( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + int mseconds) +{ + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + struct vdev_response_timer *vdev_rsp; + + if (!psoc) { + mlme_err("Invalid input"); + return QDF_STATUS_E_FAILURE; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops && !rx_ops->psoc_get_vdev_response_timer_info) { + mlme_err("VDEV_%d PSOC_%d No Rx Ops", vdev_id, + wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_FAILURE; + } + + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); + qdf_timer_mod(&vdev_rsp->rsp_timer, mseconds); + return QDF_STATUS_SUCCESS; +} + diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/src/target_if_psoc_wake_lock.c b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/src/target_if_psoc_wake_lock.c new file mode 100644 index 0000000000000000000000000000000000000000..6028911d5a2e38bd7077247fb7ac254c2ff01e1c --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/psoc/src/target_if_psoc_wake_lock.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2013-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: target_if_psoc_wake_lock.c + * + * This file provide definition for APIs related to wake lock + */ + +#include "qdf_lock.h" +#include +#include +#include +#include +#include +#include + +void target_if_wake_lock_init(struct wlan_objmgr_psoc *psoc) +{ + struct psoc_mlme_wakelock *psoc_wakelock; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->psoc_get_wakelock_info) { + mlme_err("psoc_id:%d No Rx Ops", wlan_psoc_get_id(psoc)); + return; + } + + psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc); + + qdf_wake_lock_create(&psoc_wakelock->start_wakelock, "vdev_start"); + qdf_wake_lock_create(&psoc_wakelock->stop_wakelock, "vdev_stop"); + qdf_wake_lock_create(&psoc_wakelock->delete_wakelock, "vdev_delete"); + + qdf_runtime_lock_init(&psoc_wakelock->wmi_cmd_rsp_runtime_lock); +} + +void target_if_wake_lock_deinit(struct wlan_objmgr_psoc *psoc) +{ + struct psoc_mlme_wakelock *psoc_wakelock; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->psoc_get_wakelock_info) { + mlme_err("psoc_id:%d No Rx Ops", wlan_psoc_get_id(psoc)); + return; + } + + psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc); + + qdf_wake_lock_destroy(&psoc_wakelock->start_wakelock); + qdf_wake_lock_destroy(&psoc_wakelock->stop_wakelock); + qdf_wake_lock_destroy(&psoc_wakelock->delete_wakelock); + + qdf_runtime_lock_deinit(&psoc_wakelock->wmi_cmd_rsp_runtime_lock); +} + +QDF_STATUS target_if_wake_lock_timeout_acquire( + struct wlan_objmgr_psoc *psoc, + enum wakelock_mode mode) +{ + struct psoc_mlme_wakelock *psoc_wakelock; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops && !rx_ops->psoc_get_wakelock_info) { + mlme_err("psoc_id:%d No Rx Ops", wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; + } + + psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc); + switch (mode) { + case START_WAKELOCK: + qdf_wake_lock_timeout_acquire(&psoc_wakelock->start_wakelock, + START_RESPONSE_TIMER); + break; + case STOP_WAKELOCK: + qdf_wake_lock_timeout_acquire(&psoc_wakelock->stop_wakelock, + STOP_RESPONSE_TIMER); + break; + case DELETE_WAKELOCK: + qdf_wake_lock_timeout_acquire(&psoc_wakelock->delete_wakelock, + DELETE_RESPONSE_TIMER); + break; + default: + target_if_err("operation mode is invalid"); + return QDF_STATUS_E_FAILURE; + } + + qdf_runtime_pm_prevent_suspend( + &psoc_wakelock->wmi_cmd_rsp_runtime_lock); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS target_if_wake_lock_timeout_release( + struct wlan_objmgr_psoc *psoc, + enum wakelock_mode mode) +{ + struct psoc_mlme_wakelock *psoc_wakelock; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->psoc_get_wakelock_info) { + mlme_err("psoc_id:%d No Rx Ops", wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; + } + + psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc); + switch (mode) { + case START_WAKELOCK: + qdf_wake_lock_release(&psoc_wakelock->start_wakelock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + break; + case STOP_WAKELOCK: + qdf_wake_lock_release(&psoc_wakelock->stop_wakelock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + break; + case DELETE_WAKELOCK: + qdf_wake_lock_release(&psoc_wakelock->delete_wakelock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + break; + default: + target_if_err("operation mode is invalid"); + return QDF_STATUS_E_FAILURE; + } + + qdf_runtime_pm_allow_suspend(&psoc_wakelock->wmi_cmd_rsp_runtime_lock); + + return QDF_STATUS_SUCCESS; +} + diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_rx_ops.h b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_rx_ops.h index fbfd8f45e0c29bc1040b1276e87c218e3b3886fd..7cda52628d90b9b29e743b9b043e7fea7633adc7 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_rx_ops.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_rx_ops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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 @@ -28,16 +28,68 @@ #include #include #include +#include /** - * target_if_vdev_mgr_is_driver_unloading: API to driver unload status + * target_if_vdev_mgr_is_panic_allowed: API to get if panic is allowed on + * timeout * - * Return: TRUE or FALSE + * Return: TRUE or FALSE when VDEV_ASSERT_MANAGEMENT is disabled else FALSE */ -static inline bool target_if_vdev_mgr_is_driver_unloading(void) +#ifdef VDEV_ASSERT_MANAGEMENT +static inline bool target_if_vdev_mgr_is_panic_allowed(void) { return false; } +#else +static inline bool target_if_vdev_mgr_is_panic_allowed(void) +{ + if (qdf_is_recovering() || qdf_is_fw_down()) + return false; + + return true; +} +#endif + + +/** + * target_if_vdev_mgr_offload_bcn_tx_status_handler() - API to handle beacon + * tx status event + * @scn: pointer to scan object + * @data: pointer to data + * @datalen: length of data + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +int target_if_vdev_mgr_offload_bcn_tx_status_handler(ol_scn_t scn, + uint8_t *data, + uint32_t datalen); + +/** + * target_if_vdev_mgr_tbttoffset_update_handler() - API to handle tbtt offset + * update event + * @scn: pointer to scan object + * @data: pointer to data + * @datalen: length of data + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +int target_if_vdev_mgr_tbttoffset_update_handler(ol_scn_t scn, + uint8_t *data, + uint32_t datalen); + +/** + * target_if_vdev_mgr_ext_tbttoffset_update_handler() - API to handle ext tbtt + * offset update event + * @scn: pointer to scan object + * @data: pointer to data + * @datalen: length of data + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +int target_if_vdev_mgr_ext_tbttoffset_update_handler(ol_scn_t scn, + uint8_t *data, + uint32_t datalen); /** * target_if_vdev_mgr_is_panic_on_bug: API to get panic on bug @@ -96,4 +148,13 @@ QDF_STATUS target_if_vdev_mgr_wmi_event_register( QDF_STATUS target_if_vdev_mgr_wmi_event_unregister( struct wlan_objmgr_psoc *psoc); +/** + * target_if_vdev_mgr_rsp_timer_cb() - function to handle vdev related timeouts + * @vdev_rsp: pointer to vdev response timer + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on error + */ +QDF_STATUS +target_if_vdev_mgr_rsp_timer_cb(struct vdev_response_timer *vdev_rsp); + #endif /* __TARGET_IF_VDEV_MGR_RX_OPS_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_tx_ops.h b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_tx_ops.h index e3caf0a23fbb5650cc18e1284695db0abd6cd596..14fd51c639d044e071c008c790a023c86b4f1e58 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_tx_ops.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_tx_ops.h @@ -25,7 +25,6 @@ #ifndef __TARGET_IF_VDEV_MGR_TX_OPS_H__ #define __TARGET_IF_VDEV_MGR_TX_OPS_H__ -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE #include #include #include @@ -62,13 +61,41 @@ target_if_vdev_mgr_get_tx_ops(struct wlan_objmgr_psoc *psoc) QDF_STATUS target_if_vdev_mgr_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); +/** + * target_if_vdev_mgr_assert_mgmt() - vdev assert mgmt api + * @PSOC: pointer to objmgr psoc + * @vdev_id: vdev id + * + * Return: NA + */ +#ifdef VDEV_ASSERT_MANAGEMENT +static inline void target_if_vdev_mgr_assert_mgmt( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ +} #else +static inline void target_if_vdev_mgr_assert_mgmt( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) -static inline QDF_STATUS -target_if_vdev_mgr_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) { - return QDF_STATUS_SUCCESS; + QDF_ASSERT(0); } +#endif + +/** + * target_if_vdev_mgr_rsp_timer_stop() - API to stop response timer for + * vdev manager operations + * @psoc: pointer to psoc object + * @vdev_rsp: vdev response timer + * @clear_bit: enum of wlan_vdev_mgr_tgt_if_rsp_bit + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS target_if_vdev_mgr_rsp_timer_stop( + struct wlan_objmgr_psoc *psoc, + struct vdev_response_timer *vdev_rsp, + enum wlan_vdev_mgr_tgt_if_rsp_bit clear_bit); -#endif /* CMN_VDEV_MGR_TGT_IF_ENABLE */ #endif /* __TARGET_IF_VDEV_MGR_TX_OPS_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c index 8bead4d58f6ccf933f4403d8e80805e1ac97db29..2edff715a23e5dfdd193b18dacb147db7cca3b1b 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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 @@ -29,113 +29,225 @@ #include #include #include -#include #include +#include +#include + +static inline +void target_if_vdev_mgr_handle_recovery(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + enum qdf_hang_reason recovery_reason, + uint16_t rsp_pos) +{ + mlme_nofl_err("PSOC_%d VDEV_%d: %s rsp timeout", wlan_psoc_get_id(psoc), + vdev_id, string_from_rsp_bit(rsp_pos)); + if (target_if_vdev_mgr_is_panic_allowed()) + qdf_trigger_self_recovery(psoc, recovery_reason); + else + mlme_nofl_debug("PSOC_%d VDEV_%d: Panic not allowed", + wlan_psoc_get_id(psoc), vdev_id); +} -void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg) +QDF_STATUS target_if_vdev_mgr_rsp_timer_cb(struct vdev_response_timer *vdev_rsp) { - struct wlan_objmgr_vdev *vdev = arg; struct wlan_objmgr_psoc *psoc; struct wlan_lmac_if_mlme_rx_ops *rx_ops; - struct vdev_response_timer *vdev_rsp; - struct crash_inject param; - struct wmi_unified *wmi_handle; struct vdev_start_response start_rsp = {0}; struct vdev_stop_response stop_rsp = {0}; struct vdev_delete_response del_rsp = {0}; + struct peer_delete_all_response peer_del_all_rsp = {0}; + enum qdf_hang_reason recovery_reason; uint8_t vdev_id; + uint16_t rsp_pos = RESPONSE_BIT_MAX; - vdev_id = wlan_vdev_get_id(vdev); - mlme_debug("Response timer expired for VDEV %d", vdev_id); + if (!vdev_rsp) { + mlme_err("Vdev response timer is NULL"); + return QDF_STATUS_E_FAILURE; + } - psoc = wlan_vdev_get_psoc(vdev); + psoc = vdev_rsp->psoc; if (!psoc) { mlme_err("PSOC is NULL"); - return; + return QDF_STATUS_E_FAILURE; } rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); - if (!rx_ops || !rx_ops->vdev_mgr_get_response_timer_info) { + if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) { mlme_err("No Rx Ops"); - return; + return QDF_STATUS_E_FAILURE; } - vdev_rsp = rx_ops->vdev_mgr_get_response_timer_info(vdev); if (!qdf_atomic_test_bit(START_RESPONSE_BIT, &vdev_rsp->rsp_status) && !qdf_atomic_test_bit(RESTART_RESPONSE_BIT, &vdev_rsp->rsp_status) && !qdf_atomic_test_bit(STOP_RESPONSE_BIT, &vdev_rsp->rsp_status) && - !qdf_atomic_test_bit(DELETE_RESPONSE_BIT, &vdev_rsp->rsp_status)) { - mlme_debug("No response bit is set, ignoring actions"); - return; - } - - if (target_if_vdev_mgr_is_driver_unloading() || qdf_is_recovering() || - qdf_is_fw_down()) { - /* this ensures stop timer will not be done in target_if */ - vdev_rsp->timer_status = QDF_STATUS_E_TIMEOUT; + !qdf_atomic_test_bit(DELETE_RESPONSE_BIT, &vdev_rsp->rsp_status) && + !qdf_atomic_test_bit( + PEER_DELETE_ALL_RESPONSE_BIT, + &vdev_rsp->rsp_status)) { + mlme_debug("No response bit is set, ignoring actions :%d", + vdev_rsp->vdev_id); + return QDF_STATUS_E_FAILURE; + } + + vdev_id = vdev_rsp->vdev_id; + if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) { + mlme_err("Invalid VDEV_%d PSOC_%d", vdev_id, + wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_FAILURE; + } + + vdev_rsp->timer_status = QDF_STATUS_E_TIMEOUT; + if (qdf_atomic_test_bit(START_RESPONSE_BIT, + &vdev_rsp->rsp_status) || + qdf_atomic_test_bit(RESTART_RESPONSE_BIT, + &vdev_rsp->rsp_status)) { + start_rsp.vdev_id = vdev_id; + start_rsp.status = WLAN_MLME_HOST_VDEV_START_TIMEOUT; if (qdf_atomic_test_bit(START_RESPONSE_BIT, - &vdev_rsp->rsp_status) || - qdf_atomic_test_bit(RESTART_RESPONSE_BIT, &vdev_rsp->rsp_status)) { - start_rsp.vdev_id = wlan_vdev_get_id(vdev); - start_rsp.status = WLAN_MLME_HOST_VDEV_START_TIMEOUT; - if (qdf_atomic_test_bit(START_RESPONSE_BIT, - &vdev_rsp->rsp_status)) - start_rsp.resp_type = - WMI_HOST_VDEV_START_RESP_EVENT; - else - start_rsp.resp_type = - WMI_HOST_VDEV_RESTART_RESP_EVENT; - - rx_ops->vdev_mgr_start_response(psoc, &start_rsp); + start_rsp.resp_type = + WMI_HOST_VDEV_START_RESP_EVENT; + rsp_pos = START_RESPONSE_BIT; + recovery_reason = QDF_VDEV_START_RESPONSE_TIMED_OUT; + } else { + start_rsp.resp_type = + WMI_HOST_VDEV_RESTART_RESP_EVENT; + rsp_pos = RESTART_RESPONSE_BIT; + recovery_reason = QDF_VDEV_RESTART_RESPONSE_TIMED_OUT; } - if (qdf_atomic_test_bit(STOP_RESPONSE_BIT, - &vdev_rsp->rsp_status)) { - stop_rsp.vdev_id = wlan_vdev_get_id(vdev); - rx_ops->vdev_mgr_stop_response(psoc, &stop_rsp); - } + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); + target_if_vdev_mgr_handle_recovery(psoc, vdev_id, + recovery_reason, rsp_pos); + rx_ops->vdev_mgr_start_response(psoc, &start_rsp); + } else if (qdf_atomic_test_bit(STOP_RESPONSE_BIT, + &vdev_rsp->rsp_status)) { + rsp_pos = STOP_RESPONSE_BIT; + stop_rsp.vdev_id = vdev_id; + recovery_reason = QDF_VDEV_STOP_RESPONSE_TIMED_OUT; + + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); + target_if_vdev_mgr_handle_recovery(psoc, vdev_id, + recovery_reason, rsp_pos); + rx_ops->vdev_mgr_stop_response(psoc, &stop_rsp); + } else if (qdf_atomic_test_bit(DELETE_RESPONSE_BIT, + &vdev_rsp->rsp_status)) { + del_rsp.vdev_id = vdev_id; + rsp_pos = DELETE_RESPONSE_BIT; + recovery_reason = QDF_VDEV_DELETE_RESPONSE_TIMED_OUT; + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); + target_if_vdev_mgr_handle_recovery(psoc, vdev_id, + recovery_reason, rsp_pos); + rx_ops->vdev_mgr_delete_response(psoc, &del_rsp); + } else if (qdf_atomic_test_bit(PEER_DELETE_ALL_RESPONSE_BIT, + &vdev_rsp->rsp_status)) { + peer_del_all_rsp.vdev_id = vdev_id; + rsp_pos = PEER_DELETE_ALL_RESPONSE_BIT; + recovery_reason = QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT; + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); + target_if_vdev_mgr_handle_recovery(psoc, vdev_id, + recovery_reason, rsp_pos); + rx_ops->vdev_mgr_peer_delete_all_response(psoc, + &peer_del_all_rsp); + } else { + mlme_err("PSOC_%d VDEV_%d: Unknown error", + wlan_psoc_get_id(psoc), vdev_id); + return QDF_STATUS_E_FAILURE; + } - if (qdf_atomic_test_bit(DELETE_RESPONSE_BIT, - &vdev_rsp->rsp_status)) { - del_rsp.vdev_id = wlan_vdev_get_id(vdev); - rx_ops->vdev_mgr_delete_response(psoc, &del_rsp); - } + return QDF_STATUS_SUCCESS; +} - return; +#ifdef SERIALIZE_VDEV_RESP +static QDF_STATUS target_if_vdev_mgr_rsp_flush_cb(struct scheduler_msg *msg) +{ + struct vdev_response_timer *vdev_rsp; + struct wlan_objmgr_psoc *psoc; + + if (!msg->bodyptr) { + mlme_err("Message bodyptr is NULL"); + return QDF_STATUS_E_INVAL; } - if (target_if_vdev_mgr_is_panic_on_bug()) { - QDF_DEBUG_PANIC("PSOC_%d VDEV_%d: Panic on bug, rsp status:%d", - wlan_psoc_get_id(psoc), - vdev_id, vdev_rsp->rsp_status); - } else { - mlme_err("PSOC_%d VDEV_%d: Trigger Self recovery, rsp status%d", - wlan_psoc_get_id(psoc), - vdev_id, vdev_rsp->rsp_status); - wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + vdev_rsp = msg->bodyptr; + if (!vdev_rsp) { + mlme_err("vdev response timer is NULL"); + return QDF_STATUS_E_INVAL; + } - qdf_mem_set(¶m, sizeof(param), 0); - /* RECOVERY_SIM_SELF_RECOVERY*/ - param.type = 0x08; - wmi_crash_inject(wmi_handle, ¶m); + psoc = vdev_rsp->psoc; + if (!psoc) { + mlme_err("PSOC is NULL"); + return QDF_STATUS_E_INVAL; } + + if (vdev_rsp->rsp_status) + wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID); + + return QDF_STATUS_SUCCESS; } -static int target_if_vdev_mgr_start_response_handler( - ol_scn_t scn, - uint8_t *data, - uint32_t datalen) +static void +target_if_vdev_mgr_rsp_cb_mc_ctx(void *arg) { - QDF_STATUS status; + struct scheduler_msg msg = {0}; + struct vdev_response_timer *vdev_rsp = arg; + struct wlan_objmgr_psoc *psoc; + + psoc = vdev_rsp->psoc; + if (!psoc) { + mlme_err("PSOC is NULL"); + return; + } + + msg.type = SYS_MSG_ID_MC_TIMER; + msg.reserved = SYS_MSG_COOKIE; + msg.callback = target_if_vdev_mgr_rsp_timer_cb; + msg.bodyptr = vdev_rsp; + msg.bodyval = 0; + msg.flush_callback = target_if_vdev_mgr_rsp_flush_cb; + + if (scheduler_post_message(QDF_MODULE_ID_TARGET_IF, + QDF_MODULE_ID_TARGET_IF, + QDF_MODULE_ID_SYS, &msg) == + QDF_STATUS_SUCCESS) + return; + + mlme_err("Could not enqueue timer to timer queue"); + if (psoc) + wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID); +} + +void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg) +{ + target_if_vdev_mgr_rsp_cb_mc_ctx(arg); +} + +#define VDEV_RSP_RX_CTX WMI_RX_SERIALIZER_CTX +#else +void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg) +{ + target_if_vdev_mgr_rsp_timer_cb(arg); +} + +#define VDEV_RSP_RX_CTX WMI_RX_UMAC_CTX +#endif + +static int target_if_vdev_mgr_start_response_handler(ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status = QDF_STATUS_E_INVAL; struct wlan_objmgr_psoc *psoc; struct wmi_unified *wmi_handle; struct wlan_lmac_if_mlme_rx_ops *rx_ops; struct vdev_start_response rsp = {0}; wmi_host_vdev_start_resp vdev_start_resp; + uint8_t vdev_id; + struct vdev_response_timer *vdev_rsp; if (!scn || !data) { - mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + mlme_err("Invalid input"); return -EINVAL; } @@ -162,6 +274,28 @@ static int target_if_vdev_mgr_start_response_handler( return -EINVAL; } + vdev_id = vdev_start_resp.vdev_id; + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); + if (!vdev_rsp) { + mlme_err("vdev response timer is null VDEV_%d PSOC_%d", + vdev_id, wlan_psoc_get_id(psoc)); + return -EINVAL; + } + + if (vdev_start_resp.resp_type == WMI_HOST_VDEV_RESTART_RESP_EVENT) + status = target_if_vdev_mgr_rsp_timer_stop( + psoc, vdev_rsp, + RESTART_RESPONSE_BIT); + else + status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, + START_RESPONSE_BIT); + + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", + psoc->soc_objmgr.psoc_id, vdev_id); + goto err; + } + rsp.vdev_id = vdev_start_resp.vdev_id; rsp.requestor_id = vdev_start_resp.requestor_id; rsp.status = vdev_start_resp.status; @@ -171,26 +305,28 @@ static int target_if_vdev_mgr_start_response_handler( rsp.mac_id = vdev_start_resp.mac_id; rsp.cfgd_tx_streams = vdev_start_resp.cfgd_tx_streams; rsp.cfgd_rx_streams = vdev_start_resp.cfgd_rx_streams; + rsp.max_allowed_tx_power = vdev_start_resp.max_allowed_tx_power; status = rx_ops->vdev_mgr_start_response(psoc, &rsp); +err: return qdf_status_to_os_return(status); } -static int target_if_vdev_mgr_stop_response_handler( - ol_scn_t scn, - uint8_t *data, - uint32_t datalen) +static int target_if_vdev_mgr_stop_response_handler(ol_scn_t scn, + uint8_t *data, + uint32_t datalen) { - QDF_STATUS status; + QDF_STATUS status = QDF_STATUS_E_INVAL; struct wlan_objmgr_psoc *psoc; struct wmi_unified *wmi_handle; struct wlan_lmac_if_mlme_rx_ops *rx_ops; struct vdev_stop_response rsp = {0}; uint32_t vdev_id; + struct vdev_response_timer *vdev_rsp; if (!scn || !data) { - mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + mlme_err("Invalid input"); return -EINVAL; } @@ -217,26 +353,43 @@ static int target_if_vdev_mgr_stop_response_handler( return -EINVAL; } + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); + if (!vdev_rsp) { + mlme_err("vdev response timer is null VDEV_%d PSOC_%d", + vdev_id, wlan_psoc_get_id(psoc)); + return -EINVAL; + } + + status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, + STOP_RESPONSE_BIT); + + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", + psoc->soc_objmgr.psoc_id, vdev_id); + goto err; + } + rsp.vdev_id = vdev_id; status = rx_ops->vdev_mgr_stop_response(psoc, &rsp); +err: return qdf_status_to_os_return(status); } -static int target_if_vdev_mgr_delete_response_handler( - ol_scn_t scn, - uint8_t *data, - uint32_t datalen) +static int target_if_vdev_mgr_delete_response_handler(ol_scn_t scn, + uint8_t *data, + uint32_t datalen) { - QDF_STATUS status; + QDF_STATUS status = QDF_STATUS_E_INVAL; struct wlan_objmgr_psoc *psoc; struct wmi_unified *wmi_handle; struct wlan_lmac_if_mlme_rx_ops *rx_ops; struct vdev_delete_response rsp = {0}; struct wmi_host_vdev_delete_resp vdev_del_resp; + struct vdev_response_timer *vdev_rsp; if (!scn || !data) { - mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + mlme_err("Invalid input"); return -EINVAL; } @@ -247,8 +400,7 @@ static int target_if_vdev_mgr_delete_response_handler( } rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); - if (!rx_ops || !rx_ops->vdev_mgr_stop_response || - !rx_ops->vdev_mgr_get_response_timer_info) { + if (!rx_ops || !rx_ops->vdev_mgr_delete_response) { mlme_err("No Rx Ops"); return -EINVAL; } @@ -264,16 +416,108 @@ static int target_if_vdev_mgr_delete_response_handler( return -EINVAL; } + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, + vdev_del_resp.vdev_id); + if (!vdev_rsp) { + mlme_err("vdev response timer is null VDEV_%d PSOC_%d", + vdev_del_resp.vdev_id, wlan_psoc_get_id(psoc)); + return -EINVAL; + } + + status = target_if_vdev_mgr_rsp_timer_stop( + psoc, vdev_rsp, + DELETE_RESPONSE_BIT); + + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", + wlan_psoc_get_id(psoc), vdev_del_resp.vdev_id); + goto err; + } + rsp.vdev_id = vdev_del_resp.vdev_id; status = rx_ops->vdev_mgr_delete_response(psoc, &rsp); - + target_if_wake_lock_timeout_release(psoc, DELETE_WAKELOCK); +err: return qdf_status_to_os_return(status); } -static int target_if_vdev_mgr_offload_bcn_tx_status_handler( +static int target_if_vdev_mgr_peer_delete_all_response_handler( ol_scn_t scn, uint8_t *data, uint32_t datalen) +{ + QDF_STATUS status = QDF_STATUS_E_INVAL; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + struct peer_delete_all_response rsp = {0}; + struct wmi_host_vdev_peer_delete_all_response_event + vdev_peer_del_all_resp; + struct vdev_response_timer *vdev_rsp; + + if (!scn || !data) { + mlme_err("Invalid input"); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + mlme_err("PSOC is NULL"); + return -EINVAL; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_peer_delete_all_response) { + mlme_err("No Rx Ops"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return -EINVAL; + } + + if (wmi_extract_vdev_peer_delete_all_response_event( + wmi_handle, data, + &vdev_peer_del_all_resp)) { + mlme_err("WMI extract failed"); + return -EINVAL; + } + + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, + vdev_peer_del_all_resp.vdev_id); + if (!vdev_rsp) { + mlme_err("vdev response timer is null VDEV_%d PSOC_%d", + vdev_peer_del_all_resp.vdev_id, + wlan_psoc_get_id(psoc)); + return -EINVAL; + } + + status = target_if_vdev_mgr_rsp_timer_stop( + psoc, + vdev_rsp, + PEER_DELETE_ALL_RESPONSE_BIT); + + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", + psoc->soc_objmgr.psoc_id, + vdev_peer_del_all_resp.vdev_id); + goto err; + } + + rsp.vdev_id = vdev_peer_del_all_resp.vdev_id; + rsp.status = vdev_peer_del_all_resp.status; + status = rx_ops->vdev_mgr_peer_delete_all_response(psoc, &rsp); + +err: + return qdf_status_to_os_return(status); +} + +int target_if_vdev_mgr_offload_bcn_tx_status_handler( + ol_scn_t scn, + uint8_t *data, + uint32_t datalen) { QDF_STATUS status; struct wlan_objmgr_psoc *psoc; @@ -282,7 +526,7 @@ static int target_if_vdev_mgr_offload_bcn_tx_status_handler( uint32_t vdev_id, tx_status; if (!scn || !data) { - mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + mlme_err("Invalid input"); return -EINVAL; } psoc = target_if_get_psoc_from_scn_hdl(scn); @@ -316,9 +560,8 @@ static int target_if_vdev_mgr_offload_bcn_tx_status_handler( return qdf_status_to_os_return(status); } -static int target_if_vdev_mgr_tbttoffset_update_handler( - ol_scn_t scn, - uint8_t *data, +int target_if_vdev_mgr_tbttoffset_update_handler( + ol_scn_t scn, uint8_t *data, uint32_t datalen) { QDF_STATUS status; @@ -328,7 +571,7 @@ static int target_if_vdev_mgr_tbttoffset_update_handler( uint32_t num_vdevs = 0; if (!scn || !data) { - mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + mlme_err("Invalid input"); return -EINVAL; } psoc = target_if_get_psoc_from_scn_hdl(scn); @@ -354,12 +597,13 @@ static int target_if_vdev_mgr_tbttoffset_update_handler( return -EINVAL; } - status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, false); + status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, + false); return qdf_status_to_os_return(status); } -static int target_if_vdev_mgr_ext_tbttoffset_update_handler( +int target_if_vdev_mgr_ext_tbttoffset_update_handler( ol_scn_t scn, uint8_t *data, uint32_t datalen) @@ -371,7 +615,7 @@ static int target_if_vdev_mgr_ext_tbttoffset_update_handler( uint32_t num_vdevs = 0; if (!scn || !data) { - mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + mlme_err("Invalid input"); return -EINVAL; } psoc = target_if_get_psoc_from_scn_hdl(scn); @@ -398,7 +642,79 @@ static int target_if_vdev_mgr_ext_tbttoffset_update_handler( return -EINVAL; } - status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, true); + status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, + true); + + return qdf_status_to_os_return(status); +} + +static int target_if_vdev_mgr_multi_vdev_restart_resp_handler( + ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status = QDF_STATUS_E_INVAL; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + struct multi_vdev_restart_resp restart_resp; + struct vdev_response_timer *vdev_rsp; + uint8_t max_vdevs, vdev_idx; + + if (!scn || !data) { + mlme_err("Invalid input"); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + mlme_err("PSOC is NULL"); + return -EINVAL; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_multi_vdev_restart_resp || + !rx_ops->psoc_get_vdev_response_timer_info) { + mlme_err("No Rx Ops"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return -EINVAL; + } + + qdf_mem_zero(&restart_resp, sizeof(restart_resp)); + if (wmi_extract_multi_vdev_restart_resp_event(wmi_handle, data, + &restart_resp)) { + mlme_err("WMI extract failed"); + return -EINVAL; + } + + max_vdevs = wlan_psoc_get_max_vdev_count(psoc); + for (vdev_idx = 0; vdev_idx < max_vdevs; vdev_idx++) { + if (!qdf_test_bit(vdev_idx, restart_resp.vdev_id_bmap)) + continue; + + mlme_debug("PSOC_%d VDEV_%d: Restart resp received", + wlan_psoc_get_id(psoc), vdev_idx); + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, + vdev_idx); + if (!vdev_rsp) { + mlme_err("PSOC_%d VDEV_%d: VDEV RSP is NULL", + wlan_psoc_get_id(psoc), vdev_idx); + continue; + } + + status = target_if_vdev_mgr_rsp_timer_stop( + psoc, vdev_rsp, RESTART_RESPONSE_BIT); + if (QDF_IS_STATUS_ERROR(status)) + mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", + wlan_psoc_get_id(psoc), vdev_idx); + } + + status = rx_ops->vdev_mgr_multi_vdev_restart_resp(psoc, &restart_resp); return qdf_status_to_os_return(status); } @@ -424,7 +740,7 @@ QDF_STATUS target_if_vdev_mgr_wmi_event_register( wmi_handle, wmi_vdev_stopped_event_id, target_if_vdev_mgr_stop_response_handler, - WMI_RX_UMAC_CTX); + VDEV_RSP_RX_CTX); if (retval) mlme_err("failed to register for stop response"); @@ -432,7 +748,7 @@ QDF_STATUS target_if_vdev_mgr_wmi_event_register( wmi_handle, wmi_vdev_delete_resp_event_id, target_if_vdev_mgr_delete_response_handler, - WMI_RX_UMAC_CTX); + VDEV_RSP_RX_CTX); if (retval) mlme_err("failed to register for delete response"); @@ -440,10 +756,26 @@ QDF_STATUS target_if_vdev_mgr_wmi_event_register( wmi_handle, wmi_vdev_start_resp_event_id, target_if_vdev_mgr_start_response_handler, - WMI_RX_UMAC_CTX); + VDEV_RSP_RX_CTX); if (retval) mlme_err("failed to register for start response"); + retval = wmi_unified_register_event_handler( + wmi_handle, + wmi_peer_delete_all_response_event_id, + target_if_vdev_mgr_peer_delete_all_response_handler, + VDEV_RSP_RX_CTX); + if (retval) + mlme_err("failed to register for peer delete all response"); + + retval = wmi_unified_register_event_handler( + wmi_handle, + wmi_pdev_multi_vdev_restart_response_event_id, + target_if_vdev_mgr_multi_vdev_restart_resp_handler, + VDEV_RSP_RX_CTX); + if (retval) + mlme_err("failed to register for multivdev restart response"); + return qdf_status_from_os_return(retval); } @@ -463,14 +795,22 @@ QDF_STATUS target_if_vdev_mgr_wmi_event_unregister( return QDF_STATUS_E_INVAL; } + wmi_unified_unregister_event_handler( + wmi_handle, + wmi_pdev_multi_vdev_restart_response_event_id); + + wmi_unified_unregister_event_handler( + wmi_handle, + wmi_peer_delete_all_response_event_id); + wmi_unified_unregister_event_handler(wmi_handle, - wmi_vdev_stopped_event_id); + wmi_vdev_start_resp_event_id); wmi_unified_unregister_event_handler(wmi_handle, wmi_vdev_delete_resp_event_id); wmi_unified_unregister_event_handler(wmi_handle, - wmi_vdev_start_resp_event_id); + wmi_vdev_stopped_event_id); return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c index ee271bc880481cc593ea053e5f77a9e29abcd92f..83cc320070e44d13d2386c7371aae1db1fcddb34 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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 @@ -34,6 +34,10 @@ #include #include #include +#include +#include +#include +#include static QDF_STATUS target_if_vdev_mgr_register_event_handler( struct wlan_objmgr_psoc *psoc) @@ -47,25 +51,20 @@ static QDF_STATUS target_if_vdev_mgr_unregister_event_handler( return target_if_vdev_mgr_wmi_event_unregister(psoc); } -static QDF_STATUS target_if_vdev_mgr_rsp_timer_mod( - struct wlan_objmgr_vdev *vdev, - struct vdev_response_timer *vdev_rsp, - int mseconds) +QDF_STATUS +target_if_vdev_mgr_rsp_timer_stop(struct wlan_objmgr_psoc *psoc, + struct vdev_response_timer *vdev_rsp, + enum wlan_vdev_mgr_tgt_if_rsp_bit clear_bit) { - if (!vdev || !vdev_rsp) { - mlme_err("Invalid input"); + struct wlan_lmac_if_mlme_tx_ops *txops; + + txops = target_if_vdev_mgr_get_tx_ops(psoc); + if (!txops || !txops->psoc_vdev_rsp_timer_deinit) { + mlme_err("Failed to get mlme txrx_ops VDEV_%d PSOC_%d", + vdev_rsp->vdev_id, wlan_psoc_get_id(psoc)); return QDF_STATUS_E_FAILURE; } - qdf_timer_mod(&vdev_rsp->rsp_timer, mseconds); - return QDF_STATUS_SUCCESS; -} - -static QDF_STATUS target_if_vdev_mgr_rsp_timer_stop( - struct wlan_objmgr_vdev *vdev, - struct vdev_response_timer *vdev_rsp, - uint8_t clear_bit) -{ if (qdf_atomic_test_and_clear_bit(clear_bit, &vdev_rsp->rsp_status)) { /* * This is triggered from timer expiry case only for @@ -75,99 +74,67 @@ static QDF_STATUS target_if_vdev_mgr_rsp_timer_stop( qdf_timer_stop(&vdev_rsp->rsp_timer); vdev_rsp->timer_status = QDF_STATUS_SUCCESS; + if (clear_bit == DELETE_RESPONSE_BIT) + txops->psoc_vdev_rsp_timer_deinit(psoc, + vdev_rsp->vdev_id); + /* * Releasing reference taken at the time of * starting response timer */ - wlan_objmgr_vdev_release_ref(vdev, WLAN_VDEV_TARGET_IF_ID); + wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID); return QDF_STATUS_SUCCESS; } - return QDF_STATUS_E_FAILURE; } -#ifdef VDEV_ASSERT_MANAGEMENT -static void target_if_vdev_mgr_assert_mgmt( - struct wlan_objmgr_vdev *vdev, - struct vdev_response_timer *vdev_rsp, - uint8_t set_bit) -{ - target_if_vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, - set_bit); -} -#else -static void target_if_vdev_mgr_assert_mgmt( - struct wlan_objmgr_vdev *vdev, - struct vdev_response_timer *vdev_rsp, - uint8_t set_bit) -{ - QDF_ASSERT(0); -} -#endif - static QDF_STATUS target_if_vdev_mgr_rsp_timer_start( - struct wlan_objmgr_vdev *vdev, - struct vdev_response_timer *vdev_rsp, - uint8_t set_bit) + struct wlan_objmgr_psoc *psoc, + struct vdev_response_timer *vdev_rsp, + enum wlan_vdev_mgr_tgt_if_rsp_bit set_bit) { - uint8_t vdev_id; uint8_t rsp_pos; - struct wlan_objmgr_psoc *psoc; - - psoc = wlan_vdev_get_psoc(vdev); - if (!psoc) { - mlme_err("PSOC is NULL"); - return QDF_STATUS_E_INVAL; - } + uint8_t vdev_id; - vdev_id = wlan_vdev_get_id(vdev); /* it is expected to be only one command with FW at a time */ for (rsp_pos = START_RESPONSE_BIT; rsp_pos <= RESPONSE_BIT_MAX; rsp_pos++) { if (rsp_pos != set_bit) { if (qdf_atomic_test_bit(rsp_pos, &vdev_rsp->rsp_status)) { - mlme_err("PSOC_%d VDEV_%d: Response bit is set %d", + vdev_id = vdev_rsp->vdev_id; + mlme_err("PSOC_%d VDEV_%d: %s requested, waiting for %s response", wlan_psoc_get_id(psoc), - vdev_id, vdev_rsp->rsp_status); - target_if_vdev_mgr_assert_mgmt(vdev, vdev_rsp, - rsp_pos); + vdev_id, + string_from_rsp_bit(set_bit), + string_from_rsp_bit(rsp_pos)); + target_if_vdev_mgr_assert_mgmt(psoc, + vdev_id); + target_if_vdev_mgr_rsp_timer_stop(psoc, + vdev_rsp, + rsp_pos); } } } if (qdf_atomic_test_and_set_bit(set_bit, &vdev_rsp->rsp_status)) { - mlme_err("PSOC_%d VDEV_%d: Response bit is set %d", + mlme_err("PSOC_%d VDEV_%d: %s requested, waiting for %s response", wlan_psoc_get_id(psoc), - vdev_id, vdev_rsp->rsp_status); - target_if_vdev_mgr_assert_mgmt(vdev, vdev_rsp, - set_bit); + vdev_rsp->vdev_id, string_from_rsp_bit(set_bit), + string_from_rsp_bit(set_bit)); + target_if_vdev_mgr_assert_mgmt(psoc, vdev_rsp->vdev_id); + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, set_bit); + + qdf_atomic_set_bit(set_bit, &vdev_rsp->rsp_status); } /* reference taken for timer start, will be released with stop */ - wlan_objmgr_vdev_get_ref(vdev, WLAN_VDEV_TARGET_IF_ID); + wlan_objmgr_psoc_get_ref(psoc, WLAN_PSOC_TARGET_IF_ID); qdf_timer_start(&vdev_rsp->rsp_timer, vdev_rsp->expire_time); return QDF_STATUS_SUCCESS; } -static QDF_STATUS target_if_vdev_mgr_rsp_timer_init( - struct wlan_objmgr_vdev *vdev, - qdf_timer_t *rsp_timer) -{ - if (!vdev || !rsp_timer) { - mlme_err("Invalid input"); - return QDF_STATUS_E_INVAL; - } - - qdf_timer_init(NULL, rsp_timer, - target_if_vdev_mgr_rsp_timer_mgmt_cb, - (void *)vdev, QDF_TIMER_TYPE_WAKE_APPS); - mlme_debug("VDEV_%d: Response timer initialized", - wlan_vdev_get_id(vdev)); - - return QDF_STATUS_SUCCESS; -} struct wmi_unified *target_if_vdev_mgr_wmi_handle_get(struct wlan_objmgr_vdev *vdev) @@ -315,6 +282,18 @@ target_if_vdev_mlme_id_2_wmi(uint32_t cfg_id) case WLAN_MLME_CFG_LISTEN_INTERVAL: wmi_id = wmi_vdev_param_listen_interval; break; + case WLAN_MLME_CFG_ENABLE_MULTI_GROUP_KEY: + wmi_id = wmi_vdev_param_enable_multi_group_key; + break; + case WLAN_MLME_CFG_MAX_GROUP_KEYS: + wmi_id = wmi_vdev_param_max_group_keys; + break; + case WLAN_MLME_CFG_TX_ENCAP_TYPE: + wmi_id = wmi_vdev_param_tx_encap_type; + break; + case WLAN_MLME_CFG_RX_DECAP_TYPE: + wmi_id = wmi_vdev_param_rx_decap_type; + break; default: wmi_id = cfg_id; break; @@ -323,6 +302,37 @@ target_if_vdev_mlme_id_2_wmi(uint32_t cfg_id) return wmi_id; } +static +QDF_STATUS target_if_vdev_set_tx_rx_decap_type(struct wlan_objmgr_vdev *vdev, + enum wlan_mlme_cfg_id param_id, + uint32_t value) +{ + ol_txrx_soc_handle soc_txrx_handle; + struct wlan_objmgr_psoc *psoc; + uint8_t vdev_id = wlan_vdev_get_id(vdev); + cdp_config_param_type val = {0}; + + psoc = wlan_vdev_get_psoc(vdev); + soc_txrx_handle = wlan_psoc_get_dp_handle(psoc); + + if (!soc_txrx_handle) + return QDF_STATUS_E_INVAL; + + if (param_id == WLAN_MLME_CFG_TX_ENCAP_TYPE) { + val.cdp_vdev_param_tx_encap = value; + return cdp_txrx_set_vdev_param(soc_txrx_handle, + vdev_id, CDP_TX_ENCAP_TYPE, + val); + } else if (param_id == WLAN_MLME_CFG_RX_DECAP_TYPE) { + val.cdp_vdev_param_rx_decap = value; + return cdp_txrx_set_vdev_param(soc_txrx_handle, + vdev_id, CDP_RX_DECAP_TYPE, + val); + } + + return QDF_STATUS_SUCCESS; +} + static QDF_STATUS target_if_vdev_mgr_set_param_send( struct wlan_objmgr_vdev *vdev, struct vdev_set_params *param) @@ -358,12 +368,29 @@ static QDF_STATUS target_if_vdev_mgr_create_send( QDF_STATUS status; struct wmi_unified *wmi_handle; uint8_t vap_addr[QDF_MAC_ADDR_SIZE] = {0}; + struct wlan_lmac_if_mlme_tx_ops *txops; + struct wlan_objmgr_psoc *psoc; + uint8_t vdev_id; if (!vdev || !param) { mlme_err("Invalid input"); return QDF_STATUS_E_INVAL; } + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + mlme_err("Failed to get psoc for VDEV_%d", + wlan_vdev_get_id(vdev)); + return QDF_STATUS_E_INVAL; + } + + txops = wlan_mlme_get_lmac_tx_ops(psoc); + if (!txops || !txops->psoc_vdev_rsp_timer_init) { + mlme_err("Failed to get mlme txrx_ops for VDEV_%d PSOC_%d", + wlan_vdev_get_id(vdev), wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; + } + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); if (!wmi_handle) { mlme_err("Failed to get WMI handle!"); @@ -374,6 +401,10 @@ static QDF_STATUS target_if_vdev_mgr_create_send( status = wmi_unified_vdev_create_send(wmi_handle, vap_addr, param); + vdev_id = wlan_vdev_get_id(vdev); + if (QDF_IS_STATUS_SUCCESS(status)) + status = txops->psoc_vdev_rsp_timer_init(psoc, vdev_id); + return status; } @@ -385,8 +416,8 @@ static QDF_STATUS target_if_vdev_mgr_start_send( struct wmi_unified *wmi_handle; struct wlan_objmgr_psoc *psoc; struct wlan_lmac_if_mlme_rx_ops *rx_ops; - struct vdev_response_timer *vdev_rsp; uint8_t vdev_id; + struct vdev_response_timer *vdev_rsp; if (!vdev || !param) { mlme_err("Invalid input"); @@ -402,37 +433,41 @@ static QDF_STATUS target_if_vdev_mgr_start_send( vdev_id = wlan_vdev_get_id(vdev); psoc = wlan_vdev_get_psoc(vdev); rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); - if (!rx_ops && !rx_ops->vdev_mgr_get_response_timer_info) { - mlme_err("VDEV_%d: No Rx Ops", vdev_id); + if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) { + mlme_err("VEV_%d: PSOC_%d No Rx Ops", vdev_id, + wlan_psoc_get_id(psoc)); return QDF_STATUS_E_INVAL; } - vdev_rsp = rx_ops->vdev_mgr_get_response_timer_info(vdev); + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); if (!vdev_rsp) { - mlme_err("VDEV_%d: Invalid response structure", vdev_id); - return QDF_STATUS_E_FAILURE; + mlme_err("VDEV_%d: PSOC_%d No vdev rsp timer", vdev_id, + wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; } vdev_rsp->expire_time = START_RESPONSE_TIMER; + target_if_wake_lock_timeout_acquire(psoc, START_WAKELOCK); + if (param->is_restart) - target_if_vdev_mgr_rsp_timer_start(vdev, vdev_rsp, + target_if_vdev_mgr_rsp_timer_start(psoc, vdev_rsp, RESTART_RESPONSE_BIT); else - target_if_vdev_mgr_rsp_timer_start(vdev, vdev_rsp, + target_if_vdev_mgr_rsp_timer_start(psoc, vdev_rsp, START_RESPONSE_BIT); status = wmi_unified_vdev_start_send(wmi_handle, param); if (QDF_IS_STATUS_ERROR(status)) { vdev_rsp->timer_status = QDF_STATUS_E_CANCELED; vdev_rsp->expire_time = 0; + target_if_wake_lock_timeout_release(psoc, START_WAKELOCK); if (param->is_restart) - target_if_vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, RESTART_RESPONSE_BIT); else - target_if_vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, START_RESPONSE_BIT); } - return status; } @@ -446,6 +481,7 @@ static QDF_STATUS target_if_vdev_mgr_delete_response_send( rsp.vdev_id = wlan_vdev_get_id(vdev); status = rx_ops->vdev_mgr_delete_response(psoc, &rsp); + target_if_wake_lock_timeout_release(psoc, DELETE_WAKELOCK); return status; } @@ -457,9 +493,9 @@ static QDF_STATUS target_if_vdev_mgr_delete_send( QDF_STATUS status; struct wlan_objmgr_psoc *psoc; struct wmi_unified *wmi_handle; - struct vdev_response_timer *vdev_rsp; struct wlan_lmac_if_mlme_rx_ops *rx_ops; uint8_t vdev_id; + struct vdev_response_timer *vdev_rsp; if (!vdev || !param) { mlme_err("Invalid input"); @@ -475,20 +511,23 @@ static QDF_STATUS target_if_vdev_mgr_delete_send( vdev_id = wlan_vdev_get_id(vdev); psoc = wlan_vdev_get_psoc(vdev); rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); - if (!rx_ops && !rx_ops->vdev_mgr_get_response_timer_info) { - mlme_err("VDEV_%d: No Rx Ops", vdev_id); + if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) { + mlme_err("VDEV_%d PSOC_%d No Rx Ops", vdev_id, + wlan_psoc_get_id(psoc)); return QDF_STATUS_E_INVAL; } - vdev_rsp = rx_ops->vdev_mgr_get_response_timer_info(vdev); + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); if (!vdev_rsp) { - mlme_err("VDEV_%d: Invalid response structure", vdev_id); - return QDF_STATUS_E_FAILURE; + mlme_err("VDEV_%d: PSOC_%d No vdev rsp timer", vdev_id, + wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; } vdev_rsp->expire_time = DELETE_RESPONSE_TIMER; - target_if_vdev_mgr_rsp_timer_start(vdev, vdev_rsp, + target_if_vdev_mgr_rsp_timer_start(psoc, vdev_rsp, DELETE_RESPONSE_BIT); + target_if_wake_lock_timeout_acquire(psoc, DELETE_WAKELOCK); status = wmi_unified_vdev_delete_send(wmi_handle, param->vdev_id); if (QDF_IS_STATUS_SUCCESS(status)) { @@ -498,15 +537,18 @@ static QDF_STATUS target_if_vdev_mgr_delete_send( if (!wmi_service_enabled(wmi_handle, wmi_service_sync_delete_cmds) || wlan_psoc_nif_feat_cap_get(psoc, - WLAN_SOC_F_TESTMODE_ENABLE)) + WLAN_SOC_F_TESTMODE_ENABLE)) { + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, + DELETE_RESPONSE_BIT); target_if_vdev_mgr_delete_response_send(vdev, rx_ops); + } } else { vdev_rsp->expire_time = 0; vdev_rsp->timer_status = QDF_STATUS_E_CANCELED; - target_if_vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, DELETE_RESPONSE_BIT); + target_if_wake_lock_timeout_release(psoc, DELETE_WAKELOCK); } - return status; } @@ -518,8 +560,9 @@ static QDF_STATUS target_if_vdev_mgr_stop_send( struct wmi_unified *wmi_handle; struct wlan_lmac_if_mlme_rx_ops *rx_ops; struct wlan_objmgr_psoc *psoc; - struct vdev_response_timer *vdev_rsp; uint8_t vdev_id; + struct vdev_response_timer *vdev_rsp; + if (!vdev || !param) { mlme_err("Invalid input"); @@ -535,29 +578,39 @@ static QDF_STATUS target_if_vdev_mgr_stop_send( vdev_id = wlan_vdev_get_id(vdev); psoc = wlan_vdev_get_psoc(vdev); rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); - - if (!rx_ops && !rx_ops->vdev_mgr_get_response_timer_info) { - mlme_err("VDEV_%d: No Rx Ops", vdev_id); + if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) { + mlme_err("VDEV_%d PSOC_%d No Rx Ops", vdev_id, + wlan_psoc_get_id(psoc)); return QDF_STATUS_E_INVAL; } - vdev_rsp = rx_ops->vdev_mgr_get_response_timer_info(vdev); + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); if (!vdev_rsp) { - mlme_err("VDEV_%d: Invalid response structure", vdev_id); - return QDF_STATUS_E_FAILURE; + mlme_err("VDEV_%d: PSOC_%d No vdev rsp timer", vdev_id, + wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; } vdev_rsp->expire_time = STOP_RESPONSE_TIMER; - target_if_vdev_mgr_rsp_timer_start(vdev, vdev_rsp, STOP_RESPONSE_BIT); + target_if_vdev_mgr_rsp_timer_start(psoc, vdev_rsp, STOP_RESPONSE_BIT); + /* + * START wakelock is acquired before sending the start command and + * released after sending up command to fw. This is to prevent the + * system to go into suspend state during the connection. + * In auth/assoc failure scenario UP command is not sent + * so release the START wakelock here. + */ + target_if_wake_lock_timeout_release(psoc, START_WAKELOCK); + target_if_wake_lock_timeout_acquire(psoc, STOP_WAKELOCK); status = wmi_unified_vdev_stop_send(wmi_handle, param->vdev_id); if (QDF_IS_STATUS_ERROR(status)) { vdev_rsp->expire_time = 0; vdev_rsp->timer_status = QDF_STATUS_E_CANCELED; - target_if_vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, STOP_RESPONSE_BIT); + target_if_wake_lock_timeout_release(psoc, STOP_WAKELOCK); } - return status; } @@ -567,6 +620,7 @@ static QDF_STATUS target_if_vdev_mgr_down_send( { QDF_STATUS status; struct wmi_unified *wmi_handle; + struct wlan_objmgr_psoc *psoc; if (!vdev || !param) { mlme_err("Invalid input"); @@ -579,7 +633,14 @@ static QDF_STATUS target_if_vdev_mgr_down_send( return QDF_STATUS_E_INVAL; } + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + mlme_err("Failed to get PSOC Object"); + return QDF_STATUS_E_INVAL; + } + status = wmi_unified_vdev_down_send(wmi_handle, param->vdev_id); + target_if_wake_lock_timeout_release(psoc, STOP_WAKELOCK); return status; } @@ -590,9 +651,8 @@ static QDF_STATUS target_if_vdev_mgr_up_send( { QDF_STATUS status; struct wmi_unified *wmi_handle; - struct vdev_set_params sparam = {0}; uint8_t bssid[QDF_MAC_ADDR_SIZE]; - uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; if (!vdev || !param) { mlme_err("Invalid input"); @@ -605,19 +665,15 @@ static QDF_STATUS target_if_vdev_mgr_up_send( return QDF_STATUS_E_INVAL; } - vdev_id = wlan_vdev_get_id(vdev); - sparam.vdev_id = vdev_id; - - sparam.param_id = WLAN_MLME_CFG_BEACON_INTERVAL; - wlan_util_vdev_get_param(vdev, WLAN_MLME_CFG_BEACON_INTERVAL, - &sparam.param_value); - status = target_if_vdev_mgr_set_param_send(vdev, &sparam); - if (QDF_IS_STATUS_ERROR(status)) - mlme_err("VDEV_%d: Failed to set beacon interval!", vdev_id); - + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + mlme_err("Failed to get PSOC Object"); + return QDF_STATUS_E_INVAL; + } ucfg_wlan_vdev_mgr_get_param_bssid(vdev, bssid); status = wmi_unified_vdev_up_send(wmi_handle, bssid, param); + target_if_wake_lock_timeout_release(psoc, START_WAKELOCK); return status; } @@ -759,7 +815,6 @@ static QDF_STATUS target_if_vdev_mgr_config_ratemask_cmd_send( status = wmi_unified_vdev_config_ratemask_cmd_send(wmi_handle, param); - return status; } @@ -795,14 +850,15 @@ static int32_t target_if_vdev_mgr_multi_vdev_restart_get_ref( { struct wlan_objmgr_psoc *psoc; struct wlan_objmgr_vdev *tvdev; - struct vdev_response_timer *vdev_rsp = NULL; struct wlan_lmac_if_mlme_rx_ops *rx_ops; - uint32_t vdev_idx; + int32_t vdev_idx = -1; int32_t last_vdev_idx = -1; + struct vdev_response_timer *vdev_rsp; psoc = wlan_pdev_get_psoc(pdev); rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); - if (!rx_ops && !rx_ops->vdev_mgr_get_response_timer_info) { + + if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) { mlme_err("VDEV_%d: No Rx Ops", vdev_idx); return last_vdev_idx; } @@ -818,15 +874,17 @@ static int32_t target_if_vdev_mgr_multi_vdev_restart_get_ref( return last_vdev_idx; } - last_vdev_idx = vdev_idx; - vdev_rsp = - rx_ops->vdev_mgr_get_response_timer_info(tvdev); + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info( + psoc, + wlan_vdev_get_id(tvdev)); if (!vdev_rsp) { - mlme_err("VDEV_%d: No Rx Ops", vdev_idx); + mlme_err("VDEV_%d PSOC_%d No vdev rsp timer", + vdev_idx, wlan_psoc_get_id(psoc)); return last_vdev_idx; } - target_if_vdev_mgr_rsp_timer_start(tvdev, vdev_rsp, + last_vdev_idx = vdev_idx; + target_if_vdev_mgr_rsp_timer_start(psoc, vdev_rsp, RESTART_RESPONSE_BIT); vdev_timer_started[vdev_idx] = true; } @@ -844,19 +902,30 @@ static void target_if_vdev_mgr_multi_vdev_restart_rel_ref( struct wlan_objmgr_psoc *psoc; struct wlan_objmgr_vdev *tvdev; struct wlan_lmac_if_mlme_rx_ops *rx_ops; - struct vdev_response_timer *vdev_rsp = NULL; uint32_t vdev_idx; + struct vdev_response_timer *vdev_rsp; psoc = wlan_pdev_get_psoc(pdev); rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) { + mlme_err("VDEV_%d: No Rx Ops", last_vdev_idx); + return; + } + for (vdev_idx = 0; vdev_idx <= last_vdev_idx; vdev_idx++) { tvdev = vdev_list[vdev_idx]; + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, + vdev_idx); + if (!vdev_rsp) { + mlme_err("VDEV_%d: PSOC_%d No vdev rsp timer", + vdev_idx, wlan_psoc_get_id(psoc)); + return; + } + if (QDF_IS_STATUS_ERROR(status)) { - vdev_rsp = - rx_ops->vdev_mgr_get_response_timer_info(tvdev); - if (vdev_rsp && vdev_timer_started[vdev_idx]) { + if (vdev_timer_started[vdev_idx]) { target_if_vdev_mgr_rsp_timer_stop( - tvdev, vdev_rsp, + psoc, vdev_rsp, RESTART_RESPONSE_BIT); vdev_timer_started[vdev_idx] = false; } @@ -968,6 +1037,96 @@ static QDF_STATUS target_if_vdev_mgr_sta_ps_param_send( return status; } +static QDF_STATUS target_if_vdev_mgr_peer_delete_all_send( + struct wlan_objmgr_vdev *vdev, + struct peer_delete_all_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + struct wlan_objmgr_psoc *psoc; + uint8_t vdev_id; + struct vdev_response_timer *vdev_rsp; + + if (!vdev || !param) { + mlme_err("Invalid input"); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + vdev_id = wlan_vdev_get_id(vdev); + psoc = wlan_vdev_get_psoc(vdev); + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + + if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) { + mlme_err("VDEV_%d PSOC_%d No Rx Ops", vdev_id, + wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; + } + + vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); + if (!vdev_rsp) { + mlme_err("VDEV_%d: PSOC_%d No vdev rsp timer", vdev_id, + wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_INVAL; + } + + vdev_rsp->expire_time = PEER_DELETE_ALL_RESPONSE_TIMER; + target_if_vdev_mgr_rsp_timer_start(psoc, vdev_rsp, + PEER_DELETE_ALL_RESPONSE_BIT); + + status = wmi_unified_peer_delete_all_send(wmi_handle, param); + if (QDF_IS_STATUS_ERROR(status)) { + vdev_rsp->expire_time = 0; + vdev_rsp->timer_status = QDF_STATUS_E_CANCELED; + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, + PEER_DELETE_ALL_RESPONSE_BIT); + } + return status; +} + +#if defined(WLAN_SUPPORT_FILS) || defined(CONFIG_BAND_6GHZ) +static QDF_STATUS target_if_vdev_mgr_fils_enable_send( + struct wlan_objmgr_vdev *vdev, + struct config_fils_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + if (!vdev || !param) { + mlme_err("Invalid input"); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_vdev_fils_enable_cmd_send(wmi_handle, param); + + return status; +} + +static void target_if_vdev_register_tx_fils( + struct wlan_lmac_if_mlme_tx_ops *mlme_tx_ops) +{ + mlme_tx_ops->vdev_fils_enable_send = + target_if_vdev_mgr_fils_enable_send; +} +#else +static void target_if_vdev_register_tx_fils( + struct wlan_lmac_if_mlme_tx_ops *mlme_tx_ops) +{ +} +#endif + QDF_STATUS target_if_vdev_mgr_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) { @@ -1012,14 +1171,27 @@ target_if_vdev_mgr_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) mlme_tx_ops->beacon_tmpl_send = target_if_vdev_mgr_beacon_tmpl_send; mlme_tx_ops->vdev_set_param_send = target_if_vdev_mgr_set_param_send; + mlme_tx_ops->vdev_set_tx_rx_decap_type = + target_if_vdev_set_tx_rx_decap_type; mlme_tx_ops->vdev_sta_ps_param_send = target_if_vdev_mgr_sta_ps_param_send; - mlme_tx_ops->vdev_mgr_rsp_timer_init = - target_if_vdev_mgr_rsp_timer_init; - mlme_tx_ops->vdev_mgr_rsp_timer_mod = + mlme_tx_ops->psoc_vdev_rsp_timer_mod = target_if_vdev_mgr_rsp_timer_mod; + mlme_tx_ops->peer_delete_all_send = + target_if_vdev_mgr_peer_delete_all_send; + target_if_vdev_register_tx_fils(mlme_tx_ops); + + mlme_tx_ops->psoc_vdev_rsp_timer_init = + target_if_psoc_vdev_rsp_timer_init; + mlme_tx_ops->psoc_vdev_rsp_timer_deinit = + target_if_psoc_vdev_rsp_timer_deinit; + mlme_tx_ops->psoc_vdev_rsp_timer_inuse = + target_if_psoc_vdev_rsp_timer_inuse; + mlme_tx_ops->psoc_wake_lock_init = + target_if_wake_lock_init; + mlme_tx_ops->psoc_wake_lock_deinit = + target_if_wake_lock_deinit; mlme_tx_ops->vdev_mgr_rsp_timer_stop = target_if_vdev_mgr_rsp_timer_stop; - return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/regulatory/src/target_if_reg_11d.c b/drivers/staging/qca-wifi-host-cmn/target_if/regulatory/src/target_if_reg_11d.c index 2e2bca8e89ae20ec1f783b9d96b789d7bdf3b6ed..c857868d380b38572ea4ddbbb820fa27d52b95e1 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/regulatory/src/target_if_reg_11d.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/regulatory/src/target_if_reg_11d.c @@ -36,7 +36,7 @@ bool tgt_if_regulatory_is_11d_offloaded(struct wlan_objmgr_psoc *psoc) return false; if (reg_rx_ops->reg_ignore_fw_reg_offload_ind && - reg_rx_ops->reg_ignore_fw_reg_offload_ind(psoc)) { + reg_rx_ops->reg_ignore_fw_reg_offload_ind(psoc)) { target_if_debug("Ignore fw reg 11d offload indication"); return 0; } diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/scan/src/target_if_scan.c b/drivers/staging/qca-wifi-host-cmn/target_if/scan/src/target_if_scan.c index b63b38b2595f338e977d81cbec14e870cea0f8e7..a3b825bfac3e2e1d81218a26d51ff167be98f616 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/scan/src/target_if_scan.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/scan/src/target_if_scan.c @@ -29,7 +29,6 @@ #include #include - static inline struct wlan_lmac_if_scan_rx_ops * target_if_scan_get_rx_ops(struct wlan_objmgr_psoc *psoc) { @@ -93,12 +92,10 @@ target_if_scan_event_handler(ol_scn_t scn, uint8_t *data, uint32_t datalen) int target_if_nlo_complete_handler(ol_scn_t scn, uint8_t *data, uint32_t len) { - wmi_nlo_event *nlo_event; struct scan_event_info *event_info; struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; struct wlan_lmac_if_scan_rx_ops *scan_rx_ops; - WMI_NLO_MATCH_EVENTID_param_tlvs *param_buf = - (WMI_NLO_MATCH_EVENTID_param_tlvs *) data; QDF_STATUS status; if (!scn || !data) { @@ -112,16 +109,25 @@ int target_if_nlo_complete_handler(ol_scn_t scn, uint8_t *data, return -EINVAL; } + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("wmi_handle is NULL"); + return -EINVAL; + } + event_info = qdf_mem_malloc(sizeof(*event_info)); if (!event_info) return -ENOMEM; - nlo_event = param_buf->fixed_param; - target_if_debug("PNO complete event received for vdev %d", - nlo_event->vdev_id); + if (wmi_extract_nlo_complete_ev_param(wmi_handle, data, + &event_info->event)) { + target_if_err("Failed to extract WMI PNO complete event"); + qdf_mem_free(event_info); + return -EINVAL; + } - event_info->event.type = SCAN_EVENT_TYPE_NLO_COMPLETE; - event_info->event.vdev_id = nlo_event->vdev_id; + target_if_debug("PNO complete event received for vdev %d", + event_info->event.vdev_id); scan_rx_ops = target_if_scan_get_rx_ops(psoc); if (scan_rx_ops->scan_ev_handler) { @@ -141,12 +147,10 @@ int target_if_nlo_complete_handler(ol_scn_t scn, uint8_t *data, int target_if_nlo_match_event_handler(ol_scn_t scn, uint8_t *data, uint32_t len) { - wmi_nlo_event *nlo_event; struct scan_event_info *event_info; struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; struct wlan_lmac_if_scan_rx_ops *scan_rx_ops; - WMI_NLO_MATCH_EVENTID_param_tlvs *param_buf = - (WMI_NLO_MATCH_EVENTID_param_tlvs *) data; QDF_STATUS status; if (!scn || !data) { @@ -160,16 +164,25 @@ int target_if_nlo_match_event_handler(ol_scn_t scn, uint8_t *data, return -EINVAL; } + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("wmi_handle is NULL"); + return -EINVAL; + } + event_info = qdf_mem_malloc(sizeof(*event_info)); if (!event_info) return -ENOMEM; - nlo_event = param_buf->fixed_param; - target_if_debug("PNO match event received for vdev %d", - nlo_event->vdev_id); + if (wmi_extract_nlo_match_ev_param(wmi_handle, data, + &event_info->event)) { + target_if_err("Failed to extract WMI PNO match event"); + qdf_mem_free(event_info); + return -EINVAL; + } - event_info->event.type = SCAN_EVENT_TYPE_NLO_MATCH; - event_info->event.vdev_id = nlo_event->vdev_id; + target_if_debug("PNO match event received for vdev %d", + event_info->event.vdev_id); scan_rx_ops = target_if_scan_get_rx_ops(psoc); if (scan_rx_ops->scan_ev_handler) { @@ -378,7 +391,7 @@ QDF_STATUS target_if_scan_start(struct wlan_objmgr_pdev *pdev, struct scan_start_request *req) { - void *pdev_wmi_handle; + wmi_unified_t pdev_wmi_handle; pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev); if (!pdev_wmi_handle) { @@ -392,7 +405,7 @@ QDF_STATUS target_if_scan_cancel(struct wlan_objmgr_pdev *pdev, struct scan_cancel_param *req) { - void *pdev_wmi_handle; + wmi_unified_t pdev_wmi_handle; pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev); if (!pdev_wmi_handle) { diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.c b/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.c index e14eab404b9fedc482316e4ba47951477749406e..6dc413934eca84cf7157083f176d792d05e533de 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011,2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011,2017-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -27,10 +27,11 @@ #include #include #include -#include #include #include #include +#include +#include /** * @spectral_ops - Spectral function table, holds the Spectral functions that @@ -88,12 +89,14 @@ target_if_spectral_get_vdev(struct target_if_spectral *spectral) * target_if_send_vdev_spectral_configure_cmd() - Send WMI command to configure * spectral parameters * @spectral: Pointer to Spectral target_if internal private data + * @smode: Spectral scan mode * @param: Pointer to spectral_config giving the Spectral configuration * * Return: QDF_STATUS_SUCCESS on success, negative error code on failure */ static int target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral, + enum spectral_scan_mode smode, struct spectral_config *param) { struct vdev_spectral_configure_params sparam; @@ -133,6 +136,8 @@ target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral, sparam.bin_scale = param->ss_bin_scale; sparam.dbm_adj = param->ss_dbm_adj; sparam.chn_mask = param->ss_chn_mask; + sparam.mode = smode; + sparam.center_freq = param->ss_frequency; return spectral->param_wmi_cmd_ops.wmi_spectral_configure_cmd_send( GET_WMI_HDL_FROM_PDEV(pdev), &sparam); @@ -142,6 +147,7 @@ target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral, * target_if_send_vdev_spectral_enable_cmd() - Send WMI command to * enable/disable Spectral * @spectral: Pointer to Spectral target_if internal private data + * @smode: Spectral scan mode * @is_spectral_active_valid: Flag to indicate if spectral activate (trigger) is * valid * @is_spectral_active: Value of spectral activate @@ -152,6 +158,7 @@ target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral, */ static int target_if_send_vdev_spectral_enable_cmd(struct target_if_spectral *spectral, + enum spectral_scan_mode smode, uint8_t is_spectral_active_valid, uint8_t is_spectral_active, uint8_t is_spectral_enabled_valid, @@ -180,6 +187,7 @@ target_if_send_vdev_spectral_enable_cmd(struct target_if_spectral *spectral, param.enabled_valid = is_spectral_enabled_valid; param.active = is_spectral_active; param.enabled = is_spectral_enabled; + param.mode = smode; return spectral->param_wmi_cmd_ops.wmi_spectral_enable_cmd_send( GET_WMI_HDL_FROM_PDEV(pdev), ¶m); @@ -345,7 +353,7 @@ target_if_log_read_spectral_params( const char *function_name, struct spectral_config *pparam) { - spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Returning following params:\nss_count = %u\nss_period = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u\n", + spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Returning following params:\nss_count = %u\nss_period = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u\nss_frequency=%u\n", function_name, pparam->ss_count, pparam->ss_period, @@ -364,7 +372,8 @@ target_if_log_read_spectral_params( pparam->ss_rpt_mode, pparam->ss_bin_scale, pparam->ss_dbm_adj, - pparam->ss_chn_mask); + pparam->ss_chn_mask, + pparam->ss_frequency); } /** @@ -666,7 +675,7 @@ target_if_log_write_spectral_params( const char *function_name, int ret) { - spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Params:\nss_count = %u\nss_period = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u\nstatus = %d", + spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Params:\nss_count = %u\nss_period = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u\nss_frequency=%u\nstatus = %d", function_name, param->ss_count, param->ss_period, @@ -684,7 +693,10 @@ target_if_log_write_spectral_params( param->ss_pwr_format, param->ss_rpt_mode, param->ss_bin_scale, - param->ss_dbm_adj, param->ss_chn_mask, ret); + param->ss_dbm_adj, + param->ss_chn_mask, + param->ss_frequency, + ret); } /** @@ -731,7 +743,7 @@ target_if_spectral_info_write( pval = (uint8_t *)input; qdf_spin_lock(&info->osps_lock); - ret = target_if_send_vdev_spectral_enable_cmd(spectral, + ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode, 1, *pval, 0, 0); target_if_log_write_spectral_active( @@ -761,7 +773,7 @@ target_if_spectral_info_write( pval = (uint8_t *)input; qdf_spin_lock(&info->osps_lock); - ret = target_if_send_vdev_spectral_enable_cmd(spectral, + ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode, 0, 0, 1, *pval); target_if_log_write_spectral_enabled( @@ -792,7 +804,7 @@ target_if_spectral_info_write( qdf_spin_lock(&info->osps_lock); ret = target_if_send_vdev_spectral_configure_cmd(spectral, - param); + smode, param); target_if_log_write_spectral_params( param, @@ -1324,6 +1336,114 @@ target_if_spectral_get_macaddr(void *arg, char *addr) return 0; } +/** + * target_if_init_spectral_param_min_max() - Initialize Spectral parameter + * min and max values + * + * @param_min_max: Pointer to Spectral parameter min and max structure + * @gen: Spectral HW generation + * @target_type: Target type + * + * Initialize Spectral parameter min and max values + * + * Return: QDF_STATUS + */ +static QDF_STATUS +target_if_init_spectral_param_min_max( + struct spectral_param_min_max *param_min_max, + enum spectral_gen gen, uint32_t target_type) +{ + switch (gen) { + case SPECTRAL_GEN3: + param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3; + param_min_max->fft_size_max[CH_WIDTH_20MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; + if (target_type == TARGET_TYPE_QCN9000) { + param_min_max->fft_size_max[CH_WIDTH_40MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; + param_min_max->fft_size_max[CH_WIDTH_80MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; + param_min_max->fft_size_max[CH_WIDTH_160MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; + param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; + } else { + param_min_max->fft_size_max[CH_WIDTH_40MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; + param_min_max->fft_size_max[CH_WIDTH_80MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; + param_min_max->fft_size_max[CH_WIDTH_160MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; + param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; + } + break; + + case SPECTRAL_GEN2: + param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2; + param_min_max->fft_size_max[CH_WIDTH_20MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; + param_min_max->fft_size_max[CH_WIDTH_40MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; + param_min_max->fft_size_max[CH_WIDTH_80MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; + param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; + param_min_max->fft_size_max[CH_WIDTH_160MHZ] = + SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; + break; + + default: + spectral_err("Invalid spectral generation %d", gen); + return QDF_STATUS_E_INVAL; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_init_spectral_param_properties() - Initialize Spectral parameter + * properties + * @spectral: Pointer to Spectral target_if internal private data + * + * Initialize Spectral parameter properties + * + * Return: QDF_STATUS + */ +static QDF_STATUS +target_if_init_spectral_param_properties(struct target_if_spectral *spectral) +{ + enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; + int param; + + /* Initialize default values for properties. + * Default values are supported for all the parameters for all modes + * and allows different values for each mode for all the parameters . + */ + for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { + for (param = 0; param < SPECTRAL_PARAM_MAX; param++) { + spectral->properties[smode][param].supported = true; + spectral->properties[smode][param].common_all_modes = + false; + } + } + + /* Once FW advertisement is in place remove this hard coding */ + smode = SPECTRAL_SCAN_MODE_NORMAL; + spectral->properties[SPECTRAL_SCAN_MODE_NORMAL] + [SPECTRAL_PARAM_FREQUENCY].supported = false; + for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { + spectral->properties[smode] + [SPECTRAL_PARAM_SPECT_PRI].common_all_modes = true; + spectral->properties[smode] + [SPECTRAL_PARAM_SCAN_PERIOD].common_all_modes = true; + spectral->properties[smode] + [SPECTRAL_PARAM_INIT_DELAY].common_all_modes = true; + } + + return QDF_STATUS_SUCCESS; +} + /** * target_if_init_spectral_capability() - Initialize Spectral capability * @spectral: Pointer to Spectral target_if internal private data @@ -1342,6 +1462,11 @@ target_if_init_spectral_capability(struct target_if_spectral *spectral) struct target_psoc_info *tgt_psoc_info; struct wlan_psoc_host_service_ext_param *ext_svc_param; struct spectral_caps *pcap = &spectral->capability; + struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL; + struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL; + struct wlan_psoc_host_chainmask_table *table; + int j; + uint32_t table_id; pdev = spectral->pdev_obj; psoc = wlan_pdev_get_psoc(pdev); @@ -1368,19 +1493,56 @@ target_if_init_spectral_capability(struct target_if_spectral *spectral) pcap->spectral_cap = 1; pcap->advncd_spectral_cap = 1; pcap->hw_gen = spectral->spectral_gen; + if (spectral->spectral_gen >= SPECTRAL_GEN3) { + mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); + if (!mac_phy_cap_arr) { + spectral_err("mac phy cap array is null"); + return QDF_STATUS_E_FAILURE; + } - for (param_idx = 0; param_idx < num_bin_scaling_params; param_idx++) { - if (scaling_params[param_idx].pdev_id == pdev_id) { - pcap->is_scaling_params_populated = true; - pcap->formula_id = scaling_params[param_idx].formula_id; - pcap->low_level_offset = - scaling_params[param_idx].low_level_offset; - pcap->high_level_offset = - scaling_params[param_idx].high_level_offset; - pcap->rssi_thr = scaling_params[param_idx].rssi_thr; - pcap->default_agc_max_gain = - scaling_params[param_idx].default_agc_max_gain; - break; + mac_phy_cap = &mac_phy_cap_arr[pdev_id]; + if (!mac_phy_cap) { + spectral_err("mac phy cap is null"); + return QDF_STATUS_E_FAILURE; + } + + table_id = mac_phy_cap->chainmask_table_id; + table = &ext_svc_param->chainmask_table[table_id]; + if (!table) { + spectral_err("chainmask table not found"); + return QDF_STATUS_E_FAILURE; + } + + for (j = 0; j < table->num_valid_chainmasks; j++) { + pcap->agile_spectral_cap |= + table->cap_list[j].supports_aSpectral; + pcap->agile_spectral_cap_160 |= + table->cap_list[j].supports_aSpectral_160; + } + pcap->agile_spectral_cap_80p80 = pcap->agile_spectral_cap_160; + } else { + pcap->agile_spectral_cap = false; + pcap->agile_spectral_cap_160 = false; + pcap->agile_spectral_cap_80p80 = false; + } + + if (scaling_params) { + for (param_idx = 0; param_idx < num_bin_scaling_params; + param_idx++) { + if (scaling_params[param_idx].pdev_id == pdev_id) { + pcap->is_scaling_params_populated = true; + pcap->formula_id = + scaling_params[param_idx].formula_id; + pcap->low_level_offset = + scaling_params[param_idx].low_level_offset; + pcap->high_level_offset = + scaling_params[param_idx].high_level_offset; + pcap->rssi_thr = + scaling_params[param_idx].rssi_thr; + pcap->default_agc_max_gain = + scaling_params[param_idx].default_agc_max_gain; + break; + } } } @@ -1916,6 +2078,114 @@ target_if_spectral_attach_simulation(struct target_if_spectral *spectral) } #endif +/** + * target_if_spectral_len_adj_swar_init() - Initialize FFT bin length adjustment + * related info + * @swar: Pointer to Spectral FFT bin length adjustment SWAR params + * @target_type: Target type + * + * Function to Initialize parameters related to Spectral FFT bin + * length adjustment SWARs. + * + * Return: void + */ +static void +target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar *swar, + uint32_t target_type) +{ + if (target_type == TARGET_TYPE_QCA8074V2 || + target_type == TARGET_TYPE_QCN9000) + swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE; + else if (target_type == TARGET_TYPE_QCA8074 || + target_type == TARGET_TYPE_QCA6018 || + target_type == TARGET_TYPE_QCA6390) + swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE; + else + swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR; + + if (target_type == TARGET_TYPE_QCA8074 || + target_type == TARGET_TYPE_QCA8074V2 || + target_type == TARGET_TYPE_QCA6018 || + target_type == TARGET_TYPE_QCN9000) { + swar->inband_fftbin_size_adj = 1; + swar->null_fftbin_adj = 1; + } else { + swar->inband_fftbin_size_adj = 0; + swar->null_fftbin_adj = 0; + } + + if (target_type == TARGET_TYPE_QCA8074V2) + swar->packmode_fftbin_size_adj = 1; + else + swar->packmode_fftbin_size_adj = 0; +} + +/** + * target_if_spectral_report_params_init() - Initialize parameters which + * describes the structure of Spectral reports + * + * @rparams: Pointer to Spectral report parameter object + * @target_type: target type + * + * Function to Initialize parameters related to the structure of Spectral + * reports. + * + * Return: void + */ +static void +target_if_spectral_report_params_init( + struct spectral_report_params *rparams, + uint32_t target_type) +{ + /* This entries are currently used by gen3 chipsets only. Hence + * initialization is done for gen3 alone. In future if other generations + * needs to use them they have to add proper initial values. + */ + if (target_type == TARGET_TYPE_QCN9000) + rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_2; + else + rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_1; + + switch (rparams->version) { + case SPECTRAL_REPORT_FORMAT_VERSION_1: + rparams->ssumaary_padding_bytes = + NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V1; + rparams->fft_report_hdr_len = + FFT_REPORT_HEADER_LENGTH_GEN3_V1; + break; + case SPECTRAL_REPORT_FORMAT_VERSION_2: + rparams->ssumaary_padding_bytes = + NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V2; + rparams->fft_report_hdr_len = + FFT_REPORT_HEADER_LENGTH_GEN3_V2; + break; + default: + qdf_assert_always(0); + } +} + +/** + * target_if_spectral_timestamp_war_init() - Initialize Spectral timestamp WAR + * related info + * @twar: Pointer to Spectral timstamp WAR related info + * + * Function to Initialize parameters related to Spectral timestamp WAR + * + * Return: void + */ +static void +target_if_spectral_timestamp_war_init(struct spectral_timestamp_war *twar) +{ + enum spectral_scan_mode smode; + + smode = SPECTRAL_SCAN_MODE_NORMAL; + for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { + twar->last_fft_timestamp[smode] = 0; + twar->timestamp_war_offset[smode] = 0; + } + twar->target_reset_count = 0; +} + /** * target_if_pdev_spectral_init() - Initialize target_if Spectral * functionality for the given pdev @@ -1936,6 +2206,7 @@ target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) struct wlan_objmgr_psoc *psoc; struct wlan_lmac_if_target_tx_ops *tx_ops; enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; + QDF_STATUS status; if (!pdev) { spectral_err("SPECTRAL: pdev is NULL!"); @@ -1990,32 +2261,21 @@ target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) qdf_spinlock_create(&spectral->noise_pwr_reports_lock); target_if_spectral_clear_stats(spectral); - if (target_type == TARGET_TYPE_QCA8074V2 || - target_type == TARGET_TYPE_QCA6018) - spectral->fftbin_size_war = - SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE; - else if (target_type == TARGET_TYPE_QCA8074 || - target_type == TARGET_TYPE_QCA6390) - spectral->fftbin_size_war = - SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE; - else - spectral->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR; - if (target_type == TARGET_TYPE_QCA8074 || target_type == TARGET_TYPE_QCA8074V2 || - target_type == TARGET_TYPE_QCA6018) { - spectral->inband_fftbin_size_adj = 1; - spectral->null_fftbin_adj = 1; - } else { - spectral->inband_fftbin_size_adj = 0; - spectral->null_fftbin_adj = 0; - } - spectral->last_fft_timestamp = 0; - spectral->timestamp_war_offset = 0; + target_type == TARGET_TYPE_QCA6018 || + target_type == TARGET_TYPE_QCA6390 || + target_type == TARGET_TYPE_QCN9000) + spectral->direct_dma_support = true; + + target_if_spectral_len_adj_swar_init(&spectral->len_adj_swar, + target_type); + target_if_spectral_report_params_init(&spectral->rparams, target_type); if ((target_type == TARGET_TYPE_QCA8074) || (target_type == TARGET_TYPE_QCA8074V2) || (target_type == TARGET_TYPE_QCA6018) || + (target_type == TARGET_TYPE_QCN9000) || (target_type == TARGET_TYPE_QCA6290) || (target_type == TARGET_TYPE_QCA6390)) { spectral->spectral_gen = SPECTRAL_GEN3; @@ -2024,8 +2284,6 @@ target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3; spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3; spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3; - spectral->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3; - spectral->fft_size_max = SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3; } else { spectral->spectral_gen = SPECTRAL_GEN2; spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2; @@ -2033,10 +2291,17 @@ target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2; spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2; spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2); - spectral->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2; - spectral->fft_size_max = SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; } + status = target_if_init_spectral_param_min_max( + &spectral->param_min_max, + spectral->spectral_gen, target_type); + if (QDF_IS_STATUS_ERROR(status)) { + spectral_err("Failed to initialize parameter min max values"); + goto fail; + } + + target_if_init_spectral_param_properties(spectral); /* Init spectral capability */ if (target_if_init_spectral_capability(spectral) != QDF_STATUS_SUCCESS) { @@ -2047,6 +2312,7 @@ target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) return NULL; target_if_init_spectral_ops(spectral); + target_if_spectral_timestamp_war_init(&spectral->timestamp_war); /* Spectral mode specific init */ for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { @@ -2058,8 +2324,7 @@ target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) target_if_spectral_register_funcs(spectral, &spectral_ops); if (target_if_spectral_check_hw_capability(spectral) == false) { - target_if_spectral_detach(spectral); - spectral = NULL; + goto fail; } else { /* * TODO: Once the driver architecture transitions to chipset @@ -2090,6 +2355,10 @@ target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) } return spectral; + +fail: + target_if_spectral_detach(spectral); + return NULL; } /** @@ -2116,153 +2385,634 @@ target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev) return; } +/* target_if_spectral_find_agile_width() - Given a channel width enum, find the + * corresponding translation for Agile channel width. + * Translation schema of different operating modes: + * 20 -> 20, 40 -> 40, (80 & 160 & 80_80) -> 80. + * @chwidth: Channel width enum. + * + * Return: The translated channel width enum. + */ +static enum phy_ch_width +target_if_spectral_find_agile_width(enum phy_ch_width chwidth) +{ + switch (chwidth) { + case CH_WIDTH_20MHZ: + return CH_WIDTH_20MHZ; + case CH_WIDTH_40MHZ: + return CH_WIDTH_40MHZ; + case CH_WIDTH_80MHZ: + case CH_WIDTH_80P80MHZ: + case CH_WIDTH_160MHZ: + return CH_WIDTH_80MHZ; + default: + spectral_err("Invalid chwidth enum %d", chwidth); + return CH_WIDTH_INVALID; + } +} + /** - * target_if_set_spectral_config() - Set spectral config - * @pdev: Pointer to pdev object - * @threshtype: config type - * @value: config value - * @smode: Spectral scan mode - * @err: Spectral error code + * target_if_calculate_center_freq() - Helper routine to + * check whether given frequency is center frequency of a + * WLAN channel * - * API to set spectral configurations + * @spectral: Pointer to Spectral object + * @chan_freq: Center frequency of a WLAN channel + * @is_valid: Indicates whether given frequency is valid * - * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure + * Return: QDF_STATUS */ -QDF_STATUS -target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev, - const uint32_t threshtype, const uint32_t value, - const enum spectral_scan_mode smode, - enum spectral_cp_error_code *err) +static QDF_STATUS +target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev *pdev, + uint32_t chan_freq, + bool *is_valid) { - struct spectral_config params; - struct target_if_spectral_ops *p_sops = NULL; - struct target_if_spectral *spectral = NULL; - struct spectral_config *sparams; + struct regulatory_channel *cur_chan_list; + int i; - spectral = get_target_if_spectral_handle_from_pdev(pdev); - p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); - if (!spectral) { - spectral_err("spectral object is NULL"); + if (!pdev) { + spectral_err("pdev object is null"); return QDF_STATUS_E_FAILURE; } - if (smode >= SPECTRAL_SCAN_MODE_MAX) { - spectral_err("Invalid Spectral mode %u", smode); + if (!is_valid) { + spectral_err("is valid argument is null"); return QDF_STATUS_E_FAILURE; } - sparams = &spectral->params[smode]; - if (!spectral->params_valid[smode]) { - target_if_spectral_info_read(spectral, - smode, - TARGET_IF_SPECTRAL_INFO_PARAMS, - &spectral->params[smode], - sizeof(spectral->params[smode])); - spectral->params_valid[smode] = true; + cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list)); + if (!cur_chan_list) + return QDF_STATUS_E_FAILURE; + + if (wlan_reg_get_current_chan_list( + pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { + spectral_err("Failed to get cur_chan list"); + qdf_mem_free(cur_chan_list); + return QDF_STATUS_E_FAILURE; } - switch (threshtype) { - case SPECTRAL_PARAM_FFT_PERIOD: - sparams->ss_fft_period = value; - break; - case SPECTRAL_PARAM_SCAN_PERIOD: - sparams->ss_period = value; - break; - case SPECTRAL_PARAM_SCAN_COUNT: - sparams->ss_count = value; - break; - case SPECTRAL_PARAM_SHORT_REPORT: - sparams->ss_short_report = (!!value) ? true : false; - break; - case SPECTRAL_PARAM_SPECT_PRI: - sparams->ss_spectral_pri = (!!value) ? true : false; - break; - case SPECTRAL_PARAM_FFT_SIZE: - if ((value < spectral->fft_size_min) || - (value > spectral->fft_size_max)) - return QDF_STATUS_E_FAILURE; - sparams->ss_fft_size = value; - break; - case SPECTRAL_PARAM_GC_ENA: - sparams->ss_gc_ena = !!value; - break; - case SPECTRAL_PARAM_RESTART_ENA: - sparams->ss_restart_ena = !!value; - break; - case SPECTRAL_PARAM_NOISE_FLOOR_REF: - sparams->ss_noise_floor_ref = value; - break; - case SPECTRAL_PARAM_INIT_DELAY: - sparams->ss_init_delay = value; - break; - case SPECTRAL_PARAM_NB_TONE_THR: - sparams->ss_nb_tone_thr = value; - break; - case SPECTRAL_PARAM_STR_BIN_THR: - sparams->ss_str_bin_thr = value; - break; - case SPECTRAL_PARAM_WB_RPT_MODE: - sparams->ss_wb_rpt_mode = !!value; - break; - case SPECTRAL_PARAM_RSSI_RPT_MODE: - sparams->ss_rssi_rpt_mode = !!value; - break; - case SPECTRAL_PARAM_RSSI_THR: - sparams->ss_rssi_thr = value; - break; - case SPECTRAL_PARAM_PWR_FORMAT: - sparams->ss_pwr_format = !!value; - break; - case SPECTRAL_PARAM_RPT_MODE: - if ((value < SPECTRAL_PARAM_RPT_MODE_MIN) || - (value > SPECTRAL_PARAM_RPT_MODE_MAX)) - return QDF_STATUS_E_FAILURE; - sparams->ss_rpt_mode = value; - break; - case SPECTRAL_PARAM_BIN_SCALE: - sparams->ss_bin_scale = value; - break; - case SPECTRAL_PARAM_DBM_ADJ: - sparams->ss_dbm_adj = !!value; - break; - case SPECTRAL_PARAM_CHN_MASK: - sparams->ss_chn_mask = value; - break; - case SPECTRAL_PARAM_FREQUENCY: - sparams->ss_frequency = value; - break; + *is_valid = false; + for (i = 0; i < NUM_CHANNELS; i++) { + uint32_t flags; + uint32_t center_freq; + + flags = cur_chan_list[i].chan_flags; + center_freq = cur_chan_list[i].center_freq; + + if (!(flags & REGULATORY_CHAN_DISABLED) && + (center_freq == chan_freq)) { + *is_valid = true; + break; + } } - p_sops->configure_spectral(spectral, sparams, smode); - /* only to validate the writes */ - p_sops->get_spectral_config(spectral, ¶ms, smode); + qdf_mem_free(cur_chan_list); + return QDF_STATUS_SUCCESS; } /** - * target_if_get_fft_bin_count() - Get fft bin count for a given fft length - * @fft_len: FFT length - * @pdev: Pointer to pdev object + * target_if_calculate_center_freq() - Helper routine to + * find the center frequency of the agile span from a + * WLAN channel center frequency * - * API to get fft bin count for a given fft length + * @spectral: Pointer to Spectral object + * @chan_freq: Center frequency of a WLAN channel + * @center_freq: Pointer to center frequency * - * Return: FFt bin count + * Return: QDF_STATUS */ -static int -target_if_get_fft_bin_count(int fft_len) +static QDF_STATUS +target_if_calculate_center_freq(struct target_if_spectral *spectral, + uint16_t chan_freq, + uint16_t *center_freq) { - int bin_count = 0; + struct wlan_objmgr_vdev *vdev; + enum phy_ch_width ch_width; + enum phy_ch_width agile_ch_width; - switch (fft_len) { - case 5: - bin_count = 16; - break; - case 6: - bin_count = 32; - break; - case 7: - bin_count = 64; - break; + if (!spectral) { + spectral_err("spectral target if object is null"); + return QDF_STATUS_E_FAILURE; + } + + if (!center_freq) { + spectral_err("center_freq argument is null"); + return QDF_STATUS_E_FAILURE; + } + + vdev = target_if_spectral_get_vdev(spectral); + if (!vdev) { + spectral_err("vdev is NULL"); + return QDF_STATUS_E_FAILURE; + } + ch_width = target_if_vdev_get_ch_width(vdev); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + agile_ch_width = target_if_spectral_find_agile_width(ch_width); + + if (agile_ch_width == CH_WIDTH_20MHZ) { + *center_freq = chan_freq; + } else { + uint16_t start_freq; + uint16_t end_freq; + const struct bonded_channel_freq *bonded_chan_ptr = NULL; + + wlan_reg_get_5g_bonded_channel_and_state_for_freq + (spectral->pdev_obj, chan_freq, agile_ch_width, + &bonded_chan_ptr); + if (!bonded_chan_ptr) { + spectral_err("Bonded channel is not found"); + return QDF_STATUS_E_FAILURE; + } + start_freq = bonded_chan_ptr->start_freq; + end_freq = bonded_chan_ptr->end_freq; + *center_freq = (start_freq + end_freq) >> 1; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_validate_center_freq() - Helper routine to + * validate user provided agile center frequency + * + * @spectral: Pointer to Spectral object + * @center_freq: User provided agile span center frequency + * @is_valid: Indicates whether agile span center frequency is valid + * + * Return: QDF_STATUS + */ +static QDF_STATUS +target_if_validate_center_freq(struct target_if_spectral *spectral, + uint16_t center_freq, + bool *is_valid) +{ + struct wlan_objmgr_vdev *vdev; + enum phy_ch_width ch_width; + enum phy_ch_width agile_ch_width; + struct wlan_objmgr_pdev *pdev; + QDF_STATUS status; + + if (!spectral) { + spectral_err("spectral target if object is null"); + return QDF_STATUS_E_FAILURE; + } + + if (!is_valid) { + spectral_err("is_valid argument is null"); + return QDF_STATUS_E_FAILURE; + } + + pdev = spectral->pdev_obj; + vdev = target_if_spectral_get_vdev(spectral); + if (!vdev) { + spectral_err("vdev is NULL"); + return QDF_STATUS_E_FAILURE; + } + ch_width = target_if_vdev_get_ch_width(vdev); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + agile_ch_width = target_if_spectral_find_agile_width(ch_width); + + if (agile_ch_width == CH_WIDTH_20MHZ) { + status = target_if_is_center_freq_of_any_chan + (pdev, center_freq, is_valid); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + } else { + uint16_t start_freq; + uint16_t end_freq; + const struct bonded_channel_freq *bonded_chan_ptr = NULL; + bool is_chan; + + status = target_if_is_center_freq_of_any_chan + (pdev, center_freq + FREQ_OFFSET_10MHZ, + &is_chan); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + + if (is_chan) { + uint32_t calulated_center_freq; + + wlan_reg_get_5g_bonded_channel_and_state_for_freq + (pdev, center_freq + FREQ_OFFSET_10MHZ, + agile_ch_width, + &bonded_chan_ptr); + if (!bonded_chan_ptr) { + spectral_err("Bonded channel is not found"); + return QDF_STATUS_E_FAILURE; + } + start_freq = bonded_chan_ptr->start_freq; + end_freq = bonded_chan_ptr->end_freq; + calulated_center_freq = (start_freq + end_freq) >> 1; + *is_valid = (center_freq == calulated_center_freq); + } else { + *is_valid = false; + } + } + + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_is_agile_span_overlap_with_operating_span() - Helper routine to + * check whether agile span overlaps with current operating band. + * + * @spectral: Pointer to Spectral object + * @ss_frequency: Agile span center frequency + * @is_overlapping: Indicates whether Agile span overlaps with operating span + * + * Helper routine to check whether agile span overlaps with current + * operating band. + * + * Return: QDF_STATUS + */ +static QDF_STATUS +target_if_is_agile_span_overlap_with_operating_span + (struct target_if_spectral *spectral, + uint32_t ss_frequency, + bool *is_overlapping) +{ + enum phy_ch_width ch_width; + enum phy_ch_width agile_ch_width; + const struct bonded_channel_freq *bonded_chan_ptr = NULL; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_pdev *pdev; + int16_t chan_freq; + uint32_t op_start_freq; + uint32_t op_end_freq; + uint32_t agile_start_freq; + uint32_t agile_end_freq; + uint32_t cfreq2; + + if (!spectral) { + spectral_err("Spectral object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + pdev = spectral->pdev_obj; + if (!pdev) { + spectral_err("pdev object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + if (!is_overlapping) { + spectral_err("Argument(is_overlapping) is NULL"); + return QDF_STATUS_E_FAILURE; + } + + vdev = target_if_spectral_get_vdev(spectral); + if (!vdev) { + spectral_err("vdev is NULL"); + return QDF_STATUS_E_FAILURE; + } + ch_width = target_if_vdev_get_ch_width(vdev); + chan_freq = target_if_vdev_get_chan_freq(vdev); + cfreq2 = target_if_vdev_get_chan_freq_seg2(vdev); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + if (cfreq2 < 0) + return QDF_STATUS_E_FAILURE; + + if (ch_width == CH_WIDTH_20MHZ) { + op_start_freq = chan_freq - FREQ_OFFSET_10MHZ; + op_end_freq = chan_freq + FREQ_OFFSET_10MHZ; + } else { + wlan_reg_get_5g_bonded_channel_and_state_for_freq + (pdev, chan_freq, ch_width, &bonded_chan_ptr); + if (!bonded_chan_ptr) { + spectral_err("Bonded channel is not found"); + return QDF_STATUS_E_FAILURE; + } + op_start_freq = bonded_chan_ptr->start_freq - FREQ_OFFSET_10MHZ; + op_end_freq = bonded_chan_ptr->end_freq - FREQ_OFFSET_10MHZ; + } + + agile_ch_width = target_if_spectral_find_agile_width(ch_width); + if (agile_ch_width == CH_WIDTH_INVALID) + return QDF_STATUS_E_FAILURE; + agile_start_freq = ss_frequency - + (wlan_reg_get_bw_value(agile_ch_width) >> 1); + agile_end_freq = ss_frequency + + (wlan_reg_get_bw_value(agile_ch_width) >> 1); + if (agile_end_freq <= op_start_freq || op_end_freq <= agile_start_freq) + *is_overlapping = false; + else + *is_overlapping = true; + + /* Use non zero cfreq2 to identify 80p80 */ + if (cfreq2) { + uint32_t sec80_start_feq; + uint32_t sec80_end_freq; + + sec80_start_feq = cfreq2 - 40; + sec80_end_freq = cfreq2 + 40; + + if ((agile_end_freq > sec80_start_feq) && + (sec80_end_freq > agile_start_freq)) + *is_overlapping = true; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_spectral_populate_chwidth() - Helper routine to + * populate channel width for different Spectral modes + * + * @spectral: Pointer to Spectral object + * + * Helper routine to populate channel width for different Spectral modes + * + * Return: QDF_STATUS + */ +static QDF_STATUS +target_if_spectral_populate_chwidth(struct target_if_spectral *spectral) { + struct wlan_objmgr_vdev *vdev; + enum phy_ch_width vdev_ch_with; + + vdev = target_if_spectral_get_vdev(spectral); + if (!vdev) { + spectral_err("vdev is null"); + return QDF_STATUS_E_FAILURE; + } + + vdev_ch_with = target_if_vdev_get_ch_width(vdev); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + if (vdev_ch_with == CH_WIDTH_INVALID) { + spectral_err("Invalid channel width %d", vdev_ch_with); + return QDF_STATUS_E_FAILURE; + } + spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] = vdev_ch_with; + spectral->ch_width[SPECTRAL_SCAN_MODE_AGILE] = + target_if_spectral_find_agile_width(vdev_ch_with); + + return QDF_STATUS_SUCCESS; +} + +/** + * _target_if_set_spectral_config() - Set spectral config + * @spectral: Pointer to spectral object + * @threshtype: config type + * @value: config value + * @smode: Spectral scan mode + * @err: Spectral error code + * + * API to set spectral configurations + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure + */ +static QDF_STATUS +_target_if_set_spectral_config(struct target_if_spectral *spectral, + const uint32_t threshtype, const uint32_t value, + const enum spectral_scan_mode smode, + enum spectral_cp_error_code *err) +{ + struct spectral_config params; + struct target_if_spectral_ops *p_sops; + struct spectral_config *sparams; + QDF_STATUS status; + bool is_overlapping; + uint16_t agile_cfreq; + bool is_valid_chan; + struct spectral_param_min_max *param_min_max; + + if (!err) { + spectral_err("Error code argument is null"); + QDF_ASSERT(0); + return QDF_STATUS_E_FAILURE; + } + *err = SPECTRAL_SCAN_ERR_INVALID; + + if (!spectral) { + spectral_err("spectral object is NULL"); + return QDF_STATUS_E_FAILURE; + } + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + param_min_max = &spectral->param_min_max; + + if (smode >= SPECTRAL_SCAN_MODE_MAX) { + spectral_err("Invalid Spectral mode %u", smode); + *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; + return QDF_STATUS_E_FAILURE; + } + + sparams = &spectral->params[smode]; + + if (!spectral->params_valid[smode]) { + target_if_spectral_info_read(spectral, + smode, + TARGET_IF_SPECTRAL_INFO_PARAMS, + &spectral->params[smode], + sizeof(spectral->params[smode])); + spectral->params_valid[smode] = true; + } + + switch (threshtype) { + case SPECTRAL_PARAM_FFT_PERIOD: + sparams->ss_fft_period = value; + break; + case SPECTRAL_PARAM_SCAN_PERIOD: + sparams->ss_period = value; + break; + case SPECTRAL_PARAM_SCAN_COUNT: + sparams->ss_count = value; + break; + case SPECTRAL_PARAM_SHORT_REPORT: + sparams->ss_short_report = (!!value) ? true : false; + break; + case SPECTRAL_PARAM_SPECT_PRI: + sparams->ss_spectral_pri = (!!value) ? true : false; + break; + case SPECTRAL_PARAM_FFT_SIZE: + status = target_if_spectral_populate_chwidth(spectral); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + if ((value < param_min_max->fft_size_min) || + (value > param_min_max->fft_size_max + [spectral->ch_width[smode]])) { + *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; + return QDF_STATUS_E_FAILURE; + } + sparams->ss_fft_size = value; + break; + case SPECTRAL_PARAM_GC_ENA: + sparams->ss_gc_ena = !!value; + break; + case SPECTRAL_PARAM_RESTART_ENA: + sparams->ss_restart_ena = !!value; + break; + case SPECTRAL_PARAM_NOISE_FLOOR_REF: + sparams->ss_noise_floor_ref = value; + break; + case SPECTRAL_PARAM_INIT_DELAY: + sparams->ss_init_delay = value; + break; + case SPECTRAL_PARAM_NB_TONE_THR: + sparams->ss_nb_tone_thr = value; + break; + case SPECTRAL_PARAM_STR_BIN_THR: + sparams->ss_str_bin_thr = value; + break; + case SPECTRAL_PARAM_WB_RPT_MODE: + sparams->ss_wb_rpt_mode = !!value; + break; + case SPECTRAL_PARAM_RSSI_RPT_MODE: + sparams->ss_rssi_rpt_mode = !!value; + break; + case SPECTRAL_PARAM_RSSI_THR: + sparams->ss_rssi_thr = value; + break; + case SPECTRAL_PARAM_PWR_FORMAT: + sparams->ss_pwr_format = !!value; + break; + case SPECTRAL_PARAM_RPT_MODE: + if ((value < SPECTRAL_PARAM_RPT_MODE_MIN) || + (value > SPECTRAL_PARAM_RPT_MODE_MAX)) { + *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; + return QDF_STATUS_E_FAILURE; + } + sparams->ss_rpt_mode = value; + break; + case SPECTRAL_PARAM_BIN_SCALE: + sparams->ss_bin_scale = value; + break; + case SPECTRAL_PARAM_DBM_ADJ: + sparams->ss_dbm_adj = !!value; + break; + case SPECTRAL_PARAM_CHN_MASK: + sparams->ss_chn_mask = value; + break; + case SPECTRAL_PARAM_FREQUENCY: + status = target_if_is_center_freq_of_any_chan + (spectral->pdev_obj, value, &is_valid_chan); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + + if (is_valid_chan) { + status = target_if_calculate_center_freq(spectral, + value, + &agile_cfreq); + if (QDF_IS_STATUS_ERROR(status)) { + *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; + return QDF_STATUS_E_FAILURE; + } + } else { + bool is_valid_agile_cfreq; + + status = target_if_validate_center_freq + (spectral, value, &is_valid_agile_cfreq); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + + if (!is_valid_agile_cfreq) { + *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; + spectral_err("Invalid agile center frequency"); + return QDF_STATUS_E_FAILURE; + } + + agile_cfreq = value; + } + + status = target_if_is_agile_span_overlap_with_operating_span + (spectral, agile_cfreq, &is_overlapping); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + + if (is_overlapping) { + spectral_err("Agile span overlapping with current BW"); + *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; + return QDF_STATUS_E_FAILURE; + } + sparams->ss_frequency = agile_cfreq; + break; + } + + p_sops->configure_spectral(spectral, sparams, smode); + /* only to validate the writes */ + p_sops->get_spectral_config(spectral, ¶ms, smode); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev, + const uint32_t threshtype, const uint32_t value, + const enum spectral_scan_mode smode, + enum spectral_cp_error_code *err) +{ + enum spectral_scan_mode mode = SPECTRAL_SCAN_MODE_NORMAL; + struct target_if_spectral *spectral; + QDF_STATUS status; + + if (!err) { + spectral_err("Error code argument is null"); + QDF_ASSERT(0); + return QDF_STATUS_E_FAILURE; + } + *err = SPECTRAL_SCAN_ERR_INVALID; + + if (!pdev) { + spectral_err("pdev object is NULL"); + return QDF_STATUS_E_FAILURE; + } + spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("spectral object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + if (smode >= SPECTRAL_SCAN_MODE_MAX) { + spectral_err("Invalid Spectral mode %u", smode); + *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; + return QDF_STATUS_E_FAILURE; + } + + if (!spectral->properties[smode][threshtype].supported) { + spectral_err("Spectral parameter(%u) unsupported for mode %u", + threshtype, smode); + *err = SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED; + return QDF_STATUS_E_FAILURE; + } + + if (spectral->properties[smode][threshtype].common_all_modes) { + spectral_warn("Setting Spectral parameter %u for all modes", + threshtype); + for (; mode < SPECTRAL_SCAN_MODE_MAX; mode++) { + status = _target_if_set_spectral_config + (spectral, threshtype, value, + mode, err); + if (QDF_IS_STATUS_ERROR(status)) + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; + } + + return _target_if_set_spectral_config(spectral, threshtype, + value, smode, err); +} + +/** + * target_if_get_fft_bin_count() - Get fft bin count for a given fft length + * @fft_len: FFT length + * @pdev: Pointer to pdev object + * + * API to get fft bin count for a given fft length + * + * Return: FFt bin count + */ +static int +target_if_get_fft_bin_count(int fft_len) +{ + int bin_count = 0; + + switch (fft_len) { + case 5: + bin_count = 16; + break; + case 6: + bin_count = 32; + break; + case 7: + bin_count = 64; + break; case 8: bin_count = 128; break; @@ -2343,8 +3093,19 @@ target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev, struct target_if_spectral *spectral = NULL; spectral = get_target_if_spectral_handle_from_pdev(pdev); + + if (!spectral) { + spectral_err("SPECTRAL : Module doesn't exist"); + return QDF_STATUS_E_FAILURE; + } + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + if (!p_sops) { + spectral_err("p_sops is null"); + return QDF_STATUS_E_FAILURE; + } + if (smode >= SPECTRAL_SCAN_MODE_MAX) { spectral_err("Invalid Spectral mode %u", smode); return QDF_STATUS_E_FAILURE; @@ -2378,7 +3139,7 @@ target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, int extension_channel = 0; int current_channel = 0; struct target_if_spectral_ops *p_sops = NULL; - struct wlan_objmgr_vdev *vdev = NULL; + QDF_STATUS status; if (!spectral) { spectral_err("Spectral LMAC object is NULL"); @@ -2404,15 +3165,11 @@ target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, extension_channel = p_sops->get_extension_channel(spectral); current_channel = p_sops->get_current_channel(spectral); - vdev = target_if_spectral_get_vdev(spectral); - if (!vdev) - return 1; - - spectral->ch_width = target_if_vdev_get_ch_width(vdev); - wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); - - if (spectral->ch_width == CH_WIDTH_INVALID) + status = target_if_spectral_populate_chwidth(spectral); + if (QDF_IS_STATUS_ERROR(status)) { + spectral_err("Failed to get channel widths"); return 1; + } if (spectral->capability.advncd_spectral_cap) { spectral->lb_edge_extrabins = 0; @@ -2428,7 +3185,7 @@ target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, spectral->rb_edge_extrabins = 4; } - if (spectral->ch_width == CH_WIDTH_20MHZ) { + if (spectral->ch_width[smode] == CH_WIDTH_20MHZ) { spectral->sc_spectral_20_40_mode = 0; spectral->spectral_numbins = @@ -2448,7 +3205,7 @@ target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, current_channel; spectral->classifier_params.upper_chan_in_mhz = 0; - } else if (spectral->ch_width == CH_WIDTH_40MHZ) { + } else if (spectral->ch_width[smode] == CH_WIDTH_40MHZ) { /* TODO : Remove this variable */ spectral->sc_spectral_20_40_mode = 1; spectral->spectral_numbins = @@ -2477,7 +3234,7 @@ target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, extension_channel; } - } else if (spectral->ch_width == CH_WIDTH_80MHZ) { + } else if (spectral->ch_width[smode] == CH_WIDTH_80MHZ) { /* Set the FFT Size */ /* TODO : Remove this variable */ spectral->sc_spectral_20_40_mode = 0; @@ -2515,7 +3272,7 @@ target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, extension_channel; } - } else if (spectral->ch_width == CH_WIDTH_160MHZ) { + } else if (spectral->ch_width[smode] == CH_WIDTH_160MHZ) { /* Set the FFT Size */ /* The below applies to both 160 and 80+80 cases */ @@ -2652,9 +3409,8 @@ target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, if (!p_sops->is_spectral_active(spectral, smode)) { p_sops->configure_spectral(spectral, spectral_params, smode); p_sops->start_spectral_scan(spectral, smode, err); - spectral->timestamp_war_offset = 0; - spectral->last_fft_timestamp = 0; - } else { + spectral->timestamp_war.timestamp_war_offset[smode] = 0; + spectral->timestamp_war.last_fft_timestamp[smode] = 0; } /* get current spectral configuration */ @@ -2665,13 +3421,284 @@ target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, return 0; } +/** + * target_if_is_aspectral_prohibited_by_adfs() - Is Agile Spectral prohibited by + * Agile DFS + * @psoc: Pointer to psoc + * @object: Pointer to pdev + * @arg: Pointer to flag which indicates whether Agile Spectral is prohibited + * + * This API checks whether Agile DFS is running on any of the pdevs. If so, it + * indicates that Agile Spectral scan is prohibited by Agile DFS. + * + * Return: void + */ +static void +target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc *psoc, + void *object, void *arg) +{ + bool *is_aspectral_prohibited = arg; + struct wlan_objmgr_pdev *cur_pdev = object; + bool is_agile_dfs_enabled_cur_pdev = false; + QDF_STATUS status; + + qdf_assert_always(is_aspectral_prohibited); + if (*is_aspectral_prohibited) + return; + + qdf_assert_always(psoc); + qdf_assert_always(cur_pdev); + + status = ucfg_dfs_get_agile_precac_enable + (cur_pdev, + &is_agile_dfs_enabled_cur_pdev); + if (QDF_IS_STATUS_ERROR(status)) { + spectral_err("Get agile precac failed, prohibiting aSpectral"); + *is_aspectral_prohibited = true; + return; + } + + if (is_agile_dfs_enabled_cur_pdev) { + spectral_err("aDFS is in progress on one of the pdevs"); + *is_aspectral_prohibited = true; + } +} + +/** + * target_if_get_curr_band() - Get current operating band of pdev + * + * @spectral: pointer to spectral object + * + * API to get current operating band of a given pdev. + * + * Return: if success enum reg_wifi_band, REG_BAND_UNKNOWN in case of failure + */ +static enum reg_wifi_band +target_if_get_curr_band(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_vdev *vdev; + int16_t chan_freq; + enum reg_wifi_band cur_band; + + if (!pdev) { + spectral_err("pdev is NULL"); + return REG_BAND_UNKNOWN; + } + + vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID); + if (!vdev) { + spectral_debug("vdev is NULL"); + return REG_BAND_UNKNOWN; + } + chan_freq = target_if_vdev_get_chan_freq(vdev); + cur_band = wlan_reg_freq_to_band(chan_freq); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + + return cur_band; +} + +/** + * target_if_is_agile_scan_active_in_5g() - Is Agile Spectral scan active on + * any of the 5G pdevs + * @psoc: Pointer to psoc + * @object: Pointer to pdev + * @arg: Pointer to flag which indicates whether Agile Spectral scan is in + * progress in any 5G pdevs + * + * Return: void + */ +static void +target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc *psoc, + void *object, void *arg) +{ + enum reg_wifi_band band; + bool *is_agile_scan_inprog_5g_pdev = arg; + struct target_if_spectral *spectral; + struct wlan_objmgr_pdev *cur_pdev = object; + struct target_if_spectral_ops *p_sops; + + if (*is_agile_scan_inprog_5g_pdev) + return; + + spectral = get_target_if_spectral_handle_from_pdev(cur_pdev); + if (!spectral) { + spectral_err("target if spectral handle is NULL"); + return; + } + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + + band = target_if_get_curr_band(cur_pdev); + if (band == REG_BAND_UNKNOWN) { + spectral_debug("Failed to get current band"); + return; + } + + if (band == REG_BAND_5G && + p_sops->is_spectral_active(spectral, SPECTRAL_SCAN_MODE_AGILE)) + *is_agile_scan_inprog_5g_pdev = true; +} + +/** + * target_if_is_agile_supported_cur_chmask() - Is Agile Spectral scan supported + * for current vdev rx chainmask. + * + * @spectral: Pointer to Spectral object + * @is_supported: Pointer to is_supported + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure + */ +static QDF_STATUS +target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral, + bool *is_supported) +{ + struct wlan_objmgr_vdev *vdev; + uint8_t vdev_rxchainmask; + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + struct target_psoc_info *tgt_psoc_info; + struct wlan_psoc_host_service_ext_param *ext_svc_param; + struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL; + struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL; + struct wlan_psoc_host_chainmask_table *table; + int j; + uint32_t table_id; + enum phy_ch_width ch_width; + uint8_t pdev_id; + + if (!spectral) { + spectral_err("spectral target if object is null"); + return QDF_STATUS_E_FAILURE; + } + + if (!is_supported) { + spectral_err("is supported argument is null"); + return QDF_STATUS_E_FAILURE; + } + + if (spectral->spectral_gen <= SPECTRAL_GEN2) { + spectral_err("HW Agile mode is not supported up to gen 2"); + return QDF_STATUS_E_FAILURE; + } + + pdev = spectral->pdev_obj; + if (!pdev) { + spectral_err("pdev is null"); + return QDF_STATUS_E_FAILURE; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + spectral_err("psoc is null"); + return QDF_STATUS_E_FAILURE; + } + + vdev = target_if_spectral_get_vdev(spectral); + if (!vdev) { + spectral_err("First vdev is NULL"); + return QDF_STATUS_E_FAILURE; + } + + vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); + if (!vdev_rxchainmask) { + spectral_err("vdev rx chainmask is zero"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + return QDF_STATUS_E_FAILURE; + } + + ch_width = target_if_vdev_get_ch_width(vdev); + if (ch_width == CH_WIDTH_INVALID) { + spectral_err("Invalid channel width"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + return QDF_STATUS_E_FAILURE; + } + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + + tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); + if (!tgt_psoc_info) { + spectral_err("target_psoc_info is null"); + return QDF_STATUS_E_FAILURE; + } + + ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); + if (!ext_svc_param) { + spectral_err("Extended service ready param null"); + return QDF_STATUS_E_FAILURE; + } + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); + if (!mac_phy_cap_arr) { + spectral_err("mac phy cap array is null"); + return QDF_STATUS_E_FAILURE; + } + + mac_phy_cap = &mac_phy_cap_arr[pdev_id]; + if (!mac_phy_cap) { + spectral_err("mac phy cap is null"); + return QDF_STATUS_E_FAILURE; + } + + table_id = mac_phy_cap->chainmask_table_id; + table = &ext_svc_param->chainmask_table[table_id]; + if (!table) { + spectral_err("chainmask table not found"); + return QDF_STATUS_E_FAILURE; + } + + for (j = 0; j < table->num_valid_chainmasks; j++) { + if (table->cap_list[j].chainmask == vdev_rxchainmask) { + if (ch_width <= CH_WIDTH_80MHZ) + *is_supported = + table->cap_list[j].supports_aSpectral; + else + *is_supported = + table->cap_list[j].supports_aSpectral_160; + break; + } + } + + if (j == table->num_valid_chainmasks) { + spectral_err("vdev rx chainmask %u not found in table id = %u", + vdev_rxchainmask, table_id); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, const enum spectral_scan_mode smode, enum spectral_cp_error_code *err) { - struct target_if_spectral_ops *p_sops = NULL; - struct target_if_spectral *spectral = NULL; + struct target_if_spectral_ops *p_sops; + struct target_if_spectral *spectral; + struct wlan_objmgr_psoc *psoc; + enum reg_wifi_band band; + + if (!err) { + spectral_err("Error code argument is null"); + QDF_ASSERT(0); + return QDF_STATUS_E_FAILURE; + } + *err = SPECTRAL_SCAN_ERR_INVALID; + + if (!pdev) { + spectral_err("pdev object is NUll"); + return QDF_STATUS_E_FAILURE; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + spectral_err("psoc is null"); + return QDF_STATUS_E_FAILURE; + } + + if (smode >= SPECTRAL_SCAN_MODE_MAX) { + *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; + spectral_err("Invalid Spectral mode %u", smode); + return QDF_STATUS_E_FAILURE; + } spectral = get_target_if_spectral_handle_from_pdev(pdev); if (!spectral) { @@ -2679,12 +3706,97 @@ target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_E_FAILURE; } - if (smode >= SPECTRAL_SCAN_MODE_MAX) { - spectral_err("Invalid Spectral mode %u", smode); - return QDF_STATUS_E_FAILURE; + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + if (!p_sops) { + spectral_err("p_sops is null"); + return QDF_STATUS_E_FAILURE; + } + + if (smode == SPECTRAL_SCAN_MODE_AGILE) { + QDF_STATUS status; + bool is_supported = false; + + status = target_if_is_agile_supported_cur_chmask(spectral, + &is_supported); + if (QDF_IS_STATUS_ERROR(status)) { + *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; + return QDF_STATUS_E_FAILURE; + } + + if (!is_supported) { + spectral_err("aSpectral unsupported for cur chainmask"); + *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; + return QDF_STATUS_E_FAILURE; + } + } + + band = target_if_get_curr_band(spectral->pdev_obj); + if (band == REG_BAND_UNKNOWN) { + spectral_err("Failed to get current band"); + return QDF_STATUS_E_FAILURE; + } + if ((band == REG_BAND_5G) && (smode == SPECTRAL_SCAN_MODE_AGILE)) { + struct target_psoc_info *tgt_hdl; + enum wmi_host_hw_mode_config_type mode; + bool is_agile_scan_inprog_5g_pdev; + + if (p_sops->is_spectral_active(spectral, + SPECTRAL_SCAN_MODE_AGILE)) { + spectral_err("Agile Scan in progress in current pdev"); + return QDF_STATUS_E_FAILURE; + } + + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); + if (!tgt_hdl) { + target_if_err("target_psoc_info is null"); + return QDF_STATUS_E_FAILURE; + } + + mode = target_psoc_get_preferred_hw_mode(tgt_hdl); + switch (mode) { + case WMI_HOST_HW_MODE_SBS_PASSIVE: + case WMI_HOST_HW_MODE_SBS: + case WMI_HOST_HW_MODE_DBS_SBS: + case WMI_HOST_HW_MODE_DBS_OR_SBS: + is_agile_scan_inprog_5g_pdev = false; + wlan_objmgr_iterate_obj_list + (psoc, WLAN_PDEV_OP, + target_if_is_agile_scan_active_in_5g, + &is_agile_scan_inprog_5g_pdev, 0, + WLAN_SPECTRAL_ID); + break; + default: + is_agile_scan_inprog_5g_pdev = false; + break; + } + + if (is_agile_scan_inprog_5g_pdev) { + spectral_err("Agile Scan in progress in one of the SBS 5G pdev"); + *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; + return QDF_STATUS_E_FAILURE; + } } - p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + if (smode == SPECTRAL_SCAN_MODE_AGILE) { + bool is_aspectral_prohibited = false; + QDF_STATUS status; + + status = wlan_objmgr_iterate_obj_list + (psoc, WLAN_PDEV_OP, + target_if_is_aspectral_prohibited_by_adfs, + &is_aspectral_prohibited, 0, + WLAN_SPECTRAL_ID); + if (QDF_IS_STATUS_ERROR(status)) { + spectral_err("Failed to iterate over pdevs"); + *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; + return QDF_STATUS_E_FAILURE; + } + + if (is_aspectral_prohibited) { + *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; + return QDF_STATUS_E_FAILURE; + } + } if (!spectral->params_valid[smode]) { target_if_spectral_info_read(spectral, @@ -2696,6 +3808,33 @@ target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, } qdf_spin_lock(&spectral->spectral_lock); + if (smode == SPECTRAL_SCAN_MODE_AGILE && + !spectral->params[smode].ss_frequency) { + *err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED; + qdf_spin_unlock(&spectral->spectral_lock); + return QDF_STATUS_E_FAILURE; + } + + if (smode == SPECTRAL_SCAN_MODE_AGILE) { + QDF_STATUS status; + bool is_overlapping; + + status = target_if_is_agile_span_overlap_with_operating_span + (spectral, + spectral->params[smode].ss_frequency, + &is_overlapping); + if (QDF_IS_STATUS_ERROR(status)) { + qdf_spin_unlock(&spectral->spectral_lock); + return QDF_STATUS_E_FAILURE; + } + + if (is_overlapping) { + *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; + qdf_spin_unlock(&spectral->spectral_lock); + return QDF_STATUS_E_FAILURE; + } + } + target_if_spectral_scan_enable_params(spectral, &spectral->params[smode], smode, err); @@ -2706,23 +3845,36 @@ target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, QDF_STATUS target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev, - const enum spectral_scan_mode smode) + const enum spectral_scan_mode smode, + enum spectral_cp_error_code *err) { - struct target_if_spectral_ops *p_sops = NULL; - struct target_if_spectral *spectral = NULL; + struct target_if_spectral_ops *p_sops; + struct target_if_spectral *spectral; - spectral = get_target_if_spectral_handle_from_pdev(pdev); - if (!spectral) { - spectral_err("Spectral LMAC object is NUll "); + if (!err) { + spectral_err("Error code argument is null"); + QDF_ASSERT(0); return QDF_STATUS_E_FAILURE; } - p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + *err = SPECTRAL_SCAN_ERR_INVALID; if (smode >= SPECTRAL_SCAN_MODE_MAX) { + *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; spectral_err("Invalid Spectral mode %u", smode); return QDF_STATUS_E_FAILURE; } + if (!pdev) { + spectral_err("pdev object is NUll "); + return QDF_STATUS_E_FAILURE; + } + spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("Spectral LMAC object is NUll "); + return QDF_STATUS_E_FAILURE; + } + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + qdf_spin_lock(&spectral->spectral_lock); p_sops->stop_spectral_scan(spectral, smode); if (spectral->classify_scan) { @@ -2759,8 +3911,19 @@ target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev, struct target_if_spectral_ops *p_sops = NULL; spectral = get_target_if_spectral_handle_from_pdev(pdev); + + if (!spectral) { + spectral_err("SPECTRAL : Module doesn't exist"); + return QDF_STATUS_E_FAILURE; + } + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + if (!p_sops) { + spectral_err("p_sops is null"); + return QDF_STATUS_E_FAILURE; + } + if (smode >= SPECTRAL_SCAN_MODE_MAX) { spectral_err("Invalid Spectral mode %u", smode); return QDF_STATUS_E_FAILURE; @@ -2786,8 +3949,19 @@ target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev, struct target_if_spectral_ops *p_sops = NULL; spectral = get_target_if_spectral_handle_from_pdev(pdev); + + if (!spectral) { + spectral_err("SPECTRAL : Module doesn't exist"); + return QDF_STATUS_E_FAILURE; + } + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + if (!p_sops) { + spectral_err("p_sops is null"); + return QDF_STATUS_E_FAILURE; + } + if (smode >= SPECTRAL_SCAN_MODE_MAX) { spectral_err("Invalid Spectral mode %u", smode); return QDF_STATUS_E_FAILURE; @@ -2796,6 +3970,251 @@ target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev, return p_sops->is_spectral_enabled(spectral, smode); } +#ifdef DIRECT_BUF_RX_DEBUG +/** + * target_if_spectral_do_dbr_ring_debug() - Start/Stop Spectral DMA ring debug + * @pdev: Pointer to pdev object + * @enable: Enable/Disable Spectral DMA ring debug + * + * Start/stop Spectral DMA ring debug based on @enable. + * Also save the state for future use. + * + * Return: QDF_STATUS of operation + */ +static QDF_STATUS +target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev, bool enable) +{ + struct target_if_spectral *spectral; + struct wlan_lmac_if_tx_ops *tx_ops; + struct wlan_objmgr_psoc *psoc; + + if (!pdev) + return QDF_STATUS_E_FAILURE; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + spectral_err("psoc is null"); + return QDF_STATUS_E_INVAL; + } + tx_ops = &psoc->soc_cb.tx_ops; + + spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("Spectal LMAC object is NULL"); + return QDF_STATUS_E_INVAL; + } + + /* Save the state */ + spectral->dbr_ring_debug = enable; + + if (enable) + return tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug( + pdev, 0, SPECTRAL_DBR_RING_DEBUG_SIZE); + else + return tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug( + pdev, 0); + + return QDF_STATUS_SUCCESS; +} + +/** + * target_if_spectral_do_dbr_buff_debug() - Start/Stop Spectral DMA buffer debug + * @pdev: Pointer to pdev object + * @enable: Enable/Disable Spectral DMA buffer debug + * + * Start/stop Spectral DMA buffer debug based on @enable. + * Also save the state for future use. + * + * Return: QDF_STATUS of operation + */ +static QDF_STATUS +target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev, bool enable) +{ + struct target_if_spectral *spectral; + struct wlan_lmac_if_tx_ops *tx_ops; + struct wlan_objmgr_psoc *psoc; + + if (!pdev) + return QDF_STATUS_E_FAILURE; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + spectral_err("psoc is null"); + return QDF_STATUS_E_INVAL; + } + tx_ops = &psoc->soc_cb.tx_ops; + + spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("Spectal LMAC object is NULL"); + return QDF_STATUS_E_INVAL; + } + + /* Save the state */ + spectral->dbr_buff_debug = enable; + + if (enable) + return tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning( + pdev, 0, MEM_POISON_SIGNATURE); + else + return tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning( + pdev, 0); +} + +/** + * target_if_spectral_check_and_do_dbr_buff_debug() - Start/Stop Spectral buffer + * debug based on the previous state + * @pdev: Pointer to pdev object + * + * Return: QDF_STATUS of operation + */ +static QDF_STATUS +target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev) +{ + struct target_if_spectral *spectral; + + if (!pdev) { + spectral_err("pdev is NULL!"); + return QDF_STATUS_E_FAILURE; + } + + spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("Spectal LMAC object is NULL"); + return QDF_STATUS_E_INVAL; + } + + if (spectral->dbr_buff_debug) + return target_if_spectral_do_dbr_buff_debug(pdev, true); + else + return target_if_spectral_do_dbr_buff_debug(pdev, false); +} + +/** + * target_if_spectral_check_and_do_dbr_ring_debug() - Start/Stop Spectral ring + * debug based on the previous state + * @pdev: Pointer to pdev object + * + * Return: QDF_STATUS of operation + */ +static QDF_STATUS +target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev) +{ + struct target_if_spectral *spectral; + + if (!pdev) { + spectral_err("pdev is NULL!"); + return QDF_STATUS_E_FAILURE; + } + + spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("Spectal LMAC object is NULL"); + return QDF_STATUS_E_INVAL; + } + + if (spectral->dbr_ring_debug) + return target_if_spectral_do_dbr_ring_debug(pdev, true); + else + return target_if_spectral_do_dbr_ring_debug(pdev, false); +} + +/** + * target_if_spectral_set_dma_debug() - Set DMA debug for Spectral + * @pdev: Pointer to pdev object + * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug + * @debug_value: Value to be set for @dma_debug_type + * + * Set DMA debug for Spectral and start/stop Spectral DMA debug function + * based on @debug_value + * + * Return: QDF_STATUS of operation + */ +static QDF_STATUS +target_if_spectral_set_dma_debug( + struct wlan_objmgr_pdev *pdev, + enum spectral_dma_debug dma_debug_type, + bool debug_value) +{ + struct target_if_spectral_ops *p_sops; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_tx_ops *tx_ops; + struct target_if_spectral *spectral; + + if (!pdev) + return QDF_STATUS_E_FAILURE; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + spectral_err("psoc is null"); + return QDF_STATUS_E_INVAL; + } + tx_ops = &psoc->soc_cb.tx_ops; + + if (!tx_ops->target_tx_ops.tgt_get_tgt_type) { + spectral_err("Unable to fetch target type"); + return QDF_STATUS_E_FAILURE; + } + + spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("Spectal LMAC object is NULL"); + return QDF_STATUS_E_INVAL; + } + + if (spectral->direct_dma_support) { + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + if (p_sops->is_spectral_active(spectral, + SPECTRAL_SCAN_MODE_NORMAL) || + p_sops->is_spectral_active(spectral, + SPECTRAL_SCAN_MODE_AGILE)) { + spectral_err("Altering DBR debug config isn't allowed during an ongoing scan"); + return QDF_STATUS_E_FAILURE; + } + + switch (dma_debug_type) { + case SPECTRAL_DMA_RING_DEBUG: + target_if_spectral_do_dbr_ring_debug(pdev, debug_value); + break; + + case SPECTRAL_DMA_BUFFER_DEBUG: + target_if_spectral_do_dbr_buff_debug(pdev, debug_value); + break; + + default: + spectral_err("Unsupported DMA debug type : %d", + dma_debug_type); + return QDF_STATUS_E_FAILURE; + } + } + return QDF_STATUS_SUCCESS; +} +#endif /* DIRECT_BUF_RX_DEBUG */ + +/** + * target_if_spectral_direct_dma_support() - Get Direct-DMA support + * @pdev: Pointer to pdev object + * + * Return: Whether Direct-DMA is supported on this radio + */ +static bool +target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev *pdev) +{ + struct target_if_spectral *spectral; + + if (!pdev) { + spectral_err("pdev is NULL!"); + return false; + } + + spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("Spectral LMAC object is NULL"); + return false; + } + return spectral->direct_dma_support; +} + /** * target_if_set_debug_level() - Set debug level for Spectral * @pdev: Pointer to pdev object @@ -2843,6 +4262,11 @@ target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev, struct target_if_spectral *spectral = NULL; spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("SPECTRAL : Module doesn't exist"); + return QDF_STATUS_E_FAILURE; + } + qdf_mem_copy(scaps, &spectral->capability, sizeof(struct spectral_caps)); @@ -2865,6 +4289,11 @@ target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev, struct target_if_spectral *spectral = NULL; spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("SPECTRAL : Module doesn't exist"); + return QDF_STATUS_E_FAILURE; + } + qdf_mem_copy(stats, &spectral->diag_stats, sizeof(struct spectral_diag_stats)); @@ -2884,13 +4313,14 @@ void target_if_register_wmi_spectral_cmd_ops(struct wlan_objmgr_pdev *pdev, struct wmi_spectral_cmd_ops *cmd_ops) { - struct target_if_spectral *spectral = NULL; + struct target_if_spectral *spectral = + get_target_if_spectral_handle_from_pdev(pdev); - spectral = get_target_if_spectral_handle_from_pdev(pdev); - spectral->param_wmi_cmd_ops.wmi_spectral_configure_cmd_send = - cmd_ops->wmi_spectral_configure_cmd_send; - spectral->param_wmi_cmd_ops.wmi_spectral_enable_cmd_send = - cmd_ops->wmi_spectral_enable_cmd_send; + if (!spectral) { + spectral_err("Spectral LMAC object is null"); + return; + } + spectral->param_wmi_cmd_ops = *cmd_ops; } /** @@ -2908,6 +4338,12 @@ target_if_register_netlink_cb( struct target_if_spectral *spectral = NULL; spectral = get_target_if_spectral_handle_from_pdev(pdev); + + if (!spectral) { + spectral_err("SPECTRAL : Module doesn't exist"); + return; + } + qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb)); if (spectral->use_nl_bcast) @@ -2929,6 +4365,12 @@ target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev) struct target_if_spectral *spectral = NULL; spectral = get_target_if_spectral_handle_from_pdev(pdev); + + if (!spectral) { + spectral_err("SPECTRAL : Module doesn't exist"); + return false; + } + return spectral->use_nl_bcast; } @@ -2960,11 +4402,42 @@ target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev, struct target_if_spectral_ops *p_sops = NULL; spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("SPECTRAL : Module doesn't exist"); + return -EPERM; + } + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + if (!p_sops) { + spectral_err("p_sops is null"); + return -EPERM; + } + return p_sops->process_spectral_report(pdev, payload); } +#ifdef DIRECT_BUF_RX_DEBUG +static inline void +target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + if (!tx_ops) + return; + + tx_ops->sptrl_tx_ops.sptrlto_set_dma_debug = + target_if_spectral_set_dma_debug; + tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_ring_debug = + target_if_spectral_check_and_do_dbr_ring_debug; + tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_buff_debug = + target_if_spectral_check_and_do_dbr_buff_debug; +} +#else +static inline void +target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ +} +#endif + void target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) { @@ -3001,7 +4474,10 @@ target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb = target_if_deregister_netlink_cb; tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report = - target_if_process_spectral_report; + target_if_process_spectral_report; + tx_ops->sptrl_tx_ops.sptrlto_direct_dma_support = + target_if_spectral_direct_dma_support; + target_if_sptrl_debug_register_tx_ops(tx_ops); } qdf_export_symbol(target_if_sptrl_register_tx_ops); @@ -3014,6 +4490,18 @@ target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev, struct target_if_spectral *spectral = NULL; spectral = get_target_if_spectral_handle_from_pdev(pdev); + + if (!spectral) { + spectral_err("SPECTRAL : Module doesn't exist"); + return; + } + + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + if (!p_sops) { + spectral_err("p_sops is null"); + return; + } + msg = (struct spectral_samp_msg *)spectral->nl_cb.get_sbuff( spectral->pdev_obj, SPECTRAL_MSG_INTERFERENCE_NOTIFICATION, @@ -3024,7 +4512,6 @@ target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev, SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI; msg->dcs_enabled = dcs_enabled; msg->signature = SPECTRAL_SIGNATURE; - p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); p_sops->get_mac_address(spectral, msg->macaddr); if (spectral->send_phy_data (pdev, diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.h b/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.h index 9ec90a10f89182ff42ed3a180492ef8e747f3ac5..7d651c883f78fcb3b2faf2934a0e5dca397294fd 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011,2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011,2017-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -41,6 +41,7 @@ #include +#define FREQ_OFFSET_10MHZ 10 #ifndef SPECTRAL_USE_NL_BCAST #define SPECTRAL_USE_NL_BCAST (0) #endif @@ -80,12 +81,16 @@ #define OFFSET_CH_WIDTH_160 50 /* Min and max for relevant Spectral params */ -#define SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2 (1) -#define SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2 (9) -#define SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3 (5) -#define SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3 (9) -#define SPECTRAL_PARAM_RPT_MODE_MIN (0) -#define SPECTRAL_PARAM_RPT_MODE_MAX (3) +#define SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2 (1) +#define SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2 (9) +#define SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3 (5) +#define SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT (9) +#define SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000 (10) +#define SPECTRAL_PARAM_RPT_MODE_MIN (0) +#define SPECTRAL_PARAM_RPT_MODE_MAX (3) + +/* DBR ring debug size for Spectral */ +#define SPECTRAL_DBR_RING_DEBUG_SIZE 512 #ifdef BIG_ENDIAN_HOST #define SPECTRAL_MESSAGE_COPY_CHAR_ARRAY(destp, srcp, len) do { \ @@ -109,6 +114,8 @@ /* Mask for time stamp from descriptor */ #define SPECTRAL_TSMASK 0xFFFFFFFF #define SPECTRAL_SIGNATURE 0xdeadbeef +/* Signature to write onto spectral buffer and then later validate */ +#define MEM_POISON_SIGNATURE (htobe32(0xdeadbeef)) /* START of spectral GEN II HW specific details */ #define SPECTRAL_PHYERR_SIGNATURE_GEN2 0xbb @@ -238,12 +245,28 @@ struct spectral_phyerr_fft_gen2 { (((value) >= (1 << ((width) - 1))) ? \ (value - (1 << (width))) : (value)) -#define SSCAN_REPORT_DETECTOR_ID_POS_GEN3 (29) -#define SSCAN_REPORT_DETECTOR_ID_SIZE_GEN3 (2) -#define SPECTRAL_PHYERR_SIGNATURE_GEN3 (0xFA) -#define TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3 (0x02) -#define TLV_TAG_SEARCH_FFT_REPORT_GEN3 (0x03) -#define SPECTRAL_PHYERR_TLVSIZE_GEN3 (4) +#define SSCAN_SUMMARY_REPORT_HDR_A_DETECTOR_ID_POS_GEN3 (29) +#define SSCAN_SUMMARY_REPORT_HDR_A_DETECTOR_ID_SIZE_GEN3 (2) +#define SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_POS_GEN3 (0) +#define SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_SIZE_GEN3 (8) +#define SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_POS_GEN3 (18) +#define SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_SIZE_GEN3 (10) +#define SSCAN_SUMMARY_REPORT_HDR_A_PRI80_POS_GEN3 (31) +#define SSCAN_SUMMARY_REPORT_HDR_A_PRI80_SIZE_GEN3 (1) +#define SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_POS_GEN3_V1 (30) +#define SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_SIZE_GEN3_V1 (1) +#define SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_POS_GEN3_V2 (16) +#define SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_SIZE_GEN3_V2 (1) + +#define SPECTRAL_PHYERR_SIGNATURE_GEN3 (0xFA) +#define TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3 (0x02) +#define TLV_TAG_SEARCH_FFT_REPORT_GEN3 (0x03) +#define SPECTRAL_PHYERR_TLVSIZE_GEN3 (4) + +#define FFT_REPORT_HEADER_LENGTH_GEN3_V2 (24) +#define FFT_REPORT_HEADER_LENGTH_GEN3_V1 (16) +#define NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V1 (0) +#define NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V2 (16) #define PHYERR_HDR_SIG_POS \ (offsetof(struct spectral_phyerr_fft_report_gen3, fft_hdr_sig)) @@ -337,15 +360,21 @@ struct spectral_phyerr_fft_report_gen3 { * @sscan_gainchange: This bit is set to 1 if a gainchange occurred during * the spectral scan FFT. Software may choose to * disregard the results. + * @sscan_pri80: This is set to 1 to indicate that the Spectral scan was + * performed on the pri80 segment. Software may choose to + * disregard the FFT sample if this is set to 1 but detector ID + * does not correspond to the ID for the pri80 segment. */ struct sscan_report_fields_gen3 { uint8_t sscan_agc_total_gain; int16_t inband_pwr_db; uint8_t sscan_gainchange; + uint8_t sscan_pri80; }; /** - * struct spectral_sscan_report_gen3 - spectral report in phyerr event + * struct spectral_sscan_summary_report_gen3 - Spectral summary report + * event * @sscan_timestamp: Timestamp at which fft report was generated * @sscan_hdr_sig: signature * @sscan_hdr_tag: tag @@ -353,9 +382,9 @@ struct sscan_report_fields_gen3 { * @hdr_a: Header[0:31] * @resv: Header[32:63] * @hdr_b: Header[64:95] - * @resv: Header[96:127] + * @hdr_c: Header[96:127] */ -struct spectral_sscan_report_gen3 { +struct spectral_sscan_summary_report_gen3 { u_int32_t sscan_timestamp; #ifdef BIG_ENDIAN_HOST u_int8_t sscan_hdr_sig; @@ -369,7 +398,7 @@ struct spectral_sscan_report_gen3 { u_int32_t hdr_a; u_int32_t res1; u_int32_t hdr_b; - u_int32_t res2; + u_int32_t hdr_c; } __ATTRIB_PACK; #ifdef DIRECT_BUF_RX_ENABLE @@ -417,6 +446,89 @@ enum spectral_fftbin_size_war { SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE = 2, }; +/** + * enum spectral_report_format_version - This represents the report format + * version number within each Spectral generation. + * @SPECTRAL_REPORT_FORMAT_VERSION_1 : version 1 + * @SPECTRAL_REPORT_FORMAT_VERSION_2 : version 2 + */ +enum spectral_report_format_version { + SPECTRAL_REPORT_FORMAT_VERSION_1, + SPECTRAL_REPORT_FORMAT_VERSION_2, +}; + +/** + * struct spectral_fft_bin_len_adj_swar - Encapsulate information required for + * Spectral FFT bin length adjusting software WARS. + * @inband_fftbin_size_adj: Whether to carry out FFT bin size adjustment for + * in-band report format. This would be required on some chipsets under the + * following circumstances: In report mode 2 only the in-band bins are DMA'ed. + * Scatter/gather is used. However, the HW generates all bins, not just in-band, + * and reports the number of bins accordingly. The subsystem arranging for the + * DMA cannot change this value. On such chipsets the adjustment required at the + * host driver is to check if report format is 2, and if so halve the number of + * bins reported to get the number actually DMA'ed. + * @null_fftbin_adj: Whether to remove NULL FFT bins for report mode (1) in + * which only summary of metrics for each completed FFT + spectral scan summary + * report are to be provided. This would be required on some chipsets under the + * following circumstances: In report mode 1, HW reports a length corresponding + * to all bins, and provides bins with value 0. This is because the subsystem + * arranging for the FFT information does not arrange for DMA of FFT bin values + * (as expected), but cannot arrange for a smaller length to be reported by HW. + * In these circumstances, the driver would have to disregard the NULL bins and + * report a bin count of 0 to higher layers. + * @packmode_fftbin_size_adj: Pack mode in HW refers to packing of each Spectral + * FFT bin into 2 bytes. But due to a bug HW reports 2 times the expected length + * when packmode is enabled. This SWAR compensates this bug by dividing the + * length with 2. + * @fftbin_size_war: Type of FFT bin size SWAR + */ +struct spectral_fft_bin_len_adj_swar { + u_int8_t inband_fftbin_size_adj; + u_int8_t null_fftbin_adj; + uint8_t packmode_fftbin_size_adj; + enum spectral_fftbin_size_war fftbin_size_war; +}; + +/** + * struct spectral_report_params - Parameters related to format of Spectral + * report. + * @version: This represents the report format version number within each + * Spectral generation. + * @ssumaary_padding_bytes: Number of bytes of padding after Spectral summary + * report + * @fft_report_hdr_len: Number of bytes in the header of the FFT report. This + * has to be subtracted from the length field of FFT report to find the length + * of FFT bins. + */ +struct spectral_report_params { + enum spectral_report_format_version version; + uint8_t ssumaary_padding_bytes; + uint8_t fft_report_hdr_len; +}; + +/** + * struct spectral_param_min_max - Spectral parameter minimum and maximum values + * @fft_size_min: Minimum value of fft_size + * @fft_size_max: Maximum value of fft_size for each BW + */ +struct spectral_param_min_max { + uint16_t fft_size_min; + uint16_t fft_size_max[CH_WIDTH_MAX]; +}; + +/** + * struct spectral_timestamp_swar - Spectral time stamp WAR related parameters + * @timestamp_war_offset: Offset to be added to correct timestamp + * @target_reset_count: Number of times target exercised the reset routine + * @last_fft_timestamp: last fft report timestamp + */ +struct spectral_timestamp_war { + uint32_t timestamp_war_offset[SPECTRAL_SCAN_MODE_MAX]; + uint64_t target_reset_count; + uint32_t last_fft_timestamp[SPECTRAL_SCAN_MODE_MAX]; +}; + #if ATH_PERF_PWR_OFFLOAD /** * enum target_if_spectral_info - Enumerations for specifying which spectral @@ -688,16 +800,30 @@ struct vdev_spectral_enable_params; /** * struct wmi_spectral_cmd_ops - structure used holding the operations * related to wmi commands on spectral parameters. - * @wmi_spectral_configure_cmd_send: - * @wmi_spectral_enable_cmd_send: + * @wmi_spectral_configure_cmd_send: Configure Spectral parameters + * @wmi_spectral_enable_cmd_send: Enable/Disable Spectral + * @wmi_spectral_crash_inject: Inject FW crash */ struct wmi_spectral_cmd_ops { QDF_STATUS (*wmi_spectral_configure_cmd_send)( - void *wmi_hdl, - struct vdev_spectral_configure_params *param); + wmi_unified_t wmi_hdl, + struct vdev_spectral_configure_params *param); QDF_STATUS (*wmi_spectral_enable_cmd_send)( - void *wmi_hdl, - struct vdev_spectral_enable_params *param); + wmi_unified_t wmi_hdl, + struct vdev_spectral_enable_params *param); + QDF_STATUS(*wmi_spectral_crash_inject)( + wmi_unified_t wmi_handle, struct crash_inject *param); +}; + +/** + * struct spectral_param_properties - structure holding Spectral + * parameter properties + * @supported: Parameter is supported or not + * @common_all_modes: Parameter should be common for all modes or not + */ +struct spectral_param_properties { + bool supported; + bool common_all_modes; }; /** @@ -705,6 +831,7 @@ struct wmi_spectral_cmd_ops { * @pdev: Pointer to pdev * @spectral_ops: Target if internal Spectral low level operations table * @capability: Spectral capabilities structure + * @properties: Spectral parameter properties per mode * @spectral_lock: Lock used for internal Spectral operations * @spectral_curchan_radindex: Current channel spectral index * @spectral_extchan_radindex: Extension channel spectral index @@ -760,8 +887,7 @@ struct wmi_spectral_cmd_ops { * @chaninfo: Channel statistics * @tsf64: Latest TSF Value * @param_info: Offload architecture Spectral parameter cache information - * @ch_width: Indicates Channel Width 20/40/80/160 MHz with values 0, 1, 2, 3 - * respectively + * @ch_width: Indicates Channel Width 20/40/80/160 MHz for each Spectral mode * @diag_stats: Diagnostic statistics * @is_160_format: Indicates whether information provided by HW is in altered * format for 802.11ac 160/80+80 MHz support (QCA9984 onwards) @@ -784,30 +910,22 @@ struct wmi_spectral_cmd_ops { * @nl_cb: Netlink callbacks * @use_nl_bcast: Whether to use Netlink broadcast/unicast * @send_phy_data: Send data to the application layer for a particular msg type - * @inband_fftbin_size_adj: Whether to carry out FFT bin size adjustment for - * in-band report format. This would be required on some chipsets under the - * following circumstances: In report mode 2 only the in-band bins are DMA'ed. - * Scatter/gather is used. However, the HW generates all bins, not just in-band, - * and reports the number of bins accordingly. The subsystem arranging for the - * DMA cannot change this value. On such chipsets the adjustment required at the - * host driver is to check if report format is 2, and if so halve the number of - * bins reported to get the number actually DMA'ed. - * @null_fftbin_adj: Whether to remove NULL FFT bins for report mode (1) in - * which only summary of metrics for each completed FFT + spectral scan summary - * report are to be provided. This would be required on some chipsets under the - * following circumstances: In report mode 1, HW reports a length corresponding - * to all bins, and provides bins with value 0. This is because the subsystem - * arranging for the FFT information does not arrange for DMA of FFT bin values - * (as expected), but cannot arrange for a smaller length to be reported by HW. - * In these circumstances, the driver would have to disregard the NULL bins and - * report a bin count of 0 to higher layers. - * @last_fft_timestamp: last fft report timestamp - * @timestamp_war_offset: Offset to be added to correct timestamp + * @len_adj_swar: Spectral fft bin length adjustment SWAR related info + * @timestamp_war: Spectral time stamp WAR related info + * @dbr_ring_debug: Whether Spectral DBR ring debug is enabled + * @dbr_buff_debug: Whether Spectral DBR buffer debug is enabled + * @direct_dma_support: Whether Direct-DMA is supported on the current radio + * @prev_tstamp: Timestamp of the previously received sample, which has to be + * compared with the current tstamp to check descrepancy + * @rparams: Parameters related to Spectral report structure + * @param_min_max: Spectral parameter's minimum and maximum values */ struct target_if_spectral { struct wlan_objmgr_pdev *pdev_obj; struct target_if_spectral_ops spectral_ops; struct spectral_caps capability; + struct spectral_param_properties + properties[SPECTRAL_SCAN_MODE_MAX][SPECTRAL_PARAM_MAX]; qdf_spinlock_t spectral_lock; int16_t spectral_curchan_radindex; int16_t spectral_extchan_radindex; @@ -887,7 +1005,7 @@ struct target_if_spectral { struct target_if_spectral_param_state_info param_info[SPECTRAL_SCAN_MODE_MAX]; #endif - uint32_t ch_width; + enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX]; struct spectral_diag_stats diag_stats; bool is_160_format; bool is_lb_edge_extrabins_format; @@ -906,15 +1024,15 @@ struct target_if_spectral { bool use_nl_bcast; int (*send_phy_data)(struct wlan_objmgr_pdev *pdev, enum spectral_msg_type smsg_type); - enum spectral_fftbin_size_war fftbin_size_war; - u_int8_t inband_fftbin_size_adj; - u_int8_t null_fftbin_adj; + struct spectral_fft_bin_len_adj_swar len_adj_swar; + struct spectral_timestamp_war timestamp_war; enum spectral_160mhz_report_delivery_state state_160mhz_delivery; - void *spectral_report_cache; - uint32_t last_fft_timestamp; - uint32_t timestamp_war_offset; - uint16_t fft_size_min; - uint16_t fft_size_max; + bool dbr_ring_debug; + bool dbr_buff_debug; + bool direct_dma_support; + uint32_t prev_tstamp; + struct spectral_report_params rparams; + struct spectral_param_min_max param_min_max; }; /** @@ -948,12 +1066,35 @@ struct target_if_spectral { * @freq: Center frequency of primary 20MHz channel in MHz * @vhtop_ch_freq_seg1: VHT operation first segment center frequency in MHz * @vhtop_ch_freq_seg2: VHT operation second segment center frequency in MHz + * @agile_freq: Center frequency in MHz of the entire span across which Agile + * Spectral is carried out. Applicable only for Agile Spectral samples. * @freq_loading: spectral control duty cycles * @noise_floor: current noise floor (except for secondary 80 segment) * @noise_floor_sec80: current noise floor for secondary 80 segment * @interf_list: List of interfernce sources * @classifier_params: classifier parameters * @sc: classifier parameters + * @pri80ind: Indication from hardware that the sample was received on the + * primary 80 MHz segment. If this is set when smode = + * SPECTRAL_SCAN_MODE_AGILE, it indicates that Spectral was carried out on + * pri80 instead of the Agile frequency due to a channel switch - Software may + * choose to ignore the sample in this case. + * @pri80ind_sec80: Indication from hardware that the sample was received on the + * primary 80 MHz segment instead of the secondary 80 MHz segment due to a + * channel switch - Software may choose to ignore the sample if this is set. + * Applicable only if smode = SPECTRAL_SCAN_MODE_NORMAL and for 160/80+80 MHz + * Spectral operation. + * @last_raw_timestamp: Previous FFT report's raw timestamp. In case of 160MHz + * it will be primary 80 segment's timestamp as both primary & secondary + * segment's timestamps are expected to be almost equal + * @timestamp_war_offset: Offset calculated based on reset_delay and + * last_raw_stamp. It will be added to raw_timestamp to get tstamp. + * @raw_timestamp: FFT timestamp reported by HW on primary segment. + * @raw_timestamp_sec80: FFT timestamp reported by HW on secondary 80 segment. + * @reset_delay: Time gap between the last spectral report before reset and the + * end of reset. + * @target_reset_count: Indicates the the number of times the target went + * through reset routine after spectral was enabled. */ struct target_if_samp_msg_params { int8_t rssi; @@ -984,6 +1125,7 @@ struct target_if_samp_msg_params { uint16_t freq; uint16_t vhtop_ch_freq_seg1; uint16_t vhtop_ch_freq_seg2; + uint16_t agile_freq; uint16_t freq_loading; int16_t noise_floor; int16_t noise_floor_sec80; @@ -995,6 +1137,14 @@ struct target_if_samp_msg_params { uint8_t gainchange; uint8_t gainchange_sec80; enum spectral_scan_mode smode; + uint8_t pri80ind; + uint8_t pri80ind_sec80; + uint32_t last_raw_timestamp; + uint32_t timestamp_war_offset; + uint32_t raw_timestamp; + uint32_t raw_timestamp_sec80; + uint32_t reset_delay; + uint32_t target_reset_count; }; #ifdef WLAN_CONV_SPECTRAL_ENABLE @@ -1100,13 +1250,15 @@ void target_if_spectral_send_intf_found_msg( * target_if_stop_spectral_scan() - Stop spectral scan * @pdev: Pointer to pdev object * @smode: Spectral scan mode + * @err: Pointer to error code * * API to stop the current on-going spectral scan * * Return: QDF_STATUS_SUCCESS in case of success, else QDF_STATUS_E_FAILURE */ QDF_STATUS target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev, - const enum spectral_scan_mode smode); + const enum spectral_scan_mode smode, + enum spectral_cp_error_code *err); /** * target_if_spectral_get_vdev() - Get pointer to vdev to be used for Spectral @@ -1177,22 +1329,6 @@ int target_if_spectral_dump_phyerr_data_gen2( uint32_t datalen, bool is_160_format); -/** - * target_if_dump_fft_report_gen3() - Dump FFT Report for gen3 - * @spectral: Pointer to Spectral object - * @smode: Spectral scan mode - * @p_fft_report: Pointer to fft report - * @p_sfft: Pointer to search fft report - * - * Dump FFT Report for gen3 - * - * Return: Success/Failure - */ -int target_if_dump_fft_report_gen3(struct target_if_spectral *spectral, - enum spectral_scan_mode smode, - struct spectral_phyerr_fft_report_gen3 *p_fft_report, - struct spectral_search_fft_info_gen3 *p_sfft); - /** * target_if_dbg_print_samp_msg() - Print contents of SAMP Message * @p: Pointer to SAMP message @@ -1203,19 +1339,6 @@ int target_if_dump_fft_report_gen3(struct target_if_spectral *spectral, */ void target_if_dbg_print_samp_msg(struct spectral_samp_msg *pmsg); -/** - * target_if_process_sfft_report_gen3() - Process Search FFT Report for gen3 - * @p_fft_report: Pointer to fft report - * @p_sfft: Pointer to search fft report - * - * Process Search FFT Report for gen3 - * - * Return: Success/Failure - */ -int target_if_process_sfft_report_gen3( - struct spectral_phyerr_fft_report_gen3 *p_fft_report, - struct spectral_search_fft_info_gen3 *p_fft_info); - /** * get_target_if_spectral_handle_from_pdev() - Get handle to target_if internal * Spectral data @@ -1228,10 +1351,19 @@ static inline struct target_if_spectral *get_target_if_spectral_handle_from_pdev( struct wlan_objmgr_pdev *pdev) { - struct target_if_spectral *spectral = NULL; - struct wlan_objmgr_psoc *psoc = NULL; + struct target_if_spectral *spectral; + struct wlan_objmgr_psoc *psoc; + + if (!pdev) { + spectral_err("pdev is null"); + return NULL; + } psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + spectral_err("psoc is null"); + return NULL; + } spectral = (struct target_if_spectral *) psoc->soc_cb.rx_ops.sptrl_rx_ops.sptrlro_get_target_handle( @@ -1263,6 +1395,30 @@ int16_t target_if_vdev_get_chan_freq(struct wlan_objmgr_vdev *vdev) vdev); } +/** + * target_if_vdev_get_chan_freq_seg2() - Get center frequency of secondary 80 of + * given vdev + * @vdev: Pointer to vdev + * + * Get the center frequency of secondary 80 of given vdev + * + * Return: center frequency of secondary 80 + */ +static inline +int16_t target_if_vdev_get_chan_freq_seg2(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_psoc *psoc = NULL; + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + spectral_err("psoc is NULL"); + return -EINVAL; + } + + return psoc->soc_cb.rx_ops.sptrl_rx_ops.sptrlro_vdev_get_chan_freq_seg2( + vdev); +} + /** * target_if_vdev_get_ch_width() - Get the operating channel bandwidth of a * given vdev @@ -1346,6 +1502,11 @@ void target_if_spectral_set_rxchainmask(struct wlan_objmgr_pdev *pdev, } spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("Spectral target if object is null"); + return; + } + /* set chainmask for all the modes */ for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) spectral->params[smode].ss_chn_mask = spectral_rx_chainmask; @@ -1379,6 +1540,11 @@ void target_if_spectral_process_phyerr( struct target_if_spectral_ops *p_sops = NULL; spectral = get_target_if_spectral_handle_from_pdev(pdev); + if (!spectral) { + spectral_err("Spectral target if object is null"); + return; + } + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); if (!p_sops->spectral_process_phyerr) { spectral_err("null spectral_process_phyerr"); @@ -1441,7 +1607,7 @@ reset_160mhz_delivery_state_machine(struct target_if_spectral *spectral, enum spectral_msg_type smsg_type; QDF_STATUS ret; - if (spectral->ch_width == CH_WIDTH_160MHZ) { + if (spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] == CH_WIDTH_160MHZ) { spectral->state_160mhz_delivery = SPECTRAL_REPORT_WAIT_PRIMARY80; @@ -1468,7 +1634,7 @@ static inline bool is_secondaryseg_expected(struct target_if_spectral *spectral) { return - ((spectral->ch_width == CH_WIDTH_160MHZ) && + ((spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] == CH_WIDTH_160MHZ) && (spectral->state_160mhz_delivery == SPECTRAL_REPORT_WAIT_SECONDARY80)); } @@ -1485,8 +1651,8 @@ static inline bool is_primaryseg_expected(struct target_if_spectral *spectral) { return - ((spectral->ch_width != CH_WIDTH_160MHZ) || - ((spectral->ch_width == CH_WIDTH_160MHZ) && + ((spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] != CH_WIDTH_160MHZ) || + ((spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] == CH_WIDTH_160MHZ) && (spectral->state_160mhz_delivery == SPECTRAL_REPORT_WAIT_PRIMARY80))); } @@ -1502,8 +1668,8 @@ static inline bool is_primaryseg_rx_inprog(struct target_if_spectral *spectral) { return - ((spectral->ch_width != CH_WIDTH_160MHZ) || - ((spectral->ch_width == CH_WIDTH_160MHZ) && + ((spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] != CH_WIDTH_160MHZ) || + ((spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] == CH_WIDTH_160MHZ) && ((spectral->spectral_gen == SPECTRAL_GEN2) || ((spectral->spectral_gen == SPECTRAL_GEN3) && (spectral->state_160mhz_delivery == SPECTRAL_REPORT_RX_PRIMARY80))))); @@ -1521,7 +1687,7 @@ static inline bool is_secondaryseg_rx_inprog(struct target_if_spectral *spectral) { return - ((spectral->ch_width == CH_WIDTH_160MHZ) && + ((spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] == CH_WIDTH_160MHZ) && ((spectral->spectral_gen == SPECTRAL_GEN2) || ((spectral->spectral_gen == SPECTRAL_GEN3) && (spectral->state_160mhz_delivery == SPECTRAL_REPORT_RX_SECONDARY80)))); @@ -1898,6 +2064,14 @@ target_if_consume_spectral_report_gen3( struct spectral_report *report); #endif +/** + * target_if_spectral_fw_hang() - Crash the FW from Spectral module + * @spectral: Pointer to Spectral LMAC object + * + * Return: QDF_STATUS of operation + */ +QDF_STATUS target_if_spectral_fw_hang(struct target_if_spectral *spectral); + #ifdef WIN32 #pragma pack(pop, target_if_spectral) #endif diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral_netlink.c b/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral_netlink.c index a57746ac73e4e1bf481003c7bd7a572e10c45686..a2be35823b39648447730db5eebeed8946ecfc95 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral_netlink.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral_netlink.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011,2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011,2017-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -51,6 +51,7 @@ target_if_spectral_create_samp_msg(struct target_if_spectral *spectral, size_t pwr_count_sec80 = 0; enum spectral_msg_type msg_type; QDF_STATUS ret; + struct spectral_fft_bin_len_adj_swar *swar = &spectral->len_adj_swar; ret = target_if_get_spectral_msg_type(params->smode, &msg_type); if (QDF_IS_STATUS_ERROR(ret)) @@ -72,13 +73,24 @@ target_if_spectral_create_samp_msg(struct target_if_spectral *spectral, spec_samp_msg->signature = SPECTRAL_SIGNATURE; spec_samp_msg->freq = params->freq; + if (params->smode == SPECTRAL_SCAN_MODE_AGILE) + spec_samp_msg->agile_freq = params->agile_freq; spec_samp_msg->freq_loading = params->freq_loading; samp_data->spectral_mode = params->smode; samp_data->spectral_data_len = params->datalen; samp_data->spectral_rssi = params->rssi; - samp_data->ch_width = spectral->ch_width; + samp_data->ch_width = + spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL]; + samp_data->agile_ch_width = + spectral->ch_width[SPECTRAL_SCAN_MODE_AGILE]; samp_data->spectral_agc_total_gain = params->agc_total_gain; samp_data->spectral_gainchange = params->gainchange; + samp_data->spectral_pri80ind = params->pri80ind; + samp_data->last_raw_timestamp = params->last_raw_timestamp; + samp_data->timestamp_war_offset = params->timestamp_war_offset; + samp_data->raw_timestamp = params->raw_timestamp; + samp_data->reset_delay = params->reset_delay; + samp_data->target_reset_count = params->target_reset_count; samp_data->spectral_combined_rssi = (uint8_t)params->rssi; @@ -138,12 +150,12 @@ target_if_spectral_create_samp_msg(struct target_if_spectral *spectral, qdf_mem_copy(cp, pcp, sizeof(struct spectral_classifier_params)); - if (spectral->fftbin_size_war == + if (swar->fftbin_size_war == SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) { binptr_32 = (uint32_t *)bin_pwr_data; for (idx = 0; idx < pwr_count; idx++) samp_data->bin_pwr[idx] = *(binptr_32++); - } else if (spectral->fftbin_size_war == + } else if (swar->fftbin_size_war == SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) { binptr_16 = (uint16_t *)bin_pwr_data; for (idx = 0; idx < pwr_count; idx++) @@ -179,6 +191,8 @@ target_if_spectral_create_samp_msg(struct target_if_spectral *spectral, params->agc_total_gain_sec80; spec_samp_msg->samp_data.spectral_gainchange_sec80 = params->gainchange_sec80; + spec_samp_msg->samp_data.spectral_pri80ind_sec80 = + params->pri80ind_sec80; samp_data->spectral_data_len_sec80 = params->datalen_sec80; @@ -187,6 +201,8 @@ target_if_spectral_create_samp_msg(struct target_if_spectral *spectral, samp_data->spectral_max_mag_sec80 = params->max_mag_sec80; + samp_data->raw_timestamp_sec80 = params->raw_timestamp_sec80; + /* * Currently, we compute pwr_count_sec80 considering the size of * the samp_data->bin_pwr_sec80 array rather than the number of @@ -205,12 +221,12 @@ target_if_spectral_create_samp_msg(struct target_if_spectral *spectral, samp_data->bin_pwr_count_sec80 = pwr_count_sec80; bin_pwr_data = params->bin_pwr_data_sec80; - if (spectral->fftbin_size_war == + if (swar->fftbin_size_war == SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) { binptr_32 = (uint32_t *)bin_pwr_data; for (idx = 0; idx < pwr_count_sec80; idx++) samp_data->bin_pwr_sec80[idx] = *(binptr_32++); - } else if (spectral->fftbin_size_war == + } else if (swar->fftbin_size_war == SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) { binptr_16 = (uint16_t *)bin_pwr_data; for (idx = 0; idx < pwr_count_sec80; idx++) @@ -223,7 +239,7 @@ target_if_spectral_create_samp_msg(struct target_if_spectral *spectral, } } - if ((spectral->ch_width != CH_WIDTH_160MHZ) || + if (spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] != CH_WIDTH_160MHZ || (params->smode == SPECTRAL_SCAN_MODE_AGILE) || is_secondaryseg_rx_inprog(spectral)) { if (spectral->send_phy_data(spectral->pdev_obj, diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral_phyerr.c b/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral_phyerr.c index 95e79df82f84c96a46dbe453e0fb442a9eb6e594..e235149110cbf8252134aedbf155322cdfdc7cf4 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral_phyerr.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/spectral/target_if_spectral_phyerr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011,2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011,2017-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef DIRECT_BUF_RX_ENABLE #include #endif @@ -35,30 +36,87 @@ extern int spectral_debug_level; #ifdef WLAN_CONV_SPECTRAL_ENABLE +#define SPECTRAL_HEXDUMP_OCTET_PRINT_SIZE (3) +#define SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE (16) +#define SPECTRAL_HEXDUMP_EXTRA_BUFFER_PER_LINE (16) + +/* + * Provision for the expected hexdump line size as follows: + * + * Size per octet multiplied by number of octets per line + * + + * ASCII representation which is equivalent in print size to number of octets + * per line + * + + * Some extra buffer + */ +#define SPECTRAL_HEXDUMP_LINESIZE \ + ((SPECTRAL_HEXDUMP_OCTET_PRINT_SIZE * \ + SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE) + \ + SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE + \ + SPECTRAL_HEXDUMP_EXTRA_BUFFER_PER_LINE) + +/** + * target_if_spectral_hexdump() - Print hexdump of the given buffer + * @_buf: Pointer to buffer + * @_len: Length of the buffer + * + * Print the hexdump of buffer upto given length. Print upto + * SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE per line, followed by the ASCII + * representation of these octets. + */ static inline void target_if_spectral_hexdump(unsigned char *_buf, int _len) { int i, mod; - unsigned char ascii[17]; + unsigned char ascii[SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE + 1]; unsigned char *pc = (_buf); + char hexdump_line[SPECTRAL_HEXDUMP_LINESIZE + 1]; + int loc = 0; + + qdf_mem_zero(hexdump_line, sizeof(hexdump_line)); + + if (_len <= 0) { + spectral_err("buffer len is %d, too short", _len); + return; + } for (i = 0; i < _len; i++) { - mod = i % 16; + mod = i % SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE; + if (!mod) { - if (i) - spectral_debug(" %s\n", ascii); + if (i) { + qdf_assert_always(loc < sizeof(hexdump_line)); + loc += snprintf(&hexdump_line[loc], + sizeof(hexdump_line) - loc, + " %s", ascii); + spectral_debug("%s", hexdump_line); + qdf_mem_zero(hexdump_line, + sizeof(hexdump_line)); + loc = 0; + } } - spectral_debug(" %02x", pc[i]); + + qdf_assert_always(loc < sizeof(hexdump_line)); + loc += snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc, + " %02x", pc[i]); + if ((pc[i] < 0x20) || (pc[i] > 0x7e)) ascii[mod] = '.'; else ascii[mod] = pc[i]; ascii[(mod) + 1] = '\0'; } - while ((i % 16) != 0) { - spectral_debug(" "); + + while ((i % SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE) != 0) { + qdf_assert_always(loc < sizeof(hexdump_line)); + loc += snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc, + " "); i++; } - spectral_debug(" %s\n", ascii); + + qdf_assert_always(loc < sizeof(hexdump_line)); + snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc, " %s", ascii); + spectral_debug("%s", hexdump_line); } /** @@ -100,6 +158,21 @@ target_if_spectral_dump_fft(uint8_t *pfft, int fftlen) return 0; } +QDF_STATUS target_if_spectral_fw_hang(struct target_if_spectral *spectral) +{ + struct crash_inject param; + + if (!spectral) { + spectral_err("Spectral LMAC object is null"); + return QDF_STATUS_E_INVAL; + } + qdf_mem_set(¶m, sizeof(param), 0); + param.type = 1; //RECOVERY_SIM_ASSERT + + return spectral->param_wmi_cmd_ops.wmi_spectral_crash_inject( + GET_WMI_HDL_FROM_PDEV(spectral->pdev_obj), ¶m); +} + void target_if_dbg_print_samp_param(struct target_if_samp_msg_params *p) { @@ -899,8 +972,8 @@ target_if_process_phyerr_gen2(struct target_if_spectral *spectral, acs_stats->nfc_ctl_rssi = control_rssi; acs_stats->nfc_ext_rssi = extension_rssi; - if (spectral->is_160_format && - spectral->ch_width == CH_WIDTH_160MHZ) { + if (spectral->is_160_format && spectral->ch_width + [SPECTRAL_SCAN_MODE_NORMAL] == CH_WIDTH_160MHZ) { /* * We expect to see one more Search FFT report, and it * should be equal in size to the current one. @@ -1028,7 +1101,8 @@ target_if_get_combrssi_sec80_seg_gen2( total_gain_db = p_sfft_sec80->total_gain_info; /* Calculate offset */ - offset = target_if_get_offset_swar_sec80(spectral->ch_width); + offset = target_if_get_offset_swar_sec80( + spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL]); /* Calculate RSSI */ comb_rssi = ((avgpwr_db - total_gain_db) + offset); @@ -1126,7 +1200,74 @@ target_if_spectral_dump_phyerr_data_gen2(uint8_t *data, uint32_t datalen, return 0; } -int +#ifdef DIRECT_BUF_RX_ENABLE +/** + * target_if_spectral_get_bin_count_after_len_adj() - Get number of FFT bins in + * Spectral FFT report + * @fft_bin_len: FFT bin length reported by target + * @rpt_mode: Spectral report mode + * @swar: Spectral FFT bin length adjustments SWAR parameters + * + * Get actual number of FFT bins in the FFT report after adjusting the length + * by applying the SWARs for getting correct length. + * + * Return: FFT bin count + */ +static size_t +target_if_spectral_get_bin_count_after_len_adj( + size_t fft_bin_len, uint8_t rpt_mode, + struct spectral_fft_bin_len_adj_swar *swar) +{ + size_t fft_bin_count = fft_bin_len; + + if (rpt_mode == 1 && swar->null_fftbin_adj) { + /* + * No FFT bins are expected. Explicitly set FFT bin + * count to 0. + */ + fft_bin_count = 0; + } else { + /* + * Divide fft bin length by appropriate factor depending + * on the value of fftbin_size_war. + */ + switch (swar->fftbin_size_war) { + case SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE: + fft_bin_count >>= 2; + break; + case SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE: + fft_bin_count >>= 1; + /* Ideally we should be dividing fft bin length + * by 2. Due to a HW bug, actual length is two + * times the expected length. + */ + if (swar->packmode_fftbin_size_adj) + fft_bin_count >>= 1; + break; + case SPECTRAL_FFTBIN_SIZE_NO_WAR: + /* No length adjustment */ + break; + default: + qdf_assert_always(0); + } + + if (rpt_mode == 2 && swar->inband_fftbin_size_adj) + fft_bin_count >>= 1; + } + + return fft_bin_count; +} + +/** + * target_if_process_sfft_report_gen3() - Process Search FFT Report for gen3 + * @p_fft_report: Pointer to fft report + * @p_sfft: Pointer to search fft report + * + * Process Search FFT Report for gen3 + * + * Return: Success/Failure + */ +static int target_if_process_sfft_report_gen3( struct spectral_phyerr_fft_report_gen3 *p_fft_report, struct spectral_search_fft_info_gen3 *p_sfft) @@ -1174,113 +1315,122 @@ target_if_process_sfft_report_gen3( return 0; } -int +/** + * target_if_dump_fft_report_gen3() - Dump FFT Report for gen3 + * @spectral: Pointer to Spectral object + * @smode: Spectral scan mode + * @p_fft_report: Pointer to fft report + * @p_sfft: Pointer to search fft report + * + * Dump FFT Report for gen3 + * + * Return: void + */ +static void target_if_dump_fft_report_gen3(struct target_if_spectral *spectral, enum spectral_scan_mode smode, struct spectral_phyerr_fft_report_gen3 *p_fft_report, struct spectral_search_fft_info_gen3 *p_sfft) { - int i = 0; - int fft_mag = 0; - int fft_hdr_length = (p_fft_report->fft_hdr_length * 4); - int report_len = (fft_hdr_length + 8); - int fft_bin_len = (fft_hdr_length - 16); - int fft_bin_len_to_dump = fft_bin_len; - int fft_bin_len_adj = 0; - int fft_bin_len_inband_tfer = 0; - - if ((spectral->params[smode].ss_rpt_mode == 1) && - spectral->null_fftbin_adj) { - /* fft_bin_len_adj is intentionally left at 0. */ - fft_bin_len_to_dump = 0; - } else { - /* - * Divide fft bin length by appropriate factor depending - * on the value of fftbin_size_war. - */ - if (spectral->fftbin_size_war == - SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) - fft_bin_len_adj = fft_bin_len >> 2; - else if (spectral->fftbin_size_war == - SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) { - /* Ideally we should be dividing fft bin length by 2. - * Due to a HW bug, actual length is two times the - * expected length. - */ - fft_bin_len_adj = fft_bin_len >> 2; - } else - fft_bin_len_adj = fft_bin_len; - - if ((spectral->params[smode].ss_rpt_mode == 2) && - spectral->inband_fftbin_size_adj) { - fft_bin_len_adj >>= 1; - fft_bin_len_inband_tfer = fft_bin_len >> 1; - fft_bin_len_to_dump = fft_bin_len_inband_tfer; - } - } - - spectral_debug("#############################################################"); - spectral_debug("Spectral search fft_report"); - spectral_debug("fft_timestamp = 0x%x\nfft_hdr_length = %d(32 bit words)\nfft_hdr_tag = 0x%x\nfft_hdr_sig = 0x%x", - p_fft_report->fft_timestamp, - p_fft_report->fft_hdr_length, - p_fft_report->fft_hdr_tag, p_fft_report->fft_hdr_sig); - - spectral_debug("Length field in search fft report is %d(0x%x) bytes", + size_t fft_hdr_length = (p_fft_report->fft_hdr_length * 4); + size_t report_len = (fft_hdr_length + 8); + size_t fft_bin_len; + size_t fft_bin_count; + size_t fft_bin_len_inband_tfer = 0; + uint8_t *fft_bin_buf = NULL; + + fft_bin_len = fft_hdr_length - spectral->rparams.fft_report_hdr_len; + fft_bin_count = target_if_spectral_get_bin_count_after_len_adj( + fft_bin_len, + spectral->params[smode].ss_rpt_mode, + &spectral->len_adj_swar); + + if ((spectral->params[smode].ss_rpt_mode == 2) && + spectral->len_adj_swar.inband_fftbin_size_adj) + fft_bin_len_inband_tfer = fft_bin_len >> 1; + + spectral_debug("Spectral FFT Report"); + spectral_debug("fft_timestamp = 0x%x", p_fft_report->fft_timestamp); + spectral_debug("fft_hdr_length = %u(32 bit words)", + p_fft_report->fft_hdr_length); + spectral_debug("fft_hdr_tag = 0x%x", p_fft_report->fft_hdr_tag); + spectral_debug("fft_hdr_sig = 0x%x", p_fft_report->fft_hdr_sig); + + spectral_debug("Length field in search fft report is %zu(0x%zx) bytes", fft_hdr_length, fft_hdr_length); - spectral_debug("Total length of search fft report is %d(0x%x) bytes", + spectral_debug("Total length of search fft report is %zu(0x%zx) bytes", report_len, report_len); - spectral_debug("Target reported fftbins in report is %d(0x%x)", - fft_bin_len, - fft_bin_len); + spectral_debug("Target reported fftbins in report is %zu(0x%zx)", + fft_bin_len, fft_bin_len); if ((spectral->params[smode].ss_rpt_mode == 1) && - spectral->null_fftbin_adj) + spectral->len_adj_swar.null_fftbin_adj) spectral_debug("WAR: Considering number of FFT bins as 0"); else if ((spectral->params[smode].ss_rpt_mode == 2) && - spectral->inband_fftbin_size_adj) { - spectral_debug("FW fftbins actually transferred (in-band report mode) " - "%d(0x%x)", - fft_bin_len_inband_tfer, fft_bin_len_inband_tfer); + spectral->len_adj_swar.inband_fftbin_size_adj) { + spectral_debug("FW fftbins actually transferred (in-band report mode) %zu(0x%zx)", + fft_bin_len_inband_tfer, + fft_bin_len_inband_tfer); } - spectral_debug("Actual number of fftbins in report is %d(0x%x)\n", - fft_bin_len_adj, fft_bin_len_adj); - - spectral_debug("fft_detector_id = %u\nfft_num = %u\nfft_radar_check = %u\nfft_peak_sidx = %d\nfft_chn_idx = %u\nfft_base_pwr_db = %u\nfft_total_gain_db = %u\nfft_num_str_bins_ib = %u\nfft_peak_mag = %d\nfft_avgpwr_db = %u\nfft_relpwr_db = %u", - p_sfft->fft_detector_id, - p_sfft->fft_num, - p_sfft->fft_radar_check, - p_sfft->fft_peak_sidx, - p_sfft->fft_chn_idx, - p_sfft->fft_base_pwr_db, - p_sfft->fft_total_gain_db, - p_sfft->fft_num_str_bins_ib, - p_sfft->fft_peak_mag, - p_sfft->fft_avgpwr_db, p_sfft->fft_relpwr_db); - - if (fft_bin_len_to_dump > 0) { + spectral_debug("Actual number of fftbins in report is %zu(0x%zx)", + fft_bin_count, fft_bin_count); + + spectral_debug("fft_detector_id = %u", p_sfft->fft_detector_id); + spectral_debug("fft_num = %u", p_sfft->fft_num); + spectral_debug("fft_radar_check = %u", p_sfft->fft_radar_check); + spectral_debug("fft_peak_sidx = %d", p_sfft->fft_peak_sidx); + spectral_debug("fft_chn_idx = %u", p_sfft->fft_chn_idx); + spectral_debug("fft_base_pwr_db = %u", p_sfft->fft_base_pwr_db); + spectral_debug("fft_total_gain_db = %u", p_sfft->fft_total_gain_db); + spectral_debug("fft_num_str_bins_ib = %u", p_sfft->fft_num_str_bins_ib); + spectral_debug("fft_peak_mag = %d", p_sfft->fft_peak_mag); + spectral_debug("fft_avgpwr_db = %u", p_sfft->fft_avgpwr_db); + spectral_debug("fft_relpwr_db = %u", p_sfft->fft_relpwr_db); + + if (fft_bin_count > 0) { + int idx; + spectral_debug("FFT bins:"); - for (i = 0; i < fft_bin_len_to_dump; i++) { - if (i % 16 == 0) - spectral_debug("\n%d :", i); - fft_mag = - ((uint8_t *)p_fft_report)[SPECTRAL_FFT_BINS_POS + i]; - spectral_debug("%d ", fft_mag); + if (spectral->len_adj_swar.fftbin_size_war == + SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) { + uint32_t *binptr_32 = (uint32_t *)&p_fft_report->buf; + + fft_bin_buf = (uint8_t *)qdf_mem_malloc(MAX_NUM_BINS); + if (!fft_bin_buf) { + spectral_err("Failed to allocate memory"); + return; + } + for (idx = 0; idx < fft_bin_count; idx++) + fft_bin_buf[idx] = *(binptr_32++); + } else if (spectral->len_adj_swar.fftbin_size_war == + SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) { + uint16_t *binptr_16 = (uint16_t *)&p_fft_report->buf; + + fft_bin_buf = (uint8_t *)qdf_mem_malloc(MAX_NUM_BINS); + if (!fft_bin_buf) { + spectral_err("Failed to allocate memory"); + return; + } + for (idx = 0; idx < fft_bin_count; idx++) + fft_bin_buf[idx] = *(binptr_16++); + } else { + fft_bin_buf = (uint8_t *)&p_fft_report->buf; } + target_if_spectral_hexdump(fft_bin_buf, fft_bin_count); + if ((spectral->len_adj_swar.fftbin_size_war != + SPECTRAL_FFTBIN_SIZE_NO_WAR) && fft_bin_buf) + qdf_mem_free(fft_bin_buf); } - spectral_debug("\n"); - spectral_debug("#############################################################"); - - return 0; } +#endif QDF_STATUS target_if_160mhz_delivery_state_change(struct target_if_spectral *spectral, uint8_t detector_id) { QDF_STATUS status = QDF_STATUS_SUCCESS; - if (spectral->ch_width != CH_WIDTH_160MHZ) + if (spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] != CH_WIDTH_160MHZ) return QDF_STATUS_E_FAILURE; /* agile reports should not be coupled with 160 MHz state machine @@ -1333,47 +1483,84 @@ target_if_160mhz_delivery_state_change(struct target_if_spectral *spectral, #ifdef DIRECT_BUF_RX_ENABLE /** - * target_if_get_detector_id_sscan_report_gen3() - Get Spectral detector id - * @data: Pointer to Spectral summary report / Spectral - * search FFT report - * - * Get Spectral detector id from Spectral summary report / Spectral - * search FFT report + * target_if_get_detector_id_sscan_summary_report_gen3() - Get Spectral detector + * ID from Spectral summary report + * @data: Pointer to Spectral summary report * - * Return: detector id + * Return: Detector ID */ static uint8_t -target_if_get_detector_id_sscan_report_gen3(uint8_t *data) { - struct spectral_sscan_report_gen3 *psscan_report; +target_if_get_detector_id_sscan_summary_report_gen3(uint8_t *data) { + struct spectral_sscan_summary_report_gen3 *psscan_summary_report; uint8_t detector_id; - psscan_report = (struct spectral_sscan_report_gen3 *)data; - detector_id = get_bitfield(psscan_report->hdr_a, - SSCAN_REPORT_DETECTOR_ID_SIZE_GEN3, - SSCAN_REPORT_DETECTOR_ID_POS_GEN3); + qdf_assert_always(data); + + psscan_summary_report = + (struct spectral_sscan_summary_report_gen3 *)data; + + detector_id = get_bitfield( + psscan_summary_report->hdr_a, + SSCAN_SUMMARY_REPORT_HDR_A_DETECTOR_ID_SIZE_GEN3, + SSCAN_SUMMARY_REPORT_HDR_A_DETECTOR_ID_POS_GEN3); return detector_id; } /** - * target_if_consume_sscan_report_gen3() - Consume spectral summary report - * @spectral: Pointer to spectral object - * @data: Pointer to spectral summary + * target_if_consume_sscan_summary_report_gen3() - Consume Spectral summary + * report + * @data: Pointer to Spectral summary report + * @fields: Pointer to structure to be populated with extracted fields + * @rparams: Pointer to structure with Spectral report params * - * Consume spectral summary report for gen3 + * Consume Spectral summary report for gen3 * * Return: void */ static void -target_if_consume_sscan_report_gen3(struct target_if_spectral *spectral, - uint8_t *data, - struct sscan_report_fields_gen3 *fields) { - struct spectral_sscan_report_gen3 *psscan_report; - - psscan_report = (struct spectral_sscan_report_gen3 *)data; - fields->sscan_agc_total_gain = get_bitfield(psscan_report->hdr_a, 8, 0); - fields->inband_pwr_db = get_bitfield(psscan_report->hdr_a, 10, 18); - fields->sscan_gainchange = get_bitfield(psscan_report->hdr_b, 1, 30); +target_if_consume_sscan_summary_report_gen3( + uint8_t *data, + struct sscan_report_fields_gen3 *fields, + struct spectral_report_params *rparams) { + struct spectral_sscan_summary_report_gen3 *psscan_summary_report; + + qdf_assert_always(data); + qdf_assert_always(fields); + qdf_assert_always(rparams); + + psscan_summary_report = + (struct spectral_sscan_summary_report_gen3 *)data; + + fields->sscan_agc_total_gain = get_bitfield( + psscan_summary_report->hdr_a, + SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_SIZE_GEN3, + SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_POS_GEN3); + fields->inband_pwr_db = get_bitfield( + psscan_summary_report->hdr_a, + SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_SIZE_GEN3, + SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_POS_GEN3); + fields->sscan_pri80 = get_bitfield( + psscan_summary_report->hdr_a, + SSCAN_SUMMARY_REPORT_HDR_A_PRI80_SIZE_GEN3, + SSCAN_SUMMARY_REPORT_HDR_A_PRI80_POS_GEN3); + + switch (rparams->version) { + case SPECTRAL_REPORT_FORMAT_VERSION_1: + fields->sscan_gainchange = get_bitfield( + psscan_summary_report->hdr_b, + SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_SIZE_GEN3_V1, + SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_POS_GEN3_V1); + break; + case SPECTRAL_REPORT_FORMAT_VERSION_2: + fields->sscan_gainchange = get_bitfield( + psscan_summary_report->hdr_c, + SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_SIZE_GEN3_V2, + SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_POS_GEN3_V2); + break; + default: + qdf_assert_always(0); + } } /** @@ -1448,6 +1635,142 @@ target_if_get_spectral_mode(enum spectral_detector_id detector_id, return QDF_STATUS_SUCCESS; } +#ifdef DIRECT_BUF_RX_DEBUG +static void target_if_spectral_check_buffer_poisoning( + struct target_if_spectral *spectral, + struct spectral_report *report, + int num_fft_bins, enum spectral_scan_mode smode) +{ + uint32_t *data; + size_t len; + size_t words_to_check = + sizeof(struct spectral_sscan_summary_report_gen3) >> 2; + bool poisoned_words_found = false; + + if (!spectral) { + spectral_err_rl("Spectral LMAC object is null"); + return; + } + + if (!spectral->dbr_buff_debug) + return; + + if (!report) { + spectral_err_rl("Spectral report is null"); + return; + } + + /* Add search FFT report */ + if (spectral->params[smode].ss_rpt_mode > 0) + words_to_check += + sizeof(struct spectral_phyerr_fft_report_gen3) >> 2; + + /* Now add the number of FFT bins */ + if (spectral->params[smode].ss_rpt_mode > 1) { + /* Caller should take care to pass correct number of FFT bins */ + if (spectral->len_adj_swar.fftbin_size_war == + SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) + words_to_check += num_fft_bins; + else if (spectral->len_adj_swar.fftbin_size_war == + SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) + words_to_check += (num_fft_bins >> 1); + } + + data = (uint32_t *)report->data; + for (len = 0; len < words_to_check; ++len) { + if (*data == MEM_POISON_SIGNATURE) { + spectral_err("Pattern(%x) found in Spectral search FFT report at position %zu in the buffer %pK", + MEM_POISON_SIGNATURE, + (len << 2), report->data); + poisoned_words_found = true; + break; + } + ++data; + } + + /* Crash the FW even if one word is poisoned */ + if (poisoned_words_found) { + spectral_err("Pattern(%x) found in Spectral report, Hex dump of the sfft follows", + MEM_POISON_SIGNATURE); + target_if_spectral_hexdump((unsigned char *)report->data, + words_to_check << 2); + spectral_err("Asserting the FW"); + target_if_spectral_fw_hang(spectral); + } +} + +static void target_if_spectral_verify_ts(struct target_if_spectral *spectral, + uint8_t *buf, uint32_t current_ts) +{ + if (!spectral) { + spectral_err_rl("Spectral LMAC object is null"); + return; + } + + if (!spectral->dbr_buff_debug) + return; + + if (spectral->prev_tstamp) { + if (current_ts == spectral->prev_tstamp) { + spectral_err("Spectral timestamp(%u) in the current buffer(%pK) is equal to the previous timestamp, same report DMAed twice? Asserting the FW", + current_ts, buf); + target_if_spectral_fw_hang(spectral); + } + } + spectral->prev_tstamp = current_ts; +} +#else +static void target_if_spectral_check_buffer_poisoning( + struct target_if_spectral *spectral, + struct spectral_report *report, + int num_fft_bins, enum spectral_scan_mode smode) +{ +} + +static void target_if_spectral_verify_ts(struct target_if_spectral *spectral, + uint8_t *buf, uint32_t current_ts) +{ +} +#endif + +/** + * target_if_spectral_get_adjusted_timestamp() - Adjust Spectral time + * stamp to account for reset in time stamp due to target reset + * @twar: Spectral time stamp WAR related information + * @raw_timestamp: Spectral time stamp reported by target + * @reset_delay: Reset delay at target + * @smode: Spectral scan mode + * + * Correct time stamp to account for reset in time stamp due to target reset + * + * Return: Adjusted time stamp + */ +static uint32_t +target_if_spectral_get_adjusted_timestamp(struct spectral_timestamp_war *twar, + uint32_t raw_timestamp, + uint32_t reset_delay, + enum spectral_scan_mode smode) { + qdf_assert_always(smode < SPECTRAL_SCAN_MODE_MAX); + + if (reset_delay) { + enum spectral_scan_mode m = + SPECTRAL_SCAN_MODE_NORMAL; + + /* Adjust the offset for all the Spectral modes. + * Target will be sending the non zero reset delay for + * the first Spectral report after reset. This delay is + * common for all the Spectral modes. + */ + for (; m < SPECTRAL_SCAN_MODE_MAX; m++) + twar->timestamp_war_offset[m] += (reset_delay + + twar->last_fft_timestamp[m]); + twar->target_reset_count++; + } + twar->last_fft_timestamp[smode] = raw_timestamp; + + return raw_timestamp + twar->timestamp_war_offset[smode]; +} + int target_if_consume_spectral_report_gen3( struct target_if_spectral *spectral, @@ -1478,14 +1801,13 @@ target_if_consume_spectral_report_gen3( * 1. Order of FFT bin values * */ - uint64_t tsf64 = 0; struct target_if_samp_msg_params params = {0}; struct spectral_search_fft_info_gen3 search_fft_info; struct spectral_search_fft_info_gen3 *p_sfft = &search_fft_info; int8_t chn_idx_lowest_enabled = 0; int fft_hdr_length = 0; int report_len = 0; - int fft_bin_len = 0; + size_t fft_bin_count; struct target_if_spectral_ops *p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); struct spectral_phyerr_fft_report_gen3 *p_fft_report; @@ -1493,7 +1815,7 @@ target_if_consume_spectral_report_gen3( uint8_t *data = report->data; struct wlan_objmgr_vdev *vdev; uint8_t vdev_rxchainmask; - struct sscan_report_fields_gen3 sscan_report_fields; + struct sscan_report_fields_gen3 sscan_report_fields = {0}; enum spectral_detector_id detector_id; QDF_STATUS ret; @@ -1507,17 +1829,18 @@ target_if_consume_spectral_report_gen3( goto fail; } - detector_id = target_if_get_detector_id_sscan_report_gen3(data); + detector_id = target_if_get_detector_id_sscan_summary_report_gen3(data); if (detector_id > SPECTRAL_DETECTOR_AGILE) { spectral->diag_stats.spectral_invalid_detector_id++; spectral_err("Invalid detector id %u, expected is 0/1/2", detector_id); goto fail; } - target_if_consume_sscan_report_gen3(spectral, data, - &sscan_report_fields); + target_if_consume_sscan_summary_report_gen3(data, &sscan_report_fields, + &spectral->rparams); /* Advance buf pointer to the search fft report */ - data += sizeof(struct spectral_sscan_report_gen3); + data += sizeof(struct spectral_sscan_summary_report_gen3); + data += spectral->rparams.ssumaary_padding_bytes; if ((detector_id == SPECTRAL_DETECTOR_AGILE) || is_primaryseg_expected(spectral)) { @@ -1526,6 +1849,7 @@ target_if_consume_spectral_report_gen3( params.agc_total_gain = sscan_report_fields.sscan_agc_total_gain; params.gainchange = sscan_report_fields.sscan_gainchange; + params.pri80ind = sscan_report_fields.sscan_pri80; /* Process Spectral search FFT report */ if (target_if_verify_sig_and_tag_gen3( @@ -1570,47 +1894,27 @@ target_if_consume_spectral_report_gen3( goto fail; } - if ((spectral->params[params.smode].ss_rpt_mode == 1) && - spectral->null_fftbin_adj) { - /* - * No FFT bins are expected. Explicitly set FFT bin - * length to 0. - */ - fft_bin_len = 0; - } else { - fft_bin_len = (fft_hdr_length - 16); - - /* - * Divide fft bin length by appropriate factor depending - * on the value of fftbin_size_war. - */ - if (spectral->fftbin_size_war == - SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) - fft_bin_len >>= 2; - else if (spectral->fftbin_size_war == - SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) { - /* Ideally we should be dividing fft bin length - * by 2. Due to a HW bug, actual length is two - * times the expected length. - */ - fft_bin_len >>= 2; - } - if ((spectral->params[params.smode].ss_rpt_mode == 2) && - spectral->inband_fftbin_size_adj) { - fft_bin_len >>= 1; - } - } - - if (report->reset_delay) { - spectral->timestamp_war_offset += (report->reset_delay + - spectral->last_fft_timestamp); - } - tsf64 = p_sfft->timestamp; - spectral->last_fft_timestamp = p_sfft->timestamp; - tsf64 += spectral->timestamp_war_offset; + fft_bin_count = target_if_spectral_get_bin_count_after_len_adj( + fft_hdr_length - spectral->rparams.fft_report_hdr_len, + spectral->params[params.smode].ss_rpt_mode, + &spectral->len_adj_swar); + + params.last_raw_timestamp = spectral->timestamp_war. + last_fft_timestamp[params.smode]; + params.reset_delay = report->reset_delay; + params.raw_timestamp = p_sfft->timestamp; + params.tstamp = target_if_spectral_get_adjusted_timestamp( + &spectral->timestamp_war, + p_sfft->timestamp, report->reset_delay, + params.smode); + params.timestamp_war_offset = spectral->timestamp_war. + timestamp_war_offset[params.smode]; + params.target_reset_count = spectral->timestamp_war. + target_reset_count; /* Take care of state transitions for 160 MHz and 80p80 */ - if (spectral->ch_width == CH_WIDTH_160MHZ) { + if (spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] == + CH_WIDTH_160MHZ) { ret = target_if_160mhz_delivery_state_change( spectral, detector_id); @@ -1650,6 +1954,10 @@ target_if_consume_spectral_report_gen3( SPECTRAL_FFT_BINS_POS); params.freq = p_sops->get_current_channel(spectral); + if (params.smode == SPECTRAL_SCAN_MODE_AGILE) + params.agile_freq = + spectral->params[params.smode].ss_frequency; + /* * For modes upto VHT80, the noise floor is populated with * the one corresponding @@ -1659,14 +1967,17 @@ target_if_consume_spectral_report_gen3( params.noise_floor = report->noisefloor[chn_idx_lowest_enabled]; params.datalen = (fft_hdr_length * 4); - params.pwr_count = fft_bin_len; - params.tstamp = (tsf64 & SPECTRAL_TSMASK); + params.pwr_count = fft_bin_count; + + target_if_spectral_verify_ts(spectral, report->data, + params.tstamp); } else if (is_secondaryseg_expected(spectral)) { /* RSSI is in 1/2 dBm steps, Covert it to dBm scale */ rssi = (sscan_report_fields.inband_pwr_db) >> 1; params.agc_total_gain_sec80 = sscan_report_fields.sscan_agc_total_gain; params.gainchange_sec80 = sscan_report_fields.sscan_gainchange; + params.pri80ind_sec80 = sscan_report_fields.sscan_pri80; /* Process Spectral search FFT report */ if (target_if_verify_sig_and_tag_gen3( @@ -1711,40 +2022,15 @@ target_if_consume_spectral_report_gen3( goto fail; } - if ((spectral->params[params.smode].ss_rpt_mode == 1) && - spectral->null_fftbin_adj) { - /* - * No FFT bins are expected. Explicitly set FFT bin - * length to 0. - */ - fft_bin_len = 0; - } else { - fft_bin_len = (fft_hdr_length - 16); - - /* - * Divide fft bin length by appropriate factor depending - * on the value of fftbin_size_war. - */ - if (spectral->fftbin_size_war == - SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) - fft_bin_len >>= 2; - else if (spectral->fftbin_size_war == - SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) { - /* Ideally we should be dividing fft bin length - * by 2. Due to a HW bug, actual length is two - * times the expected length. - */ - fft_bin_len >>= 2; - } - - if ((spectral->params[params.smode].ss_rpt_mode == 2) && - spectral->inband_fftbin_size_adj) { - fft_bin_len >>= 1; - } - } + fft_bin_count = target_if_spectral_get_bin_count_after_len_adj( + fft_hdr_length - spectral->rparams.fft_report_hdr_len, + spectral->params[params.smode].ss_rpt_mode, + &spectral->len_adj_swar); + params.raw_timestamp_sec80 = p_sfft->timestamp; /* Take care of state transitions for 160 MHz and 80p80 */ - if (spectral->ch_width == CH_WIDTH_160MHZ) { + if (spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL] == + CH_WIDTH_160MHZ) { ret = target_if_160mhz_delivery_state_change( spectral, detector_id); @@ -1788,7 +2074,7 @@ target_if_consume_spectral_report_gen3( /* params.max_index_sec80 = p_sfft->peak_inx; */ /* XXX Does this definition of datalen *still hold? */ params.datalen_sec80 = fft_hdr_length * 4; - params.pwr_count_sec80 = fft_bin_len; + params.pwr_count_sec80 = fft_bin_count; params.bin_pwr_data_sec80 = (uint8_t *)((uint8_t *)p_fft_report + SPECTRAL_FFT_BINS_POS); @@ -1797,6 +2083,8 @@ target_if_consume_spectral_report_gen3( goto fail; } + target_if_spectral_check_buffer_poisoning(spectral, report, + fft_bin_count, params.smode); qdf_mem_copy(¶ms.classifier_params, &spectral->classifier_params, sizeof(struct spectral_classifier_params)); @@ -1805,7 +2093,6 @@ target_if_consume_spectral_report_gen3( target_if_spectral_create_samp_msg(spectral, ¶ms); return 0; - fail: spectral_err_rl("Error while processing Spectral report"); reset_160mhz_delivery_state_machine(spectral, diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/wifi_pos/inc/target_if_wifi_pos.h b/drivers/staging/qca-wifi-host-cmn/target_if/wifi_pos/inc/target_if_wifi_pos.h index b1a6b3fd856dceffd3ef2501f0d7de9ba44ba4d5..e136e099611e4595bf00990e5f1df0f5e4159faa 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/wifi_pos/inc/target_if_wifi_pos.h +++ b/drivers/staging/qca-wifi-host-cmn/target_if/wifi_pos/inc/target_if_wifi_pos.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017, 2019 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 @@ -26,6 +26,7 @@ #include "qdf_types.h" #include "qdf_status.h" +#include "wlan_cmn.h" struct oem_data_req; struct oem_data_rsp; struct wlan_objmgr_psoc; @@ -35,15 +36,6 @@ struct wlan_lmac_if_rx_ops; #ifdef WIFI_POS_CONVERGED -/** - * target_if_wifi_pos_get_txops: api to get tx ops - * @psoc: pointer to psoc object - * - * Return: tx ops - */ -struct wlan_lmac_if_wifi_pos_tx_ops *target_if_wifi_pos_get_txops( - struct wlan_objmgr_psoc *psoc); - /** * target_if_wifi_pos_get_rxops: api to get rx ops * @psoc: pointer to psoc object @@ -71,28 +63,24 @@ QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc); /** - * target_if_wifi_pos_register_tx_ops: function to register with lmac tx ops - * @tx_ops: lmac tx ops struct object + * target_if_wifi_pos_get_vht_ch_width: function to get vht channel width + * @psoc: pointer to psoc object + * @ch_width: pointer to the variable in which output value needs to be filled * - * Return: none + * Return: status of operation */ -void target_if_wifi_pos_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); +QDF_STATUS target_if_wifi_pos_get_vht_ch_width(struct wlan_objmgr_psoc *psoc, + enum phy_ch_width *ch_width); /** - * target_if_wifi_pos_register_rx_ops: function to register with lmac rx ops - * @rx_ops: lmac rx ops struct object + * target_if_wifi_pos_register_tx_ops: function to register with lmac tx ops + * @tx_ops: lmac tx ops struct object * * Return: none */ -void target_if_wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops); +void target_if_wifi_pos_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); #else -static inline struct wlan_lmac_if_wifi_pos_tx_ops *target_if_wifi_pos_get_txops( - struct wlan_objmgr_psoc *psoc) -{ - return NULL; -} - static inline struct wlan_lmac_if_wifi_pos_rx_ops *target_if_wifi_pos_get_rxops( struct wlan_objmgr_psoc *psoc) { @@ -104,10 +92,6 @@ static inline void target_if_wifi_pos_register_tx_ops( { } -static inline void target_if_wifi_pos_register_rx_ops( - struct wlan_lmac_if_rx_ops *rx_ops) -{ -} #endif #if defined(WLAN_FEATURE_CIF_CFR) && defined(WIFI_POS_CONVERGED) diff --git a/drivers/staging/qca-wifi-host-cmn/target_if/wifi_pos/src/target_if_wifi_pos.c b/drivers/staging/qca-wifi-host-cmn/target_if/wifi_pos/src/target_if_wifi_pos.c index d5bf4ae4d7df17b3306879aeaf0aa485e6d14553..6f9b00f4b8069c25853af801a6072599dbcc2fd3 100644 --- a/drivers/staging/qca-wifi-host-cmn/target_if/wifi_pos/src/target_if_wifi_pos.c +++ b/drivers/staging/qca-wifi-host-cmn/target_if/wifi_pos/src/target_if_wifi_pos.c @@ -22,6 +22,8 @@ * target if layer. */ #include "../../../../umac/wifi_pos/src/wifi_pos_utils_i.h" +#include "wifi_pos_utils_pub.h" + #include "wmi_unified_api.h" #include "wlan_lmac_if_def.h" #include "target_if_wifi_pos.h" @@ -84,7 +86,7 @@ static QDF_STATUS target_if_wifi_pos_replenish_ring( static QDF_STATUS target_if_wifi_pos_get_indirect_data( struct wifi_pos_psoc_priv_obj *priv_obj, - wmi_oem_indirect_data *indirect, + struct wmi_host_oem_indirect_data *indirect, struct oem_data_rsp *rsp, uint32_t *cookie) { void *paddr = NULL; @@ -138,7 +140,7 @@ static QDF_STATUS target_if_wifi_pos_replenish_ring( static QDF_STATUS target_if_wifi_pos_get_indirect_data( struct wifi_pos_psoc_priv_obj *priv_obj, - wmi_oem_indirect_data *indirect, + struct wmi_host_oem_indirect_data *indirect, struct oem_data_rsp *rsp, uint32_t *cookie) { return QDF_STATUS_SUCCESS; @@ -162,14 +164,15 @@ static int target_if_wifi_pos_oem_rsp_ev_handler(ol_scn_t scn, uint8_t ring_idx = 0; QDF_STATUS status; uint32_t cookie = 0; - wmi_oem_indirect_data *indirect; + struct wmi_host_oem_indirect_data *indirect; struct oem_data_rsp oem_rsp = {0}; struct wifi_pos_psoc_priv_obj *priv_obj; - struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc(); - struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops = NULL; - WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf = - (WMI_OEM_RESPONSE_EVENTID_param_tlvs *)data_buf; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops; + struct wmi_oem_response_param oem_resp_param = {0}; + wmi_unified_t wmi_handle; + psoc = target_if_get_psoc_from_scn_hdl(scn); if (!psoc) { target_if_err("psoc is null"); return QDF_STATUS_NOT_INITIALIZED; @@ -177,6 +180,13 @@ static int target_if_wifi_pos_oem_rsp_ev_handler(ol_scn_t scn, wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("wmi_handle is null"); + wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); + return QDF_STATUS_NOT_INITIALIZED; + } + priv_obj = wifi_pos_get_psoc_priv_obj(psoc); if (!priv_obj) { target_if_err("priv_obj is null"); @@ -191,15 +201,19 @@ static int target_if_wifi_pos_oem_rsp_ev_handler(ol_scn_t scn, return QDF_STATUS_NOT_INITIALIZED; } - oem_rsp.rsp_len_1 = param_buf->num_data; - oem_rsp.data_1 = param_buf->data; + ret = wmi_extract_oem_response_param(wmi_handle, + data_buf, + &oem_resp_param); + + oem_rsp.rsp_len_1 = oem_resp_param.num_data1; + oem_rsp.data_1 = oem_resp_param.data_1; - if (param_buf->num_data2) { - oem_rsp.rsp_len_2 = param_buf->num_data2; - oem_rsp.data_2 = param_buf->data2; + if (oem_resp_param.num_data2) { + oem_rsp.rsp_len_2 = oem_resp_param.num_data2; + oem_rsp.data_2 = oem_resp_param.data_2; } - indirect = (wmi_oem_indirect_data *)param_buf->indirect_data; + indirect = &oem_resp_param.indirect_data; status = target_if_wifi_pos_get_indirect_data(priv_obj, indirect, &oem_rsp, &cookie); if (QDF_IS_STATUS_ERROR(status)) { @@ -270,17 +284,18 @@ static int wifi_pos_oem_err_rpt_ev_handler(ol_scn_t scn, uint8_t *buf, } /** - * wifi_pos_oem_data_req() - start OEM data request to target - * @psoc: the pointer to psoc object manager + * target_if_wifi_pos_oem_data_req() - start OEM data request to target + * @psoc: pointer to psoc object mgr * @req: start request params * * Return: QDF_STATUS */ -static QDF_STATUS wifi_pos_oem_data_req(struct wlan_objmgr_psoc *psoc, - struct oem_data_req *req) +static QDF_STATUS +target_if_wifi_pos_oem_data_req(struct wlan_objmgr_pdev *pdev, + struct oem_data_req *req) { QDF_STATUS status; - void *wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); + wmi_unified_t wmi_hdl = get_wmi_unified_hdl_from_pdev(pdev); target_if_debug("Send oem data req to target"); @@ -307,25 +322,14 @@ void target_if_wifi_pos_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) { struct wlan_lmac_if_wifi_pos_tx_ops *wifi_pos_tx_ops; wifi_pos_tx_ops = &tx_ops->wifi_pos_tx_ops; - wifi_pos_tx_ops->data_req_tx = wifi_pos_oem_data_req; -} - -void target_if_wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) -{ - struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops; - wifi_pos_rx_ops = &rx_ops->wifi_pos_rx_ops; - wifi_pos_rx_ops->oem_rsp_event_rx = wifi_pos_oem_rsp_handler; -} - -inline struct wlan_lmac_if_wifi_pos_tx_ops *target_if_wifi_pos_get_txops( - struct wlan_objmgr_psoc *psoc) -{ - if (!psoc) { - target_if_err("passed psoc is NULL"); - return NULL; - } + wifi_pos_tx_ops->data_req_tx = target_if_wifi_pos_oem_data_req; + wifi_pos_tx_ops->wifi_pos_register_events = + target_if_wifi_pos_register_events; + wifi_pos_tx_ops->wifi_pos_deregister_events = + target_if_wifi_pos_deregister_events; + wifi_pos_tx_ops->wifi_pos_get_vht_ch_width = + target_if_wifi_pos_get_vht_ch_width; - return &psoc->soc_cb.tx_ops.wifi_pos_tx_ops; } inline struct wlan_lmac_if_wifi_pos_rx_ops *target_if_wifi_pos_get_rxops( @@ -348,15 +352,14 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc) return QDF_STATUS_E_INVAL; } - ret = wmi_unified_register_event_handler( + /* wmi_oem_response_event_id is not defined for legacy targets. + * So do not check for error for this event. + */ + wmi_unified_register_event_handler( get_wmi_unified_hdl_from_psoc(psoc), wmi_oem_response_event_id, target_if_wifi_pos_oem_rsp_ev_handler, WMI_RX_WORK_CTX); - if (ret) { - target_if_err("register_event_handler failed: err %d", ret); - return QDF_STATUS_E_INVAL; - } ret = wmi_unified_register_event_handler( get_wmi_unified_hdl_from_psoc(psoc), @@ -414,6 +417,33 @@ QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc) return QDF_STATUS_SUCCESS; } +QDF_STATUS target_if_wifi_pos_get_vht_ch_width(struct wlan_objmgr_psoc *psoc, + enum phy_ch_width *ch_width) +{ + struct target_psoc_info *tgt_hdl; + int vht_cap_info; + + *ch_width = CH_WIDTH_INVALID; + + if (!psoc) + return QDF_STATUS_E_INVAL; + + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); + if (!tgt_hdl) + return QDF_STATUS_E_INVAL; + + *ch_width = CH_WIDTH_80MHZ; + + vht_cap_info = target_if_get_vht_cap_info(tgt_hdl); + + if (vht_cap_info & WLAN_VHTCAP_SUP_CHAN_WIDTH_80_160) + *ch_width = CH_WIDTH_80P80MHZ; + else if (vht_cap_info & WLAN_VHTCAP_SUP_CHAN_WIDTH_160) + *ch_width = CH_WIDTH_160MHZ; + + return QDF_STATUS_SUCCESS; +} + #ifdef WLAN_FEATURE_CIF_CFR static QDF_STATUS target_if_wifi_pos_fill_ring(uint8_t ring_idx, struct hal_srng *srng, @@ -575,7 +605,7 @@ static QDF_STATUS target_if_wifi_pos_cfg_fw(struct wlan_objmgr_psoc *psoc, { uint8_t i; QDF_STATUS status; - void *wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); + wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc); wmi_oem_dma_ring_cfg_req_fixed_param cfg = {0}; if (!wmi_hdl) { diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cfr/core/inc/cfr_defs_i.h b/drivers/staging/qca-wifi-host-cmn/umac/cfr/core/inc/cfr_defs_i.h new file mode 100644 index 0000000000000000000000000000000000000000..196071670a69c74dfc4b9648b1eec6c57d92fae4 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/cfr/core/inc/cfr_defs_i.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _CFR_DEFS_I_H_ +#define _CFR_DEFS_I_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CFR_STOP_STR "CFR-CAPTURE-STOPPED" + +/** + * wlan_cfr_psoc_obj_create_handler() - psoc object create handler for cfr + * @psoc - pointer to psoc object + * @args - void pointer in case it needs arguments + * + * Return: status of object creation + */ +QDF_STATUS +wlan_cfr_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg); + +/** + * wlan_cfr_psoc_obj_destroy_handler() - psoc object destroy handler for cfr + * @psoc - pointer to psoc object + * @args - void pointer in case it needs arguments + * + * Return: status of destroy object + */ +QDF_STATUS +wlan_cfr_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc, void *arg); + +/** + * wlan_cfr_pdev_obj_create_handler() - pdev object create handler for cfr + * @pdev - pointer to pdev object + * @args - void pointer in case it needs arguments + * + * Return: status of object creation + */ +QDF_STATUS +wlan_cfr_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg); + +/** + * wlan_cfr_pdev_obj_destroy_handler() - pdev object destroy handler for cfr + * @pdev - pointer to pdev object + * @args - void pointer in case it needs arguments + * + * Return: status of destroy object + */ +QDF_STATUS +wlan_cfr_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, void *arg); + +/** + * wlan_cfr_peer_obj_create_handler() - peer object create handler for cfr + * @peer - pointer to peer object + * @args - void pointer in case it needs arguments + * + * Return: status of object creation + */ +QDF_STATUS +wlan_cfr_peer_obj_create_handler(struct wlan_objmgr_peer *peer, void *arg); + +/** + * wlan_cfr_peer_obj_destroy_handler() - peer object destroy handler for cfr + * @peer - pointer to peer object + * @args - void pointer in case it needs arguments + * + * Return: status ofi destry object + */ +QDF_STATUS +wlan_cfr_peer_obj_destroy_handler(struct wlan_objmgr_peer *peer, void *arg); + +/** + * cfr_streamfs_init() - stream filesystem init + * @pdev - pointer to pdev object + * + * Return: status of fs init + */ +QDF_STATUS +cfr_streamfs_init(struct wlan_objmgr_pdev *pdev); + +/** + * cfr_streamfs_remove() - stream filesystem remove + * @pdev - pointer to pdev object + * + * Return: status of fs remove + */ +QDF_STATUS +cfr_streamfs_remove(struct wlan_objmgr_pdev *pdev); + +/** + * cfr_streamfs_write() - write to stream filesystem + * @pa - pointer to pdev_cfr object + * @write_data - Pointer to data + * @write_len - data len + * + * Return: status of fs write + */ +QDF_STATUS +cfr_streamfs_write(struct pdev_cfr *pa, const void *write_data, + size_t write_len); + +/** + * cfr_streamfs_flush() - flush the write to streamfs + * @pa - pointer to pdev_cfr object + * + * Return: status of fs flush + */ +QDF_STATUS +cfr_streamfs_flush(struct pdev_cfr *pa); + +/** + * cfr_stop_indication() - write cfr stop string + * @vdev - pointer to vdev object + * + * Write stop string and indicate to up layer. + * + * Return: status of write CFR stop string + */ +QDF_STATUS cfr_stop_indication(struct wlan_objmgr_vdev *vdev); + +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cfr/core/src/cfr_common.c b/drivers/staging/qca-wifi-host-cmn/umac/cfr/core/src/cfr_common.c new file mode 100644 index 0000000000000000000000000000000000000000..58a614b0a06f8c33a72f14f17d4e0e0aeef29530 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/cfr/core/src/cfr_common.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef CFR_USE_FIXED_FOLDER +#include +#endif + +/** + * wlan_cfr_get_dbr_num_entries() - Get entry number of DBR ring + * @pdev - the physical device object. + * + * Return : Entry number of DBR ring. + */ +static uint32_t +wlan_cfr_get_dbr_num_entries(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_psoc_host_dbr_ring_caps *dbr_ring_cap; + uint8_t num_dbr_ring_caps, cap_idx, pdev_id; + struct target_psoc_info *tgt_psoc_info; + uint32_t num_entries = MAX_LUT_ENTRIES; + + if (!pdev) { + cfr_err("Invalid pdev"); + return num_entries; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + cfr_err("psoc is null"); + return num_entries; + } + + tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); + if (!tgt_psoc_info) { + cfr_err("target_psoc_info is null"); + return num_entries; + } + + num_dbr_ring_caps = target_psoc_get_num_dbr_ring_caps(tgt_psoc_info); + dbr_ring_cap = target_psoc_get_dbr_ring_caps(tgt_psoc_info); + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) { + if (dbr_ring_cap[cap_idx].pdev_id == pdev_id && + dbr_ring_cap[cap_idx].mod_id == DBR_MODULE_CFR) + num_entries = dbr_ring_cap[cap_idx].ring_elems_min; + } + + num_entries = QDF_MIN(num_entries, MAX_LUT_ENTRIES); + cfr_debug("pdev id %d, num_entries %d", pdev_id, num_entries); + + return num_entries; +} + +QDF_STATUS +wlan_cfr_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg) +{ + struct psoc_cfr *cfr_sc = NULL; + + cfr_sc = (struct psoc_cfr *)qdf_mem_malloc(sizeof(struct psoc_cfr)); + if (!cfr_sc) { + cfr_err("Failed to allocate cfr_ctx object\n"); + return QDF_STATUS_E_NOMEM; + } + + cfr_sc->psoc_obj = psoc; + + wlan_objmgr_psoc_component_obj_attach(psoc, WLAN_UMAC_COMP_CFR, + (void *)cfr_sc, + QDF_STATUS_SUCCESS); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_cfr_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc, void *arg) +{ + struct psoc_cfr *cfr_sc = NULL; + + cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_CFR); + if (cfr_sc) { + wlan_objmgr_psoc_component_obj_detach(psoc, WLAN_UMAC_COMP_CFR, + (void *)cfr_sc); + qdf_mem_free(cfr_sc); + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_cfr_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg) +{ + struct pdev_cfr *pa = NULL; + uint32_t idx; + + if (!pdev) { + cfr_err("PDEV is NULL\n"); + return QDF_STATUS_E_FAILURE; + } + + pa = (struct pdev_cfr *)qdf_mem_malloc(sizeof(struct pdev_cfr)); + if (!pa) { + cfr_err("Failed to allocate pdev_cfr object\n"); + return QDF_STATUS_E_NOMEM; + } + pa->pdev_obj = pdev; + pa->lut_num = wlan_cfr_get_dbr_num_entries(pdev); + if (!pa->lut_num) { + cfr_err("lut num is 0"); + return QDF_STATUS_E_INVAL; + } + pa->lut = (struct look_up_table **)qdf_mem_malloc(pa->lut_num * + sizeof(struct look_up_table *)); + if (!pa->lut) { + cfr_err("Failed to allocate lut, lut num %d", pa->lut_num); + qdf_mem_free(pa); + return QDF_STATUS_E_NOMEM; + } + for (idx = 0; idx < pa->lut_num; idx++) + pa->lut[idx] = (struct look_up_table *)qdf_mem_malloc( + sizeof(struct look_up_table)); + + wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_UMAC_COMP_CFR, + (void *)pa, QDF_STATUS_SUCCESS); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_cfr_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, void *arg) +{ + struct pdev_cfr *pa = NULL; + uint32_t idx; + + if (!pdev) { + cfr_err("PDEV is NULL\n"); + return QDF_STATUS_E_FAILURE; + } + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (pa) { + wlan_objmgr_pdev_component_obj_detach(pdev, WLAN_UMAC_COMP_CFR, + (void *)pa); + if (pa->lut) { + for (idx = 0; idx < pa->lut_num; idx++) + qdf_mem_free(pa->lut[idx]); + qdf_mem_free(pa->lut); + } + qdf_mem_free(pa); + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_cfr_peer_obj_create_handler(struct wlan_objmgr_peer *peer, void *arg) +{ + struct peer_cfr *pe = NULL; + + if (!peer) { + cfr_err("PEER is NULL\n"); + return QDF_STATUS_E_FAILURE; + } + + pe = (struct peer_cfr *)qdf_mem_malloc(sizeof(struct peer_cfr)); + if (!pe) { + cfr_err("Failed to allocate peer_cfr object\n"); + return QDF_STATUS_E_FAILURE; + } + + pe->peer_obj = peer; + + /* Remaining will be populated when we give CFR capture command */ + wlan_objmgr_peer_component_obj_attach(peer, WLAN_UMAC_COMP_CFR, + (void *)pe, QDF_STATUS_SUCCESS); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_cfr_peer_obj_destroy_handler(struct wlan_objmgr_peer *peer, void *arg) +{ + struct peer_cfr *pe = NULL; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_pdev *pdev = NULL; + struct pdev_cfr *pa = NULL; + + if (!peer) { + cfr_err("PEER is NULL\n"); + return QDF_STATUS_E_FAILURE; + } + + vdev = wlan_peer_get_vdev(peer); + if (vdev) + pdev = wlan_vdev_get_pdev(vdev); + + if (pdev) + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_CFR); + + pe = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_CFR); + + if (pa && pe) { + if (pe->period && pe->request) + pa->cfr_current_sta_count--; + } + + if (pe) { + wlan_objmgr_peer_component_obj_detach(peer, WLAN_UMAC_COMP_CFR, + (void *)pe); + qdf_mem_free(pe); + } + + return QDF_STATUS_SUCCESS; +} + +#ifdef CFR_USE_FIXED_FOLDER +static const char *cfr_get_dev_name(struct wlan_objmgr_pdev *pdev) +{ + const char *default_name = "wlan"; + + return default_name; +} +#else +static const char *cfr_get_dev_name(struct wlan_objmgr_pdev *pdev) +{ + struct pdev_cfr *pa = NULL; + char folder[32]; + struct net_device *pdev_netdev; + struct ol_ath_softc_net80211 *scn; + struct target_pdev_info *tgt_hdl; + const char *default_name = "wlan"; + + if (!pdev) { + cfr_err("PDEV is NULL\n"); + return default_name; + } + + tgt_hdl = wlan_pdev_get_tgt_if_handle(pdev); + + if (!tgt_hdl) { + cfr_err("target_pdev_info is NULL\n"); + return default_name; + } + + scn = target_pdev_get_feature_ptr(tgt_hdl); + pdev_netdev = scn->netdev; + + return pdev_netdev->name; +} +#endif + +QDF_STATUS cfr_streamfs_init(struct wlan_objmgr_pdev *pdev) +{ + struct pdev_cfr *pa = NULL; + char folder[32]; + + if (!pdev) { + cfr_err("PDEV is NULL\n"); + return QDF_STATUS_E_FAILURE; + } + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + + if (pa == NULL) { + cfr_err("pdev_cfr is NULL\n"); + return QDF_STATUS_E_FAILURE; + } + + if (!pa->is_cfr_capable) { + cfr_err("CFR IS NOT SUPPORTED\n"); + return QDF_STATUS_E_FAILURE; + } + + snprintf(folder, sizeof(folder), "cfr%s", cfr_get_dev_name(pdev)); + + pa->dir_ptr = qdf_streamfs_create_dir((const char *)folder, NULL); + + if (!pa->dir_ptr) { + cfr_err("Directory create failed"); + return QDF_STATUS_E_FAILURE; + } + + pa->chan_ptr = qdf_streamfs_open("cfr_dump", pa->dir_ptr, + pa->subbuf_size, + pa->num_subbufs, NULL); + + if (!pa->chan_ptr) { + cfr_err("Chan create failed"); + qdf_streamfs_remove_dir_recursive(pa->dir_ptr); + pa->dir_ptr = NULL; + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS cfr_streamfs_remove(struct wlan_objmgr_pdev *pdev) +{ + struct pdev_cfr *pa = NULL; + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (pa) { + if (pa->chan_ptr) { + qdf_streamfs_close(pa->chan_ptr); + pa->chan_ptr = NULL; + } + + if (pa->dir_ptr) { + qdf_streamfs_remove_dir_recursive(pa->dir_ptr); + pa->dir_ptr = NULL; + } + + } else + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS cfr_streamfs_write(struct pdev_cfr *pa, const void *write_data, + size_t write_len) +{ + if (pa->chan_ptr) { + + /* write to channel buffer */ + qdf_streamfs_write(pa->chan_ptr, (const void *)write_data, + write_len); + } else + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS cfr_streamfs_flush(struct pdev_cfr *pa) +{ + if (pa->chan_ptr) { + + /* Flush the data write to channel buffer */ + qdf_streamfs_flush(pa->chan_ptr); + } else + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS cfr_stop_indication(struct wlan_objmgr_vdev *vdev) +{ + struct pdev_cfr *pa; + uint32_t status; + struct wlan_objmgr_pdev *pdev; + + pdev = wlan_vdev_get_pdev(vdev); + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (!pa) { + cfr_err("pdev_cfr is NULL\n"); + return QDF_STATUS_E_INVAL; + } + + status = cfr_streamfs_write(pa, (const void *)CFR_STOP_STR, + sizeof(CFR_STOP_STR)); + + status = cfr_streamfs_flush(pa); + cfr_debug("stop indication done"); + + return status; +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/cfr_cfg.h b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/cfr_cfg.h new file mode 100644 index 0000000000000000000000000000000000000000..f7e3417a0a4a7c6160a3aa168e39121bf18ef2d5 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/cfr_cfg.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: This file contains centralized cfg definitions of CFR component + */ +#ifndef __CFR_CONFIG_H +#define __CFR_CONFIG_H + +/* + * + * cfr_disable - disable channel frequence response(CFR) feature + * @Min: 0 + * @Max: 1 + * @Default: 0 + * + * This ini is used to disable cfr feature. + * + * Related: None + * + * Supported Feature: cfr + * + * Usage: External + * + * + */ +#define CFG_CFR_DISABLE \ + CFG_INI_BOOL("cfr_disable", false, \ + "CFR disable") + +#define CFG_CFR_ALL \ + CFG(CFG_CFR_DISABLE) + +#endif /* __CFR_CONFIG_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_public_structs.h b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_public_structs.h new file mode 100644 index 0000000000000000000000000000000000000000..60803097a4ccfc1677240b34e20ddb9c25f21e9e --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_public_structs.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: declare the data structure to hold CFR specific configurations + */ +#ifndef _WLAN_CFR_PUBLIC_STRUCTS_H_ +#define _WLAN_CFR_PUBLIC_STRUCTS_H_ + +#ifdef WLAN_CFR_ENABLE +#include "qdf_types.h" + +/** + * cfr_cwm_width : Capture bandwidth + * 0 : 20MHz, 1 : 40MHz, 2 : 80MHz, 3 : 160MHz, 4 : 80+80MHz + */ +enum cfr_cwm_width { + CFR_CWM_WIDTH20, + CFR_CWM_WIDTH40, + CFR_CWM_WIDTH80, + CFR_CWM_WIDTH160, + CFR_CWM_WIDTH80_80, + + CFR_CWM_WIDTH_MAX, + CFR_CWM_WIDTHINVALID = 0xff +}; + +/** + * cfr_capture_method : Tx based CFR capture method + * @CFR_CAPTURE_METHOD_QOS_NULL : Send QOS Null frame and capture CFR on ACK + * @CFR_CAPTURE_METHOD_QOS_NULL_WITH_PHASE: Send QoS Null frame with phase + * @CFR_CAPTURE_METHOD_PROBE_RESPONSE : Capture is enabled on probe response + * If node is not found, trigger unassociated capture. + */ +enum cfr_capture_method { + CFR_CAPTURE_METHOD_QOS_NULL = 0, + CFR_CAPTURE_METHOD_QOS_NULL_WITH_PHASE = 1, + CFR_CAPTURE_METHOD_PROBE_RESPONSE = 2, + CFR_CAPTURE_METHOD_LAST_VALID, + CFR_CAPTURE_METHOD_AUTO = 0xff, + CFR_CAPTURE_METHOD_MAX, +}; + +/** + * cfr_wlanconfig_param : CFR params used to store user provided inputs + * @bandwidth : CFR capture bandwidth + * @periodicity : CFR capture periodicity in milli seconds + * @capture_method : CFR capture method + * @mac : peer mac address + * @ta : Tx address + * @ra : Rx Address + * @ta_mask: Tx address mask + * @ra_mask; Rx address mask + * *** Controls for different capture modes in RCC *** + * @en_directed_ftm: Enable capture for directed RTT FTM Packet + * @en_directed_ndpa_ndp: Enable NDPA filter followed by directed NDP capture + * @en_ta_ra_filter: Enable MAC TA/RA/type filtering channel capture + * @en_all_ftm_ack: Enable all FTM and ACK capture + * @en_ndpa_ndp_all: Enable NDPA filter followed by NDP capture, + * capture includes both directed and non-directed packets. + * @en_all_pkt: Enable capture mode to filter in all packets + * @dis_directed_ftm: Drop directed RTT FTM packets + * @dis_directed_ndpa_ndp: Drop directed NDPA and NDP packets + * @dis_ta_ra_filter: Disable MAC TA/RA/type filtering channel capture + * @dis_all_ftm_ack: Drop all FTM and ACK capture + * @dis_ndpa_ndp_all: Drop all NDPA and NDP packets + * @dis_all_pkt: Do not filter in any packet + * + * **** Fixed parameters **** + * @cap_dur: Capture duration + * @cap_intvl: Capture interval + * FW may limit the interval and duration during which HW may attempt + * to capture by programming the user provided values. + * These values(cap_dur, cap_intvl) range from 1 us to roughly 16.8 in 1 us + * units. Max value is 0xFFFFFF, i.e., 16.777215 s + * @bw: Bandwidth: 20, 40, 80, 160, 320MHz + * @nss: 8 bits are allotted for NSS mask. Specifies which numbers of + * spatial streams (MIMO factor) are permitted + * @grp_id: Group id could of any value between 0 and 15 + * @expected_mgmt_subtype/ expected_ctrl_subtype / expected_data_subtype: + * corresponds to mgmt/ ctrl/ data, all are bitmasks, in which each bit + * represents the corresponding type/ subtype value as per IEEE80211. + * + * @en_cfg and reset_cfg: This bitmap of 16 bits, indicates 16 groups. + * Valid entry should be in between 0 to 0xFFFF. + * Turning on a bit in en_cfg will enable MAC TA_RA filter + * for corresponding group; whereas turning on a bit in reset_cfg + * will reset all 9 params in the corresponding group to default values. + * + * @ul_mu_user_mask_lower, ul_mu_user_mask_upper : + * Since Cypress supports max bandwidth of 80Mhz, maximum number + * of users in a UL MU-MIMO transmission would be 37. + * mask_lower_32: Bits from 31 to 0 indicate user indices for 32 users. + * mask_upper_32: Bits from 0 to 4 indicate user indices from 33 to 37. + * + * @ freeze_tlv_delay_cnt_en, freeze_tlv_delay_cnt_thr : + * freeze_tlv_delay_cnt_thr will decide the threshold for MAC to drop the + * freeze TLV. freeze_tlv_delay_cnt_thr will only be applicable if + * freeze_tlv_delay_cnt_en is enabled. + */ +struct cfr_wlanconfig_param { + enum cfr_cwm_width bandwidth; + uint32_t periodicity; + enum cfr_capture_method capture_method; + uint8_t mac[QDF_MAC_ADDR_SIZE]; +#ifdef WLAN_ENH_CFR_ENABLE + uint8_t ta[QDF_MAC_ADDR_SIZE]; + uint8_t ra[QDF_MAC_ADDR_SIZE]; + uint8_t ta_mask[QDF_MAC_ADDR_SIZE]; + uint8_t ra_mask[QDF_MAC_ADDR_SIZE]; + uint16_t en_directed_ftm :1, + en_directed_ndpa_ndp :1, + en_ta_ra_filter :1, + en_all_ftm_ack :1, + en_ndpa_ndp_all :1, + en_all_pkt :1, + dis_directed_ftm :1, + dis_directed_ndpa_ndp :1, + dis_ta_ra_filter :1, + dis_all_ftm_ack :1, + dis_ndpa_ndp_all :1, + dis_all_pkt :1, + rsvd0 :4; + + uint32_t cap_dur :24, + rsvd1 :8; + uint32_t cap_intvl :24, + rsvd2 :8; + uint32_t bw :5, + nss :8, + grp_id :4, + rsvd3 :15; + + uint32_t expected_mgmt_subtype :16, + expected_ctrl_subtype :16; + + uint32_t expected_data_subtype :16, + rsvd5 :16; + + uint32_t en_cfg :16, + reset_cfg :16; + + uint32_t ul_mu_user_mask_lower; + uint32_t ul_mu_user_mask_upper; + + uint32_t freeze_tlv_delay_cnt_en :1, + freeze_tlv_delay_cnt_thr :8, + rsvd6 :23; +#endif +}; + +#endif /* WLAN_CFR_ENABLE */ +#endif /* _WLAN_CFR_PUBLIC_STRUCTS_H_ */ + diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_tgt_api.h b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_tgt_api.h new file mode 100644 index 0000000000000000000000000000000000000000..907524ba49b79b8a4f58eac66f72ea495072866a --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_tgt_api.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _WLAN_CFR_TGT_API_H_ +#define _WLAN_CFR_TGT_API_H_ + +#include +#include +#include +#include + +/* tgt layer has APIs in application, to access functions in target + * through tx_ops. + */ + +/** + * tgt_cfr_init_pdev() - API that registers CFR to handlers. + * @pdev: pointer to pdev_object + * + * Return: success/failure of init + */ +int tgt_cfr_init_pdev(struct wlan_objmgr_pdev *pdev); + +/** + * tgt_cfr_deinit_pdev() - API that de-registers CFR to handlers. + * @pdev: pointer to pdev_object + * + * Return: success/failure of de-init + */ +int tgt_cfr_deinit_pdev(struct wlan_objmgr_pdev *pdev); + +/** + * tgt_cfr_get_target_type() - API to determine target type. + * @psoc: pointer to psoc_object + * + * Return: enum value of target type + */ +int tgt_cfr_get_target_type(struct wlan_objmgr_psoc *psoc); + +/** + * tgt_cfr_start_capture() - API to start cfr capture on a peer. + * @pdev: pointer to pdev_object + * @peer: pointer to peer_object + * @cfr_params: pointer to config cfr_params + * + * Return: success/failure of start capture + */ +int tgt_cfr_start_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer, + struct cfr_capture_params *cfr_params); + +/** + * tgt_cfr_stop_capture() - API to stop cfr capture on a peer. + * @pdev: pointer to pdev_object + * @peer: pointer to peer_object + * + * Return: success/failure of stop capture + */ +int tgt_cfr_stop_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer); + +/** + * tgt_cfr_enable_cfr_timer() - API to enable cfr timer + * @pdev: pointer to pdev_object + * @cfr_timer: Amount of time this timer has to run. If 0, it disables timer. + * + * Return: success/failure of timer enable + */ +int +tgt_cfr_enable_cfr_timer(struct wlan_objmgr_pdev *pdev, uint32_t cfr_timer); + +/** + * tgt_cfr_support_set() - API to set cfr support + * @psoc: pointer to psoc_object + * @value: value to be set + */ +void tgt_cfr_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value); + +/** + * tgt_cfr_info_send() - API to send cfr info + * @pdev: pointer to pdev_object + * @head: pointer to cfr info head + * @hlen: head len + * @data: pointer to cfr info data + * @dlen: data len + * @tail: pointer to cfr info tail + * @tlen: tail len + * + * Return: success/failure of cfr info send + */ +uint32_t tgt_cfr_info_send(struct wlan_objmgr_pdev *pdev, void *head, + size_t hlen, void *data, size_t dlen, void *tail, + size_t tlen); + +#ifdef WLAN_ENH_CFR_ENABLE +/** + * tgt_cfr_config_rcc() - API to set RCC + * @pdev: pointer to pdev_object + * @rcc_param: rcc configurations + * + * Return: succcess / failure + */ +QDF_STATUS tgt_cfr_config_rcc(struct wlan_objmgr_pdev *pdev, + struct cfr_rcc_param *rcc_param); + +/** + * tgt_cfr_start_lut_age_timer() - API to start timer to flush aged out LUT + * entries + * @pdev: pointer to pdev_object + * + * Return: None + */ +void tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev); + +/** + * tgt_cfr_stop_lut_age_timer() - API to stop timer to flush aged out LUT + * entries + * @pdev: pointer to pdev_object + * + * Return: None + */ +void tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev); + +/** + * tgt_cfr_default_ta_ra_cfg() - API to configure default values in TA_RA mode + * entries + * @pdev: pointer to pdev_object + * + * Return: none + */ +void tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev *pdev, + struct cfr_rcc_param *rcc_param, + bool allvalid, uint16_t reset_cfg); + +/** + * tgt_cfr_dump_lut_enh() - Print all LUT entries + * @pdev: pointer to pdev_object + */ +void tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev); + +/** + * tgt_cfr_rx_tlv_process() - Process PPDU status TLVs + * @pdev_obj: pointer to pdev_object + * @nbuf: pointer to cdp_rx_indication_ppdu + */ +void tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf); + +/** + * tgt_cfr_update_global_cfg() - Update global config after successful commit + * @pdev: pointer to pdev_object + */ +void tgt_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev); + +/** + * tgt_cfr_subscribe_ppdu_desc() - Target interface to + * subscribe/unsubscribe WDI PPDU desc event + * @pdev: pointer to pdev_object + * @is_subscribe: subscribe or unsubscribei + * + * return QDF status + */ +QDF_STATUS tgt_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev, + bool is_subscribe); +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_ucfg_api.h b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_ucfg_api.h new file mode 100644 index 0000000000000000000000000000000000000000..50f2889da0d50e0efe8cfaaea511dc35999c6010 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_ucfg_api.h @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _WLAN_CFR_UCFG_API_H_ +#define _WLAN_CFR_UCFG_API_H_ + +#include +#include +#include + +#define MAX_CFR_PRD (10*60*1000) /* 10 minutes */ + +/** + * ucfg_cfr_start_capture() - function to start cfr capture for connected client + * @pdev: pointer to pdev object + * @peer: pointer to peer object + * @cfr_params: config params to cfr capture + * + * Return: status of start capture. + */ +int ucfg_cfr_start_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer, + struct cfr_capture_params *cfr_params); + +/** + * ucfg_cfr_stop_capture() - function to stop cfr capture for connected client + * @pdev: pointer to pdev object + * @peer: pointer to peer object + * + * Return: status of stop capture. + */ +int ucfg_cfr_stop_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer); + +/** + * ucfg_cfr_start_capture_probe_req() - function to start cfr capture for + * unassociated clients + * @pdev: pointer to pdev object + * @unassoc_mac: mac address of un-associated client + * @cfr_params: config params to cfr capture + * + * Return: status of start capture. + */ +int ucfg_cfr_start_capture_probe_req(struct wlan_objmgr_pdev *pdev, + struct qdf_mac_addr *unassoc_mac, + struct cfr_capture_params *params); + +/** + * ucfg_cfr_stop_capture_probe_req() - function to stop cfr capture for + * unassociated cleints + * @pdev: pointer to pdev object + * @unassoc_mac: mac address of un-associated client + * + * Return: status of stop capture. + */ +int ucfg_cfr_stop_capture_probe_req(struct wlan_objmgr_pdev *pdev, + struct qdf_mac_addr *unassoc_mac); + +/** + * ucfg_cfr_list_peers() - Lists total number of peers with cfr capture enabled + * @pdev: pointer to pdev object + * + * Return: number of peers with cfr capture enabled + */ +int ucfg_cfr_list_peers(struct wlan_objmgr_pdev *pdev); + +/** + * ucfg_cfr_set_timer() - function to enable cfr timer + * @pdev: pointer to pdev object + * @value: value to be set + * + * Return: status of timer enable + */ +int ucfg_cfr_set_timer(struct wlan_objmgr_pdev *pdev, uint32_t value); + +/** + * ucfg_cfr_get_timer() - function to get cfr_timer_enable + * @pdev: pointer to pdev object + * + * Return: value of cfr_timer_enable + */ +int ucfg_cfr_get_timer(struct wlan_objmgr_pdev *pdev); + +/** + * ucfg_cfr_stop_indication() - User space API to write cfr stop string + * @vdev - pointer to vdev object + * + * Write stop string and indicate to up layer. + * + * Return: status of write CFR stop string + */ +QDF_STATUS ucfg_cfr_stop_indication(struct wlan_objmgr_vdev *vdev); + +#ifdef WLAN_ENH_CFR_ENABLE +/* Channel capture recipe filters */ +enum capture_type { + RCC_DIRECTED_FTM_FILTER, + RCC_ALL_FTM_ACK_FILTER, + RCC_DIRECTED_NDPA_NDP_FILTER, + RCC_NDPA_NDP_ALL_FILTER, + RCC_TA_RA_FILTER, + RCC_ALL_PACKET_FILTER, + RCC_DIS_ALL_MODE, +}; + +/** + * ucfg_cfr_set_rcc_mode() - function to set RCC mode + * @vdev: pointer to vdev object + * @mode: capture type passed by user + * @value: Enable/Disable capture mode + * + * Return: status if the mode is set or not + */ +QDF_STATUS ucfg_cfr_set_rcc_mode(struct wlan_objmgr_vdev *vdev, + enum capture_type mode, uint8_t value); + +/** + * ucfg_cfr_get_rcc_enabled() - function to get RCC mode + * @vdev: pointer to vdev object + * + * Return: if the rcc is enabled or not + */ +bool ucfg_cfr_get_rcc_enabled(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_cfr_set_tara_config() - function to configure TA/RA address and mask + * @vdev: pointer to vdev object + * @params: user config + * + * Return: status + */ +QDF_STATUS ucfg_cfr_set_tara_config(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params); + +/** + * ucfg_cfr_set_bw_nss() - function to configure nss and bandwidth + * @vdev: pointer to vdev object + * @params: user config + * + * Return: status + */ +QDF_STATUS ucfg_cfr_set_bw_nss(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params); + +/** + * ucfg_cfr_set_frame_type_subtype() - function to configure frame type/subtype + * @vdev: pointer to vdev object + * @params: user config + * + * Return: status + */ +QDF_STATUS +ucfg_cfr_set_frame_type_subtype(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params); + +/** + * ucfg_cfr_set_capture_duration() - function to configure capture duration + * @vdev: pointer to vdev object + * @params: user config + * + * Return: status + */ +QDF_STATUS +ucfg_cfr_set_capture_duration(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params); + +/** + * ucfg_cfr_set_capture_interval() - function to configure capture interval + * @vdev: pointer to vdev object + * @params: user config + * + * Return: status + */ +QDF_STATUS +ucfg_cfr_set_capture_interval(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params); + +/** + * ucfg_cfr_set_en_bitmap() - function to configure 16-bit bitmap in TA_RA mode + * @vdev: pointer to vdev object + * @params: user config + * + * Return: status + */ +QDF_STATUS ucfg_cfr_set_en_bitmap(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params); + +/** + * ucfg_cfr_set_reset_bitmap() - function to clear all 9 params for all 16 + * groups in TA_RA mode + * @vdev: pointer to vdev object + * @params: user config + * + * Return: status + */ +QDF_STATUS ucfg_cfr_set_reset_bitmap(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params); + +/** + * ucfg_cfr_set_ul_mu_user_mask() - function to configure UL MU user mask + * @vdev: pointer to vdev object + * @params: user config + * + * Return: status + */ +QDF_STATUS +ucfg_cfr_set_ul_mu_user_mask(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params); + +/** + * ucfg_cfr_set_freeze_tlv_delay_cnt() - function to configure freeze TLV delay + * count threshold + * @vdev: pointer to vdev object + * @params: user config + * + * Return: status + */ +QDF_STATUS +ucfg_cfr_set_freeze_tlv_delay_cnt(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params); + +/** + * ucfg_cfr_committed_rcc_config() - function to commit user config + * @vdev: pointer to vdev object + * + * Return: status + */ +QDF_STATUS ucfg_cfr_committed_rcc_config(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_cfr_get_cfg() - function to display user config + * @vdev: pointer to vdev object + * + * Return: status + */ +QDF_STATUS ucfg_cfr_get_cfg(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_cfr_rcc_dump_dbg_counters() - function to display PPDU counters + * @vdev: pointer to vdev object + * + * Return: status + */ +QDF_STATUS ucfg_cfr_rcc_dump_dbg_counters(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_cfr_rcc_clr_dbg_counters() - function to clear CFR PPDU counters + * @vdev: pointer to vdev object + * + * Return: status + */ +QDF_STATUS ucfg_cfr_rcc_clr_dbg_counters(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_cfr_rcc_dump_lut() - function to display lookup table + * @vdev: pointer to vdev object + * + * Return: status + */ +QDF_STATUS ucfg_cfr_rcc_dump_lut(struct wlan_objmgr_vdev *vdev); + +/** + * ucfg_cfr_subscribe_ppdu_desc() - User space interface to + * subscribe/unsubscribe WDI PPDU desc event + * @pdev: pointer to pdev_object + * @is_subscribe: subscribe or unsubscribei + * + * return QDF status + */ +QDF_STATUS ucfg_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev, + bool is_subscribe); +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_utils_api.h b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_utils_api.h new file mode 100644 index 0000000000000000000000000000000000000000..24eaf26f710e5e76ee18053b052adb6cf67edf78 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/inc/wlan_cfr_utils_api.h @@ -0,0 +1,593 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _WLAN_CFR_UTILS_API_H_ +#define _WLAN_CFR_UTILS_API_H_ + +#include +#include +#ifdef WLAN_ENH_CFR_ENABLE +#include +#endif + +#define cfr_alert(format, args...) \ + QDF_TRACE_FATAL(QDF_MODULE_ID_CFR, format, ## args) + +#define cfr_err(format, args...) \ + QDF_TRACE_ERROR(QDF_MODULE_ID_CFR, format, ## args) + +#define cfr_warn(format, args...) \ + QDF_TRACE_WARN(QDF_MODULE_ID_CFR, format, ## args) + +#define cfr_info(format, args...) \ + QDF_TRACE_INFO(QDF_MODULE_ID_CFR, format, ## args) + +#define cfr_debug(format, args...) \ + QDF_TRACE_DEBUG(QDF_MODULE_ID_CFR, format, ## args) + +#define DBR_EVENT_TIMEOUT_IN_MS_CFR 1 +#define DBR_NUM_RESP_PER_EVENT_CFR 1 +#define MAX_CFR_ENABLED_CLIENTS 10 +#ifdef WLAN_ENH_CFR_ENABLE +#define MAX_CFR_MU_USERS 4 +#define NUM_CHAN_CAPTURE_STATUS 4 +#define NUM_CHAN_CAPTURE_REASON 6 +#define MAX_TA_RA_ENTRIES 16 +#define MAX_RESET_CFG_ENTRY 0xFFFF +#define CFR_INVALID_VDEV_ID 0xff +#endif + +enum cfrmetaversion { + CFR_META_VERSION_NONE, + CFR_META_VERSION_1, + CFR_META_VERSION_2, + CFR_META_VERSION_3, + CFR_META_VERSION_MAX = 0xFF, +}; + +enum cfrdataversion { + CFR_DATA_VERSION_NONE, + CFR_DATA_VERSION_1, + CFR_DATA_VERSION_MAX = 0xFF, +}; + +enum cfrplatformtype { + CFR_PLATFORM_TYPE_NONE, + CFR_PLATFORM_TYPE_MIPS, + CFR_PLATFORM_TYPE_ARM, + CFR_PLATFFORM_TYPE_MAX = 0xFF, +}; + +enum cfrradiotype { + CFR_CAPTURE_RADIO_NONE, + CFR_CAPTURE_RADIO_OSPREY, + CFR_CAPTURE_RADIO_PEAKCOCK, + CFR_CAPTURE_RADIO_SCORPION, + CFR_CAPTURE_RADIO_HONEYBEE, + CFR_CAPTURE_RADIO_DRAGONFLY, + CFR_CAPTURE_RADIO_JET, + CFR_CAPTURE_RADIO_PEREGRINE = 17, + CFR_CAPTURE_RADIO_SWIFT, + CFR_CAPTURE_RADIO_BEELINER, + CFR_CAPTURE_RADIO_CASCADE, + CFR_CAPTURE_RADIO_DAKOTA, + CFR_CAPTURE_RADIO_BESRA, + CFR_CAPTURE_RADIO_HKV2, + CFR_CAPTURE_RADIO_CYP, + CFR_CAPTURE_RADIO_HSP, + CFR_CAPTURE_RADIO_MAX = 0xFF, +}; + +enum ack_capture_mode { + CFR_LEGACY_ACK = 0, + CFR_DUP_LEGACY_ACK = 1, + CFR_HT_ACK = 2, + CFR_VHT_ACK = 3, + CFR_INVALID_ACK, /*Always keep this at last*/ +}; + +/* Similar to WMI_PEER_CFR_CAPTURE_METHOD used in one-shot capture */ +enum cfr_capture_type { + CFR_TYPE_METHOD_NULL_FRAME = 0, + CFR_TYPE_METHOD_NULL_FRAME_WITH_PHASE = 1, + CFR_TYPE_METHOD_PROBE_RESP = 2, + CFR_TYPE_METHOD_TM = 3, + CFR_TYPE_METHOD_FTM = 4, + CFR_TYPE_METHOD_ACK_RESP_TO_TM_FTM = 5, + CFR_TYPE_METHOD_TA_RA_TYPE_FILTER = 6, + CFR_TYPE_METHOD_NDPA_NDP = 7, + CFR_TYPE_METHOD_ALL_PACKET = 8, + /* Add new capture methods before this line */ + CFR_TYPE_METHOD_LAST_VALID, + CFR_TYPE_METHOD_AUTO = 0xff, + CFR_TYPE_METHOD_MAX, +}; + +struct cfr_metadata_version_1 { + u_int8_t peer_addr[QDF_MAC_ADDR_SIZE]; + u_int8_t status; + u_int8_t capture_bw; + u_int8_t channel_bw; + u_int8_t phy_mode; + u_int16_t prim20_chan; + u_int16_t center_freq1; + u_int16_t center_freq2; + u_int8_t capture_mode; + u_int8_t capture_type; + u_int8_t sts_count; + u_int8_t num_rx_chain; + u_int32_t timestamp; + u_int32_t length; +} __attribute__ ((__packed__)); + +#define HOST_MAX_CHAINS 8 + +struct cfr_metadata_version_2 { + u_int8_t peer_addr[QDF_MAC_ADDR_SIZE]; + u_int8_t status; + u_int8_t capture_bw; + u_int8_t channel_bw; + u_int8_t phy_mode; + u_int16_t prim20_chan; + u_int16_t center_freq1; + u_int16_t center_freq2; + u_int8_t capture_mode; + u_int8_t capture_type; + u_int8_t sts_count; + u_int8_t num_rx_chain; + u_int32_t timestamp; + u_int32_t length; + u_int32_t chain_rssi[HOST_MAX_CHAINS]; + u_int16_t chain_phase[HOST_MAX_CHAINS]; +} __attribute__ ((__packed__)); + +#ifdef WLAN_ENH_CFR_ENABLE +struct cfr_metadata_version_3 { + u_int8_t status; + u_int8_t capture_bw; + u_int8_t channel_bw; + u_int8_t phy_mode; + u_int16_t prim20_chan; + u_int16_t center_freq1; + u_int16_t center_freq2; + u_int8_t capture_mode; /* ack_capture_mode */ + u_int8_t capture_type; /* cfr_capture_type */ + u_int8_t sts_count; + u_int8_t num_rx_chain; + u_int64_t timestamp; + u_int32_t length; + u_int8_t is_mu_ppdu; + u_int8_t num_mu_users; + union { + u_int8_t su_peer_addr[QDF_MAC_ADDR_SIZE]; + u_int8_t mu_peer_addr[MAX_CFR_MU_USERS][QDF_MAC_ADDR_SIZE]; + } peer_addr; + u_int32_t chain_rssi[HOST_MAX_CHAINS]; + u_int16_t chain_phase[HOST_MAX_CHAINS]; +} __attribute__ ((__packed__)); +#endif + +struct csi_cfr_header { + u_int32_t start_magic_num; + u_int32_t vendorid; + u_int8_t cfr_metadata_version; + u_int8_t cfr_data_version; + u_int8_t chip_type; + u_int8_t pltform_type; + u_int32_t Reserved; + + union { + struct cfr_metadata_version_1 meta_v1; + struct cfr_metadata_version_2 meta_v2; +#ifdef WLAN_ENH_CFR_ENABLE + struct cfr_metadata_version_3 meta_v3; +#endif + } u; +} __attribute__ ((__packed__)); + +/** + * struct cfr_capture_params - structure to store cfr config param + * bandwidth: bandwitdh of capture + * period: period of capture + * method: enum of method being followed to capture cfr data. 0-QoS null data + */ +struct cfr_capture_params { + u_int8_t bandwidth; + u_int32_t period; + u_int8_t method; +}; + +/** + * struct psoc_cfr - private psoc object for cfr + * psoc_obj: pointer to psoc object + * is_cfr_capable: flag to determine if cfr is enabled or not + */ +struct psoc_cfr { + struct wlan_objmgr_psoc *psoc_obj; + uint8_t is_cfr_capable; +}; + +/** + * struct cfr_wmi_host_mem_chunk - wmi mem chunk related + * vaddr: pointer to virtual address + * paddr: physical address + * len: len of the mem chunk allocated + * req_id: reqid related to the mem chunk + */ +struct cfr_wmi_host_mem_chunk { + uint32_t *vaddr; + uint32_t paddr; + uint32_t len; + uint32_t req_id; +}; + +struct whal_cfir_dma_hdr { + uint16_t + // 'BA' + tag : 8, + // '02', length of header in 4 octet units + length : 6, + // 00 + reserved : 2; + uint16_t + // [16] + upload_done : 1, + // [17:18], 0: invalid, 1: CFR, 2: CIR, 3: DebugH + capture_type : 3, + // [19:20], 0: Legacy, 1: HT, 2: VHT, 3: HE + preamble_type : 2, + // [21:23], 0: 1-stream, 1: 2-stream, ..., 7: 8-stream + nss : 3, + // [24:27], 0: invalid, 1: 1-chain, 2: 2-chain, etc. + num_chains : 3, + // [28:30], 0: 20 MHz, 1: 40 MHz, 2: 80 MHz, 3: 160 MHz + upload_pkt_bw : 3, // [31] + sw_peer_id_valid : 1; + uint16_t + sw_peer_id : 16; // [15:0] + uint16_t + phy_ppdu_id : 16; // [15:0] +}; + +#define MAX_LUT_ENTRIES 140 /* For HKv2 136 is max */ + +/** + * struct look_up_table - Placeholder for 2 asynchronous events (DBR and + * TXRX event) + * dbr_recv: Indicates whether WMI for DBR completion is received or not + * tx_recv: Indicates whether WMI for TX completion (or) WDI event for RX + * status is received or not + * data: pointer to CFR data that ucode DMAs to host memory + * data_len: length of CFR data DMAed by ucode + * dbr_ppdu_id: PPDU id retrieved from DBR completion WMI event + * tx_ppdu_id: PPDU id retrieved from WMI TX completion event (or) PPDU status + * TLV + * dbr_address: Physical address of the CFR data dump retrieved from DBR + * completion WMI event + * tx_address1: Physical address of the CFR data from TX/RX event + * tx_address2: Physical address of the CFR data from TX/RX event + * csi_cfr_header: CFR header constructed by host + * whal_cfir_enhanced_hdr: CFR header constructed by ucode + * tx_tstamp: Timestamp when TX/RX event was received + * dbr_tstamp: Timestamp when DBR completion event was received + * header_length: Length of header DMAed by ucode in words + * payload_length: Length of CFR payload + */ +struct look_up_table { + bool dbr_recv; + bool tx_recv; + uint8_t *data; /* capture payload */ + uint32_t data_len; /* capture len */ + uint16_t dbr_ppdu_id; /* ppdu id from dbr */ + uint16_t tx_ppdu_id; /* ppdu id from TX event */ + qdf_dma_addr_t dbr_address; /* capture len */ + uint32_t tx_address1; /* capture len */ + uint32_t tx_address2; /* capture len */ + struct csi_cfr_header header; + struct whal_cfir_dma_hdr dma_hdr; + uint64_t txrx_tstamp; + uint64_t dbr_tstamp; + uint32_t header_length; + uint32_t payload_length; +}; + +struct unassoc_pool_entry { + struct qdf_mac_addr mac; + struct cfr_capture_params cfr_params; + bool is_valid; +}; + +#ifdef WLAN_ENH_CFR_ENABLE +/** + * struct ta_ra_cfr_cfg - structure to store configuration of 16 groups in + * M_TA_RA mode + * filter_group_id: Filter group number for which the below filters needs to be + * applied + * bw: CFR capture will be done for packets matching the bandwidths specified + * within this bitmask + * nss: CFR capture will be done for packets matching the Nss specified within + * this bitmask + * valid_ta: Ta_addr is valid if set + * valid_ta_mask: Ta_addr_mask is valid if set + * valid_ra: Ra_addr is valid if set + * valid_ra_mask: Ra_addr_mask is valid if set + * valid_bw_mask: Bandwidth is valid if set + * valid_nss_mask: NSS is valid if set + * valid_mgmt_subtype: Mgmt_subtype is valid if set + * valid_ctrl_subtype: Ctrl_subtype is valid if set + * valid_data_subtype: Data_subtype is valid if set + * mgmt_subtype_filter: Managments Packets matching the subtype filter + * categories will be filtered in by MAC for CFR capture. + * ctrl_subtype_filter: Control Packets matching the subtype filter + * categories will be filtered in by MAC for CFR capture. + * data_subtype_filter: Data Packets matching the subtype filter + * categories will be filtered in by MAC for CFR capture. + * tx_addr: Packets whose transmitter address matches (tx_addr & tx_addr_mask) + * will be filtered in by MAC + * tx_addr_mask: Packets whose transmitter address matches (tx_addr & + * tx_addr_mask) will be filtered in by MAC + * rx_addr: Packets whose receiver address matches (rx_addr & rx_addr_mask) + * will be filtered in by MAC + * rx_addr_mask: Packets whose receiver address matches (rx_addr & + * rx_addr_mask) will be filtered in by MAC + */ +struct ta_ra_cfr_cfg { + uint8_t filter_group_id; + uint16_t bw :5, + nss :8, + rsvd0 :3; + uint16_t valid_ta :1, + valid_ta_mask :1, + valid_ra :1, + valid_ra_mask :1, + valid_bw_mask :1, + valid_nss_mask :1, + valid_mgmt_subtype :1, + valid_ctrl_subtype :1, + valid_data_subtype :1, + rsvd1 :7; + uint16_t mgmt_subtype_filter; + uint16_t ctrl_subtype_filter; + uint16_t data_subtype_filter; + uint8_t tx_addr[QDF_MAC_ADDR_SIZE]; + uint8_t rx_addr[QDF_MAC_ADDR_SIZE]; + uint8_t tx_addr_mask[QDF_MAC_ADDR_SIZE]; + uint8_t rx_addr_mask[QDF_MAC_ADDR_SIZE]; + +} qdf_packed; + +/** + * struct cfr_rcc_param - structure to store cfr config param + * pdev_id: pdev_id for identifying the MAC + * vdev_id: vdev_id of current rcc configures + * srng_id: srng id of current rcc configures + * capture_duration: Capture Duration field for which CFR capture has to happen, + * in microsecond units + * capture_interval: Capture interval field which is time in between + * consecutive CFR capture, in microsecond units + * ul_mu_user_mask_lower: Bitfields indicates which of the users in the current + * UL MU tranmission are enabled for CFR capture. + * ul_mu_user_mask_upper: This is contiuation of the above lower mask. + * freeze_tlv_delay_cnt_en: Enable Freeze TLV delay counter in MAC + * freeze_tlv_delay_cnt_thr: Indicates the number of consecutive Rx packets to + * be skipped before CFR capture is enabled again. + * filter_group_bitmap: Bitfields set indicates which of the CFR group config is + * enabled + * m_directed_ftm: Filter Directed FTM ACK frames for CFR capture + * m_all_ftm_ack: Filter All FTM ACK frames for CFR capture + * m_ndpa_ndp_directed: Filter NDPA NDP Directed Frames for CFR capture + * m_ndpa_ndp_all: Filter all NDPA NDP for CFR capture + * m_ta_ra_filter: Filter Frames based on TA/RA/Subtype as provided in CFR Group + * config + * m_all_packet: Filter in All packets for CFR Capture + * num_grp_tlvs: Indicates the number of groups in M_TA_RA mode, that have + * changes in the current commit session, use to construct WMI group TLV(s) + * curr: Placeholder for M_TA_RA group config in current commit session + * modified_in_curr_session: Bitmap indicating number of groups in M_TA_RA mode + * that have changed in current commit session. + */ +struct cfr_rcc_param { + uint8_t pdev_id; + uint8_t vdev_id; + uint8_t srng_id; + uint32_t capture_duration; + uint32_t capture_interval; + uint32_t ul_mu_user_mask_lower; + uint32_t ul_mu_user_mask_upper; + uint16_t freeze_tlv_delay_cnt_en :1, + freeze_tlv_delay_cnt_thr :8, + rsvd0 :7; + uint16_t filter_group_bitmap; + uint8_t m_directed_ftm : 1, + m_all_ftm_ack : 1, + m_ndpa_ndp_directed : 1, + m_ndpa_ndp_all : 1, + m_ta_ra_filter : 1, + m_all_packet : 1, + rsvd1 : 2; + uint8_t num_grp_tlvs; + + struct ta_ra_cfr_cfg curr[MAX_TA_RA_ENTRIES]; + uint16_t modified_in_curr_session; +}; +#endif /* WLAN_ENH_CFR_ENABLE */ + +/** + * struct pdev_cfr - private pdev object for cfr + * pdev_obj: pointer to pdev object + * is_cfr_capable: flag to determine if cfr is enabled or not + * cfr_timer_enable: flag to enable/disable timer + * chip_type: chip type which is defined in enum cfrradiotype + * cfr_mem_chunk: Region of memory used for storing cfr data + * cfr_max_sta_count: Maximum stations supported in one-shot capture mode + * num_subbufs: No. of sub-buffers used in relayfs + * subbuf_size: Size of sub-buffer used in relayfs + * chan_ptr: Channel in relayfs + * dir_ptr: Parent directory of relayfs file + * lut: lookup table used to store asynchronous DBR and TX/RX events for + * correlation + * lut_num: Number of lut + * dbr_buf_size: Size of DBR completion buffer + * dbr_num_bufs: No. of DBR completions + * tx_evt_cnt: No. of TX completion events till CFR stop was issued + * total_tx_evt_cnt: No. of Tx completion events since wifi was up + * dbr_evt_cnt: No. of WMI DBR completion events + * release_cnt: No. of CFR data buffers relayed to userspace + * rcc_param: Structure to store CFR config for the current commit session + * global: Structure to store accumulated CFR config + * rx_tlv_evt_cnt: Number of CFR WDI events from datapath + * lut_age_timer: Timer to flush pending TXRX/DBR events in lookup table + * lut_timer_init: flag to determine if lut_age_timer is initialized or not + * is_cfr_rcc_capable: Flag to determine if RCC is enabled or not. + * flush_dbr_cnt: No. of un-correlated DBR completions flushed when a newer PPDU + * is correlated successfully with newer DBR completion + * invalid_dma_length_cnt: No. of buffers for which CFR DMA header length (or) + * data length was invalid + * flush_timeout_dbr_cnt: No. of DBR completion flushed out in ageout logic + * clear_txrx_event: No. of PPDU status TLVs over-written in LUT + * unassoc_pool: Pool of un-associated clients used when capture method is + * CFR_CAPTURE_METHOD_PROBE_RESPONSE + * last_success_tstamp: DBR timestamp which indicates that both DBR and TX/RX + * events have been received successfully. + * cfr_dma_aborts: No. of CFR DMA aborts in ucode + */ +/* + * To be extended if we get more capbality info + * from FW's extended service ready event. + */ +struct pdev_cfr { + struct wlan_objmgr_pdev *pdev_obj; + uint8_t is_cfr_capable; + uint8_t cfr_timer_enable; + uint8_t chip_type; + struct cfr_wmi_host_mem_chunk cfr_mem_chunk; + uint16_t cfr_max_sta_count; + uint16_t cfr_current_sta_count; + uint32_t num_subbufs; + uint32_t subbuf_size; + qdf_streamfs_chan_t chan_ptr; + qdf_dentry_t dir_ptr; + struct look_up_table **lut; + uint32_t lut_num; + uint32_t dbr_buf_size; + uint32_t dbr_num_bufs; + uint64_t tx_evt_cnt; + uint64_t total_tx_evt_cnt; + uint64_t dbr_evt_cnt; + uint64_t release_cnt; +#ifdef WLAN_ENH_CFR_ENABLE + struct cfr_rcc_param rcc_param; + struct ta_ra_cfr_cfg global[MAX_TA_RA_ENTRIES]; + uint64_t rx_tlv_evt_cnt; + qdf_timer_t lut_age_timer; + uint8_t lut_timer_init; + uint8_t is_cfr_rcc_capable; + uint64_t flush_dbr_cnt; + uint64_t invalid_dma_length_cnt; + uint64_t flush_timeout_dbr_cnt; + uint64_t clear_txrx_event; + uint64_t last_success_tstamp; + uint64_t cfr_dma_aborts; +#endif + struct unassoc_pool_entry unassoc_pool[MAX_CFR_ENABLED_CLIENTS]; +}; + +#define PEER_CFR_CAPTURE_ENABLE 1 +#define PEER_CFR_CAPTURE_DISABLE 0 +/** + * struct peer_cfr - private peer object for cfr + * peer_obj: pointer to peer_obj + * request: Type of request (start/stop) + * bandwidth: bandwitdth of capture for this peer + * capture_method: enum determining type of cfr data capture. + * 0-Qos null data + */ +struct peer_cfr { + struct wlan_objmgr_peer *peer_obj; + u_int8_t request; /* start/stop */ + u_int8_t bandwidth; + u_int32_t period; + u_int8_t capture_method; +}; + +/** + * cfr_initialize_pdev() - cfr initialize pdev + * @pdev: Pointer to pdev_obj + * + * Return: status of cfr pdev init + */ +QDF_STATUS cfr_initialize_pdev(struct wlan_objmgr_pdev *pdev); + +/** + * cfr_deinitialize_pdev() - cfr deinitialize pdev + * @pdev: Pointer to pdev_obj + * + * Return: status of cfr pdev deinit + */ +QDF_STATUS cfr_deinitialize_pdev(struct wlan_objmgr_pdev *pdev); + +/** + * wlan_cfr_init() - Global init for cfr. + * + * Return: status of global init pass/fail + */ +QDF_STATUS wlan_cfr_init(void); + +/** + * wlan_cfr_deinit() - Global de-init for cfr. + * + * Return: status of global de-init pass/fail + */ +QDF_STATUS wlan_cfr_deinit(void); + +/** + * wlan_cfr_pdev_open() - pdev_open function for cfr. + * @pdev: pointer to pdev object + * + * Return: status of pdev_open pass/fail + */ +QDF_STATUS wlan_cfr_pdev_open(struct wlan_objmgr_pdev *pdev); + +/** + * wlan_cfr_pdev_close() - pdev_close function for cfr. + * @pdev: pointer to pdev object + * + * Return: status of pdev_close pass/fail + */ +QDF_STATUS wlan_cfr_pdev_close(struct wlan_objmgr_pdev *pdev); + +/** + * count_set_bits() - function to count set bits in a bitmap + * @value: input bitmap + * + * Return: No. of set bits + */ +uint8_t count_set_bits(uint32_t value); + +#ifdef WLAN_ENH_CFR_ENABLE +/** + * wlan_cfr_rx_tlv_process() - Process PPDU status TLVs and store info in + * lookup table + * @pdev_obj: PDEV object + * @nbuf: ppdu info + * + * Return: none + */ +void wlan_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf); +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/src/wlan_cfr_tgt_api.c b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/src/wlan_cfr_tgt_api.c new file mode 100644 index 0000000000000000000000000000000000000000..3504ee5abd95af7f0377dc14dd5c36c4c78c0719 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/src/wlan_cfr_tgt_api.c @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Layer b/w umac and target_if (ol) txops + * It contains wrapers for txops + */ + +#include +#include +#include +#include + +uint32_t tgt_cfr_info_send(struct wlan_objmgr_pdev *pdev, void *head, + size_t hlen, void *data, size_t dlen, void *tail, + size_t tlen) +{ + struct pdev_cfr *pa; + uint32_t status; + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + + if (pa == NULL) { + cfr_err("pdev_cfr is NULL\n"); + return -1; + } + + if (head) + status = cfr_streamfs_write(pa, (const void *)head, hlen); + + if (data) + status = cfr_streamfs_write(pa, (const void *)data, dlen); + + if (tail) + status = cfr_streamfs_write(pa, (const void *)tail, tlen); + + + /* finalise the write */ + status = cfr_streamfs_flush(pa); + + return status; +} + +void tgt_cfr_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value) +{ + struct psoc_cfr *cfr_sc; + + if (psoc == NULL) + return; + + cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_CFR); + if (cfr_sc == NULL) + return; + + cfr_sc->is_cfr_capable = !!value; + cfr_debug("CFR:%s FW support advert=%d\n", __func__, + cfr_sc->is_cfr_capable); +} + +static inline struct wlan_lmac_if_cfr_tx_ops * + wlan_psoc_get_cfr_txops(struct wlan_objmgr_psoc *psoc) +{ + return &((psoc->soc_cb.tx_ops.cfr_tx_ops)); +} + +int tgt_cfr_get_target_type(struct wlan_objmgr_psoc *psoc) +{ + uint32_t target_type = 0; + struct wlan_lmac_if_target_tx_ops *target_type_tx_ops; + + target_type_tx_ops = &psoc->soc_cb.tx_ops.target_tx_ops; + + if (target_type_tx_ops->tgt_get_tgt_type) + target_type = target_type_tx_ops->tgt_get_tgt_type(psoc); + + return target_type; +} + +int tgt_cfr_init_pdev(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + int status = 0; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_init_pdev) + status = cfr_tx_ops->cfr_init_pdev(psoc, pdev); + + if (status != 0) + cfr_err("Error occurred with exit code %d\n", status); + + return status; +} + +int tgt_cfr_deinit_pdev(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + int status = 0; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_deinit_pdev) + status = cfr_tx_ops->cfr_deinit_pdev(psoc, pdev); + + if (status != 0) + cfr_err("Error occurred with exit code %d\n", status); + + return status; +} + +int tgt_cfr_start_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer, + struct cfr_capture_params *cfr_params) +{ + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + int status = 0; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_start_capture) + status = cfr_tx_ops->cfr_start_capture(pdev, peer, cfr_params); + + if (status != 0) + cfr_err("Error occurred with exit code %d\n", status); + + return status; +} + +int tgt_cfr_stop_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer) +{ + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + int status = 0; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_stop_capture) + status = cfr_tx_ops->cfr_stop_capture(pdev, peer); + + if (status != 0) + cfr_err("Error occurred with exit code %d\n", status); + + return status; +} + +int +tgt_cfr_enable_cfr_timer(struct wlan_objmgr_pdev *pdev, uint32_t cfr_timer) +{ + int status = 0; + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_enable_cfr_timer) + status = cfr_tx_ops->cfr_enable_cfr_timer(pdev, cfr_timer); + + if (status != 0) + cfr_err("Error occurred with exit code %d\n", status); + + return status; +} + +#ifdef WLAN_ENH_CFR_ENABLE +QDF_STATUS +tgt_cfr_config_rcc(struct wlan_objmgr_pdev *pdev, + struct cfr_rcc_param *rcc_param) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_config_rcc) + status = cfr_tx_ops->cfr_config_rcc(pdev, rcc_param); + + if (status != QDF_STATUS_SUCCESS) + cfr_err("Error occurred with exit code %d\n", status); + + return status; +} + +void tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + if (!psoc) { + cfr_err("Invalid PSOC: Flush LUT Timer cannot be started\n"); + return; + } + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_start_lut_timer) + cfr_tx_ops->cfr_start_lut_timer(pdev); +} + +void tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + if (!psoc) { + cfr_err("Invalid PSOC: Flush LUT Timer cannot be stopped\n"); + return; + } + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_stop_lut_timer) + cfr_tx_ops->cfr_stop_lut_timer(pdev); +} + +void tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev *pdev, + struct cfr_rcc_param *rcc_param, + bool allvalid, uint16_t reset_cfg) +{ + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_default_ta_ra_cfg) + cfr_tx_ops->cfr_default_ta_ra_cfg(rcc_param, + allvalid, reset_cfg); +} + +void tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_dump_lut_enh) + cfr_tx_ops->cfr_dump_lut_enh(pdev); +} + +void tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf) +{ + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_rx_tlv_process) + cfr_tx_ops->cfr_rx_tlv_process(pdev, nbuf); +} + +void tgt_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + if (!psoc) { + cfr_err("Invalid PSOC:Cannot update global config.\n"); + return; + } + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_update_global_cfg) + cfr_tx_ops->cfr_update_global_cfg(pdev); +} + +QDF_STATUS tgt_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev, + bool is_subscribe) +{ + struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + if (!psoc) { + cfr_err("Invalid psoc\n"); + return QDF_STATUS_E_INVAL; + } + + cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc); + + if (cfr_tx_ops->cfr_subscribe_ppdu_desc) + return cfr_tx_ops->cfr_subscribe_ppdu_desc(pdev, + is_subscribe); + + return QDF_STATUS_SUCCESS; +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/src/wlan_cfr_ucfg_api.c b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/src/wlan_cfr_ucfg_api.c new file mode 100644 index 0000000000000000000000000000000000000000..7ae271105e2d8928627b19cc65aa5ae51cd9db24 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/src/wlan_cfr_ucfg_api.c @@ -0,0 +1,1124 @@ +/* + * Copyright (c) 2019-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include "cfr_defs_i.h" +#include +#include +#include +#include +#include +#ifdef WLAN_ENH_CFR_ENABLE +#include "cdp_txrx_ctrl.h" +#endif + +int ucfg_cfr_start_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer, + struct cfr_capture_params *params) +{ + int status; + struct pdev_cfr *pa; + struct peer_cfr *pe; + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (NULL == pa) { + cfr_err("PDEV cfr object is NULL!\n"); + return -EINVAL; + } + + if (!(pa->is_cfr_capable)) { + qdf_info("cfr is not supported on this chip\n"); + return -EINVAL; + } + + /* Get peer private object */ + pe = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_CFR); + if (NULL == pe) { + cfr_err("PEER cfr object is NULL!\n"); + return -EINVAL; + } + + if ((params->period < 0) || (params->period > MAX_CFR_PRD) || + (params->period % 10)) { + cfr_err("Invalid period value: %d\n", params->period); + return -EINVAL; + } + + if (!(params->period) && (pa->cfr_timer_enable)) { + cfr_err("Single shot capture is not allowed during periodic capture\n"); + return -EINVAL; + } + + if ((params->period) && !(pa->cfr_timer_enable)) { + cfr_err("Global periodic timer is not enabled, configure global cfr timer\n"); + } + + if (params->period) { + if (pa->cfr_current_sta_count == pa->cfr_max_sta_count) { + qdf_info("max periodic cfr clients reached\n"); + return -EINVAL; + } + if (!(pe->request)) + pa->cfr_current_sta_count++; + } + + status = tgt_cfr_start_capture(pdev, peer, params); + + if (status == 0) { + pe->bandwidth = params->bandwidth; + pe->period = params->period; + pe->capture_method = params->method; + pe->request = PEER_CFR_CAPTURE_ENABLE; + } else + pa->cfr_current_sta_count--; + + return status; +} + +int ucfg_cfr_start_capture_probe_req(struct wlan_objmgr_pdev *pdev, + struct qdf_mac_addr *unassoc_mac, + struct cfr_capture_params *params) +{ + int idx, idx_to_insert = -1; + struct pdev_cfr *pa; + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (!pa) { + cfr_err("Pdev cfr object is null!"); + return -EINVAL; + } + + if (!(pa->is_cfr_capable)) { + cfr_err("CFR is not supported on this chip"); + return -EINVAL; + } + + if (pa->cfr_current_sta_count == pa->cfr_max_sta_count) { + cfr_err("max cfr cleint reached"); + return -EINVAL; + } + + for (idx = 0; idx < MAX_CFR_ENABLED_CLIENTS; idx++) { + /* Store first invalid entry's index, to add mac entry if not + * already present. + */ + if (idx_to_insert < 0) { + if (pa->unassoc_pool[idx].is_valid != true) + idx_to_insert = idx; + } + + /* Add new mac entry only if it is not present. If already + * present, update the capture parameters + */ + if (qdf_mem_cmp(&pa->unassoc_pool[idx].mac, unassoc_mac, + sizeof(struct qdf_mac_addr)) == 0) { + cfr_info("Node already present. Updating params"); + qdf_mem_copy(&pa->unassoc_pool[idx].cfr_params, + params, + sizeof(struct cfr_capture_params)); + pa->unassoc_pool[idx].is_valid = true; + return 0; + } + } + + if (idx_to_insert < 0) { + /* All the entries in the table are valid. So we have reached + * max client capacity. To add a new client, capture on one of + * the clients in table has to be stopped. + */ + cfr_err("Maximum client capacity reached"); + return -EINVAL; + } + + /* If control reaches here, we did not find mac in the table + * and we have atleast one free entry in table. + * Add the entry at index = idx_to_insert + */ + qdf_mem_copy(&pa->unassoc_pool[idx_to_insert].mac, + unassoc_mac, sizeof(struct qdf_mac_addr)); + qdf_mem_copy(&pa->unassoc_pool[idx_to_insert].cfr_params, + params, sizeof(struct cfr_capture_params)); + pa->unassoc_pool[idx_to_insert].is_valid = true; + pa->cfr_current_sta_count++; + + return 0; +} + +int ucfg_cfr_stop_capture_probe_req(struct wlan_objmgr_pdev *pdev, + struct qdf_mac_addr *unassoc_mac) +{ + struct pdev_cfr *pa; + int idx; + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (!pa) { + cfr_err("Pdev cfr object is NULL!\n"); + return -EINVAL; + } + + if (!(pa->is_cfr_capable)) { + cfr_err("CFR is not supported on this chip\n"); + return -EINVAL; + } + + for (idx = 0; idx < MAX_CFR_ENABLED_CLIENTS; idx++) { + /* Remove mac only if it is present */ + if (qdf_mem_cmp(&pa->unassoc_pool[idx].mac, unassoc_mac, + sizeof(struct qdf_mac_addr)) == 0) { + qdf_mem_zero(&pa->unassoc_pool[idx], + sizeof(struct unassoc_pool_entry)); + pa->cfr_current_sta_count--; + return 0; + } + } + + /* If mac was present in pool it would have been deleted in the + * above loop and returned from there. + * If control reached here, mac was not found. So, ignore the request. + */ + cfr_err("Trying to delete mac not present in pool. Ignoring request."); + return 0; +} + +int ucfg_cfr_set_timer(struct wlan_objmgr_pdev *pdev, uint32_t value) +{ + struct pdev_cfr *pa; + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (pa == NULL) { + cfr_err("PDEV cfr object is NULL!\n"); + return -EINVAL; + } + + if (!(pa->is_cfr_capable)) { + qdf_info("cfr is not supported on this chip\n"); + return -EINVAL; + } + + return tgt_cfr_enable_cfr_timer(pdev, value); +} +qdf_export_symbol(ucfg_cfr_set_timer); + +int ucfg_cfr_get_timer(struct wlan_objmgr_pdev *pdev) +{ + struct pdev_cfr *pa; + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (pa == NULL) { + cfr_err("PDEV cfr object is NULL!\n"); + return -EINVAL; + } + + if (!(pa->is_cfr_capable)) { + qdf_info("cfr is not supported on this chip\n"); + return -EINVAL; + } + + return pa->cfr_timer_enable; +} +qdf_export_symbol(ucfg_cfr_get_timer); + +int ucfg_cfr_stop_capture(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_peer *peer) +{ + int status; + struct peer_cfr *pe; + struct pdev_cfr *pa; + + pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR); + if (pa == NULL) { + cfr_err("PDEV cfr object is NULL!\n"); + return -EINVAL; + } + + if (!(pa->is_cfr_capable)) { + qdf_info("cfr is not supported on this chip\n"); + return -EINVAL; + } + + pe = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_CFR); + if (pe == NULL) { + cfr_err("PEER cfr object is NULL!\n"); + return -EINVAL; + } + + if ((pe->period) && (pe->request)) + status = tgt_cfr_stop_capture(pdev, peer); + else { + qdf_info("periodic cfr not started for the client\n"); + return -EINVAL; + } + + if (status == 0) { + pe->request = PEER_CFR_CAPTURE_DISABLE; + pa->cfr_current_sta_count--; + } + + return status; +} + +int ucfg_cfr_list_peers(struct wlan_objmgr_pdev *pdev) +{ + return 0; +} + +QDF_STATUS ucfg_cfr_stop_indication(struct wlan_objmgr_vdev *vdev) +{ + if (!vdev) { + cfr_err("null vdev"); + return QDF_STATUS_E_INVAL; + } + + return cfr_stop_indication(vdev); +} + +#ifdef WLAN_ENH_CFR_ENABLE + +static inline +QDF_STATUS dev_sanity_check(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_pdev **ppdev, + struct pdev_cfr **ppcfr) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (!vdev) { + cfr_err("vdev is NULL\n"); + return QDF_STATUS_E_NULL_VALUE; + } + + *ppdev = wlan_vdev_get_pdev(vdev); + + if (!*ppdev) { + cfr_err("pdev is NULL\n"); + return QDF_STATUS_E_NULL_VALUE; + } + + status = wlan_objmgr_pdev_try_get_ref(*ppdev, WLAN_CFR_ID); + if (status != QDF_STATUS_SUCCESS) { + cfr_err("Failed to get pdev reference\n"); + return status; + } + + *ppcfr = wlan_objmgr_pdev_get_comp_private_obj(*ppdev, + WLAN_UMAC_COMP_CFR); + + if (!(*ppcfr)) { + cfr_err("pdev object for CFR is null"); + wlan_objmgr_pdev_release_ref(*ppdev, WLAN_CFR_ID); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!(*ppcfr)->is_cfr_rcc_capable) { + cfr_err("cfr is not supported on this chip\n"); + wlan_objmgr_pdev_release_ref(*ppdev, WLAN_CFR_ID); + return QDF_STATUS_E_NOSUPPORT; + } + + return status; +} + +/* + * This is needed only in case of m_ta_ra_filter mode. + * If user wants to reset the group configurations to default values, + * then this handler will come into action. + * + * If user wants to reset the configurations of 0th, 1st and 3rd group, + * then the input should be : + * + * wlanconfig ath0 cfr reset_cfg 0xb + * + */ + +QDF_STATUS ucfg_cfr_set_reset_bitmap(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + pcfr->rcc_param.modified_in_curr_session |= params->reset_cfg; + tgt_cfr_default_ta_ra_cfg(pdev, &pcfr->rcc_param, + true, params->reset_cfg); + + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +/* + * This is needed only in case of m_ta_ra_filter mode. + * After providing all the group configurations, user should provide + * the information about which groups need to be enabled. + * Based on that FW will enable the configurations for CFR groups. + * If user has to enable only 0th group, then input should be : + * + * wlanconfig ath0 cfr en_cfg 0x1 + * + * Enable the bitmap from user provided configuration into cfr_rcc_param. + */ + +QDF_STATUS ucfg_cfr_set_en_bitmap(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + pcfr->rcc_param.filter_group_bitmap = params->en_cfg; + + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +/* + * Copy user provided input for ul_mu_user_mask into cfr_rcc_param. + */ + +QDF_STATUS +ucfg_cfr_set_ul_mu_user_mask(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + pcfr->rcc_param.ul_mu_user_mask_lower = params->ul_mu_user_mask_lower; + pcfr->rcc_param.ul_mu_user_mask_upper = params->ul_mu_user_mask_upper; + + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +/* + * FREEZE_TLV_DELAY_CNT_* registers are used for FREEZE TLV timeout mechanism + * in MAC side. In case MAC send FREEZE TLV to PHY too late due to + * long AST delay, PHY ucode may not handle it well or it will impact + * next frame’s normal processing, then MAC needs to drop FREEZE TLV + * sending process after reaching the threshold. + * + * This handler will copy user provided input for freeze_tlv_delay_cnt + * into cfr_rcc_param. + */ + +QDF_STATUS +ucfg_cfr_set_freeze_tlv_delay_cnt(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + pcfr->rcc_param.freeze_tlv_delay_cnt_en = + params->freeze_tlv_delay_cnt_en; + + pcfr->rcc_param.freeze_tlv_delay_cnt_thr = + params->freeze_tlv_delay_cnt_thr; + + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +/* + * Set capture interval from the provided configuration into cfr_rcc_param. + * All fixed parameters are needed to be stored into cfr_rcc_param. + */ + +QDF_STATUS +ucfg_cfr_set_capture_interval(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + pcfr->rcc_param.capture_interval = params->cap_intvl; + + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +/* + * Set capture duration from the provided configuration into cfr_rcc_param. + * All fixed parameters are needed to be stored into cfr_rcc_param. + */ + +QDF_STATUS +ucfg_cfr_set_capture_duration(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + pcfr->rcc_param.capture_duration = params->cap_dur; + + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +/* + * Copy user provided group parameters( type/ subtype of mgmt, ctrl, data ) + * into curr_cfg instance of ta_ra_cfr_cfg. + * Set valid mask for the provided configuration. + * Set modified_in_this_session for the particular group. + */ + +QDF_STATUS +ucfg_cfr_set_frame_type_subtype(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + struct ta_ra_cfr_cfg *curr_cfg = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + /* Populating current config based on user's input */ + curr_cfg = &pcfr->rcc_param.curr[params->grp_id]; + curr_cfg->mgmt_subtype_filter = params->expected_mgmt_subtype; + curr_cfg->ctrl_subtype_filter = params->expected_ctrl_subtype; + curr_cfg->data_subtype_filter = params->expected_data_subtype; + + curr_cfg->valid_mgmt_subtype = 1; + curr_cfg->valid_ctrl_subtype = 1; + curr_cfg->valid_data_subtype = 1; + + qdf_set_bit(params->grp_id, + (unsigned long *) + &pcfr->rcc_param.modified_in_curr_session); + + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +/* + * Copy user provided group parameters( BW and NSS ) + * into curr_cfg instance of ta_ra_cfr_cfg. + * Set valid mask for the provided configuration. + * Set modified_in_this_session for the particular group. + */ + +QDF_STATUS ucfg_cfr_set_bw_nss(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + struct ta_ra_cfr_cfg *curr_cfg = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + /* Populating current config based on user's input */ + curr_cfg = &pcfr->rcc_param.curr[params->grp_id]; + curr_cfg->bw = params->bw; + curr_cfg->nss = params->nss; + + curr_cfg->valid_bw_mask = 1; + curr_cfg->valid_nss_mask = 1; + + qdf_set_bit(params->grp_id, + (unsigned long *)&pcfr->rcc_param.modified_in_curr_session); + + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +/* + * Copy user provided group parameters( TA, RA, TA_MASK, RA_MASK ) + * into curr_cfg instance of ta_ra_cfr_cfg. + * Set valid mask for the provided configuration. + * Set modified_in_this_session for the particular group. + */ + +QDF_STATUS ucfg_cfr_set_tara_config(struct wlan_objmgr_vdev *vdev, + struct cfr_wlanconfig_param *params) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + struct ta_ra_cfr_cfg *curr_cfg = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + curr_cfg = &pcfr->rcc_param.curr[params->grp_id]; + qdf_mem_copy(curr_cfg->tx_addr, params->ta, QDF_MAC_ADDR_SIZE); + qdf_mem_copy(curr_cfg->rx_addr, params->ra, QDF_MAC_ADDR_SIZE); + qdf_mem_copy(curr_cfg->tx_addr_mask, + params->ta_mask, QDF_MAC_ADDR_SIZE); + qdf_mem_copy(curr_cfg->rx_addr_mask, + params->ra_mask, QDF_MAC_ADDR_SIZE); + + curr_cfg->valid_ta = 1; + curr_cfg->valid_ta_mask = 1; + curr_cfg->valid_ra = 1; + curr_cfg->valid_ra_mask = 1; + + qdf_set_bit(params->grp_id, + (unsigned long *) + &pcfr->rcc_param.modified_in_curr_session); + + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +static bool cfr_is_filter_enabled(struct cfr_rcc_param *rcc_param) +{ + if (rcc_param->m_directed_ftm || + rcc_param->m_all_ftm_ack || + rcc_param->m_ndpa_ndp_directed || + rcc_param->m_ndpa_ndp_all || + rcc_param->m_ta_ra_filter || + rcc_param->m_all_packet) + return true; + else + return false; +} + +QDF_STATUS ucfg_cfr_get_cfg(struct wlan_objmgr_vdev *vdev) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + struct ta_ra_cfr_cfg *glbl_cfg = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + uint8_t grp_id; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + if (!cfr_is_filter_enabled(&pcfr->rcc_param)) { + cfr_err(" All RCC modes are disabled.\n"); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + return status; + } + + cfr_err("CAPTURE MODE:\n"); + + cfr_err("m_directed_ftm is : %s\n", + pcfr->rcc_param.m_directed_ftm ? + "enabled" : "disabled"); + cfr_err("m_all_ftm_ack is : %s\n", + pcfr->rcc_param.m_all_ftm_ack ? + "enabled" : "disabled"); + cfr_err("m_ndpa_ndp_directed is: %s\n", + pcfr->rcc_param.m_ndpa_ndp_directed ? + "enabled" : "disabled"); + cfr_err("m_ndpa_ndp_all is : %s\n", + pcfr->rcc_param.m_ndpa_ndp_all ? + "enabled" : "disabled"); + cfr_err("m_ta_ra_filter is : %s\n", + pcfr->rcc_param.m_ta_ra_filter ? + "enabled" : "disabled"); + cfr_err("m_all_packet is : %s\n", + pcfr->rcc_param.m_all_packet ? + "enabled" : "disabled"); + + cfr_err("capture duration : %u usec\n", + pcfr->rcc_param.capture_duration); + cfr_err("capture interval : %u usec\n", + pcfr->rcc_param.capture_interval); + cfr_err("UL MU User mask lower : %u\n", + pcfr->rcc_param.ul_mu_user_mask_lower); + cfr_err("UL MU User mask upper : %u\n", + pcfr->rcc_param.ul_mu_user_mask_upper); + cfr_err("Freeze TLV delay count is : %s\n", + pcfr->rcc_param.freeze_tlv_delay_cnt_en ? + "enabled" : "disabled"); + cfr_err("Freeze TLV delay count threshold : %u\n", + pcfr->rcc_param.freeze_tlv_delay_cnt_thr); + cfr_err("Enabled CFG id bitmap : 0x%x\n", + pcfr->rcc_param.filter_group_bitmap); + cfr_err(" Modified cfg id bitmap : 0x%x\n", + pcfr->rcc_param.modified_in_curr_session); + + cfr_err("TARA_CONFIG details:\n"); + + for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) { + glbl_cfg = &pcfr->global[grp_id]; + + cfr_err("Config ID: %d\n", grp_id); + cfr_err("Bandwidth :0x%x\n", glbl_cfg->bw); + cfr_err("NSS : 0x%x\n", glbl_cfg->nss); + cfr_err("valid_ta: %d\n", glbl_cfg->valid_ta); + cfr_err("valid_ta_mask: %d\n", glbl_cfg->valid_ta_mask); + cfr_err("valid_ra: %d\n", glbl_cfg->valid_ra); + cfr_err("valid_ra_mask: %d\n", glbl_cfg->valid_ra_mask); + cfr_err("valid_bw_mask: %d\n", glbl_cfg->valid_bw_mask); + cfr_err("valid_nss_mask: %d\n", glbl_cfg->valid_nss_mask); + cfr_err("valid_mgmt_subtype: %d\n", + glbl_cfg->valid_mgmt_subtype); + cfr_err("valid_ctrl_subtype: %d\n", + glbl_cfg->valid_ctrl_subtype); + cfr_err("valid_data_subtype: %d\n", + glbl_cfg->valid_data_subtype); + cfr_err("Mgmt subtype : 0x%x\n", + glbl_cfg->mgmt_subtype_filter); + cfr_err("CTRL subtype : 0x%x\n", + glbl_cfg->ctrl_subtype_filter); + cfr_err("Data subtype : 0x%x\n", + glbl_cfg->data_subtype_filter); + cfr_err("TX Addr: " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(glbl_cfg->tx_addr)); + cfr_err("TX Addr Mask: " QDF_FULL_MAC_FMT, + QDF_FULL_MAC_REF(glbl_cfg->tx_addr_mask)); + cfr_err("RX Addr: " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(glbl_cfg->rx_addr)); + cfr_err("RX Addr Mask: " QDF_FULL_MAC_FMT, + QDF_FULL_MAC_REF(glbl_cfg->rx_addr_mask)); + } + + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +static const char *chan_capture_status_to_str(enum chan_capture_status type) +{ + switch (type) { + case CAPTURE_IDLE: + return "CAPTURE_IDLE"; + case CAPTURE_BUSY: + return "CAPTURE_BUSY"; + case CAPTURE_ACTIVE: + return "CAPTURE_ACTIVE"; + case CAPTURE_NO_BUFFER: + return "CAPTURE_NO_BUFFER"; + default: + return "INVALID"; + } +} + +static const +char *mac_freeze_reason_to_str(enum mac_freeze_capture_reason type) +{ + switch (type) { + case FREEZE_REASON_TM: + return "FREEZE_REASON_TM"; + case FREEZE_REASON_FTM: + return "FREEZE_REASON_FTM"; + case FREEZE_REASON_ACK_RESP_TO_TM_FTM: + return "FREEZE_REASON_ACK_RESP_TO_TM_FTM"; + case FREEZE_REASON_TA_RA_TYPE_FILTER: + return "FREEZE_REASON_TA_RA_TYPE_FILTER"; + case FREEZE_REASON_NDPA_NDP: + return "FREEZE_REASON_NDPA_NDP"; + case FREEZE_REASON_ALL_PACKET: + return "FREEZE_REASON_ALL_PACKET"; + default: + return "INVALID"; + } +} + +QDF_STATUS ucfg_cfr_rcc_dump_dbg_counters(struct wlan_objmgr_vdev *vdev) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + struct wlan_objmgr_psoc *psoc = NULL; + struct cdp_cfr_rcc_stats *cfr_rcc_stats = NULL; + uint8_t stats_cnt; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + cfr_err("psoc is null!"); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + return QDF_STATUS_E_NULL_VALUE; + } + + cfr_err("total_tx_evt_cnt = %llu\n", + pcfr->total_tx_evt_cnt); + cfr_err("dbr_evt_cnt = %llu\n", + pcfr->dbr_evt_cnt); + cfr_err("rx_tlv_evt_cnt = %llu\n", + pcfr->rx_tlv_evt_cnt); + cfr_err("release_cnt = %llu\n", + pcfr->release_cnt); + cfr_err("Error cnt:\n"); + cfr_err("flush_dbr_cnt = %llu\n", + pcfr->flush_dbr_cnt); + cfr_err("invalid_dma_length_cnt = %llu\n", + pcfr->invalid_dma_length_cnt); + cfr_err("flush_timeout_dbr_cnt = %llu\n", + pcfr->flush_timeout_dbr_cnt); + cfr_err("PPDU id mismatch for same cookie:\n"); + cfr_err("clear_txrx_event = %llu\n", + pcfr->clear_txrx_event); + cfr_err("cfr_dma_aborts = %llu\n", + pcfr->cfr_dma_aborts); + + cfr_rcc_stats = qdf_mem_malloc(sizeof(struct cdp_cfr_rcc_stats)); + if (!cfr_rcc_stats) { + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + return QDF_STATUS_E_NOMEM; + } + + cdp_get_cfr_dbg_stats(wlan_psoc_get_dp_handle(psoc), + wlan_objmgr_pdev_get_pdev_id(pdev), + cfr_rcc_stats); + + cfr_err("bb_captured_channel_cnt: %llu\n", + cfr_rcc_stats->bb_captured_channel_cnt); + cfr_err("bb_captured_timeout_cnt: %llu\n", + cfr_rcc_stats->bb_captured_timeout_cnt); + cfr_err("rx_loc_info_valid_cnt: %llu\n", + cfr_rcc_stats->rx_loc_info_valid_cnt); + + cfr_err("Channel capture status:\n"); + for (stats_cnt = 0; stats_cnt < CAPTURE_MAX; stats_cnt++) { + cfr_err("%s = %llu\n", + chan_capture_status_to_str(stats_cnt), + cfr_rcc_stats->chan_capture_status[stats_cnt]); + } + + cfr_err("Freeze reason:\n"); + for (stats_cnt = 0; stats_cnt < FREEZE_REASON_MAX; stats_cnt++) { + cfr_err("%s = %llu\n", + mac_freeze_reason_to_str(stats_cnt), + cfr_rcc_stats->reason_cnt[stats_cnt]); + } + + qdf_mem_free(cfr_rcc_stats); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +QDF_STATUS ucfg_cfr_rcc_clr_dbg_counters(struct wlan_objmgr_vdev *vdev) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + struct wlan_objmgr_psoc *psoc = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + cfr_err("psoc is null!"); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + return QDF_STATUS_E_NULL_VALUE; + } + cdp_cfr_clr_dbg_stats(wlan_psoc_get_dp_handle(psoc), + wlan_objmgr_pdev_get_pdev_id(pdev)); + + pcfr->dbr_evt_cnt = 0; + pcfr->release_cnt = 0; + pcfr->total_tx_evt_cnt = 0; + pcfr->rx_tlv_evt_cnt = 0; + pcfr->flush_dbr_cnt = 0; + pcfr->flush_timeout_dbr_cnt = 0; + pcfr->invalid_dma_length_cnt = 0; + pcfr->clear_txrx_event = 0; + pcfr->cfr_dma_aborts = 0; + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +QDF_STATUS ucfg_cfr_rcc_dump_lut(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_pdev *pdev = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (!vdev) { + cfr_err("vdev is NULL\n"); + return QDF_STATUS_E_INVAL; + } + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) { + cfr_err("pdev is NULL\n"); + return QDF_STATUS_E_INVAL; + } + + if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_CFR_ID) != + QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_INVAL; + } + + cfr_err("LUT table:\n"); + tgt_cfr_dump_lut_enh(pdev); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +static void cfr_set_filter(struct wlan_objmgr_pdev *pdev, bool enable, + struct cdp_monitor_filter *filter_val) +{ + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + cfr_info("pdev_id=%d\n", wlan_objmgr_pdev_get_pdev_id(pdev)); + + cdp_cfr_filter(wlan_psoc_get_dp_handle(psoc), + wlan_objmgr_pdev_get_pdev_id(pdev), + enable, + filter_val); +} + +/* + * With the initiation of commit command, this handler will be triggered. + * + * Starts the procedure of forming the TLVs. + * If Host succeeds to send WMI command to FW, after TLV processing, then it + * will save the previous CFR configurations into one instance ta_ra_cfr_cfg, + * called glbl_cfg and update the current config to default state for the + * next commit session. + * + * Finally, reset the counter (modified_in_this_session) to 0 before moving to + * next commit session. + * + */ + +QDF_STATUS ucfg_cfr_committed_rcc_config(struct wlan_objmgr_vdev *vdev) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + struct wlan_objmgr_psoc *psoc = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct cdp_monitor_filter filter_val = {0}; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + psoc = wlan_pdev_get_psoc(pdev); + + if (!psoc) { + cfr_err("psoc is null!"); + return QDF_STATUS_E_NULL_VALUE; + } + + pcfr->rcc_param.vdev_id = wlan_vdev_get_id(vdev); + + /* + * If capture mode is valid, then Host: + * Subscribes for PPDU status TLVs in monitor status ring. + * Sets filter type to either FP or MO, based on the capture mode. + * Starts the LUT_AGE_TIMER of 1sec. + * + * If capture mode is disabled, then Host: + * unsubscribes for PPDU status TLVs in monitor status ring. + * Sets filter type to 0. + * Stops the LUT_AGE_TIMER. + * + */ + + if (cfr_is_filter_enabled(&pcfr->rcc_param)) { + if (pcfr->rcc_param.m_all_ftm_ack) { + filter_val.mode |= MON_FILTER_PASS | + MON_FILTER_OTHER; + filter_val.fp_mgmt |= FILTER_MGMT_ACTION; + filter_val.mo_mgmt |= FILTER_MGMT_ACTION; + } + + if (pcfr->rcc_param.m_ndpa_ndp_all) { + filter_val.mode |= MON_FILTER_PASS | + MON_FILTER_OTHER; + filter_val.fp_ctrl |= FILTER_CTRL_VHT_NDP; + filter_val.mo_ctrl |= FILTER_CTRL_VHT_NDP; + } + + if (pcfr->rcc_param.m_all_packet) { + filter_val.mode |= MON_FILTER_PASS | + MON_FILTER_OTHER; + filter_val.fp_mgmt |= FILTER_MGMT_ALL; + filter_val.mo_mgmt |= FILTER_MGMT_ALL; + filter_val.fp_ctrl |= FILTER_CTRL_ALL; + filter_val.mo_ctrl |= FILTER_CTRL_ALL; + filter_val.fp_data |= FILTER_DATA_ALL; + filter_val.mo_data |= FILTER_DATA_ALL; + } + + /* + * M_TA_RA in monitor other is as intensive as M_ALL pkt + * Support only FP in M_TA_RA mode + */ + if (pcfr->rcc_param.m_ta_ra_filter) { + filter_val.mode |= MON_FILTER_PASS | + MON_FILTER_OTHER; + filter_val.fp_mgmt |= FILTER_MGMT_ALL; + filter_val.mo_mgmt |= FILTER_MGMT_ALL; + filter_val.fp_ctrl |= FILTER_CTRL_ALL; + filter_val.mo_ctrl |= FILTER_CTRL_ALL; + filter_val.fp_data |= FILTER_DATA_ALL; + filter_val.mo_data |= FILTER_DATA_ALL; + } + + if (pcfr->rcc_param.m_directed_ftm) { + filter_val.mode |= MON_FILTER_PASS; + filter_val.fp_mgmt |= FILTER_MGMT_ACTION; + } + + if (pcfr->rcc_param.m_ndpa_ndp_directed) { + filter_val.mode |= MON_FILTER_PASS; + filter_val.fp_ctrl |= FILTER_CTRL_VHT_NDP; + } + + if (!cdp_get_cfr_rcc(wlan_psoc_get_dp_handle(psoc), + wlan_objmgr_pdev_get_pdev_id(pdev))) + tgt_cfr_start_lut_age_timer(pdev); + cfr_set_filter(pdev, 1, &filter_val); + } else { + if (cdp_get_cfr_rcc(wlan_psoc_get_dp_handle(psoc), + wlan_objmgr_pdev_get_pdev_id(pdev))) + tgt_cfr_stop_lut_age_timer(pdev); + cfr_set_filter(pdev, 0, &filter_val); + } + + /* Trigger wmi to start the TLV processing. */ + status = tgt_cfr_config_rcc(pdev, &pcfr->rcc_param); + if (status == QDF_STATUS_SUCCESS) { + cfr_info("CFR commit done\n"); + /* Update global config */ + tgt_cfr_update_global_cfg(pdev); + + /* Bring curr_cfg to default state for next commit session */ + tgt_cfr_default_ta_ra_cfg(pdev, &pcfr->rcc_param, + false, MAX_RESET_CFG_ENTRY); + } else { + cfr_err("CFR commit failed\n"); + } + + pcfr->rcc_param.num_grp_tlvs = 0; + pcfr->rcc_param.modified_in_curr_session = 0; + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +/* + * This handler is used to enable / disable the capture mode. + * + */ +QDF_STATUS ucfg_cfr_set_rcc_mode(struct wlan_objmgr_vdev *vdev, + enum capture_type mode, uint8_t value) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return status; + + switch (mode) { + case RCC_DIRECTED_FTM_FILTER: + pcfr->rcc_param.m_directed_ftm = value; + break; + case RCC_ALL_FTM_ACK_FILTER: + pcfr->rcc_param.m_all_ftm_ack = value; + break; + case RCC_DIRECTED_NDPA_NDP_FILTER: + pcfr->rcc_param.m_ndpa_ndp_directed = value; + break; + case RCC_NDPA_NDP_ALL_FILTER: + pcfr->rcc_param.m_ndpa_ndp_all = value; + break; + case RCC_TA_RA_FILTER: + pcfr->rcc_param.m_ta_ra_filter = value; + break; + case RCC_ALL_PACKET_FILTER: + pcfr->rcc_param.m_all_packet = value; + break; + case RCC_DIS_ALL_MODE: + pcfr->rcc_param.m_directed_ftm = value; + pcfr->rcc_param.m_all_ftm_ack = value; + pcfr->rcc_param.m_ndpa_ndp_directed = value; + pcfr->rcc_param.m_ndpa_ndp_all = value; + pcfr->rcc_param.m_ta_ra_filter = value; + pcfr->rcc_param.m_all_packet = value; + break; + + default: + break; + } + + cfr_debug(" Capture mode set by user: 0x%x\n", value); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return status; +} + +bool ucfg_cfr_get_rcc_enabled(struct wlan_objmgr_vdev *vdev) +{ + struct pdev_cfr *pcfr = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + bool rcc_enabled = false; + + status = dev_sanity_check(vdev, &pdev, &pcfr); + if (status != QDF_STATUS_SUCCESS) + return false; + + rcc_enabled = cfr_is_filter_enabled(&pcfr->rcc_param); + wlan_objmgr_pdev_release_ref(pdev, WLAN_CFR_ID); + + return rcc_enabled; +} + +QDF_STATUS ucfg_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev, + bool is_subscribe) +{ + return tgt_cfr_subscribe_ppdu_desc(pdev, is_subscribe); +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/src/wlan_cfr_utils_api.c b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/src/wlan_cfr_utils_api.c new file mode 100644 index 0000000000000000000000000000000000000000..4cb8ea2298e2710d78df20ba9bd0f71524ff0863 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/cfr/dispatcher/src/wlan_cfr_utils_api.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include "../../core/inc/cfr_defs_i.h" +#include +#include + +QDF_STATUS wlan_cfr_init(void) +{ + if (wlan_objmgr_register_psoc_create_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_psoc_obj_create_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + if (wlan_objmgr_register_psoc_destroy_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_psoc_obj_destroy_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + if (wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_pdev_obj_create_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + if (wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_pdev_obj_destroy_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + if (wlan_objmgr_register_peer_create_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_peer_obj_create_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + if (wlan_objmgr_register_peer_destroy_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_peer_obj_destroy_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_cfr_deinit(void) +{ + if (wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_psoc_obj_create_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + if (wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_psoc_obj_destroy_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + if (wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_pdev_obj_create_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + if (wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_pdev_obj_destroy_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + if (wlan_objmgr_unregister_peer_create_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_peer_obj_create_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + if (wlan_objmgr_unregister_peer_destroy_handler(WLAN_UMAC_COMP_CFR, + wlan_cfr_peer_obj_destroy_handler, NULL) + != QDF_STATUS_SUCCESS) { + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_cfr_pdev_open(struct wlan_objmgr_pdev *pdev) +{ + int status; + + /* chip specific init */ + status = tgt_cfr_init_pdev(pdev); + + if (status != QDF_STATUS_SUCCESS) { + cfr_err("tgt_cfr_init_pdev failed with %d\n", status); + return QDF_STATUS_SUCCESS; + } + + /* RealyFS init */ + status = cfr_streamfs_init(pdev); + + if (status != QDF_STATUS_SUCCESS) { + cfr_err("cfr_streamfs_init failed with %d\n", status); + return QDF_STATUS_SUCCESS; + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_cfr_pdev_close(struct wlan_objmgr_pdev *pdev) +{ + int status = QDF_STATUS_SUCCESS; + /* + * DBR does not have close as of now; + * but this is getting added as part for new gerrit + * Once we have that support we will add it. + */ + status = cfr_streamfs_remove(pdev); + + return status; +} + +QDF_STATUS cfr_initialize_pdev(struct wlan_objmgr_pdev *pdev) +{ + int status = QDF_STATUS_SUCCESS; + + /* chip specific init */ + + status = tgt_cfr_init_pdev(pdev); + + if (status != QDF_STATUS_SUCCESS) + cfr_err("cfr_initialize_pdev status=%d\n", status); + + return status; +} +qdf_export_symbol(cfr_initialize_pdev); + +QDF_STATUS cfr_deinitialize_pdev(struct wlan_objmgr_pdev *pdev) +{ + int status = QDF_STATUS_SUCCESS; + + /* chip specific deinit */ + + status = tgt_cfr_deinit_pdev(pdev); + + if (status != QDF_STATUS_SUCCESS) + cfr_err("cfr_deinitialize_pdev status=%d\n", status); + + return status; +} +qdf_export_symbol(cfr_deinitialize_pdev); + +uint8_t count_set_bits(uint32_t value) +{ + uint8_t count = 0; + + while (value) { + value &= (value - 1); + count++; + } + + return count; +} + +qdf_export_symbol(count_set_bits); + +#ifdef WLAN_ENH_CFR_ENABLE +void wlan_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf) +{ + tgt_cfr_rx_tlv_process(pdev, nbuf); +} + +qdf_export_symbol(wlan_cfr_rx_tlv_process); +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h index 7f055208569dd94bae9f029165223f572822851d..bd8814cda7ce3a5ea5020b7f8d2abaac1251b8e7 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. 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 @@ -134,6 +135,7 @@ #define WLAN_IBSS_IE_MAX_LEN 2 #define WLAN_REQUEST_IE_MAX_LEN 255 #define WLAN_RM_CAPABILITY_IE_MAX_LEN 5 +#define WLAN_RNR_IE_MIN_LEN 5 /* Wide band channel switch IE length */ #define WLAN_WIDE_BW_CHAN_SWITCH_IE_LEN 3 @@ -189,6 +191,19 @@ /* 80 + 80 MHz Operating Channel (revised signalling) */ #define WLAN_VHTOP_CHWIDTH_REVSIG_80_80 1 +#define WLAN_HEOP_FIXED_PARAM_LENGTH 7 +#define WLAN_HEOP_VHTOP_LENGTH 3 +#define WLAN_HEOP_CO_LOCATED_BSS_LENGTH 1 + +#define WLAN_HEOP_VHTOP_PRESENT_MASK 0x00004000 /* B14 */ +#define WLAN_HEOP_CO_LOCATED_BSS_MASK 0x00008000 /* B15 */ +#define WLAN_HEOP_6GHZ_INFO_PRESENT_MASK 0X00020000 /* B17 */ + +#define WLAN_HE_6GHZ_CHWIDTH_20 0 /* 20MHz Oper Ch width */ +#define WLAN_HE_6GHZ_CHWIDTH_40 1 /* 40MHz Oper Ch width */ +#define WLAN_HE_6GHZ_CHWIDTH_80 2 /* 80MHz Oper Ch width */ +#define WLAN_HE_6GHZ_CHWIDTH_160_80_80 3 /* 160/80+80 MHz Oper Ch width */ + #define WLAN_RATE_VAL 0x7f #define WLAN_BASIC_RATE_MASK 0x80 @@ -201,6 +216,9 @@ #define WLAN_BSS_MEMBERSHIP_SELECTOR_SAE_H2E 123 #define WLAN_BSS_MEMBERSHIP_SELECTOR_HE_PHY 122 +#define WLAN_MIN_HECAP_IE_LEN 22 +#define WLAN_MAX_HECAP_IE_LEN 55 + #define WLAN_CHAN_IS_5GHZ(chanidx) \ ((chanidx > 30) ? true : false) #define WLAN_CHAN_IS_2GHZ(chanidx) \ @@ -218,6 +236,20 @@ ((vhtop)->vht_op_ch_freq_seg2 != 0) && \ (abs((vhtop)->vht_op_ch_freq_seg2 - (vhtop)->vht_op_ch_freq_seg1) > 8)) +/* Check if channel width is HE160 in HE 6ghz params */ +#define WLAN_IS_HE160(he_6g_param) (((he_6g_param)->width == \ + WLAN_HE_6GHZ_CHWIDTH_160_80_80) && \ + ((he_6g_param)->chan_freq_seg1 != 0) && \ + (abs((he_6g_param)->chan_freq_seg1 - \ + (he_6g_param)->chan_freq_seg0) == 8)) + +/* Check if channel width is HE80p80 in HE 6ghz params */ +#define WLAN_IS_HE80_80(he_6g_param) (((he_6g_param)->width == \ + WLAN_HE_6GHZ_CHWIDTH_160_80_80) && \ + ((he_6g_param)->chan_freq_seg1 != 0) && \ + (abs((he_6g_param)->chan_freq_seg1 - \ + (he_6g_param)->chan_freq_seg0) > 8)) + #define LE_READ_2(p) \ ((uint16_t)\ ((((const uint8_t *)(p))[0]) |\ @@ -397,6 +429,7 @@ enum element_ie { WLAN_ELEMID_AID = 197, WLAN_ELEMID_QUIET_CHANNEL = 198, WLAN_ELEMID_OP_MODE_NOTIFY = 199, + WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT = 201, WLAN_ELEMID_VENDOR = 221, WLAN_ELEMID_FILS_INDICATION = 240, WLAN_ELEMID_RSNXE = 244, @@ -409,6 +442,7 @@ enum element_ie { * @WLAN_EXTN_ELEMID_HECAP: HE capabilities IE * @WLAN_EXTN_ELEMID_HEOP: HE Operation IE * @WLAN_EXTN_ELEMID_MUEDCA: MU-EDCA IE + * @WLAN_EXTN_ELEMID_HE_6G_CAP: HE 6GHz Band Capabilities IE * @WLAN_EXTN_ELEMID_SRP: spatial reuse parameter IE */ enum extn_element_ie { @@ -417,6 +451,7 @@ enum extn_element_ie { WLAN_EXTN_ELEMID_HEOP = 36, WLAN_EXTN_ELEMID_MUEDCA = 38, WLAN_EXTN_ELEMID_SRP = 39, + WLAN_EXTN_ELEMID_HE_6G_CAP = 59, WLAN_EXTN_ELEMID_ESP = 11, }; @@ -504,6 +539,19 @@ enum extn_element_ie { * listen interval is too large. * @STATUS_INVALID_FT_ACTION_FRAME_COUNT: Invalid FT Action frame count. * @STATUS_INVALID_PMKID: Invalid pairwise master key identifier (PMKID). + * + * Internal status codes: Add any internal status code just after + * STATUS_PROP_START and decrease the value of STATUS_PROP_START + * accordingly. + * + * @STATUS_PROP_START: Start of prop status codes. + * @STATUS_NO_NETWORK_FOUND: No network found + * @STATUS_AUTH_TX_FAIL: Failed to sent AUTH on air + * @STATUS_AUTH_NO_ACK_RECEIVED: No ack received for Auth tx + * @STATUS_AUTH_NO_RESP_RECEIVED: No Auth response for Auth tx + * @STATUS_ASSOC_TX_FAIL: Failed to sent Assoc on air + * @STATUS_ASSOC_NO_ACK_RECEIVED: No ack received for Assoc tx + * @STATUS_ASSOC_NO_RESP_RECEIVED: No Assoc response for Assoc tx */ enum wlan_status_code { STATUS_SUCCESS = 0, @@ -552,6 +600,16 @@ enum wlan_status_code { STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE = 51, STATUS_INVALID_FT_ACTION_FRAME_COUNT = 52, STATUS_INVALID_PMKID = 53, + + /* Error STATUS code for intenal usage*/ + STATUS_PROP_START = 65528, + STATUS_NO_NETWORK_FOUND = 65528, + STATUS_AUTH_TX_FAIL = 65529, + STATUS_AUTH_NO_ACK_RECEIVED = 65530, + STATUS_AUTH_NO_RESP_RECEIVED = 65531, + STATUS_ASSOC_TX_FAIL = 65532, + STATUS_ASSOC_NO_ACK_RECEIVED = 65533, + STATUS_ASSOC_NO_RESP_RECEIVED = 65534, }; #define WLAN_OUI_SIZE 4 @@ -1113,6 +1171,26 @@ struct wlan_ie_vhtop { uint16_t vhtop_basic_mcs_set; } qdf_packed; +/** + * struct he_oper_6g_param: 6 Ghz params for HE + * @primary_channel: HE 6GHz Primary channel number + * @width: HE 6GHz BSS Channel Width + * @duplicate_beacon: HE 6GHz Duplicate beacon field + * @reserved: Reserved bits + * @chan_freq_seg0: HE 6GHz Channel Centre Frequency Segment 0 + * @chan_freq_seg1: HE 6GHz Channel Centre Frequency Segment 1 + * @minimum_rate: HE 6GHz Minimum Rate + */ +struct he_oper_6g_param { + uint8_t primary_channel; + uint8_t width:2, + duplicate_beacon:1, + reserved:5; + uint8_t chan_freq_seg0; + uint8_t chan_freq_seg1; + uint8_t minimum_rate; +} qdf_packed; + /** * struct wlan_country_ie: country IE * @ie: country IE diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h index f2d5ef1adfa2c0b0d530b6d85fb2e5af67ae3095..161fd0158c55b249e2a8b700c0d0e93f778412cc 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -244,6 +244,20 @@ bool wlan_crypto_vdev_is_pmf_required(struct wlan_objmgr_vdev *vdev); bool wlan_crypto_is_pmf_enabled(struct wlan_objmgr_vdev *vdev, struct wlan_objmgr_peer *peer); +/** + * wlan_crypto_is_key_valid - called by mgmt txrx to check if key is valid + * @vdev: vdev + * @peer: peer + * @keyidx : key index + * + * This function gets called by mgmt txrx to check if key is valid + * + * Return: true or false + */ +bool wlan_crypto_is_key_valid(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer, + uint16_t keyidx); + /** * wlan_crypto_add_mmie - called by mgmt txrx to add mmie in frame * @vdev: vdev @@ -306,6 +320,21 @@ QDF_STATUS wlan_crypto_rsnie_check(struct wlan_crypto_params *, uint8_t *frm); */ uint8_t *wlan_crypto_build_wpaie(struct wlan_objmgr_vdev *vdev, uint8_t *iebuf); + +/** + * wlan_crypto_build_rsnie_with_pmksa() - called by mlme to build rsnie + * @vdev: vdev + * @iebuf: ie buffer + * @pmksa: pmksa struct + * + * This function gets called by mlme to build rsnie from given vdev + * + * Return: end of buffer + */ +uint8_t *wlan_crypto_build_rsnie_with_pmksa(struct wlan_objmgr_vdev *vdev, + uint8_t *iebuf, + struct wlan_crypto_pmksa *pmksa); + /** * wlan_crypto_build_rsnie - called by mlme to build rsnie * @vdev: vdev @@ -682,6 +711,16 @@ bool wlan_crypto_check_wpa_match(struct wlan_objmgr_psoc *psoc, uint16_t ie_len, struct wlan_crypto_params * peer_crypto_params); +/** + * wlan_crypto_parse_rsnxe_ie() - parse RSNXE IE + * @rsnxe_ie: RSNXE IE pointer + * @cap_len: pointer to hold len of ext capability + * + * Return: pointer to RSNXE capability or NULL + */ +uint8_t * +wlan_crypto_parse_rsnxe_ie(uint8_t *rsnxe_ie, uint8_t *cap_len); + /** * wlan_set_vdev_crypto_prarams_from_ie - Sets vdev crypto params from IE info * @vdev: vdev pointer @@ -812,6 +851,26 @@ struct wlan_crypto_key *wlan_crypto_get_key(struct wlan_objmgr_vdev *vdev, QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev, struct wlan_crypto_key *req, enum wlan_crypto_key_type key_type); + +/** + * wlan_crypto_free_vdev_key - Free keys for vdev + * @vdev: vdev object + * + * This function frees keys stored in vdev crypto object. + * + * Return: None + */ +void wlan_crypto_free_vdev_key(struct wlan_objmgr_vdev *vdev); + +/** + * wlan_crypto_reset_vdev_params - Reset params for vdev + * @vdev: vdev object + * + * This function reset params stored in vdev crypto object. + * + * Return: None + */ +void wlan_crypto_reset_vdev_params(struct wlan_objmgr_vdev *vdev); #else static inline void wlan_crypto_update_set_key_peer( struct wlan_objmgr_vdev *vdev, @@ -841,7 +900,29 @@ QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev, { return QDF_STATUS_SUCCESS; } + +static inline void wlan_crypto_free_vdev_key(struct wlan_objmgr_vdev *vdev) +{ +} + +static inline void wlan_crypto_reset_vdev_prarams(struct wlan_objmgr_vdev *vdev) +{ +} #endif /* CRYPTO_SET_KEY_CONVERGED */ + +/** + * wlan_crypto_get_peer_pmksa() - called to get pmksa based on pmksa parameter + * @vdev: vdev + * @pmksa: bssid + * + * This function is to get pmksa based on pmksa parameter + * + * Return: wlan_crypto_pmksa when match found else NULL. + */ +struct wlan_crypto_pmksa * +wlan_crypto_get_peer_pmksa(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_pmksa *pmksa); + /** * wlan_crypto_get_pmksa - called to get pmksa of bssid passed. * @vdev: vdev @@ -855,6 +936,21 @@ struct wlan_crypto_pmksa * wlan_crypto_get_pmksa(struct wlan_objmgr_vdev *vdev, struct qdf_mac_addr *bssid); +/** + * wlan_crypto_get_fils_pmksa - Get the PMKSA for FILS + * SSID, if the SSID and cache id matches + * @vdev: Pointer with VDEV object + * @cache_id: Cache id + * @ssid: Pointer to ssid + * @ssid_len: SSID length + * + * Return: PMKSA entry if the cache id and SSID matches + */ +struct wlan_crypto_pmksa * +wlan_crypto_get_fils_pmksa(struct wlan_objmgr_vdev *vdev, + uint8_t *cache_id, uint8_t *ssid, + uint8_t ssid_len); + /** * wlan_crypto_pmksa_flush - called to flush saved pmksa * @crypto_params: crypto_params @@ -880,4 +976,42 @@ QDF_STATUS wlan_crypto_set_del_pmksa(struct wlan_objmgr_vdev *vdev, struct wlan_crypto_pmksa *pmksa, bool set); +#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) +/** + * wlan_crypto_selective_clear_sae_single_pmk_entries - Clear the PMK entries + * for BSS which have the single PMK flag set other than the current connected + * AP + * @vdev: Vdev + * @conn_bssid: Connected bssid + */ +void +wlan_crypto_selective_clear_sae_single_pmk_entries( + struct wlan_objmgr_vdev *vdev, struct qdf_mac_addr *conn_bssid); + +/** + * wlan_crypto_set_sae_single_pmk_bss_cap - Set the peer SAE sinlge pmk + * feature supported status + * @vdev: Vdev + * @bssid: BSSID for which the flag is to be set + * @single_pmk_capable_bss: Flag to indicate Sae single pmk supported BSSID or + * not + */ +void wlan_crypto_set_sae_single_pmk_bss_cap(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *bssid, + bool single_pmk_capable_bss); +#else +static inline void +wlan_crypto_selective_clear_sae_single_pmk_entries( + struct wlan_objmgr_vdev *vdev, struct qdf_mac_addr *conn_bssid) +{ +} + +static inline +void wlan_crypto_set_sae_single_pmk_bss_cap(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *bssid, + bool single_pmk_capable_bss) +{ +} +#endif + #endif /* end of _WLAN_CRYPTO_GLOBAL_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h index 164140bad809d648db31ce8d9c13e1b26a76ea37..a5f489b530a6ec9087123e131761919ad35a3d7e 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -49,6 +49,9 @@ #define WLAN_CRYPTO_KEYIX_NONE ((uint16_t)-1) #define WLAN_CRYPTO_MAXKEYIDX (4) #define WLAN_CRYPTO_MAXIGTKKEYIDX (2) +#ifndef WLAN_CRYPTO_MAX_VLANKEYIX +#define WLAN_CRYPTO_MAX_VLANKEYIX WLAN_CRYPTO_MAXKEYIDX +#endif #define WLAN_CRYPTO_MAX_PMKID (16) /* 40 bit wep key len */ @@ -91,6 +94,8 @@ #define WLAN_CRYPTO_KEY_SWDECRYPT (0x100) /* host-based demic */ #define WLAN_CRYPTO_KEY_SWDEMIC (0x200) +/* get pn from fw for key */ +#define WLAN_CRYPTO_KEY_GET_PN (0x400) #define WLAN_CRYPTO_KEY_SWCRYPT (WLAN_CRYPTO_KEY_SWENCRYPT \ | WLAN_CRYPTO_KEY_SWDECRYPT) @@ -173,6 +178,12 @@ typedef enum wlan_crypto_rsn_cap { WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED = 0x40, } wlan_crypto_rsn_cap; +enum wlan_crypto_rsnx_cap { + WLAN_CRYPTO_RSNX_CAP_PROTECTED_TWT = 0x10, + WLAN_CRYPTO_RSNX_CAP_SAE_H2E = 0x20, + WLAN_CRYPTO_RSNX_CAP_SAE_PK = 0x40, +}; + typedef enum wlan_crypto_key_mgmt { WLAN_CRYPTO_KEY_MGMT_IEEE8021X = 0, WLAN_CRYPTO_KEY_MGMT_PSK = 1, @@ -198,8 +209,9 @@ typedef enum wlan_crypto_key_mgmt { WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384 = 21, WLAN_CRYPTO_KEY_MGMT_OWE = 22, WLAN_CRYPTO_KEY_MGMT_DPP = 23, + WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384 = 24, /** Keep WLAN_CRYPTO_KEY_MGMT_MAX at the end. */ - WLAN_CRYPTO_KEY_MGMT_MAX = WLAN_CRYPTO_KEY_MGMT_DPP, + WLAN_CRYPTO_KEY_MGMT_MAX = WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384, } wlan_crypto_key_mgmt; enum wlan_crypto_key_type { @@ -216,13 +228,19 @@ enum wlan_crypto_key_type { * @pmkid: pmkid info * @pmk: pmk info * @pmk_len: pmk len + * @single_pmk_supported: SAE single pmk supported BSS */ - struct wlan_crypto_pmksa { struct qdf_mac_addr bssid; uint8_t pmkid[PMKID_LEN]; uint8_t pmk[MAX_PMK_LEN]; uint8_t pmk_len; + uint8_t ssid_len; + uint8_t ssid[WLAN_SSID_MAX_LEN]; + uint8_t cache_id[WLAN_CACHE_ID_LEN]; +#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) + bool single_pmk_supported; +#endif }; /** @@ -348,6 +366,9 @@ struct wlan_crypto_req_key { * @delkey: function pointer to delkey in hw * @defaultkey: function pointer to set default key * @set_key: converged function pointer to set key in hw + * @getpn: function pointer to get current pn value of peer + * @register_events: function pointer to register wmi event handler + * @deregister_events: function pointer to deregister wmi event handler */ struct wlan_lmac_if_crypto_tx_ops { @@ -365,6 +386,10 @@ struct wlan_lmac_if_crypto_tx_ops { QDF_STATUS (*set_key)(struct wlan_objmgr_vdev *vdev, struct wlan_crypto_key *key, enum wlan_crypto_key_type key_type); + QDF_STATUS(*getpn)(struct wlan_objmgr_vdev *vdev, + uint8_t *macaddr, uint32_t key_type); + QDF_STATUS (*register_events)(struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*deregister_events)(struct wlan_objmgr_psoc *psoc); }; /** diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_main.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_main.h index 7f4e59f9591cb0b18870d747676f698e0ba1d963..20c1be62ab92b9fd2f9ffda9592625ae62b0a45f 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_main.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/inc/wlan_crypto_main.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -21,6 +21,7 @@ */ #ifndef _WLAN_CRYPTO_MAIN_H_ #define _WLAN_CRYPTO_MAIN_H_ +#include "wlan_crypto_global_def.h" /** * wlan_crypto_init - Init the crypto service with object manager @@ -38,5 +39,32 @@ QDF_STATUS wlan_crypto_init(void); */ QDF_STATUS wlan_crypto_deinit(void); +#ifdef CRYPTO_SET_KEY_CONVERGED +/** + * wlan_crypto_psoc_enable: psoc enable API for wlan crypto component + * @psoc: pointer to PSOC + * + * Return: status of operation + */ +QDF_STATUS wlan_crypto_psoc_enable(struct wlan_objmgr_psoc *psoc); + +/** + * wlan_crypto_psoc_disable: psoc disable API for wlan crypto component + * @psoc: pointer to PSOC + * + * Return: status of operation + */ +QDF_STATUS wlan_crypto_psoc_disable(struct wlan_objmgr_psoc *psoc); +#else +static inline QDF_STATUS wlan_crypto_psoc_enable(struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS wlan_crypto_psoc_disable(struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_SUCCESS; +} +#endif #endif /* end of _WLAN_CRYPTO_MAIN_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_def_i.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_def_i.h index d25e8ff46002e0d068ac8cd452663f2dea4460c0..b82e848ff9c0433c4bf5ee21e05b49e0a05cc576 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_def_i.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_def_i.h @@ -171,6 +171,12 @@ static inline void wlan_crypto_put_be64(u8 *a, u64 val) (psoc->soc_cb.tx_ops.crypto_tx_ops.defaultkey) #define WLAN_CRYPTO_TX_OPS_SET_KEY(psoc) \ ((psoc)->soc_cb.tx_ops.crypto_tx_ops.set_key) +#define WLAN_CRYPTO_TX_OPS_GETPN(psoc) \ + ((psoc)->soc_cb.tx_ops.crypto_tx_ops.getpn) +#define WLAN_CRYPTO_TX_OPS_REGISTER_EVENTS(psoc) \ + ((psoc)->soc_cb.tx_ops.crypto_tx_ops.register_events) +#define WLAN_CRYPTO_TX_OPS_DEREGISTER_EVENTS(psoc) \ + ((psoc)->soc_cb.tx_ops.crypto_tx_ops.deregister_events) /* unalligned little endian access */ #ifndef LE_READ_2 @@ -255,7 +261,7 @@ static inline void wlan_crypto_put_be64(u8 *a, u64 val) WLAN_RSN_SEL(11) #define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192\ WLAN_RSN_SEL(12) -#define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_192\ +#define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_384\ WLAN_RSN_SEL(13) #define RSN_AUTH_KEY_MGMT_FILS_SHA256 WLAN_RSN_SEL(14) #define RSN_AUTH_KEY_MGMT_FILS_SHA384 WLAN_RSN_SEL(15) @@ -420,6 +426,33 @@ struct wlan_crypto_mmie { uint8_t mic[16]; } __packed; +/** + * struct crypto_add_key_result - add key result structure + * @vdev_id: unique id identifying the VDEV + * @key_ix: key index + * @key_flags: key flags + * @status: status of add key + * @peer_macaddr: MAC address of the peer + * + * Structure used for add key result. + */ +struct crypto_add_key_result { + uint32_t vdev_id; + uint32_t key_ix; + uint32_t key_flags; + uint32_t status; + uint8_t peer_macaddr[QDF_MAC_ADDR_SIZE]; +}; + +/** + * typedef crypto_add_key_callback - add key callback + * @context: opaque context that the client can use to associate the + * callback with the request + * @result: result of add key + */ +typedef void (*crypto_add_key_callback)(void *context, + struct crypto_add_key_result *result); + /** * struct wlan_crypto_comp_priv - crypto component private structure * @crypto_params: crypto params for the peer @@ -429,16 +462,21 @@ struct wlan_crypto_mmie { * @def_tx_keyid: default key used for this peer * @def_igtk_tx_keyid default igtk key used for this peer * @fils_aead_set fils params for this peer + * @add_key_ctx: Opaque context to be used by the caller to associate the + * add key request with the response + * @add_key_cb: Callback function to be called with the add key result * */ struct wlan_crypto_comp_priv { struct wlan_crypto_params crypto_params; - struct wlan_crypto_key *key[WLAN_CRYPTO_MAXKEYIDX]; + struct wlan_crypto_key *key[WLAN_CRYPTO_MAX_VLANKEYIX]; struct wlan_crypto_key *igtk_key[WLAN_CRYPTO_MAXIGTKKEYIDX]; - uint32_t igtk_key_type; + enum wlan_crypto_cipher_type igtk_key_type; uint8_t def_tx_keyid; uint8_t def_igtk_tx_keyid; uint8_t fils_aead_set; + void *add_key_ctx; + crypto_add_key_callback add_key_cb; }; /** diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_global_api.c index 012501a4da91a09a9bf59bc9b0b1f9c6d526b567..15874754c0cd3e796b76e46ee8964cd810a1eb1d 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -35,6 +35,7 @@ #include "wlan_crypto_def_i.h" #include "wlan_crypto_param_handling_i.h" #include "wlan_crypto_obj_mgr_i.h" +#include "wlan_crypto_main.h" #include const struct wlan_crypto_cipher *wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_MAX]; @@ -359,6 +360,14 @@ QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params, if (qdf_is_macaddr_equal(&pmksa->bssid, &crypto_params->pmksa[i]->bssid)) { match_found = true; + } 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)) { + match_found = true; } if (match_found) { @@ -376,8 +385,8 @@ QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params, continue; if (crypto_params->pmksa[j]->pmk_len && (!qdf_mem_cmp(crypto_params->pmksa[j]->pmk, - del_pmk, - crypto_params->pmksa[j]->pmk_len))) { + del_pmk, + crypto_params->pmksa[j]->pmk_len))) { qdf_mem_zero(crypto_params->pmksa[j], sizeof(struct wlan_crypto_pmksa)); qdf_mem_free(crypto_params->pmksa[j]); @@ -394,7 +403,7 @@ 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"); - return QDF_STATUS_E_INVAL; + return QDF_STATUS_SUCCESS; } QDF_STATUS wlan_crypto_pmksa_flush(struct wlan_crypto_params *crypto_params) @@ -454,6 +463,48 @@ QDF_STATUS wlan_crypto_set_del_pmksa(struct wlan_objmgr_vdev *vdev, return status; } +struct wlan_crypto_pmksa * +wlan_crypto_get_peer_pmksa(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_pmksa *pmksa) +{ + struct wlan_crypto_comp_priv *crypto_priv; + struct wlan_crypto_params *crypto_params; + uint8_t i; + + if (!pmksa) { + crypto_err("pmksa is NULL"); + return NULL; + } + crypto_priv = (struct wlan_crypto_comp_priv *) + wlan_get_vdev_crypto_obj(vdev); + + if (!crypto_priv) { + crypto_err("crypto_priv NULL"); + return NULL; + } + + crypto_params = &crypto_priv->crypto_params; + + 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)) { + 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)){ + return crypto_params->pmksa[i]; + } + } + + return NULL; +} + struct wlan_crypto_pmksa * wlan_crypto_get_pmksa(struct wlan_objmgr_vdev *vdev, struct qdf_mac_addr *bssid) { @@ -486,6 +537,41 @@ wlan_crypto_get_pmksa(struct wlan_objmgr_vdev *vdev, struct qdf_mac_addr *bssid) return NULL; } + +struct wlan_crypto_pmksa * +wlan_crypto_get_fils_pmksa(struct wlan_objmgr_vdev *vdev, + uint8_t *cache_id, uint8_t *ssid, + uint8_t ssid_len) +{ + struct wlan_crypto_comp_priv *crypto_priv; + struct wlan_crypto_params *crypto_params; + uint8_t i; + + crypto_priv = (struct wlan_crypto_comp_priv *) + wlan_get_vdev_crypto_obj(vdev); + + if (!crypto_priv) { + crypto_err("crypto_priv NULL"); + return NULL; + } + + crypto_params = &crypto_priv->crypto_params; + for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) { + if (!crypto_params->pmksa[i]) + continue; + + if (!qdf_mem_cmp(cache_id, + crypto_params->pmksa[i]->cache_id, + WLAN_CACHE_ID_LEN) && + !qdf_mem_cmp(ssid, crypto_params->pmksa[i]->ssid, + ssid_len) && + ssid_len == crypto_params->pmksa[i]->ssid_len) + return crypto_params->pmksa[i]; + } + + return NULL; +} + /** * wlan_crypto_is_htallowed - called to check is HT allowed for cipher * @vdev: vdev @@ -597,7 +683,7 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, | WLAN_CRYPTO_KEY_RECV); } } else { - if ((req_key->keyix >= WLAN_CRYPTO_MAXKEYIDX) + if ((req_key->keyix >= WLAN_CRYPTO_MAX_VLANKEYIX) && (!IS_MGMT_CIPHER(req_key->type))) { return QDF_STATUS_E_INVAL; } @@ -737,7 +823,7 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, uint16_t kid = req_key->keyix; if (kid == WLAN_CRYPTO_KEYIX_NONE) kid = 0; - if (kid >= WLAN_CRYPTO_MAXKEYIDX) { + if (kid >= WLAN_CRYPTO_MAX_VLANKEYIX) { crypto_err("invalid keyid %d", kid); return QDF_STATUS_E_INVAL; } @@ -994,6 +1080,10 @@ QDF_STATUS wlan_crypto_getkey(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_NOENT; } key = wlan_crypto_peer_getkey(peer, req_key->keyix); + if (WLAN_CRYPTO_TX_OPS_GETPN(psoc) && + (req_key->flags & WLAN_CRYPTO_KEY_GET_PN)) + WLAN_CRYPTO_TX_OPS_GETPN(psoc)(vdev, mac_addr, + req_key->type); wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID); if (!key) return QDF_STATUS_E_INVAL; @@ -1121,11 +1211,18 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev, cipher_table = (struct wlan_crypto_cipher *)key->cipher_table; qdf_mem_zero(key->keyval, sizeof(key->keyval)); - if (WLAN_CRYPTO_TX_OPS_DELKEY(psoc)) { + if (!IS_FILS_CIPHER(cipher_table->cipher) && + WLAN_CRYPTO_TX_OPS_DELKEY(psoc)) { WLAN_CRYPTO_TX_OPS_DELKEY(psoc)(vdev, key, macaddr, cipher_table->cipher); + } else if (IS_FILS_CIPHER(cipher_table->cipher)) { + if (key->private) + qdf_mem_free(key->private); } } + + /* Zero-out local key variables */ + qdf_mem_zero(key, sizeof(struct wlan_crypto_key)); qdf_mem_free(key); return QDF_STATUS_SUCCESS; @@ -1750,6 +1847,36 @@ bool wlan_crypto_is_pmf_enabled(struct wlan_objmgr_vdev *vdev, return false; } +/** + * wlan_crypto_is_key_valid - called by mgmt txrx to check if key is valid + * @vdev: vdev + * @peer: peer + * @keyidx : key index + * + * This function gets called by mgmt txrx to check if key is valid + * + * Return: true or false + */ +bool wlan_crypto_is_key_valid(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer, + uint16_t keyidx) +{ + struct wlan_crypto_key *key = NULL; + + if (!vdev && !peer) + return false; + + if (peer) + key = wlan_crypto_peer_getkey(peer, keyidx); + else if (vdev) + key = wlan_crypto_vdev_getkey(vdev, keyidx); + + if ((key) && key->valid) + return true; + + return false; +} + static void wlan_crypto_gmac_pn_swap(uint8_t *a, uint8_t *b) { a[0] = b[5]; @@ -2285,6 +2412,8 @@ static int32_t wlan_crypto_rsn_suite_to_keymgmt(uint8_t *sel) return WLAN_CRYPTO_KEY_MGMT_OWE; case RSN_AUTH_KEY_MGMT_DPP: return WLAN_CRYPTO_KEY_MGMT_DPP; + case RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_384: + return WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384; } return status; @@ -2311,7 +2440,6 @@ QDF_STATUS wlan_crypto_wpaie_check(struct wlan_crypto_params *crypto_params, * version, mcast cipher, and 2 selector counts. * Other, variable-length data, must be checked separately. */ - RESET_AUTHMODE(crypto_params); SET_AUTHMODE(crypto_params, WLAN_CRYPTO_AUTH_WPA); if (len < 14) @@ -2326,7 +2454,6 @@ QDF_STATUS wlan_crypto_wpaie_check(struct wlan_crypto_params *crypto_params, frm += 2, len -= 2; /* multicast/group cipher */ - RESET_MCAST_CIPHERS(crypto_params); w = wlan_crypto_wpa_suite_to_cipher(frm); if (w < 0) return QDF_STATUS_E_INVAL; @@ -2339,7 +2466,6 @@ QDF_STATUS wlan_crypto_wpaie_check(struct wlan_crypto_params *crypto_params, if (len < n*4+2) return QDF_STATUS_E_INVAL; - RESET_UCAST_CIPHERS(crypto_params); for (; n > 0; n--) { w = wlan_crypto_wpa_suite_to_cipher(frm); if (w < 0) @@ -2358,7 +2484,6 @@ QDF_STATUS wlan_crypto_wpaie_check(struct wlan_crypto_params *crypto_params, return QDF_STATUS_E_INVAL; w = 0; - RESET_KEY_MGMT(crypto_params); for (; n > 0; n--) { w = wlan_crypto_wpa_suite_to_keymgmt(frm); if (w < 0) @@ -2373,7 +2498,7 @@ QDF_STATUS wlan_crypto_wpaie_check(struct wlan_crypto_params *crypto_params, frm += 2, len -= 2; } - return 0; + return QDF_STATUS_SUCCESS; } /** @@ -2615,19 +2740,9 @@ uint8_t *wlan_crypto_build_wpaie(struct wlan_objmgr_vdev *vdev, return frm; } -/** - * wlan_crypto_build_rsnie - called by mlme to build rsnie - * @vdev: vdev - * @iebuf: ie buffer - * @bssid: bssid mac address to add pmkid in rsnie - * - * This function gets called by mlme to build rsnie from given vdev - * - * Return: end of buffer - */ -uint8_t *wlan_crypto_build_rsnie(struct wlan_objmgr_vdev *vdev, - uint8_t *iebuf, - struct qdf_mac_addr *bssid) +uint8_t *wlan_crypto_build_rsnie_with_pmksa(struct wlan_objmgr_vdev *vdev, + uint8_t *iebuf, + struct wlan_crypto_pmksa *pmksa) { uint8_t *frm = iebuf; uint8_t *selcnt; @@ -2779,20 +2894,13 @@ uint8_t *wlan_crypto_build_rsnie(struct wlan_objmgr_vdev *vdev, /* optional capabilities */ if (crypto_params->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) { /* PMK list */ - if (bssid) { - struct wlan_crypto_pmksa *pmksa; - - pmksa = wlan_crypto_get_pmksa(vdev, bssid); - - if (pmksa) { - WLAN_CRYPTO_ADDSHORT(frm, 1); - qdf_mem_copy(frm, pmksa->pmkid, PMKID_LEN); - frm += PMKID_LEN; - } else { - WLAN_CRYPTO_ADDSHORT(frm, 0); - } - } else + if (pmksa) { + WLAN_CRYPTO_ADDSHORT(frm, 1); + qdf_mem_copy(frm, pmksa->pmkid, PMKID_LEN); + frm += PMKID_LEN; + } else { WLAN_CRYPTO_ADDSHORT(frm, 0); + } if (HAS_MGMT_CIPHER(crypto_params, WLAN_CRYPTO_CIPHER_AES_CMAC)) { @@ -2819,17 +2927,10 @@ uint8_t *wlan_crypto_build_rsnie(struct wlan_objmgr_vdev *vdev, } } else { /* PMK list */ - if (bssid) { - struct wlan_crypto_pmksa *pmksa; - - pmksa = wlan_crypto_get_pmksa(vdev, bssid); - if (pmksa) { - WLAN_CRYPTO_ADDSHORT(frm, 1); - qdf_mem_copy(frm, pmksa->pmkid, PMKID_LEN); - frm += PMKID_LEN; - } else { - WLAN_CRYPTO_ADDSHORT(frm, 0); - } + if (pmksa) { + WLAN_CRYPTO_ADDSHORT(frm, 1); + qdf_mem_copy(frm, pmksa->pmkid, PMKID_LEN); + frm += PMKID_LEN; } } @@ -2839,6 +2940,18 @@ uint8_t *wlan_crypto_build_rsnie(struct wlan_objmgr_vdev *vdev, return frm; } +uint8_t *wlan_crypto_build_rsnie(struct wlan_objmgr_vdev *vdev, + uint8_t *iebuf, + struct qdf_mac_addr *bssid) +{ + struct wlan_crypto_pmksa *pmksa = NULL; + + if (bssid) + pmksa = wlan_crypto_get_pmksa(vdev, bssid); + + return wlan_crypto_build_rsnie_with_pmksa(vdev, iebuf, pmksa); +} + bool wlan_crypto_rsn_info(struct wlan_objmgr_vdev *vdev, struct wlan_crypto_params *crypto_params){ struct wlan_crypto_params *my_crypto_params; @@ -2940,7 +3053,6 @@ QDF_STATUS wlan_crypto_wapiie_check(struct wlan_crypto_params *crypto_params, * version, mcast cipher, and 2 selector counts. * Other, variable-length data, must be checked separately. */ - RESET_AUTHMODE(crypto_params); SET_AUTHMODE(crypto_params, WLAN_CRYPTO_AUTH_WAPI); if (len < WLAN_CRYPTO_WAPI_IE_LEN) @@ -2959,7 +3071,6 @@ QDF_STATUS wlan_crypto_wapiie_check(struct wlan_crypto_params *crypto_params, if (len < n*4+2) return QDF_STATUS_E_INVAL; - RESET_KEY_MGMT(crypto_params); for (; n > 0; n--) { w = wlan_crypto_wapi_keymgmt(frm); if (w < 0) @@ -2975,7 +3086,6 @@ QDF_STATUS wlan_crypto_wapiie_check(struct wlan_crypto_params *crypto_params, if (len < n*4+2) return QDF_STATUS_E_INVAL; - RESET_UCAST_CIPHERS(crypto_params); for (; n > 0; n--) { w = wlan_crypto_wapi_suite_to_cipher(frm); if (w < 0) @@ -2988,7 +3098,6 @@ QDF_STATUS wlan_crypto_wapiie_check(struct wlan_crypto_params *crypto_params, return QDF_STATUS_E_INVAL; /* multicast/group cipher */ - RESET_MCAST_CIPHERS(crypto_params); w = wlan_crypto_wapi_suite_to_cipher(frm); if (w < 0) @@ -3799,7 +3908,7 @@ wlan_get_crypto_params_from_rsn_ie(struct wlan_crypto_params *crypto_params, qdf_mem_zero(crypto_params, sizeof(struct wlan_crypto_params)); rsn_ie = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSN, ie_ptr, ie_len); if (!rsn_ie) { - crypto_err("RSN IE NULL"); + crypto_debug("RSN IE not present"); return QDF_STATUS_E_INVAL; } @@ -3826,7 +3935,7 @@ wlan_get_crypto_params_from_wpa_ie(struct wlan_crypto_params *crypto_params, wpa_ie = wlan_get_vendor_ie_ptr_from_oui((uint8_t *)&wpa_oui, WLAN_OUI_SIZE, ie_ptr, ie_len); if (!wpa_ie) { - crypto_err("WPA IE NULL"); + crypto_debug("WPA IE not present"); return QDF_STATUS_E_INVAL; } @@ -3951,11 +4060,31 @@ wlan_crypto_reset_prarams(struct wlan_crypto_params *params) params->ucastcipherset = 0; params->mcastcipherset = 0; params->mgmtcipherset = 0; - params->cipher_caps = 0; params->key_mgmt = 0; params->rsn_caps = 0; } +uint8_t * +wlan_crypto_parse_rsnxe_ie(uint8_t *rsnxe_ie, uint8_t *cap_len) +{ + uint8_t len; + uint8_t *ie; + + if (!rsnxe_ie) + return NULL; + + ie = rsnxe_ie; + len = ie[1]; + ie += 2; + + if (!len) + return NULL; + + *cap_len = ie[0] & 0xf; + + return ie; +} + QDF_STATUS wlan_set_vdev_crypto_prarams_from_ie(struct wlan_objmgr_vdev *vdev, uint8_t *ie_ptr, uint16_t ie_len) @@ -3989,20 +4118,16 @@ QDF_STATUS wlan_set_vdev_crypto_prarams_from_ie(struct wlan_objmgr_vdev *vdev, wlan_crypto_reset_prarams(vdev_crypto_params); status = wlan_get_crypto_params_from_rsn_ie(&crypto_params, ie_ptr, ie_len); - if (QDF_STATUS_SUCCESS == status) { + if (QDF_IS_STATUS_SUCCESS(status)) wlan_crypto_merge_prarams(vdev_crypto_params, &crypto_params); - } else { - crypto_err("get crypto prarams from RSN IE failed"); + else send_fail = true; - } status = wlan_get_crypto_params_from_wpa_ie(&crypto_params, ie_ptr, ie_len); - if (QDF_STATUS_SUCCESS == status) { + if (QDF_IS_STATUS_SUCCESS(status)) { wlan_crypto_merge_prarams(vdev_crypto_params, &crypto_params); send_fail = false; - } else { - crypto_debug("get crypto prarams from WPA IE failed"); } return send_fail ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS; @@ -4091,11 +4216,15 @@ QDF_STATUS wlan_crypto_save_key(struct wlan_objmgr_vdev *vdev, crypto_err("Invalid Key index %d", key_index); return QDF_STATUS_E_FAILURE; } - if (key_index < WLAN_CRYPTO_MAXKEYIDX) + if (key_index < WLAN_CRYPTO_MAXKEYIDX) { crypto_priv->key[key_index] = crypto_key; - else + } else { crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX] = crypto_key; + crypto_priv->def_igtk_tx_keyid = + key_index - WLAN_CRYPTO_MAXKEYIDX; + crypto_priv->igtk_key_type = crypto_key->cipher_type; + } return QDF_STATUS_SUCCESS; } @@ -4149,4 +4278,100 @@ void wlan_crypto_update_set_key_peer(struct wlan_objmgr_vdev *vdev, qdf_mem_copy(crypto_key->macaddr, peer_mac, QDF_MAC_ADDR_SIZE); } + +#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) +void wlan_crypto_selective_clear_sae_single_pmk_entries( + struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *conn_bssid) +{ + struct wlan_crypto_params *crypto_params; + struct wlan_crypto_comp_priv *crypto_priv; + int i; + + crypto_priv = (struct wlan_crypto_comp_priv *) + wlan_get_vdev_crypto_obj(vdev); + + if (!crypto_priv) { + crypto_err("crypto_priv NULL"); + return; + } + + crypto_params = &crypto_priv->crypto_params; + + for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) { + if (!crypto_params->pmksa[i]) + continue; + + if (crypto_params->pmksa[i]->single_pmk_supported && + !qdf_is_macaddr_equal(conn_bssid, + &crypto_params->pmksa[i]->bssid)) { + qdf_mem_zero(crypto_params->pmksa[i], + sizeof(struct wlan_crypto_pmksa)); + qdf_mem_free(crypto_params->pmksa[i]); + crypto_params->pmksa[i] = NULL; + } + } +} + +void wlan_crypto_set_sae_single_pmk_bss_cap(struct wlan_objmgr_vdev *vdev, + struct qdf_mac_addr *bssid, + bool single_pmk_capable_bss) +{ + struct wlan_crypto_params *crypto_params; + struct wlan_crypto_comp_priv *crypto_priv; + int i; + + crypto_priv = (struct wlan_crypto_comp_priv *) + wlan_get_vdev_crypto_obj(vdev); + + if (!crypto_priv) { + crypto_err("crypto_priv NULL"); + return; + } + + crypto_params = &crypto_priv->crypto_params; + + for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) { + if (!crypto_params->pmksa[i]) + continue; + + if (qdf_is_macaddr_equal(bssid, + &crypto_params->pmksa[i]->bssid)) + crypto_params->pmksa[i]->single_pmk_supported = + single_pmk_capable_bss; + } +} +#endif + +void wlan_crypto_reset_vdev_params(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_crypto_comp_priv *crypto_priv; + + crypto_debug("reset params for vdev %d", wlan_vdev_get_id(vdev)); + crypto_priv = (struct wlan_crypto_comp_priv *) + wlan_get_vdev_crypto_obj(vdev); + + if (!crypto_priv) { + crypto_err("crypto_priv NULL"); + return; + } + + wlan_crypto_reset_prarams(&crypto_priv->crypto_params); +} + +QDF_STATUS wlan_crypto_psoc_enable(struct wlan_objmgr_psoc *psoc) +{ + if (psoc && WLAN_CRYPTO_TX_OPS_REGISTER_EVENTS(psoc)) + return WLAN_CRYPTO_TX_OPS_REGISTER_EVENTS(psoc)(psoc); + + return QDF_STATUS_E_FAILURE; +} + +QDF_STATUS wlan_crypto_psoc_disable(struct wlan_objmgr_psoc *psoc) +{ + if (psoc && WLAN_CRYPTO_TX_OPS_DEREGISTER_EVENTS(psoc)) + return WLAN_CRYPTO_TX_OPS_DEREGISTER_EVENTS(psoc)(psoc); + + return QDF_STATUS_E_FAILURE; +} #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c index 401ca5c7d09b8d0bca559a9415b88be9446a9115..91d163b7ff44c5ffd0e0531d2674fbfddaddf281 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c @@ -197,6 +197,22 @@ static void wlan_crypto_free_key(struct wlan_crypto_comp_priv *crypto_priv) } +#ifdef CRYPTO_SET_KEY_CONVERGED +void wlan_crypto_free_vdev_key(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_crypto_comp_priv *crypto_priv; + + crypto_debug("free key for vdev %d", wlan_vdev_get_id(vdev)); + crypto_priv = wlan_get_vdev_crypto_obj(vdev); + if (!crypto_priv) { + crypto_err("crypto_priv NULL"); + return; + } + + wlan_crypto_free_key(crypto_priv); +} +#endif + static QDF_STATUS wlan_crypto_vdev_obj_destroy_handler( struct wlan_objmgr_vdev *vdev, void *arg){ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/inc/wlan_cmn.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/inc/wlan_cmn.h index 99bf306da96182dfd623580c29ea036203466860..1a346c79c10a9fc19fe414ff00386a6d65cc6122 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/inc/wlan_cmn.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/inc/wlan_cmn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 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 @@ -61,6 +61,8 @@ /* Max length of a SSID */ #define WLAN_SSID_MAX_LEN 32 +#define WLAN_CACHE_ID_LEN 2 + /* Max sequence number */ #define WLAN_MAX_SEQ_NUM 4096 @@ -272,7 +274,10 @@ * @WLAN_UMAC_COMP_FWOL FW Offload * @WLAN_UMAC_COMP_INTEROP_ISSUES_AP interop issues ap component * @WLAN_UMAC_COMP_BLACKLIST_MGR: Blacklist mgr component + * @WLAN_UMAC_COMP_COEX: Coex config component + * @WLAN_UMAC_COMP_FTM_TIME_SYNC: WLAN FTM TIMESYNC * @WLAN_UMAC_COMP_PKT_CAPTURE: Packet capture component + * @WLAN_UMAC_COMP_GPIO: GPIO Configuration * @WLAN_UMAC_COMP_ID_MAX: Maximum components in UMAC * * This id is static. @@ -312,7 +317,10 @@ enum wlan_umac_comp_id { WLAN_UMAC_COMP_CFR = 30, WLAN_UMAC_COMP_INTEROP_ISSUES_AP = 31, WLAN_UMAC_COMP_BLACKLIST_MGR = 32, - WLAN_UMAC_COMP_PKT_CAPTURE = 33, + WLAN_UMAC_COMP_COEX = 33, + WLAN_UMAC_COMP_FTM_TIME_SYNC = 34, + WLAN_UMAC_COMP_PKT_CAPTURE = 35, + WLAN_UMAC_COMP_GPIO = 39, WLAN_UMAC_COMP_ID_MAX, }; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h index 5aeab067fdec74a5129b922752917ccd943bce66..1044b04a7233f769e2f5e5a4559ee9ebdf94dfc2 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h @@ -30,12 +30,6 @@ #include "wlan_objmgr_cmn.h" #include "qdf_nbuf.h" -#ifdef CONFIG_MCL -#define MGMT_DESC_POOL_MAX 64 -#else -#define MGMT_DESC_POOL_MAX 512 -#endif - #define mgmt_txrx_alert(params...) \ QDF_TRACE_FATAL(QDF_MODULE_ID_MGMT_TXRX, params) #define mgmt_txrx_err(params...) \ @@ -246,6 +240,20 @@ enum rrm_actioncode { RRM_NEIGHBOR_RPT, }; +/** + * enum ft_actioncode - ft action frames + * @FT_FAST_BSS_TRNST_REQ: ft request frame + * @FT_FAST_BSS_TRNST_RES: ft response frame + * @FT_FAST_BSS_TRNST_CONFIRM: ft confirm frame + * @FT_FAST_BSS_TRNST_ACK: ft ACK frame + */ +enum ft_actioncode { + FT_FAST_BSS_TRNST_REQ = 1, + FT_FAST_BSS_TRNST_RES, + FT_FAST_BSS_TRNST_CONFIRM, + FT_FAST_BSS_TRNST_ACK, +}; + /** * enum ht_actioncode - ht action frames * @HT_ACTION_NOTIFY_CHANWIDTH: ht notify bw action frame @@ -608,6 +616,10 @@ enum mgmt_frame_type { MGMT_ACTION_RRM_LINK_MEASUREMENT_RPT, MGMT_ACTION_RRM_NEIGHBOR_REQ, MGMT_ACTION_RRM_NEIGHBOR_RPT, + MGMT_ACTION_FT_REQUEST, + MGMT_ACTION_FT_RESPONSE, + MGMT_ACTION_FT_CONFIRM, + MGMT_ACTION_FT_ACK, MGMT_ACTION_HT_NOTIFY_CHANWIDTH, MGMT_ACTION_HT_SMPS, MGMT_ACTION_HT_PSMP, @@ -689,6 +701,7 @@ enum mgmt_frame_type { #define WLAN_NOISE_FLOOR_DBM_DEFAULT -96 /** * struct mgmt_rx_event_params - host mgmt header params + * @chan_freq: channel frequency on which this frame is received * @channel: channel on which this frame is received * @snr: snr information used to call rssi * @rssi_ctl[WLAN_MGMT_TXRX_HOST_MAX_ANTENNA]: RSSI of PRI 20MHz for each chain @@ -705,6 +718,7 @@ enum mgmt_frame_type { * (win specific, will be removed in phase 4) */ struct mgmt_rx_event_params { + uint32_t chan_freq; uint32_t channel; uint32_t snr; uint8_t rssi_ctl[WLAN_MGMT_TXRX_HOST_MAX_ANTENNA]; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c index 93c5aee68a55b3f7bd706750808e887fd59b82d9..3aadfd8cc5097270e569ff3858716a9c3c724e19 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c @@ -258,6 +258,32 @@ mgmt_get_rrm_action_subtype(uint8_t action_code) return frm_type; } +static enum mgmt_frame_type +mgmt_get_ft_action_subtype(uint8_t action_code) +{ + enum mgmt_frame_type frm_type; + + switch (action_code) { + case FT_FAST_BSS_TRNST_REQ: + frm_type = MGMT_ACTION_FT_REQUEST; + break; + case FT_FAST_BSS_TRNST_RES: + frm_type = MGMT_ACTION_FT_RESPONSE; + break; + case FT_FAST_BSS_TRNST_CONFIRM: + frm_type = MGMT_ACTION_FT_CONFIRM; + break; + case FT_FAST_BSS_TRNST_ACK: + frm_type = MGMT_ACTION_FT_ACK; + break; + default: + frm_type = MGMT_FRM_UNSPECIFIED; + break; + } + + return frm_type; +} + /** * mgmt_get_ht_action_subtype() - gets ht action subtype * @action_code: action code @@ -710,6 +736,9 @@ mgmt_txrx_get_action_frm_subtype(uint8_t *mpdu_data_ptr) frm_type = mgmt_get_spec_mgmt_action_subtype( action_hdr->action_code); break; + case ACTION_FAST_BSS_TRNST: + frm_type = mgmt_get_ft_action_subtype(action_hdr->action_code); + break; case ACTION_CATEGORY_QOS: frm_type = mgmt_get_qos_action_subtype(action_hdr->action_code); break; @@ -942,8 +971,9 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler( wh->i_addr3); if (!is_from_addr_valid && !is_bssid_valid) { - mgmt_txrx_debug_rl("from addr %pM bssid addr %pM both not valid, dropping them", - wh->i_addr2, wh->i_addr3); + mgmt_txrx_debug_rl("from addr "QDF_MAC_ADDR_FMT" bssid addr "QDF_MAC_ADDR_FMT" both not valid, dropping them", + QDF_MAC_ADDR_REF(wh->i_addr2), + QDF_MAC_ADDR_REF(wh->i_addr3)); qdf_nbuf_free(buf); return QDF_STATUS_E_FAILURE; } @@ -951,8 +981,9 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler( if ((mgmt_subtype == MGMT_SUBTYPE_BEACON || mgmt_subtype == MGMT_SUBTYPE_PROBE_RESP) && !(is_from_addr_valid && is_bssid_valid)) { - mgmt_txrx_debug_rl("from addr %pM bssid addr %pM not valid, modifying them", - wh->i_addr2, wh->i_addr3); + mgmt_txrx_debug_rl("from addr "QDF_MAC_ADDR_FMT" bssid addr "QDF_MAC_ADDR_FMT" not valid, modifying them", + QDF_MAC_ADDR_REF(wh->i_addr2), + QDF_MAC_ADDR_REF(wh->i_addr3)); if (!is_from_addr_valid) qdf_mem_copy(wh->i_addr2, wh->i_addr3, QDF_MAC_ADDR_SIZE); @@ -1004,8 +1035,9 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler( if (!(mgmt_subtype == MGMT_SUBTYPE_BEACON || mgmt_subtype == MGMT_SUBTYPE_PROBE_RESP || mgmt_subtype == MGMT_SUBTYPE_PROBE_REQ)) - mgmt_txrx_debug("Rcvd mgmt frame subtype %x (frame type %u) from %pM, seq_num = %d, rssi = %d tsf_delta: %u", - mgmt_subtype, frm_type, wh->i_addr2, + mgmt_txrx_debug("Rcvd mgmt frame subtype %x (frame type %u) from "QDF_MAC_ADDR_FMT", seq_num = %d, rssi = %d tsf_delta: %u", + mgmt_subtype, frm_type, + QDF_MAC_ADDR_REF(wh->i_addr2), (le16toh(*(uint16_t *)wh->i_seq) >> WLAN_SEQ_SEQ_SHIFT), mgmt_rx_params->rssi, mgmt_rx_params->tsf_delta); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c index 587a058c086228294655b17db196adad422273ac..5889f146fa7d655995aa3b067ef63a80d37505bd 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c @@ -128,7 +128,7 @@ static QDF_STATUS wlan_mgmt_txrx_psoc_obj_destroy_notification( qdf_spinlock_destroy(&mgmt_txrx_psoc_ctx->mgmt_txrx_psoc_ctx_lock); qdf_mem_free(mgmt_txrx_psoc_ctx); - mgmt_txrx_debug("mgmt txrx deletion successful, psoc: %pK", psoc); + mgmt_txrx_debug("mgmt txrx deletion successful"); return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h index e1a23a0e94187ea817d3ee08d3daba160fb3705a..fd758ccd079795d1f8da565ccdc9d59f6da29ce4 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -174,6 +174,9 @@ typedef QDF_STATUS (*wlan_objmgr_vdev_destroy_handler)( typedef void (*wlan_objmgr_vdev_status_handler)( struct wlan_objmgr_vdev *vdev, void *arg, QDF_STATUS status); +typedef void (*wlan_objmgr_vdev_peer_free_notify_handler)( + struct wlan_objmgr_vdev *vdev); + typedef QDF_STATUS (*wlan_objmgr_peer_create_handler)( struct wlan_objmgr_peer *peer, void *arg); @@ -229,7 +232,7 @@ typedef void (*wlan_objmgr_peer_status_handler)( * @WLAN_MLME_OBJ_DEL_ID: Object delete req/resp tracking with FW * @WLAN_ACTION_OUI_ID: action oui operations * @WLAN_LEGACY_SAP_ID: legacy sap fsm - * @WLAN_TGT_IF_DP_PEER_REF_ID: cp peer reference in dp (Target IF) + * @WLAN_PDEV_TARGET_IF_ID: Target interface layer for pdev APIs * @WLAN_MLME_SER_IF_ID: mlme serialization interface layer * @WLAN_SCHEDULER_ID: mlme scheduler * @WLAN_CFR_ID: CFG Capture method @@ -256,6 +259,8 @@ typedef void (*wlan_objmgr_peer_status_handler)( * @WLAN_MISC_ID: power manager, PAPI, rate set, etc. * @WLAN_FWOL_NB_ID: fw offload northbound operations * @WLAN_FWOL_SB_ID: fw offload southbound operations + * @WLAN_PSOC_TARGET_IF_ID PSOC related target_if operations + * @FTM_TIME_SYNC_ID: ftm time sync operations * @WLAN_PKT_CAPTURE_ID Packet capture operations * @WLAN_REF_ID_MAX: Max id used to generate ref count tracking array */ @@ -308,13 +313,13 @@ typedef enum { WLAN_MLME_OBJ_DEL_ID = 42, WLAN_ACTION_OUI_ID = 43, WLAN_LEGACY_SAP_ID = 44, - WLAN_TGT_IF_DP_PEER_REF_ID = 45, + WLAN_PDEV_TARGET_IF_ID = 45, WLAN_MLME_SER_IF_ID = 46, WLAN_SCHEDULER_ID = 47, WLAN_CFR_ID = 48, WLAN_VDEV_TARGET_IF_ID = 49, WLAN_RX_PKT_TAG_ID = 50, - WLAN_INTEROP_ISSUES_AP_ID = 51, + WLAN_INTEROP_ISSUES_AP_ID = 51, WLAN_WDS_ID = 52, WLAN_PROXY_ARP_ID = 53, WLAN_WNM_ID = 54, @@ -335,7 +340,9 @@ typedef enum { WLAN_MISC_ID = 69, WLAN_FWOL_NB_ID = 70, WLAN_FWOL_SB_ID = 71, - WLAN_PKT_CAPTURE_ID = 72, + WLAN_PSOC_TARGET_IF_ID = 72, + FTM_TIME_SYNC_ID = 73, + WLAN_PKT_CAPTURE_ID = 74, WLAN_REF_ID_MAX, } wlan_objmgr_ref_dbgid; @@ -394,7 +401,7 @@ static inline char *string_from_dbgid(wlan_objmgr_ref_dbgid id) "WLAN_MLME_OBJ_DEL_ID", "WLAN_ACTION_OUI_ID", "WLAN_LEGACY_SAP_ID", - "WLAN_TGT_IF_DP_PEER_REF_ID", + "WLAN_PDEV_TARGET_IF_ID", "WLAN_MLME_SER_IF_ID", "WLAN_SCHEDULER_ID", "WLAN_CFR_ID", @@ -421,6 +428,9 @@ static inline char *string_from_dbgid(wlan_objmgr_ref_dbgid id) "WLAN_MISC_ID", "WLAN_FWOL_NB_ID", "WLAN_FWOL_SB_ID", + "WLAN_PSOC_TARGET_IF_ID", + "FTM_TIME_SYNC_ID", + "WLAN_PKT_CAPTURE_ID", "WLAN_REF_ID_MAX"}; return (char *)strings[id]; @@ -432,4 +442,62 @@ static inline char *string_from_dbgid(wlan_objmgr_ref_dbgid id) #define WLAN_OBJMGR_BUG(val) #endif #define WLAN_OBJMGR_RATELIMIT_THRESH 2 + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +#define WLAN_OBJMGR_TRACE_FUNC_SIZE 30 +/** + * struct wlan_objmgr_line_ref - line reference data + * @line: line number + * @cnt: line reference count + */ +struct wlan_objmgr_line_ref { + uint32_t line; + qdf_atomic_t cnt; +}; + +/** + * struct wlan_objmgr_line_ref_node - line reference node + * @line_ref: line reference data + * @next: pointer to next line reference + */ +struct wlan_objmgr_line_ref_node { + struct wlan_objmgr_line_ref line_ref; + struct wlan_objmgr_line_ref_node *next; +}; + +/** + * struct wlan_objmgr_trace_func - trace function data + * @func: function pointer + * @line_head: pointer to head line trace reference + * @next: pointer to next function reference + */ +struct wlan_objmgr_trace_func { + char func[WLAN_OBJMGR_TRACE_FUNC_SIZE]; + struct wlan_objmgr_line_ref_node *line_head; + struct wlan_objmgr_trace_func *next; +}; + +/** + * struct wlan_objmgr_trace_id - trace reference data + * @num_func: num of functions + * @head: head pointer to function reference + */ +struct wlan_objmgr_trace_id { + uint32_t num_func; + struct wlan_objmgr_trace_func *head; +}; + +/** + * struct wlan_objmgr_trace - trace reference data + * @references: reference data + * @dereferences: dereference data + * @trace_lock: lock + */ +struct wlan_objmgr_trace { + struct wlan_objmgr_trace_id references[WLAN_REF_ID_MAX]; + struct wlan_objmgr_trace_id dereferences[WLAN_REF_ID_MAX]; + qdf_spinlock_t trace_lock; +}; +#endif /*WLAN_OBJMGR_REF_ID_TRACE*/ + #endif /* _WLAN_OBJMGR_CMN_H_*/ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_debug.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_debug.h index 2df21f0d6d2b3f546a5af044c462c39a91f8fd76..ee5c5430a6472a532a45e3732271061d1ff77e53 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_debug.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_debug.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 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 @@ -93,4 +93,53 @@ wlan_objmgr_debug_info_deinit(void) #endif /*WLAN_OBJMGR_DEBUG*/ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +/** + * wlan_objmgr_trace_ref() - Save trace info to list + * @func_head: head object of function list + * @trace: trace object + * @func: function name + * @line: line number + * + * API to trace func and line information for reference + * and dereference + * + * Return: void + */ +void +wlan_objmgr_trace_ref(struct wlan_objmgr_trace_func **func_head, + struct wlan_objmgr_trace *trace, + const char *func, int line); + +/** + * wlan_objmgr_trace_init_lock() - Initialize trace spinlock + * @trace: trace object + * + * API to initialize trace spin lock + * + * Return: void + */ +void wlan_objmgr_trace_init_lock(struct wlan_objmgr_trace *trace); + +/** + * wlan_objmgr_trace_deinit_lock() - Deinitialize trace spinlock + * @trace: trace object + * + * API to deinitialize trace spin lock + * + * Return: void + */ +void wlan_objmgr_trace_deinit_lock(struct wlan_objmgr_trace *trace); + +/** + * wlan_objmgr_trace_del_ref_list() - Delete reference trace list + * @trace: trace object + * + * API to delete trace list + * + * Return: void + */ +void wlan_objmgr_trace_del_ref_list(struct wlan_objmgr_trace *trace); +#endif /*WLAN_OBJMGR_REF_ID_TRACE*/ + #endif /*_WLAN_OBJMGR_DEBUG_H_*/ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h index 6899ea9c453144d0273b079a6ab0a14f781d82cc..64b1daead5a80a145f6c0460fe88fb0a122f53ab 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h @@ -374,6 +374,39 @@ QDF_STATUS wlan_objmgr_unregister_vdev_status_handler( wlan_objmgr_vdev_status_handler handler, void *args); +/** + * wlan_objmgr_register_vdev_peer_free_notify_handler() - register vdev peer + * free handler + * @id: component id + * @handler: function pointer of the component + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on VDEV Peer gets freed + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_vdev_peer_free_notify_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_peer_free_notify_handler handler); + +/** + * wlan_objmgr_unregister_vdev_peer_free_notify_handler() - unregister vdev + * peer free handler + * @id: component id + * @handler: function pointer of the component + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_vdev_peer_free_notify_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_peer_free_notify_handler handler); + /** * wlan_objmgr_register_peer_create_handler() - register peer create handler * @id: component id diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h index 82bc47d0647b2463c2b752195e2cff099be52712..a8c532a963f7fe754ce4e2a0d4897832239fb043 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 above @@ -24,6 +24,7 @@ #include #include "wlan_objmgr_psoc_obj.h" +#include /* STATUS: scanning */ #define WLAN_PDEV_F_SCAN 0x00000001 @@ -86,6 +87,8 @@ #define WLAN_PDEV_F_MULTIVDEV_RESTART 0x10000000 /* MBSS IE enable */ #define WLAN_PDEV_F_MBSS_IE_ENABLE 0x20000000 +/* VDEV Peer delete all */ +#define WLAN_PDEV_F_DELETE_ALL_PEER 0x40000000 /* PDEV op flags */ /* Enable htrate for wep and tkip */ @@ -162,6 +165,7 @@ struct wlan_objmgr_pdev_mlme { * @wlan_peer_count: Peer count * @max_peer_count: Max Peer count * @temp_peer_count: Temporary peer count + * @max_monitor_vdev_count: Max monitor vdev count * @wlan_psoc: back pointer to PSOC, its attached to * @ref_cnt: Ref count * @ref_id_dbg: Array to track Ref count @@ -175,6 +179,7 @@ struct wlan_objmgr_pdev_objmgr { uint16_t wlan_peer_count; uint16_t max_peer_count; uint16_t temp_peer_count; + uint8_t max_monitor_vdev_count; struct wlan_objmgr_psoc *wlan_psoc; qdf_atomic_t ref_cnt; qdf_atomic_t ref_id_dbg[WLAN_REF_ID_MAX]; @@ -190,7 +195,6 @@ struct wlan_objmgr_pdev_objmgr { * @obj_status[]: object status of each component object * @obj_state: object state * @tgt_if_handle: Target interface handle - * @dp_handle: DP module handle * @pdev_lock: lock to protect object */ struct wlan_objmgr_pdev { @@ -201,8 +205,7 @@ struct wlan_objmgr_pdev { void *pdev_comp_priv_obj[WLAN_UMAC_MAX_COMPONENTS]; QDF_STATUS obj_status[WLAN_UMAC_MAX_COMPONENTS]; WLAN_OBJ_STATE obj_state; - void *tgt_if_handle; - void *dp_handle; + target_pdev_info_t *tgt_if_handle; qdf_spinlock_t pdev_lock; }; @@ -351,13 +354,24 @@ QDF_STATUS wlan_objmgr_trigger_pdev_comp_priv_object_deletion( * Return: vdev pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_debug( + struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, dbgid) \ + wlan_objmgr_get_vdev_by_id_from_pdev_debug(pdev, \ + vdev_id, dbgid, __func__, __LINE__) +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev( struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, wlan_objmgr_ref_dbgid dbg_id); +#endif /** - * wlan_objmgr_get_vdev_by_id_from_pdev_no_state() - find vdev using id from - * pdev + * wlan_objmgr_get_vdev_by_id_from_pdev_no_state() - find vdev using id + * from pdev * @pdev: PDEV object * @vdev_id: vdev id * @dbg_id: id of the caller @@ -371,9 +385,21 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev( * Return: vdev pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state_debug( + struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_vdev_by_id_from_pdev_no_state(pdev, \ + vdev_id, dbgid) \ + wlan_objmgr_get_vdev_by_id_from_pdev_no_state_debug(pdev, \ + vdev_id, dbgid, __func__, __LINE__) +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state( struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_vdev_by_macaddr_from_pdev() - find vdev using macaddr @@ -390,9 +416,20 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state( * Return: vdev pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_debug( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *fnc, int ln); + +#define wlan_objmgr_get_vdev_by_macaddr_from_pdev(pdev, macaddr, dbgid) \ + wlan_objmgr_get_vdev_by_macaddr_from_pdev_debug(pdev, macaddr, \ + dbgid, __func__, __LINE__) +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev( struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state() - find vdev using @@ -410,9 +447,46 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev( * Return: vdev pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev + *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state_debug( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state(pdev, macaddr, \ + dbgid) \ + wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state_debug(pdev, \ + macaddr, dbgid, __func__, __LINE__) +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state( struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif + +/** + * wlan_objmgr_pdev_get_first_vdev() - Get first vdev of pdev + * @pdev: PDEV object + * @dbg_id: Object Manager ref debug id + * + * API to get reference to first vdev of pdev. + * + * Return: reference to first vdev + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_pdev_get_first_vdev_debug( + struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_pdev_get_first_vdev(pdev, dbgid) \ + wlan_objmgr_pdev_get_first_vdev_debug(pdev, dbgid, \ + __func__, __LINE__) +#else +struct wlan_objmgr_vdev *wlan_objmgr_pdev_get_first_vdev( + struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_pdev_get_comp_private_obj() - get pdev component private object @@ -792,19 +866,6 @@ QDF_STATUS wlan_objmgr_pdev_try_get_ref(struct wlan_objmgr_pdev *pdev, void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev, wlan_objmgr_ref_dbgid id); -/** - * wlan_objmgr_pdev_get_first_vdev() - Get first vdev of pdev - * @pdev: PDEV object - * @dbg_id: Object Manager ref debug id - * - * API to get reference to first vdev of pdev. - * - * Return: reference to first vdev - */ -struct wlan_objmgr_vdev *wlan_objmgr_pdev_get_first_vdev( - struct wlan_objmgr_pdev *pdev, - wlan_objmgr_ref_dbgid dbg_id); - /** * wlan_objmgr_pdev_get_pdev_id() - get pdev id * @pdev: PDEV object @@ -830,8 +891,9 @@ uint8_t wlan_objmgr_pdev_get_pdev_id(struct wlan_objmgr_pdev *pdev) * * Return: None */ -static inline void wlan_pdev_set_tgt_if_handle(struct wlan_objmgr_pdev *pdev, - void *tgt_if_handle) +static inline +void wlan_pdev_set_tgt_if_handle(struct wlan_objmgr_pdev *pdev, + target_pdev_info_t *tgt_if_handle) { /* This API is invoked with lock acquired, do not add log prints */ if (!pdev) @@ -848,7 +910,8 @@ static inline void wlan_pdev_set_tgt_if_handle(struct wlan_objmgr_pdev *pdev, * * Return: target interface handle */ -static inline void *wlan_pdev_get_tgt_if_handle(struct wlan_objmgr_pdev *pdev) +static inline +target_pdev_info_t *wlan_pdev_get_tgt_if_handle(struct wlan_objmgr_pdev *pdev) { if (!pdev) return NULL; @@ -885,6 +948,36 @@ static inline uint16_t wlan_pdev_get_max_peer_count( return pdev->pdev_objmgr.max_peer_count; } +/** + * wlan_pdev_set_max_monitor_vdev_count() - set max monitor vdev count + * @pdev: PDEV object + * @count: Max monitor vdev count + * + * API to set max monitor vdev count of PDEV + * + * Return: void + */ +static inline void wlan_pdev_set_max_monitor_vdev_count( + struct wlan_objmgr_pdev *pdev, + uint16_t count) +{ + pdev->pdev_objmgr.max_monitor_vdev_count = count; +} + +/** + * wlan_pdev_get_max_monitor_vdev_count() - get max monitor vdev count + * @pdev: PDEV object + * + * API to get max monitor vdev count of PDEV + * + * Return: max monitor vdev count + */ +static inline uint16_t wlan_pdev_get_max_monitor_vdev_count( + struct wlan_objmgr_pdev *pdev) +{ + return pdev->pdev_objmgr.max_monitor_vdev_count; +} + /** * wlan_pdev_get_peer_count() - get pdev peer count * @pdev: PDEV object @@ -978,37 +1071,15 @@ static inline uint8_t wlan_pdev_get_vdev_count(struct wlan_objmgr_pdev *pdev) } /** - * wlan_pdev_set_dp_handle() - set dp handle + * wlan_print_pdev_info() - print pdev members * @pdev: pdev object pointer - * @dp_handle: Data path module handle * * Return: void */ -static inline void wlan_pdev_set_dp_handle(struct wlan_objmgr_pdev *pdev, - void *dp_handle) -{ - if (qdf_unlikely(!pdev)) { - QDF_BUG(0); - return; - } - - pdev->dp_handle = dp_handle; -} - -/** - * wlan_pdev_get_dp_handle() - get dp handle - * @pdev: pdev object pointer - * - * Return: dp handle - */ -static inline void *wlan_pdev_get_dp_handle(struct wlan_objmgr_pdev *pdev) -{ - if (qdf_unlikely(!pdev)) { - QDF_BUG(0); - return NULL; - } - - return pdev->dp_handle; -} +#ifdef WLAN_OBJMGR_DEBUG +void wlan_print_pdev_info(struct wlan_objmgr_pdev *pdev); +#else +static inline void wlan_print_pdev_info(struct wlan_objmgr_pdev *pdev) {} +#endif #endif /* _WLAN_OBJMGR_PDEV_H_*/ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h index 4e86aa34dfb4cec762a39875d5343a2624cf0c33..2324b37667faff0914995efbe240f3f7c9cdddfc 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -143,6 +143,7 @@ struct wlan_objmgr_peer_mlme { * @ref_cnt: Ref count * @ref_id_dbg: Array to track Ref count * @print_cnt: Count to throttle Logical delete prints + * @wlan_objmgr_trace: Trace ref and deref */ struct wlan_objmgr_peer_objmgr { struct wlan_objmgr_vdev *vdev; @@ -151,14 +152,9 @@ struct wlan_objmgr_peer_objmgr { qdf_atomic_t ref_id_dbg[WLAN_REF_ID_MAX]; #endif uint8_t print_cnt; -}; - -/** - * struct wlan_peer_activity -- peer inactivity info - * - */ -struct wlan_peer_activity { /*TODO */ - +#ifdef WLAN_OBJMGR_REF_ID_TRACE + struct wlan_objmgr_trace trace; +#endif }; /** @@ -167,12 +163,10 @@ struct wlan_peer_activity { /*TODO */ * @vdev_peer: peer list node for vdev's qdf list * @macaddr[]: Peer MAC address * @peer_mlme: Peer MLME common structure - * @peer_activity: peer activity * @peer_objmgr: Peer Object manager common structure * @peer_comp_priv_obj[]: Component's private object pointers * @obj_status[]: status of each component object * @obj_state: Status of Peer object - * @dp_handle: DP module handle * @pdev_id: Pdev ID * @peer_lock: Lock for access/update peer contents */ @@ -182,12 +176,10 @@ struct wlan_objmgr_peer { uint8_t macaddr[QDF_MAC_ADDR_SIZE]; uint8_t pdev_id; struct wlan_objmgr_peer_mlme peer_mlme; - struct wlan_peer_activity peer_activity; struct wlan_objmgr_peer_objmgr peer_objmgr; void *peer_comp_priv_obj[WLAN_UMAC_MAX_COMPONENTS]; QDF_STATUS obj_status[WLAN_UMAC_MAX_COMPONENTS]; WLAN_OBJ_STATE obj_state; - void *dp_handle; qdf_spinlock_t peer_lock; }; @@ -381,8 +373,17 @@ static inline void wlan_peer_obj_unlock(struct wlan_objmgr_peer *peer) * * Return: void */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +void wlan_objmgr_peer_get_ref_debug(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id, + const char *func, int line); + +#define wlan_objmgr_peer_get_ref(peer, dbgid) \ + wlan_objmgr_peer_get_ref_debug(peer, dbgid, __func__, __LINE__) +#else void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, wlan_objmgr_ref_dbgid id); +#endif /** * wlan_objmgr_peer_try_get_ref() - increment ref count, if allowed @@ -393,8 +394,18 @@ void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, * * Return: void */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +QDF_STATUS wlan_objmgr_peer_try_get_ref_debug(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id, + const char *func, int line); + +#define wlan_objmgr_peer_try_get_ref(peer, dbgid) \ + wlan_objmgr_peer_try_get_ref_debug(peer, dbgid, \ + __func__, __LINE__) +#else QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, wlan_objmgr_ref_dbgid id); +#endif /** * wlan_objmgr_peer_release_ref() - decrement ref count @@ -406,36 +417,147 @@ QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, * * Return: void */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +void wlan_objmgr_peer_release_ref_debug(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id, + const char *func, int line); + +#define wlan_objmgr_peer_release_ref(peer, dbgid) \ + wlan_objmgr_peer_release_ref_debug(peer, dbgid, \ + __func__, __LINE__) +#else void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer, wlan_objmgr_ref_dbgid id); +#endif /** - * wlan_psoc_peer_list_peek_head() - get head of psoc peer list - * @peer_list: qdf_list_t + * wlan_peer_get_next_peer_of_psoc_ref() - get next peer to psoc peer list + * with lock and ref taken + * @peer_list: Peer list + * @hash_index: peer list hash index + * @peer: PEER object + * @dbg_id: Ref count debug module id * - * API to get the head peer of given peer (of psoc's peer list) + * API to get the next peer of given peer (of psoc's peer list) * - * Caller need to acquire lock with wlan_peer_obj_lock() + * Return: + * @next_peer: PEER object + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref_debug( + struct wlan_peer_list *peer_list, + uint8_t hash_index, + struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_peer_get_next_peer_of_psoc_ref(peer_list, hash_index, peer, \ + dbgid) \ + wlan_peer_get_next_peer_of_psoc_ref_debug(peer_list, \ + hash_index, peer, dbgid, __func__, __LINE__) +#else +struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref( + struct wlan_peer_list *peer_list, + uint8_t hash_index, + struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid dbg_id); +#endif + +/** + * wlan_peer_get_next_active_peer_of_psoc() - get next active peer to psoc peer + * list + * @peer_list: Peer list + * @hash_index: peer list hash index + * @peer: PEER object + * @dbg_id: Ref count debug module id + * + * API to get the next peer of given peer (of psoc's peer list) * * Return: - * @peer: head peer + * @next_peer: PEER object */ -static inline struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head( - qdf_list_t *peer_list) -{ - struct wlan_objmgr_peer *peer; - qdf_list_node_t *psoc_node = NULL; +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc_debug( + struct wlan_peer_list *peer_list, + uint8_t hash_index, + struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_peer_get_next_active_peer_of_psoc(peer_list, hash_index, \ + peer, dbgid) \ + wlan_peer_get_next_active_peer_of_psoc_debug(peer_list, \ + hash_index, peer, dbgid, __func__, __LINE__) +#else +struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc( + struct wlan_peer_list *peer_list, + uint8_t hash_index, + struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid dbg_id); +#endif - /* This API is invoked with lock acquired, do not add log prints */ - if (qdf_list_peek_front(peer_list, &psoc_node) != QDF_STATUS_SUCCESS) - return NULL; +/** + * wlan_peer_get_next_active_peer_of_vdev() - get next active_peer of vdev list + * @vdev: VDEV object + * @peer_list: Peer object list + * @peer: PEER object + * @dbg_id: Ref count debug module id + * + * API to get the next active peer of given peer (of vdev's peer list) + * + * Return: + * @next_peer: PEER object + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev_debug( + struct wlan_objmgr_vdev *vdev, + qdf_list_t *peer_list, + struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); - peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer, psoc_peer); - return peer; -} +#define wlan_peer_get_next_active_peer_of_vdev(vdev, peer_list, peer, dbgid) \ + wlan_peer_get_next_active_peer_of_vdev_debug(vdev, peer_list, \ + peer, dbgid, __func__, __LINE__) +#else +struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev( + struct wlan_objmgr_vdev *vdev, + qdf_list_t *peer_list, + struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid dbg_id); +#endif /** - * wlan_psoc_peer_list_peek_active_head() - get active head of psoc peer list + * wlan_vdev_peer_list_peek_active_head() - get active head of vdev peer list + * @vdev: VDEV object + * @peer_list: qdf_list_t + * @dbg_id: Ref count debug module id + * + * API to get the active head peer of given peer (of vdev's peer list) + * + * Return: + * @peer: active head peer + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head_debug( + struct wlan_objmgr_vdev *vdev, + qdf_list_t *peer_list, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_vdev_peer_list_peek_active_head(vdev, peer_list, dbgid) \ + wlan_vdev_peer_list_peek_active_head_debug(vdev, peer_list, \ + dbgid, __func__, __LINE__) +#else +struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head( + struct wlan_objmgr_vdev *vdev, + qdf_list_t *peer_list, + wlan_objmgr_ref_dbgid dbg_id); +#endif + +/** + * wlan_psoc_peer_list_peek_head_ref() - get head of psoc peer list + * with ref and lock protected * @peer_list: wlan_peer_list * @hash_index: peer list hash index * @dbg_id: Ref count debug module id @@ -445,14 +567,25 @@ static inline struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head( * Return: * @peer: head peer */ -struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head( +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref_debug( + struct wlan_peer_list *peer_list, + uint8_t hash_index, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_psoc_peer_list_peek_head_ref(peer_list, hash_index, dbgid) \ + wlan_psoc_peer_list_peek_head_ref_debug(peer_list, hash_index, \ + dbgid, __func__, __LINE__) +#else +struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref( struct wlan_peer_list *peer_list, uint8_t hash_index, wlan_objmgr_ref_dbgid dbg_id); +#endif /** - * wlan_psoc_peer_list_peek_head_lock_ref() - get head of psoc peer list - * with ref and lock protected + * wlan_psoc_peer_list_peek_active_head() - get active head of psoc peer list * @peer_list: wlan_peer_list * @hash_index: peer list hash index * @dbg_id: Ref count debug module id @@ -462,51 +595,72 @@ struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head( * Return: * @peer: head peer */ -struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref( +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head_debug( + struct wlan_peer_list *peer_list, + uint8_t hash_index, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_psoc_peer_list_peek_active_head(peer_list, hash_index, dbgid) \ + wlan_psoc_peer_list_peek_active_head_debug(peer_list, \ + hash_index, dbgid, __func__, __LINE__) +#else +struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head( struct wlan_peer_list *peer_list, uint8_t hash_index, wlan_objmgr_ref_dbgid dbg_id); +#endif /** - * wlan_vdev_peer_list_peek_head() - get head of vdev peer list + * wlan_psoc_peer_list_peek_head() - get head of psoc peer list * @peer_list: qdf_list_t * - * API to get the head peer of given peer (of vdev's peer list) + * API to get the head peer of given peer (of psoc's peer list) * * Caller need to acquire lock with wlan_peer_obj_lock() * * Return: * @peer: head peer */ -static inline struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_head( +static inline struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head( qdf_list_t *peer_list) { struct wlan_objmgr_peer *peer; - qdf_list_node_t *vdev_node = NULL; + qdf_list_node_t *psoc_node = NULL; /* This API is invoked with lock acquired, do not add log prints */ - if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) + if (qdf_list_peek_front(peer_list, &psoc_node) != QDF_STATUS_SUCCESS) return NULL; - peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer, vdev_peer); + peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer, psoc_peer); return peer; } /** - * wlan_vdev_peer_list_peek_active_head() - get active head of vdev peer list - * @vdev: VDEV object + * wlan_vdev_peer_list_peek_head() - get head of vdev peer list * @peer_list: qdf_list_t - * @dbg_id: Ref count debug module id * - * API to get the active head peer of given peer (of vdev's peer list) + * API to get the head peer of given peer (of vdev's peer list) + * + * Caller need to acquire lock with wlan_peer_obj_lock() * * Return: - * @peer: active head peer + * @peer: head peer */ -struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head( - struct wlan_objmgr_vdev *vdev, - qdf_list_t *peer_list, - wlan_objmgr_ref_dbgid dbg_id); +static inline struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_head( + qdf_list_t *peer_list) +{ + struct wlan_objmgr_peer *peer; + qdf_list_node_t *vdev_node = NULL; + + /* This API is invoked with lock acquired, do not add log prints */ + if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) + return NULL; + + peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer, vdev_peer); + return peer; +} /** * wlan_peer_get_next_peer_of_vdev() - get next peer of vdev list @@ -540,24 +694,6 @@ static inline struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_vdev( return peer_next; } -/** - * wlan_peer_get_next_active_peer_of_vdev() - get next active_peer of vdev list - * @vdev: VDEV object - * @peer_list: Peer object list - * @peer: PEER object - * @dbg_id: Ref count debug module id - * - * API to get the next active peer of given peer (of vdev's peer list) - * - * Return: - * @next_peer: PEER object - */ -struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev( - struct wlan_objmgr_vdev *vdev, - qdf_list_t *peer_list, - struct wlan_objmgr_peer *peer, - wlan_objmgr_ref_dbgid dbg_id); - /** * wlan_peer_set_next_peer_of_vdev() - add peer to vdev peer list * @peer: PEER object @@ -611,45 +747,6 @@ static inline struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc( return peer_next; } -/** - * wlan_peer_get_next_active_peer_of_psoc() - get next active peer to psoc peer - * list - * @peer_list: Peer list - * @hash_index: peer list hash index - * @peer: PEER object - * @dbg_id: Ref count debug module id - * - * API to get the next peer of given peer (of psoc's peer list) - * - * Return: - * @next_peer: PEER object - */ -struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc( - struct wlan_peer_list *peer_list, - uint8_t hash_index, - struct wlan_objmgr_peer *peer, - wlan_objmgr_ref_dbgid dbg_id); - - -/** - * wlan_peer_get_next_peer_of_psoc_ref() - get next peer to psoc peer list - * with lock and ref taken - * @peer_list: Peer list - * @hash_index: peer list hash index - * @peer: PEER object - * @dbg_id: Ref count debug module id - * - * API to get the next peer of given peer (of psoc's peer list) - * - * Return: - * @next_peer: PEER object - */ -struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref( - struct wlan_peer_list *peer_list, - uint8_t hash_index, - struct wlan_objmgr_peer *peer, - wlan_objmgr_ref_dbgid dbg_id); - /** * wlan_peer_set_next_peer_of_psoc() - add peer to psoc peer list * @peer: PEER object @@ -806,7 +903,7 @@ static inline void wlan_peer_set_vdev(struct wlan_objmgr_peer *peer, * Return: void */ static inline void wlan_peer_mlme_flag_set(struct wlan_objmgr_peer *peer, - uint32_t flag) + uint32_t flag) { peer->peer_mlme.peer_flags |= flag; } @@ -957,40 +1054,6 @@ static inline void wlan_peer_mlme_reset_seq_num( peer->peer_mlme.seq_num = 0; } -/** - * wlan_peer_set_dp_handle() - set dp handle - * @peer: peer object pointer - * @dp_handle: Data path module handle - * - * Return: void - */ -static inline void wlan_peer_set_dp_handle(struct wlan_objmgr_peer *peer, - void *dp_handle) -{ - if (qdf_unlikely(!peer)) { - QDF_BUG(0); - return; - } - - peer->dp_handle = dp_handle; -} - -/** - * wlan_peer_get_dp_handle() - get dp handle - * @peer: peer object pointer - * - * Return: dp handle - */ -static inline void *wlan_peer_get_dp_handle(struct wlan_objmgr_peer *peer) -{ - if (qdf_unlikely(!peer)) { - QDF_BUG(0); - return NULL; - } - - return peer->dp_handle; -} - /** * wlan_peer_get_psoc() - get psoc * @peer: PEER object @@ -1059,4 +1122,61 @@ uint32_t wlan_objmgr_peer_get_comp_ref_cnt(struct wlan_objmgr_peer *peer, enum wlan_umac_comp_id id); +/** + * wlan_objmgr_peer_trace_init_lock() - Initialize peer trace lock + * @peer: peer object pointer + * + * Return: void + */ +#ifdef WLAN_OBJMGR_TRACE +static inline void +wlan_objmgr_peer_trace_init_lock(struct wlan_objmgr_peer *peer) +{ + wlan_objmgr_trace_init_lock(&peer->peer_objmgr.trace); +} +#else +static inline void +wlan_objmgr_peer_trace_init_lock(struct wlan_objmgr_peer *peer) +{ +} +#endif + +/** + * wlan_objmgr_peer_trace_deinit_lock() - Deinitialize peer trace lock + * @peer: peer object pointer + * + * Return: void + */ +#ifdef WLAN_OBJMGR_TRACE +static inline void +wlan_objmgr_peer_trace_deinit_lock(struct wlan_objmgr_peer *peer) +{ + wlan_objmgr_trace_deinit_lock(&peer->peer_objmgr.trace); +} +#else +static inline void +wlan_objmgr_peer_trace_deinit_lock(struct wlan_objmgr_peer *peer) +{ +} +#endif + +/** + * wlan_objmgr_peer_trace_del_ref_list() - Delete peer trace reference list + * @peer: peer object pointer + * + * Return: void + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static inline void +wlan_objmgr_peer_trace_del_ref_list(struct wlan_objmgr_peer *peer) +{ + wlan_objmgr_trace_del_ref_list(&peer->peer_objmgr.trace); +} +#else +static inline void +wlan_objmgr_peer_trace_del_ref_list(struct wlan_objmgr_peer *peer) +{ +} +#endif + #endif /* _WLAN_OBJMGR_PEER_OBJ_H_*/ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h index f7eea2d6a4955201ab5c30c2cb62dc2bd8b16b31..c2c60313d699404ea2b2fc91171978820f84aaba 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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,6 +25,7 @@ #include "wlan_objmgr_cmn.h" #include "wlan_objmgr_debug.h" #include "wlan_lmac_if_def.h" +#include #define REG_DMN_CH144 0x0001 #define REG_DMN_ENTREPRISE 0x0002 @@ -131,6 +132,14 @@ #define WLAN_SOC_CEXT_OBSS_NBW_RU 0x00010000 /* MBSS IE support */ #define WLAN_SOC_CEXT_MBSS_IE 0x00020000 + /* RXOLE Flow Search Support */ +#define WLAN_SOC_CEXT_RX_FSE_SUPPORT 0x00040000 + /* Dynamic HW Mode Switch Support */ +#define WLAN_SOC_CEXT_DYNAMIC_HW_MODE 0x00080000 + /* Restricted 80+80 MHz support */ +#define WLAN_SOC_RESTRICTED_80P80_SUPPORT 0x00100000 + /* Indicates Firmware supports sending NSS ratio info to host */ +#define WLAN_SOC_NSS_RATIO_TO_HOST_SUPPORT 0x00200000 /* feature_flags */ /* CONF: ATH FF enabled */ @@ -187,11 +196,33 @@ #define WLAN_SOC_F_SPECTRAL_DISABLE 0x00800000 /* FTM testmode enable */ #define WLAN_SOC_F_TESTMODE_ENABLE 0x01000000 + /* Dynamic HW mode swithch enable */ +#define WLAN_SOC_F_DYNAMIC_HW_MODE 0x02000000 /* PSOC op flags */ /* Invalid VHT cap */ #define WLAN_SOC_OP_VHT_INVALID_CAP 0x00000001 + +/* enum wlan_nss_ratio - NSS ratio received from FW during service ready ext + * event. + * WLAN_NSS_RATIO_1BY2_NSS : Max nss of 160MHz is equals to half of the max nss + * of 80MHz + * WLAN_NSS_RATIO_3BY4_NSS : Max nss of 160MHz is equals to 3/4 of the max nss + * of 80MHz + * WLAN_NSS_RATIO_1_NSS : Max nss of 160MHz is equals to the max nss of 80MHz + * WLAN_NSS_RATIO_2_NSS : Max nss of 160MHz is equals to two times the max + * nss of 80MHz + * Values of this enum should be in sync with WMI_NSS_RATIO_INFO value provided + * in wmi_unified.h. + */ +enum wlan_nss_ratio { + WLAN_NSS_RATIO_1BY2_NSS = 0x0, + WLAN_NSS_RATIO_3BY4_NSS = 0x1, + WLAN_NSS_RATIO_1_NSS = 0x2, + WLAN_NSS_RATIO_2_NSS = 0x3, +}; + /** * struct wlan_objmgr_psoc_regulatory - Regulatory sub structure of PSOC * @country_code: Country code @@ -332,7 +363,7 @@ struct wlan_objmgr_psoc { void *soc_comp_priv_obj[WLAN_UMAC_MAX_COMPONENTS]; QDF_STATUS obj_status[WLAN_UMAC_MAX_COMPONENTS]; WLAN_OBJ_STATE obj_state; - void *tgt_if_handle; + target_psoc_info_t *tgt_if_handle; void *dp_handle; qdf_spinlock_t psoc_lock; }; @@ -543,9 +574,19 @@ QDF_STATUS wlan_objmgr_trigger_psoc_comp_priv_object_deletion( * Return: peer pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_debug( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, const char *func, int line); + +#define wlan_objmgr_get_peer_by_mac(psoc, macaddr, dbgid) \ + wlan_objmgr_get_peer_by_mac_debug(psoc, macaddr, dbgid, \ + __func__, __LINE__) +#else struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac( struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_peer() - find peer from psoc's peer list @@ -563,9 +604,20 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac( * Return: peer pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_peer(psoc, pdev_id, macaddr, dbgid) \ + wlan_objmgr_get_peer_debug(psoc, pdev_id, macaddr, dbgid, \ + __func__, __LINE__) +#else struct wlan_objmgr_peer *wlan_objmgr_get_peer( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_peer_nolock() - find peer from psoc's peer list (lock free) @@ -583,9 +635,20 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer( * Return: peer pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_nolock_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_peer_nolock(psoc, pdev_id, macaddr, dbgid) \ + wlan_objmgr_get_peer_nolock_debug(psoc, pdev_id, macaddr, \ + dbgid, __func__, __LINE__) +#else struct wlan_objmgr_peer *wlan_objmgr_get_peer_nolock( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_peer_logically_deleted() - find peer @@ -603,9 +666,20 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_nolock( * Return: peer pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted_debug( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_peer_logically_deleted(psoc, macaddr, dbgid) \ + wlan_objmgr_get_peer_logically_deleted_debug(psoc, macaddr, \ + dbgid, __func__, __LINE__) +#else struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted( struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_peer_no_state() - find peer from psoc's peer list @@ -624,9 +698,20 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted( * Return: peer pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_peer_no_state(psoc, pdev_id, macaddr, dbgid) \ + wlan_objmgr_get_peer_no_state_debug(psoc, pdev_id, macaddr, \ + dbgid, __func__, __LINE__) +#else struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev() - get peer from @@ -649,10 +734,23 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state( * Return: List of peer pointers * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +qdf_list_t *wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *bssid, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev( \ + psoc, pdev_id, bssid, macaddr, dbgid) \ + wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev_debug( \ + psoc, pdev_id, bssid, macaddr, dbgid, __func__, __LINE__) +#else qdf_list_t *wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *bssid, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_peer_by_mac_n_vdev() - find peer from psoc's peer list @@ -673,10 +771,23 @@ qdf_list_t *wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev( * Return: peer pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *bssid, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_peer_by_mac_n_vdev(psoc, pdevid, bssid, macaddr, \ + dbgid) \ + wlan_objmgr_get_peer_by_mac_n_vdev_debug(psoc, pdevid, \ + bssid, macaddr, dbgid, __func__, __LINE__) +#else struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *bssid, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_peer_by_mac_n_vdev_no_state() - find peer from psoc's peer @@ -697,10 +808,23 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev( * Return: peer pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_no_state_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *bssid, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_peer_by_mac_n_vdev_no_state(psoc, pdevid, bssid, \ + macaddr, dbgid) \ + wlan_objmgr_get_peer_by_mac_n_vdev_no_state_debug(psoc, \ + pdevid, bssid, macaddr, dbgid, __func__, __LINE__) +#else struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_no_state( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *bssid, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_pdev_by_id() - retrieve pdev by id @@ -793,10 +917,22 @@ struct wlan_objmgr_pdev *wlan_objmgr_get_pdev_by_macaddr_no_state( * Return: vdev pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_opmode_from_psoc_debug( + struct wlan_objmgr_psoc *psoc, + enum QDF_OPMODE opmode, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_vdev_by_opmode_from_psoc(psoc, opmode, dbgid) \ + wlan_objmgr_get_vdev_by_opmode_from_psoc_debug(psoc, opmode, \ + dbgid, __func__, __LINE__) +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_opmode_from_psoc( struct wlan_objmgr_psoc *psoc, enum QDF_OPMODE opmode, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_vdev_by_id_from_psoc() - retrieve vdev by id @@ -813,9 +949,20 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_opmode_from_psoc( * Return: vdev pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_debug( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, dbgid) \ + wlan_objmgr_get_vdev_by_id_from_psoc_debug(psoc, vdev_id, \ + dbgid, __func__, __LINE__) +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc( struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_vdev_by_id_from_psoc_no_state() - retrieve vdev by id @@ -833,9 +980,20 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc( * Return: vdev pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_no_state_debug( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_vdev_by_id_from_psoc_no_state(psoc, vdev_id, dbgid) \ + wlan_objmgr_get_vdev_by_id_from_psoc_no_state_debug(psoc, \ + vdev_id, dbgid, __func__, __LINE__) +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_no_state( struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_vdev_by_macaddr_from_psoc() - retrieve vdev by macaddr @@ -853,9 +1011,21 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_no_state( * Return: vdev pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_vdev_by_macaddr_from_psoc(psoc, pdev_id, macaddr, \ + dbgid) \ + wlan_objmgr_get_vdev_by_macaddr_from_psoc_debug(psoc, pdev_id, \ + macaddr, dbgid, __func__, __LINE__) +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state() - retrieve vdev by @@ -875,9 +1045,22 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc( * Return: vdev pointer * NULL on FAILURE */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev + *wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state(psoc, pdev_id, \ + macaddr, dbgid) \ + wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state_debug(psoc, \ + pdev_id, macaddr, dbgid, __func__, __LINE__) +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id); +#endif /** * wlan_psoc_obj_lock() - Acquire PSOC spinlock @@ -1224,8 +1407,9 @@ static inline uint8_t wlan_psoc_get_pdev_count(struct wlan_objmgr_psoc *psoc) * * Return: None */ -static inline void wlan_psoc_set_tgt_if_handle(struct wlan_objmgr_psoc *psoc, - void *tgt_if_handle) +static inline +void wlan_psoc_set_tgt_if_handle(struct wlan_objmgr_psoc *psoc, + target_psoc_info_t *tgt_if_handle) { if (!psoc) return; @@ -1241,7 +1425,8 @@ static inline void wlan_psoc_set_tgt_if_handle(struct wlan_objmgr_psoc *psoc, * * Return: target interface handle */ -static inline void *wlan_psoc_get_tgt_if_handle(struct wlan_objmgr_psoc *psoc) +static inline +target_psoc_info_t *wlan_psoc_get_tgt_if_handle(struct wlan_objmgr_psoc *psoc) { if (!psoc) return NULL; @@ -1446,25 +1631,33 @@ QDF_STATUS wlan_objmgr_psoc_set_user_config(struct wlan_objmgr_psoc *psoc, * wlan_objmgr_psoc_check_for_pdev_leaks() - Assert no pdevs attached to @psoc * @psoc: The psoc to check * - * Return: None + * Return: No. of psoc leaks */ -void wlan_objmgr_psoc_check_for_pdev_leaks(struct wlan_objmgr_psoc *psoc); +uint32_t wlan_objmgr_psoc_check_for_pdev_leaks(struct wlan_objmgr_psoc *psoc); /** * wlan_objmgr_psoc_check_for_vdev_leaks() - Assert no vdevs attached to @psoc * @psoc: The psoc to check * - * Return: None + * Return: No. of vdev leaks */ -void wlan_objmgr_psoc_check_for_vdev_leaks(struct wlan_objmgr_psoc *psoc); +uint32_t wlan_objmgr_psoc_check_for_vdev_leaks(struct wlan_objmgr_psoc *psoc); /** * wlan_objmgr_psoc_check_for_peer_leaks() - Assert no peers attached to @psoc * @psoc: The psoc to check * + * Return: No. of peer leaks + */ +uint32_t wlan_objmgr_psoc_check_for_peer_leaks(struct wlan_objmgr_psoc *psoc); + +/** + * wlan_objmgr_psoc_check_for_leaks() - Assert on leak + * @psoc: The psoc to check + * * Return: None */ -void wlan_objmgr_psoc_check_for_peer_leaks(struct wlan_objmgr_psoc *psoc); +void wlan_objmgr_psoc_check_for_leaks(struct wlan_objmgr_psoc *psoc); /** * wlan_objmgr_psoc_get_band_capability () - get user config @@ -1549,4 +1742,17 @@ static inline uint8_t wlan_psoc_get_id( return psoc->soc_objmgr.psoc_id; } + +/** + * wlan_print_psoc_info() - print psoc members + * @psoc: psoc object pointer + * + * Return: void + */ +#ifdef WLAN_OBJMGR_DEBUG +void wlan_print_psoc_info(struct wlan_objmgr_psoc *psoc); +#else +static inline void wlan_print_psoc_info(struct wlan_objmgr_psoc *psoc) {} +#endif + #endif /* _WLAN_OBJMGR_PSOC_OBJ_H_*/ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h index a3cd24b47515647b6b61a9e961b1a96aa8fd2ee2..ce4637ef16e8f6c33c13ddf7cbce45881875eb8f 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -32,11 +32,9 @@ #include "wlan_objmgr_pdev_obj.h" #include "wlan_objmgr_psoc_obj.h" #include "wlan_vdev_mlme_main.h" -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE #include "include/wlan_vdev_mlme.h" #include "wlan_vdev_mlme_api.h" #include "wlan_mlme_dbg.h" -#endif /* CONF: privacy enabled */ #define WLAN_VDEV_F_PRIVACY 0x00000001 @@ -168,6 +166,8 @@ #define WLAN_VDEV_FEXT_MAT 0x20000000 /* VDEV is wired PSTA*/ #define WLAN_VDEV_FEXT_WIRED_PSTA 0x40000000 + /* Fils discovery on 6G SAP*/ +#define WLAN_VDEV_FEXT_FILS_DISC_6G_SAP 0x80000000 /* VDEV OP flags */ /* if the vap destroyed by user */ @@ -234,7 +234,6 @@ /* Invalid VDEV identifier */ #define WLAN_INVALID_VDEV_ID 255 - /** * struct wlan_vdev_create_params - Create params, HDD/OSIF passes this * structure While creating VDEV @@ -258,11 +257,11 @@ struct wlan_vdev_create_params { * struct wlan_channel - channel structure * @ch_freq: Channel in Mhz. * @ch_ieee: IEEE channel number. - * @ch_flags: Channel flags. - * @ch_flagext: Channel extension flags. - * @ch_maxpower: Maximum tx power in dBm. * @ch_freq_seg1: Channel Center frequeny for VHT80/160 and HE80/160. * @ch_freq_seg2: Second channel Center frequency applicable for 80+80MHz mode. + * @ch_maxpower: Maximum tx power in dBm. + * @ch_flagext: Channel extension flags. + * @ch_flags: Channel flags. * @ch_cfreq1: channel center frequency for primary * @ch_cfreq2: channel center frequency for secondary * @ch_width: Channel width. @@ -271,11 +270,11 @@ struct wlan_vdev_create_params { struct wlan_channel { uint16_t ch_freq; uint8_t ch_ieee; - uint64_t ch_flags; - uint16_t ch_flagext; - int8_t ch_maxpower; uint8_t ch_freq_seg1; uint8_t ch_freq_seg2; + int8_t ch_maxpower; + uint16_t ch_flagext; + uint64_t ch_flags; uint32_t ch_cfreq1; uint32_t ch_cfreq2; enum phy_ch_width ch_width; @@ -317,17 +316,6 @@ struct wlan_objmgr_vdev_mlme { uint32_t vdev_op_flags; uint8_t mataddr[QDF_MAC_ADDR_SIZE]; uint8_t macaddr[QDF_MAC_ADDR_SIZE]; -#ifndef CMN_VDEV_MGR_TGT_IF_ENABLE - char ssid[WLAN_SSID_MAX_LEN + 1]; - uint8_t ssid_len; - uint8_t nss; - uint8_t tx_chainmask; - uint8_t rx_chainmask; - uint8_t tx_power; - uint32_t max_rate; - uint32_t tx_mgmt_rate; - uint32_t per_band_mgmt_rate[WLAN_BAND_NUM_MAX]; -#endif }; /** @@ -351,6 +339,7 @@ struct wlan_objmgr_vdev_nif { * @c_flags: creation specific flags * @ref_cnt: Ref count * @ref_id_dbg: Array to track Ref count + * @wlan_objmgr_trace: Trace ref and deref */ struct wlan_objmgr_vdev_objmgr { uint8_t vdev_id; @@ -364,6 +353,9 @@ struct wlan_objmgr_vdev_objmgr { uint32_t c_flags; qdf_atomic_t ref_cnt; qdf_atomic_t ref_id_dbg[WLAN_REF_ID_MAX]; +#ifdef WLAN_OBJMGR_REF_ID_TRACE + struct wlan_objmgr_trace trace; +#endif }; /** @@ -375,7 +367,6 @@ struct wlan_objmgr_vdev_objmgr { * @vdev_comp_priv_obj[]:Component's private objects list * @obj_status[]: Component object status * @obj_state: VDEV object state - * @dp_handle: DP module handle * @vdev_lock: VDEV lock */ struct wlan_objmgr_vdev { @@ -386,7 +377,6 @@ struct wlan_objmgr_vdev { void *vdev_comp_priv_obj[WLAN_UMAC_MAX_COMPONENTS]; QDF_STATUS obj_status[WLAN_UMAC_MAX_COMPONENTS]; WLAN_OBJ_STATE obj_state; - void *dp_handle; qdf_spinlock_t vdev_lock; }; @@ -591,34 +581,6 @@ static inline struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_head( return vdev; } -/** - * wlan_pdev_peek_active_first_vdev() - get first active vdev from pdev list - * @pdev: PDEV object - * @dbg_id: id of the caller - * - * API to get the head active vdev of given pdev (of pdev's vdev list) - * - * Return: - */ -struct wlan_objmgr_vdev *wlan_pdev_peek_active_first_vdev( - struct wlan_objmgr_pdev *pdev, - wlan_objmgr_ref_dbgid dbg_id); - -/** - * wlan_pdev_vdev_list_peek_active_head() - get first active vdev from pdev list - * @vdev: VDEV object - * @vdev_list: qdf_list_t - * @dbg_id: id of the caller - * - * API to get the head active vdev of given vdev (of pdev's vdev list) - * - * Return: - * @peer: head peer - */ -struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head( - struct wlan_objmgr_pdev *pdev, - qdf_list_t *vdev_list, - wlan_objmgr_ref_dbgid dbg_id); /** * wlan_vdev_get_next_vdev_of_pdev() - get next vdev @@ -652,23 +614,6 @@ static inline struct wlan_objmgr_vdev *wlan_vdev_get_next_vdev_of_pdev( return vdev_next; } -/** - * wlan_vdev_get_next_active_vdev_of_pdev() - get next active vdev - * @pdev: PDEV object - * @vdev_list: qdf_list_t - * @vdev: VDEV object - * @dbg_id: id of the caller - * - * API to get next active vdev object pointer of vdev - * - * Return: - * @vdev_next: VDEV object - */ -struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev( - struct wlan_objmgr_pdev *pdev, - qdf_list_t *vdev_list, - struct wlan_objmgr_vdev *vdev, - wlan_objmgr_ref_dbgid dbg_id); /** @@ -939,252 +884,6 @@ static inline struct wlan_channel *wlan_vdev_mlme_get_des_chan( return vdev->vdev_mlme.des_chan; } -#ifndef CMN_VDEV_MGR_TGT_IF_ENABLE - -/** - * wlan_vdev_mlme_set_ssid() - set ssid - * @vdev: VDEV object - * @ssid: SSID (input) - * @ssid_len: Length of SSID - * - * API to set the SSID of VDEV - * - * Caller need to acquire lock with wlan_vdev_obj_lock() - * - * Return: SUCCESS, if update is done - * FAILURE, if ssid length is > max ssid len - */ -static inline QDF_STATUS wlan_vdev_mlme_set_ssid( - struct wlan_objmgr_vdev *vdev, - const uint8_t *ssid, uint8_t ssid_len) -{ - /* This API is invoked with lock acquired, do not add log prints */ - if (ssid_len <= WLAN_SSID_MAX_LEN) { - qdf_mem_copy(vdev->vdev_mlme.ssid, ssid, ssid_len); - vdev->vdev_mlme.ssid_len = ssid_len; - } else { - vdev->vdev_mlme.ssid_len = 0; - return QDF_STATUS_E_FAILURE; - } - return QDF_STATUS_SUCCESS; -} - -/** - * wlan_vdev_mlme_get_ssid() - get ssid - * @vdev: VDEV object - * @ssid: SSID - * @ssid_len: Length of SSID - * - * API to get the SSID of VDEV, it updates the SSID and its length - * in @ssid, @ssid_len respectively - * - * Caller need to acquire lock with wlan_vdev_obj_lock() - * - * Return: SUCCESS, if update is done - * FAILURE, if ssid length is > max ssid len - */ -static inline QDF_STATUS wlan_vdev_mlme_get_ssid( - struct wlan_objmgr_vdev *vdev, - uint8_t *ssid, uint8_t *ssid_len) -{ - /* This API is invoked with lock acquired, do not add log prints */ - if (vdev->vdev_mlme.ssid_len > 0) { - *ssid_len = vdev->vdev_mlme.ssid_len; - qdf_mem_copy(ssid, vdev->vdev_mlme.ssid, *ssid_len); - } else { - *ssid_len = 0; - return QDF_STATUS_E_FAILURE; - } - return QDF_STATUS_SUCCESS; -} - -/** - * wlan_vdev_mlme_set_nss() - set NSS - * @vdev: VDEV object - * @nss: nss configured by user - * - * API to set the Number of Spatial streams - * - * Return: void - */ -static inline void wlan_vdev_mlme_set_nss(struct wlan_objmgr_vdev *vdev, - uint8_t nss) -{ - vdev->vdev_mlme.nss = nss; -} - -/** - * wlan_vdev_mlme_get_nss() - get NSS - * @vdev: VDEV object - * - * API to get the Number of Spatial Streams - * - * Return: - * @nss: nss value - */ -static inline uint8_t wlan_vdev_mlme_get_nss( - struct wlan_objmgr_vdev *vdev) -{ - return vdev->vdev_mlme.nss; -} - -/** - * wlan_vdev_mlme_set_txchainmask() - set Tx chainmask - * @vdev: VDEV object - * @chainmask : chainmask either configured by user or max supported - * - * API to set the Tx chainmask - * - * Return: void - */ -static inline void wlan_vdev_mlme_set_txchainmask( - struct wlan_objmgr_vdev *vdev, - uint8_t chainmask) -{ - vdev->vdev_mlme.tx_chainmask = chainmask; -} - -/** - * wlan_vdev_mlme_get_txchainmask() - get Tx chainmask - * @vdev: VDEV object - * - * API to get the Tx chainmask - * - * Return: - * @chainmask : Tx chainmask either configured by user or max supported - */ -static inline uint8_t wlan_vdev_mlme_get_txchainmask( - struct wlan_objmgr_vdev *vdev) -{ - return vdev->vdev_mlme.tx_chainmask; -} - -/** - * wlan_vdev_mlme_set_rxchainmask() - set Rx chainmask - * @vdev: VDEV object - * @chainmask : Rx chainmask either configured by user or max supported - * - * API to set the Rx chainmask - * - * Return: void - */ -static inline void wlan_vdev_mlme_set_rxchainmask( - struct wlan_objmgr_vdev *vdev, - uint8_t chainmask) -{ - vdev->vdev_mlme.rx_chainmask = chainmask; -} - -/** - * wlan_vdev_mlme_get_rxchainmask() - get Rx chainmask - * @vdev: VDEV object - * - * API to get the Rx chainmask - * - * Return: - * @chainmask : Rx chainmask either configured by user or max supported - */ -static inline uint8_t wlan_vdev_mlme_get_rxchainmask( - struct wlan_objmgr_vdev *vdev) -{ - /* This API is invoked with lock acquired, do not add log prints */ - return vdev->vdev_mlme.rx_chainmask; -} - -/** - * wlan_vdev_mlme_set_txpower() - set tx power - * @vdev: VDEV object - * @txpow: tx power either configured by used or max allowed - * - * API to set the tx power - * - * Return: void - */ -static inline void wlan_vdev_mlme_set_txpower( - struct wlan_objmgr_vdev *vdev, - uint8_t txpow) -{ - vdev->vdev_mlme.tx_power = txpow; -} - -/** - * wlan_vdev_mlme_get_txpower() - get tx power - * @vdev: VDEV object - * - * API to get the tx power - * - * Return: - * @txpow: tx power either configured by used or max allowed - */ -static inline uint8_t wlan_vdev_mlme_get_txpower( - struct wlan_objmgr_vdev *vdev) -{ - return vdev->vdev_mlme.tx_power; -} - -/** - * wlan_vdev_mlme_set_maxrate() - set max rate - * @vdev: VDEV object - * @maxrate: configured by used or based on configured mode - * - * API to set the max rate the vdev supports - * - * Return: void - */ -static inline void wlan_vdev_mlme_set_maxrate( - struct wlan_objmgr_vdev *vdev, - uint32_t maxrate) -{ - vdev->vdev_mlme.max_rate = maxrate; -} - -/** - * wlan_vdev_mlme_get_maxrate() - get max rate - * @vdev: VDEV object - * - * API to get the max rate the vdev supports - * - * Return: - * @maxrate: configured by used or based on configured mode - */ -static inline uint32_t wlan_vdev_mlme_get_maxrate( - struct wlan_objmgr_vdev *vdev) -{ - return vdev->vdev_mlme.max_rate; -} - -/** - * wlan_vdev_mlme_set_txmgmtrate() - set txmgmtrate - * @vdev: VDEV object - * @txmgmtrate: Tx Mgmt rate - * - * API to set Mgmt Tx rate - * - * Return: void - */ -static inline void wlan_vdev_mlme_set_txmgmtrate( - struct wlan_objmgr_vdev *vdev, - uint32_t txmgmtrate) -{ - vdev->vdev_mlme.tx_mgmt_rate = txmgmtrate; -} - -/** - * wlan_vdev_mlme_get_txmgmtrate() - get txmgmtrate - * @vdev: VDEV object - * - * API to get Mgmt Tx rate - * - * Return: - * @txmgmtrate: Tx Mgmt rate - */ -static inline uint32_t wlan_vdev_mlme_get_txmgmtrate( - struct wlan_objmgr_vdev *vdev) -{ - return vdev->vdev_mlme.tx_mgmt_rate; -} -#endif - /** * wlan_vdev_mlme_feat_cap_set() - set feature caps * @vdev: VDEV object @@ -1416,6 +1115,22 @@ static inline struct wlan_objmgr_peer *wlan_vdev_get_bsspeer( return vdev->vdev_objmgr.bss_peer; } +/** + * wlan_objmgr_vdev_find_peer_by_mac() - get a peer with given mac from vdev + * @vdev: VDEV object + * @peer_mac: mac address of the peer to be found + * @dbg_id: dbg_id of the module + * + * API to get and increment ref count of BSS peer of VDEV + * + * Return: + * @peer: peer pointer to the peer of the mac address + */ +struct wlan_objmgr_peer * +wlan_objmgr_vdev_find_peer_by_mac(struct wlan_objmgr_vdev *vdev, + uint8_t *peer_mac, + wlan_objmgr_ref_dbgid dbg_id); + /** * wlan_objmgr_vdev_try_get_bsspeer() - get and increment ref count of BSS peer * of VDEV @@ -1510,8 +1225,17 @@ static inline uint16_t wlan_vdev_get_peer_count(struct wlan_objmgr_vdev *vdev) * * Return: void */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +void wlan_objmgr_vdev_get_ref_debug(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, + const char *func, int line); + +#define wlan_objmgr_vdev_get_ref(vdev, dbgid) \ + wlan_objmgr_vdev_get_ref_debug(vdev, dbgid, __func__, __LINE__) +#else void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, wlan_objmgr_ref_dbgid id); +#endif /** * wlan_objmgr_vdev_try_get_ref() - increment ref count, if allowed @@ -1522,8 +1246,18 @@ void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, * * Return: void */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +QDF_STATUS wlan_objmgr_vdev_try_get_ref_debug(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, + const char *func, int line); + +#define wlan_objmgr_vdev_try_get_ref(vdev, dbgid) \ + wlan_objmgr_vdev_try_get_ref_debug(vdev, dbgid, \ + __func__, __LINE__) +#else QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, wlan_objmgr_ref_dbgid id); +#endif /** * wlan_objmgr_vdev_release_ref() - decrement ref count @@ -1535,8 +1269,111 @@ QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, * * Return: void */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +void wlan_objmgr_vdev_release_ref_debug(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, + const char *func, int line); + +#define wlan_objmgr_vdev_release_ref(vdev, dbgid)\ + wlan_objmgr_vdev_release_ref_debug(vdev, dbgid, \ + __func__, __LINE__) +#else void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev, wlan_objmgr_ref_dbgid id); +#endif + +/** + * wlan_vdev_get_next_active_vdev_of_pdev() - get next active vdev + * @pdev: PDEV object + * @vdev_list: qdf_list_t + * @vdev: VDEV object + * @dbg_id: id of the caller + * + * API to get next active vdev object pointer of vdev + * + * Return: + * @vdev_next: VDEV object + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev_debug( + struct wlan_objmgr_pdev *pdev, + qdf_list_t *vdev_list, + struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_vdev_get_next_active_vdev_of_pdev(pdev, vdev_list, vdev, dbgid) \ + wlan_vdev_get_next_active_vdev_of_pdev_debug(pdev, vdev_list, \ + vdev, dbgid, __func__, __LINE__) +#else +struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev( + struct wlan_objmgr_pdev *pdev, + qdf_list_t *vdev_list, + struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid dbg_id); +#endif + +/** + * wlan_pdev_peek_active_first_vdev() - get first active vdev from pdev list + * @pdev: PDEV object + * @dbg_id: id of the caller + * + * API to get the head active vdev of given pdev (of pdev's vdev list) + * + * Return: + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_pdev_peek_active_first_vdev_debug( + struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_pdev_peek_active_first_vdev(pdev, dbgid) \ + wlan_pdev_peek_active_first_vdev_debug(pdev, dbgid, \ + __func__, __LINE__) +#else +struct wlan_objmgr_vdev *wlan_pdev_peek_active_first_vdev( + struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid dbg_id); +#endif + +/** + * wlan_pdev_vdev_list_peek_active_head() - get first active vdev from pdev list + * @vdev: VDEV object + * @vdev_list: qdf_list_t + * @dbg_id: id of the caller + * + * API to get the head active vdev of given vdev (of pdev's vdev list) + * + * Return: + * @peer: head peer + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head_debug( + struct wlan_objmgr_pdev *pdev, + qdf_list_t *vdev_list, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line); + +#define wlan_pdev_vdev_list_peek_active_head(pdev, vdev_list, dbgid) \ + wlan_pdev_vdev_list_peek_active_head_debug(pdev, vdev_list, \ + dbgid, __func__, __LINE__) +#else +struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head( + struct wlan_objmgr_pdev *pdev, + qdf_list_t *vdev_list, + wlan_objmgr_ref_dbgid dbg_id); +#endif + +/** + * wlan_objmgr_vdev_peer_freed_notify() - Notifies modules about peer freed + * @vdev: VDEV object + * + * API to invokes registered callbacks to notify about peer freed + * + * Return: void + */ +void wlan_objmgr_vdev_peer_freed_notify(struct wlan_objmgr_vdev *vdev); /** * wlan_vdev_set_max_peer_count() - set max peer count @@ -1568,37 +1405,72 @@ static inline uint16_t wlan_vdev_get_max_peer_count( } /** - * wlan_vdev_set_dp_handle() - set dp handle + * wlan_print_vdev_info() - print vdev members * @vdev: vdev object pointer - * @dp_handle: Data path module handle * * Return: void */ -static inline void wlan_vdev_set_dp_handle(struct wlan_objmgr_vdev *vdev, - void *dp_handle) -{ - if (qdf_unlikely(!vdev)) { - QDF_BUG(0); - return; - } +#ifdef WLAN_OBJMGR_DEBUG +void wlan_print_vdev_info(struct wlan_objmgr_vdev *vdev); +#else +static inline void wlan_print_vdev_info(struct wlan_objmgr_vdev *vdev) {} +#endif - vdev->dp_handle = dp_handle; +/** + * wlan_objmgr_vdev_trace_init_lock() - Initialize trace lock + * @vdev: vdev object pointer + * + * Return: void + */ +#ifdef WLAN_OBJMGR_TRACE +static inline void +wlan_objmgr_vdev_trace_init_lock(struct wlan_objmgr_vdev *vdev) +{ + wlan_objmgr_trace_init_lock(&vdev->vdev_objmgr.trace); +} +#else +static inline void +wlan_objmgr_vdev_trace_init_lock(struct wlan_objmgr_vdev *vdev) +{ } +#endif /** - * wlan_vdev_get_dp_handle() - get dp handle + * wlan_objmgr_vdev_trace_deinit_lock() - Deinitialize trace lock * @vdev: vdev object pointer * - * Return: dp handle + * Return: void */ -static inline void *wlan_vdev_get_dp_handle(struct wlan_objmgr_vdev *vdev) +#ifdef WLAN_OBJMGR_TRACE +static inline void +wlan_objmgr_vdev_trace_deinit_lock(struct wlan_objmgr_vdev *vdev) { - if (qdf_unlikely(!vdev)) { - QDF_BUG(0); - return NULL; - } + wlan_objmgr_trace_deinit_lock(&vdev->vdev_objmgr.trace); +} +#else +static inline void +wlan_objmgr_vdev_trace_deinit_lock(struct wlan_objmgr_vdev *vdev) +{ +} +#endif - return vdev->dp_handle; +/** + * wlan_objmgr_vdev_trace_del_ref_list() - Delete trace ref list + * @vdev: vdev object pointer + * + * Return: void + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static inline void +wlan_objmgr_vdev_trace_del_ref_list(struct wlan_objmgr_vdev *vdev) +{ + wlan_objmgr_trace_del_ref_list(&vdev->vdev_objmgr.trace); +} +#else +static inline void +wlan_objmgr_vdev_trace_del_ref_list(struct wlan_objmgr_vdev *vdev) +{ } +#endif #endif /* _WLAN_OBJMGR_VDEV_OBJ_H_*/ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_debug.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_debug.c index ea9efebcee8edc093ebf2a8effcbe51440b6e587..a6d9b242b374073b43cb1b0c9b883a9801d50e46 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_debug.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_debug.c @@ -27,9 +27,14 @@ #include "wlan_objmgr_global_obj_i.h" #include #include +#include -#define LOG_DEL_OBJ_TIMEOUT_VALUE_MSEC 5000 -#define LOG_DEL_OBJ_DESTROY_DURATION_SEC 5 +/* + * Default TTL (of FW) for mgmt frames is 5 sec, by considering all the other + * delays, arrived with this value + */ +#define LOG_DEL_OBJ_TIMEOUT_VALUE_MSEC 8000 +#define LOG_DEL_OBJ_DESTROY_DURATION_SEC 8 /* * The max duration for which a obj can be allowed to remain in L-state * The duration should be higher than the psoc idle timeout. @@ -37,6 +42,13 @@ #define LOG_DEL_OBJ_DESTROY_ASSERT_DURATION_SEC 32 #define LOG_DEL_OBJ_LIST_MAX_COUNT (3 + 5 + 48 + 4096) +union wlan_objmgr_del_obj { + struct wlan_objmgr_psoc *obj_psoc; + struct wlan_objmgr_pdev *obj_pdev; + struct wlan_objmgr_vdev *obj_vdev; + struct wlan_objmgr_peer *obj_peer; +}; + /** * struct log_del_obj - Logically deleted Object * @obj: Represents peer/vdev/pdev/psoc @@ -46,7 +58,7 @@ * deleted state */ struct log_del_obj { - void *obj; + union wlan_objmgr_del_obj obj; qdf_list_node_t node; enum wlan_objmgr_obj_type obj_type; qdf_time_t tstamp; @@ -89,18 +101,18 @@ wlan_obj_type_get_obj_name(enum wlan_objmgr_obj_type obj_type) } static uint8_t* -wlan_objmgr_debug_get_macaddr(void *obj, +wlan_objmgr_debug_get_macaddr(union wlan_objmgr_del_obj *obj, enum wlan_objmgr_obj_type obj_type) { switch (obj_type) { case WLAN_PSOC_OP: - return wlan_psoc_get_hw_macaddr(obj); + return wlan_psoc_get_hw_macaddr(obj->obj_psoc); case WLAN_PDEV_OP: - return wlan_pdev_get_hw_macaddr(obj); + return wlan_pdev_get_hw_macaddr(obj->obj_pdev); case WLAN_VDEV_OP: - return wlan_vdev_mlme_get_macaddr(obj); + return wlan_vdev_mlme_get_macaddr(obj->obj_vdev); case WLAN_PEER_OP: - return wlan_peer_get_macaddr(obj); + return wlan_peer_get_macaddr(obj->obj_peer); default: obj_mgr_err("invalid obj_type"); return NULL; @@ -123,6 +135,29 @@ wlan_objmgr_insert_ld_obj_to_list(struct wlan_objmgr_debug_info *debug_info, qdf_spin_unlock_bh(&debug_info->list_lock); } +static void wlan_obj_type_get_obj(union wlan_objmgr_del_obj *obj, + union wlan_objmgr_del_obj *del_obj, + enum wlan_objmgr_obj_type obj_type) +{ + switch (obj_type) { + case WLAN_PSOC_OP: + del_obj->obj_psoc = obj->obj_psoc; + return; + case WLAN_PDEV_OP: + del_obj->obj_pdev = obj->obj_pdev; + return; + case WLAN_VDEV_OP: + del_obj->obj_vdev = obj->obj_vdev; + return; + case WLAN_PEER_OP: + del_obj->obj_peer = obj->obj_peer; + return; + default: + obj_mgr_err("invalid obj_type"); + return; + } +} + void wlan_objmgr_notify_log_delete(void *obj, enum wlan_objmgr_obj_type obj_type) { @@ -131,6 +166,7 @@ void wlan_objmgr_notify_log_delete(void *obj, uint8_t *macaddr; qdf_time_t tstamp; struct log_del_obj *node; + union wlan_objmgr_del_obj *del_obj = (union wlan_objmgr_del_obj *)&obj; if (!obj) { obj_mgr_err("object is null"); @@ -146,7 +182,7 @@ void wlan_objmgr_notify_log_delete(void *obj, return; } - macaddr = wlan_objmgr_debug_get_macaddr(obj, obj_type); + macaddr = wlan_objmgr_debug_get_macaddr(del_obj, obj_type); if (!macaddr) { obj_mgr_err("macaddr is null"); return; @@ -163,16 +199,38 @@ void wlan_objmgr_notify_log_delete(void *obj, if (!node) return; - node->obj = obj; + wlan_obj_type_get_obj(del_obj, &node->obj, obj_type); node->obj_type = obj_type; node->tstamp = tstamp; - obj_mgr_debug("#%s : mac_addr :" QDF_MAC_ADDR_STR" entered L-state", - obj_name, QDF_MAC_ADDR_ARRAY(macaddr)); + obj_mgr_debug("#%s : mac_addr: "QDF_MAC_ADDR_FMT" entered L-state", + obj_name, QDF_MAC_ADDR_REF(macaddr)); wlan_objmgr_insert_ld_obj_to_list(debug_info, &node->node); } +static bool wlan_objmgr_del_obj_match(union wlan_objmgr_del_obj *obj, + union wlan_objmgr_del_obj *del_obj, + enum wlan_objmgr_obj_type obj_type) +{ + switch (obj_type) { + case WLAN_PSOC_OP: + if (del_obj->obj_psoc == obj->obj_psoc) + return true; + case WLAN_PDEV_OP: + if (del_obj->obj_pdev == obj->obj_pdev) + return true; + case WLAN_VDEV_OP: + if (del_obj->obj_vdev == obj->obj_vdev) + return true; + case WLAN_PEER_OP: + if (del_obj->obj_peer == obj->obj_peer) + return true; + default: + return false; + } +} + static void -wlan_objmgr_rem_ld_obj_from_list(void *obj, +wlan_objmgr_rem_ld_obj_from_list(union wlan_objmgr_del_obj *obj, struct wlan_objmgr_debug_info *debug_info, enum wlan_objmgr_obj_type obj_type) { @@ -188,7 +246,8 @@ wlan_objmgr_rem_ld_obj_from_list(void *obj, while (QDF_IS_STATUS_SUCCESS(status)) { obj_to_remove = qdf_container_of(node, struct log_del_obj, node); - if (obj_to_remove->obj == obj && + if (wlan_objmgr_del_obj_match(obj, &obj_to_remove->obj, + obj_type) && obj_to_remove->obj_type == obj_type) { status = qdf_list_remove_node(list, &obj_to_remove->node); @@ -211,6 +270,7 @@ void wlan_objmgr_notify_destroy(void *obj, struct wlan_objmgr_debug_info *debug_info; uint8_t *macaddr; const char *obj_name; + union wlan_objmgr_del_obj *del_obj = (union wlan_objmgr_del_obj *)&obj; qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); debug_info = g_umac_glb_obj->debug_info; @@ -220,7 +280,7 @@ void wlan_objmgr_notify_destroy(void *obj, obj_mgr_err("debug_info is null"); return; } - macaddr = wlan_objmgr_debug_get_macaddr(obj, obj_type); + macaddr = wlan_objmgr_debug_get_macaddr(del_obj, obj_type); if (!macaddr) { obj_mgr_err("macaddr is null"); return; @@ -230,10 +290,11 @@ void wlan_objmgr_notify_destroy(void *obj, obj_mgr_err("obj_name is null"); return; } - obj_mgr_debug("#%s, macaddr: " QDF_MAC_ADDR_STR" exited L-state", - obj_name, QDF_MAC_ADDR_ARRAY(macaddr)); + obj_mgr_debug("#%s : macaddr: "QDF_MAC_ADDR_FMT" exited L-state", + obj_name, QDF_MAC_ADDR_REF(macaddr)); - wlan_objmgr_rem_ld_obj_from_list(obj, debug_info, obj_type); + wlan_objmgr_rem_ld_obj_from_list(del_obj, + debug_info, obj_type); } /** @@ -266,28 +327,24 @@ static inline void wlan_objmgr_debug_obj_destroyed_panic(const char *obj_name) * * Return: None */ -static void wlan_objmgr_print_pending_refs(void *obj, +static void wlan_objmgr_print_pending_refs(union wlan_objmgr_del_obj *obj, enum wlan_objmgr_obj_type obj_type) { switch (obj_type) { case WLAN_PSOC_OP: - wlan_objmgr_print_ref_ids(((struct wlan_objmgr_psoc *) - obj)->soc_objmgr.ref_id_dbg, + wlan_objmgr_print_ref_ids(obj->obj_psoc->soc_objmgr.ref_id_dbg, QDF_TRACE_LEVEL_DEBUG); break; case WLAN_PDEV_OP: - wlan_objmgr_print_ref_ids(((struct wlan_objmgr_pdev *) - obj)->pdev_objmgr.ref_id_dbg, + wlan_objmgr_print_ref_ids(obj->obj_pdev->pdev_objmgr.ref_id_dbg, QDF_TRACE_LEVEL_DEBUG); break; case WLAN_VDEV_OP: - wlan_objmgr_print_ref_ids(((struct wlan_objmgr_vdev *) - obj)->vdev_objmgr.ref_id_dbg, + wlan_objmgr_print_ref_ids(obj->obj_vdev->vdev_objmgr.ref_id_dbg, QDF_TRACE_LEVEL_DEBUG); break; case WLAN_PEER_OP: - wlan_objmgr_print_ref_ids(((struct wlan_objmgr_peer *) - obj)->peer_objmgr.ref_id_dbg, + wlan_objmgr_print_ref_ids(obj->obj_peer->peer_objmgr.ref_id_dbg, QDF_TRACE_LEVEL_DEBUG); break; default: @@ -295,6 +352,84 @@ static void wlan_objmgr_print_pending_refs(void *obj, } } +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static void +wlan_objmgr_print_ref_func_line(struct wlan_objmgr_trace_func *func_head, + uint32_t id) +{ + uint32_t ref_cnt; + struct wlan_objmgr_line_ref_node *tmp_ln_node; + + obj_mgr_debug("ID: %s", string_from_dbgid(id)); + while (func_head) { + obj_mgr_debug("Func: %s", func_head->func); + tmp_ln_node = func_head->line_head; + while (tmp_ln_node) { + ref_cnt = qdf_atomic_read(&tmp_ln_node->line_ref.cnt); + obj_mgr_debug("line: %d cnt: %d", + tmp_ln_node->line_ref.line, + ref_cnt); + tmp_ln_node = tmp_ln_node->next; + } + func_head = func_head->next; + } +} + +static void +wlan_objmgr_trace_print_ref(union wlan_objmgr_del_obj *obj, + enum wlan_objmgr_obj_type obj_type) +{ + uint32_t id; + struct wlan_objmgr_trace_func *func_head; + struct wlan_objmgr_trace *trace; + struct wlan_objmgr_vdev_objmgr *vdev_obj; + struct wlan_objmgr_peer_objmgr *peer_obj; + + switch (obj_type) { + case WLAN_VDEV_OP: + vdev_obj = &obj->obj_vdev->vdev_objmgr; + trace = &vdev_obj->trace; + for (id = 0; id < WLAN_REF_ID_MAX; id++) { + if (qdf_atomic_read(&vdev_obj->ref_id_dbg[id])) { + obj_mgr_debug("Reference:"); + + func_head = trace->references[id].head; + wlan_objmgr_print_ref_func_line(func_head, id); + + obj_mgr_debug("Dereference:"); + func_head = trace->dereferences[id].head; + wlan_objmgr_print_ref_func_line(func_head, id); + } + } + break; + case WLAN_PEER_OP: + peer_obj = &obj->obj_peer->peer_objmgr; + trace = &peer_obj->trace; + for (id = 0; id < WLAN_REF_ID_MAX; id++) { + if (qdf_atomic_read(&vdev_obj->ref_id_dbg[id])) { + obj_mgr_debug("Reference:"); + + func_head = trace->references[id].head; + wlan_objmgr_print_ref_func_line(func_head, id); + + obj_mgr_debug("Dereference:"); + func_head = trace->dereferences[id].head; + wlan_objmgr_print_ref_func_line(func_head, id); + } + } + break; + default: + break; + } +} +#else +static void +wlan_objmgr_trace_print_ref(union wlan_objmgr_del_obj *obj, + enum wlan_objmgr_obj_type obj_type) +{ +} +#endif + /* timeout handler for iterating logically deleted object */ static void wlan_objmgr_iterate_log_del_obj_handler(void *timer_arg) @@ -335,7 +470,8 @@ static void wlan_objmgr_iterate_log_del_obj_handler(void *timer_arg) do { del_obj = qdf_container_of(node, struct log_del_obj, node); obj_type = del_obj->obj_type; - macaddr = wlan_objmgr_debug_get_macaddr(del_obj->obj, obj_type); + macaddr = wlan_objmgr_debug_get_macaddr(&del_obj->obj, + obj_type); obj_name = wlan_obj_type_get_obj_name(obj_type); /* If object is in logically deleted state for time more than @@ -356,10 +492,11 @@ static void wlan_objmgr_iterate_log_del_obj_handler(void *timer_arg) break; } - obj_mgr_alert("#%s in L-state,MAC: " QDF_MAC_ADDR_STR, - obj_name, QDF_MAC_ADDR_ARRAY(macaddr)); - wlan_objmgr_print_pending_refs(del_obj->obj, obj_type); + obj_mgr_alert("#%s in L-state,MAC: " QDF_MAC_ADDR_FMT, + obj_name, QDF_MAC_ADDR_REF(macaddr)); + wlan_objmgr_print_pending_refs(&del_obj->obj, obj_type); + wlan_objmgr_trace_print_ref(&del_obj->obj, obj_type); if (cur_tstamp > del_obj->tstamp + LOG_DEL_OBJ_DESTROY_ASSERT_DURATION_SEC) { if (!qdf_is_recovering() && !qdf_is_fw_down()) @@ -455,3 +592,163 @@ void wlan_objmgr_debug_info_init(void) g_umac_glb_obj->debug_info = debug_info; qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); } + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +void +wlan_objmgr_trace_init_lock(struct wlan_objmgr_trace *trace) +{ + qdf_spinlock_create(&trace->trace_lock); +} + +void +wlan_objmgr_trace_deinit_lock(struct wlan_objmgr_trace *trace) +{ + qdf_spinlock_destroy(&trace->trace_lock); +} +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static inline struct wlan_objmgr_line_ref_node* +wlan_objmgr_trace_line_node_alloc(int line) +{ + struct wlan_objmgr_line_ref_node *line_node; + + line_node = qdf_mem_malloc_atomic(sizeof(*line_node)); + if (!line_node) + return NULL; + + line_node->line_ref.line = line; + qdf_atomic_set(&line_node->line_ref.cnt, 1); + line_node->next = NULL; + + return line_node; +} + +static inline struct wlan_objmgr_trace_func* +wlan_objmgr_trace_ref_node_alloc(const char *func, int line) +{ + struct wlan_objmgr_trace_func *func_node; + struct wlan_objmgr_line_ref_node *line_node; + + func_node = qdf_mem_malloc_atomic(sizeof(*func_node)); + if (!func_node) + return NULL; + + line_node = wlan_objmgr_trace_line_node_alloc(line); + if (!line_node) { + qdf_mem_free(func_node); + return NULL; + } + + func_node->line_head = line_node; + qdf_str_lcopy(func_node->func, func, WLAN_OBJMGR_TRACE_FUNC_SIZE); + func_node->next = NULL; + + return func_node; +} + +static inline void +wlan_objmgr_trace_check_line(struct wlan_objmgr_trace_func *tmp_func_node, + struct wlan_objmgr_trace *trace, int line) +{ + struct wlan_objmgr_line_ref_node *line_node; + struct wlan_objmgr_line_ref_node *tmp_ln_node; + + tmp_ln_node = tmp_func_node->line_head; + while (tmp_ln_node) { + line_node = tmp_ln_node; + if (tmp_ln_node->line_ref.line == line) { + qdf_atomic_inc(&tmp_ln_node->line_ref.cnt); + break; + } + tmp_ln_node = tmp_ln_node->next; + } + if (!tmp_ln_node) { + tmp_ln_node = wlan_objmgr_trace_line_node_alloc(line); + if (tmp_ln_node) + line_node->next = tmp_ln_node; + } +} + +void +wlan_objmgr_trace_ref(struct wlan_objmgr_trace_func **func_head, + struct wlan_objmgr_trace *trace, + const char *func, int line) +{ + struct wlan_objmgr_trace_func *tmp_func_node; + struct wlan_objmgr_trace_func *func_node; + + qdf_spin_lock_bh(&trace->trace_lock); + if (!*func_head) { + tmp_func_node = wlan_objmgr_trace_ref_node_alloc(func, line); + if (tmp_func_node) + *func_head = tmp_func_node; + } else { + tmp_func_node = *func_head; + while (tmp_func_node) { + func_node = tmp_func_node; + if (!qdf_str_ncmp(tmp_func_node->func, func, + WLAN_OBJMGR_TRACE_FUNC_SIZE - 1)) { + wlan_objmgr_trace_check_line(tmp_func_node, + trace, line); + break; + } + tmp_func_node = tmp_func_node->next; + } + + if (!tmp_func_node) { + tmp_func_node = wlan_objmgr_trace_ref_node_alloc(func, + line); + if (tmp_func_node) + func_node->next = tmp_func_node; + } + } + qdf_spin_unlock_bh(&trace->trace_lock); +} + +void +wlan_objmgr_trace_del_line(struct wlan_objmgr_line_ref_node **line_head) +{ + struct wlan_objmgr_line_ref_node *del_tmp_node; + struct wlan_objmgr_line_ref_node *line_node; + + line_node = *line_head; + while (line_node) { + del_tmp_node = line_node; + line_node = line_node->next; + qdf_mem_free(del_tmp_node); + } + *line_head = NULL; +} + +void +wlan_objmgr_trace_del_ref_list(struct wlan_objmgr_trace *trace) +{ + struct wlan_objmgr_trace_func *func_node; + struct wlan_objmgr_trace_func *del_tmp_node; + uint32_t id; + + qdf_spin_lock_bh(&trace->trace_lock); + for (id = 0; id < WLAN_REF_ID_MAX; id++) { + func_node = trace->references[id].head; + while (func_node) { + del_tmp_node = func_node; + wlan_objmgr_trace_del_line(&del_tmp_node->line_head); + func_node = func_node->next; + qdf_mem_free(del_tmp_node); + } + trace->references[id].head = NULL; + } + for (id = 0; id < WLAN_REF_ID_MAX; id++) { + func_node = trace->dereferences[id].head; + while (func_node) { + del_tmp_node = func_node; + wlan_objmgr_trace_del_line(&del_tmp_node->line_head); + func_node = func_node->next; + qdf_mem_free(del_tmp_node); + } + trace->dereferences[id].head = NULL; + } + qdf_spin_unlock_bh(&trace->trace_lock); +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c index 19748d8587b1f3ca8c7f2f596e48047b3872aea1..f307d213bba6238c33f510250917d6398d953c3a 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c @@ -556,6 +556,55 @@ QDF_STATUS wlan_objmgr_unregister_vdev_status_handler( return QDF_STATUS_SUCCESS; } +QDF_STATUS wlan_objmgr_register_vdev_peer_free_notify_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_peer_free_notify_handler handler) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + obj_mgr_err("Component %d is out of range", id); + WLAN_OBJMGR_BUG(0); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->vdev_peer_free_notify_handler[id]) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + obj_mgr_err("Callback for comp %d is already registered", id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler in Global object table */ + g_umac_glb_obj->vdev_peer_free_notify_handler[id] = handler; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_vdev_peer_free_notify_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_peer_free_notify_handler handler) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + obj_mgr_err("Component %d is out of range", id); + WLAN_OBJMGR_BUG(0); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->vdev_peer_free_notify_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + obj_mgr_err("Callback for Component %d is not registered", id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers to NULL */ + g_umac_glb_obj->vdev_peer_free_notify_handler[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + + return QDF_STATUS_SUCCESS; +} QDF_STATUS wlan_objmgr_register_peer_create_handler( enum wlan_umac_comp_id id, diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h index c42ca6ca911907052444b6ac8d0dc6a4bc12bc70..b9e24673a6878a757c0eb4f836e1bf38a4ce072b 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 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 @@ -44,6 +44,7 @@ struct wlan_objmgr_debug_info; * @vdev_create_handler_arg[]: VDEV create handler args array * @vdev_destroy_handler[]: VDEV destroy handler array * @vdev_destroy_handler_arg[]: VDEV destroy handler args array + * @vdev_peer_free_notify_handler[]: VDEV peer free notify handler array * @vdev_status_handler[]: VDEV status handler array * @vdev_status_handler_arg[]: VDEV status handler args array * @peer_create_handler[]: PEER create handler array @@ -81,6 +82,8 @@ struct wlan_objmgr_global { wlan_objmgr_vdev_destroy_handler vdev_destroy_handler[WLAN_UMAC_MAX_COMPONENTS]; void *vdev_destroy_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_vdev_peer_free_notify_handler + vdev_peer_free_notify_handler[WLAN_UMAC_MAX_COMPONENTS]; wlan_objmgr_vdev_status_handler vdev_status_handler[WLAN_UMAC_MAX_COMPONENTS]; void *vdev_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c index d3494b0a6ef0f63fcbfdfb063c8dd77c88346fae..06311d9c1127f5ac6d3c62c19bf57d15312a309e 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -172,7 +172,7 @@ struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create( return NULL; } - obj_mgr_info("Created pdev %d", pdev->pdev_objmgr.wlan_pdev_id); + obj_mgr_debug("Created pdev %d", pdev->pdev_objmgr.wlan_pdev_id); return pdev; } @@ -194,7 +194,8 @@ static QDF_STATUS wlan_objmgr_pdev_obj_destroy(struct wlan_objmgr_pdev *pdev) pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); - obj_mgr_info("Physically deleting pdev %d", pdev_id); + wlan_print_pdev_info(pdev); + obj_mgr_debug("Physically deleting pdev %d", pdev_id); if (pdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { obj_mgr_err("PDEV object delete is not invoked pdevid:%d objstate:%d", @@ -243,8 +244,8 @@ QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev) return QDF_STATUS_E_FAILURE; } - obj_mgr_info("Logically deleting pdev %d", - pdev->pdev_objmgr.wlan_pdev_id); + obj_mgr_debug("Logically deleting pdev %d", + pdev->pdev_objmgr.wlan_pdev_id); print_idx = qdf_get_pidx(); wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg, @@ -622,9 +623,198 @@ QDF_STATUS wlan_objmgr_pdev_vdev_detach(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } -struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev( +void *wlan_objmgr_pdev_get_comp_private_obj( + struct wlan_objmgr_pdev *pdev, + enum wlan_umac_comp_id id) +{ + void *comp_priv_obj; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + QDF_BUG(0); + return NULL; + } + + if (!pdev) { + QDF_BUG(0); + return NULL; + } + + comp_priv_obj = pdev->pdev_comp_priv_obj[id]; + + return comp_priv_obj; +} + +qdf_export_symbol(wlan_objmgr_pdev_get_comp_private_obj); + +void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid id) +{ + if (!pdev) { + obj_mgr_err("pdev obj is NULL"); + QDF_ASSERT(0); + return; + } + qdf_atomic_inc(&pdev->pdev_objmgr.ref_cnt); + qdf_atomic_inc(&pdev->pdev_objmgr.ref_id_dbg[id]); +} + +qdf_export_symbol(wlan_objmgr_pdev_get_ref); + +QDF_STATUS wlan_objmgr_pdev_try_get_ref(struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid id) +{ + uint8_t pdev_id; + + if (!pdev) { + obj_mgr_err("pdev obj is NULL"); + QDF_ASSERT(0); + return QDF_STATUS_E_FAILURE; + } + + wlan_pdev_obj_lock(pdev); + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + if (pdev->obj_state != WLAN_OBJ_STATE_CREATED) { + wlan_pdev_obj_unlock(pdev); + if (pdev->pdev_objmgr.print_cnt++ <= + WLAN_OBJMGR_RATELIMIT_THRESH) + obj_mgr_err( + "[Ref id: %d] pdev [%d] is not in Created(st:%d)", + id, pdev_id, pdev->obj_state); + return QDF_STATUS_E_RESOURCES; + } + + wlan_objmgr_pdev_get_ref(pdev, id); + wlan_pdev_obj_unlock(pdev); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(wlan_objmgr_pdev_try_get_ref); + +void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid id) +{ + uint8_t pdev_id; + + if (!pdev) { + obj_mgr_err("pdev obj is NULL"); + QDF_ASSERT(0); + return; + } + + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_id_dbg[id])) { + obj_mgr_err("pdev (id:%d)ref cnt was not taken by %d", + pdev_id, id); + wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg, + QDF_TRACE_LEVEL_FATAL); + WLAN_OBJMGR_BUG(0); + return; + } + + if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_cnt)) { + obj_mgr_err("pdev ref cnt is 0: pdev-id:%d", pdev_id); + WLAN_OBJMGR_BUG(0); + return; + } + + qdf_atomic_dec(&pdev->pdev_objmgr.ref_id_dbg[id]); + /* Decrement ref count, free pdev, if ref count == 0 */ + if (qdf_atomic_dec_and_test(&pdev->pdev_objmgr.ref_cnt)) + wlan_objmgr_pdev_obj_destroy(pdev); +} + +qdf_export_symbol(wlan_objmgr_pdev_release_ref); + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_pdev_get_first_vdev_debug( + struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; + qdf_list_t *vdev_list = NULL; + struct wlan_objmgr_vdev *vdev; + qdf_list_node_t *node = NULL; + qdf_list_node_t *prev_node = NULL; + + wlan_pdev_obj_lock(pdev); + + /* VDEV list */ + vdev_list = &objmgr->wlan_vdev_list; + if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { + wlan_pdev_obj_unlock(pdev); + return NULL; + } + + do { + vdev = qdf_container_of(node, struct wlan_objmgr_vdev, + vdev_node); + if (wlan_objmgr_vdev_try_get_ref_debug(vdev, + dbg_id, func, line) == + QDF_STATUS_SUCCESS) { + wlan_pdev_obj_unlock(pdev); + return vdev; + } + + prev_node = node; + } while (qdf_list_peek_next(vdev_list, prev_node, &node) == + QDF_STATUS_SUCCESS); + + wlan_pdev_obj_unlock(pdev); + + return NULL; +} + +qdf_export_symbol(wlan_objmgr_pdev_get_first_vdev_debug); +#else +struct wlan_objmgr_vdev *wlan_objmgr_pdev_get_first_vdev( + struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; + qdf_list_t *vdev_list = NULL; + struct wlan_objmgr_vdev *vdev; + qdf_list_node_t *node = NULL; + qdf_list_node_t *prev_node = NULL; + + wlan_pdev_obj_lock(pdev); + + /* VDEV list */ + vdev_list = &objmgr->wlan_vdev_list; + if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { + wlan_pdev_obj_unlock(pdev); + return NULL; + } + + do { + vdev = qdf_container_of(node, struct wlan_objmgr_vdev, + vdev_node); + if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == + QDF_STATUS_SUCCESS) { + wlan_pdev_obj_unlock(pdev); + return vdev; + } + + prev_node = node; + } while (qdf_list_peek_next(vdev_list, prev_node, &node) == + QDF_STATUS_SUCCESS); + + wlan_pdev_obj_unlock(pdev); + + return NULL; +} + +qdf_export_symbol(wlan_objmgr_pdev_get_first_vdev); +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_debug( struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, - wlan_objmgr_ref_dbgid dbg_id) + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_vdev *vdev_next; @@ -637,12 +827,15 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev( vdev_list = &objmgr->wlan_vdev_list; /* Get first vdev */ vdev = wlan_pdev_vdev_list_peek_head(vdev_list); - /* Iterate through pdev's vdev list, till vdev id matches with - entry of vdev list */ + /** + * Iterate through pdev's vdev list, till vdev id matches with + * entry of vdev list + */ while (vdev) { if (wlan_vdev_get_id(vdev) == vdev_id) { - if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != - QDF_STATUS_SUCCESS) + if (wlan_objmgr_vdev_try_get_ref_debug(vdev, dbg_id, + func, line) != + QDF_STATUS_SUCCESS) vdev = NULL; wlan_pdev_obj_unlock(pdev); @@ -655,9 +848,10 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev( wlan_pdev_obj_unlock(pdev); return NULL; } -qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev); -struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state( +qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev_debug); +#else +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev( struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, wlan_objmgr_ref_dbgid dbg_id) { @@ -678,9 +872,11 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state( */ while (vdev) { if (wlan_vdev_get_id(vdev) == vdev_id) { - wlan_objmgr_vdev_get_ref(vdev, dbg_id); - wlan_pdev_obj_unlock(pdev); + if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != + QDF_STATUS_SUCCESS) + vdev = NULL; + wlan_pdev_obj_unlock(pdev); return vdev; } /* get next vdev */ @@ -688,14 +884,17 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state( vdev = vdev_next; } wlan_pdev_obj_unlock(pdev); - return NULL; } -qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev_no_state); -struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev( - struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, - wlan_objmgr_ref_dbgid dbg_id) +qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev); +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state_debug( + struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_vdev *vdev_next; @@ -703,20 +902,21 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev( qdf_list_t *vdev_list; wlan_pdev_obj_lock(pdev); + objmgr = &pdev->pdev_objmgr; vdev_list = &objmgr->wlan_vdev_list; /* Get first vdev */ vdev = wlan_pdev_vdev_list_peek_head(vdev_list); - /* Iterate through pdev's vdev list, till vdev macaddr matches with - entry of vdev list */ + /** + * Iterate through pdev's vdev list, till vdev id matches with + * entry of vdev list + */ while (vdev) { - if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) - == QDF_STATUS_SUCCESS) { - if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != - QDF_STATUS_SUCCESS) - vdev = NULL; - + if (wlan_vdev_get_id(vdev) == vdev_id) { + wlan_objmgr_vdev_get_ref_debug(vdev, dbg_id, + func, line); wlan_pdev_obj_unlock(pdev); + return vdev; } /* get next vdev */ @@ -728,9 +928,11 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev( return NULL; } -struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state( - struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, - wlan_objmgr_ref_dbgid dbg_id) +qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev_no_state_debug); +#else +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_pdev_no_state( + struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_vdev *vdev_next; @@ -738,15 +940,17 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state( qdf_list_t *vdev_list; wlan_pdev_obj_lock(pdev); + objmgr = &pdev->pdev_objmgr; vdev_list = &objmgr->wlan_vdev_list; /* Get first vdev */ vdev = wlan_pdev_vdev_list_peek_head(vdev_list); - /* Iterate through pdev's vdev list, till vdev macaddr matches with - entry of vdev list */ + /** + * Iterate through pdev's vdev list, till vdev id matches with + * entry of vdev list + */ while (vdev) { - if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) - == QDF_STATUS_SUCCESS) { + if (wlan_vdev_get_id(vdev) == vdev_id) { wlan_objmgr_vdev_get_ref(vdev, dbg_id); wlan_pdev_obj_unlock(pdev); @@ -761,146 +965,196 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state( return NULL; } -void *wlan_objmgr_pdev_get_comp_private_obj( - struct wlan_objmgr_pdev *pdev, - enum wlan_umac_comp_id id) -{ - void *comp_priv_obj; - - /* component id is invalid */ - if (id >= WLAN_UMAC_MAX_COMPONENTS) { - QDF_BUG(0); - return NULL; - } - - if (!pdev) { - QDF_BUG(0); - return NULL; - } - - comp_priv_obj = pdev->pdev_comp_priv_obj[id]; - - return comp_priv_obj; -} -qdf_export_symbol(wlan_objmgr_pdev_get_comp_private_obj); +qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_pdev_no_state); +#endif -void wlan_objmgr_pdev_get_ref(struct wlan_objmgr_pdev *pdev, - wlan_objmgr_ref_dbgid id) +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_debug( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *fnc, int ln) { - if (!pdev) { - obj_mgr_err("pdev obj is NULL"); - QDF_ASSERT(0); - return; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_vdev *vdev_next; + struct wlan_objmgr_pdev_objmgr *objmgr; + qdf_list_t *vdev_list; + + wlan_pdev_obj_lock(pdev); + objmgr = &pdev->pdev_objmgr; + vdev_list = &objmgr->wlan_vdev_list; + /* Get first vdev */ + vdev = wlan_pdev_vdev_list_peek_head(vdev_list); + /** + * Iterate through pdev's vdev list, till vdev macaddr matches with + * entry of vdev list + */ + while (vdev) { + if (QDF_IS_STATUS_SUCCESS( + WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr))) { + if (QDF_IS_STATUS_SUCCESS( + wlan_objmgr_vdev_try_get_ref_debug(vdev, dbg_id, + fnc, ln))) { + wlan_pdev_obj_unlock(pdev); + return vdev; + } + } + /* get next vdev */ + vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); + vdev = vdev_next; } - qdf_atomic_inc(&pdev->pdev_objmgr.ref_cnt); - qdf_atomic_inc(&pdev->pdev_objmgr.ref_id_dbg[id]); + wlan_pdev_obj_unlock(pdev); - return; + return NULL; } -qdf_export_symbol(wlan_objmgr_pdev_get_ref); - -QDF_STATUS wlan_objmgr_pdev_try_get_ref(struct wlan_objmgr_pdev *pdev, - wlan_objmgr_ref_dbgid id) +#else +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) { - uint8_t pdev_id; - - if (!pdev) { - obj_mgr_err("pdev obj is NULL"); - QDF_ASSERT(0); - return QDF_STATUS_E_FAILURE; - } + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_vdev *vdev_next; + struct wlan_objmgr_pdev_objmgr *objmgr; + qdf_list_t *vdev_list; wlan_pdev_obj_lock(pdev); - pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); - if (pdev->obj_state != WLAN_OBJ_STATE_CREATED) { - wlan_pdev_obj_unlock(pdev); - if (pdev->pdev_objmgr.print_cnt++ <= - WLAN_OBJMGR_RATELIMIT_THRESH) - obj_mgr_err( - "[Ref id: %d] pdev [%d] is not in Created(st:%d)", - id, pdev_id, pdev->obj_state); - return QDF_STATUS_E_RESOURCES; + objmgr = &pdev->pdev_objmgr; + vdev_list = &objmgr->wlan_vdev_list; + /* Get first vdev */ + vdev = wlan_pdev_vdev_list_peek_head(vdev_list); + /** + * Iterate through pdev's vdev list, till vdev macaddr matches with + * entry of vdev list + */ + while (vdev) { + if (QDF_IS_STATUS_SUCCESS( + WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr))) { + if (QDF_IS_STATUS_SUCCESS( + wlan_objmgr_vdev_try_get_ref(vdev, dbg_id))) { + wlan_pdev_obj_unlock(pdev); + return vdev; + } + } + /* get next vdev */ + vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); + vdev = vdev_next; } - - wlan_objmgr_pdev_get_ref(pdev, id); wlan_pdev_obj_unlock(pdev); - return QDF_STATUS_SUCCESS; + return NULL; } -qdf_export_symbol(wlan_objmgr_pdev_try_get_ref); +#endif -void wlan_objmgr_pdev_release_ref(struct wlan_objmgr_pdev *pdev, - wlan_objmgr_ref_dbgid id) +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev + *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state_debug( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { - uint8_t pdev_id; - - if (!pdev) { - obj_mgr_err("pdev obj is NULL"); - QDF_ASSERT(0); - return; - } - - pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_vdev *vdev_next; + struct wlan_objmgr_pdev_objmgr *objmgr; + qdf_list_t *vdev_list; - if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_id_dbg[id])) { - obj_mgr_err("pdev (id:%d)ref cnt was not taken by %d", - pdev_id, id); - wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg, - QDF_TRACE_LEVEL_FATAL); - WLAN_OBJMGR_BUG(0); - return; - } + wlan_pdev_obj_lock(pdev); + objmgr = &pdev->pdev_objmgr; + vdev_list = &objmgr->wlan_vdev_list; + /* Get first vdev */ + vdev = wlan_pdev_vdev_list_peek_head(vdev_list); + /** + * Iterate through pdev's vdev list, till vdev macaddr matches with + * entry of vdev list + */ + while (vdev) { + if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) + == QDF_STATUS_SUCCESS) { + wlan_objmgr_vdev_get_ref_debug(vdev, dbg_id, + func, line); + wlan_pdev_obj_unlock(pdev); - if (!qdf_atomic_read(&pdev->pdev_objmgr.ref_cnt)) { - obj_mgr_err("pdev ref cnt is 0: pdev-id:%d", pdev_id); - WLAN_OBJMGR_BUG(0); - return; + return vdev; + } + /* get next vdev */ + vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); + vdev = vdev_next; } + wlan_pdev_obj_unlock(pdev); - qdf_atomic_dec(&pdev->pdev_objmgr.ref_id_dbg[id]); - /* Decrement ref count, free pdev, if ref count == 0 */ - if (qdf_atomic_dec_and_test(&pdev->pdev_objmgr.ref_cnt)) - wlan_objmgr_pdev_obj_destroy(pdev); - - return; + return NULL; } -qdf_export_symbol(wlan_objmgr_pdev_release_ref); - -struct wlan_objmgr_vdev *wlan_objmgr_pdev_get_first_vdev( - struct wlan_objmgr_pdev *pdev, +#else +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) { - struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; - qdf_list_t *vdev_list = NULL; struct wlan_objmgr_vdev *vdev; - qdf_list_node_t *node = NULL; - qdf_list_node_t *prev_node = NULL; + struct wlan_objmgr_vdev *vdev_next; + struct wlan_objmgr_pdev_objmgr *objmgr; + qdf_list_t *vdev_list; wlan_pdev_obj_lock(pdev); - - /* VDEV list */ + objmgr = &pdev->pdev_objmgr; vdev_list = &objmgr->wlan_vdev_list; - if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { - wlan_pdev_obj_unlock(pdev); - return NULL; - } - - do { - vdev = qdf_container_of(node, struct wlan_objmgr_vdev, - vdev_node); - if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) == - QDF_STATUS_SUCCESS) { + /* Get first vdev */ + vdev = wlan_pdev_vdev_list_peek_head(vdev_list); + /** + * Iterate through pdev's vdev list, till vdev macaddr matches with + * entry of vdev list + */ + while (vdev) { + if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) + == QDF_STATUS_SUCCESS) { + wlan_objmgr_vdev_get_ref(vdev, dbg_id); wlan_pdev_obj_unlock(pdev); + return vdev; } - - prev_node = node; - } while (qdf_list_peek_next(vdev_list, prev_node, &node) == - QDF_STATUS_SUCCESS); - + /* get next vdev */ + vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); + vdev = vdev_next; + } wlan_pdev_obj_unlock(pdev); return NULL; } +#endif -qdf_export_symbol(wlan_objmgr_pdev_get_first_vdev); +#ifdef WLAN_OBJMGR_DEBUG +void wlan_print_pdev_info(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_pdev_objmgr *pdev_objmgr; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_vdev *vdev_next; + qdf_list_t *vdev_list; + uint16_t index = 0; + + pdev_objmgr = &pdev->pdev_objmgr; + + obj_mgr_debug("pdev: %pK", pdev); + obj_mgr_debug("wlan_pdev_id: %d", pdev_objmgr->wlan_pdev_id); + obj_mgr_debug("wlan_vdev_count: %d", pdev_objmgr->wlan_vdev_count); + obj_mgr_debug("max_vdev_count: %d", pdev_objmgr->max_vdev_count); + obj_mgr_debug("wlan_peer_count: %d", pdev_objmgr->wlan_peer_count); + obj_mgr_debug("max_peer_count: %d", pdev_objmgr->max_peer_count); + obj_mgr_debug("temp_peer_count: %d", pdev_objmgr->temp_peer_count); + obj_mgr_debug("wlan_psoc: %pK", pdev_objmgr->wlan_psoc); + obj_mgr_debug("ref_cnt: %d", qdf_atomic_read(&pdev_objmgr->ref_cnt)); + + wlan_pdev_obj_lock(pdev); + vdev_list = &pdev_objmgr->wlan_vdev_list; + /* Get first vdev */ + vdev = wlan_pdev_vdev_list_peek_head(vdev_list); + + while (vdev) { + obj_mgr_debug("wlan_vdev_list[%d]: %pK", index, vdev); + wlan_print_vdev_info(vdev); + index++; + /* get next vdev */ + vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); + vdev = vdev_next; + } + wlan_pdev_obj_unlock(pdev); +} + +qdf_export_symbol(wlan_print_pdev_info); +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c index 33e3baa93de45a78d76cac1a1f6f4e7cc8e5415a..c99f3ac372f32d97219c1ce649f9477a722a08ee 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c @@ -84,9 +84,8 @@ static QDF_STATUS wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer *peer) vdev = wlan_peer_get_vdev(peer); if (!vdev) { obj_mgr_err( - "VDEV is NULL for peer(%02x:%02x:%02x:%02x:%02x:%02x)", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); + "VDEV is NULL for peer("QDF_MAC_ADDR_FMT")", + QDF_MAC_ADDR_REF(macaddr)); return QDF_STATUS_E_FAILURE; } @@ -96,9 +95,8 @@ static QDF_STATUS wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer *peer) psoc = wlan_vdev_get_psoc(vdev); if (!psoc) { obj_mgr_err( - "PSOC is NULL for peer(%02x:%02x:%02x:%02x:%02x:%02x)", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); + "PSOC is NULL for peer("QDF_MAC_ADDR_FMT")", + QDF_MAC_ADDR_REF(macaddr)); return QDF_STATUS_E_FAILURE; } @@ -109,25 +107,32 @@ static QDF_STATUS wlan_objmgr_peer_obj_free(struct wlan_objmgr_peer *peer) wlan_objmgr_peer_release_ref(wlan_vdev_get_bsspeer(vdev), WLAN_OBJMGR_ID); + wlan_objmgr_vdev_get_ref(vdev, WLAN_OBJMGR_ID); + /* Detach peer from VDEV's peer list */ if (wlan_objmgr_vdev_peer_detach(vdev, peer) == QDF_STATUS_E_FAILURE) { obj_mgr_err( - "Peer(%02x:%02x:%02x:%02x:%02x:%02x) VDEV detach fail, vdev id: %d", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5], vdev_id); + "Peer("QDF_MAC_ADDR_FMT") VDEV detach fail, vdev id: %d", + QDF_MAC_ADDR_REF(macaddr), vdev_id); + wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); return QDF_STATUS_E_FAILURE; } /* Detach peer from PSOC's peer list */ if (wlan_objmgr_psoc_peer_detach(psoc, peer) == QDF_STATUS_E_FAILURE) { obj_mgr_err( - "Peer(%02x:%02x:%02x:%02x:%02x:%02x) PSOC detach failure", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); + "Peer("QDF_MAC_ADDR_FMT") PSOC detach failure", + QDF_MAC_ADDR_REF(macaddr)); + wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); return QDF_STATUS_E_FAILURE; } + wlan_objmgr_peer_trace_del_ref_list(peer); + wlan_objmgr_peer_trace_deinit_lock(peer); qdf_spinlock_destroy(&peer->peer_lock); qdf_mem_free(peer); + wlan_objmgr_vdev_peer_freed_notify(vdev); + wlan_objmgr_vdev_release_ref(vdev, WLAN_OBJMGR_ID); + return QDF_STATUS_SUCCESS; } @@ -161,18 +166,16 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( if (!vdev) { obj_mgr_err( - "VDEV is NULL for peer (%02x:%02x:%02x:%02x:%02x:%02x)", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); + "VDEV is NULL for peer ("QDF_MAC_ADDR_FMT")", + QDF_MAC_ADDR_REF(macaddr)); return NULL; } /* Get psoc, if psoc is NULL, return */ psoc = wlan_vdev_get_psoc(vdev); if (!psoc) { obj_mgr_err( - "PSOC is NULL for peer (%02x:%02x:%02x:%02x:%02x:%02x)", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); + "PSOC is NULL for peer ("QDF_MAC_ADDR_FMT")", + QDF_MAC_ADDR_REF(macaddr)); return NULL; } /* Allocate memory for peer object */ @@ -196,14 +199,15 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( peer->peer_objmgr.print_cnt = 0; qdf_spinlock_create(&peer->peer_lock); + wlan_objmgr_peer_trace_init_lock(peer); /* Attach peer to psoc, psoc maintains the node table for the device */ if (wlan_objmgr_psoc_peer_attach(psoc, peer) != QDF_STATUS_SUCCESS) { obj_mgr_warn( - "Peer(%02x:%02x:%02x:%02x:%02x:%02x) PSOC attach failure", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); + "Peer("QDF_MAC_ADDR_FMT") PSOC attach failure", + QDF_MAC_ADDR_REF(macaddr)); qdf_spinlock_destroy(&peer->peer_lock); + wlan_objmgr_peer_trace_deinit_lock(peer); qdf_mem_free(peer); return NULL; } @@ -211,12 +215,12 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( if (wlan_objmgr_vdev_peer_attach(vdev, peer) != QDF_STATUS_SUCCESS) { obj_mgr_warn( - "Peer(%02x:%02x:%02x:%02x:%02x:%02x) VDEV attach failure", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); + "Peer("QDF_MAC_ADDR_FMT") VDEV attach failure", + QDF_MAC_ADDR_REF(macaddr)); /* if attach fails, detach from psoc table before free */ wlan_objmgr_psoc_peer_detach(psoc, peer); qdf_spinlock_destroy(&peer->peer_lock); + wlan_objmgr_peer_trace_deinit_lock(peer); qdf_mem_free(peer); return NULL; } @@ -256,15 +260,14 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( } else if (obj_status == QDF_STATUS_E_FAILURE) { /* Clean up the peer */ obj_mgr_err( - "Peer(%02x:%02x:%02x:%02x:%02x:%02x) comp object alloc fail", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); + "Peer("QDF_MAC_ADDR_FMT") comp object alloc fail", + QDF_MAC_ADDR_REF(macaddr)); wlan_objmgr_peer_obj_delete(peer); return NULL; } - obj_mgr_debug("Created peer " QDF_MAC_ADDR_STR " type %d", - QDF_MAC_ADDR_ARRAY(macaddr), type); + obj_mgr_debug("Created peer " QDF_MAC_ADDR_FMT " type %d", + QDF_MAC_ADDR_REF(macaddr), type); return peer; } @@ -285,13 +288,13 @@ static QDF_STATUS wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer) macaddr = wlan_peer_get_macaddr(peer); - obj_mgr_debug("Physically deleting peer " QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(macaddr)); + obj_mgr_debug("Physically deleting peer " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(macaddr)); if (peer->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { obj_mgr_err("PEER object del is not invoked obj_state:%d peer " - QDF_MAC_ADDR_STR, peer->obj_state, - QDF_MAC_ADDR_ARRAY(macaddr)); + QDF_MAC_ADDR_FMT, peer->obj_state, + QDF_MAC_ADDR_REF(macaddr)); WLAN_OBJMGR_BUG(0); } @@ -337,8 +340,8 @@ QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer) macaddr = wlan_peer_get_macaddr(peer); wlan_peer_obj_unlock(peer); - obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_STR, - QDF_MAC_ADDR_ARRAY(macaddr)); + obj_mgr_debug("Logically deleting peer " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(macaddr)); print_idx = qdf_get_pidx(); wlan_objmgr_print_peer_ref_ids(peer, QDF_TRACE_LEVEL_DEBUG); @@ -597,8 +600,69 @@ wlan_objmgr_peer_get_debug_id_ref(struct wlan_objmgr_peer *peer, wlan_objmgr_ref_dbgid id) {} #endif -void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, - wlan_objmgr_ref_dbgid id) +#ifdef WLAN_OBJMGR_REF_ID_DEBUG +static QDF_STATUS +wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id) +{ + if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) { + uint8_t *macaddr; + + macaddr = wlan_peer_get_macaddr(peer); + obj_mgr_err( + "peer("QDF_MAC_ADDR_FMT") ref was not taken by %d", + QDF_MAC_ADDR_REF(macaddr), id); + wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, + QDF_TRACE_LEVEL_FATAL); + WLAN_OBJMGR_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]); + return QDF_STATUS_SUCCESS; +} +#else +static QDF_STATUS +wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id) +{ + return QDF_STATUS_SUCCESS; +} +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static inline void +wlan_objmgr_peer_ref_trace(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id, + const char *func, int line) +{ + struct wlan_objmgr_trace *trace; + + trace = &peer->peer_objmgr.trace; + + if (func) + wlan_objmgr_trace_ref(&trace->references[id].head, + trace, func, line); +} + +static inline void +wlan_objmgr_peer_deref_trace(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id, + const char *func, int line) +{ + struct wlan_objmgr_trace *trace; + + trace = &peer->peer_objmgr.trace; + if (func) + wlan_objmgr_trace_ref(&trace->dereferences[id].head, + trace, func, line); +} +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +void wlan_objmgr_peer_get_ref_debug(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id, + const char *func, int line) { if (!peer) { obj_mgr_err("peer obj is NULL for %d", id); @@ -609,12 +673,65 @@ void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); wlan_objmgr_peer_get_debug_id_ref(peer, id); + wlan_objmgr_peer_ref_trace(peer, id, func, line); return; } + +qdf_export_symbol(wlan_objmgr_peer_get_ref_debug); +#else +void wlan_objmgr_peer_get_ref(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id) +{ + if (!peer) { + obj_mgr_err("peer obj is NULL for %d", id); + QDF_ASSERT(0); + return; + } + /* Increment ref count */ + qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); + wlan_objmgr_peer_get_debug_id_ref(peer, id); +} + qdf_export_symbol(wlan_objmgr_peer_get_ref); +#endif +#ifdef WLAN_OBJMGR_REF_ID_TRACE +QDF_STATUS wlan_objmgr_peer_try_get_ref_debug(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id, + const char *func, int line) +{ + if (!peer) { + obj_mgr_err("peer obj is NULL for %d", id); + QDF_ASSERT(0); + return QDF_STATUS_E_FAILURE; + } + + wlan_peer_obj_lock(peer); + if (peer->obj_state != WLAN_OBJ_STATE_CREATED) { + wlan_peer_obj_unlock(peer); + if (peer->peer_objmgr.print_cnt++ <= + WLAN_OBJMGR_RATELIMIT_THRESH) { + uint8_t *macaddr; + + macaddr = wlan_peer_get_macaddr(peer); + obj_mgr_debug( + "peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)", + QDF_MAC_ADDR_REF(macaddr), + peer->obj_state); + } + return QDF_STATUS_E_RESOURCES; + } + + wlan_objmgr_peer_get_ref_debug(peer, id, func, line); + wlan_peer_obj_unlock(peer); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(wlan_objmgr_peer_try_get_ref_debug); +#else QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, - wlan_objmgr_ref_dbgid id) + wlan_objmgr_ref_dbgid id) { if (!peer) { obj_mgr_err("peer obj is NULL for %d", id); @@ -631,8 +748,8 @@ QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, macaddr = wlan_peer_get_macaddr(peer); obj_mgr_debug( - "peer(" QDF_MAC_ADDR_STR ") not in Created st(%d)", - QDF_MAC_ADDR_ARRAY(macaddr), + "peer(" QDF_MAC_ADDR_FMT ") not in Created st(%d)", + QDF_MAC_ADDR_REF(macaddr), peer->obj_state); } return QDF_STATUS_E_RESOURCES; @@ -643,81 +760,120 @@ QDF_STATUS wlan_objmgr_peer_try_get_ref(struct wlan_objmgr_peer *peer, return QDF_STATUS_SUCCESS; } + qdf_export_symbol(wlan_objmgr_peer_try_get_ref); +#endif -#ifdef WLAN_OBJMGR_REF_ID_DEBUG -static QDF_STATUS -wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, - wlan_objmgr_ref_dbgid id) +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc_debug( + struct wlan_peer_list *peer_list, + uint8_t hash_index, + struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { - if (!qdf_atomic_read(&peer->peer_objmgr.ref_id_dbg[id])) { - uint8_t *macaddr; + struct wlan_objmgr_peer *peer_next = NULL; + qdf_list_node_t *psoc_node = NULL; + qdf_list_node_t *prev_psoc_node = NULL; + qdf_list_t *obj_list; - macaddr = wlan_peer_get_macaddr(peer); - obj_mgr_err( - "peer(%02x:%02x:%02x:%02x:%02x:%02x) ref was not taken by %d", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5], id); - wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg, - QDF_TRACE_LEVEL_FATAL); - WLAN_OBJMGR_BUG(0); - return QDF_STATUS_E_FAILURE; + qdf_spin_lock_bh(&peer_list->peer_list_lock); + obj_list = &peer_list->peer_hash[hash_index]; + + prev_psoc_node = &peer->psoc_peer; + while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == + QDF_STATUS_SUCCESS) { + peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer, + psoc_peer); + + if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id, + func, line) == + QDF_STATUS_SUCCESS) { + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + return peer_next; + } + + prev_psoc_node = psoc_node; } - qdf_atomic_dec(&peer->peer_objmgr.ref_id_dbg[id]); - return QDF_STATUS_SUCCESS; + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + + return NULL; } #else -static QDF_STATUS -wlan_objmgr_peer_release_debug_id_ref(struct wlan_objmgr_peer *peer, - wlan_objmgr_ref_dbgid id) +struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc( + struct wlan_peer_list *peer_list, + uint8_t hash_index, + struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid dbg_id) { - return QDF_STATUS_SUCCESS; + struct wlan_objmgr_peer *peer_next = NULL; + qdf_list_node_t *psoc_node = NULL; + qdf_list_node_t *prev_psoc_node = NULL; + qdf_list_t *obj_list; + + qdf_spin_lock_bh(&peer_list->peer_list_lock); + obj_list = &peer_list->peer_hash[hash_index]; + + prev_psoc_node = &peer->psoc_peer; + while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == + QDF_STATUS_SUCCESS) { + peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer, + psoc_peer); + + if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) == + QDF_STATUS_SUCCESS) { + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + return peer_next; + } + + prev_psoc_node = psoc_node; + } + + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + + return NULL; } #endif -void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer, - wlan_objmgr_ref_dbgid id) +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head_debug( + struct wlan_objmgr_vdev *vdev, + qdf_list_t *peer_list, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { - QDF_STATUS status; + struct wlan_objmgr_peer *peer; + qdf_list_node_t *vdev_node = NULL; + qdf_list_node_t *prev_vdev_node = NULL; - if (!peer) { - obj_mgr_err("peer obj is NULL for %d", id); - QDF_ASSERT(0); - return; + wlan_vdev_obj_lock(vdev); + + if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) { + wlan_vdev_obj_unlock(vdev); + return NULL; } - if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { - uint8_t *macaddr; + do { + peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer, + vdev_peer); - macaddr = wlan_peer_get_macaddr(peer); - obj_mgr_err("peer(%02x:%02x:%02x:%02x:%02x:%02x) ref cnt is 0", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); - WLAN_OBJMGR_BUG(0); - return; - } + if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id, + func, line) == + QDF_STATUS_SUCCESS) { + wlan_vdev_obj_unlock(vdev); + return peer; + } - status = wlan_objmgr_peer_release_debug_id_ref(peer, id); - if (QDF_IS_STATUS_ERROR(status)) - return; + prev_vdev_node = vdev_node; + } while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == + QDF_STATUS_SUCCESS); - /* Provide synchronization from the access to add peer - * to logically deleted peer list. - */ - wlan_peer_obj_lock(peer); - /* Decrement ref count, free peer object, if ref count == 0 */ - if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) { - wlan_peer_obj_unlock(peer); - wlan_objmgr_peer_obj_destroy(peer); - } else { - wlan_peer_obj_unlock(peer); - } + wlan_vdev_obj_unlock(vdev); - return; + return NULL; } -qdf_export_symbol(wlan_objmgr_peer_release_ref); - +#else struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head( struct wlan_objmgr_vdev *vdev, qdf_list_t *peer_list, @@ -752,7 +908,46 @@ struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_active_head( return NULL; } +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev_debug( + struct wlan_objmgr_vdev *vdev, + qdf_list_t *peer_list, + struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_peer *peer_next; + qdf_list_node_t *vdev_node = NULL; + qdf_list_node_t *prev_vdev_node = NULL; + + if (!peer) + return NULL; + wlan_vdev_obj_lock(vdev); + + prev_vdev_node = &peer->vdev_peer; + while (qdf_list_peek_next(peer_list, prev_vdev_node, &vdev_node) == + QDF_STATUS_SUCCESS) { + peer_next = qdf_container_of(vdev_node, struct wlan_objmgr_peer, + vdev_peer); + + if (wlan_objmgr_peer_try_get_ref_debug(peer_next, dbg_id, + func, line) == + QDF_STATUS_SUCCESS) { + wlan_vdev_obj_unlock(vdev); + return peer_next; + } + + prev_vdev_node = vdev_node; + } + + wlan_vdev_obj_unlock(vdev); + + return NULL; +} +#else struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev( struct wlan_objmgr_vdev *vdev, qdf_list_t *peer_list, @@ -787,14 +982,16 @@ struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_vdev( return NULL; } +#endif -struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc( +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head_debug( struct wlan_peer_list *peer_list, uint8_t hash_index, - struct wlan_objmgr_peer *peer, - wlan_objmgr_ref_dbgid dbg_id) + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { - struct wlan_objmgr_peer *peer_next = NULL; + struct wlan_objmgr_peer *peer; qdf_list_node_t *psoc_node = NULL; qdf_list_node_t *prev_psoc_node = NULL; qdf_list_t *obj_list; @@ -802,26 +999,29 @@ struct wlan_objmgr_peer *wlan_peer_get_next_active_peer_of_psoc( qdf_spin_lock_bh(&peer_list->peer_list_lock); obj_list = &peer_list->peer_hash[hash_index]; - prev_psoc_node = &peer->psoc_peer; - while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == - QDF_STATUS_SUCCESS) { - peer_next = qdf_container_of(psoc_node, struct wlan_objmgr_peer, - psoc_peer); + if (qdf_list_peek_front(obj_list, &psoc_node) != QDF_STATUS_SUCCESS) { + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + return NULL; + } - if (wlan_objmgr_peer_try_get_ref(peer_next, dbg_id) == + do { + peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer, + psoc_peer); + if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id, + func, line) == QDF_STATUS_SUCCESS) { qdf_spin_unlock_bh(&peer_list->peer_list_lock); - return peer_next; + return peer; } prev_psoc_node = psoc_node; - } + } while (qdf_list_peek_next(obj_list, prev_psoc_node, &psoc_node) == + QDF_STATUS_SUCCESS); qdf_spin_unlock_bh(&peer_list->peer_list_lock); - return NULL; } - +#else struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head( struct wlan_peer_list *peer_list, uint8_t hash_index, @@ -856,7 +1056,35 @@ struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_active_head( qdf_spin_unlock_bh(&peer_list->peer_list_lock); return NULL; } +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref_debug( + struct wlan_peer_list *peer_list, + uint8_t hash_index, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_peer *peer; + qdf_list_t *obj_list; + + qdf_spin_lock_bh(&peer_list->peer_list_lock); + obj_list = &peer_list->peer_hash[hash_index]; + + peer = wlan_psoc_peer_list_peek_head(obj_list); + /* This API is invoked by caller, only when caller need to access the + * peer object, though object is not in active state, this API should be + * used carefully, where multiple object frees are not triggered + */ + if (peer) + wlan_objmgr_peer_get_ref_debug(peer, dbg_id, func, line); + + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + + return peer; +} +#else struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref( struct wlan_peer_list *peer_list, uint8_t hash_index, @@ -870,8 +1098,7 @@ struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref( peer = wlan_psoc_peer_list_peek_head(obj_list); - /** - * This API is invoked by caller, only when caller need to access the + /* This API is invoked by caller, only when caller need to access the * peer object, though object is not in active state, this API should be * used carefully, where multiple object frees are not triggered */ @@ -882,7 +1109,34 @@ struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head_ref( return peer; } +#endif +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref_debug( + struct wlan_peer_list *peer_list, uint8_t hash_index, + struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + qdf_list_t *obj_list; + struct wlan_objmgr_peer *peer_next; + + qdf_spin_lock_bh(&peer_list->peer_list_lock); + obj_list = &peer_list->peer_hash[hash_index]; + + peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer); + /* This API is invoked by caller, only when caller need to access the + * peer object, though object is not in active state, this API should be + * used carefully, where multiple free on object are not triggered + */ + if (peer_next) + wlan_objmgr_peer_get_ref_debug(peer_next, dbg_id, func, line); + + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + + return peer_next; +} +#else struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref( struct wlan_peer_list *peer_list, uint8_t hash_index, struct wlan_objmgr_peer *peer, @@ -895,8 +1149,7 @@ struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref( obj_list = &peer_list->peer_hash[hash_index]; peer_next = wlan_peer_get_next_peer_of_psoc(obj_list, peer); - /** - * This API is invoked by caller, only when caller need to access the + /* This API is invoked by caller, only when caller need to access the * peer object, though object is not in active state, this API should be * used carefully, where multiple free on object are not triggered */ @@ -907,6 +1160,93 @@ struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc_ref( return peer_next; } +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +void wlan_objmgr_peer_release_ref_debug(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id, + const char *func, int line) +{ + QDF_STATUS status; + + if (!peer) { + obj_mgr_err("peer obj is NULL for %d", id); + QDF_ASSERT(0); + return; + } + + if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { + uint8_t *macaddr; + + macaddr = wlan_peer_get_macaddr(peer); + obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0", + QDF_MAC_ADDR_REF(macaddr)); + WLAN_OBJMGR_BUG(0); + return; + } + + status = wlan_objmgr_peer_release_debug_id_ref(peer, id); + if (QDF_IS_STATUS_ERROR(status)) + return; + + wlan_objmgr_peer_deref_trace(peer, id, func, line); + /* Provide synchronization from the access to add peer + * to logically deleted peer list. + */ + wlan_peer_obj_lock(peer); + /* Decrement ref count, free peer object, if ref count == 0 */ + if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) { + wlan_peer_obj_unlock(peer); + wlan_objmgr_peer_obj_destroy(peer); + } else { + wlan_peer_obj_unlock(peer); + } + + return; +} + +qdf_export_symbol(wlan_objmgr_peer_release_ref_debug); +#else +void wlan_objmgr_peer_release_ref(struct wlan_objmgr_peer *peer, + wlan_objmgr_ref_dbgid id) +{ + QDF_STATUS status; + + if (!peer) { + obj_mgr_err("peer obj is NULL for %d", id); + QDF_ASSERT(0); + return; + } + + if (!qdf_atomic_read(&peer->peer_objmgr.ref_cnt)) { + uint8_t *macaddr; + + macaddr = wlan_peer_get_macaddr(peer); + obj_mgr_err("peer("QDF_MAC_ADDR_FMT") ref cnt is 0", + QDF_MAC_ADDR_REF(macaddr)); + WLAN_OBJMGR_BUG(0); + return; + } + + status = wlan_objmgr_peer_release_debug_id_ref(peer, id); + if (QDF_IS_STATUS_ERROR(status)) + return; + + /* Provide synchronization from the access to add peer + * to logically deleted peer list. + */ + wlan_peer_obj_lock(peer); + /* Decrement ref count, free peer object, if ref count == 0 */ + if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) { + wlan_peer_obj_unlock(peer); + wlan_objmgr_peer_obj_destroy(peer); + } else { + wlan_peer_obj_unlock(peer); + } +} + +qdf_export_symbol(wlan_objmgr_peer_release_ref); +#endif #ifdef WLAN_OBJMGR_REF_ID_DEBUG void diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c index 4a5e2593f6c08c38f8cfe6bb47cbaaea9fb5f397..d5d2ce5d12fd39325122af4e181fc267f4683a5e 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 @@ -202,6 +202,7 @@ static QDF_STATUS wlan_objmgr_psoc_obj_destroy(struct wlan_objmgr_psoc *psoc) } wlan_objmgr_notify_destroy(psoc, WLAN_PSOC_OP); + wlan_print_psoc_info(psoc); obj_mgr_info("Physically deleting psoc %d", psoc->soc_objmgr.psoc_id); if (psoc->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) { @@ -941,45 +942,37 @@ QDF_STATUS wlan_objmgr_psoc_vdev_detach(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } -struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_opmode_from_psoc( - struct wlan_objmgr_psoc *psoc, - enum QDF_OPMODE opmode, - wlan_objmgr_ref_dbgid dbg_id) +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_debug( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { - struct wlan_objmgr_vdev *vdev = NULL; - int vdev_cnt = 0; - uint16_t max_vdev_cnt; + struct wlan_objmgr_vdev *vdev; /* if PSOC is NULL, return */ if (!psoc) return NULL; + /* vdev id is invalid */ + if (vdev_id >= wlan_psoc_get_max_vdev_count(psoc)) + return NULL; wlan_psoc_obj_lock(psoc); - - max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc); /* retrieve vdev pointer from vdev list */ - while (vdev_cnt < max_vdev_cnt) { - vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_cnt]; - vdev_cnt++; - if (!vdev) - continue; - wlan_vdev_obj_lock(vdev); - if (vdev->vdev_mlme.vdev_opmode == opmode) { - wlan_vdev_obj_unlock(vdev); - if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != - QDF_STATUS_SUCCESS) { - vdev = NULL; - continue; - } - break; - } - wlan_vdev_obj_unlock(vdev); + vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id]; + if (vdev) { + if (wlan_objmgr_vdev_try_get_ref_debug(vdev, dbg_id, + func, line) != + QDF_STATUS_SUCCESS) + vdev = NULL; } wlan_psoc_obj_unlock(psoc); return vdev; } +qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_psoc_debug); +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc( struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, wlan_objmgr_ref_dbgid dbg_id) @@ -1005,8 +998,38 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc( return vdev; } + qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_psoc); +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_no_state_debug( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_vdev *vdev; + + /* if PSOC is NULL, return */ + if (!psoc) + return NULL; + /* vdev id is invalid */ + if (vdev_id >= wlan_psoc_get_max_vdev_count(psoc)) + return NULL; + + wlan_psoc_obj_lock(psoc); + /* retrieve vdev pointer from vdev list */ + vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id]; + if (vdev) + wlan_objmgr_vdev_get_ref_debug(vdev, dbg_id, func, line); + + wlan_psoc_obj_unlock(psoc); + + return vdev; +} +qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_psoc_no_state_debug); +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_no_state( struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, wlan_objmgr_ref_dbgid dbg_id) @@ -1030,8 +1053,123 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_id_from_psoc_no_state( return vdev; } + qdf_export_symbol(wlan_objmgr_get_vdev_by_id_from_psoc_no_state); +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_opmode_from_psoc_debug( + struct wlan_objmgr_psoc *psoc, + enum QDF_OPMODE opmode, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_vdev *vdev = NULL; + int vdev_cnt = 0; + uint16_t max_vdev_cnt; + + /* if PSOC is NULL, return */ + if (!psoc) + return NULL; + + wlan_psoc_obj_lock(psoc); + + max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc); + /* retrieve vdev pointer from vdev list */ + while (vdev_cnt < max_vdev_cnt) { + vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_cnt]; + vdev_cnt++; + if (!vdev) + continue; + wlan_vdev_obj_lock(vdev); + if (vdev->vdev_mlme.vdev_opmode == opmode) { + wlan_vdev_obj_unlock(vdev); + if (wlan_objmgr_vdev_try_get_ref_debug(vdev, dbg_id, + func, line) != + QDF_STATUS_SUCCESS) { + vdev = NULL; + continue; + } + break; + } + wlan_vdev_obj_unlock(vdev); + } + wlan_psoc_obj_unlock(psoc); + + return vdev; +} +#else +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_opmode_from_psoc( + struct wlan_objmgr_psoc *psoc, + enum QDF_OPMODE opmode, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_vdev *vdev = NULL; + int vdev_cnt = 0; + uint16_t max_vdev_cnt; + + /* if PSOC is NULL, return */ + if (!psoc) + return NULL; + + wlan_psoc_obj_lock(psoc); + + max_vdev_cnt = wlan_psoc_get_max_vdev_count(psoc); + /* retrieve vdev pointer from vdev list */ + while (vdev_cnt < max_vdev_cnt) { + vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_cnt]; + vdev_cnt++; + if (!vdev) + continue; + wlan_vdev_obj_lock(vdev); + if (vdev->vdev_mlme.vdev_opmode == opmode) { + wlan_vdev_obj_unlock(vdev); + if (wlan_objmgr_vdev_try_get_ref(vdev, dbg_id) != + QDF_STATUS_SUCCESS) { + vdev = NULL; + continue; + } + break; + } + wlan_vdev_obj_unlock(vdev); + } + wlan_psoc_obj_unlock(psoc); + + return vdev; +} +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_pdev *pdev; + + /* if PSOC is NULL, return */ + if (!psoc) + return NULL; + + if (!macaddr) + return NULL; + + pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, dbg_id); + if (!pdev) { + obj_mgr_err("pdev is null"); + return NULL; + } + vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev_debug(pdev, macaddr, + dbg_id, + func, line); + wlan_objmgr_pdev_release_ref(pdev, dbg_id); + + return vdev; +} +qdf_export_symbol(wlan_objmgr_get_vdev_by_macaddr_from_psoc_debug); +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) @@ -1056,8 +1194,44 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc( return vdev; } + qdf_export_symbol(wlan_objmgr_get_vdev_by_macaddr_from_psoc); +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev + *wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_pdev *pdev; + + /* if PSOC is NULL, return */ + if (!psoc) + return NULL; + + if (!macaddr) + return NULL; + + pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, dbg_id); + if (!pdev) { + obj_mgr_err("pdev is null"); + return NULL; + } + vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev_no_state_debug(pdev, + macaddr, + dbg_id, + func, + line); + wlan_objmgr_pdev_release_ref(pdev, dbg_id); + return vdev; +} + +qdf_export_symbol(wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state_debug); +#else struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) @@ -1082,7 +1256,9 @@ struct wlan_objmgr_vdev *wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state( return vdev; } + qdf_export_symbol(wlan_objmgr_get_vdev_by_macaddr_from_psoc_no_state); +#endif static void wlan_obj_psoc_peerlist_add_tail(qdf_list_t *obj_list, struct wlan_objmgr_peer *obj) @@ -1120,20 +1296,23 @@ static QDF_STATUS wlan_peer_bssid_match(struct wlan_objmgr_peer *peer, } /** - * wlan_obj_psoc_peerlist_get_peer_logically_deleted() - get peer - * from psoc peer list + * wlan_obj_psoc_peerlist_get_peer_by_pdev_id() - get peer from + * psoc peer list * @psoc: PSOC object * @macaddr: MAC address + * #pdev_id: Pdev id * - * API to finds peer object pointer of logically deleted peer + * API to finds peer object pointer by MAC addr and pdev id from hash list * * Return: peer pointer * NULL on FAILURE */ -static struct wlan_objmgr_peer * - wlan_obj_psoc_peerlist_get_peer_logically_deleted( +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static struct wlan_objmgr_peer + *wlan_obj_psoc_peerlist_get_peer_by_pdev_id_debug( qdf_list_t *obj_list, uint8_t *macaddr, - wlan_objmgr_ref_dbgid dbg_id) + uint8_t pdev_id, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { struct wlan_objmgr_peer *peer; struct wlan_objmgr_peer *peer_temp; @@ -1142,16 +1321,14 @@ static struct wlan_objmgr_peer * peer = wlan_psoc_peer_list_peek_head(obj_list); while (peer) { /* For peer, macaddr is key */ - if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) - == QDF_STATUS_SUCCESS) { - /* Return peer in logically deleted state */ - if (peer->obj_state == - WLAN_OBJ_STATE_LOGICALLY_DELETED) { - wlan_objmgr_peer_get_ref(peer, dbg_id); - + if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) && + (wlan_peer_get_pdev_id(peer) == pdev_id)) { + if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id, + func, line) == + QDF_STATUS_SUCCESS) { return peer; } - } /* Move to next peer */ peer_temp = peer; @@ -1161,20 +1338,10 @@ static struct wlan_objmgr_peer * /* Not found, return NULL */ return NULL; } - -/** - * wlan_obj_psoc_peerlist_get_peer() - get peer from psoc peer list - * @psoc: PSOC object - * @macaddr: MAC address - * - * API to finds peer object pointer by MAC addr from hash list - * - * Return: peer pointer - * NULL on FAILURE - */ -static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer( - qdf_list_t *obj_list, uint8_t *macaddr, - wlan_objmgr_ref_dbgid dbg_id) +#else +static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_pdev_id( + qdf_list_t *obj_list, uint8_t *macaddr, + uint8_t pdev_id, wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_peer *peer; struct wlan_objmgr_peer *peer_temp; @@ -1183,10 +1350,11 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer( peer = wlan_psoc_peer_list_peek_head(obj_list); while (peer) { /* For peer, macaddr is key */ - if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) - == QDF_STATUS_SUCCESS) { + if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) && + (wlan_peer_get_pdev_id(peer) == pdev_id)) { if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == - QDF_STATUS_SUCCESS) { + QDF_STATUS_SUCCESS) { return peer; } } @@ -1198,21 +1366,23 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer( /* Not found, return NULL */ return NULL; } +#endif /** - * wlan_obj_psoc_peerlist_get_peer_by_pdev_id() - get peer from psoc peer list + * wlan_obj_psoc_peerlist_get_peer() - get peer from psoc peer list * @psoc: PSOC object * @macaddr: MAC address - * #pdev_id: Pdev id * - * API to finds peer object pointer by MAC addr and pdev id from hash list + * API to finds peer object pointer by MAC addr from hash list * * Return: peer pointer * NULL on FAILURE */ -static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_pdev_id( - qdf_list_t *obj_list, uint8_t *macaddr, - uint8_t pdev_id, wlan_objmgr_ref_dbgid dbg_id) +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_debug( + qdf_list_t *obj_list, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { struct wlan_objmgr_peer *peer; struct wlan_objmgr_peer *peer_temp; @@ -1221,11 +1391,11 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_pdev_id( peer = wlan_psoc_peer_list_peek_head(obj_list); while (peer) { /* For peer, macaddr is key */ - if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) - == QDF_STATUS_SUCCESS) && - (wlan_peer_get_pdev_id(peer) == pdev_id)) { - if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == - QDF_STATUS_SUCCESS) { + if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) { + if (wlan_objmgr_peer_try_get_ref_debug(peer, dbg_id, + func, line) == + QDF_STATUS_SUCCESS) { return peer; } } @@ -1237,10 +1407,10 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_pdev_id( /* Not found, return NULL */ return NULL; } - -static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_no_state( - qdf_list_t *obj_list, uint8_t *macaddr, - uint8_t pdev_id, wlan_objmgr_ref_dbgid dbg_id) +#else +static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer( + qdf_list_t *obj_list, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_peer *peer; struct wlan_objmgr_peer *peer_temp; @@ -1248,13 +1418,13 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_no_state( /* Iterate through hash list to get the peer */ peer = wlan_psoc_peer_list_peek_head(obj_list); while (peer) { - /* For peer, macaddr and pdev_id is key */ - if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) - == QDF_STATUS_SUCCESS) && - (wlan_peer_get_pdev_id(peer) == pdev_id)) { - wlan_objmgr_peer_get_ref(peer, dbg_id); - - return peer; + /* For peer, macaddr is key */ + if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) { + if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == + QDF_STATUS_SUCCESS) { + return peer; + } } /* Move to next peer */ peer_temp = peer; @@ -1264,110 +1434,169 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_no_state( /* Not found, return NULL */ return NULL; } +#endif /** - * wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid() - get peer - * from psoc peer list using - * mac and vdev self mac - * @obj_list: peer object list + * wlan_obj_psoc_peerlist_get_peer_logically_deleted() - get peer + * from psoc peer list + * @psoc: PSOC object * @macaddr: MAC address - * @bssid: BSSID address - * @dbg_id: id of the caller - * - * API to finds peer object pointer by MAC addr and BSSID from - * peer hash list for a node which is in logically deleted state, - * bssid check is done on matching peer * - * Caller to free the list allocated in this function + * API to finds peer object pointer of logically deleted peer * - * Return: list of peer pointers + * Return: peer pointer * NULL on FAILURE */ -static qdf_list_t - *wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid( +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static struct wlan_objmgr_peer * + wlan_obj_psoc_peerlist_get_peer_logically_deleted_debug( + qdf_list_t *obj_list, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_temp; + + /* Iterate through hash list to get the peer */ + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer) { + /* For peer, macaddr is key */ + if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) { + /* Return peer in logically deleted state */ + if (peer->obj_state == + WLAN_OBJ_STATE_LOGICALLY_DELETED) { + wlan_objmgr_peer_get_ref_debug(peer, dbg_id, + func, line); + + return peer; + } + + } + /* Move to next peer */ + peer_temp = peer; + peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + } + + /* Not found, return NULL */ + return NULL; +} +#else +static struct wlan_objmgr_peer * + wlan_obj_psoc_peerlist_get_peer_logically_deleted( qdf_list_t *obj_list, uint8_t *macaddr, - uint8_t *bssid, uint8_t pdev_id, wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_peer *peer; struct wlan_objmgr_peer *peer_temp; - struct wlan_logically_del_peer *peer_list = NULL; - qdf_list_t *logical_del_peer_list = NULL; - bool lock_released = false; - logical_del_peer_list = qdf_mem_malloc(sizeof(*logical_del_peer_list)); - if (!logical_del_peer_list) - return NULL; + /* Iterate through hash list to get the peer */ + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer) { + /* For peer, macaddr is key */ + if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) { + /* Return peer in logically deleted state */ + if (peer->obj_state == + WLAN_OBJ_STATE_LOGICALLY_DELETED) { + wlan_objmgr_peer_get_ref(peer, dbg_id); - qdf_list_create(logical_del_peer_list, WLAN_UMAC_PSOC_MAX_PEERS); + return peer; + } + } + /* Move to next peer */ + peer_temp = peer; + peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + } + + /* Not found, return NULL */ + return NULL; +} +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static struct wlan_objmgr_peer + *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state_debug( + qdf_list_t *obj_list, uint8_t *macaddr, + uint8_t *bssid, + uint8_t pdev_id, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_temp; /* Iterate through hash list to get the peer */ peer = wlan_psoc_peer_list_peek_head(obj_list); while (peer) { - wlan_peer_obj_lock(peer); - /* For peer, macaddr and pdev id are keys */ - if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) - == QDF_STATUS_SUCCESS) && - (wlan_peer_get_pdev_id(peer) == pdev_id)) { + /* For peer, macaddr is key */ + if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) { /* - * if BSSID not NULL, - * then match is requested by caller, check BSSID + * BSSID match is requested by caller, check BSSID * (vdev mac == bssid) -- return peer * (vdev mac != bssid) -- perform next iteration */ - if ((!bssid) || - (wlan_peer_bssid_match(peer, bssid) == - QDF_STATUS_SUCCESS)) { - /* Return peer in logically deleted state */ - if ((peer->obj_state == - WLAN_OBJ_STATE_LOGICALLY_DELETED) && - qdf_atomic_read( - &peer->peer_objmgr.ref_cnt)) { + if ((wlan_peer_bssid_match(peer, bssid) == + QDF_STATUS_SUCCESS) && + (wlan_peer_get_pdev_id(peer) == pdev_id)) { + wlan_objmgr_peer_get_ref_debug(peer, dbg_id, + func, line); - wlan_objmgr_peer_get_ref(peer, dbg_id); - wlan_peer_obj_unlock(peer); - lock_released = true; + return peer; + } + } + /* Move to next peer */ + peer_temp = peer; + peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + } - peer_list = - qdf_mem_malloc( - sizeof(struct wlan_logically_del_peer)); - if (!peer_list) { - wlan_objmgr_peer_release_ref(peer, dbg_id); - /* Lock is already released */ - WLAN_OBJMGR_BUG(0); - break; - } + /* Not found, return NULL */ + return NULL; +} +#else +static struct wlan_objmgr_peer + *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state( + qdf_list_t *obj_list, uint8_t *macaddr, + uint8_t *bssid, + uint8_t pdev_id, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_temp; - peer_list->peer = peer; + /* Iterate through hash list to get the peer */ + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer) { + /* For peer, macaddr is key */ + if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) { + /* + * BSSID match is requested by caller, check BSSID + * (vdev mac == bssid) -- return peer + * (vdev mac != bssid) -- perform next iteration + */ + if ((wlan_peer_bssid_match(peer, bssid) == + QDF_STATUS_SUCCESS) && + (wlan_peer_get_pdev_id(peer) == pdev_id)) { + wlan_objmgr_peer_get_ref(peer, dbg_id); - qdf_list_insert_front( - logical_del_peer_list, - &peer_list->list); - } + return peer; } } - - if (!lock_released) - wlan_peer_obj_unlock(peer); - /* Move to next peer */ peer_temp = peer; peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); - lock_released = false; } /* Not found, return NULL */ - if (qdf_list_empty(logical_del_peer_list)) { - qdf_mem_free(logical_del_peer_list); - return NULL; - } else { - return logical_del_peer_list; - } - + return NULL; } +#endif /** - * wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid() - get peer from psoc peer + * wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid() - get peer + * from psoc peer * list using mac and vdev * self mac * @psoc: PSOC object @@ -1380,10 +1609,13 @@ static qdf_list_t * Return: peer pointer * NULL on FAILURE */ -static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid( +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static struct wlan_objmgr_peer + *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_debug( qdf_list_t *obj_list, uint8_t *macaddr, uint8_t *bssid, uint8_t pdev_id, - wlan_objmgr_ref_dbgid dbg_id) + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { struct wlan_objmgr_peer *peer; struct wlan_objmgr_peer *peer_temp; @@ -1402,7 +1634,10 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid( if ((wlan_peer_bssid_match(peer, bssid) == QDF_STATUS_SUCCESS) && (wlan_peer_get_pdev_id(peer) == pdev_id)) { - if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) + if (wlan_objmgr_peer_try_get_ref_debug(peer, + dbg_id, + func, + line) == QDF_STATUS_SUCCESS) { return peer; } @@ -1415,12 +1650,10 @@ static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid( /* Not found, return NULL */ return NULL; } - -static struct wlan_objmgr_peer - *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state( +#else +static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid( qdf_list_t *obj_list, uint8_t *macaddr, - uint8_t *bssid, - uint8_t pdev_id, + uint8_t *bssid, uint8_t pdev_id, wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_peer *peer; @@ -1440,107 +1673,610 @@ static struct wlan_objmgr_peer if ((wlan_peer_bssid_match(peer, bssid) == QDF_STATUS_SUCCESS) && (wlan_peer_get_pdev_id(peer) == pdev_id)) { - wlan_objmgr_peer_get_ref(peer, dbg_id); + if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) + == QDF_STATUS_SUCCESS) { + return peer; + } + } + } + /* Move to next peer */ + peer_temp = peer; + peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + } + /* Not found, return NULL */ + return NULL; +} +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_no_state_debug( + qdf_list_t *obj_list, uint8_t *macaddr, + uint8_t pdev_id, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_temp; + + /* Iterate through hash list to get the peer */ + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer) { + /* For peer, macaddr and pdev_id is key */ + if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) && + (wlan_peer_get_pdev_id(peer) == pdev_id)) { + wlan_objmgr_peer_get_ref_debug(peer, dbg_id, func, + line); + + return peer; + } + /* Move to next peer */ + peer_temp = peer; + peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + } + + /* Not found, return NULL */ + return NULL; +} +#else +static struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer_no_state( + qdf_list_t *obj_list, uint8_t *macaddr, + uint8_t pdev_id, wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_temp; + + /* Iterate through hash list to get the peer */ + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer) { + /* For peer, macaddr and pdev_id is key */ + if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) && + (wlan_peer_get_pdev_id(peer) == pdev_id)) { + wlan_objmgr_peer_get_ref(peer, dbg_id); + + return peer; + } + /* Move to next peer */ + peer_temp = peer; + peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + } + + /* Not found, return NULL */ + return NULL; +} +#endif + +/** + * wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid() - + * get peer + * from psoc peer list using + * mac and vdev self mac + * @obj_list: peer object list + * @macaddr: MAC address + * @bssid: BSSID address + * @dbg_id: id of the caller + * @func: function name + * @line: line number + * + * API to finds peer object pointer by MAC addr and BSSID from + * peer hash list for a node which is in logically deleted state, + * bssid check is done on matching peer + * + * Caller to free the list allocated in this function + * + * Return: list of peer pointers + * NULL on FAILURE + */ +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static qdf_list_t + *wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid_debug( + qdf_list_t *obj_list, uint8_t *macaddr, + uint8_t *bssid, uint8_t pdev_id, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_temp; + struct wlan_logically_del_peer *peer_list = NULL; + qdf_list_t *logical_del_peer_list = NULL; + bool lock_released = false; + + logical_del_peer_list = qdf_mem_malloc(sizeof(*logical_del_peer_list)); + if (!logical_del_peer_list) + return NULL; + + qdf_list_create(logical_del_peer_list, WLAN_UMAC_PSOC_MAX_PEERS); + + /* Iterate through hash list to get the peer */ + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer) { + wlan_peer_obj_lock(peer); + /* For peer, macaddr and pdev id are keys */ + if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) && + (wlan_peer_get_pdev_id(peer) == pdev_id)) { + /* + * if BSSID not NULL, + * then match is requested by caller, check BSSID + * (vdev mac == bssid) -- return peer + * (vdev mac != bssid) -- perform next iteration + */ + if ((!bssid) || + (wlan_peer_bssid_match(peer, bssid) == + QDF_STATUS_SUCCESS)) { + /* Return peer in logically deleted state */ + if ((peer->obj_state == + WLAN_OBJ_STATE_LOGICALLY_DELETED) && + qdf_atomic_read( + &peer->peer_objmgr.ref_cnt)) { + wlan_objmgr_peer_get_ref_debug(peer, + dbg_id, + func, + line); + wlan_peer_obj_unlock(peer); + lock_released = true; + + peer_list = + qdf_mem_malloc( + sizeof(struct wlan_logically_del_peer)); + if (!peer_list) { + wlan_objmgr_peer_release_ref(peer, dbg_id); + /* Lock is already released */ + WLAN_OBJMGR_BUG(0); + break; + } + + peer_list->peer = peer; + + qdf_list_insert_front( + logical_del_peer_list, + &peer_list->list); + } + } + } + + if (!lock_released) + wlan_peer_obj_unlock(peer); + + /* Move to next peer */ + peer_temp = peer; + peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + lock_released = false; + } + + /* Not found, return NULL */ + if (qdf_list_empty(logical_del_peer_list)) { + qdf_mem_free(logical_del_peer_list); + return NULL; + } else { + return logical_del_peer_list; + } +} +#else +static qdf_list_t + *wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid( + qdf_list_t *obj_list, uint8_t *macaddr, + uint8_t *bssid, uint8_t pdev_id, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_temp; + struct wlan_logically_del_peer *peer_list = NULL; + qdf_list_t *logical_del_peer_list = NULL; + bool lock_released = false; + + logical_del_peer_list = qdf_mem_malloc(sizeof(*logical_del_peer_list)); + if (!logical_del_peer_list) + return NULL; + + qdf_list_create(logical_del_peer_list, WLAN_UMAC_PSOC_MAX_PEERS); + + /* Iterate through hash list to get the peer */ + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer) { + wlan_peer_obj_lock(peer); + /* For peer, macaddr and pdev id are keys */ + if ((WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) && + (wlan_peer_get_pdev_id(peer) == pdev_id)) { + /* + * if BSSID not NULL, + * then match is requested by caller, check BSSID + * (vdev mac == bssid) -- return peer + * (vdev mac != bssid) -- perform next iteration + */ + if ((!bssid) || + (wlan_peer_bssid_match(peer, bssid) == + QDF_STATUS_SUCCESS)) { + /* Return peer in logically deleted state */ + if ((peer->obj_state == + WLAN_OBJ_STATE_LOGICALLY_DELETED) && + qdf_atomic_read( + &peer->peer_objmgr.ref_cnt)) { + wlan_objmgr_peer_get_ref(peer, dbg_id); + wlan_peer_obj_unlock(peer); + lock_released = true; + + peer_list = + qdf_mem_malloc( + sizeof(struct wlan_logically_del_peer)); + if (!peer_list) { + wlan_objmgr_peer_release_ref(peer, dbg_id); + /* Lock is already released */ + WLAN_OBJMGR_BUG(0); + break; + } + + peer_list->peer = peer; + + qdf_list_insert_front( + logical_del_peer_list, + &peer_list->list); + } + } + } + + if (!lock_released) + wlan_peer_obj_unlock(peer); + + /* Move to next peer */ + peer_temp = peer; + peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + lock_released = false; + } + + /* Not found, return NULL */ + if (qdf_list_empty(logical_del_peer_list)) { + qdf_mem_free(logical_del_peer_list); + return NULL; + } else { + return logical_del_peer_list; + } +} +#endif + +QDF_STATUS wlan_objmgr_psoc_peer_attach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_peer *peer) +{ + struct wlan_objmgr_psoc_objmgr *objmgr; + uint8_t hash_index; + struct wlan_peer_list *peer_list; + + wlan_psoc_obj_lock(psoc); + objmgr = &psoc->soc_objmgr; + /* Max temporary peer limit is reached, return failure */ + if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) { + if (objmgr->temp_peer_count >= WLAN_MAX_PSOC_TEMP_PEERS) { + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_E_FAILURE; + } + } else { + /* Max peer limit is reached, return failure */ + if (objmgr->wlan_peer_count + >= wlan_psoc_get_max_peer_count(psoc)) { + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_E_FAILURE; + } + } + + /* Derive hash index from mac address */ + hash_index = WLAN_PEER_HASH(peer->macaddr); + peer_list = &objmgr->peer_list; + /* psoc lock should be taken before list lock */ + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* add peer to hash peer list */ + wlan_obj_psoc_peerlist_add_tail( + &peer_list->peer_hash[hash_index], + peer); + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + /* Increment peer count */ + if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) + objmgr->temp_peer_count++; + else + objmgr->wlan_peer_count++; + + wlan_psoc_obj_unlock(psoc); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_psoc_peer_detach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_peer *peer) +{ + struct wlan_objmgr_psoc_objmgr *objmgr; + uint8_t hash_index; + struct wlan_peer_list *peer_list; + + wlan_psoc_obj_lock(psoc); + objmgr = &psoc->soc_objmgr; + /* if list is empty, return */ + if (objmgr->wlan_peer_count == 0) { + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_E_FAILURE; + } + /* Get hash index, to locate the actual peer list */ + hash_index = WLAN_PEER_HASH(peer->macaddr); + peer_list = &objmgr->peer_list; + /* psoc lock should be taken before list lock */ + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* removes the peer from peer_list */ + if (wlan_obj_psoc_peerlist_remove_peer( + &peer_list->peer_hash[hash_index], + peer) == + QDF_STATUS_E_FAILURE) { + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + wlan_psoc_obj_unlock(psoc); + obj_mgr_err("Failed to detach peer"); + return QDF_STATUS_E_FAILURE; + } + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + /* Decrement peer count */ + if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) + objmgr->temp_peer_count--; + else + objmgr->wlan_peer_count--; + wlan_psoc_obj_unlock(psoc); + + return QDF_STATUS_SUCCESS; +} + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_psoc_objmgr *objmgr; + uint8_t hash_index; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_peer_list *peer_list; + + if (pdev_id >= WLAN_UMAC_MAX_PDEVS) + QDF_ASSERT(0); + + if (!macaddr) + return NULL; + + /* psoc lock should be taken before peer list lock */ + wlan_psoc_obj_lock(psoc); + objmgr = &psoc->soc_objmgr; + /* List is empty, return NULL */ + if (objmgr->wlan_peer_count == 0) { + wlan_psoc_obj_unlock(psoc); + return NULL; + } + /* reduce the search window, with hash key */ + hash_index = WLAN_PEER_HASH(macaddr); + peer_list = &objmgr->peer_list; + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* Iterate through peer list, get peer */ + peer = wlan_obj_psoc_peerlist_get_peer_by_pdev_id_debug( + &peer_list->peer_hash[hash_index], macaddr, + pdev_id, dbg_id, func, line); + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + wlan_psoc_obj_unlock(psoc); + + return peer; +} + +qdf_export_symbol(wlan_objmgr_get_peer_debug); +#else +struct wlan_objmgr_peer *wlan_objmgr_get_peer( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_psoc_objmgr *objmgr; + uint8_t hash_index; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_peer_list *peer_list; + + if (pdev_id >= WLAN_UMAC_MAX_PDEVS) + QDF_ASSERT(0); + + if (!macaddr) + return NULL; + + /* psoc lock should be taken before peer list lock */ + wlan_psoc_obj_lock(psoc); + objmgr = &psoc->soc_objmgr; + /* List is empty, return NULL */ + if (objmgr->wlan_peer_count == 0) { + wlan_psoc_obj_unlock(psoc); + return NULL; + } + /* reduce the search window, with hash key */ + hash_index = WLAN_PEER_HASH(macaddr); + peer_list = &objmgr->peer_list; + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* Iterate through peer list, get peer */ + peer = wlan_obj_psoc_peerlist_get_peer_by_pdev_id( + &peer_list->peer_hash[hash_index], macaddr, pdev_id, dbg_id); + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + wlan_psoc_obj_unlock(psoc); + + return peer; +} + +qdf_export_symbol(wlan_objmgr_get_peer); +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_debug( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_psoc_objmgr *objmgr; + uint8_t hash_index; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_peer_list *peer_list; + + if (!macaddr) + return NULL; + + /* psoc lock should be taken before peer list lock */ + wlan_psoc_obj_lock(psoc); + objmgr = &psoc->soc_objmgr; + /* List is empty, return NULL */ + if (objmgr->wlan_peer_count == 0) { + wlan_psoc_obj_unlock(psoc); + return NULL; + } + /* reduce the search window, with hash key */ + hash_index = WLAN_PEER_HASH(macaddr); + peer_list = &objmgr->peer_list; + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* Iterate through peer list, get peer */ + peer = wlan_obj_psoc_peerlist_get_peer_debug( + &peer_list->peer_hash[hash_index], + macaddr, dbg_id, func, line); + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + wlan_psoc_obj_unlock(psoc); + + return peer; +} + +qdf_export_symbol(wlan_objmgr_get_peer_by_mac_debug); +#else +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_psoc_objmgr *objmgr; + uint8_t hash_index; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_peer_list *peer_list; + + if (!macaddr) + return NULL; + + /* psoc lock should be taken before peer list lock */ + wlan_psoc_obj_lock(psoc); + objmgr = &psoc->soc_objmgr; + /* List is empty, return NULL */ + if (objmgr->wlan_peer_count == 0) { + wlan_psoc_obj_unlock(psoc); + return NULL; + } + /* reduce the search window, with hash key */ + hash_index = WLAN_PEER_HASH(macaddr); + peer_list = &objmgr->peer_list; + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* Iterate through peer list, get peer */ + peer = wlan_obj_psoc_peerlist_get_peer( + &peer_list->peer_hash[hash_index], macaddr, dbg_id); + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + wlan_psoc_obj_unlock(psoc); + + return peer; +} + +qdf_export_symbol(wlan_objmgr_get_peer_by_mac); +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted_debug( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_psoc_objmgr *objmgr; + uint8_t hash_index; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_peer_list *peer_list; - return peer; - } - } - /* Move to next peer */ - peer_temp = peer; - peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + /* psoc lock should be taken before peer list lock */ + wlan_psoc_obj_lock(psoc); + objmgr = &psoc->soc_objmgr; + /* List is empty, return NULL */ + if (objmgr->wlan_peer_count == 0) { + wlan_psoc_obj_unlock(psoc); + return NULL; } + /* reduce the search window, with hash key */ + hash_index = WLAN_PEER_HASH(macaddr); + peer_list = &objmgr->peer_list; + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* Iterate through peer list, get peer */ + peer = wlan_obj_psoc_peerlist_get_peer_logically_deleted_debug( + &peer_list->peer_hash[hash_index], macaddr, dbg_id, + func, line); + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + wlan_psoc_obj_unlock(psoc); - /* Not found, return NULL */ - return NULL; + return peer; } - -QDF_STATUS wlan_objmgr_psoc_peer_attach(struct wlan_objmgr_psoc *psoc, - struct wlan_objmgr_peer *peer) +#else +struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_psoc_objmgr *objmgr; uint8_t hash_index; + struct wlan_objmgr_peer *peer = NULL; struct wlan_peer_list *peer_list; + /* psoc lock should be taken before peer list lock */ wlan_psoc_obj_lock(psoc); objmgr = &psoc->soc_objmgr; - /* Max temporary peer limit is reached, return failure */ - if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) { - if (objmgr->temp_peer_count >= WLAN_MAX_PSOC_TEMP_PEERS) { - wlan_psoc_obj_unlock(psoc); - return QDF_STATUS_E_FAILURE; - } - } else { - /* Max peer limit is reached, return failure */ - if (objmgr->wlan_peer_count - >= wlan_psoc_get_max_peer_count(psoc)) { - wlan_psoc_obj_unlock(psoc); - return QDF_STATUS_E_FAILURE; - } + /* List is empty, return NULL */ + if (objmgr->wlan_peer_count == 0) { + wlan_psoc_obj_unlock(psoc); + return NULL; } - - /* Derive hash index from mac address */ - hash_index = WLAN_PEER_HASH(peer->macaddr); + /* reduce the search window, with hash key */ + hash_index = WLAN_PEER_HASH(macaddr); peer_list = &objmgr->peer_list; - /* psoc lock should be taken before list lock */ qdf_spin_lock_bh(&peer_list->peer_list_lock); - /* add peer to hash peer list */ - wlan_obj_psoc_peerlist_add_tail( - &peer_list->peer_hash[hash_index], - peer); + /* Iterate through peer list, get peer */ + peer = wlan_obj_psoc_peerlist_get_peer_logically_deleted( + &peer_list->peer_hash[hash_index], macaddr, dbg_id); qdf_spin_unlock_bh(&peer_list->peer_list_lock); - /* Increment peer count */ - if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) - objmgr->temp_peer_count++; - else - objmgr->wlan_peer_count++; - wlan_psoc_obj_unlock(psoc); - return QDF_STATUS_SUCCESS; + return peer; } +#endif -QDF_STATUS wlan_objmgr_psoc_peer_detach(struct wlan_objmgr_psoc *psoc, - struct wlan_objmgr_peer *peer) +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_no_state_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *bssid, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { struct wlan_objmgr_psoc_objmgr *objmgr; uint8_t hash_index; + struct wlan_objmgr_peer *peer = NULL; struct wlan_peer_list *peer_list; + /* psoc lock should be taken before peer list lock */ wlan_psoc_obj_lock(psoc); objmgr = &psoc->soc_objmgr; - /* if list is empty, return */ + /* List is empty, return NULL */ if (objmgr->wlan_peer_count == 0) { wlan_psoc_obj_unlock(psoc); - return QDF_STATUS_E_FAILURE; + return NULL; } - /* Get hash index, to locate the actual peer list */ - hash_index = WLAN_PEER_HASH(peer->macaddr); + /* reduce the search window, with hash key */ + hash_index = WLAN_PEER_HASH(macaddr); peer_list = &objmgr->peer_list; - /* psoc lock should be taken before list lock */ qdf_spin_lock_bh(&peer_list->peer_list_lock); - /* removes the peer from peer_list */ - if (wlan_obj_psoc_peerlist_remove_peer( - &peer_list->peer_hash[hash_index], - peer) == - QDF_STATUS_E_FAILURE) { - qdf_spin_unlock_bh(&peer_list->peer_list_lock); - wlan_psoc_obj_unlock(psoc); - obj_mgr_err("Failed to detach peer"); - return QDF_STATUS_E_FAILURE; - } + /* Iterate through peer list, get peer */ + peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state_debug( + &peer_list->peer_hash[hash_index], macaddr, bssid, + pdev_id, dbg_id, func, line); qdf_spin_unlock_bh(&peer_list->peer_list_lock); - /* Decrement peer count */ - if (peer->peer_mlme.peer_type == WLAN_PEER_STA_TEMP) - objmgr->temp_peer_count--; - else - objmgr->wlan_peer_count--; wlan_psoc_obj_unlock(psoc); - return QDF_STATUS_SUCCESS; + return peer; } -struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted( - struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, +qdf_export_symbol(wlan_objmgr_get_peer_by_mac_n_vdev_no_state_debug); +#else +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_no_state( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *bssid, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_psoc_objmgr *objmgr; @@ -1561,26 +2297,30 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_logically_deleted( peer_list = &objmgr->peer_list; qdf_spin_lock_bh(&peer_list->peer_list_lock); /* Iterate through peer list, get peer */ - peer = wlan_obj_psoc_peerlist_get_peer_logically_deleted( - &peer_list->peer_hash[hash_index], macaddr, dbg_id); + peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state( + &peer_list->peer_hash[hash_index], macaddr, bssid, + pdev_id, dbg_id); qdf_spin_unlock_bh(&peer_list->peer_list_lock); wlan_psoc_obj_unlock(psoc); return peer; } -struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac( - struct wlan_objmgr_psoc *psoc, uint8_t *macaddr, - wlan_objmgr_ref_dbgid dbg_id) +qdf_export_symbol(wlan_objmgr_get_peer_by_mac_n_vdev_no_state); +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *bssid, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { struct wlan_objmgr_psoc_objmgr *objmgr; uint8_t hash_index; struct wlan_objmgr_peer *peer = NULL; struct wlan_peer_list *peer_list; - if (!macaddr) - return NULL; - /* psoc lock should be taken before peer list lock */ wlan_psoc_obj_lock(psoc); objmgr = &psoc->soc_objmgr; @@ -1594,30 +2334,27 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac( peer_list = &objmgr->peer_list; qdf_spin_lock_bh(&peer_list->peer_list_lock); /* Iterate through peer list, get peer */ - peer = wlan_obj_psoc_peerlist_get_peer( - &peer_list->peer_hash[hash_index], macaddr, dbg_id); + peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_debug( + &peer_list->peer_hash[hash_index], macaddr, bssid, + pdev_id, dbg_id, func, line); qdf_spin_unlock_bh(&peer_list->peer_list_lock); wlan_psoc_obj_unlock(psoc); return peer; } -qdf_export_symbol(wlan_objmgr_get_peer_by_mac); -struct wlan_objmgr_peer *wlan_objmgr_get_peer( +qdf_export_symbol(wlan_objmgr_get_peer_by_mac_n_vdev_debug); +#else +struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, - uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) + uint8_t *bssid, uint8_t *macaddr, + wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_psoc_objmgr *objmgr; uint8_t hash_index; struct wlan_objmgr_peer *peer = NULL; struct wlan_peer_list *peer_list; - if (pdev_id >= WLAN_UMAC_MAX_PDEVS) - QDF_ASSERT(0); - - if (!macaddr) - return NULL; - /* psoc lock should be taken before peer list lock */ wlan_psoc_obj_lock(psoc); objmgr = &psoc->soc_objmgr; @@ -1631,15 +2368,48 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer( peer_list = &objmgr->peer_list; qdf_spin_lock_bh(&peer_list->peer_list_lock); /* Iterate through peer list, get peer */ - peer = wlan_obj_psoc_peerlist_get_peer_by_pdev_id( - &peer_list->peer_hash[hash_index], macaddr, pdev_id, dbg_id); + peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid( + &peer_list->peer_hash[hash_index], macaddr, bssid, + pdev_id, dbg_id); qdf_spin_unlock_bh(&peer_list->peer_list_lock); wlan_psoc_obj_unlock(psoc); return peer; } -qdf_export_symbol(wlan_objmgr_get_peer); +qdf_export_symbol(wlan_objmgr_get_peer_by_mac_n_vdev); +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_nolock_debug( + struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_psoc_objmgr *objmgr; + uint8_t hash_index; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_peer_list *peer_list; + + /* psoc lock should be taken before peer list lock */ + objmgr = &psoc->soc_objmgr; + /* List is empty, return NULL */ + if (objmgr->wlan_peer_count == 0) + return NULL; + + /* reduce the search window, with hash key */ + hash_index = WLAN_PEER_HASH(macaddr); + peer_list = &objmgr->peer_list; + /* Iterate through peer list, get peer */ + peer = wlan_obj_psoc_peerlist_get_peer_by_pdev_id_debug( + &peer_list->peer_hash[hash_index], macaddr, + pdev_id, dbg_id, func, line); + + return peer; +} + +qdf_export_symbol(wlan_objmgr_get_peer_nolock_debug); +#else struct wlan_objmgr_peer *wlan_objmgr_get_peer_nolock( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) @@ -1664,12 +2434,15 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_nolock( return peer; } -qdf_export_symbol(wlan_objmgr_get_peer_nolock); +qdf_export_symbol(wlan_objmgr_get_peer_nolock); +#endif -struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state( +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state_debug( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, - uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { struct wlan_objmgr_psoc_objmgr *objmgr; uint8_t hash_index; @@ -1689,19 +2462,20 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state( peer_list = &objmgr->peer_list; qdf_spin_lock_bh(&peer_list->peer_list_lock); /* Iterate through peer list, get peer */ - peer = wlan_obj_psoc_peerlist_get_peer_no_state( - &peer_list->peer_hash[hash_index], macaddr, pdev_id, dbg_id); + peer = wlan_obj_psoc_peerlist_get_peer_no_state_debug( + &peer_list->peer_hash[hash_index], macaddr, + pdev_id, dbg_id, func, line); qdf_spin_unlock_bh(&peer_list->peer_list_lock); wlan_psoc_obj_unlock(psoc); return peer; } -qdf_export_symbol(wlan_objmgr_get_peer_no_state); -struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev( +qdf_export_symbol(wlan_objmgr_get_peer_no_state_debug); +#else +struct wlan_objmgr_peer *wlan_objmgr_get_peer_no_state( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, - uint8_t *bssid, uint8_t *macaddr, - wlan_objmgr_ref_dbgid dbg_id) + uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_psoc_objmgr *objmgr; uint8_t hash_index; @@ -1721,19 +2495,20 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev( peer_list = &objmgr->peer_list; qdf_spin_lock_bh(&peer_list->peer_list_lock); /* Iterate through peer list, get peer */ - peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid( - &peer_list->peer_hash[hash_index], macaddr, bssid, - pdev_id, dbg_id); + peer = wlan_obj_psoc_peerlist_get_peer_no_state( + &peer_list->peer_hash[hash_index], macaddr, pdev_id, dbg_id); qdf_spin_unlock_bh(&peer_list->peer_list_lock); wlan_psoc_obj_unlock(psoc); return peer; } -qdf_export_symbol(wlan_objmgr_get_peer_by_mac_n_vdev); +qdf_export_symbol(wlan_objmgr_get_peer_no_state); +#endif /** - * wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev() - get peer from psoc + * wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev() - + * get peer from psoc * peer list using * mac and vdev * self mac @@ -1742,6 +2517,8 @@ qdf_export_symbol(wlan_objmgr_get_peer_by_mac_n_vdev); * @macaddr: MAC address * @bssid: BSSID address. NULL mac means search all. * @dbg_id: id of the caller + * @func: function name + * @line: line number * * API to finds peer object pointer by MAC addr and BSSID from * peer hash list, bssid check is done on matching peer @@ -1750,10 +2527,12 @@ qdf_export_symbol(wlan_objmgr_get_peer_by_mac_n_vdev); * NULL on FAILURE */ -qdf_list_t *wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev( +#ifdef WLAN_OBJMGR_REF_ID_TRACE +qdf_list_t *wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev_debug( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *bssid, uint8_t *macaddr, - wlan_objmgr_ref_dbgid dbg_id) + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) { struct wlan_objmgr_psoc_objmgr *objmgr; uint8_t hash_index; @@ -1775,26 +2554,27 @@ qdf_list_t *wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev( /* Iterate through peer list, get peer */ logical_del_peer_list = - wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid( + wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid_debug( &peer_list->peer_hash[hash_index], macaddr, - bssid, pdev_id, dbg_id); + bssid, pdev_id, dbg_id, func, line); qdf_spin_unlock_bh(&peer_list->peer_list_lock); wlan_psoc_obj_unlock(psoc); return logical_del_peer_list; } -qdf_export_symbol(wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev); -struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_no_state( +qdf_export_symbol(wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev_debug); +#else +qdf_list_t *wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev( struct wlan_objmgr_psoc *psoc, uint8_t pdev_id, uint8_t *bssid, uint8_t *macaddr, wlan_objmgr_ref_dbgid dbg_id) { struct wlan_objmgr_psoc_objmgr *objmgr; uint8_t hash_index; - struct wlan_objmgr_peer *peer = NULL; - struct wlan_peer_list *peer_list; + struct wlan_peer_list *peer_list = NULL; + qdf_list_t *logical_del_peer_list = NULL; /* psoc lock should be taken before peer list lock */ wlan_psoc_obj_lock(psoc); @@ -1808,16 +2588,21 @@ struct wlan_objmgr_peer *wlan_objmgr_get_peer_by_mac_n_vdev_no_state( hash_index = WLAN_PEER_HASH(macaddr); peer_list = &objmgr->peer_list; qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* Iterate through peer list, get peer */ - peer = wlan_obj_psoc_peerlist_get_peer_by_mac_n_bssid_no_state( - &peer_list->peer_hash[hash_index], macaddr, bssid, - pdev_id, dbg_id); + logical_del_peer_list = + wlan_obj_psoc_populate_logically_del_peerlist_by_mac_n_bssid( + &peer_list->peer_hash[hash_index], macaddr, + bssid, pdev_id, dbg_id); + qdf_spin_unlock_bh(&peer_list->peer_list_lock); wlan_psoc_obj_unlock(psoc); - return peer; + return logical_del_peer_list; } -qdf_export_symbol(wlan_objmgr_get_peer_by_mac_n_vdev_no_state); + +qdf_export_symbol(wlan_objmgr_populate_logically_deleted_peerlist_by_mac_n_vdev); +#endif void *wlan_objmgr_psoc_get_comp_private_obj(struct wlan_objmgr_psoc *psoc, enum wlan_umac_comp_id id) @@ -2005,7 +2790,7 @@ QDF_STATUS wlan_objmgr_psoc_set_user_config(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } -void wlan_objmgr_psoc_check_for_pdev_leaks(struct wlan_objmgr_psoc *psoc) +uint32_t wlan_objmgr_psoc_check_for_pdev_leaks(struct wlan_objmgr_psoc *psoc) { struct wlan_objmgr_psoc_objmgr *_psoc; struct wlan_objmgr_pdev *pdev; @@ -2014,13 +2799,13 @@ void wlan_objmgr_psoc_check_for_pdev_leaks(struct wlan_objmgr_psoc *psoc) QDF_BUG(psoc); if (!psoc) - return; + return leaks; wlan_psoc_obj_lock(psoc); _psoc = &psoc->soc_objmgr; if (!_psoc->wlan_pdev_count) { wlan_psoc_obj_unlock(psoc); - return; + return leaks; } obj_mgr_alert("objmgr pdev leaks detected for psoc %u!", @@ -2045,14 +2830,12 @@ void wlan_objmgr_psoc_check_for_pdev_leaks(struct wlan_objmgr_psoc *psoc) wlan_pdev_obj_unlock(pdev); } - QDF_DEBUG_PANIC("%u objmgr pdev leaks detected for psoc %u!", - leaks, _psoc->psoc_id); - wlan_psoc_obj_unlock(psoc); + return leaks; } qdf_export_symbol(wlan_objmgr_psoc_check_for_pdev_leaks); -void wlan_objmgr_psoc_check_for_vdev_leaks(struct wlan_objmgr_psoc *psoc) +uint32_t wlan_objmgr_psoc_check_for_vdev_leaks(struct wlan_objmgr_psoc *psoc) { struct wlan_objmgr_psoc_objmgr *_psoc; struct wlan_objmgr_vdev *vdev; @@ -2061,13 +2844,13 @@ void wlan_objmgr_psoc_check_for_vdev_leaks(struct wlan_objmgr_psoc *psoc) QDF_BUG(psoc); if (!psoc) - return; + return leaks; wlan_psoc_obj_lock(psoc); _psoc = &psoc->soc_objmgr; if (!_psoc->wlan_vdev_count) { wlan_psoc_obj_unlock(psoc); - return; + return leaks; } obj_mgr_alert("objmgr vdev leaks detected for psoc %u!", @@ -2091,10 +2874,8 @@ void wlan_objmgr_psoc_check_for_vdev_leaks(struct wlan_objmgr_psoc *psoc) wlan_vdev_obj_unlock(vdev); } - QDF_DEBUG_PANIC("%u objmgr vdev leaks detected for psoc %u!", - leaks, _psoc->psoc_id); - wlan_psoc_obj_unlock(psoc); + return leaks; } qdf_export_symbol(wlan_objmgr_psoc_check_for_vdev_leaks); @@ -2108,8 +2889,8 @@ wlan_objmgr_print_peer_ref_leaks(struct wlan_objmgr_peer *peer, int vdev_id) ref_id_dbg = peer->peer_objmgr.ref_id_dbg; wlan_objmgr_for_each_refs(ref_id_dbg, ref_id, refs) { - obj_mgr_alert(QDF_MAC_ADDR_STR " %7u %4u %s", - QDF_MAC_ADDR_ARRAY(peer->macaddr), + obj_mgr_alert(QDF_MAC_ADDR_FMT " %7u %4u %s", + QDF_MAC_ADDR_REF(peer->macaddr), vdev_id, refs, string_from_dbgid(ref_id)); @@ -2119,15 +2900,15 @@ wlan_objmgr_print_peer_ref_leaks(struct wlan_objmgr_peer *peer, int vdev_id) static inline void wlan_objmgr_print_peer_ref_leaks(struct wlan_objmgr_peer *peer, int vdev_id) { - obj_mgr_alert(QDF_MAC_ADDR_STR " %7u %4u %s", - QDF_MAC_ADDR_ARRAY(peer->macaddr), + obj_mgr_alert(QDF_MAC_ADDR_FMT " %7u %4u %s", + QDF_MAC_ADDR_REF(peer->macaddr), vdev_id, qdf_atomic_read(&peer->peer_objmgr.ref_cnt), "TOTAL_REF_COUNT"); } #endif -void wlan_objmgr_psoc_check_for_peer_leaks(struct wlan_objmgr_psoc *psoc) +uint32_t wlan_objmgr_psoc_check_for_peer_leaks(struct wlan_objmgr_psoc *psoc) { struct wlan_objmgr_psoc_objmgr *_psoc; struct wlan_objmgr_vdev *vdev; @@ -2136,13 +2917,13 @@ void wlan_objmgr_psoc_check_for_peer_leaks(struct wlan_objmgr_psoc *psoc) QDF_BUG(psoc); if (!psoc) - return; + return leaks; wlan_psoc_obj_lock(psoc); _psoc = &psoc->soc_objmgr; if (!_psoc->temp_peer_count && !_psoc->wlan_peer_count) { wlan_psoc_obj_unlock(psoc); - return; + return leaks; } obj_mgr_alert("objmgr peer leaks detected for psoc %u!", @@ -2164,9 +2945,72 @@ void wlan_objmgr_psoc_check_for_peer_leaks(struct wlan_objmgr_psoc *psoc) wlan_vdev_obj_unlock(vdev); } - QDF_DEBUG_PANIC("%u objmgr peer leaks detected for psoc %u!", - leaks, _psoc->psoc_id); - wlan_psoc_obj_unlock(psoc); + return leaks; } qdf_export_symbol(wlan_objmgr_psoc_check_for_peer_leaks); + +void wlan_objmgr_psoc_check_for_leaks(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_objmgr_psoc_objmgr *_psoc; + uint32_t peer_leaks = 0; + uint32_t vdev_leaks = 0; + uint32_t pdev_leaks = 0; + + _psoc = &psoc->soc_objmgr; + + peer_leaks = wlan_objmgr_psoc_check_for_peer_leaks(psoc); + vdev_leaks = wlan_objmgr_psoc_check_for_vdev_leaks(psoc); + pdev_leaks = wlan_objmgr_psoc_check_for_pdev_leaks(psoc); + + if (peer_leaks || vdev_leaks || pdev_leaks) { + QDF_DEBUG_PANIC("%u objmgr peer leaks %u objmgr vdev leaks" + "%u objmgr pdev leaks detected for psoc %u!", + peer_leaks, vdev_leaks, pdev_leaks, + _psoc->psoc_id); + } +} + +qdf_export_symbol(wlan_objmgr_psoc_check_for_leaks); + +#ifdef WLAN_OBJMGR_DEBUG +void wlan_print_psoc_info(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_objmgr_psoc_objmgr *psoc_objmgr; + struct wlan_objmgr_pdev *pdev; + struct wlan_objmgr_vdev *vdev; + uint16_t index = 0; + + psoc_objmgr = &psoc->soc_objmgr; + + obj_mgr_debug("psoc: %pK", psoc); + obj_mgr_debug("psoc_id: %d", psoc_objmgr->psoc_id); + obj_mgr_debug("wlan_pdev_count: %d", psoc_objmgr->wlan_pdev_count); + obj_mgr_debug("wlan_pdev_id_map: 0x%x", psoc_objmgr->wlan_pdev_id_map); + obj_mgr_debug("wlan_vdev_count: %d", psoc_objmgr->wlan_vdev_count); + obj_mgr_debug("max_vdev_count: %d", psoc_objmgr->max_vdev_count); + obj_mgr_debug("wlan_peer_count: %d", psoc_objmgr->wlan_peer_count); + obj_mgr_debug("max_peer_count: %d", psoc_objmgr->max_peer_count); + obj_mgr_debug("temp_peer_count: %d", psoc_objmgr->temp_peer_count); + obj_mgr_debug("ref_cnt: %d", qdf_atomic_read(&psoc_objmgr->ref_cnt)); + obj_mgr_debug("qdf_dev: %pK", psoc_objmgr->qdf_dev); + + obj_mgr_debug("wlan_vdev_id_map[%d]: 0x%x", + index, psoc_objmgr->wlan_vdev_id_map[index]); + index++; + obj_mgr_debug("wlan_vdev_id_map[%d]: 0x%x", + index, psoc_objmgr->wlan_vdev_id_map[index]); + + wlan_objmgr_for_each_psoc_pdev(psoc, index, pdev) { + obj_mgr_debug("wlan_pdev_list[%d]: %pK", index, pdev); + wlan_print_pdev_info(pdev); + } + + wlan_objmgr_for_each_psoc_vdev(psoc, index, vdev) { + obj_mgr_debug("wlan_vdev_list[%d]: %pK", index, vdev); + wlan_print_vdev_info(vdev); + } +} + +qdf_export_symbol(wlan_print_psoc_info); +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c index b7c1eb137e12476b03e71c996957b5999fb9619f..7646a2a7a28a57eeb404e7cff72c8c14b006c7af 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 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 above @@ -104,6 +104,8 @@ static QDF_STATUS wlan_objmgr_vdev_obj_free(struct wlan_objmgr_vdev *vdev) QDF_STATUS_E_FAILURE) return QDF_STATUS_E_FAILURE; + wlan_objmgr_vdev_trace_del_ref_list(vdev); + wlan_objmgr_vdev_trace_deinit_lock(vdev); qdf_spinlock_destroy(&vdev->vdev_lock); qdf_mem_free(vdev->vdev_mlme.bss_chan); @@ -168,6 +170,7 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( return NULL; } + wlan_objmgr_vdev_trace_init_lock(vdev); /* Initialize spinlock */ qdf_spinlock_create(&vdev->vdev_lock); /* Attach VDEV to PSOC VDEV's list */ @@ -178,6 +181,7 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( qdf_mem_free(vdev->vdev_mlme.bss_chan); qdf_mem_free(vdev->vdev_mlme.des_chan); qdf_spinlock_destroy(&vdev->vdev_lock); + wlan_objmgr_vdev_trace_deinit_lock(vdev); qdf_mem_free(vdev); return NULL; } @@ -192,6 +196,7 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( qdf_mem_free(vdev->vdev_mlme.bss_chan); qdf_mem_free(vdev->vdev_mlme.des_chan); qdf_spinlock_destroy(&vdev->vdev_lock); + wlan_objmgr_vdev_trace_deinit_lock(vdev); qdf_mem_free(vdev); return NULL; } @@ -260,13 +265,13 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( /* Component object failed to be created, clean up the object */ } else if (obj_status == QDF_STATUS_E_FAILURE) { /* Clean up the psoc */ - wlan_objmgr_vdev_obj_delete(vdev); obj_mgr_err("VDEV comp objects creation failed for vdev-id:%d", vdev->vdev_objmgr.vdev_id); + wlan_objmgr_vdev_obj_delete(vdev); return NULL; } - obj_mgr_info("Created vdev %d", vdev->vdev_objmgr.vdev_id); + obj_mgr_debug("Created vdev %d", vdev->vdev_objmgr.vdev_id); return vdev; } @@ -338,7 +343,7 @@ QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev) return QDF_STATUS_E_FAILURE; } - obj_mgr_info("Logically deleting vdev %d", vdev->vdev_objmgr.vdev_id); + obj_mgr_debug("Logically deleting vdev %d", vdev->vdev_objmgr.vdev_id); print_idx = qdf_get_pidx(); wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, @@ -512,8 +517,8 @@ QDF_STATUS wlan_objmgr_iterate_peerobj_list( if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { wlan_vdev_obj_unlock(vdev); - obj_mgr_err("VDEV is not in create state(:%d): vdev-id:%d", - vdev_id, vdev->obj_state); + obj_mgr_err("VDEV is not in create state:%d: vdev-id:%d", + vdev->obj_state, vdev_id); return QDF_STATUS_E_FAILURE; } wlan_objmgr_vdev_get_ref(vdev, dbg_id); @@ -538,6 +543,59 @@ QDF_STATUS wlan_objmgr_iterate_peerobj_list( return QDF_STATUS_SUCCESS; } +/** + ** APIs to get a peer with given mac in a vdev + */ +struct wlan_objmgr_peer * +wlan_objmgr_vdev_find_peer_by_mac(struct wlan_objmgr_vdev *vdev, + uint8_t *peer_mac, + wlan_objmgr_ref_dbgid dbg_id) +{ + qdf_list_t *peer_list; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_objmgr_peer *peer_next = NULL; + uint8_t vdev_id; + + if (!vdev) { + obj_mgr_err("VDEV is NULL"); + return NULL; + } + wlan_vdev_obj_lock(vdev); + vdev_id = wlan_vdev_get_id(vdev); + + if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { + wlan_vdev_obj_unlock(vdev); + obj_mgr_err("VDEV is not in create state:%d: vdev-id:%d", + vdev->obj_state, vdev_id); + return NULL; + } + wlan_objmgr_vdev_get_ref(vdev, dbg_id); + peer_list = &vdev->vdev_objmgr.wlan_peer_list; + /* Iterate through VDEV's peer list */ + peer = wlan_vdev_peer_list_peek_head(peer_list); + while (peer) { + peer_next = wlan_peer_get_next_peer_of_vdev(peer_list, + peer); + if (wlan_objmgr_peer_try_get_ref(peer, dbg_id) == + QDF_STATUS_SUCCESS) { + if (!WLAN_ADDR_EQ(peer_mac, + wlan_peer_get_macaddr(peer))) { + wlan_objmgr_vdev_release_ref(vdev, + dbg_id); + wlan_vdev_obj_unlock(vdev); + return peer; + } + wlan_objmgr_peer_release_ref(peer, dbg_id); + } + peer = peer_next; + } + wlan_objmgr_vdev_release_ref(vdev, dbg_id); + wlan_vdev_obj_unlock(vdev); + return NULL; +} + +qdf_export_symbol(wlan_objmgr_vdev_find_peer_by_mac); + /** * wlan_obj_vdev_populate_logically_del_peerlist() - get peer * from vdev peer list @@ -803,7 +861,9 @@ QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev, wlan_vdev_set_selfpeer(vdev, peer); opmode = wlan_vdev_mlme_get_opmode(vdev); /* For AP mode, self peer and BSS peer are same */ - if ((opmode == QDF_SAP_MODE) || (opmode == QDF_P2P_GO_MODE)) + if ((opmode == QDF_SAP_MODE) || + (opmode == QDF_P2P_GO_MODE) || + (opmode == QDF_NDI_MODE)) wlan_vdev_set_bsspeer(vdev, peer); } /* set BSS peer for sta */ @@ -923,8 +983,40 @@ void *wlan_objmgr_vdev_get_comp_private_obj( } qdf_export_symbol(wlan_objmgr_vdev_get_comp_private_obj); -void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, - wlan_objmgr_ref_dbgid id) +#ifdef WLAN_OBJMGR_REF_ID_TRACE +static inline void +wlan_objmgr_vdev_ref_trace(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, + const char *func, int line) +{ + struct wlan_objmgr_trace *trace; + + trace = &vdev->vdev_objmgr.trace; + + if (func) + wlan_objmgr_trace_ref(&trace->references[id].head, + trace, func, line); +} + +static inline void +wlan_objmgr_vdev_deref_trace(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, + const char *func, int line) +{ + struct wlan_objmgr_trace *trace; + + trace = &vdev->vdev_objmgr.trace; + + if (func) + wlan_objmgr_trace_ref(&trace->dereferences[id].head, + trace, func, line); +} +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +void wlan_objmgr_vdev_get_ref_debug(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, + const char *func, int line) { if (!vdev) { obj_mgr_err("vdev obj is NULL for id:%d", id); @@ -935,12 +1027,32 @@ void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt); qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]); + wlan_objmgr_vdev_ref_trace(vdev, id, func, line); return; } + +qdf_export_symbol(wlan_objmgr_vdev_get_ref_debug); +#else +void wlan_objmgr_vdev_get_ref(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id) +{ + if (!vdev) { + obj_mgr_err("vdev obj is NULL for id:%d", id); + QDF_ASSERT(0); + return; + } + /* Increment ref count */ + qdf_atomic_inc(&vdev->vdev_objmgr.ref_cnt); + qdf_atomic_inc(&vdev->vdev_objmgr.ref_id_dbg[id]); +} + qdf_export_symbol(wlan_objmgr_vdev_get_ref); +#endif -QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, - wlan_objmgr_ref_dbgid id) +#ifdef WLAN_OBJMGR_REF_ID_TRACE +QDF_STATUS wlan_objmgr_vdev_try_get_ref_debug(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, + const char *func, int line) { uint8_t vdev_id; @@ -964,50 +1076,152 @@ QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, } /* Increment ref count */ - wlan_objmgr_vdev_get_ref(vdev, id); + wlan_objmgr_vdev_get_ref_debug(vdev, id, func, line); wlan_vdev_obj_unlock(vdev); return QDF_STATUS_SUCCESS; } -qdf_export_symbol(wlan_objmgr_vdev_try_get_ref); -void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev, - wlan_objmgr_ref_dbgid id) +qdf_export_symbol(wlan_objmgr_vdev_try_get_ref_debug); +#else +QDF_STATUS wlan_objmgr_vdev_try_get_ref(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id) { uint8_t vdev_id; if (!vdev) { obj_mgr_err("vdev obj is NULL for id:%d", id); QDF_ASSERT(0); - return; + return QDF_STATUS_E_FAILURE; } + wlan_vdev_obj_lock(vdev); vdev_id = wlan_vdev_get_id(vdev); + if (vdev->obj_state != WLAN_OBJ_STATE_CREATED) { + wlan_vdev_obj_unlock(vdev); + if (vdev->vdev_objmgr.print_cnt++ <= + WLAN_OBJMGR_RATELIMIT_THRESH) + obj_mgr_err( + "[Ref id: %d] vdev(%d) is not in Created state(%d)", + id, vdev_id, vdev->obj_state); - if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) { - obj_mgr_err("vdev (id:%d)ref cnt was not taken by %d", - vdev_id, id); - wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, - QDF_TRACE_LEVEL_FATAL); - WLAN_OBJMGR_BUG(0); - return; + return QDF_STATUS_E_RESOURCES; } - if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { - obj_mgr_err("vdev ref cnt is 0"); - WLAN_OBJMGR_BUG(0); - return; + /* Increment ref count */ + wlan_objmgr_vdev_get_ref(vdev, id); + wlan_vdev_obj_unlock(vdev); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(wlan_objmgr_vdev_try_get_ref); +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev_debug( + struct wlan_objmgr_pdev *pdev, + qdf_list_t *vdev_list, + struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_vdev *vdev_next; + qdf_list_node_t *node = &vdev->vdev_node; + qdf_list_node_t *prev_node = NULL; + + if (!node) + return NULL; + + wlan_pdev_obj_lock(pdev); + prev_node = node; + while (qdf_list_peek_next(vdev_list, prev_node, &node) == + QDF_STATUS_SUCCESS) { + vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev, + vdev_node); + if (wlan_objmgr_vdev_try_get_ref_debug(vdev_next, dbg_id, + func, line) == + QDF_STATUS_SUCCESS) { + wlan_pdev_obj_unlock(pdev); + return vdev_next; + } + + prev_node = node; } - qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]); + wlan_pdev_obj_unlock(pdev); - /* Decrement ref count, free vdev, if ref count == 0 */ - if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) - wlan_objmgr_vdev_obj_destroy(vdev); + return NULL; +} +#else +struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev( + struct wlan_objmgr_pdev *pdev, + qdf_list_t *vdev_list, + struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid dbg_id) +{ + struct wlan_objmgr_vdev *vdev_next; + qdf_list_node_t *node = &vdev->vdev_node; + qdf_list_node_t *prev_node = NULL; - return; + if (!node) + return NULL; + + wlan_pdev_obj_lock(pdev); + prev_node = node; + while (qdf_list_peek_next(vdev_list, prev_node, &node) == + QDF_STATUS_SUCCESS) { + vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev, + vdev_node); + if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) == + QDF_STATUS_SUCCESS) { + wlan_pdev_obj_unlock(pdev); + return vdev_next; + } + + prev_node = node; + } + wlan_pdev_obj_unlock(pdev); + + return NULL; } -qdf_export_symbol(wlan_objmgr_vdev_release_ref); +#endif + +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head_debug( + struct wlan_objmgr_pdev *pdev, + qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_vdev *vdev; + qdf_list_node_t *node = NULL; + qdf_list_node_t *prev_node = NULL; + wlan_pdev_obj_lock(pdev); + + if (qdf_list_peek_front(vdev_list, &node) != QDF_STATUS_SUCCESS) { + wlan_pdev_obj_unlock(pdev); + return NULL; + } + + do { + vdev = qdf_container_of(node, struct wlan_objmgr_vdev, + vdev_node); + if (wlan_objmgr_vdev_try_get_ref_debug(vdev, dbg_id, + func, line) == + QDF_STATUS_SUCCESS) { + wlan_pdev_obj_unlock(pdev); + return vdev; + } + + prev_node = node; + } while (qdf_list_peek_next(vdev_list, prev_node, &node) == + QDF_STATUS_SUCCESS); + + wlan_pdev_obj_unlock(pdev); + + return NULL; +} +#else struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head( struct wlan_objmgr_pdev *pdev, qdf_list_t *vdev_list, wlan_objmgr_ref_dbgid dbg_id) @@ -1040,7 +1254,24 @@ struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_active_head( return NULL; } +#endif +#ifdef WLAN_OBJMGR_REF_ID_TRACE +struct wlan_objmgr_vdev *wlan_pdev_peek_active_first_vdev_debug( + struct wlan_objmgr_pdev *pdev, + wlan_objmgr_ref_dbgid dbg_id, + const char *func, int line) +{ + struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; + qdf_list_t *vdev_list; + + /* VDEV list */ + vdev_list = &objmgr->wlan_vdev_list; + + return wlan_pdev_vdev_list_peek_active_head_debug(pdev, vdev_list, + dbg_id, func, line); +} +#else struct wlan_objmgr_vdev *wlan_pdev_peek_active_first_vdev( struct wlan_objmgr_pdev *pdev, wlan_objmgr_ref_dbgid dbg_id) @@ -1054,36 +1285,112 @@ struct wlan_objmgr_vdev *wlan_pdev_peek_active_first_vdev( return wlan_pdev_vdev_list_peek_active_head(pdev, vdev_list, dbg_id); } +#endif -struct wlan_objmgr_vdev *wlan_vdev_get_next_active_vdev_of_pdev( - struct wlan_objmgr_pdev *pdev, - qdf_list_t *vdev_list, - struct wlan_objmgr_vdev *vdev, - wlan_objmgr_ref_dbgid dbg_id) +#ifdef WLAN_OBJMGR_REF_ID_TRACE +void wlan_objmgr_vdev_release_ref_debug(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id, + const char *func, int line) { - struct wlan_objmgr_vdev *vdev_next; - qdf_list_node_t *node = &vdev->vdev_node; - qdf_list_node_t *prev_node = NULL; + uint8_t vdev_id; - if (!node) - return NULL; + if (!vdev) { + obj_mgr_err("vdev obj is NULL for id:%d", id); + QDF_ASSERT(0); + return; + } - wlan_pdev_obj_lock(pdev); - prev_node = node; - while (qdf_list_peek_next(vdev_list, prev_node, &node) == - QDF_STATUS_SUCCESS) { - vdev_next = qdf_container_of(node, struct wlan_objmgr_vdev, - vdev_node); - if (wlan_objmgr_vdev_try_get_ref(vdev_next, dbg_id) == - QDF_STATUS_SUCCESS) { - wlan_pdev_obj_unlock(pdev); - return vdev_next; - } + vdev_id = wlan_vdev_get_id(vdev); - prev_node = node; + if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) { + obj_mgr_alert("vdev (id:%d)ref cnt was not taken by %d", + vdev_id, id); + wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, + QDF_TRACE_LEVEL_FATAL); + WLAN_OBJMGR_BUG(0); + return; } - wlan_pdev_obj_unlock(pdev); - return NULL; + if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { + obj_mgr_alert("vdev ref cnt is 0"); + WLAN_OBJMGR_BUG(0); + return; + } + qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]); + wlan_objmgr_vdev_deref_trace(vdev, id, func, line); + + /* Decrement ref count, free vdev, if ref count == 0 */ + if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) + wlan_objmgr_vdev_obj_destroy(vdev); } +qdf_export_symbol(wlan_objmgr_vdev_release_ref_debug); +#else +void wlan_objmgr_vdev_release_ref(struct wlan_objmgr_vdev *vdev, + wlan_objmgr_ref_dbgid id) +{ + uint8_t vdev_id; + + if (!vdev) { + obj_mgr_err("vdev obj is NULL for id:%d", id); + QDF_ASSERT(0); + return; + } + + vdev_id = wlan_vdev_get_id(vdev); + + if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_id_dbg[id])) { + obj_mgr_alert("vdev (id:%d)ref cnt was not taken by %d", + vdev_id, id); + wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg, + QDF_TRACE_LEVEL_FATAL); + WLAN_OBJMGR_BUG(0); + return; + } + + if (!qdf_atomic_read(&vdev->vdev_objmgr.ref_cnt)) { + obj_mgr_alert("vdev ref cnt is 0"); + WLAN_OBJMGR_BUG(0); + return; + } + qdf_atomic_dec(&vdev->vdev_objmgr.ref_id_dbg[id]); + + /* Decrement ref count, free vdev, if ref count == 0 */ + if (qdf_atomic_dec_and_test(&vdev->vdev_objmgr.ref_cnt)) + wlan_objmgr_vdev_obj_destroy(vdev); +} + +qdf_export_symbol(wlan_objmgr_vdev_release_ref); +#endif + +#ifdef WLAN_OBJMGR_DEBUG +void wlan_print_vdev_info(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_vdev_objmgr *vdev_objmgr; + uint32_t ref_cnt; + + vdev_objmgr = &vdev->vdev_objmgr; + + ref_cnt = qdf_atomic_read(&vdev_objmgr->ref_cnt); + + obj_mgr_debug("vdev: %pK", vdev); + obj_mgr_debug("vdev_id: %d", vdev_objmgr->vdev_id); + obj_mgr_debug("print_cnt: %d", vdev_objmgr->print_cnt); + obj_mgr_debug("wlan_pdev: %pK", vdev_objmgr->wlan_pdev); + obj_mgr_debug("ref_cnt: %d", ref_cnt); +} + +qdf_export_symbol(wlan_print_vdev_info); +#endif + +void wlan_objmgr_vdev_peer_freed_notify(struct wlan_objmgr_vdev *vdev) +{ + wlan_objmgr_vdev_peer_free_notify_handler stat_handler; + uint8_t i; + + for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { + stat_handler = g_umac_glb_obj->vdev_peer_free_notify_handler[i]; + if (stat_handler) + stat_handler(vdev); + } +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/inc/wlan_serialization_api.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/inc/wlan_serialization_api.h index bbc81bacec88a84f49d68b76c87714cbe131d943..2d33bd0beb015427ae1ac696c8f988bdc554b029 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/inc/wlan_serialization_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/inc/wlan_serialization_api.h @@ -1,6 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -160,7 +159,40 @@ typedef QDF_STATUS (*wlan_ser_umac_cmd_cb)(void *umac_cmd); /** * enum wlan_umac_cmd_id - Command Type - * @WLAN_SER_CMD_SCAN: Scan command + * @WLAN_SER_CMD_SCAN: Scan command + * @WLAN_SER_CMD_NONSCAN: Non-scan command + * @WLAN_SER_CMD_HDD_ISSUE_REASSOC_SAME_AP: HDD Reassoc cmd + * @WLAN_SER_CMD_SME_ISSUE_REASSOC_SAME_AP: SME Reassoc cmd + * @WLAN_SER_CMD_SME_ISSUE_DISASSOC_FOR_HANDOFF: SME Disassoc cmd + * @WLAN_SER_CMD_SME_ISSUE_ASSOC_TO_SIMILAR_AP: SME Assoc cmd + * @WLAN_SER_CMD_FORCE_IBSS_LEAVE: IBSS leave AP cmd + * @WLAN_SER_CMD_SME_ISSUE_FT_REASSOC: SME reassoc cmd + * @WLAN_SER_CMD_FORCE_DISASSOC_STA: Force diassoc for STA vap + * @WLAN_SER_CMD_FORCE_DEAUTH_STA: Force deauth for STA vap + * @WLAN_SER_CMD_PERFORM_PRE_AUTH: Pre auth ops cmd + * @WLAN_SER_CMD_WM_STATUS_CHANGE: WM status modification cmd + * @WLAN_SER_CMD_NDP_INIT_REQ: NDP init request cmd + * @WLAN_SER_CMD_NDP_RESP_REQ: NDP response to request cmd + * @WLAN_SER_CMD_NDP_DATA_END_INIT_REQ: NDP data end init request + * @WLAN_SER_CMD_NDP_END_ALL_REQ: NDP close all request + * @WLAN_SER_CMD_ADDTS: ADD Ts cmd + * @WLAN_SER_CMD_DELTS: Del Ts cmd + * @WLAN_SER_CMD_TDLS_SEND_MGMT: TDLS mgmt send cmd + * @WLAN_SER_CMD_TDLS_ADD_PEER: TDLS cmd to add peer + * @WLAN_SER_CMD_TDLS_DEL_PEER: TDLS cmd to del peer + * @WLAN_SER_CMD_SET_HW_MODE: Cmd to set hardware mode change + * @WLAN_SER_CMD_NSS_UPDATE: Cmd to update NSS config + * @WLAN_SER_CMD_SET_DUAL_MAC_CONFIG: Cmd to set dual mac + * @WLAN_SER_CMD_SET_ANTENNA_MODE: Set antenna mode + * @WLAN_SER_CMD_VDEV_DELETE: Cmd to del vdev + * @WLAN_SER_CMD_VDEV_START_BSS: Cmd to start a AP VDEV + * @WLAN_SER_CMD_VDEV_STOP_BSS: Cmd to stop a AP VDEV + * @WLAN_SER_CMD_VDEV_CONNECT: Cmd to start a STA VDEV + * @WLAN_SER_CMD_VDEV_DISCONNECT: Cmd to stop a STA VDEV + * @WLAN_SER_CMD_VDEV_RESTART: Cmd to restart a VDEV + * @WLAN_SER_CMD_PDEV_RESTART: Cmd to restart all VDEVs of a PDEV + * @WLAN_SER_CMD_PDEV_CSA_RESTART: Cmd to CSA restart all AP VDEVs of a PDEV + * @WLAN_SER_CMD_GET_DISCONNECT_STATS: Cmd to get peer stats on disconnection */ enum wlan_serialization_cmd_type { /* all scan command before non-scan */ @@ -190,12 +222,15 @@ enum wlan_serialization_cmd_type { WLAN_SER_CMD_NSS_UPDATE, WLAN_SER_CMD_SET_DUAL_MAC_CONFIG, WLAN_SER_CMD_SET_ANTENNA_MODE, - WLAN_SER_CMD_DEL_STA_SESSION, + WLAN_SER_CMD_VDEV_DELETE, WLAN_SER_CMD_VDEV_START_BSS, WLAN_SER_CMD_VDEV_STOP_BSS, WLAN_SER_CMD_VDEV_CONNECT, WLAN_SER_CMD_VDEV_DISCONNECT, WLAN_SER_CMD_VDEV_RESTART, + WLAN_SER_CMD_PDEV_RESTART, + WLAN_SER_CMD_PDEV_CSA_RESTART, + WLAN_SER_CMD_GET_DISCONNECT_STATS, WLAN_SER_CMD_MAX }; @@ -209,6 +244,8 @@ enum wlan_serialization_cmd_type { * @WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD: Cancel all non scans on a given vdev * @WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE: Cancel all non scans on a given vdev * and matching cmd type + * @WLAN_SER_CANCEL_VDEV_NON_SCAN_NB_CMD: Cancel all non-blocking, + * non-scan commands of a given vdev * @WLAN_SER_CANCEL_NON_SCAN_CMD: Cancel the given non scan command */ enum wlan_serialization_cancel_type { @@ -219,6 +256,7 @@ enum wlan_serialization_cancel_type { WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD, WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD, WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE, + WLAN_SER_CANCEL_VDEV_NON_SCAN_NB_CMD, WLAN_SER_CANCEL_NON_SCAN_CMD, WLAN_SER_CANCEL_MAX, }; @@ -259,6 +297,18 @@ enum wlan_serialization_cmd_status { WLAN_SER_CMD_NOT_FOUND, }; +/** + * enum wlan_ser_cmd_attr - Serialization cmd attribute + * @WLAN_SER_CMD_ATTR_NONE - No attribuate associated + * @WLAN_SER_CMD_ATTR_BLOCK - Blocking attribute + * @WLAN_SER_CMD_ATTR_NONBLOCK - Non-blocking attribute + */ +enum wlan_ser_cmd_attr { + WLAN_SER_CMD_ATTR_NONE, + WLAN_SER_CMD_ATTR_BLOCK, + WLAN_SER_CMD_ATTR_NONBLOCK, +}; + /** * struct wlan_serialization_command - Command to be serialized * @wlan_serialization_cmd_type: Type of command @@ -575,6 +625,16 @@ wlan_serialization_get_vdev_active_cmd_type(struct wlan_objmgr_vdev *vdev); QDF_STATUS wlan_ser_get_cmd_activation_status(struct wlan_objmgr_vdev *vdev); +/** + * wlan_ser_is_vdev_queue_enabled() - Return vdev queue status + * @vdev: vdev object + * + * This API return vdev queue enable status + * + * Return: true if vdev queue is enabled + */ +bool wlan_ser_is_vdev_queue_enabled(struct wlan_objmgr_vdev *vdev); + /** * wlan_ser_validate_umac_cmd() - validate umac cmd data * @vdev: objmgr vdev pointer @@ -631,4 +691,14 @@ void wlan_serialization_purge_all_pending_cmd_by_vdev_id( void wlan_serialization_purge_all_scan_cmd_by_vdev_id( struct wlan_objmgr_pdev *pdev, uint8_t vdev_id); + +/** + * wlan_ser_vdev_queue_disable -Disable vdev specific serialization queue + * @vdev: Vdev Object + * + * This function disables the serialization for the vdev queue + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_ser_vdev_queue_disable(struct wlan_objmgr_vdev *vdev); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/inc/wlan_serialization_legacy_api.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/inc/wlan_serialization_legacy_api.h index 56cff30dec03cfc6eca777e6676853c78b40fcfe..0c48da459aed79ec45969339b4ef357b667165ee 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/inc/wlan_serialization_legacy_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/inc/wlan_serialization_legacy_api.h @@ -79,19 +79,6 @@ wlan_serialization_get_pending_list_next_node_using_psoc( struct wlan_objmgr_psoc *psoc, struct wlan_serialization_command *prev_cmd, uint8_t is_cmd_for_pending_scan_queue); -/** - * wlan_serialization_get_active_list_count() - Return Active list count - * @psoc: pointer to soc - * @is_cmd_from_active_scan_queue: flag to determine whether command needed - * from scan or non-scan active queue - * - * Get the number of nodes present in active list - * - * Return: count number of active commands in queue - */ - -uint32_t wlan_serialization_get_active_list_count(struct wlan_objmgr_psoc *psoc, - uint8_t is_cmd_from_active_scan_queue); /** * wlan_serialization_get_pending_list_count() - Return pending list count * @psoc: pointer to soc diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_api.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_api.c index 7c22472a76ce5a0521bced4c5db6941acb7b1bf0..6cf61b7cf3cbcf9389e39c8aea52154b844b5d6e 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -643,6 +643,25 @@ wlan_serialization_get_vdev_active_cmd_type(struct wlan_objmgr_vdev *vdev) return cmd_type; } +bool wlan_ser_is_vdev_queue_enabled(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_ser_vdev_obj *ser_vdev_obj; + struct wlan_serialization_vdev_queue *vdev_queue; + + ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev); + if (!ser_vdev_obj) { + ser_err("invalid ser_vdev_obj"); + return false; + } + + vdev_queue = wlan_serialization_get_vdev_queue_obj( + ser_vdev_obj, WLAN_SER_CMD_NONSCAN); + if (vdev_queue->queue_disable) + return false; + else + return true; +} + QDF_STATUS wlan_ser_get_cmd_activation_status(struct wlan_objmgr_vdev *vdev) { @@ -766,9 +785,11 @@ void wlan_serialization_purge_all_pdev_cmd(struct wlan_objmgr_pdev *pdev) wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, NULL, NULL, WLAN_SER_CMD_SCAN, true); wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, NULL, NULL, - WLAN_SER_CMD_NONSCAN, false); + WLAN_SER_CMD_NONSCAN, false, + WLAN_SER_CMD_ATTR_NONE); wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, NULL, NULL, - WLAN_SER_CMD_NONSCAN, true); + WLAN_SER_CMD_NONSCAN, true, + WLAN_SER_CMD_ATTR_NONE); } static inline @@ -815,7 +836,8 @@ void wlan_serialization_purge_all_pending_cmd_by_vdev_id( wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, vdev, NULL, WLAN_SER_CMD_SCAN, false); wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, vdev, NULL, - WLAN_SER_CMD_NONSCAN, false); + WLAN_SER_CMD_NONSCAN, false, + WLAN_SER_CMD_ATTR_NONE); wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); } @@ -852,3 +874,47 @@ void wlan_serialization_purge_all_scan_cmd_by_vdev_id( wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); } + +QDF_STATUS wlan_ser_vdev_queue_disable(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_pdev *pdev; + struct wlan_ser_vdev_obj *ser_vdev_obj; + struct wlan_serialization_vdev_queue *vdev_queue; + struct wlan_ser_pdev_obj *ser_pdev_obj; + struct wlan_serialization_pdev_queue *pdev_q; + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) { + ser_err("invalid PDEV object"); + return QDF_STATUS_E_INVAL; + } + + ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); + if (!ser_pdev_obj) { + ser_err("invalid ser_pdev_obj"); + return QDF_STATUS_E_INVAL; + } + + ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev); + if (!ser_vdev_obj) { + ser_err("invalid ser_vdev_obj"); + return QDF_STATUS_E_INVAL; + } + + pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; + + vdev_queue = wlan_serialization_get_vdev_queue_obj( + ser_vdev_obj, WLAN_SER_CMD_NONSCAN); + if (!vdev_queue) { + ser_err("invalid vdev_queue object"); + return QDF_STATUS_E_INVAL; + } + + wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock); + vdev_queue->queue_disable = true; + wlan_serialization_release_lock(&pdev_q->pdev_queue_lock); + ser_debug("Disabling the serialization for vdev:%d", + wlan_vdev_get_id(vdev)); + + return QDF_STATUS_SUCCESS; +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal.c index dc9443a1b8c75f3186fbecc67a0f2a46b0d1952c..88dfc763614710aff9711adf174244183b703f6e 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal.c @@ -1,6 +1,5 @@ /* * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. 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 @@ -364,7 +363,8 @@ QDF_STATUS wlan_serialization_activate_cmd( wlan_serialization_cmd_cancel_handler( ser_pdev_obj, &cmd_list->cmd, NULL, NULL, cmd_list->cmd.cmd_type, - WLAN_SERIALIZATION_ACTIVE_QUEUE); + WLAN_SERIALIZATION_ACTIVE_QUEUE, + WLAN_SER_CMD_ATTR_NONE); error: return status; } @@ -543,6 +543,7 @@ QDF_STATUS wlan_serialization_generic_timer_cb(void *arg) struct wlan_serialization_timer *timer = arg; struct wlan_serialization_command *cmd = timer->cmd; struct wlan_objmgr_vdev *vdev = NULL; + enum wlan_serialization_cmd_status status; if (!cmd) { @@ -566,10 +567,11 @@ QDF_STATUS wlan_serialization_generic_timer_cb(void *arg) * dequeue cmd API will cleanup and destroy the timer. If it fails to * dequeue command then we have to destroy the timer. */ - wlan_serialization_dequeue_cmd(cmd, SER_TIMEOUT, true); + status = wlan_serialization_dequeue_cmd(cmd, SER_TIMEOUT, true); /* Release the ref taken before the timer was started */ - wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); + if (status == WLAN_SER_CMD_IN_ACTIVE_LIST) + wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); return QDF_STATUS_SUCCESS; } @@ -815,7 +817,8 @@ wlan_serialization_cmd_cancel_handler( struct wlan_ser_pdev_obj *ser_obj, struct wlan_serialization_command *cmd, struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, - enum wlan_serialization_cmd_type cmd_type, uint8_t queue_type) + enum wlan_serialization_cmd_type cmd_type, uint8_t queue_type, + enum wlan_ser_cmd_attr cmd_attr) { enum wlan_serialization_cmd_status active_status = WLAN_SER_CMD_NOT_FOUND; @@ -837,7 +840,7 @@ wlan_serialization_cmd_cancel_handler( else active_status = wlan_ser_cancel_non_scan_cmd( ser_obj, pdev, vdev, cmd, - cmd_type, true); + cmd_type, true, cmd_attr); } if (queue_type & WLAN_SERIALIZATION_PENDING_QUEUE) { @@ -848,7 +851,7 @@ wlan_serialization_cmd_cancel_handler( else pending_status = wlan_ser_cancel_non_scan_cmd( ser_obj, pdev, vdev, cmd, - cmd_type, false); + cmd_type, false, cmd_attr); } if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST && @@ -894,38 +897,44 @@ wlan_serialization_find_and_cancel_cmd( /* remove scan cmd which matches the given cmd struct */ status = wlan_serialization_cmd_cancel_handler( ser_obj, cmd, NULL, NULL, - WLAN_SER_CMD_SCAN, queue_type); + WLAN_SER_CMD_SCAN, queue_type, + WLAN_SER_CMD_ATTR_NONE); break; case WLAN_SER_CANCEL_PDEV_SCANS: /* remove all scan cmds which matches the pdev object */ status = wlan_serialization_cmd_cancel_handler( ser_obj, NULL, pdev, NULL, - WLAN_SER_CMD_SCAN, queue_type); + WLAN_SER_CMD_SCAN, queue_type, + WLAN_SER_CMD_ATTR_NONE); break; case WLAN_SER_CANCEL_VDEV_SCANS: case WLAN_SER_CANCEL_VDEV_HOST_SCANS: /* remove all scan cmds which matches the vdev object */ status = wlan_serialization_cmd_cancel_handler( ser_obj, NULL, NULL, cmd->vdev, - WLAN_SER_CMD_SCAN, queue_type); + WLAN_SER_CMD_SCAN, queue_type, + WLAN_SER_CMD_ATTR_NONE); break; case WLAN_SER_CANCEL_NON_SCAN_CMD: /* remove nonscan cmd which matches the given cmd */ status = wlan_serialization_cmd_cancel_handler( ser_obj, cmd, NULL, NULL, - WLAN_SER_CMD_NONSCAN, queue_type); + WLAN_SER_CMD_NONSCAN, queue_type, + WLAN_SER_CMD_ATTR_NONE); break; case WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD: /* remove all non scan cmds which matches the pdev object */ status = wlan_serialization_cmd_cancel_handler( ser_obj, NULL, pdev, NULL, - WLAN_SER_CMD_NONSCAN, queue_type); + WLAN_SER_CMD_NONSCAN, queue_type, + WLAN_SER_CMD_ATTR_NONE); break; case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD: /* remove all non scan cmds which matches the vdev object */ status = wlan_serialization_cmd_cancel_handler( ser_obj, NULL, NULL, cmd->vdev, - WLAN_SER_CMD_NONSCAN, queue_type); + WLAN_SER_CMD_NONSCAN, queue_type, + WLAN_SER_CMD_ATTR_NONE); break; case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE: /* @@ -934,7 +943,18 @@ wlan_serialization_find_and_cancel_cmd( */ status = wlan_serialization_cmd_cancel_handler( ser_obj, NULL, NULL, cmd->vdev, - cmd->cmd_type, queue_type); + cmd->cmd_type, queue_type, + WLAN_SER_CMD_ATTR_NONE); + break; + case WLAN_SER_CANCEL_VDEV_NON_SCAN_NB_CMD: + /* + * remove all non-blocking non-scan cmds which matches the given + * vdev + */ + status = wlan_serialization_cmd_cancel_handler( + ser_obj, NULL, NULL, cmd->vdev, + WLAN_SER_CMD_NONSCAN, queue_type, + WLAN_SER_CMD_ATTR_NONBLOCK); break; default: ser_err("Invalid request"); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal_i.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal_i.h index 44b6b9b1fb53b4f2c91cbea76292721fbfff6fa3..a1cb902fad3b1afd5089769c86e0e54d8732747d 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal_i.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal_i.h @@ -205,6 +205,7 @@ wlan_serialization_find_and_cancel_cmd( * @vdev: pointer to vdev * @cmd_type: pointer to cmd_type * @queue_type: If active queue or pending queue + * @cmd_attr: Attrbute to indicate a blocking or a non-blocking command * * This API will decide from which queue, command needs to be cancelled * and pass that queue and other parameter required to cancel the command @@ -219,5 +220,6 @@ wlan_serialization_cmd_cancel_handler( struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, enum wlan_serialization_cmd_type cmd_type, - uint8_t queue_type); + uint8_t queue_type, + enum wlan_ser_cmd_attr cmd_attr); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_legacy_api.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_legacy_api.c index 7e237225a86f8287ce5c09a44ba2e8238f3eaaed..1469630d49231fb0a834311bde839de37f4dcfd6 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_legacy_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_legacy_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -77,35 +77,6 @@ wlan_serialization_get_pdev_priv_obj_using_psoc(struct wlan_objmgr_psoc *psoc) return ser_pdev_obj; } -uint32_t wlan_serialization_get_active_list_count( - struct wlan_objmgr_psoc *psoc, - uint8_t is_cmd_from_active_scan_queue) -{ - struct wlan_ser_pdev_obj *ser_pdev_obj; - qdf_list_t *queue; - struct wlan_serialization_pdev_queue *pdev_queue; - uint32_t count; - - ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); - if (!ser_pdev_obj) { - ser_err("invalid ser_pdev_obj"); - return 0; - } - - if (is_cmd_from_active_scan_queue) - pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; - else - pdev_queue = - &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; - - wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); - queue = &pdev_queue->active_list; - count = qdf_list_size(queue); - wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); - - return count; -} - uint32_t wlan_serialization_get_pending_list_count( struct wlan_objmgr_psoc *psoc, uint8_t is_cmd_from_pending_scan_queue) @@ -200,10 +171,8 @@ wlan_serialization_peek_head_pending_cmd_using_psoc( pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; queue = &pdev_queue->pending_list; - if (wlan_serialization_list_empty(queue)) { - ser_err("Empty Queue"); + if (wlan_serialization_list_empty(queue)) goto end; - } wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue( diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_main.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_main.c index 1ae48be7107203924a16e7f37d3ae7e3f428ce66..683d00074434a9219ce7647e25aa18dec536e3b7 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_main.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_main.c @@ -52,11 +52,12 @@ QDF_STATUS wlan_serialization_psoc_disable(struct wlan_objmgr_psoc *psoc) if (status != QDF_STATUS_SUCCESS) ser_err("ser cleanning up all timer failed"); + /* Use lock to free to avoid any race where timer is still in use */ + wlan_serialization_acquire_lock(&ser_soc_obj->timer_lock); qdf_mem_free(ser_soc_obj->timers); ser_soc_obj->timers = NULL; ser_soc_obj->max_active_cmds = 0; - - wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock); + wlan_serialization_release_lock(&ser_soc_obj->timer_lock); error: return status; } @@ -87,7 +88,6 @@ QDF_STATUS wlan_serialization_psoc_enable(struct wlan_objmgr_psoc *psoc) goto error; } - wlan_serialization_create_lock(&ser_soc_obj->timer_lock); status = QDF_STATUS_SUCCESS; error: @@ -127,6 +127,7 @@ static QDF_STATUS wlan_serialization_psoc_create_handler( ser_err("Obj attach failed"); goto error; } + wlan_serialization_create_lock(&soc_ser_obj->timer_lock); ser_debug("ser psoc obj created"); status = QDF_STATUS_SUCCESS; @@ -144,7 +145,6 @@ static void wlan_serialization_destroy_cmd_pool( struct wlan_serialization_pdev_queue *pdev_queue) { qdf_list_node_t *node = NULL; - struct wlan_serialization_command_list *cmd_list; ser_debug("Destroy cmd pool list %pK, size %d", &pdev_queue->cmd_pool_list, @@ -152,8 +152,7 @@ static void wlan_serialization_destroy_cmd_pool( while (!qdf_list_empty(&pdev_queue->cmd_pool_list)) { qdf_list_remove_front(&pdev_queue->cmd_pool_list, &node); - cmd_list = (struct wlan_serialization_command_list *)node; - qdf_mem_free(cmd_list); + qdf_mem_free(node); } qdf_list_destroy(&pdev_queue->cmd_pool_list); @@ -329,6 +328,7 @@ wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc, if (status != QDF_STATUS_SUCCESS) ser_err("ser psoc private obj detach failed"); + wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock); ser_debug("ser psoc obj deleted with status %d", status); qdf_mem_free(ser_soc_obj); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c index 96f587f0e08c1c73125c4110b5bb911b76bcc99d..cd41cb7a6a395201557562705cdbc0285eeb6827 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c @@ -360,6 +360,9 @@ wlan_ser_move_non_scan_pending_to_active( qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION, &active_cmd_list->cmd_in_use); + if (active_cmd_list->cmd.is_blocking) + pdev_queue->blocking_cmd_waiting--; + wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); wlan_serialization_activate_cmd(active_cmd_list, ser_pdev_obj, @@ -367,15 +370,11 @@ wlan_ser_move_non_scan_pending_to_active( wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); - if (vdev_queue_lookup) + if (vdev_queue_lookup || pdev_queue->blocking_cmd_active) break; pending_node = NULL; - if (active_cmd_list->cmd.is_blocking) { - pdev_queue->blocking_cmd_waiting--; - break; - } } wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); @@ -455,7 +454,7 @@ wlan_ser_cancel_non_scan_cmd( struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, struct wlan_serialization_command *cmd, enum wlan_serialization_cmd_type cmd_type, - uint8_t is_active_queue) + uint8_t is_active_queue, enum wlan_ser_cmd_attr cmd_attr) { qdf_list_t *pdev_queue; qdf_list_t *vdev_queue; @@ -532,6 +531,18 @@ wlan_ser_cancel_non_scan_cmd( continue; } + /* + * If a non-blocking cmd is required to be cancelled, but + * the nnode cmd is a blocking cmd then continue with the + * next command in the list else proceed with cmd cancel. + */ + if ((cmd_attr == WLAN_SER_CMD_ATTR_NONBLOCK) && + wlan_serialization_match_cmd_blocking(nnode, + WLAN_SER_PDEV_NODE)) { + pnode = nnode; + continue; + } + /* * active queue can't be removed directly, requester needs to * wait for active command response and send remove request for diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_non_scan_i.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_non_scan_i.h index 5426ae4c5ee17e803ac52c26ef37a2063f6afcc5..d52402bf8efb1b2b723ddc98be46798fcebf9dbb 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_non_scan_i.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_non_scan_i.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 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 @@ -115,6 +115,8 @@ wlan_ser_remove_non_scan_cmd(struct wlan_ser_pdev_obj *ser_pdev_obj, * @cmd_type: Serialization command type to be cancelled * @is_active_queue: If the cmd has to be removed from active queue or pending * queue + * @cmd_attr: Indicate the attribute of the cmd to be cancelled + * i.e blocking/non-blocking * * Return: Status specifying the cancel of a command from the given queue */ @@ -124,5 +126,6 @@ wlan_ser_cancel_non_scan_cmd(struct wlan_ser_pdev_obj *ser_obj, struct wlan_objmgr_vdev *vdev, struct wlan_serialization_command *cmd, enum wlan_serialization_cmd_type cmd_type, - uint8_t is_active_queue); + uint8_t is_active_queue, + enum wlan_ser_cmd_attr cmd_attr); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_utils.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_utils.c index b7c626aa0c516e0002968e9266b5592abfb4de71..4ec739408f03b2c70a2a02ee8a11c0b9f19309fb 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_utils.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_utils.c @@ -157,9 +157,26 @@ QDF_STATUS wlan_serialization_cleanup_vdev_timers( struct wlan_serialization_timer *ser_timer; QDF_STATUS status = QDF_STATUS_SUCCESS; uint32_t i = 0; + struct wlan_objmgr_pdev *pdev = NULL; + struct wlan_objmgr_psoc *psoc = NULL; + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) { + QDF_BUG(0); + ser_err("pdev is null"); + status = QDF_STATUS_E_FAILURE; + goto error; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + QDF_BUG(0); + ser_err("psoc is null"); + status = QDF_STATUS_E_FAILURE; + goto error; + } - psoc_ser_obj = wlan_serialization_get_psoc_obj( - wlan_vdev_get_psoc(vdev)); + psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc); if (!psoc_ser_obj) { ser_err("Invalid psoc_ser_obj"); @@ -462,7 +479,7 @@ wlan_serialization_remove_cmd_from_queue( goto error; if (!queue || wlan_serialization_list_empty(queue)) { - ser_err("Empty queue"); + ser_debug("Empty queue"); goto error; } @@ -757,6 +774,30 @@ bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode, return match_found; } +bool wlan_serialization_match_cmd_blocking( + qdf_list_node_t *nnode, + enum wlan_serialization_node node_type) +{ + struct wlan_serialization_command_list *cmd_list = NULL; + bool match_found = false; + + if (node_type == WLAN_SER_PDEV_NODE) + cmd_list = + qdf_container_of(nnode, + struct wlan_serialization_command_list, + pdev_node); + else + cmd_list = + qdf_container_of(nnode, + struct wlan_serialization_command_list, + vdev_node); + + if (cmd_list->cmd.is_blocking) + match_found = true; + + return match_found; +} + qdf_list_node_t * wlan_serialization_find_cmd(qdf_list_t *queue, enum wlan_serialization_match_type match_type, diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h index 61e5348dfc975a48f24098a87e8f5024a6ffc0e9..a7bc208aad7daa94e6158b9401fa970dbe0d1e74 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h @@ -546,6 +546,19 @@ bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode, struct wlan_objmgr_pdev *pdev, enum wlan_serialization_node node_type); +/** + * wlan_serialization_match_cmd_blocking() - Check for a blocking cmd + * @nnode: The node on which the matching has to be done + * @node_type: Pdev node or vdev node + * + * This API will check if the give command of nnode is a blocking command. + * + * Return: True if blocking command, false otherwise. + */ +bool wlan_serialization_match_cmd_blocking( + qdf_list_node_t *nnode, + enum wlan_serialization_node node_type); + /** * wlan_serialization_find_cmd() - Find the cmd matching the given criterias * @cmd: Serialization command information diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/sm_engine/inc/wlan_sm_engine_dbg.h b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/sm_engine/inc/wlan_sm_engine_dbg.h index 512b860532c206fbb9f1737e42fcc4ca99106f2e..9edb7eb03a9fc033feacc4974daabc8be170e6fa 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/sm_engine/inc/wlan_sm_engine_dbg.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/sm_engine/inc/wlan_sm_engine_dbg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 @@ -137,6 +137,18 @@ void wlan_sm_history_delete(struct wlan_sm *sm); */ void wlan_sm_print_history(struct wlan_sm *sm); +#if SM_HIST_DEBUGFS_SUPPORT +/** + * wlan_sm_print_fs_history() - API to print SM history in proc + * @sm: state machine handle + * @m: debug fs file handle + * + * Prints SM history through proc + * + * Return: void + */ +void wlan_sm_print_fs_history(struct wlan_sm *sm, qdf_debugfs_file_t m); +#endif #else /* SM_ENG_HIST_ENABLE */ /** diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/sm_engine/src/wlan_sm_engine_dbg.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/sm_engine/src/wlan_sm_engine_dbg.c index 3676d0c706500b6a84fc1a2eb8a5de12aa7c8a90..b21ee4cc6cbf8de1710e671341e59d7b3ff23fdb 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/sm_engine/src/wlan_sm_engine_dbg.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/sm_engine/src/wlan_sm_engine_dbg.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 above @@ -116,3 +116,63 @@ void wlan_sm_print_history(struct wlan_sm *sm) qdf_spin_unlock_bh(&p_sm_history->sm_history_lock); } + +#if SM_HIST_DEBUGFS_SUPPORT +static void wlan_sm_print_fs_history_entry(struct wlan_sm *sm, + struct wlan_sm_history_info *ent, + uint16_t i, qdf_debugfs_file_t m) +{ + const char *event_name = NULL; + + if (sm->event_names) { + if (ent->event_type < sm->num_event_names) + event_name = sm->event_names[ent->event_type]; + + if (!ent->trace_type) + return; + + qdf_debugfs_printf(m, + "|%6d |%11d |%23s[%3d] |%19s[%2d] |%19s[%2d] |\n", + i, ent->trace_type, + event_name ? event_name : "UNKNOWN_EVENT", + ent->event_type, + sm->state_info[ent->initial_state].name, + ent->initial_state, + sm->state_info[ent->final_state].name, + ent->final_state); + } else { + qdf_debugfs_printf(m, + "|%6d |%11d |%28d |%19s[%2d] |%19s[%2d] |\n", + i, ent->trace_type, + ent->event_type, + sm->state_info[ent->initial_state].name, + ent->initial_state, + sm->state_info[ent->final_state].name, + ent->final_state); + } +} + +void wlan_sm_print_fs_history(struct wlan_sm *sm, qdf_debugfs_file_t m) +{ + struct wlan_sm_history *p_sm_history = &sm->history; + uint8_t i; + uint8_t idx; + + /* + * History saved in circular buffer. + * Save a pointer to next write location and increment pointer. + */ + qdf_spin_lock_bh(&p_sm_history->sm_history_lock); + qdf_debugfs_printf(m, "|%6s |%11s |%28s |%23s |%23s |\n", "Index", + "Trace Type", "Event", + "Initial State", "Final State"); + + for (i = 0; i < WLAN_SM_ENGINE_HISTORY_SIZE; i++) { + idx = (p_sm_history->index + i) % WLAN_SM_ENGINE_HISTORY_SIZE; + wlan_sm_print_fs_history_entry(sm, &p_sm_history->data[idx], + idx, m); + } + + qdf_spin_unlock_bh(&p_sm_history->sm_history_lock); +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/utils/src/wlan_utility.c b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/utils/src/wlan_utility.c index 5bab3e124d4da9d382d540a5276b62fc057b451b..c82001afd5944381360e248d33b32627d2b061f4 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/utils/src/wlan_utility.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cmn_services/utils/src/wlan_utility.c @@ -28,7 +28,9 @@ uint32_t wlan_chan_to_freq(uint8_t chan) { - /* ch 0 - ch 13 */ + if (chan == 0 ) + return 0; + if (chan < WLAN_24_GHZ_CHANNEL_14) return WLAN_24_GHZ_BASE_FREQ + chan * WLAN_CHAN_SPACING_5MHZ; else if (chan == WLAN_24_GHZ_CHANNEL_14) @@ -47,6 +49,9 @@ uint8_t wlan_freq_to_chan(uint32_t freq) { uint8_t chan; + if (freq == 0) + return 0; + if (freq > WLAN_24_GHZ_BASE_FREQ && freq < WLAN_CHAN_14_FREQ) chan = ((freq - WLAN_24_GHZ_BASE_FREQ) / WLAN_CHAN_SPACING_5MHZ); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/coex/core/inc/wlan_coex_main.h b/drivers/staging/qca-wifi-host-cmn/umac/coex/core/inc/wlan_coex_main.h new file mode 100644 index 0000000000000000000000000000000000000000..22cde21af03fe1fd2f10c639307a7b3fb3b9324b --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/coex/core/inc/wlan_coex_main.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * DOC: contains declarations for coex core functions + */ + +#ifndef _WLAN_COEX_MAIN_API_H_ +#define _WLAN_COEX_MAIN_API_H_ + +#ifdef FEATURE_COEX +#include "wlan_coex_ucfg_api.h" +#include "wmi_unified_param.h" +#include "wlan_objmgr_psoc_obj.h" +#include "wlan_objmgr_vdev_obj.h" + +#define coex_err(params...) \ + QDF_TRACE_ERROR(QDF_MODULE_ID_COEX, params) +#define coex_info(params...) \ + QDF_TRACE_INFO(QDF_MODULE_ID_COEX, params) +#define coex_debug(params...) \ + QDF_TRACE_DEBUG(QDF_MODULE_ID_COEX, params) + +/** + * struct coex_psoc_obj - coex object definition + * @btc_chain_mode: BT Coex chain mode. + * @coex_config_updated: callback functions for each config type, which will + * be called when config is updated. + */ +struct coex_psoc_obj { + uint8_t btc_chain_mode; + update_coex_cb coex_config_updated[COEX_CONFIG_TYPE_MAX]; +}; + +/** + * wlan_psoc_get_coex_obj() - private API to get coex object from psoc + * @psoc: psoc object + * + * Return: coex object + */ +#define wlan_psoc_get_coex_obj(psoc) \ + wlan_psoc_get_coex_obj_fl(psoc, __func__, __LINE__) + +static inline struct coex_psoc_obj * +wlan_psoc_get_coex_obj_fl(struct wlan_objmgr_psoc *psoc, + const char *func, uint32_t line) +{ + struct coex_psoc_obj *psoc_obj; + + psoc_obj = (struct coex_psoc_obj *) + wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_COEX); + if (!psoc_obj) { + coex_err("%s:%u, Failed to get coex psoc object", func, line); + return NULL; + } + return psoc_obj; +} + +/** + * wlan_coex_psoc_init() - API to initialize coex component + * @psoc: soc context + * + * Return: QDF_STATUS + */ +QDF_STATUS +wlan_coex_psoc_init(struct wlan_objmgr_psoc *psoc); + +/** + * wlan_coex_psoc_deinit() - API to deinitialize coex component + * @psoc: soc context + * + * Return: QDF_STATUS + */ +QDF_STATUS +wlan_coex_psoc_deinit(struct wlan_objmgr_psoc *psoc); + +/** + * wlan_coex_config_send() - private API to send coex config + * @vdev: pointer to vdev object + * @param: parameters of coex config + * + * Return: status of operation + */ +QDF_STATUS wlan_coex_config_send(struct wlan_objmgr_vdev *vdev, + struct coex_config_params *param); + +/** + * wlan_coex_config_updated() - private API to notify that coex config + * is updated. + * @vdev: pointer to vdev object + * @type: type of coex config + * + * Return: status of operation + */ +QDF_STATUS +wlan_coex_config_updated(struct wlan_objmgr_vdev *vdev, uint8_t type); + +/** + * wlan_coex_psoc_created_notification() - PSOC obj create callback + * @psoc: PSOC object + * @arg_list: Variable argument list + * + * This callback is registered with object manager during initialization to + * get notified when the object is created. + * + * Return: Success or Failure + */ +QDF_STATUS wlan_coex_psoc_created_notification(struct wlan_objmgr_psoc *psoc, + void *arg_list); + +/** + * wlan_coex_psoc_destroyed_notification() - PSOC obj delete callback + * @psoc: PSOC object + * @arg_list: Variable argument list + * + * This callback is registered with object manager during initialization to + * get notified when the object is deleted. + * + * Return: Success or Failure + */ +QDF_STATUS wlan_coex_psoc_destroyed_notification(struct wlan_objmgr_psoc *psoc, + void *arg_list); + +/** + * wlan_coex_psoc_set_btc_chain_mode() - private API to set BT coex chain mode + * for psoc + * @psoc: pointer to psoc object + * @val: BT coex chain mode + * + * Return : status of operation + */ +QDF_STATUS +wlan_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val); + +/** + * wlan_coex_psoc_get_btc_chain_mode() - private API to get BT coex chain mode + * from psoc + * @psoc: pointer to psoc object + * @val: pointer to BT coex chain mode + * + * Return : status of operation + */ +QDF_STATUS +wlan_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val); +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/coex/core/src/wlan_coex_main.c b/drivers/staging/qca-wifi-host-cmn/umac/coex/core/src/wlan_coex_main.c new file mode 100644 index 0000000000000000000000000000000000000000..d48b6e54eba229245d28acd55d5e4af61288b75e --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/coex/core/src/wlan_coex_main.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * DOC: contains definitions for coex core functions + */ + +#include +#include +#include + +QDF_STATUS wlan_coex_psoc_created_notification(struct wlan_objmgr_psoc *psoc, + void *arg_list) +{ + struct coex_psoc_obj *psoc_obj; + QDF_STATUS status; + + psoc_obj = qdf_mem_malloc(sizeof(*psoc_obj)); + if (!psoc_obj) + return QDF_STATUS_E_NOMEM; + + /* Attach scan private date to psoc */ + status = wlan_objmgr_psoc_component_obj_attach(psoc, + WLAN_UMAC_COMP_COEX, + psoc_obj, + QDF_STATUS_SUCCESS); + if (QDF_IS_STATUS_ERROR(status)) { + coex_err("Failed to attach psoc coex component"); + qdf_mem_free(psoc_obj); + } else { + coex_debug("Coex object attach to psoc successful"); + } + + return status; +} + +QDF_STATUS wlan_coex_psoc_destroyed_notification(struct wlan_objmgr_psoc *psoc, + void *arg_list) +{ + void *psoc_obj; + QDF_STATUS status; + + psoc_obj = wlan_psoc_get_coex_obj(psoc); + if (!psoc_obj) + return QDF_STATUS_E_FAILURE; + + status = wlan_objmgr_psoc_component_obj_detach(psoc, + WLAN_UMAC_COMP_COEX, + psoc_obj); + if (QDF_IS_STATUS_ERROR(status)) + coex_err("Failed to detach psoc coex component"); + + qdf_mem_free(psoc_obj); + + return status; +} + +QDF_STATUS +wlan_coex_psoc_init(struct wlan_objmgr_psoc *psoc) +{ + struct coex_psoc_obj *coex_obj; + + coex_obj = wlan_psoc_get_coex_obj(psoc); + if (!coex_obj) + return QDF_STATUS_E_INVAL; + + coex_obj->btc_chain_mode = WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED; + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_coex_psoc_deinit(struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_coex_config_send(struct wlan_objmgr_vdev *vdev, + struct coex_config_params *param) +{ + QDF_STATUS status; + + status = tgt_send_coex_config(vdev, param); + if (QDF_IS_STATUS_ERROR(status)) + coex_err("failed to send coex config"); + + return status; +} + +QDF_STATUS +wlan_coex_config_updated(struct wlan_objmgr_vdev *vdev, uint8_t type) +{ + struct wlan_objmgr_psoc *psoc; + struct coex_psoc_obj *coex_obj; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (!vdev) { + coex_err("NULL vdev"); + return QDF_STATUS_E_INVAL; + } + + if (type >= COEX_CONFIG_TYPE_MAX) { + coex_err("config type out of range: %d", type); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + coex_err("NULL psoc"); + return QDF_STATUS_E_INVAL; + } + + coex_obj = wlan_psoc_get_coex_obj(psoc); + if (!coex_obj) + return QDF_STATUS_E_INVAL; + + if (coex_obj->coex_config_updated[type]) + status = coex_obj->coex_config_updated[type](vdev); + + return status; +} + +QDF_STATUS +wlan_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val) +{ + struct coex_psoc_obj *coex_obj; + + coex_obj = wlan_psoc_get_coex_obj(psoc); + if (!coex_obj) + return QDF_STATUS_E_INVAL; + + coex_obj->btc_chain_mode = val; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val) +{ + struct coex_psoc_obj *coex_obj; + + if (!val) { + coex_err("invalid param for getting btc chain mode"); + return QDF_STATUS_E_INVAL; + } + + coex_obj = wlan_psoc_get_coex_obj(psoc); + if (!coex_obj) + return QDF_STATUS_E_INVAL; + + *val = coex_obj->btc_chain_mode; + return QDF_STATUS_SUCCESS; +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/inc/wlan_coex_tgt_api.h b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/inc/wlan_coex_tgt_api.h new file mode 100644 index 0000000000000000000000000000000000000000..452ce1bc6c1d31d081a4ad295bb9c69a1042eb7c --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/inc/wlan_coex_tgt_api.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * DOC: contains coex south bound interface definitions + */ + +#ifndef _WLAN_COEX_TGT_API_H_ +#define _WLAN_COEX_TGT_API_H_ + +#ifdef FEATURE_COEX +struct coex_config_params; + +/** + * tgt_send_coex_config() - invoke target_if send coex config + * @vdev: vdev object + * @param: coex config parameters + * + * Return: QDF_STATUS + */ +QDF_STATUS +tgt_send_coex_config(struct wlan_objmgr_vdev *vdev, + struct coex_config_params *param); +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/inc/wlan_coex_ucfg_api.h b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/inc/wlan_coex_ucfg_api.h new file mode 100644 index 0000000000000000000000000000000000000000..2fd5a24230bfe0dca64907426e0ba087b63cecf4 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/inc/wlan_coex_ucfg_api.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * DOC: contains coex north bound interface declarations + */ + +#ifndef _WLAN_COEX_UCFG_API_H_ +#define _WLAN_COEX_UCFG_API_H_ + +#include "qdf_status.h" +#include +#include +#include "qca_vendor.h" + +#define WLAN_COEX_BTC_CHAIN_MODE_SHARED QCA_BTC_CHAIN_SHARED +#define WLAN_COEX_BTC_CHAIN_MODE_SEPARATED QCA_BTC_CHAIN_SEPARATED +#define WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED 0xFF + +/** + * enum coex_config_type - coex config type definitions + * @COEX_CONFIG_BTC_CHAIN_MODE: config BT coex chain mode + * @COEX_CONFIG_TYPE_MAX: max value + */ +enum coex_config_type { + COEX_CONFIG_BTC_CHAIN_MODE, + /* keep last */ + COEX_CONFIG_TYPE_MAX, +}; + +/** + * typedef update_coex_cb() - cb to inform coex config + * @vdev: vdev pointer + * + * Return: void + */ +typedef QDF_STATUS (*update_coex_cb)(struct wlan_objmgr_vdev *vdev); + +#ifdef FEATURE_COEX +/** + * ucfg_coex_register_cfg_updated_handler() - API to register coex config + * updated handler. + * @psoc: pointer to psoc object + * @type: type of coex config + * @handler: handler to be registered + * + * Return: status of operation + */ +QDF_STATUS +ucfg_coex_register_cfg_updated_handler(struct wlan_objmgr_psoc *psoc, + enum coex_config_type type, + update_coex_cb handler); + +/** + * ucfg_coex_psoc_set_btc_chain_mode() - API to set BT coex chain mode for psoc + * @psoc: pointer to psoc object + * @val: BT coex chain mode + * + * Return : status of operation + */ +QDF_STATUS +ucfg_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val); + +/** + * ucfg_coex_psoc_get_btc_chain_mode() - API to get BT coex chain mode from psoc + * @psoc: pointer to psoc object + * @val: pointer to BT coex chain mode + * + * Return : status of operation + */ +QDF_STATUS +ucfg_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val); + +/** + * ucfg_coex_send_btc_chain_mode() - API to send BT coex config to target if + * @vdev: pointer to vdev object + * @mode: BT coex chain mode + * + * Return: status of operation + */ +QDF_STATUS +ucfg_coex_send_btc_chain_mode(struct wlan_objmgr_vdev *vdev, uint8_t mode); +#else +static inline QDF_STATUS +ucfg_coex_register_cfg_updated_handler(struct wlan_objmgr_psoc *psoc, + enum coex_config_type type, + update_coex_cb handler) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS +ucfg_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val) +{ + if (val) + *val = WLAN_COEX_BTC_CHAIN_MODE_UNSETTLED; + + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS +ucfg_coex_send_btc_chain_mode(struct wlan_objmgr_vdev *vdev, uint8_t mode) +{ + return QDF_STATUS_SUCCESS; +} +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/inc/wlan_coex_utils_api.h b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/inc/wlan_coex_utils_api.h new file mode 100644 index 0000000000000000000000000000000000000000..76bb68d495848aaa973ddd5688d759574006b677 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/inc/wlan_coex_utils_api.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_coex_utils_api.h + * + * This header file provides declaration of public APIs exposed to other UMAC + * components. + */ + +#ifndef _WLAN_COEX_UTILS_API_H_ +#define _WLAN_COEX_UTILS_API_H_ +#include + +/* + * wlan_coex_init() - Coex module initialization API + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_coex_init(void); + +/* + * wlan_coex_deinit() - Coex module deinitialization API + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_coex_deinit(void); + +/** + * wlan_coex_psoc_open() - Open coex component + * @psoc: soc context + * + * This function gets called when dispatcher opening. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS +wlan_coex_psoc_open(struct wlan_objmgr_psoc *psoc); + +/** + * wlan_coex_psoc_close() - Close coex component + * @psoc: soc context + * + * This function gets called when dispatcher closing. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS +wlan_coex_psoc_close(struct wlan_objmgr_psoc *psoc); +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/src/wlan_coex_tgt_api.c b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/src/wlan_coex_tgt_api.c new file mode 100644 index 0000000000000000000000000000000000000000..4022a7c13eb5a9f2be0e75b7d0bbdc47da6dd42e --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/src/wlan_coex_tgt_api.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * DOC: contains coex south bound interface definitions + */ + +#include +#include +#include +#include "wlan_objmgr_pdev_obj.h" + +static inline struct wlan_lmac_if_coex_tx_ops * +wlan_psoc_get_coex_txops(struct wlan_objmgr_psoc *psoc) +{ + return &psoc->soc_cb.tx_ops.coex_ops; +} + +static inline struct wlan_lmac_if_coex_tx_ops * +wlan_vdev_get_coex_txops(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + coex_err("NULL psoc"); + return NULL; + } + + return wlan_psoc_get_coex_txops(psoc); +} + +QDF_STATUS +tgt_send_coex_config(struct wlan_objmgr_vdev *vdev, + struct coex_config_params *param) +{ + struct wlan_lmac_if_coex_tx_ops *coex_ops; + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + + if (!vdev) { + coex_err("NULL vdev"); + return QDF_STATUS_E_NULL_VALUE; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + coex_err("NULL psoc"); + return QDF_STATUS_E_NULL_VALUE; + } + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) { + coex_err("NULL pdev"); + return QDF_STATUS_E_NULL_VALUE; + } + + coex_ops = wlan_psoc_get_coex_txops(psoc); + QDF_ASSERT(coex_ops->coex_config_send); + if (coex_ops->coex_config_send) + return coex_ops->coex_config_send(pdev, param); + + return QDF_STATUS_SUCCESS; +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/src/wlan_coex_ucfg_api.c b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/src/wlan_coex_ucfg_api.c new file mode 100644 index 0000000000000000000000000000000000000000..68321ee4c1f557245235a74f28d5e9514c1884f1 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/src/wlan_coex_ucfg_api.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * DOC: contains coex north bound interface definitions + */ + +#include +#include +#include "wmi_unified.h" + +QDF_STATUS +ucfg_coex_register_cfg_updated_handler(struct wlan_objmgr_psoc *psoc, + enum coex_config_type type, + update_coex_cb handler) +{ + struct coex_psoc_obj *coex_obj; + + if (type >= COEX_CONFIG_TYPE_MAX) { + coex_err("invalid coex type: %d", type); + return QDF_STATUS_E_INVAL; + } + + coex_obj = wlan_psoc_get_coex_obj(psoc); + if (!coex_obj) + return QDF_STATUS_E_INVAL; + + coex_obj->coex_config_updated[type] = handler; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +ucfg_coex_psoc_set_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t val) +{ + return wlan_coex_psoc_set_btc_chain_mode(psoc, val); +} + +QDF_STATUS +ucfg_coex_psoc_get_btc_chain_mode(struct wlan_objmgr_psoc *psoc, uint8_t *val) +{ + return wlan_coex_psoc_get_btc_chain_mode(psoc, val); +} + +QDF_STATUS +ucfg_coex_send_btc_chain_mode(struct wlan_objmgr_vdev *vdev, uint8_t mode) +{ + struct coex_config_params param = {0}; + + if (mode != WLAN_COEX_BTC_CHAIN_MODE_SHARED && + mode != WLAN_COEX_BTC_CHAIN_MODE_SEPARATED) + return QDF_STATUS_E_INVAL; + + param.vdev_id = wlan_vdev_get_id(vdev); + param.config_type = WMI_COEX_CONFIG_BTCOEX_SEPARATE_CHAIN_MODE; + param.config_arg1 = mode; + + coex_debug("send btc chain mode %d for vdev %d", mode, param.vdev_id); + + return wlan_coex_config_send(vdev, ¶m); +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/src/wlan_coex_utils_api.c b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/src/wlan_coex_utils_api.c new file mode 100644 index 0000000000000000000000000000000000000000..32178781bac0b16a280e74efc99d5bda0706f8cb --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/coex/dispatcher/src/wlan_coex_utils_api.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_coex_utils_api.c + * + * This file provides definitions of public APIs exposed to other UMAC + * components. + */ + +#include +#include +#include + +QDF_STATUS wlan_coex_init(void) +{ + QDF_STATUS status; + + status = wlan_objmgr_register_psoc_create_handler( + WLAN_UMAC_COMP_COEX, + wlan_coex_psoc_created_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) { + coex_err("Failed to register psoc create handler"); + goto fail_create_psoc; + } + + status = wlan_objmgr_register_psoc_destroy_handler( + WLAN_UMAC_COMP_COEX, + wlan_coex_psoc_destroyed_notification, NULL); + if (QDF_IS_STATUS_ERROR(status)) { + coex_err("Failed to create psoc delete handler"); + goto fail_psoc_destroy; + } + + coex_debug("coex psoc create and delete handler registered"); + return status; + +fail_psoc_destroy: + wlan_objmgr_unregister_psoc_create_handler( + WLAN_UMAC_COMP_COEX, + wlan_coex_psoc_created_notification, NULL); +fail_create_psoc: + return status; +} + +QDF_STATUS wlan_coex_deinit(void) +{ + QDF_STATUS status; + + status = wlan_objmgr_unregister_psoc_destroy_handler( + WLAN_UMAC_COMP_COEX, + wlan_coex_psoc_destroyed_notification, NULL); + if (status != QDF_STATUS_SUCCESS) + coex_err("Failed to unregister psoc delete handler"); + + status = wlan_objmgr_unregister_psoc_create_handler( + WLAN_UMAC_COMP_COEX, + wlan_coex_psoc_created_notification, NULL); + if (status != QDF_STATUS_SUCCESS) + coex_err("Failed to unregister psoc create handler"); + + return status; +} + +QDF_STATUS +wlan_coex_psoc_open(struct wlan_objmgr_psoc *psoc) +{ + return wlan_coex_psoc_init(psoc); +} + +QDF_STATUS +wlan_coex_psoc_close(struct wlan_objmgr_psoc *psoc) +{ + return wlan_coex_psoc_deinit(psoc); +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/core/src/wlan_cp_stats_defs.h b/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/core/src/wlan_cp_stats_defs.h index 9d0dd0e8dc11172b616094615dbe8e3faa7aad41..762cdfe70b34ea6096ac7e0d6399e9db4d2cf72c 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/core/src/wlan_cp_stats_defs.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/core/src/wlan_cp_stats_defs.h @@ -35,6 +35,7 @@ #include #include "wlan_cp_stats_cmn_defs.h" #include +#include /* noise floor */ #define CP_STATS_TGT_NOISE_FLOOR_DBM (-96) @@ -54,7 +55,7 @@ struct psoc_cp_stats { void *psoc_comp_priv_obj[WLAN_CP_STATS_MAX_COMPONENTS]; qdf_spinlock_t psoc_cp_stats_lock; struct psoc_cmn_cp_stats *cmn_stats; - void *obj_stats; + psoc_ext_cp_stats_t *obj_stats; void (*legacy_stats_cb)(void *stats); }; @@ -67,7 +68,7 @@ struct psoc_cp_stats { */ struct pdev_cp_stats { struct wlan_objmgr_pdev *pdev_obj; - void *pdev_stats; + pdev_ext_cp_stats_t *pdev_stats; void *pdev_comp_priv_obj[WLAN_CP_STATS_MAX_COMPONENTS]; qdf_spinlock_t pdev_cp_stats_lock; }; @@ -80,8 +81,8 @@ struct pdev_cp_stats { * @vdev_cp_stats_lock: lock to protect object */ struct vdev_cp_stats { - struct wlan_objmgr_vdev *vdev_obj; - void *vdev_stats; + struct wlan_objmgr_vdev *vdev_obj; + vdev_ext_cp_stats_t *vdev_stats; void *vdev_comp_priv_obj[WLAN_CP_STATS_MAX_COMPONENTS]; qdf_spinlock_t vdev_cp_stats_lock; }; @@ -90,14 +91,12 @@ struct vdev_cp_stats { * struct peer_cp_stats - defines cp stats at peer object * @peer_obj: pointer to peer * @peer_stats: pointer to ic/mc specific stats - * @peer_adv_stats: pointer to peer adv stats * @peer_comp_priv_obj[]: component's private object pointers * @peer_cp_stats_lock: lock to protect object */ struct peer_cp_stats { - struct wlan_objmgr_peer *peer_obj; - void *peer_stats; - void *peer_adv_stats; + struct wlan_objmgr_peer *peer_obj; + peer_ext_cp_stats_t *peer_stats; void *peer_comp_priv_obj[WLAN_CP_STATS_MAX_COMPONENTS]; qdf_spinlock_t peer_cp_stats_lock; }; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h b/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h index ade2073f00a9f614ae42ab6f058813b73deebfa3..d06ad955d4f2734ea8efca5852acc8445c7276ab 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h @@ -33,6 +33,8 @@ #define MAX_NUM_CHAINS 2 +#define MAX_MIB_STATS 1 + #define IS_MSB_SET(__num) ((__num) & BIT(31)) #define IS_LSB_SET(__num) ((__num) & BIT(0)) @@ -44,11 +46,13 @@ * @TYPE_CONNECTION_TX_POWER: tx power was requested * @TYPE_STATION_STATS: station stats was requested * @TYPE_PEER_STATS: peer stats was requested + * @TYPE_MIB_STATS: MIB stats was requested */ enum stats_req_type { TYPE_CONNECTION_TX_POWER = 0, TYPE_STATION_STATS, TYPE_PEER_STATS, + TYPE_MIB_STATS, TYPE_MAX, }; @@ -65,6 +69,8 @@ enum stats_req_type { * @TX_RATE_HE20: HE 20 rates * @TX_RATE_HE40: HE 40 rates * @TX_RATE_HE80: HE 80 rates + * @TX_RATE_HE160: HE 160 rates + * @TX_RATE_VHT160: VHT 160 rates */ enum tx_rate_info { TX_RATE_LEGACY = 0x1, @@ -78,6 +84,8 @@ enum tx_rate_info { TX_RATE_HE20 = 0x100, TX_RATE_HE40 = 0x200, TX_RATE_HE80 = 0x400, + TX_RATE_HE160 = 0x800, + TX_RATE_VHT160 = 0x1000, }; /** @@ -155,7 +163,8 @@ struct stats_event; /** * struct request_info: details of each request * @cookie: identifier for os_if request - * @callback: callback to process os_if request when response comes. + * @u: unified data type for callback to process tx power/peer rssi/ + * station stats/mib stats request when response comes. * @vdev_id: vdev_id of request * @pdev_id: pdev_id of request * @peer_mac_addr: peer mac address @@ -167,6 +176,8 @@ struct request_info { void (*get_peer_rssi_cb)(struct stats_event *ev, void *cookie); void (*get_station_stats_cb)(struct stats_event *ev, void *cookie); + void (*get_mib_stats_cb)(struct stats_event *ev, + void *cookie); } u; uint32_t vdev_id; uint32_t pdev_id; @@ -289,7 +300,8 @@ struct peer_extd_stats { * @rx_rate: rx rate * @peer_rssi: rssi * @peer_macaddr: mac address - * @peer_extd_stats: Pointer to peer extended stats + * @extd_stats: Pointer to peer extended stats + * @adv_stats: Pointer to peer adv (extd2) stats */ struct peer_mc_cp_stats { uint32_t tx_rate; @@ -297,6 +309,7 @@ struct peer_mc_cp_stats { int8_t peer_rssi; uint8_t peer_macaddr[QDF_MAC_ADDR_SIZE]; struct peer_extd_stats *extd_stats; + struct peer_adv_mc_cp_stats *adv_stats; }; /** @@ -313,6 +326,137 @@ struct peer_adv_mc_cp_stats { uint64_t rx_bytes; }; +#ifdef WLAN_FEATURE_MIB_STATS +/** + * struct dot11_counters - mib group containing attributes that are MAC counters + * @tx_frags: successfully transmitted fragments + * @group_tx_frames: transmitted group addressed frames + * @failed_cnt: MSDUs not transmitted successfully + * @rx_frags: fragments successfully received + * @group_rx_frames: group addressed frames received + * @fcs_error_cnt: FCS errors detected + * @tx_frames: frames successfully transmitted + */ +struct dot11_counters { + uint32_t tx_frags; + uint32_t group_tx_frames; + uint32_t failed_cnt; + uint32_t rx_frags; + uint32_t group_rx_frames; + uint32_t fcs_error_cnt; + uint32_t tx_frames; +}; + +/** + * struct dot11_mac_statistics - mib stats information on the operation of MAC + * @retry_cnt: retries done by mac for successful transmition + * @multi_retry_cnt: multiple retries done before successful transmition + * @frame_dup_cnt: duplicate no of frames + * @rts_success_cnt: number of CTS received (in response to RTS) + * @rts_fail_cnt: number of CTS not received (in response to RTS) + * @tx_ack_fail_cnt: number of ACK not received + */ +struct dot11_mac_statistics { + uint32_t retry_cnt; + uint32_t multi_retry_cnt; + uint32_t frame_dup_cnt; + uint32_t rts_success_cnt; + uint32_t rts_fail_cnt; + uint32_t tx_ack_fail_cnt; +}; + +/** + * dot11_qos_counters - qos mac counters + * @qos_tx_frag_cnt: transmitted QoS fragments + * @qos_failed_cnt: failed Qos fragments + * @qos_retry_cnt: Qos frames transmitted after retransmissions + * @qos_multi_retry_cnt: Qos frames transmitted after more than + * one retransmissions + * @qos_frame_dup_cnt: duplicate frames + * @qos_rts_success_cnt: number of CTS received (in response to RTS) + * @qos_rts_fail_cnt: number of CTS not received (in response to RTS) + * @tx_qos_ack_fail_cnt_up: number of ACK not received + * (in response to Qos frame) + * @qos_rx_frag_cnt: number of received MPDU of type Data + * @qos_tx_frame_cnt: number of transmitted MPDU of type Data + * @qos_discarded_frame_cnt: total Discarded MSDUs + * @qos_mpdu_rx_cnt: total received MPDU + * @qos_retries_rx_cnt: received MPDU with retry bit equal to 1 + */ +struct dot11_qos_counters { + uint32_t qos_tx_frag_cnt; + uint32_t qos_failed_cnt; + uint32_t qos_retry_cnt; + uint32_t qos_multi_retry_cnt; + uint32_t qos_frame_dup_cnt; + uint32_t qos_rts_success_cnt; + uint32_t qos_rts_fail_cnt; + uint32_t tx_qos_ack_fail_cnt_up; + uint32_t qos_rx_frag_cnt; + uint32_t qos_tx_frame_cnt; + uint32_t qos_discarded_frame_cnt; + uint32_t qos_mpdu_rx_cnt; + uint32_t qos_retries_rx_cnt; +}; + +/** + * dot11_rsna_stats - mib rsn stats + * @rm_ccmp_replays: received robust management CCMP MPDUs discarded + * by the replay mechanism + * @tkip_icv_err: TKIP ICV errors encountered + * @tkip_replays: TKIP replay errors detected + * @ccmp_decrypt_err: MPDUs discarded by the CCMP decryption algorithm + * @ccmp_replays: received CCMP MPDUs discarded by the replay mechanism + * @cmac_icv_err: MPDUs discarded by the CMAC integrity check algorithm + * @cmac_replays: MPDUs discarded by the CMAC replay errors + */ +struct dot11_rsna_stats { + uint32_t rm_ccmp_replays; + uint32_t tkip_icv_err; + uint32_t tkip_replays; + uint32_t ccmp_decrypt_err; + uint32_t ccmp_replays; + uint32_t cmac_icv_err; + uint32_t cmac_replays; +}; + +/** + * dot11_counters_group3 - dot11 group3 stats + * @tx_ampdu_cnt: transmitted AMPDUs + * @tx_mpdus_in_ampdu_cnt: number of MPDUs in the A-MPDU in transmitted AMPDUs + * @tx_octets_in_ampdu_cnt: octets in the transmitted A-MPDUs + * @ampdu_rx_cnt: received A-MPDU + * @mpdu_in_rx_ampdu_cnt: MPDUs received in the A-MPDU + * @rx_octets_in_ampdu_cnt: octets in the received A-MPDU + * @rx_ampdu_deli_crc_err_cnt: number of MPDUs delimiter with CRC error + */ +struct dot11_counters_group3 { + uint32_t tx_ampdu_cnt; + uint32_t tx_mpdus_in_ampdu_cnt; + uint64_t tx_octets_in_ampdu_cnt; + uint32_t ampdu_rx_cnt; + uint32_t mpdu_in_rx_ampdu_cnt; + uint64_t rx_octets_in_ampdu_cnt; + uint32_t rx_ampdu_deli_crc_err_cnt; +}; + +/** + * mib_stats_metrics - mib stats counters + * @mib_counters: dot11Counters group + * @mib_mac_statistics: dot11MACStatistics group + * @mib_qos_counters: dot11QoSCounters group + * @mib_rsna_stats: dot11RSNAStats group + * @mib_counters_group3: dot11CountersGroup3 group + */ +struct mib_stats_metrics { + struct dot11_counters mib_counters; + struct dot11_mac_statistics mib_mac_statistics; + struct dot11_qos_counters mib_qos_counters; + struct dot11_rsna_stats mib_rsna_stats; + struct dot11_counters_group3 mib_counters_group3; +}; +#endif + /** * struct congestion_stats_event: congestion stats event param * @vdev_id: vdev_id of the event @@ -356,6 +500,8 @@ struct chain_rssi_event { * @cca_stats: if populated indicates congestion stats * @num_summary_stats: number of summary stats * @vdev_summary_stats: if populated indicates array of summary stats per vdev + * @num_mib_stats: number of mib stats + * @mib_stats: if populated indicates array of mib stats per vdev * @num_chain_rssi_stats: number of chain rssi stats * @vdev_chain_rssi: if populated indicates array of chain rssi per vdev * @tx_rate: tx rate (kbps) @@ -375,6 +521,10 @@ struct stats_event { struct congestion_stats_event *cca_stats; uint32_t num_summary_stats; struct summary_stats_event *vdev_summary_stats; +#ifdef WLAN_FEATURE_MIB_STATS + uint32_t num_mib_stats; + struct mib_stats_metrics *mib_stats; +#endif uint32_t num_chain_rssi_stats; struct chain_rssi_event *vdev_chain_rssi; uint32_t tx_rate; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h b/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h index efbd21e7a6d55947cc6176ee88c860c4436cb89c..3a9247a113f771c570d4c8dd7b70acfc0a5b7163 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/inc/wlan_cp_stats_mc_ucfg_api.h @@ -158,11 +158,17 @@ QDF_STATUS ucfg_mc_cp_stats_set_pending_req(struct wlan_objmgr_psoc *psoc, * ucfg_mc_cp_stats_reset_pending_req() - API to reset pending request * @psoc: pointer to psoc object * @type: request to update + * @last_req: last request + * @pending: pending request present + * + * The function is an atomic operation of "reset" and "get" last request. * * Return: status of operation */ QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc, - enum stats_req_type type); + enum stats_req_type type, + struct request_info *last_req, + bool *pending); /** * ucfg_mc_cp_stats_get_pending_req() - API to get pending request diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c b/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c index dfa70901c7a94ca3642c3ca76b65d3cf92add1b3..8c9d4726ea90019ac8d70d4eba60fa569042536f 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019 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 @@ -69,6 +69,7 @@ static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev = NULL; struct pdev_mc_cp_stats *pdev_mc_stats; struct pdev_cp_stats *pdev_cp_stats_priv; + bool pending = false; if (!ev->pdev_stats) return; @@ -119,8 +120,10 @@ static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc, if (tgt_mc_cp_stats_is_last_event(ev, TYPE_CONNECTION_TX_POWER)) { ucfg_mc_cp_stats_reset_pending_req(psoc, - TYPE_CONNECTION_TX_POWER); - if (last_req.u.get_tx_power_cb) + TYPE_CONNECTION_TX_POWER, + &last_req, + &pending); + if (last_req.u.get_tx_power_cb && pending) last_req.u.get_tx_power_cb(max_pwr, last_req.cookie); } end: @@ -137,8 +140,8 @@ static void peer_rssi_iterator(struct wlan_objmgr_pdev *pdev, struct peer_extd_stats *peer_extd_mc_stats; if (WLAN_PEER_SELF == wlan_peer_get_peer_type(peer)) { - cp_stats_debug("ignore self peer: %pM", - wlan_peer_get_macaddr(peer)); + cp_stats_debug("ignore self peer: "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(wlan_peer_get_macaddr(peer))); return; } @@ -210,7 +213,8 @@ tgt_mc_cp_stats_prepare_raw_peer_rssi(struct wlan_objmgr_psoc *psoc, peer = wlan_objmgr_get_peer(psoc, last_req->pdev_id, mac_addr, WLAN_CP_STATS_ID); if (!peer) { - cp_stats_err("peer[%pM] is null", mac_addr); + cp_stats_err("peer["QDF_MAC_ADDR_FMT"] is null", + QDF_MAC_ADDR_REF(mac_addr)); goto end; } @@ -261,6 +265,7 @@ tgt_mc_cp_stats_update_peer_adv_stats(struct wlan_objmgr_psoc *psoc, { uint8_t *peer_mac_addr; struct wlan_objmgr_peer *peer; + struct peer_mc_cp_stats *peer_mc_stats; struct peer_adv_mc_cp_stats *peer_adv_mc_stats; QDF_STATUS status = QDF_STATUS_SUCCESS; struct peer_cp_stats *peer_cp_stats_priv; @@ -282,7 +287,8 @@ tgt_mc_cp_stats_update_peer_adv_stats(struct wlan_objmgr_psoc *psoc, goto end; } wlan_cp_stats_peer_obj_lock(peer_cp_stats_priv); - peer_adv_mc_stats = peer_cp_stats_priv->peer_adv_stats; + peer_mc_stats = peer_cp_stats_priv->peer_stats; + peer_adv_mc_stats = peer_mc_stats->adv_stats; qdf_mem_copy(peer_adv_mc_stats->peer_macaddr, peer_adv_stats->peer_macaddr, @@ -341,8 +347,9 @@ tgt_mc_cp_stats_update_peer_stats(struct wlan_objmgr_psoc *psoc, peer_mc_stats->rx_rate = peer_stats->rx_rate; if (peer_stats->peer_rssi) peer_mc_stats->peer_rssi = peer_stats->peer_rssi; - cp_stats_nofl_debug("PEER STATS: peer_mac=%pM, tx_rate=%u, rx_rate=%u, peer_rssi=%d", - peer_mc_stats->peer_macaddr, peer_mc_stats->tx_rate, + cp_stats_nofl_debug("PEER STATS: peer_mac="QDF_MAC_ADDR_FMT", tx_rate=%u, rx_rate=%u, peer_rssi=%d", + QDF_MAC_ADDR_REF(peer_mc_stats->peer_macaddr), + peer_mc_stats->tx_rate, peer_mc_stats->rx_rate, peer_mc_stats->peer_rssi); wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv); @@ -400,8 +407,8 @@ tgt_mc_cp_stats_update_peer_extd_stats( peer_extended_stats->rx_mc_bc_cnt; wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv); - cp_stats_debug("peer_mac=%pM, rx_mc_bc_cnt=%u", - peer_extended_stats->peer_macaddr, + cp_stats_debug("peer_mac="QDF_MAC_ADDR_FMT", rx_mc_bc_cnt=%u", + QDF_MAC_ADDR_REF(peer_extended_stats->peer_macaddr), peer_extended_stats->rx_mc_bc_cnt); end: @@ -460,9 +467,9 @@ static void tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc *psoc, uint32_t i; QDF_STATUS status; struct request_info last_req = {0}; + bool pending = false; uint32_t selected; - if (is_station_stats) status = ucfg_mc_cp_stats_get_pending_req(psoc, TYPE_STATION_STATS, @@ -537,11 +544,48 @@ static void tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc *psoc, tgt_mc_cp_stats_extract_peer_extd_stats(psoc, ev); if (tgt_mc_cp_stats_is_last_event(ev, TYPE_PEER_STATS)) { - ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS); - tgt_mc_cp_stats_prepare_raw_peer_rssi(psoc, &last_req); + ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS, + &last_req, &pending); + if (pending && last_req.u.get_peer_rssi_cb) + tgt_mc_cp_stats_prepare_raw_peer_rssi(psoc, &last_req); } } +#ifdef WLAN_FEATURE_MIB_STATS +static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc, + struct stats_event *ev) +{ + QDF_STATUS status; + struct request_info last_req = {0}; + bool pending = false; + + if (!ev->mib_stats) { + cp_stats_debug("no mib stats"); + return; + } + + status = ucfg_mc_cp_stats_get_pending_req(psoc, + TYPE_MIB_STATS, &last_req); + + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed"); + return; + } + + if (tgt_mc_cp_stats_is_last_event(ev, TYPE_MIB_STATS)) { + ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_MIB_STATS, + &last_req, &pending); + if (last_req.u.get_mib_stats_cb && pending) + last_req.u.get_mib_stats_cb(ev, last_req.cookie); + } +} +#else +static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc, + struct stats_event *ev) +{ +} +#endif + static void tgt_mc_cp_stats_extract_cca_stats(struct wlan_objmgr_psoc *psoc, struct stats_event *ev) { @@ -633,7 +677,8 @@ static void tgt_mc_cp_stats_extract_vdev_summary_stats( peer = wlan_objmgr_get_peer(psoc, last_req.pdev_id, last_req.peer_mac_addr, WLAN_CP_STATS_ID); if (!peer) { - cp_stats_debug("peer is null %pM", last_req.peer_mac_addr); + cp_stats_debug("peer is null "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(last_req.peer_mac_addr)); goto end; } @@ -792,11 +837,11 @@ tgt_mc_cp_stats_prepare_n_send_raw_station_stats(struct wlan_objmgr_psoc *psoc, info.tx_rate = peer_mc_stats->tx_rate / 100; info.rx_rate = peer_mc_stats->rx_rate / 100; - if (peer_cp_stats_priv->peer_adv_stats) { + if (peer_mc_stats->adv_stats) { info.num_peer_adv_stats = 1; qdf_mem_copy(info.peer_adv_stats, - peer_cp_stats_priv->peer_adv_stats, - sizeof(peer_cp_stats_priv->peer_adv_stats)); + peer_mc_stats->adv_stats, + sizeof(peer_mc_stats->adv_stats)); } wlan_cp_stats_peer_obj_unlock(peer_cp_stats_priv); @@ -819,6 +864,7 @@ static void tgt_mc_cp_stats_extract_station_stats( { QDF_STATUS status; struct request_info last_req = {0}; + bool pending = false; status = ucfg_mc_cp_stats_get_pending_req(psoc, TYPE_STATION_STATS, @@ -838,9 +884,12 @@ static void tgt_mc_cp_stats_extract_station_stats( * reset type_map bit for station stats . */ if (tgt_mc_cp_stats_is_last_event(ev, TYPE_STATION_STATS)) { - ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_STATION_STATS); - tgt_mc_cp_stats_prepare_n_send_raw_station_stats(psoc, - &last_req); + ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_STATION_STATS, + &last_req, + &pending); + if (pending && last_req.u.get_station_stats_cb) + tgt_mc_cp_stats_prepare_n_send_raw_station_stats( + psoc, &last_req); } } @@ -866,6 +915,9 @@ QDF_STATUS tgt_mc_cp_stats_process_stats_event(struct wlan_objmgr_psoc *psoc, if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_STATION_STATS)) tgt_mc_cp_stats_extract_station_stats(psoc, ev); + if (ucfg_mc_cp_stats_is_req_pending(psoc, TYPE_MIB_STATS)) + tgt_mc_cp_stats_extract_mib_stats(psoc, ev); + tgt_mc_cp_stats_extract_cca_stats(psoc, ev); tgt_mc_cp_send_lost_link_stats(psoc, ev); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c b/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c index f527e6ba07649adcb5f11be927dec07dedbc3eb4..44c517de4c300fc777adea8f1454706b6599011d 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 @@ -90,18 +90,21 @@ QDF_STATUS wlan_cp_stats_peer_cs_init(struct peer_cp_stats *peer_cs) if (!peer_mc_stats) return QDF_STATUS_E_NOMEM; - peer_cs->peer_adv_stats = qdf_mem_malloc(sizeof - (struct peer_adv_mc_cp_stats)); - if (!peer_cs->peer_adv_stats) { + peer_mc_stats->adv_stats = + qdf_mem_malloc(sizeof(struct peer_adv_mc_cp_stats)); + + if (!peer_mc_stats->adv_stats) { qdf_mem_free(peer_mc_stats); + peer_mc_stats = NULL; return QDF_STATUS_E_NOMEM; } peer_mc_stats->extd_stats = qdf_mem_malloc(sizeof(struct peer_extd_stats)); + if (!peer_mc_stats->extd_stats) { - qdf_mem_free(peer_cs->peer_adv_stats); - peer_cs->peer_adv_stats = NULL; + qdf_mem_free(peer_mc_stats->adv_stats); + peer_mc_stats->adv_stats = NULL; qdf_mem_free(peer_mc_stats); peer_mc_stats = NULL; return QDF_STATUS_E_NOMEM; @@ -115,8 +118,8 @@ QDF_STATUS wlan_cp_stats_peer_cs_deinit(struct peer_cp_stats *peer_cs) { struct peer_mc_cp_stats *peer_mc_stats = peer_cs->peer_stats; - qdf_mem_free(peer_cs->peer_adv_stats); - peer_cs->peer_adv_stats = NULL; + qdf_mem_free(peer_mc_stats->adv_stats); + peer_mc_stats->adv_stats = NULL; qdf_mem_free(peer_mc_stats->extd_stats); peer_mc_stats->extd_stats = NULL; qdf_mem_free(peer_cs->peer_stats); @@ -529,7 +532,9 @@ QDF_STATUS ucfg_mc_cp_stats_set_pending_req(struct wlan_objmgr_psoc *psoc, } QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc, - enum stats_req_type type) + enum stats_req_type type, + struct request_info *last_req, + bool *pending) { struct psoc_mc_cp_stats *psoc_mc_stats; struct psoc_cp_stats *psoc_cp_stats_priv; @@ -547,6 +552,12 @@ QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc, wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv); psoc_mc_stats = psoc_cp_stats_priv->obj_stats; + if (psoc_mc_stats->pending.type_map & (1 << type)) { + *last_req = psoc_mc_stats->pending.req[type]; + *pending = true; + } else { + *pending = false; + } psoc_mc_stats->pending.type_map &= ~(1 << type); qdf_mem_zero(&psoc_mc_stats->pending.req[type], sizeof(psoc_mc_stats->pending.req[type])); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs.h index d617adaee23939a2b1025670eb9f1343d8345d2b..24f5a84c959095c4ba0f6b1ea2e2b23d872448fd 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2005-2006 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -29,16 +29,18 @@ #include /* qdf_spinlock */ #include #include +#include /* qdf_str_lcopy */ #include #include "dfs_structs.h" #include "dfs_channel.h" #include "dfs_ioctl_private.h" #include /* For qdf_packed*/ -#include /* For STAILQ_ENTRY */ +#include "queue.h" /* For STAILQ_ENTRY */ #include #include #include +#include /* File Line and Submodule String */ #define FLSM(x, str) #str " : " FL(x) @@ -195,6 +197,12 @@ #define WLAN_DFS_DATA_STRUCT_LOCK_DESTROY(_dfs) \ qdf_spinlock_destroy(&(_dfs)->dfs_data_struct_lock) +/* Wrappers to call MLME radar during mode switch lock. */ +#define DFS_RADAR_MODE_SWITCH_LOCK(_dfs) \ + dfs_mlme_acquire_radar_mode_switch_lock((_dfs)->dfs_pdev_obj) +#define DFS_RADAR_MODE_SWITCH_UNLOCK(_dfs) \ + dfs_mlme_release_radar_mode_switch_lock((_dfs)->dfs_pdev_obj) + /* Mask for time stamp from descriptor */ #define DFS_TSMASK 0xFFFFFFFF /* Shift for time stamp from descriptor */ @@ -319,14 +327,8 @@ #define NUM_BINS 128 #define THOUSAND 1000 -/* ETSI11_WORLD regdmn pair id */ -#define ETSI11_WORLD_REGDMN_PAIR_ID 0x26 -#define ETSI12_WORLD_REGDMN_PAIR_ID 0x28 -#define ETSI13_WORLD_REGDMN_PAIR_ID 0x27 -#define ETSI14_WORLD_REGDMN_PAIR_ID 0x29 - /* Array offset to ETSI legacy pulse */ -#define ETSI_LEGACY_PULSE_ARR_OFFSET 2 +#define ETSI_LEGACY_PULSE_ARR_OFFSET 4 #define ETSI_RADAR_EN302_502_FREQ_LOWER 5725 #define ETSI_RADAR_EN302_502_FREQ_UPPER 5865 @@ -400,6 +402,11 @@ * in host. NOL timer can be configured by user. NOL in FW (for FO) is disabled. */ #define USENOL_ENABLE_NOL_HOST_DISABLE_NOL_FW 2 + +/* Non Agile detector IDs */ +#define DETECTOR_ID_0 0 +#define DETECTOR_ID_1 1 +/* Agile detector ID */ #define AGILE_DETECTOR_ID 2 /** @@ -688,9 +695,14 @@ struct dfs_filtertype { * @dfs_ch_flags: Channel flags. * @dfs_ch_flagext: Extended channel flags. * @dfs_ch_ieee: IEEE channel number. - * @dfs_ch_vhtop_ch_freq_seg1: Channel Center frequency. - * @dfs_ch_vhtop_ch_freq_seg2: Channel Center frequency applicable for 80+80MHz - * mode of operation. + * @dfs_ch_vhtop_ch_freq_seg1: IEEE Channel Center of primary segment + * @dfs_ch_vhtop_ch_freq_seg2: IEEE Channel Center applicable for 80+80MHz + * mode of operation. + * @dfs_ch_mhz_freq_seg1: Channel center frequency of primary segment in + * MHZ. + * @dfs_ch_mhz_freq_seg2: Channel center frequency of secondary segment + * in MHZ applicable only for 80+80MHZ mode of + * operation. */ struct dfs_channel { uint16_t dfs_ch_freq; @@ -699,6 +711,8 @@ struct dfs_channel { uint8_t dfs_ch_ieee; uint8_t dfs_ch_vhtop_ch_freq_seg1; uint8_t dfs_ch_vhtop_ch_freq_seg2; + uint16_t dfs_ch_mhz_freq_seg1; + uint16_t dfs_ch_mhz_freq_seg2; }; /** @@ -724,7 +738,7 @@ struct dfs_state { * @nol_dfs Back pointer to dfs object. * @nol_freq: Centre frequency. * @nol_chwidth: Event width (MHz). - * @nol_start_us: NOL start time in us. + * @nol_start_ticks: NOL start time in OS ticks. * @nol_timeout_ms: NOL timeout value in msec. * @nol_timer: Per element NOL timer. * @nol_next: Next element pointer. @@ -734,7 +748,7 @@ struct dfs_nolelem { struct wlan_dfs *nol_dfs; uint32_t nol_freq; uint32_t nol_chwidth; - uint64_t nol_start_us; + unsigned long nol_start_ticks; uint32_t nol_timeout_ms; qdf_timer_t nol_timer; struct dfs_nolelem *nol_next; @@ -889,6 +903,20 @@ struct dfs_event_log { #define FREQ_OFFSET_BOUNDARY_FOR_80MHZ 40 +/** + * struct dfs_mode_switch_defer_params - Parameters storing DFS information + * before defer, as part of HW mode switch. + * + * @radar_params: Deferred radar parameters. + * @is_cac_completed: Boolean representing CAC completion event. + * @is_radar_detected: Boolean representing radar event. + */ +struct dfs_mode_switch_defer_params { + struct radar_found_info *radar_params; + bool is_cac_completed; + bool is_radar_detected; +}; + /** * struct wlan_dfs - The main dfs structure. * @dfs_debug_mask: Current debug bitmask. @@ -931,14 +959,23 @@ struct dfs_event_log { * received. * @is_radar_during_precac: Radar found during precac. * @dfs_precac_lock: Lock to protect precac lists. - * @dfs_precac_enable: Enable the precac. * @dfs_precac_secondary_freq: Second segment freq for precac. - * @dfs_precac_primary_freq: Primary freq. + * Applicable to only legacy chips. + * @dfs_precac_secondary_freq_mhz: Second segment freq in MHZ for precac. + * Applicable to only legacy chips. + * @dfs_precac_primary_freq: PreCAC Primary freq applicable only to + * legacy chips. + * @dfs_precac_primary_freq_mhz: PreCAC Primary freq in MHZ applicable only + * to legacy chips. * @dfs_defer_precac_channel_change: Defer precac channel change. * @dfs_precac_inter_chan: Intermediate non-DFS channel used while * doing precac. + * @dfs_precac_inter_chan_freq: Intermediate non-DFS freq used while + * doing precac. * @dfs_autoswitch_des_chan: Desired channel which has to be used * after precac. + * @dfs_autoswitch_des_chan_freq: Desired freq which has to be used + * after precac. * @dfs_autoswitch_des_mode: Desired PHY mode which has to be used * after precac. * @dfs_pre_cac_timeout_channel_change: Channel change due to precac timeout. @@ -979,13 +1016,14 @@ struct dfs_event_log { * not be re-done. * @dfs_precac_timeout_override: Overridden precac timeout. * @dfs_num_precac_freqs: Number of PreCAC VHT80 frequencies. - * @dfs_precac_required_list: PreCAC required list. - * @dfs_precac_done_list: PreCAC done list. - * @dfs_precac_nol_list: PreCAC NOL List. + * @dfs_precac_list: PreCAC list (contains individual trees). + * @dfs_precac_chwidth: PreCAC channel width enum. * @dfs_curchan: DFS current channel. + * @dfs_prevchan: DFS previous channel. * @dfs_cac_started_chan: CAC started channel. * @dfs_pdev_obj: DFS pdev object. * @dfs_is_offload_enabled: Set if DFS offload enabled. + * @dfs_agile_precac_freq_mhz: Freq in MHZ configured on Agile DFS engine. * @dfs_use_nol: Use the NOL when radar found(default: TRUE) * @dfs_nol_lock: Lock to protect nol list. * @tx_leakage_threshold: Tx leakage threshold for dfs. @@ -1031,8 +1069,21 @@ struct dfs_event_log { * @dfs_nol_ie_bitmap: The bitmap of radar affected subchannels * in the current channel list * to be sent in NOL IE with RCSA. - * @dfs_is_rcsa_ie_sent To send or to not send RCSA IE. - * @dfs_is_nol_ie_sent To send or to not send NOL IE. + * @dfs_is_rcsa_ie_sent: To send or to not send RCSA IE. + * @dfs_is_nol_ie_sent: To send or to not send NOL IE. + * @dfs_legacy_precac_ucfg: User configuration for legacy preCAC in + * partial offload chipsets. + * @dfs_agile_precac_ucfg: User configuration for agile preCAC. + * @dfs_fw_adfs_support_non_160: Target Agile DFS support for non-160 BWs. + * @dfs_fw_adfs_support_160: Target Agile DFS support for 160 BW. + * @dfs_allow_hw_pulses: Allow/Block HW pulses. When synthetic + * pulses are injected, the HW pulses should + * be blocked and this variable should be + * false so that HW pulses and synthetic + * pulses do not get mixed up. + * defer timer running. + * @dfs_defer_params: DFS deferred event parameters (allocated + * only for the duration of defer alone). */ struct wlan_dfs { uint32_t dfs_debug_mask; @@ -1079,13 +1130,27 @@ struct wlan_dfs { bool is_radar_during_precac; qdf_spinlock_t dfs_precac_lock; bool dfs_precac_enable; +#ifdef CONFIG_CHAN_NUM_API uint8_t dfs_precac_secondary_freq; uint8_t dfs_precac_primary_freq; +#endif +#ifdef CONFIG_CHAN_FREQ_API + uint16_t dfs_precac_secondary_freq_mhz; + uint16_t dfs_precac_primary_freq_mhz; +#endif uint8_t dfs_defer_precac_channel_change; #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +#ifdef CONFIG_CHAN_NUM_API uint8_t dfs_precac_inter_chan; uint8_t dfs_autoswitch_des_chan; +#endif enum wlan_phymode dfs_autoswitch_des_mode; +#endif +#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +#ifdef CONFIG_CHAN_FREQ_API + uint16_t dfs_precac_inter_chan_freq; + uint16_t dfs_autoswitch_des_chan_freq; +#endif #endif uint8_t dfs_pre_cac_timeout_channel_change:1; qdf_timer_t wlan_dfs_task_timer; @@ -1126,22 +1191,22 @@ struct wlan_dfs { #if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD) uint8_t dfs_disable_radar_marking; #endif - TAILQ_HEAD(, dfs_precac_entry) dfs_precac_required_list; - TAILQ_HEAD(, dfs_precac_entry) dfs_precac_done_list; - TAILQ_HEAD(, dfs_precac_entry) dfs_precac_nol_list; - -#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS - TAILQ_HEAD(, dfs_etsi_precac_entry) dfs_etsiprecac_required_list; - TAILQ_HEAD(, dfs_etsi_precac_entry) dfs_etsiprecac_done_list; -#endif + TAILQ_HEAD(, dfs_precac_entry) dfs_precac_list; + enum phy_ch_width dfs_precac_chwidth; struct dfs_channel *dfs_curchan; + struct dfs_channel *dfs_prevchan; struct dfs_channel dfs_cac_started_chan; struct wlan_objmgr_pdev *dfs_pdev_obj; struct dfs_soc_priv_obj *dfs_soc_obj; #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) uint8_t dfs_psoc_idx; +#endif +#ifdef CONFIG_CHAN_NUM_API uint8_t dfs_agile_precac_freq; +#endif +#ifdef CONFIG_CHAN_FREQ_API + uint16_t dfs_agile_precac_freq_mhz; #endif bool dfs_is_offload_enabled; int dfs_use_nol; @@ -1175,7 +1240,14 @@ struct wlan_dfs { uint8_t dfs_nol_ie_bitmap; bool dfs_is_rcsa_ie_sent; bool dfs_is_nol_ie_sent; - bool dfs_agile_precac_enable; + uint8_t dfs_legacy_precac_ucfg:1, + dfs_agile_precac_ucfg:1, + dfs_fw_adfs_support_non_160:1, + dfs_fw_adfs_support_160:1; +#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(WLAN_DFS_SYNTHETIC_RADAR) + bool dfs_allow_hw_pulses; +#endif + struct dfs_mode_switch_defer_params dfs_defer_params; }; #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) @@ -1206,6 +1278,7 @@ struct wlan_dfs_priv { * @dfs_precac_timer: agile precac timer * @dfs_precac_timer_running: precac timer running flag * @ocac_status: Off channel CAC complete status + * @dfs_nol_ctx: dfs NOL data for all radios. */ struct dfs_soc_priv_obj { struct wlan_objmgr_psoc *psoc; @@ -1220,6 +1293,7 @@ struct dfs_soc_priv_obj { bool precac_state_started; bool ocac_status; #endif + struct dfsreq_nolinfo *dfs_psoc_nolinfo; }; /** @@ -1951,9 +2025,23 @@ void dfs_detach(struct wlan_dfs *dfs); * @prevchan_ieee: Prevchan number. * @prevchan_flags: Prevchan flags. */ +#ifdef CONFIG_CHAN_NUM_API void dfs_cac_valid_reset(struct wlan_dfs *dfs, uint8_t prevchan_ieee, uint32_t prevchan_flags); +#endif + +/** + * dfs_cac_valid_reset_for_freq() - Cancels the dfs_cac_valid_timer timer. + * @dfs: Pointer to wlan_dfs structure. + * @prevchan_chan: Prevchan frequency + * @prevchan_flags: Prevchan flags. + */ +#ifdef CONFIG_CHAN_FREQ_API +void dfs_cac_valid_reset_for_freq(struct wlan_dfs *dfs, + uint16_t prevchan_freq, + uint32_t prevchan_flags); +#endif /** * dfs_cac_stop() - Clear the AP CAC timer. @@ -1973,39 +2061,6 @@ void dfs_cancel_cac_timer(struct wlan_dfs *dfs); */ void dfs_start_cac_timer(struct wlan_dfs *dfs); -/** - * dfs_is_subset_channel() - Check if the new_chan is subset of the old_chan. - * @dfs: Pointer to wlan_dfs structure. - * @old_chan: Pointer to old channel. - * @new_chan: Pointer to new channel. - * - * Return: true if the new channel is subset of or same as the old channel, - * else false. - */ -bool dfs_is_subset_channel(struct wlan_dfs *dfs, - struct dfs_channel *old_chan, - struct dfs_channel *new_chan); - -/** - * dfs_is_curchan_subset_of_cac_started_chan() - Check if the dfs current - * channel is subset of cac started channel. - * @dfs: Pointer to wlan_dfs structure. - * - * If the current channel and the cac_started_chan is same or - * if the current channel is subset of the cac_started_chan then - * this function returns true. - * - * Return: true if current channel is same or subset of cac started channel, - * else false. - */ -bool dfs_is_curchan_subset_of_cac_started_chan(struct wlan_dfs *dfs); - -/** - * dfs_clear_cac_started_chan() - Clear dfs cac started channel. - * @dfs: Pointer to wlan_dfs structure. - */ -void dfs_clear_cac_started_chan(struct wlan_dfs *dfs); - /** * dfs_set_update_nol_flag() - Sets update_nol flag. * @dfs: Pointer to wlan_dfs structure. @@ -2160,16 +2215,10 @@ int dfs_get_debug_info(struct wlan_dfs *dfs, void *data); /** - * dfs_cac_timer_init() - Initialize cac timers. + * dfs_cac_timer_attach() - Initialize cac timers. * @dfs: Pointer to wlan_dfs structure. */ -void dfs_cac_timer_init(struct wlan_dfs *dfs); - -/** - * dfs_cac_attach() - Initialize dfs cac variables. - * @dfs: Pointer to wlan_dfs structure. - */ -void dfs_cac_attach(struct wlan_dfs *dfs); +void dfs_cac_timer_attach(struct wlan_dfs *dfs); /** * dfs_cac_timer_reset() - Cancel dfs cac timers. @@ -2345,6 +2394,7 @@ static inline bool dfs_is_en302_502_applicable(struct wlan_dfs *dfs) * @dfs_ch_vhtop_ch_freq_seg1: Channel Center frequency1. * @dfs_ch_vhtop_ch_freq_seg2: Channel Center frequency2. */ +#ifdef CONFIG_CHAN_NUM_API void dfs_set_current_channel(struct wlan_dfs *dfs, uint16_t dfs_ch_freq, uint64_t dfs_ch_flags, @@ -2352,7 +2402,33 @@ void dfs_set_current_channel(struct wlan_dfs *dfs, uint8_t dfs_ch_ieee, uint8_t dfs_ch_vhtop_ch_freq_seg1, uint8_t dfs_ch_vhtop_ch_freq_seg2); +#endif +#ifdef CONFIG_CHAN_FREQ_API +/** + * dfs_set_current_channel_for_freq() - Set DFS current channel. + * @dfs: Pointer to wlan_dfs structure. + * @dfs_chan_freq: Frequency in Mhz. + * @dfs_chan_flags: Channel flags. + * @dfs_chan_flagext: Extended channel flags. + * @dfs_chan_ieee: IEEE channel number. + * @dfs_chan_vhtop_freq_seg1: Channel Center frequency1. + * @dfs_chan_vhtop_freq_seg2: Channel Center frequency2. + * @dfs_chan_mhz_freq_seg1: Channel center frequency of primary segment in MHZ. + * @dfs_chan_mhz_freq_seg2: Channel center frequency of secondary segment in MHZ + * applicable only for 80+80MHZ mode of operation. + */ +void dfs_set_current_channel_for_freq(struct wlan_dfs *dfs, + uint16_t dfs_chan_freq, + uint64_t dfs_chan_flags, + uint16_t dfs_chan_flagext, + uint8_t dfs_chan_ieee, + uint8_t dfs_chan_vhtop_freq_seg1, + uint8_t dfs_chan_vhtop_freq_seg2, + uint16_t dfs_chan_mhz_freq_seg1, + uint16_t dfs_chan_mhz_freq_seg2); + +#endif /** * dfs_get_nol_chfreq_and_chwidth() - Get channel freq and width from NOL list. * @dfs_nol: Pointer to NOL channel entry. @@ -2587,16 +2663,20 @@ bool dfs_process_nol_ie_bitmap(struct wlan_dfs *dfs, uint8_t nol_ie_bandwidth, uint8_t nol_ie_bitmap); /** - * dfs_check_for_cac_start() - Check for DFS CAC start conditions. + * dfs_is_cac_required() - Check if DFS CAC is required for the current channel. * @dfs: Pointer to wlan_dfs structure. + * @cur_chan: Pointer to current channel of dfs_channel structure. + * @prev_chan: Pointer to previous channel of dfs_channel structure. * @continue_current_cac: If AP can start CAC then this variable indicates * whether to continue with the current CAC or restart the CAC. This variable * is valid only if this function returns true. * - * Return: true if AP can start or continue the current CAC, else false. + * Return: true if AP requires CAC or can continue current CAC, else false. */ -bool dfs_check_for_cac_start(struct wlan_dfs *dfs, - bool *continue_current_cac); +bool dfs_is_cac_required(struct wlan_dfs *dfs, + struct dfs_channel *cur_chan, + struct dfs_channel *prev_chan, + bool *continue_current_cac); /** * dfs_task_testtimer_reset() - stop dfs test timer. @@ -2649,4 +2729,103 @@ static inline int dfs_is_disable_radar_marking_set(struct wlan_dfs *dfs, #if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD) bool dfs_get_disable_radar_marking(struct wlan_dfs *dfs); #endif + +/** + * dfs_reset_agile_config() - Reset the ADFS config variables. + * @dfs: Pointer to dfs_soc_priv_obj. + */ +#ifdef QCA_SUPPORT_AGILE_DFS +void dfs_reset_agile_config(struct dfs_soc_priv_obj *dfs_soc); +#endif + +/** + * dfs_reinit_timers() - Reinit timers in DFS. + * @dfs: Pointer to wlan_dfs. + */ +int dfs_reinit_timers(struct wlan_dfs *dfs); + +/** + * dfs_reset_dfs_prevchan() - Reset DFS previous channel structure. + * @dfs: Pointer to wlan_dfs object. + * + * Return: None. + */ +void dfs_reset_dfs_prevchan(struct wlan_dfs *dfs); + +/** + * dfs_init_tmp_psoc_nol() - Init temporary psoc NOL structure. + * @dfs: Pointer to wlan_dfs object. + * @num_radios: Num of radios in the PSOC. + * + * Return: void. + */ +void dfs_init_tmp_psoc_nol(struct wlan_dfs *dfs, uint8_t num_radios); + +/** + * dfs_deinit_tmp_psoc_nol() - De-init temporary psoc NOL structure. + * @dfs: Pointer to wlan_dfs object. + * + * Return: void. + */ +void dfs_deinit_tmp_psoc_nol(struct wlan_dfs *dfs); + +/** + * dfs_save_dfs_nol_in_psoc() - Save NOL data of given pdev. + * @dfs: Pointer to wlan_dfs object. + * @pdev_id: The pdev ID which will have the NOL data. + * @low_5ghz_freq: The low 5GHz frequency value of the target pdev id. + * @high_5ghz_freq: The high 5GHz frequency value of the target pdev id. + * + * Based on the frequency of the NOL channel, copy it to the target pdev_id + * structure in psoc. + * + * Return: void. + */ +void dfs_save_dfs_nol_in_psoc(struct wlan_dfs *dfs, + uint8_t pdev_id, + uint16_t low_5ghz_freq, + uint16_t high_5ghz_freq); + +/** + * dfs_reinit_nol_from_psoc_copy() - Reinit saved NOL data to corresponding + * DFS object. + * @dfs: Pointer to wlan_dfs object. + * @pdev_id: pdev_id of the given dfs object. + * + * Return: void. + */ +void dfs_reinit_nol_from_psoc_copy(struct wlan_dfs *dfs, uint8_t pdev_id); + +/** + * dfs_is_hw_mode_switch_in_progress() - Check if HW mode switch in progress. + * @dfs: Pointer to wlan_dfs object. + * + * Return: True if mode switch is in progress, else false. + */ +bool dfs_is_hw_mode_switch_in_progress(struct wlan_dfs *dfs); + +/** + * dfs_start_mode_switch_defer_timer() - start mode switch defer timer. + * @dfs: Pointer to wlan_dfs object. + * + * Return: void. + */ +void dfs_start_mode_switch_defer_timer(struct wlan_dfs *dfs); + +/** + * dfs_complete_deferred_tasks() - Process mode switch completion event and + * handle deffered tasks. + * @dfs: Pointer to wlan_dfs object. + * + * Return: void. + */ +void dfs_complete_deferred_tasks(struct wlan_dfs *dfs); + +/** + * dfs_process_cac_completion() - Process DFS CAC completion event. + * @dfs: Pointer to wlan_dfs object. + * + * Return: void. + */ +void dfs_process_cac_completion(struct wlan_dfs *dfs); #endif /* _DFS_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_etsi_precac.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_etsi_precac.h deleted file mode 100644 index 59c449b9bd7d1dc2b4e3d1142f2b5245cb23be20..0000000000000000000000000000000000000000 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_etsi_precac.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * DOC: This file has ETSI Pre-CAC DFS APIs. - */ - -#ifndef _DFS_ETSI_PRECAC_H_ -#define _DFS_ETSI_PRECAC_H_ - -#include "dfs.h" - -#define VHT160_IEEE_FREQ_DIFF 16 - -/** - * struct dfs_etsi_precac_entry - PreCAC entry for ETSI domain - * @pe_list: ETSI PreCAC entry. - * @ieee: channel number - * @etsi_caclst_ticks start tick, OS speicfic. - * @dfs: Pointer to wlan_dfs structure. - */ -struct dfs_etsi_precac_entry { - TAILQ_ENTRY(dfs_etsi_precac_entry) pe_list; - uint16_t ieee; - unsigned long etsi_caclst_ticks; - struct wlan_dfs *dfs; -}; - -/** - * dfs_print_etsi_precaclists() - Print etsi precac list. - * @dfs: Pointer to wlan_dfs structure. - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -void dfs_print_etsi_precaclists(struct wlan_dfs *dfs); -#else -static inline void dfs_print_etsi_precaclists(struct wlan_dfs *dfs) -{ -} -#endif - -/** - * dfs_reset_etsi_precac_lists() - Resets the ETSI precac lists. - * @dfs: Pointer to wlan_dfs structure. - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -void dfs_reset_etsi_precac_lists(struct wlan_dfs *dfs); -#else -static inline void dfs_reset_etsi_precac_lists(struct wlan_dfs *dfs) -{ -} -#endif - -/** - * dfs_reset_etsiprecaclists()- Clears and initializes etsi_precac_required_list - * etsi_precac_done_list. - * - * @dfs: Pointer to wlan_dfs structure. - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -void dfs_reset_etsiprecaclists(struct wlan_dfs *dfs); -#else -static inline void dfs_reset_etsiprecaclists(struct wlan_dfs *dfs) -{ -} -#endif - -/** - * dfs_add_to_etsi_precac_required_list()- Add channel to ETSI PreCAC Required - * list. - * - * @dfs: Pointer to wlan_dfs structure. - * @chan: Pointer to channel to be added to ETSI PreCAC Required List. - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -void dfs_add_to_etsi_precac_required_list(struct wlan_dfs *dfs, uint8_t *chan); -#else -static inline void dfs_add_to_etsi_precac_required_list(struct wlan_dfs *dfs, - uint8_t *chan) -{ -} -#endif - -/** - * dfs_deinit_etsi_precac_list() - Clears the etsi precac list. - * @dfs: Pointer to wlan_dfs dtructure. - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -void dfs_deinit_etsi_precac_list(struct wlan_dfs *dfs); -#else -static inline void dfs_deinit_etsi_precac_list(struct wlan_dfs *dfs) -{ -} -#endif - -/** - * dfs_etsi_precac_attach() - Initialize ETSI precac variables. - * @dfs: Pointer to DFS structure. - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -void dfs_etsi_precac_attach(struct wlan_dfs *dfs); -#else -static inline void dfs_etsi_precac_attach(struct wlan_dfs *dfs) -{ -} -#endif - -/** - * dfs_etsi_precac_detach() - Free etsi_precac memory. - * @dfs: Pointer to wlan_dfs dtructure. - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -void dfs_etsi_precac_detach(struct wlan_dfs *dfs); -#else -static inline void dfs_etsi_precac_detach(struct wlan_dfs *dfs) -{ -} -#endif - -/** - * dfs_init_etsiprecac_list() - Init ETSI precac list. - * @dfs: Pointer to wlan_dfs dtructure. - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -void dfs_init_etsi_precac_list(struct wlan_dfs *dfs); -#else -static inline void dfs_init_etsi_precac_list(struct wlan_dfs *dfs) -{ -} -#endif - -/** - * dfs_is_subchan_in_etsi_precac_done_list() - Is HT20 sub channel - * in etsi precac done list. - * @dfs: Pointer to wlan_dfs structure. - * @channel: HT20 sub channel - * - * Return: If subchannel present in precac done list return 1. - * Otherwise return 0 - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -int dfs_is_subchan_in_etsi_precac_done_list(struct wlan_dfs *dfs, - uint8_t channel); -#else -static inline int dfs_is_subchan_in_etsi_precac_done_list(struct wlan_dfs *dfs) -{ - return 0; -} -#endif -/** - * dfs_is_etsi_precac_done() - Is precac done. - * @dfs: Pointer to wlan_dfs structure. - * - * Return: If precac already done in channel, return 1. Otherwise return 0. - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -bool dfs_is_etsi_precac_done(struct wlan_dfs *dfs); -#else -static inline bool dfs_is_etsi_precac_done(struct wlan_dfs *dfs) -{ - return false; -} -#endif - -/** - * dfs_mark_etsi_precac_dfs() - Mark the precac channel as radar for ETSI. - * @dfs: Pointer to wlan_dfs structure. - * @channels: List of HT20 primary channels - * @num_channels: Number of HT20 primary channels - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -void dfs_mark_etsi_precac_dfs(struct wlan_dfs *dfs, - uint8_t *channels, uint8_t num_channels); -#else -static inline void dfs_mark_etsi_precac_dfs(struct wlan_dfs *dfs, - uint8_t *channels, - uint8_t num_channels) -{ -} -#endif - -/** - * dfs_add_chan_to_etsi_done_list() - Add subchannel to ETSI CAC done list, - * if present in ETSI CAC required list - * @dfs: Pointer to wlan_dfs structure. - * @channel: HT20 primary channel - * - * Return: If channel added to ETSI CAC done list, return 1. Otherwise return 0. - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -int dfs_add_chan_to_etsi_done_list(struct wlan_dfs *dfs, uint8_t channel); -#else -static inline int dfs_add_chan_to_etsi_done_list(struct wlan_dfs *dfs, - uint8_t channel) -{ - return 0; -} -#endif - -/** - * dfs_add_to_etsi_precac_done_list() - Add channel to ETSI CAC done list - * @curchan: Pointer to dfs_channel structure. - * - */ -#if defined(QCA_SUPPORT_ETSI_PRECAC_DFS) -void dfs_add_to_etsi_precac_done_list(struct wlan_dfs *dfs); -#else -static inline void dfs_add_to_etsi_precac_done_list(struct wlan_dfs *dfs) -{ -} -#endif - -#endif /* _DFS_ETSI_PRECAC_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_filter_init.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_filter_init.h index 10ac388975707fed640abf1b4a62a9620e5d530f..5b86d7a104fb77e5fc2e84fe471abe94a5c2c6b1 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_filter_init.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_filter_init.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -88,26 +88,12 @@ static inline void dfs_main_timer_detach(struct wlan_dfs *dfs) } #endif -#ifdef CONFIG_WIN -#if DA_SUPPORT -#if defined(WLAN_DFS_DIRECT_ATTACH) +#if defined(DA_SUPPORT) && defined(WLAN_DFS_DIRECT_ATTACH) void dfs_get_da_radars(struct wlan_dfs *dfs); #else static inline void dfs_get_da_radars(struct wlan_dfs *dfs) { } #endif -#else -#define dfs_get_da_radars(dfs) /**/ -#endif /* _DA_SUPPORT_ */ -#else -#if defined(WLAN_DFS_DIRECT_ATTACH) -void dfs_get_da_radars(struct wlan_dfs *dfs); -#else -static inline void dfs_get_da_radars(struct wlan_dfs *dfs) -{ -} -#endif -#endif /* _CONFIG_WIN_ */ #endif /* _DFS_FILTER_INIT_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_internal.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_internal.h index 07ff4b1670e43a84a7d1e91e6ff5c017b8d868bf..33bcb7514375d089b92992edda3f2a0a6d404f3f 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_internal.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2008 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for @@ -36,6 +36,7 @@ * @DFS_MKK4_DOMAIN: MKK domain * @DFS_CN_DOMAIN: China domain * @DFS_KR_DOMAIN: Korea domain + * @DFS_MKKN_DOMAIN: MKKN domain * @DFS_UNDEF_DOMAIN: Undefined domain */ enum DFS_DOMAIN { @@ -45,6 +46,7 @@ enum DFS_DOMAIN { DFS_MKK4_DOMAIN = 3, DFS_CN_DOMAIN = 4, DFS_KR_DOMAIN = 5, + DFS_MKKN_DOMAIN = 6, DFS_UNDEF_DOMAIN }; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_partial_offload_radar.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_partial_offload_radar.h index 40b94f6a8b6769767ceac6c14cc17c3ea2bd2293..4fb8f7ec0dfbb54c6894bead3ccdba70c2a338a5 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_partial_offload_radar.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_partial_offload_radar.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -197,4 +197,56 @@ static inline void dfs_false_radarfound_reset_vars(struct wlan_dfs *dfs) { } #endif + +#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(WLAN_DFS_SYNTHETIC_RADAR) +/** + * dfs_allow_hw_pulses() - Set or unset dfs_allow_hw_pulses + * which allow or disallow HW pulses. + * @dfs: Pointer to DFS pdev object. + * @allow_hw_pulses: allow/disallow synthetic pulse detection true/false. + * + * Return: void + */ +void dfs_allow_hw_pulses(struct wlan_dfs *dfs, bool allow_hw_pulses); +#else +static inline void dfs_allow_hw_pulses(struct wlan_dfs *dfs, + bool allow_hw_pulses) +{ +} +#endif + +#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(WLAN_DFS_SYNTHETIC_RADAR) +/** + * dfs_is_hw_pulses_allowed() - Check if HW pulses are allowed or not. + * @pdev: Pointer to DFS pdev object. + * + * Return: bool + */ +bool dfs_is_hw_pulses_allowed(struct wlan_dfs *dfs); +#else +static inline bool dfs_is_hw_pulses_allowed(struct wlan_dfs *dfs) +{ + return true; +} +#endif + +/** + * dfs_inject_synthetic_pulse_sequence() - Inject the synthetic pulse to the + * phyerror processing algorithm. + * @dfs: Pointer to wlan_dfs structure. + * @buf: Pointer to buffer of pulses. + * + * Return: QDF_STATUS + */ +#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(WLAN_DFS_SYNTHETIC_RADAR) +QDF_STATUS dfs_inject_synthetic_pulse_sequence(struct wlan_dfs *dfs, + unsigned char *buf); +#else +static inline +QDF_STATUS dfs_inject_synthetic_pulse_sequence(struct wlan_dfs *dfs, + unsigned char *buf) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* WLAN_DFS_PARTIAL_OFFLOAD && WLAN_DFS_SYNTHETIC_RADAR */ #endif /* _DFS_PARTIAL_OFFLOAD_RADAR_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_phyerr_tlv.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_phyerr_tlv.h index 08500d023da12691c60d769e9dde72dc4b20276b..0fad819bde94ff3131e571b958b5c0b46cae461a 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_phyerr_tlv.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_phyerr_tlv.h @@ -81,11 +81,6 @@ #define RADAR_REPORT_PULSE_SUBCHAN_MASK 0x00FF0000 #define RADAR_REPORT_PULSE_SUBCHAN_MASK_S 16 -#define RADAR_REPORT_PULSE_REG_4 0x03 - -#define RADAR_REPORT_PULSE_RSSI 0x3FFC0000 -#define RADAR_REPORT_PULSE_RSSI_S 18 - #define RADAR_REPORT_PULSE_TSF_OFFSET 0x0000FF00 #define RADAR_REPORT_PULSE_TSF_OFFSET_S 8 diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_process_radar_found_ind.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_process_radar_found_ind.h index 2017742340e26edfb4dea4316867876067ef7542..d41cc034a9eb3f48ca37f06978b0305148389582 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_process_radar_found_ind.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_process_radar_found_ind.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 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 @@ -69,18 +69,29 @@ #define DFS_CHIRP_OFFSET 10 /* second segment freq offset */ #define DFS_160MHZ_SECOND_SEG_OFFSET 40 +/*Primary segment id is 0 */ +#define PRIMARY_SEG 0 /* Frequency offset indices */ #define CENTER_CH 0 #define LEFT_CH 1 #define RIGHT_CH 2 +#ifdef CONFIG_CHAN_NUM_API /* Next channel number offset's from center channel number */ #define DFS_5GHZ_NEXT_CHAN_OFFSET 2 #define DFS_5GHZ_2ND_CHAN_OFFSET 6 #define DFS_5GHZ_3RD_CHAN_OFFSET 10 #define DFS_5GHZ_4TH_CHAN_OFFSET 14 - +#endif + +#ifdef CONFIG_CHAN_FREQ_API +/* Next channel frequency offsets from center channel frequency */ +#define DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET 10 +#define DFS_5GHZ_2ND_CHAN_FREQ_OFFSET 30 +#define DFS_5GHZ_3RD_CHAN_FREQ_OFFSET 50 +#define DFS_5GHZ_4TH_CHAN_FREQ_OFFSET 70 +#endif /* Max number of bonding channels in 160 MHz segment */ #define NUM_CHANNELS_160MHZ 8 @@ -138,17 +149,41 @@ void dfs_radarfound_action_generic(struct wlan_dfs *dfs, uint8_t seg_id); /** * dfs_get_bonding_channels() - Get bonding channels. - * @dfs: Pointer to wlan_dfs structure. - * @curchan: Pointer to dfs_channels to know width and primary channel. - * @segment_id: Segment id, useful for 80+80/160 MHz operating band. - * @channels: Pointer to save radar affected channels. + * @dfs: Pointer to wlan_dfs structure. + * @curchan: Pointer to dfs_channels to know width and primary channel. + * @segment_id: Segment id, useful for 80+80/160 MHz operating band. + * @detector_id: Detector id, used to find if radar is detected on + * Agile detector. + * @channels: Pointer to save radar affected channels. * * Return: Number of channels. */ +#ifdef CONFIG_CHAN_NUM_API uint8_t dfs_get_bonding_channels(struct wlan_dfs *dfs, struct dfs_channel *curchan, uint32_t segment_id, + uint8_t detector_id, uint8_t *channels); +#endif + +/** + * dfs_get_bonding_channels_for_freq() - Get bonding channels. + * @dfs: Pointer to wlan_dfs structure. + * @curchan: Pointer to dfs_channels to know width and primary channel. + * @segment_id: Segment id, useful for 80+80/160 MHz operating band. + * @detector_id: Detector id, used to find if radar is detected on + * Agile detector. + * @freq_list: Pointer to save radar affected channel's frequency. + * + * Return: Number of channels. + */ +#ifdef CONFIG_CHAN_FREQ_API +uint8_t dfs_get_bonding_channels_for_freq(struct wlan_dfs *dfs, + struct dfs_channel *curchan, + uint32_t segment_id, + uint8_t detector_id, + uint16_t *freq_list); +#endif /** * dfs_get_bonding_channels_without_seg_info() - Get bonding channels in chan @@ -157,8 +192,24 @@ uint8_t dfs_get_bonding_channels(struct wlan_dfs *dfs, * * Return: number of sub channels in the input channel. */ +#ifdef CONFIG_CHAN_NUM_API uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan, uint8_t *channels); +#endif + +/** + * dfs_get_bonding_channel_without_seg_info_for_freq() - Get bonding channels + * in chan. + * @chan: Pointer to dfs_channel structure. + * @freq_list: channel array holding list of bonded channel's frequency. + * + * Return: number of sub channels in the input channel. + */ +#ifdef CONFIG_CHAN_FREQ_API +uint8_t +dfs_get_bonding_channel_without_seg_info_for_freq(struct dfs_channel *chan, + uint16_t *freq_list); +#endif /** * dfs_set_nol_subchannel_marking() - Set or unset NOL subchannel marking. diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_random_chan_sel.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_random_chan_sel.h index 88d8cbbd079ee2f1a3273acd73e5266d66997d37..bf03f79856fed011045ad761676f03fe36d6408c 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_random_chan_sel.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_random_chan_sel.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 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 @@ -69,20 +69,29 @@ /* Next 5GHz channel number */ #define DFS_80_NUM_SUB_CHANNEL 4 +/* Next 5GHz channel freq offset */ +#define DFS_80_NUM_SUB_CHANNEL_FREQ 20 + /* Next 5GHz channel number */ #define DFS_NEXT_5GHZ_CHANNEL 4 +/* Next 5GHz channel number */ +#define DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET 20 + /* Number of 20MHz channels in bitmap */ #define DFS_MAX_20M_SUB_CH 8 +/* Frequency difference between 80+80 MHz */ +#define DFS_80P80M_FREQ_DIFF 40 + /* Number of 80MHz channels in 5GHz band */ #define DFS_MAX_80MHZ_BANDS 6 /* Start channel and center channel diff in 80Mhz */ #define DFS_80MHZ_START_CENTER_CH_DIFF 6 -/* Max number of channels */ -#define DFS_MAX_NUM_CHAN 128 +/* Start channel and center channel freq diff in 80Mhz */ +#define DFS_80MHZ_START_CENTER_CH_FREQ_DIFF 30 /* Bitmap mask for 80MHz */ #define DFS_80MHZ_MASK 0x0F @@ -102,6 +111,11 @@ /* Max 2.4 GHz channel number */ #define DFS_MAX_24GHZ_CHANNEL 14 +/* Max 2.4 GHz channel frequency */ +#define DFS_MAX_24GHZ_CHANNEL_FREQ 2484 + +/* Adjacent weather radar channel frequency */ +#define DFS_ADJACENT_WEATHER_RADAR_CHANNEL_FREQ 5580 /* Max valid channel number */ #define MAX_CHANNEL_NUM 184 @@ -121,20 +135,30 @@ #endif #define DFS_IS_CHANNEL_WEATHER_RADAR(_f) (((_f) >= 5600) && ((_f) <= 5650)) +#ifdef CONFIG_CHAN_NUM_API #define DFS_IS_CHAN_JAPAN_INDOOR(_ch) (((_ch) >= 36) && ((_ch) <= 64)) #define DFS_IS_CHAN_JAPAN_W53(_ch) (((_ch) >= 52) && ((_ch) <= 64)) #define DFS_IS_CHAN_JAPAN_OUTDOOR(_ch) (((_ch) >= 100) && ((_ch) <= 140)) +#endif + +#ifdef CONFIG_CHAN_FREQ_API +#define DFS_IS_CHAN_JAPAN_INDOOR_FREQ(_ch)(((_ch) >= 5180) && ((_ch) <= 5320)) +#define DFS_IS_CHAN_JAPAN_OUTDOOR_FREQ(_ch)(((_ch) >= 5500) && ((_ch) <= 5700)) +#define DFS_IS_CHAN_JAPAN_W53_FREQ(_ch) (((_ch) >= 5260) && ((_ch) <= 5320)) +#endif /** * struct chan_bonding_info - for holding channel bonding bitmap * @chan_map: channel map * @rsvd: reserved * @start_chan: start channel + * @start_chan_freq: start channel frequency in MHZ. */ struct chan_bonding_info { uint8_t chan_map:4; uint8_t rsvd:4; uint8_t start_chan; + uint16_t start_chan_freq; }; /** @@ -154,6 +178,7 @@ struct chan_bonding_bitmap { */ struct dfs_tx_leak_info { uint8_t leak_chan; + uint16_t leak_chan_freq; uint32_t leak_lvl; }; @@ -164,7 +189,9 @@ struct dfs_tx_leak_info { */ struct dfs_matrix_tx_leak_info { uint8_t channel; - struct dfs_tx_leak_info chan_matrix[CHAN_ENUM_144 - CHAN_ENUM_36 + 1]; + uint16_t channel_freq; + struct dfs_tx_leak_info chan_matrix[CHAN_ENUM_5720 - + CHAN_ENUM_5180 + 1]; }; #endif @@ -181,10 +208,32 @@ struct dfs_matrix_tx_leak_info { * * Return: QDF_STATUS */ +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS dfs_mark_leaking_ch(struct wlan_dfs *dfs, enum phy_ch_width ch_width, uint8_t temp_ch_lst_sz, uint8_t *temp_ch_lst); +#endif + +/** + * dfs_mark_leaking_chan_for_freq() - to mark channel leaking in to nol + * @dfs: dfs handler. + * @ch_width: channel width + * @temp_chan_lst_sz: the target channel list size. + * @temp_freq_lst: the target frequency channel list + * + * This function removes the channels from temp channel list that + * (if selected as target channel) will cause leakage in one of + * the NOL channels + * + * Return: QDF_STATUS + */ +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS dfs_mark_leaking_chan_for_freq(struct wlan_dfs *dfs, + enum phy_ch_width ch_width, + uint8_t temp_chan_lst_sz, + uint16_t *temp_freq_lst); +#endif /** * dfs_prepare_random_channel() - This function picks a random channel from @@ -205,6 +254,7 @@ QDF_STATUS dfs_mark_leaking_ch(struct wlan_dfs *dfs, * * Return: channel number, else zero. */ +#ifdef CONFIG_CHAN_NUM_API uint8_t dfs_prepare_random_channel(struct wlan_dfs *dfs, struct dfs_channel *ch_list, uint32_t ch_count, @@ -213,3 +263,34 @@ uint8_t dfs_prepare_random_channel(struct wlan_dfs *dfs, struct dfs_channel *cur_chan, uint8_t dfs_region, struct dfs_acs_info *acs_info); +#endif + +/** + * dfs_prepare_random_channel() - This function picks a random channel from + * the list of available channels. + * @dfs: dfs handler. + * @chan_list: channel list. + * @ch_count: Number of channels in given list. + * @flags: DFS_RANDOM_CH_FLAG_* + * @chan_wd: input channel width, used same variable to return new ch width. + * @cur_chan: current channel. + * @dfs_region: DFS region. + * @acs_info: acs channel range information. + * + * Function used to find random channel selection from a given list. + * First this function removes channels based on flags and then uses final + * list to find channel based on requested bandwidth, if requested bandwidth + * not available, it chooses next lower bandwidth and try. + * + * Return: channel frequency, else zero. + */ +#ifdef CONFIG_CHAN_FREQ_API +uint16_t dfs_prepare_random_channel_for_freq(struct wlan_dfs *dfs, + struct dfs_channel *ch_list, + uint32_t chan_count, + uint32_t flags, + uint8_t *chan_wd, + struct dfs_channel *cur_chan, + uint8_t dfs_region, + struct dfs_acs_info *acs_info); +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_zero_cac.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_zero_cac.h index cfeddc3a323bf2386c682c703fcc27478c57c8de..dd718e97f4b8be504a7473d863fa88f756dd6970 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_zero_cac.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/dfs_zero_cac.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting * All rights reserved. * @@ -34,23 +34,64 @@ #include "dfs.h" #include +#ifdef CONFIG_CHAN_NUM_API #define VHT160_IEEE_FREQ_DIFF 16 +#endif + #define OCAC_SUCCESS 0 #define OCAC_RESET 1 #define OCAC_CANCEL 2 +#define TREE_DEPTH 3 +#define N_SUBCHANS_FOR_80BW 4 + +#define INITIAL_20_CHAN_OFFSET -6 +#define INITIAL_40_CHAN_OFFSET -4 +#define INITIAL_80_CHAN_OFFSET 0 + +#define NEXT_20_CHAN_OFFSET 4 +#define NEXT_40_CHAN_OFFSET 8 +#define NEXT_80_CHAN_OFFSET 16 + +#define DFS_CHWIDTH_20_VAL 20 +#define DFS_CHWIDTH_40_VAL 40 +#define DFS_CHWIDTH_80_VAL 80 +#define DFS_CHWIDTH_160_VAL 160 + +#define WEATHER_CHAN_START 120 +#define WEATHER_CHAN_END 128 + +/* PreCAC timeout durations in ms. */ +#define MIN_PRECAC_DURATION (6 * 60 * 1000) /* 6 mins */ +#define MIN_WEATHER_PRECAC_DURATION (60 * 60 * 1000) /* 1 hour */ +#define MAX_PRECAC_DURATION (4 * 60 * 60 * 1000) /* 4 hours */ +#define MAX_WEATHER_PRECAC_DURATION (24 * 60 * 60 * 1000) /* 24 hours */ + +#define PCAC_DFS_INDEX_ZERO 0 +#define PCAC_TIMER_NOT_RUNNING 0 +#define PRECAC_NOT_STARTED 0 /** - * struct dfs_precac_entry - PreCAC entry. - * @pe_list: PreCAC entry. - * @vht80_freq: VHT80 freq. - * @precac_nol_timer: Per element precac NOL timer. - * @dfs: Pointer to wlan_dfs structure. + * struct precac_tree_node - Individual tree node structure for every node in + * the precac forest maintained. + * @left_child: Pointer to the left child of the node. + * @right_child: Pointer to the right child of the node. + * @ch_ieee: Center channel ieee value. + * @ch_freq: Center channel frequency value (BSTree node key value). + * @n_caced_subchs: Number of CACed subchannels of the ch_ieee. + * @n_nol_subchs: Number of subchannels of the ch_ieee in NOL. + * @n_valid_subchs: Number of subchannels of the ch_ieee available (as per + * the country's channel list). + * @bandwidth: Bandwidth of the ch_ieee (in the current node). */ -struct dfs_precac_entry { - TAILQ_ENTRY(dfs_precac_entry) pe_list; - uint8_t vht80_freq; - qdf_timer_t precac_nol_timer; - struct wlan_dfs *dfs; +struct precac_tree_node { + struct precac_tree_node *left_child; + struct precac_tree_node *right_child; + uint8_t ch_ieee; + uint16_t ch_freq; + uint8_t n_caced_subchs; + uint8_t n_nol_subchs; + uint8_t n_valid_subchs; + uint8_t bandwidth; }; /** @@ -69,6 +110,22 @@ enum precac_chan_state { PRECAC_NOL, }; +/** + * struct dfs_precac_entry - PreCAC entry. + * @pe_list: PreCAC entry. + * @vht80_ch_ieee: VHT80 centre channel IEEE value. + * @vht80_ch_freq: VHT80 centre channel frequency value. + * @dfs: Pointer to wlan_dfs structure. + * @tree_root: Tree root node with 80MHz channel key. + */ +struct dfs_precac_entry { + TAILQ_ENTRY(dfs_precac_entry) pe_list; + uint8_t vht80_ch_ieee; + uint16_t vht80_ch_freq; + struct wlan_dfs *dfs; + struct precac_tree_node *tree_root; +}; + /** * dfs_zero_cac_timer_init() - Initialize zero-cac timers * @dfs_soc_obj: Pointer to DFS SOC object structure. @@ -106,9 +163,7 @@ static inline void dfs_reset_precac_lists(struct wlan_dfs *dfs) #endif /** - * dfs_reset_precaclists() - Clears and initiakizes precac_required_list, - * precac_done_list and precac_nol_list. - * + * dfs_reset_precaclists() - Clears and initializes precac_list. * @dfs: Pointer to wlan_dfs structure. */ #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT) @@ -149,14 +204,35 @@ void dfs_init_precac_list(struct wlan_dfs *dfs); * @precac_chan: Start thr precac timer in this channel. */ #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT) +#ifdef CONFIG_CHAN_NUM_API void dfs_start_precac_timer(struct wlan_dfs *dfs, uint8_t precac_chan); +#endif + +/** + * dfs_start_precac_timer() - Start precac timer. + * @dfs: Pointer to wlan_dfs structure. + * @precac_chan_freq: Frequency to start precac timer. + */ +#ifdef CONFIG_CHAN_FREQ_API +void dfs_start_precac_timer_for_freq(struct wlan_dfs *dfs, + uint16_t precac_chan_freq); +#endif #else +#ifdef CONFIG_CHAN_NUM_API static inline void dfs_start_precac_timer(struct wlan_dfs *dfs, uint8_t precac_chan) { } #endif +#ifdef CONFIG_CHAN_FREQ_API +static inline +void dfs_start_precac_timer_for_freq(struct wlan_dfs *dfs, + uint16_t precac_chan_freq) +{ +} +#endif +#endif /** * dfs_cancel_precac_timer() - Cancel the precac timer. @@ -239,27 +315,79 @@ static inline bool dfs_is_precac_done(struct wlan_dfs *dfs, * * Return: True if intermediate channel needs to configure. False otherwise. */ +#ifdef CONFIG_CHAN_NUM_API bool dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs, uint8_t *pref_chan, enum wlan_phymode mode); +#endif + +/** + * dfs_decide_precac_preferred_chan_for_freq() - Choose operating channel among + * configured DFS channel and + * intermediate channel based on + * precac status of configured + * DFS channel. + * @dfs: Pointer to wlan_dfs structure. + * @pref_chan: Configured DFS channel frequency + * @mode: Configured PHY mode. + * + * Return: True if intermediate channel needs to configure. False otherwise. + */ + +#ifdef CONFIG_CHAN_FREQ_API +bool +dfs_decide_precac_preferred_chan_for_freq(struct wlan_dfs *dfs, + uint16_t *pref_chan_freq, + enum wlan_phymode mode); +#endif #else +#ifdef CONFIG_CHAN_NUM_API static inline void dfs_decide_precac_preferred_chan(struct wlan_dfs *dfs, uint8_t *pref_chan, enum wlan_phymode mode) { } #endif +#ifdef CONFIG_CHAN_FREQ_API +static inline void +dfs_decide_precac_preferred_chan_for_freq(struct wlan_dfs *dfs, + uint8_t *pref_chan, + enum wlan_phymode mode) +{ +} +#endif +#endif /** - * dfs_get_freq_from_precac_required_list() - Get VHT80 freq from - * precac_required_list. - * @dfs: Pointer to wlan_dfs structure. - * @exclude_ieee_freq: Find a VHT80 freqency that is not equal to - * exclude_ieee_freq. + * dfs_get_ieeechan_for_precac() - Get chan of required bandwidth from + * precac_list. + * @dfs: Pointer to wlan_dfs structure. + * @exclude_pri_ch_ieee: Primary channel IEEE to be excluded for preCAC. + * @exclude_sec_ch_ieee: Secondary channel IEEE to be excluded for preCAC. + * @bandwidth: Bandwidth of requested channel. + */ +#ifdef CONFIG_CHAN_NUM_API +uint8_t dfs_get_ieeechan_for_precac(struct wlan_dfs *dfs, + uint8_t exclude_pri_ch_ieee, + uint8_t exclude_sec_ch_ieee, + uint8_t bandwidth); +#endif + +/** + * dfs_get_ieeechan_for_precac_for_freq() - Get chan of required bandwidth from + * precac_list. + * @dfs: Pointer to wlan_dfs structure. + * @exclude_pri_chan_freq: Primary channel freq to be excluded for preCAC. + * @exclude_sec_chan_freq: Secondary channel freq to be excluded for preCAC. + * @bandwidth: Bandwidth of requested channel. */ -uint8_t dfs_get_freq_from_precac_required_list(struct wlan_dfs *dfs, - uint8_t exclude_ieee_freq); +#ifdef CONFIG_CHAN_FREQ_API +uint16_t dfs_get_ieeechan_for_precac_for_freq(struct wlan_dfs *dfs, + uint16_t exclude_pri_chan_freq, + uint16_t exclude_sec_chan_freq, + uint8_t bandwidth); +#endif /** * dfs_override_precac_timeout() - Override the default precac timeout. @@ -329,6 +457,7 @@ static inline int dfs_get_override_precac_timeout(struct wlan_dfs *dfs, * exhausted the VHT80_80/VHT160 comes back to VHT80 mode. */ #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT) +#ifdef CONFIG_CHAN_NUM_API void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs, uint32_t chan_mode, uint8_t ch_freq_seg1, @@ -337,7 +466,32 @@ void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs, uint32_t *phy_mode, bool *dfs_set_cfreq2, bool *set_agile); +#endif + +/* + * dfs_find_vht80_chan_for_precac() - Find VHT80 channel for precac. + * @dfs: Pointer to wlan_dfs structure. + * @chan_mode: Channel mode. + * @ch_freq_seg1: Segment1 channel freq in mhz. + * @cfreq1: cfreq1. + * @cfreq2: cfreq2. + * @phy_mode: Precac phymode. + * @dfs_set_cfreq2: Precac cfreq2 + * @set_agile: Agile mode flag. + */ +#ifdef CONFIG_CHAN_FREQ_API +void dfs_find_vht80_chan_for_precac_for_freq(struct wlan_dfs *dfs, + uint32_t chan_mode, + uint16_t ch_freq_seg1_mhz, + uint32_t *cfreq1, + uint32_t *cfreq2, + uint32_t *phy_mode, + bool *dfs_set_cfreq2, + bool *set_agile); +#endif + #else +#ifdef CONFIG_CHAN_NUM_API static inline void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs, uint32_t chan_mode, uint8_t ch_freq_seg1, @@ -350,6 +504,21 @@ static inline void dfs_find_vht80_chan_for_precac(struct wlan_dfs *dfs, } #endif +#ifdef CONFIG_CHAN_FREQ_API +static inline +void dfs_find_vht80_chan_for_precac_for_freq(struct wlan_dfs *dfs, + uint32_t chan_mode, + uint16_t ch_freq_seg1_mhz, + uint32_t *cfreq1, + uint32_t *cfreq2, + uint32_t *phy_mode, + bool *dfs_set_cfreq2, + bool *set_agile) +{ +} +#endif +#endif + #if defined(QCA_SUPPORT_AGILE_DFS) /** * dfs_find_pdev_for_agile_precac() - Find pdev to select channel for precac. @@ -376,16 +545,39 @@ void dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev, uint32_t center_freq); /** - * dfs_find_vht80_chan_for_agile_precac() - . - * @pdev :Pointer to wlan_objmgr_pdev structure. - * @*ch_freq: Pointer to channel number for agile set request. - * @ch_freq_seg1 : Current primary beaconing channel number. - * @ch_freq_seg2 : Current secondary segment channel number. + * dfs_get_ieeechan_for_agilecac() - Find an IEEE channel for agile CAC. + * @dfs: Pointer to wlan_dfs structure. + * @ch_ieee: Pointer to channel number for agile set request. + * @pri_ch_ieee: Current primary IEEE channel. + * @sec_ch_ieee: Current secondary IEEE channel (in HT80_80 mode). + * + * Find an IEEE channel for agileCAC which is not the current operating + * channels (indicated by pri_ch_ieee, sec_ch_ieee). + */ +#ifdef CONFIG_CHAN_NUM_API +void dfs_get_ieeechan_for_agilecac(struct wlan_dfs *dfs, + uint8_t *ch_ieee, + uint8_t pri_ch_ieee, + uint8_t sec_ch_ieee); +#endif + +/** + * dfs_get_ieeechan_for_agilecac_for_freq() - Find chan freq for agile CAC. + * @dfs: Pointer to wlan_dfs structure. + * @chan_freq: Pointer to channel freq for agile set request. + * @pri_chan_freq: Current primary IEEE channel freq. + * @sec_chan_freq: Current secondary IEEE channel freq (in HT80_80 mode). + * + * Find an IEEE channel freq for agileCAC which is not the current operating + * channels (indicated by pri_chan_freq, sec_chan_freq). */ -void dfs_find_vht80_chan_for_agile_precac(struct wlan_dfs *dfs, - uint8_t *ch_freq, - uint8_t ch_freq_seg1, - uint8_t ch_freq_seg2); +#ifdef CONFIG_CHAN_FREQ_API +void dfs_get_ieeechan_for_agilecac_for_freq(struct wlan_dfs *dfs, + uint16_t *chan_freq, + uint16_t pri_chan_freq, + uint16_t sec_chan_freq); +#endif + /** * dfs_agile_precac_start() - Start agile precac. * @dfs: Pointer to wlan_dfs structure. @@ -393,14 +585,31 @@ void dfs_find_vht80_chan_for_agile_precac(struct wlan_dfs *dfs, void dfs_agile_precac_start(struct wlan_dfs *dfs); /** - * dfs_start_agile_precac_timer() - Start precac timer. - * @dfs: Pointer to wlan_dfs structure. - * @precac_chan: Start thr precac timer in this channel. + * dfs_start_agile_precac_timer() - Start precac timer for the given channel. + * @dfs: Pointer to wlan_dfs structure. * @ocac_status: Status of the off channel CAC. + * @adfs_param: Agile DFS CAC parameters. + * + * Start the precac timer with proper timeout values based on the channel to + * be preCACed. The preCAC channel number and chwidth information is present + * in the adfs_param argument. Once the timer is started, update the timeout + * fields in adfs_param. */ void dfs_start_agile_precac_timer(struct wlan_dfs *dfs, - uint8_t precac_chan, - uint8_t ocac_status); + uint8_t ocac_status, + struct dfs_agile_cac_params *adfs_param); + +/** + * dfs_set_fw_adfs_support() - Set FW aDFS support in dfs object. + * @dfs: Pointer to wlan_dfs structure. + * @fw_adfs_support_160: aDFS enabled when pdev is on 160/80P80MHz. + * @fw_adfs_support_non_160: aDFS enabled when pdev is on 20/40/80MHz. + * + * Return: void. + */ +void dfs_set_fw_adfs_support(struct wlan_dfs *dfs, + bool fw_adfs_support_160, + bool fw_adfs_support_non_160); #else static inline void dfs_find_pdev_for_agile_precac(struct wlan_objmgr_pdev *pdev, uint8_t *cur_precac_dfs_index) @@ -418,20 +627,40 @@ dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev, { } -static inline void dfs_find_vht80_chan_for_agile_precac(struct wlan_dfs *dfs, - uint8_t *ch_freq, - uint8_t ch_freq_seg1, - uint8_t ch_freq_seg2) +#ifdef CONFIG_CHAN_NUM_API +static inline void dfs_get_ieeechan_for_agilecac(struct wlan_dfs *dfs, + uint8_t *ch_ieee, + uint8_t pri_ch_ieee, + uint8_t sec_ch_ieee) { } +#endif + +#ifdef CONFIG_CHAN_FREQ_API +static inline void +dfs_get_ieeechan_for_agilecac_for_freq(struct wlan_dfs *dfs, + uint16_t *chan_freq, + uint16_t pri_chan_freq, + uint16_t sec_chan_freq) +{ +} +#endif static inline void dfs_agile_precac_start(struct wlan_dfs *dfs) { } -static inline void dfs_start_agile_precac_timer(struct wlan_dfs *dfs, - uint8_t precac_chan, - uint8_t ocac_status) +static inline void +dfs_start_agile_precac_timer(struct wlan_dfs *dfs, + uint8_t ocac_status, + struct dfs_agile_cac_params *adfs_param) +{ +} + +static inline void +dfs_set_fw_adfs_support(struct wlan_dfs *dfs, + bool fw_adfs_support_160, + bool fw_adfs_support_non_160) { } #endif @@ -455,7 +684,7 @@ static inline void dfs_agile_soc_obj_init(struct wlan_dfs *dfs, /** * dfs_set_precac_enable() - Set precac enable flag. * @dfs: Pointer to wlan_dfs structure. - * @value: input value for dfs_precac_enable flag. + * @value: input value for dfs_legacy_precac_ucfg flag. */ #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT) void dfs_set_precac_enable(struct wlan_dfs *dfs, @@ -468,24 +697,46 @@ static inline void dfs_set_precac_enable(struct wlan_dfs *dfs, #endif /** - * dfs_get_precac_enable() - Get precac enable flag. - * @dfs: Pointer to wlan_dfs structure. + * dfs_is_legacy_precac_enabled() - Check if legacy preCAC is enabled for the + * DFS onject. + * @dfs: Pointer to the wlan_dfs object. + * + * Return: True if legacy preCAC is enabled, else false. */ #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT) -uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs); +bool dfs_is_legacy_precac_enabled(struct wlan_dfs *dfs); #else -static inline uint32_t dfs_get_precac_enable(struct wlan_dfs *dfs) +static inline bool dfs_is_legacy_precac_enabled(struct wlan_dfs *dfs) { return 0; } #endif +/** + * dfs_is_agile_precac_enabled() - Check if agile preCAC is enabled for the DFS. + * @dfs: Pointer to the wlan_dfs object. + * + * Return: True if agile DFS is enabled, else false. + * + * For agile preCAC to be enabled, + * 1. User configuration should be set. + * 2. Target should support aDFS. + */ +#ifdef QCA_SUPPORT_AGILE_DFS +bool dfs_is_agile_precac_enabled(struct wlan_dfs *dfs); +#else +static inline bool dfs_is_agile_precac_enabled(struct wlan_dfs *dfs) +{ + return false; +} +#endif + #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT /** * dfs_set_precac_intermediate_chan() - Set intermediate chan to be used while * doing precac. * @dfs: Pointer to wlan_dfs structure. - * @value: input value for dfs_precac_enable flag. + * @value: input value for dfs_legacy_precac_ucfg flag. * * Return: * * 0 - Successfully set intermediate channel. @@ -526,13 +777,28 @@ static inline uint32_t dfs_get_intermediate_chan(struct wlan_dfs *dfs) * Return: * * PRECAC_REQUIRED: Precac has not done on precac_chan. * * PRECAC_NOW : Precac is running on precac_chan. - * * PRECAC_DONE : precac_chan is in precac done list. - * * PRECAC_NOL : precac_chan is in precac NOL list. + * * PRECAC_DONE : precac_chan is in CAC done state in precac list. + * * PRECAC_NOL : precac_chan is in NOL state in precac list. * * PRECAC_ERR : Invalid precac state. */ enum precac_chan_state dfs_get_precac_chan_state(struct wlan_dfs *dfs, uint8_t precac_chan); + +/** + * dfs_get_precac_chan_state_for_freq() - Get precac status of a given channel. + * @dfs: Pointer to wlan_dfs structure. + * @precac_chan: Channel freq for which precac state need to be checked. + */ + +#ifdef CONFIG_CHAN_FREQ_API +enum precac_chan_state +dfs_get_precac_chan_state_for_freq(struct wlan_dfs *dfs, + uint16_t precac_chan_freq); +#endif + #else + +#ifdef CONFIG_CHAN_NUM_API static inline enum precac_chan_state dfs_get_precac_chan_state(struct wlan_dfs *dfs, uint8_t precac_chan) @@ -541,6 +807,16 @@ dfs_get_precac_chan_state(struct wlan_dfs *dfs, } #endif +#ifdef CONFIG_CHAN_FREQ_API +static inline enum precac_chan_state +dfs_get_precac_chan_state_for_freq(struct wlan_dfs *dfs, + uint16_t precac_chan_freq) +{ + return PRECAC_REQUIRED; +} +#endif +#endif + /** * dfs_zero_cac_reset() - Reset Zero cac DFS variables. * @dfs: Pointer to wlan_dfs structure. @@ -548,50 +824,261 @@ dfs_get_precac_chan_state(struct wlan_dfs *dfs, void dfs_zero_cac_reset(struct wlan_dfs *dfs); /** - * dfs_is_ht20_40_80_chan_in_precac_done_list() - Is precac done on a - * VHT20/40/80 channel. + * dfs_reinit_precac_lists() - Reinit DFS preCAC lists. + * @src_dfs: Source DFS from which the preCAC list is copied. + * @dest_dfs: Destination DFS to which the preCAC list is copied. + * @low_5g_freq: Low 5G frequency value of the destination DFS. + * @high_5g_freq: High 5G frequency value of the destination DFS. + * + * Copy all the preCAC list entries from the source DFS to the destination DFS + * which fall within the frequency range of low_5g_freq and high_5g_freq. + * + * Return: None (void). + */ +#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT) +void dfs_reinit_precac_lists(struct wlan_dfs *src_dfs, + struct wlan_dfs *dest_dfs, + uint16_t low_5g_freq, + uint16_t high_5g_freq); +#else +static inline void dfs_reinit_precac_lists(struct wlan_dfs *src_dfs, + struct wlan_dfs *dest_dfs, + uint16_t low_5g_freq, + uint16_t high_5g_freq) +{ +} +#endif + +/** + * dfs_is_precac_done_on_ht20_40_80_chan() - Is precac done on a + * VHT20/40/80 channel. *@dfs: Pointer to wlan_dfs structure. - *@chan: Pointer to dfs_channel for which preCAC done is checked. + *@chan: Channel IEEE value. * * Return: - * * True: If channel is present in precac-done list. - * * False: If channel is not present in precac-done list. + * * True: If CAC is done on channel. + * * False: If CAC is not done on channel. */ -bool dfs_is_ht20_40_80_chan_in_precac_done_list(struct wlan_dfs *dfs, - struct dfs_channel *chan); +#ifdef CONFIG_CHAN_NUM_API +bool dfs_is_precac_done_on_ht20_40_80_chan(struct wlan_dfs *dfs, + uint8_t chan); +#endif /** - * dfs_is_ht8080_ht160_chan_in_precac_done_list() - Is precac done on - * VHT80+80 or VHT160 - * channel. - * @dfs: Pointer to wlan_dfs structure. - * @chan: Pointer to dfs_channel for which preCAC done is checked. + * dfs_is_precac_done_on_ht20_40_80_chan_for_freq() - Is precac done on a + * VHT20/40/80 channel. + *@dfs: Pointer to wlan_dfs structure. + *@chan: Channel frequency * * Return: - * * True: If channel is present in precac-done list. - * * False: If channel is not present in precac-done list. + * * True: If CAC is done on channel. + * * False: If CAC is not done on channel. */ -bool dfs_is_ht8080_ht160_chan_in_precac_done_list(struct wlan_dfs *dfs, - struct dfs_channel *chan); +#ifdef CONFIG_CHAN_FREQ_API +bool dfs_is_precac_done_on_ht20_40_80_chan_for_freq(struct wlan_dfs *dfs, + uint16_t chan_freq); +#endif /** - * dfs_mark_precac_dfs() - Mark the precac channel as radar. + * dfs_is_precac_done_on_ht8080_ht160_chan() - Is precac done on + * VHT80+80 or VHT160 + * channel. * @dfs: Pointer to wlan_dfs structure. - * @is_radar_found_on_secondary_seg: Radar found on secondary seg for Cascade. - * @detector_id: detector id which found RADAR in HW. + * @chan: Pointer to dfs_channel for which preCAC done is checked. + * + * Return: + * * True: If CAC is done on channel. + * * False: If CAC is not done on channel. */ +bool dfs_is_precac_done_on_ht8080_ht160_chan(struct wlan_dfs *dfs, + struct dfs_channel *chan); + #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT) -void dfs_mark_precac_dfs(struct wlan_dfs *dfs, - uint8_t is_radar_found_on_secondary_seg, - uint8_t detector_id); +/** + * dfs_find_chwidth_and_center_chan() - Find the channel width enum and + * primary and secondary center channel + * value of the current channel. + * @dfs: Pointer to wlan_dfs structure. + * @chwidth: Channel width enum of current channel. + * @primary_chan_ieee: Primary IEEE channel. + * @secondary_chan_ieee: Secondary IEEE channel (in HT80_80 mode). + */ +#ifdef CONFIG_CHAN_NUM_API +void dfs_find_chwidth_and_center_chan(struct wlan_dfs *dfs, + enum phy_ch_width *chwidth, + uint8_t *primary_chan_ieee, + uint8_t *secondary_chan_ieee); + +#endif + +#ifdef CONFIG_CHAN_FREQ_API +/** + * dfs_find_chwidth_and_center_chan_for_freq() - Find the channel width enum and + * primary and secondary center channel + * value of the current channel. + * @dfs: Pointer to wlan_dfs structure. + * @chwidth: Channel width enum of current channel. + * @primary_chan_freq: Primary IEEE channel freq. + * @secondary_chan_freq: Secondary IEEE channel freq (in HT80_80 mode). + */ +void dfs_find_chwidth_and_center_chan_for_freq(struct wlan_dfs *dfs, + enum phy_ch_width *chwidth, + uint16_t *primary_chan_freq, + uint16_t *secondary_chan_freq); +#endif + +/** + * dfs_mark_precac_done() - Mark the channel as preCAC done. + * @dfs: Pointer to wlan_dfs structure. + * @pri_ch_ieee: Primary channel IEEE. + * @sec_ch_ieee: Secondary channel IEEE (only in HT80_80 mode). + * @ch_width: Channel width enum. + */ +#ifdef CONFIG_CHAN_NUM_API +void dfs_mark_precac_done(struct wlan_dfs *dfs, + uint8_t pri_ch_ieee, + uint8_t sec_ch_ieee, + enum phy_ch_width ch_width); +#endif + +#ifdef CONFIG_CHAN_FREQ_API +/** + * dfs_mark_precac_done_for_freq() - Mark the channel as preCAC done. + * @dfs: Pointer to wlan_dfs structure. + * @pri_chan_freq: Primary channel IEEE freq. + * @sec_chan_freq: Secondary channel IEEE freq(only in HT80_80 mode). + * @chan_width: Channel width enum. + */ +void dfs_mark_precac_done_for_freq(struct wlan_dfs *dfs, + uint16_t pri_chan_freq, + uint16_t sec_chan_freq, + enum phy_ch_width chan_width); +#endif + +/** + * dfs_mark_precac_nol() - Mark the precac channel as radar. + * @dfs: Pointer to wlan_dfs structure. + * @is_radar_found_on_secondary_seg: Radar found on secondary seg for Cascade. + * @detector_id: detector id which found RADAR in HW. + * @channels: Array of radar found subchannels. + * @num_channels: Number of radar found subchannels. + */ +#ifdef CONFIG_CHAN_NUM_API +void dfs_mark_precac_nol(struct wlan_dfs *dfs, + uint8_t is_radar_found_on_secondary_seg, + uint8_t detector_id, + uint8_t *channels, + uint8_t num_channels); +#endif + +/** + * dfs_mark_precac_nol_for_freq() - Mark the precac channel as radar. + * @dfs: Pointer to wlan_dfs structure. + * @is_radar_found_on_secondary_seg: Radar found on secondary seg for Cascade. + * @detector_id: detector id which found RADAR in HW. + * @freq_list: Array of radar found frequencies. + * @num_channels: Number of radar found subchannels. + */ +#ifdef CONFIG_CHAN_FREQ_API +void dfs_mark_precac_nol_for_freq(struct wlan_dfs *dfs, + uint8_t is_radar_found_on_secondary_seg, + uint8_t detector_id, + uint16_t *freq_list, + uint8_t num_channels); +#endif + +/** + * dfs_unmark_precac_nol() - Unmark the precac channel as radar. + * @dfs: Pointer to wlan_dfs structure. + * @channel: channel marked as radar. + */ +#ifdef CONFIG_CHAN_NUM_API +void dfs_unmark_precac_nol(struct wlan_dfs *dfs, uint8_t channel); +#endif + +/** + * dfs_unmark_precac_nol_for_freq() - Unmark the precac channel as radar. + * @dfs: Pointer to wlan_dfs structure. + * @channel: channel freq marked as radar. + */ +#ifdef CONFIG_CHAN_FREQ_API +void dfs_unmark_precac_nol_for_freq(struct wlan_dfs *dfs, uint16_t chan_freq); +#endif + #else -static inline void dfs_mark_precac_dfs(struct wlan_dfs *dfs, - uint8_t is_radar_found_on_secondary_seg, - uint8_t detector_id) +#ifdef CONFIG_CHAN_NUM_API +static inline void +dfs_find_chwidth_and_center_chan(struct wlan_dfs *dfs, + enum phy_ch_width *chwidth, + uint8_t *primary_chan_ieee, + uint8_t *secondary_chan_ieee) +{ +} +#endif + +#ifdef CONFIG_CHAN_FREQ_API +static inline void +dfs_find_chwidth_and_center_chan_for_freq(struct wlan_dfs *dfs, + enum phy_ch_width *chwidth, + uint16_t *primary_chan_freq, + uint16_t *secondary_chan_freq) { } #endif +#ifdef CONFIG_CHAN_NUM_API +static inline void dfs_mark_precac_done(struct wlan_dfs *dfs, + uint8_t pri_ch_ieee, + uint8_t sec_ch_ieee, + enum phy_ch_width ch_width) +{ +} +#endif + +#ifdef CONFIG_CHAN_FREQ_API +static inline void dfs_mark_precac_done_for_freq(struct wlan_dfs *dfs, + uint16_t pri_chan_freq, + uint16_t sec_chan_freq, + enum phy_ch_width chan_width) +{ +} +#endif + +#ifdef CONFIG_CHAN_NUM_API +static inline void dfs_mark_precac_nol(struct wlan_dfs *dfs, + uint8_t is_radar_found_on_secondary_seg, + uint8_t detector_id, + uint8_t *channels, + uint8_t num_channels) +{ +} +#endif + +#ifdef CONFIG_CHAN_FREQ_API +static inline void +dfs_mark_precac_nol_for_freq(struct wlan_dfs *dfs, + uint8_t is_radar_found_on_secondary_seg, + uint8_t detector_id, + uint16_t *freq, + uint8_t num_channels) +{ +} +#endif + +#ifdef CONFIG_CHAN_NUM_API +static inline void dfs_unmark_precac_nol(struct wlan_dfs *dfs, uint8_t channel) +{ +} +#endif + +#ifdef CONFIG_CHAN_FREQ_API +static inline void dfs_unmark_precac_nol_for_freq(struct wlan_dfs *dfs, + uint16_t chan_freq) +{ +} +#endif +#endif + /** * dfs_is_precac_timer_running() - Check whether precac timer is running. * @dfs: Pointer to wlan_dfs structure. @@ -604,4 +1091,21 @@ static inline bool dfs_is_precac_timer_running(struct wlan_dfs *dfs) return false; } #endif + +#ifdef CONFIG_CHAN_FREQ_API +#define VHT160_FREQ_DIFF 80 + +#define INITIAL_20_CHAN_FREQ_OFFSET -30 +#define INITIAL_40_CHAN_FREQ_OFFSET -20 +#define INITIAL_80_CHAN_FREQ_OFFSET 0 + +#define NEXT_20_CHAN_FREQ_OFFSET 20 +#define NEXT_40_CHAN_FREQ_OFFSET 40 +#define NEXT_80_CHAN_FREQ_OFFSET 80 + +#define WEATHER_CHAN_START_FREQ 5600 +#define WEATHER_CHAN_END_FREQ 5640 + +#endif + #endif /* _DFS_ZERO_CAC_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_bindetects.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_bindetects.c index 67548ad0a121335060690a2b3fdd139b3d4d0c34..81db766c57bb30e3dc54e86a655fa5c6469c39eb 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_bindetects.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_bindetects.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2002-2010, Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -322,6 +322,7 @@ void dfs_add_pulse( dl->dl_numelems = n+1; } } + dfs_debug(dfs, WLAN_DEBUG_DFS2, "dl firstElem = %d lastElem = %d", dl->dl_firstelem, dl->dl_lastelem); } @@ -544,6 +545,55 @@ static inline int dfs_bin_basic_sanity( return 1; } +/** + * dfs_pick_lowpri() - Pick lowpri as refpri + * @dfs: Pointer to wlan_dfs structure. + * @dl: Pointer to dfs delayline. + * @rf: Pointer to dfs_filter structure. + * @lowpriindex: Low PRI index. + * @scoreindex: score index. + * @primargin: PRI margin. + */ +#ifdef DFS_PRI_MULTIPLIER +static inline void dfs_pick_lowpri(struct wlan_dfs *dfs, + struct dfs_delayline *dl, + struct dfs_filter *rf, + uint32_t lowpriindex, + uint32_t *scoreindex, + uint32_t primargin) +{ + uint32_t candidate_refpri, deltapri, lowpri; + uint32_t dindex_candidate, dindex_lowpri; + uint32_t i; + + dindex_candidate = (dl->dl_firstelem + *scoreindex) & DFS_MAX_DL_MASK; + dindex_lowpri = (dl->dl_firstelem + lowpriindex) & DFS_MAX_DL_MASK; + + candidate_refpri = dl->dl_elems[dindex_candidate].de_time; + lowpri = dl->dl_elems[dindex_lowpri].de_time; + + if (rf->rf_ignore_pri_window == 0 && + candidate_refpri != lowpri) { + for (i = 1; i <= dfs->dfs_pri_multiplier; i++) { + deltapri = DFS_DIFF(candidate_refpri, i * lowpri); + if (deltapri < primargin) { + *scoreindex = lowpriindex; + break; + } + } + } +} +#else +static inline void dfs_pick_lowpri(struct wlan_dfs *dfs, + struct dfs_delayline *dl, + struct dfs_filter *rf, + uint32_t lowpriindex, + uint32_t *scoreindex, + uint32_t primargin) +{ +} +#endif + /** * dfs_find_scoreindex() - Find score index * @rf: Pointer to dfs_filter structure. @@ -667,6 +717,18 @@ int dfs_bin_check( dfs_find_scoreindex(rf, highscore, lowpriindex, highscoreindex, &scoreindex); + /* + * Observed ETSI type2 while channel loading 31% with pulse pri: + * 1489, 2978, 2978, 2978, 1489, 2978, 1489 us. With above logic, + * the highscore will be 4 (2978), scoreindex is 5. In this case, + * index 0, 4, 6 pulses will be not matched later in + * dfs_count_the_other_delay_elements(), which leads to the radar was + * not detected. The fix is: compare the highscore pri with lowpri, + * if they have relationship, within primargin of + * [1, dfs_pri_multiplier] times of lowpri, choose lowpri as refpri. + */ + dfs_pick_lowpri(dfs, dl, rf, lowpriindex, &scoreindex, primargin); + /* We got the possible pri, save its parameters as reference. */ dfs_find_refs(dl, rf, scoreindex, &refdur, &refpri); @@ -802,8 +864,8 @@ static void dfs_count_the_other_delay_elements( int fundamentalpri) { int delayindex; - uint32_t searchpri, searchdur, deltadur, deltapri1, deltapri2; - uint32_t j = 0, delta_time_stamps, deltapri; + uint32_t searchpri, searchdur, deltadur; + uint32_t j = 0, delta_time_stamps, deltapri, k; int dindex, primatch, numpulsetochk = 2; int32_t sidx_min = DFS_BIG_SIDX; int32_t sidx_max = -DFS_BIG_SIDX; @@ -819,23 +881,30 @@ static void dfs_count_the_other_delay_elements( dl->dl_elems[dindex].de_time -= refpri; searchpri = refpri; } + searchdur = dl->dl_elems[delayindex].de_dur; deltadur = DFS_DIFF(searchdur, refdur); deltapri = DFS_DIFF(searchpri, refpri); - deltapri1 = DFS_DIFF(searchpri, refpri); - deltapri2 = DFS_DIFF(searchpri, 2 * refpri); primatch = 0; if ((rf->rf_ignore_pri_window > 0) && (rf->rf_patterntype != 2)) { for (j = 0; j < rf->rf_numpulses; j++) { - deltapri1 = DFS_DIFF(searchpri, (j + 1) * refpri); - if (deltapri1 < (2 * primargin)) { + deltapri = DFS_DIFF(searchpri, (j + 1) * refpri); + if (deltapri < (2 * primargin)) { primatch = 1; break; } } - } else if ((deltapri1 < primargin) || (deltapri2 < primargin)) { + } else if (rf->rf_patterntype == 2) { primatch = 1; + } else { + for (k = 1; k <= dfs->dfs_pri_multiplier; k++) { + deltapri = DFS_DIFF(searchpri, k * refpri); + if (deltapri < primargin) { + primatch = 1; + break; + } + } } if (primatch && (deltadur < durmargin)) { diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_init.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_init.c index 716d0d3852bed213a500c793e5360272c1104914..b5eaa3f40c142e96e0f31e6bae87a35d7e33c21d 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_init.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_init.c @@ -431,12 +431,61 @@ int dfs_check_etsi_overlap(int center_freq, int chan_width, chan_freq_high)); } +#ifdef CONFIG_CHAN_FREQ_API +bool dfs_is_en302_502_applicable(struct wlan_dfs *dfs) +{ + int chan_freq; + int chan_width; + int overlap = 0; + struct wlan_objmgr_vdev *vdev = NULL; + struct wlan_channel *bss_chan = NULL; + + /* Get centre frequency */ + chan_freq = dfs->dfs_curchan->dfs_ch_mhz_freq_seg1; + vdev = wlan_objmgr_pdev_get_first_vdev(dfs->dfs_pdev_obj, WLAN_DFS_ID); + if (!vdev) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "vdev is NULL"); + return false; + } + + bss_chan = wlan_vdev_mlme_get_bss_chan(vdev); + wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID); + /* Grab width */ + chan_width = wlan_reg_get_bw_value(bss_chan->ch_width); + + if (WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan)) { + /* HT80_80 mode has 2 segments and each segment must + * be checked for control channel first. + */ + overlap = dfs_check_etsi_overlap( + chan_freq, chan_width / 2, + ETSI_RADAR_EN302_502_FREQ_LOWER, + ETSI_RADAR_EN302_502_FREQ_UPPER); + + /* check for extension channel */ + chan_freq = dfs->dfs_curchan->dfs_ch_mhz_freq_seg2; + + overlap += dfs_check_etsi_overlap( + chan_freq, chan_width / 2, + ETSI_RADAR_EN302_502_FREQ_LOWER, + ETSI_RADAR_EN302_502_FREQ_UPPER); + } else { + overlap = dfs_check_etsi_overlap( + chan_freq, chan_width, + ETSI_RADAR_EN302_502_FREQ_LOWER, + ETSI_RADAR_EN302_502_FREQ_UPPER); + } + + return(wlan_reg_is_regdmn_en302502_applicable(dfs->dfs_pdev_obj) && + overlap); +} +#else +#ifdef CONFIG_CHAN_NUM_API bool dfs_is_en302_502_applicable(struct wlan_dfs *dfs) { int chan_freq; int chan_width; int overlap = 0; - uint16_t regdmn; struct wlan_objmgr_vdev *vdev = NULL; struct wlan_channel *bss_chan = NULL; @@ -478,11 +527,8 @@ bool dfs_is_en302_502_applicable(struct wlan_dfs *dfs) ETSI_RADAR_EN302_502_FREQ_UPPER); } - regdmn = utils_dfs_get_cur_rd(dfs->dfs_pdev_obj); - - return(((regdmn == ETSI11_WORLD_REGDMN_PAIR_ID) || - (regdmn == ETSI12_WORLD_REGDMN_PAIR_ID) || - (regdmn == ETSI13_WORLD_REGDMN_PAIR_ID) || - (regdmn == ETSI14_WORLD_REGDMN_PAIR_ID)) && + return(wlan_reg_is_regdmn_en302502_applicable(dfs->dfs_pdev_obj) && overlap); } +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_partial_offload_radar.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_partial_offload_radar.c index 4595f3db2b269436fbaf3f002ef222fd8fda9723..80f508aa80c81228151ecdce124a789df3adf9e7 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_partial_offload_radar.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_partial_offload_radar.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2011, Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -96,6 +96,16 @@ static struct dfs_pulse dfs_mkk4_radars[] = { {16, 15, 2000, 5000, 0, 4, 7, 11, 23, 22, 0, 3, 0, 5, 0, 11}, }; +/** + * struct dfs_pulse dfs_mkkn_radars - MKKN radar table for Offload chipsets. + */ +static struct dfs_pulse dfs_mkkn_radars[] = { + /** Since the table is empty no new radar type shall be detected. + * New filters shall be added to this tables after proper testing + * and verification. + */ +}; + /** * struct dfs_bin5pulse dfs_fcc_bin5pulses - FCC BIN5 pulses for Offload * chipsets. @@ -168,6 +178,14 @@ static struct dfs_pulse dfs_etsi_radars[] = { /* PRF 4500, 20us duration, 9 pulses per burst */ {9, 20, 4500, 4500, 1, 4, 5, 19, 21, 18, 0, 0, 1, 1000, 0, 41}, + /* Type 3 */ + /* 10 15us, 200-1000 PRF, 15 pulses */ + {15, 15, 200, 1000, 0, 4, 5, 8, 18, 22, 0, 0, 0, 5, 0, 42}, + + /* Type 4 */ + /* 1-15us, 1200-1600 PRF, 15 pulses */ + {15, 15, 1200, 1600, 0, 4, 5, 0, 18, 22, 0, 0, 0, 5, 0, 43}, + /* TYPE staggered pulse */ /* Type 5*/ /* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */ @@ -206,34 +224,34 @@ static struct dfs_pulse dfs_china_radars[] = { /* TYPE staggered pulse */ /* Type 5*/ /* 0.8-2us, 2-3 bursts,300-400 PRF, 12 pulses each */ - {36, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 51}, + {36, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 0, 0, 51}, /* Type 6 */ /* 0.8-2us, 2-3 bursts, 400-1200 PRF, 16 pulses each */ - {48, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 52}, + {48, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 0, 0, 52}, /* constant PRF based */ /* Type 1 */ /* 0.5-5us, 200 1000 PRF, 12 pulses */ - {12, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 53}, - {12, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 57}, - {12, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 58}, - {12, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 59}, + {12, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 0, 0, 53}, + {12, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 0, 0, 57}, + {12, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 0, 0, 58}, + {12, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 0, 0, 59}, /* Type 2 */ /* 0.5-15us, 200-1600 PRF, 16 pulses */ - {16, 15, 200, 1600, 0, 24, 8, 0, 18, 24, 0, 0, 0, 54}, + {16, 15, 200, 1600, 0, 24, 8, 0, 18, 24, 0, 0, 0, 0, 0, 54}, /* Type 3 */ /* 0.5-30us, 2300-4000 PRF, 24 pulses*/ - {24, 15, 2300, 4000, 0, 24, 10, 0, 33, 24, 0, 0, 0, 55}, + {24, 15, 2300, 4000, 0, 24, 10, 0, 33, 24, 0, 0, 0, 0, 0, 55}, /* Type 4 */ /* 20-30us, 2000-4000 PRF, 20 pulses*/ - {20, 30, 2000, 4000, 0, 24, 6, 19, 33, 24, 0, 0, 0, 56}, + {20, 30, 2000, 4000, 0, 24, 6, 19, 33, 24, 0, 0, 0, 0, 0, 56}, /* 1us, 1000 PRF, 20 pulses */ /* 1000 us PRI */ - {20, 1, 1000, 1000, 0, 6, 6, 0, 1, 18, 0, 3, 0, 50}, + {20, 1, 1000, 1000, 0, 6, 6, 0, 1, 18, 0, 3, 0, 0, 0, 50}, }; /** @@ -247,13 +265,14 @@ static struct dfs_pulse dfs_korea_radars[] = { {10, 1, 1800, 1800, 0, 4, 4, 0, 1, 18, 0, 3, 1, 5, 0, 41}, /* Korea Type 3 */ - {70, 1, 330, 330, 0, 4, 20, 0, 2, 18, 0, 3, 1, 5, 0, 42}, + {70, 1, 330, 330, 0, 4, 20, 0, 3, 18, 0, 3, 1, 5, 0, 42}, /* Korea Type 4 */ {3, 1, 3003, 3003, 1, 7, 2, 0, 1, 18, 0, 0, 1, 1000, 0, 43}, }; #define RSSI_THERSH_AR900B 15 +#define RSSI_THERSH_ADRASTEA 18 /** * dfs_assign_fcc_pulse_table() - Assign FCC pulse table @@ -284,6 +303,37 @@ static inline void dfs_assign_fcc_pulse_table( } } +#ifdef DFS_OVERRIDE_RF_THRESHOLD +static void dfs_set_adrastea_rf_thrshold( + struct wlan_objmgr_psoc *psoc, + int dfsdomain, + uint32_t target_type, + struct wlan_dfs_radar_tab_info *rinfo) +{ + int i; + struct wlan_lmac_if_target_tx_ops *tx_ops; + + tx_ops = &psoc->soc_cb.tx_ops.target_tx_ops; + + if (tx_ops->tgt_is_tgt_type_adrastea(target_type) && + dfsdomain == DFS_ETSI_DOMAIN) { + for (i = 0; i < rinfo->numradars; i++) { + rinfo->dfs_radars[i].rp_rssithresh = + DFS_MIN(rinfo->dfs_radars[i].rp_rssithresh, + RSSI_THERSH_ADRASTEA); + } + } +} +#else +static inline void dfs_set_adrastea_rf_thrshold( + struct wlan_objmgr_psoc *psoc, + int dfsdomain, + uint32_t target_type, + struct wlan_dfs_radar_tab_info *rinfo) +{ +} +#endif + void dfs_get_po_radars(struct wlan_dfs *dfs) { struct wlan_dfs_radar_tab_info rinfo; @@ -366,6 +416,14 @@ void dfs_get_po_radars(struct wlan_dfs *dfs) rinfo.b5pulses = NULL; rinfo.numb5radars = 0; break; + case DFS_MKKN_DOMAIN: + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "MKKN domain"); + rinfo.dfsdomain = DFS_MKKN_DOMAIN; + rinfo.dfs_radars = dfs_mkkn_radars; + rinfo.numradars = QDF_ARRAY_SIZE(dfs_mkkn_radars); + rinfo.b5pulses = NULL; + rinfo.numb5radars = 0; + break; case DFS_MKK4_DOMAIN: dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "MKK4 domain"); rinfo.dfsdomain = DFS_MKK4_DOMAIN; @@ -418,6 +476,8 @@ void dfs_get_po_radars(struct wlan_dfs *dfs) rinfo.dfs_radars[i].rp_rssithresh = RSSI_THERSH_AR900B; } + dfs_set_adrastea_rf_thrshold(psoc, dfsdomain, target_type, &rinfo); + WLAN_DFS_DATA_STRUCT_LOCK(dfs); dfs_init_radar_filters(dfs, &rinfo); WLAN_DFS_DATA_STRUCT_UNLOCK(dfs); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_phyerr_tlv.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_phyerr_tlv.c index 90f395900fe0e2374387ae9c0e6a748cf018fa1e..d67ea476962c940ea2aab293fecbe965a1a48531 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_phyerr_tlv.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_phyerr_tlv.c @@ -162,7 +162,6 @@ static void dfs_radar_summary_parse(struct wlan_dfs *dfs, MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_AGC_TOTAL_GAIN); rsu->agc_mb_gain = MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_AGC_MB_GAIN); - rsu->rssi = MS(rs[RADAR_REPORT_PULSE_REG_4], RADAR_REPORT_PULSE_RSSI); } /** @@ -446,6 +445,60 @@ static int dfs_tlv_parse_frame(struct wlan_dfs *dfs, * * Return: Returns the channel center. */ +#ifdef CONFIG_CHAN_FREQ_API +static int dfs_tlv_calc_freq_info(struct wlan_dfs *dfs, + struct rx_radar_status *rs) +{ + uint32_t chan_centre; + uint32_t chan_width; + int chan_offset; + + /* For now, just handle up to VHT80 correctly. */ + if (!dfs->dfs_curchan) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_curchan is null"); + return 0; + /* + * For now, the only 11ac channel with freq1/freq2 setup is + * VHT80. Should have a flag macro to check this! + */ + } else if (WLAN_IS_CHAN_11AC_VHT80(dfs->dfs_curchan)) { + /* + * 11AC, so cfreq1/cfreq2 are setup. + * If it's 80+80 this won't work - need to use seg + * appropriately! + */ + chan_centre = dfs->dfs_curchan->dfs_ch_mhz_freq_seg1; + } else { + /* + * HT20/HT40. + * This is hard-coded - it should be 5 or 10 for half/quarter + * appropriately. + */ + chan_width = 20; + + /* Grab default channel centre. */ + chan_centre = dfs->dfs_curchan->dfs_ch_freq; + + /* Calculate offset based on HT40U/HT40D and VHT40U/VHT40D. */ + if (WLAN_IS_CHAN_11N_HT40PLUS(dfs->dfs_curchan) || + (dfs->dfs_curchan->dfs_ch_flags & WLAN_CHAN_VHT40PLUS)) + chan_offset = chan_width; + else if (WLAN_IS_CHAN_11N_HT40MINUS(dfs->dfs_curchan) || + (dfs->dfs_curchan->dfs_ch_flags & + WLAN_CHAN_VHT40MINUS)) + chan_offset = -chan_width; + else + chan_offset = 0; + + /* Calculate new _real_ channel centre. */ + chan_centre += (chan_offset / 2); + } + + /* Return ev_chan_centre in MHz. */ + return chan_centre; +} +#else +#ifdef CONFIG_CHAN_NUM_API static int dfs_tlv_calc_freq_info(struct wlan_dfs *dfs, struct rx_radar_status *rs) { @@ -500,6 +553,9 @@ static int dfs_tlv_calc_freq_info(struct wlan_dfs *dfs, /* Return ev_chan_centre in MHz. */ return chan_centre; } +#endif +#endif + /** * dfs_tlv_calc_event_freq_pulse() - Calculate the centre frequency and diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_process_radarevent.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_process_radarevent.c index 350e9c68379fa242213076055a95dcd0a5063ce9..8e287bc4d22e1b0705fe293f847c30e2f2d53754 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_process_radarevent.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_process_radarevent.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2002-2010, Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -31,6 +31,16 @@ #include "wlan_dfs_lmac_api.h" #include "../dfs_partial_offload_radar.h" +#ifdef DFS_FCC_TYPE4_DURATION_CHECK +#define DFS_WAR_30_MHZ_SEPARATION 30 +#define DFS_WAR_PEAK_INDEX_ZERO 0 +#define DFS_TYPE4_WAR_PULSE_DURATION_LOWER_LIMIT 11 +#define DFS_TYPE4_WAR_PULSE_DURATION_UPPER_LIMIT 33 +#define DFS_TYPE4_WAR_PRI_LOWER_LIMIT 200 +#define DFS_TYPE4_WAR_PRI_UPPER_LIMIT 500 +#define DFS_TYPE4_WAR_VALID_PULSE_DURATION 12 +#endif + #define FREQ_5500_MHZ 5500 #define FREQ_5500_MHZ 5500 @@ -92,6 +102,58 @@ static inline uint8_t dfs_process_pulse_dur(struct wlan_dfs *dfs, return (uint8_t)dfs_round((int32_t)((dfs->dur_multiplier)*re_dur)); } +#ifdef DFS_FCC_TYPE4_DURATION_CHECK +/* + * dfs_dur_check() - Modify the pulse duration for FCC Type 4 and JAPAN W56 + * Type 8 radar pulses when the conditions mentioned in the + * function body are reported in the radar summary report. + * @dfs: Pointer to wlan_dfs structure. + * @chan: Current channel. + * @re: Pointer to dfs_event. + * @diff_ts: timestamp of current pulse - timestamp of last pulse. + * + * return: Void + */ +static inline void dfs_dur_check( + struct wlan_dfs *dfs, + struct dfs_channel *chan, + struct dfs_event *re, + uint32_t diff_ts) +{ + if ((dfs->dfsdomain == DFS_FCC_DOMAIN || + dfs->dfsdomain == DFS_MKK4_DOMAIN) && + ((chan->dfs_ch_flags & WLAN_CHAN_VHT80) == WLAN_CHAN_VHT80) && + (DFS_DIFF(chan->dfs_ch_freq, chan->dfs_ch_mhz_freq_seg1) == + DFS_WAR_30_MHZ_SEPARATION) && + re->re_sidx == DFS_WAR_PEAK_INDEX_ZERO && + (re->re_dur > DFS_TYPE4_WAR_PULSE_DURATION_LOWER_LIMIT && + re->re_dur < DFS_TYPE4_WAR_PULSE_DURATION_UPPER_LIMIT) && + (diff_ts > DFS_TYPE4_WAR_PRI_LOWER_LIMIT && + diff_ts < DFS_TYPE4_WAR_PRI_UPPER_LIMIT)) { + dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, + "chan flags=%llu, Pri Chan %d MHz center %d MHZ", + chan->dfs_ch_flags, + chan->dfs_ch_freq, chan->dfs_ch_mhz_freq_seg1); + + dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Report Peak Index = %d,re.re_dur = %d,diff_ts = %d", + re->re_sidx, re->re_dur, diff_ts); + + re->re_dur = DFS_TYPE4_WAR_VALID_PULSE_DURATION; + dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Modifying the pulse duration to %d", re->re_dur); + } +} +#else +static inline void dfs_dur_check( + struct wlan_dfs *dfs, + struct dfs_channel *chan, + struct dfs_event *re, + uint32_t diff_ts) +{ +} +#endif + /* * dfs_print_radar_events() - Prints the Radar events. * @dfs: Pointer to wlan_dfs structure. @@ -427,7 +489,9 @@ void __dfs_process_radarevent(struct wlan_dfs *dfs, (uint32_t) deltaT, re->re_dur, ext_chan_event_flag); - if (*found) { + if (*found && + (utils_get_dfsdomain(dfs->dfs_pdev_obj) != + DFS_CN_DOMAIN)) { ori_rf_check_delta_peak = rf->rf_check_delta_peak; /* @@ -574,6 +638,28 @@ static inline void dfs_radarfound_reset_vars( } } +/* + * dfs_print_radar_found_freq() - Print radar found frequency. + * @dfs: Pointer to wlan_dfs. + */ +#ifdef CONFIG_CHAN_FREQ_API +static void dfs_print_radar_found_freq(struct wlan_dfs *dfs) +{ + dfs_debug(dfs, WLAN_DEBUG_DFS, + "bangradar on 2nd segment cfreq = %u", + dfs->dfs_precac_secondary_freq_mhz); +} +#else +#ifdef CONFIG_CHAN_NUM_API +static void dfs_print_radar_found_freq(struct wlan_dfs *dfs) +{ + dfs_debug(dfs, WLAN_DEBUG_DFS, + "bangradar on 2nd segment cfreq = %u", + dfs->dfs_precac_secondary_freq); +} +#endif +#endif + /** * dfs_handle_bangradar - Handle the case of bangradar * @dfs: Pointer to wlan_dfs structure. @@ -606,9 +692,7 @@ static inline int dfs_handle_bangradar( WLAN_IS_CHAN_11AC_VHT160(chan) || WLAN_IS_CHAN_11AC_VHT80_80(chan)) { dfs->is_radar_found_on_secondary_seg = 1; - dfs_debug(dfs, WLAN_DEBUG_DFS, - "bangradar on 2nd segment cfreq = %u", - dfs->dfs_precac_secondary_freq); + dfs_print_radar_found_freq(dfs); } else { dfs_debug(dfs, WLAN_DEBUG_DFS, "No second segment"); @@ -1239,6 +1323,8 @@ static inline int dfs_process_each_radarevent( dfs_add_to_pulseline(dfs, &re, &this_ts, &test_ts, &diff_ts, &index); + dfs_dur_check(dfs, chan, &re, diff_ts); + dfs_log_event(dfs, &re, this_ts, diff_ts, index); dfs_conditional_clear_delaylines(dfs, diff_ts, this_ts, re); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_radar.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_radar.c index 922a33a16213fed59f8b44f03c020bfd0ae8b53d..fae38b0cd719f39e51b6a50f74ee34e6462494c7 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_radar.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_radar.c @@ -61,6 +61,80 @@ void dfs_phyerr_param_copy(struct wlan_dfs_phyerr_param *dst, qdf_mem_copy(dst, src, sizeof(*dst)); } +#ifdef CONFIG_CHAN_FREQ_API +struct dfs_state *dfs_getchanstate(struct wlan_dfs *dfs, uint8_t *index, + int ext_chan_flag) +{ + struct dfs_state *rs = NULL; + struct dfs_channel *ch, cmp_ch1; + int i; + QDF_STATUS err; + + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return NULL; + } + ch = &cmp_ch1; + if (ext_chan_flag) { + err = dfs_mlme_get_extchan_for_freq( + dfs->dfs_pdev_obj, + &ch->dfs_ch_freq, + &ch->dfs_ch_flags, + &ch->dfs_ch_flagext, + &ch->dfs_ch_ieee, + &ch->dfs_ch_vhtop_ch_freq_seg1, + &ch->dfs_ch_vhtop_ch_freq_seg2, + &ch->dfs_ch_mhz_freq_seg1, + &ch->dfs_ch_mhz_freq_seg2); + + if (err == QDF_STATUS_SUCCESS) { + dfs_debug(dfs, WLAN_DEBUG_DFS2, + "Extension channel freq = %u flags=0x%x", + ch->dfs_ch_freq, + ch->dfs_ch_flagext); + } else { + return NULL; + } + } else { + ch = dfs->dfs_curchan; + dfs_debug(dfs, WLAN_DEBUG_DFS2, + "Primary channel freq = %u flags=0x%x", + ch->dfs_ch_freq, ch->dfs_ch_flagext); + } + + for (i = 0; i < DFS_NUM_RADAR_STATES; i++) { + if ((dfs->dfs_radar[i].rs_chan.dfs_ch_freq == + ch->dfs_ch_freq) && + (dfs->dfs_radar[i].rs_chan.dfs_ch_flags == + ch->dfs_ch_flags)) { + if (index) + *index = (uint8_t)i; + return &dfs->dfs_radar[i]; + } + } + /* No existing channel found, look for first free channel state entry.*/ + for (i = 0; i < DFS_NUM_RADAR_STATES; i++) { + if (dfs->dfs_radar[i].rs_chan.dfs_ch_freq == 0) { + rs = &dfs->dfs_radar[i]; + /* Found one, set channel info and default thresholds.*/ + rs->rs_chan = *ch; + + /* Copy the parameters from the default set. */ + dfs_phyerr_param_copy(&rs->rs_param, + &dfs->dfs_defaultparams); + + if (index) + *index = (uint8_t)i; + + return rs; + } + } + dfs_debug(dfs, WLAN_DEBUG_DFS2, "No more radar states left."); + + return NULL; +} +#else +#ifdef CONFIG_CHAN_NUM_API struct dfs_state *dfs_getchanstate(struct wlan_dfs *dfs, uint8_t *index, int ext_chan_flag) { @@ -129,7 +203,103 @@ struct dfs_state *dfs_getchanstate(struct wlan_dfs *dfs, uint8_t *index, return NULL; } +#endif +#endif +#ifdef CONFIG_CHAN_FREQ_API +void dfs_radar_enable(struct wlan_dfs *dfs, int no_cac, uint32_t opmode) +{ + int is_ext_ch; + int is_fastclk = 0; + struct dfs_channel *exch, extchan; + QDF_STATUS err = QDF_STATUS_E_FAILURE; + + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + is_ext_ch = WLAN_IS_CHAN_11N_HT40(dfs->dfs_curchan); + lmac_dfs_disable(dfs->dfs_pdev_obj, no_cac); + /* + * In all modes, if the primary is DFS then we have to + * enable radar detection. In HT80_80, we can have + * primary non-DFS 80MHz with extension 80MHz DFS. + */ + if ((WLAN_IS_CHAN_DFS(dfs->dfs_curchan) || + ((WLAN_IS_CHAN_11AC_VHT160(dfs->dfs_curchan) || + WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan)) && + WLAN_IS_CHAN_DFS_CFREQ2(dfs->dfs_curchan))) || + (dfs_is_precac_timer_running(dfs))) { + struct dfs_state *rs_pri = NULL, *rs_ext = NULL; + uint8_t index_pri, index_ext; + + dfs->dfs_proc_phyerr |= DFS_AR_EN; + dfs->dfs_proc_phyerr |= DFS_RADAR_EN; + dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN; + + exch = &extchan; + if (is_ext_ch) { + err = dfs_mlme_get_extchan_for_freq + ( + dfs->dfs_pdev_obj, + &exch->dfs_ch_freq, + &exch->dfs_ch_flags, + &exch->dfs_ch_flagext, + &exch->dfs_ch_ieee, + &exch->dfs_ch_vhtop_ch_freq_seg1, + &exch->dfs_ch_vhtop_ch_freq_seg2, + &exch->dfs_ch_mhz_freq_seg1, + &exch->dfs_ch_mhz_freq_seg2); + } + dfs_reset_alldelaylines(dfs); + + rs_pri = dfs_getchanstate(dfs, &index_pri, 0); + if (err == QDF_STATUS_SUCCESS) + rs_ext = dfs_getchanstate(dfs, &index_ext, 1); + + if (rs_pri && ((err == QDF_STATUS_E_FAILURE) || (rs_ext))) { + struct wlan_dfs_phyerr_param pe; + + qdf_mem_set(&pe, sizeof(pe), '\0'); + + if (index_pri != dfs->dfs_curchan_radindex) + dfs_reset_alldelaylines(dfs); + + dfs->dfs_curchan_radindex = (int16_t)index_pri; + + if (rs_ext) + dfs->dfs_extchan_radindex = (int16_t)index_ext; + + dfs_phyerr_param_copy(&pe, &rs_pri->rs_param); + dfs_debug(dfs, WLAN_DEBUG_DFS3, + "firpwr=%d, rssi=%d, height=%d, prssi=%d, inband=%d, relpwr=%d, relstep=%d, maxlen=%d", + pe.pe_firpwr, + pe.pe_rrssi, pe.pe_height, + pe.pe_prssi, pe.pe_inband, + pe.pe_relpwr, pe.pe_relstep, + pe.pe_maxlen); + + lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk, + &pe, dfs->dfsdomain); + dfs_debug(dfs, WLAN_DEBUG_DFS, + "Enabled radar detection on channel %d", + dfs->dfs_curchan->dfs_ch_freq); + + dfs->dur_multiplier = is_fastclk ? + DFS_FAST_CLOCK_MULTIPLIER : + DFS_NO_FAST_CLOCK_MULTIPLIER; + + dfs_debug(dfs, WLAN_DEBUG_DFS3, + "duration multiplier is %d", + dfs->dur_multiplier); + } else + dfs_debug(dfs, WLAN_DEBUG_DFS, + "No more radar states left"); + } +} +#else +#ifdef CONFIG_CHAN_NUM_API void dfs_radar_enable(struct wlan_dfs *dfs, int no_cac, uint32_t opmode) { int is_ext_ch; @@ -220,6 +390,8 @@ void dfs_radar_enable(struct wlan_dfs *dfs, int no_cac, uint32_t opmode) "No more radar states left"); } } +#endif +#endif int dfs_set_thresholds(struct wlan_dfs *dfs, const uint32_t threshtype, const uint32_t value) diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs.c index d69592f7beda953b12311a00633fed49e00d7bdd..e05d6be2c5fbe4713e0db6c5ea38afd474acf012 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2002-2006, Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -31,7 +31,7 @@ #include "../dfs_full_offload.h" #include #include "wlan_dfs_utils_api.h" -#include "../dfs_etsi_precac.h" +#include "../dfs_process_radar_found_ind.h" #include "../dfs_partial_offload_radar.h" /* Disable NOL in FW. */ @@ -69,15 +69,20 @@ static inline struct dfs_channel *dfs_alloc_dfs_curchan(void) return qdf_mem_malloc(sizeof(struct dfs_channel)); } +static inline struct dfs_channel *dfs_alloc_dfs_prevchan(void) +{ + return qdf_mem_malloc(sizeof(struct dfs_channel)); +} + /* - * dfs_free_dfs_curchan() - Free dfs_channel buffer - * @dfs_curchan: dfs_channel buffer pointer + * dfs_free_dfs_chan() - Free dfs_channel buffer + * @dfs_chan: dfs_channel buffer pointer * * Return: None */ -static inline void dfs_free_dfs_curchan(struct dfs_channel *dfs_curchan) +static inline void dfs_free_dfs_chan(struct dfs_channel *dfs_chan) { - qdf_mem_free(dfs_curchan); + qdf_mem_free(dfs_chan); } #else @@ -85,6 +90,7 @@ static inline void dfs_free_dfs_curchan(struct dfs_channel *dfs_curchan) /* Static buffers for DFS objects */ static struct wlan_dfs global_dfs; static struct dfs_channel global_dfs_curchan; +static struct dfs_channel global_dfs_prevchan; static inline struct wlan_dfs *dfs_alloc_wlan_dfs(void) { @@ -100,7 +106,12 @@ static inline struct dfs_channel *dfs_alloc_dfs_curchan(void) return &global_dfs_curchan; } -static inline void dfs_free_dfs_curchan(struct dfs_channel *dfs_curchan) +static inline struct dfs_channel *dfs_alloc_dfs_prevchan(void) +{ + return &global_dfs_prevchan; +} + +static inline void dfs_free_dfs_chan(struct dfs_channel *dfs_chan) { } #endif @@ -112,6 +123,28 @@ static inline void dfs_free_dfs_curchan(struct dfs_channel *dfs_curchan) * channel as RADAR and does not add the channel to NOL. It sends the CSA in * the current channel. */ +#ifdef CONFIG_CHAN_FREQ_API +static os_timer_func(dfs_testtimer_task) +{ + struct wlan_dfs *dfs = NULL; + + OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); + dfs->wlan_dfstest = 0; + + /* + * Flip the channel back to the original channel. + * Make sure this is done properly with a CSA. + */ + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "go back to channel %d", + dfs->wlan_dfstest_ieeechan); + dfs_mlme_start_csa_for_freq(dfs->dfs_pdev_obj, + dfs->wlan_dfstest_ieeechan, + dfs->dfs_curchan->dfs_ch_freq, + dfs->dfs_curchan->dfs_ch_mhz_freq_seg2, + dfs->dfs_curchan->dfs_ch_flags); +} +#else +#ifdef CONFIG_CHAN_NUM_API static os_timer_func(dfs_testtimer_task) { struct wlan_dfs *dfs = NULL; @@ -131,6 +164,8 @@ static os_timer_func(dfs_testtimer_task) dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2, dfs->dfs_curchan->dfs_ch_flags); } +#endif +#endif int dfs_get_debug_info(struct wlan_dfs *dfs, void *data) { @@ -162,6 +197,12 @@ int dfs_create_object(struct wlan_dfs **dfs) return 1; } + (*dfs)->dfs_prevchan = dfs_alloc_dfs_prevchan(); + if (!((*dfs)->dfs_prevchan)) { + dfs_free_wlan_dfs(*dfs); + return 1; + } + qdf_mem_zero((*dfs)->dfs_prevchan, sizeof(struct dfs_channel)); return 0; } @@ -185,9 +226,8 @@ int dfs_attach(struct wlan_dfs *dfs) return ret; } } - dfs_cac_attach(dfs); + dfs_cac_timer_attach(dfs); dfs_zero_cac_attach(dfs); - dfs_etsi_precac_attach(dfs); dfs_nol_attach(dfs); /* @@ -257,13 +297,13 @@ void dfs_detach(struct wlan_dfs *dfs) dfs_main_detach(dfs); dfs_zero_cac_detach(dfs); dfs_nol_detach(dfs); - dfs_etsi_precac_detach(dfs); } #ifndef WLAN_DFS_STATIC_MEM_ALLOC void dfs_destroy_object(struct wlan_dfs *dfs) { - dfs_free_dfs_curchan(dfs->dfs_curchan); + dfs_free_dfs_chan(dfs->dfs_prevchan); + dfs_free_dfs_chan(dfs->dfs_curchan); dfs_free_wlan_dfs(dfs); } #else @@ -700,11 +740,29 @@ int dfs_control(struct wlan_dfs *dfs, break; case DFS_SHOW_PRECAC_LISTS: dfs_print_precaclists(dfs); - dfs_print_etsi_precaclists(dfs); break; case DFS_RESET_PRECAC_LISTS: dfs_reset_precac_lists(dfs); - dfs_reset_etsi_precac_lists(dfs); + break; + case DFS_INJECT_SEQUENCE: + error = dfs_inject_synthetic_pulse_sequence(dfs, indata); + if (error) + dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Not injected Synthetic pulse"); + break; + + case DFS_ALLOW_HW_PULSES: + if (insize < sizeof(u_int8_t) || !indata) { + error = -EINVAL; + break; + } + dfs_allow_hw_pulses(dfs, !!(*(u_int8_t *)indata)); + break; + case DFS_SET_PRI_MULTIPILER: + dfs->dfs_pri_multiplier = *(int *)indata; + dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Set dfs pri multiplier to %d, dfsdomain %d", + dfs->dfs_pri_multiplier, dfs->dfsdomain); break; default: error = -EINVAL; @@ -714,6 +772,40 @@ int dfs_control(struct wlan_dfs *dfs, return error; } +/** + * dfs_is_curchan_same_as_given_chan() - Find if dfs_curchan has the same + * channel parameters provided. + * @dfs_curchan: Pointer to DFS current channel structure. + * @dfs_ch_freq: New curchan's primary frequency. + * @dfs_ch_flags: New curchan's channel flags. + * @dfs_ch_flagext: New curchan's channel flags extension. + * @dfs_ch_vhtop_ch_freq_seg1: New curchan's primary centre IEEE. + * @dfs_ch_vhtop_ch_freq_seg2: New curchan's secondary centre IEEE. + * + * Return: True if curchan has the same channel parameters of the given channel, + * else false. + */ +static bool +dfs_is_curchan_same_as_given_chan(struct dfs_channel *dfs_curchan, + uint16_t dfs_ch_freq, + uint64_t dfs_ch_flags, + uint16_t dfs_ch_flagext, + uint8_t dfs_ch_vhtop_ch_freq_seg1, + uint8_t dfs_ch_vhtop_ch_freq_seg2) +{ + if ((dfs_curchan->dfs_ch_freq == dfs_ch_freq) && + (dfs_curchan->dfs_ch_flags == dfs_ch_flags) && + (dfs_curchan->dfs_ch_flagext == dfs_ch_flagext) && + (dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 == + dfs_ch_vhtop_ch_freq_seg1) && + (dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 == + dfs_ch_vhtop_ch_freq_seg2)) + return true; + + return false; +} + +#ifdef CONFIG_CHAN_NUM_API void dfs_set_current_channel(struct wlan_dfs *dfs, uint16_t dfs_ch_freq, uint64_t dfs_ch_flags, @@ -727,6 +819,29 @@ void dfs_set_current_channel(struct wlan_dfs *dfs, return; } + if (!dfs->dfs_curchan) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_curchan is NULL"); + return; + } + + /* Check if the input parameters are the same as that of dfs_curchan */ + if (dfs_is_curchan_same_as_given_chan(dfs->dfs_curchan, + dfs_ch_freq, + dfs_ch_flags, + dfs_ch_flagext, + dfs_ch_vhtop_ch_freq_seg1, + dfs_ch_vhtop_ch_freq_seg2)) { + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, + "dfs_curchan already updated"); + return; + } + + /* Update dfs previous channel with the old dfs_curchan, if it exists */ + if (dfs->dfs_curchan->dfs_ch_freq) + qdf_mem_copy(dfs->dfs_prevchan, + dfs->dfs_curchan, + sizeof(struct dfs_channel)); + dfs->dfs_curchan->dfs_ch_freq = dfs_ch_freq; dfs->dfs_curchan->dfs_ch_flags = dfs_ch_flags; dfs->dfs_curchan->dfs_ch_flagext = dfs_ch_flagext; @@ -734,6 +849,53 @@ void dfs_set_current_channel(struct wlan_dfs *dfs, dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 = dfs_ch_vhtop_ch_freq_seg1; dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 = dfs_ch_vhtop_ch_freq_seg2; } +#endif + +#ifdef CONFIG_CHAN_FREQ_API +void dfs_set_current_channel_for_freq(struct wlan_dfs *dfs, + uint16_t dfs_chan_freq, + uint64_t dfs_chan_flags, + uint16_t dfs_chan_flagext, + uint8_t dfs_chan_ieee, + uint8_t dfs_chan_vhtop_freq_seg1, + uint8_t dfs_chan_vhtop_freq_seg2, + uint16_t dfs_chan_mhz_freq_seg1, + uint16_t dfs_chan_mhz_freq_seg2) + +{ + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + /* Check if the input parameters are the same as that of dfs_curchan */ + if (dfs_is_curchan_same_as_given_chan(dfs->dfs_curchan, + dfs_chan_freq, + dfs_chan_flags, + dfs_chan_flagext, + dfs_chan_vhtop_freq_seg1, + dfs_chan_vhtop_freq_seg2)) { + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, + "dfs_curchan already updated"); + return; + } + + /* Update dfs previous channel with the old dfs_curchan, if it exists */ + if (dfs->dfs_curchan->dfs_ch_freq) + qdf_mem_copy(dfs->dfs_prevchan, + dfs->dfs_curchan, + sizeof(struct dfs_channel)); + + dfs->dfs_curchan->dfs_ch_freq = dfs_chan_freq; + dfs->dfs_curchan->dfs_ch_flags = dfs_chan_flags; + dfs->dfs_curchan->dfs_ch_flagext = dfs_chan_flagext; + dfs->dfs_curchan->dfs_ch_ieee = dfs_chan_ieee; + dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 = dfs_chan_vhtop_freq_seg1; + dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 = dfs_chan_vhtop_freq_seg2; + dfs->dfs_curchan->dfs_ch_mhz_freq_seg1 = dfs_chan_mhz_freq_seg1; + dfs->dfs_curchan->dfs_ch_mhz_freq_seg2 = dfs_chan_mhz_freq_seg2; +} +#endif void dfs_update_cur_chan_flags(struct wlan_dfs *dfs, uint64_t flags, @@ -742,3 +904,40 @@ void dfs_update_cur_chan_flags(struct wlan_dfs *dfs, dfs->dfs_curchan->dfs_ch_flags = flags; dfs->dfs_curchan->dfs_ch_flagext = flagext; } + +int dfs_reinit_timers(struct wlan_dfs *dfs) +{ + dfs_cac_timer_attach(dfs); + dfs_zero_cac_timer_init(dfs->dfs_soc_obj); + dfs_nol_timer_init(dfs); + dfs_main_task_testtimer_init(dfs); + return 0; +} + +void dfs_reset_dfs_prevchan(struct wlan_dfs *dfs) +{ + qdf_mem_zero(dfs->dfs_prevchan, sizeof(struct dfs_channel)); +} + +bool dfs_is_hw_mode_switch_in_progress(struct wlan_dfs *dfs) +{ + return lmac_dfs_is_hw_mode_switch_in_progress(dfs->dfs_pdev_obj); +} + +void dfs_complete_deferred_tasks(struct wlan_dfs *dfs) +{ + if (dfs->dfs_defer_params.is_radar_detected) { + /* Handle radar event that was deferred and free the temporary + * storage of the radar event parameters. + */ + dfs_process_radar_ind(dfs, dfs->dfs_defer_params.radar_params); + qdf_mem_free(dfs->dfs_defer_params.radar_params); + dfs->dfs_defer_params.is_radar_detected = false; + } else if (dfs->dfs_defer_params.is_cac_completed) { + /* Handle CAC completion event that was deferred for HW mode + * switch. + */ + dfs_process_cac_completion(dfs); + dfs->dfs_defer_params.is_cac_completed = false; + } +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_cac.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_cac.c index f5dc99db66f644adae74ff9f4dbfc30c01680ac5..0bbeb00858ce23851bcbb15b03edee2c889696bd 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_cac.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_cac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting * All rights reserved. * @@ -30,7 +30,6 @@ #include "../dfs_channel.h" #include "../dfs_zero_cac.h" -#include "../dfs_etsi_precac.h" #include #include "wlan_dfs_utils_api.h" #include "wlan_dfs_mlme_api.h" @@ -65,6 +64,7 @@ int dfs_get_override_cac_timeout(struct wlan_dfs *dfs, int *cac_timeout) return 0; } +#ifdef CONFIG_CHAN_NUM_API void dfs_cac_valid_reset(struct wlan_dfs *dfs, uint8_t prevchan_ieee, uint32_t prevchan_flags) @@ -80,6 +80,24 @@ void dfs_cac_valid_reset(struct wlan_dfs *dfs, } } } +#endif + +#ifdef CONFIG_CHAN_FREQ_API +void dfs_cac_valid_reset_for_freq(struct wlan_dfs *dfs, + uint16_t prevchan_freq, + uint32_t prevchan_flags) +{ + if (dfs->dfs_cac_valid_time) { + if ((prevchan_freq != dfs->dfs_curchan->dfs_ch_freq) || + (prevchan_flags != dfs->dfs_curchan->dfs_ch_flags)) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Cancelling timer & clearing cac_valid"); + qdf_timer_stop(&dfs->dfs_cac_valid_timer); + dfs->dfs_cac_valid = 0; + } + } +} +#endif /** * dfs_cac_valid_timeout() - Timeout function for dfs_cac_valid_timer @@ -94,14 +112,107 @@ static os_timer_func(dfs_cac_valid_timeout) dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, ": Timed out!!"); } +/** + * dfs_clear_cac_started_chan() - Clear dfs cac started channel. + * @dfs: Pointer to wlan_dfs structure. + */ +static void dfs_clear_cac_started_chan(struct wlan_dfs *dfs) +{ + qdf_mem_zero(&dfs->dfs_cac_started_chan, + sizeof(dfs->dfs_cac_started_chan)); +} + +void dfs_process_cac_completion(struct wlan_dfs *dfs) +{ + enum phy_ch_width ch_width = CH_WIDTH_INVALID; + uint16_t primary_chan_freq = 0, secondary_chan_freq = 0; + struct dfs_channel *dfs_curchan; + + dfs->dfs_cac_timer_running = 0; + dfs_curchan = dfs->dfs_curchan; + + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "cac expired, chan %d cur time %d", + dfs->dfs_curchan->dfs_ch_freq, + (qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000)); + + /* + * When radar is detected during a CAC we are woken up prematurely to + * switch to a new channel. Check the channel to decide how to act. + */ + if (WLAN_IS_CHAN_RADAR(dfs->dfs_curchan)) { + dfs_mlme_mark_dfs_for_freq(dfs->dfs_pdev_obj, + dfs_curchan->dfs_ch_ieee, + dfs_curchan->dfs_ch_freq, + dfs_curchan->dfs_ch_mhz_freq_seg2, + dfs_curchan->dfs_ch_flags); + dfs_debug(dfs, WLAN_DEBUG_DFS, + "CAC timer on chan %u (%u MHz) stopped due to radar", + dfs_curchan->dfs_ch_ieee, + dfs_curchan->dfs_ch_freq); + } else { + dfs_debug(dfs, WLAN_DEBUG_DFS, + "CAC timer on channel %u (%u MHz) expired;" + "no radar detected", + dfs_curchan->dfs_ch_ieee, + dfs_curchan->dfs_ch_freq); + + /* On CAC completion, set the bit 'cac_valid'. + * CAC will not be re-done if this bit is reset. + * The flag will be reset when dfs_cac_valid_timer + * timesout. + */ + if (dfs->dfs_cac_valid_time) { + dfs->dfs_cac_valid = 1; + qdf_timer_mod(&dfs->dfs_cac_valid_timer, + dfs->dfs_cac_valid_time * 1000); + } + + dfs_find_chwidth_and_center_chan_for_freq(dfs, + &ch_width, + &primary_chan_freq, + &secondary_chan_freq); + /* Mark the current channel as preCAC done */ + dfs_mark_precac_done_for_freq(dfs, primary_chan_freq, + secondary_chan_freq, ch_width); + } + + dfs_clear_cac_started_chan(dfs); + /* Iterate over the nodes, processing the CAC completion event. */ + dfs_mlme_proc_cac(dfs->dfs_pdev_obj, 0); + + /* Send a CAC timeout, VAP up event to user space */ + dfs_mlme_deliver_event_up_after_cac(dfs->dfs_pdev_obj); + + if (dfs->dfs_defer_precac_channel_change == 1) { + dfs_mlme_channel_change_by_precac(dfs->dfs_pdev_obj); + dfs->dfs_defer_precac_channel_change = 0; + } +} + /** * dfs_cac_timeout() - DFS cactimeout function. * * Sets dfs_cac_timer_running to 0 and dfs_cac_valid_timer. */ +#ifdef CONFIG_CHAN_FREQ_API +static os_timer_func(dfs_cac_timeout) +{ + struct wlan_dfs *dfs = NULL; + + OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); + + if (dfs_is_hw_mode_switch_in_progress(dfs)) + dfs->dfs_defer_params.is_cac_completed = true; + else + dfs_process_cac_completion(dfs); +} +#else +#ifdef CONFIG_CHAN_NUM_API static os_timer_func(dfs_cac_timeout) { struct wlan_dfs *dfs = NULL; + enum phy_ch_width ch_width = CH_WIDTH_INVALID; + uint8_t primary_chan_ieee = 0, secondary_chan_ieee = 0; OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); dfs->dfs_cac_timer_running = 0; @@ -110,10 +221,6 @@ static os_timer_func(dfs_cac_timeout) dfs->dfs_curchan->dfs_ch_freq, (qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000)); - /* Once CAC is done, add channel to ETSI precacdone list*/ - if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) - dfs_add_to_etsi_precac_done_list(dfs); - /* * When radar is detected during a CAC we are woken up prematurely to * switch to a new channel. Check the channel to decide how to act. @@ -144,8 +251,17 @@ static os_timer_func(dfs_cac_timeout) qdf_timer_mod(&dfs->dfs_cac_valid_timer, dfs->dfs_cac_valid_time * 1000); } + + dfs_find_chwidth_and_center_chan(dfs, + &ch_width, + &primary_chan_ieee, + &secondary_chan_ieee); + /* Mark the current channel as preCAC done */ + dfs_mark_precac_done(dfs, primary_chan_ieee, + secondary_chan_ieee, ch_width); } + dfs_clear_cac_started_chan(dfs); /* Iterate over the nodes, processing the CAC completion event. */ dfs_mlme_proc_cac(dfs->dfs_pdev_obj, 0); @@ -157,9 +273,13 @@ static os_timer_func(dfs_cac_timeout) dfs->dfs_defer_precac_channel_change = 0; } } +#endif +#endif -void dfs_cac_timer_init(struct wlan_dfs *dfs) +void dfs_cac_timer_attach(struct wlan_dfs *dfs) { + dfs->dfs_cac_timeout_override = -1; + dfs->wlan_dfs_cac_time = WLAN_DFS_WAIT_MS; qdf_timer_init(NULL, &(dfs->dfs_cac_timer), dfs_cac_timeout, @@ -173,21 +293,12 @@ void dfs_cac_timer_init(struct wlan_dfs *dfs) QDF_TIMER_TYPE_WAKE_APPS); } -void dfs_cac_attach(struct wlan_dfs *dfs) -{ - dfs->dfs_cac_timeout_override = -1; - dfs->wlan_dfs_cac_time = WLAN_DFS_WAIT_MS; - dfs_cac_timer_init(dfs); -} - void dfs_cac_timer_reset(struct wlan_dfs *dfs) { qdf_timer_stop(&dfs->dfs_cac_timer); dfs_get_override_cac_timeout(dfs, &(dfs->dfs_cac_timeout_override)); - qdf_mem_zero(&dfs->dfs_cac_started_chan, - sizeof(dfs->dfs_cac_started_chan)); - + dfs_clear_cac_started_chan(dfs); } void dfs_cac_timer_detach(struct wlan_dfs *dfs) @@ -203,6 +314,31 @@ int dfs_is_ap_cac_timer_running(struct wlan_dfs *dfs) return dfs->dfs_cac_timer_running; } +#ifdef CONFIG_CHAN_FREQ_API +void dfs_start_cac_timer(struct wlan_dfs *dfs) +{ + int cac_timeout = 0; + struct dfs_channel *chan = dfs->dfs_curchan; + + cac_timeout = + dfs_mlme_get_cac_timeout_for_freq(dfs->dfs_pdev_obj, + chan->dfs_ch_freq, + chan->dfs_ch_mhz_freq_seg2, + chan->dfs_ch_flags); + + dfs->dfs_cac_started_chan = *chan; + + dfs_debug(dfs, WLAN_DEBUG_DFS, + "chan = %d cfreq2 = %d timeout = %d sec, curr_time = %d sec", + chan->dfs_ch_ieee, chan->dfs_ch_vhtop_ch_freq_seg2, + cac_timeout, + qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000); + + qdf_timer_mod(&dfs->dfs_cac_timer, cac_timeout * 1000); + dfs->dfs_cac_aborted = 0; +} +#else +#ifdef CONFIG_CHAN_NUM_API void dfs_start_cac_timer(struct wlan_dfs *dfs) { int cac_timeout = 0; @@ -224,10 +360,13 @@ void dfs_start_cac_timer(struct wlan_dfs *dfs) qdf_timer_mod(&dfs->dfs_cac_timer, cac_timeout * 1000); dfs->dfs_cac_aborted = 0; } +#endif +#endif void dfs_cancel_cac_timer(struct wlan_dfs *dfs) { qdf_timer_stop(&dfs->dfs_cac_timer); + dfs_clear_cac_started_chan(dfs); } void dfs_cac_stop(struct wlan_dfs *dfs) @@ -241,6 +380,7 @@ void dfs_cac_stop(struct wlan_dfs *dfs) qdf_timer_stop(&dfs->dfs_cac_timer); if (dfs->dfs_cac_timer_running) dfs->dfs_cac_aborted = 1; + dfs_clear_cac_started_chan(dfs); dfs->dfs_cac_timer_running = 0; } @@ -252,49 +392,29 @@ void dfs_stacac_stop(struct wlan_dfs *dfs) dfs_debug(dfs, WLAN_DEBUG_DFS, "Stopping STA CAC Timer %d procphyerr 0x%08x", dfs->dfs_curchan->dfs_ch_freq, phyerr); + dfs_clear_cac_started_chan(dfs); } -bool dfs_is_subset_channel(struct wlan_dfs *dfs, - struct dfs_channel *old_chan, - struct dfs_channel *new_chan) +/* + * dfs_is_subset_channel_for_freq() - Find out if prev channel and current + * channel are subsets of each other. + * @old_subchans_freq: Pointer to previous sub-channels freq. + * @old_n_chans: Number of previous sub-channels. + * @new_subchans_freq: Pointer to new sub-channels freq. + * @new_n_chans: Number of new sub-channels + */ +#ifdef CONFIG_CHAN_FREQ_API +static bool +dfs_is_subset_channel_for_freq(uint16_t *old_subchans_freq, + uint8_t old_n_chans, + uint16_t *new_subchans_freq, + uint8_t new_n_chans) { - uint8_t old_subchans[NUM_CHANNELS_160MHZ]; - uint8_t new_subchans[NUM_CHANNELS_160MHZ]; - uint8_t old_n_chans; - uint8_t new_n_chans; - int i = 0, j = 0; - bool is_found = false; - - if (WLAN_IS_CHAN_11AC_VHT160(old_chan) || - WLAN_IS_CHAN_11AC_VHT80_80(old_chan)) { - /* If primary segment is NON-DFS */ - if (!WLAN_IS_CHAN_DFS(old_chan)) - old_n_chans = dfs_get_bonding_channels(dfs, - old_chan, - SEG_ID_SECONDARY, - old_subchans); - else - old_n_chans = dfs_get_bonding_channels_without_seg_info( - old_chan, old_subchans); - } else { - old_n_chans = dfs_get_bonding_channels_without_seg_info( - old_chan, old_subchans); - } + bool is_found; + int i, j; - if (WLAN_IS_CHAN_11AC_VHT160(new_chan) || - WLAN_IS_CHAN_11AC_VHT80_80(new_chan)) { - /* If primary segment is NON-DFS */ - if (WLAN_IS_CHAN_DFS(new_chan)) - new_n_chans = dfs_get_bonding_channels( - dfs, new_chan, SEG_ID_SECONDARY, - new_subchans); - else - new_n_chans = dfs_get_bonding_channels_without_seg_info( - new_chan, new_subchans); - } else { - new_n_chans = dfs_get_bonding_channels_without_seg_info( - new_chan, new_subchans); - } + if (!new_n_chans) + return true; if (new_n_chans > old_n_chans) return false; @@ -302,7 +422,7 @@ bool dfs_is_subset_channel(struct wlan_dfs *dfs, for (i = 0; i < new_n_chans; i++) { is_found = false; for (j = 0; j < old_n_chans; j++) { - if (new_subchans[i] == old_subchans[j]) { + if (new_subchans_freq[i] == old_subchans_freq[j]) { is_found = true; break; } @@ -317,22 +437,83 @@ bool dfs_is_subset_channel(struct wlan_dfs *dfs, return is_found; } +#endif -bool dfs_is_curchan_subset_of_cac_started_chan(struct wlan_dfs *dfs) +#ifdef CONFIG_CHAN_FREQ_API +static uint8_t +dfs_find_dfs_sub_channels_for_freq(struct wlan_dfs *dfs, + struct dfs_channel *chan, + uint16_t *subchan_arr) { - return dfs_is_subset_channel(dfs, &dfs->dfs_cac_started_chan, - dfs->dfs_curchan); + if (WLAN_IS_CHAN_MODE_160(chan) || WLAN_IS_CHAN_MODE_80_80(chan)) { + if (WLAN_IS_CHAN_DFS(chan) && WLAN_IS_CHAN_DFS_CFREQ2(chan)) + return dfs_get_bonding_channel_without_seg_info_for_freq + (chan, subchan_arr); + if (WLAN_IS_CHAN_DFS(chan)) + return dfs_get_bonding_channels_for_freq(dfs, + chan, + SEG_ID_PRIMARY, + DETECTOR_ID_0, + subchan_arr); + if (WLAN_IS_CHAN_DFS_CFREQ2(chan)) + return dfs_get_bonding_channels_for_freq + (dfs, chan, SEG_ID_SECONDARY, + DETECTOR_ID_0, subchan_arr); + /* All channels in 160/80_80 BW are non DFS, return 0 + * as number of subchannels + */ + return 0; + } else if (WLAN_IS_CHAN_DFS(chan)) { + return dfs_get_bonding_channel_without_seg_info_for_freq + (chan, subchan_arr); + } + /* All channels are non DFS, return 0 as number of subchannels*/ + return 0; } +#endif -void dfs_clear_cac_started_chan(struct wlan_dfs *dfs) +/* dfs_is_new_chan_subset_of_old_chan() - Find if new channel is subset of + * old channel. + * @dfs: Pointer to wlan_dfs structure. + * @new_chan: Pointer to new channel of dfs_channel structure. + * @old_chan: Pointer to old channel of dfs_channel structure. + * + * Return: True if new channel is subset of old channel, else false. + */ +#ifdef CONFIG_CHAN_FREQ_API +static bool +dfs_is_new_chan_subset_of_old_chan(struct wlan_dfs *dfs, + struct dfs_channel *new_chan, + struct dfs_channel *old_chan) { - qdf_mem_zero(&dfs->dfs_cac_started_chan, - sizeof(dfs->dfs_cac_started_chan)); + uint16_t new_subchans[NUM_CHANNELS_160MHZ]; + uint16_t old_subchans[NUM_CHANNELS_160MHZ]; + uint8_t n_new_subchans = 0; + uint8_t n_old_subchans = 0; + + /* Given channel is the old channel. i.e. The channel which + * should have the new channel as subset. + */ + n_old_subchans = dfs_find_dfs_sub_channels_for_freq(dfs, old_chan, + old_subchans); + /* cur_chan is the new channel to be check if subset of old channel */ + n_new_subchans = dfs_find_dfs_sub_channels_for_freq(dfs, new_chan, + new_subchans); + + return dfs_is_subset_channel_for_freq(old_subchans, + n_old_subchans, + new_subchans, + n_new_subchans); } +#endif -bool dfs_check_for_cac_start(struct wlan_dfs *dfs, - bool *continue_current_cac) +bool dfs_is_cac_required(struct wlan_dfs *dfs, + struct dfs_channel *cur_chan, + struct dfs_channel *prev_chan, + bool *continue_current_cac) { + struct dfs_channel *cac_started_chan = &dfs->dfs_cac_started_chan; + if (dfs->dfs_ignore_dfs || dfs->dfs_cac_valid || dfs->dfs_ignore_cac) { dfs_debug(dfs, WLAN_DEBUG_DFS, "Skip CAC, ignore_dfs = %d cac_valid = %d ignore_cac = %d", @@ -341,18 +522,11 @@ bool dfs_check_for_cac_start(struct wlan_dfs *dfs, return false; } - if (dfs_is_etsi_precac_done(dfs)) { - dfs_debug(dfs, WLAN_DEBUG_DFS, - "ETSI PRE-CAC alreay done on this channel %d", - dfs->dfs_curchan->dfs_ch_ieee); - return false; - } - /* If the channel has completed PRE-CAC then CAC can be skipped here. */ - if (dfs_is_precac_done(dfs, dfs->dfs_curchan)) { + if (dfs_is_precac_done(dfs, cur_chan)) { dfs_debug(dfs, WLAN_DEBUG_DFS, "PRE-CAC alreay done on this channel %d", - dfs->dfs_curchan->dfs_ch_ieee); + cur_chan->dfs_ch_ieee); return false; } @@ -365,7 +539,9 @@ bool dfs_check_for_cac_start(struct wlan_dfs *dfs, * VAP(1) comes up in the same channel then instead of * cancelling the CAC we can let the CAC continue. */ - if (dfs_is_curchan_subset_of_cac_started_chan(dfs)) { + if (dfs_is_new_chan_subset_of_old_chan(dfs, + cur_chan, + cac_started_chan)) { *continue_current_cac = true; } else { /* New CAC is needed, cancel the running CAC @@ -385,7 +561,9 @@ bool dfs_check_for_cac_start(struct wlan_dfs *dfs, dfs_cancel_cac_timer(dfs); } } else { /* CAC timer is not running. */ - if (dfs_is_curchan_subset_of_cac_started_chan(dfs)) { + if (dfs_is_new_chan_subset_of_old_chan(dfs, + cur_chan, + prev_chan)) { /* AP bandwidth reduce case: * When AP detects the RADAR in in-service monitoring * mode in channel A, it cancels the running CAC and diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_filter_init.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_filter_init.c index 7a7ba255831183628f85334ffb0b5e06d7db5e72..01f3b821d370a5806aa0e53dd5b0b8095e1b7f8b 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_filter_init.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_filter_init.c @@ -218,6 +218,7 @@ int dfs_main_attach(struct wlan_dfs *dfs) /*Verify : Passing NULL to qdf_timer_init().*/ dfs_main_task_timer_init(dfs); + dfs_allow_hw_pulses(dfs, true); dfs_host_wait_timer_init(dfs); WLAN_DFSQ_LOCK_CREATE(dfs); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_nol.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_nol.c index 45a0ffdee782751a191dd234cde39298422b43f4..eda749ad4c1b5c9a68d82e0393ce6d5eac1fbfac 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_nol.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_nol.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2002-2010, Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -55,6 +55,64 @@ bool dfs_get_update_nol_flag(struct wlan_dfs *dfs) * * Clears the WLAN_CHAN_DFS_RADAR_FOUND flag for the NOL timeout channel. */ +/* Unused function */ +#ifdef CONFIG_CHAN_FREQ_API +static os_timer_func(dfs_nol_timeout) +{ + struct dfs_channel *c = NULL, lc; + unsigned long oldest, now; + struct wlan_dfs *dfs = NULL; + int i; + int nchans = 0; + + c = &lc; + + OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); + dfs_mlme_get_dfs_ch_nchans(dfs->dfs_pdev_obj, &nchans); + + now = oldest = qdf_system_ticks(); + for (i = 0; i < nchans; i++) { + dfs_mlme_get_dfs_channels_for_freq + (dfs->dfs_pdev_obj, + &c->dfs_ch_freq, + &c->dfs_ch_flags, + &c->dfs_ch_flagext, + &c->dfs_ch_ieee, + &c->dfs_ch_vhtop_ch_freq_seg1, + &c->dfs_ch_vhtop_ch_freq_seg2, + &c->dfs_ch_mhz_freq_seg1, + &c->dfs_ch_mhz_freq_seg2, + i); + if (WLAN_IS_CHAN_RADAR(c)) { + if (qdf_system_time_after_eq(now, + dfs->dfs_nol_event[i] + + dfs_get_nol_timeout(dfs))) { + c->dfs_ch_flagext &= ~WLAN_CHAN_DFS_RADAR_FOUND; + if (c->dfs_ch_flags & WLAN_CHAN_DFS_RADAR) { + /* + * NB: do this here so we get only one + * msg instead of one for every channel + * table entry. + */ + dfs_debug(dfs, WLAN_DEBUG_DFS, + "radar on channel %u (%u MHz) cleared after timeout", + c->dfs_ch_ieee, + c->dfs_ch_freq); + } + } else if (dfs->dfs_nol_event[i] < oldest) { + oldest = dfs->dfs_nol_event[i]; + } + } + } + if (oldest != now) { + /* Arrange to process next channel up for a status change. */ + qdf_timer_mod(&dfs->dfs_nol_timer, + dfs_get_nol_timeout(dfs) - + qdf_system_ticks_to_msecs(qdf_system_ticks())); + } +} +#else +#ifdef CONFIG_CHAN_NUM_API static os_timer_func(dfs_nol_timeout) { struct dfs_channel *c = NULL, lc; @@ -108,6 +166,8 @@ static os_timer_func(dfs_nol_timeout) qdf_system_ticks_to_msecs(qdf_system_ticks())); } } +#endif +#endif /** * dfs_nol_elem_free_work_cb - Free NOL element @@ -227,6 +287,40 @@ static void dfs_nol_delete(struct wlan_dfs *dfs, * * When NOL times out, this function removes the channel from NOL list. */ +#ifdef CONFIG_CHAN_FREQ_API +static os_timer_func(dfs_remove_from_nol) +{ + struct dfs_nolelem *nol_arg; + struct wlan_dfs *dfs; + uint16_t delfreq; + uint16_t delchwidth; + uint8_t chan; + + OS_GET_TIMER_ARG(nol_arg, struct dfs_nolelem *); + + dfs = nol_arg->nol_dfs; + delfreq = nol_arg->nol_freq; + delchwidth = nol_arg->nol_chwidth; + + /* Delete the given NOL entry. */ + DFS_NOL_DELETE_CHAN_LOCKED(dfs, delfreq, delchwidth); + + /* Update the wireless stack with the new NOL. */ + dfs_nol_update(dfs); + + dfs_mlme_nol_timeout_notification(dfs->dfs_pdev_obj); + chan = utils_dfs_freq_to_chan(delfreq); + utils_dfs_deliver_event(dfs->dfs_pdev_obj, delfreq, + WLAN_EV_NOL_FINISHED); + dfs_debug(dfs, WLAN_DEBUG_DFS_NOL, + "remove channel %d from nol", chan); + utils_dfs_unmark_precac_nol_for_freq(dfs->dfs_pdev_obj, delfreq); + utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj, + &delfreq, 1, DFS_NOL_RESET); + utils_dfs_save_nol(dfs->dfs_pdev_obj); +} +#else +#ifdef CONFIG_CHAN_NUM_API static os_timer_func(dfs_remove_from_nol) { struct dfs_nolelem *nol_arg; @@ -253,12 +347,13 @@ static os_timer_func(dfs_remove_from_nol) WLAN_EV_NOL_FINISHED); dfs_debug(dfs, WLAN_DEBUG_DFS_NOL, "remove channel %d from nol", chan); - utils_dfs_add_to_etsi_precac_required_list(dfs->dfs_pdev_obj, - &chan); + utils_dfs_unmark_precac_nol(dfs->dfs_pdev_obj, chan); utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj, &chan, 1, DFS_NOL_RESET); utils_dfs_save_nol(dfs->dfs_pdev_obj); } +#endif +#endif void dfs_print_nol(struct wlan_dfs *dfs) { @@ -274,16 +369,16 @@ void dfs_print_nol(struct wlan_dfs *dfs) nol = dfs->dfs_nol; dfs_debug(dfs, WLAN_DEBUG_DFS_NOL, "NOL"); while (nol) { - diff_ms = qdf_do_div(qdf_get_monotonic_boottime() - - nol->nol_start_us, 1000); + diff_ms = qdf_system_ticks_to_msecs(qdf_system_ticks() - + nol->nol_start_ticks); diff_ms = (nol->nol_timeout_ms - diff_ms); remaining_sec = diff_ms / 1000; /* Convert to seconds */ dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, - "nol:%d channel=%d MHz width=%d MHz time left=%u seconds nol start_us=%llu", + "nol:%d channel=%d MHz width=%d MHz time left=%u seconds nol starttick=%llu", i++, nol->nol_freq, nol->nol_chwidth, remaining_sec, - nol->nol_start_us); + (uint64_t)nol->nol_start_ticks); nol = nol->nol_next; } } @@ -338,13 +433,52 @@ void dfs_get_nol(struct wlan_dfs *dfs, while (nol) { dfs_nol[*nchan].nol_freq = nol->nol_freq; dfs_nol[*nchan].nol_chwidth = nol->nol_chwidth; - dfs_nol[*nchan].nol_start_us = nol->nol_start_us; + dfs_nol[*nchan].nol_start_ticks = nol->nol_start_ticks; dfs_nol[*nchan].nol_timeout_ms = nol->nol_timeout_ms; ++(*nchan); nol = nol->nol_next; } } +#ifdef CONFIG_CHAN_FREQ_API +void dfs_set_nol(struct wlan_dfs *dfs, + struct dfsreq_nolelem *dfs_nol, + int nchan) +{ +#define TIME_IN_MS 1000 + uint32_t nol_time_lft_ms; + struct dfs_channel chan; + int i; + + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + for (i = 0; i < nchan; i++) { + nol_time_lft_ms = + qdf_system_ticks_to_msecs(qdf_system_ticks() - + dfs_nol[i].nol_start_ticks); + + if (nol_time_lft_ms < dfs_nol[i].nol_timeout_ms) { + chan.dfs_ch_freq = dfs_nol[i].nol_freq; + chan.dfs_ch_flags = 0; + chan.dfs_ch_flagext = 0; + nol_time_lft_ms = + (dfs_nol[i].nol_timeout_ms - nol_time_lft_ms); + + DFS_NOL_ADD_CHAN_LOCKED(dfs, chan.dfs_ch_freq, + (nol_time_lft_ms / TIME_IN_MS)); + utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj, + &chan.dfs_ch_freq, + 1, DFS_NOL_SET); + } + } +#undef TIME_IN_MS + dfs_nol_update(dfs); +} +#else +#ifdef CONFIG_CHAN_NUM_API void dfs_set_nol(struct wlan_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int nchan) @@ -361,8 +495,9 @@ void dfs_set_nol(struct wlan_dfs *dfs, } for (i = 0; i < nchan; i++) { - nol_time_left_ms = qdf_do_div(qdf_get_monotonic_boottime() - - dfs_nol[i].nol_start_us, 1000); + nol_time_left_ms = + qdf_system_ticks_to_msecs(qdf_system_ticks() - + dfs_nol[i].nol_start_ticks); if (nol_time_left_ms < dfs_nol[i].nol_timeout_ms) { chan.dfs_ch_freq = dfs_nol[i].nol_freq; @@ -381,6 +516,8 @@ void dfs_set_nol(struct wlan_dfs *dfs, #undef TIME_IN_MS dfs_nol_update(dfs); } +#endif +#endif void dfs_nol_addchan(struct wlan_dfs *dfs, uint16_t freq, @@ -402,7 +539,7 @@ void dfs_nol_addchan(struct wlan_dfs *dfs, while (nol) { if ((nol->nol_freq == freq) && (nol->nol_chwidth == ch_width)) { - nol->nol_start_us = qdf_get_monotonic_boottime(); + nol->nol_start_ticks = qdf_system_ticks(); nol->nol_timeout_ms = dfs_nol_timeout * TIME_IN_MS; dfs_debug(dfs, WLAN_DEBUG_DFS_NOL, @@ -427,7 +564,7 @@ void dfs_nol_addchan(struct wlan_dfs *dfs, elem->nol_dfs = dfs; elem->nol_freq = freq; elem->nol_chwidth = ch_width; - elem->nol_start_us = qdf_get_monotonic_boottime(); + elem->nol_start_ticks = qdf_system_ticks(); elem->nol_timeout_ms = dfs_nol_timeout*TIME_IN_MS; elem->nol_next = NULL; if (prev) { @@ -438,8 +575,9 @@ void dfs_nol_addchan(struct wlan_dfs *dfs, } qdf_timer_init(NULL, - &elem->nol_timer, dfs_remove_from_nol, - elem, QDF_TIMER_TYPE_WAKE_APPS); + &elem->nol_timer, dfs_remove_from_nol, + elem, QDF_TIMER_TYPE_WAKE_APPS); + qdf_timer_mod(&elem->nol_timer, dfs_nol_timeout * TIME_IN_MS); /* Update the NOL counter. */ @@ -542,9 +680,41 @@ void dfs_nol_free_list(struct wlan_dfs *dfs) dfs->dfs_nol = NULL; } +#ifdef CONFIG_CHAN_FREQ_API +void dfs_nol_timer_cleanup(struct wlan_dfs *dfs) +{ + struct dfs_nolelem *nol; + uint16_t nol_freq; + + while (true) { + WLAN_DFSNOL_LOCK(dfs); + + nol = dfs->dfs_nol; + if (nol) { + dfs->dfs_nol = nol->nol_next; + dfs->dfs_nol_count--; + nol_freq = nol->nol_freq; + WLAN_DFSNOL_UNLOCK(dfs); + utils_dfs_reg_update_nol_chan_for_freq( + dfs->dfs_pdev_obj, + &nol_freq, + 1, + DFS_NOL_RESET); + + qdf_timer_free(&nol->nol_timer); + qdf_mem_free(nol); + } else { + WLAN_DFSNOL_UNLOCK(dfs); + break; + } + } +} +#else +#ifdef CONFIG_CHAN_NUM_API void dfs_nol_timer_cleanup(struct wlan_dfs *dfs) { struct dfs_nolelem *nol; + uint8_t nol_chan; while (true) { WLAN_DFSNOL_LOCK(dfs); @@ -553,7 +723,12 @@ void dfs_nol_timer_cleanup(struct wlan_dfs *dfs) if (nol) { dfs->dfs_nol = nol->nol_next; dfs->dfs_nol_count--; + nol_chan = utils_dfs_freq_to_chan(nol->nol_freq); WLAN_DFSNOL_UNLOCK(dfs); + utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj, + &nol_chan, + 1, + DFS_NOL_RESET); qdf_timer_free(&nol->nol_timer); qdf_mem_free(nol); @@ -563,6 +738,8 @@ void dfs_nol_timer_cleanup(struct wlan_dfs *dfs) } } } +#endif +#endif void dfs_nol_workqueue_cleanup(struct wlan_dfs *dfs) { @@ -586,6 +763,42 @@ void dfs_getnol(struct wlan_dfs *dfs, void *dfs_nolinfo) DFS_GET_NOL_LOCKED(dfs, nolinfo->dfs_nol, &(nolinfo->dfs_ch_nchans)); } +#ifdef CONFIG_CHAN_FREQ_API +void dfs_clear_nolhistory(struct wlan_dfs *dfs) +{ + struct dfs_channel *chan_list; + int nchans = 0; + bool sta_opmode; + + if (!dfs->dfs_is_stadfs_enabled) + return; + + sta_opmode = dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj); + if (!sta_opmode) + return; + + nchans = dfs_get_num_chans(); + + chan_list = qdf_mem_malloc(nchans * sizeof(*chan_list)); + if (!chan_list) + return; + + utils_dfs_get_nol_history_chan_list(dfs->dfs_pdev_obj, + (void *)chan_list, &nchans); + if (!nchans) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero chans"); + qdf_mem_free(chan_list); + return; + } + + utils_dfs_reg_update_nol_history_chan_for_freq(dfs->dfs_pdev_obj, + (void *)chan_list, nchans, + DFS_NOL_HISTORY_RESET); + + qdf_mem_free(chan_list); +} +#else +#ifdef CONFIG_CHAN_NUM_API void dfs_clear_nolhistory(struct wlan_dfs *dfs) { struct dfs_channel *chan_list; @@ -619,15 +832,52 @@ void dfs_clear_nolhistory(struct wlan_dfs *dfs) qdf_mem_free(chan_list); } +#endif +#endif -#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) +#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) && \ + defined(CONFIG_CHAN_FREQ_API) +void dfs_remove_spoof_channel_from_nol(struct wlan_dfs *dfs) +{ + struct dfs_nolelem *nol; + uint16_t freq_list[NUM_CHANNELS_160MHZ]; + int i, nchans = 0; + + nchans = dfs_get_bonding_channels_for_freq(dfs, + &dfs->dfs_radar_found_chan, + SEG_ID_PRIMARY, + DETECTOR_ID_0, + freq_list); + + WLAN_DFSNOL_LOCK(dfs); + for (i = 0; i < nchans && i < NUM_CHANNELS_160MHZ; i++) { + nol = dfs->dfs_nol; + while (nol) { + if (nol->nol_freq == freq_list[i]) { + OS_SET_TIMER(&nol->nol_timer, 0); + break; + } + nol = nol->nol_next; + } + } + WLAN_DFSNOL_UNLOCK(dfs); + + utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj, + freq_list, nchans, DFS_NOL_RESET); +} +#else +#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) && \ + defined(CONFIG_CHAN_NUM_API) void dfs_remove_spoof_channel_from_nol(struct wlan_dfs *dfs) { struct dfs_nolelem *nol; uint8_t channels[NUM_CHANNELS_160MHZ]; int i, nchans = 0; - nchans = dfs_get_bonding_channels(dfs, &dfs->dfs_radar_found_chan, 0, + nchans = dfs_get_bonding_channels(dfs, + &dfs->dfs_radar_found_chan, + SEG_ID_PRIMARY, + DETECTOR_ID_0, channels); WLAN_DFSNOL_LOCK(dfs); @@ -648,3 +898,102 @@ void dfs_remove_spoof_channel_from_nol(struct wlan_dfs *dfs) channels, nchans, DFS_NOL_RESET); } #endif +#endif + +void dfs_init_tmp_psoc_nol(struct wlan_dfs *dfs, uint8_t num_radios) +{ + struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj; + + if (WLAN_UMAC_MAX_PDEVS < num_radios) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "num_radios (%u) exceeds limit", num_radios); + return; + } + + /* Allocate the temporary psoc NOL copy structure for the number + * of radios provided. + */ + dfs_soc_obj->dfs_psoc_nolinfo = + qdf_mem_malloc(sizeof(struct dfsreq_nolinfo) * num_radios); +} + +void dfs_deinit_tmp_psoc_nol(struct wlan_dfs *dfs) +{ + struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj; + + if (!dfs_soc_obj->dfs_psoc_nolinfo) + return; + + qdf_mem_free(dfs_soc_obj->dfs_psoc_nolinfo); + dfs_soc_obj->dfs_psoc_nolinfo = NULL; +} + +void dfs_save_dfs_nol_in_psoc(struct wlan_dfs *dfs, + uint8_t pdev_id, + uint16_t low_5ghz_freq, + uint16_t high_5ghz_freq) +{ + struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj; + struct dfsreq_nolinfo tmp_nolinfo, *nolinfo; + uint32_t i, num_chans = 0; + uint16_t tmp_freq; + + if (!dfs->dfs_nol_count) + return; + + if (!dfs_soc_obj->dfs_psoc_nolinfo) + return; + + nolinfo = &dfs_soc_obj->dfs_psoc_nolinfo[pdev_id]; + /* Fetch the NOL entries for the DFS object. */ + dfs_getnol(dfs, &tmp_nolinfo); + + /* nolinfo might already have some data. Do not overwrite it */ + num_chans = nolinfo->dfs_ch_nchans; + for (i = 0; i < tmp_nolinfo.dfs_ch_nchans; i++) { + tmp_freq = tmp_nolinfo.dfs_nol[i].nol_freq; + + /* Add to nolinfo only if within the pdev's frequency range. */ + if ((low_5ghz_freq < tmp_freq) && (high_5ghz_freq > tmp_freq)) { + /* Figure out the completed duration of each NOL. */ + uint32_t nol_completed_ms = + qdf_system_ticks_to_msecs(qdf_system_ticks() - + tmp_nolinfo.dfs_nol[i].nol_start_ticks); + + nolinfo->dfs_nol[num_chans] = tmp_nolinfo.dfs_nol[i]; + /* Remember the remaining NOL time in the timeout + * variable. + */ + nolinfo->dfs_nol[num_chans++].nol_timeout_ms -= + nol_completed_ms; + } + } + + nolinfo->dfs_ch_nchans = num_chans; +} + +void dfs_reinit_nol_from_psoc_copy(struct wlan_dfs *dfs, uint8_t pdev_id) +{ + struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj; + struct dfsreq_nolinfo *nol; + uint8_t i; + + if (!dfs_soc_obj->dfs_psoc_nolinfo) + return; + + if (!dfs_soc_obj->dfs_psoc_nolinfo[pdev_id].dfs_ch_nchans) + return; + + nol = &dfs_soc_obj->dfs_psoc_nolinfo[pdev_id]; + + /* The NOL timeout value in each entry points to the remaining time + * of the NOL. This is to indicate that the NOL entries are paused + * and are not left to continue. + * While adding these NOL, update the start ticks to current time + * to avoid losing entries which might have timed out during + * the pause and resume mechanism. + */ + for (i = 0; i < nol->dfs_ch_nchans; i++) + nol->dfs_nol[i].nol_start_ticks = qdf_system_ticks(); + dfs_set_nol(dfs, nol->dfs_nol, nol->dfs_ch_nchans); +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c index 2ef7188e067516297b8b10f960cf95e791bd027b..6c02b7036bc7818d17e76c582bc9ad214966ad92 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -23,7 +23,6 @@ #include "../dfs.h" #include "../dfs_zero_cac.h" -#include "../dfs_etsi_precac.h" #include "../dfs_process_radar_found_ind.h" #include #include @@ -151,22 +150,24 @@ int dfs_get_nol_subchannel_marking(struct wlan_dfs *dfs, } /** - * dfs_radar_add_channel_list_to_nol()- Add given channels to nol + * dfs_radar_add_channel_list_to_nol_for_freq()- Add given channels to nol * @dfs: Pointer to wlan_dfs structure. - * @channels: Pointer to the channel list. + * @freq_list: Pointer to list of frequency. * @num_channels: Number of channels in the list. * * Add list of channels to nol, only if the channel is dfs. * * Return: QDF_STATUS */ -static QDF_STATUS dfs_radar_add_channel_list_to_nol(struct wlan_dfs *dfs, - uint8_t *channels, - uint8_t num_channels) +#ifdef CONFIG_CHAN_FREQ_API +static QDF_STATUS +dfs_radar_add_channel_list_to_nol_for_freq(struct wlan_dfs *dfs, + uint16_t *freq_list, + uint8_t num_channels) { int i; - uint8_t last_chan = 0; - uint8_t nollist[NUM_CHANNELS_160MHZ]; + uint16_t last_chan_freq = 0; + uint16_t nol_freq_list[NUM_CHANNELS_160MHZ]; uint8_t num_ch = 0; if (num_channels > NUM_CHANNELS_160MHZ) { @@ -176,25 +177,25 @@ static QDF_STATUS dfs_radar_add_channel_list_to_nol(struct wlan_dfs *dfs, } for (i = 0; i < num_channels; i++) { - if (channels[i] == 0 || - channels[i] == last_chan) + if (freq_list[i] == 0 || + freq_list[i] == last_chan_freq) continue; - if (!utils_is_dfs_ch(dfs->dfs_pdev_obj, channels[i])) { + if (!utils_is_dfs_chan_for_freq(dfs->dfs_pdev_obj, + freq_list[i])) { dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip", - channels[i]); + freq_list[i]); continue; } - last_chan = channels[i]; + last_chan_freq = freq_list[i]; DFS_NOL_ADD_CHAN_LOCKED(dfs, - (uint16_t)utils_dfs_chan_to_freq(channels[i]), - dfs->wlan_dfs_nol_timeout); - nollist[num_ch++] = last_chan; + freq_list[i], + dfs->wlan_dfs_nol_timeout); + nol_freq_list[num_ch++] = last_chan_freq; utils_dfs_deliver_event(dfs->dfs_pdev_obj, - (uint16_t) - utils_dfs_chan_to_freq(channels[i]), + freq_list[i], WLAN_EV_NOL_STARTED); dfs_info(dfs, WLAN_DEBUG_DFS_NOL, "ch=%d Added to NOL", - last_chan); + last_chan_freq); } if (!num_ch) { @@ -203,21 +204,22 @@ static QDF_STATUS dfs_radar_add_channel_list_to_nol(struct wlan_dfs *dfs, return QDF_STATUS_E_FAILURE; } - utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj, - nollist, num_ch, DFS_NOL_SET); + utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj, + nol_freq_list, num_ch, + DFS_NOL_SET); if (dfs->dfs_is_stadfs_enabled) if (dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj)) - utils_dfs_reg_update_nol_history_ch( - dfs->dfs_pdev_obj, nollist, num_ch, - DFS_NOL_HISTORY_SET); + utils_dfs_reg_update_nol_history_chan_for_freq( + dfs->dfs_pdev_obj, nol_freq_list, + num_ch, DFS_NOL_HISTORY_SET); dfs_nol_update(dfs); utils_dfs_save_nol(dfs->dfs_pdev_obj); return QDF_STATUS_SUCCESS; } - +#endif /** * dfs_radar_chan_for_80()- Find frequency offsets for 80MHz * @freq_offset: freq offset @@ -323,6 +325,56 @@ static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset, * @radar_found: Pointer to radar_found_info. * @freq_center: Pointer to retrieve the value of radar found cfreq. */ +#ifdef CONFIG_CHAN_FREQ_API +static void +dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs, + struct radar_found_info *radar_found, + uint32_t *freq_center) +{ + struct dfs_channel *curchan = dfs->dfs_curchan; + + /* Radar found on agile detector ID. + * Applicable to chips that have a separate agile radar detector + * engine. + */ + if (radar_found->detector_id == AGILE_DETECTOR_ID) { + *freq_center = dfs->dfs_agile_precac_freq_mhz; + } else if (!radar_found->segment_id) { + *freq_center = curchan->dfs_ch_mhz_freq_seg1; + } else { + /* Radar found on secondary segment by the HW when + * preCAC was running. It (dfs_precac_enable) is specific to + * legacy chips. + */ + if (dfs_is_precac_timer_running(dfs) && + dfs_is_legacy_precac_enabled(dfs)) { + *freq_center = dfs->dfs_precac_secondary_freq_mhz; + } else { + /* Radar found on secondary segment by the HW, when preCAC + * was not running in legacy chips or preCAC was running + * in Lithium chips. + */ + *freq_center = curchan->dfs_ch_mhz_freq_seg2; + if (WLAN_IS_CHAN_MODE_160(curchan)) { + /* If center frequency of entire 160 band + * is less than center frequency of primary + * segment, then the center frequency of + * secondary segment is -40 of center + * frequency of entire 160 segment. + */ + if (curchan->dfs_ch_mhz_freq_seg2 < + curchan->dfs_ch_mhz_freq_seg1) + *freq_center -= + DFS_160MHZ_SECOND_SEG_OFFSET; + else + *freq_center += + DFS_160MHZ_SECOND_SEG_OFFSET; + } + } + } +} +#else +#ifdef CONFIG_CHAN_NUM_API static void dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs, struct radar_found_info @@ -330,47 +382,76 @@ dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs, uint32_t *freq_center) { struct dfs_channel *curchan = dfs->dfs_curchan; - uint64_t flag; - - flag = curchan->dfs_ch_flags; - if (!radar_found->segment_id) { + /* Radar found on agile detector ID. + * Applicable to chips that have a separate agile radar detector + * engine. + */ + if (radar_found->detector_id == AGILE_DETECTOR_ID) { + *freq_center = utils_dfs_chan_to_freq( + dfs->dfs_agile_precac_freq); + /* Radar found on primary segment by the HW. */ + } else if (radar_found->segment_id == PRIMARY_SEG) { *freq_center = utils_dfs_chan_to_freq( curchan->dfs_ch_vhtop_ch_freq_seg1); } else { - if (dfs_is_precac_timer_running(dfs)) { + /* Radar found on secondary segment by the HW when + * preCAC was running. It (dfs_precac_enable) is specific to + * legacy chips. + */ + if (dfs_is_precac_timer_running(dfs) && + dfs_is_legacy_precac_enabled(dfs)) { *freq_center = utils_dfs_chan_to_freq( dfs->dfs_precac_secondary_freq); } else { - *freq_center = utils_dfs_chan_to_freq( - curchan->dfs_ch_vhtop_ch_freq_seg2); - if ((flag & WLAN_CHAN_VHT160) || - (flag & WLAN_CHAN_HE160)) - *freq_center += DFS_160MHZ_SECOND_SEG_OFFSET; + /* Radar found on secondary segment by the HW, when preCAC + * was not running in legacy chips or preCAC was running + * in Lithium chips. + */ + *freq_center = utils_dfs_chan_to_freq( + curchan->dfs_ch_vhtop_ch_freq_seg2); + if (WLAN_IS_CHAN_MODE_160(curchan)) { + /* If center frequency of entire 160 band + * is less than center frequency of primary + * segment, then the center frequency of + * secondary segment is -40 of center + * frequency of entire 160 segment. + */ + if (curchan->dfs_ch_vhtop_ch_freq_seg2 < + curchan->dfs_ch_vhtop_ch_freq_seg1) + *freq_center -= + DFS_160MHZ_SECOND_SEG_OFFSET; + else + *freq_center += + DFS_160MHZ_SECOND_SEG_OFFSET; + } } } } +#endif +#endif /** - * dfs_find_radar_affected_subchans() - Finds radar affected sub channels. + * dfs_find_radar_affected_subchans_for_freq() - Find radar affected sub chans. * @dfs: Pointer to wlan_dfs structure. * @radar_found: Pointer to radar_found structure. - * @channels: Pointer to save radar affected channels. + * @freq_list: Pointer to save radar affected channels. * @freq_center: Freq_center of the radar affected chan. * * Return: Number of channels. */ -static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs, - struct radar_found_info - *radar_found, - uint8_t *channels, - uint32_t freq_center) +#ifdef CONFIG_CHAN_FREQ_API +static uint8_t +dfs_find_radar_affected_subchans_for_freq(struct wlan_dfs *dfs, + struct radar_found_info *radar_found, + uint16_t *freq_list, + uint32_t freq_center) { int i, j; uint8_t num_radar_subchans; uint32_t flag; int32_t sidx; - uint8_t candidate_subchan; - uint8_t cur_subchans[NUM_CHANNELS_160MHZ]; + uint16_t candidate_subchan_freq; + uint16_t cur_subchans[NUM_CHANNELS_160MHZ]; uint8_t n_cur_subchans; struct dfs_channel *curchan = dfs->dfs_curchan; struct freqs_offsets freq_offset; @@ -384,8 +465,8 @@ static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs, sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset); dfs_info(dfs, WLAN_DEBUG_DFS, - "seg=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d", - radar_found->segment_id, sidx, + "seg=%d, det=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d", + radar_found->segment_id, radar_found->detector_id, sidx, radar_found->freq_offset, radar_found->is_chirp, flag, freq_center); @@ -417,27 +498,31 @@ static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs, return 0; } - n_cur_subchans = dfs_get_bonding_channels(dfs, curchan, - radar_found->segment_id, - cur_subchans); + n_cur_subchans = + dfs_get_bonding_channels_for_freq(dfs, curchan, + radar_found->segment_id, + radar_found->detector_id, + cur_subchans); for (i = 0, num_radar_subchans = 0; i < DFS_NUM_FREQ_OFFSET; i++) { - candidate_subchan = utils_dfs_freq_to_chan(freq_offset.freq[i]); + candidate_subchan_freq = freq_offset.freq[i]; for (j = 0; j < n_cur_subchans; j++) { - if (cur_subchans[j] == candidate_subchan) { - channels[num_radar_subchans++] = - candidate_subchan; + if (cur_subchans[j] == candidate_subchan_freq) { + freq_list[num_radar_subchans++] = + candidate_subchan_freq; dfs_info(dfs, WLAN_DEBUG_DFS, "offset=%d, channel=%d", num_radar_subchans, - channels[num_radar_subchans - 1]); + freq_list[num_radar_subchans - 1]); break; } } } return num_radar_subchans; } +#endif +#ifdef CONFIG_CHAN_NUM_API uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan, uint8_t *channels) { @@ -485,23 +570,166 @@ uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan, return nchannels; } +#endif + +/* + * dfs_get_bonding_channel_without_seg_info_for_freq() - Get bonding frequency + * list. + * @chan: Pointer to dfs_channel. + * @freq_list: Pointer to frequency list. + */ +#ifdef CONFIG_CHAN_FREQ_API +uint8_t +dfs_get_bonding_channel_without_seg_info_for_freq(struct dfs_channel *chan, + uint16_t *freq_list) +{ + uint16_t center_freq; + uint8_t nchannels = 0; + + center_freq = chan->dfs_ch_mhz_freq_seg1; + + if (WLAN_IS_CHAN_MODE_20(chan)) { + nchannels = 1; + freq_list[0] = center_freq; + } else if (WLAN_IS_CHAN_MODE_40(chan)) { + nchannels = 2; + freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + } else if (WLAN_IS_CHAN_MODE_80(chan)) { + nchannels = 4; + freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + } else if (WLAN_IS_CHAN_MODE_80_80(chan)) { + nchannels = 8; + freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + center_freq = chan->dfs_ch_mhz_freq_seg2; + freq_list[4] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + freq_list[5] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[6] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[7] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + } else if (WLAN_IS_CHAN_MODE_160(chan)) { + nchannels = 8; + center_freq = chan->dfs_ch_mhz_freq_seg2; + freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; + freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; + freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; + freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; + } + + return nchannels; +} +#endif + +/* + * dfs_get_bonding_channels_for_freq() - Get bonding channel frequency. + * @dfs: Pointer to wlan_dfs. + * @curchan: Pointer to dfs_channel. + * @segment_id: Segment ID. + * @detector_id: Detector ID. + * @freq_list: Pointer to frequency list. + */ +#ifdef CONFIG_CHAN_FREQ_API +uint8_t dfs_get_bonding_channels_for_freq(struct wlan_dfs *dfs, + struct dfs_channel *curchan, + uint32_t segment_id, + uint8_t detector_id, + uint16_t *freq_list) +{ + uint16_t center_freq; + uint8_t nchannels = 0; + if (detector_id == AGILE_DETECTOR_ID) + center_freq = dfs->dfs_agile_precac_freq_mhz; + else if (!segment_id) + center_freq = curchan->dfs_ch_mhz_freq_seg1; + else { + /* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is + * zero and "dfs_precac_secondary_freq" holds the secondary + * frequency. + */ + if (dfs_is_precac_timer_running(dfs)) + center_freq = dfs->dfs_precac_secondary_freq_mhz; + else + center_freq = curchan->dfs_ch_mhz_freq_seg2; + } + + if (WLAN_IS_CHAN_MODE_20(curchan)) { + nchannels = 1; + freq_list[0] = center_freq; + } else if (WLAN_IS_CHAN_MODE_40(curchan)) { + nchannels = 2; + freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + } else if (WLAN_IS_CHAN_MODE_80(curchan) || + WLAN_IS_CHAN_MODE_80_80(curchan) || + detector_id == AGILE_DETECTOR_ID) { + /* If the current channel's bandwidth is 80/80+80/160Mhz, + * the corresponding agile Detector's bandwidth will be 80Mhz. + * Therefore, if radar is found on the agile detector find + * subchannels for 80Mhz bandwidth. + */ + nchannels = 4; + freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + } else if (WLAN_IS_CHAN_MODE_160(curchan)) { + nchannels = 8; + center_freq = curchan->dfs_ch_mhz_freq_seg2; + freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; + freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; + freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; + freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; + freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; + freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; + } + + return nchannels; +} +#endif + +#ifdef CONFIG_CHAN_NUM_API uint8_t dfs_get_bonding_channels(struct wlan_dfs *dfs, struct dfs_channel *curchan, uint32_t segment_id, + uint8_t detector_id, uint8_t *channels) { uint8_t center_chan; uint8_t nchannels = 0; - if (!segment_id) + if (detector_id == AGILE_DETECTOR_ID) + center_chan = dfs->dfs_agile_precac_freq; + else if (!segment_id) center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1; else { /* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is * zero and "dfs_precac_secondary_freq" holds the secondary - * frequency. + * frequency in case of legacy chips. + * For chips that support a separate agile detector engine, + * "dfs_agile_precac_freq" holds the frequency that agile + * engine operates on. + * + * In case of radar detected by the HW in the secondary 80 + * channel,"dfs_ch_vhtop_ch_freq_seg2" holds the secondary + * segment center frequency in the below cases: + * 1. preCAC timer is running in chips that support separate + * agile engines. + * 2. preCAC timer is not running. */ - if (dfs_is_precac_timer_running(dfs)) + if (dfs_is_precac_timer_running(dfs) && + dfs_is_legacy_precac_enabled(dfs)) center_chan = dfs->dfs_precac_secondary_freq; else center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; @@ -515,7 +743,13 @@ uint8_t dfs_get_bonding_channels(struct wlan_dfs *dfs, channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; } else if (WLAN_IS_CHAN_MODE_80(curchan) || - WLAN_IS_CHAN_MODE_80_80(curchan)) { + WLAN_IS_CHAN_MODE_80_80(curchan) || + detector_id == AGILE_DETECTOR_ID) { + /* If the current channel's bandwidth is 80/80+80/160Mhz, + * the corresponding agile Detector's bandwidth will be 80Mhz. + * Therefore, if radar is found on the agile detector find + * subchannels for 80Mhz bandwidth. + */ nchannels = 4; channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; @@ -536,6 +770,7 @@ uint8_t dfs_get_bonding_channels(struct wlan_dfs *dfs, return nchannels; } +#endif static inline void dfs_reset_bangradar(struct wlan_dfs *dfs) { @@ -586,33 +821,31 @@ int dfs_second_segment_radar_disable(struct wlan_dfs *dfs) /* dfs_prepare_nol_ie_bitmap: Create a Bitmap from the radar found subchannels * to be sent along with RCSA. - * - * Get the subchannels affected by radar and all the channels in current - * channel. - * start from the first bit pointing to first subchannel in the current - * channel, set as 1 if radar affected, 0 if unaffected. - * If the number of subchannels increases (future cases), the bitmap should - * be an array of required size. - * - * Please change macro "MIN_DFS_SUBCHAN_BW" when NOL logic changes. + * @dfs: Pointer to wlan_dfs. + * @radar_found: Pointer to radar_found_info. + * @in_sub_channels: Pointer to Sub-channels. + * @n_in_sub_channels: Number of sub-channels. */ -static void dfs_prepare_nol_ie_bitmap(struct wlan_dfs *dfs, - struct radar_found_info *radar_found, - uint8_t *in_sub_channels, - uint8_t n_in_sub_channels) +#ifdef CONFIG_CHAN_FREQ_API +static void +dfs_prepare_nol_ie_bitmap_for_freq(struct wlan_dfs *dfs, + struct radar_found_info *radar_found, + uint16_t *in_sub_channels, + uint8_t n_in_sub_channels) { - uint8_t cur_subchans[NUM_CHANNELS_160MHZ]; + uint16_t cur_subchans[NUM_CHANNELS_160MHZ]; uint8_t n_cur_subchans; uint8_t i; uint8_t j; uint8_t bits = 0x01; - n_cur_subchans = dfs_get_bonding_channels(dfs, dfs->dfs_curchan, - radar_found->segment_id, - cur_subchans); + n_cur_subchans = + dfs_get_bonding_channels_for_freq(dfs, dfs->dfs_curchan, + radar_found->segment_id, + radar_found->detector_id, + cur_subchans); dfs->dfs_nol_ie_bandwidth = MIN_DFS_SUBCHAN_BW; - dfs->dfs_nol_ie_startfreq = - (uint16_t)utils_dfs_chan_to_freq(cur_subchans[0]); + dfs->dfs_nol_ie_startfreq = cur_subchans[0]; /* Search through the array list of radar affected subchannels * to find if the subchannel in our current channel has radar hit. @@ -628,6 +861,7 @@ static void dfs_prepare_nol_ie_bitmap(struct wlan_dfs *dfs, bits <<= 1; } } +#endif void dfs_fetch_nol_ie_info(struct wlan_dfs *dfs, uint8_t *nol_ie_bandwidth, @@ -663,12 +897,13 @@ static void dfs_reset_nol_ie_bitmap(struct wlan_dfs *dfs) dfs->dfs_nol_ie_bitmap = 0; } +#ifdef CONFIG_CHAN_FREQ_API bool dfs_process_nol_ie_bitmap(struct wlan_dfs *dfs, uint8_t nol_ie_bandwidth, uint16_t nol_ie_startfreq, uint8_t nol_ie_bitmap) { uint8_t num_subchans; uint8_t bits = 0x01; - uint8_t radar_subchans[NUM_CHANNELS_160MHZ]; + uint16_t radar_subchans[NUM_CHANNELS_160MHZ]; bool should_nol_ie_be_sent = true; qdf_mem_zero(radar_subchans, sizeof(radar_subchans)); @@ -678,10 +913,11 @@ bool dfs_process_nol_ie_bitmap(struct wlan_dfs *dfs, uint8_t nol_ie_bandwidth, * can't be sent to uplink. */ num_subchans = - dfs_get_bonding_channels(dfs, - dfs->dfs_curchan, - dfs->dfs_curchan->dfs_ch_freq, - radar_subchans); + dfs_get_bonding_channels_for_freq(dfs, + dfs->dfs_curchan, + SEG_ID_PRIMARY, + DETECTOR_ID_0, + radar_subchans); should_nol_ie_be_sent = false; } else { /* Add the NOL IE information in DFS structure so that RCSA @@ -695,38 +931,91 @@ bool dfs_process_nol_ie_bitmap(struct wlan_dfs *dfs, uint8_t nol_ie_bandwidth, for (num_subchans = 0; num_subchans < NUM_CHANNELS_160MHZ; num_subchans++) { if (nol_ie_bitmap & bits) { - radar_subchans[num_subchans] = - utils_dfs_freq_to_chan(frequency); + radar_subchans[num_subchans] = frequency; } bits <<= 1; frequency += nol_ie_bandwidth; } } - dfs_radar_add_channel_list_to_nol(dfs, radar_subchans, num_subchans); + dfs_radar_add_channel_list_to_nol_for_freq(dfs, radar_subchans, + num_subchans); return should_nol_ie_be_sent; } +#endif +#ifdef CONFIG_CHAN_FREQ_API QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, struct radar_found_info *radar_found) { bool wait_for_csa = false; - uint8_t channels[NUM_CHANNELS_160MHZ]; + uint16_t freq_list[NUM_CHANNELS_160MHZ]; uint8_t num_channels; - QDF_STATUS status; + QDF_STATUS status = QDF_STATUS_E_FAILURE; uint32_t freq_center; uint32_t radarfound_freq; + struct dfs_channel *dfs_curchan; + + /* Acquire a lock to avoid initiating mode switch till radar + * processing is completed. + */ + DFS_RADAR_MODE_SWITCH_LOCK(dfs); - if (!dfs->dfs_curchan) { + /* Before processing radar, check if HW mode switch is in progress. + * If in progress, defer the processing of radar event received till + * the mode switch is completed. + */ + if (dfs_is_hw_mode_switch_in_progress(dfs)) { + struct radar_found_info *radar_params = NULL; + + radar_params = qdf_mem_malloc(sizeof(*radar_params)); + if (!radar_params) + goto exit; + + /* If CAC timer is running, cancel it here rather than + * after processing to avoid handling unnecessary CAC timeouts. + */ + if (dfs->dfs_cac_timer_running) + dfs_cac_stop(dfs); + + /* If CAC timer is to be handled after mode switch and then + * we receive radar, no point in handling CAC completion. + */ + if (dfs->dfs_defer_params.is_cac_completed) + dfs->dfs_defer_params.is_cac_completed = false; + qdf_mem_copy(radar_params, radar_found, sizeof(*radar_params)); + dfs->dfs_defer_params.radar_params = radar_params; + dfs->dfs_defer_params.is_radar_detected = true; + status = QDF_STATUS_SUCCESS; + goto exit; + } + + dfs_curchan = dfs->dfs_curchan; + + if (!dfs_curchan) { dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs->dfs_curchan is NULL"); - return QDF_STATUS_E_FAILURE; + goto exit; } - /* Check if the current channel is a non DFS channel */ - if (!dfs_radarevent_basic_sanity(dfs, dfs->dfs_curchan)) { + /* Check if the current channel is a non DFS channel + * If the current channel is non-DFS and the radar is from Agile + * Detector we need to process it since Agile Detector has a + * different channel. + */ + if (!dfs_radarevent_basic_sanity(dfs, dfs_curchan) && + !(radar_found->detector_id == AGILE_DETECTOR_ID)) { dfs_err(dfs, WLAN_DEBUG_DFS, "radar event on a non-DFS channel"); - return QDF_STATUS_E_FAILURE; + goto exit; + } + + /* Sanity checks for radar on Agile detector */ + if (radar_found->detector_id == AGILE_DETECTOR_ID && + (!dfs_is_agile_precac_enabled(dfs) || !dfs->dfs_agile_precac_freq_mhz)) + { + dfs_err(dfs, WLAN_DEBUG_DFS, + "radar on Agile detector when ADFS is not running"); + goto exit; } /* For Full Offload, FW sends segment id,freq_offset and chirp @@ -743,7 +1032,11 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, dfs_compute_radar_found_cfreq(dfs, radar_found, &freq_center); radarfound_freq = freq_center + radar_found->freq_offset; - if (radar_found->segment_id == SEG_ID_SECONDARY) + if (radar_found->detector_id == AGILE_DETECTOR_ID) + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Radar found on Agile detector freq=%d radar freq=%d", + freq_center, radarfound_freq); + else if (radar_found->segment_id == SEG_ID_SECONDARY) dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "Radar found on second segment.Radarfound Freq=%d MHz.Secondary Chan cfreq=%d MHz.", radarfound_freq, freq_center); @@ -751,63 +1044,58 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, "Radar found on channel=%d, freq=%d MHz. Primary beaconning chan:%d, freq=%d MHz.", utils_dfs_freq_to_chan(radarfound_freq), - radarfound_freq, dfs->dfs_curchan->dfs_ch_ieee, - dfs->dfs_curchan->dfs_ch_freq); + radarfound_freq, dfs_curchan->dfs_ch_ieee, + dfs_curchan->dfs_ch_freq); - utils_dfs_deliver_event(dfs->dfs_pdev_obj, - radarfound_freq, + utils_dfs_deliver_event(dfs->dfs_pdev_obj, radarfound_freq, WLAN_EV_RADAR_DETECTED); if (!dfs->dfs_use_nol) { dfs_reset_bangradar(dfs); dfs_send_csa_to_current_chan(dfs); - return QDF_STATUS_SUCCESS; + status = QDF_STATUS_SUCCESS; + goto exit; } if (dfs->dfs_bangradar_type == DFS_BANGRADAR_FOR_ALL_SUBCHANS) - num_channels = dfs_get_bonding_channels_without_seg_info( - dfs->dfs_curchan, channels); + num_channels = + dfs_get_bonding_channel_without_seg_info_for_freq + (dfs_curchan, freq_list); /* BW reduction is dependent on subchannel marking */ else if ((dfs->dfs_use_nol_subchannel_marking) && (!(dfs->dfs_bangradar_type) || - (dfs->dfs_bangradar_type == - DFS_BANGRADAR_FOR_SPECIFIC_SUBCHANS))) - num_channels = dfs_find_radar_affected_subchans(dfs, - radar_found, - channels, - freq_center); + (dfs->dfs_bangradar_type == + DFS_BANGRADAR_FOR_SPECIFIC_SUBCHANS))) + num_channels = + dfs_find_radar_affected_subchans_for_freq(dfs, + radar_found, + freq_list, + freq_center); else - num_channels = dfs_get_bonding_channels(dfs, - dfs->dfs_curchan, - radar_found->segment_id, - channels); + num_channels = dfs_get_bonding_channels_for_freq + (dfs, dfs_curchan, radar_found->segment_id, + radar_found->detector_id, freq_list); dfs_reset_bangradar(dfs); - if (dfs->dfs_agile_precac_enable && radar_found->detector_id == - AGILE_DETECTOR_ID) { - dfs_debug(dfs, WLAN_DEBUG_DFS, - "%s: %d Radar found on agile detector:%d , STAY in Same operating Channel", - __func__, __LINE__, radar_found->detector_id); - dfs_mark_precac_dfs(dfs, dfs->is_radar_found_on_secondary_seg, - radar_found->detector_id); - return QDF_STATUS_SUCCESS; - } - - status = dfs_radar_add_channel_list_to_nol(dfs, channels, num_channels); + status = dfs_radar_add_channel_list_to_nol_for_freq(dfs, + freq_list, + num_channels); if (QDF_IS_STATUS_ERROR(status)) { dfs_err(dfs, WLAN_DEBUG_DFS, "radar event received on invalid channel"); - return status; + goto exit; } + dfs->dfs_is_nol_ie_sent = false; - (dfs->is_radar_during_precac) ? + (dfs->is_radar_during_precac || + radar_found->detector_id == AGILE_DETECTOR_ID) ? (dfs->dfs_is_rcsa_ie_sent = false) : (dfs->dfs_is_rcsa_ie_sent = true); if (dfs->dfs_use_nol_subchannel_marking) { dfs_reset_nol_ie_bitmap(dfs); - dfs_prepare_nol_ie_bitmap(dfs, radar_found, channels, - num_channels); + dfs_prepare_nol_ie_bitmap_for_freq(dfs, radar_found, freq_list, + num_channels); dfs->dfs_is_nol_ie_sent = true; } @@ -822,27 +1110,20 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, dfs->is_radar_found_on_secondary_seg, dfs_is_precac_timer_running(dfs)); /* - * Even if radar found on primary, we need to move the channel - * from precac-required-list and precac-done-list to - * precac-nol-list. + * Even if radar found on primary, we need to mark the channel as NOL + * in preCAC list. The preCAC list also maintains the current CAC + * channels as part of pre-cleared DFS. Hence call the API + * to mark channels as NOL irrespective of preCAC being enabled or not. */ - if (dfs->dfs_precac_enable || dfs->dfs_agile_precac_enable) { - dfs_debug(dfs, WLAN_DEBUG_DFS, - "%s: %d Radar found on dfs detector:%d", - __func__, __LINE__, radar_found->detector_id); - dfs_mark_precac_dfs(dfs, - dfs->is_radar_found_on_secondary_seg, - radar_found->detector_id); - } - - if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) { - /* Remove chan from ETSI Pre-CAC Cleared List*/ - dfs_info(dfs, WLAN_DEBUG_DFS_NOL, - "%s : %d remove channel from ETSI PreCAC List\n", - __func__, __LINE__); - dfs_mark_etsi_precac_dfs(dfs, channels, num_channels); - } + dfs_debug(dfs, WLAN_DEBUG_DFS, + "%s: %d Radar found on dfs detector:%d", + __func__, __LINE__, radar_found->detector_id); + dfs_mark_precac_nol_for_freq(dfs, + dfs->is_radar_found_on_secondary_seg, + radar_found->detector_id, + freq_list, + num_channels); /* * This calls into the umac DFS code, which sets the umac * related radar flags and begins the channel change @@ -855,6 +1136,11 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, &wait_for_csa); + /* If radar is found on preCAC or Agile CAC, return here since + * channel change is not required. + */ + if (radar_found->detector_id == AGILE_DETECTOR_ID) + goto exit; if (!dfs->dfs_is_offload_enabled && dfs->is_radar_found_on_secondary_seg) { dfs_second_segment_radar_disable(dfs); @@ -862,7 +1148,7 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, if (dfs->is_radar_during_precac) { dfs->is_radar_during_precac = 0; - return QDF_STATUS_SUCCESS; + goto exit; } } @@ -873,7 +1159,7 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, * needs to be fixed. See EV 105776. */ if (wait_for_csa) - return QDF_STATUS_SUCCESS; + goto exit; /* * EV 129487 : We have detected radar in the channel, @@ -887,11 +1173,14 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, dfs_second_segment_radar_disable(dfs); } - dfs_mlme_mark_dfs(dfs->dfs_pdev_obj, - dfs->dfs_curchan->dfs_ch_ieee, - dfs->dfs_curchan->dfs_ch_freq, - dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2, - dfs->dfs_curchan->dfs_ch_flags); + dfs_mlme_mark_dfs_for_freq(dfs->dfs_pdev_obj, + dfs->dfs_curchan->dfs_ch_ieee, + dfs->dfs_curchan->dfs_ch_freq, + dfs->dfs_curchan->dfs_ch_mhz_freq_seg2, + dfs->dfs_curchan->dfs_ch_flags); - return QDF_STATUS_SUCCESS; +exit: + DFS_RADAR_MODE_SWITCH_UNLOCK(dfs); + return status; } +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_random_chan_sel.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_random_chan_sel.c index 1ac50a0e5f2569830512bb86edacb219f164a421..774006c2002e7a4e05934f2906d412fb0da876bd 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_random_chan_sel.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_random_chan_sel.c @@ -20,6 +20,7 @@ #include "../dfs_random_chan_sel.h" #include #include +#include "../dfs_process_radar_found_ind.h" #ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION /* @@ -35,681 +36,681 @@ /* channel tx leakage table - ht80 */ struct dfs_matrix_tx_leak_info ht80_chan[] = { - {52, - {{36, 148}, {40, 199}, - {44, 193}, {48, 197}, - {52, DFS_TX_LEAKAGE_MIN}, {56, 153}, - {60, 137}, {64, 134}, - {100, 358}, {104, 350}, - {108, 404}, {112, 344}, - {116, 424}, {120, 429}, - {124, 437}, {128, 435}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {52, 5260, + {{36, 5180, 148}, {40, 5200, 199}, + {44, 5520, 193}, {48, 5240, 197}, + {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, 153}, + {60, 5300, 137}, {64, 5320, 134}, + {100, 5500, 358}, {104, 5520, 350}, + {108, 5540, 404}, {112, 5560, 344}, + {116, 5580, 424}, {120, 5600, 429}, + {124, 5620, 437}, {128, 5640, 435}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {56, - {{36, 171}, {40, 178}, - {44, 171}, {48, 178}, - {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, - {60, DFS_TX_LEAKAGE_MIN}, {64, 280}, - {100, 351}, {104, 376}, - {108, 362}, {112, 362}, - {116, 403}, {120, 397}, - {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {56, 5280, + {{36, 5180, 171}, {40, 5200, 178}, + {44, 5220, 171}, {48, 5240, 178}, + {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, 280}, + {100, 5500, 351}, {104, 5520, 376}, + {108, 5540, 362}, {112, 5560, 362}, + {116, 5580, 403}, {120, 5600, 397}, + {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {60, - {{36, 156}, {40, 146}, - {44, DFS_TX_LEAKAGE_MIN}, {48, DFS_TX_LEAKAGE_MIN}, - {52, 180}, {56, DFS_TX_LEAKAGE_MIN}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, 376}, {104, 360}, - {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, - {116, 395}, {120, 399}, - {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {60,5300, + {{36, 5180, 156}, {40, 5200, 146}, + {44, 5220, DFS_TX_LEAKAGE_MIN}, {48, 5240, DFS_TX_LEAKAGE_MIN}, + {52, 5260, 180}, {56, 5280, DFS_TX_LEAKAGE_MIN}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, 376}, {104, 5520, 360}, + {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, + {116, 5580, 395}, {120, 5600, 399}, + {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {64, - {{36, 217}, {40, 221}, - {44, DFS_TX_LEAKAGE_MIN}, {48, DFS_TX_LEAKAGE_MIN}, - {52, 176}, {56, 176}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, 384}, {104, 390}, - {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, - {116, 375}, {120, 374}, - {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {64, 5320, + {{36, 5180, 217}, {40, 5200, 221}, + {44, 5220, DFS_TX_LEAKAGE_MIN}, {48, 5240, DFS_TX_LEAKAGE_MIN}, + {52, 5260, 176}, {56, 5280, 176}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, 384}, {104, 5520, 390}, + {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, + {116, 5580, 375}, {120, 5600, 374}, + {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {100, - {{36, 357}, {40, 326}, - {44, 321}, {48, 326}, - {52, 378}, {56, 396}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, - {108, 196}, {112, 116}, - {116, 166}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {100, 5500, + {{36, 5180, 357}, {40, 5200, 326}, + {44, 5220, 321}, {48, 5240, 326}, + {52, 5260, 378}, {56, 5280, 396}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, + {108, 5540, 196}, {112, 5560, 116}, + {116, 5580, 166}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {104, - {{36, 325}, {40, 325}, - {44, 305}, {48, 352}, - {52, 411}, {56, 411}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, - {108, DFS_TX_LEAKAGE_MIN}, {112, 460}, - {116, 198}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {104, 5520, + {{36, 5180, 325}, {40, 5200, 325}, + {44, 5220, 305}, {48, 5240, 352}, + {52, 5260, 411}, {56, 5280, 411}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, 460}, + {116, 5580, 198}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {108, - {{36, 304}, {40, 332}, - {44, 310}, {48, 335}, - {52, 431}, {56, 391}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, 280}, {104, DFS_TX_LEAKAGE_MIN}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, 185}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {108, 5540, + {{36,5180, 304}, {40, 5200, 332}, + {44, 5220, 310}, {48, 5240, 335}, + {52, 5260, 431}, {56, 5280, 391}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, 280}, {104, 5520, DFS_TX_LEAKAGE_MIN}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, 185}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {112, - {{36, 327}, {40, 335}, - {44, 331}, {48, 345}, - {52, 367}, {56, 401}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, 131}, {104, 132}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, 189}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {112,5560, + {{36, 5180, 327}, {40, 5200, 335}, + {44, 5220, 331}, {48, 5240, 345}, + {52, 5260, 367}, {56, 5280, 401}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, 131}, {104, 5520, 132}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, 189}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {116, - {{36, 384}, {40, 372}, - {44, 389}, {48, 396}, - {52, 348}, {56, 336}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, 172}, {104, 169}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {116, 5580, + {{36, 5180, 384}, {40, 5200, 372}, + {44, 5220, 389}, {48, 5240, 396}, + {52, 5260, 348}, {56, 5280, 336}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, 172}, {104, 5520, 169}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {120, - {{36, 395}, {40, 419}, - {44, 439}, {48, 407}, - {52, 321}, {56, 334}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, 134}, {104, 186}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, 159}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {120, 5600, + {{36, 5180, 395}, {40, 5200, 419}, + {44, 5220, 439}, {48, 5240, 407}, + {52, 5260, 321}, {56, 5280, 334}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, 134}, {104, 5520, 186}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 159}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {124, - {{36, 469}, {40, 433}, - {44, 434}, {48, 435}, - {52, 332}, {56, 345}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, 146}, {104, 177}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, 350}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, 138}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {124, 5620, + {{36, 5180, 469}, {40, 5200, 433}, + {44, 5220, 434}, {48, 5240, 435}, + {52, 5260, 332}, {56, 5280, 345}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, 146}, {104, 5520, 177}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, 350}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 138}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {128, - {{36, 408}, {40, 434}, - {44, 449}, {48, 444}, - {52, 341}, {56, 374}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, 205}, {104, 208}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, 142}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {128, 5640, + {{36, 5180, 408}, {40, 5200, 434}, + {44, 5220, 449}, {48, 5240, 444}, + {52, 5260, 341}, {56, 5280, 374}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, 205}, {104, 5520, 208}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, 142}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {132, - {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX}, - {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {132, 5660, + {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX}, + {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {136, - {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX}, - {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {136, 5680, + {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX}, + {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {140, - {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX}, - {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {140, 5700, + {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX}, + {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {144, - {{36, DFS_TX_LEAKAGE_MAX}, {40, DFS_TX_LEAKAGE_MAX}, - {44, DFS_TX_LEAKAGE_MAX}, {48, DFS_TX_LEAKAGE_MAX}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {144, 5720, + {{36, 5180, DFS_TX_LEAKAGE_MAX}, {40, 5200, DFS_TX_LEAKAGE_MAX}, + {44, 5220, DFS_TX_LEAKAGE_MAX}, {48, 5240, DFS_TX_LEAKAGE_MAX}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, }; /* channel tx leakage table - ht40 */ struct dfs_matrix_tx_leak_info ht40_chan[] = { - {52, - {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN}, - {44, 230}, {48, 230}, - {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, - {60, DFS_TX_LEAKAGE_AUTO_MIN}, {64, DFS_TX_LEAKAGE_AUTO_MIN}, - {100, 625}, {104, 323}, - {108, 646}, {112, 646}, - {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, - {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {52, 5260, + {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN}, + {44, 5220, 230}, {48, 5240, 230}, + {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, + {60, 5300, DFS_TX_LEAKAGE_AUTO_MIN}, {64, 5320, DFS_TX_LEAKAGE_AUTO_MIN}, + {100, 5500, 625}, {104, 5520, 323}, + {108, 5540, 646}, {112, 5560, 646}, + {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, + {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {56, - {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN}, - {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, DFS_TX_LEAKAGE_AUTO_MIN}, - {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, 611}, {104, 611}, - {108, 617}, {112, 617}, - {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, - {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {56, 5280, + {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN}, + {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN}, + {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, 611}, {104, 5520, 611}, + {108, 5540, 617}, {112, 5560, 617}, + {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, + {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {60, - {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN}, - {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, DFS_TX_LEAKAGE_AUTO_MIN}, - {52, 190}, {56, 190}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, 608}, {104, 608}, - {108, 623}, {112, 623}, - {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, - {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {60, 5300, + {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN}, + {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN}, + {52, 5260, 190}, {56, 5280, 190}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, 608}, {104, 5520, 608}, + {108, 5540, 623}, {112, 5560, 623}, + {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, + {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {64, - {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, DFS_TX_LEAKAGE_AUTO_MIN}, - {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, DFS_TX_LEAKAGE_AUTO_MIN}, - {52, 295}, {56, 295}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, 594}, {104, 594}, - {108, 625}, {112, 625}, - {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, - {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {64, 5320, + {{36, 5180, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN}, + {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, DFS_TX_LEAKAGE_AUTO_MIN}, + {52, 5260, 295}, {56, 5280, 295}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, 594}, {104, 5520, 594}, + {108, 5540, 625}, {112, 5560, 625}, + {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, + {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {100, - {{36, 618}, {40, 618}, - {44, 604}, {48, 604}, - {52, 596}, {56, 596}, - {60, 584}, {64, 584}, - {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, - {108, 299}, {112, 299}, - {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, - {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, - {132, 538}, {136, 538}, - {140, 598}, - {144, DFS_TX_LEAKAGE_MIN} + {100, 5500, + {{36, 5180, 618}, {40, 5200, 618}, + {44, 5220, 604}, {48, 5240, 604}, + {52, 5260, 596}, {56, 5280, 596}, + {60, 5300, 584}, {64, 5320, 584}, + {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, + {108, 5540, 299}, {112, 5560, 299}, + {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, + {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, + {132, 5660, 538}, {136,5680, 538}, + {140, 5700, 598}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {104, - {{36, 636}, {40, 636}, - {44, 601}, {48, 601}, - {52, 616}, {56, 616}, - {60, 584}, {64, 584}, - {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, - {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, - {132, 553}, {136, 553}, - {140, 568}, - {144, DFS_TX_LEAKAGE_MIN} + {104, 5520, + {{36, 5180, 636}, {40, 5200, 636}, + {44, 5220, 601}, {48, 5240, 601}, + {52, 5260, 616}, {56, 5280, 616}, + {60, 5300, 584}, {64, 5320, 584}, + {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, + {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, + {132, 5660, 553}, {136, 5680, 553}, + {140, 5700, 568}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {108, - {{36, 600}, {40, 600}, - {44, 627}, {48, 627}, - {52, 611}, {56, 611}, - {60, 611}, {64, 611}, - {100, 214}, {104, 214}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, - {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, - {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN}, - {140, 534}, - {144, DFS_TX_LEAKAGE_MIN} + {108, 5540, + {{36, 5180, 600}, {40, 5200, 600}, + {44, 5220, 627}, {48, 5240, 627}, + {52, 5260, 611}, {56, 5280, 611}, + {60, 5300, 611}, {64, 5320, 611}, + {100, 5500, 214}, {104, 5520, 214}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, + {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, + {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN}, + {140, 5700, 534}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {112, - {{36, 645}, {40, 645}, - {44, 641}, {48, 641}, - {52, 618}, {56, 618}, - {60, 612}, {64, 612}, - {100, 293}, {104, 293}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, - {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN}, - {140, 521}, - {144, DFS_TX_LEAKAGE_MIN} + {112, 5560, + {{36, 5180, 645}, {40, 5200, 645}, + {44, 5220, 641}, {48, 5240, 641}, + {52, 5260, 618}, {56, 5280, 618}, + {60, 5300, 612}, {64, 5320, 612}, + {100, 5500, 293}, {104, 5520, 293}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, + {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN}, + {140, 5700, 521}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {116, - {{36, 661}, {40, 661}, - {44, 624}, {48, 624}, - {52, 634}, {56, 634}, - {60, 611}, {64, 611}, - {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN}, - {108, 217}, {112, 217}, - {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, - {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN}, - {140, DFS_TX_LEAKAGE_AUTO_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {116, 5580, + {{36, 5180, 661}, {40, 5200, 661}, + {44, 5220, 624}, {48, 5240, 624}, + {52, 5260, 634}, {56, 5280, 634}, + {60, 5300, 611}, {64, 5320, 611}, + {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN}, + {108, 5540, 217}, {112, 5560, 217}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, + {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN}, + {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {120, - {{36, 667}, {40, 667}, - {44, 645}, {48, 645}, - {52, 633}, {56, 633}, - {60, 619}, {64, 619}, - {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN}, - {108, 291}, {112, 291}, - {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN}, - {140, DFS_TX_LEAKAGE_AUTO_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {120, 5600, + {{36, 5180, 667}, {40, 5200, 667}, + {44, 5220, 645}, {48, 5240, 645}, + {52, 5260, 633}, {56, 5280, 633}, + {60, 5300, 619}, {64, 5320, 619}, + {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN}, + {108, 5540, 291}, {112, 5560, 291}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN}, + {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {124, - {{36, 676}, {40, 676}, - {44, 668}, {48, 668}, - {52, 595}, {56, 595}, - {60, 622}, {64, 622}, - {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN}, - {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN}, - {116, 225}, {120, 225}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_AUTO_MIN}, {136, DFS_TX_LEAKAGE_AUTO_MIN}, - {140, DFS_TX_LEAKAGE_AUTO_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {124, 5620, + {{36, 5180, 676}, {40, 5200, 676}, + {44, 5220, 668}, {48, 5240, 668}, + {52, 5260, 595}, {56, 5280, 595}, + {60, 5300, 622}, {64, 5320, 622}, + {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN}, + {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN}, + {116, 5580, 225}, {120, 5600, 225}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_AUTO_MIN}, {136, 5680, DFS_TX_LEAKAGE_AUTO_MIN}, + {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {128, - {{36, 678}, {40, 678}, - {44, 664}, {48, 664}, - {52, 651}, {56, 651}, - {60, 643}, {64, 643}, - {100, DFS_TX_LEAKAGE_AUTO_MIN}, {104, DFS_TX_LEAKAGE_AUTO_MIN}, - {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN}, - {116, 293}, {120, 293}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_AUTO_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {128, 5640, + {{36, 5180, 678}, {40, 5200, 678}, + {44, 5220, 664}, {48, 5240, 664}, + {52, 5260, 651}, {56, 5280, 651}, + {60, 5300, 643}, {64, 5320, 643}, + {100, 5500, DFS_TX_LEAKAGE_AUTO_MIN}, {104, 5520, DFS_TX_LEAKAGE_AUTO_MIN}, + {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN}, + {116, 5580, 293}, {120, 5600, 293}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_AUTO_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {132, - {{36, 689}, {40, 689}, - {44, 669}, {48, 669}, - {52, 662}, {56, 662}, - {60, 609}, {64, 609}, - {100, 538}, {104, 538}, - {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN}, - {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, - {124, 247}, {128, 247}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {132, 5660, + {{36, 5180, 689}, {40, 5200, 689}, + {44, 5220, 669}, {48, 5240, 669}, + {52, 5260, 662}, {56, 5280, 662}, + {60, 5300, 609}, {64, 5320, 609}, + {100, 5500, 538}, {104, 5520, 538}, + {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN}, + {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, + {124, 5620, 247}, {128, 5640, 247}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {136, - {{36, 703}, {40, 703}, - {44, 688}, {48, DFS_TX_LEAKAGE_MIN}, - {52, 671}, {56, 671}, - {60, 658}, {64, 658}, - {100, 504}, {104, 504}, - {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN}, - {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, - {124, 289}, {128, 289}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {136, 5680, + {{36, 5180, 703}, {40, 5200, 703}, + {44, 5220, 688}, {48, 5240, DFS_TX_LEAKAGE_MIN}, + {52, 5260, 671}, {56, 5280, 671}, + {60, 5300, 658}, {64, 5320, 658}, + {100, 5500, 504}, {104, 5520, 504}, + {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN}, + {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, + {124, 5620, 289}, {128, 5640, 289}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {140, - {{36, 695}, {40, 695}, - {44, 684}, {48, 684}, - {52, 664}, {56, 664}, - {60, 658}, {64, 658}, - {100, 601}, {104, 601}, - {108, 545}, {112, 545}, - {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, - {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, - {132, 262}, {136, 262}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {140, 5700, + {{36, 5180, 695}, {40, 5200, 695}, + {44, 5220, 684}, {48, 5240, 684}, + {52, 5260, 664}, {56, 5280, 664}, + {60, 5300, 658}, {64, 5320, 658}, + {100, 5500, 601}, {104, 5520, 601}, + {108, 5540, 545}, {112, 5560, 545}, + {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, + {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, + {132, 5660, 262}, {136, 5680, 262}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {144, - {{36, 695}, {40, 695}, - {44, 684}, {48, 684}, - {52, 664}, {56, 664}, - {60, 658}, {64, 658}, - {100, 601}, {104, 601}, - {108, 545}, {112, 545}, - {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, DFS_TX_LEAKAGE_AUTO_MIN}, - {124, DFS_TX_LEAKAGE_AUTO_MIN}, {128, DFS_TX_LEAKAGE_AUTO_MIN}, - {132, 262}, {136, 262}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {144, 5720, + {{36, 5180, 695}, {40, 5200, 695}, + {44, 5220, 684}, {48, 5240, 684}, + {52, 5260, 664}, {56, 5280, 664}, + {60, 5300, 658}, {64, 5320, 658}, + {100, 5500, 601}, {104, 5520, 601}, + {108, 5540, 545}, {112, 5560, 545}, + {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, DFS_TX_LEAKAGE_AUTO_MIN}, + {124, 5620, DFS_TX_LEAKAGE_AUTO_MIN}, {128, 5640, DFS_TX_LEAKAGE_AUTO_MIN}, + {132, 5660, 262}, {136, 5680, 262}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, }; /* channel tx leakage table - ht20 */ struct dfs_matrix_tx_leak_info ht20_chan[] = { - {52, - {{36, DFS_TX_LEAKAGE_AUTO_MIN}, {40, 286}, - {44, 225}, {48, 121}, - {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, - {60, 300}, {64, DFS_TX_LEAKAGE_AUTO_MIN}, - {100, 637}, {104, DFS_TX_LEAKAGE_MAX}, - {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, - {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, - {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {52, 5260, + {{36, 5180,DFS_TX_LEAKAGE_AUTO_MIN}, {40, 5200, 286}, + {44, 5220, 225}, {48,5240, 121}, + {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, + {60, 5300, 300}, {64, 5320, DFS_TX_LEAKAGE_AUTO_MIN}, + {100, 5500, 637}, {104, 5520, DFS_TX_LEAKAGE_MAX}, + {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, + {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, + {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {56, - {{36, 468}, {40, DFS_TX_LEAKAGE_AUTO_MIN}, - {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 206}, - {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX}, - {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, - {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, - {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {56, 5280, + {{36, 5180, 468}, {40, 5200, DFS_TX_LEAKAGE_AUTO_MIN}, + {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 5240, 206}, + {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX}, + {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, + {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, + {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {60, - {{36, 507}, {40, 440}, - {44, DFS_TX_LEAKAGE_AUTO_MIN}, {48, 313}, - {52, DFS_TX_LEAKAGE_MIN}, {56, DFS_TX_LEAKAGE_MIN}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX}, - {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, - {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, - {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {60, 5300, + {{36, 5180, 507}, {40, 5200, 440}, + {44, 5220, DFS_TX_LEAKAGE_AUTO_MIN}, {48,5240, 313}, + {52, 5260, DFS_TX_LEAKAGE_MIN}, {56, 5280, DFS_TX_LEAKAGE_MIN}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX}, + {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, + {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, + {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {64, - {{36, 516}, {40, 520}, - {44, 506}, {48, DFS_TX_LEAKAGE_AUTO_MIN}, - {52, 301}, {56, 258}, - {60, DFS_TX_LEAKAGE_MIN}, {64, DFS_TX_LEAKAGE_MIN}, - {100, 620}, {104, 617}, - {108, DFS_TX_LEAKAGE_MAX}, {112, DFS_TX_LEAKAGE_MAX}, - {116, DFS_TX_LEAKAGE_MAX}, {120, DFS_TX_LEAKAGE_MAX}, - {124, DFS_TX_LEAKAGE_MAX}, {128, DFS_TX_LEAKAGE_MAX}, - {132, DFS_TX_LEAKAGE_MAX}, {136, DFS_TX_LEAKAGE_MAX}, - {140, DFS_TX_LEAKAGE_MAX}, - {144, DFS_TX_LEAKAGE_MIN} + {64, 5320 , + {{36, 5180, 516}, {40, 5200, 520}, + {44, 5220, 506}, {48, 5240,DFS_TX_LEAKAGE_AUTO_MIN}, + {52, 5260, 301}, {56, 5280, 258}, + {60, 5300, DFS_TX_LEAKAGE_MIN}, {64, 5320, DFS_TX_LEAKAGE_MIN}, + {100, 5500, 620}, {104, 5520, 617}, + {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, DFS_TX_LEAKAGE_MAX}, + {116, 5580, DFS_TX_LEAKAGE_MAX}, {120, 5600, DFS_TX_LEAKAGE_MAX}, + {124, 5620, DFS_TX_LEAKAGE_MAX}, {128, 5640, DFS_TX_LEAKAGE_MAX}, + {132, 5660, DFS_TX_LEAKAGE_MAX}, {136, 5680, DFS_TX_LEAKAGE_MAX}, + {140, 5700, DFS_TX_LEAKAGE_MAX}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {100, - {{36, 616}, {40, 601}, - {44, 604}, {48, 589}, - {52, 612}, {56, 592}, - {60, 590}, {64, 582}, - {100, DFS_TX_LEAKAGE_MIN}, {104, 131}, - {108, DFS_TX_LEAKAGE_AUTO_MIN}, {112, DFS_TX_LEAKAGE_AUTO_MIN}, - {116, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 522}, - {124, 571}, {128, 589}, - {132, 593}, {136, 598}, - {140, 594}, - {144, DFS_TX_LEAKAGE_MIN}, + {100, 5500, + {{36, 5180, 616}, {40, 5200, 601}, + {44, 5220, 604}, {48, 5240, 589}, + {52, 5260, 612}, {56, 5280, 592}, + {60, 5300, 590}, {64, 5320, 582}, + {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, 131}, + {108, 5540, DFS_TX_LEAKAGE_AUTO_MIN}, {112, 5560, DFS_TX_LEAKAGE_AUTO_MIN}, + {116, 5580, DFS_TX_LEAKAGE_AUTO_MIN}, {120, 5600, 522}, + {124, 5620, 571}, {128, 5640, 589}, + {132, 5660, 593}, {136, 5680, 598}, + {140, 5700, 594}, + {144, 5720, DFS_TX_LEAKAGE_MIN}, } }, - {104, - {{36, 622}, {40, 624}, - {44, 618}, {48, 610}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, DFS_TX_LEAKAGE_MIN}, {104, DFS_TX_LEAKAGE_MIN}, - {108, DFS_TX_LEAKAGE_MIN}, {112, 463}, - {116, 483}, {120, 503}, - {124, 523}, {128, 565}, - {132, 570}, {136, 588}, - {140, 585}, - {144, DFS_TX_LEAKAGE_MIN}, + {104, 5520, + {{36, 5180, 622}, {40, 5200, 624}, + {44, 5220, 618}, {48, 5240, 610}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, DFS_TX_LEAKAGE_MIN}, {104, 5520, DFS_TX_LEAKAGE_MIN}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, 463}, + {116, 5580, 483}, {120, 5600, 503}, + {124, 5620, 523}, {128, 5640, 565}, + {132, 5660, 570}, {136, 5680, 588}, + {140, 5700, 585}, + {144, 5720, DFS_TX_LEAKAGE_MIN}, } }, - {108, - {{36, 620}, {40, 638}, - {44, 611}, {48, 614}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, 477}, {104, DFS_TX_LEAKAGE_MIN}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, 477}, {120, 497}, - {124, 517}, {128, 537}, - {132, 557}, {136, 577}, - {140, 603}, - {144, DFS_TX_LEAKAGE_MIN}, + {108, 5540, + {{36, 5180, 620}, {40, 5200, 638}, + {44, 5220, 611}, {48, 5240, 614}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, 477}, {104, 5520, DFS_TX_LEAKAGE_MIN}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, 477}, {120, 5600, 497}, + {124, 5620, 517}, {128, 5640, 537}, + {132, 5660, 557}, {136, 5680, 577}, + {140, 5700, 603}, + {144, 5720, DFS_TX_LEAKAGE_MIN}, } }, - {112, - {{36, 636}, {40, 623}, - {44, 638}, {48, 628}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, DFS_TX_LEAKAGE_MAX}, {64, 606}, - {100, 501}, {104, 481}, - {108, DFS_TX_LEAKAGE_MIN}, {112, DFS_TX_LEAKAGE_MIN}, - {116, DFS_TX_LEAKAGE_MIN}, {120, 481}, - {124, 501}, {128, 421}, - {132, 541}, {136, 561}, - {140, 583}, - {144, DFS_TX_LEAKAGE_MIN}, + {112, 5560, + {{36, 5180, 636}, {40, 5200, 623}, + {44, 5220, 638}, {48, 5240, 628}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, 606}, + {100, 5500, 501}, {104, 5520, 481}, + {108, 5540, DFS_TX_LEAKAGE_MIN}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, 481}, + {124, 5620, 501}, {128, 5640, 421}, + {132, 5660, 541}, {136, 5680, 561}, + {140, 5700, 583}, + {144, 5720, DFS_TX_LEAKAGE_MIN}, } }, - {116, - {{36, 646}, {40, 648}, - {44, 633}, {48, 634}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, 615}, {64, 594}, - {100, 575}, {104, 554}, - {108, 534}, {112, DFS_TX_LEAKAGE_MIN}, - {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, 534}, {136, 554}, - {140, 574}, - {144, DFS_TX_LEAKAGE_MIN}, + {116, 5580, + {{36, 5180, 646}, {40, 5200, 648}, + {44, 5220, 633}, {48, 5240, 634}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, 615}, {64, 5320, 594}, + {100, 5500, 575}, {104, 5520, 554}, + {108, 5540, 534}, {112, 5560, DFS_TX_LEAKAGE_MIN}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, 534}, {136, 5680, 554}, + {140, 5700, 574}, + {144, 5720, DFS_TX_LEAKAGE_MIN}, } }, - {120, - {{36, 643}, {40, 649}, - {44, 654}, {48, 629}, - {52, DFS_TX_LEAKAGE_MAX}, {56, 621}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, 565}, {104, 545}, - {108, 525}, {112, 505}, - {116, DFS_TX_LEAKAGE_MIN}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, 505}, - {132, 525}, {136, 545}, - {140, 565}, - {144, DFS_TX_LEAKAGE_MIN}, + {120, 5600, + {{36, 5180, 643}, {40, 5200, 649}, + {44, 5220, 654}, {48, 5240, 629}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, 621}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, 565}, {104, 5520, 545}, + {108, 5540, 525}, {112, 5560, 505}, + {116, 5580, DFS_TX_LEAKAGE_MIN}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, 505}, + {132, 5660, 525}, {136, 5680, 545}, + {140, 5700, 565}, + {144, 5720, DFS_TX_LEAKAGE_MIN}, } }, - {124, - {{36, 638}, {40, 657}, - {44, 663}, {48, 649}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, 581}, {104, 561}, - {108, 541}, {112, 521}, - {116, 499}, {120, DFS_TX_LEAKAGE_MIN}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, 499}, {136, 519}, - {140, 539}, - {144, DFS_TX_LEAKAGE_MIN} + {124, 5620, + {{36, 5180, 638}, {40, 5200, 657}, + {44, 5220, 663}, {48, 5240, 649}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, 581}, {104, 5520, 561}, + {108, 5540, 541}, {112, 5560, 521}, + {116, 5580, 499}, {120, 5600, DFS_TX_LEAKAGE_MIN}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, 499}, {136, 5680, 519}, + {140, 5700, 539}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {128, - {{36, 651}, {40, 651}, - {44, 674}, {48, 640}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, 603}, {104, 560}, - {108, 540}, {112, 520}, - {116, 499}, {120, 479}, - {124, DFS_TX_LEAKAGE_MIN}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, 479}, - {140, 499}, - {144, DFS_TX_LEAKAGE_MIN} + {128, 5640, + {{36, 5180, 651}, {40, 5200, 651}, + {44, 5220, 674}, {48, 5240, 640}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, 603}, {104, 5520, 560}, + {108, 5540, 540}, {112, 5560, 520}, + {116, 5580, 499}, {120, 5600, 479}, + {124, 5620, DFS_TX_LEAKAGE_MIN}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, 479}, + {140, 5700, 499}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {132, - {{36, 643}, {40, 668}, - {44, 651}, {48, 657}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, DFS_TX_LEAKAGE_MAX}, {104, 602}, - {108, 578}, {112, 570}, - {116, 550}, {120, 530}, - {124, 510}, {128, DFS_TX_LEAKAGE_MIN}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, 490}, - {144, DFS_TX_LEAKAGE_MIN} + {132, 5660, + {{36, 5180, 643}, {40, 5200, 668}, + {44, 5220, 651}, {48, 5240, 657}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, 602}, + {108, 5540, 578}, {112,5560, 570}, + {116, 5580, 550}, {120, 5600, 530}, + {124, 5620, 510}, {128, 5640, DFS_TX_LEAKAGE_MIN}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, 490}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {136, - {{36, 654}, {40, 667}, - {44, 666}, {48, 642}, - {52, DFS_TX_LEAKAGE_MAX}, {56, DFS_TX_LEAKAGE_MAX}, - {60, DFS_TX_LEAKAGE_MAX}, {64, DFS_TX_LEAKAGE_MAX}, - {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX}, - {108, DFS_TX_LEAKAGE_MAX}, {112, 596}, - {116, 555}, {120, 535}, - {124, 515}, {128, 495}, - {132, DFS_TX_LEAKAGE_MIN}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {136,5680, + {{36, 5180, 654}, {40, 5200, 667}, + {44, 5220, 666}, {48, 5240, 642}, + {52, 5260, DFS_TX_LEAKAGE_MAX}, {56, 5280, DFS_TX_LEAKAGE_MAX}, + {60, 5300, DFS_TX_LEAKAGE_MAX}, {64, 5320, DFS_TX_LEAKAGE_MAX}, + {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX}, + {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 596}, + {116, 5580, 555}, {120, 5600, 535}, + {124, 5620, 515}, {128, 5640, 495}, + {132, 5660, DFS_TX_LEAKAGE_MIN}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {140, - {{36, 679}, {40, 673}, - {44, 667}, {48, 656}, - {52, 634}, {56, 663}, - {60, 662}, {64, 660}, - {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX}, - {108, DFS_TX_LEAKAGE_MAX}, {112, 590}, - {116, 573}, {120, 553}, - {124, 533}, {128, 513}, - {132, 490}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {140,5700, + {{36, 5180, 679}, {40, 5200, 673}, + {44, 5220, 667}, {48, 5240, 656}, + {52, 5260, 634}, {56, 5280, 663}, + {60, 5300, 662}, {64, 5320, 660}, + {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX}, + {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 590}, + {116, 5580, 573}, {120, 5600, 553}, + {124, 5620, 533}, {128, 5640, 513}, + {132, 5660, 490}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, - {144, - {{36, 679}, {40, 673}, - {44, 667}, {48, 656}, - {52, 634}, {56, 663}, - {60, 662}, {64, 660}, - {100, DFS_TX_LEAKAGE_MAX}, {104, DFS_TX_LEAKAGE_MAX}, - {108, DFS_TX_LEAKAGE_MAX}, {112, 590}, - {116, 573}, {120, 553}, - {124, 533}, {128, 513}, - {132, 490}, {136, DFS_TX_LEAKAGE_MIN}, - {140, DFS_TX_LEAKAGE_MIN}, - {144, DFS_TX_LEAKAGE_MIN} + {144,5720, + {{36, 5180, 679}, {40, 5200, 673}, + {44, 5220, 667}, {48, 5240, 656}, + {52, 5260, 634}, {56, 5280, 663}, + {60, 5300, 662}, {64, 5320, 660}, + {100, 5500, DFS_TX_LEAKAGE_MAX}, {104, 5520, DFS_TX_LEAKAGE_MAX}, + {108, 5540, DFS_TX_LEAKAGE_MAX}, {112, 5560, 590}, + {116, 5580, 573}, {120, 5600, 553}, + {124, 5620, 533}, {128, 5640, 513}, + {132, 5660, 490}, {136, 5680, DFS_TX_LEAKAGE_MIN}, + {140, 5700, DFS_TX_LEAKAGE_MIN}, + {144, 5720, DFS_TX_LEAKAGE_MIN} } }, }; @@ -723,6 +724,7 @@ struct dfs_matrix_tx_leak_info ht20_chan[] = { * * Return: TRUE or FALSE */ +#ifdef CONFIG_CHAN_NUM_API static bool dfs_find_target_channel_in_channel_matrix(enum phy_ch_width ch_width, uint8_t NOL_channel, @@ -771,7 +773,72 @@ dfs_find_target_channel_in_channel_matrix(enum phy_ch_width ch_width, return true; } } +#endif + +/* + * dfs_find_target_channel_in_channel_matrix_for_freq() - finds the leakage + * matrix. + * @chan_width: target channel width + * @nol_channel: the NOL channel frequency whose leakage matrix is required + * @pTarget_chnl_mtrx: pointer to target channel matrix returned. + * + * This function gives the leakage matrix for given NOL channel and ch_width + * + * Return: TRUE or FALSE + */ +#ifdef CONFIG_CHAN_FREQ_API +static bool +dfs_find_target_channel_in_channel_matrix_for_freq(enum phy_ch_width chan_width, + uint16_t nol_freq, + struct dfs_tx_leak_info + **pTarget_chnl_mtrx) +{ + struct dfs_tx_leak_info *target_chan_matrix = NULL; + struct dfs_matrix_tx_leak_info *pchan_matrix = NULL; + uint32_t nchan_matrix; + int i = 0; + switch (chan_width) { + case CH_WIDTH_20MHZ: + /* HT20 */ + pchan_matrix = ht20_chan; + nchan_matrix = QDF_ARRAY_SIZE(ht20_chan); + break; + case CH_WIDTH_40MHZ: + /* HT40 */ + pchan_matrix = ht40_chan; + nchan_matrix = QDF_ARRAY_SIZE(ht40_chan); + break; + case CH_WIDTH_80MHZ: + /* HT80 */ + pchan_matrix = ht80_chan; + nchan_matrix = QDF_ARRAY_SIZE(ht80_chan); + break; + default: + /* handle exception and fall back to HT20 table */ + pchan_matrix = ht20_chan; + nchan_matrix = QDF_ARRAY_SIZE(ht20_chan); + break; + } + + for (i = 0; i < nchan_matrix; i++) { + /* find the SAP channel to map the leakage matrix */ + if (nol_freq == pchan_matrix[i].channel_freq) { + target_chan_matrix = pchan_matrix[i].chan_matrix; + break; + } + } + + if (!target_chan_matrix) { + return false; + } else { + *pTarget_chnl_mtrx = target_chan_matrix; + return true; + } +} +#endif + +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS dfs_mark_leaking_ch(struct wlan_dfs *dfs, enum phy_ch_width ch_width, @@ -779,7 +846,7 @@ dfs_mark_leaking_ch(struct wlan_dfs *dfs, uint8_t *temp_ch_lst) { struct dfs_tx_leak_info *target_chan_matrix = NULL; - uint32_t num_channel = (CHAN_ENUM_144 - CHAN_ENUM_36) + 1; + uint32_t num_channel = (CHAN_ENUM_5720 - CHAN_ENUM_5180) + 1; uint32_t j = 0; uint32_t k = 0; uint8_t dfs_nol_channel; @@ -838,7 +905,79 @@ dfs_mark_leaking_ch(struct wlan_dfs *dfs, return QDF_STATUS_SUCCESS; } +#endif + +#ifdef CONFIG_CHAN_FREQ_API +#define END_CHAN_INDEX CHAN_ENUM_5720 +#define START_CHAN_INDEX CHAN_ENUM_5180 +QDF_STATUS +dfs_mark_leaking_chan_for_freq(struct wlan_dfs *dfs, + enum phy_ch_width ch_width, + uint8_t temp_chan_lst_sz, + uint16_t *temp_freq_lst) +{ + struct dfs_tx_leak_info *target_chan_matrix = NULL; + uint32_t num_channel = (END_CHAN_INDEX - START_CHAN_INDEX) + 1; + uint32_t j = 0; + uint32_t k = 0; + struct dfs_nolelem *nol; + + nol = dfs->dfs_nol; + while (nol) { + if (false == dfs_find_target_channel_in_channel_matrix_for_freq( + ch_width, nol->nol_freq, + &target_chan_matrix)) { + /* + * should never happen, we should always find a table + * here, if we don't, need a fix here! + */ + dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "Couldn't find target channel matrix!"); + QDF_ASSERT(0); + return QDF_STATUS_E_FAILURE; + } + /* + * following is based on assumption that both temp_freq_lst + * and target channel matrix are in increasing order of + * ch_id + */ + for (j = 0, k = 0; j < temp_chan_lst_sz && k < num_channel;) { + if (temp_freq_lst[j] == 0) { + j++; + continue; + } + if (target_chan_matrix[k].leak_chan_freq != + temp_freq_lst[j]) { + k++; + continue; + } + /* + * check leakage from candidate channel + * to NOL channel + */ + if (target_chan_matrix[k].leak_lvl <= + dfs->tx_leakage_threshold) { + /* + * candidate channel will have + * bad leakage in NOL channel, + * remove from temp list + */ + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "dfs: channel: %d will have bad leakage due to channel: %d\n", + nol->nol_freq, temp_freq_lst[j]); + temp_freq_lst[j] = 0; + } + j++; + k++; + } + nol = nol->nol_next; + } /* end of loop that selects each NOL */ + + return QDF_STATUS_SUCCESS; +} +#endif #else +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS dfs_mark_leaking_ch(struct wlan_dfs *dfs, enum phy_ch_width ch_width, @@ -848,18 +987,30 @@ dfs_mark_leaking_ch(struct wlan_dfs *dfs, return QDF_STATUS_SUCCESS; } #endif +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS +dfs_mark_leaking_chan_for_freq(struct wlan_dfs *dfs, + enum phy_ch_width ch_width, + uint8_t temp_chan_lst_sz, + uint16_t *temp_freq_lst) +{ + return QDF_STATUS_SUCCESS; +} +#endif +#endif /** * dfs_populate_80mhz_available_channels()- Populate channels for 80MHz using * bitmap * @dfs: Pointer to DFS structure. * @bitmap: bitmap - * @avail_chnl: prepared channel list + * @avail_freq_list: prepared channel list * * Prepare 80MHz channels from the bitmap. * * Return: channel count */ +#ifdef CONFIG_CHAN_NUM_API static uint8_t dfs_populate_80mhz_available_channels( struct wlan_dfs *dfs, struct chan_bonding_bitmap *bitmap, @@ -889,6 +1040,46 @@ static uint8_t dfs_populate_80mhz_available_channels( return chnl_count; } +#endif + +/* + * dfs_populate_80mhz_available_channel_for_freq() - Populate 80MHZ channels + * available for selection. + * @dfs: Pointer to wlan_dfs. + * @bitmap: Pointer to bonding channel bitmap. + * @avail_freq_list: Pointer to frequency list of available channels. + */ +#ifdef CONFIG_CHAN_FREQ_API +static uint8_t dfs_populate_80mhz_available_channel_for_freq( + struct wlan_dfs *dfs, + struct chan_bonding_bitmap *bitmap, + uint16_t *avail_freq_list) +{ + uint8_t i = 0; + uint8_t chnl_count = 0; + uint16_t start_chan_freq = 0; + + for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { + start_chan_freq = bitmap->chan_bonding_set[i].start_chan_freq; + if (bitmap->chan_bonding_set[i].chan_map == + DFS_80MHZ_MASK) { + avail_freq_list[chnl_count++] = start_chan_freq + + (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 0); + avail_freq_list[chnl_count++] = start_chan_freq + + (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 1); + avail_freq_list[chnl_count++] = start_chan_freq + + (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 2); + avail_freq_list[chnl_count++] = start_chan_freq + + (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 3); + } + } + + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "channel count %d", chnl_count); + + return chnl_count; +} +#endif /** * dfs_populate_40mhz_available_channels()- Populate channels for 40MHz using @@ -901,6 +1092,7 @@ static uint8_t dfs_populate_80mhz_available_channels( * * Return: channel count */ +#ifdef CONFIG_CHAN_NUM_API static uint8_t dfs_populate_40mhz_available_channels( struct wlan_dfs *dfs, struct chan_bonding_bitmap *bitmap, @@ -933,6 +1125,42 @@ static uint8_t dfs_populate_40mhz_available_channels( return chnl_count; } +#endif + +#ifdef CONFIG_CHAN_FREQ_API +static uint8_t +dfs_populate_40mhz_available_channel_for_freq(struct wlan_dfs *dfs, + struct chan_bonding_bitmap *bmap, + uint16_t *avail_freq_list) +{ + uint8_t i = 0; + uint8_t chnl_count = 0; + uint16_t start_chan_freq = 0; + + for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { + start_chan_freq = bmap->chan_bonding_set[i].start_chan_freq; + if ((bmap->chan_bonding_set[i].chan_map & + DFS_40MHZ_MASK_L) == DFS_40MHZ_MASK_L) { + avail_freq_list[chnl_count++] = start_chan_freq + + (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 0); + avail_freq_list[chnl_count++] = start_chan_freq + + (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 1); + } + if ((bmap->chan_bonding_set[i].chan_map & + DFS_40MHZ_MASK_H) == DFS_40MHZ_MASK_H) { + avail_freq_list[chnl_count++] = start_chan_freq + + (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 2); + avail_freq_list[chnl_count++] = start_chan_freq + + (DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET * 3); + } + } + + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "channel count %d", chnl_count); + + return chnl_count; +} +#endif /** * dfs_populate_available_channels()- Populate channels based on width and @@ -946,6 +1174,7 @@ static uint8_t dfs_populate_40mhz_available_channels( * * Return: channel count */ +#ifdef CONFIG_CHAN_NUM_API static uint8_t dfs_populate_available_channels( struct wlan_dfs *dfs, struct chan_bonding_bitmap *bitmap, @@ -969,6 +1198,47 @@ static uint8_t dfs_populate_available_channels( return 0; } +#endif + +/** + * dfs_populate_available_channel_for_freq()- Populate channels based on width + * and bitmap. + * @dfs: Pointer to DFS structure. + * @bitmap: bitmap + * @chan_width: channel width + * @avail_freq_list: prepared channel list + * + * Prepare channel list based on width and channel bitmap. + * + * Return: channel count + */ +#ifdef CONFIG_CHAN_FREQ_API +static uint8_t +dfs_populate_available_channel_for_freq(struct wlan_dfs *dfs, + struct chan_bonding_bitmap *bitmap, + uint8_t chan_width, + uint16_t *freq_list) +{ + switch (chan_width) { + case DFS_CH_WIDTH_160MHZ: + case DFS_CH_WIDTH_80P80MHZ: + case DFS_CH_WIDTH_80MHZ: + return dfs_populate_80mhz_available_channel_for_freq(dfs, + bitmap, + freq_list); + case DFS_CH_WIDTH_40MHZ: + return dfs_populate_40mhz_available_channel_for_freq(dfs, + bitmap, + freq_list); + default: + dfs_err(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "Invalid chan_width %d", chan_width); + break; + } + + return 0; +} +#endif /** * dfs_get_rand_from_lst()- Get random channel from a given channel list @@ -980,6 +1250,7 @@ static uint8_t dfs_populate_available_channels( * * Return: channel number */ +#ifdef CONFIG_CHAN_NUM_API static uint8_t dfs_get_rand_from_lst( struct wlan_dfs *dfs, uint8_t *ch_lst, @@ -1003,6 +1274,44 @@ static uint8_t dfs_get_rand_from_lst( return ch_lst[i]; } +#endif + +/** + * dfs_get_rand_from_lst_for_freq()- Get random channel from a given channel + * list. + * @dfs: Pointer to DFS structure. + * @freq_lst: Frequency list + * @num_chan: number of channels + * + * Get random channel from given channel list. + * + * Return: channel frequency. + */ + +#ifdef CONFIG_CHAN_FREQ_API +static uint16_t dfs_get_rand_from_lst_for_freq(struct wlan_dfs *dfs, + uint16_t *freq_lst, + uint8_t num_chan) +{ + uint8_t i; + uint32_t rand_byte = 0; + + if (!num_chan || !freq_lst) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "invalid param freq_lst %pK, num_chan = %d", + freq_lst, num_chan); + return 0; + } + + get_random_bytes((uint8_t *)&rand_byte, 1); + i = (rand_byte + qdf_mc_timer_get_system_ticks()) % num_chan; + + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "random channel %d", freq_lst[i]); + + return freq_lst[i]; +} +#endif /** * dfs_random_channel_sel_set_bitmap()- Set channel bit in bitmap based @@ -1015,6 +1324,7 @@ static uint8_t dfs_get_rand_from_lst( * * Return: None */ +#ifdef CONFIG_CHAN_NUM_API static void dfs_random_channel_sel_set_bitmap( struct wlan_dfs *dfs, struct chan_bonding_bitmap *bitmap, @@ -1036,6 +1346,45 @@ static void dfs_random_channel_sel_set_bitmap( dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "Channel=%d is not in the bitmap", channel); } +#endif + +/** + * dfs_random_channel_sel_set_bitmap()- Set channel bit in bitmap based + * on given channel number + * @dfs: Pointer to DFS structure. + * @bitmap: bitmap + * @chan_freq: channel frequency + * + * Set channel bit in bitmap based on given channel frequency. + * + * Return: None + */ +#ifdef CONFIG_CHAN_FREQ_API +#define FREQUENCY_BAND_LIMIT 60 +static void +dfs_random_channel_sel_set_bitmap_for_freq(struct wlan_dfs *dfs, + struct chan_bonding_bitmap *bitmap, + uint16_t chan_freq) +{ + int i = 0; + int start_chan_freq = 0; + + for (i = 0; i < DFS_MAX_80MHZ_BANDS; i++) { + start_chan_freq = bitmap->chan_bonding_set[i].start_chan_freq; + if (chan_freq >= start_chan_freq && + chan_freq <= start_chan_freq + + FREQUENCY_BAND_LIMIT) { + bitmap->chan_bonding_set[i].chan_map |= + (1 << ((chan_freq - start_chan_freq) / + DFS_80_NUM_SUB_CHANNEL_FREQ)); + return; + } + } + + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "Frequency=%d is not in the bitmap", chan_freq); +} +#endif /** * dfs_find_ch_with_fallback()- find random channel @@ -1050,6 +1399,7 @@ static void dfs_random_channel_sel_set_bitmap( * * Return: channel number */ +#ifdef CONFIG_CHAN_NUM_API static uint8_t dfs_find_ch_with_fallback( struct wlan_dfs *dfs, uint8_t *ch_wd, @@ -1062,7 +1412,7 @@ static uint8_t dfs_find_ch_with_fallback( struct chan_bonding_bitmap ch_map = { { {0} } }; uint8_t count = 0, i, index = 0, final_cnt = 0, target_channel = 0; uint8_t primary_seg_start_ch = 0, sec_seg_ch = 0, new_160_start_ch = 0; - uint8_t final_lst[DFS_MAX_NUM_CHAN] = {0}; + uint8_t final_lst[NUM_CHANNELS] = {0}; /* initialize ch_map for all 80 MHz bands: we have 6 80MHz bands */ ch_map.chan_bonding_set[0].start_chan = 36; @@ -1184,27 +1534,159 @@ static uint8_t dfs_find_ch_with_fallback( return target_channel; } +#endif /** - * dfs_remove_cur_ch_from_list()- remove current operating channels - * @ch_list: list of avilable channel list - * @ch_cnt: number of channels. - * @ch_wd: channel width. - * @cur_chan: current channel. + * dfs_find_ch_with_fallback_for_freq()- find random channel + * @dfs: Pointer to DFS structure. + * @chan_wd: channel width + * @center_freq_seg1: center frequency of secondary segment. + * @freq_lst: list of available frequency. + * @num_chan: number of channels in the list. * - * Remove current channels from list of available channels. + * Find random channel based on given channel width and channel list, + * fallback to lower width if requested channel width not available. * - * Return: channel number + * Return: channel frequency. */ -static void dfs_remove_cur_ch_from_list( - struct dfs_channel *ch_list, - uint32_t *ch_cnt, - uint8_t *ch_wd, - struct dfs_channel *cur_chan) +#ifdef CONFIG_CHAN_FREQ_API +static uint16_t dfs_find_ch_with_fallback_for_freq(struct wlan_dfs *dfs, + uint8_t *chan_wd, + uint16_t *center_freq_seg1, + uint16_t *freq_lst, + uint32_t num_chan) { - /* TODO */ - return; + bool flag = false; + uint32_t rand_byte = 0; + struct chan_bonding_bitmap ch_map = { { {0} } }; + uint8_t count = 0, i, index = 0, final_cnt = 0; + uint16_t target_channel = 0; + uint16_t primary_seg_start_ch = 0, sec_seg_ch = 0, new_160_start_ch = 0; + uint16_t final_lst[NUM_CHANNELS] = {0}; + + /* initialize ch_map for all 80 MHz bands: we have 6 80MHz bands */ + ch_map.chan_bonding_set[0].start_chan_freq = 5180; + ch_map.chan_bonding_set[1].start_chan_freq = 5260; + ch_map.chan_bonding_set[2].start_chan_freq = 5500; + ch_map.chan_bonding_set[3].start_chan_freq = 5580; + ch_map.chan_bonding_set[4].start_chan_freq = 5660; + ch_map.chan_bonding_set[5].start_chan_freq = 5745; + + for (i = 0; i < num_chan; i++) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "channel = %d added to bitmap", freq_lst[i]); + dfs_random_channel_sel_set_bitmap_for_freq(dfs, &ch_map, + freq_lst[i]); + } + + /* populate available channel list from bitmap */ + final_cnt = dfs_populate_available_channel_for_freq(dfs, &ch_map, + *chan_wd, final_lst); + + /* If no valid ch bonding found, fallback */ + if (final_cnt == 0) { + if ((*chan_wd == DFS_CH_WIDTH_160MHZ) || + (*chan_wd == DFS_CH_WIDTH_80P80MHZ) || + (*chan_wd == DFS_CH_WIDTH_80MHZ)) { + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "from [%d] to 40Mhz", *chan_wd); + *chan_wd = DFS_CH_WIDTH_40MHZ; + } else if (*chan_wd == DFS_CH_WIDTH_40MHZ) { + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "from 40Mhz to 20MHz"); + *chan_wd = DFS_CH_WIDTH_20MHZ; + } + return 0; + } + + /* ch count should be > 8 to switch new channel in 160Mhz band */ + if (((*chan_wd == DFS_CH_WIDTH_160MHZ) || + (*chan_wd == DFS_CH_WIDTH_80P80MHZ)) && + (final_cnt < DFS_MAX_20M_SUB_CH)) { + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "from [%d] to 80Mhz", *chan_wd); + *chan_wd = DFS_CH_WIDTH_80MHZ; + return 0; + } + + if (*chan_wd == DFS_CH_WIDTH_160MHZ) { + /* + * Only 2 blocks for 160Mhz bandwidth i.e 36-64 & 100-128 + * and all the channels in these blocks are continuous + * and separated by 4Mhz. + */ + for (i = 1; ((i < final_cnt)); i++) { + if ((final_lst[i] - final_lst[i - 1]) == + DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET) + count++; + else + count = 0; + if (count == DFS_MAX_20M_SUB_CH - 1) { + flag = true; + new_160_start_ch = final_lst[i - count]; + break; + } + } + } else if (*chan_wd == DFS_CH_WIDTH_80P80MHZ) { + flag = true; + } + + if ((flag == false) && (*chan_wd > DFS_CH_WIDTH_80MHZ)) { + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "from [%d] to 80Mhz", *chan_wd); + *chan_wd = DFS_CH_WIDTH_80MHZ; + return 0; + } + + if (*chan_wd == DFS_CH_WIDTH_160MHZ) { + get_random_bytes((uint8_t *)&rand_byte, 1); + rand_byte = (rand_byte + qdf_mc_timer_get_system_ticks()) + % DFS_MAX_20M_SUB_CH; + target_channel = new_160_start_ch + (rand_byte * + DFS_80_NUM_SUB_CHANNEL_FREQ); + } else if (*chan_wd == DFS_CH_WIDTH_80P80MHZ) { + get_random_bytes((uint8_t *)&rand_byte, 1); + index = (rand_byte + qdf_mc_timer_get_system_ticks()) % + final_cnt; + target_channel = final_lst[index]; + index -= (index % DFS_80_NUM_SUB_CHANNEL); + primary_seg_start_ch = final_lst[index]; + + /* reset channels associate with primary 80Mhz */ + for (i = 0; i < DFS_80_NUM_SUB_CHANNEL; i++) + final_lst[i + index] = 0; + /* select and calculate center freq for secondary segment */ + for (i = 0; i < final_cnt / DFS_80_NUM_SUB_CHANNEL; i++) { + if (final_lst[i * DFS_80_NUM_SUB_CHANNEL] && + (abs(primary_seg_start_ch - + final_lst[i * DFS_80_NUM_SUB_CHANNEL]) > + (DFS_80P80M_FREQ_DIFF * 2))) { + sec_seg_ch = final_lst[i * + DFS_80_NUM_SUB_CHANNEL] + + DFS_80MHZ_START_CENTER_CH_FREQ_DIFF; + break; + } + } + + if (!sec_seg_ch && (final_cnt == DFS_MAX_20M_SUB_CH)) + *chan_wd = DFS_CH_WIDTH_160MHZ; + else if (!sec_seg_ch) + *chan_wd = DFS_CH_WIDTH_80MHZ; + + *center_freq_seg1 = sec_seg_ch; + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "Center frequency seg1 = %d", sec_seg_ch); + } else { + target_channel = dfs_get_rand_from_lst_for_freq(dfs, + final_lst, + final_cnt); + } + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "target channel = %d", target_channel); + + return target_channel; } +#endif bool dfs_is_freq_in_nol(struct wlan_dfs *dfs, uint32_t freq) { @@ -1241,8 +1723,9 @@ bool dfs_is_freq_in_nol(struct wlan_dfs *dfs, uint32_t freq) * * prepare channel list based on flags * - * Return: None + * return: none */ +#ifdef CONFIG_CHAN_NUM_API static void dfs_apply_rules(struct wlan_dfs *dfs, uint32_t flags, uint8_t *random_chan_list, @@ -1301,8 +1784,8 @@ static void dfs_apply_rules(struct wlan_dfs *dfs, if (acs_info && acs_info->acs_mode) { for (j = 0; j < acs_info->num_of_channel; j++) { - if (acs_info->channel_list[j] == - chan->dfs_ch_ieee) { + if (acs_info->chan_freq_list[j] == + wlan_chan_to_freq(chan->dfs_ch_ieee)) { found = true; break; } @@ -1379,7 +1862,178 @@ static void dfs_apply_rules(struct wlan_dfs *dfs, *random_chan_cnt += 1; } } +#endif + +/** + * dfs_apply_rules_for_freq()- prepare channel list based on flags + * @dfs: dfs handler + * @flags: channel flags + * @random_chan_freq_list: output channel list + * @random_chan_cnt: output channel count + * @chan_list: input channel list + * @chan_cnt: input channel count + * @dfs_region: dfs region + * @acs_info: acs channel range information + * + * prepare channel list based on flags + * + * return: none + */ +#ifdef CONFIG_CHAN_FREQ_API +static void dfs_apply_rules_for_freq(struct wlan_dfs *dfs, + uint32_t flags, + uint16_t *random_chan_freq_list, + uint32_t *random_chan_cnt, + struct dfs_channel *chan_list, + uint32_t chan_cnt, + uint8_t dfs_region, + struct dfs_acs_info *acs_info) +{ + struct dfs_channel *chan; + bool flag_no_weather = 0; + bool flag_no_lower_5g = 0; + bool flag_no_upper_5g = 0; + bool flag_no_dfs_chan = 0; + bool flag_no_2g_chan = 0; + bool flag_no_5g_chan = 0; + bool flag_no_japan_w53 = 0; + int i; + bool found = false; + uint16_t j; + uint16_t freq_list[NUM_CHANNELS_160MHZ]; + uint8_t num_channels = 0; + + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "flags %d", flags); + flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ? + flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0; + + if (dfs_region == DFS_MKK_REGION_VAL) { + flag_no_lower_5g = flags & DFS_RANDOM_CH_FLAG_NO_LOWER_5G_CH; + flag_no_upper_5g = flags & DFS_RANDOM_CH_FLAG_NO_UPEER_5G_CH; + flag_no_japan_w53 = flags & DFS_RANDOM_CH_FLAG_NO_JAPAN_W53_CH; + } + + flag_no_dfs_chan = flags & DFS_RANDOM_CH_FLAG_NO_DFS_CH; + flag_no_2g_chan = flags & DFS_RANDOM_CH_FLAG_NO_2GHZ_CH; + flag_no_5g_chan = flags & DFS_RANDOM_CH_FLAG_NO_5GHZ_CH; + + if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) { + num_channels = + dfs_get_bonding_channel_without_seg_info_for_freq + (dfs->dfs_curchan, freq_list); + } + + for (i = 0; i < chan_cnt; i++) { + chan = &chan_list[i]; + found = false; + + if ((chan->dfs_ch_ieee == 0) || + (chan->dfs_ch_ieee > MAX_CHANNEL_NUM)) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "invalid channel %d", chan->dfs_ch_ieee); + continue; + } + + if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) { + for (j = 0; j < num_channels; j++) { + if (chan->dfs_ch_freq == freq_list[j]) { + dfs_debug(dfs, + WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip %d current operating channel", + chan->dfs_ch_freq); + found = true; + break; + } + } + + if (found) + continue; + } + + if (acs_info && acs_info->acs_mode) { + for (j = 0; j < acs_info->num_of_channel; j++) { + if (acs_info->chan_freq_list[j] == + chan->dfs_ch_freq) { + found = true; + break; + } + } + + if (!found) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip ch freq %d not in acs range", + chan->dfs_ch_freq); + continue; + } + found = false; + } + + if (flag_no_2g_chan && + chan->dfs_ch_freq <= DFS_MAX_24GHZ_CHANNEL_FREQ) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip 2.4 GHz channel=%d", chan->dfs_ch_ieee); + continue; + } + + if (flag_no_5g_chan && chan->dfs_ch_freq > + DFS_MAX_24GHZ_CHANNEL_FREQ) + { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip 5 GHz channel=%d", chan->dfs_ch_ieee); + continue; + } + + if (flag_no_weather) { + if (DFS_IS_CHANNEL_WEATHER_RADAR(chan->dfs_ch_freq)) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip weather channel=%d", + chan->dfs_ch_ieee); + continue; + } + } + + if (flag_no_lower_5g && + DFS_IS_CHAN_JAPAN_INDOOR_FREQ(chan->dfs_ch_freq)) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip indoor channel=%d", chan->dfs_ch_ieee); + continue; + } + + if (flag_no_upper_5g && + DFS_IS_CHAN_JAPAN_OUTDOOR_FREQ(chan->dfs_ch_freq)) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip outdoor channel=%d", chan->dfs_ch_ieee); + continue; + } + + if (flag_no_dfs_chan && + (chan->dfs_ch_flagext & WLAN_CHAN_DFS)) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip dfs channel=%d", chan->dfs_ch_ieee); + continue; + } + + if (flag_no_japan_w53 && + DFS_IS_CHAN_JAPAN_W53_FREQ(chan->dfs_ch_freq)) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip japan W53 channel=%d", + chan->dfs_ch_ieee); + continue; + } + + if (dfs_is_freq_in_nol(dfs, chan->dfs_ch_freq)) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip nol channel=%d", chan->dfs_ch_ieee); + continue; + } + + random_chan_freq_list[*random_chan_cnt] = chan->dfs_ch_freq; + *random_chan_cnt += 1; + } +} +#endif +#ifdef CONFIG_CHAN_NUM_API uint8_t dfs_prepare_random_channel(struct wlan_dfs *dfs, struct dfs_channel *ch_list, uint32_t ch_cnt, @@ -1415,9 +2069,6 @@ uint8_t dfs_prepare_random_channel(struct wlan_dfs *dfs, if (!random_chan_list) return 0; - if (flags & DFS_RANDOM_CH_FLAG_NO_CURR_OPE_CH) - dfs_remove_cur_ch_from_list(ch_list, &ch_cnt, ch_wd, cur_chan); - dfs_apply_rules(dfs, flags, random_chan_list, &random_chan_cnt, ch_list, ch_cnt, dfs_region, acs_info); @@ -1491,3 +2142,139 @@ uint8_t dfs_prepare_random_channel(struct wlan_dfs *dfs, return target_ch; } +#endif + +#ifdef CONFIG_CHAN_FREQ_API +uint16_t dfs_prepare_random_channel_for_freq(struct wlan_dfs *dfs, + struct dfs_channel *chan_list, + uint32_t chan_cnt, + uint32_t flags, + uint8_t *chan_wd, + struct dfs_channel *cur_chan, + uint8_t dfs_region, + struct dfs_acs_info *acs_info) +{ + int i = 0; + uint8_t final_cnt = 0; + uint16_t target_freq = 0; + uint16_t *random_chan_freq_list = NULL; + uint32_t random_chan_cnt = 0; + uint16_t flag_no_weather = 0; + uint16_t *leakage_adjusted_lst; + uint16_t final_lst[NUM_CHANNELS] = {0}; + uint16_t *dfs_cfreq_seg2 = NULL; + + if (!chan_list || !chan_cnt) { + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "Invalid params %pK, chan_cnt=%d", + chan_list, chan_cnt); + return 0; + } + + if (*chan_wd < DFS_CH_WIDTH_20MHZ || *chan_wd > DFS_CH_WIDTH_80P80MHZ) { + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "Invalid chan_wd %d", *chan_wd); + return 0; + } + + random_chan_freq_list = + qdf_mem_malloc(chan_cnt * sizeof(*random_chan_freq_list)); + if (!random_chan_freq_list) + return 0; + + dfs_apply_rules_for_freq(dfs, flags, random_chan_freq_list, + &random_chan_cnt, chan_list, chan_cnt, + dfs_region, acs_info); + flag_no_weather = (dfs_region == DFS_ETSI_REGION_VAL) ? + flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0; + + /* list adjusted after leakage has been marked */ + leakage_adjusted_lst = qdf_mem_malloc(random_chan_cnt * + sizeof(*leakage_adjusted_lst)); + if (!leakage_adjusted_lst) { + qdf_mem_free(random_chan_freq_list); + return 0; + } + + do { + int ret; + + qdf_mem_copy(leakage_adjusted_lst, random_chan_freq_list, + random_chan_cnt * sizeof(*leakage_adjusted_lst)); + ret = dfs_mark_leaking_chan_for_freq(dfs, *chan_wd, + random_chan_cnt, + leakage_adjusted_lst); + if (QDF_IS_STATUS_ERROR(ret)) { + qdf_mem_free(random_chan_freq_list); + qdf_mem_free(leakage_adjusted_lst); + return 0; + } + + if (*chan_wd == DFS_CH_WIDTH_20MHZ) { + /* + * PASS: 3 - from leakage_adjusted_lst, prepare valid + * ch list and use random number from that + */ + for (i = 0; i < random_chan_cnt; i++) { + if (leakage_adjusted_lst[i] == 0) + continue; + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "Channel=%d added to available list", + leakage_adjusted_lst[i]); + final_lst[final_cnt] = leakage_adjusted_lst[i]; + final_cnt++; + } + target_freq = dfs_get_rand_from_lst_for_freq(dfs, + final_lst, + final_cnt); + break; + } + dfs_cfreq_seg2 = &cur_chan->dfs_ch_mhz_freq_seg2; + target_freq = + dfs_find_ch_with_fallback_for_freq(dfs, chan_wd, + dfs_cfreq_seg2, + leakage_adjusted_lst, + random_chan_cnt); + + /* Since notion of 80+80 is not present in the regulatory + * channel the function may return invalid 80+80 channels for + * some devices (e.g. Pine). Therefore, check if we need to + * correct it by checking the following condition. + */ + if ((*chan_wd == DFS_CH_WIDTH_80P80MHZ) && + (flags & DFS_RANDOM_CH_FLAG_RESTRICTED_80P80_ENABLED) && + !(CHAN_WITHIN_RESTRICTED_80P80(target_freq, + *dfs_cfreq_seg2))) { + *chan_wd = DFS_CH_WIDTH_160MHZ; + target_freq = dfs_find_ch_with_fallback_for_freq( + dfs, chan_wd, dfs_cfreq_seg2, + leakage_adjusted_lst, random_chan_cnt); + } + + /* + * When flag_no_weather is set, avoid usage of Adjacent + * weather radar channel in HT40 mode as extension channel + * will be on 5600. + */ + if (flag_no_weather && + (target_freq == + DFS_ADJACENT_WEATHER_RADAR_CHANNEL_FREQ) && + (*chan_wd == DFS_CH_WIDTH_40MHZ)) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip weather adjacent ch=%d\n", + target_freq); + continue; + } + + if (target_freq) + break; + } while (true); + + qdf_mem_free(random_chan_freq_list); + qdf_mem_free(leakage_adjusted_lst); + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, "target_freq = %d", + target_freq); + + return target_freq; +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h index aa339a023875b4e615d14e10377abde988a72329..a17d29b32d64fe77c0f075b8286324da0dec56ce 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2010, Atheros Communications Inc. * All Rights Reserved. * @@ -53,29 +53,45 @@ #define DFS_SET_DISABLE_RADAR_MARKING 25 #define DFS_GET_DISABLE_RADAR_MARKING 26 +#define DFS_INJECT_SEQUENCE 27 +#define DFS_ALLOW_HW_PULSES 28 +#define DFS_SET_PRI_MULTIPILER 29 + +#define RESTRICTED_80P80_START_CHAN 132 +#define RESTRICTED_80P80_END_CHAN 161 + +/* Check if the given channels are within restricted 80P80 start chan(132) and + * end chan (161). + */ +#define CHAN_WITHIN_RESTRICTED_80P80(chan, cfreq_seg2) \ + ((((chan) >= RESTRICTED_80P80_START_CHAN) && \ + ((chan) <= RESTRICTED_80P80_END_CHAN) && \ + ((cfreq_seg2) >= RESTRICTED_80P80_START_CHAN) && \ + ((cfreq_seg2) <= RESTRICTED_80P80_END_CHAN)) ? true : false) + /* * Spectral IOCTLs use DFS_LAST_IOCTL as the base. * This must always be the last IOCTL in DFS and have * the highest value. */ -#define DFS_LAST_IOCTL 27 +#define DFS_LAST_IOCTL 29 #ifndef DFS_CHAN_MAX -#define DFS_CHAN_MAX 1023 +#define DFS_CHAN_MAX 25 #endif /** * struct dfsreq_nolelem - NOL elements. * @nol_freq: NOL channel frequency. * @nol_chwidth: NOL channel width. - * @nol_start_us: OS microseconds when the NOL timer started. + * @nol_start_ticks: OS ticks when the NOL timer started. * @nol_timeout_ms: Nol timeout value in msec. */ struct dfsreq_nolelem { uint16_t nol_freq; uint16_t nol_chwidth; - uint64_t nol_start_us; + unsigned long nol_start_ticks; uint32_t nol_timeout_ms; }; @@ -189,6 +205,10 @@ struct dfs_bangradar_params { /* Flag to exclude Japan W53 channnels */ #define DFS_RANDOM_CH_FLAG_NO_JAPAN_W53_CH 0x0100 /* 0000 0001 0000 0000 */ +/* Restricted 80P80 MHz is enabled */ +#define DFS_RANDOM_CH_FLAG_RESTRICTED_80P80_ENABLED 0x0200 + /* 0000 0010 0000 0000 */ + /** * struct wlan_dfs_caps - DFS capability structure. * @wlan_dfs_ext_chan_ok: Can radar be detected on the extension chan? @@ -271,4 +291,69 @@ enum WLAN_DFS_EVENTS { WLAN_EV_NOL_FINISHED, }; +#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(WLAN_DFS_SYNTHETIC_RADAR) +/** + * Structure of Pulse to be injected into the DFS Module + * ****************************************************** + * Header + * ====== + * ----------|--------------| + * num_pulses| total_len_seq| + * ----------|--------------| + * Buffer Contents per pulse: + * ========================== + * ------|----------|-----------|----------|-----------|---------------|-------- + * r_rssi|r_ext_rssi|r_rs_tstamp|r_fulltsf |fft_datalen|total_len_pulse|FFT + * | | | | | |Buffer.. + * ------|----------|-----------|----------|-----------|---------------|-------- + */ + +/** + * struct synthetic_pulse - Radar Pulse Structure to be filled on reading the + * user file. + * @r_rssi: RSSI of the pulse. + * @r_ext_rssi: Extension Channel RSSI. + * @r_rs_tstamp: Timestamp. + * @r_fulltsf: TSF64. + * @fft_datalen: Total len of FFT. + * @total_len_pulse: Total len of the pulse. + * @fft_buf: Pointer to fft data. + */ + +struct synthetic_pulse { + uint8_t r_rssi; + uint8_t r_ext_rssi; + uint32_t r_rs_tstamp; + uint64_t r_fulltsf; + uint16_t fft_datalen; + uint16_t total_len_pulse; + unsigned char *fft_buf; +} qdf_packed; + +/** + * struct synthetic_seq - Structure to hold an array of pointers to the + * pulse structure. + * @num_pulses: Total num of pulses in the sequence. + * @total_len_seq: Total len of the sequence. + * @pulse: Array of pointers to synthetic_pulse structure. + */ + +struct synthetic_seq { + uint8_t num_pulses; + uint32_t total_len_seq; + struct synthetic_pulse *pulse[0]; +}; + +/** + * struct seq_store - Structure to hold an array of pointers to the synthetic + * sequence structure. + * @num_sequence: Total number of "sequence of pulses" in the file. + * @seq_arr: Array of pointers to synthetic_seq structure. + */ + +struct seq_store { + uint8_t num_sequence; + struct synthetic_seq *seq_arr[0]; +}; +#endif /* WLAN_DFS_PARTIAL_OFFLOAD && WLAN_DFS_SYNTHETIC_RADAR */ #endif /* _DFS_IOCTL_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_lmac_api.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_lmac_api.h index 99b671e9159680a37b3a94712aa0dad03d681262..5ed030da216a6b55681281a4e62cd0183d263c43 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_lmac_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_lmac_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -118,4 +118,13 @@ static inline bool lmac_is_host_dfs_check_support_enabled( return false; } #endif + +/** + * lmac_dfs_is_hw_mode_switch_in_progress() - Check if HW mode switch is in + * progress. + * @pdev: Pointer to PDEV structure. + * + * Return: true if HW mode switch is in progress, else false. + */ +bool lmac_dfs_is_hw_mode_switch_in_progress(struct wlan_objmgr_pdev *pdev); #endif /* _WLAN_DFS_LMAC_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h index 3719595f858694e5d8febac5a90b4a597ce89251..3593f06d0f0a7620562363225b96ee3100fc1268 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -44,12 +44,29 @@ void dfs_mlme_start_rcsa(struct wlan_objmgr_pdev *pdev, * @vhtop_ch_freq_seg2: VHT80 Cfreq2. * @flags: channel flags. */ +#ifdef CONFIG_CHAN_NUM_API void dfs_mlme_mark_dfs(struct wlan_objmgr_pdev *pdev, uint8_t ieee, uint16_t freq, uint8_t vhtop_ch_freq_seg2, uint64_t flags); +#endif +/** + * dfs_mlme_mark_dfs_for_freq() - Mark the channel in the channel list. + * @pdev: Pointer to DFS pdev object. + * @ieee: Channel number. + * @freq: Channel frequency. + * @vhtop_ch_freq_seg2_mhz: VHT80 Cfreq2 in Mhz. + * @flags: channel flags. + */ +#ifdef CONFIG_CHAN_FREQ_API +void dfs_mlme_mark_dfs_for_freq(struct wlan_objmgr_pdev *pdev, + uint8_t ieee, + uint16_t freq, + uint16_t vhtop_ch_freq_mhz_seg2, + uint64_t flags); +#endif /** * dfs_mlme_start_csa() - Sends CSA in ieeeChan * @pdev: Pointer to DFS pdev object. @@ -58,12 +75,29 @@ void dfs_mlme_mark_dfs(struct wlan_objmgr_pdev *pdev, * @cfreq2: HT80 cfreq2. * @flags: channel flags. */ +#ifdef CONFIG_CHAN_NUM_API void dfs_mlme_start_csa(struct wlan_objmgr_pdev *pdev, uint8_t ieee_chan, uint16_t freq, uint8_t cfreq2, uint64_t flags); +#endif +/** + * dfs_mlme_start_csa_for_freq() - Sends CSA in ieeeChan + * @pdev: Pointer to DFS pdev object. + * @ieee_chan: Channel number. + * @freq: Channel frequency. + * @cfreq2: HT80 cfreq2 in Mhz. + * @flags: channel flags. + */ +#ifdef CONFIG_CHAN_FREQ_API +void dfs_mlme_start_csa_for_freq(struct wlan_objmgr_pdev *pdev, + uint8_t ieee_chan, + uint16_t freq, + uint16_t cfreq2_mhz, + uint64_t flags); +#endif /** * dfs_mlme_proc_cac() - Process the CAC completion event. * @pdev: Pointer to DFS pdev object. @@ -96,6 +130,7 @@ void dfs_mlme_get_dfs_ch_nchans(struct wlan_objmgr_pdev *pdev, int *nchans); * @dfs_ch_vhtop_ch_freq_seg2: Channel Center frequency applicable for 80+80MHz * mode of operation. */ +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS dfs_mlme_get_extchan(struct wlan_objmgr_pdev *pdev, uint16_t *dfs_ch_freq, uint64_t *dfs_ch_flags, @@ -103,6 +138,34 @@ QDF_STATUS dfs_mlme_get_extchan(struct wlan_objmgr_pdev *pdev, uint8_t *dfs_ch_ieee, uint8_t *dfs_ch_vhtop_ch_freq_seg1, uint8_t *dfs_ch_vhtop_ch_freq_seg2); +#endif + +/** + * dfs_mlme_get_extchan() - Get extension channel. + * @pdev: Pointer to DFS pdev object. + * @dfs_chan_freq: Frequency in Mhz. + * @dfs_chan_flags: Channel flags. + * @dfs_chan_flagext: Extended channel flags. + * @dfs_chan_ieee: IEEE channel number. + * @dfs_chan_vhtop_ch_freq_seg1: Channel Center IEEE. + * @dfs_chan_vhtop_ch_freq_seg2: Channel Center IEEE applicable for 80+80MHz + * mode of operation. + * @dfs_chan_mhz_freq_seg1: Primary channel center freq. + * @dfs_chan_mhz_freq_seg2: Secondary channel center freq applicable for + * 80+80 MHZ. + */ + +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS dfs_mlme_get_extchan_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *dfs_chan_freq, + uint64_t *dfs_chan_flags, + uint16_t *dfs_chan_flagext, + uint8_t *dfs_chan_ieee, + uint8_t *dfs_chan_vhtop_ch_freq_seg1, + uint8_t *dfs_chan_vhtop_ch_freq_seg2, + uint16_t *dfs_chan_mhz_freq_seg1, + uint16_t *dfs_chan_mhz_freq_seg2); +#endif /** * dfs_mlme_set_no_chans_available() - Set no_chans_available flag. @@ -140,6 +203,7 @@ int dfs_mlme_ieee2mhz(struct wlan_objmgr_pdev *pdev, * * QDF_STATUS_SUCCESS : Channel found. * * QDF_STATUS_E_FAILURE: Channel not found. */ +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS dfs_mlme_find_dot11_channel(struct wlan_objmgr_pdev *pdev, uint8_t ieee, @@ -151,6 +215,46 @@ dfs_mlme_find_dot11_channel(struct wlan_objmgr_pdev *pdev, uint8_t *dfs_ch_ieee, uint8_t *dfs_ch_vhtop_ch_freq_seg1, uint8_t *dfs_ch_vhtop_ch_freq_seg2); +#endif + +/** + * dfs_mlme_find_dot11_chan_for_freq() - Find a channel pointer given the mode, + * frequency and channel flags. + * @pdev: Pointer to DFS pdev object. + * @ch_freq: Channel frequency. + * @des_cfreq2_mhz: cfreq2 in MHZ. + * @mode: Phymode + * @dfs_chan_freq: Frequency in Mhz. + * @dfs_chan_flags: Channel flags. + * @dfs_chan_flagext: Extended channel flags. + * @dfs_chan_ieee: IEEE channel number. + * @dfs_chan_vhtop_ch_freq_seg1: Channel Center IEEE for primary 80 segment. + * @dfs_chan_vhtop_ch_freq_seg2: Channel Center frequency applicable for + * 80+80MHz mode of operation. + * @dfs_chan_mhz_freq_seg1: Channel center frequency of primary 80 segment. + * @dfs_chan_mhz_freq_seg2: Channel center frequency for secondary 80 + * segment applicable only for 80+80MHZ mode of + * operation. + * + * Return: + * * QDF_STATUS_SUCCESS : Channel found. + * * QDF_STATUS_E_FAILURE: Channel not found. + */ +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS +dfs_mlme_find_dot11_chan_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t chan_freq, + uint16_t des_cfreq2_mhz, + int mode, + uint16_t *dfs_chan_freq, + uint64_t *dfs_chan_flags, + uint16_t *dfs_chan_flagext, + uint8_t *dfs_chan_ieee, + uint8_t *dfs_chan_vhtop_ch_freq_seg1, + uint8_t *dfs_chan_vhtop_ch_freq_seg2, + uint16_t *dfs_chan_mhz_freq_seg1, + uint16_t *dfs_chan_mhz_freq_seg2); +#endif /** * dfs_mlme_get_dfs_ch_channels() - Get channel from channel list. @@ -164,6 +268,7 @@ dfs_mlme_find_dot11_channel(struct wlan_objmgr_pdev *pdev, * mode of operation. * @index: Index into channel list. */ +#ifdef CONFIG_CHAN_NUM_API void dfs_mlme_get_dfs_ch_channels(struct wlan_objmgr_pdev *pdev, uint16_t *dfs_ch_freq, uint64_t *dfs_ch_flags, @@ -172,6 +277,36 @@ void dfs_mlme_get_dfs_ch_channels(struct wlan_objmgr_pdev *pdev, uint8_t *dfs_ch_vhtop_ch_freq_seg1, uint8_t *dfs_ch_vhtop_ch_freq_seg2, int index); +#endif + +/** + * dfs_mlme_get_dfs_channels_for_freq() - Get DFS channel from channel list. + * @pdev: Pointer to DFS pdev object. + * @dfs_chan_freq: Frequency in Mhz. + * @dfs_chan_flags: Channel flags. + * @dfs_chan_flagext: Extended channel flags. + * @dfs_chan_ieee: IEEE channel number. + * @dfs_chan_vhtop_ch_freq_seg1: Channel Center IEEE number. + * @dfs_chan_vhtop_ch_freq_seg2: Channel Center IEEE applicable for 80+80MHz + * mode of operation. + * @dfs_chan_mhz_freq_seg1 : Primary 80 Channel Center frequency. + * @dfs_chan_mhz_freq_seg2 : Channel center frequency applicable only for + * 80+80 mode of operation. + * @index: Index into channel list. + */ +#ifdef CONFIG_CHAN_FREQ_API +void +dfs_mlme_get_dfs_channels_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *dfs_chan_freq, + uint64_t *dfs_chan_flags, + uint16_t *dfs_chan_flagext, + uint8_t *dfs_chan_ieee, + uint8_t *dfs_chan_vhtop_ch_freq_seg1, + uint8_t *dfs_chan_vhtop_ch_freq_seg2, + uint16_t *dfs_chan_mhz_freq_seg1, + uint16_t *dfs_chan_mhz_freq_seg2, + int index); +#endif /** * dfs_mlme_dfs_ch_flags_ext() - Get extension channel flags. @@ -209,11 +344,27 @@ void dfs_mlme_clist_update(struct wlan_objmgr_pdev *pdev, * mode of operation. * @dfs_ch_flags: Channel flags. */ +#ifdef CONFIG_CHAN_NUM_API int dfs_mlme_get_cac_timeout(struct wlan_objmgr_pdev *pdev, uint16_t dfs_ch_freq, uint8_t dfs_ch_vhtop_ch_freq_seg2, uint64_t dfs_ch_flags); +#endif +/** + * dfs_mlme_get_cac_timeout_for_freq() - Get cac_timeout. + * @pdev: Pointer to DFS pdev object. + * @dfs_chan_freq: Frequency in Mhz. + * @dfs_chan_vhtop_freq_seg2: Channel Center frequency applicable for 80+80MHz + * mode of operation. + * @dfs_chan_flags: Channel flags. + */ +#ifdef CONFIG_CHAN_FREQ_API +int dfs_mlme_get_cac_timeout_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t dfs_chan_freq, + uint16_t dfs_chan_vhtop_freq_seg2_mhz, + uint64_t dfs_chan_flags); +#endif /** * dfs_mlme_rebuild_chan_list_with_non_dfs_channels() - Rebuild the channel list * with only non DFS channels. @@ -257,12 +408,12 @@ void dfs_mlme_restart_vaps_with_non_dfs_chan(struct wlan_objmgr_pdev *pdev, */ #if defined(WLAN_SUPPORT_PRIMARY_ALLOWED_CHAN) bool dfs_mlme_check_allowed_prim_chanlist(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num); + uint32_t chan_freq); #else static inline bool dfs_mlme_check_allowed_prim_chanlist(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num) + uint32_t chan_freq) { return true; } @@ -289,4 +440,22 @@ void dfs_mlme_handle_dfs_scan_violation(struct wlan_objmgr_pdev *pdev) * Return: true if pdev opmode is STA, else false. */ bool dfs_mlme_is_opmode_sta(struct wlan_objmgr_pdev *pdev); + +/** + * dfs_mlme_acquire_radar_mode_switch_lock() - Acquire lock for radar processing + * over mode switch handling. + * @pdev: Pointer to DFS pdev object. + * + * Return: void. + */ +void dfs_mlme_acquire_radar_mode_switch_lock(struct wlan_objmgr_pdev *pdev); + +/** + * dfs_mlme_release_radar_mode_switch_lock() - Release lock taken for radar + * processing over mode switch handling. + * @pdev: Pointer to DFS pdev object. + * + * Return: void. + */ +void dfs_mlme_release_radar_mode_switch_lock(struct wlan_objmgr_pdev *pdev); #endif /* _WLAN_DFS_MLME_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h index 5ee103a4ac9e165ed70781bf54e69ac42c71ad9e..dfa407daeff1a7e2235c48b2d4479a8bd549b05e 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h @@ -56,12 +56,12 @@ struct radar_found_info { /** * struct dfs_acs_info - acs info, ch range * @acs_mode: to enable/disable acs 1/0. - * @channel_list: channel list in acs config + * @chan_freq_list: channel frequency list * @num_of_channel: number of channel in ACS channel list */ struct dfs_acs_info { uint8_t acs_mode; - uint8_t *channel_list; + uint32_t *chan_freq_list; uint8_t num_of_channel; }; @@ -124,4 +124,20 @@ struct dfs_radar_found_params { u_int32_t sidx_min; u_int32_t sidx_max; }; + +/** + * struct dfs_agile_cac_params - Agile DFS-CAC parameters. + * @precac_chan: Agile preCAC channel. + * @precac_chan_freq: Agile preCAC channel frequency in MHZ. + * @precac_chwidth: Agile preCAC channel width. + * @min_precac_timeout: Minimum agile preCAC timeout. + * @max_precac_timeout: Maximum agile preCAC timeout. + */ +struct dfs_agile_cac_params { + uint8_t precac_chan; + uint16_t precac_chan_freq; + enum phy_ch_width precac_chwidth; + uint32_t min_precac_timeout; + uint32_t max_precac_timeout; +}; #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h index c2b4ed4d85dba03d6728aeda75e6b814d563a0d5..c49a497ae22ddbdb2aab46ea90cf47e8684ea6e3 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -97,7 +97,7 @@ struct dfs_emulate_bang_radar_test_cmd { * @vdev_id: Physical device identifier * @chan_freq: Channel number * @chan_width: Channel Width - * @center_freq: Center Frequency channel number + * @center_freq: Center channel number * @ocac_status: off channel cac status */ struct vdev_adfs_complete_status { @@ -122,6 +122,7 @@ extern struct dfs_to_mlme global_dfs_to_mlme; * @dfs_ch_vhtop_ch_freq_seg2: Channel Center frequency2. */ #ifdef DFS_COMPONENT_ENABLE +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS tgt_dfs_set_current_channel(struct wlan_objmgr_pdev *pdev, uint16_t dfs_ch_freq, uint64_t dfs_ch_flags, @@ -129,6 +130,34 @@ QDF_STATUS tgt_dfs_set_current_channel(struct wlan_objmgr_pdev *pdev, uint8_t dfs_ch_ieee, uint8_t dfs_ch_vhtop_ch_freq_seg1, uint8_t dfs_ch_vhtop_ch_freq_seg2); +#endif + +/** + * tgt_dfs_set_current_channel_for_freq() - Fill dfs channel structure from + * dfs_channel structure. + * @pdev: Pointer to DFS pdev object. + * @dfs_ch_freq: Frequency in Mhz. + * @dfs_ch_flags: Channel flags. + * @dfs_ch_flagext: Extended channel flags. + * @dfs_ch_ieee: IEEE channel number. + * @dfs_ch_vhtop_ch_freq_seg1: Channel Center frequency1. + * @dfs_ch_vhtop_ch_freq_seg2: Channel Center frequency2. + * @dfs_ch_mhz_freq_seg1: Channel center frequency of primary segment in MHZ. + * @dfs_ch_mhz_freq_seg2: Channel center frequency of secondary segment in MHZ + * applicable only for 80+80MHZ mode of operation. + */ +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS +tgt_dfs_set_current_channel_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t dfs_ch_freq, + uint64_t dfs_ch_flags, + uint16_t dfs_ch_flagext, + uint8_t dfs_ch_ieee, + uint8_t dfs_ch_vhtop_ch_freq_seg1, + uint8_t dfs_ch_vhtop_ch_freq_seg2, + uint16_t dfs_ch_mhz_freq_seg1, + uint16_t dfs_ch_mhz_freq_seg2); +#endif /** * tgt_dfs_radar_enable() - Enables the radar. @@ -350,6 +379,7 @@ QDF_STATUS tgt_dfs_ocac_complete(struct wlan_objmgr_pdev *pdev, * wrapper function for dfs_find_vht80_chan_for_precacdfs_cancel_cac_timer(). * This function called from outside of dfs component. */ +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS tgt_dfs_find_vht80_chan_for_precac(struct wlan_objmgr_pdev *pdev, uint32_t chan_mode, uint8_t ch_freq_seg1, @@ -358,6 +388,32 @@ QDF_STATUS tgt_dfs_find_vht80_chan_for_precac(struct wlan_objmgr_pdev *pdev, uint32_t *phy_mode, bool *dfs_set_cfreq2, bool *set_agile); +#endif + +/** + * tgt_dfs_find_vht80_precac_chan_freq() - Find VHT80 channel for precac + * @pdev: Pointer to DFS pdev object. + * @chan_mode: Channel mode. + * @ch_freq_seg1_mhz: Segment1 channel freq in MHZ. + * @cfreq1: cfreq1. + * @cfreq2: cfreq2. + * @phy_mode: Precac phymode. + * @dfs_set_cfreq2: Precac cfreq2 + * @set_agile: Agile mode flag. + * + * wrapper function for dfs_find_vht80_chan_for_precac_for_freq(). + */ +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS +tgt_dfs_find_vht80_precac_chan_freq(struct wlan_objmgr_pdev *pdev, + uint32_t chan_mode, + uint16_t ch_freq_mhz_seg1, + uint32_t *cfreq1, + uint32_t *cfreq2, + uint32_t *phy_mode, + bool *dfs_set_cfreq2, + bool *set_agile); +#endif /** * tgt_dfs_cac_complete() - Process cac complete indication. @@ -528,4 +584,97 @@ tgt_dfs_send_subchan_marking(struct wlan_objmgr_pdev *pdev, bool subchanmark) return QDF_STATUS_SUCCESS; } #endif +#ifdef QCA_SUPPORT_AGILE_DFS +/** + * tgt_dfs_set_fw_adfs_support() - Set FW aDFS support in dfs object. + * @pdev: Pointer to pdev object. + * @fw_adfs_support_160: aDFS enabled when pdev is on 160/80P80MHz. + * @fw_adfs_support_non_160: aDFS enabled when pdev is on 20/40/80MHz. + * + * Return: void. + */ +void tgt_dfs_set_fw_adfs_support(struct wlan_objmgr_pdev *pdev, + bool fw_adfs_support_160, + bool fw_adfs_support_non_160); +#else +static inline +void tgt_dfs_set_fw_adfs_support(struct wlan_objmgr_pdev *pdev, + bool fw_adfs_support_160, + bool fw_adfs_support_non_160) +{ +} +#endif + +/** + * tgt_dfs_init_tmp_psoc_nol() - Init temporary psoc NOL structure. + * @pdev: Pointer to pdev object. + * @num_radios: Number of radios in the psoc. + * + * Return: void. + */ +void tgt_dfs_init_tmp_psoc_nol(struct wlan_objmgr_pdev *pdev, + uint8_t num_radios); + +/** + * tgt_dfs_deinit_tmp_psoc_nol() - De-init temporary psoc NOL structure. + * @pdev: Pointer to pdev object. + * + * Return: void. + */ +void tgt_dfs_deinit_tmp_psoc_nol(struct wlan_objmgr_pdev *pdev); + +/** + * tgt_dfs_save_dfs_nol_in_psoc() - Save NOL data of given pdev. + * @pdev: Pointer to pdev object. + * @pdev_id: The pdev ID which will have the NOL data. + * @low_5ghz_freq: The low 5GHz frequency value of the target pdev id. + * @high_5ghz_freq: The high 5GHz frequency value of the target pdev id. + * + * Based on the frequency of the NOL channel, copy it to the target pdev_id + * structure in psoc. + * + * Return: void. + */ +void tgt_dfs_save_dfs_nol_in_psoc(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id, + uint16_t low_5ghz_freq, + uint16_t high_5ghz_freq); + +/** + * tgt_dfs_reinit_nol_from_psoc_copy() - Reinit saved NOL data to corresponding + * pdevs. + * @pdev: Pointer to pdev object. + * @pdev_id: pdev_id of the given pdev. + * + * Return: void. + */ +void tgt_dfs_reinit_nol_from_psoc_copy(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id); + +/** + * tgt_dfs_reinit_precac_lists() - Reinit preCAC lists. + * @src_pdev: Source pdev object from which the preCAC list is copied. + * @dest_pdev: Destination pdev object to which the preCAC list is copied. + * @low_5g_freq: Low 5G frequency value of the destination DFS. + * @high_5g_freq: High 5G frequency value of the destination DFS. + * + * Copy all the preCAC list entries from the source pdev object to the + * destination pdev object which fall within the frequency range of + * low_5g_freq and high_5g_freq. + * + * Return: None (void). + */ +void tgt_dfs_reinit_precac_lists(struct wlan_objmgr_pdev *src_pdev, + struct wlan_objmgr_pdev *dest_pdev, + uint16_t low_5g_freq, + uint16_t high_5g_freq); + +/** + * tgt_dfs_complete_deferred_tasks() - Process HW mode switch completion and + * handle deferred tasks. + * @pdev: Pointer to primary pdev object. + * + * Return: void. + */ +void tgt_dfs_complete_deferred_tasks(struct wlan_objmgr_pdev *pdev); #endif /* _WLAN_DFS_TGT_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h index 9c409ccbfab2f2fb3d1bcc7b626c49e204018117..2d7d7fb8252beee3ae5b8cb376288c418c7fd3e2 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -64,6 +64,19 @@ * @mlme_update_scan_channel_list: Update the scan channel list sent to FW. * @mlme_bringdown_vaps: Bringdown vaps if no chans is present. * @mlme_dfs_deliver_event: Deliver DFS events to user space + * @mlme_precac_chan_change_csa_for_freq:Channel change triggered by PrCAC using + * Channel Switch Announcement. + * @mlme_mark_dfs_for_freq: Mark DFS channel frequency as radar. + * @mlme_get_extchan_for_freq: Get the extension channel. + * @mlme_find_dot11_chan_for_freq: Find a channel pointer. + * @mlme_get_dfs_channels_for_freq: Get DFS channels from current channel + * list. + * @mlme_get_cac_timeout_for_freq: Get CAC timeout for a given channel + * frequency. + * @mlme_acquire_radar_mode_switch_lock: Acquire lock for radar processing over + * mode switch. + * @mlme_release_radar_mode_switch_lock: Release lock taken for radar processing + * over mode switch. */ struct dfs_to_mlme { QDF_STATUS (*pdev_component_obj_attach)(struct wlan_objmgr_pdev *pdev, @@ -75,19 +88,37 @@ struct dfs_to_mlme { void *comp_priv_obj); QDF_STATUS (*dfs_start_rcsa)(struct wlan_objmgr_pdev *pdev, bool *wait_for_csa); +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS (*mlme_mark_dfs)(struct wlan_objmgr_pdev *pdev, uint8_t ieee, uint16_t freq, uint8_t vhtop_ch_freq_seg2, uint64_t flags); +#endif +#ifdef CONFIG_CHAN_FREQ_API + QDF_STATUS (*mlme_mark_dfs_for_freq)(struct wlan_objmgr_pdev *pdev, + uint8_t ieee, + uint16_t freq, + uint16_t ic_mhz_freq_seg2, + uint64_t flags); +#endif +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS (*mlme_start_csa)(struct wlan_objmgr_pdev *pdev, uint8_t ieee_chan, uint16_t freq, uint8_t cfreq2, uint64_t flags); +#endif +#ifdef CONFIG_CHAN_FREQ_API + QDF_STATUS (*mlme_start_csa_for_freq)(struct wlan_objmgr_pdev *pdev, + uint8_t ieee_chan, uint16_t freq, + uint16_t cfreq2, uint64_t flags); +#endif + QDF_STATUS (*mlme_proc_cac)(struct wlan_objmgr_pdev *pdev); QDF_STATUS (*mlme_deliver_event_up_after_cac)( struct wlan_objmgr_pdev *pdev); QDF_STATUS (*mlme_get_dfs_ch_nchans)(struct wlan_objmgr_pdev *pdev, int *nchans); +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS (*mlme_get_extchan)(struct wlan_objmgr_pdev *pdev, uint16_t *dfs_ch_freq, uint64_t *dfs_ch_flags, @@ -95,12 +126,25 @@ struct dfs_to_mlme { uint8_t *dfs_ch_ieee, uint8_t *dfs_ch_vhtop_ch_freq_seg1, uint8_t *dfs_ch_vhtop_ch_freq_seg2); +#endif +#ifdef CONFIG_CHAN_FREQ_API + QDF_STATUS (*mlme_get_extchan_for_freq)(struct wlan_objmgr_pdev *pdev, + uint16_t *dfs_ch_freq, + uint64_t *dfs_ch_flags, + uint16_t *dfs_ch_flagext, + uint8_t *dfs_ch_ieee, + uint8_t *dfs_vhtop_ch_freq_seg1, + uint8_t *dfs_vhtop_ch_freq_seg2, + uint16_t *dfs_ch_mhz_freq_seg1, + uint16_t *dfs_ch_mhz_freq_seg2); +#endif QDF_STATUS (*mlme_set_no_chans_available)(struct wlan_objmgr_pdev *pdev, int val); QDF_STATUS (*mlme_ieee2mhz)(struct wlan_objmgr_pdev *pdev, int ieee, uint64_t flag, int *freq); +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS (*mlme_find_dot11_channel)(struct wlan_objmgr_pdev *pdev, uint8_t ieee, uint8_t des_cfreq2, @@ -111,7 +155,22 @@ struct dfs_to_mlme { uint8_t *dfs_ch_ieee, uint8_t *dfs_ch_vhtop_ch_freq_seg1, uint8_t *dfs_ch_vhtop_ch_freq_seg2); - +#endif +#ifdef CONFIG_CHAN_FREQ_API + QDF_STATUS (*mlme_find_dot11_chan_for_freq)(struct wlan_objmgr_pdev *, + uint16_t freq, + uint16_t des_cfreq2_mhz, + int mode, + uint16_t *dfs_ch_freq, + uint64_t *dfs_ch_flags, + uint16_t *dfs_ch_flagext, + uint8_t *dfs_ch_ieee, + uint8_t *dfs_ch_freq_seg1, + uint8_t *dfs_ch_freq_seg2, + uint16_t *dfs_cfreq1_mhz, + uint16_t *dfs_cfreq2_mhz); +#endif +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS (*mlme_get_dfs_ch_channels)(struct wlan_objmgr_pdev *pdev, uint16_t *dfs_ch_freq, uint64_t *dfs_ch_flags, @@ -120,14 +179,37 @@ struct dfs_to_mlme { uint8_t *dfs_ch_vhtop_ch_freq_seg1, uint8_t *dfs_ch_vhtop_ch_freq_seg2, int index); +#endif +#ifdef CONFIG_CHAN_FREQ_API + QDF_STATUS (*mlme_get_dfs_channels_for_freq)( + struct wlan_objmgr_pdev *pdev, + uint16_t *dfs_chan_freq, + uint64_t *dfs_chan_flags, + uint16_t *dfs_chan_flagext, + uint8_t *dfs_chan_ieee, + uint8_t *dfs_chan_vhtop_ch_freq_seg1, + uint8_t *dfs_chan_vhtop_ch_freq_seg2, + uint16_t *dfs_chan_mhz_freq_seg1, + uint16_t *dfs_chan_mhz_freq_seg2, + int index); +#endif QDF_STATUS (*mlme_dfs_ch_flags_ext)(struct wlan_objmgr_pdev *pdev, uint16_t *flag_ext); QDF_STATUS (*mlme_channel_change_by_precac)( struct wlan_objmgr_pdev *pdev); #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT - QDF_STATUS (*mlme_precac_chan_change_csa)(struct wlan_objmgr_pdev *pdev, - uint8_t des_chan, - enum wlan_phymode des_mode); +#ifdef CONFIG_CHAN_FREQ_API + QDF_STATUS + (*mlme_precac_chan_change_csa_for_freq)(struct wlan_objmgr_pdev *, + uint16_t des_chan_freq, + enum wlan_phymode des_mode); +#endif +#ifdef CONFIG_CHAN_NUM_API + QDF_STATUS + (*mlme_precac_chan_change_csa)(struct wlan_objmgr_pdev *, + uint8_t des_chan, + enum wlan_phymode des_mode); +#endif #endif QDF_STATUS (*mlme_nol_timeout_notification)( struct wlan_objmgr_pdev *pdev); @@ -135,17 +217,27 @@ struct dfs_to_mlme { void *nollist, int nentries); bool (*mlme_is_opmode_sta)(struct wlan_objmgr_pdev *pdev); +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS (*mlme_get_cac_timeout)(struct wlan_objmgr_pdev *pdev, uint16_t dfs_ch_freq, uint8_t c_vhtop_ch_freq_seg2, uint64_t dfs_ch_flags, int *cac_timeout); +#endif +#ifdef CONFIG_CHAN_FREQ_API + QDF_STATUS + (*mlme_get_cac_timeout_for_freq)(struct wlan_objmgr_pdev *pdev, + uint16_t dfs_ch_freq, + uint16_t c_vhtop_ch_freq_seg2, + uint64_t dfs_ch_flags, + int *cac_timeout); +#endif QDF_STATUS (*mlme_rebuild_chan_list_with_non_dfs_channels) (struct wlan_objmgr_pdev *pdev); QDF_STATUS (*mlme_restart_vaps_with_non_dfs_chan) (struct wlan_objmgr_pdev *pdev, int no_chans_avail); bool (*mlme_check_allowed_prim_chanlist) - (struct wlan_objmgr_pdev *pdev, uint32_t chan_num); + (struct wlan_objmgr_pdev *pdev, uint32_t chan); QDF_STATUS (*mlme_update_scan_channel_list) (struct wlan_objmgr_pdev *pdev); QDF_STATUS (*mlme_bringdown_vaps) @@ -154,6 +246,10 @@ struct dfs_to_mlme { (struct wlan_objmgr_pdev *pdev, uint16_t freq, enum WLAN_DFS_EVENTS event); + void (*mlme_acquire_radar_mode_switch_lock) + (struct wlan_objmgr_pdev *pdev); + void (*mlme_release_radar_mode_switch_lock) + (struct wlan_objmgr_pdev *pdev); }; extern struct dfs_to_mlme global_dfs_to_mlme; @@ -240,7 +336,7 @@ QDF_STATUS ucfg_dfs_override_precac_timeout(struct wlan_objmgr_pdev *pdev, /** * ucfg_dfs_set_precac_enable() - Set precac enable flag. * @pdev: Pointer to DFS pdev object. - * @value: input value for dfs_precac_enable flag. + * @value: input value for dfs_legacy_precac_ucfg flag. * * Wrapper function for dfs_set_precac_enable(). * This function called from outside of dfs component. @@ -249,14 +345,31 @@ QDF_STATUS ucfg_dfs_set_precac_enable(struct wlan_objmgr_pdev *pdev, uint32_t value); /** - * ucfg_dfs_get_precac_enable() - Get precac enable flag. + * ucfg_dfs_get_legacy_precac_enable() - Get the legacy precac enable flag. * @pdev: Pointer to DFS pdev object. * @buff: Pointer to save precac_enable value. * - * Wrapper function for dfs_get_precac_enable(). + * Wrapper function for dfs_is_legacy_precac_enabled() and returns the + * legacy precac enable flag for partial offload chipsets. + * This function called from outside of dfs component. + */ +QDF_STATUS ucfg_dfs_get_legacy_precac_enable(struct wlan_objmgr_pdev *pdev, + bool *buff); + +/** + * ucfg_dfs_get_agile_precac_enable() - Get agile precac enable flag. + * @pdev: Pointer to DFS pdev object. + * @buff: Pointer to save dfs_agile_precac_ucfg value. + * + * Wrapper function for dfs_is_legacy_precac_enabled(). * This function called from outside of dfs component. + * + * Return: + * * QDF_STATUS_SUCCESS: Successfully able to get agile precac flag. + * * QDF_STATUS_E_FAILURE: Failed to get agile precac flag. */ -QDF_STATUS ucfg_dfs_get_precac_enable(struct wlan_objmgr_pdev *pdev, int *buff); +QDF_STATUS ucfg_dfs_get_agile_precac_enable(struct wlan_objmgr_pdev *pdev, + bool *buff); #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT /** @@ -299,11 +412,32 @@ QDF_STATUS ucfg_dfs_get_precac_intermediate_chan(struct wlan_objmgr_pdev *pdev, * * Return: Precac state of the given channel. */ +#ifdef CONFIG_CHAN_NUM_API enum precac_chan_state ucfg_dfs_get_precac_chan_state(struct wlan_objmgr_pdev *pdev, uint8_t precac_chan); #endif +/** + * ucfg_dfs_get_precac_chan_state_for_freq() - Get precac status for the + * given channel. + * @pdev: Pointer to DFS pdev object. + * @precac_chan: Channel frequency for which precac state needs to be + * determined. + * + * Wrapper function for dfs_get_precac_chan_state(). + * This function called from outside of dfs component. + * + * Return: Precac state of the given channel. + */ +#ifdef CONFIG_CHAN_FREQ_API +enum precac_chan_state +ucfg_dfs_get_precac_chan_state_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t precac_freq); +#endif + +#endif + #ifdef QCA_MCL_DFS_SUPPORT /** * ucfg_dfs_update_config() - Update DFS user config. @@ -345,6 +479,46 @@ QDF_STATUS ucfg_dfs_set_override_status_timeout(struct wlan_objmgr_pdev *pdev, } #endif +#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(WLAN_DFS_SYNTHETIC_RADAR) +/** + * ucfg_dfs_allow_hw_pulses() - Set or unset dfs-allow_hw_pulses + * which isolates synthetic radar pulse detection from actual radar detection. + * @pdev: Pointer to DFS pdev object. + * @allow_hw_pulses: Allow synthetic pulse detection true/false. + * + * Wrapper function for dfs_set_allow_hw_pulses(). + * This function called from outside of dfs component. + * + * Return: void + */ +void ucfg_dfs_allow_hw_pulses(struct wlan_objmgr_pdev *pdev, + bool allow_hw_pulses); + +/** + * ucfg_dfs_is_hw_pulses_allowed() - Check if actual radar detection is allowed + * or synthetic pulse detection is enabled. + * @pdev: Pointer to DFS pdev object. + * + * Wrapper function for dfs_is_hw_pulses_allowed(). + * This function called from outside of dfs component. + * + * Return: bool + */ +bool ucfg_dfs_is_hw_pulses_allowed(struct wlan_objmgr_pdev *pdev); +#else +static inline +void ucfg_dfs_allow_hw_pulses(struct wlan_objmgr_pdev *pdev, + bool allow_hw_pulses) +{ +} + +static inline +bool ucfg_dfs_is_hw_pulses_allowed(struct wlan_objmgr_pdev *pdev) +{ + return true; +} +#endif + /** * ucfg_dfs_get_override_status_timeout() - Get the value of host dfs status * wait timeout. @@ -394,4 +568,32 @@ QDF_STATUS ucfg_dfs_set_nol_subchannel_marking(struct wlan_objmgr_pdev *pdev, */ QDF_STATUS ucfg_dfs_get_nol_subchannel_marking(struct wlan_objmgr_pdev *pdev, bool *nol_subchannel_marking); +/** + * ucfg_dfs_reinit_timers() - Init DFS timers. + * @pdev: Pointer to wlan_objmgr_pdev structure. + * + * Wrapper function to reset CAC, NOL, DFS Test Timer and ZeroCAC Timer. + * This is invoked per pdev to reinitialize timers after HW Mode Switch is + * triggered. + */ +QDF_STATUS ucfg_dfs_reinit_timers(struct wlan_objmgr_pdev *pdev); + +/** + * ucfg_dfs_reset_agile_config() - Reset ADFS config. + * @pdev: Pointer to wlan_objmgr_pdev structure. + * + * Wrapper function to reset Agile DFS config such as the variables which hold + * information about the state of the preCAC timer, active precac + * dfs index and OCAC status. It is invoked before HW Mode switch is triggered + * to ensure ADFS config is in a well known consistent state. + */ +#ifdef QCA_SUPPORT_AGILE_DFS +QDF_STATUS ucfg_dfs_reset_agile_config(struct wlan_objmgr_psoc *psoc); +#else +static inline QDF_STATUS ucfg_dfs_reset_agile_config(struct wlan_objmgr_psoc + *psoc) +{ + return QDF_STATUS_SUCCESS; +} +#endif #endif /* _WLAN_DFS_UCFG_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h index f1950749ae47ff8b815f7e48c9a2d598bae3c661..d074bb68831643515833053428db234841fe4033 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -93,10 +93,26 @@ extern struct dfs_to_mlme global_dfs_to_mlme; * Wrapper function for dfs_cac_valid_reset(). This function called from * outside of DFS component. */ - +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS utils_dfs_cac_valid_reset(struct wlan_objmgr_pdev *pdev, uint8_t prevchan_ieee, uint32_t prevchan_flags); +#endif + +/** + * utils_dfs_cac_valid_reset_for_freq() - Cancels the dfs_cac_valid_timer timer. + * @pdev: Pointer to DFS pdev object. + * @prevchan_freq: Prevchan frequency. + * @prevchan_flags: Prevchan flags. + * + * Wrapper function for dfs_cac_valid_reset_for_freq(). This function called + * from outside of DFS component. + */ +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS utils_dfs_cac_valid_reset_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t prevchan_freq, + uint32_t prevchan_flags); +#endif /** * utils_dfs_reset() - Reset DFS members. @@ -116,8 +132,7 @@ QDF_STATUS utils_dfs_reset(struct wlan_objmgr_pdev *pdev); bool utils_dfs_is_freq_in_nol(struct wlan_objmgr_pdev *pdev, uint32_t freq); /** - * utils_dfs_reset_precaclists() - Clears and initiakizes precac_required_list, - * precac_done_list and precac_nol_list. + * utils_dfs_reset_precaclists() - Clears and initializes precac_list. * @pdev: Pointer to DFS pdev object. * * Wrapper function for dfs_reset_precaclists(). This function called from @@ -126,42 +141,28 @@ bool utils_dfs_is_freq_in_nol(struct wlan_objmgr_pdev *pdev, uint32_t freq); QDF_STATUS utils_dfs_reset_precaclists(struct wlan_objmgr_pdev *pdev); /** - * utils_dfs_reset_etsi_precaclists() - Clears and initializes etsi - * precac_required_list, - * etsi precac_done_list and - * etsi precac_nol_list. + * utils_dfs_unmark_precac_nol() - Clears precac channel marked as NOL. * @pdev: Pointer to DFS pdev object. + * @chan: channel to be unmarked as NOL. * - * Wrapper function for dfs_reset_etsiprecaclists(). This function called from - * outside of DFS component. + * Return void. */ -#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS -QDF_STATUS utils_dfs_reset_etsi_precaclists(struct wlan_objmgr_pdev *pdev); -#else -static inline QDF_STATUS utils_dfs_reset_etsi_precaclists( - struct wlan_objmgr_pdev *pdev) -{ - return QDF_STATUS_SUCCESS; -} +#ifdef CONFIG_CHAN_NUM_API +void utils_dfs_unmark_precac_nol(struct wlan_objmgr_pdev *pdev, uint8_t chan); #endif -/** utils_dfs_add_to_etsi_precac_required_list() - Add channel to ETSI PreCAC - * Required list. +/** + * utils_dfs_unmark_precac_nol_for_freq() - Clears precac channel marked as NOL. * @pdev: Pointer to DFS pdev object. - * @chan: Pointer to channel to be added to ETSI PreCAC Required List. + * @chan_freq: channel freq to be unmarked as NOL. * - * Return: void + * Return void. */ -#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS -void utils_dfs_add_to_etsi_precac_required_list(struct wlan_objmgr_pdev *pdev, - uint8_t *chan); -#else -static inline void -utils_dfs_add_to_etsi_precac_required_list(struct wlan_objmgr_pdev *pdev, - uint8_t *chan) -{ -} +#ifdef CONFIG_CHAN_FREQ_API +void utils_dfs_unmark_precac_nol_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t chan_freq); #endif + /** * utils_dfs_cancel_precac_timer() - Cancel the precac timer. * @pdev: Pointer to DFS pdev object. @@ -196,12 +197,32 @@ QDF_STATUS utils_dfs_start_precac_timer(struct wlan_objmgr_pdev *pdev); * * Return: True if intermediate channel needs to configure. False otherwise. */ +#ifdef CONFIG_CHAN_NUM_API bool utils_dfs_precac_decide_pref_chan(struct wlan_objmgr_pdev *pdev, uint8_t *ch_ieee, enum wlan_phymode mode); #endif +/** + * utils_dfs_precac_decide_pref_chan() - Choose preferred channel + * @pdev: Pointer to DFS pdev object. + * @ch_freq: Pointer to channel frequency. + * @mode: Configured PHY mode. + * + * Wrapper function for dfs_decide_precac_preferred_chan(). This + * function called from outside of dfs component. + * + * Return: True if intermediate channel needs to configure. False otherwise. + */ +#ifdef CONFIG_CHAN_FREQ_API +bool +utils_dfs_precac_decide_pref_chan_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *ch_freq, + enum wlan_phymode mode); +#endif +#endif + /** * utils_dfs_cancel_cac_timer() - Cancels the CAC timer. * @pdev: Pointer to DFS pdev object. @@ -443,10 +464,80 @@ QDF_STATUS utils_dfs_get_nol_chfreq_and_chwidth(struct wlan_objmgr_pdev *pdev, * * Return: QDF_STATUS */ +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS utils_dfs_get_random_channel(struct wlan_objmgr_pdev *pdev, uint16_t flags, struct ch_params *ch_params, uint32_t *hw_mode, uint8_t *target_chan, struct dfs_acs_info *acs_info); +#endif + +/** + * utils_dfs_get_random_channel_for_freq() - Get random channel. + * @pdev: Pointer to DFS pdev object. + * @flags: random channel selection flags. + * @ch_params: current channel params. + * @hw_mode: current operating mode. + * @target_chan: Pointer to target_chan freq. + * @acs_info: acs range info. + * + * wrapper function for get_random_chan(). this + * function called from outside of dfs component. + * + * Return: QDF_STATUS + */ +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS +utils_dfs_get_random_channel_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t flags, + struct ch_params *ch_params, + uint32_t *hw_mode, uint16_t *target_chan, + struct dfs_acs_info *acs_info); +#endif + +/** + * utils_dfs_get_vdev_random_channel() - Get random channel for vdev + * @pdev: Pointer to DFS pdev object. + * @vdev: vdev of the request + * @flags: random channel selection flags. + * @ch_params: current channel params. + * @hw_mode: current operating mode. + * @target_chan: Pointer to target_chan. + * @acs_info: acs range info. + * + * Get random channel based on vdev interface type. If the vdev is null, + * the function will get random channel by SAP interface type. + * + * Return: QDF_STATUS + */ +#ifdef CONFIG_CHAN_NUM_API +QDF_STATUS utils_dfs_get_vdev_random_channel( + struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, + uint16_t flags, struct ch_params *ch_params, uint32_t *hw_mode, + uint8_t *target_chan, struct dfs_acs_info *acs_info); +#endif + +/** + * utils_dfs_get_vdev_random_channel() - Get random channel for vdev + * @pdev: Pointer to DFS pdev object. + * @vdev: vdev of the request + * @flags: random channel selection flags. + * @ch_params: current channel params. + * @hw_mode: current operating mode. + * @target_chan: Pointer to target_chan_freq. + * @acs_info: acs range info. + * + * Get random channel based on vdev interface type. If the vdev is null, + * the function will get random channel by SAP interface type. + * + * Return: QDF_STATUS + */ + +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS utils_dfs_get_vdev_random_channel_for_freq( + struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, + uint16_t flags, struct ch_params *ch_params, uint32_t *hw_mode, + uint16_t *target_chan_freq, struct dfs_acs_info *acs_info); +#endif /** * utils_dfs_bw_reduced_channel() - Get BW reduced channel. @@ -460,10 +551,32 @@ QDF_STATUS utils_dfs_get_random_channel(struct wlan_objmgr_pdev *pdev, * * Return: QDF_STATUS */ +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS utils_dfs_bw_reduced_channel(struct wlan_objmgr_pdev *pdev, struct ch_params *ch_params, uint32_t *hw_mode, uint8_t *target_chan); +#endif + +/** + * utils_dfs_bw_reduced_channel_for_freq() - Get BW reduced channel. + * @pdev: Pointer to DFS pdev object. + * @ch_params: current channel params. + * @hw_mode: current operating mode. + * @target_chan: Pointer to target_chan freq. + * + * wrapper function for get bw_reduced_channel. this + * function called from outside of dfs component. + * + * Return: QDF_STATUS + */ +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS utils_dfs_bw_reduced_channel_for_freq(struct wlan_objmgr_pdev *pdev, + struct ch_params *ch_params, + uint32_t *hw_mode, + uint16_t *target_chan_freq); +#endif + /** * utils_dfs_init_nol() - Initialize nol from platform driver. * @pdev: pdev handler. @@ -516,17 +629,21 @@ static inline void utils_dfs_print_nol_channels(struct wlan_objmgr_pdev *pdev) void utils_dfs_clear_nol_channels(struct wlan_objmgr_pdev *pdev); /** - * utils_is_dfs_ch() - is channel dfs. + * utils_is_dfs_chan_for_freq() - is channel dfs. * @pdev: pdev handler. + * @chan_freq: Channel frequency in MHZ. * * is channel dfs. * * Return: True if channel dfs, else false. */ -static inline bool utils_is_dfs_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan) +#ifdef CONFIG_CHAN_FREQ_API +static inline bool utils_is_dfs_chan_for_freq(struct wlan_objmgr_pdev *pdev, + uint32_t chan_freq) { - return wlan_reg_is_dfs_ch(pdev, chan); + return wlan_reg_is_dfs_for_freq(pdev, chan_freq); } +#endif /** * utils_is_dfs_cfreq2_ch() - is channel dfs cfreq2. @@ -536,15 +653,7 @@ static inline bool utils_is_dfs_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan) * * Return: True if channel dfs cfreq2, else false. */ -#if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD) bool utils_is_dfs_cfreq2_ch(struct wlan_objmgr_pdev *pdev); -#else -static inline -bool utils_is_dfs_cfreq2_ch(struct wlan_objmgr_pdev *pdev) -{ - return false; -} -#endif /** * utils_dfs_reg_update_nol_ch() - set nol channel @@ -556,11 +665,29 @@ bool utils_is_dfs_cfreq2_ch(struct wlan_objmgr_pdev *pdev) * * Return: void */ +#ifdef CONFIG_CHAN_NUM_API void utils_dfs_reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, uint8_t *ch_list, uint8_t num_ch, bool nol_ch); +#endif +/** + * utils_dfs_reg_update_nol_chan_for_freq() - set nol channel + * + * @pdev: pdev ptr + * @ch_list: freq channel list to be returned + * @num_ch: number of channels + * @nol_ch: nol flag + * + * Return: void + */ +#ifdef CONFIG_CHAN_FREQ_API +void utils_dfs_reg_update_nol_chan_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *ch_list, + uint8_t num_ch, + bool nol_ch); +#endif /** * utils_dfs_freq_to_chan () - convert channel freq to channel number * @freq: frequency @@ -609,11 +736,33 @@ QDF_STATUS utils_dfs_update_cur_chan_flags(struct wlan_objmgr_pdev *pdev, * * Return: QDF_STATUS */ +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS utils_dfs_mark_leaking_ch(struct wlan_objmgr_pdev *pdev, enum phy_ch_width ch_width, uint8_t temp_ch_lst_sz, uint8_t *temp_ch_lst); +#endif +/** + * utils_dfs_mark_leaking_chan_for_freq() - to mark channel leaking in to nol + * @pdev: Pointer to pdev structure. + * @ch_width: channel width + * @temp_ch_lst_sz: the target channel list + * @temp_ch_lst: the target frequency list + * + * This function removes the channels from temp channel list that + * (if selected as target channel) will cause leakage in one of + * the NOL channels + * + * Return: QDF_STATUS + */ +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS utils_dfs_mark_leaking_chan_for_freq(struct wlan_objmgr_pdev *pdev, + enum phy_ch_width ch_width, + uint8_t temp_ch_lst_sz, + uint16_t *temp_ch_lst); +#endif #else +#ifdef CONFIG_CHAN_NUM_API static inline QDF_STATUS utils_dfs_mark_leaking_ch (struct wlan_objmgr_pdev *pdev, enum phy_ch_width ch_width, @@ -623,6 +772,17 @@ static inline QDF_STATUS utils_dfs_mark_leaking_ch return QDF_STATUS_SUCCESS; } #endif +#ifdef CONFIG_CHAN_FREQ_API +static inline QDF_STATUS utils_dfs_mark_leaking_chan_for_freq + (struct wlan_objmgr_pdev *pdev, + enum phy_ch_width ch_width, + uint8_t temp_ch_lst_sz, + uint16_t *temp_ch_lst) +{ + return QDF_STATUS_SUCCESS; +} +#endif +#endif /** * utils_get_dfsdomain() - Get DFS domain. * @pdev: Pointer to PDEV structure. @@ -695,22 +855,63 @@ void utils_dfs_get_nol_history_chan_list(struct wlan_objmgr_pdev *pdev, * * Return: void */ +#ifdef CONFIG_CHAN_NUM_API void utils_dfs_reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, uint8_t *ch_list, uint8_t num_ch, bool nol_history_ch); +#endif /** - * utils_dfs_check_for_cac_start() - Check for DFS CAC start conditions. + * utils_dfs_reg_update_nol_history_chan_for_freq() - set nol history channel + * + * @pdev: pdev ptr + * @ch_list: freq channel list to be returned + * @num_ch: number of channels + * @nol_history_ch: nol history flag + * + * Return: void + */ +#ifdef CONFIG_CHAN_FREQ_API +void utils_dfs_reg_update_nol_history_chan_for_freq(struct wlan_objmgr_pdev *, + uint16_t *freq_list, + uint8_t num_ch, + bool nol_history_ch); +#endif + +/** + * utils_dfs_is_cac_required() - Check if CAC is required on the cur_chan. + * @pdev: pdev ptr + * @cur_chan: Pointer to current channel of wlan_channel structure. + * @prev_chan: Pointer to previous channel of wlan_channel structure. + * @continue_current_cac: If AP can start CAC then this variable indicates + * whether to continue with the current CAC or restart the CAC. This variable + * is valid only if this function returns true. + * + * Return: true if AP requires CAC or can continue current CAC, else false. + */ +bool utils_dfs_is_cac_required(struct wlan_objmgr_pdev *pdev, + struct wlan_channel *cur_chan, + struct wlan_channel *prev_chan, + bool *continue_current_cac); + +/** + * utils_dfs_is_cac_required_on_dfs_curchan() - Check if CAC is required on the + * dfs_curchan. * @pdev: pdev ptr * @continue_current_cac: If AP can start CAC then this variable indicates * whether to continue with the current CAC or restart the CAC. This variable * is valid only if this function returns true. * - * Return: true if AP can start or continue the current CAC, else false. + * This API checks if the dfs_curchan is a subset of the dfs_prevchan. + * dfs_curchan and dfs_prevchan are updated after start response by + * dfs_set_current_channel(). + * + * Return: true if AP requires CAC or can continue current CAC, else false. */ -bool utils_dfs_check_for_cac_start(struct wlan_objmgr_pdev *pdev, - bool *continue_current_cac); +bool +utils_dfs_is_cac_required_on_dfs_curchan(struct wlan_objmgr_pdev *pdev, + bool *continue_current_cac); /** utils_dfs_is_precac_done() - Check if precac has been done in chosen channel * @pdev: Pointer to DFS pdev object. @@ -753,8 +954,10 @@ void utils_dfs_deliver_event(struct wlan_objmgr_pdev *pdev, uint16_t freq, enum WLAN_DFS_EVENTS event); /** - * utils_dfs_clear_cac_started_chan() - Clear dfs cac started channel. - * @pdev: pdev ptr + * utils_dfs_reset_dfs_prevchan() - Reset DFS previous channel structure. + * @pdev: Pointer to DFS pdev object. + * + * Return: None. */ -void utils_dfs_clear_cac_started_chan(struct wlan_objmgr_pdev *pdev); +void utils_dfs_reset_dfs_prevchan(struct wlan_objmgr_pdev *pdev); #endif /* _WLAN_DFS_UTILS_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c index 90dfed33d36876f688dd1fb44f3a6a1cec74d824..db9cc0c7ab3045ab442b150e442b9caa81accb74 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -50,24 +50,57 @@ struct wlan_dfs *wlan_pdev_get_dfs_obj(struct wlan_objmgr_pdev *pdev) return dfs; } +/* + * register_dfs_precac_auto_chan_callbacks_freq() - Register auto chan switch + * frequency based APIs callback. + * @mlme_callback: Pointer to dfs_to_mlme. + */ #ifndef QCA_MCL_DFS_SUPPORT -#ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +#if defined(WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT) && defined(CONFIG_CHAN_FREQ_API) static inline void -register_dfs_precac_auto_chan_callbacks(struct dfs_to_mlme *mlme_callback) +register_dfs_precac_auto_chan_callbacks_freq(struct dfs_to_mlme *mlme_callback) { if (!mlme_callback) return; - mlme_callback->mlme_precac_chan_change_csa = - mlme_dfs_precac_chan_change_csa; + mlme_callback->mlme_precac_chan_change_csa_for_freq = + mlme_dfs_precac_chan_change_csa_for_freq; } #else static inline void -register_dfs_precac_auto_chan_callbacks(struct dfs_to_mlme *mlme_callback) +register_dfs_precac_auto_chan_callbacks_freq(struct dfs_to_mlme *mlme_callback) +{ +} +#endif +#endif + +/* + * register_dfs_callbacks_for_freq() - Register dfs callbacks. + * @mlme_callback: Pointer to dfs_to_mlme. + */ +#ifndef QCA_MCL_DFS_SUPPORT +#ifdef CONFIG_CHAN_FREQ_API +static inline void +register_dfs_callbacks_for_freq(struct dfs_to_mlme *mlme_callback) { + if (!mlme_callback) + return; + + mlme_callback->mlme_mark_dfs_for_freq = mlme_dfs_mark_dfs_for_freq; + mlme_callback->mlme_find_dot11_chan_for_freq = + mlme_dfs_find_dot11_chan_for_freq; + mlme_callback->mlme_get_dfs_channels_for_freq = + mlme_dfs_get_dfs_channels_for_freq; + mlme_callback->mlme_get_cac_timeout_for_freq = + mlme_dfs_get_cac_timeout_for_freq; + mlme_callback->mlme_get_extchan_for_freq = + mlme_dfs_get_extchan_for_freq; + mlme_callback->mlme_start_csa_for_freq = mlme_dfs_start_csa_for_freq; } #endif +#endif +#ifndef QCA_MCL_DFS_SUPPORT void register_dfs_callbacks(void) { struct dfs_to_mlme *tmp_dfs_to_mlme = &global_dfs_to_mlme; @@ -78,26 +111,19 @@ void register_dfs_callbacks(void) wlan_objmgr_pdev_component_obj_detach; tmp_dfs_to_mlme->dfs_start_rcsa = mlme_dfs_start_rcsa; - tmp_dfs_to_mlme->mlme_mark_dfs = mlme_dfs_mark_dfs; - tmp_dfs_to_mlme->mlme_start_csa = mlme_dfs_start_csa; tmp_dfs_to_mlme->mlme_proc_cac = mlme_dfs_proc_cac; tmp_dfs_to_mlme->mlme_deliver_event_up_after_cac = mlme_dfs_deliver_event_up_after_cac; tmp_dfs_to_mlme->mlme_get_dfs_ch_nchans = mlme_dfs_get_dfs_ch_nchans; - tmp_dfs_to_mlme->mlme_get_extchan = mlme_dfs_get_extchan; tmp_dfs_to_mlme->mlme_set_no_chans_available = mlme_dfs_set_no_chans_available; tmp_dfs_to_mlme->mlme_ieee2mhz = mlme_dfs_ieee2mhz; - tmp_dfs_to_mlme->mlme_find_dot11_channel = mlme_dfs_find_dot11_channel; - tmp_dfs_to_mlme->mlme_get_dfs_ch_channels = - mlme_dfs_get_dfs_ch_channels; tmp_dfs_to_mlme->mlme_dfs_ch_flags_ext = mlme_dfs_dfs_ch_flags_ext; tmp_dfs_to_mlme->mlme_channel_change_by_precac = mlme_dfs_channel_change_by_precac; tmp_dfs_to_mlme->mlme_nol_timeout_notification = mlme_dfs_nol_timeout_notification; tmp_dfs_to_mlme->mlme_clist_update = mlme_dfs_clist_update; - tmp_dfs_to_mlme->mlme_get_cac_timeout = mlme_dfs_get_cac_timeout; tmp_dfs_to_mlme->mlme_rebuild_chan_list_with_non_dfs_channels = mlme_dfs_rebuild_chan_list_with_non_dfs_channels; tmp_dfs_to_mlme->mlme_restart_vaps_with_non_dfs_chan = @@ -113,10 +139,16 @@ void register_dfs_callbacks(void) tmp_dfs_to_mlme->mlme_dfs_deliver_event = mlme_dfs_deliver_event; + tmp_dfs_to_mlme->mlme_acquire_radar_mode_switch_lock = + mlme_acquire_radar_mode_switch_lock; + tmp_dfs_to_mlme->mlme_release_radar_mode_switch_lock = + mlme_release_radar_mode_switch_lock; /* * Register precac auto channel switch feature related callbacks */ - register_dfs_precac_auto_chan_callbacks(tmp_dfs_to_mlme); + register_dfs_precac_auto_chan_callbacks_freq(tmp_dfs_to_mlme); + /* Register freq based callbacks */ + register_dfs_callbacks_for_freq(tmp_dfs_to_mlme); } #else void register_dfs_callbacks(void) diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_lmac_api.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_lmac_api.c index bfa0b4ee4ae961cd4b910ad681e8eb1dbb13717b..48c0bb454d06edf3d65df63f170d765ab9a44edb 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_lmac_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_lmac_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -197,3 +197,20 @@ bool lmac_is_host_dfs_check_support_enabled(struct wlan_objmgr_pdev *pdev) return enabled; } #endif + +bool lmac_dfs_is_hw_mode_switch_in_progress(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; + bool is_hw_mode_switch_in_progress = false; + + psoc = wlan_pdev_get_psoc(pdev); + dfs_tx_ops = &psoc->soc_cb.tx_ops.dfs_tx_ops; + + if (dfs_tx_ops->dfs_check_mode_switch_state) + dfs_tx_ops->dfs_check_mode_switch_state( + pdev, + &is_hw_mode_switch_in_progress); + + return is_hw_mode_switch_in_progress; +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c index dac0e47a06c74ee983bf48e9de35b9a2f03a5be8..54e68c6af7f254026dc8e1848b5f72a47583d8bf 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -39,6 +39,7 @@ void dfs_mlme_start_rcsa(struct wlan_objmgr_pdev *pdev, } #ifndef QCA_MCL_DFS_SUPPORT +#ifdef CONFIG_CHAN_NUM_API void dfs_mlme_mark_dfs(struct wlan_objmgr_pdev *pdev, uint8_t ieee, uint16_t freq, @@ -52,7 +53,24 @@ void dfs_mlme_mark_dfs(struct wlan_objmgr_pdev *pdev, vhtop_ch_freq_seg2, flags); } -#else +#endif +#ifdef CONFIG_CHAN_FREQ_API +void dfs_mlme_mark_dfs_for_freq(struct wlan_objmgr_pdev *pdev, + uint8_t ieee, + uint16_t freq, + uint16_t vhtop_ch_freq_seg2, + uint64_t flags) +{ + if (global_dfs_to_mlme.mlme_mark_dfs_for_freq) + global_dfs_to_mlme.mlme_mark_dfs_for_freq(pdev, + ieee, + freq, + vhtop_ch_freq_seg2, + flags); +} +#endif +#else /* Else of ndef MCL_DFS_SUPPORT */ +#ifdef CONFIG_CHAN_NUM_API static void dfs_send_radar_ind(struct wlan_objmgr_pdev *pdev, void *object, void *arg) @@ -69,7 +87,33 @@ static void dfs_send_radar_ind(struct wlan_objmgr_pdev *pdev, dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, "eWNI_SME_DFS_RADAR_FOUND pdev%d posted", vdev_id); } +#endif +/* dfs_send_radar_ind_for_freq() - Send radar found indication. + * @pdev: Pointer to wlan_objmgr_pdev. + * @object: Pointer to wlan_objmgr_vdev. + * @arg : void pointer to args. + */ +#ifdef CONFIG_CHAN_FREQ_API +static void dfs_send_radar_ind_for_freq(struct wlan_objmgr_pdev *pdev, + void *object, + void *arg) +{ + struct scheduler_msg sme_msg = {0}; + uint8_t vdev_id = wlan_vdev_get_id((struct wlan_objmgr_vdev *)object); + + sme_msg.type = eWNI_SME_DFS_RADAR_FOUND; + sme_msg.bodyptr = NULL; + sme_msg.bodyval = vdev_id; + scheduler_post_message(QDF_MODULE_ID_DFS, + QDF_MODULE_ID_SME, + QDF_MODULE_ID_SME, &sme_msg); + dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, "eWNI_SME_DFS_RADAR_FOUND pdev%d posted", + vdev_id); +} +#endif + +#ifdef CONFIG_CHAN_NUM_API void dfs_mlme_mark_dfs(struct wlan_objmgr_pdev *pdev, uint8_t ieee, uint16_t freq, @@ -92,7 +136,32 @@ void dfs_mlme_mark_dfs(struct wlan_objmgr_pdev *pdev, } #endif +#ifdef CONFIG_CHAN_FREQ_API +void dfs_mlme_mark_dfs_for_freq(struct wlan_objmgr_pdev *pdev, + uint8_t ieee, + uint16_t freq, + uint16_t vhtop_ch_freq_seg2, + uint64_t flags) +{ + struct wlan_objmgr_vdev *vdev; + + if (!pdev) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null pdev"); + return; + } + + vdev = wlan_pdev_peek_active_first_vdev(pdev, WLAN_DFS_ID); + + if (vdev) { + dfs_send_radar_ind_for_freq(pdev, vdev, NULL); + wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID); + } +} +#endif +#endif + #ifndef QCA_MCL_DFS_SUPPORT +#ifdef CONFIG_CHAN_NUM_API void dfs_mlme_start_csa(struct wlan_objmgr_pdev *pdev, uint8_t ieee_chan, uint16_t freq, uint8_t cfreq2, uint64_t flags) @@ -101,7 +170,19 @@ void dfs_mlme_start_csa(struct wlan_objmgr_pdev *pdev, global_dfs_to_mlme.mlme_start_csa(pdev, ieee_chan, freq, cfreq2, flags); } +#endif +#ifdef CONFIG_CHAN_FREQ_API +void dfs_mlme_start_csa_for_freq(struct wlan_objmgr_pdev *pdev, + uint8_t ieee_chan, uint16_t freq, + uint16_t cfreq2, uint64_t flags) +{ + if (global_dfs_to_mlme.mlme_start_csa_for_freq) + global_dfs_to_mlme.mlme_start_csa_for_freq(pdev, ieee_chan, + freq, cfreq2, flags); +} +#endif #else +#ifdef CONFIG_CHAN_NUM_API void dfs_mlme_start_csa(struct wlan_objmgr_pdev *pdev, uint8_t ieee_chan, uint16_t freq, uint8_t cfreq2, uint64_t flags) @@ -121,6 +202,27 @@ void dfs_mlme_start_csa(struct wlan_objmgr_pdev *pdev, } } #endif +#ifdef CONFIG_CHAN_FREQ_API +void dfs_mlme_start_csa_for_freq(struct wlan_objmgr_pdev *pdev, + uint8_t ieee_chan, uint16_t freq, + uint16_t cfreq2, uint64_t flags) +{ + struct wlan_objmgr_vdev *vdev; + + if (!pdev) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null pdev"); + return; + } + + vdev = wlan_pdev_peek_active_first_vdev(pdev, WLAN_DFS_ID); + + if (vdev) { + dfs_send_radar_ind(pdev, vdev, NULL); + wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID); + } +} +#endif +#endif #ifndef QCA_MCL_DFS_SUPPORT void dfs_mlme_proc_cac(struct wlan_objmgr_pdev *pdev, uint32_t vdev_id) @@ -159,6 +261,7 @@ void dfs_mlme_get_dfs_ch_nchans(struct wlan_objmgr_pdev *pdev, nchans); } +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS dfs_mlme_get_extchan(struct wlan_objmgr_pdev *pdev, uint16_t *dfs_ch_freq, uint64_t *dfs_ch_flags, @@ -178,6 +281,33 @@ QDF_STATUS dfs_mlme_get_extchan(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_E_FAILURE; } +#endif + +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS dfs_mlme_get_extchan_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *dfs_chan_freq, + uint64_t *dfs_chan_flags, + uint16_t *dfs_chan_flagext, + uint8_t *dfs_chan_ieee, + uint8_t *dfs_chan_vhtop_ch_freq_seg1, + uint8_t *dfs_chan_vhtop_ch_freq_seg2, + uint16_t *dfs_chan_mhz_freq_seg1, + uint16_t *dfs_chan_mhz_freq_seg2) +{ + if (global_dfs_to_mlme.mlme_get_extchan_for_freq) + return global_dfs_to_mlme.mlme_get_extchan_for_freq(pdev, + dfs_chan_freq, + dfs_chan_flags, + dfs_chan_flagext, + dfs_chan_ieee, + dfs_chan_vhtop_ch_freq_seg1, + dfs_chan_vhtop_ch_freq_seg2, + dfs_chan_mhz_freq_seg1, + dfs_chan_mhz_freq_seg2); + + return QDF_STATUS_E_FAILURE; +} +#endif void dfs_mlme_set_no_chans_available(struct wlan_objmgr_pdev *pdev, int val) @@ -201,6 +331,7 @@ int dfs_mlme_ieee2mhz(struct wlan_objmgr_pdev *pdev, int ieee, uint64_t flag) return freq; } +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS dfs_mlme_find_dot11_channel(struct wlan_objmgr_pdev *pdev, uint8_t ieee, @@ -226,7 +357,41 @@ dfs_mlme_find_dot11_channel(struct wlan_objmgr_pdev *pdev, dfs_ch_vhtop_ch_freq_seg2); return QDF_STATUS_E_FAILURE; } +#endif + +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS +dfs_mlme_find_dot11_chan_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + uint16_t des_cfreq2, + int mode, + uint16_t *dfs_chan_freq, + uint64_t *dfs_chan_flag, + uint16_t *dfs_flagext, + uint8_t *dfs_chan_ieee, + uint8_t *dfs_cfreq1, + uint8_t *dfs_cfreq2, + uint16_t *cfreq1_mhz, + uint16_t *cfreq2_mhz) +{ + if (global_dfs_to_mlme.mlme_find_dot11_chan_for_freq) + return global_dfs_to_mlme.mlme_find_dot11_chan_for_freq(pdev, + freq, + des_cfreq2, + mode, + dfs_chan_freq, + dfs_chan_flag, + dfs_flagext, + dfs_chan_ieee, + dfs_cfreq1, + dfs_cfreq2, + cfreq1_mhz, + cfreq2_mhz); + return QDF_STATUS_E_FAILURE; +} +#endif +#ifdef CONFIG_CHAN_NUM_API void dfs_mlme_get_dfs_ch_channels(struct wlan_objmgr_pdev *pdev, uint16_t *dfs_ch_freq, uint64_t *dfs_ch_flags, @@ -246,6 +411,33 @@ void dfs_mlme_get_dfs_ch_channels(struct wlan_objmgr_pdev *pdev, dfs_ch_vhtop_ch_freq_seg2, index); } +#endif + +#ifdef CONFIG_CHAN_FREQ_API +void dfs_mlme_get_dfs_channels_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *dfs_chan_freq, + uint64_t *dfs_chan_flags, + uint16_t *dfs_chan_flagext, + uint8_t *dfs_chan_ieee, + uint8_t *dfs_chan_vhtop_freq_seg1, + uint8_t *dfs_chan_vhtop_freq_seg2, + uint16_t *dfs_ch_mhz_freq_seg1, + uint16_t *dfs_ch_mhz_freq_seg2, + int index) +{ + if (global_dfs_to_mlme.mlme_get_dfs_channels_for_freq) + global_dfs_to_mlme.mlme_get_dfs_channels_for_freq(pdev, + dfs_chan_freq, + dfs_chan_flags, + dfs_chan_flagext, + dfs_chan_ieee, + dfs_chan_vhtop_freq_seg1, + dfs_chan_vhtop_freq_seg2, + dfs_ch_mhz_freq_seg1, + dfs_ch_mhz_freq_seg2, + index); +} +#endif uint32_t dfs_mlme_dfs_ch_flags_ext(struct wlan_objmgr_pdev *pdev) { @@ -282,6 +474,7 @@ void dfs_mlme_clist_update(struct wlan_objmgr_pdev *pdev, nentries); } +#ifdef CONFIG_CHAN_NUM_API int dfs_mlme_get_cac_timeout(struct wlan_objmgr_pdev *pdev, uint16_t dfs_ch_freq, uint8_t dfs_ch_vhtop_ch_freq_seg2, @@ -298,6 +491,26 @@ int dfs_mlme_get_cac_timeout(struct wlan_objmgr_pdev *pdev, return cac_timeout; } +#endif + +#ifdef CONFIG_CHAN_FREQ_API +int dfs_mlme_get_cac_timeout_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t dfs_chan_freq, + uint16_t dfs_cfreq2, + uint64_t dfs_ch_flags) +{ + int cac_timeout = 0; + + if (global_dfs_to_mlme.mlme_get_cac_timeout_for_freq) + global_dfs_to_mlme.mlme_get_cac_timeout_for_freq(pdev, + dfs_chan_freq, + dfs_cfreq2, + dfs_ch_flags, + &cac_timeout); + + return cac_timeout; +} +#endif #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) int dfs_mlme_rebuild_chan_list_with_non_dfs_channels( @@ -323,13 +536,13 @@ void dfs_mlme_restart_vaps_with_non_dfs_chan(struct wlan_objmgr_pdev *pdev, #if defined(WLAN_SUPPORT_PRIMARY_ALLOWED_CHAN) bool dfs_mlme_check_allowed_prim_chanlist(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num) + uint32_t chan_freq) { if (!global_dfs_to_mlme.mlme_check_allowed_prim_chanlist) return true; return global_dfs_to_mlme.mlme_check_allowed_prim_chanlist(pdev, - chan_num); + chan_freq); } #endif @@ -354,3 +567,19 @@ bool dfs_mlme_is_opmode_sta(struct wlan_objmgr_pdev *pdev) return global_dfs_to_mlme.mlme_is_opmode_sta(pdev); } + +void dfs_mlme_acquire_radar_mode_switch_lock(struct wlan_objmgr_pdev *pdev) +{ + if (!global_dfs_to_mlme.mlme_acquire_radar_mode_switch_lock) + return; + + global_dfs_to_mlme.mlme_acquire_radar_mode_switch_lock(pdev); +} + +void dfs_mlme_release_radar_mode_switch_lock(struct wlan_objmgr_pdev *pdev) +{ + if (!global_dfs_to_mlme.mlme_release_radar_mode_switch_lock) + return; + + global_dfs_to_mlme.mlme_release_radar_mode_switch_lock(pdev); +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c index 40339b536a9fc119f5581abc8bd782a46d853e13..577976dad0eaa7359e30a4b91281fbb23cf539e9 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -71,6 +71,7 @@ bool tgt_dfs_is_pdev_5ghz(struct wlan_objmgr_pdev *pdev) return is_5ghz; } +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS tgt_dfs_set_current_channel(struct wlan_objmgr_pdev *pdev, uint16_t dfs_ch_freq, uint64_t dfs_ch_flags, @@ -101,6 +102,46 @@ QDF_STATUS tgt_dfs_set_current_channel(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } qdf_export_symbol(tgt_dfs_set_current_channel); +#endif + +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS +tgt_dfs_set_current_channel_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t dfs_chan_freq, + uint64_t dfs_chan_flags, + uint16_t dfs_chan_flagext, + uint8_t dfs_chan_ieee, + uint8_t dfs_chan_vhtop_freq_seg1, + uint8_t dfs_chan_vhtop_freq_seg2, + uint16_t dfs_chan_mhz_freq_seg1, + uint16_t dfs_chan_mhz_freq_seg2) +{ + struct wlan_dfs *dfs; + + if (!tgt_dfs_is_pdev_5ghz(pdev)) + return QDF_STATUS_SUCCESS; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return QDF_STATUS_E_FAILURE; + } + + dfs_set_current_channel_for_freq(dfs, + dfs_chan_freq, + dfs_chan_flags, + dfs_chan_flagext, + dfs_chan_ieee, + dfs_chan_vhtop_freq_seg1, + dfs_chan_vhtop_freq_seg2, + dfs_chan_mhz_freq_seg1, + dfs_chan_mhz_freq_seg2); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(tgt_dfs_set_current_channel_for_freq); +#endif QDF_STATUS tgt_dfs_radar_enable(struct wlan_objmgr_pdev *pdev, int no_cac, uint32_t opmode, bool enable) @@ -385,26 +426,98 @@ QDF_STATUS tgt_dfs_agile_precac_start(struct wlan_objmgr_pdev *pdev) qdf_export_symbol(tgt_dfs_agile_precac_start); #ifdef QCA_SUPPORT_AGILE_DFS +#ifdef CONFIG_CHAN_FREQ_API QDF_STATUS tgt_dfs_set_agile_precac_state(struct wlan_objmgr_pdev *pdev, int agile_precac_state) { struct wlan_dfs *dfs; + struct dfs_soc_priv_obj *dfs_soc; + bool is_precac_running_on_given_pdev = false; int i; + if (!tgt_dfs_is_pdev_5ghz(pdev)) + return QDF_STATUS_SUCCESS; + dfs = wlan_pdev_get_dfs_obj(pdev); if (!dfs) { dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); return QDF_STATUS_E_FAILURE; } - dfs->dfs_soc_obj->precac_state_started = agile_precac_state; - if (!dfs->dfs_soc_obj->precac_state_started) { - for (i = 0; i < dfs->dfs_soc_obj->num_dfs_privs; i++) - dfs->dfs_soc_obj->dfs_priv[i].agile_precac_active = 0; + dfs_soc = dfs->dfs_soc_obj; + for (i = 0; i < dfs_soc->num_dfs_privs; i++) { + if (dfs_soc->dfs_priv[i].dfs == dfs) { + /* Set the pdev state to given value. */ + dfs_soc->dfs_priv[i].agile_precac_active = + agile_precac_state; + /* If the pdev state is changed to inactive, + * reset the agile channel. + */ + if (!agile_precac_state) + dfs->dfs_agile_precac_freq_mhz = 0; + if (dfs_soc->cur_precac_dfs_index == i) + is_precac_running_on_given_pdev = true; + } } + /* If preCAC is running on this pdev and the agile_precac_state + * is set to false, set the global state in dfs_soc_obj to false. + * If this global state is not set to false, then preCAC will not be + * started the next time this pdev becomes active. + */ + if (is_precac_running_on_given_pdev && !agile_precac_state) + dfs_soc->precac_state_started = PRECAC_NOT_STARTED; + return QDF_STATUS_SUCCESS; } +#else +#ifdef CONFIG_CHAN_NUM_API +QDF_STATUS tgt_dfs_set_agile_precac_state(struct wlan_objmgr_pdev *pdev, + int agile_precac_state) +{ + struct wlan_dfs *dfs; + struct dfs_soc_priv_obj *dfs_soc; + bool is_precac_running_on_given_pdev = false; + int i; + + if (!tgt_dfs_is_pdev_5ghz(pdev)) + return QDF_STATUS_SUCCESS; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return QDF_STATUS_E_FAILURE; + } + + dfs_soc = dfs->dfs_soc_obj; + for (i = 0; i < dfs_soc->num_dfs_privs; i++) { + if (dfs_soc->dfs_priv[i].dfs == dfs) { + /* Set the pdev state to given value. */ + dfs_soc->dfs_priv[i].agile_precac_active = + agile_precac_state; + /* If the pdev state is changed to inactive, + * reset the agile channel. + */ + if (!agile_precac_state) + dfs->dfs_agile_precac_freq = 0; + if (dfs_soc->cur_precac_dfs_index == i) + is_precac_running_on_given_pdev = true; + } + } + + /* If preCAC is running on this pdev and the agile_precac_state + * is set to false, set the global state in dfs_soc_obj to false. + * If this global state is not set to false, then preCAC will not be + * started the next time this pdev becomes active. + */ + if (is_precac_running_on_given_pdev && !agile_precac_state) + dfs_soc->precac_state_started = PRECAC_NOT_STARTED; + + return QDF_STATUS_SUCCESS; +} +#endif +#endif + #else QDF_STATUS tgt_dfs_set_agile_precac_state(struct wlan_objmgr_pdev *pdev, int agile_precac_state) @@ -446,6 +559,7 @@ QDF_STATUS tgt_dfs_ocac_complete(struct wlan_objmgr_pdev *pdev, #endif qdf_export_symbol(tgt_dfs_ocac_complete); +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS tgt_dfs_find_vht80_chan_for_precac(struct wlan_objmgr_pdev *pdev, uint32_t chan_mode, uint8_t ch_freq_seg1, @@ -475,6 +589,41 @@ QDF_STATUS tgt_dfs_find_vht80_chan_for_precac(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } qdf_export_symbol(tgt_dfs_find_vht80_chan_for_precac); +#endif + +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS +tgt_dfs_find_vht80_precac_chan_freq(struct wlan_objmgr_pdev *pdev, + uint32_t chan_mode, + uint16_t chan_freq_seg1_mhz, + uint32_t *cfreq1, + uint32_t *cfreq2, + uint32_t *phy_mode, + bool *dfs_set_cfreq2, + bool *set_agile) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return QDF_STATUS_E_FAILURE; + } + + dfs_find_vht80_chan_for_precac_for_freq(dfs, + chan_mode, + chan_freq_seg1_mhz, + cfreq1, + cfreq2, + phy_mode, + dfs_set_cfreq2, + set_agile); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(tgt_dfs_find_vht80_precac_chan_freq); +#endif QDF_STATUS tgt_dfs_process_radar_ind(struct wlan_objmgr_pdev *pdev, struct radar_found_info *radar_found) @@ -774,3 +923,123 @@ bool tgt_dfs_is_stadfs_enabled(struct wlan_objmgr_pdev *pdev) return dfs->dfs_is_stadfs_enabled; } + +#ifdef QCA_SUPPORT_AGILE_DFS +void tgt_dfs_set_fw_adfs_support(struct wlan_objmgr_pdev *pdev, + bool fw_adfs_support_160, + bool fw_adfs_support_non_160) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_set_fw_adfs_support(dfs, + fw_adfs_support_160, + fw_adfs_support_non_160); +} + +qdf_export_symbol(tgt_dfs_set_fw_adfs_support); +#endif + +void tgt_dfs_init_tmp_psoc_nol(struct wlan_objmgr_pdev *pdev, + uint8_t num_radios) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_init_tmp_psoc_nol(dfs, num_radios); +} + +qdf_export_symbol(tgt_dfs_init_tmp_psoc_nol); + +void tgt_dfs_deinit_tmp_psoc_nol(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_deinit_tmp_psoc_nol(dfs); +} + +qdf_export_symbol(tgt_dfs_deinit_tmp_psoc_nol); + +void tgt_dfs_save_dfs_nol_in_psoc(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id, + uint16_t low_5ghz_freq, + uint16_t high_5ghz_freq) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_save_dfs_nol_in_psoc(dfs, pdev_id, low_5ghz_freq, high_5ghz_freq); +} + +qdf_export_symbol(tgt_dfs_save_dfs_nol_in_psoc); + +void tgt_dfs_reinit_nol_from_psoc_copy(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_reinit_nol_from_psoc_copy(dfs, pdev_id); +} + +qdf_export_symbol(tgt_dfs_reinit_nol_from_psoc_copy); + +void tgt_dfs_reinit_precac_lists(struct wlan_objmgr_pdev *src_pdev, + struct wlan_objmgr_pdev *dest_pdev, + uint16_t low_5g_freq, + uint16_t high_5g_freq) +{ + struct wlan_dfs *src_dfs, *dest_dfs; + + src_dfs = wlan_pdev_get_dfs_obj(src_pdev); + if (!src_dfs) { + dfs_err(src_dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + dest_dfs = wlan_pdev_get_dfs_obj(dest_pdev); + if (!dest_dfs) { + dfs_err(dest_dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_reinit_precac_lists(src_dfs, dest_dfs, low_5g_freq, high_5g_freq); +} + +void tgt_dfs_complete_deferred_tasks(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_complete_deferred_tasks(dfs); +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c index 1709fe17e23f8dbbb402818ce08c873c217b3a6d..556e304dda4138423f62e224cffdc23b3642f8ad 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -139,8 +139,8 @@ QDF_STATUS ucfg_dfs_set_precac_enable(struct wlan_objmgr_pdev *pdev, } qdf_export_symbol(ucfg_dfs_set_precac_enable); -QDF_STATUS ucfg_dfs_get_precac_enable(struct wlan_objmgr_pdev *pdev, - int *buff) +QDF_STATUS ucfg_dfs_get_legacy_precac_enable(struct wlan_objmgr_pdev *pdev, + bool *buff) { struct wlan_dfs *dfs; @@ -153,11 +153,38 @@ QDF_STATUS ucfg_dfs_get_precac_enable(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_E_FAILURE; } - *buff = dfs_get_precac_enable(dfs); + *buff = dfs_is_legacy_precac_enabled(dfs); return QDF_STATUS_SUCCESS; } -qdf_export_symbol(ucfg_dfs_get_precac_enable); + +qdf_export_symbol(ucfg_dfs_get_legacy_precac_enable); + +QDF_STATUS ucfg_dfs_get_agile_precac_enable(struct wlan_objmgr_pdev *pdev, + bool *buff) +{ + struct wlan_dfs *dfs; + + if (!pdev || !buff) + return QDF_STATUS_E_FAILURE; + + if (!tgt_dfs_is_pdev_5ghz(pdev)) { + *buff = false; + return QDF_STATUS_SUCCESS; + } + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); + return QDF_STATUS_E_FAILURE; + } + + *buff = dfs_is_agile_precac_enabled(dfs); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(ucfg_dfs_get_agile_precac_enable); QDF_STATUS ucfg_dfs_set_nol_subchannel_marking(struct wlan_objmgr_pdev *pdev, @@ -222,6 +249,7 @@ QDF_STATUS ucfg_dfs_get_precac_intermediate_chan(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } +#ifdef CONFIG_CHAN_NUM_API enum precac_chan_state ucfg_dfs_get_precac_chan_state(struct wlan_objmgr_pdev *pdev, uint8_t precac_chan) @@ -236,7 +264,31 @@ ucfg_dfs_get_precac_chan_state(struct wlan_objmgr_pdev *pdev, } retval = dfs_get_precac_chan_state(dfs, precac_chan); - if (PRECAC_ERR == retval) { + if (retval == PRECAC_ERR) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Could not find precac channel state"); + } + + return retval; +} +#endif + +#ifdef CONFIG_CHAN_FREQ_API +enum precac_chan_state +ucfg_dfs_get_precac_chan_state_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t precac_chan_freq) +{ + struct wlan_dfs *dfs; + enum precac_chan_state retval = PRECAC_ERR; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); + return PRECAC_ERR; + } + + retval = dfs_get_precac_chan_state_for_freq(dfs, precac_chan_freq); + if (retval == PRECAC_ERR) { dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "Could not find precac channel state"); } @@ -244,6 +296,7 @@ ucfg_dfs_get_precac_chan_state(struct wlan_objmgr_pdev *pdev, return retval; } #endif +#endif #ifdef QCA_MCL_DFS_SUPPORT QDF_STATUS ucfg_dfs_update_config(struct wlan_objmgr_psoc *psoc, @@ -310,3 +363,88 @@ QDF_STATUS ucfg_dfs_get_override_status_timeout(struct wlan_objmgr_pdev *pdev, qdf_export_symbol(ucfg_dfs_get_override_status_timeout); #endif + +#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(WLAN_DFS_SYNTHETIC_RADAR) +void ucfg_dfs_allow_hw_pulses(struct wlan_objmgr_pdev *pdev, + bool allow_hw_pulses) +{ + struct wlan_dfs *dfs; + + if (!tgt_dfs_is_pdev_5ghz(pdev)) + return; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_allow_hw_pulses(dfs, allow_hw_pulses); +} + +qdf_export_symbol(ucfg_dfs_allow_hw_pulses); + +bool ucfg_dfs_is_hw_pulses_allowed(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + if (!tgt_dfs_is_pdev_5ghz(pdev)) + return false; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + return dfs_is_hw_pulses_allowed(dfs); +} + +qdf_export_symbol(ucfg_dfs_is_hw_pulses_allowed); +#endif + +#ifdef QCA_SUPPORT_AGILE_DFS +QDF_STATUS ucfg_dfs_reset_agile_config(struct wlan_objmgr_psoc *psoc) +{ + struct dfs_soc_priv_obj *soc_obj; + + if (!psoc) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); + return QDF_STATUS_E_FAILURE; + } + + soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_DFS); + if (!soc_obj) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to get dfs psoc component"); + return QDF_STATUS_E_FAILURE; + } + + dfs_reset_agile_config(soc_obj); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(ucfg_dfs_reset_agile_config); +#endif + +QDF_STATUS ucfg_dfs_reinit_timers(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + if (!tgt_dfs_is_pdev_5ghz(pdev)) + return QDF_STATUS_SUCCESS; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return QDF_STATUS_E_FAILURE; + } + + dfs_reinit_timers(dfs); + + return QDF_STATUS_SUCCESS; +} + +qdf_export_symbol(ucfg_dfs_reinit_timers); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c index 0ba8a971afc79e9887c3ad847f80c57399956c30..c47703619671fb08488b9820739641623d7cdad6 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -27,7 +27,6 @@ #include "wlan_dfs_mlme_api.h" #include "../../core/src/dfs.h" #include "../../core/src/dfs_zero_cac.h" -#include "../../core/src/dfs_etsi_precac.h" #include #include "../../core/src/dfs_random_chan_sel.h" #ifdef QCA_DFS_USE_POLICY_MANAGER @@ -54,7 +53,6 @@ QDF_STATUS utils_dfs_reset(struct wlan_objmgr_pdev *pdev) dfs_reset(dfs); dfs_nol_update(dfs); dfs_reset_precaclists(dfs); - dfs_reset_etsiprecaclists(dfs); return QDF_STATUS_SUCCESS; } @@ -70,6 +68,7 @@ bool utils_dfs_is_freq_in_nol(struct wlan_objmgr_pdev *pdev, uint32_t freq) return dfs_is_freq_in_nol(dfs, freq); } +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS utils_dfs_cac_valid_reset(struct wlan_objmgr_pdev *pdev, uint8_t prevchan_ieee, uint32_t prevchan_flags) @@ -85,8 +84,12 @@ QDF_STATUS utils_dfs_cac_valid_reset(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } qdf_export_symbol(utils_dfs_cac_valid_reset); +#endif -QDF_STATUS utils_dfs_reset_precaclists(struct wlan_objmgr_pdev *pdev) +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS utils_dfs_cac_valid_reset_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t prevchan_freq, + uint32_t prevchan_flags) { struct wlan_dfs *dfs; @@ -94,14 +97,15 @@ QDF_STATUS utils_dfs_reset_precaclists(struct wlan_objmgr_pdev *pdev) if (!dfs) return QDF_STATUS_E_FAILURE; - dfs_reset_precaclists(dfs); + dfs_cac_valid_reset_for_freq(dfs, prevchan_freq, prevchan_flags); return QDF_STATUS_SUCCESS; } -qdf_export_symbol(utils_dfs_reset_precaclists); -#ifdef QCA_SUPPORT_ETSI_PRECAC_DFS -QDF_STATUS utils_dfs_reset_etsi_precaclists(struct wlan_objmgr_pdev *pdev) +qdf_export_symbol(utils_dfs_cac_valid_reset_for_freq); +#endif + +QDF_STATUS utils_dfs_reset_precaclists(struct wlan_objmgr_pdev *pdev) { struct wlan_dfs *dfs; @@ -109,15 +113,30 @@ QDF_STATUS utils_dfs_reset_etsi_precaclists(struct wlan_objmgr_pdev *pdev) if (!dfs) return QDF_STATUS_E_FAILURE; - dfs_reset_etsiprecaclists(dfs); + dfs_reset_precaclists(dfs); return QDF_STATUS_SUCCESS; } +qdf_export_symbol(utils_dfs_reset_precaclists); + +#ifdef CONFIG_CHAN_NUM_API +void utils_dfs_unmark_precac_nol(struct wlan_objmgr_pdev *pdev, uint8_t chan) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) + return; + + dfs_unmark_precac_nol(dfs, chan); +} -qdf_export_symbol(utils_dfs_reset_etsi_precaclists); +qdf_export_symbol(utils_dfs_unmark_precac_nol); +#endif -void utils_dfs_add_to_etsi_precac_required_list(struct wlan_objmgr_pdev *pdev, - uint8_t *chan) +#ifdef CONFIG_CHAN_FREQ_API +void utils_dfs_unmark_precac_nol_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t chan_freq) { struct wlan_dfs *dfs; @@ -125,10 +144,10 @@ void utils_dfs_add_to_etsi_precac_required_list(struct wlan_objmgr_pdev *pdev, if (!dfs) return; - dfs_add_to_etsi_precac_required_list(dfs, chan); + dfs_unmark_precac_nol_for_freq(dfs, chan_freq); } -qdf_export_symbol(utils_dfs_add_to_etsi_precac_required_list); +qdf_export_symbol(utils_dfs_unmark_precac_nol_for_freq); #endif QDF_STATUS utils_dfs_cancel_precac_timer(struct wlan_objmgr_pdev *pdev) @@ -145,6 +164,26 @@ QDF_STATUS utils_dfs_cancel_precac_timer(struct wlan_objmgr_pdev *pdev) } qdf_export_symbol(utils_dfs_cancel_precac_timer); +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS utils_dfs_start_precac_timer(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "NULL dfs"); + return QDF_STATUS_E_FAILURE; + } + + if (!dfs->dfs_precac_secondary_freq_mhz) + return QDF_STATUS_E_FAILURE; + + dfs_start_precac_timer_for_freq(dfs, + dfs->dfs_precac_secondary_freq_mhz); + return QDF_STATUS_SUCCESS; +} +#else +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS utils_dfs_start_precac_timer(struct wlan_objmgr_pdev *pdev) { struct wlan_dfs *dfs; @@ -161,8 +200,11 @@ QDF_STATUS utils_dfs_start_precac_timer(struct wlan_objmgr_pdev *pdev) dfs->dfs_precac_secondary_freq); return QDF_STATUS_SUCCESS; } +#endif +#endif #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT +#ifdef CONFIG_CHAN_NUM_API bool utils_dfs_precac_decide_pref_chan(struct wlan_objmgr_pdev *pdev, uint8_t *ch_ieee, @@ -179,6 +221,23 @@ utils_dfs_precac_decide_pref_chan(struct wlan_objmgr_pdev *pdev, } #endif +#ifdef CONFIG_CHAN_FREQ_API +bool +utils_dfs_precac_decide_pref_chan_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *chan_freq, + enum wlan_phymode mode) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "NULL dfs"); + return false; + } + return dfs_decide_precac_preferred_chan_for_freq(dfs, chan_freq, mode); +} +#endif +#endif QDF_STATUS utils_dfs_cancel_cac_timer(struct wlan_objmgr_pdev *pdev) { struct wlan_dfs *dfs; @@ -220,17 +279,6 @@ QDF_STATUS utils_dfs_cac_stop(struct wlan_objmgr_pdev *pdev) } qdf_export_symbol(utils_dfs_cac_stop); -void utils_dfs_clear_cac_started_chan(struct wlan_objmgr_pdev *pdev) -{ - struct wlan_dfs *dfs; - - dfs = wlan_pdev_get_dfs_obj(pdev); - if (!dfs) - return; - - dfs_clear_cac_started_chan(dfs); -} - /** dfs_fill_chan_info() - Fill the dfs channel structure with wlan * channel. * @chan: Pointer to DFS channel structure. @@ -238,6 +286,21 @@ void utils_dfs_clear_cac_started_chan(struct wlan_objmgr_pdev *pdev) * * Return: void */ +#ifdef CONFIG_CHAN_FREQ_API +static void dfs_fill_chan_info(struct dfs_channel *chan, + struct wlan_channel *wlan_chan) +{ + chan->dfs_ch_freq = wlan_chan->ch_freq; + chan->dfs_ch_flags = wlan_chan->ch_flags; + chan->dfs_ch_flagext = wlan_chan->ch_flagext; + chan->dfs_ch_ieee = wlan_chan->ch_ieee; + chan->dfs_ch_vhtop_ch_freq_seg1 = wlan_chan->ch_freq_seg1; + chan->dfs_ch_vhtop_ch_freq_seg2 = wlan_chan->ch_freq_seg2; + chan->dfs_ch_mhz_freq_seg1 = wlan_chan->ch_cfreq1; + chan->dfs_ch_mhz_freq_seg2 = wlan_chan->ch_cfreq2; +} +#else +#ifdef CONFIG_CHAN_NUM_API static void dfs_fill_chan_info(struct dfs_channel *chan, struct wlan_channel *wlan_chan) { @@ -248,6 +311,8 @@ static void dfs_fill_chan_info(struct dfs_channel *chan, chan->dfs_ch_vhtop_ch_freq_seg1 = wlan_chan->ch_freq_seg1; chan->dfs_ch_vhtop_ch_freq_seg2 = wlan_chan->ch_freq_seg2; } +#endif +#endif bool utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev, struct wlan_channel *wlan_chan) @@ -264,8 +329,31 @@ bool utils_dfs_is_precac_done(struct wlan_objmgr_pdev *pdev, return dfs_is_precac_done(dfs, &chan); } -bool utils_dfs_check_for_cac_start(struct wlan_objmgr_pdev *pdev, - bool *continue_current_cac) +bool utils_dfs_is_cac_required(struct wlan_objmgr_pdev *pdev, + struct wlan_channel *cur_chan, + struct wlan_channel *prev_chan, + bool *continue_current_cac) +{ + struct wlan_dfs *dfs; + struct dfs_channel cur_channel; + struct dfs_channel prev_channel; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) + return false; + + dfs_fill_chan_info(&cur_channel, cur_chan); + dfs_fill_chan_info(&prev_channel, prev_chan); + + return dfs_is_cac_required(dfs, + &cur_channel, + &prev_channel, + continue_current_cac); +} + +bool +utils_dfs_is_cac_required_on_dfs_curchan(struct wlan_objmgr_pdev *pdev, + bool *continue_current_cac) { struct wlan_dfs *dfs; @@ -273,7 +361,10 @@ bool utils_dfs_check_for_cac_start(struct wlan_objmgr_pdev *pdev, if (!dfs) return false; - return dfs_check_for_cac_start(dfs, continue_current_cac); + return dfs_is_cac_required(dfs, + dfs->dfs_curchan, + dfs->dfs_prevchan, + continue_current_cac); } QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev) @@ -663,6 +754,7 @@ void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, * utils_dfs_get_channel_list() - Get channel list from regdb component, based * on current channel list. * @pdev: Pointer to pdev structure. + * @vdev: vdev of request * @chan: Pointer to channel list. * @num_chan: number of channels. * @@ -671,7 +763,74 @@ void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, * so that the random channel function does not select either 2.4GHz or 4.9GHz * channel. */ +#ifdef CONFIG_CHAN_FREQ_API static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_vdev *vdev, + struct dfs_channel *chan_list, + uint32_t *num_chan) +{ + struct dfs_channel *tmp_chan_list = NULL; + struct wlan_dfs *dfs; + bool is_curchan_5g; + bool is_curchan_24g; + bool is_curchan_49g; + uint32_t chan_num; + uint32_t center_freq; + uint16_t flagext; + int i, j = 0; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); + return; + } + + tmp_chan_list = qdf_mem_malloc(*num_chan * sizeof(*tmp_chan_list)); + if (!tmp_chan_list) + return; + + utils_dfs_get_chan_list(pdev, (void *)tmp_chan_list, num_chan); + + chan_num = dfs->dfs_curchan->dfs_ch_ieee; + center_freq = dfs->dfs_curchan->dfs_ch_freq; + is_curchan_5g = WLAN_REG_IS_5GHZ_CH_FREQ(center_freq); + is_curchan_24g = WLAN_REG_IS_24GHZ_CH_FREQ(center_freq); + is_curchan_49g = WLAN_REG_IS_49GHZ_FREQ(center_freq); + + for (i = 0; i < *num_chan; i++) { + chan_num = tmp_chan_list[i].dfs_ch_ieee; + center_freq = tmp_chan_list[i].dfs_ch_freq; + flagext = tmp_chan_list[i].dfs_ch_flagext; + /* No change in prototype needed. Hence retaining same func */ + if (!dfs_mlme_check_allowed_prim_chanlist(pdev, center_freq)) + continue; + + if ((is_curchan_5g) && WLAN_REG_IS_5GHZ_CH_FREQ(center_freq)) { + chan_list[j].dfs_ch_ieee = chan_num; + chan_list[j].dfs_ch_freq = center_freq; + chan_list[j].dfs_ch_flagext = flagext; + j++; + } else if ((is_curchan_24g) && + WLAN_REG_IS_24GHZ_CH_FREQ(center_freq)) { + chan_list[j].dfs_ch_ieee = chan_num; + chan_list[j].dfs_ch_freq = center_freq; + j++; + } else if ((is_curchan_49g) && + WLAN_REG_IS_49GHZ_FREQ(center_freq)) { + chan_list[j].dfs_ch_ieee = chan_num; + chan_list[j].dfs_ch_freq = center_freq; + j++; + } + } + + *num_chan = j; + + qdf_mem_free(tmp_chan_list); +} +#else /* NUM_API */ +#ifdef CONFIG_CHAN_NUM_API +static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_vdev *vdev, struct dfs_channel *chan_list, uint32_t *num_chan) { @@ -733,6 +892,8 @@ static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, qdf_mem_free(tmp_chan_list); } +#endif +#endif #else @@ -742,17 +903,19 @@ void utils_dfs_get_nol_history_chan_list(struct wlan_objmgr_pdev *pdev, utils_dfs_get_chan_list(pdev, clist, num_chan); } -void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, - void *clist, uint32_t *num_chan) +static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_vdev *vdev, + struct dfs_channel *chan_list, + uint32_t *num_chan) { - uint8_t pcl_ch[QDF_MAX_NUM_CHAN] = {0}; - uint8_t weight_list[QDF_MAX_NUM_CHAN] = {0}; + uint32_t pcl_ch[NUM_CHANNELS] = {0}; + uint8_t weight_list[NUM_CHANNELS] = {0}; uint32_t len; uint32_t weight_len; int i; struct wlan_objmgr_psoc *psoc; uint32_t conn_count = 0; - struct dfs_channel *chan_list = (struct dfs_channel *)clist; + enum policy_mgr_con_mode mode; psoc = wlan_pdev_get_psoc(pdev); if (!psoc) { @@ -763,14 +926,21 @@ void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, len = QDF_ARRAY_SIZE(pcl_ch); weight_len = QDF_ARRAY_SIZE(weight_list); + + if (vdev) + mode = policy_mgr_convert_device_mode_to_qdf_type( + wlan_vdev_mlme_get_opmode(vdev)); + else + mode = PM_SAP_MODE; conn_count = policy_mgr_mode_specific_connection_count( - psoc, PM_SAP_MODE, NULL); + psoc, mode, NULL); if (0 == conn_count) - policy_mgr_get_pcl(psoc, PM_SAP_MODE, pcl_ch, - &len, weight_list, weight_len); + policy_mgr_get_pcl(psoc, mode, pcl_ch, + &len, weight_list, weight_len); else - policy_mgr_get_pcl_for_existing_conn(psoc, PM_SAP_MODE, pcl_ch, - &len, weight_list, weight_len, true); + policy_mgr_get_pcl_for_existing_conn( + psoc, mode, pcl_ch, &len, weight_list, + weight_len, true); if (*num_chan < len) { dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, @@ -781,29 +951,27 @@ void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, } for (i = 0; i < len; i++) { - chan_list[i].dfs_ch_ieee = pcl_ch[i]; - chan_list[i].dfs_ch_freq = - wlan_reg_chan_to_freq(pdev, pcl_ch[i]); + chan_list[i].dfs_ch_ieee = + wlan_reg_freq_to_chan(pdev, pcl_ch[i]); + chan_list[i].dfs_ch_freq = pcl_ch[i]; } *num_chan = i; dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, "num channels %d", i); } -static void utils_dfs_get_channel_list(struct wlan_objmgr_pdev *pdev, - struct dfs_channel *chan_list, - uint32_t *num_chan) +void utils_dfs_get_chan_list(struct wlan_objmgr_pdev *pdev, + void *clist, uint32_t *num_chan) { - utils_dfs_get_chan_list(pdev, (void *)chan_list, num_chan); + utils_dfs_get_channel_list(pdev, NULL, (struct dfs_channel *)clist, + num_chan); } #endif -QDF_STATUS utils_dfs_get_random_channel( - struct wlan_objmgr_pdev *pdev, - uint16_t flags, - struct ch_params *ch_params, - uint32_t *hw_mode, - uint8_t *target_chan, - struct dfs_acs_info *acs_info) +#ifdef CONFIG_CHAN_NUM_API +QDF_STATUS utils_dfs_get_vdev_random_channel( + struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, + uint16_t flags, struct ch_params *ch_params, uint32_t *hw_mode, + uint8_t *target_chan, struct dfs_acs_info *acs_info) { uint32_t dfs_reg; uint32_t num_chan = NUM_CHANNELS; @@ -831,7 +999,7 @@ QDF_STATUS utils_dfs_get_random_channel( if (!chan_list) goto random_chan_error; - utils_dfs_get_channel_list(pdev, chan_list, &num_chan); + utils_dfs_get_channel_list(pdev, vdev, chan_list, &num_chan); if (!num_chan) { dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero channels"); goto random_chan_error; @@ -870,8 +1038,125 @@ QDF_STATUS utils_dfs_get_random_channel( return status; } + +qdf_export_symbol(utils_dfs_get_vdev_random_channel); +#endif + +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS utils_dfs_get_vdev_random_channel_for_freq( + struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, + uint16_t flags, struct ch_params *chan_params, uint32_t *hw_mode, + uint16_t *target_chan_freq, struct dfs_acs_info *acs_info) +{ + uint32_t dfs_reg; + uint32_t num_chan = NUM_CHANNELS; + struct wlan_dfs *dfs = NULL; + struct wlan_objmgr_psoc *psoc; + struct dfs_channel *chan_list = NULL; + struct dfs_channel cur_chan; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + *target_chan_freq = 0; + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); + goto random_chan_error; + } + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); + goto random_chan_error; + } + + wlan_reg_get_dfs_region(pdev, &dfs_reg); + chan_list = qdf_mem_malloc(num_chan * sizeof(*chan_list)); + if (!chan_list) + goto random_chan_error; + + utils_dfs_get_channel_list(pdev, vdev, chan_list, &num_chan); + if (!num_chan) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "zero channels"); + goto random_chan_error; + } + + cur_chan.dfs_ch_vhtop_ch_freq_seg1 = chan_params->center_freq_seg0; + cur_chan.dfs_ch_vhtop_ch_freq_seg2 = chan_params->center_freq_seg1; + cur_chan.dfs_ch_mhz_freq_seg1 = chan_params->mhz_freq_seg0; + cur_chan.dfs_ch_mhz_freq_seg2 = chan_params->mhz_freq_seg1; + + if (!chan_params->ch_width) + utils_dfs_get_max_sup_width(pdev, + (uint8_t *)&chan_params->ch_width); + + *target_chan_freq = dfs_prepare_random_channel_for_freq(dfs, chan_list, + num_chan, flags, (uint8_t *)&chan_params->ch_width, + &cur_chan, (uint8_t)dfs_reg, acs_info); + + chan_params->center_freq_seg0 = cur_chan.dfs_ch_vhtop_ch_freq_seg1; + chan_params->center_freq_seg1 = cur_chan.dfs_ch_vhtop_ch_freq_seg2; + chan_params->mhz_freq_seg0 = cur_chan.dfs_ch_mhz_freq_seg1; + chan_params->mhz_freq_seg1 = cur_chan.dfs_ch_mhz_freq_seg2; + + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "input width=%d", chan_params->ch_width); + + if (*target_chan_freq) { + wlan_reg_set_channel_params_for_freq(pdev, *target_chan_freq, 0, + chan_params); + utils_dfs_get_max_phy_mode(pdev, hw_mode); + status = QDF_STATUS_SUCCESS; + } + + dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "ch=%d, seg0=%d, seg1=%d, width=%d", + *target_chan_freq, chan_params->center_freq_seg0, + chan_params->center_freq_seg1, chan_params->ch_width); + +random_chan_error: + qdf_mem_free(chan_list); + + return status; +} + +qdf_export_symbol(utils_dfs_get_vdev_random_channel_for_freq); +#endif + +#ifdef CONFIG_CHAN_NUM_API +QDF_STATUS utils_dfs_get_random_channel( + struct wlan_objmgr_pdev *pdev, + uint16_t flags, + struct ch_params *ch_params, + uint32_t *hw_mode, + uint8_t *target_chan, + struct dfs_acs_info *acs_info) +{ + return utils_dfs_get_vdev_random_channel( + pdev, NULL, flags, ch_params, hw_mode, target_chan, + acs_info); +} qdf_export_symbol(utils_dfs_get_random_channel); +#endif + +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS utils_dfs_get_random_channel_for_freq( + struct wlan_objmgr_pdev *pdev, + uint16_t flags, + struct ch_params *ch_params, + uint32_t *hw_mode, + uint16_t *target_chan_freq, + struct dfs_acs_info *acs_info) +{ + return utils_dfs_get_vdev_random_channel_for_freq(pdev, NULL, flags, + ch_params, hw_mode, + target_chan_freq, + acs_info); +} +qdf_export_symbol(utils_dfs_get_random_channel_for_freq); +#endif + +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS utils_dfs_bw_reduced_channel( struct wlan_objmgr_pdev *pdev, struct ch_params *ch_params, @@ -919,6 +1204,60 @@ QDF_STATUS utils_dfs_bw_reduced_channel( } qdf_export_symbol(utils_dfs_bw_reduced_channel); +#endif + +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS utils_dfs_bw_reduced_channel_for_freq( + struct wlan_objmgr_pdev *pdev, + struct ch_params *chan_params, + uint32_t *hw_mode, + uint16_t *target_chan_freq) +{ + struct wlan_dfs *dfs = NULL; + struct wlan_objmgr_psoc *psoc; + enum channel_state ch_state; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct dfs_channel *dfs_curchan; + + *target_chan_freq = 0; + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); + return status; + } + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); + return status; + } + dfs_curchan = dfs->dfs_curchan; + ch_state = + wlan_reg_get_channel_state_for_freq(pdev, + dfs_curchan->dfs_ch_freq); + + if (ch_state == CHANNEL_STATE_DFS || + ch_state == CHANNEL_STATE_ENABLE) { + chan_params->mhz_freq_seg0 = + dfs_curchan->dfs_ch_mhz_freq_seg1; + chan_params->mhz_freq_seg1 = + dfs_curchan->dfs_ch_mhz_freq_seg2; + wlan_reg_set_channel_params_for_freq(pdev, + dfs_curchan->dfs_ch_freq, + 0, chan_params); + + *target_chan_freq = dfs_curchan->dfs_ch_freq; + utils_dfs_get_max_phy_mode(pdev, hw_mode); + + return QDF_STATUS_SUCCESS; + } + + return status; +} + +qdf_export_symbol(utils_dfs_bw_reduced_channel_for_freq); +#endif + #ifdef QCA_DFS_NOL_PLATFORM_DRV_SUPPORT void utils_dfs_init_nol(struct wlan_objmgr_pdev *pdev) @@ -1053,6 +1392,7 @@ void utils_dfs_clear_nol_channels(struct wlan_objmgr_pdev *pdev) } qdf_export_symbol(utils_dfs_clear_nol_channels); +#ifdef CONFIG_CHAN_NUM_API void utils_dfs_reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, uint8_t *ch_list, uint8_t num_ch, @@ -1062,7 +1402,21 @@ void utils_dfs_reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, wlan_reg_update_nol_ch(pdev, ch_list, num_ch, nol_ch); } qdf_export_symbol(utils_dfs_reg_update_nol_ch); +#endif +#ifdef CONFIG_CHAN_FREQ_API +void utils_dfs_reg_update_nol_chan_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *freq_list, + uint8_t num_chan, + bool nol_chan) +{ + wlan_reg_update_nol_ch_for_freq(pdev, freq_list, num_chan, nol_chan); +} + +qdf_export_symbol(utils_dfs_reg_update_nol_chan_for_freq); +#endif + +#ifdef CONFIG_CHAN_NUM_API void utils_dfs_reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, uint8_t *ch_list, uint8_t num_ch, @@ -1070,6 +1424,19 @@ void utils_dfs_reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, { wlan_reg_update_nol_history_ch(pdev, ch_list, num_ch, nol_history_ch); } +#endif + +#ifdef CONFIG_CHAN_FREQ_API +void +utils_dfs_reg_update_nol_history_chan_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *freq_list, + uint8_t num_chan, + bool nol_history_chan) +{ + wlan_reg_update_nol_history_ch_for_freq(pdev, freq_list, num_chan, + nol_history_chan); +} +#endif uint8_t utils_dfs_freq_to_chan(uint32_t freq) { @@ -1112,6 +1479,7 @@ uint32_t utils_dfs_chan_to_freq(uint8_t chan) qdf_export_symbol(utils_dfs_chan_to_freq); #ifdef QCA_MCL_DFS_SUPPORT +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS utils_dfs_mark_leaking_ch(struct wlan_objmgr_pdev *pdev, enum phy_ch_width ch_width, uint8_t temp_ch_lst_sz, @@ -1130,6 +1498,27 @@ QDF_STATUS utils_dfs_mark_leaking_ch(struct wlan_objmgr_pdev *pdev, qdf_export_symbol(utils_dfs_mark_leaking_ch); #endif +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS utils_dfs_mark_leaking_chan_for_freq(struct wlan_objmgr_pdev *pdev, + enum phy_ch_width ch_width, + uint8_t temp_chan_lst_sz, + uint16_t *temp_freq_lst) +{ + struct wlan_dfs *dfs = NULL; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs"); + return QDF_STATUS_E_FAILURE; + } + + return dfs_mark_leaking_chan_for_freq(dfs, ch_width, temp_chan_lst_sz, + temp_freq_lst); +} +qdf_export_symbol(utils_dfs_mark_leaking_chan_for_freq); +#endif +#endif + int utils_get_dfsdomain(struct wlan_objmgr_pdev *pdev) { enum dfs_reg dfsdomain; @@ -1197,6 +1586,7 @@ QDF_STATUS utils_dfs_get_disable_radar_marking(struct wlan_objmgr_pdev *pdev, } qdf_export_symbol(utils_dfs_get_disable_radar_marking); +#endif bool utils_is_dfs_cfreq2_ch(struct wlan_objmgr_pdev *pdev) { @@ -1210,7 +1600,6 @@ bool utils_is_dfs_cfreq2_ch(struct wlan_objmgr_pdev *pdev) } qdf_export_symbol(utils_is_dfs_cfreq2_ch); -#endif void utils_dfs_deliver_event(struct wlan_objmgr_pdev *pdev, uint16_t freq, enum WLAN_DFS_EVENTS event) @@ -1218,3 +1607,19 @@ void utils_dfs_deliver_event(struct wlan_objmgr_pdev *pdev, uint16_t freq, if (global_dfs_to_mlme.mlme_dfs_deliver_event) global_dfs_to_mlme.mlme_dfs_deliver_event(pdev, freq, event); } + +void utils_dfs_reset_dfs_prevchan(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + if (!tgt_dfs_is_pdev_5ghz(pdev)) + return; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is null"); + return; + } + + dfs_reset_dfs_prevchan(dfs); +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/drivers/staging/qca-wifi-host-cmn/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index bb83c9f385f3df48ba489b3c7139983736ec2d51..2f2b0150505d022e57086255191fa19efe64ff58 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 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 @@ -20,7 +20,6 @@ #ifndef _WLAN_LMAC_IF_DEF_H_ #define _WLAN_LMAC_IF_DEF_H_ -#include #include "qdf_status.h" #include "wlan_objmgr_cmn.h" #ifdef DFS_COMPONENT_ENABLE @@ -80,10 +79,8 @@ struct dbr_module_config; #include #endif /* QCA_SUPPORT_CP_STATS */ -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE #include #include -#endif /* CMN_VDEV_MGR_TGT_IF_ENABLE */ #ifdef QCA_SUPPORT_CP_STATS /** @@ -182,18 +179,12 @@ struct wlan_lmac_if_ftm_tx_ops { uint8_t *buf, uint32_t len, uint8_t mac_id); }; - +enum wlan_mlme_cfg_id; /** * struct wlan_lmac_if_mlme_tx_ops - south bound tx function pointers for mlme - * @scan_sta_power_events: function to handle STA power events - * @scan_connection_lost: function to get scan connection lost - * @scan_end: function to end scan * @get_wifi_iface_id: function to get wifi interface id * @vdev_mlme_attach: function to register events * @vdev_mlme_detach: function to unregister events - * @vdev_mgr_rsp_timer_init: function to initialize vdev response timer - * @vdev_mgr_rsp_timer_mod: function to timer_mod vdev response timer - * @vdev_mgr_rsp_timer_stop: function to stop vdev response timer * @vdev_create_send: function to send vdev create * @vdev_start_send: function to send vdev start * @vdev_up_send: function to send vdev up @@ -201,6 +192,7 @@ struct wlan_lmac_if_ftm_tx_ops { * @vdev_stop_send: function to send vdev stop * @vdev_down_send: function to send vdev down * @vdev_set_param_send: function to send vdev parameter + * @vdev_set_tx_rx_decap_type: function to send vdev tx rx cap/decap type * @vdev_set_nac_rssi_send: function to send nac rssi * @vdev_set_neighbour_rx_cmd_send: function to send vdev neighbour rx cmd * @vdev_sifs_trigger_send: function to send vdev sifs trigger @@ -212,28 +204,19 @@ struct wlan_lmac_if_ftm_tx_ops { * @beacon_tmpl_send: function to send beacon template * @vdev_bcn_miss_offload_send: function to send beacon miss offload * @vdev_sta_ps_param_send: function to sent STA power save config - * @target_is_pre_lithium: function to get target type status + * @peer_delete_all_send: function to send vdev delete all peer request + * @psoc_vdev_rsp_timer_init: function to initialize psoc vdev response timer + * @psoc_vdev_rsp_timer_deinit: function to deinitialize psoc vdev rsp timer + * @psoc_vdev_rsp_timer_inuse: function to determine whether the vdev rsp + * timer is inuse or not + * @psoc_vdev_rsp_timer_mod: function to modify the time of vdev rsp timer + * @psoc_wake_lock_init: Initialize psoc wake lock for vdev response timer + * @psoc_wake_lock_deinit: De-Initialize psoc wake lock for vdev response timer */ struct wlan_lmac_if_mlme_tx_ops { - void (*scan_sta_power_events)(struct wlan_objmgr_pdev *pdev, - int event_type, int event_status); - void (*scan_connection_lost)(struct wlan_objmgr_pdev *pdev); - void (*scan_end)(struct wlan_objmgr_pdev *pdev); uint32_t (*get_wifi_iface_id) (struct wlan_objmgr_pdev *pdev); QDF_STATUS (*vdev_mlme_attach)(struct wlan_objmgr_psoc *psoc); QDF_STATUS (*vdev_mlme_detach)(struct wlan_objmgr_psoc *psoc); -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE - QDF_STATUS (*vdev_mgr_rsp_timer_init)( - struct wlan_objmgr_vdev *vdev, - qdf_timer_t *rsp_timer); - QDF_STATUS (*vdev_mgr_rsp_timer_mod)( - struct wlan_objmgr_vdev *vdev, - struct vdev_response_timer *vdev_rsp, - int mseconds); - QDF_STATUS (*vdev_mgr_rsp_timer_stop)( - struct wlan_objmgr_vdev *vdev, - struct vdev_response_timer *vdev_rsp, - uint8_t clear_bit); QDF_STATUS (*vdev_create_send)(struct wlan_objmgr_vdev *vdev, struct vdev_create_params *param); QDF_STATUS (*vdev_start_send)(struct wlan_objmgr_vdev *vdev, @@ -248,6 +231,9 @@ struct wlan_lmac_if_mlme_tx_ops { struct vdev_down_params *param); QDF_STATUS (*vdev_set_param_send)(struct wlan_objmgr_vdev *vdev, struct vdev_set_params *param); + QDF_STATUS (*vdev_set_tx_rx_decap_type)(struct wlan_objmgr_vdev *vdev, + enum wlan_mlme_cfg_id param_id, + uint32_t value); QDF_STATUS (*vdev_set_nac_rssi_send)( struct wlan_objmgr_vdev *vdev, struct vdev_scan_nac_rssi_params *param); @@ -274,10 +260,37 @@ struct wlan_lmac_if_mlme_tx_ops { struct beacon_params *param); QDF_STATUS (*beacon_tmpl_send)(struct wlan_objmgr_vdev *vdev, struct beacon_tmpl_params *param); +#if defined(WLAN_SUPPORT_FILS) || defined(CONFIG_BAND_6GHZ) + QDF_STATUS (*vdev_fils_enable_send)(struct wlan_objmgr_vdev *vdev, + struct config_fils_params *param); +#endif QDF_STATUS (*vdev_bcn_miss_offload_send)(struct wlan_objmgr_vdev *vdev); QDF_STATUS (*vdev_sta_ps_param_send)(struct wlan_objmgr_vdev *vdev, struct sta_ps_params *param); -#endif + QDF_STATUS (*peer_delete_all_send)( + struct wlan_objmgr_vdev *vdev, + struct peer_delete_all_params *param); + QDF_STATUS (*psoc_vdev_rsp_timer_init)( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); + void (*psoc_vdev_rsp_timer_deinit)( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); + QDF_STATUS (*psoc_vdev_rsp_timer_inuse)( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); + QDF_STATUS (*psoc_vdev_rsp_timer_mod)( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, + int mseconds); + void (*psoc_wake_lock_init)( + struct wlan_objmgr_psoc *psoc); + void (*psoc_wake_lock_deinit)( + struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*vdev_mgr_rsp_timer_stop)( + struct wlan_objmgr_psoc *psoc, + struct vdev_response_timer *vdev_rsp, + enum wlan_vdev_mgr_tgt_if_rsp_bit clear_bit); }; /** @@ -427,12 +440,15 @@ struct wlan_lmac_if_atf_tx_ops { * @fd_vdev_config_fils: Enable and configure FILS Discovery * @fd_register_event_handler: Register swfda WMI event handler * @fd_unregister_event_handler: Un-register swfda WMI event handler + * @fd_offload_tmpl_send: Send FD template to FW */ struct wlan_lmac_if_fd_tx_ops { QDF_STATUS (*fd_vdev_config_fils)(struct wlan_objmgr_vdev *vdev, uint32_t fd_period); void (*fd_register_event_handler)(struct wlan_objmgr_psoc *psoc); void (*fd_unregister_event_handler)(struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*fd_offload_tmpl_send)(struct wlan_objmgr_pdev *pdev, + struct fils_discovery_tmpl_params *fd_tmpl_param); }; #endif @@ -475,6 +491,14 @@ struct wlan_lmac_if_sa_api_tx_ops { * @cfr_enable_cfr_timer: Function to enable CFR timer * @cfr_start_capture: Function to start CFR capture * @cfr_stop_capture: Function to stop CFR capture + * @cfr_config_rcc: Function to set the Repetitive channel capture params + * @cfr_start_lut_timer: Function to start timer to flush aged-out LUT entries + * @cfr_stop_lut_timer: Function to stop timer to flush aged-out LUT entries + * @cfr_default_ta_ra_cfg: Function to configure default values for TA_RA mode + * @cfr_dump_lut_enh: Function to dump LUT entries + * @cfr_rx_tlv_process: Function to process PPDU status TLVs + * @cfr_update_global_cfg: Function to update the global config for + * a successful commit session. */ struct wlan_lmac_if_cfr_tx_ops { int (*cfr_init_pdev)(struct wlan_objmgr_psoc *psoc, @@ -488,6 +512,19 @@ struct wlan_lmac_if_cfr_tx_ops { struct cfr_capture_params *params); int (*cfr_stop_capture)(struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_peer *peer); +#ifdef WLAN_ENH_CFR_ENABLE + QDF_STATUS (*cfr_config_rcc)(struct wlan_objmgr_pdev *pdev, + struct cfr_rcc_param *params); + void (*cfr_start_lut_timer)(struct wlan_objmgr_pdev *pdev); + void (*cfr_stop_lut_timer)(struct wlan_objmgr_pdev *pdev); + void (*cfr_default_ta_ra_cfg)(struct cfr_rcc_param *params, + bool allvalid, uint16_t reset_cfg); + void (*cfr_dump_lut_enh)(struct wlan_objmgr_pdev *pdev); + void (*cfr_rx_tlv_process)(struct wlan_objmgr_pdev *pdev, void *nbuf); + void (*cfr_update_global_cfg)(struct wlan_objmgr_pdev *pdev); + QDF_STATUS (*cfr_subscribe_ppdu_desc)(struct wlan_objmgr_pdev *pdev, + bool is_subscribe); +#endif }; #endif /* WLAN_CFR_ENABLE */ @@ -517,6 +554,12 @@ struct wmi_spectral_cmd_ops; * @sptrlto_use_nl_bcast: Get whether to use Netlink broadcast/unicast * @sptrlto_deregister_netlink_cb: De-register Spectral Netlink callbacks * @sptrlto_process_spectral_report: Process spectral report + * @sptrlto_set_dma_debug: Set DMA debug for Spectral + * @sptrlto_direct_dma_support: Whether Direct-DMA is supported on this radio + * @sptrlto_check_and_do_dbr_ring_debug: Start/Stop Spectral ring debug based + * on the previous state + * @sptrlto_check_and_do_dbr_buff_debug: Start/Stop Spectral buffer debug based + * on the previous state **/ struct wlan_lmac_if_sptrl_tx_ops { void *(*sptrlto_pdev_spectral_init)(struct wlan_objmgr_pdev *pdev); @@ -537,7 +580,8 @@ struct wlan_lmac_if_sptrl_tx_ops { enum spectral_cp_error_code *err); QDF_STATUS (*sptrlto_stop_spectral_scan) (struct wlan_objmgr_pdev *pdev, - const enum spectral_scan_mode smode); + const enum spectral_scan_mode smode, + enum spectral_cp_error_code *err); bool (*sptrlto_is_spectral_active)(struct wlan_objmgr_pdev *pdev, const enum spectral_scan_mode smode); bool (*sptrlto_is_spectral_enabled)(struct wlan_objmgr_pdev *pdev, @@ -562,6 +606,16 @@ struct wlan_lmac_if_sptrl_tx_ops { int (*sptrlto_process_spectral_report)( struct wlan_objmgr_pdev *pdev, void *payload); + QDF_STATUS (*sptrlto_set_dma_debug)( + struct wlan_objmgr_pdev *pdev, + enum spectral_dma_debug dma_debug_type, + bool dma_debug_enable); + bool (*sptrlto_direct_dma_support)(struct wlan_objmgr_pdev *pdev); + QDF_STATUS (*sptrlto_check_and_do_dbr_ring_debug)( + struct wlan_objmgr_pdev *pdev); + QDF_STATUS (*sptrlto_check_and_do_dbr_buff_debug)( + struct wlan_objmgr_pdev *pdev); + }; #endif /* WLAN_CONV_SPECTRAL_ENABLE */ @@ -570,10 +624,17 @@ struct wlan_lmac_if_sptrl_tx_ops { * struct wlan_lmac_if_wifi_pos_tx_ops - structure of firmware tx function * pointers for wifi_pos component * @data_req_tx: function pointer to send wifi_pos req to firmware + * @wifi_pos_register_events: function pointer to register wifi_pos events + * @wifi_pos_deregister_events: function pointer to deregister wifi_pos events + * @wifi_pos_get_vht_ch_width: Function pointer to get max supported bw by FW */ struct wlan_lmac_if_wifi_pos_tx_ops { - QDF_STATUS (*data_req_tx)(struct wlan_objmgr_psoc *psoc, + QDF_STATUS (*data_req_tx)(struct wlan_objmgr_pdev *pdev, struct oem_data_req *req); + QDF_STATUS (*wifi_pos_register_events)(struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*wifi_pos_deregister_events)(struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*wifi_pos_get_vht_ch_width)(struct wlan_objmgr_psoc *psoc, + enum phy_ch_width *ch_width); }; #endif @@ -591,6 +652,10 @@ struct wlan_lmac_if_wifi_pos_tx_ops { * @direct_buf_rx_print_ring_stat: Print ring status per module per pdev * * @direct_buf_rx_get_ring_params: Get ring parameters for module_id + * @direct_buf_rx_start_ring_debug: Start DBR ring debug + * @direct_buf_rx_stop_ring_debug: Stop DBR ring debug + * @direct_buf_rx_start_buffer_poisoning: Start DBR buffer poisoning + * @direct_buf_rx_stop_buffer_poisoning: Stop DBR buffer poisoning */ struct wlan_lmac_if_direct_buf_rx_tx_ops { QDF_STATUS (*direct_buf_rx_module_register)( @@ -611,8 +676,17 @@ struct wlan_lmac_if_direct_buf_rx_tx_ops { (struct wlan_objmgr_pdev *pdev, struct module_ring_params *param, uint8_t module_id, uint8_t srng_id); + QDF_STATUS (*direct_buf_rx_start_ring_debug)( + struct wlan_objmgr_pdev *pdev, uint8_t mod_id, + uint32_t num_ring_debug_entries); + QDF_STATUS (*direct_buf_rx_stop_ring_debug)( + struct wlan_objmgr_pdev *pdev, uint8_t mod_id); + QDF_STATUS (*direct_buf_rx_start_buffer_poisoning)( + struct wlan_objmgr_pdev *pdev, uint8_t mod_id, uint32_t value); + QDF_STATUS (*direct_buf_rx_stop_buffer_poisoning)( + struct wlan_objmgr_pdev *pdev, uint8_t mod_id); }; -#endif +#endif /* DIRECT_BUF_RX_ENABLE */ #ifdef FEATURE_WLAN_TDLS /* fwd declarations for tdls tx ops */ @@ -736,6 +810,7 @@ struct wlan_lmac_if_reg_tx_ops { * @dfs_send_avg_radar_params_to_fw: Send average radar parameters to FW. * @dfs_send_usenol_pdev_param: Send usenol pdev param to FW. * @dfs_send_subchan_marking_pdev_param: Send subchan marking pdev param to FW. + * @dfs_check_mode_switch_state: Find if HW mode switch is in progress. */ struct wlan_lmac_if_dfs_tx_ops { @@ -766,8 +841,9 @@ struct wlan_lmac_if_dfs_tx_ops { QDF_STATUS (*dfs_process_emulate_bang_radar_cmd)( struct wlan_objmgr_pdev *pdev, struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test); - QDF_STATUS (*dfs_agile_ch_cfg_cmd)(struct wlan_objmgr_pdev *pdev, - uint8_t *ch_freq); + QDF_STATUS (*dfs_agile_ch_cfg_cmd)( + struct wlan_objmgr_pdev *pdev, + struct dfs_agile_cac_params *adfs_params); QDF_STATUS (*dfs_ocac_abort_cmd)(struct wlan_objmgr_pdev *pdev); QDF_STATUS (*dfs_is_pdev_5ghz)(struct wlan_objmgr_pdev *pdev, bool *is_5ghz); @@ -788,6 +864,9 @@ struct wlan_lmac_if_dfs_tx_ops { QDF_STATUS (*dfs_send_subchan_marking_pdev_param)( struct wlan_objmgr_pdev *pdev, bool subchanmark); + QDF_STATUS (*dfs_check_mode_switch_state)( + struct wlan_objmgr_pdev *pdev, + bool *is_hw_mode_switch_in_progress); }; /** @@ -797,6 +876,7 @@ struct wlan_lmac_if_dfs_tx_ops { * @tgt_is_tgt_type_ipq4019: To check IPQ4019 target type. * @tgt_is_tgt_type_qca9984: To check QCA9984 target type. * @tgt_is_tgt_type_qca9888: To check QCA9888 target type. + * @tgt_is_tgt_type_adrastea: To check QCS40X target type. * @tgt_get_tgt_type: Get target type * @tgt_get_tgt_version: Get target version * @tgt_get_tgt_revision: Get target revision @@ -806,6 +886,7 @@ struct wlan_lmac_if_target_tx_ops { bool (*tgt_is_tgt_type_ipq4019)(uint32_t); bool (*tgt_is_tgt_type_qca9984)(uint32_t); bool (*tgt_is_tgt_type_qca9888)(uint32_t); + bool (*tgt_is_tgt_type_adrastea)(uint32_t); uint32_t (*tgt_get_tgt_type)(struct wlan_objmgr_psoc *psoc); uint32_t (*tgt_get_tgt_version)(struct wlan_objmgr_psoc *psoc); uint32_t (*tgt_get_tgt_revision)(struct wlan_objmgr_psoc *psoc); @@ -843,6 +924,36 @@ struct wlan_lmac_if_green_ap_tx_ops { }; #endif +#ifdef FEATURE_COEX +struct coex_config_params; + +/** + * struct wlan_lmac_if_coex_tx_ops - south bound tx function pointers for coex + * @coex_config_send: function pointer to send coex config to fw + */ +struct wlan_lmac_if_coex_tx_ops { + QDF_STATUS (*coex_config_send)(struct wlan_objmgr_pdev *pdev, + struct coex_config_params *param); +}; +#endif + +#ifdef WLAN_FEATURE_GPIO_CFG +struct gpio_config_params; +struct gpio_output_params; + +/** + * struct wlan_lmac_if_gpio_tx_ops - south bound tx function pointers for gpio + * @set_gpio_config: function pointert to send gpio config to fw + * @set_gpio_output: function pointert to send gpio output to fw + */ +struct wlan_lmac_if_gpio_tx_ops { + QDF_STATUS (*set_gpio_config)(struct wlan_objmgr_psoc *psoc, + struct gpio_config_params *param); + QDF_STATUS (*set_gpio_output)(struct wlan_objmgr_psoc *psoc, + struct gpio_output_params *param); +}; +#endif + /** * struct wlan_lmac_if_tx_ops - south bound tx function pointers * @mgmt_txrx_tx_ops: mgmt txrx tx ops @@ -850,9 +961,11 @@ struct wlan_lmac_if_green_ap_tx_ops { * @dfs_tx_ops: dfs tx ops. * @green_ap_tx_ops: green_ap tx_ops * @cp_stats_tx_ops: cp stats tx_ops + * @coex_ops: coex tx_ops + * @gpio_ops: gpio tx_ops * * Callback function tabled to be registered with umac. - * umac will use the functional table to send events/frames to lmac/wmi + * umac will use the functional table to send events/frames to wmi */ struct wlan_lmac_if_tx_ops { @@ -921,6 +1034,14 @@ struct wlan_lmac_if_tx_ops { #endif struct wlan_lmac_if_ftm_tx_ops ftm_tx_ops; + +#ifdef FEATURE_COEX + struct wlan_lmac_if_coex_tx_ops coex_ops; +#endif + +#ifdef WLAN_FEATURE_GPIO_CFG + struct wlan_lmac_if_gpio_tx_ops gpio_ops; +#endif }; /** @@ -970,8 +1091,8 @@ struct wlan_lmac_if_reg_rx_ops { enum dfs_reg *dfs_reg); QDF_STATUS (*reg_ch_avoid_event_handler)(struct wlan_objmgr_psoc *psoc, struct ch_avoid_ind_type *ch_avoid_ind); - uint32_t (*reg_freq_to_chan)(struct wlan_objmgr_pdev *pdev, - uint32_t freq); + uint8_t (*reg_freq_to_chan)(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); QDF_STATUS (*reg_set_chan_144)(struct wlan_objmgr_pdev *pdev, bool enable_ch_144); bool (*reg_get_chan_144)(struct wlan_objmgr_pdev *pdev); @@ -981,7 +1102,13 @@ struct wlan_lmac_if_reg_rx_ops { struct cur_regdmn_info *cur_regdmn); QDF_STATUS (*reg_enable_dfs_channels)(struct wlan_objmgr_pdev *pdev, bool dfs_enable); + QDF_STATUS (*reg_modify_pdev_chan_range)(struct + wlan_objmgr_pdev *pdev); + QDF_STATUS (*reg_disable_chan_coex)(struct wlan_objmgr_pdev *pdev, + uint8_t unii_5g_bitmap); bool (*reg_ignore_fw_reg_offload_ind)(struct wlan_objmgr_psoc *psoc); + QDF_STATUS (*reg_get_unii_5g_bitmap)(struct wlan_objmgr_pdev *pdev, + uint8_t *bitmap); }; #ifdef CONVERGED_P2P_ENABLE @@ -1133,6 +1260,7 @@ struct wlan_lmac_if_atf_rx_ops { * @fd_free: Free FD frame buffer * @fd_get_valid_fd_period: Get valid FD period * @fd_swfda_handler: SWFDA event handler + * @fd_offload: Offload FD frame */ struct wlan_lmac_if_fd_rx_ops { uint8_t (*fd_is_fils_enable)(struct wlan_objmgr_vdev *vdev); @@ -1142,6 +1270,8 @@ struct wlan_lmac_if_fd_rx_ops { uint32_t (*fd_get_valid_fd_period)(struct wlan_objmgr_vdev *vdev, uint8_t *is_modified); QDF_STATUS (*fd_swfda_handler)(struct wlan_objmgr_vdev *vdev); + QDF_STATUS (*fd_offload)(struct wlan_objmgr_vdev *vdev, + uint32_t vdev_id); }; #endif @@ -1199,11 +1329,14 @@ struct wlan_lmac_if_cfr_rx_ops { * struct wlan_lmac_if_sptrl_rx_ops - Spectral south bound Rx operations * * @sptrlro_get_target_handle: Get Spectral handle for target/LMAC private data + * @sptrlro_vdev_get_chan_freq_seg2: Get secondary 80 center frequency * @sptrlro_spectral_is_feature_disabled: Check if spectral feature is disabled */ struct wlan_lmac_if_sptrl_rx_ops { void * (*sptrlro_get_target_handle)(struct wlan_objmgr_pdev *pdev); int16_t (*sptrlro_vdev_get_chan_freq)(struct wlan_objmgr_vdev *vdev); + int16_t (*sptrlro_vdev_get_chan_freq_seg2) + (struct wlan_objmgr_vdev *vdev); enum phy_ch_width (*sptrlro_vdev_get_ch_width)( struct wlan_objmgr_vdev *vdev); int (*sptrlro_vdev_get_sec20chan_freq_mhz)( @@ -1240,7 +1373,8 @@ struct wlan_lmac_if_wifi_pos_rx_ops { * @dfs_cancel_precac_timer: Cancel the precac timer. * @dfs_override_precac_timeout: Override the default precac timeout. * @dfs_set_precac_enable: Set precac enable flag. - * @dfs_get_precac_enable: Get precac enable flag. + * @dfs_get_legacy_precac_enable: Get the precac enable flag for + * partial offload (legacy) chipsets. * @dfs_set_precac_intermediate_chan: Set intermediate channel for precac. * @dfs_get_precac_intermediate_chan: Get intermediate channel for precac. * @dfs_precac_preferred_chan: Configure preferred channel during @@ -1253,8 +1387,10 @@ struct wlan_lmac_if_wifi_pos_rx_ops { * @dfs_dfs_cac_complete_ind: Process cac complete indication. * @dfs_agile_precac_start: Initiate Agile PreCAC run. * @dfs_set_agile_precac_state: Set agile precac state. + * @dfs_reset_adfs_config: Reset agile dfs variables. * @dfs_dfs_ocac_complete_ind: Process offchan cac complete indication. * @dfs_stop: Clear dfs timers. + * @dfs_reinit_timers: Reinitialize DFS timers. * @dfs_enable_stadfs: Enable/Disable STADFS capability. * @dfs_is_stadfs_enabled: Get STADFS capability value. * @dfs_process_phyerr_filter_offload:Process radar event. @@ -1267,6 +1403,17 @@ struct wlan_lmac_if_wifi_pos_rx_ops { * timeout. * @dfs_reset_spoof_test: Checks if radar detection is enabled. * @dfs_is_disable_radar_marking_set: Check if dis_radar_marking param is set. + * @dfs_allow_hw_pulses: Set or unset dfs_allow_hw_pulses which + * allow or disallow HW pulses. + * @dfs_is_hw_pulses_allowed: Check if HW pulses are allowed or not. + * @dfs_set_fw_adfs_support: Set the agile DFS FW support in DFS. + * @dfs_reset_dfs_prevchan: Reset DFS previous channel structure. + * @dfs_init_tmp_psoc_nol: Init temporary PSOC NOL structure. + * @dfs_deinit_tmp_psoc_nol: Deinit temporary PSOC NOL structure. + * @dfs_save_dfs_nol_in_psoc: Copy DFS NOL data to the PSOC copy. + * @dfs_reinit_nol_from_psoc_copy: Reinit DFS NOL from the PSOC NOL copy. + * @dfs_reinit_precac_lists: Reinit precac lists from other pdev. + * @dfs_complete_deferred_tasks: Process mode switch completion in DFS. */ struct wlan_lmac_if_dfs_rx_ops { QDF_STATUS (*dfs_get_radars)(struct wlan_objmgr_pdev *pdev); @@ -1295,6 +1442,7 @@ struct wlan_lmac_if_dfs_rx_ops { QDF_STATUS (*dfs_is_precac_timer_running)(struct wlan_objmgr_pdev *pdev, bool *is_precac_timer_running ); +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS (*dfs_find_vht80_chan_for_precac)(struct wlan_objmgr_pdev *pdev, uint32_t chan_mode, @@ -1304,9 +1452,23 @@ struct wlan_lmac_if_dfs_rx_ops { uint32_t *phy_mode, bool *dfs_set_cfreq2, bool *set_agile); +#endif +#ifdef CONFIG_CHAN_FREQ_API + QDF_STATUS + (*dfs_find_vht80_chan_for_precac_for_freq)(struct wlan_objmgr_pdev + *pdev, + uint32_t chan_mode, + uint16_t ch_freq_seg1, + uint32_t *cfreq1, + uint32_t *cfreq2, + uint32_t *phy_mode, + bool *dfs_set_cfreq2, + bool *set_agile); +#endif QDF_STATUS (*dfs_agile_precac_start)(struct wlan_objmgr_pdev *pdev); QDF_STATUS (*dfs_set_agile_precac_state)(struct wlan_objmgr_pdev *pdev, int agile_precac_state); + QDF_STATUS (*dfs_reset_adfs_config)(struct wlan_objmgr_psoc *psoc); QDF_STATUS (*dfs_dfs_ocac_complete_ind)(struct wlan_objmgr_pdev *pdev, struct vdev_adfs_complete_status *ocac_st); @@ -1317,22 +1479,43 @@ struct wlan_lmac_if_dfs_rx_ops { int precac_timeout); QDF_STATUS (*dfs_set_precac_enable)(struct wlan_objmgr_pdev *pdev, uint32_t value); - QDF_STATUS (*dfs_get_precac_enable)(struct wlan_objmgr_pdev *pdev, - int *buff); + QDF_STATUS + (*dfs_get_legacy_precac_enable)(struct wlan_objmgr_pdev *pdev, + bool *buff); + QDF_STATUS (*dfs_get_agile_precac_enable)(struct wlan_objmgr_pdev *pdev, + bool *buff); #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT QDF_STATUS (*dfs_set_precac_intermediate_chan)(struct wlan_objmgr_pdev *pdev, uint32_t value); QDF_STATUS (*dfs_get_precac_intermediate_chan)(struct wlan_objmgr_pdev *pdev, int *buff); +#ifdef CONFIG_CHAN_NUM_API bool (*dfs_decide_precac_preferred_chan)(struct wlan_objmgr_pdev *pdev, uint8_t *pref_chan, enum wlan_phymode mode); +#endif +#ifdef CONFIG_CHAN_FREQ_API + bool (*dfs_decide_precac_preferred_chan_for_freq)(struct + wlan_objmgr_pdev *pdev, + uint16_t *pref_chan_freq, + enum wlan_phymode mode); +#endif + +#ifdef CONFIG_CHAN_NUM_API enum precac_chan_state (*dfs_get_precac_chan_state)(struct wlan_objmgr_pdev *pdev, uint8_t precac_chan); +#endif + +#ifdef CONFIG_CHAN_FREQ_API + enum precac_chan_state (*dfs_get_precac_chan_state_for_freq)(struct + wlan_objmgr_pdev *pdev, + uint16_t pcac_freq); +#endif #endif QDF_STATUS (*dfs_get_override_precac_timeout)( struct wlan_objmgr_pdev *pdev, int *precac_timeout); +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS (*dfs_set_current_channel)(struct wlan_objmgr_pdev *pdev, uint16_t ic_freq, uint64_t ic_flags, @@ -1340,6 +1523,19 @@ struct wlan_lmac_if_dfs_rx_ops { uint8_t ic_ieee, uint8_t ic_vhtop_ch_freq_seg1, uint8_t ic_vhtop_ch_freq_seg2); +#endif +#ifdef CONFIG_CHAN_FREQ_API + QDF_STATUS + (*dfs_set_current_channel_for_freq)(struct wlan_objmgr_pdev *pdev, + uint16_t ic_freq, + uint64_t ic_flags, + uint16_t ic_flagext, + uint8_t ic_ieee, + uint8_t ic_vhtop_ch_freq_seg1, + uint8_t ic_vhtop_ch_freq_seg2, + uint16_t dfs_ch_mhz_freq_seg1, + uint16_t dfs_ch_mhz_freq_seg2); +#endif #ifdef DFS_COMPONENT_ENABLE QDF_STATUS (*dfs_process_radar_ind)(struct wlan_objmgr_pdev *pdev, struct radar_found_info *radar_found); @@ -1347,6 +1543,7 @@ struct wlan_lmac_if_dfs_rx_ops { uint32_t vdev_id); #endif QDF_STATUS (*dfs_stop)(struct wlan_objmgr_pdev *pdev); + QDF_STATUS (*dfs_reinit_timers)(struct wlan_objmgr_pdev *pdev); void (*dfs_enable_stadfs)(struct wlan_objmgr_pdev *pdev, bool val); bool (*dfs_is_stadfs_enabled)(struct wlan_objmgr_pdev *pdev); QDF_STATUS (*dfs_process_phyerr_filter_offload)( @@ -1377,105 +1574,45 @@ struct wlan_lmac_if_dfs_rx_ops { bool value); QDF_STATUS (*dfs_is_bw_reduction_needed)(struct wlan_objmgr_pdev *pdev, bool *bw_reduce); + void (*dfs_allow_hw_pulses)(struct wlan_objmgr_pdev *pdev, + bool allow_hw_pulses); + bool (*dfs_is_hw_pulses_allowed)(struct wlan_objmgr_pdev *pdev); + void (*dfs_set_fw_adfs_support)(struct wlan_objmgr_pdev *pdev, + bool fw_adfs_support_160, + bool fw_adfs_support_non_160); + void (*dfs_reset_dfs_prevchan)(struct wlan_objmgr_pdev *pdev); + void (*dfs_init_tmp_psoc_nol)(struct wlan_objmgr_pdev *pdev, + uint8_t num_radios); + void (*dfs_deinit_tmp_psoc_nol)(struct wlan_objmgr_pdev *pdev); + void (*dfs_save_dfs_nol_in_psoc)(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id, + uint16_t low_5ghz_freq, + uint16_t high_5ghz_freq); + void (*dfs_reinit_nol_from_psoc_copy)(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id); + void (*dfs_reinit_precac_lists)(struct wlan_objmgr_pdev *src_pdev, + struct wlan_objmgr_pdev *dest_pdev, + uint16_t low_5g_freq, + uint16_t high_5g_freq); + void (*dfs_complete_deferred_tasks)(struct wlan_objmgr_pdev *pdev); }; /** * struct wlan_lmac_if_mlme_rx_ops: Function pointer to call MLME functions - * @wlan_mlme_scan_start: function to start scan - * @wlan_mlme_register_pm_event_handler: function to register pm event - * @wlan_mlme_unregister_pm_event_handler: function unregister for pm event - * @wlan_mlme_register_vdev_event_handler: function to register for vdev event - * @wlan_mlme_unregister_vdev_event_handler: functiont o unregister for vdev + * @vdev_mgr_start_response: function to handle start response + * @vdev_mgr_stop_response: function to handle stop response + * @vdev_mgr_delete_response: function to handle delete response + * @vdev_mgr_offload_bcn_tx_status_event_handle: function to handle offload + * beacon tx + * @vdev_mgr_tbttoffset_update_handle: function to handle tbtt offset event + * @vdev_mgr_peer_delete_all_response: function to handle vdev delete all peer * event - * @wlan_mlme_send_probe_request: function to send probe - * @wlan_mlme_resmgr_request_bsschan: function to request bsschan - * @wlan_mlme_resmgr_request_offchan: function to request offchan - * @wlan_mlme_resmgr_active: function to check resmgr status - * @wlan_mlme_get_cw_inter_found: function to get cw interference - * @wlan_mlme_set_home_channel: function to set home channel - * @wlan_mlme_set_channel: function to set channel - * @wlan_mlme_start_record_stats: functiont to start record stats - * @wlan_mlme_end_record_stats: function to end recording of stats - * @wlan_mlme_get_enh_rpt_ind: function to get enhanced repeater index - * @wlan_mlme_pause: function to pause mlme - * @wlan_mlme_unpause: function to unpause mlme - * @wlan_mlme_vdev_pause_control: function to set vdev pause control - * @wlan_mlme_sta_power_pause: function to set sta power pause - * @wlan_mlme_sta_power_unpause: function to set sta power pause - * @wlan_mlme_set_vdev_sleep: function to sleep vdev sleep - * @wlan_mlme_set_vdev_wakeup: function to set vdev wakeup - * @wlan_mlme_get_traffic_indication_timestamp: function to get tid timestamp - * @wlan_mlme_get_acs_in_progress: function to get ACS progress - * @wlan_mlme_end_scan: function to end scan - * @mlme_get_rsp_timer: function to get vdev mgr response timer - * @mlme_response_timeout_cb: function to trigger on response time expiry - * @mlme_start_response: function to handle vdev start response - * @mlme_stop_response: function to handle vdev stop response - * @mlme_offload_bcn_tx_status_event_handle: function to get offload beacon tx - * status - * @mlme_tbttoffset_update_handle: function to handle tbttoffset event + * @psoc_get_wakelock_info: function to get wakelock info + * @psoc_get_vdev_response_timer_info: function to get vdev response timer + * structure for a specific vdev id + * @vdev_mgr_multi_vdev_restart_resp: function to handle mvr response */ struct wlan_lmac_if_mlme_rx_ops { - - void (*wlan_mlme_scan_start)(struct wlan_objmgr_pdev *pdev); - void (*wlan_mlme_register_pm_event_handler)( - struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id); - void (*wlan_mlme_unregister_pm_event_handler)( - struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id); - QDF_STATUS (*wlan_mlme_register_vdev_event_handler)( - struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id); - QDF_STATUS (*wlan_mlme_unregister_vdev_event_handler)( - struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id); - int (*wlan_mlme_send_probe_request)(struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id, - u_int8_t *destination, - u_int8_t *bssid, - u_int8_t *ssid, - u_int32_t ssidlen, - u_int8_t *ie, - size_t len); - int (*wlan_mlme_resmgr_request_bsschan)(struct wlan_objmgr_pdev *pdev); - int (*wlan_mlme_resmgr_request_offchan)(struct wlan_objmgr_pdev *pdev, - u_int32_t freq, - u_int32_t flags, - u_int32_t estimated_offchannel_time); - int (*wlan_mlme_resmgr_active)(struct wlan_objmgr_pdev *pdev); - int (*wlan_mlme_get_cw_inter_found)(struct wlan_objmgr_pdev *pdev); - int (*wlan_mlme_set_home_channel)(struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id); - int (*wlan_mlme_set_channel)(struct wlan_objmgr_pdev *pdev, - u_int32_t freq, - u_int32_t flags); - void (*wlan_mlme_start_record_stats)(struct wlan_objmgr_pdev *pdev); - void (*wlan_mlme_end_record_stats)(struct wlan_objmgr_pdev *pdev); - int (*wlan_mlme_get_enh_rpt_ind)(struct wlan_objmgr_pdev *pdev); - int (*wlan_mlme_pause)(struct wlan_objmgr_pdev *pdev); - void (*wlan_mlme_unpause)(struct wlan_objmgr_pdev *pdev); - int (*wlan_mlme_vdev_pause_control)(struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id); - int (*wlan_mlme_sta_power_pause)( - struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id, - u_int32_t timeout); - int (*wlan_mlme_sta_power_unpause)(struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id); - int (*wlan_mlme_set_vdev_sleep)(struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id); - int (*wlan_mlme_set_vdev_wakeup)(struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id); - qdf_time_t (*wlan_mlme_get_traffic_indication_timestamp)( - struct wlan_objmgr_pdev *pdev); - int (*wlan_mlme_get_acs_in_progress)(struct wlan_objmgr_pdev *pdev, - uint8_t vdev_id); - void (*wlan_mlme_end_scan)(struct wlan_objmgr_pdev *pdev); - -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE - struct vdev_response_timer *(*vdev_mgr_get_response_timer_info)( - struct wlan_objmgr_vdev *vdev); QDF_STATUS (*vdev_mgr_start_response)( struct wlan_objmgr_psoc *psoc, struct vdev_start_response *rsp); @@ -1491,7 +1628,19 @@ struct wlan_lmac_if_mlme_rx_ops { QDF_STATUS (*vdev_mgr_tbttoffset_update_handle)( uint32_t num_vdevs, bool is_ext); + QDF_STATUS (*vdev_mgr_peer_delete_all_response)( + struct wlan_objmgr_psoc *psoc, + struct peer_delete_all_response *rsp); + QDF_STATUS (*vdev_mgr_multi_vdev_restart_resp)( + struct wlan_objmgr_psoc *psoc, + struct multi_vdev_restart_resp *rsp); +#ifdef FEATURE_VDEV_RSP_WAKELOCK + struct psoc_mlme_wakelock *(*psoc_get_wakelock_info)( + struct wlan_objmgr_psoc *psoc); #endif + struct vdev_response_timer *(*psoc_get_vdev_response_timer_info)( + struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); }; #ifdef WLAN_SUPPORT_GREEN_AP diff --git a/drivers/staging/qca-wifi-host-cmn/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c b/drivers/staging/qca-wifi-host-cmn/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c index f0ce9d6864ef63b3a651468cea70f9f123d3defd..cd8fdf12a2c70aadf4bd790cea35e480a44f1c34 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -64,15 +64,16 @@ #ifdef QCA_SUPPORT_CP_STATS #include #endif /* QCA_SUPPORT_CP_STATS */ - -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE #include -#endif #ifdef WLAN_CFR_ENABLE #include "wlan_cfr_tgt_api.h" #endif +#ifdef WIFI_POS_CONVERGED +#include "wifi_pos_api.h" +#endif + /* Function pointer for OL/WMA specific UMAC tx_ops * registration. */ @@ -80,18 +81,11 @@ QDF_STATUS (*wlan_lmac_if_umac_tx_ops_register) (struct wlan_lmac_if_tx_ops *tx_ops); qdf_export_symbol(wlan_lmac_if_umac_tx_ops_register); -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE static void tgt_vdev_mgr_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) { tgt_vdev_mgr_register_rx_ops(rx_ops); } -#else -static void -tgt_vdev_mgr_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) -{ -} -#endif #ifdef QCA_SUPPORT_CP_STATS /** @@ -188,6 +182,7 @@ wlan_lmac_if_fd_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) fd_rx_ops->fd_free = tgt_fd_free; fd_rx_ops->fd_get_valid_fd_period = tgt_fd_get_valid_fd_period; fd_rx_ops->fd_swfda_handler = tgt_fd_swfda_handler; + fd_rx_ops->fd_offload = tgt_fd_offload; } #else static void @@ -272,7 +267,7 @@ wlan_lmac_if_crypto_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) static void wlan_lmac_if_umac_rx_ops_register_wifi_pos( struct wlan_lmac_if_rx_ops *rx_ops) { - target_if_wifi_pos_register_rx_ops(rx_ops); + wifi_pos_register_rx_ops(rx_ops); } #else static void wlan_lmac_if_umac_rx_ops_register_wifi_pos( @@ -323,8 +318,17 @@ static void wlan_lmac_if_umac_reg_rx_ops_register( rx_ops->reg_rx_ops.reg_enable_dfs_channels = ucfg_reg_enable_dfs_channels; + rx_ops->reg_rx_ops.reg_modify_pdev_chan_range = + wlan_reg_modify_pdev_chan_range; + rx_ops->reg_rx_ops.reg_ignore_fw_reg_offload_ind = tgt_reg_ignore_fw_reg_offload_ind; + + rx_ops->reg_rx_ops.reg_disable_chan_coex = + wlan_reg_disable_chan_coex; + + rx_ops->reg_rx_ops.reg_get_unii_5g_bitmap = + ucfg_reg_get_unii_5g_bitmap; } #ifdef CONVERGED_P2P_ENABLE @@ -353,6 +357,51 @@ static void wlan_lmac_if_umac_rx_ops_register_p2p( } #endif +/* + * register_precac_auto_chan_rx_ops_ieee() - Register auto chan switch rx ops + * for IEEE channel based APIs. + * rx_ops: Pointer to wlan_lmac_if_dfs_rx_ops + */ +#ifdef DFS_COMPONENT_ENABLE +#if defined(WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT) && defined(CONFIG_CHAN_NUM_API) +static inline void +register_precac_auto_chan_rx_ops_ieee(struct wlan_lmac_if_dfs_rx_ops *rx_ops) +{ + if (!rx_ops) + return; + rx_ops->dfs_get_precac_chan_state = ucfg_dfs_get_precac_chan_state; +} +#else +static inline void +register_precac_auto_chan_rx_ops_ieee(struct wlan_lmac_if_dfs_rx_ops *rx_ops) +{ +} +#endif +#endif + +/* + * register_precac_auto_chan_rx_ops_freq() - Register auto chan switch rx ops + * for frequency based channel APIs. + * rx_ops: Pointer to wlan_lmac_if_dfs_rx_ops + */ +#ifdef DFS_COMPONENT_ENABLE +#if defined(WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT) && defined(CONFIG_CHAN_FREQ_API) +static inline void +register_precac_auto_chan_rx_ops_freq(struct wlan_lmac_if_dfs_rx_ops *rx_ops) +{ + if (!rx_ops) + return; + rx_ops->dfs_get_precac_chan_state_for_freq = + ucfg_dfs_get_precac_chan_state_for_freq; +} +#else +static inline void +register_precac_auto_chan_rx_ops_freq(struct wlan_lmac_if_dfs_rx_ops *rx_ops) +{ +} +#endif +#endif + #ifdef DFS_COMPONENT_ENABLE #ifdef WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT static inline void @@ -364,7 +413,6 @@ register_precac_auto_chan_rx_ops(struct wlan_lmac_if_dfs_rx_ops *rx_ops) ucfg_dfs_set_precac_intermediate_chan; rx_ops->dfs_get_precac_intermediate_chan = ucfg_dfs_get_precac_intermediate_chan; - rx_ops->dfs_get_precac_chan_state = ucfg_dfs_get_precac_chan_state; } #else static inline void @@ -373,6 +421,41 @@ register_precac_auto_chan_rx_ops(struct wlan_lmac_if_dfs_rx_ops *rx_ops) } #endif +/* + * register_dfs_rx_ops_for_freq() - Register DFS rx ops for frequency based + * channel APIs. + * rx_ops: Pointer to wlan_lmac_if_dfs_rx_ops. + */ +#ifdef CONFIG_CHAN_FREQ_API +static void register_dfs_rx_ops_for_freq(struct wlan_lmac_if_dfs_rx_ops *rx_ops) +{ + if (!rx_ops) + return; + rx_ops->dfs_find_vht80_chan_for_precac_for_freq = + tgt_dfs_find_vht80_precac_chan_freq; + rx_ops->dfs_set_current_channel_for_freq = + tgt_dfs_set_current_channel_for_freq; +} +#endif + +/* + * register_dfs_rx_ops_for_ieee() - Register DFS rx ops for IEEE channel based + * APIs + * rx_ops: Pointer to wlan_lmac_if_dfs_rx_ops. + */ + +#ifdef CONFIG_CHAN_NUM_API +static void register_dfs_rx_ops_for_ieee(struct wlan_lmac_if_dfs_rx_ops *rx_ops) +{ + if (!rx_ops) + return; + rx_ops->dfs_find_vht80_chan_for_precac = + tgt_dfs_find_vht80_chan_for_precac; + rx_ops->dfs_set_current_channel = + tgt_dfs_set_current_channel; +} +#endif + static QDF_STATUS wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) { @@ -388,25 +471,27 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) dfs_rx_ops->dfs_control = tgt_dfs_control; dfs_rx_ops->dfs_is_precac_timer_running = tgt_dfs_is_precac_timer_running; - dfs_rx_ops->dfs_find_vht80_chan_for_precac = - tgt_dfs_find_vht80_chan_for_precac; dfs_rx_ops->dfs_agile_precac_start = tgt_dfs_agile_precac_start; dfs_rx_ops->dfs_set_agile_precac_state = tgt_dfs_set_agile_precac_state; dfs_rx_ops->dfs_start_precac_timer = utils_dfs_start_precac_timer; dfs_rx_ops->dfs_cancel_precac_timer = utils_dfs_cancel_precac_timer; + dfs_rx_ops->dfs_reset_adfs_config = ucfg_dfs_reset_agile_config; dfs_rx_ops->dfs_override_precac_timeout = ucfg_dfs_override_precac_timeout; dfs_rx_ops->dfs_set_precac_enable = ucfg_dfs_set_precac_enable; - dfs_rx_ops->dfs_get_precac_enable = ucfg_dfs_get_precac_enable; + dfs_rx_ops->dfs_get_legacy_precac_enable = + ucfg_dfs_get_legacy_precac_enable; + dfs_rx_ops->dfs_get_agile_precac_enable = + ucfg_dfs_get_agile_precac_enable; dfs_rx_ops->dfs_get_override_precac_timeout = ucfg_dfs_get_override_precac_timeout; - dfs_rx_ops->dfs_set_current_channel = tgt_dfs_set_current_channel; dfs_rx_ops->dfs_process_radar_ind = tgt_dfs_process_radar_ind; dfs_rx_ops->dfs_dfs_cac_complete_ind = tgt_dfs_cac_complete; dfs_rx_ops->dfs_dfs_ocac_complete_ind = tgt_dfs_ocac_complete; dfs_rx_ops->dfs_stop = tgt_dfs_stop; + dfs_rx_ops->dfs_reinit_timers = ucfg_dfs_reinit_timers; dfs_rx_ops->dfs_enable_stadfs = tgt_dfs_enable_stadfs; dfs_rx_ops->dfs_is_stadfs_enabled = tgt_dfs_is_stadfs_enabled; dfs_rx_ops->dfs_process_phyerr_filter_offload = @@ -430,8 +515,31 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) utils_dfs_bw_reduce; dfs_rx_ops->dfs_is_bw_reduction_needed = utils_dfs_is_bw_reduce; - + dfs_rx_ops->dfs_allow_hw_pulses = + ucfg_dfs_allow_hw_pulses; + dfs_rx_ops->dfs_is_hw_pulses_allowed = + ucfg_dfs_is_hw_pulses_allowed; + dfs_rx_ops->dfs_set_fw_adfs_support = + tgt_dfs_set_fw_adfs_support; + dfs_rx_ops->dfs_reset_dfs_prevchan = + utils_dfs_reset_dfs_prevchan; + dfs_rx_ops->dfs_init_tmp_psoc_nol = + tgt_dfs_init_tmp_psoc_nol; + dfs_rx_ops->dfs_deinit_tmp_psoc_nol = + tgt_dfs_deinit_tmp_psoc_nol; + dfs_rx_ops->dfs_save_dfs_nol_in_psoc = + tgt_dfs_save_dfs_nol_in_psoc; + dfs_rx_ops->dfs_reinit_nol_from_psoc_copy = + tgt_dfs_reinit_nol_from_psoc_copy; + dfs_rx_ops->dfs_reinit_precac_lists = + tgt_dfs_reinit_precac_lists; + dfs_rx_ops->dfs_complete_deferred_tasks = + tgt_dfs_complete_deferred_tasks; register_precac_auto_chan_rx_ops(dfs_rx_ops); + register_precac_auto_chan_rx_ops_ieee(dfs_rx_ops); + register_precac_auto_chan_rx_ops_freq(dfs_rx_ops); + register_dfs_rx_ops_for_freq(dfs_rx_ops); + register_dfs_rx_ops_for_ieee(dfs_rx_ops); return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/umac/green_ap/dispatcher/inc/cfg_green_ap_params.h b/drivers/staging/qca-wifi-host-cmn/umac/green_ap/dispatcher/inc/cfg_green_ap_params.h index 4cbb2491668307b9153609f695e70d75e3221093..410dfb5d4786b4da5347d6225f6116f2c431b874 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/green_ap/dispatcher/inc/cfg_green_ap_params.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/green_ap/dispatcher/inc/cfg_green_ap_params.h @@ -43,7 +43,7 @@ #define CFG_ENABLE_GREEN_AP_FEATURE CFG_INI_BOOL( \ "gEnableGreenAp", \ - MCL_OR_WIN_VALUE(1, 0), \ + PLATFORM_VALUE(1, 0), \ "enable green ap") /* @@ -66,7 +66,7 @@ #define CFG_ENABLE_EGAP_FEATURE CFG_INI_BOOL( \ "gEnableEGAP", \ - MCL_OR_WIN_VALUE(1,0), \ + PLATFORM_VALUE(1, 0), \ "enable e-gap") /* * diff --git a/drivers/staging/qca-wifi-host-cmn/umac/green_ap/dispatcher/src/wlan_green_ap_api.c b/drivers/staging/qca-wifi-host-cmn/umac/green_ap/dispatcher/src/wlan_green_ap_api.c index 70cd45b0b1d728c39628f86849bf65e17cc70555..7fa69dceb56d280913a824c993d1feda89216155 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/green_ap/dispatcher/src/wlan_green_ap_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/green_ap/dispatcher/src/wlan_green_ap_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -156,7 +156,7 @@ static QDF_STATUS wlan_green_ap_pdev_obj_destroy_notification( qdf_spinlock_destroy(&green_ap_ctx->lock); qdf_mem_free(green_ap_ctx); - green_ap_info("green ap deletion successful, pdev: %pK", pdev); + green_ap_info("green ap deletion successful"); return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_mlme_cmn.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_mlme_cmn.h index eee5f244862aeb107a8399a3e89fd048fbce02ac..3991f6aee8275130b7ae7234e0fd50f7362e47b9 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_mlme_cmn.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_mlme_cmn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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 above @@ -20,11 +20,16 @@ #ifndef _WLAN_MLME_CMN_H_ #define _WLAN_MLME_CMN_H_ +#include #include #include /** * struct vdev_mlme_ext_ops - VDEV MLME legacy callbacks structure + * @mlme_psoc_ext_hdl_create: callback to invoke creation of legacy + * psoc object + * @mlme_psoc_ext_hdl_destroy: callback to invoke destroy of legacy + * psoc object * @mlme_pdev_ext_hdl_create: callback to invoke creation of legacy * pdev object * @mlme_pdev_ext_hdl_destroy: callback to invoke destroy of legacy @@ -42,8 +47,14 @@ * command * @mlme_vdev_enqueue_exp_cmd: callback to enqueue exception command * required by serialization + * @mlme_multi_vdev_restart_resp: callback to process multivdev restart + * response */ struct mlme_ext_ops { + QDF_STATUS (*mlme_psoc_ext_hdl_create)( + struct psoc_mlme_obj *psoc_mlme); + QDF_STATUS (*mlme_psoc_ext_hdl_destroy)( + struct psoc_mlme_obj *pdev_mlme); QDF_STATUS (*mlme_pdev_ext_hdl_create)( struct pdev_mlme_obj *pdev_mlme); QDF_STATUS (*mlme_pdev_ext_hdl_destroy)( @@ -63,8 +74,36 @@ struct mlme_ext_ops { QDF_STATUS (*mlme_vdev_enqueue_exp_cmd)( struct vdev_mlme_obj *vdev_mlme, uint8_t cmd_type); + QDF_STATUS (*mlme_vdev_ext_delete_rsp)( + struct wlan_objmgr_psoc *psoc, + struct vdev_delete_response *rsp); + QDF_STATUS (*mlme_multi_vdev_restart_resp)( + struct wlan_objmgr_psoc *psoc, + struct multi_vdev_restart_resp *resp); }; +/** + * mlme_psoc_ops_ext_hdl_create() - Alloc PSOC mlme ext handle + * @psoc_mlme: PSOC MLME comp object + * + * API to allocate PSOC MLME ext handle + * + * Return: SUCCESS on successful allocation + * Else FAILURE + */ +QDF_STATUS mlme_psoc_ops_ext_hdl_create(struct psoc_mlme_obj *psoc_mlme); + +/** + * mlme_psoc_ops_ext_hdl_destroy() - Destroy PSOC mlme ext handle + * @psoc_mlme: PSOC MLME comp object + * + * API to free psoc MLME ext handle + * + * Return: SUCCESS on successful free + * Else FAILURE + */ +QDF_STATUS mlme_psoc_ops_ext_hdl_destroy(struct psoc_mlme_obj *psoc_mlme); + /** * mlme_pdev_ops_ext_hdl_create - Alloc PDEV mlme ext handle * @pdev_mlme_obj: PDEV MLME comp object @@ -182,6 +221,19 @@ QDF_STATUS mlme_vdev_ops_stop_fw_send(struct wlan_objmgr_vdev *vdev); */ QDF_STATUS mlme_vdev_ops_down_fw_send(struct wlan_objmgr_vdev *vdev); +/* + * mlme_vdev_ops_ext_hdl_multivdev_restart_resp() - Handler multivdev restart + * response event + * @psoc: PSOC object manager handle + * @resp: Restart response event + * + * Return: Success on successful handling of the response event, + * Else failure + */ +QDF_STATUS mlme_vdev_ops_ext_hdl_multivdev_restart_resp( + struct wlan_objmgr_psoc *psoc, + struct multi_vdev_restart_resp *resp); + /** * mlme_set_ops_register_cb - Sets ops registration callback * @ops_cb: Function pointer @@ -212,4 +264,17 @@ QDF_STATUS wlan_cmn_mlme_init(void); * FAILURE, if registration fails */ QDF_STATUS wlan_cmn_mlme_deinit(void); + +/** + * mlme_vdev_ops_ext_hdl_delete_rsp - Vdev Delete response ext handler + * @psoc: PSOC object + * @rsp: Vdev delete response received from the firmware + * + * API to invoke the legacy delete response handler for legacy cleanup + * + * Return: SUCCESS on successful deletion + * FAILURE, if deletion fails + */ +QDF_STATUS mlme_vdev_ops_ext_hdl_delete_rsp(struct wlan_objmgr_psoc *psoc, + struct vdev_delete_response *rsp); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_pdev_mlme.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_pdev_mlme.h index 96e8786eee804f4d058fd01fdfb50137a4d08823..6f3c68ffeb1fc027834e50cb0a8b56f86e312ef0 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_pdev_mlme.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_pdev_mlme.h @@ -22,6 +22,18 @@ #include #include +#include + +/* + * struct pdev_restart_attr - Pdev restart attributes + * @vdev: vdev on which the pdev restart cmd was enqueued + * @restart_bmap: Bitmap for vdev requesting multivdev restart + */ +struct pdev_restart_attr { + struct wlan_objmgr_vdev *vdev; + unsigned long restart_bmap[2]; +}; + /** * struct pdev_mlme_obj - PDEV MLME component object * @pdev: PDEV object @@ -35,13 +47,14 @@ */ struct pdev_mlme_obj { struct wlan_objmgr_pdev *pdev; - void *ext_pdev_ptr; + mlme_pdev_ext_t *ext_pdev_ptr; QDF_STATUS (*mlme_register_ops)(struct vdev_mlme_obj *vdev_mlme); qdf_spinlock_t vdev_restart_lock; qdf_timer_t restart_req_timer; unsigned long restart_pend_vdev_bmap[2]; unsigned long restart_send_vdev_bmap[2]; unsigned long start_send_vdev_arr[2]; + struct pdev_restart_attr pdev_restart; }; #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_psoc_mlme.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_psoc_mlme.h new file mode 100644 index 0000000000000000000000000000000000000000..c7ca931ca5d5a1ee125c92904b5728e59ba170c1 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_psoc_mlme.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Define PSOC MLME structure + */ +#ifndef _WLAN_PSOC_MLME_H_ +#define _WLAN_PSOC_MLME_H_ + +#include +#include +#include +#ifdef FEATURE_VDEV_RSP_WAKELOCK +#include +#endif + +/* Max RNR size given max vaps are 16 */ +#define MAX_RNR_SIZE 256 + +/** + * struct wlan_rnr_global_cache - RNR cache buffer per soc + * @rnr_buf: RNR cache buffer + * @rnr_cnt: Count of APs in cache + * @rnr_size: Size of RNR cache (RNR IE) + */ +struct wlan_6ghz_rnr_global_cache { + char rnr_buf[MAX_RNR_SIZE]; + int rnr_cnt; + uint16_t rnr_size; +}; + +/** + * struct psoc_mlme_obj - PSoC MLME component object + * @psoc: PSoC object + * @ext_psoc_ptr: PSoC legacy pointer + * @psoc_vdev_rt: PSoC Vdev response timer + * @psoc_mlme_wakelock: Wakelock to prevent system going to suspend + * @rnr_6ghz_cache: Cache of 6Ghz vap in RNR ie format + */ +struct psoc_mlme_obj { + struct wlan_objmgr_psoc *psoc; + mlme_psoc_ext_t *ext_psoc_ptr; + struct vdev_response_timer psoc_vdev_rt[WLAN_UMAC_PSOC_MAX_VDEVS]; +#ifdef FEATURE_VDEV_RSP_WAKELOCK + struct psoc_mlme_wakelock psoc_mlme_wakelock; +#endif + struct wlan_6ghz_rnr_global_cache rnr_6ghz_cache; +}; + +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_vdev_mlme.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_vdev_mlme.h index d12fc27e8e44beac3e144f6b666ed966dfe88b1d..5bf922d9c99e89effa2467245e40be1db5d8e08c 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_vdev_mlme.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/include/wlan_vdev_mlme.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 above @@ -23,6 +23,7 @@ #include #include #include +#include struct vdev_mlme_obj; @@ -30,17 +31,24 @@ struct vdev_mlme_obj; #define MULTIPLE_VDEV_RESTART_REQ_ID 0x1234 /* values for vdev_type */ +#define WLAN_VDEV_MLME_TYPE_UNKNOWN 0x0 #define WLAN_VDEV_MLME_TYPE_AP 0x1 #define WLAN_VDEV_MLME_TYPE_STA 0x2 #define WLAN_VDEV_MLME_TYPE_IBSS 0x3 #define WLAN_VDEV_MLME_TYPE_MONITOR 0x4 +#define WLAN_VDEV_MLME_TYPE_NAN 0x5 +#define WLAN_VDEV_MLME_TYPE_OCB 0x6 +#define WLAN_VDEV_MLME_TYPE_NDI 0x7 /* values for vdev_subtype */ +#define WLAN_VDEV_MLME_SUBTYPE_UNKNOWN 0x0 #define WLAN_VDEV_MLME_SUBTYPE_P2P_DEVICE 0x1 #define WLAN_VDEV_MLME_SUBTYPE_P2P_CLIENT 0x2 #define WLAN_VDEV_MLME_SUBTYPE_P2P_GO 0x3 #define WLAN_VDEV_MLME_SUBTYPE_PROXY_STA 0x4 #define WLAN_VDEV_MLME_SUBTYPE_MESH 0x5 +#define WLAN_VDEV_MLME_SUBTYPE_MESH_11S 0x6 +#define WLAN_VDEV_MLME_SUBTYPE_SMART_MONITOR 0x7 /* vdev control flags (per bits) */ #define WLAN_VDEV_MLME_FLAGS_NON_MBSSID_AP 0x00000001 @@ -192,7 +200,7 @@ struct vdev_mlme_proto { * @type: vdev type * @sub_type: vdev subtype * @rx_decap_type: rx decap type - * @tx_decap_type: tx decap type + * @tx_encap_type: tx encap type * @disable_hw_ack: disable ha ack flag * @bssid: bssid * @phy_mode: phy mode @@ -217,7 +225,7 @@ struct vdev_mlme_mgmt_generic { uint8_t type; uint8_t subtype; uint8_t rx_decap_type; - uint8_t tx_decap_type; + uint8_t tx_encap_type; bool disable_hw_ack; uint8_t bssid[QDF_MAC_ADDR_SIZE]; uint32_t phy_mode; @@ -225,9 +233,12 @@ struct vdev_mlme_mgmt_generic { /** * struct vdev_mlme_mgmt_ap - ap specific vdev mlme mgmt cfg - * @. + * @hidden_ssid: flag to indicate whether it is hidden ssid + * @cac_duration_ms: cac duration in millseconds */ struct vdev_mlme_mgmt_ap { + bool hidden_ssid; + uint32_t cac_duration_ms; }; /** @@ -262,6 +273,7 @@ struct vdev_mlme_inactivity_params { * @max_rate: max bandwidth rate * @tx_mgmt_rate: Tx Mgmt rate * @bcn_tx_rate: beacon Tx rate + * @bcn_tx_rate_code: beacon Tx rate code * @type: Type of ratemask configuration * @lower32: Lower 32 bits in the 1st 64-bit value * @higher32: Higher 32 bits in the 1st 64-bit value @@ -275,6 +287,9 @@ struct vdev_mlme_rate_info { uint32_t max_rate; uint32_t tx_mgmt_rate; uint32_t bcn_tx_rate; +#ifdef WLAN_BCN_RATECODE_ENABLE + uint32_t bcn_tx_rate_code; +#endif uint8_t type; uint32_t lower32; uint32_t higher32; @@ -438,6 +453,8 @@ enum vdev_start_resp_type { * @mlme_vdev_notify_start_state_exit: callback to notify on vdev start * start state exit * @mlme_vdev_is_newchan_no_cac: callback to check CAC is required + * @mlme_vdev_ext_peer_delete_all_rsp: callback to initiate actions for + * vdev mlme peer delete all response */ struct vdev_mlme_ops { QDF_STATUS (*mlme_vdev_validate_basic_params)( @@ -496,9 +513,6 @@ struct vdev_mlme_ops { QDF_STATUS (*mlme_vdev_notify_down_complete)( struct vdev_mlme_obj *vdev_mlme, uint16_t event_data_len, void *event_data); - QDF_STATUS (*mlme_vdev_ext_delete_rsp)( - struct vdev_mlme_obj *vdev_mlme, - struct vdev_delete_response *rsp); QDF_STATUS (*mlme_vdev_ext_stop_rsp)( struct vdev_mlme_obj *vdev_mlme, struct vdev_stop_response *rsp); @@ -509,6 +523,9 @@ struct vdev_mlme_ops { struct vdev_mlme_obj *vdev_mlme); QDF_STATUS (*mlme_vdev_is_newchan_no_cac)( struct vdev_mlme_obj *vdev_mlme); + QDF_STATUS (*mlme_vdev_ext_peer_delete_all_rsp)( + struct vdev_mlme_obj *vdev_mlme, + struct peer_delete_all_response *rsp); }; /** @@ -522,6 +539,7 @@ struct vdev_mlme_ops { * @ops: VDEV MLME callback table * @ext_vdev_ptr: VDEV MLME legacy pointer * @vdev_rt: VDEV response timer + * @vdev_wakelock: vdev wakelock sub structure */ struct vdev_mlme_obj { struct vdev_mlme_proto proto; @@ -533,494 +551,9 @@ struct vdev_mlme_obj { struct wlan_sm *sm_hdl; struct wlan_objmgr_vdev *vdev; struct vdev_mlme_ops *ops; - void *ext_vdev_ptr; - struct vdev_response_timer vdev_rt; + mlme_vdev_ext_t *ext_vdev_ptr; }; -/** - * mlme_vdev_validate_basic_params - Validate basic params - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API validate MLME VDEV basic parameters - * - * Return: SUCCESS on successful validation - * FAILURE, if any parameter is not initialized - */ -static inline QDF_STATUS mlme_vdev_validate_basic_params( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_validate_basic_params) - ret = vdev_mlme->ops->mlme_vdev_validate_basic_params( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_reset_proto_params - Reset VDEV protocol params - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API resets the protocol params fo vdev - * - * Return: SUCCESS on successful reset - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_reset_proto_params( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_reset_proto_params) - ret = vdev_mlme->ops->mlme_vdev_reset_proto_params( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_start_send - Invokes VDEV start operation - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API invokes VDEV start operation - * - * Return: SUCCESS on successful completion of start operation - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_start_send( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_start_send) - ret = vdev_mlme->ops->mlme_vdev_start_send( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_restart_send - Invokes VDEV restart operation - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API invokes VDEV restart operation - * - * Return: SUCCESS on successful completion of restart operation - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_restart_send( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_restart_send) - ret = vdev_mlme->ops->mlme_vdev_restart_send( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_stop_start_send - Invoke block VDEV restart operation - * @vdev_mlme_obj: VDEV MLME comp object - * @restart: restart req/start req - * @event_data_len: data size - * @event_data: event data - * - * API invokes stops pending VDEV restart operation - * - * Return: SUCCESS alsways - */ -static inline QDF_STATUS mlme_vdev_stop_start_send( - struct vdev_mlme_obj *vdev_mlme, - uint8_t restart, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_stop_start_send) - ret = vdev_mlme->ops->mlme_vdev_stop_start_send( - vdev_mlme, restart, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_start_continue - VDEV start response handling - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API invokes VDEV start response actions - * - * Return: SUCCESS on successful completion of start response operation - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_start_continue( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_start_continue) - ret = vdev_mlme->ops->mlme_vdev_start_continue( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_start_req_failed - Invoke Station VDEV connection, if it pause - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API invokes on START fail response - * - * Return: SUCCESS on successful invocation of callback - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_start_req_failed( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_start_req_failed) - ret = vdev_mlme->ops->mlme_vdev_start_req_failed( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_sta_conn_start - Invoke Station VDEV connection, if it pause - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API invokes connection SM to start station connection - * - * Return: SUCCESS on successful invocation of connection sm - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_sta_conn_start( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_sta_conn_start) - ret = vdev_mlme->ops->mlme_vdev_sta_conn_start( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_up_send - VDEV up operation - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API invokes VDEV up operations - * - * Return: SUCCESS on successful completion of up operation - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_up_send( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_up_send) - ret = vdev_mlme->ops->mlme_vdev_up_send( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_notify_up_complete - VDEV up state transition notification - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API notifies MLME on moving to UP state - * - * Return: SUCCESS on successful completion of up notification - * FAILURE, if it fails due to any - */ -static inline -QDF_STATUS mlme_vdev_notify_up_complete(struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, - void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if (vdev_mlme->ops && vdev_mlme->ops->mlme_vdev_notify_up_complete) - ret = vdev_mlme->ops->mlme_vdev_notify_up_complete( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_notify_roam_start - VDEV Roaming notification - * @vdev_mlme_obj: VDEV MLME comp object - * @event_len: data size - * @event_data: event data - * - * API notifies MLME on roaming - * - * Return: SUCCESS on successful completion of up notification - * FAILURE, if it fails due to any - */ -static inline -QDF_STATUS mlme_vdev_notify_roam_start(struct vdev_mlme_obj *vdev_mlme, - uint16_t event_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if (vdev_mlme->ops && vdev_mlme->ops->mlme_vdev_notify_roam_start) - ret = vdev_mlme->ops->mlme_vdev_notify_roam_start(vdev_mlme, - event_len, - event_data); - - return ret; -} - -/** - * mlme_vdev_update_beacon - Updates beacon - * @vdev_mlme_obj: VDEV MLME comp object - * @op: beacon update type - * @event_data_len: data size - * @event_data: event data - * - * API updates/allocates/frees the beacon - * - * Return: SUCCESS on successful update of beacon - * FAILURE, if it fails due to any - */ -static inline -QDF_STATUS mlme_vdev_update_beacon(struct vdev_mlme_obj *vdev_mlme, - enum beacon_update_op op, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if (vdev_mlme->ops && vdev_mlme->ops->mlme_vdev_update_beacon) - ret = vdev_mlme->ops->mlme_vdev_update_beacon(vdev_mlme, op, - event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_disconnect_peers - Disconnect peers - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API trigger stations disconnection with AP VDEV or AP disconnection with STA - * VDEV - * - * Return: SUCCESS on successful invocation of station disconnection - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_disconnect_peers( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_disconnect_peers) - ret = vdev_mlme->ops->mlme_vdev_disconnect_peers( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_dfs_cac_timer_stop - Stop CAC timer - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API stops the CAC timer through DFS API - * - * Return: SUCCESS on successful CAC timer stop - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_dfs_cac_timer_stop( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_dfs_cac_timer_stop) - ret = vdev_mlme->ops->mlme_vdev_dfs_cac_timer_stop( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_stop_send - Invokes VDEV stop operation - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API invokes VDEV stop operation - * - * Return: SUCCESS on successful completion of stop operation - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_stop_send( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_stop_send) - ret = vdev_mlme->ops->mlme_vdev_stop_send( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_stop_continue - VDEV stop response handling - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API invokes VDEV stop response actions - * - * Return: SUCCESS on successful completion of stop response operation - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_stop_continue( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_stop_continue) - ret = vdev_mlme->ops->mlme_vdev_stop_continue(vdev_mlme, - event_data_len, - event_data); - - return ret; -} - -/** - * mlme_vdev_down_send - VDEV down operation - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API invokes VDEV down operation - * - * Return: SUCCESS on successful completion of VDEV down operation - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_down_send( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_down_send) - ret = vdev_mlme->ops->mlme_vdev_down_send( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_notify_down_complete - VDEV init state transition notification - * @vdev_mlme_obj: VDEV MLME comp object - * @event_data_len: data size - * @event_data: event data - * - * API notifies MLME on moving to INIT state - * - * Return: SUCCESS on successful completion of down notification - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_notify_down_complete( - struct vdev_mlme_obj *vdev_mlme, - uint16_t event_data_len, void *event_data) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_notify_down_complete) - ret = vdev_mlme->ops->mlme_vdev_notify_down_complete( - vdev_mlme, event_data_len, event_data); - - return ret; -} - -/** - * mlme_vdev_notify_start_state_exit - VDEV SM start state exit notification - * @vdev_mlme_obj: VDEV MLME comp object - * - * API notifies on start state exit - * - * Return: SUCCESS on successful completion of notification - * FAILURE, if it fails due to any - */ -static inline QDF_STATUS mlme_vdev_notify_start_state_exit( - struct vdev_mlme_obj *vdev_mlme) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && - vdev_mlme->ops->mlme_vdev_notify_start_state_exit) - ret = vdev_mlme->ops->mlme_vdev_notify_start_state_exit( - vdev_mlme); - - return ret; -} - -/** - * mlme_vdev_is_newchan_no_cac - Checks new channel requires CAC - * @vdev_mlme_obj: VDEV MLME comp object - * - * API checks whether Channel needs CAC period, - * if yes, it moves to SUSPEND_RESTART to disconnect stations before - * sending RESTART to FW, otherwise, it moves to RESTART_PROGRESS substate - * - * Return: SUCCESS to move to RESTART_PROGRESS substate - * FAILURE, move to SUSPEND_RESTART state - */ -static inline QDF_STATUS mlme_vdev_is_newchan_no_cac( - struct vdev_mlme_obj *vdev_mlme) -{ - QDF_STATUS ret = QDF_STATUS_SUCCESS; - - if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_is_newchan_no_cac) - ret = vdev_mlme->ops->mlme_vdev_is_newchan_no_cac(vdev_mlme); - - return ret; -} - -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE /** * wlan_vdev_mlme_set_ssid() - set ssid * @vdev: VDEV object @@ -1349,5 +882,4 @@ static inline uint32_t wlan_vdev_mlme_get_txmgmtrate( return vdev_mlme->mgmt.rate_info.tx_mgmt_rate; } -#endif /* CMN_VDEV_MGR_TGT_IF_ENABLE */ #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/inc/wlan_psoc_mlme_main.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/inc/wlan_psoc_mlme_main.h new file mode 100644 index 0000000000000000000000000000000000000000..36026b7ae1a8d35e1366813d0cd2ad331893ef1b --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/inc/wlan_psoc_mlme_main.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Define PSOC MLME structure + */ +#ifndef _WLAN_PSOC_MLME_MAIN_H_ +#define _WLAN_PSOC_MLME_MAIN_H_ + +/** + * wlan_psoc_mlme_init() - Initializes PSOC MLME component + * + * Registers callbacks with object manager for create/destroy + * + * Return: SUCCESS on successful initialization + * FAILURE, if initialization fails + */ +QDF_STATUS wlan_psoc_mlme_init(void); + +/** + * wlan_psoc_mlme_deinit() - Uninitializes PSOC MLME component + * + * Unregisters callbacks with object manager for create/destroy + * + * Return: SUCCESS on successful de-initialization + * FAILURE, if de-initialization fails + */ +QDF_STATUS wlan_psoc_mlme_deinit(void); + +/** + * mlme_psoc_get_priv: get MLME priv object from psoc object + * @psoc: pointer to psoc object + * + * Return: pointer to MLME psoc private object + */ +struct psoc_mlme_obj *mlme_psoc_get_priv(struct wlan_objmgr_psoc *psoc); + +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/inc/wlan_vdev_mlme_main.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/inc/wlan_vdev_mlme_main.h index 8a89344b2bda51748ca04b71ab423c2c3aa84a38..e13bcddf009b8e42a22eec02d2cea4558e5ccd3f 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/inc/wlan_vdev_mlme_main.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/inc/wlan_vdev_mlme_main.h @@ -116,6 +116,8 @@ enum wlan_vdev_state { * @WLAN_VDEV_SM_EV_DOWN_COMPLETE: Notification of DOWN complete * @WLAN_VDEV_SM_EV_ROAM: Notifiction on ROAMING * @WLAN_VDEV_SM_EV_STOP_REQ: Invoke API to initiate STOP handshake + * @WLAN_VDEV_SM_EV_CHAN_SWITCH_DISABLED:Test only, CSA completes without + * change in channel */ enum wlan_vdev_sm_evt { WLAN_VDEV_SM_EV_START = 0, @@ -148,6 +150,7 @@ enum wlan_vdev_sm_evt { WLAN_VDEV_SM_EV_DOWN_COMPLETE = 27, WLAN_VDEV_SM_EV_ROAM = 28, WLAN_VDEV_SM_EV_STOP_REQ = 29, + WLAN_VDEV_SM_EV_CHAN_SWITCH_DISABLED = 30, }; /** diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/src/wlan_cmn_mlme_main.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/src/wlan_cmn_mlme_main.c index 5054286c2d74e1ca34244a08c63a72b0e0cdd64d..0f03758b28f0de019a655b2cc3c11566ad8faba2 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/src/wlan_cmn_mlme_main.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/src/wlan_cmn_mlme_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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 above @@ -18,13 +18,14 @@ * DOC: Implements MLME global APIs */ -#include "wlan_objmgr_cmn.h" -#include "include/wlan_mlme_cmn.h" -#include "include/wlan_pdev_mlme.h" -#include "include/wlan_vdev_mlme.h" -#include "include/wlan_mlme_cmn.h" -#include "wlan_pdev_mlme_main.h" -#include "wlan_vdev_mlme_main.h" +#include +#include +#include +#include +#include +#include +#include +#include struct mlme_ext_ops *glbl_ops; mlme_get_global_ops_cb glbl_ops_cb; @@ -33,6 +34,10 @@ QDF_STATUS wlan_cmn_mlme_init(void) { QDF_STATUS status; + status = wlan_psoc_mlme_init(); + if (status != QDF_STATUS_SUCCESS) + return status; + status = wlan_pdev_mlme_init(); if (status != QDF_STATUS_SUCCESS) return status; @@ -59,14 +64,38 @@ QDF_STATUS wlan_cmn_mlme_deinit(void) if (status != QDF_STATUS_SUCCESS) return status; + status = wlan_psoc_mlme_deinit(); + if (status != QDF_STATUS_SUCCESS) + return status; + return QDF_STATUS_SUCCESS; } +QDF_STATUS mlme_psoc_ops_ext_hdl_create(struct psoc_mlme_obj *psoc_mlme) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if (glbl_ops && glbl_ops->mlme_psoc_ext_hdl_create) + ret = glbl_ops->mlme_psoc_ext_hdl_create(psoc_mlme); + + return ret; +} + +QDF_STATUS mlme_psoc_ops_ext_hdl_destroy(struct psoc_mlme_obj *psoc_mlme) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if (glbl_ops && glbl_ops->mlme_psoc_ext_hdl_destroy) + ret = glbl_ops->mlme_psoc_ext_hdl_destroy(psoc_mlme); + + return ret; +} + QDF_STATUS mlme_pdev_ops_ext_hdl_create(struct pdev_mlme_obj *pdev_mlme) { QDF_STATUS ret = QDF_STATUS_SUCCESS; - if ((glbl_ops) && glbl_ops->mlme_pdev_ext_hdl_create) + if (glbl_ops && glbl_ops->mlme_pdev_ext_hdl_create) ret = glbl_ops->mlme_pdev_ext_hdl_create(pdev_mlme); return ret; @@ -76,7 +105,7 @@ QDF_STATUS mlme_pdev_ops_ext_hdl_destroy(struct pdev_mlme_obj *pdev_mlme) { QDF_STATUS ret = QDF_STATUS_SUCCESS; - if ((glbl_ops) && glbl_ops->mlme_pdev_ext_hdl_destroy) + if (glbl_ops && glbl_ops->mlme_pdev_ext_hdl_destroy) ret = glbl_ops->mlme_pdev_ext_hdl_destroy(pdev_mlme); return ret; @@ -86,7 +115,7 @@ QDF_STATUS mlme_vdev_ops_ext_hdl_create(struct vdev_mlme_obj *vdev_mlme) { QDF_STATUS ret = QDF_STATUS_SUCCESS; - if ((glbl_ops) && glbl_ops->mlme_vdev_ext_hdl_create) + if (glbl_ops && glbl_ops->mlme_vdev_ext_hdl_create) ret = glbl_ops->mlme_vdev_ext_hdl_create(vdev_mlme); return ret; @@ -96,7 +125,7 @@ QDF_STATUS mlme_vdev_ops_ext_hdl_post_create(struct vdev_mlme_obj *vdev_mlme) { QDF_STATUS ret = QDF_STATUS_SUCCESS; - if ((glbl_ops) && glbl_ops->mlme_vdev_ext_hdl_post_create) + if (glbl_ops && glbl_ops->mlme_vdev_ext_hdl_post_create) ret = glbl_ops->mlme_vdev_ext_hdl_post_create(vdev_mlme); return ret; @@ -106,7 +135,7 @@ QDF_STATUS mlme_vdev_ops_ext_hdl_destroy(struct vdev_mlme_obj *vdev_mlme) { QDF_STATUS ret = QDF_STATUS_SUCCESS; - if ((glbl_ops) && glbl_ops->mlme_vdev_ext_hdl_destroy) + if (glbl_ops && glbl_ops->mlme_vdev_ext_hdl_destroy) ret = glbl_ops->mlme_vdev_ext_hdl_destroy(vdev_mlme); return ret; @@ -128,7 +157,7 @@ QDF_STATUS mlme_vdev_ops_multivdev_restart_fw_cmd_send( { QDF_STATUS ret = QDF_STATUS_SUCCESS; - if ((glbl_ops) && glbl_ops->mlme_multivdev_restart_fw_send) + if (glbl_ops && glbl_ops->mlme_multivdev_restart_fw_send) glbl_ops->mlme_multivdev_restart_fw_send(pdev); return ret; @@ -165,6 +194,29 @@ QDF_STATUS mlme_vdev_enqueue_exp_ser_cmd(struct vdev_mlme_obj *vdev_mlme, return ret; } +QDF_STATUS mlme_vdev_ops_ext_hdl_delete_rsp(struct wlan_objmgr_psoc *psoc, + struct vdev_delete_response *rsp) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((glbl_ops) && glbl_ops->mlme_vdev_ext_delete_rsp) + ret = glbl_ops->mlme_vdev_ext_delete_rsp(psoc, rsp); + + return ret; +} + +QDF_STATUS mlme_vdev_ops_ext_hdl_multivdev_restart_resp( + struct wlan_objmgr_psoc *psoc, + struct multi_vdev_restart_resp *resp) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((glbl_ops) && glbl_ops->mlme_multi_vdev_restart_resp) + ret = glbl_ops->mlme_multi_vdev_restart_resp(psoc, resp); + + return ret; +} + void mlme_set_ops_register_cb(mlme_get_global_ops_cb ops_cb) { glbl_ops_cb = ops_cb; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/src/wlan_psoc_mlme_main.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/src/wlan_psoc_mlme_main.c new file mode 100644 index 0000000000000000000000000000000000000000..cf409c99e3474c4bc7873110fdc61813c274880d --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/src/wlan_psoc_mlme_main.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2019-2020 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Implements PSOC MLME APIs + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct psoc_mlme_obj *mlme_psoc_get_priv(struct wlan_objmgr_psoc *psoc) +{ + struct psoc_mlme_obj *psoc_mlme; + + psoc_mlme = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_MLME); + if (!psoc_mlme) { + mlme_err("PSOC MLME component object is NULL"); + return NULL; + } + + return psoc_mlme; +} + +qdf_export_symbol(mlme_psoc_get_priv); + +static QDF_STATUS mlme_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, + void *arg) +{ + struct psoc_mlme_obj *psoc_mlme; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + psoc_mlme = qdf_mem_malloc(sizeof(struct psoc_mlme_obj)); + if (!psoc_mlme) { + mlme_err("Failed to allocate PSOS mlme Object"); + return QDF_STATUS_E_NOMEM; + } + + psoc_mlme->psoc = psoc; + + status = mlme_psoc_ops_ext_hdl_create(psoc_mlme); + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("Failed to allocate psoc ext handle"); + goto init_failed; + } + + status = wlan_objmgr_psoc_component_obj_attach(psoc, + WLAN_UMAC_COMP_MLME, + psoc_mlme, + QDF_STATUS_SUCCESS); + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("Failed to attach psoc_ctx with psoc"); + goto init_failed; + } + + return QDF_STATUS_SUCCESS; +init_failed: + qdf_mem_free(psoc_mlme); + + return status; +} + +static QDF_STATUS mlme_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc, + void *arg) +{ + struct psoc_mlme_obj *psoc_mlme; + + psoc_mlme = mlme_psoc_get_priv(psoc); + if (!psoc_mlme) { + mlme_err("PSOC MLME component object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + wlan_objmgr_psoc_component_obj_detach(psoc, WLAN_UMAC_COMP_MLME, + psoc_mlme); + + mlme_psoc_ops_ext_hdl_destroy(psoc_mlme); + + qdf_mem_free(psoc_mlme); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_psoc_mlme_init(void) +{ + if (wlan_objmgr_register_psoc_create_handler + (WLAN_UMAC_COMP_MLME, + mlme_psoc_obj_create_handler, NULL) + != QDF_STATUS_SUCCESS) + return QDF_STATUS_E_FAILURE; + + if (wlan_objmgr_register_psoc_destroy_handler + (WLAN_UMAC_COMP_MLME, + mlme_psoc_obj_destroy_handler, NULL) + != QDF_STATUS_SUCCESS) { + if (wlan_objmgr_unregister_psoc_create_handler + (WLAN_UMAC_COMP_MLME, + mlme_psoc_obj_create_handler, NULL) + != QDF_STATUS_SUCCESS) + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_psoc_mlme_deinit(void) +{ + if (wlan_objmgr_unregister_psoc_create_handler + (WLAN_UMAC_COMP_MLME, + mlme_psoc_obj_create_handler, NULL) + != QDF_STATUS_SUCCESS) + return QDF_STATUS_E_FAILURE; + + if (wlan_objmgr_unregister_psoc_destroy_handler + (WLAN_UMAC_COMP_MLME, + mlme_psoc_obj_destroy_handler, NULL) + != QDF_STATUS_SUCCESS) + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/src/wlan_vdev_mlme_main.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/src/wlan_vdev_mlme_main.c index ddd41b2744093081d4d5ca118603baa991f6e7d2..7ef6dfb1285f8671d526208c26c428d45552a55a 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/src/wlan_vdev_mlme_main.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_objmgr/dispatcher/src/wlan_vdev_mlme_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 above @@ -22,22 +22,27 @@ #include #include #include -#include "include/wlan_mlme_cmn.h" -#include "include/wlan_vdev_mlme.h" -#include "include/wlan_pdev_mlme.h" -#include "vdev_mgr/core/src/vdev_mlme_sm.h" -#include "wlan_pdev_mlme_api.h" -#include "wlan_vdev_mlme_api.h" -#include "wlan_serialization_api.h" -#include "wlan_utility.h" +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev, void *arg) { struct vdev_mlme_obj *vdev_mlme; struct wlan_objmgr_pdev *pdev; + struct wlan_objmgr_psoc *psoc; struct pdev_mlme_obj *pdev_mlme; + struct wlan_lmac_if_mlme_tx_ops *txops; + QDF_STATUS status; if (!vdev) { mlme_err(" VDEV is NULL"); @@ -50,9 +55,33 @@ static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_FAILURE; } + /** + * 1st check whether for this vdev any vdev commands are pending for + * response. + */ + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + mlme_err("PSOC is NULL"); + return QDF_STATUS_E_FAILURE; + } + + txops = wlan_mlme_get_lmac_tx_ops(psoc); + if (!txops || !txops->psoc_vdev_rsp_timer_inuse) { + mlme_err("Failed to get mlme txrx_ops PSOC_%d", + wlan_psoc_get_id(psoc)); + return QDF_STATUS_E_FAILURE; + } + + status = txops->psoc_vdev_rsp_timer_inuse(psoc, wlan_vdev_get_id(vdev)); + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("The vdev response is pending for VDEV_%d status:%d", + wlan_vdev_get_id(vdev), status); + return QDF_STATUS_E_FAILURE; + } + pdev_mlme = wlan_pdev_mlme_get_cmpt_obj(pdev); if (!pdev_mlme) { - mlme_err(" PDEV MLME is NULL"); + mlme_err("PDEV MLME is NULL"); return QDF_STATUS_E_FAILURE; } @@ -103,28 +132,10 @@ static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_FAILURE; } -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE -static void mlme_vdev_obj_timer_deinit( - struct vdev_mlme_obj *vdev_mlme) -{ - struct vdev_response_timer *vdev_rsp; - - vdev_rsp = &vdev_mlme->vdev_rt; - qdf_timer_free(&vdev_rsp->rsp_timer); -} -#else -static void mlme_vdev_obj_timer_deinit( - struct vdev_mlme_obj *vdev_mlme) -{ -} -#endif static QDF_STATUS mlme_vdev_obj_destroy_handler(struct wlan_objmgr_vdev *vdev, void *arg) { struct vdev_mlme_obj *vdev_mlme; - struct wlan_objmgr_psoc *psoc; - struct cdp_soc_t *soc_txrx_handle; - struct cdp_vdev *vdev_txrx_handle; if (!vdev) { mlme_err(" VDEV is NULL"); @@ -137,17 +148,6 @@ static QDF_STATUS mlme_vdev_obj_destroy_handler(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_SUCCESS; } - psoc = wlan_vdev_get_psoc(vdev); - soc_txrx_handle = (struct cdp_soc_t *)wlan_psoc_get_dp_handle(psoc); - vdev_txrx_handle = wlan_vdev_get_dp_handle(vdev); - if (soc_txrx_handle && vdev_txrx_handle) { - wlan_vdev_set_dp_handle(vdev, NULL); - cdp_vdev_detach(soc_txrx_handle, vdev_txrx_handle, - NULL, NULL); - } - - mlme_vdev_obj_timer_deinit(vdev_mlme); - mlme_vdev_sm_destroy(vdev_mlme); mlme_vdev_ops_ext_hdl_destroy(vdev_mlme); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_utils/wlan_vdev_mlme_ser_if.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_utils/wlan_vdev_mlme_ser_if.c index 3e9a4435114b75c1cec7f5ac2bddf1d7a1aac897..80ea23bc43155dffce5b964fcc6cb3f47b27aa1a 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_utils/wlan_vdev_mlme_ser_if.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_utils/wlan_vdev_mlme_ser_if.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 above @@ -41,6 +41,8 @@ wlan_vdev_mlme_ser_start_bss(struct wlan_serialization_command *cmd) return WLAN_SER_CMD_DENIED_UNSPECIFIED; } + if (!wlan_ser_is_vdev_queue_enabled(cmd->vdev)) + return WLAN_SER_CMD_QUEUE_DISABLED; /* * Serialization command filtering logic * a. Cancel any existing start bss cmd in the pending queue @@ -77,6 +79,9 @@ wlan_vdev_mlme_ser_stop_bss(struct wlan_serialization_command *cmd) mlme_err("Null input"); return WLAN_SER_CMD_DENIED_UNSPECIFIED; } + + if (!wlan_ser_is_vdev_queue_enabled(cmd->vdev)) + return WLAN_SER_CMD_QUEUE_DISABLED; /* * Serialization command filtering logic * a. Cancel any existing start/stop/restart command in the pending @@ -90,7 +95,7 @@ wlan_vdev_mlme_ser_stop_bss(struct wlan_serialization_command *cmd) wlan_serialization_is_cmd_present_in_pending_queue(NULL, cmd); wlan_vdev_mlme_ser_cancel_request(cmd->vdev, WLAN_SER_CMD_NONSCAN, - WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD); + WLAN_SER_CANCEL_VDEV_NON_SCAN_NB_CMD); if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) { mlme_debug("Cmd already exist in the active queue"); @@ -106,21 +111,94 @@ wlan_vdev_mlme_ser_stop_bss(struct wlan_serialization_command *cmd) } enum wlan_serialization_status -wlan_vdev_mlme_ser_restart_bss(struct wlan_serialization_command *cmd) +wlan_vdev_mlme_ser_vdev_restart(struct wlan_serialization_command *cmd) { if (!cmd || !cmd->vdev) { mlme_err("Null input"); return WLAN_SER_CMD_DENIED_UNSPECIFIED; } + + if (!wlan_ser_is_vdev_queue_enabled(cmd->vdev)) + return WLAN_SER_CMD_QUEUE_DISABLED; + /* + * Serialization command filtering logic + * a. If there exists START or PDEV/VDEV restart command in the pending + * queue then ignore this new vdev restart request. + * b. Else enqueue the new VDEV RESTART cmd + */ + cmd->cmd_type = WLAN_SER_CMD_VDEV_START_BSS; + if (wlan_serialization_is_cmd_present_in_pending_queue(NULL, cmd)) { + mlme_debug("Start cmd already in the pending queue"); + return WLAN_SER_CMD_ALREADY_EXISTS; + } + + cmd->cmd_type = WLAN_SER_CMD_PDEV_RESTART; + if (wlan_serialization_is_cmd_present_in_pending_queue(NULL, cmd)) { + mlme_debug("Pdev restart already in the pending queue"); + return WLAN_SER_CMD_ALREADY_EXISTS; + } + + cmd->cmd_type = WLAN_SER_CMD_VDEV_RESTART; + if (wlan_serialization_is_cmd_present_in_pending_queue(NULL, cmd)) { + mlme_debug("Vdev restart already in the pending queue"); + return WLAN_SER_CMD_ALREADY_EXISTS; + } + + return wlan_serialization_request(cmd); +} + +void wlan_mlme_restart_pdev_iter_cb(struct wlan_objmgr_pdev *pdev, + void *object, void *arg) +{ + struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; + uint8_t *pdev_restart_pending = (uint8_t *)arg; + struct wlan_serialization_command cmd = {0}; + uint8_t vdev_id = wlan_vdev_get_id(vdev); + + cmd.vdev = vdev; + cmd.cmd_id = vdev_id; + cmd.cmd_type = WLAN_SER_CMD_PDEV_RESTART; /* * Serialization command filtering logic - * a. Cancel any existing RESTART cmd in the pending queue - * b. Enqueue the new RESTART cmd + * a. Cancel any existing VDEV restart cmd in the pending queue + * b. If Pdev restart already exist in pending queue then return else + * enqueue the new PDEV RESTART cmd */ wlan_vdev_mlme_ser_cancel_request( - cmd->vdev, + vdev, WLAN_SER_CMD_VDEV_RESTART, WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE); + + if (wlan_serialization_is_cmd_present_in_pending_queue(NULL, &cmd)) { + mlme_debug("Cmd already exist in the pending queue vdev:%u", + vdev_id); + *pdev_restart_pending = 1; + } +} + +enum wlan_serialization_status +wlan_vdev_mlme_ser_pdev_restart(struct wlan_serialization_command *cmd) +{ + struct wlan_objmgr_pdev *pdev; + uint8_t pdev_restart_in_pending = 0; + + if (!cmd || !cmd->vdev) { + mlme_err("Null input"); + return WLAN_SER_CMD_DENIED_UNSPECIFIED; + } + + if (!wlan_ser_is_vdev_queue_enabled(cmd->vdev)) + return WLAN_SER_CMD_QUEUE_DISABLED; + + pdev = wlan_vdev_get_pdev(cmd->vdev); + wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, + wlan_mlme_restart_pdev_iter_cb, + &pdev_restart_in_pending, 0, + WLAN_MLME_SER_IF_ID); + + if (pdev_restart_in_pending) + return WLAN_SER_CMD_ALREADY_EXISTS; + return wlan_serialization_request(cmd); } @@ -133,6 +211,9 @@ wlan_vdev_mlme_ser_connect(struct wlan_serialization_command *cmd) mlme_err("Null input"); return WLAN_SER_CMD_DENIED_UNSPECIFIED; } + + if (!wlan_ser_is_vdev_queue_enabled(cmd->vdev)) + return WLAN_SER_CMD_QUEUE_DISABLED; /* * Serialization command filtering logic * a. Cancel any existing CONNECT cmd in the pending queue @@ -165,16 +246,19 @@ wlan_vdev_mlme_ser_disconnect(struct wlan_serialization_command *cmd) mlme_err("Null input"); return WLAN_SER_CMD_DENIED_UNSPECIFIED; } + + if (!wlan_ser_is_vdev_queue_enabled(cmd->vdev)) + return WLAN_SER_CMD_QUEUE_DISABLED; /* * Serialization command filtering logic - * a.Cancel any existing CONNECT/DISCONNECT/RESTART command in the + * a.Cancel any existing non-blocking non-scan command in the * pending queue * b.If there is a DISCONNECT cmd in active queue then return * c.Else enqueue the DISCONNECT cmd */ wlan_vdev_mlme_ser_cancel_request(cmd->vdev, WLAN_SER_CMD_NONSCAN, - WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD); + WLAN_SER_CANCEL_VDEV_NON_SCAN_NB_CMD); if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) { mlme_debug("Cmd already exist in the active queue"); @@ -184,6 +268,96 @@ wlan_vdev_mlme_ser_disconnect(struct wlan_serialization_command *cmd) return wlan_serialization_request(cmd); } +static void +wlan_mlme_cancel_pending_csa_restart(struct wlan_objmgr_pdev *pdev, + void *object, void *arg) +{ + struct wlan_objmgr_vdev *vdev = object; + bool *csa_restart_pending = arg; + struct wlan_serialization_command cmd = {0}; + uint8_t vdev_id = wlan_vdev_get_id(vdev); + + cmd.vdev = vdev; + cmd.cmd_id = vdev_id; + cmd.cmd_type = WLAN_SER_CMD_PDEV_CSA_RESTART; + if (wlan_serialization_is_cmd_present_in_pending_queue(NULL, &cmd)) { + mlme_debug("Cmd already exist in the pending queue vdev:%u", + vdev_id); + *csa_restart_pending = true; + } + + wlan_vdev_mlme_ser_cancel_request( + vdev, + WLAN_SER_CMD_PDEV_CSA_RESTART, + WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE); +} + +static void +wlan_mlme_check_pdev_restart(struct wlan_objmgr_pdev *pdev, + void *object, void *arg) +{ + struct wlan_objmgr_vdev *vdev = object; + bool *pdev_restart_pending = arg; + struct wlan_serialization_command cmd = {0}; + uint8_t vdev_id = wlan_vdev_get_id(vdev); + + cmd.vdev = vdev; + cmd.cmd_id = vdev_id; + cmd.cmd_type = WLAN_SER_CMD_PDEV_RESTART; + if (wlan_serialization_is_cmd_present_in_active_queue(NULL, &cmd)) { + mlme_debug("Pdev restart already in the active queue vdev:%u", + vdev_id); + *pdev_restart_pending = true; + } +} + +enum wlan_serialization_status +wlan_vdev_mlme_ser_pdev_csa_restart(struct wlan_serialization_command *cmd) +{ + struct wlan_objmgr_pdev *pdev; + bool csa_restart_pending = false; + bool pdev_restart_pending = false; + enum wlan_serialization_status ret; + + if (!cmd || !cmd->vdev) { + mlme_err("Null input"); + return WLAN_SER_CMD_DENIED_UNSPECIFIED; + } + + if (!wlan_ser_is_vdev_queue_enabled(cmd->vdev)) + return WLAN_SER_CMD_QUEUE_DISABLED; + + /* + * Serialization command filtering logic + * a. Cancel any existing PDEV CSA restart cmd in the pending queue + * b. If there exists PDEV RESTART command in the active queue + * then deny this request + * c. If PDEV CSA RESTART cmd already existed in pending queue + * then enqueue and return already exists + * d. Else enqueue this PDEV CSA RESTART cmd + */ + pdev = wlan_vdev_get_pdev(cmd->vdev); + wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, + wlan_mlme_cancel_pending_csa_restart, + &csa_restart_pending, 0, + WLAN_MLME_SER_IF_ID); + + wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, + wlan_mlme_check_pdev_restart, + &pdev_restart_pending, 0, + WLAN_MLME_SER_IF_ID); + + if (pdev_restart_pending) + return WLAN_SER_CMD_DENIED_UNSPECIFIED; + + ret = wlan_serialization_request(cmd); + + if (csa_restart_pending && ret == WLAN_SER_CMD_PENDING) + return WLAN_SER_CMD_ALREADY_EXISTS; + + return ret; +} + void wlan_vdev_mlme_ser_remove_request(struct wlan_objmgr_vdev *vdev, uint32_t cmd_id, @@ -191,7 +365,7 @@ wlan_vdev_mlme_ser_remove_request(struct wlan_objmgr_vdev *vdev, { struct wlan_serialization_queued_cmd_info cmd = {0}; - mlme_debug("Remove the cmd type:%d", cmd_type); + mlme_debug("Vdev:%d remove cmd:%d", wlan_vdev_get_id(vdev), cmd_type); cmd.vdev = vdev; cmd.cmd_id = cmd_id; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_utils/wlan_vdev_mlme_ser_if.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_utils/wlan_vdev_mlme_ser_if.h index ba4cb3461fd084a676343ad7a6e9bfa252707c35..4f90e3080690a10a20f942a6b2d79b4b62be7795 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_utils/wlan_vdev_mlme_ser_if.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/mlme_utils/wlan_vdev_mlme_ser_if.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 @@ -49,13 +49,22 @@ enum wlan_serialization_status wlan_vdev_mlme_ser_stop_bss(struct wlan_serialization_command *cmd); /** - * wlan_vdev_mlme_ser_restart_bss() - Add restart bss cmd to serialization + * wlan_vdev_mlme_ser_vdev_restart() - Add vdev restart cmd to serialization * @cmd: Serialization command * * Return: Status of enqueue in the serialization module */ enum wlan_serialization_status -wlan_vdev_mlme_ser_restart_bss(struct wlan_serialization_command *cmd); +wlan_vdev_mlme_ser_vdev_restart(struct wlan_serialization_command *cmd); + +/** + * wlan_vdev_mlme_ser_pdev_restart() - Add pdev restart cmd to serialization + * @cmd: Serialization command + * + * Return: Status of enqueue in the serialization module + */ +enum wlan_serialization_status +wlan_vdev_mlme_ser_pdev_restart(struct wlan_serialization_command *cmd); /** * wlan_vdev_mlme_ser_connect() - Add connect cmd to serialization @@ -110,4 +119,14 @@ wlan_vdev_mlme_ser_cancel_request(struct wlan_objmgr_vdev *vdev, */ void mlme_ser_inc_act_cmd_timeout(struct wlan_serialization_command *cmd); +/** + * wlan_vdev_mlme_ser_pdev_csa_restart - Add pdev CSA restart cmd to + * serialization + * @cmd: Serialization command + * + * Return: Status of enqueue in the serialization module + */ +enum wlan_serialization_status +wlan_vdev_mlme_ser_pdev_csa_restart(struct wlan_serialization_command *cmd); + #endif /* _WLAN_VDEV_MLME_SER_IF_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/pdev_mgr/dispatcher/inc/wlan_pdev_mlme_api.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/pdev_mgr/dispatcher/inc/wlan_pdev_mlme_api.h index 739832a4b10e3d39b811af8048dc03810b4761ee..4b99fd081274276c5716917bb57e1e7a25a7041a 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/pdev_mgr/dispatcher/inc/wlan_pdev_mlme_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/pdev_mgr/dispatcher/inc/wlan_pdev_mlme_api.h @@ -23,6 +23,7 @@ /** * wlan_pdev_mlme_get_cmpt_obj - Returns MLME component object + * @pdev: PDEV object * * Retrieves MLME component object from PDEV object * @@ -33,12 +34,13 @@ struct pdev_mlme_obj *wlan_pdev_mlme_get_cmpt_obj( struct wlan_objmgr_pdev *pdev); /** * wlan_pdev_mlme_get_ext_hdl - Returns legacy handle + * @pdev: PDEV object * * Retrieves legacy handle from pdev mlme component object * * Return: legacy handle on SUCCESS * NULL, if it fails to retrieve */ -void *wlan_pdev_mlme_get_ext_hdl(struct wlan_objmgr_pdev *pdev); +mlme_pdev_ext_t *wlan_pdev_mlme_get_ext_hdl(struct wlan_objmgr_pdev *pdev); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/pdev_mgr/dispatcher/src/wlan_pdev_mlme_api.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/pdev_mgr/dispatcher/src/wlan_pdev_mlme_api.c index 03b04ac61efaf6bb93a8d863433cb1c6e54109c8..87973069bef9aa7329526b64947c269bc7b90458 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/pdev_mgr/dispatcher/src/wlan_pdev_mlme_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/pdev_mgr/dispatcher/src/wlan_pdev_mlme_api.c @@ -43,7 +43,7 @@ struct pdev_mlme_obj *wlan_pdev_mlme_get_cmpt_obj(struct wlan_objmgr_pdev *pdev) return pdev_mlme; } -void *wlan_pdev_mlme_get_ext_hdl(struct wlan_objmgr_pdev *pdev) +mlme_pdev_ext_t *wlan_pdev_mlme_get_ext_hdl(struct wlan_objmgr_pdev *pdev) { struct pdev_mlme_obj *pdev_mlme; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/psoc_mgr/dispatcher/inc/wlan_psoc_mlme_api.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/psoc_mgr/dispatcher/inc/wlan_psoc_mlme_api.h new file mode 100644 index 0000000000000000000000000000000000000000..f9911ab14c77d3704a5bb090e52ebe0a723fb0cc --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/psoc_mgr/dispatcher/inc/wlan_psoc_mlme_api.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Define PSOC MLME public APIs + */ + +#ifndef _WLAN_PSOC_MLME_API_H_ +#define _WLAN_PSOC_MLME_API_H_ + +/** + * wlan_psoc_mlme_get_cmpt_obj() - Returns PSOC MLME component object + * @psoc: PSOC object + * + * Retrieves MLME component object from PSOC object + * + * Return: comp handle on SUCCESS + * NULL, if it fails to retrieve + */ +struct psoc_mlme_obj *wlan_psoc_mlme_get_cmpt_obj( + struct wlan_objmgr_psoc *psoc); + +/** + * wlan_psoc_mlme_get_ext_hdl() - Returns legacy handle + * @psoc: PSOC object + * + * Retrieves legacy handle from psoc mlme component object + * + * Return: legacy handle on SUCCESS + * NULL, if it fails to retrieve + */ +mlme_psoc_ext_t *wlan_psoc_mlme_get_ext_hdl(struct wlan_objmgr_psoc *psoc); + +/** + * wlan_psoc_mlme_set_ext_hdl() - Set legacy handle + * @psoc_mlme: psoc_mlme object + * psoc_ext_hdl: PSOC level legacy handle + * + * Sets legacy handle in psoc mlme component object + * + * Return: Void + */ +void wlan_psoc_mlme_set_ext_hdl(struct psoc_mlme_obj *psoc_mlme, + mlme_psoc_ext_t *psoc_ext_hdl); + +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/psoc_mgr/dispatcher/src/wlan_psoc_mlme_api.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/psoc_mgr/dispatcher/src/wlan_psoc_mlme_api.c new file mode 100644 index 0000000000000000000000000000000000000000..508d017531b519711c16e1b95ad4555efe6c3942 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/psoc_mgr/dispatcher/src/wlan_psoc_mlme_api.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Implements PSOC MLME public APIs + */ + +#include +#include +#include +#include +#include + +struct psoc_mlme_obj *wlan_psoc_mlme_get_cmpt_obj(struct wlan_objmgr_psoc *psoc) +{ + struct psoc_mlme_obj *psoc_mlme; + + psoc_mlme = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_MLME); + if (!psoc_mlme) { + mlme_err("PSOC MLME component object is NULL"); + return NULL; + } + + return psoc_mlme; +} + +qdf_export_symbol(wlan_psoc_mlme_get_cmpt_obj); + +mlme_psoc_ext_t *wlan_psoc_mlme_get_ext_hdl(struct wlan_objmgr_psoc *psoc) +{ + struct psoc_mlme_obj *psoc_mlme; + + psoc_mlme = wlan_psoc_mlme_get_cmpt_obj(psoc); + if (psoc_mlme) + return psoc_mlme->ext_psoc_ptr; + + return NULL; +} + +qdf_export_symbol(wlan_psoc_mlme_get_ext_hdl); + +void wlan_psoc_mlme_set_ext_hdl(struct psoc_mlme_obj *psoc_mlme, + mlme_psoc_ext_t *psoc_ext_hdl) +{ + psoc_mlme->ext_psoc_ptr = psoc_ext_hdl; +} + +qdf_export_symbol(wlan_psoc_mlme_set_ext_hdl); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.c index fa3002c7689af8d6a9ad3752304b430d8bc8f5e8..7d3bc3c9350ec46f4156e62353bf82ddf0f92c3c 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-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 @@ -34,6 +34,7 @@ #include #include #include +#include static QDF_STATUS vdev_mgr_create_param_update( struct vdev_mlme_obj *mlme_obj, @@ -98,6 +99,7 @@ static QDF_STATUS vdev_mgr_start_param_update( bool set_agile = false, dfs_set_cfreq2 = false; struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_pdev *pdev; + enum QDF_OPMODE op_mode; vdev = mlme_obj->vdev; if (!vdev) { @@ -120,13 +122,23 @@ static QDF_STATUS vdev_mgr_start_param_update( des_chan = wlan_vdev_mlme_get_des_chan(vdev); param->vdev_id = wlan_vdev_get_id(vdev); - tgt_dfs_set_current_channel(pdev, des_chan->ch_freq, - des_chan->ch_flags, - des_chan->ch_flagext, - des_chan->ch_ieee, - des_chan->ch_freq_seg1, - des_chan->ch_freq_seg2); - + op_mode = wlan_vdev_mlme_get_opmode(vdev); + if ((op_mode == QDF_SAP_MODE || op_mode == QDF_P2P_GO_MODE) && + (WLAN_REG_IS_5GHZ_CH_FREQ(des_chan->ch_freq) || + WLAN_REG_IS_49GHZ_FREQ(des_chan->ch_freq) || + WLAN_REG_IS_6GHZ_CHAN_FREQ(des_chan->ch_freq))) { + tgt_dfs_set_current_channel_for_freq(pdev, des_chan->ch_freq, + des_chan->ch_flags, + des_chan->ch_flagext, + des_chan->ch_ieee, + des_chan->ch_freq_seg1, + des_chan->ch_freq_seg2, + des_chan->ch_cfreq1, + des_chan->ch_cfreq2); + if (des_chan->ch_cfreq2) + param->channel.dfs_set_cfreq2 = + utils_is_dfs_cfreq2_ch(pdev); + } param->beacon_interval = mlme_obj->proto.generic.beacon_interval; param->dtim_period = mlme_obj->proto.generic.dtim_period; param->disable_hw_ack = mlme_obj->mgmt.generic.disable_hw_ack; @@ -144,10 +156,14 @@ static QDF_STATUS vdev_mgr_start_param_update( param->channel.mhz = des_chan->ch_freq; param->channel.half_rate = mlme_obj->mgmt.rate_info.half_rate; param->channel.quarter_rate = mlme_obj->mgmt.rate_info.quarter_rate; - param->channel.dfs_set = utils_is_dfs_ch(pdev, param->channel.chan_id); - param->channel.dfs_set_cfreq2 = utils_is_dfs_cfreq2_ch(pdev); + + if (op_mode == QDF_SAP_MODE || op_mode == QDF_P2P_GO_MODE) + param->channel.dfs_set = wlan_reg_is_dfs_for_freq( + pdev, + des_chan->ch_freq); + param->channel.is_chan_passive = - utils_is_dfs_ch(pdev, param->channel.chan_id); + utils_is_dfs_chan_for_freq(pdev, param->channel.mhz); param->channel.allow_ht = mlme_obj->proto.ht_info.allow_ht; param->channel.allow_vht = mlme_obj->proto.vht_info.allow_vht; param->channel.phy_mode = mlme_obj->mgmt.generic.phy_mode; @@ -158,22 +174,25 @@ static QDF_STATUS vdev_mgr_start_param_update( param->channel.maxregpower = mlme_obj->mgmt.generic.maxregpower; param->channel.antennamax = mlme_obj->mgmt.generic.antennamax; param->channel.reg_class_id = mlme_obj->mgmt.generic.reg_class_id; - param->bcn_tx_rate_code = mlme_obj->mgmt.rate_info.bcn_tx_rate; + param->bcn_tx_rate_code = vdev_mgr_fetch_ratecode(mlme_obj); param->ldpc_rx_enabled = mlme_obj->proto.generic.ldpc; + if (mlme_obj->mgmt.generic.type == WLAN_VDEV_MLME_TYPE_AP) { + param->hidden_ssid = mlme_obj->mgmt.ap.hidden_ssid; + param->cac_duration_ms = mlme_obj->mgmt.ap.cac_duration_ms; + } wlan_vdev_mlme_get_ssid(vdev, param->ssid.mac_ssid, ¶m->ssid.length); if (des_chan->ch_phymode == WLAN_PHYMODE_11AC_VHT80 || des_chan->ch_phymode == WLAN_PHYMODE_11AXA_HE80) { - tgt_dfs_find_vht80_chan_for_precac(pdev, - des_chan->ch_phymode, - des_chan->ch_freq_seg1, - ¶m->channel.cfreq1, - ¶m->channel.cfreq2, - ¶m->channel.phy_mode, - &dfs_set_cfreq2, - &set_agile); - + tgt_dfs_find_vht80_precac_chan_freq(pdev, + des_chan->ch_phymode, + des_chan->ch_freq_seg1, + ¶m->channel.cfreq1, + ¶m->channel.cfreq2, + ¶m->channel.phy_mode, + &dfs_set_cfreq2, + &set_agile); param->channel.dfs_set_cfreq2 = dfs_set_cfreq2; param->channel.set_agile = set_agile; } @@ -330,6 +349,8 @@ QDF_STATUS vdev_mgr_up_send(struct vdev_mlme_obj *mlme_obj) struct beacon_tmpl_params bcn_tmpl_param = {0}; enum QDF_OPMODE opmode; struct wlan_objmgr_vdev *vdev; + struct config_fils_params fils_param = {0}; + uint8_t is_6g_sap_fd_enabled; if (!mlme_obj) { mlme_err("VDEV_MLME is NULL"); @@ -357,6 +378,25 @@ QDF_STATUS vdev_mgr_up_send(struct vdev_mlme_obj *mlme_obj) return status; status = tgt_vdev_mgr_up_send(mlme_obj, ¶m); + if (QDF_IS_STATUS_ERROR(status)) + return status; + + is_6g_sap_fd_enabled = wlan_vdev_mlme_feat_ext_cap_get(vdev, + WLAN_VDEV_FEXT_FILS_DISC_6G_SAP); + mlme_debug("SAP FD enabled %d", is_6g_sap_fd_enabled); + if (opmode == QDF_SAP_MODE && mlme_obj->vdev->vdev_mlme.des_chan && + WLAN_REG_IS_6GHZ_CHAN_FREQ( + mlme_obj->vdev->vdev_mlme.des_chan->ch_freq)) { + fils_param.vdev_id = wlan_vdev_get_id(mlme_obj->vdev); + if (is_6g_sap_fd_enabled) { + fils_param.fd_period = DEFAULT_FILS_DISCOVERY_PERIOD; + } else { + fils_param.send_prb_rsp_frame = true; + fils_param.fd_period = DEFAULT_PROBE_RESP_PERIOD; + } + status = tgt_vdev_mgr_fils_enable_send(mlme_obj, + &fils_param); + } return status; } @@ -449,6 +489,7 @@ static QDF_STATUS vdev_mgr_multiple_restart_param_update( uint32_t disable_hw_ack, uint32_t *vdev_ids, uint32_t num_vdevs, + struct vdev_mlme_mvr_param *mvr_param, struct multiple_vdev_restart_params *param) { param->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); @@ -461,6 +502,8 @@ static QDF_STATUS vdev_mgr_multiple_restart_param_update( sizeof(uint32_t) * (param->num_vdevs)); qdf_mem_copy(¶m->ch_param, chan, sizeof(struct mlme_channel_param)); + qdf_mem_copy(param->mvr_param, mvr_param, + sizeof(*mvr_param) * (param->num_vdevs)); return QDF_STATUS_SUCCESS; } @@ -469,14 +512,15 @@ QDF_STATUS vdev_mgr_multiple_restart_send(struct wlan_objmgr_pdev *pdev, struct mlme_channel_param *chan, uint32_t disable_hw_ack, uint32_t *vdev_ids, - uint32_t num_vdevs) + uint32_t num_vdevs, + struct vdev_mlme_mvr_param *mvr_param) { struct multiple_vdev_restart_params param = {0}; vdev_mgr_multiple_restart_param_update(pdev, chan, disable_hw_ack, vdev_ids, num_vdevs, - ¶m); + mvr_param, ¶m); return tgt_vdev_mgr_multiple_vdev_restart_send(pdev, ¶m); } @@ -526,3 +570,41 @@ QDF_STATUS vdev_mgr_set_custom_aggr_size_send( return tgt_vdev_mgr_set_custom_aggr_size_send(vdev_mlme, ¶m); } + +static QDF_STATUS vdev_mgr_peer_delete_all_param_update( + struct vdev_mlme_obj *mlme_obj, + struct peer_delete_all_params *param) +{ + struct wlan_objmgr_vdev *vdev; + + vdev = mlme_obj->vdev; + if (!vdev) { + mlme_err("VDEV is NULL"); + return QDF_STATUS_E_INVAL; + } + + param->vdev_id = wlan_vdev_get_id(vdev); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS vdev_mgr_peer_delete_all_send(struct vdev_mlme_obj *mlme_obj) +{ + QDF_STATUS status; + struct peer_delete_all_params param = {0}; + + if (!mlme_obj) { + mlme_err("Invalid input"); + return QDF_STATUS_E_INVAL; + } + + status = vdev_mgr_peer_delete_all_param_update(mlme_obj, ¶m); + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("Param Update Error: %d", status); + return status; + } + + status = tgt_vdev_mgr_peer_delete_all_send(mlme_obj, ¶m); + + return status; +} + diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.h index 9ce437d87cbd03f34a2b0ad331b480d3c17e7125..f6461213aba55da257b950650f2142d79700f24e 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mgr_ops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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 @@ -26,7 +26,6 @@ #ifndef __VDEV_MGR_OPS_H__ #define __VDEV_MGR_OPS_H__ -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE #include #include #include @@ -220,14 +219,35 @@ QDF_STATUS vdev_mgr_bcn_miss_offload_send(struct vdev_mlme_obj *mlme_obj); * @disable_hw_ack: ddisable hw ack value * @vdev_ids: pointer to list of vdev ids which require restart * @num_vdevs: number of vdevs in list + * @mvr_param: multiple vdev restart param * * Return: QDF_STATUS - Success or Failure */ -QDF_STATUS vdev_mlme_multiple_restart_send(struct wlan_objmgr_pdev *pdev, - struct mlme_channel_param *chan, - uint32_t disable_hw_ack, - uint32_t *vdev_ids, - uint32_t num_vdevs); +QDF_STATUS vdev_mgr_multiple_restart_send( + struct wlan_objmgr_pdev *pdev, + struct mlme_channel_param *chan, + uint32_t disable_hw_ack, + uint32_t *vdev_ids, + uint32_t num_vdevs, + struct vdev_mlme_mvr_param *mvr_param); -#endif /* CMN_VDEV_MGR_TGT_IF_ENABLE */ +/** + * vdev_mgr_peer_delete_all_send() – MLME API to send peer delete all request + * @mlme_obj: pointer to vdev_mlme_obj + * + * Return: QDF_STATUS - Success or Failure + */ +QDF_STATUS vdev_mgr_peer_delete_all_send(struct vdev_mlme_obj *mlme_obj); + +#ifdef WLAN_BCN_RATECODE_ENABLE +static inline uint32_t vdev_mgr_fetch_ratecode(struct vdev_mlme_obj *mlme_obj) +{ + return mlme_obj->mgmt.rate_info.bcn_tx_rate_code; +} +#else +static inline uint32_t vdev_mgr_fetch_ratecode(struct vdev_mlme_obj *mlme_obj) +{ + return mlme_obj->mgmt.rate_info.bcn_tx_rate; +} +#endif #endif /* __VDEV_MGR_OPS_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm.c index b512e6e6d665a8270c5f342ebf69d43f2c345f43..47d178eb3af52f870a9fe4b72e650ba887a15e3e 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm.c @@ -920,7 +920,12 @@ static bool mlme_vdev_subst_start_conn_progress_event(void *ctx, case WLAN_VDEV_SM_EV_CONN_PROGRESS: /* This API decides to move to DFS CAC WAIT or UP state, * for station notify connection state machine */ - mlme_vdev_start_continue(vdev_mlme, event_data_len, event_data); + if (mlme_vdev_start_continue(vdev_mlme, event_data_len, + event_data) != QDF_STATUS_SUCCESS) + mlme_vdev_sm_deliver_event( + vdev_mlme, + WLAN_VDEV_SM_EV_CONNECTION_FAIL, + event_data_len, event_data); status = true; break; @@ -1369,6 +1374,19 @@ static bool mlme_vdev_subst_suspend_csa_restart_event(void *ctx, bool status; switch (event) { + case WLAN_VDEV_SM_EV_CHAN_SWITCH_DISABLED: + /** + * This event is sent when CSA count becomes 0 without + * change in channel i.e. only Beacon Probe response template + * is updated (CSA / ECSA IE is removed). + */ + + mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_UP); + mlme_vdev_sm_deliver_event(vdev_mlme, + WLAN_VDEV_SM_EV_UP_HOST_RESTART, + event_data_len, event_data); + status = true; + break; case WLAN_VDEV_SM_EV_CSA_RESTART: mlme_vdev_update_beacon(vdev_mlme, BEACON_CSA, event_data_len, event_data); @@ -1635,6 +1653,7 @@ static const char *vdev_sm_event_names[] = { "EV_DOWN_COMPLETE", "EV_ROAM", "EV_STOP_REQ", + "EV_CHAN_SWITCH_DISABLED", }; struct wlan_sm_state_info sm_info[] = { diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm.h index 22ecfcd71f2ddc1891e154582e2c3d98eee5ff74..deb784b49a122b3d5a1808cf5b89eed77049fb68 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/core/src/vdev_mlme_sm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 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 @@ -97,6 +97,489 @@ QDF_STATUS mlme_vdev_sm_create(struct vdev_mlme_obj *vdev_mlme); */ QDF_STATUS mlme_vdev_sm_destroy(struct vdev_mlme_obj *vdev_mlme); +/** + * mlme_vdev_validate_basic_params - Validate basic params + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API validate MLME VDEV basic parameters + * + * Return: SUCCESS on successful validation + * FAILURE, if any parameter is not initialized + */ +static inline QDF_STATUS mlme_vdev_validate_basic_params( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_validate_basic_params) + ret = vdev_mlme->ops->mlme_vdev_validate_basic_params( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_reset_proto_params - Reset VDEV protocol params + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API resets the protocol params fo vdev + * + * Return: SUCCESS on successful reset + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_reset_proto_params( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_reset_proto_params) + ret = vdev_mlme->ops->mlme_vdev_reset_proto_params( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_start_send - Invokes VDEV start operation + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API invokes VDEV start operation + * + * Return: SUCCESS on successful completion of start operation + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_start_send( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_start_send) + ret = vdev_mlme->ops->mlme_vdev_start_send( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_restart_send - Invokes VDEV restart operation + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API invokes VDEV restart operation + * + * Return: SUCCESS on successful completion of restart operation + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_restart_send( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_restart_send) + ret = vdev_mlme->ops->mlme_vdev_restart_send( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_stop_start_send - Invoke block VDEV restart operation + * @vdev_mlme_obj: VDEV MLME comp object + * @restart: restart req/start req + * @event_data_len: data size + * @event_data: event data + * + * API invokes stops pending VDEV restart operation + * + * Return: SUCCESS alsways + */ +static inline QDF_STATUS mlme_vdev_stop_start_send( + struct vdev_mlme_obj *vdev_mlme, + uint8_t restart, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_stop_start_send) + ret = vdev_mlme->ops->mlme_vdev_stop_start_send( + vdev_mlme, restart, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_start_continue - VDEV start response handling + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API invokes VDEV start response actions + * + * Return: SUCCESS on successful completion of start response operation + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_start_continue( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_start_continue) + ret = vdev_mlme->ops->mlme_vdev_start_continue( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_start_req_failed - Invoke Station VDEV connection, if it pause + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API invokes on START fail response + * + * Return: SUCCESS on successful invocation of callback + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_start_req_failed( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_start_req_failed) + ret = vdev_mlme->ops->mlme_vdev_start_req_failed( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_sta_conn_start - Invoke Station VDEV connection, if it pause + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API invokes connection SM to start station connection + * + * Return: SUCCESS on successful invocation of connection sm + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_sta_conn_start( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_sta_conn_start) + ret = vdev_mlme->ops->mlme_vdev_sta_conn_start( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_up_send - VDEV up operation + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API invokes VDEV up operations + * + * Return: SUCCESS on successful completion of up operation + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_up_send( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_up_send) + ret = vdev_mlme->ops->mlme_vdev_up_send( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_notify_up_complete - VDEV up state transition notification + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API notifies MLME on moving to UP state + * + * Return: SUCCESS on successful completion of up notification + * FAILURE, if it fails due to any + */ +static inline +QDF_STATUS mlme_vdev_notify_up_complete(struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, + void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if (vdev_mlme->ops && vdev_mlme->ops->mlme_vdev_notify_up_complete) + ret = vdev_mlme->ops->mlme_vdev_notify_up_complete( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_notify_roam_start - VDEV Roaming notification + * @vdev_mlme_obj: VDEV MLME comp object + * @event_len: data size + * @event_data: event data + * + * API notifies MLME on roaming + * + * Return: SUCCESS on successful completion of up notification + * FAILURE, if it fails due to any + */ +static inline +QDF_STATUS mlme_vdev_notify_roam_start(struct vdev_mlme_obj *vdev_mlme, + uint16_t event_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if (vdev_mlme->ops && vdev_mlme->ops->mlme_vdev_notify_roam_start) + ret = vdev_mlme->ops->mlme_vdev_notify_roam_start(vdev_mlme, + event_len, + event_data); + + return ret; +} + +/** + * mlme_vdev_update_beacon - Updates beacon + * @vdev_mlme_obj: VDEV MLME comp object + * @op: beacon update type + * @event_data_len: data size + * @event_data: event data + * + * API updates/allocates/frees the beacon + * + * Return: SUCCESS on successful update of beacon + * FAILURE, if it fails due to any + */ +static inline +QDF_STATUS mlme_vdev_update_beacon(struct vdev_mlme_obj *vdev_mlme, + enum beacon_update_op op, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if (vdev_mlme->ops && vdev_mlme->ops->mlme_vdev_update_beacon) + ret = vdev_mlme->ops->mlme_vdev_update_beacon(vdev_mlme, op, + event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_disconnect_peers - Disconnect peers + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API trigger stations disconnection with AP VDEV or AP disconnection with STA + * VDEV + * + * Return: SUCCESS on successful invocation of station disconnection + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_disconnect_peers( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_disconnect_peers) + ret = vdev_mlme->ops->mlme_vdev_disconnect_peers( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_dfs_cac_timer_stop - Stop CAC timer + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API stops the CAC timer through DFS API + * + * Return: SUCCESS on successful CAC timer stop + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_dfs_cac_timer_stop( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_dfs_cac_timer_stop) + ret = vdev_mlme->ops->mlme_vdev_dfs_cac_timer_stop( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_stop_send - Invokes VDEV stop operation + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API invokes VDEV stop operation + * + * Return: SUCCESS on successful completion of stop operation + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_stop_send( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_stop_send) + ret = vdev_mlme->ops->mlme_vdev_stop_send( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_stop_continue - VDEV stop response handling + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API invokes VDEV stop response actions + * + * Return: SUCCESS on successful completion of stop response operation + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_stop_continue( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_stop_continue) + ret = vdev_mlme->ops->mlme_vdev_stop_continue(vdev_mlme, + event_data_len, + event_data); + + return ret; +} + +/** + * mlme_vdev_down_send - VDEV down operation + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API invokes VDEV down operation + * + * Return: SUCCESS on successful completion of VDEV down operation + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_down_send( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_down_send) + ret = vdev_mlme->ops->mlme_vdev_down_send( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_notify_down_complete - VDEV init state transition notification + * @vdev_mlme_obj: VDEV MLME comp object + * @event_data_len: data size + * @event_data: event data + * + * API notifies MLME on moving to INIT state + * + * Return: SUCCESS on successful completion of down notification + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_notify_down_complete( + struct vdev_mlme_obj *vdev_mlme, + uint16_t event_data_len, void *event_data) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_notify_down_complete) + ret = vdev_mlme->ops->mlme_vdev_notify_down_complete( + vdev_mlme, event_data_len, event_data); + + return ret; +} + +/** + * mlme_vdev_notify_start_state_exit - VDEV SM start state exit notification + * @vdev_mlme_obj: VDEV MLME comp object + * + * API notifies on start state exit + * + * Return: SUCCESS on successful completion of notification + * FAILURE, if it fails due to any + */ +static inline QDF_STATUS mlme_vdev_notify_start_state_exit( + struct vdev_mlme_obj *vdev_mlme) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && + vdev_mlme->ops->mlme_vdev_notify_start_state_exit) + ret = vdev_mlme->ops->mlme_vdev_notify_start_state_exit( + vdev_mlme); + + return ret; +} + +/** + * mlme_vdev_is_newchan_no_cac - Checks new channel requires CAC + * @vdev_mlme_obj: VDEV MLME comp object + * + * API checks whether Channel needs CAC period, + * if yes, it moves to SUSPEND_RESTART to disconnect stations before + * sending RESTART to FW, otherwise, it moves to RESTART_PROGRESS substate + * + * Return: SUCCESS to move to RESTART_PROGRESS substate + * FAILURE, move to SUSPEND_RESTART state + */ +static inline QDF_STATUS mlme_vdev_is_newchan_no_cac( + struct vdev_mlme_obj *vdev_mlme) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_is_newchan_no_cac) + ret = vdev_mlme->ops->mlme_vdev_is_newchan_no_cac(vdev_mlme); + + return ret; +} + #ifdef VDEV_SM_LOCK_SUPPORT /** * mlme_vdev_sm_spinlock_create - Create VDEV MLME spinlock @@ -208,13 +691,13 @@ static inline void mlme_vdev_cmd_mutex_release(struct vdev_mlme_obj *vdev_mlme) #else static inline void mlme_vdev_sm_spinlock_create(struct vdev_mlme_obj *vdev_mlme) { - mlme_info("VDEV SM lock is disabled!!!"); + mlme_debug("VDEV SM lock is disabled!!!"); } static inline void mlme_vdev_sm_spinlock_destroy( struct vdev_mlme_obj *vdev_mlme) { - mlme_info("VDEV SM lock is disabled!!!"); + mlme_debug("VDEV SM lock is disabled!!!"); } static inline void mlme_vdev_sm_spin_lock(struct vdev_mlme_obj *vdev_mlme) @@ -228,13 +711,13 @@ static inline void mlme_vdev_sm_spin_unlock(struct vdev_mlme_obj *vdev_mlme) static inline void mlme_vdev_cmd_mutex_create(struct vdev_mlme_obj *vdev_mlme) { - mlme_info("VDEV CMD lock is disabled!!!"); + mlme_debug("VDEV CMD lock is disabled!!!"); } static inline void mlme_vdev_cmd_mutex_destroy(struct vdev_mlme_obj *vdev_mlme) { - mlme_info("VDEV CMD lock is disabled!!!"); + mlme_debug("VDEV CMD lock is disabled!!!"); } static inline void mlme_vdev_cmd_mutex_acquire(struct vdev_mlme_obj *vdev_mlme) diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_api.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_api.h index b8b650566f50d4082eb30614bd3d7a6e064bbf72..893b76185aed147cb4714d75ac126ddbbfebed37 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_api.h @@ -25,26 +25,37 @@ #ifndef __WLAN_VDEV_MGR_RX_OPS_H__ #define __WLAN_VDEV_MGR_RX_OPS_H__ -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE #include #include /** - * tgt_vdev_mgr_register_rx_ops(): API to register rx ops with lmac + * tgt_vdev_mgr_register_rx_ops() - API to register rx ops with lmac * @rx_ops: rx ops struct * * Return: none */ void tgt_vdev_mgr_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops); -#else + /** - * tgt_vdev_mgr_register_rx_ops(): API to register rx ops with lmac - * @rx_ops: rx ops struct + * tgt_vdev_mgr_ext_tbttoffset_update_handle() - API to handle ext tbtt offset + * update event + * @num_vdevs: number of vdevs + * @is_ext: ext is set/reset * - * Return: none + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +tgt_vdev_mgr_ext_tbttoffset_update_handle(uint32_t num_vdevs, bool is_ext); + +/** + * tgt_vdev_mgr_get_response_timer_info() - API to get vdev_mgr timer info + * @psoc: objmgr psoc object + * @vdev_id: vdev id + * + * Return: struct vdev_response_timer on success else NULL */ -static inline void -tgt_vdev_mgr_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) {} -#endif /* CMN_VDEV_MGR_TGT_IF_ENABLE */ +struct vdev_response_timer * +tgt_vdev_mgr_get_response_timer_info(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id); #endif /* __WLAN_VDEV_MGR_RX_OPS_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_defs.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_defs.h index 2dce8e791034e545eca83933507c0a2af06215be..4495ae8c3bad852c47ab27678615f2646e289166 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_defs.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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 @@ -27,30 +27,77 @@ #define __WLAN_VDEV_MGR_TGT_IF_RX_DEFS_H__ #include +#include +#ifdef FEATURE_RUNTIME_PM +#include +#endif -#define START_RESPONSE_BIT 0x1 -#define RESTART_RESPONSE_BIT 0x2 -#define STOP_RESPONSE_BIT 0x3 -#define DELETE_RESPONSE_BIT 0x4 -#define RESPONSE_BIT_MAX (START_RESPONSE_BIT | RESTART_RESPONSE_BIT |\ - STOP_RESPONSE_BIT | DELETE_RESPONSE_BIT) +/** + * enum wlan_vdev_mgr_tgt_if_rsp_bit - response status bit + * START_RESPONSE_BIT: vdev start response bit + * RESTART_RESPONSE_BIT: vdev restart response bit + * STOP_RESPONSE_BIT: vdev stop response bit + * DELETE_RESPONSE_BIT: vdev delete response bit + * PEER_DELETE_ALL_RESPONSE_BIT: vdev peer delete all response bit + */ +enum wlan_vdev_mgr_tgt_if_rsp_bit { + START_RESPONSE_BIT = 0, + RESTART_RESPONSE_BIT = 1, + STOP_RESPONSE_BIT = 2, + DELETE_RESPONSE_BIT = 3, + PEER_DELETE_ALL_RESPONSE_BIT = 4, + RESPONSE_BIT_MAX, +}; -#define START_RESPONSE_TIMER 6000 /* 6 seconds */ -#define STOP_RESPONSE_TIMER 3000 /* 3 seconds */ -#define DELETE_RESPONSE_TIMER 3000 /* 3 seconds */ +/** + * string_from_rsp_bit() - Convert response bit to string + * @bit - response bit as in wlan_vdev_mgr_tgt_if_rsp_bit + * + * Please note to add new string in the array at index equal to + * its enum value in wlan_vdev_mgr_tgt_if_rsp_bit. + */ +static inline char *string_from_rsp_bit(enum wlan_vdev_mgr_tgt_if_rsp_bit bit) +{ + static const char *strings[] = { "START", + "RESTART", + "STOP", + "DELETE", + "PEER DELETE ALL", + "RESPONE MAX"}; + return (char *)strings[bit]; +} + +#ifdef FEATURE_RUNTIME_PM +/* Add extra PMO_RESUME_TIMEOUT for runtime PM resume timeout */ +#define START_RESPONSE_TIMER (6000 + PMO_RESUME_TIMEOUT) +#define STOP_RESPONSE_TIMER (4000 + PMO_RESUME_TIMEOUT) +#define DELETE_RESPONSE_TIMER (4000 + PMO_RESUME_TIMEOUT) +#define PEER_DELETE_ALL_RESPONSE_TIMER (6000 + PMO_RESUME_TIMEOUT) +#else +#define START_RESPONSE_TIMER 6000 +#define STOP_RESPONSE_TIMER 4000 +#define DELETE_RESPONSE_TIMER 4000 +#define PEER_DELETE_ALL_RESPONSE_TIMER 6000 +#endif /** * struct vdev_response_timer - vdev mgmt response ops timer + * @psoc: Object manager psoc * @rsp_timer: VDEV MLME mgmt response timer * @rsp_status: variable to check response status * @expire_time: time to expire timer * @timer_status: status of timer + * @rsp_timer_inuse: Status bit to inform whether the rsp timer is inuse + * @vdev_id: vdev object id */ struct vdev_response_timer { + struct wlan_objmgr_psoc *psoc; qdf_timer_t rsp_timer; unsigned long rsp_status; uint32_t expire_time; QDF_STATUS timer_status; + qdf_atomic_t rsp_timer_inuse; + uint8_t vdev_id; }; /** @@ -64,6 +111,7 @@ struct vdev_response_timer { * @mac_id: mac id * @cfgd_tx_streams: configured tx streams * @cfgd_rx_streams: configured rx streams + * @max_allowed_tx_power: max tx power allowed */ struct vdev_start_response { uint8_t vdev_id; @@ -75,6 +123,7 @@ struct vdev_start_response { uint32_t mac_id; uint32_t cfgd_tx_streams; uint32_t cfgd_rx_streams; + uint32_t max_allowed_tx_power; }; /** @@ -93,4 +142,27 @@ struct vdev_delete_response { uint8_t vdev_id; }; +/** + * struct peer_delete_all_response - peer delete all response structure + * @vdev_id: vdev id + * @status: FW status for vdev delete all peer request + */ +struct peer_delete_all_response { + uint8_t vdev_id; + uint8_t status; +}; + +#define VDEV_ID_BMAP_SIZE 2 +/** + * struct multi_vdev_restart_resp - multi-vdev restart response structure + * @pdev_id: pdev id + * @status: FW status for multi vdev restart request + * @vdev_id_bmap: Bitmap of vdev_ids + */ +struct multi_vdev_restart_resp { + uint8_t pdev_id; + uint8_t status; + unsigned long vdev_id_bmap[VDEV_ID_BMAP_SIZE]; +}; + #endif /* __WLAN_VDEV_MGR_TGT_IF_RX_DEFS_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_api.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_api.h index bb50fefbcaaee0f1565c038a71bb6cebd4803b71..ddca045633c64707a9b01e9b4fca1eb948c793c2 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_api.h @@ -27,7 +27,6 @@ #ifndef __WLAN_VDEV_MGR_TX_OPS_API_H__ #define __WLAN_VDEV_MGR_TX_OPS_API_H__ -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE #include #include #include @@ -222,6 +221,33 @@ QDF_STATUS tgt_vdev_mgr_beacon_tmpl_send( struct vdev_mlme_obj *mlme_obj, struct beacon_tmpl_params *param); +#if defined(WLAN_SUPPORT_FILS) || defined(CONFIG_BAND_6GHZ) +/** + * tgt_vdev_mgr_fils_enable_send()- API to send fils enable command + * @mlme_obj: pointer to vdev_mlme_obj + * @param: pointer to config_fils_params struct + * + * Return: QDF_STATUS - Success or Failure + */ +QDF_STATUS tgt_vdev_mgr_fils_enable_send( + struct vdev_mlme_obj *mlme_obj, + struct config_fils_params *param); +#else +/** + * tgt_vdev_mgr_fils_enable_send()- API to send fils enable command + * @mlme_obj: pointer to vdev_mlme_obj + * @param: pointer to config_fils_params struct + * + * Return: QDF_STATUS - Success or Failure + */ +static inline QDF_STATUS tgt_vdev_mgr_fils_enable_send( + struct vdev_mlme_obj *mlme_obj, + struct config_fils_params *param) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * tgt_vdev_mgr_multiple_vdev_restart_send() – API to send multiple vdev * restart @@ -234,6 +260,18 @@ QDF_STATUS tgt_vdev_mgr_multiple_vdev_restart_send( struct wlan_objmgr_pdev *pdev, struct multiple_vdev_restart_params *param); +/** + * tgt_vdev_mgr_set_tx_rx_decap_type() – API to send tx rx decap type + * @mlme_obj: pointer to vdev mlme obj + * @param_id: param id + * value: value to set for param id + * + * Return: QDF_STATUS - Success or Failure + */ +QDF_STATUS tgt_vdev_mgr_set_tx_rx_decap_type(struct vdev_mlme_obj *mlme_obj, + enum wlan_mlme_cfg_id param_id, + uint32_t value); + /** * tgt_vdev_mgr_set_param_send() – API to send parameter cfg * @mlme_obj: pointer to vdev_mlme_obj @@ -253,5 +291,15 @@ QDF_STATUS tgt_vdev_mgr_set_param_send( */ QDF_STATUS tgt_vdev_mgr_bcn_miss_offload_send(struct vdev_mlme_obj *mlme_obj); -#endif /* CMN_VDEV_MGR_TGT_IF_ENABLE */ +/** + * tgt_vdev_mgr_peer_delete_all_send() – API to send peer delete all request + * @mlme_obj: pointer to vdev_mlme_obj + * @param: pointer to peer_delete_all_params + * + * Return: QDF_STATUS - Success or Failure + */ +QDF_STATUS tgt_vdev_mgr_peer_delete_all_send( + struct vdev_mlme_obj *mlme_obj, + struct peer_delete_all_params *param); + #endif /* __WLAN_VDEV_MGR_TX_OPS_API_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_defs.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_defs.h index 71e1b9f51575e43167f45ba7c8d34dbaea98ca93..51283ab146fd62956b0335efa2f0ab93b4855ff1 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_defs.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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,7 +25,6 @@ #ifndef __WLAN_VDEV_MGR_TX_OPS_DEFS_H__ #define __WLAN_VDEV_MGR_TX_OPS_DEFS_H__ -#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE #include /** @@ -83,9 +82,38 @@ enum wlan_mlme_host_vdev_start_status { WLAN_MLME_HOST_VDEV_START_CHAN_INVALID, WLAN_MLME_HOST_VDEV_START_CHAN_BLOCKED, WLAN_MLME_HOST_VDEV_START_CHAN_DFS_VIOLATION, + WLAN_MLME_HOST_VDEV_START_CHAN_INVALID_REGDOMAIN, + WLAN_MLME_HOST_VDEV_START_CHAN_INVALID_BAND, WLAN_MLME_HOST_VDEV_START_TIMEOUT, + /* Add new response status code from here */ + WLAN_MLME_HOST_VDEV_START_MAX_REASON, }; +/** + * string_from_start_rsp_status() - Convert start response status to string + * @start_rsp - start response status + * + * Please note to add new string in the array at index equal to + * its enum value in wlan_mlme_host_vdev_start_status. + */ +static inline char *string_from_start_rsp_status( + enum wlan_mlme_host_vdev_start_status start_rsp) +{ + static const char *strings[] = { "START_OK", + "CHAN_INVALID", + "CHAN_BLOCKED", + "CHAN_DFS_VIOLATION", + "CHAN_INVALID_REGDOMAIN", + "CHAN_INVALID_BAND", + "START_RESPONSE_TIMEOUT", + "START_RESPONSE_UNKNOWN"}; + + if (start_rsp >= WLAN_MLME_HOST_VDEV_START_MAX_REASON) + start_rsp = WLAN_MLME_HOST_VDEV_START_MAX_REASON; + + return (char *)strings[start_rsp]; +} + /** * enum wlan_mlme_host_start_event_param - start/restart resp event */ @@ -122,10 +150,14 @@ struct sta_ps_params { * struct tbttoffset_params - Tbttoffset event params * @vdev_id: Virtual AP device identifier * @tbttoffset : Tbttoffset for the virtual AP device + * @vdev_tbtt_qtime_lo: Tbtt qtime low value + * @vdev_tbtt_qtime_hi: Tbtt qtime high value */ struct tbttoffset_params { uint32_t vdev_id; uint32_t tbttoffset; + uint32_t vdev_tbtt_qtime_lo; + uint32_t vdev_tbtt_qtime_hi; }; /** @@ -138,6 +170,7 @@ struct tbttoffset_params { * @csa_switch_count_offset: CSA swith count offset in beacon frame * @ext_csa_switch_count_offset: ECSA switch count offset in beacon frame * @esp_ie_offset: ESP IE offset in beacon frame + * @mu_edca_ie_offset: Mu EDCA IE offset in beacon frame * @frm: beacon template parameter */ struct beacon_tmpl_params { @@ -149,6 +182,7 @@ struct beacon_tmpl_params { uint32_t csa_switch_count_offset; uint32_t ext_csa_switch_count_offset; uint32_t esp_ie_offset; + uint32_t mu_edca_ie_offset; uint8_t *frm; }; @@ -174,6 +208,19 @@ struct beacon_params { bool is_high_latency; }; +/* struct fils_discovery_tmpl_params - FILS Discovery template cmd parameter + * @vdev_id: vdev ID + * @tmpl_len: FILS Discovery template length + * @tmpl_aligned: FILS Discovery template alignment + * @frm: FILS Discovery template parameter + */ +struct fils_discovery_tmpl_params { + uint8_t vdev_id; + uint32_t tmpl_len; + uint32_t tmpl_len_aligned; + uint8_t *frm; +}; + /** * struct mlme_channel_param - Channel parameters with all * info required by target. @@ -219,6 +266,14 @@ struct mlme_channel_param { uint8_t reg_class_id; }; +/** + * struct vdev_mlme_mvr_param - Multiple vdev restart params + * @phymode: phymode information + */ +struct vdev_mlme_mvr_param { + uint32_t phymode; +}; + /** * struct multiple_vdev_restart_params - Multiple vdev restart cmd parameter * @pdev_id: Pdev identifier @@ -228,6 +283,7 @@ struct mlme_channel_param { * @num_vdevs: No. of vdevs that need to be restarted * @ch_param: Pointer to channel_param * @vdev_ids: Pointer to array of vdev_ids + * @mvr_param: array holding multi vdev restart param */ struct multiple_vdev_restart_params { uint32_t pdev_id; @@ -237,6 +293,7 @@ struct multiple_vdev_restart_params { uint32_t num_vdevs; struct mlme_channel_param ch_param; uint32_t vdev_ids[WLAN_UMAC_PDEV_MAX_VDEVS]; + struct vdev_mlme_mvr_param mvr_param[WLAN_UMAC_PDEV_MAX_VDEVS]; }; /** @@ -251,6 +308,22 @@ struct peer_flush_params { uint8_t peer_mac[QDF_MAC_ADDR_SIZE]; }; +/* Default FILS DISCOVERY/probe response sent in period of 20TU */ +#define DEFAULT_FILS_DISCOVERY_PERIOD 20 +#define DEFAULT_PROBE_RESP_PERIOD 20 + +/** + * struct config_fils_params - FILS config params + * @vdev_id: vdev id + * @fd_period: 0 - Disabled, non-zero - Period in ms (mili seconds) + * @send_prb_rsp_frame: send broadcast prb resp frame + */ +struct config_fils_params { + uint8_t vdev_id; + uint32_t fd_period; + uint32_t send_prb_rsp_frame: 1; +}; + /** * struct config_ratemask_params - ratemask config parameters * @vdev_id: vdev id @@ -258,6 +331,7 @@ struct peer_flush_params { * @lower32: Lower 32 bits in the 1st 64-bit value * @higher32: Higher 32 bits in the 1st 64-bit value * @lower32_2: Lower 32 bits in the 2nd 64-bit value + * @higher32_2: Higher 32 bits in the 2nd 64-bit value */ struct config_ratemask_params { uint8_t vdev_id; @@ -265,6 +339,7 @@ struct config_ratemask_params { uint32_t lower32; uint32_t higher32; uint32_t lower32_2; + uint32_t higher32_2; }; /** @@ -442,5 +517,12 @@ struct vdev_down_params { uint8_t vdev_id; }; -#endif +/** + * struct peer_delete_all_params - peer delete all request parameter + * @vdev_id: vdev id + */ +struct peer_delete_all_params { + uint8_t vdev_id; +}; + #endif /* __WLAN_VDEV_MGR_TX_OPS_DEFS_H__ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_ucfg_api.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_ucfg_api.h index 3b6bab0b96487ca97d187b6e8e592680215f3c72..484175b71b8ad0d1fe6279e2d73f946829ec7a20 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_ucfg_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_ucfg_api.h @@ -92,7 +92,7 @@ enum wlan_mlme_cfg_id { WLAN_MLME_CFG_TYPE, WLAN_MLME_CFG_SUBTYPE, WLAN_MLME_CFG_UAPSD, - WLAN_MLME_CFG_TX_DECAP_TYPE, + WLAN_MLME_CFG_TX_ENCAP_TYPE, WLAN_MLME_CFG_RX_DECAP_TYPE, WLAN_MLME_CFG_RATEMASK_TYPE, WLAN_MLME_CFG_RATEMASK_LOWER32, @@ -101,6 +101,8 @@ enum wlan_mlme_cfg_id { WLAN_MLME_CFG_BCN_TX_RATE, WLAN_MLME_CFG_BCN_TX_RATE_CODE, WLAN_MLME_CFG_RATEMASK_CAPS, + WLAN_MLME_CFG_ENABLE_MULTI_GROUP_KEY, + WLAN_MLME_CFG_MAX_GROUP_KEYS, WLAN_MLME_CFG_MAX }; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mlme_api.h b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mlme_api.h index 278da74f597ce03372573da4c2e3c76ea8a3531d..11945cc8c4caee6086229db56af35c946fb784da 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mlme_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mlme_api.h @@ -21,6 +21,7 @@ #ifndef _WLAN_VDEV_MLME_API_H_ #define _WLAN_VDEV_MLME_API_H_ +#include /** * wlan_vdev_mlme_get_cmpt_obj - Retrieves MLME component object * from VDEV object @@ -42,7 +43,8 @@ struct vdev_mlme_obj *wlan_vdev_mlme_get_cmpt_obj( * * Return: */ -void wlan_vdev_mlme_set_ext_hdl(struct wlan_objmgr_vdev *vdev, void *ext_hdl); +void wlan_vdev_mlme_set_ext_hdl(struct wlan_objmgr_vdev *vdev, + mlme_vdev_ext_t *ext_hdl); /** * wlan_vdev_mlme_get_ext_hdl - Returns legacy handle @@ -53,7 +55,7 @@ void wlan_vdev_mlme_set_ext_hdl(struct wlan_objmgr_vdev *vdev, void *ext_hdl); * Return: legacy handle on SUCCESS * NULL, if it fails to retrieve */ -void *wlan_vdev_mlme_get_ext_hdl(struct wlan_objmgr_vdev *vdev); +mlme_vdev_ext_t *wlan_vdev_mlme_get_ext_hdl(struct wlan_objmgr_vdev *vdev); /** * wlan_vdev_mlme_sm_deliver_evt() - Delivers event to VDEV MLME SM diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_rx_api.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_rx_api.c index b7584b9d3ca02c51775f1638ccda2df250d2d866..2979d716a30b7d983b9f3142962b139f1e63b3ed 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_rx_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_rx_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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 @@ -22,27 +22,40 @@ * This file provide definition for APIs registered for LMAC MLME Rx Ops */ #include +#include #include #include #include #include #include #include +#include +#include +#include -static struct vdev_response_timer * -tgt_vdev_mgr_get_response_timer_info(struct wlan_objmgr_vdev *vdev) +struct vdev_response_timer * +tgt_vdev_mgr_get_response_timer_info(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) { - struct vdev_mlme_obj *vdev_mlme; + struct psoc_mlme_obj *psoc_mlme; - vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); - if (!vdev_mlme) { - mlme_err("VDEV_%d: VDEV_MLME is NULL", wlan_vdev_get_id(vdev)); + if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) { + mlme_err("Incorrect vdev_id: %d", vdev_id); return NULL; } - return &vdev_mlme->vdev_rt; + psoc_mlme = mlme_psoc_get_priv(psoc); + if (!psoc_mlme) { + mlme_err("VDEV_%d PSOC_%d PSOC_MLME is NULL", vdev_id, + wlan_psoc_get_id(psoc)); + return NULL; + } + + return &psoc_mlme->psoc_vdev_rt[vdev_id]; } +qdf_export_symbol(tgt_vdev_mgr_get_response_timer_info); + static QDF_STATUS tgt_vdev_mgr_start_response_handler( struct wlan_objmgr_psoc *psoc, struct vdev_start_response *rsp) @@ -50,8 +63,6 @@ static QDF_STATUS tgt_vdev_mgr_start_response_handler( QDF_STATUS status = QDF_STATUS_E_FAILURE; struct vdev_mlme_obj *vdev_mlme; struct wlan_objmgr_vdev *vdev; - struct vdev_response_timer *vdev_rsp; - struct wlan_lmac_if_mlme_tx_ops *tx_ops; if (!rsp || !psoc) { mlme_err("Invalid input"); @@ -67,25 +78,8 @@ static QDF_STATUS tgt_vdev_mgr_start_response_handler( vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); if (!vdev_mlme) { - mlme_err("VDEV_%d: VDEV_MLME is NULL", rsp->vdev_id); - goto tgt_vdev_mgr_start_response_handler_end; - } - - vdev_rsp = &vdev_mlme->vdev_rt; - if (!vdev_rsp) { - mlme_err("VDEV_%d: Invalid response", rsp->vdev_id); - goto tgt_vdev_mgr_start_response_handler_end; - } - - tx_ops = target_if_vdev_mgr_get_tx_ops(psoc); - if (rsp->resp_type == RESTART_RESPONSE) - status = tx_ops->vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, - RESTART_RESPONSE_BIT); - else - status = tx_ops->vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, - START_RESPONSE_BIT); - if (QDF_IS_STATUS_ERROR(status)) { - mlme_err("VDEV_%d: Unexpected response", rsp->vdev_id); + mlme_err("VDEV_%d PSOC_%d VDEV_MLME is NULL", rsp->vdev_id, + wlan_psoc_get_id(psoc)); goto tgt_vdev_mgr_start_response_handler_end; } @@ -93,6 +87,7 @@ static QDF_STATUS tgt_vdev_mgr_start_response_handler( status = vdev_mlme->ops->mlme_vdev_ext_start_rsp( vdev_mlme, rsp); + tgt_vdev_mgr_start_response_handler_end: wlan_objmgr_vdev_release_ref(vdev, WLAN_VDEV_TARGET_IF_ID); return status; @@ -105,8 +100,6 @@ static QDF_STATUS tgt_vdev_mgr_stop_response_handler( QDF_STATUS status = QDF_STATUS_E_FAILURE; struct vdev_mlme_obj *vdev_mlme; struct wlan_objmgr_vdev *vdev; - struct vdev_response_timer *vdev_rsp; - struct wlan_lmac_if_mlme_tx_ops *tx_ops; if (!rsp || !psoc) { mlme_err("Invalid input"); @@ -122,21 +115,8 @@ static QDF_STATUS tgt_vdev_mgr_stop_response_handler( vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); if (!vdev_mlme) { - mlme_err("VDEV_%d: VDEV_MLME is NULL", rsp->vdev_id); - goto tgt_vdev_mgr_stop_response_handler_end; - } - - vdev_rsp = &vdev_mlme->vdev_rt; - if (!vdev_rsp) { - mlme_err("VDEV_%d: Invalid response", rsp->vdev_id); - goto tgt_vdev_mgr_stop_response_handler_end; - } - - tx_ops = target_if_vdev_mgr_get_tx_ops(psoc); - status = tx_ops->vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, - STOP_RESPONSE_BIT); - if (QDF_IS_STATUS_ERROR(status)) { - mlme_err("VDEV_%d: Unexpected response", rsp->vdev_id); + mlme_err("VDEV_%d: PSOC_%d VDEV_MLME is NULL", rsp->vdev_id, + wlan_psoc_get_id(psoc)); goto tgt_vdev_mgr_stop_response_handler_end; } @@ -144,20 +124,29 @@ static QDF_STATUS tgt_vdev_mgr_stop_response_handler( status = vdev_mlme->ops->mlme_vdev_ext_stop_rsp( vdev_mlme, rsp); + tgt_vdev_mgr_stop_response_handler_end: wlan_objmgr_vdev_release_ref(vdev, WLAN_VDEV_TARGET_IF_ID); return status; } -QDF_STATUS tgt_vdev_mgr_delete_response_handler( +static QDF_STATUS tgt_vdev_mgr_delete_response_handler( struct wlan_objmgr_psoc *psoc, struct vdev_delete_response *rsp) { QDF_STATUS status = QDF_STATUS_E_FAILURE; + + status = mlme_vdev_ops_ext_hdl_delete_rsp(psoc, rsp); + return status; +} + +static QDF_STATUS tgt_vdev_mgr_peer_delete_all_response_handler( + struct wlan_objmgr_psoc *psoc, + struct peer_delete_all_response *rsp) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; struct vdev_mlme_obj *vdev_mlme; struct wlan_objmgr_vdev *vdev; - struct vdev_response_timer *vdev_rsp; - struct wlan_lmac_if_mlme_tx_ops *tx_ops; if (!rsp || !psoc) { mlme_err("Invalid input"); @@ -174,31 +163,18 @@ QDF_STATUS tgt_vdev_mgr_delete_response_handler( vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); if (!vdev_mlme) { - mlme_err("VDEV_%d: VDEV_MLME is NULL", rsp->vdev_id); - goto tgt_vdev_mgr_delete_response_handler_end; - } - - vdev_rsp = &vdev_mlme->vdev_rt; - if (!vdev_rsp) { - mlme_err("VDEV_%d: Invalid response", rsp->vdev_id); - goto tgt_vdev_mgr_delete_response_handler_end; - } - - tx_ops = target_if_vdev_mgr_get_tx_ops(psoc); - status = tx_ops->vdev_mgr_rsp_timer_stop(vdev, vdev_rsp, - DELETE_RESPONSE_BIT); - if (QDF_IS_STATUS_ERROR(status)) { - mlme_err("VDEV_%d: Unexpected response", rsp->vdev_id); - goto tgt_vdev_mgr_delete_response_handler_end; + mlme_err("VDEV_%d: PSOC_%d VDEV_MLME is NULL", rsp->vdev_id, + wlan_psoc_get_id(psoc)); + goto tgt_vdev_mgr_peer_delete_all_response_handler_end; } if ((vdev_mlme->ops) && - vdev_mlme->ops->mlme_vdev_ext_delete_rsp) - status = vdev_mlme->ops->mlme_vdev_ext_delete_rsp( + vdev_mlme->ops->mlme_vdev_ext_peer_delete_all_rsp) + status = vdev_mlme->ops->mlme_vdev_ext_peer_delete_all_rsp( vdev_mlme, rsp); -tgt_vdev_mgr_delete_response_handler_end: +tgt_vdev_mgr_peer_delete_all_response_handler_end: wlan_objmgr_vdev_release_ref(vdev, WLAN_VDEV_TARGET_IF_ID); return status; } @@ -220,7 +196,7 @@ tgt_vdev_mgr_tbttoffset_update_handler(uint32_t num_vdevs, bool is_ext) return status; } -static QDF_STATUS +QDF_STATUS tgt_vdev_mgr_ext_tbttoffset_update_handle(uint32_t num_vdevs, bool is_ext) { QDF_STATUS status = QDF_STATUS_E_FAILURE; @@ -228,6 +204,42 @@ tgt_vdev_mgr_ext_tbttoffset_update_handle(uint32_t num_vdevs, bool is_ext) return status; } +static QDF_STATUS tgt_vdev_mgr_multi_vdev_restart_resp_handler( + struct wlan_objmgr_psoc *psoc, + struct multi_vdev_restart_resp *resp) +{ + return mlme_vdev_ops_ext_hdl_multivdev_restart_resp(psoc, resp); +} + +#ifdef FEATURE_VDEV_RSP_WAKELOCK +static struct psoc_mlme_wakelock * +tgt_psoc_get_wakelock_info(struct wlan_objmgr_psoc *psoc) +{ + struct psoc_mlme_obj *psoc_mlme; + + psoc_mlme = mlme_psoc_get_priv(psoc); + if (!psoc_mlme) { + mlme_err("PSOC_MLME is NULL"); + return NULL; + } + + return &psoc_mlme->psoc_mlme_wakelock; +} + +static inline void +tgt_psoc_reg_wakelock_info_rx_op(struct wlan_lmac_if_mlme_rx_ops + *mlme_rx_ops) +{ + mlme_rx_ops->psoc_get_wakelock_info = tgt_psoc_get_wakelock_info; +} +#else +static inline void +tgt_psoc_reg_wakelock_info_rx_op(struct wlan_lmac_if_mlme_rx_ops + *mlme_rx_ops) +{ +} +#endif + void tgt_vdev_mgr_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) { struct wlan_lmac_if_mlme_rx_ops *mlme_rx_ops = &rx_ops->mops; @@ -242,6 +254,11 @@ void tgt_vdev_mgr_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) tgt_vdev_mgr_stop_response_handler; mlme_rx_ops->vdev_mgr_delete_response = tgt_vdev_mgr_delete_response_handler; - mlme_rx_ops->vdev_mgr_get_response_timer_info = + mlme_rx_ops->vdev_mgr_peer_delete_all_response = + tgt_vdev_mgr_peer_delete_all_response_handler; + mlme_rx_ops->psoc_get_vdev_response_timer_info = tgt_vdev_mgr_get_response_timer_info; + mlme_rx_ops->vdev_mgr_multi_vdev_restart_resp = + tgt_vdev_mgr_multi_vdev_restart_resp_handler; + tgt_psoc_reg_wakelock_info_rx_op(&rx_ops->mops); } diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_tx_api.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_tx_api.c index 286b0b6cfcd960ea8deb2838c2b4af103dd9ad05..d7cdc2aab189740162967a06f49d50b6a565a3fa 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_tx_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_tgt_if_tx_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020 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 @@ -57,13 +57,10 @@ QDF_STATUS tgt_vdev_mgr_create_send( struct wlan_objmgr_pdev *pdev; struct wlan_objmgr_vdev *vdev; ol_txrx_soc_handle soc_txrx_handle; - struct cdp_pdev *pdev_txrx_handle; - struct cdp_vdev *vdev_txrx_handle; enum wlan_op_mode cdp_txrx_opmode; enum wlan_op_subtype cdp_txrx_subtype; uint32_t vdev_id; uint8_t *vdev_addr; - struct vdev_response_timer *vdev_rsp; if (!param) { mlme_err("Invalid input"); @@ -73,42 +70,37 @@ QDF_STATUS tgt_vdev_mgr_create_send( vdev = mlme_obj->vdev; vdev_id = wlan_vdev_get_id(vdev); txops = wlan_vdev_mlme_get_lmac_txops(vdev); - if (!txops || !txops->vdev_create_send || - !txops->vdev_mgr_rsp_timer_init) { - mlme_err("VDEV_%d: No Tx Ops", vdev_id); + if (!txops || !txops->vdev_create_send) { + mlme_err("VDEV_%d No Tx Ops", vdev_id); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + mlme_err("psoc object is NULL"); return QDF_STATUS_E_INVAL; } status = txops->vdev_create_send(vdev, param); - if (QDF_IS_STATUS_SUCCESS(status)) { - vdev_rsp = &mlme_obj->vdev_rt; - txops->vdev_mgr_rsp_timer_init(vdev, &vdev_rsp->rsp_timer); - } else { - mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); + if (QDF_IS_STATUS_ERROR(status)) { + mlme_err("VDEV_%d PSOC_%d Tx Ops Error : %d", vdev_id, + wlan_psoc_get_id(psoc), status); return status; } cdp_txrx_opmode = wlan_util_vdev_get_cdp_txrx_opmode(vdev); cdp_txrx_subtype = wlan_util_vdev_get_cdp_txrx_subtype(vdev); vdev_addr = wlan_vdev_mlme_get_macaddr(vdev); - psoc = wlan_vdev_get_psoc(vdev); pdev = wlan_vdev_get_pdev(vdev); soc_txrx_handle = wlan_psoc_get_dp_handle(psoc); - pdev_txrx_handle = wlan_pdev_get_dp_handle(pdev); - if (!soc_txrx_handle || !pdev_txrx_handle) - return QDF_STATUS_E_FAILURE; - - vdev_txrx_handle = cdp_vdev_attach(soc_txrx_handle, - pdev_txrx_handle, - vdev_addr, vdev_id, - cdp_txrx_opmode, - cdp_txrx_subtype); - if (!vdev_txrx_handle) + if (!soc_txrx_handle) return QDF_STATUS_E_FAILURE; - wlan_vdev_set_dp_handle(vdev, vdev_txrx_handle); - - return status; + return cdp_vdev_attach(soc_txrx_handle, + wlan_objmgr_pdev_get_pdev_id(pdev), + vdev_addr, vdev_id, + cdp_txrx_opmode, + cdp_txrx_subtype); } QDF_STATUS tgt_vdev_mgr_create_complete(struct vdev_mlme_obj *vdev_mlme) @@ -195,6 +187,8 @@ QDF_STATUS tgt_vdev_mgr_delete_send( QDF_STATUS status; struct wlan_lmac_if_mlme_tx_ops *txops; struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_psoc *psoc; + ol_txrx_soc_handle soc_txrx_handle; uint8_t vdev_id; if (!param) { @@ -210,6 +204,12 @@ QDF_STATUS tgt_vdev_mgr_delete_send( return QDF_STATUS_E_INVAL; } + psoc = wlan_vdev_get_psoc(vdev); + soc_txrx_handle = wlan_psoc_get_dp_handle(psoc); + if (soc_txrx_handle) + cdp_vdev_detach(soc_txrx_handle, wlan_vdev_get_id(vdev), + NULL, NULL); + status = txops->vdev_delete_send(vdev, param); if (QDF_IS_STATUS_ERROR(status)) mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); @@ -292,7 +292,6 @@ QDF_STATUS tgt_vdev_mgr_up_send( QDF_STATUS status; struct wlan_lmac_if_mlme_tx_ops *txops; ol_txrx_soc_handle soc_txrx_handle; - struct cdp_vdev *vdev_txrx_handle; struct wlan_objmgr_psoc *psoc; struct wlan_objmgr_vdev *vdev; uint8_t vdev_id; @@ -313,17 +312,9 @@ QDF_STATUS tgt_vdev_mgr_up_send( /* cdp set rx and tx decap type */ psoc = wlan_vdev_get_psoc(vdev); soc_txrx_handle = wlan_psoc_get_dp_handle(psoc); - vdev_txrx_handle = wlan_vdev_get_dp_handle(vdev); - if (!soc_txrx_handle || !vdev_txrx_handle) + if (!soc_txrx_handle || vdev_id == WLAN_INVALID_VDEV_ID) return QDF_STATUS_E_INVAL; - cdp_set_vdev_rx_decap_type(soc_txrx_handle, - (struct cdp_vdev *)vdev_txrx_handle, - mlme_obj->mgmt.generic.rx_decap_type); - cdp_set_tx_encap_type(soc_txrx_handle, - (struct cdp_vdev *)vdev_txrx_handle, - mlme_obj->mgmt.generic.tx_decap_type); - status = txops->vdev_up_send(vdev, param); if (QDF_IS_STATUS_ERROR(status)) mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); @@ -486,6 +477,33 @@ QDF_STATUS tgt_vdev_mgr_beacon_tmpl_send( return QDF_STATUS_SUCCESS; } +#if defined(WLAN_SUPPORT_FILS) || defined(CONFIG_BAND_6GHZ) +QDF_STATUS tgt_vdev_mgr_fils_enable_send( + struct vdev_mlme_obj *mlme_obj, + struct config_fils_params *param) +{ + QDF_STATUS status; + struct wlan_lmac_if_mlme_tx_ops *txops; + struct wlan_objmgr_vdev *vdev; + uint8_t vdev_id; + + vdev = mlme_obj->vdev; + vdev_id = wlan_vdev_get_id(vdev); + txops = wlan_vdev_mlme_get_lmac_txops(vdev); + if (!txops || !txops->vdev_fils_enable_send) { + mlme_err("VDEV_%d: No Tx Ops fils Enable", vdev_id); + return QDF_STATUS_E_INVAL; + } + + status = txops->vdev_fils_enable_send(vdev, param); + if (QDF_IS_STATUS_ERROR(status)) + mlme_err("VDEV_%d: Tx Ops fils Enable Error : %d", + vdev_id, status); + + return status; +} +#endif + QDF_STATUS tgt_vdev_mgr_multiple_vdev_restart_send( struct wlan_objmgr_pdev *pdev, struct multiple_vdev_restart_params *param) @@ -521,6 +539,35 @@ QDF_STATUS tgt_vdev_mgr_multiple_vdev_restart_send( return status; } +QDF_STATUS tgt_vdev_mgr_set_tx_rx_decap_type(struct vdev_mlme_obj *mlme_obj, + enum wlan_mlme_cfg_id param_id, + uint32_t value) +{ + QDF_STATUS status; + struct wlan_lmac_if_mlme_tx_ops *txops; + struct wlan_objmgr_vdev *vdev; + uint8_t vdev_id; + + if (!mlme_obj) { + mlme_err("Invalid input"); + return QDF_STATUS_E_INVAL; + } + + vdev = mlme_obj->vdev; + vdev_id = wlan_vdev_get_id(vdev); + txops = wlan_vdev_mlme_get_lmac_txops(vdev); + if (!txops || !txops->vdev_set_tx_rx_decap_type) { + mlme_err("VDEV_%d: No Tx Ops", vdev_id); + return QDF_STATUS_E_INVAL; + } + + status = txops->vdev_set_tx_rx_decap_type(vdev, param_id, value); + if (QDF_IS_STATUS_ERROR(status)) + mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); + + return status; +} + QDF_STATUS tgt_vdev_mgr_set_param_send( struct vdev_mlme_obj *mlme_obj, struct vdev_set_params *param) @@ -578,3 +625,32 @@ QDF_STATUS tgt_vdev_mgr_sta_ps_param_send( return status; } + +QDF_STATUS tgt_vdev_mgr_peer_delete_all_send( + struct vdev_mlme_obj *mlme_obj, + struct peer_delete_all_params *param) +{ + QDF_STATUS status; + struct wlan_lmac_if_mlme_tx_ops *txops; + struct wlan_objmgr_vdev *vdev; + uint8_t vdev_id; + + if (!param) { + mlme_err("Invalid input"); + return QDF_STATUS_E_INVAL; + } + + vdev = mlme_obj->vdev; + vdev_id = wlan_vdev_get_id(vdev); + txops = wlan_vdev_mlme_get_lmac_txops(vdev); + if (!txops || !txops->peer_delete_all_send) { + mlme_err("VDEV_%d: No Tx Ops", vdev_id); + return QDF_STATUS_E_INVAL; + } + + status = txops->peer_delete_all_send(vdev, param); + if (QDF_IS_STATUS_ERROR(status)) + mlme_err("VDEV_%d: Tx Ops Error : %d", vdev_id, status); + + return QDF_STATUS_SUCCESS; +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_ucfg_api.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_ucfg_api.c index 779755df8178392b401c1ddea31f896e60aca5d7..6582f3cc7e702cf77903c9d0575f8128f6ef7509 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_ucfg_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_ucfg_api.c @@ -28,6 +28,7 @@ #include #include #include +#include void ucfg_wlan_vdev_mgr_get_param_bssid( struct wlan_objmgr_vdev *vdev, diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_utils_api.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_utils_api.c index fd329da926722ef249513477aee17cbcab7e3bb8..b631396ce720a101d07662f71732c45c94bf0ea3 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_utils_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mgr_utils_api.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include static QDF_STATUS vdev_mgr_config_ratemask_update( struct vdev_mlme_obj *mlme_obj, @@ -84,6 +86,24 @@ wlan_util_vdev_get_cdp_txrx_opmode(struct wlan_objmgr_vdev *vdev) case QDF_MONITOR_MODE: cdp_txrx_opmode = wlan_op_mode_monitor; break; + case QDF_P2P_DEVICE_MODE: + cdp_txrx_opmode = wlan_op_mode_ap; + break; + case QDF_P2P_CLIENT_MODE: + cdp_txrx_opmode = wlan_op_mode_sta; + break; + case QDF_P2P_GO_MODE: + cdp_txrx_opmode = wlan_op_mode_ap; + break; + case QDF_OCB_MODE: + cdp_txrx_opmode = wlan_op_mode_ocb; + break; + case QDF_IBSS_MODE: + cdp_txrx_opmode = wlan_op_mode_ibss; + break; + case QDF_NDI_MODE: + cdp_txrx_opmode = wlan_op_mode_ndi; + break; default: cdp_txrx_opmode = wlan_op_mode_unknown; }; @@ -117,7 +137,7 @@ wlan_util_vdev_mlme_set_param(struct vdev_mlme_obj *vdev_mlme, struct vdev_mlme_proto *mlme_proto; struct vdev_mlme_mgmt *mlme_mgmt; struct vdev_mlme_inactivity_params *inactivity_params; - int is_wmi_cmd = 0; + bool is_wmi_cmd = false; int ret = QDF_STATUS_SUCCESS; struct vdev_set_params param = {0}; @@ -133,27 +153,27 @@ wlan_util_vdev_mlme_set_param(struct vdev_mlme_obj *vdev_mlme, switch (param_id) { case WLAN_MLME_CFG_DTIM_PERIOD: mlme_proto->generic.dtim_period = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_SLOT_TIME: mlme_proto->generic.slot_time = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_PROTECTION_MODE: mlme_proto->generic.protection_mode = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_BEACON_INTERVAL: mlme_proto->generic.beacon_interval = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_LDPC: mlme_proto->generic.ldpc = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_NSS: mlme_proto->generic.nss = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_TSF_ADJUST: mlme_proto->generic.tsfadjust = mlme_cfg.tsf; @@ -186,22 +206,22 @@ wlan_util_vdev_mlme_set_param(struct vdev_mlme_obj *vdev_mlme, mlme_proto->vht_info.bfee_sts_cap = mlme_cfg.value; break; case WLAN_MLME_CFG_TXBF_CAPS: - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_HT_CAPS: mlme_proto->ht_info.ht_caps = mlme_cfg.value; break; case WLAN_MLME_CFG_HE_OPS: mlme_proto->he_ops_info.he_ops = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_RTS_THRESHOLD: mlme_mgmt->generic.rts_threshold = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_FRAG_THRESHOLD: mlme_mgmt->generic.frag_threshold = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_PROBE_DELAY: mlme_mgmt->generic.probe_delay = mlme_cfg.value; @@ -211,19 +231,19 @@ wlan_util_vdev_mlme_set_param(struct vdev_mlme_obj *vdev_mlme, break; case WLAN_MLME_CFG_DROP_UNENCRY: mlme_mgmt->generic.drop_unencry = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_TX_PWR_LIMIT: mlme_mgmt->generic.tx_pwrlimit = mlme_cfg.value; break; case WLAN_MLME_CFG_TX_POWER: mlme_mgmt->generic.tx_power = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_AMPDU: mlme_mgmt->generic.ampdu = mlme_cfg.value; mlme_cfg.value = (mlme_cfg.value << 8) + 0xFF; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_AMPDU_SIZE: mlme_mgmt->generic.ampdu = mlme_cfg.value; @@ -231,7 +251,7 @@ wlan_util_vdev_mlme_set_param(struct vdev_mlme_obj *vdev_mlme, case WLAN_MLME_CFG_AMSDU: mlme_mgmt->generic.amsdu = mlme_cfg.value; mlme_cfg.value = (mlme_cfg.value << 8) + 0xFF; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_AMSDU_SIZE: mlme_mgmt->generic.amsdu = mlme_cfg.value; @@ -245,17 +265,17 @@ wlan_util_vdev_mlme_set_param(struct vdev_mlme_obj *vdev_mlme, case WLAN_MLME_CFG_MIN_IDLE_INACTIVE_TIME: inactivity_params->keepalive_min_idle_inactive_time_secs = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_MAX_IDLE_INACTIVE_TIME: inactivity_params->keepalive_max_idle_inactive_time_secs = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_MAX_UNRESPONSIVE_INACTIVE_TIME: inactivity_params->keepalive_max_unresponsive_time_secs = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_RATE_FLAGS: mlme_mgmt->rate_info.rate_flags = mlme_cfg.value; @@ -286,7 +306,7 @@ wlan_util_vdev_mlme_set_param(struct vdev_mlme_obj *vdev_mlme, break; case WLAN_MLME_CFG_LISTEN_INTERVAL: mlme_mgmt->powersave_info.listen_interval = mlme_cfg.value; - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_MODDTIM_CNT: mlme_mgmt->powersave_info.moddtim_cnt = mlme_cfg.value; @@ -328,11 +348,19 @@ wlan_util_vdev_mlme_set_param(struct vdev_mlme_obj *vdev_mlme, case WLAN_MLME_CFG_UAPSD: mlme_proto->sta.uapsd_cfg = mlme_cfg.value; break; - case WLAN_MLME_CFG_TX_DECAP_TYPE: - mlme_mgmt->generic.tx_decap_type = mlme_cfg.value; + case WLAN_MLME_CFG_TX_ENCAP_TYPE: + is_wmi_cmd = true; + mlme_mgmt->generic.tx_encap_type = mlme_cfg.value; + tgt_vdev_mgr_set_tx_rx_decap_type(vdev_mlme, + WLAN_MLME_CFG_TX_ENCAP_TYPE, + mlme_cfg.value); break; case WLAN_MLME_CFG_RX_DECAP_TYPE: + is_wmi_cmd = true; mlme_mgmt->generic.rx_decap_type = mlme_cfg.value; + tgt_vdev_mgr_set_tx_rx_decap_type(vdev_mlme, + WLAN_MLME_CFG_RX_DECAP_TYPE, + mlme_cfg.value); break; case WLAN_MLME_CFG_RATEMASK_TYPE: mlme_mgmt->rate_info.type = mlme_cfg.value; @@ -350,10 +378,16 @@ wlan_util_vdev_mlme_set_param(struct vdev_mlme_obj *vdev_mlme, mlme_mgmt->rate_info.bcn_tx_rate = mlme_cfg.value; break; case WLAN_MLME_CFG_BCN_TX_RATE_CODE: - is_wmi_cmd = 1; + is_wmi_cmd = true; break; case WLAN_MLME_CFG_TX_MGMT_RATE_CODE: - is_wmi_cmd = 1; + is_wmi_cmd = true; + break; + case WLAN_MLME_CFG_ENABLE_MULTI_GROUP_KEY: + is_wmi_cmd = true; + break; + case WLAN_MLME_CFG_MAX_GROUP_KEYS: + is_wmi_cmd = true; break; default: break; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mlme_api.c b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mlme_api.c index 1d0629976cff5b08db46e6900b83bc844d865390..fafc0bed56c3e9bd0c38d41e8f6d7f26abbf45df 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mlme_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mlme_api.c @@ -46,7 +46,8 @@ struct vdev_mlme_obj *wlan_vdev_mlme_get_cmpt_obj(struct wlan_objmgr_vdev *vdev) qdf_export_symbol(wlan_vdev_mlme_get_cmpt_obj); -void wlan_vdev_mlme_set_ext_hdl(struct wlan_objmgr_vdev *vdev, void *ext_hdl) +void wlan_vdev_mlme_set_ext_hdl(struct wlan_objmgr_vdev *vdev, + mlme_vdev_ext_t *ext_hdl) { struct vdev_mlme_obj *vdev_mlme; @@ -62,7 +63,7 @@ void wlan_vdev_mlme_set_ext_hdl(struct wlan_objmgr_vdev *vdev, void *ext_hdl) qdf_export_symbol(wlan_vdev_mlme_set_ext_hdl); -void *wlan_vdev_mlme_get_ext_hdl(struct wlan_objmgr_vdev *vdev) +mlme_vdev_ext_t *wlan_vdev_mlme_get_ext_hdl(struct wlan_objmgr_vdev *vdev) { struct vdev_mlme_obj *vdev_mlme; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_build_chan_list.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_build_chan_list.c index 065efcf4463c564e51b99e4272c518b34a243146..d783f8158316141ea1f35927ff25ab2995931dab 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_build_chan_list.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_build_chan_list.c @@ -183,12 +183,10 @@ static void reg_do_auto_bw_correction(uint32_t num_reg_rules, uint16_t new_bw; for (count = 0; count < num_reg_rules - 1; count++) { - if ((reg_rule_ptr[count].end_freq == - reg_rule_ptr[count + 1].start_freq) && - ((reg_rule_ptr[count].max_bw + - reg_rule_ptr[count + 1].max_bw) <= max_bw)) { - new_bw = reg_rule_ptr[count].max_bw + - reg_rule_ptr[count + 1].max_bw; + if (reg_rule_ptr[count].end_freq == + reg_rule_ptr[count + 1].start_freq) { + new_bw = QDF_MIN(max_bw, reg_rule_ptr[count].max_bw + + reg_rule_ptr[count + 1].max_bw); reg_rule_ptr[count].max_bw = new_bw; reg_rule_ptr[count + 1].max_bw = new_bw; } @@ -255,18 +253,43 @@ static void reg_modify_chan_list_for_indoor_channels( } } +#ifdef CONFIG_BAND_6GHZ +static void reg_modify_chan_list_for_band_6G( + struct regulatory_channel *chan_list) +{ + enum channel_enum chan_enum; + + reg_debug("disabling 6G"); + for (chan_enum = MIN_6GHZ_CHANNEL; + chan_enum <= MAX_6GHZ_CHANNEL; chan_enum++) { + chan_list[chan_enum].chan_flags |= + REGULATORY_CHAN_DISABLED; + chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; + } +} +#else +static inline void reg_modify_chan_list_for_band_6G( + struct regulatory_channel *chan_list) +{ +} +#endif + /** - * reg_modify_chan_list_for_band() - Based on the input band value, either - * disable 2GHz or 5GHz channels. + * reg_modify_chan_list_for_band() - Based on the input band bitmap, either + * disable 2GHz, 5GHz, or 6GHz channels. * @chan_list: Pointer to regulatory channel list. - * @band_val: Input band value. + * @band_bitmap: Input bitmap of reg_wifi_band values. */ static void reg_modify_chan_list_for_band(struct regulatory_channel *chan_list, - enum band_info band_val) + uint32_t band_bitmap) { enum channel_enum chan_enum; - if (band_val == BAND_2G) { + if (!band_bitmap) + return; + + if (!(band_bitmap & BIT(REG_BAND_5G))) { + reg_debug("disabling 5G"); for (chan_enum = MIN_5GHZ_CHANNEL; chan_enum <= MAX_5GHZ_CHANNEL; chan_enum++) { chan_list[chan_enum].chan_flags |= @@ -275,7 +298,8 @@ static void reg_modify_chan_list_for_band(struct regulatory_channel *chan_list, } } - if (band_val == BAND_5G) { + if (!(band_bitmap & BIT(REG_BAND_2G))) { + reg_debug("disabling 2G"); for (chan_enum = MIN_24GHZ_CHANNEL; chan_enum <= MAX_24GHZ_CHANNEL; chan_enum++) { chan_list[chan_enum].chan_flags |= @@ -283,6 +307,10 @@ static void reg_modify_chan_list_for_band(struct regulatory_channel *chan_list, chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; } } + + if (!(band_bitmap & BIT(REG_BAND_6G))) + reg_modify_chan_list_for_band_6G(chan_list); + } /** @@ -360,13 +388,13 @@ static void reg_modify_chan_list_for_nol_list( * Return: None */ static void reg_find_low_limit_chan_enum( - struct regulatory_channel *chan_list, uint32_t low_freq, + struct regulatory_channel *chan_list, qdf_freq_t low_freq, uint32_t *low_limit) { enum channel_enum chan_enum; uint16_t min_bw; uint16_t max_bw; - uint32_t center_freq; + qdf_freq_t center_freq; for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { min_bw = chan_list[chan_enum].min_bw; @@ -396,13 +424,13 @@ static void reg_find_low_limit_chan_enum( * Return: None */ static void reg_find_high_limit_chan_enum( - struct regulatory_channel *chan_list, uint32_t high_freq, + struct regulatory_channel *chan_list, qdf_freq_t high_freq, uint32_t *high_limit) { enum channel_enum chan_enum; uint16_t min_bw; uint16_t max_bw; - uint32_t center_freq; + qdf_freq_t center_freq; for (chan_enum = NUM_CHANNELS - 1; chan_enum >= 0; chan_enum--) { min_bw = chan_list[chan_enum].min_bw; @@ -427,6 +455,37 @@ static void reg_find_high_limit_chan_enum( } } +#ifdef REG_DISABLE_JP_CH144 +/** + * reg_modify_chan_list_for_japan() - Disable channel 144 for MKK17_MKKC + * regdomain by default. + * @pdev: Pointer to pdev + * + * Return: None + */ +static void +reg_modify_chan_list_for_japan(struct wlan_objmgr_pdev *pdev) +{ +#define MKK17_MKKC 0xE1 + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return; + } + + if (pdev_priv_obj->reg_dmn_pair == MKK17_MKKC) + pdev_priv_obj->en_chan_144 = false; + +#undef MKK17_MKKC +} +#else +static inline void +reg_modify_chan_list_for_japan(struct wlan_objmgr_pdev *pdev) +{ +} +#endif /** * reg_modify_chan_list_for_freq_range() - Modify channel list for the given low * and high frequency range. @@ -440,10 +499,10 @@ static void reg_find_high_limit_chan_enum( */ static void reg_modify_chan_list_for_freq_range(struct regulatory_channel *chan_list, - uint32_t low_freq_2g, - uint32_t high_freq_2g, - uint32_t low_freq_5g, - uint32_t high_freq_5g) + qdf_freq_t low_freq_2g, + qdf_freq_t high_freq_2g, + qdf_freq_t low_freq_5g, + qdf_freq_t high_freq_5g) { uint32_t low_limit_2g = NUM_CHANNELS; uint32_t high_limit_2g = NUM_CHANNELS; @@ -584,6 +643,134 @@ reg_modify_chan_list_for_srd_channels(struct wlan_objmgr_pdev *pdev, } #endif +#ifdef DISABLE_UNII_SHARED_BANDS +/** + * reg_is_reg_unii_band_1_set() - Check UNII bitmap + * @unii_bitmap: 5G UNII band bitmap + * + * This function checks the input bitmap to disable UNII-1 band channels. + * + * Return: Return true if UNII-1 channels need to be disabled, + * else return false. + */ +static bool reg_is_reg_unii_band_1_set(uint8_t unii_bitmap) +{ + return !!(unii_bitmap & BIT(REG_UNII_BAND_1)); +} + +/** + * reg_is_reg_unii_band_2a_set() - Check UNII bitmap + * @unii_bitmap: 5G UNII band bitmap + * + * This function checks the input bitmap to disable UNII-2A band channels. + * + * Return: Return true if UNII-2A channels need to be disabled, + * else return false. + */ +static bool reg_is_reg_unii_band_2a_set(uint8_t unii_bitmap) +{ + return !!(unii_bitmap & BIT(REG_UNII_BAND_2A)); +} + +/** + * reg_is_5g_enum() - Check if channel enum is a 5G channel enum + * @chan_enum: channel enum + * + * Return: Return true if the input channel enum is 5G, else return false. + */ +static bool reg_is_5g_enum(enum channel_enum chan_enum) +{ + return (chan_enum >= MIN_5GHZ_CHANNEL && chan_enum <= MAX_5GHZ_CHANNEL); +} + +/** + * reg_remove_unii_chan_from_chan_list() - Remove UNII band channels + * @chan_list: Pointer to current channel list + * @start_enum: starting enum value + * @end_enum: ending enum value + * + * Remove channels in a unii band based in on the input start_enum and end_enum. + * Disable the state and flags. Set disable_coex flag to true. + * + * return: void. + */ +static void +reg_remove_unii_chan_from_chan_list(struct regulatory_channel *chan_list, + enum channel_enum start_enum, + enum channel_enum end_enum) +{ + enum channel_enum chan_enum; + + if (!(reg_is_5g_enum(start_enum) && reg_is_5g_enum(end_enum))) { + reg_err_rl("start_enum or end_enum is invalid"); + return; + } + + for (chan_enum = start_enum; chan_enum <= end_enum; chan_enum++) { + chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; + chan_list[chan_enum].chan_flags |= REGULATORY_CHAN_DISABLED; + } +} + +/** + * reg_modify_disable_chan_list_for_unii1_and_unii2a() - Disable UNII-1 and + * UNII2A band + * @pdev_priv_obj: Pointer to pdev private object + * + * This function disables the UNII-1 and UNII-2A band channels + * based on input unii_5g_bitmap. + * + * Return: void. + */ +static void +reg_modify_disable_chan_list_for_unii1_and_unii2a( + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) +{ + uint8_t unii_bitmap = pdev_priv_obj->unii_5g_bitmap; + struct regulatory_channel *chan_list = pdev_priv_obj->cur_chan_list; + + if (reg_is_reg_unii_band_1_set(unii_bitmap)) { + reg_remove_unii_chan_from_chan_list(chan_list, + MIN_UNII_1_BAND_CHANNEL, + MAX_UNII_1_BAND_CHANNEL); + } + + if (reg_is_reg_unii_band_2a_set(unii_bitmap)) { + reg_remove_unii_chan_from_chan_list(chan_list, + MIN_UNII_2A_BAND_CHANNEL, + MAX_UNII_2A_BAND_CHANNEL); + } +} +#else +static inline bool reg_is_reg_unii_band_1_set(uint8_t unii_bitmap) +{ + return false; +} + +static inline bool reg_is_reg_unii_band_2a_set(uint8_t unii_bitmap) +{ + return false; +} + +static inline bool reg_is_5g_enum(enum channel_enum chan_enum) +{ + return false; +} + +static inline void +reg_remove_unii_chan_from_chan_list(struct regulatory_channel *chan_list, + enum channel_enum start_enum, + enum channel_enum end_enum) +{ +} + +static inline void +reg_modify_disable_chan_list_for_unii1_and_unii2a( + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) +{ +} +#endif + void reg_compute_pdev_current_chan_list(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) { @@ -599,6 +786,8 @@ void reg_compute_pdev_current_chan_list(struct wlan_regulatory_pdev_priv_obj reg_modify_chan_list_for_band(pdev_priv_obj->cur_chan_list, pdev_priv_obj->band_capability); + reg_modify_disable_chan_list_for_unii1_and_unii2a(pdev_priv_obj); + reg_modify_chan_list_for_dfs_channels(pdev_priv_obj->cur_chan_list, pdev_priv_obj->dfs_enabled); @@ -687,6 +876,9 @@ void reg_propagate_mas_chan_list_to_pdev(struct wlan_objmgr_psoc *psoc, &psoc_priv_obj->mas_chan_params[pdev_id]); psoc_reg_rules = &psoc_priv_obj->mas_chan_params[pdev_id].reg_rules; reg_save_reg_rules_to_pdev(psoc_reg_rules, pdev_priv_obj); + reg_modify_chan_list_for_japan(pdev); + pdev_priv_obj->chan_list_recvd = + psoc_priv_obj->chan_list_recvd[pdev_id]; reg_compute_pdev_current_chan_list(pdev_priv_obj); reg_tx_ops = reg_get_psoc_tx_ops(psoc); @@ -701,6 +893,40 @@ void reg_propagate_mas_chan_list_to_pdev(struct wlan_objmgr_psoc *psoc, } } +/** + * reg_populate_6g_band_channels() - For all the valid 6GHz regdb channels + * in the master channel list, find the regulatory rules and call + * reg_fill_channel_info() to populate master channel list with txpower, + * antennagain, BW info, etc. + * @reg_rule_5g: Pointer to regulatory rule. + * @num_5g_reg_rules: Number of regulatory rules. + * @min_bw_5g: Minimum regulatory bandwidth. + * @mas_chan_list: Pointer to the master channel list. + */ +#ifdef CONFIG_BAND_6GHZ +static void +reg_populate_6g_band_channels(struct cur_reg_rule *reg_rule_5g, + uint32_t num_5g_reg_rules, + uint16_t min_bw_5g, + struct regulatory_channel *mas_chan_list) +{ + reg_populate_band_channels(MIN_6GHZ_CHANNEL, + MAX_6GHZ_CHANNEL, + reg_rule_5g, + num_5g_reg_rules, + min_bw_5g, + mas_chan_list); +} +#else +static void +reg_populate_6g_band_channels(struct cur_reg_rule *reg_rule_5g, + uint32_t num_5g_reg_rules, + uint16_t min_bw_5g, + struct regulatory_channel *mas_chan_list) +{ +} +#endif /* CONFIG_BAND_6GHZ */ + #ifdef CONFIG_REG_CLIENT /** * reg_send_ctl_info() - Send CTL info to firmware when regdb is not offloaded @@ -857,7 +1083,8 @@ QDF_STATUS reg_process_master_chan_list( REGULATORY_CHAN_DISABLED; mas_chan_list[chan_enum].state = CHANNEL_STATE_DISABLE; - mas_chan_list[chan_enum].nol_chan = false; + if (!soc_reg->retain_nol_across_regdmn_update) + mas_chan_list[chan_enum].nol_chan = false; } soc_reg->num_phy = regulat_info->num_phy; @@ -921,17 +1148,21 @@ QDF_STATUS reg_process_master_chan_list( reg_rule_2g, num_2g_reg_rules, min_bw_2g, mas_chan_list); - if (num_5g_reg_rules != 0) + if (num_5g_reg_rules != 0) { reg_populate_band_channels(MIN_5GHZ_CHANNEL, MAX_5GHZ_CHANNEL, reg_rule_5g, num_5g_reg_rules, min_bw_5g, mas_chan_list); - - if (num_5g_reg_rules != 0) reg_populate_band_channels(MIN_49GHZ_CHANNEL, MAX_49GHZ_CHANNEL, - reg_rule_5g, num_5g_reg_rules, - min_bw_5g, mas_chan_list); + reg_rule_5g, num_5g_reg_rules, + min_bw_5g, mas_chan_list); + reg_populate_6g_band_channels(reg_rule_5g, + num_5g_reg_rules, + min_bw_5g, + mas_chan_list); + } + soc_reg->chan_list_recvd[phy_id] = true; status = reg_send_ctl_info(soc_reg, regulat_info, tx_ops); if (!QDF_IS_STATUS_SUCCESS(status)) return status; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_callbacks.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_callbacks.c index 709b35302c63133fc0b76d0bb8c95dd09fb35d11..ed253021d0778bbfaacc6f346c8dac017c89ca3f 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_callbacks.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_callbacks.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-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 @@ -211,6 +211,11 @@ QDF_STATUS reg_send_scheduler_msg_sb(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_FAILURE; } + if (!pdev_priv_obj->chan_list_recvd) { + reg_err("Empty channel list"); + return QDF_STATUS_E_FAILURE; + } + status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID); if (QDF_IS_STATUS_ERROR(status)) { reg_err("error taking psoc ref cnt"); @@ -267,6 +272,11 @@ QDF_STATUS reg_send_scheduler_msg_nb(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_FAILURE; } + if (!pdev_priv_obj->chan_list_recvd) { + reg_err("Empty channel list"); + return QDF_STATUS_E_FAILURE; + } + status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_NB_ID); if (QDF_IS_STATUS_ERROR(status)) { reg_err("error taking psoc ref cnt"); @@ -336,7 +346,6 @@ QDF_STATUS reg_notify_sap_event(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; pdev_priv_obj->sap_state = sap_state; - set_disable_channel_state(pdev_priv_obj); reg_compute_pdev_current_chan_list(pdev_priv_obj); status = reg_send_scheduler_msg_sb(psoc, pdev); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_db.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_db.c index 39e9f3b03d1a1b4d20d309bfa92cc9e8c073330a..8b47d2f8fcf16d8a80c24260e8fb27547626ebed 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_db.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_db.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -20,7 +20,7 @@ /** * DOC: reg_db.c * This file implements QCA regulatory database. - * Current implementation conforms to database version 30. + * Current implementation conforms to database version 31. */ #include @@ -118,6 +118,8 @@ enum country_code { CTRY_ISRAEL = 376, CTRY_ITALY = 380, CTRY_JAMAICA = 388, + CTRY_JAPAN = 392, + CTRY_JAPAN15 = 4015, CTRY_JERSEY = 832, CTRY_JORDAN = 400, CTRY_KAZAKHSTAN = 398, @@ -223,11 +225,9 @@ enum country_code { CTRY_VIRGIN_ISLANDS = 850, CTRY_VIRGIN_ISLANDS_BRITISH = 92, CTRY_WALLIS_AND_FUTUNA = 876, + CTRY_XA = 4100, /* Used by Linux Client for legacy MKK domain */ CTRY_YEMEN = 887, CTRY_ZIMBABWE = 716, - CTRY_JAPAN = 392, - CTRY_JAPAN15 = 4015, - CTRY_XA = 4100, }; enum reg_domain { @@ -246,12 +246,17 @@ enum reg_domain { FCC6_WORLD = 0x23, FCC6_FCCA = 0x14, FCC8_FCCA = 0x16, + FCC8_WORLD = 0x09, FCC9_FCCA = 0x17, FCC10_FCCA = 0x18, FCC11_WORLD = 0x19, FCC13_WORLD = 0xE4, FCC14_FCCB = 0xE6, - +#ifdef CONFIG_BAND_6GHZ + FCC15_FCCA = 0xEA, + FCC16_FCCA = 0xE8, + FCC17_FCCA = 0xE9, +#endif ETSI1_WORLD = 0x37, ETSI3_WORLD = 0x36, ETSI4_WORLD = 0x30, @@ -319,17 +324,17 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_ALBANIA, ETSI1_WORLD, "AL", 40, 160, 0}, {CTRY_ALGERIA, APL13_WORLD, "DZ", 40, 160, 0}, {CTRY_AMERICAN_SAMOA, FCC3_FCCA, "AS", 40, 160, 0}, - {CTRY_ANDORRA, ETSI3_WORLD, "AD", 40, 160, 0}, + {CTRY_ANDORRA, ETSI1_WORLD, "AD", 40, 160, 0}, {CTRY_ANGUILLA, ETSI1_WORLD, "AI", 40, 160, 0}, {CTRY_ANTIGUA_AND_BARBUDA, ETSI1_WORLD, "AG", 40, 160, 0}, {CTRY_ARGENTINA, APL16_ETSIC, "AR", 40, 160, 0}, - {CTRY_ARMENIA, ETSI4_WORLD, "AM", 40, 20, 0}, + {CTRY_ARMENIA, APL4_WORLD, "AM", 40, 160, 0}, {CTRY_ARUBA, ETSI1_WORLD, "AW", 40, 160, 0}, {CTRY_AUSTRALIA, FCC6_WORLD, "AU", 40, 160, 0}, {CTRY_AUSTRIA, ETSI1_WORLD, "AT", 40, 160, 0}, {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", 40, 160, 0}, {CTRY_BAHAMAS, FCC3_WORLD, "BS", 40, 160, 0}, - {CTRY_BAHRAIN, APL15_WORLD, "BH", 40, 20, 0}, + {CTRY_BAHRAIN, APL15_WORLD, "BH", 40, 160, 0}, {CTRY_BANGLADESH, APL1_WORLD, "BD", 40, 160, 0}, {CTRY_BARBADOS, FCC2_WORLD, "BB", 40, 160, 0}, {CTRY_BELARUS, ETSI1_WORLD, "BY", 40, 160, 0}, @@ -337,10 +342,10 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_BELIZE, ETSI8_WORLD, "BZ", 40, 160, 0}, {CTRY_BERMUDA, FCC3_FCCA, "BM", 40, 160, 0}, {CTRY_BHUTAN, ETSI1_WORLD, "BT", 40, 160, 0}, - {CTRY_BOLIVIA, APL8_WORLD, "BO", 40, 160, 0}, + {CTRY_BOLIVIA, FCC8_WORLD, "BO", 40, 160, 0}, {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA", 40, 160, 0}, {CTRY_BRAZIL, FCC3_ETSIC, "BR", 40, 160, 0}, - {CTRY_BRUNEI_DARUSSALAM, APL6_WORLD, "BN", 40, 160, 0}, + {CTRY_BRUNEI_DARUSSALAM, FCC8_WORLD, "BN", 40, 160, 0}, {CTRY_BULGARIA, ETSI1_WORLD, "BG", 40, 160, 0}, {CTRY_BURKINA_FASO, FCC3_WORLD, "BF", 40, 160, 0}, {CTRY_CAMBODIA, ETSI1_WORLD, "KH", 40, 160, 0}, @@ -362,9 +367,9 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_DENMARK, ETSI1_WORLD, "DK", 40, 160, 0}, {CTRY_DOMINICA, FCC1_FCCA, "DM", 40, 160, 0}, {CTRY_DOMINICAN_REPUBLIC, FCC3_FCCA, "DO", 40, 160, 0}, - {CTRY_ECUADOR, FCC3_WORLD, "EC", 40, 20, 0}, + {CTRY_ECUADOR, FCC3_FCCA, "EC", 40, 160, 0}, {CTRY_EGYPT, ETSI3_WORLD, "EG", 40, 160, 0}, - {CTRY_EL_SALVADOR, FCC1_WORLD, "SV", 40, 20, 0}, + {CTRY_EL_SALVADOR, FCC3_WORLD, "SV", 40, 160, 0}, {CTRY_ESTONIA, ETSI1_WORLD, "EE", 40, 160, 0}, {CTRY_ETHIOPIA, ETSI1_WORLD, "ET", 40, 160, 0}, {CTRY_FALKLAND_ISLANDS, ETSI1_WORLD, "FK", 40, 160, 0}, @@ -401,12 +406,14 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_ISRAEL, ETSI3_WORLD, "IL", 40, 160, 0}, {CTRY_ITALY, ETSI1_WORLD, "IT", 40, 160, 0}, {CTRY_JAMAICA, FCC13_WORLD, "JM", 40, 160, 0}, + {CTRY_JAPAN, MKK17_MKKC, "JP", 40, 160, 0}, + {CTRY_JAPAN15, MKK17_MKKC, "JP", 40, 160, 0}, {CTRY_JERSEY, ETSI1_WORLD, "JE", 40, 160, 0}, {CTRY_JORDAN, APL4_WORLD, "JO", 40, 160, 0}, {CTRY_KAZAKHSTAN, MKK5_MKKC, "KZ", 40, 160, 0}, {CTRY_KENYA, ETSI13_WORLD, "KE", 40, 160, 0}, {CTRY_KOREA_ROC, APL9_MKKC, "KR", 40, 160, 0}, - {CTRY_KUWAIT, ETSI3_WORLD, "KW", 40, 160, 0}, + {CTRY_KUWAIT, ETSI1_WORLD, "KW", 40, 160, 0}, {CTRY_LATVIA, ETSI1_WORLD, "LV", 40, 160, 0}, {CTRY_LEBANON, FCC3_WORLD, "LB", 40, 160, 0}, {CTRY_LESOTHO, ETSI1_WORLD, "LS", 40, 160, 0}, @@ -439,7 +446,7 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN", 40, 160, 0}, {CTRY_NEW_CALEDONIA, ETSI1_WORLD, "NC", 40, 160, 0}, {CTRY_NEW_ZEALAND, FCC3_ETSIC, "NZ", 40, 160, 0}, - {CTRY_NIGERIA, APL8_WORLD, "NG", 40, 160, 0}, + {CTRY_NIGERIA, APL6_WORLD, "NG", 40, 160, 0}, {CTRY_NORTHERN_MARIANA_ISLANDS, FCC3_FCCA, "MP", 40, 160, 0}, {CTRY_NICARAGUA, FCC3_FCCA, "NI", 40, 160, 0}, {CTRY_NIUE, ETSI1_WORLD, "NU", 40, 160, 0}, @@ -483,7 +490,7 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA", 40, 160, 0}, {CTRY_SPAIN, ETSI1_WORLD, "ES", 40, 160, 0}, {CTRY_SURINAME, ETSI1_WORLD, "SR", 40, 160, 0}, - {CTRY_SRI_LANKA, FCC3_WORLD, "LK", 40, 20, 0}, + {CTRY_SRI_LANKA, FCC3_ETSIC, "LK", 40, 160, 0}, {CTRY_SVALBARD_AND_JAN_MAYEN, FCC6_WORLD, "SJ", 40, 160, 0}, {CTRY_SWEDEN, ETSI1_WORLD, "SE", 40, 160, 0}, {CTRY_SWITZERLAND, ETSI1_WORLD, "CH", 40, 160, 0}, @@ -510,10 +517,8 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_VIRGIN_ISLANDS, FCC3_FCCA, "VI", 40, 160, 0}, {CTRY_VIRGIN_ISLANDS_BRITISH, ETSI1_WORLD, "VG", 40, 160, 0}, {CTRY_WALLIS_AND_FUTUNA, ETSI1_WORLD, "WF", 40, 160, 0}, - {CTRY_YEMEN, NULL1_WORLD, "YE", 40, 0, 0}, + {CTRY_YEMEN, ETSI1_WORLD, "YE", 40, 160, 0}, {CTRY_ZIMBABWE, ETSI1_WORLD, "ZW", 40, 160, 0}, - {CTRY_JAPAN, MKK5_MKKC, "JP", 40, 160, 0}, - {CTRY_JAPAN15, MKK5_MKKC, "JP", 40, 160, 0}, }; #else #ifdef WLAN_FEATURE_DSRC @@ -523,17 +528,17 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_ALBANIA, ETSI13_WORLD, "AL", 40, 160, 0}, {CTRY_ALGERIA, APL13_WORLD, "DZ", 40, 160, 0}, {CTRY_AMERICAN_SAMOA, FCC3_FCCA, "AS", 40, 160, 0}, - {CTRY_ANDORRA, ETSI3_WORLD, "AD", 40, 160, 0}, + {CTRY_ANDORRA, ETSI1_WORLD, "AD", 40, 160, 0}, {CTRY_ANGUILLA, ETSI1_WORLD, "AI", 40, 160, 0}, {CTRY_ANTIGUA_AND_BARBUDA, ETSI10_WORLD, "AG", 40, 160, 0}, {CTRY_ARGENTINA, APL17_ETSIC, "AR", 40, 160, 0}, - {CTRY_ARMENIA, ETSI4_WORLD, "AM", 40, 20, 0}, + {CTRY_ARMENIA, ETSI4_WORLD, "AM", 40, 160, 0}, {CTRY_ARUBA, ETSI1_WORLD, "AW", 40, 160, 0}, {CTRY_AUSTRALIA, FCC6_WORLD, "AU", 40, 160, 0}, {CTRY_AUSTRIA, ETSI10_WORLD, "AT", 40, 160, 0}, {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", 40, 160, 0}, {CTRY_BAHAMAS, FCC3_WORLD, "BS", 40, 160, 0}, - {CTRY_BAHRAIN, APL15_WORLD, "BH", 40, 20, 0}, + {CTRY_BAHRAIN, APL15_WORLD, "BH", 40, 160, 0}, {CTRY_BANGLADESH, APL1_WORLD, "BD", 40, 160, 0}, {CTRY_BARBADOS, FCC2_WORLD, "BB", 40, 160, 0}, {CTRY_BELARUS, ETSI1_WORLD, "BY", 40, 160, 0}, @@ -541,10 +546,10 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_BELIZE, ETSI8_WORLD, "BZ", 40, 160, 0}, {CTRY_BERMUDA, FCC3_FCCA, "BM", 40, 160, 0}, {CTRY_BHUTAN, ETSI1_WORLD, "BT", 40, 160, 0}, - {CTRY_BOLIVIA, APL8_WORLD, "BO", 40, 160, 0}, + {CTRY_BOLIVIA, FCC3_WORLD, "BO", 40, 160, 0}, {CTRY_BOSNIA_HERZ, ETSI13_WORLD, "BA", 40, 160, 0}, {CTRY_BRAZIL, FCC3_ETSIC, "BR", 40, 160, 0}, - {CTRY_BRUNEI_DARUSSALAM, APL6_WORLD, "BN", 40, 160, 0}, + {CTRY_BRUNEI_DARUSSALAM, FCC3_WORLD, "BN", 40, 160, 0}, {CTRY_BULGARIA, ETSI10_WORLD, "BG", 40, 160, 0}, {CTRY_BURKINA_FASO, FCC3_WORLD, "BF", 40, 160, 0}, {CTRY_CAMBODIA, ETSI1_WORLD, "KH", 40, 160, 0}, @@ -566,9 +571,9 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_DENMARK, ETSI10_WORLD, "DK", 40, 160, 0}, {CTRY_DOMINICA, FCC2_FCCA, "DM", 40, 160, 0}, {CTRY_DOMINICAN_REPUBLIC, FCC3_FCCA, "DO", 40, 160, 0}, - {CTRY_ECUADOR, FCC3_WORLD, "EC", 40, 20, 0}, + {CTRY_ECUADOR, FCC3_FCCA, "EC", 40, 160, 0}, {CTRY_EGYPT, ETSI3_WORLD, "EG", 40, 160, 0}, - {CTRY_EL_SALVADOR, FCC2_WORLD, "SV", 40, 20, 0}, + {CTRY_EL_SALVADOR, FCC3_WORLD, "SV", 40, 160, 0}, {CTRY_ESTONIA, ETSI10_WORLD, "EE", 40, 160, 0}, {CTRY_ETHIOPIA, ETSI1_WORLD, "ET", 40, 160, 0}, {CTRY_FALKLAND_ISLANDS, ETSI10_WORLD, "FK", 40, 160, 0}, @@ -605,12 +610,15 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_ISRAEL, ETSI3_WORLD, "IL", 40, 160, 0}, {CTRY_ITALY, ETSI10_WORLD, "IT", 40, 160, 0}, {CTRY_JAMAICA, FCC13_WORLD, "JM", 40, 160, 0}, + {CTRY_JAPAN, MKK17_MKKC, "JP", 40, 160, 0}, + {CTRY_JAPAN15, MKK5_MKKC, "JP", 40, 160, 0}, + {CTRY_XA, MKK5_MKKA, "XA", 40, 160, 0}, {CTRY_JERSEY, ETSI10_WORLD, "JE", 40, 160, 0}, {CTRY_JORDAN, APL4_WORLD, "JO", 40, 160, 0}, {CTRY_KAZAKHSTAN, MKK5_MKKC, "KZ", 40, 160, 0}, {CTRY_KENYA, ETSI13_WORLD, "KE", 40, 160, 0}, {CTRY_KOREA_ROC, APL9_MKKC, "KR", 40, 160, 0}, - {CTRY_KUWAIT, ETSI3_WORLD, "KW", 40, 160, 0}, + {CTRY_KUWAIT, ETSI13_WORLD, "KW", 40, 160, 0}, {CTRY_LATVIA, ETSI10_WORLD, "LV", 40, 160, 0}, {CTRY_LEBANON, FCC3_WORLD, "LB", 40, 160, 0}, {CTRY_LESOTHO, ETSI1_WORLD, "LS", 40, 160, 0}, @@ -643,7 +651,7 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_NETHERLANDS_ANTILLES, ETSI10_WORLD, "AN", 40, 160, 0}, {CTRY_NEW_CALEDONIA, ETSI10_WORLD, "NC", 40, 160, 0}, {CTRY_NEW_ZEALAND, FCC3_ETSIC, "NZ", 40, 160, 0}, - {CTRY_NIGERIA, APL8_WORLD, "NG", 40, 160, 0}, + {CTRY_NIGERIA, APL6_WORLD, "NG", 40, 160, 0}, {CTRY_NORTHERN_MARIANA_ISLANDS, FCC10_FCCA, "MP", 40, 160, 0}, {CTRY_NICARAGUA, FCC3_FCCA, "NI", 40, 160, 0}, {CTRY_NIUE, ETSI10_WORLD, "NU", 40, 160, 0}, @@ -687,7 +695,7 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA", 40, 160, 0}, {CTRY_SPAIN, ETSI10_WORLD, "ES", 40, 160, 0}, {CTRY_SURINAME, ETSI1_WORLD, "SR", 40, 160, 0}, - {CTRY_SRI_LANKA, FCC3_WORLD, "LK", 40, 20, 0}, + {CTRY_SRI_LANKA, FCC3_ETSIC, "LK", 40, 160, 0}, {CTRY_SVALBARD_AND_JAN_MAYEN, FCC6_WORLD, "SJ", 40, 160, 0}, {CTRY_SWEDEN, ETSI10_WORLD, "SE", 40, 160, 0}, {CTRY_SWITZERLAND, ETSI10_WORLD, "CH", 40, 160, 0}, @@ -714,10 +722,8 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_VIRGIN_ISLANDS, FCC10_FCCA, "VI", 40, 160, 0}, {CTRY_VIRGIN_ISLANDS_BRITISH, ETSI10_WORLD, "VG", 40, 160, 0}, {CTRY_WALLIS_AND_FUTUNA, ETSI1_WORLD, "WF", 40, 160, 0}, - {CTRY_YEMEN, NULL1_WORLD, "YE", 40, 0, 0}, + {CTRY_YEMEN, ETSI1_WORLD, "YE", 40, 160, 0}, {CTRY_ZIMBABWE, ETSI1_WORLD, "ZW", 40, 160, 0}, - {CTRY_JAPAN, MKK5_MKKC, "JP", 40, 160, 0}, - {CTRY_XA, MKK5_MKKA, "XA", 40, 160, 0}, }; #else const struct country_code_to_reg_domain g_all_countries[] = { @@ -726,17 +732,17 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_ALBANIA, ETSI13_WORLD, "AL", 40, 160, 0}, {CTRY_ALGERIA, APL13_WORLD, "DZ", 40, 160, 0}, {CTRY_AMERICAN_SAMOA, FCC3_FCCA, "AS", 40, 160, 0}, - {CTRY_ANDORRA, ETSI3_WORLD, "AD", 40, 160, 0}, + {CTRY_ANDORRA, ETSI13_WORLD, "AD", 40, 160, 0}, {CTRY_ANGUILLA, ETSI1_WORLD, "AI", 40, 160, 0}, {CTRY_ANTIGUA_AND_BARBUDA, ETSI13_WORLD, "AG", 40, 160, 0}, {CTRY_ARGENTINA, APL17_ETSIC, "AR", 40, 160, 0}, - {CTRY_ARMENIA, ETSI4_WORLD, "AM", 40, 20, 0}, + {CTRY_ARMENIA, ETSI4_WORLD, "AM", 40, 160, 0}, {CTRY_ARUBA, ETSI1_WORLD, "AW", 40, 160, 0}, {CTRY_AUSTRALIA, FCC6_WORLD, "AU", 40, 160, 0}, {CTRY_AUSTRIA, ETSI13_WORLD, "AT", 40, 160, 0}, {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", 40, 160, 0}, {CTRY_BAHAMAS, FCC3_WORLD, "BS", 40, 160, 0}, - {CTRY_BAHRAIN, APL15_WORLD, "BH", 40, 20, 0}, + {CTRY_BAHRAIN, APL15_WORLD, "BH", 40, 160, 0}, {CTRY_BANGLADESH, APL1_WORLD, "BD", 40, 160, 0}, {CTRY_BARBADOS, FCC2_WORLD, "BB", 40, 160, 0}, {CTRY_BELARUS, ETSI1_WORLD, "BY", 40, 160, 0}, @@ -744,10 +750,10 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_BELIZE, ETSI8_WORLD, "BZ", 40, 160, 0}, {CTRY_BERMUDA, FCC3_FCCA, "BM", 40, 160, 0}, {CTRY_BHUTAN, ETSI1_WORLD, "BT", 40, 160, 0}, - {CTRY_BOLIVIA, APL8_WORLD, "BO", 40, 160, 0}, + {CTRY_BOLIVIA, FCC3_WORLD, "BO", 40, 160, 0}, {CTRY_BOSNIA_HERZ, ETSI13_WORLD, "BA", 40, 160, 0}, {CTRY_BRAZIL, FCC3_ETSIC, "BR", 40, 160, 0}, - {CTRY_BRUNEI_DARUSSALAM, APL6_WORLD, "BN", 40, 160, 0}, + {CTRY_BRUNEI_DARUSSALAM, FCC3_WORLD, "BN", 40, 160, 0}, {CTRY_BULGARIA, ETSI13_WORLD, "BG", 40, 160, 0}, {CTRY_BURKINA_FASO, FCC3_WORLD, "BF", 40, 160, 0}, {CTRY_CAMBODIA, ETSI1_WORLD, "KH", 40, 160, 0}, @@ -769,9 +775,9 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_DENMARK, ETSI13_WORLD, "DK", 40, 160, 0}, {CTRY_DOMINICA, FCC2_FCCA, "DM", 40, 160, 0}, {CTRY_DOMINICAN_REPUBLIC, FCC3_FCCA, "DO", 40, 160, 0}, - {CTRY_ECUADOR, FCC3_WORLD, "EC", 40, 20, 0}, + {CTRY_ECUADOR, FCC3_FCCA, "EC", 40, 160, 0}, {CTRY_EGYPT, ETSI3_WORLD, "EG", 40, 160, 0}, - {CTRY_EL_SALVADOR, FCC2_WORLD, "SV", 40, 20, 0}, + {CTRY_EL_SALVADOR, FCC3_WORLD, "SV", 40, 160, 0}, {CTRY_ESTONIA, ETSI13_WORLD, "EE", 40, 160, 0}, {CTRY_ETHIOPIA, ETSI1_WORLD, "ET", 40, 160, 0}, {CTRY_FALKLAND_ISLANDS, ETSI13_WORLD, "FK", 40, 160, 0}, @@ -808,12 +814,15 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_ISRAEL, ETSI3_WORLD, "IL", 40, 160, 0}, {CTRY_ITALY, ETSI13_WORLD, "IT", 40, 160, 0}, {CTRY_JAMAICA, FCC13_WORLD, "JM", 40, 160, 0}, + {CTRY_JAPAN, MKK17_MKKC, "JP", 40, 160, 0}, + {CTRY_JAPAN15, MKK5_MKKC, "JP", 40, 160, 0}, + {CTRY_XA, MKK5_MKKA, "XA", 40, 160, 0}, {CTRY_JERSEY, ETSI13_WORLD, "JE", 40, 160, 0}, {CTRY_JORDAN, APL4_WORLD, "JO", 40, 160, 0}, {CTRY_KAZAKHSTAN, MKK5_MKKC, "KZ", 40, 160, 0}, {CTRY_KENYA, ETSI13_WORLD, "KE", 40, 160, 0}, {CTRY_KOREA_ROC, APL9_MKKC, "KR", 40, 160, 0}, - {CTRY_KUWAIT, ETSI3_WORLD, "KW", 40, 160, 0}, + {CTRY_KUWAIT, ETSI13_WORLD, "KW", 40, 160, 0}, {CTRY_LATVIA, ETSI13_WORLD, "LV", 40, 160, 0}, {CTRY_LEBANON, FCC3_WORLD, "LB", 40, 160, 0}, {CTRY_LESOTHO, ETSI1_WORLD, "LS", 40, 160, 0}, @@ -846,7 +855,7 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_NETHERLANDS_ANTILLES, ETSI13_WORLD, "AN", 40, 160, 0}, {CTRY_NEW_CALEDONIA, ETSI13_WORLD, "NC", 40, 160, 0}, {CTRY_NEW_ZEALAND, FCC3_ETSIC, "NZ", 40, 160, 0}, - {CTRY_NIGERIA, APL8_WORLD, "NG", 40, 160, 0}, + {CTRY_NIGERIA, APL6_WORLD, "NG", 40, 160, 0}, {CTRY_NORTHERN_MARIANA_ISLANDS, FCC3_FCCA, "MP", 40, 160, 0}, {CTRY_NICARAGUA, FCC3_FCCA, "NI", 40, 160, 0}, {CTRY_NIUE, ETSI13_WORLD, "NU", 40, 160, 0}, @@ -890,7 +899,7 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA", 40, 160, 0}, {CTRY_SPAIN, ETSI13_WORLD, "ES", 40, 160, 0}, {CTRY_SURINAME, ETSI1_WORLD, "SR", 40, 160, 0}, - {CTRY_SRI_LANKA, FCC3_WORLD, "LK", 40, 20, 0}, + {CTRY_SRI_LANKA, FCC3_ETSIC, "LK", 40, 160, 0}, {CTRY_SVALBARD_AND_JAN_MAYEN, FCC6_WORLD, "SJ", 40, 160, 0}, {CTRY_SWEDEN, ETSI13_WORLD, "SE", 40, 160, 0}, {CTRY_SWITZERLAND, ETSI13_WORLD, "CH", 40, 160, 0}, @@ -917,10 +926,8 @@ const struct country_code_to_reg_domain g_all_countries[] = { {CTRY_VIRGIN_ISLANDS, FCC3_FCCA, "VI", 40, 160, 0}, {CTRY_VIRGIN_ISLANDS_BRITISH, ETSI13_WORLD, "VG", 40, 160, 0}, {CTRY_WALLIS_AND_FUTUNA, ETSI1_WORLD, "WF", 40, 160, 0}, - {CTRY_YEMEN, NULL1_WORLD, "YE", 40, 0, 0}, + {CTRY_YEMEN, ETSI1_WORLD, "YE", 40, 160, 0}, {CTRY_ZIMBABWE, ETSI1_WORLD, "ZW", 40, 160, 0}, - {CTRY_JAPAN, MKK5_MKKC, "JP", 40, 160, 0}, - {CTRY_XA, MKK5_MKKA, "XA", 40, 160, 0}, }; #endif #endif @@ -954,6 +961,11 @@ enum reg_domains_5g { FCC11, FCC13, FCC14, +#ifdef CONFIG_BAND_6GHZ + FCC15, + FCC16, + FCC17, +#endif ETSI1, ETSI3, ETSI4, @@ -1013,10 +1025,16 @@ const struct reg_domain_pair g_reg_dmn_pairs[] = { {FCC6_WORLD, FCC6, WORLD}, {FCC6_FCCA, FCC6, FCCA}, {FCC8_FCCA, FCC8, FCCA}, + {FCC8_WORLD, FCC8, WORLD}, + {FCC10_FCCA, FCC10, FCCA}, {FCC11_WORLD, FCC11, WORLD}, {FCC13_WORLD, FCC13, WORLD}, {FCC14_FCCB, FCC14, FCCB}, - +#ifdef CONFIG_BAND_6GHZ + {FCC15_FCCA, FCC15, FCCA}, + {FCC16_FCCA, FCC16, FCCA}, + {FCC17_FCCA, FCC17, FCCA}, +#endif {ETSI1_WORLD, ETSI1, WORLD}, {ETSI3_WORLD, ETSI3, WORLD}, {ETSI4_WORLD, ETSI4, WORLD}, @@ -1144,6 +1162,7 @@ enum reg_rules_5g { CHAN_5170_5250_7, CHAN_5170_5250_8, CHAN_5170_5250_9, + CHAN_5170_5250_10, CHAN_5170_5330_1, CHAN_5170_5330_2, CHAN_5250_5330_1, @@ -1160,6 +1179,8 @@ enum reg_rules_5g { CHAN_5250_5330_12, CHAN_5250_5330_13, CHAN_5250_5330_14, + CHAN_5250_5330_15, + CHAN_5250_5330_16, CHAN_5490_5730_1, CHAN_5490_5730_2, CHAN_5490_5730_3, @@ -1174,6 +1195,7 @@ enum reg_rules_5g { CHAN_5490_5710_5, CHAN_5490_5710_6, CHAN_5490_5710_7, + CHAN_5490_5710_8, CHAN_5490_5590_1, CHAN_5490_5590_2, CHAN_5490_5590_3, @@ -1208,6 +1230,16 @@ enum reg_rules_5g { CHAN_5855_5875_1, CHAN_5850_5925_1, CHAN_5850_5925_2, +#ifdef CONFIG_BAND_6GHZ + CHAN_5935_6435_1, + CHAN_5935_6435_2, + CHAN_6435_6535_1, + CHAN_6435_6535_2, + CHAN_6535_6875_1, + CHAN_6535_6875_2, + CHAN_6875_7115_1, + CHAN_6875_7115_2, +#endif }; const struct regulatory_rule reg_rules_5g[] = { @@ -1224,6 +1256,7 @@ const struct regulatory_rule reg_rules_5g[] = { [CHAN_5170_5250_7] = {5170, 5250, 80, 20, REGULATORY_CHAN_INDOOR_ONLY}, [CHAN_5170_5250_8] = {5170, 5250, 80, 23, REGULATORY_CHAN_INDOOR_ONLY}, [CHAN_5170_5250_9] = {5170, 5250, 40, 30, 0}, + [CHAN_5170_5250_10] = {5170, 5250, 20, 20, REGULATORY_CHAN_INDOOR_ONLY}, [CHAN_5170_5330_1] = {5170, 5330, 160, 20, REGULATORY_CHAN_NO_IR}, [CHAN_5170_5330_2] = {5170, 5330, 160, 24, 0}, [CHAN_5250_5330_1] = {5250, 5330, 80, 23, REGULATORY_CHAN_RADAR}, @@ -1242,6 +1275,9 @@ const struct regulatory_rule reg_rules_5g[] = { [CHAN_5250_5330_13] = {5250, 5330, 40, 30, REGULATORY_CHAN_RADAR}, [CHAN_5250_5330_14] = {5250, 5330, 80, 20, REGULATORY_CHAN_RADAR | REGULATORY_CHAN_INDOOR_ONLY}, + [CHAN_5250_5330_15] = {5250, 5330, 20, 20, REGULATORY_CHAN_RADAR | + REGULATORY_CHAN_INDOOR_ONLY}, + [CHAN_5250_5330_16] = {5250, 5330, 80, 23, REGULATORY_CHAN_INDOOR_ONLY}, [CHAN_5490_5730_1] = {5490, 5730, 160, 24, REGULATORY_CHAN_RADAR}, [CHAN_5490_5730_2] = {5490, 5730, 160, 20, REGULATORY_CHAN_NO_IR}, [CHAN_5490_5730_3] = {5490, 5730, 160, 30, 0}, @@ -1256,6 +1292,7 @@ const struct regulatory_rule reg_rules_5g[] = { [CHAN_5490_5710_5] = {5490, 5710, 160, 24, REGULATORY_CHAN_RADAR}, [CHAN_5490_5710_6] = {5490, 5710, 160, 26, REGULATORY_CHAN_RADAR}, [CHAN_5490_5710_7] = {5490, 5710, 160, 23, REGULATORY_CHAN_RADAR}, + [CHAN_5490_5710_8] = {5490, 5710, 20, 27, REGULATORY_CHAN_RADAR}, [CHAN_5490_5590_1] = {5490, 5590, 80, 24, REGULATORY_CHAN_RADAR}, [CHAN_5490_5590_2] = {5490, 5590, 80, 30, 0}, [CHAN_5490_5590_3] = {5490, 5590, 80, 36, 0}, @@ -1290,6 +1327,16 @@ const struct regulatory_rule reg_rules_5g[] = { [CHAN_5855_5875_1] = {5855, 5875, 20, 30, 0}, [CHAN_5850_5925_1] = {5850, 5925, 20, 24, 0}, [CHAN_5850_5925_2] = {5850, 5925, 20, 30, 0}, +#ifdef CONFIG_BAND_6GHZ + [CHAN_5935_6435_1] = {5935, 6435, 160, 18, REGULATORY_CHAN_AFC}, + [CHAN_5935_6435_2] = {5935, 6435, 160, 30, REGULATORY_CHAN_AFC}, + [CHAN_6435_6535_1] = {6435, 6535, 100, 18, REGULATORY_CHAN_INDOOR_ONLY}, + [CHAN_6435_6535_2] = {6435, 6535, 100, 24, REGULATORY_CHAN_INDOOR_ONLY}, + [CHAN_6535_6875_1] = {6535, 6875, 160, 18, REGULATORY_CHAN_AFC}, + [CHAN_6535_6875_2] = {6535, 6875, 160, 30, REGULATORY_CHAN_AFC}, + [CHAN_6875_7115_1] = {6875, 7115, 160, 18, REGULATORY_CHAN_INDOOR_ONLY}, + [CHAN_6875_7115_2] = {6875, 7115, 160, 24, REGULATORY_CHAN_INDOOR_ONLY}, +#endif }; @@ -1345,6 +1392,33 @@ const struct regdomain regdomains_5g[] = { CHAN_5490_5730_4, CHAN_5735_5835_2} }, +#ifdef CONFIG_BAND_6GHZ + [FCC15] = {CTL_FCC, DFS_FCC_REGION, 2, 0, 8, {CHAN_5170_5250_5, + CHAN_5250_5330_7, + CHAN_5490_5730_1, + CHAN_5735_5835_2, + CHAN_5935_6435_1, + CHAN_6435_6535_1, + CHAN_6535_6875_1, + CHAN_6875_7115_1} }, + + [FCC16] = {CTL_FCC, DFS_FCC_REGION, 2, 0, 8, {CHAN_5170_5250_4, + CHAN_5250_5330_7, + CHAN_5490_5730_1, + CHAN_5735_5835_2, + CHAN_5935_6435_2, + CHAN_6435_6535_2, + CHAN_6535_6875_2, + CHAN_6875_7115_2} }, + + [FCC17] = {CTL_FCC, DFS_FCC_REGION, 2, 0, 6, {CHAN_5170_5250_4, + CHAN_5250_5330_7, + CHAN_5490_5730_1, + CHAN_5735_5835_2, + CHAN_5935_6435_2, + CHAN_6535_6875_2} }, +#endif + [ETSI1] = {CTL_ETSI, DFS_ETSI_REGION, 2, 0, 3, {CHAN_5170_5250_8, CHAN_5250_5330_12, CHAN_5490_5710_1} }, @@ -1370,9 +1444,9 @@ const struct regdomain regdomains_5g[] = { CHAN_5490_5710_3, CHAN_5850_5925_2} }, - [ETSI11] = {CTL_ETSI, DFS_ETSI_REGION, 10, 0, 4, {CHAN_5170_5250_7, - CHAN_5250_5330_14, - CHAN_5490_5710_3, + [ETSI11] = {CTL_ETSI, DFS_ETSI_REGION, 10, 0, 4, {CHAN_5170_5250_10, + CHAN_5250_5330_15, + CHAN_5490_5710_8, CHAN_5735_5875_1} }, [ETSI12] = {CTL_ETSI, DFS_ETSI_REGION, 2, 0, 4, {CHAN_5170_5250_7, @@ -1436,8 +1510,8 @@ const struct regdomain regdomains_5g[] = { CHAN_5250_5330_1, CHAN_5735_5835_4} }, - [APL15] = {CTL_FCC, DFS_UNINIT_REGION, 2, 0, 3, {CHAN_5170_5250_2, - CHAN_5250_5330_5, + [APL15] = {CTL_FCC, DFS_UNINIT_REGION, 2, 0, 3, {CHAN_5170_5250_8, + CHAN_5250_5330_16, CHAN_5735_5835_4} }, [APL16] = {CTL_FCC, DFS_UNINIT_REGION, 2, 0, 5, {CHAN_5170_5250_1, @@ -1484,9 +1558,9 @@ const struct regdomain regdomains_5g[] = { [MKK16] = {CTL_MKK, DFS_MKK_REGION, 2, 0, 1, {CHAN_5490_5710_6} }, - [MKK17] = {CTL_MKK, DFS_MKK_REGION, 2, 0, 3, {CHAN_5170_5250_8, + [MKK17] = {CTL_MKK, DFS_MKKN_REGION, 2, 0, 3, {CHAN_5170_5250_8, CHAN_5250_5330_12, - CHAN_5490_5710_7} }, + CHAN_5490_5730_6} }, [WORLD_5G_1] = {CTL_NONE, DFS_UNINIT_REGION, 2, 0, 2, {CHAN_5170_5330_1, @@ -1584,3 +1658,11 @@ bool reg_etsi13_regdmn(uint8_t reg_dmn) { return reg_dmn == ETSI13; } + +bool reg_en302_502_regdmn(uint16_t regdmn) +{ + return ((regdmn == ETSI11_WORLD) || + (regdmn == ETSI12_WORLD) || + (regdmn == ETSI14_WORLD) || + (regdmn == ETSI15_WORLD)); +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_db.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_db.h index 8183a27a70dd9fd7d11549e7978adc9a8bd4db27..b07c14339a647fc1a577e1e3162ad752c3d992a4 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_db.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_db.h @@ -104,4 +104,12 @@ QDF_STATUS reg_get_default_country(uint16_t *default_country); * Return: true or false */ bool reg_etsi13_regdmn(uint8_t reg_dmn); + +/** + * reg_en302_502_regdmn() - Check if the reg domain is en302_502 applicable. + * @reg_dmn: Regulatory domain pair ID. + * + * Return: True if EN302_502 applicable, else false. + */ +bool reg_en302_502_regdmn(uint16_t reg_dmn); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_lte.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_lte.c index 2a31e23c447fdbd85ac6abbb4f504025ac3e0f11..2687c314ffe6104212c6c6fca912a46fc79220cd 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_lte.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_lte.c @@ -48,8 +48,8 @@ static QDF_STATUS reg_process_ch_avoid_freq(struct wlan_objmgr_psoc *psoc, enum channel_enum ch_loop; enum channel_enum start_ch_idx; enum channel_enum end_ch_idx; - uint16_t start_channel; - uint16_t end_channel; + uint8_t start_channel; + uint8_t end_channel; uint32_t i; struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; struct ch_avoid_freq_type *range; @@ -62,7 +62,7 @@ static QDF_STATUS reg_process_ch_avoid_freq(struct wlan_objmgr_psoc *psoc, for (i = 0; i < psoc_priv_obj->avoid_freq_list.ch_avoid_range_cnt; i++) { - if (psoc_priv_obj->unsafe_chan_list.ch_cnt >= NUM_CHANNELS) { + if (psoc_priv_obj->unsafe_chan_list.chan_cnt >= NUM_CHANNELS) { reg_warn("LTE Coex unsafe channel list full"); break; } @@ -106,10 +106,10 @@ static QDF_STATUS reg_process_ch_avoid_freq(struct wlan_objmgr_psoc *psoc, for (ch_loop = start_ch_idx; ch_loop <= end_ch_idx; ch_loop++) { - psoc_priv_obj->unsafe_chan_list.ch_list[ - psoc_priv_obj->unsafe_chan_list.ch_cnt++] = - REG_CH_NUM(ch_loop); - if (psoc_priv_obj->unsafe_chan_list.ch_cnt >= + psoc_priv_obj->unsafe_chan_list.chan_freq_list[ + psoc_priv_obj->unsafe_chan_list.chan_cnt++] = + REG_CH_TO_FREQ(ch_loop); + if (psoc_priv_obj->unsafe_chan_list.chan_cnt >= NUM_CHANNELS) { reg_warn("LTECoex unsafe ch list full"); break; @@ -117,16 +117,15 @@ static QDF_STATUS reg_process_ch_avoid_freq(struct wlan_objmgr_psoc *psoc, } } - - if (!psoc_priv_obj->unsafe_chan_list.ch_cnt) + if (!psoc_priv_obj->unsafe_chan_list.chan_cnt) return QDF_STATUS_SUCCESS; - for (ch_loop = 0; ch_loop < psoc_priv_obj->unsafe_chan_list.ch_cnt; + for (ch_loop = 0; ch_loop < psoc_priv_obj->unsafe_chan_list.chan_cnt; ch_loop++) { if (ch_loop >= NUM_CHANNELS) break; reg_debug("Unsafe freq %d", - psoc_priv_obj->unsafe_chan_list.ch_list[ch_loop]); + psoc_priv_obj->unsafe_chan_list.chan_freq_list[ch_loop]); } return QDF_STATUS_SUCCESS; @@ -186,6 +185,11 @@ QDF_STATUS reg_process_ch_avoid_event(struct wlan_objmgr_psoc *psoc, reg_err("reg psoc private obj is NULL"); return QDF_STATUS_E_FAILURE; } + if (CH_AVOID_RULE_DO_NOT_RESTART == + psoc_priv_obj->restart_beaconing) { + reg_debug("skipping all LTE Coex unsafe channel range"); + return QDF_STATUS_SUCCESS; + } /* Make unsafe channel list */ reg_debug("band count %d", ch_avoid_event->ch_avoid_range_cnt); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_offload_11d_scan.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_offload_11d_scan.c index 9c67ef618ac5c21bbc177c1f8df69c6ebd46f387..2099d3847ad8d4a3d55749bcc2001a35ce95bb29 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_offload_11d_scan.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_offload_11d_scan.c @@ -406,7 +406,7 @@ QDF_STATUS reg_save_new_11d_country(struct wlan_objmgr_psoc *psoc, if (tx_ops->set_country_code) { tx_ops->set_country_code(psoc, &country_code); } else { - reg_err("country set handler is not present"); + reg_err("NULL country set handler"); for (ctr = 0; ctr < psoc_priv_obj->num_phy; ctr++) psoc_priv_obj->new_11d_ctry_pending[ctr] = false; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_opclass.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_opclass.c index c6eb0ce191f0fe78892fe528cfd2940236d48479..d661630d032f68d82843ee4da50787b9c5f16031 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_opclass.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_opclass.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -33,94 +33,225 @@ #include #include "reg_build_chan_list.h" #include "reg_opclass.h" +#include "reg_services_common.h" #ifdef HOST_OPCLASS static struct reg_dmn_supp_op_classes reg_dmn_curr_supp_opp_classes = { 0 }; #endif static const struct reg_dmn_op_class_map_t global_op_class[] = { - {81, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, - {82, 25, BW20, {14} }, - {83, 40, BW40_LOW_PRIMARY, {1, 2, 3, 4, 5, 6, 7, 8, 9} }, - {84, 40, BW40_HIGH_PRIMARY, {5, 6, 7, 8, 9, 10, 11, 12, 13} }, - {115, 20, BW20, {36, 40, 44, 48} }, - {116, 40, BW40_LOW_PRIMARY, {36, 44} }, - {117, 40, BW40_HIGH_PRIMARY, {40, 48} }, - {118, 20, BW20, {52, 56, 60, 64} }, - {119, 40, BW40_LOW_PRIMARY, {52, 60} }, - {120, 40, BW40_HIGH_PRIMARY, {56, 64} }, - {121, 20, BW20, - {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} }, - {122, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132} }, - {123, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136} }, - {125, 20, BW20, {149, 153, 157, 161, 165, 169} }, - {126, 40, BW40_LOW_PRIMARY, {149, 157} }, - {127, 40, BW40_HIGH_PRIMARY, {153, 161} }, - {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, - 112, 116, 120, 124, 128, 132, 136, 140, 144, - 149, 153, 157, 161} }, - {0, 0, 0, {0} }, + {81, 25, BW20, BIT(BEHAV_NONE), 2407, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, + {82, 25, BW20, BIT(BEHAV_NONE), 2414, + {14} }, + {83, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 2407, + {1, 2, 3, 4, 5, 6, 7, 8, 9} }, + {84, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 2407, + {5, 6, 7, 8, 9, 10, 11, 12, 13} }, + {115, 20, BW20, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48} }, + {116, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {36, 44} }, + {117, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {40, 48} }, + {118, 20, BW20, BIT(BEHAV_NONE), 5000, + {52, 56, 60, 64} }, + {119, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {52, 60} }, + {120, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {56, 64} }, + {121, 20, BW20, BIT(BEHAV_NONE), 5000, + {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144} }, + {122, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {100, 108, 116, 124, 132, 140} }, + {123, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {104, 112, 120, 128, 136, 144} }, + {125, 20, BW20, BIT(BEHAV_NONE), 5000, + {149, 153, 157, 161, 165, 169} }, + {126, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {149, 157} }, + {127, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {153, 161} }, + {128, 80, BW80, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, + 100, 104, 108, 112, 116, 120, 124, + 128, 132, 136, 140, 144, + 149, 153, 157, 161} }, + {129, 160, BW80, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, + 100, 104, 108, 112, 116, 120, 124, 128} }, + {130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, + 100, 104, 108, 112, 116, 120, 124, 128, + 132, 136, 140, 144, 149, 153, 157, 161} }, + +#ifdef CONFIG_BAND_6GHZ + {131, 20, BW20, BIT(BEHAV_NONE), 5940, + {1, 5, 9, 13, 17, 21, 25, 29, 33, + 37, 41, 45, 49, 53, 57, 61, 65, 69, + 73, 77, 81, 85, 89, 93, 97, + 101, 105, 109, 113, 117, 121, 125, + 129, 133, 137, 141, 145, 149, 153, + 157, 161, 165, 169, 173, 177, 181, + 185, 189, 193, 197, 201, 205, 209, + 213, 217, 221, 225, 229, 233} }, + + {132, 40, BW40_LOW_PRIMARY, BIT(BEHAV_NONE), 5940, + {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, + 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, + 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, + 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, + 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, + 221, 225, 229, 233} }, + + {133, 80, BW80, BIT(BEHAV_NONE), 5940, + {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, + 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, + 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, + 141, 145, 149, 153, 157, 161, 165, 169, 173, + 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, + 217, 221, 225, 229, 233} }, + + {134, 160, BW80, BIT(BEHAV_NONE), 5940, + {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, + 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, + 93, 97, 101, 105, 109, 113, 117, 121, 125, + 129, 133, 137, 141, 145, 149, 153, 157, 161, + 165, 169, 173, 177, 181, 185, 189, 193, 197, + 201, 205, 209, 213, 217, 221, 225, 229, 233} }, + + {135, 80, BW80, BIT(BEHAV_BW80_PLUS), 5940, + {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, + 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, + 85, 89, 93, 97, 101, 105, 109, 113, 117, + 121, 125, 129, 133, 137, 141, 145, 149, + 153, 157, 161, 165, 169, 173, 177, 181, + 185, 189, 193, 197, 201, 205, 209, 213, + 217, 221, 225, 229, 233} }, +#endif + {0, 0, 0, 0, 0, {0} }, }; static const struct reg_dmn_op_class_map_t us_op_class[] = { - {1, 20, BW20, {36, 40, 44, 48} }, - {2, 20, BW20, {52, 56, 60, 64} }, - {4, 20, BW20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, - 144} }, - {5, 20, BW20, {149, 153, 157, 161, 165} }, - {12, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} }, - {22, 40, BW40_LOW_PRIMARY, {36, 44} }, - {23, 40, BW40_LOW_PRIMARY, {52, 60} }, - {24, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132} }, - {26, 40, BW40_LOW_PRIMARY, {149, 157} }, - {27, 40, BW40_HIGH_PRIMARY, {40, 48} }, - {28, 40, BW40_HIGH_PRIMARY, {56, 64} }, - {29, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136} }, - {30, 40, BW40_HIGH_PRIMARY, {153, 161} }, - {31, 40, BW40_HIGH_PRIMARY, {153, 161} }, - {32, 40, BW40_LOW_PRIMARY, {1, 2, 3, 4, 5, 6, 7} }, - {33, 40, BW40_HIGH_PRIMARY, {5, 6, 7, 8, 9, 10, 11} }, - {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, - 112, 116, 120, 124, 128, 132, 136, 140, 144, - 149, 153, 157, 161} }, - {0, 0, 0, {0} }, + {1, 20, BW20, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48} }, + {2, 20, BW20, BIT(BEHAV_NONE), 5000, + {52, 56, 60, 64} }, + {4, 20, BW20, BIT(BEHAV_NONE), 5000, + {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144} }, + {5, 20, BW20, BIT(BEHAV_NONE), 5000, + {149, 153, 157, 161, 165} }, + {12, 25, BW20, BIT(BEHAV_NONE), 2407, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} }, + {22, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {36, 44} }, + {23, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {52, 60} }, + {24, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {100, 108, 116, 124, 132} }, + {26, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {149, 157} }, + {27, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {40, 48} }, + {28, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {56, 64} }, + {29, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {104, 112, 120, 128, 136} }, + {30, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {153, 161} }, + {31, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {153, 161} }, + {32, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 2407, + {1, 2, 3, 4, 5, 6, 7} }, + {33, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 2407, + {5, 6, 7, 8, 9, 10, 11} }, + {128, 80, BW80, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, 100, + 104, 108, 112, 116, 120, 124, 128, 132, + 136, 140, 144, 149, 153, 157, 161} }, + {129, 160, BW80, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, 100, + 104, 108, 112, 116, 120, 124, 128} }, + {130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, 100, + 104, 108, 112, 116, 120, 124, 128, 132, + 136, 140, 144, 149, 153, 157, 161} }, + {0, 0, 0, 0, 0, {0} }, }; static const struct reg_dmn_op_class_map_t euro_op_class[] = { - {1, 20, BW20, {36, 40, 44, 48} }, - {2, 20, BW20, {52, 56, 60, 64} }, - {3, 20, BW20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} }, - {4, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, - {5, 40, BW40_LOW_PRIMARY, {36, 44} }, - {6, 40, BW40_LOW_PRIMARY, {52, 60} }, - {7, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132} }, - {8, 40, BW40_HIGH_PRIMARY, {40, 48} }, - {9, 40, BW40_HIGH_PRIMARY, {56, 64} }, - {10, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136} }, - {11, 40, BW40_LOW_PRIMARY, {1, 2, 3, 4, 5, 6, 7, 8, 9} }, - {12, 40, BW40_HIGH_PRIMARY, {5, 6, 7, 8, 9, 10, 11, 12, 13} }, - {17, 20, BW20, {149, 153, 157, 161, 165, 169} }, - {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128} }, - {0, 0, 0, {0} }, + {1, 20, BW20, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48} }, + {2, 20, BW20, BIT(BEHAV_NONE), 5000, + {52, 56, 60, 64} }, + {3, 20, BW20, BIT(BEHAV_NONE), 5000, + {100, 104, 108, 112, 116, 120, + 124, 128, 132, 136, 140} }, + {4, 25, BW20, BIT(BEHAV_NONE), 2407, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, + {5, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {36, 44} }, + {6, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {52, 60} }, + {7, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {100, 108, 116, 124, 132} }, + {8, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {40, 48} }, + {9, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {56, 64} }, + {10, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {104, 112, 120, 128, 136} }, + {11, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 2407, + {1, 2, 3, 4, 5, 6, 7, 8, 9} }, + {12, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 2407, + {5, 6, 7, 8, 9, 10, 11, 12, 13} }, + {17, 20, BW20, BIT(BEHAV_NONE), 5000, + {149, 153, 157, 161, 165, 169} }, + {128, 80, BW80, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, + 124, 128} }, + {129, 160, BW80, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, 100, + 104, 108, 112, 116, 120, 124, 128} }, + {130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, + 124, 128} }, + {0, 0, 0, 0, 0, {0} }, }; static const struct reg_dmn_op_class_map_t japan_op_class[] = { - {1, 20, BW20, {36, 40, 44, 48} }, - {30, 25, BW20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, - {31, 25, BW20, {14} }, - {32, 20, BW20, {52, 56, 60, 64} }, - {34, 20, BW20, - {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} }, - {36, 40, BW40_LOW_PRIMARY, {36, 44} }, - {37, 40, BW40_LOW_PRIMARY, {52, 60} }, - {39, 40, BW40_LOW_PRIMARY, {100, 108, 116, 124, 132} }, - {41, 40, BW40_HIGH_PRIMARY, {40, 48} }, - {42, 40, BW40_HIGH_PRIMARY, {56, 64} }, - {44, 40, BW40_HIGH_PRIMARY, {104, 112, 120, 128, 136} }, - {128, 80, BW80, {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128} }, - {0, 0, 0, {0} }, + {1, 20, BW20, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48} }, + {30, 25, BW20, BIT(BEHAV_NONE), 2407, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} }, + {31, 25, BW20, BIT(BEHAV_NONE), 2407, + {14} }, + {32, 20, BW20, BIT(BEHAV_NONE), 5000, + {52, 56, 60, 64} }, + {34, 20, BW20, BIT(BEHAV_NONE), 5000, + {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140} }, + {36, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {36, 44} }, + {37, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {52, 60} }, + {39, 40, BW40_LOW_PRIMARY, BIT(BEHAV_BW40_LOW_PRIMARY), 5000, + {100, 108, 116, 124, 132} }, + {41, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {40, 48} }, + {42, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {56, 64} }, + {44, 40, BW40_HIGH_PRIMARY, BIT(BEHAV_BW40_HIGH_PRIMARY), 5000, + {104, 112, 120, 128, 136} }, + {128, 80, BW80, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, + 124, 128} }, + {129, 160, BW80, BIT(BEHAV_NONE), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, 100, + 104, 108, 112, 116, 120, 124, 128} }, + {130, 80, BW80, BIT(BEHAV_BW80_PLUS), 5000, + {36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, + 124, 128} }, + {0, 0, 0, 0, 0, {0} }, }; #ifdef HOST_OPCLASS @@ -130,9 +261,8 @@ static const struct reg_dmn_op_class_map_t japan_op_class[] = { * * Return: class. */ -static -const struct reg_dmn_op_class_map_t *reg_get_class_from_country(uint8_t - *country) +static const +struct reg_dmn_op_class_map_t *reg_get_class_from_country(uint8_t *country) { const struct reg_dmn_op_class_map_t *class = NULL; @@ -181,7 +311,7 @@ uint16_t reg_dmn_get_chanwidth_from_opclass(uint8_t *country, uint8_t channel, for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && class->channels[i]); i++) { if (channel == class->channels[i]) - return class->ch_spacing; + return class->chan_spacing; } } class++; @@ -211,6 +341,34 @@ uint16_t reg_dmn_get_opclass_from_channel(uint8_t *country, uint8_t channel, return 0; } +uint8_t reg_dmn_get_opclass_from_freq_width(uint8_t *country, + qdf_freq_t freq, + uint8_t ch_width, + uint16_t behav_limit) +{ + const struct reg_dmn_op_class_map_t *op_class_tbl = NULL; + uint16_t i = 0; + + op_class_tbl = reg_get_class_from_country(country); + + while (op_class_tbl && op_class_tbl->op_class) { + if (op_class_tbl->chan_spacing == ch_width) { + for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && + op_class_tbl->channels[i]); i++) { + if ((op_class_tbl->start_freq + + (FREQ_TO_CHAN_SCALE * + op_class_tbl->channels[i]) == freq) && + (behav_limit & op_class_tbl->behav_limit)) { + return op_class_tbl->op_class; + } + } + } + op_class_tbl++; + } + + return 0; +} + void reg_dmn_print_channels_in_opclass(uint8_t *country, uint8_t op_class) { const struct reg_dmn_op_class_map_t *class = NULL; @@ -273,4 +431,452 @@ uint16_t reg_dmn_get_curr_opclasses(uint8_t *num_classes, uint8_t *class) return 0; } + +#ifdef CONFIG_CHAN_FREQ_API +void reg_freq_width_to_chan_op_class_auto(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + uint16_t chan_width, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num) +{ + if (reg_freq_to_band(freq) == REG_BAND_6G) { + global_tbl_lookup = true; + if (chan_width == BW_40_MHZ) + behav_limit = BIT(BEHAV_NONE); + } else { + global_tbl_lookup = false; + } + + reg_freq_width_to_chan_op_class(pdev, freq, + chan_width, + global_tbl_lookup, + behav_limit, + op_class, + chan_num); +} + +void reg_freq_width_to_chan_op_class(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + uint16_t chan_width, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num) +{ + const struct reg_dmn_op_class_map_t *op_class_tbl; + enum channel_enum chan_enum; + uint16_t i; + + chan_enum = reg_get_chan_enum_for_freq(freq); + + if (chan_enum == INVALID_CHANNEL) { + reg_err_rl("Invalid chan enum %d", chan_enum); + return; + } + + if (global_tbl_lookup) { + op_class_tbl = global_op_class; + } else { + if (channel_map == channel_map_us) + op_class_tbl = us_op_class; + else if (channel_map == channel_map_eu) + op_class_tbl = euro_op_class; + else if (channel_map == channel_map_china) + op_class_tbl = us_op_class; + else if (channel_map == channel_map_jp) + op_class_tbl = japan_op_class; + else + op_class_tbl = global_op_class; + } + + while (op_class_tbl->op_class) { + if (op_class_tbl->chan_spacing >= chan_width) { + for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && + op_class_tbl->channels[i]); i++) { + if ((op_class_tbl->start_freq + + FREQ_TO_CHAN_SCALE * + op_class_tbl->channels[i] == freq) && + (behav_limit & op_class_tbl->behav_limit || + behav_limit == BIT(BEHAV_NONE))) { + *chan_num = op_class_tbl->channels[i]; + *op_class = op_class_tbl->op_class; + return; + } + } + } + op_class_tbl++; + } + + reg_err_rl("no op class for frequency %d", freq); +} + +void reg_freq_to_chan_op_class(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num) +{ + enum channel_enum chan_enum; + struct regulatory_channel *cur_chan_list; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct ch_params chan_params; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err_rl("NULL pdev reg obj"); + return; + } + + cur_chan_list = pdev_priv_obj->cur_chan_list; + + chan_enum = reg_get_chan_enum_for_freq(freq); + + if (chan_enum == INVALID_CHANNEL) { + reg_err_rl("Invalid chan enum %d", chan_enum); + return; + } + + chan_params.ch_width = CH_WIDTH_MAX; + reg_set_channel_params_for_freq(pdev, freq, 0, &chan_params); + + reg_freq_width_to_chan_op_class(pdev, freq, + reg_get_bw_value(chan_params.ch_width), + global_tbl_lookup, + behav_limit, + op_class, + chan_num); +} + +bool reg_country_opclass_freq_check(struct wlan_objmgr_pdev *pdev, + const uint8_t country[3], + uint8_t op_class, + qdf_freq_t chan_freq) +{ + const struct reg_dmn_op_class_map_t *op_class_tbl; + uint8_t i; + + op_class_tbl = reg_get_class_from_country((uint8_t *)country); + + while (op_class_tbl && op_class_tbl->op_class) { + if (op_class_tbl->op_class == op_class) { + for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && + op_class_tbl->channels[i]); i++) { + if (op_class_tbl->channels[i] * + FREQ_TO_CHAN_SCALE + + op_class_tbl->start_freq == chan_freq) + return true; + } + } + op_class_tbl++; + } + return false; +} + +#endif + +uint16_t reg_get_op_class_width(struct wlan_objmgr_pdev *pdev, + uint8_t op_class, + bool global_tbl_lookup) +{ + const struct reg_dmn_op_class_map_t *op_class_tbl; + + if (global_tbl_lookup) { + op_class_tbl = global_op_class; + } else { + if (channel_map == channel_map_us) + op_class_tbl = us_op_class; + else if (channel_map == channel_map_eu) + op_class_tbl = euro_op_class; + else if (channel_map == channel_map_china) + op_class_tbl = us_op_class; + else if (channel_map == channel_map_jp) + op_class_tbl = japan_op_class; + else + op_class_tbl = global_op_class; + } + + while (op_class_tbl->op_class) { + if (op_class_tbl->op_class == op_class) + return op_class_tbl->chan_spacing; + op_class_tbl++; + } + + return 0; +} + +uint16_t reg_chan_opclass_to_freq(uint8_t chan, + uint8_t op_class, + bool global_tbl_lookup) +{ + const struct reg_dmn_op_class_map_t *op_class_tbl = NULL; + uint8_t i = 0; + + if (global_tbl_lookup) { + op_class_tbl = global_op_class; + } else { + if (channel_map == channel_map_global) { + op_class_tbl = global_op_class; + } else if (channel_map == channel_map_us) { + op_class_tbl = us_op_class; + } else if (channel_map == channel_map_eu) { + op_class_tbl = euro_op_class; + } else if (channel_map == channel_map_china) { + op_class_tbl = us_op_class; + } else if (channel_map == channel_map_jp) { + op_class_tbl = japan_op_class; + } else { + reg_err_rl("Invalid channel map"); + return 0; + } + } + + while (op_class_tbl->op_class) { + if (op_class_tbl->op_class == op_class) { + for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && + op_class_tbl->channels[i]); i++) { + if (op_class_tbl->channels[i] == chan) { + chan = op_class_tbl->channels[i]; + return op_class_tbl->start_freq + + (chan * FREQ_TO_CHAN_SCALE); + } + } + reg_err_rl("Channel not found"); + return 0; + } + op_class_tbl++; + } + reg_err_rl("Invalid opclass"); + return 0; +} + +#ifdef HOST_OPCLASS_EXT +qdf_freq_t reg_country_chan_opclass_to_freq(struct wlan_objmgr_pdev *pdev, + const uint8_t country[3], + uint8_t chan, uint8_t op_class, + bool strict) +{ + const struct reg_dmn_op_class_map_t *op_class_tbl, *op_class_tbl_org; + uint16_t i; + + if (reg_is_6ghz_op_class(pdev, op_class)) + op_class_tbl_org = global_op_class; + else + op_class_tbl_org = + reg_get_class_from_country((uint8_t *)country); + op_class_tbl = op_class_tbl_org; + while (op_class_tbl && op_class_tbl->op_class) { + if (op_class_tbl->op_class == op_class) { + for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && + op_class_tbl->channels[i]); i++) { + if (op_class_tbl->channels[i] == chan) + return op_class_tbl->start_freq + + (chan * FREQ_TO_CHAN_SCALE); + } + } + op_class_tbl++; + } + reg_debug_rl("Not found ch %d in op class %d ch list, strict %d", + chan, op_class, strict); + if (strict) + return 0; + + op_class_tbl = op_class_tbl_org; + while (op_class_tbl && op_class_tbl->op_class) { + for (i = 0; (i < REG_MAX_CHANNELS_PER_OPERATING_CLASS && + op_class_tbl->channels[i]); i++) { + if (op_class_tbl->channels[i] == chan) + return op_class_tbl->start_freq + + (chan * FREQ_TO_CHAN_SCALE); + } + op_class_tbl++; + } + reg_debug_rl("Got invalid freq 0 for ch %d", chan); + + return 0; +} +#endif + +static void +reg_get_op_class_tbl_by_chan_map(const struct + reg_dmn_op_class_map_t **op_class_tbl) +{ + if (channel_map == channel_map_us) + *op_class_tbl = us_op_class; + else if (channel_map == channel_map_eu) + *op_class_tbl = euro_op_class; + else if (channel_map == channel_map_china) + *op_class_tbl = us_op_class; + else if (channel_map == channel_map_jp) + *op_class_tbl = japan_op_class; + else + *op_class_tbl = global_op_class; +} + +/** + * reg_get_channel_cen - Calculate central channel in the channel set. + * + * @op_class_tbl - Pointer to op_class_tbl. + * @idx - Pointer to channel index. + * @num_channels - Number of channels. + * @center_chan - Pointer to center channel number + * + * Return : void + */ +static void reg_get_channel_cen(const struct + reg_dmn_op_class_map_t *op_class_tbl, + uint8_t *idx, + uint8_t num_channels, + uint8_t *center_chan) +{ + uint8_t i; + uint16_t new_chan = 0; + + for (i = *idx; i < (*idx + num_channels); i++) + new_chan += op_class_tbl->channels[i]; + + new_chan = new_chan / num_channels; + *center_chan = new_chan; + *idx = *idx + num_channels; +} + +/** + * reg_get_chan_or_chan_center - Calculate central channel in the channel set. + * + * @op_class_tbl - Pointer to op_class_tbl. + * @idx - Pointer to channel index. + * + * Return : Center channel number + */ +static uint8_t reg_get_chan_or_chan_center(const struct + reg_dmn_op_class_map_t *op_class_tbl, + uint8_t *idx) +{ + uint8_t center_chan; + + if (((op_class_tbl->chan_spacing == BW_80_MHZ) && + (op_class_tbl->behav_limit == BIT(BEHAV_NONE))) || + ((op_class_tbl->chan_spacing == BW_80_MHZ) && + (op_class_tbl->behav_limit == BIT(BEHAV_BW80_PLUS)))) { + reg_get_channel_cen(op_class_tbl, + idx, + NUM_20_MHZ_CHAN_IN_80_MHZ_CHAN, + ¢er_chan); + } else if (op_class_tbl->chan_spacing == BW_160_MHZ) { + reg_get_channel_cen(op_class_tbl, + idx, + NUM_20_MHZ_CHAN_IN_160_MHZ_CHAN, + ¢er_chan); + } else { + center_chan = op_class_tbl->channels[*idx]; + *idx = *idx + 1; + } + + return center_chan; +} + +/** + * reg_get_channels_from_opclassmap()- Get channels from the opclass map + * @pdev: Pointer to pdev + * @reg_ap_cap: Pointer to reg_ap_cap + * @index: Pointer to index of reg_ap_cap + * @op_class_tbl: Pointer to op_class_tbl + * @is_opclass_operable: Set true if opclass is operable, else set false + * + * Populate channels from opclass map to reg_ap_cap as supported and + * non-supported channels. + * + * Return: void. + */ +static void +reg_get_channels_from_opclassmap( + struct wlan_objmgr_pdev *pdev, + struct regdmn_ap_cap_opclass_t *reg_ap_cap, + uint8_t index, + const struct reg_dmn_op_class_map_t *op_class_tbl, + bool *is_opclass_operable) +{ + uint8_t op_cls_chan; + qdf_freq_t search_freq; + bool is_freq_present; + uint8_t chan_idx = 0, n_sup_chans = 0, n_unsup_chans = 0; + + while (op_class_tbl->channels[chan_idx]) { + op_cls_chan = op_class_tbl->channels[chan_idx]; + search_freq = op_class_tbl->start_freq + + (FREQ_TO_CHAN_SCALE * op_cls_chan); + is_freq_present = + reg_is_freq_present_in_cur_chan_list(pdev, search_freq); + + if (!is_freq_present) { + reg_ap_cap[index].non_sup_chan_list[n_unsup_chans++] = + reg_get_chan_or_chan_center(op_class_tbl, + &chan_idx); + reg_ap_cap[index].num_non_supported_chan++; + } else { + reg_ap_cap[index].sup_chan_list[n_sup_chans++] = + reg_get_chan_or_chan_center(op_class_tbl, + &chan_idx); + reg_ap_cap[index].num_supported_chan++; + } + } + + if (reg_ap_cap[index].num_supported_chan >= 1) + *is_opclass_operable = true; +} + +QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev, + struct regdmn_ap_cap_opclass_t *reg_ap_cap, + uint8_t *n_opclasses, + uint8_t max_supp_op_class, + bool global_tbl_lookup) +{ + uint8_t max_reg_power = 0; + const struct reg_dmn_op_class_map_t *op_class_tbl; + uint8_t index = 0; + + if (global_tbl_lookup) + op_class_tbl = global_op_class; + else + reg_get_op_class_tbl_by_chan_map(&op_class_tbl); + + max_reg_power = reg_get_max_tx_power(pdev); + + while (op_class_tbl->op_class && (index < max_supp_op_class)) { + bool is_opclass_operable = false; + + qdf_mem_zero(reg_ap_cap[index].sup_chan_list, + REG_MAX_CHANNELS_PER_OPERATING_CLASS); + reg_ap_cap[index].num_supported_chan = 0; + qdf_mem_zero(reg_ap_cap[index].non_sup_chan_list, + REG_MAX_CHANNELS_PER_OPERATING_CLASS); + reg_ap_cap[index].num_non_supported_chan = 0; + reg_get_channels_from_opclassmap(pdev, + reg_ap_cap, + index, + op_class_tbl, + &is_opclass_operable); + if (is_opclass_operable) { + reg_ap_cap[index].op_class = op_class_tbl->op_class; + reg_ap_cap[index].ch_width = + op_class_tbl->chan_spacing; + reg_ap_cap[index].start_freq = + op_class_tbl->start_freq; + reg_ap_cap[index].max_tx_pwr_dbm = max_reg_power; + reg_ap_cap[index].behav_limit = + op_class_tbl->behav_limit; + index++; + } + + op_class_tbl++; + } + + *n_opclasses = index; + + return QDF_STATUS_SUCCESS; +} + #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_opclass.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_opclass.h index 8b2ffd969a68e529fef15b78d8b7b348e9fe7344..0cd260c0cdf8859da78d158c23e6fd83995fbb16 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_opclass.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_opclass.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -47,6 +47,21 @@ uint16_t reg_dmn_get_chanwidth_from_opclass(uint8_t *country, uint8_t channel, */ uint16_t reg_dmn_get_opclass_from_channel(uint8_t *country, uint8_t channel, uint8_t offset); + +/** + * reg_dmn_get_opclass_from_freq_width() - Get operating class from frequency + * @country: Country code. + * @freq: Channel center frequency. + * @ch_width: Channel width. + * @behav_limit: Behaviour limit. + * + * Return: Error code. + */ +uint8_t reg_dmn_get_opclass_from_freq_width(uint8_t *country, + qdf_freq_t freq, + uint8_t ch_width, + uint16_t behav_limit); + /** * reg_dmn_get_opclass_from_channe() - Print channels in op class. * @country: Country code. @@ -74,6 +89,147 @@ uint16_t reg_dmn_set_curr_opclasses(uint8_t num_classes, uint8_t *class); */ uint16_t reg_dmn_get_curr_opclasses(uint8_t *num_classes, uint8_t *class); +/** + * reg_get_opclass_details() - Get details about the current opclass table. + * @pdev: Pointer to pdev. + * @reg_ap_cap: Pointer to reg_ap_cap. + * @n_opclasses: Pointer to number of opclasses. + * @max_supp_op_class: Maximum number of operating classes supported. + * @global_tbl_lookup: Whether to lookup global op class table. + * + * Return: QDF_STATUS_SUCCESS if success, else return QDF_STATUS_FAILURE. + */ +QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev, + struct regdmn_ap_cap_opclass_t *reg_ap_cap, + uint8_t *n_opclasses, + uint8_t max_supp_op_class, + bool global_tbl_lookup); +#ifdef CONFIG_CHAN_FREQ_API + +/** + * reg_freq_width_to_chan_op_class() - convert frequency to oper class, + * channel + * @pdev: pdev pointer + * @freq: channel frequency in mhz + * @chan_width: channel width + * @global_tbl_lookup: whether to lookup global op class tbl + * @behav_limit: behavior limit + * @op_class: operating class + * @chan_num: channel number + * + * Return: Void. + */ +void reg_freq_width_to_chan_op_class(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + uint16_t chan_width, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num); + +/** + * reg_freq_width_to_chan_op_class_auto() - convert frequency to operating + * class,channel after fixing up the global_tbl_lookup and behav_limit + * for 6G frequencies. + * @pdev: pdev pointer + * @freq: channel frequency in mhz + * @chan_width: channel width + * @global_tbl_lookup: whether to lookup global op class tbl + * @behav_limit: behavior limit + * @op_class: operating class + * @chan_num: channel number + * + * Return: Void. + */ +void reg_freq_width_to_chan_op_class_auto(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + uint16_t chan_width, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num); + +/** + * reg_freq_to_chan_op_class() - convert frequency to oper class, + * channel + * @pdev: pdev pointer + * @freq: channel frequency in mhz + * @global_tbl_lookup: whether to lookup global op class tbl + * @behav_limit: behavior limit + * @op_class: operating class + * @chan_num: channel number + * + * Return: Void. + */ +void reg_freq_to_chan_op_class(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num); + +/** + * reg_country_opclass_freq_check() - check for frequency in (tbl, oper class) + * + * @pdev: pdev pointer + * @country: country from country IE + * @op_class: operating class + * @chan_freq: channel frequency in mhz + * + * Return: bool + */ +bool reg_country_opclass_freq_check(struct wlan_objmgr_pdev *pdev, + const uint8_t country[3], + uint8_t op_class, + qdf_freq_t chan_freq); +#endif + +/** + * reg_get_op_class_width() - get oper class width + * + * @pdev: pdev pointer + * @global_tbl_lookup: whether to lookup global op class tbl + * @op_class: operating class + * Return: uint16 + */ +uint16_t reg_get_op_class_width(struct wlan_objmgr_pdev *pdev, + uint8_t op_class, + bool global_tbl_lookup); + +#ifdef HOST_OPCLASS_EXT +/** + * reg_country_chan_opclass_to_freq() - Convert channel number to frequency + * based on country code and op class + * @pdev: pdev object. + * @country: country code. + * @chan: IEEE Channel Number. + * @op_class: Opclass. + * @strict: flag to find channel from matched operating class code. + * + * Look up (channel, operating class) pair in country operating class tables + * and return the channel frequency. + * If not found and "strict" flag is false, try to get frequency (Mhz) by + * channel number only. + * + * Return: Channel center frequency else return 0. + */ +qdf_freq_t reg_country_chan_opclass_to_freq(struct wlan_objmgr_pdev *pdev, + const uint8_t country[3], + uint8_t chan, uint8_t op_class, + bool strict); +#endif + +/** + * reg_chan_opclass_to_freq() - Convert channel number and opclass to frequency + * @chan: IEEE Channel Number. + * @op_class: Opclass. + * @global_tbl_lookup: Global table lookup. + * + * Return: Channel center frequency else return 0. + */ +uint16_t reg_chan_opclass_to_freq(uint8_t chan, + uint8_t op_class, + bool global_tbl_lookup); #else static inline uint16_t reg_dmn_get_chanwidth_from_opclass( @@ -100,10 +256,99 @@ static inline uint16_t reg_dmn_get_opclass_from_channel( return 0; } +static inline +uint8_t reg_dmn_get_opclass_from_freq_width(uint8_t *country, + qdf_freq_t freq, + uint8_t ch_width, + uint16_t behav_limit) +{ + return 0; +} + static inline void reg_dmn_print_channels_in_opclass(uint8_t *country, uint8_t op_class) { } +static inline +QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev, + struct regdmn_ap_cap_opclass_t *reg_ap_cap, + uint8_t *n_opclasses, + uint8_t max_supp_op_class, + bool global_tbl_lookup) +{ + return QDF_STATUS_E_FAILURE; +} + +#ifdef CONFIG_CHAN_FREQ_API + +static inline void +reg_freq_width_to_chan_op_class(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + uint16_t chan_width, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num) +{ +} + +static inline void +reg_freq_width_to_chan_op_class_auto(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + uint16_t chan_width, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num) +{ +} + +static inline void +reg_freq_to_chan_op_class(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num) +{ +} + +static inline bool +reg_country_opclass_freq_check(struct wlan_objmgr_pdev *pdev, + const uint8_t country[3], + uint8_t op_class, + uint16_t chan_freq) +{ +} + +#endif + +static inline uint16_t reg_get_op_class_width(struct wlan_objmgr_pdev *pdev, + uint8_t op_class, + bool global_tbl_lookup) +{ + return 0; +} + +#ifdef HOST_OPCLASS_EXT +static inline +qdf_freq_t reg_country_chan_opclass_to_freq(struct wlan_objmgr_pdev *pdev, + const uint8_t country[3], + uint8_t chan, uint8_t op_class, + bool strict) +{ + return 0; +} +#endif + +static inline uint16_t +reg_chan_opclass_to_freq(uint8_t chan, + uint8_t op_class, + bool global_tbl_lookup) +{ + return 0; +} + #endif #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_priv_objs.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_priv_objs.c index 3da6ecf696bc047b71776a32bf66a5be21101b3b..8f31c6a3a3f9c6aa8b99000a31b199984b386bb6 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_priv_objs.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_priv_objs.c @@ -32,6 +32,7 @@ #include "reg_services_common.h" #include "reg_build_chan_list.h" #include "reg_host_11d.h" +#include "reg_callbacks.h" struct wlan_regulatory_psoc_priv_obj *reg_get_psoc_obj( struct wlan_objmgr_psoc *psoc) @@ -81,7 +82,8 @@ QDF_STATUS wlan_regulatory_psoc_obj_created_notification( soc_reg_obj->offload_enabled = false; soc_reg_obj->psoc_ptr = psoc; soc_reg_obj->dfs_enabled = true; - soc_reg_obj->band_capability = BAND_ALL; + soc_reg_obj->band_capability = (BIT(REG_BAND_2G) | BIT(REG_BAND_5G) | + BIT(REG_BAND_6G)); soc_reg_obj->enable_11d_supp = false; soc_reg_obj->indoor_chan_enabled = true; soc_reg_obj->force_ssc_disable_indoor_channel = false; @@ -89,8 +91,9 @@ QDF_STATUS wlan_regulatory_psoc_obj_created_notification( soc_reg_obj->vdev_cnt_11d = 0; soc_reg_obj->vdev_id_for_11d_scan = INVALID_VDEV_ID; soc_reg_obj->restart_beaconing = CH_AVOID_RULE_RESTART; - soc_reg_obj->enable_srd_chan_in_master_mode = true; + soc_reg_obj->enable_srd_chan_in_master_mode = 0xFF; soc_reg_obj->enable_11d_in_world_mode = false; + soc_reg_obj->retain_nol_across_regdmn_update = false; for (i = 0; i < MAX_STA_VDEV_CNT; i++) soc_reg_obj->vdev_ids_11d[i] = INVALID_VDEV_ID; @@ -100,6 +103,7 @@ QDF_STATUS wlan_regulatory_psoc_obj_created_notification( for (pdev_cnt = 0; pdev_cnt < PSOC_MAX_PHY_REG_CAP; pdev_cnt++) { mas_chan_list = soc_reg_obj->mas_chan_params[pdev_cnt].mas_chan_list; + soc_reg_obj->chan_list_recvd[pdev_cnt] = false; for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { mas_chan_list[chan_enum].chan_flags |= @@ -152,6 +156,25 @@ QDF_STATUS wlan_regulatory_psoc_obj_destroyed_notification( return status; } +#ifdef DISABLE_UNII_SHARED_BANDS +/** + * reg_reset_unii_5g_bitmap() - Reset the value of unii_5g_bitmap. + * @pdev_priv_obj: pointer to wlan_regulatory_pdev_priv_obj. + * + * Return : void + */ +static void +reg_reset_unii_5g_bitmap(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) +{ + pdev_priv_obj->unii_5g_bitmap = 0x0; +} +#else +static void inline +reg_reset_unii_5g_bitmap(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) +{ +} +#endif + QDF_STATUS wlan_regulatory_pdev_obj_created_notification( struct wlan_objmgr_pdev *pdev, void *arg_list) { @@ -183,10 +206,11 @@ QDF_STATUS wlan_regulatory_pdev_obj_created_notification( pdev_priv_obj->pdev_ptr = pdev; pdev_priv_obj->dfs_enabled = psoc_priv_obj->dfs_enabled; pdev_priv_obj->set_fcc_channel = false; - pdev_priv_obj->band_capability = psoc_priv_obj->band_capability; + pdev_priv_obj->band_capability = psoc_priv_obj->band_capability; pdev_priv_obj->indoor_chan_enabled = psoc_priv_obj->indoor_chan_enabled; pdev_priv_obj->en_chan_144 = true; + reg_reset_unii_5g_bitmap(pdev_priv_obj); qdf_spinlock_create(&pdev_priv_obj->reg_rules_lock); @@ -228,6 +252,8 @@ QDF_STATUS wlan_regulatory_pdev_obj_created_notification( psoc_reg_rules = &psoc_priv_obj->mas_chan_params[pdev_id].reg_rules; reg_save_reg_rules_to_pdev(psoc_reg_rules, pdev_priv_obj); + pdev_priv_obj->chan_list_recvd = + psoc_priv_obj->chan_list_recvd[pdev_id]; status = wlan_objmgr_pdev_component_obj_attach( pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj, diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_priv_objs.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_priv_objs.h index c5f6cd301baa52c560e4d7f868f0721ebb43cd22..dc0c8bce08cde8209c591b53b91f2922c0aa8582 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_priv_objs.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_priv_objs.h @@ -80,6 +80,7 @@ struct chan_change_cbk_entry { /** * struct wlan_regulatory_psoc_priv_obj - wlan regulatory psoc private object + * @chan_list_recvd: whether channel list has been received * @new_user_ctry_pending: In this array, element[phy_id] is true if any user * country update is pending for pdev (phy_id), used in case of MCL. * @new_init_ctry_pending: In this array, element[phy_id] is true if any user @@ -88,9 +89,16 @@ struct chan_change_cbk_entry { * country update is pending for pdev (phy_id). * @world_country_pending: In this array, element[phy_id] is true if any world * country update is pending for pdev (phy_id). + * @band_capability: bitmap of bands enabled, using enum reg_wifi_band as the + * bit position value + * @ignore_fw_reg_offload_ind: Ignore FW reg offload indication + * @six_ghz_supported: whether 6ghz is supported + * @retain_nol_across_regdmn_update: Retain the NOL list across the regdomain + * changes. */ struct wlan_regulatory_psoc_priv_obj { struct mas_chan_params mas_chan_params[PSOC_MAX_PHY_REG_CAP]; + bool chan_list_recvd[PSOC_MAX_PHY_REG_CAP]; bool offload_enabled; bool six_ghz_supported; uint8_t num_phy; @@ -105,7 +113,7 @@ struct wlan_regulatory_psoc_priv_obj { bool new_11d_ctry_pending[PSOC_MAX_PHY_REG_CAP]; bool world_country_pending[PSOC_MAX_PHY_REG_CAP]; bool dfs_enabled; - enum band_info band_capability; + uint32_t band_capability; bool indoor_chan_enabled; bool ignore_fw_reg_offload_ind; bool enable_11d_supp_original; @@ -133,14 +141,17 @@ struct wlan_regulatory_psoc_priv_obj { struct wlan_psoc_host_hal_reg_capabilities_ext reg_cap[PSOC_MAX_PHY_REG_CAP]; bool force_ssc_disable_indoor_channel; - bool enable_srd_chan_in_master_mode; + uint8_t enable_srd_chan_in_master_mode; bool enable_11d_in_world_mode; qdf_spinlock_t cbk_list_lock; + bool retain_nol_across_regdmn_update; }; /** * struct wlan_regulatory_pdev_priv_obj - wlan regulatory pdev private object * @pdev_opened: whether pdev has been opened by application + * @band_capability: bitmap of bands enabled, using enum reg_wifi_band as the + * bit position value */ struct wlan_regulatory_pdev_priv_obj { struct regulatory_channel cur_chan_list[NUM_CHANNELS]; @@ -156,16 +167,19 @@ struct wlan_regulatory_pdev_priv_obj { char current_country[REG_ALPHA2_LEN + 1]; uint16_t reg_dmn_pair; uint16_t ctry_code; +#ifdef DISABLE_UNII_SHARED_BANDS + uint8_t unii_5g_bitmap; +#endif enum dfs_reg dfs_region; uint32_t phybitmap; struct wlan_objmgr_pdev *pdev_ptr; - uint32_t range_2g_low; - uint32_t range_2g_high; - uint32_t range_5g_low; - uint32_t range_5g_high; + qdf_freq_t range_2g_low; + qdf_freq_t range_2g_high; + qdf_freq_t range_5g_low; + qdf_freq_t range_5g_high; bool dfs_enabled; bool set_fcc_channel; - enum band_info band_capability; + uint32_t band_capability; bool indoor_chan_enabled; bool en_chan_144; uint32_t wireless_modes; @@ -174,6 +188,7 @@ struct wlan_regulatory_pdev_priv_obj { bool sap_state; struct reg_rule_info reg_rules; qdf_spinlock_t reg_rules_lock; + bool chan_list_recvd; bool pdev_opened; }; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services_common.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services_common.c index 809619220b8207b357b54ab73892a4b85461f000..be27444d70a67faea1b843b658dca11899a8aa20 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services_common.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -34,9 +34,10 @@ #include "reg_db_parser.h" #include "reg_build_chan_list.h" #include +#include const struct chan_map *channel_map; - +#ifdef CONFIG_CHAN_NUM_API static const struct bonded_channel bonded_chan_40mhz_list[] = { {36, 40}, {44, 48}, @@ -66,6 +67,98 @@ static const struct bonded_channel bonded_chan_160mhz_list[] = { {36, 64}, {100, 128} }; +#endif /* CONFIG_CHAN_NUM_API */ + +#ifdef CONFIG_CHAN_FREQ_API +/* bonded_chan_40mhz_list_freq - List of 40MHz bonnded channel frequencies */ +static const struct bonded_channel_freq bonded_chan_40mhz_list_freq[] = { + {5180, 5200}, + {5220, 5240}, + {5260, 5280}, + {5300, 5320}, + {5500, 5520}, + {5540, 5560}, + {5580, 5600}, + {5620, 5640}, + {5660, 5680}, + {5700, 5720}, + {5745, 5765}, + {5785, 5805}, + {5825, 5845}, +#ifdef CONFIG_BAND_6GHZ + {5945, 5965}, + {5985, 6005}, + {6025, 6045}, + {6065, 6085}, + {6105, 6125}, + {6145, 6165}, + {6185, 6205}, + {6225, 6245}, + {6265, 6285}, + {6305, 6325}, + {6345, 6365}, + {6385, 6405}, + {6425, 6445}, + {6465, 6485}, + {6505, 6525}, + {6545, 6565}, + {6585, 6605}, + {6625, 6645}, + {6665, 6685}, + {6705, 6725}, + {6745, 6765}, + {6785, 6805}, + {6825, 6845}, + {6865, 6885}, + {6905, 6925}, + {6945, 6965}, + {6985, 7005}, + {7025, 7045}, + {7065, 7085} +#endif /*CONFIG_BAND_6GHZ*/ +}; + +/* bonded_chan_80mhz_list_freq - List of 80MHz bonnded channel frequencies */ +static const struct bonded_channel_freq bonded_chan_80mhz_list_freq[] = { + {5180, 5240}, + {5260, 5320}, + {5500, 5560}, + {5580, 5640}, + {5660, 5720}, + {5745, 5805}, +#ifdef CONFIG_BAND_6GHZ + {5945, 6005}, + {6025, 6085}, + {6105, 6165}, + {6185, 6245}, + {6265, 6325}, + {6345, 6405}, + {6425, 6485}, + {6505, 6565}, + {6585, 6645}, + {6665, 6725}, + {6745, 6805}, + {6825, 6885}, + {6905, 6965}, + {6985, 7045} +#endif /*CONFIG_BAND_6GHZ*/ +}; + +/* bonded_chan_160mhz_list_freq - List of 160MHz bonnded channel frequencies */ +static const struct bonded_channel_freq bonded_chan_160mhz_list_freq[] = { + {5180, 5320}, + {5500, 5640}, +#ifdef CONFIG_BAND_6GHZ + {5945, 6085}, + {6105, 6245}, + {6265, 6405}, + {6425, 6565}, + {6585, 6725}, + {6745, 6885}, + {6905, 7045} +#endif /*CONFIG_BAND_6GHZ*/ +}; +#endif /*CONFIG_CHAN_FREQ_API*/ static const enum phy_ch_width get_next_lower_bw[] = { [CH_WIDTH_80P80MHZ] = CH_WIDTH_160MHZ, @@ -77,74 +170,7 @@ static const enum phy_ch_width get_next_lower_bw[] = { [CH_WIDTH_5MHZ] = CH_WIDTH_INVALID }; -#ifdef CONFIG_LEGACY_CHAN_ENUM -static const struct chan_map channel_map_old[NUM_CHANNELS] = { - [CHAN_ENUM_1] = {2412, 1, 2, 40}, - [CHAN_ENUM_2] = {2417, 2, 2, 40}, - [CHAN_ENUM_3] = {2422, 3, 2, 40}, - [CHAN_ENUM_4] = {2427, 4, 2, 40}, - [CHAN_ENUM_5] = {2432, 5, 2, 40}, - [CHAN_ENUM_6] = {2437, 6, 2, 40}, - [CHAN_ENUM_7] = {2442, 7, 2, 40}, - [CHAN_ENUM_8] = {2447, 8, 2, 40}, - [CHAN_ENUM_9] = {2452, 9, 2, 40}, - [CHAN_ENUM_10] = {2457, 10, 2, 40}, - [CHAN_ENUM_11] = {2462, 11, 2, 40}, - [CHAN_ENUM_12] = {2467, 12, 2, 40}, - [CHAN_ENUM_13] = {2472, 13, 2, 40}, - [CHAN_ENUM_14] = {2484, 14, 2, 40}, - - [CHAN_ENUM_36] = {5180, 36, 2, 160}, - [CHAN_ENUM_40] = {5200, 40, 2, 160}, - [CHAN_ENUM_44] = {5220, 44, 2, 160}, - [CHAN_ENUM_48] = {5240, 48, 2, 160}, - [CHAN_ENUM_52] = {5260, 52, 2, 160}, - [CHAN_ENUM_56] = {5280, 56, 2, 160}, - [CHAN_ENUM_60] = {5300, 60, 2, 160}, - [CHAN_ENUM_64] = {5320, 64, 2, 160}, - - [CHAN_ENUM_100] = {5500, 100, 2, 160}, - [CHAN_ENUM_104] = {5520, 104, 2, 160}, - [CHAN_ENUM_108] = {5540, 108, 2, 160}, - [CHAN_ENUM_112] = {5560, 112, 2, 160}, - [CHAN_ENUM_116] = {5580, 116, 2, 160}, - [CHAN_ENUM_120] = {5600, 120, 2, 160}, - [CHAN_ENUM_124] = {5620, 124, 2, 160}, - [CHAN_ENUM_128] = {5640, 128, 2, 160}, - [CHAN_ENUM_132] = {5660, 132, 2, 160}, - [CHAN_ENUM_136] = {5680, 136, 2, 160}, - [CHAN_ENUM_140] = {5700, 140, 2, 160}, - [CHAN_ENUM_144] = {5720, 144, 2, 160}, - - [CHAN_ENUM_149] = {5745, 149, 2, 160}, - [CHAN_ENUM_153] = {5765, 153, 2, 160}, - [CHAN_ENUM_157] = {5785, 157, 2, 160}, - [CHAN_ENUM_161] = {5805, 161, 2, 160}, - [CHAN_ENUM_165] = {5825, 165, 2, 160}, -#ifndef WLAN_FEATURE_DSRC - [CHAN_ENUM_169] = {5845, 169, 2, 40}, - [CHAN_ENUM_173] = {5865, 173, 2, 20}, -#else - [CHAN_ENUM_170] = {5852, 170, 2, 20}, - [CHAN_ENUM_171] = {5855, 171, 2, 20}, - [CHAN_ENUM_172] = {5860, 172, 2, 20}, - [CHAN_ENUM_173] = {5865, 173, 2, 20}, - [CHAN_ENUM_174] = {5870, 174, 2, 20}, - [CHAN_ENUM_175] = {5875, 175, 2, 20}, - [CHAN_ENUM_176] = {5880, 176, 2, 20}, - [CHAN_ENUM_177] = {5885, 177, 2, 20}, - [CHAN_ENUM_178] = {5890, 178, 2, 20}, - [CHAN_ENUM_179] = {5895, 179, 2, 20}, - [CHAN_ENUM_180] = {5900, 180, 2, 20}, - [CHAN_ENUM_181] = {5905, 181, 2, 20}, - [CHAN_ENUM_182] = {5910, 182, 2, 20}, - [CHAN_ENUM_183] = {5915, 183, 2, 20}, - [CHAN_ENUM_184] = {5920, 184, 2, 20}, -#endif -}; - -#else -static const struct chan_map channel_map_us[NUM_CHANNELS] = { +const struct chan_map channel_map_us[NUM_CHANNELS] = { [CHAN_ENUM_2412] = {2412, 1, 20, 40}, [CHAN_ENUM_2417] = {2417, 2, 20, 40}, [CHAN_ENUM_2422] = {2422, 3, 20, 40}, @@ -229,11 +255,21 @@ static const struct chan_map channel_map_us[NUM_CHANNELS] = { [CHAN_ENUM_5805] = {5805, 161, 2, 160}, [CHAN_ENUM_5825] = {5825, 165, 2, 160}, [CHAN_ENUM_5845] = {5845, 169, 2, 160}, +#ifdef WLAN_FEATURE_DSRC [CHAN_ENUM_5850] = {5850, 170, 2, 160}, [CHAN_ENUM_5855] = {5855, 171, 2, 160}, [CHAN_ENUM_5860] = {5860, 172, 2, 160}, +#else + [CHAN_ENUM_5850] = {5850, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5855] = {5855, INVALID_CHANNEL_NUM, 2, 160}, + [CHAN_ENUM_5860] = {5860, INVALID_CHANNEL_NUM, 2, 160}, +#endif [CHAN_ENUM_5865] = {5865, 173, 2, 160}, +#ifdef WLAN_FEATURE_DSRC [CHAN_ENUM_5870] = {5870, 174, 2, 160}, +#else + [CHAN_ENUM_5870] = {5870, INVALID_CHANNEL_NUM, 2, 160}, +#endif [CHAN_ENUM_5875] = {5875, 175, 2, 160}, [CHAN_ENUM_5880] = {5880, 176, 2, 160}, [CHAN_ENUM_5885] = {5885, 177, 2, 160}, @@ -244,9 +280,70 @@ static const struct chan_map channel_map_us[NUM_CHANNELS] = { [CHAN_ENUM_5910] = {5910, 182, 2, 160}, [CHAN_ENUM_5915] = {5915, 183, 2, 160}, [CHAN_ENUM_5920] = {5920, 184, 2, 160}, +#ifdef CONFIG_BAND_6GHZ + [CHAN_ENUM_5945] = {5945, 1, 2, 160}, + [CHAN_ENUM_5965] = {5965, 5, 2, 160}, + [CHAN_ENUM_5985] = {5985, 9, 2, 160}, + [CHAN_ENUM_6005] = {6005, 13, 2, 160}, + [CHAN_ENUM_6025] = {6025, 17, 2, 160}, + [CHAN_ENUM_6045] = {6045, 21, 2, 160}, + [CHAN_ENUM_6065] = {6065, 25, 2, 160}, + [CHAN_ENUM_6085] = {6085, 29, 2, 160}, + [CHAN_ENUM_6105] = {6105, 33, 2, 160}, + [CHAN_ENUM_6125] = {6125, 37, 2, 160}, + [CHAN_ENUM_6145] = {6145, 41, 2, 160}, + [CHAN_ENUM_6165] = {6165, 45, 2, 160}, + [CHAN_ENUM_6185] = {6185, 49, 2, 160}, + [CHAN_ENUM_6205] = {6205, 53, 2, 160}, + [CHAN_ENUM_6225] = {6225, 57, 2, 160}, + [CHAN_ENUM_6245] = {6245, 61, 2, 160}, + [CHAN_ENUM_6265] = {6265, 65, 2, 160}, + [CHAN_ENUM_6285] = {6285, 69, 2, 160}, + [CHAN_ENUM_6305] = {6305, 73, 2, 160}, + [CHAN_ENUM_6325] = {6325, 77, 2, 160}, + [CHAN_ENUM_6345] = {6345, 81, 2, 160}, + [CHAN_ENUM_6365] = {6365, 85, 2, 160}, + [CHAN_ENUM_6385] = {6385, 89, 2, 160}, + [CHAN_ENUM_6405] = {6405, 93, 2, 160}, + [CHAN_ENUM_6425] = {6425, 97, 2, 160}, + [CHAN_ENUM_6445] = {6445, 101, 2, 160}, + [CHAN_ENUM_6465] = {6465, 105, 2, 160}, + [CHAN_ENUM_6485] = {6485, 109, 2, 160}, + [CHAN_ENUM_6505] = {6505, 113, 2, 160}, + [CHAN_ENUM_6525] = {6525, 117, 2, 160}, + [CHAN_ENUM_6545] = {6545, 121, 2, 160}, + [CHAN_ENUM_6565] = {6565, 125, 2, 160}, + [CHAN_ENUM_6585] = {6585, 129, 2, 160}, + [CHAN_ENUM_6605] = {6605, 133, 2, 160}, + [CHAN_ENUM_6625] = {6625, 137, 2, 160}, + [CHAN_ENUM_6645] = {6645, 141, 2, 160}, + [CHAN_ENUM_6665] = {6665, 145, 2, 160}, + [CHAN_ENUM_6685] = {6685, 149, 2, 160}, + [CHAN_ENUM_6705] = {6705, 153, 2, 160}, + [CHAN_ENUM_6725] = {6725, 157, 2, 160}, + [CHAN_ENUM_6745] = {6745, 161, 2, 160}, + [CHAN_ENUM_6765] = {6765, 165, 2, 160}, + [CHAN_ENUM_6785] = {6785, 169, 2, 160}, + [CHAN_ENUM_6805] = {6805, 173, 2, 160}, + [CHAN_ENUM_6825] = {6825, 177, 2, 160}, + [CHAN_ENUM_6845] = {6845, 181, 2, 160}, + [CHAN_ENUM_6865] = {6865, 185, 2, 160}, + [CHAN_ENUM_6885] = {6885, 189, 2, 160}, + [CHAN_ENUM_6905] = {6905, 193, 2, 160}, + [CHAN_ENUM_6925] = {6925, 197, 2, 160}, + [CHAN_ENUM_6945] = {6945, 201, 2, 160}, + [CHAN_ENUM_6965] = {6965, 205, 2, 160}, + [CHAN_ENUM_6985] = {6985, 209, 2, 160}, + [CHAN_ENUM_7005] = {7005, 213, 2, 160}, + [CHAN_ENUM_7025] = {7025, 217, 2, 160}, + [CHAN_ENUM_7045] = {7045, 221, 2, 160}, + [CHAN_ENUM_7065] = {7065, 225, 2, 160}, + [CHAN_ENUM_7085] = {7085, 229, 2, 160}, + [CHAN_ENUM_7105] = {7105, 233, 2, 160} +#endif /* CONFIG_BAND_6GHZ */ }; -static const struct chan_map channel_map_eu[NUM_CHANNELS] = { +const struct chan_map channel_map_eu[NUM_CHANNELS] = { [CHAN_ENUM_2412] = {2412, 1, 20, 40}, [CHAN_ENUM_2417] = {2417, 2, 20, 40}, [CHAN_ENUM_2422] = {2422, 3, 20, 40}, @@ -346,9 +443,70 @@ static const struct chan_map channel_map_eu[NUM_CHANNELS] = { [CHAN_ENUM_5910] = {5910, 182, 2, 160}, [CHAN_ENUM_5915] = {5915, 183, 2, 160}, [CHAN_ENUM_5920] = {5920, 184, 2, 160}, +#ifdef CONFIG_BAND_6GHZ + [CHAN_ENUM_5945] = {5945, 1, 2, 160}, + [CHAN_ENUM_5965] = {5965, 5, 2, 160}, + [CHAN_ENUM_5985] = {5985, 9, 2, 160}, + [CHAN_ENUM_6005] = {6005, 13, 2, 160}, + [CHAN_ENUM_6025] = {6025, 17, 2, 160}, + [CHAN_ENUM_6045] = {6045, 21, 2, 160}, + [CHAN_ENUM_6065] = {6065, 25, 2, 160}, + [CHAN_ENUM_6085] = {6085, 29, 2, 160}, + [CHAN_ENUM_6105] = {6105, 33, 2, 160}, + [CHAN_ENUM_6125] = {6125, 37, 2, 160}, + [CHAN_ENUM_6145] = {6145, 41, 2, 160}, + [CHAN_ENUM_6165] = {6165, 45, 2, 160}, + [CHAN_ENUM_6185] = {6185, 49, 2, 160}, + [CHAN_ENUM_6205] = {6205, 53, 2, 160}, + [CHAN_ENUM_6225] = {6225, 57, 2, 160}, + [CHAN_ENUM_6245] = {6245, 61, 2, 160}, + [CHAN_ENUM_6265] = {6265, 65, 2, 160}, + [CHAN_ENUM_6285] = {6285, 69, 2, 160}, + [CHAN_ENUM_6305] = {6305, 73, 2, 160}, + [CHAN_ENUM_6325] = {6325, 77, 2, 160}, + [CHAN_ENUM_6345] = {6345, 81, 2, 160}, + [CHAN_ENUM_6365] = {6365, 85, 2, 160}, + [CHAN_ENUM_6385] = {6385, 89, 2, 160}, + [CHAN_ENUM_6405] = {6405, 93, 2, 160}, + [CHAN_ENUM_6425] = {6425, 97, 2, 160}, + [CHAN_ENUM_6445] = {6445, 101, 2, 160}, + [CHAN_ENUM_6465] = {6465, 105, 2, 160}, + [CHAN_ENUM_6485] = {6485, 109, 2, 160}, + [CHAN_ENUM_6505] = {6505, 113, 2, 160}, + [CHAN_ENUM_6525] = {6525, 117, 2, 160}, + [CHAN_ENUM_6545] = {6545, 121, 2, 160}, + [CHAN_ENUM_6565] = {6565, 125, 2, 160}, + [CHAN_ENUM_6585] = {6585, 129, 2, 160}, + [CHAN_ENUM_6605] = {6605, 133, 2, 160}, + [CHAN_ENUM_6625] = {6625, 137, 2, 160}, + [CHAN_ENUM_6645] = {6645, 141, 2, 160}, + [CHAN_ENUM_6665] = {6665, 145, 2, 160}, + [CHAN_ENUM_6685] = {6685, 149, 2, 160}, + [CHAN_ENUM_6705] = {6705, 153, 2, 160}, + [CHAN_ENUM_6725] = {6725, 157, 2, 160}, + [CHAN_ENUM_6745] = {6745, 161, 2, 160}, + [CHAN_ENUM_6765] = {6765, 165, 2, 160}, + [CHAN_ENUM_6785] = {6785, 169, 2, 160}, + [CHAN_ENUM_6805] = {6805, 173, 2, 160}, + [CHAN_ENUM_6825] = {6825, 177, 2, 160}, + [CHAN_ENUM_6845] = {6845, 181, 2, 160}, + [CHAN_ENUM_6865] = {6865, 185, 2, 160}, + [CHAN_ENUM_6885] = {6885, 189, 2, 160}, + [CHAN_ENUM_6905] = {6905, 193, 2, 160}, + [CHAN_ENUM_6925] = {6925, 197, 2, 160}, + [CHAN_ENUM_6945] = {6945, 201, 2, 160}, + [CHAN_ENUM_6965] = {6965, 205, 2, 160}, + [CHAN_ENUM_6985] = {6985, 209, 2, 160}, + [CHAN_ENUM_7005] = {7005, 213, 2, 160}, + [CHAN_ENUM_7025] = {7025, 217, 2, 160}, + [CHAN_ENUM_7045] = {7045, 221, 2, 160}, + [CHAN_ENUM_7065] = {7065, 225, 2, 160}, + [CHAN_ENUM_7085] = {7085, 229, 2, 160}, + [CHAN_ENUM_7105] = {7105, 233, 2, 160} +#endif /* CONFIG_BAND_6GHZ */ }; -static const struct chan_map channel_map_jp[NUM_CHANNELS] = { +const struct chan_map channel_map_jp[NUM_CHANNELS] = { [CHAN_ENUM_2412] = {2412, 1, 20, 40}, [CHAN_ENUM_2417] = {2417, 2, 20, 40}, [CHAN_ENUM_2422] = {2422, 3, 20, 40}, @@ -448,9 +606,70 @@ static const struct chan_map channel_map_jp[NUM_CHANNELS] = { [CHAN_ENUM_5910] = {5910, INVALID_CHANNEL_NUM, 2, 160}, [CHAN_ENUM_5915] = {5915, INVALID_CHANNEL_NUM, 2, 160}, [CHAN_ENUM_5920] = {5920, INVALID_CHANNEL_NUM, 2, 160}, +#ifdef CONFIG_BAND_6GHZ + [CHAN_ENUM_5945] = {5945, 1, 2, 160}, + [CHAN_ENUM_5965] = {5965, 5, 2, 160}, + [CHAN_ENUM_5985] = {5985, 9, 2, 160}, + [CHAN_ENUM_6005] = {6005, 13, 2, 160}, + [CHAN_ENUM_6025] = {6025, 17, 2, 160}, + [CHAN_ENUM_6045] = {6045, 21, 2, 160}, + [CHAN_ENUM_6065] = {6065, 25, 2, 160}, + [CHAN_ENUM_6085] = {6085, 29, 2, 160}, + [CHAN_ENUM_6105] = {6105, 33, 2, 160}, + [CHAN_ENUM_6125] = {6125, 37, 2, 160}, + [CHAN_ENUM_6145] = {6145, 41, 2, 160}, + [CHAN_ENUM_6165] = {6165, 45, 2, 160}, + [CHAN_ENUM_6185] = {6185, 49, 2, 160}, + [CHAN_ENUM_6205] = {6205, 53, 2, 160}, + [CHAN_ENUM_6225] = {6225, 57, 2, 160}, + [CHAN_ENUM_6245] = {6245, 61, 2, 160}, + [CHAN_ENUM_6265] = {6265, 65, 2, 160}, + [CHAN_ENUM_6285] = {6285, 69, 2, 160}, + [CHAN_ENUM_6305] = {6305, 73, 2, 160}, + [CHAN_ENUM_6325] = {6325, 77, 2, 160}, + [CHAN_ENUM_6345] = {6345, 81, 2, 160}, + [CHAN_ENUM_6365] = {6365, 85, 2, 160}, + [CHAN_ENUM_6385] = {6385, 89, 2, 160}, + [CHAN_ENUM_6405] = {6405, 93, 2, 160}, + [CHAN_ENUM_6425] = {6425, 97, 2, 160}, + [CHAN_ENUM_6445] = {6445, 101, 2, 160}, + [CHAN_ENUM_6465] = {6465, 105, 2, 160}, + [CHAN_ENUM_6485] = {6485, 109, 2, 160}, + [CHAN_ENUM_6505] = {6505, 113, 2, 160}, + [CHAN_ENUM_6525] = {6525, 117, 2, 160}, + [CHAN_ENUM_6545] = {6545, 121, 2, 160}, + [CHAN_ENUM_6565] = {6565, 125, 2, 160}, + [CHAN_ENUM_6585] = {6585, 129, 2, 160}, + [CHAN_ENUM_6605] = {6605, 133, 2, 160}, + [CHAN_ENUM_6625] = {6625, 137, 2, 160}, + [CHAN_ENUM_6645] = {6645, 141, 2, 160}, + [CHAN_ENUM_6665] = {6665, 145, 2, 160}, + [CHAN_ENUM_6685] = {6685, 149, 2, 160}, + [CHAN_ENUM_6705] = {6705, 153, 2, 160}, + [CHAN_ENUM_6725] = {6725, 157, 2, 160}, + [CHAN_ENUM_6745] = {6745, 161, 2, 160}, + [CHAN_ENUM_6765] = {6765, 165, 2, 160}, + [CHAN_ENUM_6785] = {6785, 169, 2, 160}, + [CHAN_ENUM_6805] = {6805, 173, 2, 160}, + [CHAN_ENUM_6825] = {6825, 177, 2, 160}, + [CHAN_ENUM_6845] = {6845, 181, 2, 160}, + [CHAN_ENUM_6865] = {6865, 185, 2, 160}, + [CHAN_ENUM_6885] = {6885, 189, 2, 160}, + [CHAN_ENUM_6905] = {6905, 193, 2, 160}, + [CHAN_ENUM_6925] = {6925, 197, 2, 160}, + [CHAN_ENUM_6945] = {6945, 201, 2, 160}, + [CHAN_ENUM_6965] = {6965, 205, 2, 160}, + [CHAN_ENUM_6985] = {6985, 209, 2, 160}, + [CHAN_ENUM_7005] = {7005, 213, 2, 160}, + [CHAN_ENUM_7025] = {7025, 217, 2, 160}, + [CHAN_ENUM_7045] = {7045, 221, 2, 160}, + [CHAN_ENUM_7065] = {7065, 225, 2, 160}, + [CHAN_ENUM_7085] = {7085, 229, 2, 160}, + [CHAN_ENUM_7105] = {7105, 233, 2, 160} +#endif /* CONFIG_BAND_6GHZ */ }; -static const struct chan_map channel_map_global[NUM_CHANNELS] = { +const struct chan_map channel_map_global[NUM_CHANNELS] = { [CHAN_ENUM_2412] = {2412, 1, 20, 40}, [CHAN_ENUM_2417] = {2417, 2, 20, 40}, [CHAN_ENUM_2422] = {2422, 3, 20, 40}, @@ -550,9 +769,70 @@ static const struct chan_map channel_map_global[NUM_CHANNELS] = { [CHAN_ENUM_5910] = {5910, INVALID_CHANNEL_NUM, 2, 160}, [CHAN_ENUM_5915] = {5915, INVALID_CHANNEL_NUM, 2, 160}, [CHAN_ENUM_5920] = {5920, INVALID_CHANNEL_NUM, 2, 160}, +#ifdef CONFIG_BAND_6GHZ + [CHAN_ENUM_5945] = {5945, 1, 2, 160}, + [CHAN_ENUM_5965] = {5965, 5, 2, 160}, + [CHAN_ENUM_5985] = {5985, 9, 2, 160}, + [CHAN_ENUM_6005] = {6005, 13, 2, 160}, + [CHAN_ENUM_6025] = {6025, 17, 2, 160}, + [CHAN_ENUM_6045] = {6045, 21, 2, 160}, + [CHAN_ENUM_6065] = {6065, 25, 2, 160}, + [CHAN_ENUM_6085] = {6085, 29, 2, 160}, + [CHAN_ENUM_6105] = {6105, 33, 2, 160}, + [CHAN_ENUM_6125] = {6125, 37, 2, 160}, + [CHAN_ENUM_6145] = {6145, 41, 2, 160}, + [CHAN_ENUM_6165] = {6165, 45, 2, 160}, + [CHAN_ENUM_6185] = {6185, 49, 2, 160}, + [CHAN_ENUM_6205] = {6205, 53, 2, 160}, + [CHAN_ENUM_6225] = {6225, 57, 2, 160}, + [CHAN_ENUM_6245] = {6245, 61, 2, 160}, + [CHAN_ENUM_6265] = {6265, 65, 2, 160}, + [CHAN_ENUM_6285] = {6285, 69, 2, 160}, + [CHAN_ENUM_6305] = {6305, 73, 2, 160}, + [CHAN_ENUM_6325] = {6325, 77, 2, 160}, + [CHAN_ENUM_6345] = {6345, 81, 2, 160}, + [CHAN_ENUM_6365] = {6365, 85, 2, 160}, + [CHAN_ENUM_6385] = {6385, 89, 2, 160}, + [CHAN_ENUM_6405] = {6405, 93, 2, 160}, + [CHAN_ENUM_6425] = {6425, 97, 2, 160}, + [CHAN_ENUM_6445] = {6445, 101, 2, 160}, + [CHAN_ENUM_6465] = {6465, 105, 2, 160}, + [CHAN_ENUM_6485] = {6485, 109, 2, 160}, + [CHAN_ENUM_6505] = {6505, 113, 2, 160}, + [CHAN_ENUM_6525] = {6525, 117, 2, 160}, + [CHAN_ENUM_6545] = {6545, 121, 2, 160}, + [CHAN_ENUM_6565] = {6565, 125, 2, 160}, + [CHAN_ENUM_6585] = {6585, 129, 2, 160}, + [CHAN_ENUM_6605] = {6605, 133, 2, 160}, + [CHAN_ENUM_6625] = {6625, 137, 2, 160}, + [CHAN_ENUM_6645] = {6645, 141, 2, 160}, + [CHAN_ENUM_6665] = {6665, 145, 2, 160}, + [CHAN_ENUM_6685] = {6685, 149, 2, 160}, + [CHAN_ENUM_6705] = {6705, 153, 2, 160}, + [CHAN_ENUM_6725] = {6725, 157, 2, 160}, + [CHAN_ENUM_6745] = {6745, 161, 2, 160}, + [CHAN_ENUM_6765] = {6765, 165, 2, 160}, + [CHAN_ENUM_6785] = {6785, 169, 2, 160}, + [CHAN_ENUM_6805] = {6805, 173, 2, 160}, + [CHAN_ENUM_6825] = {6825, 177, 2, 160}, + [CHAN_ENUM_6845] = {6845, 181, 2, 160}, + [CHAN_ENUM_6865] = {6865, 185, 2, 160}, + [CHAN_ENUM_6885] = {6885, 189, 2, 160}, + [CHAN_ENUM_6905] = {6905, 193, 2, 160}, + [CHAN_ENUM_6925] = {6925, 197, 2, 160}, + [CHAN_ENUM_6945] = {6945, 201, 2, 160}, + [CHAN_ENUM_6965] = {6965, 205, 2, 160}, + [CHAN_ENUM_6985] = {6985, 209, 2, 160}, + [CHAN_ENUM_7005] = {7005, 213, 2, 160}, + [CHAN_ENUM_7025] = {7025, 217, 2, 160}, + [CHAN_ENUM_7045] = {7045, 221, 2, 160}, + [CHAN_ENUM_7065] = {7065, 225, 2, 160}, + [CHAN_ENUM_7085] = {7085, 229, 2, 160}, + [CHAN_ENUM_7105] = {7105, 233, 2, 160} +#endif /* CONFIG_BAND_6GHZ */ }; -static const struct chan_map channel_map_china[NUM_CHANNELS] = { +const struct chan_map channel_map_china[NUM_CHANNELS] = { [CHAN_ENUM_2412] = {2412, 1, 20, 40}, [CHAN_ENUM_2417] = {2417, 2, 20, 40}, [CHAN_ENUM_2422] = {2422, 3, 20, 40}, @@ -652,15 +932,69 @@ static const struct chan_map channel_map_china[NUM_CHANNELS] = { [CHAN_ENUM_5910] = {5910, INVALID_CHANNEL_NUM, 2, 160}, [CHAN_ENUM_5915] = {5915, INVALID_CHANNEL_NUM, 2, 160}, [CHAN_ENUM_5920] = {5920, INVALID_CHANNEL_NUM, 2, 160}, +#ifdef CONFIG_BAND_6GHZ + [CHAN_ENUM_5945] = {5945, 1, 2, 160}, + [CHAN_ENUM_5965] = {5965, 5, 2, 160}, + [CHAN_ENUM_5985] = {5985, 9, 2, 160}, + [CHAN_ENUM_6005] = {6005, 13, 2, 160}, + [CHAN_ENUM_6025] = {6025, 17, 2, 160}, + [CHAN_ENUM_6045] = {6045, 21, 2, 160}, + [CHAN_ENUM_6065] = {6065, 25, 2, 160}, + [CHAN_ENUM_6085] = {6085, 29, 2, 160}, + [CHAN_ENUM_6105] = {6105, 33, 2, 160}, + [CHAN_ENUM_6125] = {6125, 37, 2, 160}, + [CHAN_ENUM_6145] = {6145, 41, 2, 160}, + [CHAN_ENUM_6165] = {6165, 45, 2, 160}, + [CHAN_ENUM_6185] = {6185, 49, 2, 160}, + [CHAN_ENUM_6205] = {6205, 53, 2, 160}, + [CHAN_ENUM_6225] = {6225, 57, 2, 160}, + [CHAN_ENUM_6245] = {6245, 61, 2, 160}, + [CHAN_ENUM_6265] = {6265, 65, 2, 160}, + [CHAN_ENUM_6285] = {6285, 69, 2, 160}, + [CHAN_ENUM_6305] = {6305, 73, 2, 160}, + [CHAN_ENUM_6325] = {6325, 77, 2, 160}, + [CHAN_ENUM_6345] = {6345, 81, 2, 160}, + [CHAN_ENUM_6365] = {6365, 85, 2, 160}, + [CHAN_ENUM_6385] = {6385, 89, 2, 160}, + [CHAN_ENUM_6405] = {6405, 93, 2, 160}, + [CHAN_ENUM_6425] = {6425, 97, 2, 160}, + [CHAN_ENUM_6445] = {6445, 101, 2, 160}, + [CHAN_ENUM_6465] = {6465, 105, 2, 160}, + [CHAN_ENUM_6485] = {6485, 109, 2, 160}, + [CHAN_ENUM_6505] = {6505, 113, 2, 160}, + [CHAN_ENUM_6525] = {6525, 117, 2, 160}, + [CHAN_ENUM_6545] = {6545, 121, 2, 160}, + [CHAN_ENUM_6565] = {6565, 125, 2, 160}, + [CHAN_ENUM_6585] = {6585, 129, 2, 160}, + [CHAN_ENUM_6605] = {6605, 133, 2, 160}, + [CHAN_ENUM_6625] = {6625, 137, 2, 160}, + [CHAN_ENUM_6645] = {6645, 141, 2, 160}, + [CHAN_ENUM_6665] = {6665, 145, 2, 160}, + [CHAN_ENUM_6685] = {6685, 149, 2, 160}, + [CHAN_ENUM_6705] = {6705, 153, 2, 160}, + [CHAN_ENUM_6725] = {6725, 157, 2, 160}, + [CHAN_ENUM_6745] = {6745, 161, 2, 160}, + [CHAN_ENUM_6765] = {6765, 165, 2, 160}, + [CHAN_ENUM_6785] = {6785, 169, 2, 160}, + [CHAN_ENUM_6805] = {6805, 173, 2, 160}, + [CHAN_ENUM_6825] = {6825, 177, 2, 160}, + [CHAN_ENUM_6845] = {6845, 181, 2, 160}, + [CHAN_ENUM_6865] = {6865, 185, 2, 160}, + [CHAN_ENUM_6885] = {6885, 189, 2, 160}, + [CHAN_ENUM_6905] = {6905, 193, 2, 160}, + [CHAN_ENUM_6925] = {6925, 197, 2, 160}, + [CHAN_ENUM_6945] = {6945, 201, 2, 160}, + [CHAN_ENUM_6965] = {6965, 205, 2, 160}, + [CHAN_ENUM_6985] = {6985, 209, 2, 160}, + [CHAN_ENUM_7005] = {7005, 213, 2, 160}, + [CHAN_ENUM_7025] = {7025, 217, 2, 160}, + [CHAN_ENUM_7045] = {7045, 221, 2, 160}, + [CHAN_ENUM_7065] = {7065, 225, 2, 160}, + [CHAN_ENUM_7085] = {7085, 229, 2, 160}, + [CHAN_ENUM_7105] = {7105, 233, 2, 160} +#endif /* CONFIG_BAND_6GHZ */ }; -#endif -#ifdef CONFIG_LEGACY_CHAN_ENUM -void reg_init_channel_map(enum dfs_reg dfs_region) -{ - channel_map = channel_map_old; -} -#else void reg_init_channel_map(enum dfs_reg dfs_region) { switch (dfs_region) { @@ -675,6 +1009,7 @@ void reg_init_channel_map(enum dfs_reg dfs_region) channel_map = channel_map_eu; break; case DFS_MKK_REGION: + case DFS_MKKN_REGION: channel_map = channel_map_jp; break; case DFS_CN_REGION: @@ -685,7 +1020,6 @@ void reg_init_channel_map(enum dfs_reg dfs_region) break; } } -#endif uint16_t reg_get_bw_value(enum phy_ch_width bw) { @@ -719,6 +1053,7 @@ struct wlan_lmac_if_reg_tx_ops *reg_get_psoc_tx_ops( return &((psoc->soc_cb.tx_ops.reg_ops)); } +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS reg_get_channel_list_with_power(struct wlan_objmgr_pdev *pdev, struct channel_power *ch_list, uint8_t *num_chan) @@ -747,6 +1082,8 @@ QDF_STATUS reg_get_channel_list_with_power(struct wlan_objmgr_pdev *pdev, reg_channels[i].chan_flags != REGULATORY_CHAN_DISABLED) { ch_list[count].chan_num = reg_channels[i].chan_num; + ch_list[count].center_freq = + reg_channels[i].center_freq; ch_list[count++].tx_power = reg_channels[i].tx_power; } @@ -757,7 +1094,7 @@ QDF_STATUS reg_get_channel_list_with_power(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } -enum channel_enum reg_get_chan_enum(uint32_t chan_num) +enum channel_enum reg_get_chan_enum(uint8_t chan_num) { uint32_t count; @@ -765,13 +1102,13 @@ enum channel_enum reg_get_chan_enum(uint32_t chan_num) if (channel_map[count].chan_num == chan_num) return count; - reg_err("invalid channel number %d", chan_num); + reg_err_rl("invalid channel number %d", chan_num); return INVALID_CHANNEL; } enum channel_state reg_get_channel_state(struct wlan_objmgr_pdev *pdev, - uint32_t ch) + uint8_t ch) { enum channel_enum ch_idx; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; @@ -791,32 +1128,6 @@ enum channel_state reg_get_channel_state(struct wlan_objmgr_pdev *pdev, return pdev_priv_obj->cur_chan_list[ch_idx].state; } - -static uint32_t reg_get_channel_flags(struct wlan_objmgr_pdev *pdev, - uint32_t chan) -{ - enum channel_enum chan_enum; - struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; - - chan_enum = reg_get_chan_enum(chan); - - if (chan_enum == INVALID_CHANNEL) { - reg_err("chan is not valid"); - return REGULATORY_CHAN_INVALID; - } - - pdev_priv_obj = reg_get_pdev_obj(pdev); - - if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { - reg_err("pdev reg obj is NULL"); - return REGULATORY_CHAN_INVALID; - } - - return pdev_priv_obj->cur_chan_list[chan_enum].chan_flags; -} - - - /** * reg_get_5g_bonded_chan_array() - get ptr to bonded channel * @pdev: Pointer to pdev structure @@ -829,7 +1140,7 @@ static uint32_t reg_get_channel_flags(struct wlan_objmgr_pdev *pdev, */ static enum channel_state reg_get_5g_bonded_chan_array( struct wlan_objmgr_pdev *pdev, - uint32_t oper_chan, + uint8_t oper_chan, const struct bonded_channel bonded_chan_ar[], uint16_t array_size, const struct bonded_channel **bonded_chan_ptr_ptr) @@ -863,17 +1174,8 @@ static enum channel_state reg_get_5g_bonded_chan_array( return chan_state; } -/** - * reg_get_5g_bonded_channel() - get the 5G bonded channel state - * @pdev: Pointer to pdev structure - * @chan_num: channel number - * @ch_width: channel width - * @bonded_chan_ptr_ptr: bonded channel ptr ptr - * - * Return: channel state - */ -static enum channel_state reg_get_5g_bonded_channel( - struct wlan_objmgr_pdev *pdev, uint32_t chan_num, +enum channel_state reg_get_5g_bonded_channel( + struct wlan_objmgr_pdev *pdev, uint8_t chan_num, enum phy_ch_width ch_width, const struct bonded_channel **bonded_chan_ptr_ptr) { @@ -1024,6 +1326,7 @@ enum channel_state reg_get_2g_bonded_channel_state( return CHANNEL_STATE_ENABLE; } +#endif /* CONFIG_CHAN_NUM_API */ /** * reg_combine_channel_states() - Get minimum of channel state1 and state2 @@ -1043,6 +1346,7 @@ static enum channel_state reg_combine_channel_states( return min(chan_state1, chan_state2); } +#ifdef CONFIG_CHAN_NUM_API /** * reg_set_5g_channel_params () - Sets channel parameteres for given bandwidth * @ch: channel number. @@ -1203,22 +1507,7 @@ void reg_set_channel_params(struct wlan_objmgr_pdev *pdev, else if (REG_IS_24GHZ_CH(ch)) reg_set_2g_channel_params(pdev, ch, ch_params, sec_ch_2g); } - -QDF_STATUS reg_get_curr_band(struct wlan_objmgr_pdev *pdev, - enum band_info *band) -{ - struct wlan_regulatory_pdev_priv_obj *pdev_reg; - - pdev_reg = reg_get_pdev_obj(pdev); - if (!IS_VALID_PDEV_REG_OBJ(pdev_reg)) { - reg_err("pdev reg component is NULL"); - return QDF_STATUS_E_INVAL; - } - - *band = pdev_reg->band_capability; - - return QDF_STATUS_SUCCESS; -} +#endif /* CONFIG_CHAN_NUM_API */ QDF_STATUS reg_read_default_country(struct wlan_objmgr_psoc *psoc, uint8_t *country_code) @@ -1272,8 +1561,9 @@ void reg_set_dfs_region(struct wlan_objmgr_pdev *pdev, reg_init_channel_map(dfs_reg); } +#ifdef CONFIG_CHAN_NUM_API uint32_t reg_get_channel_reg_power(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num) + uint8_t chan_num) { enum channel_enum chan_enum; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; @@ -1298,8 +1588,8 @@ uint32_t reg_get_channel_reg_power(struct wlan_objmgr_pdev *pdev, return reg_channels[chan_enum].tx_power; } -uint32_t reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num) +qdf_freq_t reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num) { enum channel_enum chan_enum; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; @@ -1323,27 +1613,33 @@ uint32_t reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, } bool reg_is_dfs_ch(struct wlan_objmgr_pdev *pdev, - uint32_t chan) + uint8_t chan) { - uint32_t chan_flags; + enum channel_state ch_state; - chan_flags = reg_get_channel_flags(pdev, chan); + ch_state = reg_get_channel_state(pdev, chan); - return chan_flags & REGULATORY_CHAN_RADAR; + return ch_state == CHANNEL_STATE_DFS; } +#endif /* CONFIG_CHAN_NUM_API */ -uint32_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, - uint32_t freq) +uint8_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) { uint32_t count; struct regulatory_channel *chan_list; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + if (freq == 0) { + reg_err_rl("Invalid freq %d", freq); + return 0; + } + pdev_priv_obj = reg_get_pdev_obj(pdev); if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { reg_err("reg pdev priv obj is NULL"); - return QDF_STATUS_E_FAILURE; + return 0; } chan_list = pdev_priv_obj->mas_chan_list; @@ -1371,7 +1667,7 @@ uint32_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, (freq - chan_list[count - 1].center_freq) / 5); end: - reg_err("invalid frequency %d", freq); + reg_err_rl("invalid frequency %d", freq); return 0; } @@ -1394,7 +1690,7 @@ static uint16_t reg_compute_chan_to_freq(struct wlan_objmgr_pdev *pdev, chan_list = pdev_priv_obj->mas_chan_list; for (count = min_chan_range; count <= max_chan_range; count++) { - if (reg_chan_is_49ghz(pdev, chan_list[count].chan_num)) { + if (REG_IS_49GHZ_FREQ(chan_list[count].center_freq)) { if (chan_list[count].chan_num == chan_num) break; continue; @@ -1417,7 +1713,7 @@ static uint16_t reg_compute_chan_to_freq(struct wlan_objmgr_pdev *pdev, goto end; if ((chan_list[count - 1].chan_num == INVALID_CHANNEL_NUM) || - reg_chan_is_49ghz(pdev, chan_list[count - 1].chan_num) || + REG_IS_49GHZ_FREQ(chan_list[count - 1].center_freq) || (chan_list[count].chan_num == INVALID_CHANNEL_NUM)) { reg_err("Channel %d invalid in current reg domain", chan_num); @@ -1439,23 +1735,34 @@ uint16_t reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, uint16_t min_chan_range = MIN_24GHZ_CHANNEL; uint16_t max_chan_range = MAX_5GHZ_CHANNEL; + if (chan_num == 0) { + reg_err_rl("Invalid channel %d", chan_num); + return 0; + } + return reg_compute_chan_to_freq(pdev, chan_num, min_chan_range, max_chan_range); } -uint32_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num) +#ifdef CONFIG_CHAN_NUM_API +qdf_freq_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num) { uint32_t count; struct regulatory_channel *chan_list; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + if (chan_num == 0) { + reg_err_rl("Invalid channel %d", chan_num); + return 0; + } + pdev_priv_obj = reg_get_pdev_obj(pdev); if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { reg_err("reg pdev priv obj is NULL"); - return QDF_STATUS_E_FAILURE; + return 0; } chan_list = pdev_priv_obj->cur_chan_list; @@ -1475,23 +1782,16 @@ uint32_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, return 0; } -#ifndef CONFIG_LEGACY_CHAN_ENUM bool reg_chan_is_49ghz(struct wlan_objmgr_pdev *pdev, uint8_t chan_num) { - uint32_t freq = 0; + qdf_freq_t freq = 0; freq = reg_chan_to_freq(pdev, chan_num); return REG_IS_49GHZ_FREQ(freq) ? true : false; } -#else -bool reg_chan_is_49ghz(struct wlan_objmgr_pdev *pdev, uint8_t chan_num) -{ - return false; -} -#endif -enum band_info reg_chan_to_band(uint32_t chan_num) +enum band_info reg_chan_to_band(uint8_t chan_num) { if (chan_num <= 14) return BAND_2G; @@ -1533,6 +1833,7 @@ void reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, reg_compute_pdev_current_chan_list(pdev_priv_obj); } +#endif /* CONFIG_CHAN_NUM_API */ QDF_STATUS reg_program_default_cc(struct wlan_objmgr_pdev *pdev, uint16_t regdmn) @@ -1765,7 +2066,7 @@ QDF_STATUS reg_get_curr_regdomain(struct wlan_objmgr_pdev *pdev, } if (index == num_reg_dmn) { - reg_err("invalid regdomain"); + reg_debug_rl("invalid regdomain"); return QDF_STATUS_E_FAILURE; } @@ -1883,8 +2184,8 @@ QDF_STATUS reg_set_hal_reg_cap( } bool reg_chan_in_range(struct regulatory_channel *chan_list, - uint32_t low_freq_2g, uint32_t high_freq_2g, - uint32_t low_freq_5g, uint32_t high_freq_5g, + qdf_freq_t low_freq_2g, qdf_freq_t high_freq_2g, + qdf_freq_t low_freq_5g, qdf_freq_t high_freq_5g, enum channel_enum ch_enum) { uint32_t low_limit_2g = NUM_CHANNELS; @@ -1894,7 +2195,7 @@ bool reg_chan_in_range(struct regulatory_channel *chan_list, bool chan_in_range; enum channel_enum chan_enum; uint16_t min_bw; - uint32_t center_freq; + qdf_freq_t center_freq; for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) { min_bw = chan_list[chan_enum].min_bw; @@ -1958,6 +2259,7 @@ bool reg_chan_in_range(struct regulatory_channel *chan_list, return false; } +#ifdef CONFIG_CHAN_NUM_API void reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, uint8_t *chan_list, uint8_t num_chan, bool nol_history_chan) @@ -2005,6 +2307,7 @@ bool reg_is_5ghz_ch(uint32_t chan) { return REG_IS_5GHZ_CH(chan); } +#endif /* CONFIG_CHAN_NUM_API */ bool reg_is_24ghz_ch_freq(uint32_t freq) { @@ -2016,53 +2319,285 @@ bool reg_is_5ghz_ch_freq(uint32_t freq) return REG_IS_5GHZ_FREQ(freq); } -#ifndef CONFIG_LEGACY_CHAN_ENUM -bool reg_is_49ghz_freq(uint32_t freq) +/** + * BAND_2G_PRESENT() - Check if REG_BAND_2G is set in the band_mask + * @band_mask: Bitmask for bands + * + * Return: True if REG_BAND_2G is set in the band_mask, else false + */ +static inline bool BAND_2G_PRESENT(uint8_t band_mask) +{ + return !!(band_mask & (BIT(REG_BAND_2G))); +} + +/** + * BAND_5G_PRESENT() - Check if REG_BAND_5G is set in the band_mask + * @band_mask: Bitmask for bands + * + * Return: True if REG_BAND_5G is set in the band_mask, else false + */ +static inline bool BAND_5G_PRESENT(uint8_t band_mask) +{ + return !!(band_mask & (BIT(REG_BAND_5G))); +} + +bool reg_is_freq_indoor(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq) +{ + struct regulatory_channel *cur_chan_list; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + enum channel_enum chan_enum; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return false; + } + + chan_enum = reg_get_chan_enum_for_freq(freq); + + if (chan_enum == INVALID_CHANNEL) { + reg_err_rl("Invalid chan enum %d", chan_enum); + return false; + } + + cur_chan_list = pdev_priv_obj->cur_chan_list; + + return (cur_chan_list[chan_enum].chan_flags & + REGULATORY_CHAN_INDOOR_ONLY); +} + +#ifdef CONFIG_BAND_6GHZ +bool reg_is_6ghz_chan_freq(uint16_t freq) +{ + return REG_IS_6GHZ_FREQ(freq); +} + +uint16_t reg_min_6ghz_chan_freq(void) +{ + return REG_MIN_6GHZ_CHAN_FREQ; +} + +uint16_t reg_max_6ghz_chan_freq(void) +{ + return REG_MAX_6GHZ_CHAN_FREQ; +} + +bool reg_is_6ghz_psc_chan_freq(uint16_t freq) +{ + if (!REG_IS_6GHZ_FREQ(freq)) { + reg_debug(" Channel frequency is not a 6GHz frequency"); + return false; + } + + if (!(((freq - SIXG_STARTING_FREQ) + (FREQ_LEFT_SHIFT)) % + (FREQ_TO_CHAN_SCALE * NUM_80MHZ_BAND_IN_6G))) { + return true; + } + + reg_debug_rl("Channel freq %d MHz is not a 6GHz PSC frequency", freq); + + return false; +} + +/** + * BAND_6G_PRESENT() - Check if REG_BAND_6G is set in the band_mask + * @band_mask: Bitmask for bands + * + * Return: True if REG_BAND_6G is set in the band_mask, else false + */ +static inline bool BAND_6G_PRESENT(uint8_t band_mask) +{ + return !!(band_mask & (BIT(REG_BAND_6G))); +} +#else +static inline bool BAND_6G_PRESENT(uint8_t band_mask) +{ + return false; +} +#endif /* CONFIG_BAND_6GHZ */ + +uint16_t +reg_get_band_channel_list(struct wlan_objmgr_pdev *pdev, + uint8_t band_mask, + struct regulatory_channel *channel_list) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct regulatory_channel *cur_chan_list; + uint16_t i, num_channels = 0; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return 0; + } + + cur_chan_list = pdev_priv_obj->cur_chan_list; + + if (BAND_2G_PRESENT(band_mask)) { + for (i = MIN_24GHZ_CHANNEL; i <= MAX_24GHZ_CHANNEL; i++) { + if ((cur_chan_list[i].state != CHANNEL_STATE_DISABLE) && + !(cur_chan_list[i].chan_flags & + REGULATORY_CHAN_DISABLED)) { + channel_list[num_channels] = cur_chan_list[i]; + num_channels++; + } + } + } + if (BAND_5G_PRESENT(band_mask)) { + for (i = MIN_49GHZ_CHANNEL; i <= MAX_5GHZ_CHANNEL; i++) { + if ((cur_chan_list[i].state != CHANNEL_STATE_DISABLE) && + !(cur_chan_list[i].chan_flags & + REGULATORY_CHAN_DISABLED)) { + channel_list[num_channels] = cur_chan_list[i]; + num_channels++; + } + } + } + if (BAND_6G_PRESENT(band_mask)) { + for (i = MIN_6GHZ_CHANNEL; i <= MAX_6GHZ_CHANNEL; i++) { + if ((cur_chan_list[i].state != CHANNEL_STATE_DISABLE) && + !(cur_chan_list[i].chan_flags & + REGULATORY_CHAN_DISABLED)) { + channel_list[num_channels] = cur_chan_list[i]; + num_channels++; + } + } + } + + if (!num_channels) { + reg_err("Failed to retrieve the channel list"); + return 0; + } + + return num_channels; +} + +qdf_freq_t reg_chan_band_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num, + uint8_t band_mask) +{ + enum channel_enum min_chan, max_chan; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + uint16_t freq; + + if (chan_num == 0) { + reg_err_rl("Invalid channel %d", chan_num); + return 0; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return 0; + } + + if (BAND_6G_PRESENT(band_mask)) { + if (BAND_2G_PRESENT(band_mask) || + BAND_5G_PRESENT(band_mask)) { + reg_err_rl("Incorrect band_mask %x", band_mask); + return 0; + } + + min_chan = MIN_6GHZ_CHANNEL; + max_chan = MAX_6GHZ_CHANNEL; + return reg_compute_chan_to_freq(pdev, chan_num, + min_chan, + max_chan); + } else { + if (BAND_2G_PRESENT(band_mask)) { + min_chan = MIN_24GHZ_CHANNEL; + max_chan = MAX_24GHZ_CHANNEL; + freq = reg_compute_chan_to_freq(pdev, chan_num, + min_chan, + max_chan); + if (freq != 0) + return freq; + } + + if (BAND_5G_PRESENT(band_mask)) { + min_chan = MIN_49GHZ_CHANNEL; + max_chan = MAX_5GHZ_CHANNEL; + + return reg_compute_chan_to_freq(pdev, chan_num, + min_chan, + max_chan); + } + + reg_err_rl("Incorrect band_mask %x", band_mask); + return 0; + } +} + +bool reg_is_49ghz_freq(qdf_freq_t freq) { return REG_IS_49GHZ_FREQ(freq); } -#endif -uint32_t reg_ch_num(uint32_t ch_enum) +qdf_freq_t reg_ch_num(uint32_t ch_enum) { return REG_CH_NUM(ch_enum); } -uint32_t reg_ch_to_freq(uint32_t ch_enum) +qdf_freq_t reg_ch_to_freq(uint32_t ch_enum) { return REG_CH_TO_FREQ(ch_enum); } -bool reg_is_same_band_channels(uint32_t chan_num1, uint32_t chan_num2) +#ifdef CONFIG_CHAN_NUM_API +bool reg_is_same_band_channels(uint8_t chan_num1, uint8_t chan_num2) { return (chan_num1 && chan_num2 && (REG_IS_5GHZ_CH(chan_num1) == REG_IS_5GHZ_CH(chan_num2))); } -bool reg_is_channel_valid_5g_sbs(uint32_t curchan, uint32_t newchan) +bool reg_is_channel_valid_5g_sbs(uint8_t curchan, uint8_t newchan) { return REG_IS_CHANNEL_VALID_5G_SBS(curchan, newchan); } -uint32_t reg_min_24ghz_ch_num(void) +uint8_t reg_min_24ghz_ch_num(void) { return REG_MIN_24GHZ_CH_NUM; } -uint32_t reg_max_24ghz_ch_num(void) +uint8_t reg_max_24ghz_ch_num(void) { return REG_MAX_24GHZ_CH_NUM; } -uint32_t reg_min_5ghz_ch_num(void) +uint8_t reg_min_5ghz_ch_num(void) { return REG_MIN_5GHZ_CH_NUM; } -uint32_t reg_max_5ghz_ch_num(void) +uint8_t reg_max_5ghz_ch_num(void) { return REG_MAX_5GHZ_CH_NUM; } +#endif /* CONFIG_CHAN_NUM_API */ + +#ifdef CONFIG_CHAN_FREQ_API +qdf_freq_t reg_min_24ghz_chan_freq(void) +{ + return REG_MIN_24GHZ_CH_FREQ; +} + +qdf_freq_t reg_max_24ghz_chan_freq(void) +{ + return REG_MAX_24GHZ_CH_FREQ; +} + +qdf_freq_t reg_min_5ghz_chan_freq(void) +{ + return REG_MIN_5GHZ_CH_FREQ; +} + +qdf_freq_t reg_max_5ghz_chan_freq(void) +{ + return REG_MAX_5GHZ_CH_FREQ; +} +#endif /* CONFIG_CHAN_FREQ_API */ QDF_STATUS reg_enable_dfs_channels(struct wlan_objmgr_pdev *pdev, bool enable) @@ -2116,65 +2651,1022 @@ QDF_STATUS reg_enable_dfs_channels(struct wlan_objmgr_pdev *pdev, return status; } -QDF_STATUS reg_set_ignore_fw_reg_offload_ind(struct wlan_objmgr_psoc *psoc) -{ - struct wlan_regulatory_psoc_priv_obj *psoc_reg; - - psoc_reg = reg_get_psoc_obj(psoc); - if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) { - reg_err("psoc reg component is NULL"); - return QDF_STATUS_E_INVAL; - } - - psoc_reg->ignore_fw_reg_offload_ind = true; - return QDF_STATUS_SUCCESS; -} - -bool reg_get_ignore_fw_reg_offload_ind(struct wlan_objmgr_psoc *psoc) +bool reg_is_regdmn_en302502_applicable(struct wlan_objmgr_pdev *pdev) { - struct wlan_regulatory_psoc_priv_obj *psoc_reg; + struct cur_regdmn_info cur_reg_dmn; + QDF_STATUS status; - psoc_reg = reg_get_psoc_obj(psoc); - if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) + status = reg_get_curr_regdomain(pdev, &cur_reg_dmn); + if (status != QDF_STATUS_SUCCESS) { + reg_err("Failed to get reg domain"); return false; + } - return psoc_reg->ignore_fw_reg_offload_ind; + return reg_en302_502_regdmn(cur_reg_dmn.regdmn_pair_id); } -QDF_STATUS reg_set_6ghz_supported(struct wlan_objmgr_psoc *psoc, bool val) +QDF_STATUS reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev) { + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_reg_tx_ops *reg_tx_ops; + struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap_ptr; + uint32_t cnt; + uint32_t phy_id; + enum direction dir; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct target_pdev_info *tgt_pdev; + + tgt_pdev = wlan_pdev_get_tgt_if_handle(pdev); + phy_id = (uint32_t)target_pdev_get_phy_idx(tgt_pdev); + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg component is NULL"); + return QDF_STATUS_E_INVAL; + } - psoc_priv_obj = reg_get_psoc_obj(psoc); + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + reg_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + psoc_priv_obj = reg_get_psoc_obj(psoc); if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { reg_err("psoc reg component is NULL"); - return QDF_STATUS_E_FAILURE; + return QDF_STATUS_E_INVAL; } - psoc_priv_obj->six_ghz_supported = val; + reg_cap_ptr = psoc_priv_obj->reg_cap; - return QDF_STATUS_SUCCESS; -} + for (cnt = 0; cnt < PSOC_MAX_PHY_REG_CAP; cnt++) { + if (!reg_cap_ptr) { + qdf_mem_free(pdev_priv_obj); + reg_err("reg cap ptr is NULL"); + return QDF_STATUS_E_FAULT; + } -bool reg_is_6ghz_op_class(struct wlan_objmgr_pdev *pdev, uint8_t op_class) -{ - return ((op_class >= MIN_6GHZ_OPER_CLASS) && - (op_class <= MAX_6GHZ_OPER_CLASS)); + if (reg_cap_ptr->phy_id == phy_id) + break; + reg_cap_ptr++; + } + + if (cnt == PSOC_MAX_PHY_REG_CAP) { + qdf_mem_free(pdev_priv_obj); + reg_err("extended capabilities not found for pdev"); + return QDF_STATUS_E_FAULT; + } + + if (psoc_priv_obj->offload_enabled) { + dir = NORTHBOUND; + } else { + dir = SOUTHBOUND; + } + + pdev_priv_obj->range_2g_low = reg_cap_ptr->low_2ghz_chan; + pdev_priv_obj->range_2g_high = reg_cap_ptr->high_2ghz_chan; + pdev_priv_obj->range_5g_low = reg_cap_ptr->low_5ghz_chan; + pdev_priv_obj->range_5g_high = reg_cap_ptr->high_5ghz_chan; + pdev_priv_obj->wireless_modes = reg_cap_ptr->wireless_modes; + + reg_compute_pdev_current_chan_list(pdev_priv_obj); + + reg_tx_ops = reg_get_psoc_tx_ops(psoc); + + /* Fill the ic channel list with the updated current channel + * chan list. + */ + if (reg_tx_ops->fill_umac_legacy_chanlist) { + reg_tx_ops->fill_umac_legacy_chanlist(pdev, + pdev_priv_obj->cur_chan_list); + + } else { + if (dir == NORTHBOUND) + status = reg_send_scheduler_msg_nb(psoc, pdev); + else + status = reg_send_scheduler_msg_sb(psoc, pdev); + } + + return status; +} + +#ifdef DISABLE_UNII_SHARED_BANDS +/** + * reg_is_reg_unii_band_1_or_reg_unii_band_2a() - Check the input bitmap + * @unii_5g_bitmap: 5G UNII band bitmap + * + * This function checks if either REG_UNII_BAND_1 or REG_UNII_BAND_2A, + * are present in the 5G UNII band bitmap. + * + * Return: Return true if REG_UNII_BAND_1 or REG_UNII_BAND_2A, are present in + * the UNII 5g bitmap else return false. + */ +static bool +reg_is_reg_unii_band_1_or_reg_unii_band_2a(uint8_t unii_5g_bitmap) +{ + if (!unii_5g_bitmap) + return false; + + return ((unii_5g_bitmap & (BIT(REG_UNII_BAND_1) | + BIT(REG_UNII_BAND_2A))) == unii_5g_bitmap); +} + +QDF_STATUS reg_disable_chan_coex(struct wlan_objmgr_pdev *pdev, + uint8_t unii_5g_bitmap) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct wlan_lmac_if_reg_tx_ops *reg_tx_ops; + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + reg_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err_rl("reg pdev priv obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + if (unii_5g_bitmap && + !reg_is_reg_unii_band_1_or_reg_unii_band_2a(unii_5g_bitmap)) { + reg_err_rl("Invalid unii_5g_bitmap = %d", unii_5g_bitmap); + return QDF_STATUS_E_FAILURE; + } + + if (pdev_priv_obj->unii_5g_bitmap == unii_5g_bitmap) { + reg_debug_rl("UNII bitmask for 5G channels is already set %d", + unii_5g_bitmap); + return QDF_STATUS_SUCCESS; + } + + reg_debug_rl("Setting UNII bitmask for 5G: %d", unii_5g_bitmap); + pdev_priv_obj->unii_5g_bitmap = unii_5g_bitmap; + + reg_compute_pdev_current_chan_list(pdev_priv_obj); + + reg_tx_ops = reg_get_psoc_tx_ops(psoc); + + if (reg_tx_ops->fill_umac_legacy_chanlist) { + reg_tx_ops->fill_umac_legacy_chanlist(pdev, + pdev_priv_obj->cur_chan_list); + } + + return QDF_STATUS_SUCCESS; +} +#endif + +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS reg_get_channel_list_with_power_for_freq(struct wlan_objmgr_pdev + *pdev, + struct channel_power + *ch_list, + uint8_t *num_chan) +{ + int i, count; + struct regulatory_channel *reg_channels; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + if (!num_chan || !ch_list) { + reg_err("chan_list or num_ch is NULL"); + return QDF_STATUS_E_FAILURE; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + /* set the current channel list */ + reg_channels = pdev_priv_obj->cur_chan_list; + + for (i = 0, count = 0; i < NUM_CHANNELS; i++) { + if (reg_channels[i].state && + !(reg_channels[i].chan_flags & REGULATORY_CHAN_DISABLED)) { + ch_list[count].center_freq = + reg_channels[i].center_freq; + ch_list[count++].tx_power = + reg_channels[i].tx_power; + } + } + + *num_chan = count; + + return QDF_STATUS_SUCCESS; +} + +enum channel_enum reg_get_chan_enum_for_freq(qdf_freq_t freq) +{ + uint32_t count; + + for (count = 0; count < NUM_CHANNELS; count++) + if (channel_map[count].center_freq == freq) + return count; + + reg_err("invalid channel center frequency %d", freq); + + return INVALID_CHANNEL; +} + +bool +reg_is_freq_present_in_cur_chan_list(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + enum channel_enum chan_enum; + struct regulatory_channel *cur_chan_list; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err_rl("pdev reg obj is NULL"); + return false; + } + + cur_chan_list = pdev_priv_obj->cur_chan_list; + + for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) + if (cur_chan_list[chan_enum].center_freq == freq) + if ((cur_chan_list[chan_enum].state != + CHANNEL_STATE_DISABLE) && + !(cur_chan_list[chan_enum].chan_flags & + REGULATORY_CHAN_DISABLED)) + return true; + + reg_debug_rl("Channel center frequency %d not found", freq); + + return false; +} + +enum channel_state reg_get_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + enum channel_enum ch_idx; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + ch_idx = reg_get_chan_enum_for_freq(freq); + + if (ch_idx == INVALID_CHANNEL) + return CHANNEL_STATE_INVALID; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg obj is NULL"); + return CHANNEL_STATE_INVALID; + } + + return pdev_priv_obj->cur_chan_list[ch_idx].state; +} + +static uint32_t reg_get_channel_flags_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + enum channel_enum chan_enum; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + chan_enum = reg_get_chan_enum_for_freq(freq); + + if (chan_enum == INVALID_CHANNEL) { + reg_err("chan freq is not valid"); + return REGULATORY_CHAN_INVALID; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg obj is NULL"); + return REGULATORY_CHAN_INVALID; + } + + return pdev_priv_obj->cur_chan_list[chan_enum].chan_flags; +} + +/** + * reg_get_5g_bonded_chan_array_for_freq()- Return the channel state for a + * 5G or 6G channel frequency based on the bonded channel. + * @pdev: Pointer to pdev. + * @freq: Channel center frequency. + * @bonded_chan_ar: Array of bonded channel frequencies. + * @array_size: Array size. + * @bonded_chan_ptr_ptr: Pointer to bonded_channel_freq. + * + * Return: Channel State + */ +static enum channel_state +reg_get_5g_bonded_chan_array_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + const struct bonded_channel_freq + bonded_chan_ar[], + uint16_t array_size, + const struct bonded_channel_freq + **bonded_chan_ptr_ptr) +{ + int i; + uint16_t chan_cfreq; + const struct bonded_channel_freq *bonded_chan_ptr = NULL; + enum channel_state chan_state = CHANNEL_STATE_INVALID; + enum channel_state temp_chan_state; + + for (i = 0; i < array_size; i++) { + if ((freq >= bonded_chan_ar[i].start_freq) && + (freq <= bonded_chan_ar[i].end_freq)) { + bonded_chan_ptr = &bonded_chan_ar[i]; + break; + } + } + + if (!bonded_chan_ptr) + return chan_state; + + *bonded_chan_ptr_ptr = bonded_chan_ptr; + chan_cfreq = bonded_chan_ptr->start_freq; + while (chan_cfreq <= bonded_chan_ptr->end_freq) { + temp_chan_state = reg_get_channel_state_for_freq(pdev, + chan_cfreq); + if (temp_chan_state < chan_state) + chan_state = temp_chan_state; + chan_cfreq = chan_cfreq + 20; + } + + return chan_state; +} + +/** + * reg_get_5g_bonded_channel_for_freq()- Return the channel state for a + * 5G or 6G channel frequency based on the channel width and bonded channel + * @pdev: Pointer to pdev. + * @freq: Channel center frequency. + * @ch_width: Channel Width. + * @bonded_chan_ptr_ptr: Pointer to bonded_channel_freq. + * + * Return: Channel State + */ +enum channel_state +reg_get_5g_bonded_channel_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + enum phy_ch_width ch_width, + const struct bonded_channel_freq + **bonded_chan_ptr_ptr) + +{ + if (ch_width == CH_WIDTH_80P80MHZ) + return reg_get_5g_bonded_chan_array_for_freq(pdev, freq, + bonded_chan_80mhz_list_freq, + QDF_ARRAY_SIZE(bonded_chan_80mhz_list_freq), + bonded_chan_ptr_ptr); + else if (ch_width == CH_WIDTH_160MHZ) + return reg_get_5g_bonded_chan_array_for_freq(pdev, freq, + bonded_chan_160mhz_list_freq, + QDF_ARRAY_SIZE(bonded_chan_160mhz_list_freq), + bonded_chan_ptr_ptr); + else if (ch_width == CH_WIDTH_80MHZ) + return reg_get_5g_bonded_chan_array_for_freq(pdev, freq, + bonded_chan_80mhz_list_freq, + QDF_ARRAY_SIZE(bonded_chan_80mhz_list_freq), + bonded_chan_ptr_ptr); + else if (ch_width == CH_WIDTH_40MHZ) + return reg_get_5g_bonded_chan_array_for_freq(pdev, freq, + bonded_chan_40mhz_list_freq, + QDF_ARRAY_SIZE(bonded_chan_40mhz_list_freq), + bonded_chan_ptr_ptr); + else + return reg_get_channel_state_for_freq(pdev, freq); +} + +enum channel_state +reg_get_5g_bonded_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + enum phy_ch_width bw) +{ + enum channel_enum ch_indx; + enum channel_state chan_state; + struct regulatory_channel *reg_channels; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + bool bw_enabled = false; + const struct bonded_channel_freq *bonded_chan_ptr = NULL; + + if (bw > CH_WIDTH_80P80MHZ) { + reg_err("bw passed is not good"); + return CHANNEL_STATE_INVALID; + } + + chan_state = reg_get_5g_bonded_channel_for_freq(pdev, freq, bw, + &bonded_chan_ptr); + + if ((chan_state == CHANNEL_STATE_INVALID) || + (chan_state == CHANNEL_STATE_DISABLE)) + return chan_state; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg obj is NULL"); + return CHANNEL_STATE_INVALID; + } + reg_channels = pdev_priv_obj->cur_chan_list; + + ch_indx = reg_get_chan_enum_for_freq(freq); + if (ch_indx == INVALID_CHANNEL) + return CHANNEL_STATE_INVALID; + if (bw == CH_WIDTH_5MHZ) + bw_enabled = true; + else if (bw == CH_WIDTH_10MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 10) && + (reg_channels[ch_indx].max_bw >= 10); + else if (bw == CH_WIDTH_20MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 20) && + (reg_channels[ch_indx].max_bw >= 20); + else if (bw == CH_WIDTH_40MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 40) && + (reg_channels[ch_indx].max_bw >= 40); + else if (bw == CH_WIDTH_80MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 80) && + (reg_channels[ch_indx].max_bw >= 80); + else if (bw == CH_WIDTH_160MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 160) && + (reg_channels[ch_indx].max_bw >= 160); + else if (bw == CH_WIDTH_80P80MHZ) + bw_enabled = (reg_channels[ch_indx].min_bw <= 80) && + (reg_channels[ch_indx].max_bw >= 80); + + if (bw_enabled) + return chan_state; + else + return CHANNEL_STATE_DISABLE; +} + +enum channel_state +reg_get_2g_bonded_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t oper_ch_freq, + qdf_freq_t sec_ch_freq, + enum phy_ch_width bw) +{ + enum channel_enum chan_idx; + enum channel_state chan_state; + struct regulatory_channel *reg_channels; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + bool bw_enabled = false; + enum channel_state chan_state2 = CHANNEL_STATE_INVALID; + + if (bw > CH_WIDTH_40MHZ) + return CHANNEL_STATE_INVALID; + + if (bw == CH_WIDTH_40MHZ) { + if ((sec_ch_freq + 20 != oper_ch_freq) && + (oper_ch_freq + 20 != sec_ch_freq)) + return CHANNEL_STATE_INVALID; + chan_state2 = reg_get_channel_state_for_freq(pdev, sec_ch_freq); + if (chan_state2 == CHANNEL_STATE_INVALID) + return chan_state2; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return CHANNEL_STATE_INVALID; + } + + reg_channels = pdev_priv_obj->cur_chan_list; + + chan_state = reg_get_channel_state_for_freq(pdev, oper_ch_freq); + if (chan_state2 < chan_state) + chan_state = chan_state2; + + if ((chan_state == CHANNEL_STATE_INVALID) || + (chan_state == CHANNEL_STATE_DISABLE)) + return chan_state; + + chan_idx = reg_get_chan_enum_for_freq(oper_ch_freq); + if (chan_idx == INVALID_CHANNEL) + return CHANNEL_STATE_INVALID; + if (bw == CH_WIDTH_5MHZ) + bw_enabled = true; + else if (bw == CH_WIDTH_10MHZ) + bw_enabled = (reg_channels[chan_idx].min_bw <= 10) && + (reg_channels[chan_idx].max_bw >= 10); + else if (bw == CH_WIDTH_20MHZ) + bw_enabled = (reg_channels[chan_idx].min_bw <= 20) && + (reg_channels[chan_idx].max_bw >= 20); + else if (bw == CH_WIDTH_40MHZ) + bw_enabled = (reg_channels[chan_idx].min_bw <= 40) && + (reg_channels[chan_idx].max_bw >= 40); + + if (bw_enabled) + return chan_state; + else + return CHANNEL_STATE_DISABLE; + + return CHANNEL_STATE_ENABLE; +} + +/** + * reg_set_5g_channel_params_for_freq()- Set channel parameters like center + * frequency for a bonded channel state. Also return the maximum bandwidth + * supported by the channel. + * @pdev: Pointer to pdev. + * @freq: Channel center frequency. + * ch_params: Pointer to ch_params. + * + * Return: void + */ +static void reg_set_5g_channel_params_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + struct ch_params *ch_params) +{ + /* + * Set channel parameters like center frequency for a bonded channel + * state. Also return the maximum bandwidth supported by the channel. + */ + + enum channel_state chan_state = CHANNEL_STATE_ENABLE; + enum channel_state chan_state2 = CHANNEL_STATE_ENABLE; + const struct bonded_channel_freq *bonded_chan_ptr = NULL; + const struct bonded_channel_freq *bonded_chan_ptr2 = NULL; + + if (!ch_params) { + reg_err("ch_params is NULL"); + return; + } + + if (ch_params->ch_width >= CH_WIDTH_MAX) { + if (ch_params->mhz_freq_seg1 != 0) + ch_params->ch_width = CH_WIDTH_80P80MHZ; + else + ch_params->ch_width = CH_WIDTH_160MHZ; + } + + while (ch_params->ch_width != CH_WIDTH_INVALID) { + bonded_chan_ptr = NULL; + bonded_chan_ptr2 = NULL; + chan_state = reg_get_5g_bonded_channel_for_freq( + pdev, freq, ch_params->ch_width, + &bonded_chan_ptr); + + chan_state = reg_get_5g_bonded_channel_state_for_freq( + pdev, freq, ch_params->ch_width); + + if (ch_params->ch_width == CH_WIDTH_80P80MHZ) { + chan_state2 = reg_get_5g_bonded_channel_state_for_freq( + pdev, ch_params->mhz_freq_seg1 - + NEAREST_20MHZ_CHAN_FREQ_OFFSET, + CH_WIDTH_80MHZ); + + chan_state = reg_combine_channel_states( + chan_state, chan_state2); + } + + if ((chan_state != CHANNEL_STATE_ENABLE) && + (chan_state != CHANNEL_STATE_DFS)) + goto update_bw; + if (ch_params->ch_width <= CH_WIDTH_20MHZ) { + ch_params->sec_ch_offset = NO_SEC_CH; + ch_params->mhz_freq_seg0 = freq; + if (reg_is_6ghz_chan_freq(ch_params->mhz_freq_seg0)) + ch_params->center_freq_seg0 = + (ch_params->mhz_freq_seg0 - + SIXG_STARTING_FREQ) / FREQ_TO_CHAN_SCALE; + else + ch_params->center_freq_seg0 = + (ch_params->mhz_freq_seg0 - + FIVEG_STARTING_FREQ) / FREQ_TO_CHAN_SCALE; + break; + } else if (ch_params->ch_width >= CH_WIDTH_40MHZ) { + reg_get_5g_bonded_chan_array_for_freq( + pdev, freq, bonded_chan_40mhz_list_freq, + QDF_ARRAY_SIZE(bonded_chan_40mhz_list_freq), + &bonded_chan_ptr2); + if (!bonded_chan_ptr || !bonded_chan_ptr2) + goto update_bw; + if (freq == bonded_chan_ptr2->start_freq) + ch_params->sec_ch_offset = LOW_PRIMARY_CH; + else + ch_params->sec_ch_offset = HIGH_PRIMARY_CH; + + ch_params->mhz_freq_seg0 = + (bonded_chan_ptr->start_freq + + bonded_chan_ptr->end_freq) / 2; + if (reg_is_6ghz_chan_freq(ch_params->mhz_freq_seg0)) + ch_params->center_freq_seg0 = + (ch_params->mhz_freq_seg0 - + SIXG_STARTING_FREQ) / FREQ_TO_CHAN_SCALE; + else + ch_params->center_freq_seg0 = + (ch_params->mhz_freq_seg0 - + FIVEG_STARTING_FREQ) / FREQ_TO_CHAN_SCALE; + break; + } +update_bw: + ch_params->ch_width = get_next_lower_bw[ch_params->ch_width]; + } + + if (ch_params->ch_width == CH_WIDTH_160MHZ) { + ch_params->mhz_freq_seg1 = ch_params->mhz_freq_seg0; + if (reg_is_6ghz_chan_freq(ch_params->mhz_freq_seg1)) + ch_params->center_freq_seg1 = + (ch_params->mhz_freq_seg1 - SIXG_STARTING_FREQ) / + FREQ_TO_CHAN_SCALE; + else + ch_params->center_freq_seg1 = + (ch_params->mhz_freq_seg1 - FIVEG_STARTING_FREQ) / + FREQ_TO_CHAN_SCALE; + chan_state = reg_get_5g_bonded_channel_for_freq( + pdev, freq, CH_WIDTH_80MHZ, &bonded_chan_ptr); + if (bonded_chan_ptr) { + ch_params->mhz_freq_seg0 = + (bonded_chan_ptr->start_freq + + bonded_chan_ptr->end_freq) / 2; + if (reg_is_6ghz_chan_freq(ch_params->mhz_freq_seg0)) + ch_params->center_freq_seg0 = + (ch_params->mhz_freq_seg0 - + SIXG_STARTING_FREQ) / FREQ_TO_CHAN_SCALE; + else + ch_params->center_freq_seg0 = + (ch_params->mhz_freq_seg0 - + FIVEG_STARTING_FREQ) / FREQ_TO_CHAN_SCALE; + } + } + /* Overwrite mhz_freq_seg1 to 0 for non 160 and 80+80 width */ + if (!(ch_params->ch_width == CH_WIDTH_160MHZ || + ch_params->ch_width == CH_WIDTH_80P80MHZ)) { + ch_params->mhz_freq_seg1 = 0; + ch_params->center_freq_seg1 = 0; + } } -bool reg_is_6ghz_supported(struct wlan_objmgr_pdev *pdev) +/** + * reg_set_2g_channel_params_for_freq() - set the 2.4G bonded channel parameters + * @oper_freq: operating channel + * @ch_params: channel parameters + * @sec_ch_2g_freq: 2.4G secondary channel + * + * Return: void + */ +static void reg_set_2g_channel_params_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t oper_freq, + struct ch_params *ch_params, + uint16_t sec_ch_2g_freq) { - struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + enum channel_state chan_state = CHANNEL_STATE_ENABLE; + + if (ch_params->ch_width >= CH_WIDTH_MAX) + ch_params->ch_width = CH_WIDTH_40MHZ; + if ((reg_get_bw_value(ch_params->ch_width) > 20) && !sec_ch_2g_freq) { + if (oper_freq >= TWOG_CHAN_1_IN_MHZ && oper_freq <= + TWOG_CHAN_5_IN_MHZ) + sec_ch_2g_freq = oper_freq + 20; + else if (oper_freq >= TWOG_CHAN_6_IN_MHZ && oper_freq <= + TWOG_CHAN_13_IN_MHZ) + sec_ch_2g_freq = oper_freq - 20; + } + + while (ch_params->ch_width != CH_WIDTH_INVALID) { + chan_state = + reg_get_2g_bonded_channel_state_for_freq(pdev, oper_freq, + sec_ch_2g_freq, + ch_params->ch_width); + if ((chan_state == CHANNEL_STATE_ENABLE) || + (chan_state == CHANNEL_STATE_DFS)) { + if (ch_params->ch_width == CH_WIDTH_40MHZ) { + if (oper_freq < sec_ch_2g_freq) + ch_params->sec_ch_offset = + LOW_PRIMARY_CH; + else + ch_params->sec_ch_offset = + HIGH_PRIMARY_CH; + ch_params->mhz_freq_seg0 = + (oper_freq + sec_ch_2g_freq) / 2; + if (ch_params->mhz_freq_seg0 == + TWOG_CHAN_14_IN_MHZ) + ch_params->center_freq_seg0 = 14; + else + ch_params->center_freq_seg0 = + (ch_params->mhz_freq_seg0 - + TWOG_STARTING_FREQ) / + FREQ_TO_CHAN_SCALE; + } else { + ch_params->sec_ch_offset = NO_SEC_CH; + ch_params->mhz_freq_seg0 = oper_freq; + if (ch_params->mhz_freq_seg0 == + TWOG_CHAN_14_IN_MHZ) + ch_params->center_freq_seg0 = 14; + else + ch_params->center_freq_seg0 = + (ch_params->mhz_freq_seg0 - + TWOG_STARTING_FREQ) / + FREQ_TO_CHAN_SCALE; + } + break; + } + + ch_params->ch_width = get_next_lower_bw[ch_params->ch_width]; + } + /* Overwrite mhz_freq_seg1 and center_freq_seg1 to 0 for 2.4 Ghz */ + ch_params->mhz_freq_seg1 = 0; + ch_params->center_freq_seg1 = 0; +} + +void reg_set_channel_params_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + qdf_freq_t sec_ch_2g_freq, + struct ch_params *ch_params) +{ + if (reg_is_5ghz_ch_freq(freq) || reg_is_6ghz_chan_freq(freq)) + reg_set_5g_channel_params_for_freq(pdev, freq, ch_params); + else if (reg_is_24ghz_ch_freq(freq)) + reg_set_2g_channel_params_for_freq(pdev, freq, ch_params, + sec_ch_2g_freq); +} + +uint8_t reg_get_channel_reg_power_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + enum channel_enum chan_enum; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct regulatory_channel *reg_channels; + + chan_enum = reg_get_chan_enum_for_freq(freq); + + if (chan_enum == INVALID_CHANNEL) { + reg_err("channel is invalid"); + return REG_INVALID_TXPOWER; + } + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev priv obj is NULL"); + return REG_INVALID_TXPOWER; + } + + reg_channels = pdev_priv_obj->cur_chan_list; + + return reg_channels[chan_enum].tx_power; +} + +bool reg_is_dfs_for_freq(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq) +{ + uint32_t chan_flags; + + chan_flags = reg_get_channel_flags_for_freq(pdev, freq); + + return chan_flags & REGULATORY_CHAN_RADAR; +} + +#ifdef CONFIG_REG_CLIENT +/** + * reg_get_psoc_mas_chan_list () - Get psoc master channel list + * @pdev: pointer to pdev object + * @psoc: pointer to psoc object + * + * Return: psoc master chanel list + */ +static struct regulatory_channel *reg_get_psoc_mas_chan_list( + struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_psoc *psoc) +{ + struct wlan_regulatory_psoc_priv_obj *soc_reg; + uint8_t pdev_id; + + soc_reg = reg_get_psoc_obj(psoc); + if (!soc_reg) { + reg_err("reg psoc private obj is NULL"); + return NULL; + } + pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + return soc_reg->mas_chan_params[pdev_id].mas_chan_list; +} +#else +static inline struct regulatory_channel *reg_get_psoc_mas_chan_list( + struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_psoc *psoc) +{ + return NULL; +} +#endif + +void reg_update_nol_ch_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *chan_freq_list, + uint8_t num_chan, + bool nol_chan) +{ + enum channel_enum chan_enum; + struct regulatory_channel *mas_chan_list, *psoc_mas_chan_list; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; struct wlan_objmgr_psoc *psoc; + uint16_t i; + + if (!num_chan || !chan_freq_list) { + reg_err("chan_freq_list or num_ch is NULL"); + return; + } psoc = wlan_pdev_get_psoc(pdev); - if (!psoc) { - reg_err_rl("psoc is NULL"); + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!pdev_priv_obj) { + reg_err("reg pdev private obj is NULL"); + return; + } + + psoc_mas_chan_list = reg_get_psoc_mas_chan_list(pdev, psoc); + + mas_chan_list = pdev_priv_obj->mas_chan_list; + for (i = 0; i < num_chan; i++) { + chan_enum = reg_get_chan_enum_for_freq(chan_freq_list[i]); + if (chan_enum == INVALID_CHANNEL) { + reg_err("Invalid freq in nol list, freq %d", + chan_freq_list[i]); + continue; + } + mas_chan_list[chan_enum].nol_chan = nol_chan; + if (psoc_mas_chan_list) + psoc_mas_chan_list[chan_enum].nol_chan = nol_chan; + } + + reg_compute_pdev_current_chan_list(pdev_priv_obj); + + reg_send_scheduler_msg_sb(psoc, pdev); +} + +void reg_update_nol_history_ch_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *chan_list, + uint8_t num_chan, + bool nol_history_chan) +{ + enum channel_enum chan_enum; + struct regulatory_channel *mas_chan_list; + struct regulatory_channel *cur_chan_list; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + uint16_t i; + + if (!num_chan || !chan_list) { + reg_err("chan_list or num_ch is NULL"); + return; + } + + pdev_priv_obj = wlan_objmgr_pdev_get_comp_private_obj( + pdev, WLAN_UMAC_COMP_REGULATORY); + + if (!pdev_priv_obj) { + reg_err("reg psoc private obj is NULL"); + return; + } + + mas_chan_list = pdev_priv_obj->mas_chan_list; + cur_chan_list = pdev_priv_obj->cur_chan_list; + + for (i = 0; i < num_chan; i++) { + chan_enum = reg_get_chan_enum_for_freq(chan_list[i]); + if (chan_enum == INVALID_CHANNEL) { + reg_err("Invalid ch in nol list, chan %d", + chan_list[i]); + continue; + } + mas_chan_list[chan_enum].nol_history = nol_history_chan; + cur_chan_list[chan_enum].nol_history = nol_history_chan; + } +} + +static inline bool REG_IS_FREQUENCY_VALID_5G_SBS(qdf_freq_t curfreq, + qdf_freq_t newfreq) +{ + return ((curfreq) > (newfreq) ? + REG_CH_TO_FREQ(reg_get_chan_enum_for_freq(curfreq)) + - REG_CH_TO_FREQ(reg_get_chan_enum_for_freq(newfreq)) + > REG_SBS_SEPARATION_THRESHOLD : + REG_CH_TO_FREQ(reg_get_chan_enum_for_freq(newfreq)) + - REG_CH_TO_FREQ(reg_get_chan_enum_for_freq(curfreq)) + > REG_SBS_SEPARATION_THRESHOLD); +} + +bool reg_is_frequency_valid_5g_sbs(qdf_freq_t curfreq, qdf_freq_t newfreq) +{ + return REG_IS_FREQUENCY_VALID_5G_SBS(curfreq, newfreq); +} + +qdf_freq_t reg_min_chan_freq(void) +{ + return channel_map[MIN_24GHZ_CHANNEL].center_freq; +} + +qdf_freq_t reg_max_chan_freq(void) +{ + return channel_map[NUM_CHANNELS - 1].center_freq; +} + +bool reg_is_same_band_freqs(qdf_freq_t freq1, qdf_freq_t freq2) +{ + return (freq1 && freq2 && ((REG_IS_6GHZ_FREQ(freq1) && + REG_IS_6GHZ_FREQ(freq2)) || + (REG_IS_5GHZ_FREQ(freq1) && + REG_IS_5GHZ_FREQ(freq2)) || + (REG_IS_24GHZ_CH_FREQ(freq1) && + REG_IS_24GHZ_CH_FREQ(freq2)))); +} + +enum reg_wifi_band reg_freq_to_band(qdf_freq_t freq) +{ + if (REG_IS_24GHZ_CH_FREQ(freq)) + return REG_BAND_2G; + else if (REG_IS_5GHZ_FREQ(freq) || REG_IS_49GHZ_FREQ(freq)) + return REG_BAND_5G; + else if (REG_IS_6GHZ_FREQ(freq)) + return REG_BAND_6G; + return REG_BAND_UNKNOWN; +} + +#endif /* CONFIG_CHAN_FREQ_API */ + +uint8_t reg_get_max_tx_power(struct wlan_objmgr_pdev *pdev) +{ + struct regulatory_channel *cur_chan_list; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + uint8_t i, max_tx_power = 0; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("reg pdev private obj is NULL"); + return QDF_STATUS_E_FAILURE; + } + + cur_chan_list = pdev_priv_obj->cur_chan_list; + + for (i = 0; i < NUM_CHANNELS; i++) { + if (cur_chan_list[i].state != CHANNEL_STATE_DISABLE && + cur_chan_list[i].chan_flags != REGULATORY_CHAN_DISABLED) { + if (cur_chan_list[i].tx_power > max_tx_power) + max_tx_power = cur_chan_list[i].tx_power; + } + } + + if (!max_tx_power) + reg_err_rl("max_tx_power is zero"); + + return max_tx_power; +} + +QDF_STATUS reg_set_ignore_fw_reg_offload_ind(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_reg; + + psoc_reg = reg_get_psoc_obj(psoc); + if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) { + reg_err("psoc reg component is NULL"); + return QDF_STATUS_E_INVAL; + } + + psoc_reg->ignore_fw_reg_offload_ind = true; + return QDF_STATUS_SUCCESS; +} + +bool reg_get_ignore_fw_reg_offload_ind(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_reg; + + psoc_reg = reg_get_psoc_obj(psoc); + if (!IS_VALID_PSOC_REG_OBJ(psoc_reg)) return false; + + return psoc_reg->ignore_fw_reg_offload_ind; +} + +QDF_STATUS reg_set_6ghz_supported(struct wlan_objmgr_psoc *psoc, bool val) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + psoc_priv_obj = reg_get_psoc_obj(psoc); + + if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { + reg_err("psoc reg component is NULL"); + return QDF_STATUS_E_FAILURE; } + psoc_priv_obj->six_ghz_supported = val; + + return QDF_STATUS_SUCCESS; +} + +bool reg_is_6ghz_op_class(struct wlan_objmgr_pdev *pdev, uint8_t op_class) +{ + return ((op_class >= MIN_6GHZ_OPER_CLASS) && + (op_class <= MAX_6GHZ_OPER_CLASS)); +} + +bool reg_is_6ghz_supported(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + psoc_priv_obj = reg_get_psoc_obj(psoc); if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { @@ -2184,3 +3676,47 @@ bool reg_is_6ghz_supported(struct wlan_objmgr_pdev *pdev) return psoc_priv_obj->six_ghz_supported; } + +#ifdef DISABLE_UNII_SHARED_BANDS +QDF_STATUS +reg_get_unii_5g_bitmap(struct wlan_objmgr_pdev *pdev, uint8_t *bitmap) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err_rl("pdev reg component is NULL"); + return QDF_STATUS_E_FAILURE; + } + *bitmap = pdev_priv_obj->unii_5g_bitmap; + + return QDF_STATUS_SUCCESS; +} +#endif + +#ifdef CONFIG_REG_CLIENT +enum band_info reg_band_bitmap_to_band_info(uint32_t band_bitmap) +{ + if ((band_bitmap & BIT(REG_BAND_2G)) && + (band_bitmap & BIT(REG_BAND_5G)) && + (band_bitmap & BIT(REG_BAND_6G))) + return BAND_ALL; + else if ((band_bitmap & BIT(REG_BAND_5G)) && + (band_bitmap & BIT(REG_BAND_6G))) + return BAND_5G; + else if ((band_bitmap & BIT(REG_BAND_2G)) && + (band_bitmap & BIT(REG_BAND_6G))) + return BAND_2G; + else if ((band_bitmap & BIT(REG_BAND_2G)) && + (band_bitmap & BIT(REG_BAND_5G))) + return BAND_ALL; + else if (band_bitmap & BIT(REG_BAND_2G)) + return BAND_2G; + else if (band_bitmap & BIT(REG_BAND_5G)) + return BAND_5G; + else if (band_bitmap & BIT(REG_BAND_6G)) + return BAND_2G; + else + return BAND_UNKNOWN; +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services_common.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services_common.h index 47b581132e4848a4dd573d42c1f6c2c5e52acac7..d18e01827905df5265e992b8d42bf93fa0e53f50 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services_common.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -28,7 +28,13 @@ #define IS_VALID_PSOC_REG_OBJ(psoc_priv_obj) (psoc_priv_obj) #define IS_VALID_PDEV_REG_OBJ(pdev_priv_obj) (pdev_priv_obj) +#define FREQ_TO_CHAN_SCALE 5 +/* The distance between the 80Mhz center and the nearest 20Mhz channel */ +#define NEAREST_20MHZ_CHAN_FREQ_OFFSET 10 +#define NUM_20_MHZ_CHAN_IN_80_MHZ_CHAN 4 +#define NUM_20_MHZ_CHAN_IN_160_MHZ_CHAN 8 +#ifdef CONFIG_CHAN_NUM_API #define REG_MIN_24GHZ_CH_NUM channel_map[MIN_24GHZ_CHANNEL].chan_num #define REG_MAX_24GHZ_CH_NUM channel_map[MAX_24GHZ_CHANNEL].chan_num #define REG_MIN_5GHZ_CH_NUM channel_map[MIN_5GHZ_CHANNEL].chan_num @@ -37,6 +43,7 @@ #define REG_IS_24GHZ_CH(chan_num) \ (((chan_num) >= REG_MIN_24GHZ_CH_NUM) && \ ((chan_num) <= REG_MAX_24GHZ_CH_NUM)) +#endif /* CONFIG_CHAN_NUM_API */ #define REG_MIN_24GHZ_CH_FREQ channel_map[MIN_24GHZ_CHANNEL].center_freq #define REG_MAX_24GHZ_CH_FREQ channel_map[MAX_24GHZ_CHANNEL].center_freq @@ -45,23 +52,46 @@ (((freq) >= REG_MIN_24GHZ_CH_FREQ) && \ ((freq) <= REG_MAX_24GHZ_CH_FREQ)) -#ifndef CONFIG_LEGACY_CHAN_ENUM +#ifdef CONFIG_CHAN_FREQ_API +#define REG_MIN_5GHZ_CH_FREQ channel_map[MIN_5GHZ_CHANNEL].center_freq +#define REG_MAX_5GHZ_CH_FREQ channel_map[MAX_5GHZ_CHANNEL].center_freq +#endif /* CONFIG_CHAN_FREQ_API */ + #define REG_MIN_49GHZ_CH_FREQ channel_map[MIN_49GHZ_CHANNEL].center_freq #define REG_MAX_49GHZ_CH_FREQ channel_map[MAX_49GHZ_CHANNEL].center_freq #define REG_IS_49GHZ_FREQ(freq) \ (((freq) >= REG_MIN_49GHZ_CH_FREQ) && \ ((freq) <= REG_MAX_49GHZ_CH_FREQ)) -#endif +#ifdef CONFIG_CHAN_NUM_API #define REG_IS_5GHZ_CH(chan_num) \ (((chan_num) >= REG_MIN_5GHZ_CH_NUM) && \ ((chan_num) <= REG_MAX_5GHZ_CH_NUM)) +#endif /* CONFIG_CHAN_NUM_API */ #define REG_IS_5GHZ_FREQ(freq) \ (((freq) >= channel_map[MIN_5GHZ_CHANNEL].center_freq) && \ ((freq) <= channel_map[MAX_5GHZ_CHANNEL].center_freq)) +#ifdef CONFIG_BAND_6GHZ +#define FREQ_LEFT_SHIFT 55 +#define SIXG_STARTING_FREQ 5940 +#define NUM_80MHZ_BAND_IN_6G 16 +#define NUM_PSC_FREQ 15 +#define PSC_BAND_MHZ (FREQ_TO_CHAN_SCALE * NUM_80MHZ_BAND_IN_6G) +#define REG_MIN_6GHZ_CHAN_FREQ channel_map[MIN_6GHZ_CHANNEL].center_freq +#define REG_MAX_6GHZ_CHAN_FREQ channel_map[MAX_6GHZ_CHANNEL].center_freq +#else +#define FREQ_LEFT_SHIFT 0 +#define SIXG_STARTING_FREQ 0 +#define NUM_80MHZ_BAND_IN_6G 0 +#define NUM_PSC_FREQ 0 +#define PSC_BAND_MHZ (FREQ_TO_CHAN_SCALE * NUM_80MHZ_BAND_IN_6G) +#define REG_MIN_6GHZ_CHAN_FREQ 0 +#define REG_MAX_6GHZ_CHAN_FREQ 0 +#endif /*CONFIG_BAND_6GHZ*/ + #define REG_CH_NUM(ch_enum) channel_map[ch_enum].chan_num #define REG_CH_TO_FREQ(ch_enum) channel_map[ch_enum].center_freq @@ -71,14 +101,20 @@ #define MAX_6GHZ_OPER_CLASS 135 extern const struct chan_map *channel_map; +extern const struct chan_map channel_map_us[]; +extern const struct chan_map channel_map_eu[]; +extern const struct chan_map channel_map_jp[]; +extern const struct chan_map channel_map_china[]; +extern const struct chan_map channel_map_global[]; +#ifdef CONFIG_CHAN_NUM_API /** * reg_get_chan_enum() - Get channel enum for given channel number * @chan_num: Channel number * * Return: Channel enum */ -enum channel_enum reg_get_chan_enum(uint32_t chan_num); +enum channel_enum reg_get_chan_enum(uint8_t chan_num); /** * reg_get_channel_list_with_power() - Provides the channel list with power @@ -100,7 +136,21 @@ QDF_STATUS reg_get_channel_list_with_power(struct wlan_objmgr_pdev *pdev, * Return: channel state */ enum channel_state reg_get_channel_state(struct wlan_objmgr_pdev *pdev, - uint32_t ch); + uint8_t ch); + +/** + * reg_get_5g_bonded_channel() - get the 5G bonded channel state + * @pdev: Pointer to pdev structure + * @chan_num: channel number + * @ch_width: channel width + * @bonded_chan_ptr_ptr: bonded channel ptr ptr + * + * Return: channel state + */ +enum channel_state reg_get_5g_bonded_channel( + struct wlan_objmgr_pdev *pdev, uint8_t chan_num, + enum phy_ch_width ch_width, + const struct bonded_channel **bonded_chan_ptr_ptr); /** * reg_get_5g_bonded_channel_state() - Get channel state for 5G bonded channel @@ -140,6 +190,7 @@ enum channel_state reg_get_2g_bonded_channel_state( void reg_set_channel_params(struct wlan_objmgr_pdev *pdev, uint8_t ch, uint8_t sec_ch_2g, struct ch_params *ch_params); +#endif /* CONFIG_CHAN_NUM_API */ /** * reg_read_default_country() - Get the default regulatory country @@ -161,6 +212,7 @@ QDF_STATUS reg_read_default_country(struct wlan_objmgr_psoc *psoc, void reg_get_current_dfs_region(struct wlan_objmgr_pdev *pdev, enum dfs_reg *dfs_reg); +#ifdef CONFIG_CHAN_NUM_API /** * reg_get_channel_reg_power() - Get the txpower for the given channel * @pdev: Pointer to pdev @@ -169,7 +221,7 @@ void reg_get_current_dfs_region(struct wlan_objmgr_pdev *pdev, * Return: txpower */ uint32_t reg_get_channel_reg_power(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num); + uint8_t chan_num); /** * reg_get_channel_freq() - Get the channel frequency @@ -178,8 +230,9 @@ uint32_t reg_get_channel_reg_power(struct wlan_objmgr_pdev *pdev, * * Return: frequency */ -uint32_t reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num); +qdf_freq_t reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num); +#endif /* CONFIG_CHAN_NUM_API */ /** * reg_get_bw_value() - give bandwidth value @@ -199,13 +252,15 @@ uint16_t reg_get_bw_value(enum phy_ch_width bw); void reg_set_dfs_region(struct wlan_objmgr_pdev *pdev, enum dfs_reg dfs_reg); +#ifdef CONFIG_CHAN_NUM_API /** * reg_chan_to_band() - Get band from channel number * @chan_num: channel number * * Return: band info */ -enum band_info reg_chan_to_band(uint32_t chan_num); +enum band_info reg_chan_to_band(uint8_t chan_num); +#endif /* CONFIG_CHAN_NUM_API */ /** * reg_program_chan_list() - Set user country code and populate the channel list @@ -217,6 +272,7 @@ enum band_info reg_chan_to_band(uint32_t chan_num); QDF_STATUS reg_program_chan_list(struct wlan_objmgr_pdev *pdev, struct cc_regdmn_s *rd); +#ifdef CONFIG_CHAN_NUM_API /** * reg_update_nol_ch () - Updates NOL channels in current channel list * @pdev: pointer to pdev object @@ -236,25 +292,27 @@ void reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, uint8_t *chan_list, * * Return: true or false */ -bool reg_is_dfs_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan); +bool reg_is_dfs_ch(struct wlan_objmgr_pdev *pdev, uint8_t chan); +#endif /* CONFIG_CHAN_NUM_API */ /** * reg_freq_to_chan() - Get channel number from frequency. * @pdev: Pointer to pdev * @freq: Channel frequency * - * Return: Channel number + * Return: Channel number if success, otherwise 0 */ -uint32_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, uint32_t freq); +uint8_t reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq); +#ifdef CONFIG_CHAN_NUM_API /** * reg_chan_to_freq() - Get frequency from channel number * @pdev: Pointer to pdev * @chan_num: Channel number * - * Return: Channel frequency + * Return: Channel frequency if success, otherwise 0 */ -uint32_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, uint32_t chan_num); +qdf_freq_t reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, uint8_t chan_num); /** * reg_legacy_chan_to_freq() - Get freq from chan noumber, for 2G and 5G @@ -274,6 +332,7 @@ uint16_t reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, * Return: true if the channel is 4.9GHz else false. */ bool reg_chan_is_49ghz(struct wlan_objmgr_pdev *pdev, uint8_t chan_num); +#endif /* CONFIG_CHAN_NUM_API */ /** * reg_program_default_cc() - Program default country code @@ -295,16 +354,6 @@ QDF_STATUS reg_program_default_cc(struct wlan_objmgr_pdev *pdev, QDF_STATUS reg_get_current_cc(struct wlan_objmgr_pdev *pdev, struct cc_regdmn_s *rd); -/** - * reg_get_curr_band() - Get current band - * @pdev: Pdev pointer - * @band: Pointer to save the current band - * - * Return: QDF_STATUS - */ -QDF_STATUS reg_get_curr_band(struct wlan_objmgr_pdev *pdev, - enum band_info *band); - /** * reg_set_regdb_offloaded() - set/clear regulatory offloaded flag * @@ -374,8 +423,8 @@ QDF_STATUS reg_set_hal_reg_cap( * Return: true if ch_enum is with in pdev's channel range, else false. */ bool reg_chan_in_range(struct regulatory_channel *chan_list, - uint32_t low_freq_2g, uint32_t high_freq_2g, - uint32_t low_freq_5g, uint32_t high_freq_5g, + qdf_freq_t low_freq_2g, qdf_freq_t high_freq_2g, + qdf_freq_t low_freq_5g, qdf_freq_t high_freq_5g, enum channel_enum ch_enum); /** @@ -391,6 +440,7 @@ void reg_init_channel_map(enum dfs_reg dfs_region); struct wlan_lmac_if_reg_tx_ops *reg_get_psoc_tx_ops( struct wlan_objmgr_psoc *psoc); +#ifdef CONFIG_CHAN_NUM_API /** * reg_update_nol_history_ch() - Set nol-history flag for the channels in the * list. @@ -421,6 +471,7 @@ bool reg_is_24ghz_ch(uint32_t chan); * Return: true if channel number is 5GHz, else false */ bool reg_is_5ghz_ch(uint32_t chan); +#endif /* CONFIG_CHAN_NUM_API */ /** * reg_is_24ghz_ch_freq() - Check if the given channel frequency is 2.4GHz @@ -436,17 +487,126 @@ bool reg_is_24ghz_ch_freq(uint32_t freq); * * Return: true if channel frequency is 5GHz, else false */ -bool reg_is_5ghz_ch_freq(uint32_t chan); +bool reg_is_5ghz_ch_freq(uint32_t freq); + +/** + * reg_is_freq_indoor() - Check if the input frequency is an indoor frequency. + * @pdev: Pointer to pdev. + * @freq: Channel frequency. + * + * Return: Return true if the input frequency is indoor, else false. + */ +bool reg_is_freq_indoor(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq); + +#ifdef CONFIG_BAND_6GHZ +/** + * reg_is_6ghz_chan_freq() - Check if the given channel frequency is 6GHz + * @freq: Channel frequency + * + * Return: true if channel frequency is 6GHz, else false + */ +bool reg_is_6ghz_chan_freq(uint16_t freq); + +/** + * REG_IS_6GHZ_FREQ() - Check if the given channel frequency is 6GHz + * @freq: Channel frequency + * + * Return: true if channel frequency is 6GHz, else false + */ +static inline bool REG_IS_6GHZ_FREQ(uint16_t freq) +{ + return ((freq >= REG_MIN_6GHZ_CHAN_FREQ) && + (freq <= REG_MAX_6GHZ_CHAN_FREQ)); +} + +/** + * reg_is_6ghz_psc_chan_freq() - Check if the given 6GHz channel frequency is + * preferred scanning channel frequency. + * @freq: Channel frequency + * + * Return: true if given 6GHz channel frequency is preferred scanning channel + * frequency, else false + */ +bool reg_is_6ghz_psc_chan_freq(uint16_t freq); + +/** + * reg_min_6ghz_chan_freq() - Get minimum 6GHz channel center frequency + * + * Return: Minimum 6GHz channel center frequency + */ +uint16_t reg_min_6ghz_chan_freq(void); + +/** + * reg_max_6ghz_chan_freq() - Get maximum 6GHz channel center frequency + * + * Return: Maximum 6GHz channel center frequency + */ +uint16_t reg_max_6ghz_chan_freq(void); +#else +static inline bool reg_is_6ghz_chan_freq(uint16_t freq) +{ + return false; +} + +static inline bool REG_IS_6GHZ_FREQ(uint16_t freq) +{ + return false; +} + +static inline bool reg_is_6ghz_psc_chan_freq(uint16_t freq) +{ + return false; +} + +static inline uint16_t reg_min_6ghz_chan_freq(void) +{ + return 0; +} + +static inline uint16_t reg_max_6ghz_chan_freq(void) +{ + return 0; +} +#endif /* CONFIG_BAND_6GHZ */ + +/** + * reg_get_band_channel_list() - Get the channel list and number of channels + * @pdev: pdev ptr + * @band_mask: Input bitmap with band set + * @channel_list: Pointer to Channel List + * + * Get the given channel list and number of channels from the current channel + * list based on input band bitmap. + * + * Return: Number of channels, else 0 to indicate error + */ +uint16_t reg_get_band_channel_list(struct wlan_objmgr_pdev *pdev, + uint8_t band_mask, + struct regulatory_channel *channel_list); + +/** + * reg_chan_band_to_freq - Return channel frequency based on the channel number + * and band. + * @pdev: pdev ptr + * @chan: Channel Number + * @band_mask: Bitmap for bands + * + * Return: Return channel frequency or return 0, if the channel is disabled or + * if the input channel number or band_mask is invalid. Composite bands are + * supported only for 2.4Ghz and 5Ghz bands. For other bands the following + * priority is given: 1) 6Ghz 2) 5Ghz 3) 2.4Ghz. + */ +qdf_freq_t reg_chan_band_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan, + uint8_t band_mask); -#ifndef CONFIG_LEGACY_CHAN_ENUM /** * reg_is_49ghz_freq() - Check if the given channel frequency is 4.9GHz * @freq: Channel frequency * * Return: true if channel frequency is 4.9GHz, else false */ -bool reg_is_49ghz_freq(uint32_t freq); -#endif +bool reg_is_49ghz_freq(qdf_freq_t freq); /** * reg_ch_num() - Get channel number from channel enum @@ -454,7 +614,7 @@ bool reg_is_49ghz_freq(uint32_t freq); * * Return: channel number */ -uint32_t reg_ch_num(uint32_t ch_enum); +qdf_freq_t reg_ch_num(uint32_t ch_enum); /** * reg_ch_to_freq() - Get channel frequency from channel enum @@ -462,8 +622,9 @@ uint32_t reg_ch_num(uint32_t ch_enum); * * Return: channel frequency */ -uint32_t reg_ch_to_freq(uint32_t ch_enum); +qdf_freq_t reg_ch_to_freq(uint32_t ch_enum); +#ifdef CONFIG_CHAN_NUM_API /** * reg_is_same_band_channels() - Check if given channel numbers have same band * @chan_num1: Channel number1 @@ -471,7 +632,7 @@ uint32_t reg_ch_to_freq(uint32_t ch_enum); * * Return: true if both the channels has the same band. */ -bool reg_is_same_band_channels(uint32_t chan_num1, uint32_t chan_num2); +bool reg_is_same_band_channels(uint8_t chan_num1, uint8_t chan_num2); /** * reg_is_channel_valid_5g_sbs() Check if the given channel is 5G SBS. @@ -480,35 +641,66 @@ bool reg_is_same_band_channels(uint32_t chan_num1, uint32_t chan_num2); * * Return: true if the given channel is a valid 5G SBS */ -bool reg_is_channel_valid_5g_sbs(uint32_t curchan, uint32_t newchan); +bool reg_is_channel_valid_5g_sbs(uint8_t curchan, uint8_t newchan); /** * reg_min_24ghz_ch_num() - Get minimum 2.4GHz channel number * * Return: Minimum 2.4GHz channel number */ -uint32_t reg_min_24ghz_ch_num(void); +uint8_t reg_min_24ghz_ch_num(void); /** * reg_max_24ghz_ch_num() - Get maximum 2.4GHz channel number * * Return: Maximum 2.4GHz channel number */ -uint32_t reg_max_24ghz_ch_num(void); +uint8_t reg_max_24ghz_ch_num(void); /** * reg_min_5ghz_ch_num() - Get minimum 5GHz channel number * * Return: Minimum 5GHz channel number */ -uint32_t reg_min_5ghz_ch_num(void); +uint8_t reg_min_5ghz_ch_num(void); /** * reg_max_5ghz_ch_num() - Get maximum 5GHz channel number * * Return: Maximum 5GHz channel number */ -uint32_t reg_max_5ghz_ch_num(void); +uint8_t reg_max_5ghz_ch_num(void); +#endif /* CONFIG_CHAN_NUM_API */ + +#ifdef CONFIG_CHAN_FREQ_API +/** + * reg_min_24ghz_chan_freq() - Get minimum 2.4GHz channel frequency + * + * Return: Minimum 2.4GHz channel frequency + */ +qdf_freq_t reg_min_24ghz_chan_freq(void); + +/** + * reg_max_24ghz_chan_freq() - Get maximum 2.4GHz channel frequency + * + * Return: Maximum 2.4GHz channel frequency + */ +qdf_freq_t reg_max_24ghz_chan_freq(void); + +/** + * reg_min_5ghz_chan_freq() - Get minimum 5GHz channel frequency + * + * Return: Minimum 5GHz channel frequency + */ +qdf_freq_t reg_min_5ghz_chan_freq(void); + +/** + * reg_max_5ghz_chan_freq() - Get maximum 5GHz channel frequency + * + * Return: Maximum 5GHz channel frequency + */ +qdf_freq_t reg_max_5ghz_chan_freq(void); +#endif /* CONFIG_CHAN_FREQ_API */ /** * reg_enable_dfs_channels() - Enable the use of DFS channels @@ -518,6 +710,256 @@ uint32_t reg_max_5ghz_ch_num(void); */ QDF_STATUS reg_enable_dfs_channels(struct wlan_objmgr_pdev *pdev, bool enable); +/** + * reg_is_regdmn_en302502_applicable() - Find if ETSI EN302_502 radar pattern + * is applicable in current regulatory domain. + * @pdev: Pdev object pointer. + * + * Return: True if en302_502 is applicable, else false. + */ +bool reg_is_regdmn_en302502_applicable(struct wlan_objmgr_pdev *pdev); + +/** + * reg_modify_pdev_chan_range() - Compute current channel list + * in accordance with the modified reg caps. + * @pdev: The physical dev for which channel list must be built. + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev); + +#ifdef DISABLE_UNII_SHARED_BANDS +/** + * reg_disable_chan_coex() - Disable Coexisting channels based on the input + * bitmask. + * @pdev: pointer to wlan_objmgr_pdev. + * unii_5g_bitmap: UNII 5G bitmap. + * + * Return : QDF_STATUS + */ +QDF_STATUS reg_disable_chan_coex(struct wlan_objmgr_pdev *pdev, + uint8_t unii_5g_bitmap); +#endif + +#ifdef CONFIG_CHAN_FREQ_API +/** + * reg_is_freq_present_in_cur_chan_list() - Check the input frequency + * @pdev: Pointer to pdev + * @freq: Channel center frequency in MHz + * + * Check if the input channel center frequency is present in the current + * channel list + * + * Return: Return true if channel center frequency is present in the current + * channel list, else return false. + */ +bool +reg_is_freq_present_in_cur_chan_list(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); + +/** + * reg_get_chan_enum_for_freq() - Get channel enum for given channel frequency + * @freq: Channel Frequency + * + * Return: Channel enum + */ +enum channel_enum reg_get_chan_enum_for_freq(qdf_freq_t freq); + +/** + * reg_get_channel_list_with_power_for_freq() - Provides the channel list with + * power + * @pdev: Pointer to pdev + * @ch_list: Pointer to the channel list. + * @num_chan: Pointer to save number of channels + * + * Return: QDF_STATUS + */ +QDF_STATUS +reg_get_channel_list_with_power_for_freq(struct wlan_objmgr_pdev *pdev, + struct channel_power *ch_list, + uint8_t *num_chan); + +/** + * reg_get_channel_state_for_freq() - Get channel state from regulatory + * @pdev: Pointer to pdev + * @freq: channel center frequency. + * + * Return: channel state + */ +enum channel_state reg_get_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); + +/** + * reg_get_5g_bonded_channel_state_for_freq() - Get channel state for + * 5G bonded channel using the channel frequency + * @pdev: Pointer to pdev + * @freq: channel center frequency. + * @bw: channel band width + * + * Return: channel state + */ +enum channel_state +reg_get_5g_bonded_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + enum phy_ch_width bw); + +/** + * reg_get_2g_bonded_channel_state_for_freq() - Get channel state for 2G + * bonded channel + * @freq: channel center frequency. + * @pdev: Pointer to pdev + * @oper_ch_freq: Primary channel center frequency + * @sec_ch_freq: Secondary channel center frequency + * @bw: channel band width + * + * Return: channel state + */ +enum channel_state +reg_get_2g_bonded_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t oper_ch_freq, + qdf_freq_t sec_ch_freq, + enum phy_ch_width bw); + +/** + * reg_set_channel_params_for_freq () - Sets channel parameteres for given + * bandwidth + * @pdev: Pointer to pdev + * @freq: Channel center frequency. + * @sec_ch_2g_freq: Secondary 2G channel frequency + * @ch_params: pointer to the channel parameters. + * + * Return: None + */ +void reg_set_channel_params_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + qdf_freq_t sec_ch_2g_freq, + struct ch_params *ch_params); + +/** + * reg_get_channel_reg_power_for_freq() - Get the txpower for the given channel + * @pdev: Pointer to pdev + * @freq: Channel frequency + * + * Return: txpower + */ +uint8_t reg_get_channel_reg_power_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); + +/** + * reg_update_nol_ch_for_freq () - Updates NOL channels in current channel list + * @pdev: pointer to pdev object + * @chan_freq_list: pointer to NOL channel list + * @num_ch: No.of channels in list + * @update_nol: set/reset the NOL status + * + * Return: None + */ +void reg_update_nol_ch_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *chan_freq_list, + uint8_t num_chan, + bool nol_chan); +/** + * reg_is_dfs_for_freq () - Checks the channel state for DFS + * @pdev: pdev ptr + * @freq: Channel center frequency + * + * Return: true or false + */ +bool reg_is_dfs_for_freq(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq); + +/** + * reg_chan_freq_is_49ghz() - Check if the input channel center frequency is + * 4.9GHz + * @pdev: Pdev pointer + * @chan_num: Input channel center frequency + * + * Return: true if the frequency is 4.9GHz else false. + */ +bool reg_chan_freq_is_49ghz(qdf_freq_t freq); + +/** + * reg_update_nol_history_ch_for_freq() - Set nol-history flag for the channels + * in the list. + * @pdev: Pdev ptr. + * @chan_list: Input channel freqeuncy list. + * @num_ch: Number of channels. + * @nol_history_ch: NOL-History flag. + * + * Return: void + */ +void reg_update_nol_history_ch_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *chan_list, + uint8_t num_chan, + bool nol_history_chan); + +/** + * reg_is_same_5g_band_freqs() - Check if given channel center + * frequencies have same band + * @freq1: Channel Center Frequency 1 + * @freq2: Channel Center Frequency 2 + * + * Return: true if both the frequencies has the same band. + */ +bool reg_is_same_band_freqs(qdf_freq_t freq1, qdf_freq_t freq2); + +/** + * reg_is_frequency_valid_5g_sbs() Check if the given frequency is 5G SBS. + * @curfreq: current channel frequency + * @newfreq: new channel center frequency + * + * Return: true if the given center frequency is a valid 5G SBS + */ +bool reg_is_frequency_valid_5g_sbs(qdf_freq_t curfreq, qdf_freq_t newfreq); + +/** + * reg_freq_to_band() - Get band from channel frequency + * @chan_num: channel frequency + * + * Return: wifi band + */ +enum reg_wifi_band reg_freq_to_band(qdf_freq_t freq); + +/** + * reg_min_chan_freq() - minimum channel frequency supported + * + * Return: channel frequency + */ +qdf_freq_t reg_min_chan_freq(void); + +/** + * reg_max_chan_freq() - maximum channel frequency supported + * + * Return: channel frequency + */ +qdf_freq_t reg_max_chan_freq(void); + +/** + * reg_get_5g_bonded_channel_for_freq()- Return the channel state for a + * 5G or 6G channel frequency based on the channel width and bonded channel + * @pdev: Pointer to pdev. + * @freq: Channel center frequency. + * @ch_width: Channel Width. + * @bonded_chan_ptr_ptr: Pointer to bonded_channel_freq. + * + * Return: Channel State + */ +enum channel_state +reg_get_5g_bonded_channel_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + enum phy_ch_width ch_width, + const struct bonded_channel_freq + **bonded_chan_ptr_ptr); +#endif /* CONFIG_CHAN_FREQ_API */ + +/** + * reg_get_max_tx_power() - Get maximum tx power from the current channel list + * @pdev: Pointer to pdev + * + * Return: return the value of the maximum tx power in the current channel list + * + */ +uint8_t reg_get_max_tx_power(struct wlan_objmgr_pdev *pdev); + /** * reg_set_ignore_fw_reg_offload_ind() - Set if regdb offload indication * needs to be ignored @@ -556,8 +998,33 @@ bool reg_is_6ghz_op_class(struct wlan_objmgr_pdev *pdev, /** * reg_is_6ghz_supported() - Whether 6ghz is supported * - * @pdev: pointer to pdev + * @psoc: pointer to psoc + */ +bool reg_is_6ghz_supported(struct wlan_objmgr_psoc *psoc); + +/** + * reg_get_unii_5g_bitmap() - get unii_5g_bitmap value + * @pdev: pdev pointer + * @bitmap: Pointer to retrieve the unii_5g_bitmap of enum reg_unii_band + * + * Return: QDF_STATUS */ -bool reg_is_6ghz_supported(struct wlan_objmgr_pdev *pdev); +#ifdef DISABLE_UNII_SHARED_BANDS +QDF_STATUS +reg_get_unii_5g_bitmap(struct wlan_objmgr_pdev *pdev, uint8_t *bitmap); +#endif +#ifdef CONFIG_REG_CLIENT +/** + * reg_band_bitmap_to_band_info() - Convert the band_bitmap to a band_info enum. + * Since band_info enum only has combinations for 2G and 5G, 6G is not + * considered in this function. + * @band_bitmap: bitmap on top of reg_wifi_band of bands enabled + * + * Return: BAND_ALL if both 2G and 5G band is enabled + * BAND_2G if 2G is enabled but 5G isn't + * BAND_5G if 5G is enabled but 2G isn't + */ +enum band_info reg_band_bitmap_to_band_info(uint32_t band_bitmap); +#endif #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.c index ef956a5a64d95c237f7e3ee8449febd6597f7a47..44800675e8a318755516ecadaa3e64505ae05dfc 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.c @@ -42,7 +42,8 @@ #define IS_VALID_PSOC_REG_OBJ(psoc_priv_obj) (psoc_priv_obj) #define IS_VALID_PDEV_REG_OBJ(pdev_priv_obj) (pdev_priv_obj) -bool reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint32_t ch) +#ifdef CONFIG_CHAN_NUM_API +bool reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint8_t ch) { enum channel_enum ch_idx; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; @@ -65,6 +66,34 @@ bool reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint32_t ch) return false; } +#endif /* CONFIG_CHAN_NUM_API */ + +#ifdef CONFIG_CHAN_FREQ_API +bool reg_chan_has_dfs_attribute_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + enum channel_enum ch_idx; + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + + ch_idx = reg_get_chan_enum_for_freq(freq); + + if (ch_idx == INVALID_CHANNEL) + return false; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg obj is NULL"); + return false; + } + + if (pdev_priv_obj->cur_chan_list[ch_idx].chan_flags & + REGULATORY_CHAN_RADAR) + return true; + + return false; +} +#endif /* CONFIG_CHAN_FREQ_API */ bool reg_is_world_ctry_code(uint16_t ctry_code) { @@ -276,8 +305,9 @@ QDF_STATUS reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, return QDF_STATUS_SUCCESS; } +#ifdef CONFIG_CHAN_NUM_API bool reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, - uint32_t chan) + uint8_t chan) { enum channel_state ch_state; @@ -286,12 +316,40 @@ bool reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, return (ch_state == CHANNEL_STATE_DFS) || (ch_state == CHANNEL_STATE_DISABLE); } +#endif /* CONFIG_CHAN_NUM_API */ + +#ifdef CONFIG_CHAN_FREQ_API +bool reg_is_passive_or_disable_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + enum channel_state chan_state; + + chan_state = reg_get_channel_state_for_freq(pdev, freq); + + return (chan_state == CHANNEL_STATE_DFS) || + (chan_state == CHANNEL_STATE_DISABLE); +} +#endif /* CONFIG_CHAN_FREQ_API */ #ifdef WLAN_FEATURE_DSRC -bool reg_is_dsrc_chan(struct wlan_objmgr_pdev *pdev, uint32_t chan) +#ifdef CONFIG_CHAN_FREQ_API +bool reg_is_dsrc_freq(qdf_freq_t freq) +{ + if (!REG_IS_5GHZ_FREQ(freq)) + return false; + + if (!(freq >= REG_DSRC_START_FREQ && freq <= REG_DSRC_END_FREQ)) + return false; + + return true; +} +#endif /*CONFIG_CHAN_FREQ_API*/ + +#ifdef CONFIG_CHAN_NUM_API +bool reg_is_dsrc_chan(struct wlan_objmgr_pdev *pdev, uint8_t chan) { struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; - uint32_t freq = 0; + qdf_freq_t freq = 0; pdev_priv_obj = reg_get_pdev_obj(pdev); @@ -310,6 +368,7 @@ bool reg_is_dsrc_chan(struct wlan_objmgr_pdev *pdev, uint32_t chan) return true; } +#endif /* CONFIG_CHAN_NUM_API */ #else @@ -320,17 +379,33 @@ bool reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev) status = reg_get_curr_regdomain(pdev, &cur_reg_dmn); if (status != QDF_STATUS_SUCCESS) { - reg_err("Failed to get reg domain"); + reg_debug_rl("Failed to get reg domain"); return false; } return reg_etsi13_regdmn(cur_reg_dmn.dmn_id_5g); } -bool reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, uint32_t chan) +#ifdef CONFIG_CHAN_FREQ_API +bool reg_is_etsi13_srd_chan_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t freq) +{ + if (!REG_IS_5GHZ_FREQ(freq)) + return false; + + if (!(freq >= REG_ETSI13_SRD_START_FREQ && + freq <= REG_ETSI13_SRD_END_FREQ)) + return false; + + return reg_is_etsi13_regdmn(pdev); +} +#endif /* CONFIG_CHAN_FREQ_API */ + +#ifdef CONFIG_CHAN_NUM_API +bool reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, uint8_t chan) { struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; - uint32_t freq = 0; + qdf_freq_t freq = 0; pdev_priv_obj = reg_get_pdev_obj(pdev); @@ -350,6 +425,7 @@ bool reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, uint32_t chan) return reg_is_etsi13_regdmn(pdev); } +#endif /* CONFIG_CHAN_NUM_API */ bool reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev *pdev) { @@ -373,8 +449,7 @@ bool reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev *pdev) } #endif -QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, - enum band_info band) +QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, uint32_t band_bitmap) { struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; @@ -388,8 +463,8 @@ QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_E_INVAL; } - if (pdev_priv_obj->band_capability == band) { - reg_info("same band %d", band); + if (pdev_priv_obj->band_capability == band_bitmap) { + reg_info("same band %d", band_bitmap); return QDF_STATUS_SUCCESS; } @@ -405,8 +480,8 @@ QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_E_INVAL; } - reg_info("set band_info: %d", band); - pdev_priv_obj->band_capability = band; + reg_info("set band bitmap: %d", band_bitmap); + pdev_priv_obj->band_capability = band_bitmap; reg_compute_pdev_current_chan_list(pdev_priv_obj); @@ -416,11 +491,9 @@ QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, } QDF_STATUS reg_get_band(struct wlan_objmgr_pdev *pdev, - enum band_info *band) + uint32_t *band_bitmap) { - struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; - struct wlan_objmgr_psoc *psoc; pdev_priv_obj = reg_get_pdev_obj(pdev); @@ -429,33 +502,73 @@ QDF_STATUS reg_get_band(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_E_INVAL; } + reg_debug("get band bitmap: %d", pdev_priv_obj->band_capability); + *band_bitmap = pdev_priv_obj->band_capability; + + return QDF_STATUS_SUCCESS; +} + +#ifdef DISABLE_CHANNEL_LIST +QDF_STATUS reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg component is NULL"); + return QDF_STATUS_E_INVAL; + } + psoc = wlan_pdev_get_psoc(pdev); if (!psoc) { reg_err("psoc is NULL"); return QDF_STATUS_E_INVAL; } - psoc_priv_obj = reg_get_psoc_obj(psoc); - if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) { - reg_err("psoc reg component is NULL"); + pdev_priv_obj->disable_cached_channels = false; + reg_compute_pdev_current_chan_list(pdev_priv_obj); + status = reg_send_scheduler_msg_sb(psoc, pdev); + return status; +} + +QDF_STATUS reg_disable_cached_channels(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status; + + pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { + reg_err("pdev reg component is NULL"); return QDF_STATUS_E_INVAL; } - reg_debug("get band_info: %d", pdev_priv_obj->band_capability); - *band = pdev_priv_obj->band_capability; + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + reg_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } - return QDF_STATUS_SUCCESS; + pdev_priv_obj->disable_cached_channels = true; + reg_compute_pdev_current_chan_list(pdev_priv_obj); + status = reg_send_scheduler_msg_sb(psoc, pdev); + return status; } -#ifdef DISABLE_CHANNEL_LIST -QDF_STATUS reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev) +#ifdef CONFIG_CHAN_FREQ_API +QDF_STATUS reg_cache_channel_freq_state(struct wlan_objmgr_pdev *pdev, + uint32_t *channel_list, + uint32_t num_channels) { struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; struct wlan_objmgr_psoc *psoc; - QDF_STATUS status; + uint16_t i, j; pdev_priv_obj = reg_get_pdev_obj(pdev); + if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { reg_err("pdev reg component is NULL"); return QDF_STATUS_E_INVAL; @@ -472,13 +585,36 @@ QDF_STATUS reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev) reg_err("psoc reg component is NULL"); return QDF_STATUS_E_INVAL; } + if (pdev_priv_obj->num_cache_channels > 0) { + pdev_priv_obj->num_cache_channels = 0; + qdf_mem_zero(&pdev_priv_obj->cache_disable_chan_list, + sizeof(pdev_priv_obj->cache_disable_chan_list)); + } - pdev_priv_obj->disable_cached_channels = false; - reg_compute_pdev_current_chan_list(pdev_priv_obj); - status = reg_send_scheduler_msg_sb(psoc, pdev); - return status; + for (i = 0; i < num_channels; i++) { + for (j = 0; j < NUM_CHANNELS; j++) { + if (channel_list[i] == pdev_priv_obj-> + cur_chan_list[j].center_freq) { + pdev_priv_obj-> + cache_disable_chan_list[i].center_freq = + channel_list[i]; + pdev_priv_obj-> + cache_disable_chan_list[i].state = + pdev_priv_obj->cur_chan_list[j].state; + pdev_priv_obj-> + cache_disable_chan_list[i].chan_flags = + pdev_priv_obj-> + cur_chan_list[j].chan_flags; + } + } + } + pdev_priv_obj->num_cache_channels = num_channels; + + return QDF_STATUS_SUCCESS; } +#endif /* CONFIG_CHAN_FREQ_API */ +#ifdef CONFIG_CHAN_NUM_API QDF_STATUS reg_cache_channel_state(struct wlan_objmgr_pdev *pdev, uint32_t *channel_list, uint32_t num_channels) @@ -533,12 +669,7 @@ QDF_STATUS reg_cache_channel_state(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } - -void set_disable_channel_state( - struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) -{ - pdev_priv_obj->disable_cached_channels = pdev_priv_obj->sap_state; -} +#endif /* CONFIG_CHAN_NUM_API */ #endif #ifdef CONFIG_REG_CLIENT @@ -668,6 +799,8 @@ QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc, config_vars.enable_srd_chan_in_master_mode; psoc_priv_obj->enable_11d_in_world_mode = config_vars.enable_11d_in_world_mode; + psoc_priv_obj->retain_nol_across_regdmn_update = + config_vars.retain_nol_across_regdmn_update; status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID); if (QDF_IS_STATUS_ERROR(status)) { @@ -682,7 +815,19 @@ QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc, return status; } -bool reg_is_disable_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan) +#ifdef CONFIG_CHAN_FREQ_API +bool reg_is_disable_for_freq(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq) +{ + enum channel_state ch_state; + + ch_state = reg_get_channel_state_for_freq(pdev, freq); + + return ch_state == CHANNEL_STATE_DISABLE; +} +#endif /* CONFIG_CHAN_FREQ_API */ + +#ifdef CONFIG_CHAN_NUM_API +bool reg_is_disable_ch(struct wlan_objmgr_pdev *pdev, uint8_t chan) { enum channel_state ch_state; @@ -690,6 +835,7 @@ bool reg_is_disable_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan) return ch_state == CHANNEL_STATE_DISABLE; } +#endif /* CONFIG_CHAN_NUM_API */ bool reg_is_regdb_offloaded(struct wlan_objmgr_psoc *psoc) { diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.h index 1ab8b947103693e4492ae8187c30e64bce15307e..91bd0cbaaab440cb419917a61e68bd25fdabc965 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -33,6 +33,7 @@ #define REG_ETSI13_SRD_START_FREQ 5745 #define REG_ETSI13_SRD_END_FREQ 5865 +#ifdef CONFIG_CHAN_NUM_API #define REG_IS_CHANNEL_VALID_5G_SBS(curchan, newchan) \ ((curchan) > (newchan) ? \ REG_CH_TO_FREQ(reg_get_chan_enum(curchan)) \ @@ -41,6 +42,7 @@ REG_CH_TO_FREQ(reg_get_chan_enum(newchan)) \ - REG_CH_TO_FREQ(reg_get_chan_enum(curchan)) \ > REG_SBS_SEPARATION_THRESHOLD) +#endif /* CONFIG_LEGACY_REG_API */ /** * reg_is_world_ctry_code() - Check if the given country code is WORLD regdomain @@ -50,7 +52,7 @@ */ bool reg_is_world_ctry_code(uint16_t ctry_code); -#ifdef CONFIG_REG_CLIENT +#if defined(CONFIG_REG_CLIENT) && defined(CONFIG_CHAN_NUM_API) /** * reg_chan_has_dfs_attribute() - check channel has dfs attribue or not * @ch: channel number. @@ -59,50 +61,158 @@ bool reg_is_world_ctry_code(uint16_t ctry_code); * * Return: true if chan is dfs, otherwise false */ -bool reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint32_t ch); +bool reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint8_t ch); /** - * reg_set_band() - Sets the band information for the PDEV - * @pdev: The physical dev to set the band for - * @band: The set band parameters to configure for the physical device + * reg_is_passive_or_disable_ch() - Check if the given channel is passive or + * disabled. + * @pdev: Pointer to physical dev + * @chan: Channel number * - * Return: QDF_STATUS + * Return: true if channel is passive or disabled, else false. */ -QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, enum band_info band); +bool reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, uint8_t chan); /** - * reg_get_band() - Get the band information for the PDEV - * @pdev: The physical dev to get the band for - * @band: The band parameters of the physical device + * reg_is_disable_ch() - Check if the given channel in disable state + * @pdev: Pointer to pdev + * @chan: channel number * - * Return: QDF_STATUS + * Return: True if channel state is disabled, else false + */ +bool reg_is_disable_ch(struct wlan_objmgr_pdev *pdev, uint8_t chan); +#else +static inline bool +reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint8_t ch) +{ + return false; +} + +static inline bool +reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, uint8_t chan) +{ + return false; +} + +static inline bool +reg_is_disable_ch(struct wlan_objmgr_pdev *pdev, uint8_t chan) +{ + return false; +} +#endif /* defined(CONFIG_REG_CLIENT) && defined(CONFIG_CHAN_NUM_API) */ + +#if defined(CONFIG_REG_CLIENT) && defined(CONFIG_CHAN_FREQ_API) +/** + * reg_chan_has_dfs_attribute_for_freq() - check channel frequency has dfs + * attribue or not + * @freq: channel frequency. + * + * This API gets initial dfs attribute flag of the channel frequency from + * regdomain + * + * Return: true if channel frequency is dfs, otherwise false + */ +bool reg_chan_has_dfs_attribute_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); +/** + * reg_is_passive_or_disable_for_freq() - Check if the given channel is + * passive or disabled. + * @pdev: Pointer to physical dev + * @chan: Channel frequency + * + * Return: true if channel frequency is passive or disabled, else false. + */ +bool reg_is_passive_or_disable_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); +/** + * reg_is_disable_for_freq() - Check if the given channel frequency in + * disable state + * @pdev: Pointer to pdev + * @freq: Channel frequency + * + * Return: True if channel state is disabled, else false */ -QDF_STATUS reg_get_band(struct wlan_objmgr_pdev *pdev, enum band_info *band); +bool reg_is_disable_for_freq(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq); +#else +static inline bool +reg_chan_has_dfs_attribute_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + return false; +} + +static inline bool +reg_is_passive_or_disable_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + return false; +} + +static inline bool +reg_is_disable_for_freq(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq) +{ + return false; +} +#endif /* defined(CONFIG_REG_CLIENT) && defined(CONFIG_CHAN_FREQ_API) */ #ifdef DISABLE_CHANNEL_LIST /** - * reg_restore_cached_channels() - Cache the current state of the channels + * reg_disable_cached_channels() - Disable cached channels + * @pdev: The physical dev to cache the channels for + */ +QDF_STATUS reg_disable_cached_channels(struct wlan_objmgr_pdev *pdev); +/** + * reg_restore_cached_channels() - Restore disabled cached channels * @pdev: The physical dev to cache the channels for */ QDF_STATUS reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev); +#else +static inline +QDF_STATUS reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev) +{ + return QDF_STATUS_SUCCESS; +} +static inline +QDF_STATUS reg_disable_cached_channels(struct wlan_objmgr_pdev *pdev) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* DISABLE_CHANNEL_LIST */ +#if defined(DISABLE_CHANNEL_LIST) && defined(CONFIG_CHAN_FREQ_API) /** - * reg_cache_channel_state() - Cache the current state of the channels + * reg_cache_channel_freq_state() - Cache the current state of the channels + * based on the channel center frequency * @pdev: The physical dev to cache the channels for * @channel_list: List of the channels for which states needs to be cached * @num_channels: Number of channels in the list * */ -QDF_STATUS reg_cache_channel_state(struct wlan_objmgr_pdev *pdev, - uint32_t *channel_list, - uint32_t num_channels); +QDF_STATUS reg_cache_channel_freq_state(struct wlan_objmgr_pdev *pdev, + uint32_t *channel_list, + uint32_t num_channels); #else static inline -QDF_STATUS reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev) +QDF_STATUS reg_cache_channel_freq_state(struct wlan_objmgr_pdev *pdev, + uint32_t *channel_list, + uint32_t num_channels) { return QDF_STATUS_SUCCESS; } +#endif /* defined(DISABLE_CHANNEL_LIST) && defined(CONFIG_CHAN_FREQ_API) */ +#if defined(DISABLE_CHANNEL_LIST) && defined(CONFIG_CHAN_NUM_API) +/** + * reg_cache_channel_state() - Cache the current state of the channels + * @pdev: The physical dev to cache the channels for + * @channel_list: List of the channels for which states needs to be cached + * @num_channels: Number of channels in the list + * + */ +QDF_STATUS reg_cache_channel_state(struct wlan_objmgr_pdev *pdev, + uint32_t *channel_list, + uint32_t num_channels); +#else static inline QDF_STATUS reg_cache_channel_state(struct wlan_objmgr_pdev *pdev, uint32_t *channel_list, @@ -110,7 +220,26 @@ QDF_STATUS reg_cache_channel_state(struct wlan_objmgr_pdev *pdev, { return QDF_STATUS_SUCCESS; } -#endif +#endif /* defined (DISABLE_CHANNEL_LIST) && defined(CONFIG_CHAN_NUM_API) */ + +#ifdef CONFIG_REG_CLIENT +/** + * reg_set_band() - Sets the band information for the PDEV + * @pdev: The physical dev to set the band for + * @band_bitmap: The set band parameters to configure for the physical device + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_set_band(struct wlan_objmgr_pdev *pdev, uint32_t band_bitmap); + +/** + * reg_get_band() - Get the band information for the PDEV + * @pdev: The physical dev to get the band for + * @band_bitmap: The band parameters of the physical device + * + * Return: QDF_STATUS + */ +QDF_STATUS reg_get_band(struct wlan_objmgr_pdev *pdev, uint32_t *band_bitmap); /** * reg_set_fcc_constraint() - Apply fcc constraints on channels 12/13 @@ -199,25 +328,6 @@ QDF_STATUS reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, const uint8_t *country_alpha2, enum country_src source); -/** - * reg_is_passive_or_disable_ch() - Check if the given channel is passive or - * disabled. - * @pdev: Pointer to physical dev - * @chan: Channel number - * - * Return: true if channel is passive or disabled, else false. - */ -bool reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan); - -/** - * reg_is_disable_ch() - Check if the given channel in disable state - * @pdev: Pointer to pdev - * @chan: channel number - * - * Return: True if channel state is disabled, else false - */ -bool reg_is_disable_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan); - /** * reg_set_config_vars () - set configration variables * @psoc: psoc ptr @@ -308,13 +418,6 @@ bool reg_ignore_default_country(struct wlan_regulatory_psoc_priv_obj *soc_reg, struct cur_regulatory_info *regulat_info); #else - -static inline bool reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, - uint32_t ch) -{ - return false; -} - static inline QDF_STATUS reg_read_current_country(struct wlan_objmgr_psoc *psoc, uint8_t *country_code) { @@ -349,18 +452,6 @@ static inline QDF_STATUS reg_get_domain_from_country_code( return QDF_STATUS_SUCCESS; } -static inline bool reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, - uint32_t chan) -{ - return false; -} - -static inline bool reg_is_disable_ch(struct wlan_objmgr_pdev *pdev, - uint32_t chan) -{ - return false; -} - static inline QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc, struct reg_config_vars config_vars) { @@ -427,6 +518,18 @@ bool reg_get_fcc_constraint(struct wlan_objmgr_pdev *pdev, uint32_t freq) #endif #if defined(WLAN_FEATURE_DSRC) && defined(CONFIG_REG_CLIENT) +/** + * reg_is_dsrc_freq () - Checks the channel frequency is DSRC or not + * @freq: Channel center frequency + * @pdev: pdev ptr + * + * Return: true or false + */ +#ifdef CONFIG_CHAN_FREQ_API +bool reg_is_dsrc_freq(qdf_freq_t freq); +#endif /* CONFIG_CHAN_FREQ_API*/ + +#ifdef CONFIG_CHAN_NUM_API /** * reg_is_dsrc_chan () - Checks the channel for DSRC or not * @chan: channel @@ -434,10 +537,11 @@ bool reg_get_fcc_constraint(struct wlan_objmgr_pdev *pdev, uint32_t freq) * * Return: true or false */ -bool reg_is_dsrc_chan(struct wlan_objmgr_pdev *pdev, uint32_t chan); +bool reg_is_dsrc_chan(struct wlan_objmgr_pdev *pdev, uint8_t chan); +#endif /* CONFIG_CHAN_NUM_API */ static inline bool reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, - uint32_t chan) + uint8_t chan) { return false; } @@ -447,6 +551,20 @@ static inline bool reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev) return false; } +/** + * reg_is_etsi13_srd_chan_for_freq() - Checks the channel for ETSI13 srd ch + * frequency or not + * @freq: Channel center frequency + * @pdev: pdev ptr + * + * Return: true or false + */ +static inline bool +reg_is_etsi13_srd_chan_for_freq(struct wlan_objmgr_pdev *pdev, uint16_t freq) +{ + return false; +} + static inline bool reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev *pdev) { @@ -454,11 +572,21 @@ reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev *pdev) } #elif defined(CONFIG_REG_CLIENT) static inline bool reg_is_dsrc_chan(struct wlan_objmgr_pdev *pdev, - uint32_t chan) + uint8_t chan) +{ + return false; +} + +static inline bool reg_is_dsrc_freq(qdf_freq_t freq) { return false; } +#ifdef CONFIG_CHAN_FREQ_API +bool reg_is_etsi13_srd_chan_for_freq(struct wlan_objmgr_pdev + *pdev, uint16_t freq); +#endif /*CONFIG_CHAN_FREQ_API */ + /** * reg_is_etsi13_regdmn () - Checks if the current reg domain is ETSI13 or not * @pdev: pdev ptr @@ -467,6 +595,7 @@ static inline bool reg_is_dsrc_chan(struct wlan_objmgr_pdev *pdev, */ bool reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev); +#ifdef CONFIG_CHAN_NUM_API /** * reg_is_etsi13_srd_chan () - Checks the channel for ETSI13 srd ch or not * @chan: channel @@ -474,7 +603,8 @@ bool reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev); * * Return: true or false */ -bool reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, uint32_t chan); +bool reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, uint8_t chan); +#endif /* CONFIG_CHAN_NUM_API */ /** * reg_is_etsi13_srd_chan_allowed_master_mode() - Checks if regdmn is ETSI13 @@ -487,7 +617,19 @@ bool reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, uint32_t chan); bool reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev *pdev); #else static inline bool reg_is_dsrc_chan(struct wlan_objmgr_pdev *pdev, - uint32_t chan) + uint8_t chan) +{ + return false; +} + +static inline bool reg_is_dsrc_freq(qdf_freq_t freq) +{ + return false; +} + +static inline +bool reg_is_etsi13_srd_chan_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t freq) { return false; } @@ -504,23 +646,10 @@ reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev *pdev) } static inline bool reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, - uint32_t chan) + uint8_t chan) { return false; } #endif -#if defined(DISABLE_CHANNEL_LIST) && defined(CONFIG_REG_CLIENT) -/** - * set_disable_channel_state() - Set disable channel state flag - * @pdev_priv_obj: Pointer to pdev object - */ -void set_disable_channel_state( - struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj); -#else -static inline void set_disable_channel_state( - struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj) -{ -} -#endif #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/reg_services_public_struct.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/reg_services_public_struct.h index 6dd2eea3ee6db6e997dd1b41096a8b06aaca82ce..2e3f55ee1b592bd5e644a93933b76f45f28f95f2 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/reg_services_public_struct.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/reg_services_public_struct.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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,12 +25,19 @@ #define __REG_SERVICES_PUBLIC_STRUCT_H_ #define REG_SBS_SEPARATION_THRESHOLD 100 + +#ifdef CONFIG_BAND_6GHZ +#define REG_MAX_CHANNELS_PER_OPERATING_CLASS 70 +#else #define REG_MAX_CHANNELS_PER_OPERATING_CLASS 25 +#endif + #define REG_MAX_SUPP_OPER_CLASSES 32 #define REG_MAX_CHAN_CHANGE_CBKS 30 +#define REG_INVALID_TXPOWER 255 #define MAX_STA_VDEV_CNT 4 #define INVALID_VDEV_ID 0xFF -#define INVALID_CHANNEL_NUM 0xBAD +#define INVALID_CHANNEL_NUM 0x0 #define CH_AVOID_MAX_RANGE 4 #define REG_ALPHA2_LEN 2 #define MAX_REG_RULES 10 @@ -40,6 +47,7 @@ #define REGULATORY_CHAN_RADAR BIT(3) #define REGULATORY_CHAN_NO_OFDM BIT(6) #define REGULATORY_CHAN_INDOOR_ONLY BIT(9) +#define REGULATORY_CHAN_AFC BIT(13) #define REGULATORY_CHAN_NO_HT40 BIT(4) #define REGULATORY_CHAN_NO_80MHZ BIT(7) @@ -55,6 +63,10 @@ #define REGULATORY_PHYMODE_NO11AC BIT(4) #define REGULATORY_PHYMODE_NO11AX BIT(5) +#define BW_80_MHZ 80 +#define BW_160_MHZ 160 +#define BW_40_MHZ 40 + /** * enum dfs_reg - DFS region * @DFS_UNINIT_REGION: un-initialized region @@ -63,8 +75,12 @@ * @DFS_MKK_REGION: MKK region * @DFS_CN_REGION: China region * @DFS_KR_REGION: Korea region + * @DFS_MKK_REGION: MKKN region + * that supports updated W53 RADAR pattern + * detection. * @DFS_UNDEF_REGION: Undefined region */ + enum dfs_reg { DFS_UNINIT_REGION = 0, DFS_FCC_REGION = 1, @@ -72,6 +88,7 @@ enum dfs_reg { DFS_MKK_REGION = 3, DFS_CN_REGION = 4, DFS_KR_REGION = 5, + DFS_MKKN_REGION = 6, DFS_UNDEF_REGION = 0xFFFF, }; @@ -87,224 +104,7 @@ enum op_class_table_num { OP_CLASS_JAPAN, OP_CLASS_GLOBAL }; -#ifdef CONFIG_LEGACY_CHAN_ENUM -/** - * enum channel_enum - channel enumeration - * @CHAN_ENUM_1: channel number 1 - * @CHAN_ENUM_2: channel number 2 - * @CHAN_ENUM_3: channel number 3 - * @CHAN_ENUM_4: channel number 4 - * @CHAN_ENUM_5: channel number 5 - * @CHAN_ENUM_6: channel number 6 - * @CHAN_ENUM_7: channel number 7 - * @CHAN_ENUM_8: channel number 8 - * @CHAN_ENUM_9: channel number 9 - * @CHAN_ENUM_10: channel number 10 - * @CHAN_ENUM_11: channel number 11 - * @CHAN_ENUM_12: channel number 12 - * @CHAN_ENUM_13: channel number 13 - * @CHAN_ENUM_14: channel number 14 - * @CHAN_ENUM_183: channel number 183 - * @CHAN_ENUM_184: channel number 184 - * @CHAN_ENUM_185: channel number 185 - * @CHAN_ENUM_187: channel number 187 - * @CHAN_ENUM_188: channel number 188 - * @CHAN_ENUM_189: channel number 189 - * @CHAN_ENUM_192: channel number 192 - * @CHAN_ENUM_196: channel number 196 - * @CHAN_ENUM_36: channel number 36 - * @CHAN_ENUM_40: channel number 40 - * @CHAN_ENUM_44: channel number 44 - * @CHAN_ENUM_48: channel number 48 - * @CHAN_ENUM_52: channel number 52 - * @CHAN_ENUM_56: channel number 56 - * @CHAN_ENUM_60: channel number 60 - * @CHAN_ENUM_64: channel number 64 - * @CHAN_ENUM_100: channel number 100 - * @CHAN_ENUM_104: channel number 104 - * @CHAN_ENUM_108: channel number 108 - * @CHAN_ENUM_112: channel number 112 - * @CHAN_ENUM_116: channel number 116 - * @CHAN_ENUM_120: channel number 120 - * @CHAN_ENUM_124: channel number 124 - * @CHAN_ENUM_128: channel number 128 - * @CHAN_ENUM_132: channel number 132 - * @CHAN_ENUM_136: channel number 136 - * @CHAN_ENUM_140: channel number 140 - * @CHAN_ENUM_144: channel number 144 - * @CHAN_ENUM_149: channel number 149 - * @CHAN_ENUM_153: channel number 153 - * @CHAN_ENUM_157: channel number 157 - * @CHAN_ENUM_161: channel number 161 - * @CHAN_ENUM_165: channel number 165 - * @CHAN_ENUM_169: channel number 169 - * @CHAN_ENUM_170: channel number 170 - * @CHAN_ENUM_171: channel number 171 - * @CHAN_ENUM_172: channel number 172 - * @CHAN_ENUM_173: channel number 173 - * @CHAN_ENUM_174: channel number 174 - * @CHAN_ENUM_175: channel number 175 - * @CHAN_ENUM_176: channel number 176 - * @CHAN_ENUM_177: channel number 177 - * @CHAN_ENUM_178: channel number 178 - * @CHAN_ENUM_179: channel number 179 - * @CHAN_ENUM_180: channel number 180 - * @CHAN_ENUM_181: channel number 181 - * @CHAN_ENUM_182: channel number 182 - * @CHAN_ENUM_183: channel number 183 - * @CHAN_ENUM_184: channel number 184 - */ - -#ifdef WLAN_FEATURE_DSRC -enum channel_enum { - CHAN_ENUM_1, - CHAN_ENUM_2, - CHAN_ENUM_3, - CHAN_ENUM_4, - CHAN_ENUM_5, - CHAN_ENUM_6, - CHAN_ENUM_7, - CHAN_ENUM_8, - CHAN_ENUM_9, - CHAN_ENUM_10, - CHAN_ENUM_11, - CHAN_ENUM_12, - CHAN_ENUM_13, - CHAN_ENUM_14, - - CHAN_ENUM_36, - CHAN_ENUM_40, - CHAN_ENUM_44, - CHAN_ENUM_48, - CHAN_ENUM_52, - CHAN_ENUM_56, - CHAN_ENUM_60, - CHAN_ENUM_64, - - CHAN_ENUM_100, - CHAN_ENUM_104, - CHAN_ENUM_108, - CHAN_ENUM_112, - CHAN_ENUM_116, - CHAN_ENUM_120, - CHAN_ENUM_124, - CHAN_ENUM_128, - CHAN_ENUM_132, - CHAN_ENUM_136, - CHAN_ENUM_140, - CHAN_ENUM_144, - - CHAN_ENUM_149, - CHAN_ENUM_153, - CHAN_ENUM_157, - CHAN_ENUM_161, - CHAN_ENUM_165, - - CHAN_ENUM_170, - CHAN_ENUM_171, - CHAN_ENUM_172, - CHAN_ENUM_173, - CHAN_ENUM_174, - CHAN_ENUM_175, - CHAN_ENUM_176, - CHAN_ENUM_177, - CHAN_ENUM_178, - CHAN_ENUM_179, - CHAN_ENUM_180, - CHAN_ENUM_181, - CHAN_ENUM_182, - CHAN_ENUM_183, - CHAN_ENUM_184, - - NUM_CHANNELS, - - MIN_24GHZ_CHANNEL = CHAN_ENUM_1, - MAX_24GHZ_CHANNEL = CHAN_ENUM_14, - NUM_24GHZ_CHANNELS = (MAX_24GHZ_CHANNEL - MIN_24GHZ_CHANNEL + 1), - - MIN_49GHZ_CHANNEL = INVALID_CHANNEL_NUM, - MAX_49GHZ_CHANNEL = INVALID_CHANNEL_NUM - 1, - NUM_49GHZ_CHANNELS = MAX_49GHZ_CHANNEL - MIN_49GHZ_CHANNEL + 1, - - MIN_5GHZ_CHANNEL = CHAN_ENUM_36, - MAX_5GHZ_CHANNEL = CHAN_ENUM_184, - NUM_5GHZ_CHANNELS = (MAX_5GHZ_CHANNEL - MIN_5GHZ_CHANNEL + 1), - - MIN_DSRC_CHANNEL = CHAN_ENUM_170, - MAX_DSRC_CHANNEL = CHAN_ENUM_184, - NUM_DSRC_CHANNELS = (MAX_DSRC_CHANNEL - MIN_DSRC_CHANNEL + 1), - - INVALID_CHANNEL = 0xBAD, -}; - -#else -enum channel_enum { - CHAN_ENUM_1, - CHAN_ENUM_2, - CHAN_ENUM_3, - CHAN_ENUM_4, - CHAN_ENUM_5, - CHAN_ENUM_6, - CHAN_ENUM_7, - CHAN_ENUM_8, - CHAN_ENUM_9, - CHAN_ENUM_10, - CHAN_ENUM_11, - CHAN_ENUM_12, - CHAN_ENUM_13, - CHAN_ENUM_14, - - CHAN_ENUM_36, - CHAN_ENUM_40, - CHAN_ENUM_44, - CHAN_ENUM_48, - CHAN_ENUM_52, - CHAN_ENUM_56, - CHAN_ENUM_60, - CHAN_ENUM_64, - - CHAN_ENUM_100, - CHAN_ENUM_104, - CHAN_ENUM_108, - CHAN_ENUM_112, - CHAN_ENUM_116, - CHAN_ENUM_120, - CHAN_ENUM_124, - CHAN_ENUM_128, - CHAN_ENUM_132, - CHAN_ENUM_136, - CHAN_ENUM_140, - CHAN_ENUM_144, - - CHAN_ENUM_149, - CHAN_ENUM_153, - CHAN_ENUM_157, - CHAN_ENUM_161, - CHAN_ENUM_165, - CHAN_ENUM_169, - CHAN_ENUM_173, - - NUM_CHANNELS, - - MIN_24GHZ_CHANNEL = CHAN_ENUM_1, - MAX_24GHZ_CHANNEL = CHAN_ENUM_14, - NUM_24GHZ_CHANNELS = (MAX_24GHZ_CHANNEL - MIN_24GHZ_CHANNEL + 1), - - MIN_49GHZ_CHANNEL = INVALID_CHANNEL_NUM, - MAX_49GHZ_CHANNEL = INVALID_CHANNEL_NUM - 1, - NUM_49GHZ_CHANNELS = MAX_49GHZ_CHANNEL - MIN_49GHZ_CHANNEL + 1, - - MIN_5GHZ_CHANNEL = CHAN_ENUM_36, - - MAX_5GHZ_CHANNEL = CHAN_ENUM_173, - - NUM_5GHZ_CHANNELS = (MAX_5GHZ_CHANNEL - MIN_5GHZ_CHANNEL + 1), - INVALID_CHANNEL = 0xBAD, -}; -#endif /* WLAN_FEATURE_DSRC */ - -#else /* CONFIG_LEGACY_CHAN_ENUM */ /** * enum channel_enum - channel enumeration * @CHAN_ENUM_2412: channel with freq 2412 @@ -404,6 +204,65 @@ enum channel_enum { * @CHAN_ENUM_5910: channel with freq 5910 * @CHAN_ENUM_5915: channel with freq 5915 * @CHAN_ENUM_5920: channel with freq 5920 + * @CHAN_ENUM_5945: channel with freq 5945 + * @CHAN_ENUM_5965: channel with freq 5965 + * @CHAN_ENUM_5985: channel with freq 5985 + * @CHAN_ENUM_6005: channel with freq 6005 + * @CHAN_ENUM_6025: channel with freq 6025 + * @CHAN_ENUM_6045: channel with freq 6045 + * @CHAN_ENUM_6065: channel with freq 6065 + * @CHAN_ENUM_6085: channel with freq 6085 + * @CHAN_ENUM_6105: channel with freq 6105 + * @CHAN_ENUM_6125: channel with freq 6125 + * @CHAN_ENUM_6145: channel with freq 6145 + * @CHAN_ENUM_6165: channel with freq 6165 + * @CHAN_ENUM_6185: channel with freq 6185 + * @CHAN_ENUM_6205: channel with freq 6205 + * @CHAN_ENUM_6225: channel with freq 6225 + * @CHAN_ENUM_6245: channel with freq 6245 + * @CHAN_ENUM_6265: channel with freq 6265 + * @CHAN_ENUM_6285: channel with freq 6285 + * @CHAN_ENUM_6305: channel with freq 6305 + * @CHAN_ENUM_6325: channel with freq 6325 + * @CHAN_ENUM_6345: channel with freq 6345 + * @CHAN_ENUM_6365: channel with freq 6365 + * @CHAN_ENUM_6385: channel with freq 6385 + * @CHAN_ENUM_6405: channel with freq 6405 + * @CHAN_ENUM_6425: channel with freq 6425 + * @CHAN_ENUM_6445: channel with freq 6445 + * @CHAN_ENUM_6465: channel with freq 6465 + * @CHAN_ENUM_6485: channel with freq 6485 + * @CHAN_ENUM_6505: channel with freq 6505 + * @CHAN_ENUM_6525: channel with freq 6525 + * @CHAN_ENUM_6545: channel with freq 6545 + * @CHAN_ENUM_6565: channel with freq 6565 + * @CHAN_ENUM_6585: channel with freq 6585 + * @CHAN_ENUM_6605: channel with freq 6605 + * @CHAN_ENUM_6625: channel with freq 6625 + * @CHAN_ENUM_6645: channel with freq 6645 + * @CHAN_ENUM_6665: channel with freq 6665 + * @CHAN_ENUM_6685: channel with freq 6685 + * @CHAN_ENUM_6705: channel with freq 6705 + * @CHAN_ENUM_6725: channel with freq 6725 + * @CHAN_ENUM_6745: channel with freq 6745 + * @CHAN_ENUM_6765: channel with freq 6765 + * @CHAN_ENUM_6785: channel with freq 6785 + * @CHAN_ENUM_6805: channel with freq 6805 + * @CHAN_ENUM_6825: channel with freq 6825 + * @CHAN_ENUM_6845: channel with freq 6845 + * @CHAN_ENUM_6865: channel with freq 6865 + * @CHAN_ENUM_6885: channel with freq 6885 + * @CHAN_ENUM_6905: channel with freq 6905 + * @CHAN_ENUM_6925: channel with freq 6925 + * @CHAN_ENUM_6945: channel with freq 6945 + * @CHAN_ENUM_6965: channel with freq 6965 + * @CHAN_ENUM_6985: channel with freq 6985 + * @CHAN_ENUM_7005: channel with freq 7005 + * @CHAN_ENUM_7025: channel with freq 7025 + * @CHAN_ENUM_7045: channel with freq 7045 + * @CHAN_ENUM_7065: channel with freq 7065 + * @CHAN_ENUM_7085: channel with freq 7085 + * @CHAN_ENUM_7105: channel with freq 7105 */ enum channel_enum { CHAN_ENUM_2412, @@ -506,6 +365,67 @@ enum channel_enum { CHAN_ENUM_5910, CHAN_ENUM_5915, CHAN_ENUM_5920, +#ifdef CONFIG_BAND_6GHZ + CHAN_ENUM_5945, + CHAN_ENUM_5965, + CHAN_ENUM_5985, + CHAN_ENUM_6005, + CHAN_ENUM_6025, + CHAN_ENUM_6045, + CHAN_ENUM_6065, + CHAN_ENUM_6085, + CHAN_ENUM_6105, + CHAN_ENUM_6125, + CHAN_ENUM_6145, + CHAN_ENUM_6165, + CHAN_ENUM_6185, + CHAN_ENUM_6205, + CHAN_ENUM_6225, + CHAN_ENUM_6245, + CHAN_ENUM_6265, + CHAN_ENUM_6285, + CHAN_ENUM_6305, + CHAN_ENUM_6325, + CHAN_ENUM_6345, + CHAN_ENUM_6365, + CHAN_ENUM_6385, + CHAN_ENUM_6405, + CHAN_ENUM_6425, + CHAN_ENUM_6445, + CHAN_ENUM_6465, + CHAN_ENUM_6485, + CHAN_ENUM_6505, + CHAN_ENUM_6525, + CHAN_ENUM_6545, + CHAN_ENUM_6565, + CHAN_ENUM_6585, + CHAN_ENUM_6605, + CHAN_ENUM_6625, + CHAN_ENUM_6645, + CHAN_ENUM_6665, + CHAN_ENUM_6685, + CHAN_ENUM_6705, + CHAN_ENUM_6725, + CHAN_ENUM_6745, + CHAN_ENUM_6765, + CHAN_ENUM_6785, + CHAN_ENUM_6805, + CHAN_ENUM_6825, + CHAN_ENUM_6845, + CHAN_ENUM_6865, + CHAN_ENUM_6885, + CHAN_ENUM_6905, + CHAN_ENUM_6925, + CHAN_ENUM_6945, + CHAN_ENUM_6965, + CHAN_ENUM_6985, + CHAN_ENUM_7005, + CHAN_ENUM_7025, + CHAN_ENUM_7045, + CHAN_ENUM_7065, + CHAN_ENUM_7085, + CHAN_ENUM_7105, +#endif /* CONFIG_BAND_6GHZ */ NUM_CHANNELS, @@ -526,9 +446,30 @@ enum channel_enum { NUM_DSRC_CHANNELS = (MAX_DSRC_CHANNEL - MIN_DSRC_CHANNEL + 1), INVALID_CHANNEL = 0xBAD, -}; + +#ifdef DISABLE_UNII_SHARED_BANDS + MIN_UNII_1_BAND_CHANNEL = CHAN_ENUM_5180, + MAX_UNII_1_BAND_CHANNEL = CHAN_ENUM_5240, + NUM_UNII_1_BAND_CHANNELS = (MAX_UNII_1_BAND_CHANNEL - + MIN_UNII_1_BAND_CHANNEL + 1), + + MIN_UNII_2A_BAND_CHANNEL = CHAN_ENUM_5260, + MAX_UNII_2A_BAND_CHANNEL = CHAN_ENUM_5320, + NUM_UNII_2A_BAND_CHANNELS = (MAX_UNII_2A_BAND_CHANNEL - + MIN_UNII_2A_BAND_CHANNEL + 1), #endif +#ifdef CONFIG_BAND_6GHZ + MIN_6GHZ_CHANNEL = CHAN_ENUM_5945, + MAX_6GHZ_CHANNEL = CHAN_ENUM_7105, + NUM_6GHZ_CHANNELS = (MAX_6GHZ_CHANNEL - MIN_6GHZ_CHANNEL + 1), +#else + MIN_6GHZ_CHANNEL = INVALID_CHANNEL, + MAX_6GHZ_CHANNEL = INVALID_CHANNEL, + NUM_6GHZ_CHANNELS = 0, +#endif /* CONFIG_BAND_6GHZ */ +}; + /** * enum channel_state - channel state * @CHANNEL_STATE_DISABLE: disabled state @@ -585,23 +526,29 @@ enum ctl_value { * struct ch_params * @ch_width: channel width * @sec_ch_offset: secondary channel offset - * @center_freq_seg0: center freq for segment 0 - * @center_freq_seg1: center freq for segment 1 + * @center_freq_seg0: channel number for segment 0 + * @center_freq_seg1: channel number segment 1 + * @mhz_freq_seg0: Center frequency for segment 0 + * @mhz_freq_seg1: Center frequency for segment 1 */ struct ch_params { enum phy_ch_width ch_width; uint8_t sec_ch_offset; uint8_t center_freq_seg0; uint8_t center_freq_seg1; + qdf_freq_t mhz_freq_seg0; + qdf_freq_t mhz_freq_seg1; }; /** * struct channel_power + * @center_freq: Channel Center Frequency * @chan_num: channel number * @tx_power: TX power */ struct channel_power { - uint32_t chan_num; + qdf_freq_t center_freq; + uint8_t chan_num; uint32_t tx_power; }; @@ -622,20 +569,64 @@ enum offset_t { BW_INVALID = 0xFF }; +/** + * enum behav_limit - behavior limit + * @BEHAV_NONE: none + * @BEHAV_BW40_LOW_PRIMARY: BW40 low primary + * @BEHAV_BW40_HIGH_PRIMARY: BW40 high primary + * @BEHAV_BW80_PLUS: BW 80 plus + * @BEHAV_INVALID: invalid behavior + */ +enum behav_limit { + BEHAV_NONE, + BEHAV_BW40_LOW_PRIMARY, + BEHAV_BW40_HIGH_PRIMARY, + BEHAV_BW80_PLUS, + BEHAV_INVALID = 0xFF +}; + /** * struct reg_dmn_op_class_map_t: operating class * @op_class: operating class number - * @ch_spacing: channel spacing + * @chan_spacing: channel spacing * @offset: offset + * @behav_limit: OR of bitmaps of enum behav_limit + * @start_freq: starting frequency * @channels: channel set */ struct reg_dmn_op_class_map_t { uint8_t op_class; - uint8_t ch_spacing; + uint8_t chan_spacing; enum offset_t offset; + uint16_t behav_limit; + qdf_freq_t start_freq; uint8_t channels[REG_MAX_CHANNELS_PER_OPERATING_CLASS]; }; +/** + * struct regdmn_ap_cap_opclass_t: AP Cap operation class table + * @op_class: operating class number + * @ch_width: channel width in MHz + * @start_freq: Starting Frequency in MHz + * @behav_limit: OR of bitmaps of enum behav_limit + * @max_tx_pwr_dbm: Maximum tx power in dbm + * @num_supported_chan: Number of supported channels + * @num_non_supported_chan: Number of non-supported channels + * @sup_chan_list: Array of supported channel numbers + * @non_sup_chan_list: Array of non supported channel numbers + */ +struct regdmn_ap_cap_opclass_t { + uint8_t op_class; + uint8_t ch_width; + qdf_freq_t start_freq; + uint16_t behav_limit; + uint8_t max_tx_pwr_dbm; + uint8_t num_supported_chan; + uint8_t num_non_supported_chan; + uint8_t sup_chan_list[REG_MAX_CHANNELS_PER_OPERATING_CLASS]; + uint8_t non_sup_chan_list[REG_MAX_CHANNELS_PER_OPERATING_CLASS]; +}; + /** * struct reg_dmn_supp_op_classes: operating classes * @num_classes: number of classes @@ -713,8 +704,8 @@ enum country_src { * @nol_history: Set NOL-History when STA vap detects RADAR. */ struct regulatory_channel { - uint32_t center_freq; - uint32_t chan_num; + qdf_freq_t center_freq; + uint8_t chan_num; enum channel_state state; uint32_t chan_flags; uint32_t tx_power; @@ -725,7 +716,6 @@ struct regulatory_channel { bool nol_history; }; - /** * struct regulatory: regulatory information * @reg_domain: regulatory domain pair @@ -760,8 +750,8 @@ struct regulatory { * @max_bw: max bw */ struct chan_map { - uint32_t center_freq; - uint32_t chan_num; + qdf_freq_t center_freq; + uint8_t chan_num; uint16_t min_bw; uint16_t max_bw; }; @@ -772,8 +762,18 @@ struct chan_map { * @end_ch: end channel */ struct bonded_channel { - uint16_t start_ch; - uint16_t end_ch; + uint8_t start_ch; + uint8_t end_ch; +}; + +/** + * struct bonded_channel_freq + * @start_freq: start channel frequency + * @end_freq: end channel frequency + */ +struct bonded_channel_freq { + uint16_t start_freq; + uint16_t end_freq; }; struct set_country { @@ -836,7 +836,7 @@ struct cur_reg_rule { * @min_bw_5g: minimum 5G bw * @max_bw_5g: maximum 5G bw * @num_2g_reg_rules: number 2G reg rules - * @num_5g_reg_rules: number 5G reg rules + * @num_5g_reg_rules: number 5G and 6G reg rules * @reg_rules_2g_ptr: ptr to 2G reg rules * @reg_rules_5g_ptr: ptr to 5G reg rules */ @@ -875,6 +875,38 @@ struct reg_rule_info { struct cur_reg_rule reg_rules[MAX_REG_RULES]; }; +/** + * enum reg_reg_wifi_band + * @REG_BAND_2G: 2G band + * @REG_BAND_5G: 5G band + * @REG_BAND_6G: 6G band + * @REG_BAND_UNKNOWN: Unsupported band + */ +enum reg_wifi_band { + REG_BAND_2G, + REG_BAND_5G, + REG_BAND_6G, + REG_BAND_UNKNOWN +}; + +#ifdef DISABLE_UNII_SHARED_BANDS +/** + * enum reg_unii_band + * @REG_UNII_BAND_1: Disable UNII-1 band channels + * @REG_UNII_BAND_2A: Disable UNII-2A band channels + */ +enum reg_unii_band { + REG_UNII_BAND_1 = 0x0, + REG_UNII_BAND_2A = 0x1, +}; +#endif + +#define REG_BAND_MASK_ALL (BIT(REG_BAND_2G) | BIT(REG_BAND_5G) \ + | BIT(REG_BAND_6G)) + +/* Avoid the use of band_info as it does not support 6GHz band. Use + * reg_wifi_band, as it supports the 6GHz band + */ /** * enum band_info * @BAND_ALL:all bands @@ -917,18 +949,20 @@ enum restart_beaconing_on_ch_avoid_rule { * away from active LTE channels * @enable_srd_chan_in_master_mode: SRD channel support in master mode * @enable_11d_in_world_mode: enable 11d in world mode + * @retain_nol_across_regdmn_update: Retain the NOL list across the regdomain. */ struct reg_config_vars { uint32_t enable_11d_support; uint32_t scan_11d_interval; uint32_t userspace_ctry_priority; - enum band_info band_capability; + uint32_t band_capability; uint32_t dfs_enabled; uint32_t indoor_chan_enabled; uint32_t force_ssc_disable_indoor_channel; enum restart_beaconing_on_ch_avoid_rule restart_beaconing; - bool enable_srd_chan_in_master_mode; + uint8_t enable_srd_chan_in_master_mode; bool enable_11d_in_world_mode; + bool retain_nol_across_regdmn_update; }; /** @@ -1041,8 +1075,8 @@ struct cur_regdmn_info { * @end_freq: end freq */ struct ch_avoid_freq_type { - uint32_t start_freq; - uint32_t end_freq; + qdf_freq_t start_freq; + qdf_freq_t end_freq; }; /** @@ -1057,12 +1091,12 @@ struct ch_avoid_ind_type { /** * struct unsafe_ch_list - * @ch_cnt: no.of channels - * @ch_list: channel list + * @chan_cnt: no.of channels + * @chan_freq_list: channel frequency list */ struct unsafe_ch_list { - uint16_t ch_cnt; - uint16_t ch_list[NUM_CHANNELS]; + uint16_t chan_cnt; + uint16_t chan_freq_list[NUM_CHANNELS]; }; /** @@ -1075,6 +1109,14 @@ struct avoid_freq_ind_data { struct unsafe_ch_list chan_list; }; +#define FIVEG_STARTING_FREQ 5000 +#define TWOG_STARTING_FREQ 2407 +#define TWOG_CHAN_14_IN_MHZ 2484 +#define TWOG_CHAN_1_IN_MHZ 2412 +#define TWOG_CHAN_5_IN_MHZ 2432 +#define TWOG_CHAN_6_IN_MHZ 2437 +#define TWOG_CHAN_13_IN_MHZ 2472 + /** * struct reg_ctl_params - reg ctl and regd info * @regd: regdomain pair diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h index a15aa155d545bd9b7eb45e9f34a40aaa15dc9757..0c8f420ee0cebe21a7dab14df08307b1276b0bbc 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -26,13 +26,14 @@ #ifndef __WLAN_REG_SERVICES_API_H #define __WLAN_REG_SERVICES_API_H +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_min_24ghz_ch_num() - Get minimum 2.4GHz channel number * * Return: Minimum 2.4GHz channel number */ #define WLAN_REG_MIN_24GHZ_CH_NUM wlan_reg_min_24ghz_ch_num() -uint32_t wlan_reg_min_24ghz_ch_num(void); +uint8_t wlan_reg_min_24ghz_ch_num(void); /** * wlan_reg_max_24ghz_ch_num() - Get maximum 2.4GHz channel number @@ -40,7 +41,7 @@ uint32_t wlan_reg_min_24ghz_ch_num(void); * Return: Maximum 2.4GHz channel number */ #define WLAN_REG_MAX_24GHZ_CH_NUM wlan_reg_max_24ghz_ch_num() -uint32_t wlan_reg_max_24ghz_ch_num(void); +uint8_t wlan_reg_max_24ghz_ch_num(void); /** * wlan_reg_min_5ghz_ch_num() - Get minimum 5GHz channel number @@ -48,7 +49,7 @@ uint32_t wlan_reg_max_24ghz_ch_num(void); * Return: Minimum 5GHz channel number */ #define WLAN_REG_MIN_5GHZ_CH_NUM wlan_reg_min_5ghz_ch_num() -uint32_t wlan_reg_min_5ghz_ch_num(void); +uint8_t wlan_reg_min_5ghz_ch_num(void); /** * wlan_reg_max_5ghz_ch_num() - Get maximum 5GHz channel number @@ -56,8 +57,44 @@ uint32_t wlan_reg_min_5ghz_ch_num(void); * Return: Maximum 5GHz channel number */ #define WLAN_REG_MAX_5GHZ_CH_NUM wlan_reg_max_5ghz_ch_num() -uint32_t wlan_reg_max_5ghz_ch_num(void); +uint8_t wlan_reg_max_5ghz_ch_num(void); +#endif /* CONFIG_CHAN_NUM_API */ +#ifdef CONFIG_CHAN_FREQ_API +/** + * wlan_reg_min_24ghz_chan_freq() - Get minimum 2.4GHz channel frequency + * + * Return: Minimum 2.4GHz channel frequency + */ +#define WLAN_REG_MIN_24GHZ_CHAN_FREQ wlan_reg_min_24ghz_chan_freq() +qdf_freq_t wlan_reg_min_24ghz_chan_freq(void); + +/** + * wlan_reg_max_24ghz_chan_freq() - Get maximum 2.4GHz channel frequency + * + * Return: Maximum 2.4GHz channel frequency + */ +#define WLAN_REG_MAX_24GHZ_CHAN_FREQ wlan_reg_max_24ghz_chan_freq() +qdf_freq_t wlan_reg_max_24ghz_chan_freq(void); + +/** + * wlan_reg_min_5ghz_chan_freq() - Get minimum 5GHz channel frequency + * + * Return: Minimum 5GHz channel frequency + */ +#define WLAN_REG_MIN_5GHZ_CHAN_FREQ wlan_reg_min_5ghz_chan_freq() +qdf_freq_t wlan_reg_min_5ghz_chan_freq(void); + +/** + * wlan_reg_max_5ghz_chan_freq() - Get maximum 5GHz channel frequency + * + * Return: Maximum 5GHz channel frequency + */ +#define WLAN_REG_MAX_5GHZ_CHAN_FREQ wlan_reg_max_5ghz_chan_freq() +qdf_freq_t wlan_reg_max_5ghz_chan_freq(void); +#endif /* CONFIG_CHAN_FREQ_API */ + +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_is_24ghz_ch() - Check if the given channel number is 2.4GHz * @chan: Channel number @@ -65,7 +102,7 @@ uint32_t wlan_reg_max_5ghz_ch_num(void); * Return: true if channel number is 2.4GHz, else false */ #define WLAN_REG_IS_24GHZ_CH(chan) wlan_reg_is_24ghz_ch(chan) -bool wlan_reg_is_24ghz_ch(uint32_t chan); +bool wlan_reg_is_24ghz_ch(uint8_t chan); /** * wlan_reg_is_5ghz_ch() - Check if the given channel number is 5GHz @@ -74,7 +111,8 @@ bool wlan_reg_is_24ghz_ch(uint32_t chan); * Return: true if channel number is 5GHz, else false */ #define WLAN_REG_IS_5GHZ_CH(chan) wlan_reg_is_5ghz_ch(chan) -bool wlan_reg_is_5ghz_ch(uint32_t chan); +bool wlan_reg_is_5ghz_ch(uint8_t chan); +#endif /* CONFIG_CHAN_NUM_API */ /** * wlan_reg_is_24ghz_ch_freq() - Check if the given channel frequency is 2.4GHz @@ -83,7 +121,7 @@ bool wlan_reg_is_5ghz_ch(uint32_t chan); * Return: true if channel frequency is 2.4GHz, else false */ #define WLAN_REG_IS_24GHZ_CH_FREQ(freq) wlan_reg_is_24ghz_ch_freq(freq) -bool wlan_reg_is_24ghz_ch_freq(uint32_t freq); +bool wlan_reg_is_24ghz_ch_freq(qdf_freq_t freq); /** * wlan_reg_is_5ghz_ch_freq() - Check if the given channel frequency is 5GHz @@ -92,9 +130,114 @@ bool wlan_reg_is_24ghz_ch_freq(uint32_t freq); * Return: true if channel frequency is 5GHz, else false */ #define WLAN_REG_IS_5GHZ_CH_FREQ(freq) wlan_reg_is_5ghz_ch_freq(freq) -bool wlan_reg_is_5ghz_ch_freq(uint32_t freq); +bool wlan_reg_is_5ghz_ch_freq(qdf_freq_t freq); + +/** + * wlan_reg_is_freq_indoor() - Check if a frequency is indoor. + * @pdev: Pointer to pdev. + * @freq: Channel frequency. + * + * Return: Return true if a frequency is indoor, else false. + */ +bool wlan_reg_is_freq_indoor(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq); + +#ifdef CONFIG_BAND_6GHZ +/** + * wlan_reg_is_6ghz_chan_freq() - Check if the given channel frequency is 6GHz + * @freq: Channel frequency + * + * Return: true if channel frequency is 6GHz, else false + */ +#define WLAN_REG_IS_6GHZ_CHAN_FREQ(freq) wlan_reg_is_6ghz_chan_freq(freq) +bool wlan_reg_is_6ghz_chan_freq(uint16_t freq); + +/** + * wlan_reg_is_6ghz_psc_chan_freq() - Check if the given 6GHz channel frequency + * is preferred scanning channel frequency. + * @freq: Channel frequency + * + * Return: true if given 6GHz channel frequency is preferred scanning channel + * frequency, else false + */ +#define WLAN_REG_IS_6GHZ_PSC_CHAN_FREQ(freq) \ + wlan_reg_is_6ghz_psc_chan_freq(freq) +bool wlan_reg_is_6ghz_psc_chan_freq(uint16_t freq); + +/** + * wlan_reg_min_6ghz_chan_freq() - Get minimum 6GHz channel center frequency + * + * Return: Minimum 6GHz channel center frequency + */ +#define WLAN_REG_MIN_6GHZ_CHAN_FREQ wlan_reg_min_6ghz_chan_freq() +uint16_t wlan_reg_min_6ghz_chan_freq(void); + +/** + * wlan_reg_max_6ghz_chan_freq() - Get maximum 6GHz channel center frequency + * + * Return: Maximum 6GHz channel center frequency + */ +#define WLAN_REG_MAX_6GHZ_CHAN_FREQ wlan_reg_max_6ghz_chan_freq() +uint16_t wlan_reg_max_6ghz_chan_freq(void); + +#else + +#define WLAN_REG_IS_6GHZ_CHAN_FREQ(freq) (false) +static inline bool wlan_reg_is_6ghz_chan_freq(uint16_t freq) +{ + return false; +} + +#define WLAN_REG_IS_6GHZ_PSC_CHAN_FREQ(freq) (false) +static inline bool wlan_reg_is_6ghz_psc_chan_freq(uint16_t freq) +{ + return false; +} + +#define WLAN_REG_MIN_6GHZ_CHAN_FREQ (false) +static inline uint16_t wlan_reg_min_6ghz_chan_freq(void) +{ + return 0; +} + +#define WLAN_REG_MAX_6GHZ_CHAN_FREQ (false) +static inline uint16_t wlan_reg_max_6ghz_chan_freq(void) +{ + return 0; +} +#endif /* CONFIG_BAND_6GHZ */ + +/** + * wlan_reg_get_band_channel_list() - Get channel list based on the band_mask + * @pdev: pdev ptr + * @band_mask: Input bitmap with band set + * @channel_list: Pointer to Channel List + * + * Get the given channel list and number of channels from the current channel + * list based on input band bitmap. + * + * Return: Number of channels, else 0 to indicate error + */ +uint16_t +wlan_reg_get_band_channel_list(struct wlan_objmgr_pdev *pdev, + uint8_t band_mask, + struct regulatory_channel *channel_list); + +/** + * wlan_reg_chan_band_to_freq - Return channel frequency based on the channel + * number and band. + * @pdev: pdev ptr + * @chan: Channel Number + * @band_mask: Bitmap for bands + * + * Return: Return channel frequency or return 0, if the channel is disabled or + * if the input channel number or band_mask is invalid. Composite bands are + * supported only for 2.4Ghz and 5Ghz bands. For other bands the following + * priority is given: 1) 6Ghz 2) 5Ghz 3) 2.4Ghz. + */ +qdf_freq_t wlan_reg_chan_band_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan, + uint8_t band_mask); -#ifndef CONFIG_LEGACY_CHAN_ENUM /** * wlan_reg_is_49ghz_freq() - Check if the given channel frequency is 4.9GHz * @freq: Channel frequency @@ -102,8 +245,7 @@ bool wlan_reg_is_5ghz_ch_freq(uint32_t freq); * Return: true if channel frequency is 4.9GHz, else false */ #define WLAN_REG_IS_49GHZ_FREQ(freq) wlan_reg_is_49ghz_freq(freq) -bool wlan_reg_is_49ghz_freq(uint32_t freq); -#endif +bool wlan_reg_is_49ghz_freq(qdf_freq_t freq); /** * wlan_reg_ch_num() - Get channel number from channel enum @@ -112,7 +254,7 @@ bool wlan_reg_is_49ghz_freq(uint32_t freq); * Return: channel number */ #define WLAN_REG_CH_NUM(ch_enum) wlan_reg_ch_num(ch_enum) -uint32_t wlan_reg_ch_num(uint32_t ch_enum); +uint8_t wlan_reg_ch_num(uint32_t ch_enum); /** * wlan_reg_ch_to_freq() - Get channel frequency from channel enum @@ -121,8 +263,9 @@ uint32_t wlan_reg_ch_num(uint32_t ch_enum); * Return: channel frequency */ #define WLAN_REG_CH_TO_FREQ(ch_enum) wlan_reg_ch_to_freq(ch_enum) -uint32_t wlan_reg_ch_to_freq(uint32_t ch_enum); +qdf_freq_t wlan_reg_ch_to_freq(uint32_t ch_enum); +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_is_same_band_channels() - Check if given channel numbers have same * band @@ -133,7 +276,7 @@ uint32_t wlan_reg_ch_to_freq(uint32_t ch_enum); */ #define WLAN_REG_IS_SAME_BAND_CHANNELS(chan_num1, chan_num2) \ wlan_reg_is_same_band_channels(chan_num1, chan_num2) -bool wlan_reg_is_same_band_channels(uint32_t chan_num1, uint32_t chan_num2); +bool wlan_reg_is_same_band_channels(uint8_t chan_num1, uint8_t chan_num2); /** * wlan_reg_is_channel_valid_5g_sbs() Check if the given channel is 5G SBS. @@ -144,11 +287,11 @@ bool wlan_reg_is_same_band_channels(uint32_t chan_num1, uint32_t chan_num2); */ #define WLAN_REG_IS_CHANNEL_VALID_5G_SBS(curchan, newchan) \ wlan_reg_is_channel_valid_5g_sbs(curchan, newchan) -bool wlan_reg_is_channel_valid_5g_sbs(uint32_t curchan, uint32_t newchan); +bool wlan_reg_is_channel_valid_5g_sbs(uint8_t curchan, uint8_t newchan); +#endif /* CONFIG_CHAN_NUM_API */ -#define WLAN_REG_INVALID_CHANNEL_ID -#define WLAN_REG_GET_24_END_CHAN_NUM 14 +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_chan_to_band() - Get band from channel number * @chan_num: channel number @@ -156,7 +299,7 @@ bool wlan_reg_is_channel_valid_5g_sbs(uint32_t curchan, uint32_t newchan); * Return: band info */ #define WLAN_REG_CHAN_TO_BAND(chan_num) wlan_reg_chan_to_band(chan_num) -enum band_info wlan_reg_chan_to_band(uint32_t chan_num); +enum band_info wlan_reg_chan_to_band(uint8_t chan_num); /** * wlan_reg_get_channel_list_with_power() - Provide the channel list with power @@ -167,7 +310,7 @@ enum band_info wlan_reg_chan_to_band(uint32_t chan_num); QDF_STATUS wlan_reg_get_channel_list_with_power(struct wlan_objmgr_pdev *pdev, struct channel_power *ch_list, uint8_t *num_chan); - +#endif /* CONFIG_CHAN_NUM_API */ /** * wlan_reg_read_default_country() - Read the default country for the regdomain * @country: pointer to the country code. @@ -197,6 +340,7 @@ bool wlan_reg_get_fcc_constraint(struct wlan_objmgr_pdev *pdev, uint32_t freq); QDF_STATUS wlan_reg_read_current_country(struct wlan_objmgr_psoc *psoc, uint8_t *country); +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_chan_has_dfs_attribute() - check channel has dfs attribute flag * @ch: channel number. @@ -206,7 +350,7 @@ QDF_STATUS wlan_reg_read_current_country(struct wlan_objmgr_psoc *psoc, * Return: true if chan is dfs, otherwise false */ bool -wlan_reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint32_t ch); +wlan_reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint8_t ch); /** * wlan_reg_is_etsi13_srd_chan () - Checks if the ch is ETSI13 srd ch or not @@ -217,6 +361,20 @@ wlan_reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint32_t ch); */ bool wlan_reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, uint8_t chan_num); +#endif /* CONFIG_CHAN_NUM_API */ + +#ifdef CONFIG_CHAN_FREQ_API +/** + * wlan_reg_is_etsi13_srd_chan_for_freq () - Checks if the ch is ETSI13 srd ch + * or not + * @pdev: pdev ptr + * @freq: channel center frequency + * + * Return: true or false + */ +bool wlan_reg_is_etsi13_srd_chan_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); +#endif /*CONFIG_CHAN_FREQ_API*/ /** * wlan_reg_is_etsi13_regdmn() - Checks if current reg domain is ETSI13 or not @@ -246,13 +404,14 @@ bool wlan_reg_is_etsi13_srd_chan_allowed_master_mode(struct wlan_objmgr_pdev */ bool wlan_reg_is_world(uint8_t *country); +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_get_chan_enum() - Get channel enum for given channel number * @chan_num: Channel number * * Return: Channel enum */ -enum channel_enum wlan_reg_get_chan_enum(uint32_t chan_num); +enum channel_enum wlan_reg_get_chan_enum(uint8_t chan_num); /** * wlan_reg_get_channel_state() - Get channel state from regulatory @@ -261,7 +420,7 @@ enum channel_enum wlan_reg_get_chan_enum(uint32_t chan_num); * Return: channel state */ enum channel_state wlan_reg_get_channel_state(struct wlan_objmgr_pdev *pdev, - uint32_t ch); + uint8_t ch); /** * wlan_reg_get_5g_bonded_channel_state() - Get 5G bonded channel state @@ -300,7 +459,7 @@ enum channel_state wlan_reg_get_2g_bonded_channel_state( void wlan_reg_set_channel_params(struct wlan_objmgr_pdev *pdev, uint8_t ch, uint8_t sec_ch_2g, struct ch_params *ch_params); - +#endif /* CONFIG_CHAN_NUM_API */ /** * wlan_reg_get_dfs_region () - Get the current dfs region * @dfs_reg: pointer to dfs region @@ -310,23 +469,25 @@ void wlan_reg_set_channel_params(struct wlan_objmgr_pdev *pdev, uint8_t ch, QDF_STATUS wlan_reg_get_dfs_region(struct wlan_objmgr_pdev *pdev, enum dfs_reg *dfs_reg); +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_get_channel_reg_power() - Provide the channel regulatory power - * @chan_num: chennal number + * @chan_num: channel number * * Return: int */ uint32_t wlan_reg_get_channel_reg_power(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num); + uint8_t chan_num); /** * wlan_reg_get_channel_freq() - provide the channel center freq - * @chan_num: chennal number + * @chan_num: channel number * * Return: int */ -uint32_t wlan_reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num); +qdf_freq_t wlan_reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num); +#endif /* CONFIG_CHAN_NUM_API */ /** * wlan_reg_get_current_chan_list() - provide the pdev current channel list @@ -337,6 +498,8 @@ uint32_t wlan_reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, */ QDF_STATUS wlan_reg_get_current_chan_list(struct wlan_objmgr_pdev *pdev, struct regulatory_channel *chan_list); + +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_get_bonded_channel_state() - get bonded channel state * @pdev: pdev ptr @@ -349,6 +512,7 @@ QDF_STATUS wlan_reg_get_current_chan_list(struct wlan_objmgr_pdev *pdev, enum channel_state wlan_reg_get_bonded_channel_state( struct wlan_objmgr_pdev *pdev, uint8_t ch, enum phy_ch_width bw, uint8_t sec_ch); +#endif /* CONFIG_CHAN_NUM_API */ /** * wlan_reg_set_dfs_region() - set the dfs region @@ -391,6 +555,21 @@ QDF_STATUS wlan_reg_get_domain_from_country_code(v_REGDOMAIN_t *reg_domain_ptr, uint16_t wlan_reg_dmn_get_opclass_from_channel(uint8_t *country, uint8_t channel, uint8_t offset); + +/** + * wlan_reg_get_opclass_from_freq_width() - Get operating class from frequency + * @country: Country code. + * @freq: Channel center frequency. + * @ch_width: Channel width. + * @behav_limit: Behaviour limit. + * + * Return: Error code. + */ +uint8_t wlan_reg_get_opclass_from_freq_width(uint8_t *country, + qdf_freq_t freq, + uint8_t ch_width, + uint16_t behav_limit); + /** * wlan_reg_dmn_print_channels_in_opclass() - Print channels in op-class * @country: country alpha2 @@ -435,6 +614,23 @@ uint16_t wlan_reg_dmn_get_curr_opclasses(uint8_t *num_classes, uint8_t *class); +/** + * wlan_reg_get_opclass_details() - Get details about the current opclass table. + * @pdev: Pointer to pdev. + * @reg_ap_cap: Pointer to reg_ap_cap. + * @n_opclasses: Pointer to number of opclasses. + * @max_supp_op_class: Maximum number of operating classes supported. + * @global_tbl_lookup: Whether to lookup global op class tbl. + * + * Return: QDF_STATUS_SUCCESS if success, else return QDF_STATUS_FAILURE. + */ +QDF_STATUS +wlan_reg_get_opclass_details(struct wlan_objmgr_pdev *pdev, + struct regdmn_ap_cap_opclass_t *reg_ap_cap, + uint8_t *n_opclasses, + uint8_t max_supp_op_class, + bool global_tbl_lookup); + /** * wlan_regulatory_init() - init regulatory component * @@ -466,7 +662,7 @@ QDF_STATUS regulatory_psoc_close(struct wlan_objmgr_psoc *psoc); /** * regulatory_pdev_open() - Open regulatory component - * @pdev: Pointer to pdev structure. + * @pdev: Pointer to pdev structure * * Return: Success or Failure */ @@ -480,6 +676,7 @@ QDF_STATUS regulatory_pdev_open(struct wlan_objmgr_pdev *pdev); */ QDF_STATUS regulatory_pdev_close(struct wlan_objmgr_pdev *pdev); +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_update_nol_ch () - set nol channel * @pdev: pdev ptr @@ -494,15 +691,6 @@ void wlan_reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, uint8_t num_ch, bool nol_ch); -/** - * wlan_reg_is_dfs_ch () - Checks the channel state for DFS - * @pdev: pdev ptr - * @chan: channel - * - * Return: true or false - */ -bool wlan_reg_is_dfs_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan); - /** * wlan_reg_is_dsrc_chan () - Checks if the channel is dsrc channel or not * @pdev: pdev ptr @@ -521,7 +709,7 @@ bool wlan_reg_is_dsrc_chan(struct wlan_objmgr_pdev *pdev, uint8_t chan_num); * Return: true or false */ bool wlan_reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, - uint32_t chan); + uint8_t chan); /** * wlan_reg_is_disable_ch () - Checks chan state for disabled @@ -530,7 +718,8 @@ bool wlan_reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, * * Return: true or false */ -bool wlan_reg_is_disable_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan); +bool wlan_reg_is_disable_ch(struct wlan_objmgr_pdev *pdev, uint8_t chan); +#endif /* CONFIG_CHAN_NUM_API */ /** * wlan_reg_freq_to_chan () - convert channel freq to channel number @@ -539,8 +728,8 @@ bool wlan_reg_is_disable_ch(struct wlan_objmgr_pdev *pdev, uint32_t chan); * * Return: true or false */ -uint32_t wlan_reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, - uint32_t freq); +uint8_t wlan_reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); /** * wlan_reg_chan_to_freq () - convert channel number to frequency @@ -548,8 +737,8 @@ uint32_t wlan_reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, * * Return: true or false */ -uint32_t wlan_reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, - uint32_t chan); +qdf_freq_t wlan_reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan); /** * wlan_reg_legacy_chan_to_freq () - convert chan to freq, for 2G and 5G @@ -557,8 +746,8 @@ uint32_t wlan_reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, * * Return: frequency */ -uint16_t wlan_reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, - uint8_t chan); +qdf_freq_t wlan_reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan); /** * wlan_reg_is_us() - reg is us country @@ -568,6 +757,7 @@ uint16_t wlan_reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, */ bool wlan_reg_is_us(uint8_t *country); +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_chan_is_49ghz() - Check if the input channel number is 4.9GHz * @pdev: Pdev pointer @@ -575,9 +765,9 @@ bool wlan_reg_is_us(uint8_t *country); * * Return: true if the channel is 4.9GHz else false. */ - bool wlan_reg_chan_is_49ghz(struct wlan_objmgr_pdev *pdev, uint8_t chan_num); +#endif /* CONFIG_CHAN_NUM_API */ /** * wlan_reg_set_country() - Set the current regulatory country @@ -664,10 +854,10 @@ bool wlan_reg_is_11d_scan_inprogress(struct wlan_objmgr_psoc *psoc); * Return: QDF status */ QDF_STATUS wlan_reg_get_freq_range(struct wlan_objmgr_pdev *pdev, - uint32_t *low_2g, - uint32_t *high_2g, - uint32_t *low_5g, - uint32_t *high_5g); + qdf_freq_t *low_2g, + qdf_freq_t *high_2g, + qdf_freq_t *low_5g, + qdf_freq_t *high_5g); /** * wlan_reg_get_tx_ops () - get regulatory tx ops * @psoc: psoc ptr @@ -686,6 +876,7 @@ wlan_reg_get_tx_ops(struct wlan_objmgr_psoc *psoc); QDF_STATUS wlan_reg_get_curr_regdomain(struct wlan_objmgr_pdev *pdev, struct cur_regdmn_info *cur_regdmn); +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_update_nol_history_ch() - Set nol-history flag for the channels in * the list. @@ -701,6 +892,364 @@ void wlan_reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, uint8_t *ch_list, uint8_t num_ch, bool nol_history_ch); +#endif /* CONFIG_CHAN_NUM_API */ +/** + * wlan_reg_is_regdmn_en302502_applicable() - Find if ETSI EN302_502 radar + * pattern is applicable in the current regulatory domain. + * @pdev: Pdev ptr. + * + * Return: Boolean. + * True: If EN302_502 is applicable. + * False: otherwise. + */ +bool wlan_reg_is_regdmn_en302502_applicable(struct wlan_objmgr_pdev *pdev); + +/** + * wlan_reg_modify_pdev_chan_range() - Compute current channel list for the + * modified channel range in the regcap. + * @pdev: pointer to wlan_objmgr_pdev. + * + * Return : QDF_STATUS + */ +QDF_STATUS wlan_reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev); + +/** + * wlan_reg_disable_chan_coex() - Disable Coexisting channels based on the input + * bitmask + * @pdev: pointer to wlan_objmgr_pdev. + * unii_5g_bitmap: UNII 5G bitmap. + * + * Return : QDF_STATUS + */ +#ifdef DISABLE_UNII_SHARED_BANDS +QDF_STATUS wlan_reg_disable_chan_coex(struct wlan_objmgr_pdev *pdev, + uint8_t unii_5g_bitmap); +#else +static inline QDF_STATUS +wlan_reg_disable_chan_coex(struct wlan_objmgr_pdev *pdev, + uint8_t unii_5g_bitmap) +{ + return QDF_STATUS_SUCCESS; +} +#endif + +#ifdef CONFIG_CHAN_FREQ_API +/** + * wlan_reg_is_same_band_freqs() - Check if two channel frequencies + * have same band + * @freq1: Frequency 1 + * @freq2: Frequency 2 + * + * Return: true if both the channel frequency has the same band. + */ +#define WLAN_REG_IS_SAME_BAND_FREQS(freq1, freq2) \ + wlan_reg_is_same_band_freqs(freq1, freq2) +bool wlan_reg_is_same_band_freqs(qdf_freq_t freq1, qdf_freq_t freq2); + +/** + * wlan_reg_get_chan_enum_for_freq() - Get channel enum for given channel center + * frequency + * @freq: Channel center frequency + * + * Return: Channel enum + */ +enum channel_enum wlan_reg_get_chan_enum_for_freq(qdf_freq_t freq); + +/** + * wlan_reg_update_nol_history_ch_for_freq() - Set nol-history flag for the + * channels in the list. + * + * @pdev: Pdev ptr + * @ch_list: Input channel list. + * @num_ch: Number of channels. + * @nol_history_ch: Nol history value. + * + * Return: void + */ +void wlan_reg_update_nol_history_ch_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *ch_list, + uint8_t num_ch, + bool nol_history_ch); +/** + * wlan_reg_is_frequency_valid_5g_sbs() Check if the given frequency is 5G SBS. + * @curfreq: current channel center frequency + * @newfreq:new channel center frequency + * + * Return: true if the given frequency is a valid 5G SBS + */ +#define WLAN_REG_IS_FREQUENCY_VALID_5G_SBS(curfreq, newfreq) \ + wlan_reg_is_frequency_valid_5g_sbs(curfreq, newfreq) +bool wlan_reg_is_frequency_valid_5g_sbs(qdf_freq_t curfreq, qdf_freq_t newfreq); + +/** + * wlan_reg_chan_has_dfs_attribute_for_freq() - check channel has dfs + * attribute flag + * @freq: channel center frequency. + * + * This API get chan initial dfs attribute from regdomain + * + * Return: true if chan is dfs, otherwise false + */ +bool +wlan_reg_chan_has_dfs_attribute_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); + +/** + * wlan_reg_get_channel_list_with_power_for_freq() - Provide the channel list + * with power + * @ch_list: pointer to the channel list. + * + * Return: QDF_STATUS + */ +QDF_STATUS +wlan_reg_get_channel_list_with_power_for_freq(struct wlan_objmgr_pdev *pdev, + struct channel_power *ch_list, + uint8_t *num_chan); + +/** + * wlan_reg_get_5g_bonded_channel_state_for_freq() - Get 5G bonded channel state + * @pdev: The physical dev to program country code or regdomain + * @freq: channel frequency. + * @bw: channel band width + * + * Return: channel state + */ +enum channel_state +wlan_reg_get_5g_bonded_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + enum phy_ch_width bw); +/** + * wlan_reg_get_2g_bonded_channel_state_for_freq() - Get 2G bonded channel state + * @pdev: The physical dev to program country code or regdomain + * @freq: channel center frequency. + * @sec_ch_freq: Secondary channel center frequency. + * @bw: channel band width + * + * Return: channel state + */ +enum channel_state +wlan_reg_get_2g_bonded_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + qdf_freq_t sec_ch_freq, + enum phy_ch_width bw); + +/** + * wlan_reg_get_channel_state_for_freq() - Get channel state from regulatory + * @pdev: Pointer to pdev + * @freq: channel center frequency. + * + * Return: channel state + */ +enum channel_state +wlan_reg_get_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); + +/** + * wlan_reg_set_channel_params_for_freq() - Sets channel parameteres for + * given bandwidth + * @pdev: The physical dev to program country code or regdomain + * @freq: channel center frequency. + * @sec_ch_2g_freq: Secondary channel center frequency. + * @ch_params: pointer to the channel parameters. + * + * Return: None + */ +void wlan_reg_set_channel_params_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + qdf_freq_t sec_ch_2g_freq, + struct ch_params *ch_params); + +/** + * wlan_reg_get_channel_cfreq_reg_power_for_freq() - Provide the channel + * regulatory power + * @freq: channel center frequency + * + * Return: int + */ +uint8_t wlan_reg_get_channel_reg_power_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); + +/** + * wlan_reg_update_nol_ch_for_freq () - set nol channel + * @pdev: pdev ptr + * @chan_freq_list: channel list to be returned + * @num_ch: number of channels + * @nol_ch: nol flag + * + * Return: void + */ +void wlan_reg_update_nol_ch_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *chan_freq_list, + uint8_t num_ch, + bool nol_ch); + +/** + * wlan_reg_is_dfs_freq() - Checks the channel state for DFS + * @freq: Channel center frequency + * + * Return: true or false + */ +bool wlan_reg_is_dfs_for_freq(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq); + +/** + * wlan_reg_is_dsrc_freq() - Checks if the channel is dsrc channel or not + * @freq: Channel center frequency + * + * Return: true or false + */ +bool wlan_reg_is_dsrc_freq(qdf_freq_t freq); + +/** + * wlan_reg_is_passive_or_disable_for_freq() - Checks chan state for passive + * and disabled + * @pdev: pdev ptr + * @freq: Channel center frequency + * + * Return: true or false + */ +bool wlan_reg_is_passive_or_disable_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); + +/** + * wlan_reg_is_disable_for_freq() - Checks chan state for disabled + * @pdev: pdev ptr + * @freq: Channel center frequency + * + * Return: true or false + */ +bool wlan_reg_is_disable_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq); + +/** + * wlan_reg_chan_to_band() - Get band from channel number + * @chan_num: channel number + * + * Return: wifi band + */ +enum reg_wifi_band wlan_reg_freq_to_band(qdf_freq_t freq); + +/** + * wlan_reg_min_chan_freq() - Minimum channel frequency supported + * + * Return: frequency + */ +qdf_freq_t wlan_reg_min_chan_freq(void); + +/** + * wlan_reg_max_chan_freq() - Return max. frequency + * + * Return: frequency + */ +qdf_freq_t wlan_reg_max_chan_freq(void); + +/** + * wlan_reg_freq_width_to_chan_op_class() -Get op class from freq + * @pdev: pdev ptr + * @freq: channel frequency + * @chan_width: channel width + * @global_tbl_lookup: whether to look up global table + * @behav_limit: behavior limit + * @op_class: operating class + * @chan_num: channel number + * + * Return: void + */ +void wlan_reg_freq_width_to_chan_op_class(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + uint16_t chan_width, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num); + +/** + * wlan_reg_freq_width_to_chan_op_class_auto() - convert frequency to + * operating class,channel + * @pdev: pdev pointer + * @freq: channel frequency in mhz + * @chan_width: channel width + * @global_tbl_lookup: whether to lookup global op class tbl + * @behav_limit: behavior limit + * @op_class: operating class + * @chan_num: channel number + * + * Return: Void. + */ +void wlan_reg_freq_width_to_chan_op_class_auto(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + uint16_t chan_width, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num); + +/** + * wlan_reg_freq_to_chan_and_op_class() - Converts freq to oper class + * @pdev: pdev ptr + * @freq: channel frequency + * @global_tbl_lookup: whether to look up global table + * @behav_limit: behavior limit + * @op_class: operating class + * @chan_num: channel number + * + * Return: void + */ +void wlan_reg_freq_to_chan_op_class(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num); + +/** + * wlan_reg_country_opclass_freq_check() - checks frequency in (ctry, op class) + * pair + * @pdev: pdev ptr + * @country: country information + * @op_class: operating class + * @chan_freq: channel frequency + * + * Return: bool + */ +bool wlan_reg_country_opclass_freq_check(struct wlan_objmgr_pdev *pdev, + const uint8_t country[3], + uint8_t op_class, + qdf_freq_t chan_freq); + +/** + * wlan_reg_get_5g_bonded_channel_and_state_for_freq()- Return the channel + * state for a 5G or 6G channel frequency based on the channel width and + * bonded channel. + * @pdev: Pointer to pdev. + * @freq: Channel center frequency. + * @bw Channel Width. + * @bonded_chan_ptr_ptr: Pointer to bonded_channel_freq. + * + * Return: Channel State + */ +enum channel_state +wlan_reg_get_5g_bonded_channel_and_state_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + enum phy_ch_width bw, + const + struct bonded_channel_freq + **bonded_chan_ptr_ptr); +#endif /*CONFIG_CHAN_FREQ_API */ + +/** + * wlan_reg_get_op_class_width() - Get operating class chan width + * @pdev: pdev ptr + * @freq: channel frequency + * @global_tbl_lookup: whether to look up global table + * @op_class: operating class + * @chan_num: channel number + * + * Return: channel width of op class + */ +uint16_t wlan_reg_get_op_class_width(struct wlan_objmgr_pdev *pdev, + uint8_t op_class, + bool global_tbl_lookup); + /** * wlan_reg_is_6ghz_op_class() - Whether 6ghz oper class * @pdev: pdev ptr @@ -713,10 +1262,57 @@ bool wlan_reg_is_6ghz_op_class(struct wlan_objmgr_pdev *pdev, /** * wlan_reg_is_6ghz_supported() - Whether 6ghz is supported - * @pdev: pdev ptr + * @psoc: psoc ptr * * Return: bool */ -bool wlan_reg_is_6ghz_supported(struct wlan_objmgr_pdev *pdev); +bool wlan_reg_is_6ghz_supported(struct wlan_objmgr_psoc *psoc); + +#ifdef HOST_OPCLASS_EXT +/** + * wlan_reg_country_chan_opclass_to_freq() - Convert channel number to + * frequency based on country code and op class + * @pdev: pdev object. + * @country: country code. + * @chan: IEEE Channel Number. + * @op_class: Opclass. + * @strict: flag to find channel from matched operating class code. + * + * Look up (channel, operating class) pair in country operating class tables + * and return the channel frequency. + * If not found and "strict" flag is false, try to get frequency (Mhz) by + * channel number only. + * + * Return: Channel center frequency else return 0. + */ +qdf_freq_t +wlan_reg_country_chan_opclass_to_freq(struct wlan_objmgr_pdev *pdev, + const uint8_t country[3], + uint8_t chan, uint8_t op_class, + bool strict); +#endif +/** + * reg_chan_opclass_to_freq() - Convert channel number and opclass to frequency + * @chan: IEEE Channel Number. + * @op_class: Opclass. + * @global_tbl_lookup: Global table lookup. + * + * Return: Channel center frequency else return 0. + */ +uint16_t wlan_reg_chan_opclass_to_freq(uint8_t chan, + uint8_t op_class, + bool global_tbl_lookup); +#ifdef CONFIG_REG_CLIENT +/** + * wlan_reg_band_bitmap_to_band_info() - Convert the band_bitmap to a + * band_info enum + * @band_bitmap: bitmap on top of reg_wifi_band of bands enabled + * + * Return: BAND_ALL if both 2G and 5G band is enabled + * BAND_2G if 2G is enabled but 5G isn't + * BAND_5G if 5G is enabled but 2G isn't + */ +enum band_info wlan_reg_band_bitmap_to_band_info(uint32_t band_bitmap); +#endif #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_tgt_api.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_tgt_api.h index 2fae138fdea7a719cd5216efab160b111e94e0e3..1014c325e75bf146ab804312b0dfff22e39b88ae 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_tgt_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_tgt_api.h @@ -69,7 +69,6 @@ QDF_STATUS tgt_reg_process_ch_avoid_event(struct wlan_objmgr_psoc *psoc, /** * tgt_reg_ignore_fw_reg_offload_ind() - Check whether regdb offload indication * from FW needs to be ignored. - * * @psoc: Pointer to psoc */ bool tgt_reg_ignore_fw_reg_offload_ind(struct wlan_objmgr_psoc *psoc); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h index e6fc9674b2618b0e71e3e56b3ce6db550fabe821..657bce376bd664df5e319783693abf558501a634 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -31,22 +31,23 @@ typedef QDF_STATUS (*reg_event_cb)(void *status_struct); /** * ucfg_reg_set_band() - Sets the band information for the PDEV * @pdev: The physical pdev to set the band for - * @band: The set band parameter to configure for the physical device + * @band_bitmap: The band bitmap parameter (over reg_wifi_band) to configure + * for the physical device * * Return: QDF_STATUS */ QDF_STATUS ucfg_reg_set_band(struct wlan_objmgr_pdev *pdev, - enum band_info band); + uint32_t band_bitmap); /** * ucfg_reg_get_band() - Gets the band information for the PDEV * @pdev: The physical pdev to get the band for - * @band: The band parameter of the physical device + * @band_bitmap: The band parameter of the physical device * * Return: QDF_STATUS */ QDF_STATUS ucfg_reg_get_band(struct wlan_objmgr_pdev *pdev, - enum band_info *band); + uint32_t *band_bitmap); /** * ucfg_reg_notify_sap_event() - Notify regulatory domain for sap event @@ -66,7 +67,7 @@ QDF_STATUS ucfg_reg_notify_sap_event(struct wlan_objmgr_pdev *pdev, * * Return: QDF_STATUS */ -#ifdef DISABLE_CHANNEL_LIST +#if defined(DISABLE_CHANNEL_LIST) && defined(CONFIG_CHAN_NUM_API) void ucfg_reg_cache_channel_state(struct wlan_objmgr_pdev *pdev, uint32_t *channel_list, uint32_t num_channels); @@ -77,18 +78,53 @@ void ucfg_reg_cache_channel_state(struct wlan_objmgr_pdev *pdev, uint32_t num_channels) { } -#endif +#endif /* CONFIG_CHAN_NUM_API */ /** - * ucfg_reg_restore_cached_channels() - Cache the current state of the channles - * @pdev: The physical dev to cache the channels for + * ucfg_reg_cache_channel_freq_state() - Cache the current state of the + * channels based on the channel center frequency. + * @pdev: Pointer to pdev. + * @channel_list: List of the channels for which states need to be cached. + * @num_channels: Number of channels in the list. * * Return: QDF_STATUS */ +#if defined(DISABLE_CHANNEL_LIST) && defined(CONFIG_CHAN_FREQ_API) +void ucfg_reg_cache_channel_freq_state(struct wlan_objmgr_pdev *pdev, + uint32_t *channel_list, + uint32_t num_channels); +#else +static inline +void ucfg_reg_cache_channel_freq_state(struct wlan_objmgr_pdev *pdev, + uint32_t *channel_list, + uint32_t num_channels) +{ +} +#endif /* CONFIG_CHAN_FREQ_API */ + + #ifdef DISABLE_CHANNEL_LIST +/** + * ucfg_reg_disable_cached_channels() - Disable cached channels + * @pdev: The physical dev to cache the channels for + * + * Return: None + */ +void ucfg_reg_disable_cached_channels(struct wlan_objmgr_pdev *pdev); + +/** + * ucfg_reg_restore_cached_channels() - Restore disabled cached channels + * @pdev: The physical dev to cache the channels for + * + * Return: None + */ void ucfg_reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev); #else static inline +void ucfg_reg_disable_cached_channels(struct wlan_objmgr_pdev *pdev) +{ +} +static inline void ucfg_reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev) { } @@ -153,15 +189,6 @@ QDF_STATUS ucfg_reg_set_country(struct wlan_objmgr_pdev *dev, */ QDF_STATUS ucfg_reg_reset_country(struct wlan_objmgr_psoc *psoc); -/** - * ucfg_reg_get_curr_band() - Get the current band capability - * @pdev: The physical dev to get default country from - * @band: buffer to populate the band into - * - * Return: QDF_STATUS - */ -QDF_STATUS ucfg_reg_get_curr_band(struct wlan_objmgr_pdev *pdev, - enum band_info *band); /** * ucfg_reg_enable_dfs_channels() - Enable the use of DFS channels * @pdev: The physical dev to enable DFS channels for @@ -358,4 +385,23 @@ QDF_STATUS ucfg_reg_set_hal_reg_cap(struct wlan_objmgr_psoc *psoc, */ QDF_STATUS ucfg_set_ignore_fw_reg_offload_ind(struct wlan_objmgr_psoc *psoc); +/** + * ucfg_reg_get_unii_5g_bitmap() - get unii_5g_bitmap value + * @pdev: pdev pointer + * @bitmap: Pointer to retrieve unii_5g_bitmap of enum reg_unii_band. + * + * Return: QDF_STATUS + */ +#ifdef DISABLE_UNII_SHARED_BANDS +QDF_STATUS +ucfg_reg_get_unii_5g_bitmap(struct wlan_objmgr_pdev *pdev, uint8_t *bitmap); +#else +static inline QDF_STATUS +ucfg_reg_get_unii_5g_bitmap(struct wlan_objmgr_pdev *pdev, uint8_t *bitmap) +{ + *bitmap = 0; + return QDF_STATUS_SUCCESS; +} +#endif + #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_services_api.c index 281d33996bbbe9314d4154af0c351afe0700de9f..baa186a724ae204d8bca7b9f461ea5c978546af4 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_services_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_services_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,7 @@ #include <../../core/src/reg_offload_11d_scan.h> #include +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_get_channel_list_with_power() - Provide the channel list with power * @ch_list: pointer to the channel list. @@ -56,6 +58,7 @@ QDF_STATUS wlan_reg_get_channel_list_with_power(struct wlan_objmgr_pdev *pdev, */ return reg_get_channel_list_with_power(pdev, ch_list, num_chan); } +#endif /* CONFIG_CHAN_NUM_API */ /** * wlan_reg_read_default_country() - Read the default country for the regdomain @@ -81,6 +84,7 @@ QDF_STATUS wlan_reg_read_current_country(struct wlan_objmgr_psoc *psoc, return reg_read_current_country(psoc, country); } +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_get_channel_state() - Get channel state from regulatory * @ch: channel number. @@ -88,7 +92,7 @@ QDF_STATUS wlan_reg_read_current_country(struct wlan_objmgr_psoc *psoc, * Return: channel state */ enum channel_state wlan_reg_get_channel_state(struct wlan_objmgr_pdev *pdev, - uint32_t ch) + uint8_t ch) { /* * Get channel state from regulatory @@ -97,7 +101,7 @@ enum channel_state wlan_reg_get_channel_state(struct wlan_objmgr_pdev *pdev, } bool -wlan_reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint32_t ch) +wlan_reg_chan_has_dfs_attribute(struct wlan_objmgr_pdev *pdev, uint8_t ch) { return reg_chan_has_dfs_attribute(pdev, ch); } @@ -153,6 +157,7 @@ void wlan_reg_set_channel_params(struct wlan_objmgr_pdev *pdev, uint8_t ch, */ reg_set_channel_params(pdev, ch, sec_ch_2g, ch_params); } +#endif /* CONFIG_CHAN_NUM_API */ /** * wlan_reg_get_dfs_region () - Get the current dfs region @@ -171,8 +176,9 @@ QDF_STATUS wlan_reg_get_dfs_region(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } +#ifdef CONFIG_CHAN_NUM_API uint32_t wlan_reg_get_channel_reg_power(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num) + uint8_t chan_num) { return reg_get_channel_reg_power(pdev, chan_num); } @@ -183,11 +189,12 @@ uint32_t wlan_reg_get_channel_reg_power(struct wlan_objmgr_pdev *pdev, * * Return: int */ -uint32_t wlan_reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num) +qdf_freq_t wlan_reg_get_channel_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num) { return reg_get_channel_freq(pdev, chan_num); } +#endif /* CONFIG_CHAN_NUM_API */ QDF_STATUS wlan_reg_get_current_chan_list(struct wlan_objmgr_pdev *pdev, struct regulatory_channel *chan_list) @@ -195,6 +202,8 @@ QDF_STATUS wlan_reg_get_current_chan_list(struct wlan_objmgr_pdev *pdev, return reg_get_current_chan_list(pdev, chan_list); } +qdf_export_symbol(wlan_reg_get_current_chan_list); + /** * wlan_reg_get_bw_value() - give bandwidth value * bw: bandwidth enum @@ -206,6 +215,9 @@ uint16_t wlan_reg_get_bw_value(enum phy_ch_width bw) return reg_get_bw_value(bw); } +qdf_export_symbol(wlan_reg_get_bw_value); + +#ifdef CONFIG_CHAN_NUM_API /** * wlan_reg_get_bonded_channel_state() - Get 2G bonded channel state * @ch: channel number. @@ -224,6 +236,7 @@ enum channel_state wlan_reg_get_bonded_channel_state( return reg_get_5g_bonded_channel_state(pdev, ch, bw); } +#endif /* CONFIG_CHAN_NUM_API */ /** * wlan_reg_set_dfs_region () - Get the current dfs region @@ -254,6 +267,15 @@ uint16_t wlan_reg_dmn_get_opclass_from_channel(uint8_t *country, offset); } +uint8_t wlan_reg_get_opclass_from_freq_width(uint8_t *country, + qdf_freq_t freq, + uint8_t ch_width, + uint16_t behav_limit) +{ + return reg_dmn_get_opclass_from_freq_width(country, freq, ch_width, + behav_limit); +} + void wlan_reg_dmn_print_channels_in_opclass(uint8_t *country, uint8_t opclass) { @@ -280,6 +302,18 @@ uint16_t wlan_reg_dmn_get_curr_opclasses(uint8_t *num_classes, return reg_dmn_get_curr_opclasses(num_classes, class); } +QDF_STATUS +wlan_reg_get_opclass_details(struct wlan_objmgr_pdev *pdev, + struct regdmn_ap_cap_opclass_t *reg_ap_cap, + uint8_t *n_opclasses, + uint8_t max_supp_op_class, + bool global_tbl_lookup) +{ + return reg_get_opclass_details(pdev, reg_ap_cap, n_opclasses, + max_supp_op_class, + global_tbl_lookup); +} + QDF_STATUS wlan_regulatory_init(void) { QDF_STATUS status; @@ -315,7 +349,7 @@ QDF_STATUS wlan_regulatory_init(void) reg_err("failed to register reg psoc obj create handler"); goto unreg_pdev_create; } - + channel_map = channel_map_global; reg_debug("regulatory handlers registered with obj mgr"); return status; @@ -415,7 +449,6 @@ QDF_STATUS regulatory_psoc_close(struct wlan_objmgr_psoc *psoc) QDF_STATUS regulatory_pdev_open(struct wlan_objmgr_pdev *pdev) { struct wlan_objmgr_psoc *parent_psoc; - QDF_STATUS status; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; pdev_priv_obj = reg_get_pdev_obj(pdev); @@ -429,12 +462,9 @@ QDF_STATUS regulatory_pdev_open(struct wlan_objmgr_pdev *pdev) parent_psoc = wlan_pdev_get_psoc(pdev); - status = reg_send_scheduler_msg_sb(parent_psoc, pdev); - - if (QDF_IS_STATUS_ERROR(status)) - reg_err("scheduler send msg failed"); + reg_send_scheduler_msg_nb(parent_psoc, pdev); - return status; + return QDF_STATUS_SUCCESS; } QDF_STATUS regulatory_pdev_close(struct wlan_objmgr_pdev *pdev) @@ -463,6 +493,7 @@ QDF_STATUS regulatory_pdev_close(struct wlan_objmgr_pdev *pdev) return QDF_STATUS_SUCCESS; } +#ifdef CONFIG_CHAN_NUM_API void wlan_reg_update_nol_ch(struct wlan_objmgr_pdev *pdev, uint8_t *ch_list, uint8_t num_ch, bool nol_ch) { @@ -476,47 +507,48 @@ void wlan_reg_update_nol_history_ch(struct wlan_objmgr_pdev *pdev, reg_update_nol_history_ch(pdev, ch_list, num_ch, nol_history_ch); } -bool wlan_reg_is_dfs_ch(struct wlan_objmgr_pdev *pdev, - uint32_t chan) -{ - return reg_is_dfs_ch(pdev, chan); -} - bool wlan_reg_is_passive_or_disable_ch(struct wlan_objmgr_pdev *pdev, - uint32_t chan) + uint8_t chan) { return reg_is_passive_or_disable_ch(pdev, chan); } bool wlan_reg_is_disable_ch(struct wlan_objmgr_pdev *pdev, - uint32_t chan) + uint8_t chan) { return reg_is_disable_ch(pdev, chan); } +#endif /* CONFIG_CHAN_NUM_API */ -uint32_t wlan_reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, - uint32_t freq) +uint8_t wlan_reg_freq_to_chan(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) { return reg_freq_to_chan(pdev, freq); } -uint32_t wlan_reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num) +qdf_export_symbol(wlan_reg_freq_to_chan); + +#ifdef CONFIG_CHAN_NUM_API +qdf_freq_t wlan_reg_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num) { return reg_chan_to_freq(pdev, chan_num); } -uint16_t wlan_reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, - uint8_t chan_num) +qdf_export_symbol(wlan_reg_chan_to_freq); + +qdf_freq_t wlan_reg_legacy_chan_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan_num) { return reg_legacy_chan_to_freq(pdev, chan_num); } bool wlan_reg_chan_is_49ghz(struct wlan_objmgr_pdev *pdev, - uint8_t chan_num) + uint8_t chan_num) { return reg_chan_is_49ghz(pdev, chan_num); } +#endif /* CONFIG_CHAN_NUM_API */ QDF_STATUS wlan_reg_set_country(struct wlan_objmgr_pdev *pdev, uint8_t *country) @@ -565,6 +597,7 @@ bool wlan_reg_11d_enabled_on_host(struct wlan_objmgr_psoc *psoc) return reg_11d_enabled_on_host(psoc); } +#ifdef CONFIG_CHAN_NUM_API bool wlan_reg_is_dsrc_chan(struct wlan_objmgr_pdev *pdev, uint8_t chan_num) { return reg_is_dsrc_chan(pdev, chan_num); @@ -575,6 +608,7 @@ bool wlan_reg_is_etsi13_srd_chan(struct wlan_objmgr_pdev *pdev, { return reg_is_etsi13_srd_chan(pdev, chan_num); } +#endif /* CONFIG_CHAN_NUM_API */ bool wlan_reg_is_etsi13_regdmn(struct wlan_objmgr_pdev *pdev) { @@ -616,10 +650,10 @@ bool wlan_reg_is_11d_scan_inprogress(struct wlan_objmgr_psoc *psoc) } QDF_STATUS wlan_reg_get_freq_range(struct wlan_objmgr_pdev *pdev, - uint32_t *low_2g, - uint32_t *high_2g, - uint32_t *low_5g, - uint32_t *high_5g) + qdf_freq_t *low_2g, + qdf_freq_t *high_2g, + qdf_freq_t *low_5g, + qdf_freq_t *high_5g) { struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; @@ -651,88 +685,404 @@ QDF_STATUS wlan_reg_get_curr_regdomain(struct wlan_objmgr_pdev *pdev, return reg_get_curr_regdomain(pdev, cur_regdmn); } -uint32_t wlan_reg_min_24ghz_ch_num(void) +#ifdef CONFIG_CHAN_NUM_API +uint8_t wlan_reg_min_24ghz_ch_num(void) { return reg_min_24ghz_ch_num(); } -uint32_t wlan_reg_max_24ghz_ch_num(void) +uint8_t wlan_reg_max_24ghz_ch_num(void) { return reg_max_24ghz_ch_num(); } -uint32_t wlan_reg_min_5ghz_ch_num(void) +uint8_t wlan_reg_min_5ghz_ch_num(void) { return reg_min_5ghz_ch_num(); } -uint32_t wlan_reg_max_5ghz_ch_num(void) +uint8_t wlan_reg_max_5ghz_ch_num(void) { return reg_max_5ghz_ch_num(); } +#endif /* CONFIG_CHAN_NUM_API */ + +#ifdef CONFIG_CHAN_FREQ_API +qdf_freq_t wlan_reg_min_24ghz_chan_freq(void) +{ + return reg_min_24ghz_chan_freq(); +} + +qdf_freq_t wlan_reg_max_24ghz_chan_freq(void) +{ + return reg_max_24ghz_chan_freq(); +} -bool wlan_reg_is_24ghz_ch(uint32_t chan) +qdf_freq_t wlan_reg_min_5ghz_chan_freq(void) +{ + return reg_min_5ghz_chan_freq(); +} + +qdf_freq_t wlan_reg_max_5ghz_chan_freq(void) +{ + return reg_max_5ghz_chan_freq(); +} +#endif /* CONFIG_CHAN_FREQ_API */ + +#ifdef CONFIG_CHAN_NUM_API +bool wlan_reg_is_24ghz_ch(uint8_t chan) { return reg_is_24ghz_ch(chan); } -bool wlan_reg_is_5ghz_ch(uint32_t chan) +bool wlan_reg_is_5ghz_ch(uint8_t chan) { return reg_is_5ghz_ch(chan); } +#endif /* CONFIG_CHAN_NUM_API */ -bool wlan_reg_is_24ghz_ch_freq(uint32_t freq) +bool wlan_reg_is_24ghz_ch_freq(qdf_freq_t freq) { return reg_is_24ghz_ch_freq(freq); } -bool wlan_reg_is_5ghz_ch_freq(uint32_t freq) +bool wlan_reg_is_5ghz_ch_freq(qdf_freq_t freq) { return reg_is_5ghz_ch_freq(freq); } -#ifndef CONFIG_LEGACY_CHAN_ENUM -bool wlan_reg_is_49ghz_freq(uint32_t freq) +bool wlan_reg_is_freq_indoor(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq) +{ + return reg_is_freq_indoor(pdev, freq); +} + +#ifdef CONFIG_BAND_6GHZ +bool wlan_reg_is_6ghz_chan_freq(uint16_t freq) +{ + return reg_is_6ghz_chan_freq(freq); +} + +uint16_t wlan_reg_min_6ghz_chan_freq(void) +{ + return reg_min_6ghz_chan_freq(); +} + +uint16_t wlan_reg_max_6ghz_chan_freq(void) +{ + return reg_max_6ghz_chan_freq(); +} + +bool wlan_reg_is_6ghz_psc_chan_freq(uint16_t freq) +{ + return reg_is_6ghz_psc_chan_freq(freq); +} + +#endif /* CONFIG_BAND_6GHZ */ + +uint16_t +wlan_reg_get_band_channel_list(struct wlan_objmgr_pdev *pdev, + uint8_t band_mask, + struct regulatory_channel *channel_list) +{ + if (!pdev) { + reg_err("pdev object is NULL"); + return 0; + } + + return reg_get_band_channel_list(pdev, band_mask, channel_list); +} + +qdf_freq_t wlan_reg_chan_band_to_freq(struct wlan_objmgr_pdev *pdev, + uint8_t chan, uint8_t band_mask) +{ + return reg_chan_band_to_freq(pdev, chan, band_mask); +} + +bool wlan_reg_is_49ghz_freq(qdf_freq_t freq) { return reg_is_49ghz_freq(freq); } -#endif -uint32_t wlan_reg_ch_num(uint32_t ch_enum) +uint8_t wlan_reg_ch_num(uint32_t ch_enum) { return reg_ch_num(ch_enum); } -uint32_t wlan_reg_ch_to_freq(uint32_t ch_enum) +qdf_freq_t wlan_reg_ch_to_freq(uint32_t ch_enum) { return reg_ch_to_freq(ch_enum); } -bool wlan_reg_is_same_band_channels(uint32_t chan_num1, uint32_t chan_num2) +#ifdef CONFIG_CHAN_NUM_API +bool wlan_reg_is_same_band_channels(uint8_t chan_num1, uint8_t chan_num2) { return reg_is_same_band_channels(chan_num1, chan_num2); } -bool wlan_reg_is_channel_valid_5g_sbs(uint32_t curchan, uint32_t newchan) +bool wlan_reg_is_channel_valid_5g_sbs(uint8_t curchan, uint8_t newchan) { return reg_is_channel_valid_5g_sbs(curchan, newchan); } -enum band_info wlan_reg_chan_to_band(uint32_t chan_num) +enum band_info wlan_reg_chan_to_band(uint8_t chan_num) { return reg_chan_to_band(chan_num); } +qdf_export_symbol(wlan_reg_chan_to_band); + /** * wlan_reg_get_chan_enum() - Get channel enum for given channel number * @chan_num: Channel number * * Return: Channel enum */ -enum channel_enum wlan_reg_get_chan_enum(uint32_t chan_num) +enum channel_enum wlan_reg_get_chan_enum(uint8_t chan_num) { return reg_get_chan_enum(chan_num); } +#endif /* CONFIG_CHAN_NUM_API */ + +bool wlan_reg_is_regdmn_en302502_applicable(struct wlan_objmgr_pdev *pdev) +{ + return reg_is_regdmn_en302502_applicable(pdev); +} + +/** + * wlan_reg_modify_pdev_chan_range() - Compute current channel list for the + * modified regcap. + * @pdev: pointer to struct wlan_objmgr_pdev + * + */ +QDF_STATUS wlan_reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev) +{ + return reg_modify_pdev_chan_range(pdev); +} + +#ifdef DISABLE_UNII_SHARED_BANDS +QDF_STATUS wlan_reg_disable_chan_coex(struct wlan_objmgr_pdev *pdev, + uint8_t unii_5g_bitmap) +{ + return reg_disable_chan_coex(pdev, unii_5g_bitmap); +} +#endif + +#ifdef CONFIG_CHAN_FREQ_API +bool wlan_reg_is_same_band_freqs(qdf_freq_t freq1, qdf_freq_t freq2) +{ + return reg_is_same_band_freqs(freq1, freq2); +} + +bool wlan_reg_is_frequency_valid_5g_sbs(qdf_freq_t curfreq, qdf_freq_t newfreq) +{ + return reg_is_frequency_valid_5g_sbs(curfreq, newfreq); +} + +enum channel_enum wlan_reg_get_chan_enum_for_freq(qdf_freq_t freq) +{ + return reg_get_chan_enum_for_freq(freq); +} + +bool wlan_reg_is_etsi13_srd_chan_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + return reg_is_etsi13_srd_chan_for_freq(pdev, freq); +} + +bool wlan_reg_is_dsrc_freq(qdf_freq_t freq) +{ + return reg_is_dsrc_freq(freq); +} + +void wlan_reg_update_nol_ch_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *chan_freq_list, + uint8_t num_ch, + bool nol_ch) +{ + reg_update_nol_ch_for_freq(pdev, chan_freq_list, num_ch, nol_ch); +} + +void wlan_reg_update_nol_history_ch_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t *ch_list, + uint8_t num_ch, + bool nol_history_ch) +{ + reg_update_nol_history_ch_for_freq(pdev, + ch_list, + num_ch, + nol_history_ch); +} + +bool wlan_reg_is_dfs_for_freq(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq) +{ + return reg_is_dfs_for_freq(pdev, freq); +} + +bool wlan_reg_is_passive_or_disable_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + return reg_is_passive_or_disable_for_freq(pdev, freq); +} + +bool wlan_reg_is_disable_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + return reg_is_disable_for_freq(pdev, freq); +} + +QDF_STATUS +wlan_reg_get_channel_list_with_power_for_freq(struct wlan_objmgr_pdev *pdev, + struct channel_power *ch_list, + uint8_t *num_chan) +{ + return reg_get_channel_list_with_power_for_freq(pdev, + ch_list, + num_chan); +} + +bool +wlan_reg_chan_has_dfs_attribute_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + return reg_chan_has_dfs_attribute_for_freq(pdev, freq); +} + +enum channel_state +wlan_reg_get_5g_bonded_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + enum phy_ch_width bw) +{ + return reg_get_5g_bonded_channel_state_for_freq(pdev, freq, bw); +} + +enum channel_state +wlan_reg_get_2g_bonded_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + qdf_freq_t sec_ch_freq, + enum phy_ch_width bw) +{ + return reg_get_2g_bonded_channel_state_for_freq(pdev, + freq, + sec_ch_freq, + bw); +} + +void wlan_reg_set_channel_params_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + qdf_freq_t sec_ch_2g_freq, + struct ch_params *ch_params) +{ + reg_set_channel_params_for_freq(pdev, freq, sec_ch_2g_freq, ch_params); +} + +enum channel_state +wlan_reg_get_channel_state_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + return reg_get_channel_state_for_freq(pdev, freq); +} + +uint8_t wlan_reg_get_channel_reg_power_for_freq(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq) +{ + return reg_get_channel_reg_power_for_freq(pdev, freq); +} + +enum reg_wifi_band wlan_reg_freq_to_band(qdf_freq_t freq) +{ + return reg_freq_to_band(freq); +} +qdf_export_symbol(wlan_reg_freq_to_band); + +qdf_freq_t wlan_reg_min_chan_freq(void) +{ + return reg_min_chan_freq(); +} + +qdf_freq_t wlan_reg_max_chan_freq(void) +{ + return reg_max_chan_freq(); +} + +void wlan_reg_freq_width_to_chan_op_class(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + uint16_t chan_width, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num) +{ + return reg_freq_width_to_chan_op_class(pdev, freq, chan_width, + global_tbl_lookup, + behav_limit, + op_class, + chan_num); +} + +void wlan_reg_freq_width_to_chan_op_class_auto(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + uint16_t chan_width, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num) +{ + reg_freq_width_to_chan_op_class_auto(pdev, freq, chan_width, + global_tbl_lookup, + behav_limit, + op_class, + chan_num); +} + +void wlan_reg_freq_to_chan_op_class(struct wlan_objmgr_pdev *pdev, + qdf_freq_t freq, + bool global_tbl_lookup, + uint16_t behav_limit, + uint8_t *op_class, + uint8_t *chan_num) +{ + return reg_freq_to_chan_op_class(pdev, freq, + global_tbl_lookup, + behav_limit, + op_class, + chan_num); +} + +bool wlan_reg_country_opclass_freq_check(struct wlan_objmgr_pdev *pdev, + const uint8_t country[3], + uint8_t op_class, + qdf_freq_t chan_freq) +{ + return reg_country_opclass_freq_check(pdev, country, + op_class, chan_freq); +} + +enum channel_state +wlan_reg_get_5g_bonded_channel_and_state_for_freq(struct wlan_objmgr_pdev *pdev, + uint16_t freq, + enum phy_ch_width bw, + const + struct bonded_channel_freq + **bonded_chan_ptr_ptr) +{ + /* + * Get channel frequencies and state from regulatory + */ + return reg_get_5g_bonded_channel_for_freq(pdev, freq, bw, + bonded_chan_ptr_ptr); +} + +qdf_export_symbol(wlan_reg_get_5g_bonded_channel_and_state_for_freq); + +#endif /* CONFIG CHAN FREQ API */ + +uint16_t wlan_reg_get_op_class_width(struct wlan_objmgr_pdev *pdev, + uint8_t op_class, + bool global_tbl_lookup) +{ + return reg_get_op_class_width(pdev, op_class, + global_tbl_lookup); +} bool wlan_reg_is_6ghz_op_class(struct wlan_objmgr_pdev *pdev, uint8_t op_class) @@ -740,7 +1090,36 @@ bool wlan_reg_is_6ghz_op_class(struct wlan_objmgr_pdev *pdev, return reg_is_6ghz_op_class(pdev, op_class); } -bool wlan_reg_is_6ghz_supported(struct wlan_objmgr_pdev *pdev) +bool wlan_reg_is_6ghz_supported(struct wlan_objmgr_psoc *psoc) +{ + return reg_is_6ghz_supported(psoc); +} + +#ifdef HOST_OPCLASS_EXT +qdf_freq_t +wlan_reg_country_chan_opclass_to_freq(struct wlan_objmgr_pdev *pdev, + const uint8_t country[3], + uint8_t chan, uint8_t op_class, + bool strict) +{ + return reg_country_chan_opclass_to_freq(pdev, country, chan, op_class, + strict); +} +#endif + +uint16_t wlan_reg_chan_opclass_to_freq(uint8_t chan, + uint8_t op_class, + bool global_tbl_lookup) +{ + if (!chan || !op_class) + return 0; + + return reg_chan_opclass_to_freq(chan, op_class, global_tbl_lookup); +} + +#ifdef CONFIG_REG_CLIENT +enum band_info wlan_reg_band_bitmap_to_band_info(uint32_t band_bitmap) { - return reg_is_6ghz_supported(pdev); + return reg_band_bitmap_to_band_info(band_bitmap); } +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c index b42f6ec4523fd00a312a9ccf71d7a33d3f7ce526..7cc643217795d819c5e56eb882ea0bc860ee4b51 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -119,15 +119,15 @@ QDF_STATUS ucfg_reg_get_current_cc(struct wlan_objmgr_pdev *pdev, #ifdef CONFIG_REG_CLIENT QDF_STATUS ucfg_reg_set_band(struct wlan_objmgr_pdev *pdev, - enum band_info band) + uint32_t band_bitmap) { - return reg_set_band(pdev, band); + return reg_set_band(pdev, band_bitmap); } QDF_STATUS ucfg_reg_get_band(struct wlan_objmgr_pdev *pdev, - enum band_info *band) + uint32_t *band_bitmap) { - return reg_get_band(pdev, band); + return reg_get_band(pdev, band_bitmap); } /** @@ -227,13 +227,6 @@ QDF_STATUS ucfg_reg_enable_dfs_channels(struct wlan_objmgr_pdev *pdev, return reg_enable_dfs_channels(pdev, dfs_enable); } -QDF_STATUS ucfg_reg_get_curr_band(struct wlan_objmgr_pdev *pdev, - enum band_info *band) -{ - return reg_get_curr_band(pdev, band); - -} - void ucfg_reg_register_chan_change_callback(struct wlan_objmgr_psoc *psoc, void *cbk, void *arg) { @@ -287,6 +280,24 @@ QDF_STATUS ucfg_reg_set_hal_reg_cap(struct wlan_objmgr_psoc *psoc, qdf_export_symbol(ucfg_reg_set_hal_reg_cap); #ifdef DISABLE_CHANNEL_LIST +#ifdef CONFIG_CHAN_FREQ_API +/** + * ucfg_reg_cache_channel_freq_state() - Cache the current state of the channels + * based of the channel center frequency. + * @pdev: The physical dev to cache the channels for + * @channel_list: List of the channels for which states needs to be cached + * @num_channels: Number of channels in the list + * + */ +void ucfg_reg_cache_channel_freq_state(struct wlan_objmgr_pdev *pdev, + uint32_t *channel_list, + uint32_t num_channels) +{ + reg_cache_channel_freq_state(pdev, channel_list, num_channels); +} +#endif /* CONFIG_CHAN_FREQ_API */ + +#ifdef CONFIG_CHAN_NUM_API /** * ucfg_reg_cache_channel_state() - Cache the current state of the channles * @pdev: The physical dev to cache the channels for @@ -299,18 +310,29 @@ void ucfg_reg_cache_channel_state(struct wlan_objmgr_pdev *pdev, { reg_cache_channel_state(pdev, channel_list, num_channels); } +#endif /* CONFIG_CHAN_NUM_API */ -/** - * ucfg_reg_restore_cached_channels() - Cache the current state of the channles - * @pdev: The physical dev to cache the channels for - */ void ucfg_reg_restore_cached_channels(struct wlan_objmgr_pdev *pdev) { reg_restore_cached_channels(pdev); } + +void ucfg_reg_disable_cached_channels(struct wlan_objmgr_pdev *pdev) +{ + reg_disable_cached_channels(pdev); +} + #endif QDF_STATUS ucfg_set_ignore_fw_reg_offload_ind(struct wlan_objmgr_psoc *psoc) { return reg_set_ignore_fw_reg_offload_ind(psoc); } + +#ifdef DISABLE_UNII_SHARED_BANDS +QDF_STATUS +ucfg_reg_get_unii_5g_bitmap(struct wlan_objmgr_pdev *pdev, uint8_t *bitmap) +{ + return reg_get_unii_5g_bitmap(pdev, bitmap); +} +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_bss_score.c b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_bss_score.c index dce2b85f6980491e94296cee96c59a476d7589ce..22802dca3b45e1dd899b88f700ef2f359b99aabe 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_bss_score.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_bss_score.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 @@ -26,6 +27,7 @@ #include "wlan_policy_mgr_api.h" #endif #include "wlan_reg_services_api.h" +#include "wlan_crypto_global_api.h" #define SCM_20MHZ_BW_INDEX 0 #define SCM_40MHZ_BW_INDEX 1 @@ -116,10 +118,10 @@ void scm_validate_scoring_config(struct scoring_config *score_cfg) score_cfg->weight_cfg.channel_congestion_weightage + score_cfg->weight_cfg.oce_wan_weightage; - if (total_weight > BEST_CANDIDATE_MAX_WEIGHT) { + if (total_weight > MAX_BSS_SCORE) { scm_err("total weight is greater than %d fallback to default values", - BEST_CANDIDATE_MAX_WEIGHT); + MAX_BSS_SCORE); score_cfg->weight_cfg.rssi_weightage = RSSI_WEIGHTAGE; score_cfg->weight_cfg.ht_caps_weightage = @@ -387,7 +389,7 @@ static int32_t scm_calculate_bandwidth_score( bw_weight_per_idx = score_config->bandwidth_weight_per_index; - if (WLAN_CHAN_IS_2GHZ(entry->channel.chan_idx)) { + if (WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq)) { cbmode = score_config->cb_mode_24G; if (score_config->vht_24G_cap) is_vht = true; @@ -477,17 +479,13 @@ static int32_t scm_get_congestion_pct(struct scan_cache_entry *entry) */ congestion = SCM_MAX_CHANNEL_UTILIZATION - est_air_time_percentage; - if (!congestion) - congestion = 1; - } else if (util_scan_entry_qbssload(entry)) { + } else if (entry->qbss_chan_load) { ap_load = (entry->qbss_chan_load * BEST_CANDIDATE_MAX_WEIGHT); /* * Calculate ap_load in % from qbss channel load from * 0-255 range */ congestion = qdf_do_div(ap_load, MAX_AP_LOAD); - if (!congestion) - congestion = 1; } return congestion; @@ -653,7 +651,8 @@ static uint32_t scm_get_sta_nss(struct wlan_objmgr_psoc *psoc, * NSS as 2*2. */ - if (policy_mgr_is_chnl_in_diff_band(psoc, bss_channel) && + if (policy_mgr_is_chnl_in_diff_band( + psoc, wlan_chan_to_freq(bss_channel)) && policy_mgr_is_hw_dbs_capable(psoc) && !(policy_mgr_is_hw_dbs_2x2_capable(psoc))) return 1; @@ -674,6 +673,36 @@ static uint32_t scm_get_sta_nss(struct wlan_objmgr_psoc *psoc, } #endif +/** + * scm_calculate_sae_pk_ap_weightage() - Calculate SAE-PK AP weightage + * @entry: bss entry + * @score_params: bss score params + * @sae_pk_cap_present: sae_pk cap presetn in RSNXE capability field + * + * Return: SAE-PK AP weightage score + */ +static uint32_t +scm_calculate_sae_pk_ap_weightage(struct scan_cache_entry *entry, + struct scoring_config *score_params, + bool *sae_pk_cap_present) +{ + uint8_t *rsnxe_ie, *rsnxe_cap, cap_len; + + rsnxe_ie = util_scan_entry_rsnxe(entry); + + rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnxe_ie, &cap_len); + + if (!rsnxe_cap) + return 0; + + *sae_pk_cap_present = *rsnxe_cap & WLAN_CRYPTO_RSNX_CAP_SAE_PK; + if (*sae_pk_cap_present) + return score_params->weight_cfg.sae_pk_ap_weightage * + MAX_INDEX_SCORE; + + return 0; +} + int scm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, struct scan_default_params *params, struct scan_cache_entry *entry, @@ -698,11 +727,14 @@ int scm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, int8_t rssi_pref_5g_rssi_thresh; bool same_bucket = false; bool ap_su_beam_former = false; + uint32_t sae_pk_score = 0; + bool sae_pk_cap_present = 0; struct wlan_ie_vhtcaps *vht_cap; struct scoring_config *score_config; struct weight_config *weight_config; struct wlan_scan_obj *scan_obj; uint32_t sta_nss; + struct wlan_objmgr_pdev *pdev = NULL; scan_obj = wlan_psoc_get_scan_obj(psoc); if (!scan_obj) { @@ -730,7 +762,7 @@ int scm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, weight_config->ht_caps_weightage; score += ht_score; - if (WLAN_CHAN_IS_2GHZ(entry->channel.chan_idx)) { + if (WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq)) { if (score_config->vht_24G_cap) is_vht = true; } else if (score_config->vht_cap) { @@ -787,13 +819,14 @@ int scm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, */ if ((entry->rssi_raw > rssi_pref_5g_rssi_thresh) && !same_bucket) { - if (WLAN_CHAN_IS_5GHZ(entry->channel.chan_idx)) + if (WLAN_REG_IS_5GHZ_CH_FREQ(entry->channel.chan_freq)) band_score = weight_config->chan_band_weightage * WLAN_GET_SCORE_PERCENTAGE( score_config->band_weight_per_index, SCM_BAND_5G_INDEX); - } else if (WLAN_CHAN_IS_2GHZ(entry->channel.chan_idx)) { + } else if (WLAN_REG_IS_24GHZ_CH_FREQ( + entry->channel.chan_freq)) { band_score = weight_config->chan_band_weightage * WLAN_GET_SCORE_PERCENTAGE( score_config->band_weight_per_index, @@ -806,10 +839,24 @@ int scm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, score += oce_wan_score; } - sta_nss = scm_get_sta_nss(psoc, entry->channel.chan_idx, + sae_pk_score = scm_calculate_sae_pk_ap_weightage(entry, score_config, + &sae_pk_cap_present); + score += sae_pk_score; + + pdev = wlan_objmgr_get_pdev_by_id(psoc, entry->pdev_id, WLAN_SCAN_ID); + if (!pdev) { + scm_err("pdev is NULL"); + return 0; + } + + sta_nss = scm_get_sta_nss(psoc, + wlan_reg_freq_to_chan( + pdev, + entry->channel.chan_freq), score_config->vdev_nss_24g, score_config->vdev_nss_5g); + wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID); /* * If station support nss as 2*2 but AP support NSS as 1*1, * this AP will be given half weight compare to AP which are having @@ -825,28 +872,30 @@ int scm_calculate_bss_score(struct wlan_objmgr_psoc *psoc, score_config->beamformee_cap, score_config->cb_mode_24G, score_config->cb_mode_5G, sta_nss); - scm_nofl_debug("Candidate(%pM chan %d): rssi %d HT %d VHT %d HE %d su bfer %d phy %d air time frac %d qbss %d cong_pct %d NSS %d", - entry->bssid.bytes, entry->channel.chan_idx, + scm_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d HT %d VHT %d HE %d su bfer %d phy %d air time frac %d qbss %d cong_pct %d NSS %d sae_pk_cap_present %d", + QDF_MAC_ADDR_REF(entry->bssid.bytes), + entry->channel.chan_freq, entry->rssi_raw, util_scan_entry_htcap(entry) ? 1 : 0, util_scan_entry_vhtcap(entry) ? 1 : 0, util_scan_entry_hecap(entry) ? 1 : 0, ap_su_beam_former, entry->phy_mode, entry->air_time_fraction, - entry->qbss_chan_load, congestion_pct, entry->nss); + entry->qbss_chan_load, congestion_pct, entry->nss, + sae_pk_cap_present); - scm_nofl_debug("Scores: prorated_pcnt %d rssi %d pcl %d ht %d vht %d he %d bfee %d bw %d band %d congestion %d nss %d oce wan %d TOTAL %d", + scm_nofl_debug("Scores: prorated_pcnt %d rssi %d pcl %d ht %d vht %d he %d bfee %d bw %d band %d congestion %d nss %d oce wan %d sae_pk %d TOTAL %d", prorated_pcnt, rssi_score, pcl_score, ht_score, vht_score, he_score, beamformee_score, bandwidth_score, band_score, congestion_score, nss_score, oce_wan_score, - score); + sae_pk_score, score); entry->bss_score = score; return score; } -bool scm_get_pcl_weight_of_channel(int channel_id, - struct scan_filter *filter, - int *pcl_chan_weight, - uint8_t *weight_list) +bool scm_get_pcl_weight_of_channel(uint32_t chan_freq, + struct scan_filter *filter, + int *pcl_chan_weight, + uint8_t *weight_list) { int i; bool found = false; @@ -855,7 +904,7 @@ bool scm_get_pcl_weight_of_channel(int channel_id, return found; for (i = 0; i < filter->num_of_pcl_channels; i++) { - if (filter->pcl_channel_list[i] == channel_id) { + if (filter->pcl_freq_list[i] == chan_freq) { *pcl_chan_weight = filter->pcl_weight_list[i]; found = true; break; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db.c b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db.c index 7e4ea15c8a054a06a877d699446eed8d7530e554..2c6b2a4ffc59366f886ef26a8e0e29307129138e 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -53,6 +53,114 @@ #include #include +#ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO + +struct channel_list_db *scm_get_rnr_channel_db(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_scan_obj *scan_obj = NULL; + + scan_obj = wlan_psoc_get_scan_obj(psoc); + + if (!scan_obj) + return NULL; + + return &scan_obj->rnr_channel_db; +} + +struct meta_rnr_channel *scm_get_chan_meta(struct wlan_objmgr_psoc *psoc, + uint32_t chan_freq) +{ + int i; + struct channel_list_db *rnr_channel_db; + + if (!psoc || !chan_freq || !wlan_reg_is_6ghz_chan_freq(chan_freq)) + return NULL; + + rnr_channel_db = scm_get_rnr_channel_db(psoc); + if (!rnr_channel_db) + return NULL; + + for (i = 0; i < QDF_ARRAY_SIZE(rnr_channel_db->channel); i++) + if (rnr_channel_db->channel[i].chan_freq == chan_freq) + return &rnr_channel_db->channel[i]; + + return NULL; +} + +static void scm_add_rnr_channel_db(struct wlan_objmgr_psoc *psoc, + struct scan_cache_entry *entry) +{ + uint32_t chan_freq; + uint8_t is_6g_bss, i; + struct meta_rnr_channel *channel; + struct rnr_bss_info *rnr_bss; + struct scan_rnr_node *rnr_node; + + chan_freq = entry->channel.chan_freq; + is_6g_bss = wlan_reg_is_6ghz_chan_freq(chan_freq); + + /* Return if the BSS is not 6G and RNR IE is not present */ + if (!(is_6g_bss || entry->ie_list.rnrie)) + return; + + scm_debug("BSS freq %d BSSID: "QDF_MAC_ADDR_FMT, chan_freq, + QDF_MAC_ADDR_REF(entry->bssid.bytes)); + if (is_6g_bss) { + channel = scm_get_chan_meta(psoc, chan_freq); + if (!channel) { + scm_debug("Failed to get chan Meta freq %d", chan_freq); + return; + } + channel->bss_beacon_probe_count++; + channel->beacon_probe_last_time_found = entry->scan_entry_time; + } + + /* + * If scan entry got RNR IE then loop through all + * entries and increase the BSS count in respective channels + */ + if (!entry->ie_list.rnrie) + return; + + for (i = 0; i < MAX_RNR_BSS; i++) { + rnr_bss = &entry->rnr.bss_info[i]; + /* Skip if entry is not valid */ + if (!rnr_bss->channel_number) + continue; + chan_freq = wlan_reg_chan_opclass_to_freq(rnr_bss->channel_number, + rnr_bss->operating_class, + false); + channel = scm_get_chan_meta(psoc, chan_freq); + if (!channel) { + scm_debug("Failed to get chan Meta freq %d", chan_freq); + continue; + } + channel->bss_beacon_probe_count++; + /* Don't add RNR entry if list is full */ + if (qdf_list_size(&channel->rnr_list) >= WLAN_MAX_RNR_COUNT) { + scm_debug("List is full"); + return; + } + + rnr_node = qdf_mem_malloc(sizeof(struct scan_rnr_node)); + if (!rnr_node) + return; + rnr_node->entry.timestamp = entry->scan_entry_time; + if (!qdf_is_macaddr_zero(&rnr_bss->bssid)) + qdf_mem_copy(&rnr_node->entry.bssid, + &rnr_bss->bssid, + QDF_MAC_ADDR_SIZE); + if (rnr_bss->short_ssid) + rnr_node->entry.short_ssid = rnr_bss->short_ssid; + scm_debug("Add freq %d: "QDF_MAC_ADDR_FMT" short ssid %x", chan_freq, + QDF_MAC_ADDR_REF(rnr_bss->bssid.bytes), + rnr_bss->short_ssid); + qdf_list_insert_back(&channel->rnr_list, + &rnr_node->node); + } +} +#endif + /** * scm_del_scan_node() - API to remove scan node from the list * @list: hash list @@ -183,7 +291,6 @@ static void scm_scan_entry_del(struct scan_dbs *scan_db, return; } scan_node->cookie = 0; - scm_scan_entry_put_ref(scan_db, scan_node, false); } @@ -316,8 +423,8 @@ static void scm_check_and_age_out(struct scan_dbs *scan_db, { if (util_scan_entry_age(node->entry) >= scan_aging_time) { - scm_debug("Aging out BSSID: %pM with age %lu ms", - node->entry->bssid.bytes, + scm_debug("Aging out BSSID: "QDF_MAC_ADDR_FMT" with age %lu ms", + QDF_MAC_ADDR_REF(node->entry->bssid.bytes), util_scan_entry_age(node->entry)); qdf_spin_lock_bh(&scan_db->scan_db_lock); scm_scan_entry_del(scan_db, node); @@ -401,9 +508,9 @@ static QDF_STATUS scm_flush_oldest_entry(struct scan_dbs *scan_db) } if (oldest_node) { - scm_debug("Flush oldest BSSID: %pM with age %lu ms", - oldest_node->entry->bssid.bytes, - util_scan_entry_age(oldest_node->entry)); + scm_debug("Flush oldest BSSID: "QDF_MAC_ADDR_FMT" with age %lu ms", + QDF_MAC_ADDR_REF(oldest_node->entry->bssid.bytes), + util_scan_entry_age(oldest_node->entry)); /* Release ref_cnt taken for oldest_node and delete it */ qdf_spin_lock_bh(&scan_db->scan_db_lock); scm_scan_entry_del(scan_db, oldest_node); @@ -512,8 +619,8 @@ scm_copy_info_from_dup_entry(struct wlan_objmgr_pdev *pdev, scan_params->frm_subtype == MGMT_SUBTYPE_BEACON && !util_scan_is_null_ssid(&scan_params->ssid)) { if (scan_obj->cb.unlink_bss) { - scm_debug("Hidden AP %pM switch to non-hidden SSID, So unlink the entry", - scan_entry->bssid.bytes); + scm_debug("Hidden AP "QDF_MAC_ADDR_FMT" switch to non-hidden SSID, So unlink the entry", + QDF_MAC_ADDR_REF(scan_entry->bssid.bytes)); scan_obj->cb.unlink_bss(pdev, scan_entry); } } @@ -559,37 +666,45 @@ scm_copy_info_from_dup_entry(struct wlan_objmgr_pdev *pdev, if ((scan_params->frm_subtype == MGMT_SUBTYPE_BEACON) && !util_scan_entry_htinfo(scan_params) && !util_scan_entry_ds_param(scan_params) && - (scan_params->channel.chan_idx != scan_entry->channel.chan_idx) && + (scan_params->channel.chan_freq != scan_entry->channel.chan_freq) && (scan_params->rssi_raw < ADJACENT_CHANNEL_RSSI_THRESHOLD)) { - scan_params->channel.chan_idx = scan_entry->channel.chan_idx; + scan_params->channel.chan_freq = scan_entry->channel.chan_freq; scan_params->channel_mismatch = true; } /* Use old value for rssi if beacon was heard on adjacent channel. */ if (scan_params->channel_mismatch) { + scan_params->snr = scan_entry->snr; + scan_params->avg_snr = scan_entry->avg_snr; scan_params->rssi_raw = scan_entry->rssi_raw; scan_params->avg_rssi = scan_entry->avg_rssi; scan_params->rssi_timestamp = scan_entry->rssi_timestamp; } else { - /* If elapsed time since last rssi update for this + /* If elapsed time since last rssi and snr update for this * entry is smaller than a thresold, calculate a - * running average of the RSSI values. - * Otherwise new frames RSSI is more representive + * running average of the RSSI and SNR values. + * Otherwise new frames RSSI and SNR are more representive * of the signal strength. */ time_gap = scan_params->scan_entry_time - scan_entry->rssi_timestamp; - if (time_gap > WLAN_RSSI_AVERAGING_TIME) + if (time_gap > WLAN_RSSI_AVERAGING_TIME) { scan_params->avg_rssi = WLAN_RSSI_IN(scan_params->rssi_raw); + scan_params->avg_snr = + WLAN_SNR_IN(scan_params->snr); + } else { - /* Copy previous average rssi to new entry */ + /* Copy previous average rssi and snr to new entry */ + scan_params->avg_snr = scan_entry->avg_snr; scan_params->avg_rssi = scan_entry->avg_rssi; /* Average with previous samples */ WLAN_RSSI_LPF(scan_params->avg_rssi, - scan_params->rssi_raw); + scan_params->rssi_raw); + WLAN_SNR_LPF(scan_params->avg_snr, + scan_params->snr); } scan_params->rssi_timestamp = scan_params->scan_entry_time; @@ -691,20 +806,22 @@ static QDF_STATUS scm_add_update_entry(struct wlan_objmgr_psoc *psoc, if (scan_params->ie_list.csa || scan_params->ie_list.xcsa || scan_params->ie_list.cswrp) - scm_debug("CSA IE present for BSSID: %pM", - scan_params->bssid.bytes); + scm_debug("CSA IE present for BSSID: "QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(scan_params->bssid.bytes)); is_dup_found = scm_find_duplicate(pdev, scan_obj, scan_db, scan_params, &dup_node); security_type = scan_params->security_type; - scm_nofl_debug("Received %s: %pM \"%.*s\" chan %d rssi %d tsf_delta %u seq %d phy %d hidden %d mismatch %d %s%s%s%s pdev %d boot_time %llu ns", + scm_nofl_debug("Received %s: "QDF_MAC_ADDR_FMT" \"%.*s\" freq %d rssi %d tsf_delta %u seq %d snr %d phy %d hidden %d mismatch %d %s%s%s%s pdev %d boot_time %llu ns", (scan_params->frm_subtype == MGMT_SUBTYPE_PROBE_RESP) ? - "prb rsp" : "bcn", scan_params->bssid.bytes, + "prb rsp" : "bcn", + QDF_MAC_ADDR_REF(scan_params->bssid.bytes), scan_params->ssid.length, scan_params->ssid.ssid, - scan_params->channel.chan_idx, scan_params->rssi_raw, + scan_params->channel.chan_freq, scan_params->rssi_raw, scan_params->tsf_delta, scan_params->seq_num, - scan_params->phy_mode, scan_params->is_hidden_ssid, + scan_params->snr, scan_params->phy_mode, + scan_params->is_hidden_ssid, scan_params->channel_mismatch, security_type & SCAN_SECURITY_TYPE_WPA ? "[WPA]" : "", security_type & SCAN_SECURITY_TYPE_RSN ? "[RSN]" : "", @@ -801,7 +918,7 @@ QDF_STATUS __scm_handle_bcn_probe(struct scan_bcn_probe_event *bcn) } if (bcn->frm_type == MGMT_SUBTYPE_BEACON && - utils_is_dfs_ch(pdev, bcn->rx_data->channel)) { + wlan_reg_is_dfs_for_freq(pdev, bcn->rx_data->chan_freq)) { util_scan_add_hidden_ssid(pdev, bcn->buf); } @@ -810,8 +927,8 @@ QDF_STATUS __scm_handle_bcn_probe(struct scan_bcn_probe_event *bcn) qdf_nbuf_len(bcn->buf), bcn->frm_type, bcn->rx_data); if (!scan_list || qdf_list_empty(scan_list)) { - scm_debug("failed to unpack %d frame BSSID: %pM", - bcn->frm_type, hdr->i_addr3); + scm_debug("failed to unpack %d frame BSSID: "QDF_MAC_ADDR_FMT, + bcn->frm_type, QDF_MAC_ADDR_REF(hdr->i_addr3)); status = QDF_STATUS_E_INVAL; goto free_nbuf; } @@ -820,8 +937,8 @@ QDF_STATUS __scm_handle_bcn_probe(struct scan_bcn_probe_event *bcn) for (i = 0; i < list_count; i++) { status = qdf_list_remove_front(scan_list, &next_node); if (QDF_IS_STATUS_ERROR(status) || !next_node) { - scm_debug("list remove failure i:%d, lsize:%d, BSSID: %pM", - i, list_count, hdr->i_addr3); + scm_debug("list remove failure i:%d, lsize:%d, BSSID: "QDF_MAC_ADDR_FMT, + i, list_count, QDF_MAC_ADDR_REF(hdr->i_addr3)); status = QDF_STATUS_E_INVAL; goto free_nbuf; } @@ -833,16 +950,28 @@ QDF_STATUS __scm_handle_bcn_probe(struct scan_bcn_probe_event *bcn) if (scan_obj->drop_bcn_on_chan_mismatch && scan_entry->channel_mismatch) { - scm_nofl_debug("Drop frame for chan mismatch %pM Seq Num: %d chan %d RSSI %d", - scan_entry->bssid.bytes, + scm_nofl_debug("Drop frame for chan mismatch "QDF_MAC_ADDR_FMT" Seq Num: %d freq %d RSSI %d", + QDF_MAC_ADDR_REF(scan_entry->bssid.bytes), + scan_entry->seq_num, + scan_entry->channel.chan_freq, + scan_entry->rssi_raw); + util_scan_free_cache_entry(scan_entry); + qdf_mem_free(scan_node); + continue; + } + /* Do not add invalid channel entry as kernel will reject it */ + if (scan_obj->drop_bcn_on_invalid_freq && + wlan_reg_is_disable_for_freq(pdev, + scan_entry->channel.chan_freq)) { + scm_nofl_debug("Drop frame for invalid freq %d: "QDF_MAC_ADDR_FMT" Seq Num: %d RSSI %d", + scan_entry->channel.chan_freq, + QDF_MAC_ADDR_REF(scan_entry->bssid.bytes), scan_entry->seq_num, - scan_entry->channel.chan_idx, scan_entry->rssi_raw); util_scan_free_cache_entry(scan_entry); qdf_mem_free(scan_node); continue; } - if (scan_obj->cb.update_beacon) scan_obj->cb.update_beacon(pdev, scan_entry); @@ -851,8 +980,8 @@ QDF_STATUS __scm_handle_bcn_probe(struct scan_bcn_probe_event *bcn) status = scm_add_update_entry(psoc, pdev, scan_entry); if (QDF_IS_STATUS_ERROR(status)) { - scm_debug("failed to add entry for BSSID: %pM Seq Num: %d", - scan_entry->bssid.bytes, + scm_debug("failed to add entry for BSSID: "QDF_MAC_ADDR_FMT" Seq Num: %d", + QDF_MAC_ADDR_REF(scan_entry->bssid.bytes), scan_entry->seq_num); util_scan_free_cache_entry(scan_entry); qdf_mem_free(scan_node); @@ -916,16 +1045,15 @@ static void scm_list_insert_sorted(struct wlan_objmgr_psoc *psoc, scm_err("wlan_scan_psoc_get_def_params failed"); return; } - if (filter->num_of_pcl_channels > 0 && (scan_node->entry->rssi_raw > SCM_PCL_RSSI_THRESHOLD)) { if (scm_get_pcl_weight_of_channel( - scan_node->entry->channel.chan_idx, + scan_node->entry->channel.chan_freq, filter, &pcl_chan_weight, filter->pcl_weight_list)) { - scm_debug("pcl channel %d pcl_chan_weight %d", - scan_node->entry->channel.chan_idx, - pcl_chan_weight); + scm_debug("pcl freq %d pcl_chan_weight %d", + scan_node->entry->channel.chan_freq, + pcl_chan_weight); } } if (params->is_bssid_hint_priority && @@ -963,7 +1091,6 @@ static void scm_list_insert_sorted(struct wlan_objmgr_psoc *psoc, if (!cur_lst) qdf_list_insert_back(scan_list, &scan_node->node); - } /** @@ -1294,21 +1421,22 @@ QDF_STATUS scm_flush_results(struct wlan_objmgr_pdev *pdev, * scm_filter_channels() - Remove entries not belonging to channel list * @scan_db: scan db * @db_node: node on which filters are applied - * @chan_list: valid channel list + * @chan_freq_list: valid channel frequency (in MHz) list * @num_chan: number of channels * * Return: QDF_STATUS */ -static void scm_filter_channels(struct scan_dbs *scan_db, - struct scan_cache_node *db_node, - uint8_t *chan_list, uint32_t num_chan) +static void scm_filter_channels(struct wlan_objmgr_pdev *pdev, + struct scan_dbs *scan_db, + struct scan_cache_node *db_node, + uint32_t *chan_freq_list, uint32_t num_chan) { int i; bool match = false; for (i = 0; i < num_chan; i++) { - if (chan_list[i] == - util_scan_entry_channel_num(db_node->entry)) { + if (chan_freq_list[i] == util_scan_entry_channel_frequency( + db_node->entry)) { match = true; break; } @@ -1322,7 +1450,7 @@ static void scm_filter_channels(struct scan_dbs *scan_db, } void scm_filter_valid_channel(struct wlan_objmgr_pdev *pdev, - uint8_t *chan_list, uint32_t num_chan) + uint32_t *chan_freq_list, uint32_t num_chan) { int i; struct wlan_objmgr_psoc *psoc; @@ -1353,8 +1481,8 @@ void scm_filter_valid_channel(struct wlan_objmgr_pdev *pdev, cur_node = scm_get_next_node(scan_db, &scan_db->scan_hash_tbl[i], NULL); while (cur_node) { - scm_filter_channels(scan_db, - cur_node, chan_list, num_chan); + scm_filter_channels(pdev, scan_db, + cur_node, chan_freq_list, num_chan); next_node = scm_get_next_node(scan_db, &scan_db->scan_hash_tbl[i], cur_node); cur_node = next_node; @@ -1412,7 +1540,6 @@ QDF_STATUS scm_db_init(struct wlan_objmgr_psoc *psoc) qdf_list_create(&scan_db->scan_hash_tbl[j], MAX_SCAN_CACHE_SIZE); } - return QDF_STATUS_SUCCESS; } @@ -1443,6 +1570,146 @@ QDF_STATUS scm_db_deinit(struct wlan_objmgr_psoc *psoc) return QDF_STATUS_SUCCESS; } +#ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO +QDF_STATUS scm_channel_list_db_init(struct wlan_objmgr_psoc *psoc) +{ + uint32_t i, j; + uint32_t min_freq, max_freq; + struct channel_list_db *rnr_channel_db; + + min_freq = wlan_reg_min_6ghz_chan_freq(); + max_freq = wlan_reg_max_6ghz_chan_freq(); + + scm_info("min_freq %d max_freq %d", min_freq, max_freq); + i = min_freq; + rnr_channel_db = scm_get_rnr_channel_db(psoc); + if (!rnr_channel_db) + return QDF_STATUS_E_INVAL; + + for (j = 0; j < QDF_ARRAY_SIZE(rnr_channel_db->channel); j++) { + if (i >= min_freq && i <= max_freq) + rnr_channel_db->channel[j].chan_freq = i; + i += 20; + /* init list for all to avoid uninitialized list */ + qdf_list_create(&rnr_channel_db->channel[j].rnr_list, + WLAN_MAX_RNR_COUNT); + } + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS scm_channel_list_db_deinit(struct wlan_objmgr_psoc *psoc) +{ + int i; + qdf_list_node_t *cur_node, *next_node; + struct meta_rnr_channel *channel; + struct scan_rnr_node *rnr_node; + struct channel_list_db *rnr_channel_db; + + rnr_channel_db = scm_get_rnr_channel_db(psoc); + if (!rnr_channel_db) + return QDF_STATUS_E_INVAL; + + for (i = 0; i < QDF_ARRAY_SIZE(rnr_channel_db->channel); i++) { + channel = &rnr_channel_db->channel[i]; + channel->chan_freq = 0; + channel->beacon_probe_last_time_found = 0; + channel->bss_beacon_probe_count = 0; + channel->saved_profile_count = 0; + cur_node = NULL; + qdf_list_peek_front(&channel->rnr_list, &cur_node); + while (cur_node) { + next_node = NULL; + qdf_list_peek_next(&channel->rnr_list, cur_node, + &next_node); + rnr_node = qdf_container_of(cur_node, + struct scan_rnr_node, + node); + qdf_list_remove_node(&channel->rnr_list, + &rnr_node->node); + qdf_mem_free(rnr_node); + cur_node = next_node; + next_node = NULL; + } + qdf_list_destroy(&channel->rnr_list); + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS scm_rnr_db_flush(struct wlan_objmgr_psoc *psoc) +{ + int i; + qdf_list_node_t *cur_node, *next_node; + struct meta_rnr_channel *channel; + struct scan_rnr_node *rnr_node; + struct channel_list_db *rnr_channel_db; + + rnr_channel_db = scm_get_rnr_channel_db(psoc); + if (!rnr_channel_db) + return QDF_STATUS_E_INVAL; + + for (i = 0; i < QDF_ARRAY_SIZE(rnr_channel_db->channel); i++) { + channel = &rnr_channel_db->channel[i]; + cur_node = NULL; + qdf_list_peek_front(&channel->rnr_list, &cur_node); + while (cur_node) { + next_node = NULL; + qdf_list_peek_next(&channel->rnr_list, cur_node, + &next_node); + rnr_node = qdf_container_of(cur_node, + struct scan_rnr_node, + node); + qdf_list_remove_node(&channel->rnr_list, + &rnr_node->node); + qdf_mem_free(rnr_node); + cur_node = next_node; + next_node = NULL; + } + /* Reset beacon info */ + channel->beacon_probe_last_time_found = 0; + channel->bss_beacon_probe_count = 0; + } + + return QDF_STATUS_SUCCESS; +} + +void scm_update_rnr_from_scan_cache(struct wlan_objmgr_pdev *pdev) +{ + uint8_t i; + struct scan_dbs *scan_db; + struct scan_cache_node *cur_node; + struct scan_cache_node *next_node = NULL; + struct wlan_objmgr_psoc *psoc; + struct scan_cache_entry *entry; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + scm_err("psoc is NULL"); + return; + } + scan_db = wlan_pdev_get_scan_db(psoc, pdev); + if (!scan_db) { + scm_err("scan_db is NULL"); + return; + } + + for (i = 0 ; i < SCAN_HASH_SIZE; i++) { + cur_node = scm_get_next_node(scan_db, + &scan_db->scan_hash_tbl[i], NULL); + while (cur_node) { + entry = cur_node->entry; + scm_add_rnr_channel_db(psoc, entry); + next_node = + scm_get_next_node(scan_db, + &scan_db->scan_hash_tbl[i], + cur_node); + cur_node = next_node; + next_node = NULL; + } + } +} +#endif + QDF_STATUS scm_update_scan_mlme_info(struct wlan_objmgr_pdev *pdev, struct scan_cache_entry *entry) { @@ -1515,7 +1782,7 @@ QDF_STATUS scm_scan_update_mlme_by_bssinfo(struct wlan_objmgr_pdev *pdev, entry = cur_node->entry; if (qdf_is_macaddr_equal(&bss_info->bssid, &entry->bssid) && (util_is_ssid_match(&bss_info->ssid, &entry->ssid)) && - (bss_info->chan == entry->channel.chan_idx)) { + (bss_info->freq == entry->channel.chan_freq)) { /* Acquire db lock to prevent simultaneous update */ qdf_spin_lock_bh(&scan_db->scan_db_lock); qdf_mem_copy(&entry->mlme_info, mlme, diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db.h b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db.h index 7d4e658217136c318edbb0517a2624a9191c1ab4..54140085ee014699ed22f940735a63e76504dce0 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 @@ -34,8 +35,6 @@ (((const uint8_t *)(addr))[QDF_MAC_ADDR_SIZE - 1] % SCAN_HASH_SIZE) #define SCM_PCL_RSSI_THRESHOLD -75 -#define BEST_CANDIDATE_MAX_BSS_SCORE 10000 - #define ADJACENT_CHANNEL_RSSI_THRESHOLD -80 /** @@ -145,7 +144,7 @@ QDF_STATUS scm_flush_results(struct wlan_objmgr_pdev *pdev, * scm_filter_valid_channel() - The Public API to filter scan result * based on valid channel list * @pdev: pdev object - * @chan_list: valid channel list + * @chan_freq_list: valid channel frequency (in MHz) list * @num_chan: number of valid channels * * The Public API to to filter scan result @@ -154,7 +153,7 @@ QDF_STATUS scm_flush_results(struct wlan_objmgr_pdev *pdev, * Return: void. */ void scm_filter_valid_channel(struct wlan_objmgr_pdev *pdev, - uint8_t *chan_list, uint32_t num_chan); + uint32_t *chan_freq_list, uint32_t num_chan); /** * scm_iterate_scan_db() - function to iterate scan table @@ -199,6 +198,71 @@ QDF_STATUS scm_db_init(struct wlan_objmgr_psoc *psoc); */ QDF_STATUS scm_db_deinit(struct wlan_objmgr_psoc *psoc); +#ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO + +/** + * scm_get_rnr_channel_db() - API to get rnr db + * @psoc: psoc + * + * Return: rnr db + */ +struct channel_list_db *scm_get_rnr_channel_db(struct wlan_objmgr_psoc *psoc); + +/** + * scm_get_chan_meta() - API to return channel meta + * @psoc: psoc + * @freq: channel frequency + * + * Return: channel meta information + */ +struct meta_rnr_channel *scm_get_chan_meta(struct wlan_objmgr_psoc *psoc, + uint32_t chan_freq); + +/** + * scm_channel_list_db_init() - API to init scan list priority list db + * @psoc: psoc + * + * Return: QDF_STATUS + */ +QDF_STATUS scm_channel_list_db_init(struct wlan_objmgr_psoc *psoc); + +/** + * scm_channel_list_db_deinit() - API to deinit scan list priority list db + * @psoc: psoc + * + * Return: QDF_STATUS + */ +QDF_STATUS scm_channel_list_db_deinit(struct wlan_objmgr_psoc *psoc); + +/** + * scm_rnr_db_flush() - API to flush rnr entries + * @psoc: psoc + * + * Return: QDF_STATUS + */ +QDF_STATUS scm_rnr_db_flush(struct wlan_objmgr_psoc *psoc); + +/** + * scm_update_rnr_from_scan_cache() - API to update rnr info from scan cache + * @pdev: pdev + * + * Return: void + */ +void scm_update_rnr_from_scan_cache(struct wlan_objmgr_pdev *pdev); + +#else +static inline QDF_STATUS scm_channel_list_db_init(struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_SUCCESS; +} + +static inline +QDF_STATUS scm_channel_list_db_deinit(struct wlan_objmgr_psoc *psoc) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * scm_validate_scoring_config() - validate score config * @score_cfg: config to be validated diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db_i.h b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db_i.h index d0c91c4e2e1594bd4cd660a42fa474a2d814f899..690dad03d531167fcb95c3de61742fbd66d2820b 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db_i.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db_i.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017, 2019 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 @@ -117,7 +117,7 @@ wlan_pdev_get_scan_db(struct wlan_objmgr_psoc *psoc, /** * scm_get_pcl_weight_of_channel() - Get PCL weight if channel is present in pcl - * @channel_id: channel of bss + * @chan_freq: channel frequency of bss, unit: MHz * @filter: filter * @pcl_chan_weight: Get PCL weight for corresponding channel * @weight_list: Weight list for all the pcl channels. @@ -126,8 +126,8 @@ wlan_pdev_get_scan_db(struct wlan_objmgr_psoc *psoc, * * Return: true or false */ -bool scm_get_pcl_weight_of_channel(int channel_id, - struct scan_filter *filter, - int *pcl_chan_weight, - uint8_t *weight_list); +bool scm_get_pcl_weight_of_channel(uint32_t chan_freq, + struct scan_filter *filter, + int *pcl_chan_weight, + uint8_t *weight_list); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_filter.c b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_filter.c index 4581289d75c2b8f77ce8f2355e69e0d1a50af5c6..bbde9124c273ac2920a6b1b5c6d113d8ec97faa5 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_filter.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_filter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -295,8 +295,9 @@ scm_check_pmf_match(struct scan_filter *filter, match = false; if (!match) - scm_debug("%pM : PMF cap didn't match (filter %d AP %d)", - db_entry->bssid.bytes, filter->pmf_cap, + scm_debug(QDF_MAC_ADDR_FMT" : PMF cap didn't match (filter %d AP %d)", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes), + filter->pmf_cap, ap_pmf_cap); return match; @@ -398,7 +399,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, if (!security) return false; if (!util_scan_entry_rsn(db_entry)) { - scm_debug("%pM : doesn't have RSN IE", db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : doesn't have RSN IE", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } status = wlan_parse_rsn_ie(util_scan_entry_rsn(db_entry), &rsn); @@ -415,15 +417,15 @@ static bool scm_is_rsn_security(struct scan_filter *filter, match = scm_is_cipher_match(rsn.pwise_cipher_suites, rsn.pwise_cipher_count, WLAN_RSN_SEL(cipher_type)); if (!match) { - scm_debug("%pM : pairwise cipher didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : pairwise cipher didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } match = scm_is_rsn_mcast_cipher_match(&rsn, filter, &neg_mccipher); if (!match) { - scm_debug("%pM : mcast cipher didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : mcast cipher didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } @@ -673,8 +675,8 @@ static bool scm_is_rsn_security(struct scan_filter *filter, } if (!match) { - scm_debug("%pM : akm suites didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : akm suites didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } @@ -768,8 +770,8 @@ static bool scm_is_wpa_security(struct scan_filter *filter, if (!security) return false; if (!util_scan_entry_wpa(db_entry)) { - scm_debug("%pM : AP doesn't have WPA IE", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : AP doesn't have WPA IE", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } @@ -787,15 +789,15 @@ static bool scm_is_wpa_security(struct scan_filter *filter, match = scm_is_cipher_match(wpa.uc_ciphers, wpa.uc_cipher_count, WLAN_WPA_SEL(cipher_type)); if (!match) { - scm_debug("%pM : unicase cipher didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : unicase cipher didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } match = scm_is_wpa_mcast_cipher_match(&wpa, filter, &neg_mccipher); if (!match) { - scm_debug("%pM : mcast cipher didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : mcast cipher didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } @@ -845,7 +847,8 @@ static bool scm_is_wpa_security(struct scan_filter *filter, } if (!match) - scm_debug("%pM : akm didn't match", db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : akm didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); if (match) { security->auth_type = neg_auth; @@ -877,8 +880,8 @@ static bool scm_is_wapi_security(struct scan_filter *filter, if (!security) return false; if (!util_scan_entry_wapi(db_entry)) { - scm_debug("%pM : mcast cipher didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : mcast cipher didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } @@ -890,8 +893,8 @@ static bool scm_is_wapi_security(struct scan_filter *filter, match = scm_is_cipher_match(wapi.uc_cipher_suites, wapi.uc_cipher_count, WLAN_WAPI_SEL(cipher_type)); if (!match) { - scm_debug("%pM : unicast cipher didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : unicast cipher didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } @@ -905,8 +908,8 @@ static bool scm_is_wapi_security(struct scan_filter *filter, break; } if (!match) { - scm_debug("%pM : mcast cipher didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : mcast cipher didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } neg_mccipher = filter->mc_enc_type[i]; @@ -920,8 +923,8 @@ static bool scm_is_wapi_security(struct scan_filter *filter, wapi.akm_suite_count, WLAN_WAPI_SEL(WLAN_WAI_PSK))) { neg_auth = WLAN_AUTH_TYPE_WAPI_WAI_PSK; } else { - scm_debug("%pM : akm is not supported", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : akm is not supported", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } @@ -934,8 +937,8 @@ static bool scm_is_wapi_security(struct scan_filter *filter, } if (!match) - scm_debug("%pM : akm suite didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : akm suite didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); if (match) { security->auth_type = neg_auth; security->mc_enc = neg_mccipher; @@ -1034,6 +1037,7 @@ static bool scm_is_fils_config_match(struct scan_filter *filter, int i; struct fils_indication_ie *indication_ie; uint8_t *data; + uint8_t *end_ptr; if (!filter->fils_scan_filter.realm_check) return true; @@ -1045,14 +1049,19 @@ static bool scm_is_fils_config_match(struct scan_filter *filter, indication_ie = (struct fils_indication_ie *) db_entry->ie_list.fils_indication; + end_ptr = (uint8_t *)indication_ie + indication_ie->len + 2; + data = indication_ie->variable_data; - if (indication_ie->is_cache_id_present) + if (indication_ie->is_cache_id_present && + (data + CACHE_IDENTIFIER_LEN) <= end_ptr) data += CACHE_IDENTIFIER_LEN; - if (indication_ie->is_hessid_present) + if (indication_ie->is_hessid_present && + (data + HESSID_LEN) <= end_ptr) data += HESSID_LEN; - for (i = 1; i <= indication_ie->realm_identifiers_cnt; i++) { + for (i = 1; i <= indication_ie->realm_identifiers_cnt && + (data + REAM_HASH_LEN) <= end_ptr; i++) { if (!qdf_mem_cmp(filter->fils_scan_filter.fils_realm, data, REAM_HASH_LEN)) return true; @@ -1170,7 +1179,9 @@ bool scm_filter_match(struct wlan_objmgr_psoc *psoc, */ if (!match && util_scan_entry_is_hidden_ap(db_entry)) { for (i = 0; i < filter->num_of_auth; i++) { - if (filter->auth_type[i] == WLAN_AUTH_TYPE_OWE) { + if (filter->auth_type[i] == WLAN_AUTH_TYPE_OWE && + util_is_bssid_match(&filter->bssid_hint, + &db_entry->bssid)) { match = true; break; } @@ -1194,9 +1205,9 @@ bool scm_filter_match(struct wlan_objmgr_psoc *psoc, match = false; for (i = 0; i < filter->num_of_channels; i++) { - if (!filter->channel_list[i] || ( - (filter->channel_list[i] == - db_entry->channel.chan_idx))) { + if (!filter->chan_freq_list[i] || + filter->chan_freq_list[i] == + db_entry->channel.chan_freq) { match = true; break; } @@ -1212,14 +1223,15 @@ bool scm_filter_match(struct wlan_objmgr_psoc *psoc, if (!filter->ignore_auth_enc_type && !scm_is_security_match(filter, db_entry, security)) { - scm_debug("%pM : Ignore as security profile didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : Ignore as security profile didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } if (!util_is_bss_type_match(filter->bss_type, db_entry->cap_info)) { - scm_debug("%pM : Ignore as bss type didn't match cap_info %x bss_type %d", - db_entry->bssid.bytes, db_entry->cap_info.value, + scm_debug(QDF_MAC_ADDR_FMT" : Ignore as bss type didn't match cap_info %x bss_type %d", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes), + db_entry->cap_info.value, filter->bss_type); return false; } @@ -1229,31 +1241,31 @@ bool scm_filter_match(struct wlan_objmgr_psoc *psoc, if (filter->only_wmm_ap && !db_entry->ie_list.wmeinfo && !db_entry->ie_list.wmeparam) { - scm_debug("%pM : Ignore as required wmeinfo and wme params not present", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : Ignore as required wmeinfo and wme params not present", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } /* Match realm */ if (!scm_is_fils_config_match(filter, db_entry)) { - scm_debug("%pM :Ignore as fils config didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" :Ignore as fils config didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } cc_ie = util_scan_entry_country(db_entry); if (!util_country_code_match(filter->country, cc_ie)) { - scm_debug("%pM : Ignore as country %.*s didn't match", - db_entry->bssid.bytes, 2, filter->country); + scm_debug(QDF_MAC_ADDR_FMT" : Ignore as country %.*s didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes), + 2, filter->country); return false; } if (!util_mdie_match(filter->mobility_domain, (struct rsn_mdie *)db_entry->ie_list.mdie)) { - scm_debug("%pM : Ignore as mdie didn't match", - db_entry->bssid.bytes); + scm_debug(QDF_MAC_ADDR_FMT" : Ignore as mdie didn't match", + QDF_MAC_ADDR_REF(db_entry->bssid.bytes)); return false; } - return true; } diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_main.h b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_main.h index 33b55a4e8c894914e002e8573a7eeec7612b1d3c..26ea25e967bd94f55cac45bb0a3852819e054bad 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_main.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_main.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -30,6 +30,7 @@ #include #include "wlan_scan_cache_db.h" #include "wlan_scan_11d.h" +#include "wlan_scan_cfg.h" #define scm_alert(params...) \ QDF_TRACE_FATAL(QDF_MODULE_ID_SCAN, params) @@ -89,6 +90,9 @@ #define SCAN_P2P_SCAN_MAX_BURST_DURATION (240) #define SCAN_GO_BURST_SCAN_MAX_NUM_OFFCHANNELS (6) +/* MAX RNR entries per channel*/ +#define WLAN_MAX_RNR_COUNT 15 + /** * struct probe_time_dwell_time - probe time, dwell time map * @dwell_time: dwell time @@ -112,19 +116,6 @@ struct probe_time_dwell_time { #define SCM_NUM_RSSI_CAT 15 #define SCAN_STA_MIRACAST_MCC_REST_TIME 400 -#ifndef CONFIG_MCL -#define MAX_SCAN_CACHE_SIZE 1024 -#define SCAN_MAX_REST_TIME 0 -#define SCAN_MIN_REST_TIME 50 -#define SCAN_BURST_DURATION 0 -#define SCAN_PROBE_SPACING_TIME 0 -#define SCAN_PROBE_DELAY 0 -#define SCAN_MAX_SCAN_TIME 50000 -#define SCAN_NETWORK_IDLE_TIMEOUT 200 -#define HIDDEN_SSID_TIME (0xFFFFFFFF) -#define SCAN_CHAN_STATS_EVENT_ENAB (true) -#endif - #define SCAN_TIMEOUT_GRACE_PERIOD 10 #define SCAN_MAX_BSS_PDEV 100 #define SCAN_PRIORITY SCAN_PRIORITY_LOW @@ -143,6 +134,21 @@ struct probe_time_dwell_time { */ #define SCAN_FLAG_EXT_FILTER_PUBLIC_ACTION_FRAME 0x4 +/* Indicate to scan all PSC channel */ +#define SCAN_FLAG_EXT_6GHZ_SCAN_ALL_PSC_CH 0x8 + +/* Indicate to scan all NON-PSC channel */ +#define SCAN_FLAG_EXT_6GHZ_SCAN_ALL_NON_PSC_CH 0x10 + +/* Indicate to save scan result matching hint from scan client */ +#define SCAN_FLAG_EXT_6GHZ_MATCH_HINT 0x20 + +/* Skip any channel on which RNR information is not received */ +#define SCAN_FLAG_EXT_6GHZ_SKIP_NON_RNR_CH 0x40 + +/* Indicate client hint req is high priority than FW rnr or FILS discovery */ +#define SCAN_FLAG_EXT_6GHZ_CLIENT_HIGH_PRIORITY 0x80 + /* Passive dwell time if bt_a2dp is enabled. Time in msecs*/ #define PASSIVE_DWELL_TIME_BT_A2DP_ENABLED 28 @@ -238,6 +244,7 @@ struct scan_vdev_obj { * @pno_wake_lock: pno wake lock * @pno_cb: callback to call on PNO completion * @mawc_params: Configuration parameters for NLO MAWC. + * @user_config_sched_scan_plan: if enabled set user confing sched scan plan */ struct pno_def_config { bool pno_offload_enabled; @@ -256,9 +263,11 @@ struct pno_def_config { qdf_wake_lock_t pno_wake_lock; struct cb_handler pno_cb; struct nlo_mawc_params mawc_params; + bool user_config_sched_scan_plan; }; #endif +#ifdef FEATURE_WLAN_EXTSCAN /** * struct extscan_def_config - def configuration for EXTSCAN * @extscan_enabled: enable extscan @@ -274,6 +283,7 @@ struct extscan_def_config { uint32_t extscan_active_max_chn_time; uint32_t extscan_active_min_chn_time; }; +#endif /** * struct scan_default_params - default scan parameters to be used @@ -283,6 +293,8 @@ struct extscan_def_config { * @skip_dfs_chan_in_p2p_search: Skip DFS channels in p2p search. * @use_wake_lock_in_user_scan: if wake lock will be acquired during user scan * @active_dwell_2g: default active dwell time for 2G channels, if it's not zero + * @active_dwell_6g: default active dwell time for 6G channels + * @passive_dwell_6g: default passive dwell time for 6G channels * @passive_dwell:default passive dwell time * @max_rest_time: default max rest time * @sta_miracast_mcc_rest_time: max rest time for miracast and mcc @@ -308,6 +320,7 @@ struct extscan_def_config { * @max_bss_per_pdev: maximum number of bss entries to be maintained per pdev * @max_active_scans_allowed: maximum number of active parallel scan allowed * per psoc + * @scan_mode_6g: scan mode in 6Ghz * @enable_connected_scan: enable scans after connection * @scan_priority: default scan priority * @adaptive_dwell_time_mode: adaptive dwell mode with connection @@ -365,6 +378,8 @@ struct scan_default_params { bool skip_dfs_chan_in_p2p_search; bool use_wake_lock_in_user_scan; uint32_t active_dwell_2g; + uint32_t active_dwell_6g; + uint32_t passive_dwell_6g; uint32_t passive_dwell; uint32_t max_rest_time; uint32_t sta_miracast_mcc_rest_time; @@ -393,6 +408,7 @@ struct scan_default_params { uint8_t p2p_scan_burst_duration; uint8_t go_scan_burst_duration; uint8_t ap_scan_burst_duration; + enum scan_mode_6ghz scan_mode_6g; bool enable_connected_scan; enum scan_priority scan_priority; enum scan_dwelltime_adaptive_mode adaptive_dwell_time_mode; @@ -482,8 +498,12 @@ struct scan_cb { * @miracast_enabled: miracast enabled * @disable_timeout: command timeout disabled * @drop_bcn_on_chan_mismatch: drop bcn if channel mismatch + * @drop_bcn_on_invalid_freq: drop bcn if freq is invalid in IEs (DS/HT/HE) * @scan_start_request_buff: buffer used to pass * scan config to event handlers + * @rnr_channel_db: RNR channel list database + * @allow_bss_with_incomplete_ie: Continue scan entry even if any corrupted IES + * are present. */ struct wlan_scan_obj { uint32_t scan_disabled; @@ -507,7 +527,12 @@ struct wlan_scan_obj { bool miracast_enabled; bool disable_timeout; bool drop_bcn_on_chan_mismatch; + bool drop_bcn_on_invalid_freq; struct scan_start_request scan_start_request_buff; +#ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO + struct channel_list_db rnr_channel_db; +#endif + bool allow_bss_with_incomplete_ie; }; /** diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_manager.c b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_manager.c index 9f2293c07054ae62475abb1bd847907de754fd3c..f39ee60c17e7d7e0ae3e06f695beb7cbcedacf04 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_manager.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_manager.c @@ -1,6 +1,5 @@ /* * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. 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 @@ -35,6 +34,19 @@ #include #endif #include +#include + +/* Beacon/probe weightage multiplier */ +#define BCN_PROBE_WEIGHTAGE 5 + +/* Saved profile weightage multiplier */ +#define SAVED_PROFILE_WEIGHTAGE 10 + +/* maximum number of 6ghz hints can be sent per scan request */ +#define MAX_HINTS_PER_SCAN_REQ 15 + +/* maximum number of hints can be sent per 6ghz channel */ +#define MAX_HINTS_PER_CHANNEL 4 QDF_STATUS scm_scan_free_scan_request_mem(struct scan_start_request *req) @@ -548,7 +560,7 @@ int scm_scan_get_burst_duration(int max_ch_time, bool miracast_enabled) return burst_duration; } -#define SCM_ACTIVE_DWELL_TIME_NAN 40 +#define SCM_ACTIVE_DWELL_TIME_NAN 60 #define SCM_ACTIVE_DWELL_TIME_SAP 40 /** @@ -614,16 +626,39 @@ static void scm_req_update_concurrency_params(struct wlan_objmgr_vdev *vdev, req->scan_req.adaptive_dwell_time_mode = scan_obj->scan_def.adaptive_dwell_time_mode_nc; /* - * If AP/GO is active and has connected clients set min rest time - * same as max rest time, so that firmware spends more time on home - * channel which will increase the probability of sending beacon at TBTT + * If AP/GO is active and has connected clients : + * 1.set min rest time same as max rest time, so that + * firmware spends more time on home channel which will + * increase the probability of sending beacon at TBTT + * 2.if DBS is supported and SAP is not on 2g, + * do not reset active dwell time for 2g. + */ + + /* + * For SAP, the dwell time cannot exceed 32 ms as it can't go + * offchannel more than 32 ms. For Go, since we + * advertise NOA, GO can have regular dwell time which is 40 ms. */ if ((ap_present && sap_peer_count) || (go_present && go_peer_count)) { - req->scan_req.dwell_time_active_2g = 0; + if ((policy_mgr_is_hw_dbs_capable(psoc) && + policy_mgr_is_sap_go_on_2g(psoc)) || + !policy_mgr_is_hw_dbs_capable(psoc)) { + if (ap_present) + req->scan_req.dwell_time_active_2g = + QDF_MIN(req->scan_req.dwell_time_active, + (SCAN_CTS_DURATION_MS_MAX - + SCAN_ROAM_SCAN_CHANNEL_SWITCH_TIME)); + else + req->scan_req.dwell_time_active_2g = 0; + } req->scan_req.min_rest_time = req->scan_req.max_rest_time; } + if (policy_mgr_current_concurrency_is_mcc(psoc)) + req->scan_req.min_rest_time = + scan_obj->scan_def.conc_max_rest_time; + /* * If scan req for SAP (ACS Sacn) use dwell_time_active_def as dwell * time for 2g channels instead of dwell_time_active_2g @@ -683,11 +718,14 @@ static void scm_req_update_concurrency_params(struct wlan_objmgr_vdev *vdev, break; } - if (ndi_present) { + if (go_present && sta_active) { req->scan_req.burst_duration = - scm_scan_get_burst_duration( - req->scan_req.dwell_time_active, - scan_obj->miracast_enabled); + req->scan_req.dwell_time_active; + break; + } + + if (ndi_present || (p2p_cli_present && sta_active)) { + req->scan_req.burst_duration = 0; break; } } while (0); @@ -710,34 +748,42 @@ static void scm_req_update_concurrency_params(struct wlan_objmgr_vdev *vdev, } if (ap_present) { - uint8_t ap_chan; + uint16_t ap_chan_freq; struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); - ap_chan = policy_mgr_get_channel(psoc, PM_SAP_MODE, NULL); + ap_chan_freq = policy_mgr_get_channel(psoc, PM_SAP_MODE, NULL); /* * P2P/STA scan while SoftAP is sending beacons. * Max duration of CTS2self is 32 ms, which limits the - * dwell time. If DBS is supported and if SAP is on 2G channel - * then keep passive dwell time default. + * dwell time. + * If DBS is supported and: + * 1.if SAP is on 2G channel then keep passive + * dwell time default. + * 2.if SAP is on 5G/6G channel then update dwell time active. */ if (sap_peer_count) { - req->scan_req.dwell_time_active = - QDF_MIN(req->scan_req.dwell_time_active, - (SCAN_CTS_DURATION_MS_MAX - + if (policy_mgr_is_hw_dbs_capable(psoc) && + (WLAN_REG_IS_5GHZ_CH_FREQ(ap_chan_freq) || + WLAN_REG_IS_6GHZ_CHAN_FREQ(ap_chan_freq))) { + req->scan_req.dwell_time_active = + QDF_MIN(req->scan_req.dwell_time_active, + (SCAN_CTS_DURATION_MS_MAX - SCAN_ROAM_SCAN_CHANNEL_SWITCH_TIME)); + } if (!policy_mgr_is_hw_dbs_capable(psoc) || (policy_mgr_is_hw_dbs_capable(psoc) && - WLAN_CHAN_IS_5GHZ(ap_chan))) { + WLAN_REG_IS_5GHZ_CH_FREQ(ap_chan_freq))) { req->scan_req.dwell_time_passive = req->scan_req.dwell_time_active; } } + if (scan_obj->scan_def.ap_scan_burst_duration) { req->scan_req.burst_duration = scan_obj->scan_def.ap_scan_burst_duration; } else { req->scan_req.burst_duration = 0; - if (utils_is_dfs_ch(pdev, ap_chan)) + if (wlan_reg_is_dfs_for_freq(pdev, ap_chan_freq)) req->scan_req.burst_duration = SCAN_BURST_SCAN_MAX_NUM_OFFCHANNELS * req->scan_req.dwell_time_active; @@ -746,8 +792,7 @@ static void scm_req_update_concurrency_params(struct wlan_objmgr_vdev *vdev, if (ndi_present) { req->scan_req.dwell_time_active = - QDF_MIN(req->scan_req.dwell_time_active, - SCM_ACTIVE_DWELL_TIME_NAN); + SCM_ACTIVE_DWELL_TIME_NAN; req->scan_req.dwell_time_active_2g = QDF_MIN(req->scan_req.dwell_time_active_2g, SCM_ACTIVE_DWELL_TIME_NAN); @@ -815,6 +860,262 @@ static inline void scm_scan_chlist_concurrency_modify( } #endif +#ifdef CONFIG_BAND_6GHZ +static void +scm_update_6ghz_channel_list(struct wlan_objmgr_vdev *vdev, + struct chan_list *chan_list, + struct wlan_scan_obj *scan_obj) +{ + uint8_t i; + struct regulatory_channel *chan_list_6g; + bool psc_channel_found = false; + bool channel_6g_found = false; + uint8_t num_scan_channels = 0, channel_count; + struct wlan_objmgr_pdev *pdev; + uint32_t freq; + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) + return; + + scm_debug("6g scan mode %d", scan_obj->scan_def.scan_mode_6g); + for (i = 0; i < chan_list->num_chan; i++) { + freq = chan_list->chan[i].freq; + if ((scan_obj->scan_def.scan_mode_6g == + SCAN_MODE_6G_NO_CHANNEL) && + (wlan_reg_is_6ghz_chan_freq(freq))) { + /* Drop the 6Ghz channels */ + continue; + } else if ((scan_obj->scan_def.scan_mode_6g == + SCAN_MODE_6G_PSC_CHANNEL) && + (wlan_reg_is_6ghz_chan_freq(freq))) { + /* Allow only PSC channels */ + if (wlan_reg_is_6ghz_psc_chan_freq(freq)) + psc_channel_found = true; + else + continue; + } else if ((scan_obj->scan_def.scan_mode_6g == + SCAN_MODE_6G_ALL_CHANNEL) && + (wlan_reg_is_6ghz_chan_freq(freq))) { + /* Allow any 6ghz channel */ + channel_6g_found = true; + } + chan_list->chan[num_scan_channels++] = + chan_list->chan[i]; + } + + scm_debug("psc_channel_found %d channel_6g_found%d", + psc_channel_found, channel_6g_found); + if ((scan_obj->scan_def.scan_mode_6g == SCAN_MODE_6G_PSC_CHANNEL && + !psc_channel_found) || + (scan_obj->scan_def.scan_mode_6g == SCAN_MODE_6G_ALL_CHANNEL && + !channel_6g_found)) { + chan_list_6g = qdf_mem_malloc(NUM_6GHZ_CHANNELS * + sizeof(struct regulatory_channel)); + if (!chan_list_6g) + goto end; + + /* Add the 6Ghz channels based on config*/ + channel_count = wlan_reg_get_band_channel_list(pdev, + BIT(REG_BAND_6G), + chan_list_6g); + scm_debug("Number of 6G channels %d", channel_count); + for (i = 0; i < channel_count; i++) { + if ((scan_obj->scan_def.scan_mode_6g == + SCAN_MODE_6G_PSC_CHANNEL) && + (!psc_channel_found) && + wlan_reg_is_6ghz_psc_chan_freq(chan_list_6g[i]. + center_freq)) { + chan_list->chan[num_scan_channels++].freq = + chan_list_6g[i].center_freq; + } else if ((scan_obj->scan_def.scan_mode_6g == + SCAN_MODE_6G_ALL_CHANNEL) && + (!channel_6g_found)) { + chan_list->chan[num_scan_channels++].freq = + chan_list_6g[i].center_freq; + } + } + qdf_mem_free(chan_list_6g); + } +end: + chan_list->num_chan = num_scan_channels; +} +#else +static void +scm_update_6ghz_channel_list(struct wlan_objmgr_vdev *vdev, + struct chan_list *chan_list, + struct wlan_scan_obj *scan_obj) +{ +} +#endif + +#ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO +static void scm_sort_6ghz_channel_list(struct wlan_objmgr_vdev *vdev, + struct chan_list *chan_list) +{ + uint8_t i, j = 0, max, tmp_list_count; + struct meta_rnr_channel *channel; + struct chan_info temp_list[MAX_6GHZ_CHANNEL]; + struct rnr_chan_weight *rnr_chan_info, temp; + uint32_t weight; + struct wlan_objmgr_psoc *psoc; + + rnr_chan_info = qdf_mem_malloc(sizeof(rnr_chan_info) * MAX_6GHZ_CHANNEL); + if (!rnr_chan_info) + return; + + for (i = 0; i < chan_list->num_chan; i++) { + if (WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_list->chan[i].freq)) + temp_list[j++].freq = chan_list->chan[i].freq; + } + tmp_list_count = j; + scm_debug("Total 6ghz channels %d", tmp_list_count); + + /* No Need to sort if the 6ghz channels are less than one */ + if (tmp_list_count < 1) { + qdf_mem_free(rnr_chan_info); + return; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + scm_err("Psoc is NULL"); + return; + } + + /* compute the weightage */ + for (i = 0, j = 0; i < tmp_list_count; i++) { + channel = scm_get_chan_meta(psoc, temp_list[i].freq); + if (!channel) + continue; + weight = channel->bss_beacon_probe_count * BCN_PROBE_WEIGHTAGE + + channel->saved_profile_count * SAVED_PROFILE_WEIGHTAGE; + rnr_chan_info[j].weight = weight; + rnr_chan_info[j].chan_freq = temp_list[i].freq; + j++; + scm_debug("Freq %d weight %d bcn_cnt %d", temp_list[i].freq, + weight, channel->bss_beacon_probe_count); + } + + /* Sort the channel using selection sort - descending order */ + for (i = 0; i < tmp_list_count - 1; i++) { + max = i; + for (j = i + 1; j < tmp_list_count; j++) { + if (rnr_chan_info[j].weight > + rnr_chan_info[max].weight) + max = j; + } + if (max != i) { + qdf_mem_copy(&temp, &rnr_chan_info[max], + sizeof(*rnr_chan_info)); + qdf_mem_copy(&rnr_chan_info[max], &rnr_chan_info[i], + sizeof(*rnr_chan_info)); + qdf_mem_copy(&rnr_chan_info[i], &temp, + sizeof(*rnr_chan_info)); + } + } + + /* update the 6g list based on the weightage */ + for (i = 0, j = 0; (i < NUM_CHANNELS && j < tmp_list_count); i++) { + if (wlan_reg_is_6ghz_chan_freq(chan_list->chan[i].freq)) + chan_list->chan[i].freq = rnr_chan_info[j++].chan_freq; + } + qdf_mem_free(rnr_chan_info); +} + +static void scm_update_rnr_info(struct wlan_objmgr_psoc *psoc, + struct scan_start_request *req) +{ + uint8_t i, num_bssid = 0, num_ssid = 0; + uint8_t total_count = MAX_HINTS_PER_SCAN_REQ; + uint32_t freq; + struct meta_rnr_channel *chan; + qdf_list_node_t *cur_node, *next_node = NULL; + struct scan_rnr_node *rnr_node; + struct chan_list *chan_list; + QDF_STATUS status; + + if (!req) + return; + + chan_list = &req->scan_req.chan_list; + for (i = 0; i < chan_list->num_chan; i++) { + freq = chan_list->chan[i].freq; + + chan = scm_get_chan_meta(psoc, freq); + if (!chan) { + scm_debug("Failed to get meta, freq %d", freq); + continue; + } + if (qdf_list_empty(&chan->rnr_list)) + continue; + + qdf_list_peek_front(&chan->rnr_list, &cur_node); + while (cur_node && total_count) { + rnr_node = qdf_container_of(cur_node, + struct scan_rnr_node, + node); + if (!qdf_is_macaddr_zero(&rnr_node->entry.bssid) && + req->scan_req.num_hint_bssid < + WLAN_SCAN_MAX_HINT_BSSID) { + qdf_mem_copy(&req->scan_req.hint_bssid[num_bssid++].bssid, + &rnr_node->entry.bssid, + QDF_MAC_ADDR_SIZE); + req->scan_req.num_hint_bssid++; + total_count--; + } else if (rnr_node->entry.short_ssid && + req->scan_req.num_hint_s_ssid < + WLAN_SCAN_MAX_HINT_S_SSID) { + req->scan_req.hint_s_ssid[num_ssid++].short_ssid = + rnr_node->entry.short_ssid; + req->scan_req.num_hint_s_ssid++; + total_count--; + } + status = qdf_list_peek_next(&chan->rnr_list, cur_node, + &next_node); + if (QDF_IS_STATUS_ERROR(status)) + break; + cur_node = next_node; + next_node = NULL; + } + } +} + +static void scm_add_rnr_info(struct wlan_objmgr_pdev *pdev, + struct scan_start_request *req) +{ + struct wlan_objmgr_psoc *psoc; + struct channel_list_db *rnr_db; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) + return; + rnr_db = scm_get_rnr_channel_db(psoc); + if (!rnr_db) + return; + + rnr_db->scan_count++; + if (rnr_db->scan_count >= RNR_UPDATE_SCAN_CNT_THRESHOLD) { + rnr_db->scan_count = 0; + scm_rnr_db_flush(psoc); + scm_update_rnr_from_scan_cache(pdev); + } + + scm_update_rnr_info(psoc, req); +} + +#else +static void scm_sort_6ghz_channel_list(struct wlan_objmgr_vdev *vdev, + struct chan_list *chan_list) +{ +} + +static void scm_add_rnr_info(struct wlan_objmgr_pdev *pdev, + struct scan_start_request *req) +{ +} +#endif + /** * scm_update_channel_list() - update scan req params depending on dfs inis * and initial scan request. @@ -834,6 +1135,7 @@ scm_update_channel_list(struct scan_start_request *req, bool first_scan_done = true; bool p2p_search = false; bool skip_dfs_ch = true; + uint32_t first_freq; pdev = wlan_vdev_get_pdev(req->vdev); @@ -854,10 +1156,11 @@ scm_update_channel_list(struct scan_start_request *req, * No need to update channels if req is single channel* ie ROC, * Preauth or a single channel scan etc. * If the single chan in the scan channel list is an NOL channel,it is - * not removed as it would reduce the number of scan channels to 0 - * and FW would scan all chans which is unexpected in this scenerio. + * removed and it would reduce the number of scan channels to 0. */ - if (req->scan_req.chan_list.num_chan == 1) + first_freq = req->scan_req.chan_list.chan[0].freq; + if ((req->scan_req.chan_list.num_chan == 1) && + (!utils_dfs_is_freq_in_nol(pdev, first_freq))) return; /* do this only for STA and P2P-CLI mode */ @@ -878,9 +1181,7 @@ scm_update_channel_list(struct scan_start_request *req, freq = req->scan_req.chan_list.chan[i].freq; if (skip_dfs_ch && - wlan_reg_chan_has_dfs_attribute(pdev, - wlan_reg_freq_to_chan( - pdev, freq))) { + wlan_reg_chan_has_dfs_attribute_for_freq(pdev, freq)) { scm_nofl_debug("Skip DFS freq %d", freq); continue; } @@ -892,7 +1193,15 @@ scm_update_channel_list(struct scan_start_request *req, req->scan_req.chan_list.chan[num_scan_channels++] = req->scan_req.chan_list.chan[i]; } + req->scan_req.chan_list.num_chan = num_scan_channels; + /* Dont upadte the channel list for SAP mode */ + if (wlan_vdev_mlme_get_opmode(req->vdev) != QDF_SAP_MODE) { + scm_update_6ghz_channel_list(req->vdev, + &req->scan_req.chan_list, + scan_obj); + scm_sort_6ghz_channel_list(req->vdev, &req->scan_req.chan_list); + } scm_scan_chlist_concurrency_modify(req->vdev, req); } @@ -1022,6 +1331,8 @@ scm_scan_req_update_params(struct wlan_objmgr_vdev *vdev, else if (!req->scan_req.chan_list.num_chan) ucfg_scan_init_chanlist_params(req, 0, NULL, NULL); + if (scan_obj->scan_def.scan_mode_6g != SCAN_MODE_6G_NO_CHANNEL) + scm_add_rnr_info(pdev, req); scm_update_channel_list(req, scan_obj); } @@ -1034,9 +1345,10 @@ static inline void scm_print_scan_req_info(struct scan_req_params *req) struct chan_list *chan_lst; #define MAX_SCAN_FREQ_TO_PRINT 60 - scm_nofl_debug("Scan start: scan id %d vdev %d Dwell time: act %d pass %d act_2G %d, probe time %d n_probes %d flags %x ext_flag %x events %x policy %d wide_bw %d pri %d", + scm_nofl_debug("Scan start: scan id %d vdev %d Dwell time: act %d pass %d act_2G %d act_6G %d pass_6G %d, probe time %d n_probes %d flags %x ext_flag %x events %x policy %d wide_bw %d pri %d", req->scan_id, req->vdev_id, req->dwell_time_active, req->dwell_time_passive, req->dwell_time_active_2g, + req->dwell_time_active_6g, req->dwell_time_passive_6g, req->repeat_probe_time, req->n_probes, req->scan_flags, req->scan_ctrl_flags_ext, req->scan_events, req->scan_policy_type, req->scan_f_wide_band, diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_cfg.h b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_cfg.h index 49a3d09e42cb48a0cc7891638bddce6806bec49f..175a3beccbb1121496cc9c6abfe9501641fc7eca 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_cfg.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -24,6 +24,19 @@ #include "cfg_define.h" +/** + * enum scan_mode_6ghz - scan mode for 6GHz + * @SCAN_MODE_6G_NO_CHANNEL: Remove 6GHz channels in the scan request + * @SCAN_MODE_6G_PSC_CHANNEL: Allow/Add 6Ghz PSC channels to scan request + * @SCAN_MODE_6G_ALL_CHANNEL: Allow all the 6Ghz channels + */ +enum scan_mode_6ghz { + SCAN_MODE_6G_NO_CHANNEL, + SCAN_MODE_6G_PSC_CHANNEL, + SCAN_MODE_6G_ALL_CHANNEL, + SCAN_MODE_6G_MAX = SCAN_MODE_6G_ALL_CHANNEL, +}; + /* * * drop_bcn_on_chan_mismatch - drop the beacon for chan mismatch @@ -45,6 +58,27 @@ true,\ "drop bcn on channel mismatch") +/* + * + * drop_bcn_on_invalid_freq - drop the beacon or probe resp with invalid freq + * @Min: 0 + * @Max: 1 + * @Default: 1 + * + * This ini is used to decide whether to drop the beacon/probe resp or not + * if channel received in DS param, HT info and HE IE is invalid. + * + * Related: None + * + * Usage: External + * + * + */ +#define CFG_DROP_BCN_ON_INVALID_FREQ CFG_INI_BOOL(\ + "drop_bcn_on_invalid_freq",\ + true,\ + "drop bcn on invalid freq in HT, DS, HE IE") + /* * * gActiveMaxChannelTime - Set max channel time for active scan @@ -63,7 +97,7 @@ */ #define CFG_ACTIVE_MAX_CHANNEL_TIME CFG_INI_UINT(\ "gActiveMaxChannelTime",\ - 0, 10000, MCL_OR_WIN_VALUE(40, 105),\ + 0, 10000, PLATFORM_VALUE(40, 105),\ CFG_VALUE_OR_DEFAULT, "active dwell time") /* @@ -125,9 +159,51 @@ */ #define CFG_ACTIVE_MAX_2G_CHANNEL_TIME CFG_INI_UINT(\ "active_max_channel_time_2g",\ - 0, 10000, MCL_OR_WIN_VALUE(80, 0),\ + 0, 10000, PLATFORM_VALUE(80, 0),\ CFG_VALUE_OR_DEFAULT, "active dwell time for 2G channels") +/* + * + * active_max_channel_time_6g - Set max time for active 6G channel scan + * @Min: 0 + * @Max: 10000 + * @Default: 40 + * + * This ini is used to set maximum time in msecs spent in active 6G channel scan + * + * + * Related: None + * + * Usage: External + * + * + */ +#define CFG_ACTIVE_MAX_6G_CHANNEL_TIME CFG_INI_UINT(\ + "active_max_channel_time_6g",\ + 0, 10000, 40,\ + CFG_VALUE_OR_DEFAULT, "active dwell time for 6G channels") + +/* + * + * passive_max_channel_time_6g - Set max time for passive 6G channel scan + * @Min: 0 + * @Max: 10000 + * @Default: 30 + * + * This ini is used to set maximum time in msecs spent in passive 6G chan scan + * + * + * Related: None + * + * Usage: External + * + * + */ +#define CFG_PASSIVE_MAX_6G_CHANNEL_TIME CFG_INI_UINT(\ + "passive_max_channel_time_6g",\ + 0, 10000, 30,\ + CFG_VALUE_OR_DEFAULT, "passive dwell time for 6G channels") + /* * * gPassiveMaxChannelTime - Set max channel time for passive scan @@ -146,7 +222,7 @@ */ #define CFG_PASSIVE_MAX_CHANNEL_TIME CFG_INI_UINT(\ "gPassiveMaxChannelTime",\ - 0, 10000, MCL_OR_WIN_VALUE(110, 300),\ + 0, 10000, PLATFORM_VALUE(110, 300),\ CFG_VALUE_OR_DEFAULT, "passive dwell time") /* @@ -161,7 +237,7 @@ */ #define CFG_SCAN_NUM_PROBES CFG_INI_UINT(\ "gScanNumProbes",\ - 0, 20, MCL_OR_WIN_VALUE(0, 2),\ + 0, 20, PLATFORM_VALUE(0, 2),\ CFG_VALUE_OR_DEFAULT,\ "number of probes on each channel") @@ -185,7 +261,7 @@ */ #define CFG_SCAN_PROBE_REPEAT_TIME CFG_INI_UINT(\ "gScanProbeRepeatTime",\ - 0, 30, MCL_OR_WIN_VALUE(20, 50),\ + 0, 50, PLATFORM_VALUE(20, 50),\ CFG_VALUE_OR_DEFAULT,\ "probe repeat time on each channel") @@ -217,7 +293,7 @@ */ #define CFG_ADAPTIVE_SCAN_DWELL_MODE CFG_INI_UINT(\ "hostscan_adaptive_dwell_mode",\ - 0, 4, MCL_OR_WIN_VALUE(2, 0),\ + 0, 4, PLATFORM_VALUE(2, 0),\ CFG_VALUE_OR_DEFAULT,\ "Enable adaptive dwell mode") @@ -249,7 +325,7 @@ */ #define CFG_ADAPTIVE_SCAN_DWELL_MODE_NC CFG_INI_UINT(\ "hostscan_adaptive_dwell_mode_no_conn",\ - 0, 4, MCL_OR_WIN_VALUE(4, 0),\ + 0, 4, PLATFORM_VALUE(4, 0),\ CFG_VALUE_OR_DEFAULT,\ "Enable adaptive dwell mode without connection") @@ -307,6 +383,30 @@ "Set priority for connection with bssid_hint") #ifdef FEATURE_WLAN_SCAN_PNO +/* + * + * g_user_config_sched_scan_plan - set user config sched scan plans. + * @Min: 0 + * @Max:1 + * @Default: 1 + * + * This ini is used to decide if user config number of sched scan plan needs to + * be configured or only one sched scan plan needs to be configured. + * If this ini is enabled then user config number of sched scan plans will be + * configured else only one sched scan plan will be configured. + * + * Supported Feature: PNO scan + * + * Usage: External + * + * + */ + +#define CFG_USER_CONFIG_SCHED_SCAN_PLAN CFG_INI_BOOL(\ + "g_user_config_sched_scan_plan",\ + true, \ + "set user config sched scan plans") + /* * * g_max_sched_scan_plan_iterations - pno sched max scan plan iterations. @@ -632,7 +732,7 @@ * mawc_nlo_enabled - For NLO/PNO, enable MAWC based scan * @Min: 0 * @Max: 1 - * @Default: 1 + * @Default: 0 * * Enable/Disable the Motion Aided Wireless Connectivity * based NLO using this parameter @@ -645,7 +745,7 @@ */ #define CFG_MAWC_NLO_ENABLED CFG_INI_BOOL( \ "mawc_nlo_enabled", \ - 1, \ + 0, \ "Enable MAWC based scan") /* @@ -737,7 +837,8 @@ CFG(CFG_MAWC_NLO_ENABLED) \ CFG(CFG_MAWC_NLO_EXP_BACKOFF_RATIO) \ CFG(CFG_MAWC_NLO_INIT_SCAN_INTERVAL) \ - CFG(CFG_MAWC_NLO_MAX_SCAN_INTERVAL) + CFG(CFG_MAWC_NLO_MAX_SCAN_INTERVAL) \ + CFG(CFG_USER_CONFIG_SCHED_SCAN_PLAN) #else #define CFG_SCAN_PNO @@ -763,7 +864,7 @@ */ #define CFG_ACTIVE_MAX_CHANNEL_TIME_CONC CFG_INI_UINT(\ "gActiveMaxChannelTimeConc",\ - 0, 10000, MCL_OR_WIN_VALUE(40, 0),\ + 0, 10000, PLATFORM_VALUE(40, 0),\ CFG_VALUE_OR_DEFAULT, \ "active scan time in STA+SAP concurrent") @@ -787,7 +888,7 @@ */ #define CFG_PASSIVE_MAX_CHANNEL_TIME_CONC CFG_INI_UINT(\ "gPassiveMaxChannelTimeConc",\ - 0, 10000, MCL_OR_WIN_VALUE(110, 0),\ + 0, 10000, PLATFORM_VALUE(110, 0),\ CFG_VALUE_OR_DEFAULT, \ "Set priority for connection with bssid_hint") @@ -810,7 +911,7 @@ */ #define CFG_MAX_REST_TIME_CONC CFG_INI_UINT(\ "nRestTimeConc",\ - 0, 10000, MCL_OR_WIN_VALUE(100, 0),\ + 0, 10000, PLATFORM_VALUE(100, 0),\ CFG_VALUE_OR_DEFAULT, \ "Rest time before moving to a new channel") @@ -835,7 +936,7 @@ */ #define CFG_MIN_REST_TIME_CONC CFG_INI_UINT(\ "min_rest_time_conc",\ - 0, 50, MCL_OR_WIN_VALUE(50, 0),\ + 0, 50, PLATFORM_VALUE(50, 0),\ CFG_VALUE_OR_DEFAULT, \ "minimum time spent on home channel") @@ -890,7 +991,7 @@ */ #define CFG_IDLE_TIME_CONC CFG_INI_UINT(\ "gIdleTimeConc",\ - 0, 25, MCL_OR_WIN_VALUE(25, 0),\ + 0, 25, PLATFORM_VALUE(25, 0),\ CFG_VALUE_OR_DEFAULT, \ "data inactivity time on bss channel") @@ -1147,8 +1248,60 @@ false,\ "Enable/Disable SNR Monitoring") +/* + * + * scan_mode_6ghz - 6ghz Scan mode + * @Min: 0 + * @Max: 2 + * @Default: 2 + * + * Configure the 6Ghz scan mode + * 0 - Remove 6GHz channels in the scan request + * 1 - Allow/Add 6Ghz PSC channels to scan request + * 2 - Allow all the 6Ghz channels + * + * Related: SCAN + * + * Usage: Internal/External + * + * + */ +#define CFG_6GHZ_SCAN_MODE CFG_INI_UINT( \ + "scan_mode_6ghz", \ + SCAN_MODE_6G_NO_CHANNEL, \ + SCAN_MODE_6G_MAX, \ + PLATFORM_VALUE(SCAN_MODE_6G_PSC_CHANNEL, \ + SCAN_MODE_6G_ALL_CHANNEL), \ + CFG_VALUE_OR_DEFAULT, \ + "6ghz scan mode") + +/* + * + * scan_allow_bss_with_corrupted_ie - Continue scan even if corrupted IEs are + * present. + * @Min: 0 + * @Max: 1 + * @Default: 0 + * + * This ini is used to continue scan even if corrupted IEs are present. If this + * ini is enable, the scan module skips the IEs following corrupted IEs(IE's + * with invalid len) and adds the scan entry without completely dropping the + * frame. + * + * Related: scan + * + * Usage: External + * + * + */ +#define CFG_SCAN_ALLOW_BSS_WITH_CORRUPTED_IE CFG_INI_BOOL( \ + "scan_allow_bss_with_corrupted_ie", \ + false, \ + "scan allow bss with corrupted ie") + #define CFG_SCAN_ALL \ CFG(CFG_DROP_BCN_ON_CHANNEL_MISMATCH) \ + CFG(CFG_DROP_BCN_ON_INVALID_FREQ) \ CFG(CFG_ENABLE_WAKE_LOCK_IN_SCAN) \ CFG(CFG_ACTIVE_MAX_CHANNEL_TIME) \ CFG(CFG_ENABLE_DFS_SCAN) \ @@ -1156,6 +1309,8 @@ CFG(CFG_INITIAL_NO_DFS_SCAN) \ CFG(CFG_ACTIVE_MAX_2G_CHANNEL_TIME) \ CFG(CFG_PASSIVE_MAX_CHANNEL_TIME) \ + CFG(CFG_ACTIVE_MAX_6G_CHANNEL_TIME) \ + CFG(CFG_PASSIVE_MAX_6G_CHANNEL_TIME) \ CFG(CFG_SCAN_NUM_PROBES) \ CFG(CFG_SCAN_PROBE_REPEAT_TIME) \ CFG(CFG_ADAPTIVE_SCAN_DWELL_MODE) \ @@ -1176,6 +1331,8 @@ CFG(CFG_ENABLE_SNR_MONITORING) \ CFG(CFG_AP_SCAN_BURST_DURATION) \ CFG(CFG_ENABLE_SKIP_DFS_IN_P2P_SEARCH) \ + CFG(CFG_6GHZ_SCAN_MODE) \ + CFG(CFG_SCAN_ALLOW_BSS_WITH_CORRUPTED_IE) \ CFG_SCAN_PNO #endif /* __CONFIG_SCAN_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_public_structs.h index 10f5feebcc04cbf75b85400ae1d7385f782b9068..bba10550cf9205b1c6e2bcfe26c15bf0e5ed3afb 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_public_structs.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_public_structs.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 @@ -29,13 +29,16 @@ #include #include #include +#include typedef uint16_t wlan_scan_requester; typedef uint32_t wlan_scan_id; +#define WLAN_SCAN_MAX_HINT_S_SSID 10 +#define WLAN_SCAN_MAX_HINT_BSSID 10 +#define MAX_RNR_BSS 5 #define WLAN_SCAN_MAX_NUM_SSID 16 #define WLAN_SCAN_MAX_NUM_BSSID 4 -#define WLAN_SCAN_MAX_NUM_CHANNELS 68 #define SCM_CANCEL_SCAN_WAIT_TIME 50 #define SCM_CANCEL_SCAN_WAIT_ITERATION 600 @@ -68,14 +71,12 @@ typedef uint32_t wlan_scan_id; #define CHANNEL_CONGESTION_WEIGHTAGE 5 #define OCE_WAN_WEIGHTAGE 0 #define BEST_CANDIDATE_MAX_WEIGHT 100 +#define MAX_BSS_SCORE 200 #define MAX_INDEX_SCORE 100 #define MAX_INDEX_PER_INI 4 +#define SAE_PK_AP_WEIGHTAGE 3 -#ifdef CONFIG_MCL -#define MAX_BCN_PROBE_IN_SCAN_QUEUE 150 -#else -#define MAX_BCN_PROBE_IN_SCAN_QUEUE 2000 -#endif +#define BEST_CANDIDATE_MAX_BSS_SCORE (MAX_BSS_SCORE * 100) #define WLAN_GET_BITS(_val, _index, _num_bits) \ (((_val) >> (_index)) & ((1 << (_num_bits)) - 1)) @@ -89,6 +90,7 @@ typedef uint32_t wlan_scan_id; WLAN_GET_BITS(value32, (8 * (bw_index)), 8) #define WLAN_SET_SCORE_PERCENTAGE(value32, score_pcnt, bw_index) \ WLAN_SET_BITS(value32, (8 * (bw_index)), 8, score_pcnt) +#define TBTT_INFO_COUNT 16 /* forward declaration */ struct wlan_objmgr_vdev; @@ -97,15 +99,15 @@ struct wlan_objmgr_psoc; /** * struct channel_info - BSS channel information - * @chan_idx: current operating channel index + * @chan_freq: channel frequency * @cfreq0: channel frequency index0 * @cfreq1: channel frequency index1 * @priv: channel private information */ struct channel_info { - uint8_t chan_idx; - uint8_t cfreq0; - uint8_t cfreq1; + uint32_t chan_freq; + uint32_t cfreq0; + uint32_t cfreq1; void *priv; }; @@ -156,12 +158,16 @@ struct element_info { * @cswrp: pointer to channel switch announcement wrapper ie * @widebw: pointer to wide band channel switch sub ie * @txpwrenvlp: pointer to tx power envelop sub ie + * @hecap: pointer to hecap ie + * @hecap_6g: pointer to he 6ghz cap ie * @srp: pointer to spatial reuse parameter sub extended ie * @fils_indication: pointer to FILS indication ie * @esp: pointer to ESP indication ie * @mbo_oce: pointer to mbo/oce indication ie + * @rnrie: reduced neighbor report IE * @adaptive_11r: pointer to adaptive 11r IE * @single_pmk: Pointer to sae single pmk IE + * @rsnxe: Pointer to rsnxe IE */ struct ie_list { uint8_t *tim; @@ -203,15 +209,18 @@ struct ie_list { uint8_t *secchanoff; uint8_t *mdie; uint8_t *hecap; + uint8_t *hecap_6g; uint8_t *heop; uint8_t *srp; uint8_t *fils_indication; uint8_t *esp; uint8_t *mbo_oce; uint8_t *muedca; + uint8_t *rnrie; uint8_t *extender; uint8_t *adaptive_11r; uint8_t *single_pmk; + uint8_t *rsnxe; }; enum scan_entry_connection_state { @@ -242,12 +251,12 @@ struct mlme_info { /** * struct bss_info - information required to uniquely define a bss - * @chan: bss operating primary channel index + * @freq: freq of operating primary channel * @ssid: ssid of bss * @bssid: bssid of bss */ struct bss_info { - uint8_t chan; + uint32_t freq; struct wlan_ssid ssid; struct qdf_mac_addr bssid; }; @@ -285,6 +294,82 @@ struct scan_mbssid_info { uint8_t trans_bssid[QDF_MAC_ADDR_SIZE]; }; +/** + * struct rnr_bss_info - Reduced Neighbor Report BSS information + * @neighbor_ap_tbtt_offset: Neighbor AP TBTT offset + * @channel_number: channel number + * @operating_class: operting class + * @bssid: BSS MAC address + * @short_ssid: short ssid + * @bss_params: BSS parameters + */ +struct rnr_bss_info { + uint8_t neighbor_ap_tbtt_offset; + uint32_t channel_number; + uint32_t operating_class; + struct qdf_mac_addr bssid; + uint32_t short_ssid; + uint8_t bss_params; +}; + +/** + * struct tbtt_information_header - TBTT information header + * @tbbt_info_fieldtype: TBTT information field type + * @filter_neighbor_ap: filtered neighbor ap + * @tbbt_info_count: TBTT information count + * @tbtt_info_length: TBTT informaiton length + */ +struct tbtt_information_header { + uint16_t tbbt_info_fieldtype:2; + uint16_t filtered_neighbor_ap:1; + uint16_t reserved:1; + uint16_t tbtt_info_count:4; + uint16_t tbtt_info_length:8; +}; + +/** + * struct neighbor_ap_info_field - Neighbor information field + * @tbtt_info_header: TBTT information header + * @operting_class: operating class + * @channel_number: channel number + */ +struct neighbor_ap_info_field { + struct tbtt_information_header tbtt_header; + uint8_t operting_class; + uint8_t channel_number; +}; + +/** + * enum tbtt_information_field - TBTT information field + * @TBTT_NEIGHBOR_AP_OFFSET_ONLY: TBTT information field type + * @TBTT_NEIGHBOR_AP_BSS_PARAM: neighbor AP and bss param + * @TBTT_NEIGHBOR_AP_SHORTSSID: neighbor AP and Short ssid + * @TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM: neighbor AP, short ssid and bss param + * @TBTT_NEIGHBOR_AP_BSSID: neighbor AP and bssid + * @TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM: neighbor AP, bssid and bss param + * @TBTT_NEIGHBOR_AP_BSSSID_S_SSID: neighbor AP, bssid and short ssid + * @TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM: neighbor AP, bssid, short ssid + * and bss params + */ +enum tbtt_information_field { + TBTT_NEIGHBOR_AP_OFFSET_ONLY = 1, + TBTT_NEIGHBOR_AP_BSS_PARAM = 2, + TBTT_NEIGHBOR_AP_SHORTSSID = 5, + TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM = 6, + TBTT_NEIGHBOR_AP_BSSID = 7, + TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM = 8, + TBTT_NEIGHBOR_AP_BSSSID_S_SSID = 11, + TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM = 12 +}; + +/** + * struct reduced_neighbor_report - Reduced Neighbor Report + * @bss_info: RNR BSS Information + */ +struct reduced_neighbor_report { + struct rnr_bss_info bss_info[MAX_RNR_BSS]; +}; + #define SCAN_SECURITY_TYPE_WEP 0x01 #define SCAN_SECURITY_TYPE_WPA 0x02 #define SCAN_SECURITY_TYPE_WAPI 0x04 @@ -300,8 +385,10 @@ struct scan_mbssid_info { * @security_type: security supported * @seq_num: sequence number * @phy_mode: Phy mode of the AP - * @avg_rssi: Average RSSI fof the AP + * @avg_rssi: Average RSSI of the AP * @rssi_raw: The rssi of the last beacon/probe received + * @snr: The snr of the last beacon/probe received + * @avg_snr: Average SNR of the AP * @bcn_int: Beacon interval of the AP * @cap_info: Capability of the AP * @tsf_info: TSF info @@ -317,6 +404,7 @@ struct scan_mbssid_info { * @hidden_ssid_timestamp: boottime in microsec when hidden * ssid was received * @mbssid_info: Multi bssid information + * @rnr: Reduced neighbor report information * @channel: channel info on which AP is present * @channel_mismatch: if channel received in metadata * doesnot match the one in beacon @@ -330,6 +418,7 @@ struct scan_mbssid_info { * @alt_wcn_ie: alternate WCN IE * @ie_list: IE list pointers * @raw_frame: contain raw frame and the length of the raw frame + * @pdev_id: pdev id */ struct scan_cache_entry { uint8_t frm_subtype; @@ -342,6 +431,8 @@ struct scan_cache_entry { enum wlan_phymode phy_mode; int32_t avg_rssi; int8_t rssi_raw; + uint8_t snr; + uint32_t avg_snr; uint16_t bcn_int; union wlan_capability cap_info; union { @@ -359,6 +450,7 @@ struct scan_cache_entry { qdf_time_t rssi_timestamp; qdf_time_t hidden_ssid_timestamp; struct scan_mbssid_info mbssid_info; + struct reduced_neighbor_report rnr; struct channel_info channel; bool channel_mismatch; struct mlme_info mlme_info; @@ -371,6 +463,12 @@ struct scan_cache_entry { struct element_info alt_wcn_ie; struct ie_list ie_list; struct element_info raw_frame; + /* + * This is added temporarily for 6GHz channel to freq conversion + * to get pdev wherever it requores to convert frequency to + * channel as regulatory apis requires pdev as argument + */ + uint8_t pdev_id; }; #define MAX_FAVORED_BSSID 16 @@ -389,6 +487,7 @@ struct scan_cache_entry { * @pcl_weightage: PCL weightage * @channel_congestion_weightage: channel congestion weightage * @oce_wan_weightage: OCE WAN metrics weightage + * @sae_pk_ap_weightage: SAE-PK AP weigtage */ struct weight_config { uint8_t rssi_weightage; @@ -402,6 +501,7 @@ struct weight_config { uint8_t pcl_weightage; uint8_t channel_congestion_weightage; uint8_t oce_wan_weightage; + uint8_t sae_pk_ap_weightage; }; /** @@ -547,11 +647,11 @@ struct fils_filter_info { * @country[3]: Ap with specific country code * @bssid_list: bssid list * @ssid_list: ssid list - * @channel_list: channel list + * @chan_freq_list: channel frequency list, frequency unit: MHz * @auth_type: auth type list * @enc_type: unicast enc type list * @mc_enc_type: multicast cast enc type list - * @pcl_channel_list: PCL channel list + * @pcl_freq_list: PCL channel frequency list, frequency unit: MHz * @fils_scan_filter: FILS info * @pcl_weight_list: PCL Weight list * @bssid_hint: Mac address of bssid_hint @@ -582,13 +682,13 @@ struct scan_filter { uint8_t country[3]; struct qdf_mac_addr bssid_list[WLAN_SCAN_FILTER_NUM_BSSID]; struct wlan_ssid ssid_list[WLAN_SCAN_FILTER_NUM_SSID]; - uint8_t channel_list[QDF_MAX_NUM_CHAN]; + uint32_t chan_freq_list[NUM_CHANNELS]; enum wlan_auth_type auth_type[WLAN_NUM_OF_SUPPORT_AUTH_TYPE]; enum wlan_enc_type enc_type[WLAN_NUM_OF_ENCRYPT_TYPE]; enum wlan_enc_type mc_enc_type[WLAN_NUM_OF_ENCRYPT_TYPE]; - uint8_t pcl_channel_list[QDF_MAX_NUM_CHAN]; + uint32_t pcl_freq_list[NUM_CHANNELS]; struct fils_filter_info fils_scan_filter; - uint8_t pcl_weight_list[QDF_MAX_NUM_CHAN]; + uint8_t pcl_weight_list[NUM_CHANNELS]; struct qdf_mac_addr bssid_hint; }; @@ -624,27 +724,6 @@ enum scan_priority { SCAN_PRIORITY_COUNT, }; - -/** - * enum scan_type - type of scan - * @SCAN_TYPE_BACKGROUND: background scan - * @SCAN_TYPE_FOREGROUND: foregrounc scan - * @SCAN_TYPE_SPECTRAL: spectral scan - * @SCAN_TYPE_REPEATER_BACKGROUND: background scan in repeater - * @SCAN_TYPE_REPEATER_EXT_BACKGROUND: background scan in extended repeater - * @SCAN_TYPE_RADIO_MEASUREMENTS: redio measurement - * @SCAN_TYPE_COUNT: number of scan types supported - */ -enum scan_type { - SCAN_TYPE_BACKGROUND, - SCAN_TYPE_FOREGROUND, - SCAN_TYPE_SPECTRAL, - SCAN_TYPE_REPEATER_BACKGROUND, - SCAN_TYPE_REPEATER_EXT_BACKGROUND, - SCAN_TYPE_RADIO_MEASUREMENTS, - SCAN_TYPE_COUNT, -}; - /** * enum scan_phy_mode - phymode used for scan * @SCAN_PHY_MODE_11A: 11a mode @@ -703,21 +782,6 @@ enum scan_phy_mode { SCAN_PHY_MODE_MAX = 24 }; -/** - * struct scan_extra_params_legacy - * extra parameters required for legacy DA scan module - * @scan_type: type of scan - * @min_dwell_active: min active dwell time - * @min_dwell_passive: min passive dwell time - * @init_rest_time: init rest time for enhanced independent repeater - */ -struct scan_extra_params_legacy { - enum scan_type scan_type; - uint32_t min_dwell_active; - uint32_t min_dwell_passive; - uint32_t init_rest_time; -}; - /** * enum scan_dwelltime_adaptive_mode: dwelltime_mode * @SCAN_DWELL_MODE_DEFAULT: Use firmware default mode @@ -766,7 +830,7 @@ struct probe_req_whitelist_attr { * @phymode: phymode in which @frequency should be scanned */ struct chan_info { - uint32_t freq; + qdf_freq_t freq; uint32_t phymode; }; @@ -777,8 +841,32 @@ struct chan_info { * @chan: channel parameters used for this scan */ struct chan_list { - uint32_t num_chan; - struct chan_info chan[WLAN_SCAN_MAX_NUM_CHANNELS]; + uint8_t num_chan; + struct chan_info chan[NUM_CHANNELS]; +}; + +/** + * struct hint_short_ssid - short SSID hint + * and their phymode + * @freq_flags: freq unit: MHz (upper 16bits) + * flags (lower 16bits) + * @short_ssid: short SSID + */ +struct hint_short_ssid { + uint32_t freq_flags; + uint32_t short_ssid; +}; + +/** + * struct hint_bssid - BSSID hint + * and their phymode + * @freq_flags: freq unit: MHz (upper 16bits) + * flags (lower 16bits) + * @bssid: BSSID + */ +struct hint_bssid { + uint32_t freq_flags; + struct qdf_mac_addr bssid; }; /** @@ -820,6 +908,8 @@ enum scan_request_type { * @dwell_time_active: active dwell time * @dwell_time_active_2g: active dwell time for 2G channels, if it's not zero * @dwell_time_passive: passive dwell time + * @dwell_time_active_6g: 6Ghz active dwell time + * @dwell_time_passive_6g: 6Ghz passive dwell time * @min_rest_time: min rest time * @max_rest_time: max rest time * @repeat_probe_time: repeat probe time @@ -869,6 +959,10 @@ enum scan_request_type { * @htcap: htcap ie * @vhtcap: vhtcap ie * @scan_ctrl_flags_ext: scan control flag extended + * @num_hint_s_ssid: number of short SSID hints + * @num_hint_bssid: number of BSSID hints + * @hint_s_ssid: short SSID hints + * @hint_bssid: BSSID hints */ struct scan_req_params { @@ -899,6 +993,8 @@ struct scan_req_params { uint32_t dwell_time_active; uint32_t dwell_time_active_2g; uint32_t dwell_time_passive; + uint32_t dwell_time_active_6g; + uint32_t dwell_time_passive_6g; uint32_t min_rest_time; uint32_t max_rest_time; uint32_t repeat_probe_time; @@ -960,17 +1056,19 @@ struct scan_req_params { struct element_info htcap; struct element_info vhtcap; uint32_t scan_ctrl_flags_ext; + uint32_t num_hint_s_ssid; + uint32_t num_hint_bssid; + struct hint_short_ssid hint_s_ssid[WLAN_SCAN_MAX_HINT_S_SSID]; + struct hint_bssid hint_bssid[WLAN_SCAN_MAX_HINT_BSSID]; }; /** * struct scan_start_request - scan request config * @vdev: vdev - * @legacy_params: extra parameters required for legacy DA arch * @scan_req: common scan start request parameters */ struct scan_start_request { struct wlan_objmgr_vdev *vdev; - struct scan_extra_params_legacy legacy_params; struct scan_req_params scan_req; }; @@ -1171,7 +1269,7 @@ enum scan_cb_type { /* Set PNO */ #define SCAN_PNO_MAX_PLAN_REQUEST 2 -#define SCAN_PNO_MAX_NETW_CHANNELS_EX 60 +#define SCAN_PNO_MAX_NETW_CHANNELS_EX (NUM_CHANNELS) #define SCAN_PNO_MAX_SUPP_NETWORKS 16 #define SCAN_PNO_DEF_SLOW_SCAN_MULTIPLIER 6 #define SCAN_PNO_DEF_SCAN_TIMER_REPEAT 20 @@ -1357,4 +1455,62 @@ enum ext_cap_bit_field { OBSS_NARROW_BW_RU_IN_ULOFDMA_TOLERENT_SUPPORT = 79, }; +/** + * scan_rnr_info - RNR information + * @timestamp: time stamp of beacon/probe + * @short_ssid: Short SSID + * @bssid: BSSID + */ +struct scan_rnr_info { + qdf_time_t timestamp; + uint32_t short_ssid; + struct qdf_mac_addr bssid; +}; + +/** + * struct scan_rnr_node - Scan RNR entry node + * @node: node pointers + * @entry: scan RNR entry pointer + */ +struct scan_rnr_node { + qdf_list_node_t node; + struct scan_rnr_info entry; +}; + +/** + * meta_rnr_channel - Channel information for scan priority algorithm + * @chan_freq: channel frequency + * @bss_beacon_probe_count: Beacon and probe request count + * @saved_profile_count: Saved profile count + * @beacon_probe_last_time_found: Timestamp of beacon/probe observed + * @rnr_list: RNR list to store RNR IE information + */ +struct meta_rnr_channel { + uint32_t chan_freq; + uint32_t bss_beacon_probe_count; + uint32_t saved_profile_count; + qdf_time_t beacon_probe_last_time_found; + qdf_list_t rnr_list; +}; + +#define RNR_UPDATE_SCAN_CNT_THRESHOLD 2 +/** + * channel_list_db - Database for channel information + * @channel: channel meta information + * @scan_count: scan count since the db was updated + */ +struct channel_list_db { + struct meta_rnr_channel channel[NUM_6GHZ_CHANNELS]; + uint8_t scan_count; +}; + +/** + * rnr_chan_weight - RNR channel weightage + * @chan_freq: channel frequency + * @weight: weightage of the channel + */ +struct rnr_chan_weight { + uint32_t chan_freq; + uint32_t weight; +}; #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h index dbc4f90ee54402f8773a548e2466022dac6e5d7f..4f2f5a66b267163edee4fe2aeb629a6160bf50c4 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-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 @@ -371,7 +371,7 @@ QDF_STATUS ucfg_scan_flush_results(struct wlan_objmgr_pdev *pdev, * ucfg_scan_filter_valid_channel() - The Public API to filter scan result * based on valid channel list * @pdev: pdev object - * @chan_list: valid channel list + * @chan_freq_list: valid channel frequency (in MHz) list * @num_chan: number of valid channels * * The Public API to to filter scan result @@ -380,7 +380,7 @@ QDF_STATUS ucfg_scan_flush_results(struct wlan_objmgr_pdev *pdev, * Return: void. */ void ucfg_scan_filter_valid_channel(struct wlan_objmgr_pdev *pdev, - uint8_t *chan_list, uint32_t num_chan); + uint32_t *chan_freq_list, uint32_t num_chan); /** * ucfg_scan_db_iterate() - function to iterate scan table @@ -954,6 +954,16 @@ ucfg_scan_get_max_sched_scan_plan_interval(struct wlan_objmgr_psoc *psoc); uint32_t ucfg_scan_get_max_sched_scan_plan_iterations(struct wlan_objmgr_psoc *psoc); +/** + * ucfg_scan_get_user_config_sched_scan_plan() - API to get user config sched + * scan plan configuration value + * @psoc: pointer to psoc object + * + * Return: value. + */ +bool +ucfg_scan_get_user_config_sched_scan_plan(struct wlan_objmgr_psoc *psoc); + #else static inline bool ucfg_scan_is_pno_offload_enabled(struct wlan_objmgr_psoc *psoc) @@ -1008,6 +1018,12 @@ ucfg_scan_get_max_sched_scan_plan_iterations(struct wlan_objmgr_psoc *psoc) return 0; } +static inline bool +ucfg_scan_get_user_config_sched_scan_plan(struct wlan_objmgr_psoc *psoc) +{ + return true; +} + #endif /* FEATURE_WLAN_SCAN_PNO */ /** diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_utils_api.h b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_utils_api.h index 6fb5f54d3f653dd8408939864584d24e8c98f6bb..f40242324a1d32bf0976f18bc2d0d29360ff39ad 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_utils_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/inc/wlan_scan_utils_api.h @@ -30,6 +30,7 @@ #include #include #include +#include #define ASCII_SPACE_CHARACTER 32 @@ -207,7 +208,7 @@ util_scan_entry_reset_timestamp(struct scan_cache_entry *scan_entry) #define WLAN_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */ -#define WLAN_RSSI_LPF_LEN 10 +#define WLAN_RSSI_LPF_LEN 0 #define WLAN_RSSI_DUMMY_MARKER 0x127 #define WLAN_EP_MUL(x, mul) ((x) * (mul)) @@ -230,7 +231,7 @@ util_scan_entry_reset_timestamp(struct scan_cache_entry *scan_entry) ((x != WLAN_RSSI_DUMMY_MARKER) ? ((((x) << 3) + (y) - (x)) >> 3) : (y)) #define WLAN_RSSI_LPF(x, y) do { \ - if ((y) >= RSSI_LPF_THRESHOLD) \ + if ((y) < RSSI_LPF_THRESHOLD) \ x = WLAN_LPF_RSSI((x), WLAN_RSSI_IN((y)), WLAN_RSSI_LPF_LEN); \ } while (0) @@ -239,6 +240,24 @@ util_scan_entry_reset_timestamp(struct scan_cache_entry *scan_entry) x = WLAN_LPF_RSSI((x), WLAN_RSSI_IN((y)), WLAN_RSSI_LPF_LEN); \ } while (0) +#define WLAN_SNR_EP_MULTIPLIER BIT(7) /* pow2 to optimize out * and / */ +#define WLAN_SNR_DUMMY_MARKER 0x127 +#define SNR_LPF_THRESHOLD 0 +#define WLAN_SNR_LPF_LEN 10 + +#define WLAN_SNR_OUT(x) (((x) != WLAN_SNR_DUMMY_MARKER) ? \ + (WLAN_EP_RND((x), WLAN_SNR_EP_MULTIPLIER)) : WLAN_SNR_DUMMY_MARKER) + +#define WLAN_SNR_IN(x) (WLAN_EP_MUL((x), WLAN_SNR_EP_MULTIPLIER)) + +#define WLAN_LPF_SNR(x, y, len) \ + ((x != WLAN_SNR_DUMMY_MARKER) ? ((((x) << 3) + (y) - (x)) >> 3) : (y)) + +#define WLAN_SNR_LPF(x, y) do { \ + if ((y) > SNR_LPF_THRESHOLD) \ + x = WLAN_LPF_SNR((x), WLAN_SNR_IN((y)), WLAN_SNR_LPF_LEN); \ + } while (0) + /** * util_scan_entry_rssi() - function to read rssi of scan entry * @scan_entry: scan entry @@ -247,20 +266,33 @@ util_scan_entry_reset_timestamp(struct scan_cache_entry *scan_entry) * * Return: rssi */ -static inline uint8_t +static inline int32_t util_scan_entry_rssi(struct scan_cache_entry *scan_entry) { - uint32_t rssi = WLAN_RSSI_OUT(scan_entry->avg_rssi); + return WLAN_RSSI_OUT(scan_entry->avg_rssi); +} + +/** + * util_scan_entry_snr() - function to read snr of scan entry + * @scan_entry: scan entry + * + * API, function to read snr value of scan entry + * + * Return: snr + */ +static inline uint8_t +util_scan_entry_snr(struct scan_cache_entry *scan_entry) +{ + uint32_t snr = WLAN_SNR_OUT(scan_entry->avg_snr); /* * An entry is in the BSS list means we've received at least one beacon - * from the corresponding AP, so the rssi must be initialized. + * from the corresponding AP, so the snr must be initialized. * - * If the RSSI is not initialized, return 0 (i.e. RSSI == Noise Floor). - * Once se_avgrssi field has been initialized, ATH_RSSI_OUT always - * returns values that fit in an 8-bit variable - * (RSSI values are typically 0-90). + * If the SNR is not initialized, return 0 (i.e. SNR == Noise Floor). + * Once se_avgsnr field has been initialized, ATH_SNR_OUT always + * returns values that fit in an 8-bit variable. */ - return (rssi >= WLAN_RSSI_DUMMY_MARKER) ? 0 : (uint8_t) rssi; + return (snr >= WLAN_SNR_DUMMY_MARKER) ? 0 : (uint8_t)snr; } /** @@ -672,9 +704,12 @@ util_scan_copy_beacon_data(struct scan_cache_entry *new_entry, old_ptr, new_ptr); ie_lst->esp = conv_ptr(ie_lst->esp, old_ptr, new_ptr); ie_lst->mbo_oce = conv_ptr(ie_lst->mbo_oce, old_ptr, new_ptr); + ie_lst->muedca = conv_ptr(ie_lst->muedca, old_ptr, new_ptr); + ie_lst->rnrie = conv_ptr(ie_lst->rnrie, old_ptr, new_ptr); ie_lst->extender = conv_ptr(ie_lst->extender, old_ptr, new_ptr); ie_lst->adaptive_11r = conv_ptr(ie_lst->adaptive_11r, old_ptr, new_ptr); ie_lst->single_pmk = conv_ptr(ie_lst->single_pmk, old_ptr, new_ptr); + ie_lst->rsnxe = conv_ptr(ie_lst->rsnxe, old_ptr, new_ptr); return QDF_STATUS_SUCCESS; } @@ -742,17 +777,17 @@ util_scan_entry_channel(struct scan_cache_entry *scan_entry) } /** - * util_scan_entry_channel_num() - function to read channel number + * util_scan_entry_channel_frequency() - function to read channel number * @scan_entry: scan entry * * API, function to read channel number * * Return: channel number */ -static inline uint8_t -util_scan_entry_channel_num(struct scan_cache_entry *scan_entry) +static inline uint32_t +util_scan_entry_channel_frequency(struct scan_cache_entry *scan_entry) { - return scan_entry->channel.chan_idx; + return scan_entry->channel.chan_freq; } /** @@ -1418,6 +1453,19 @@ util_scan_entry_hecap(struct scan_cache_entry *scan_entry) return scan_entry->ie_list.hecap; } +/** + * util_scan_entry_he_6g_cap() - function to read he 6GHz caps vendor ie + * @scan_entry: scan entry + * + * API, function to read he 6GHz caps vendor ie + * + * Return: he caps vendorie or NULL if ie is not present + */ +static inline uint8_t* +util_scan_entry_he_6g_cap(struct scan_cache_entry *scan_entry) +{ + return scan_entry->ie_list.hecap_6g; +} /** * util_scan_entry_heop() - function to read heop vendor ie @@ -1553,6 +1601,20 @@ util_scan_entry_mbo_oce(struct scan_cache_entry *scan_entry) return scan_entry->ie_list.mbo_oce; } +/** + * util_scan_entry_rsnxe() - function to read RSNXE ie + * @scan_entry: scan entry + * + * API, function to read RSNXE ie + * + * Return: RSNXE ie + */ +static inline uint8_t * +util_scan_entry_rsnxe(struct scan_cache_entry *scan_entry) +{ + return scan_entry->ie_list.rsnxe; +} + /** * util_scan_scm_chan_to_band() - function to tell band for channel number * @chan: Channel number diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index ca8be76518e88e52fd7944330cc0a3c2e42fb114..b77e7fc3939e59f80e01fcc020babe1ad20f3e2a 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -1,6 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2017-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 above @@ -72,9 +71,9 @@ QDF_STATUS ucfg_scan_flush_results(struct wlan_objmgr_pdev *pdev, } void ucfg_scan_filter_valid_channel(struct wlan_objmgr_pdev *pdev, - uint8_t *chan_list, uint32_t num_chan) + uint32_t *chan_freq_list, uint32_t num_chan) { - scm_filter_valid_channel(pdev, chan_list, num_chan); + scm_filter_valid_channel(pdev, chan_freq_list, num_chan); } QDF_STATUS ucfg_scan_init(void) @@ -261,6 +260,8 @@ wlan_pno_global_init(struct wlan_objmgr_psoc *psoc, cfg_get(psoc, CFG_MAX_SCHED_SCAN_PLAN_INTERVAL); pno_def->max_sched_scan_plan_iterations = cfg_get(psoc, CFG_MAX_SCHED_SCAN_PLAN_ITERATIONS); + pno_def->user_config_sched_scan_plan = + cfg_get(psoc, CFG_USER_CONFIG_SCHED_SCAN_PLAN); mawc_cfg->enable = cfg_get(psoc, CFG_MAWC_NLO_ENABLED); mawc_cfg->exp_backoff_ratio = @@ -625,8 +626,8 @@ ucfg_scan_config_hidden_ssid_for_bssid(struct wlan_objmgr_pdev *pdev, if (!scan_obj) return QDF_STATUS_E_FAILURE; - scm_debug("Configure bsssid:%pM ssid:%.*s", - bssid, ssid->length, ssid->ssid); + scm_debug("Configure bsssid:"QDF_MAC_ADDR_FMT" ssid:%.*s", + QDF_MAC_ADDR_REF(bssid), ssid->length, ssid->ssid); qdf_mem_copy(scan_obj->pdev_info[pdev_id].conf_bssid, bssid, QDF_MAC_ADDR_SIZE); scan_obj->pdev_info[pdev_id].conf_ssid.length = ssid->length; @@ -956,6 +957,8 @@ wlan_scan_global_init(struct wlan_objmgr_psoc *psoc, scan_obj->scan_disabled = 0; scan_obj->drop_bcn_on_chan_mismatch = cfg_get(psoc, CFG_DROP_BCN_ON_CHANNEL_MISMATCH); + scan_obj->drop_bcn_on_invalid_freq = + cfg_get(psoc, CFG_DROP_BCN_ON_INVALID_FREQ); scan_obj->disable_timeout = false; scan_obj->scan_def.active_dwell = cfg_get(psoc, CFG_ACTIVE_MAX_CHANNEL_TIME); @@ -970,6 +973,10 @@ wlan_scan_global_init(struct wlan_objmgr_psoc *psoc, cfg_get(psoc, CFG_ENABLE_WAKE_LOCK_IN_SCAN); scan_obj->scan_def.active_dwell_2g = cfg_get(psoc, CFG_ACTIVE_MAX_2G_CHANNEL_TIME); + scan_obj->scan_def.active_dwell_6g = + cfg_get(psoc, CFG_ACTIVE_MAX_6G_CHANNEL_TIME); + scan_obj->scan_def.passive_dwell_6g = + cfg_get(psoc, CFG_PASSIVE_MAX_6G_CHANNEL_TIME); scan_obj->scan_def.passive_dwell = cfg_get(psoc, CFG_PASSIVE_MAX_CHANNEL_TIME); scan_obj->scan_def.max_rest_time = SCAN_MAX_REST_TIME; @@ -1039,6 +1046,9 @@ wlan_scan_global_init(struct wlan_objmgr_psoc *psoc, scan_obj->scan_def.scan_ev_restarted = true; scan_obj->scan_def.enable_connected_scan = cfg_get(psoc, CFG_ENABLE_CONNECTED_SCAN); + scan_obj->scan_def.scan_mode_6g = cfg_get(psoc, CFG_6GHZ_SCAN_MODE); + scan_obj->allow_bss_with_incomplete_ie = + cfg_get(psoc, CFG_SCAN_ALLOW_BSS_WITH_CORRUPTED_IE); /* init scan id seed */ qdf_atomic_init(&scan_obj->scan_ids); @@ -1160,6 +1170,8 @@ ucfg_scan_init_default_params(struct wlan_objmgr_vdev *vdev, req->scan_req.scan_priority = def->scan_priority; req->scan_req.dwell_time_active = def->active_dwell; req->scan_req.dwell_time_active_2g = def->active_dwell_2g; + req->scan_req.dwell_time_active_6g = def->active_dwell_6g; + req->scan_req.dwell_time_passive_6g = def->passive_dwell_6g; req->scan_req.dwell_time_passive = def->passive_dwell; req->scan_req.min_rest_time = def->min_rest_time; req->scan_req.max_rest_time = def->max_rest_time; @@ -1270,8 +1282,8 @@ ucfg_scan_init_bssid_params(struct scan_start_request *req, */ static bool is_chan_enabled_for_scan(struct regulatory_channel *reg_chan, - uint32_t low_2g, uint32_t high_2g, uint32_t low_5g, - uint32_t high_5g) + qdf_freq_t low_2g, qdf_freq_t high_2g, qdf_freq_t low_5g, + qdf_freq_t high_5g) { if (reg_chan->state == CHANNEL_STATE_DISABLE) return false; @@ -1299,7 +1311,7 @@ ucfg_scan_init_chanlist_params(struct scan_start_request *req, uint32_t idx; QDF_STATUS status; struct regulatory_channel *reg_chan_list = NULL; - uint32_t low_2g, high_2g, low_5g, high_5g; + qdf_freq_t low_2g, high_2g, low_5g, high_5g; struct wlan_objmgr_pdev *pdev = NULL; uint32_t *scan_freqs = NULL; uint32_t max_chans = sizeof(req->scan_req.chan_list.chan) / @@ -1626,6 +1638,7 @@ ucfg_scan_psoc_open(struct wlan_objmgr_psoc *psoc) qdf_spinlock_create(&scan_obj->lock); ucfg_scan_register_pmo_handler(); scm_db_init(psoc); + scm_channel_list_db_init(psoc); return QDF_STATUS_SUCCESS; } @@ -1649,6 +1662,7 @@ ucfg_scan_psoc_close(struct wlan_objmgr_psoc *psoc) ucfg_scan_unregister_pmo_handler(); qdf_spinlock_destroy(&scan_obj->lock); wlan_scan_global_deinit(psoc); + scm_channel_list_db_deinit(psoc); return QDF_STATUS_SUCCESS; } @@ -2040,4 +2054,17 @@ ucfg_scan_get_max_sched_scan_plan_iterations(struct wlan_objmgr_psoc *psoc) return scan_obj->pno_cfg.max_sched_scan_plan_iterations; } +bool +ucfg_scan_get_user_config_sched_scan_plan(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_scan_obj *scan_obj; + + scan_obj = wlan_psoc_get_scan_obj(psoc); + if (!scan_obj) { + scm_err("Failed to get scan object"); + return cfg_default(CFG_MAX_SCHED_SCAN_PLAN_ITERATIONS); + } + + return scan_obj->pno_cfg.user_config_sched_scan_plan; +} #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_utils_api.c index d589d0dd71163537b3afe5a116c46462fccb2c8c..02ab28c5bc979aa3b8998b79f560e5a37772941c 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. 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 @@ -29,6 +29,9 @@ #include #define MAX_IE_LEN 1024 +#define SHORT_SSID_LEN 4 +#define NEIGHBOR_AP_LEN 1 +#define BSS_PARAMS_LEN 1 const char* util_scan_get_ev_type_name(enum scan_event_type type) @@ -142,8 +145,8 @@ bool util_is_scan_entry_match( util_scan_is_null_ssid(&entry2->ssid)) return true; } else if (entry1->cap_info.wlan_caps.ibss && - (entry1->channel.chan_idx == - entry2->channel.chan_idx)) { + (entry1->channel.chan_freq == + entry2->channel.chan_freq)) { /* * Same channel cannot have same SSID for * different IBSS, so no need to check BSSID @@ -182,14 +185,194 @@ static bool util_is_pureg_rate(uint8_t *rates, uint8_t nrates) return pureg; } +#ifdef CONFIG_BAND_6GHZ +static struct he_oper_6g_param *util_scan_get_he_6g_params(uint8_t *he_ops) +{ + uint8_t len; + uint32_t he_oper_params; + + if (!he_ops) + return NULL; + + len = he_ops[1]; + he_ops += sizeof(struct ie_header); + + if (len < WLAN_HEOP_FIXED_PARAM_LENGTH) + return NULL; + + /* element id extension */ + he_ops++; + len--; + + he_oper_params = LE_READ_4(he_ops); + if (!(he_oper_params & WLAN_HEOP_6GHZ_INFO_PRESENT_MASK)) + return NULL; + + /* fixed params - element id extension */ + he_ops += WLAN_HEOP_FIXED_PARAM_LENGTH - 1; + len -= WLAN_HEOP_FIXED_PARAM_LENGTH - 1; + + if (!len) + return NULL; + + /* vht oper params */ + if (he_oper_params & WLAN_HEOP_VHTOP_PRESENT_MASK) { + if (len < WLAN_HEOP_VHTOP_LENGTH) + return NULL; + he_ops += WLAN_HEOP_VHTOP_LENGTH; + len -= WLAN_HEOP_VHTOP_LENGTH; + } + + if (!len) + return NULL; + + if (he_oper_params & WLAN_HEOP_CO_LOCATED_BSS_MASK) { + he_ops += WLAN_HEOP_CO_LOCATED_BSS_LENGTH; + len -= WLAN_HEOP_CO_LOCATED_BSS_LENGTH; + } + + if (len < sizeof(struct he_oper_6g_param)) + return NULL; + + return (struct he_oper_6g_param *)he_ops; +} + +static QDF_STATUS +util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev, + struct scan_cache_entry *scan_params, + qdf_freq_t *chan_freq, uint8_t band_mask) +{ + struct he_oper_6g_param *he_6g_params; + uint8_t *he_ops; + struct wlan_scan_obj *scan_obj; + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + scm_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + + scan_obj = wlan_psoc_get_scan_obj(psoc); + if (!scan_obj) { + scm_err("scan_obj is NULL"); + return QDF_STATUS_E_INVAL; + } + + he_ops = util_scan_entry_heop(scan_params); + if (!util_scan_entry_hecap(scan_params) || !he_ops) + return QDF_STATUS_SUCCESS; + + he_6g_params = util_scan_get_he_6g_params(he_ops); + if (!he_6g_params) + return QDF_STATUS_SUCCESS; + + *chan_freq = wlan_reg_chan_band_to_freq(pdev, + he_6g_params->primary_channel, + band_mask); + if (scan_obj->drop_bcn_on_invalid_freq && + wlan_reg_is_disable_for_freq(pdev, *chan_freq)) { + scm_debug_rl(QDF_MAC_ADDR_FMT": Drop as invalid channel %d freq %d in HE 6Ghz params", + scan_params->bssid.bytes, + he_6g_params->primary_channel, *chan_freq); + return QDF_STATUS_E_INVAL; + } + + return QDF_STATUS_SUCCESS; +} + static enum wlan_phymode -util_scan_get_phymode_5g(struct scan_cache_entry *scan_params) +util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev, + struct scan_cache_entry *scan_params) +{ + struct he_oper_6g_param *he_6g_params; + enum wlan_phymode phymode = WLAN_PHYMODE_11AXA_HE20; + uint8_t *he_ops; + uint8_t band_mask = BIT(REG_BAND_6G); + + he_ops = util_scan_entry_heop(scan_params); + if (!util_scan_entry_hecap(scan_params) || !he_ops) + return phymode; + + he_6g_params = util_scan_get_he_6g_params(he_ops); + if (!he_6g_params) + return phymode; + + switch (he_6g_params->width) { + case WLAN_HE_6GHZ_CHWIDTH_20: + phymode = WLAN_PHYMODE_11AXA_HE20; + break; + case WLAN_HE_6GHZ_CHWIDTH_40: + phymode = WLAN_PHYMODE_11AXA_HE40; + break; + case WLAN_HE_6GHZ_CHWIDTH_80: + phymode = WLAN_PHYMODE_11AXA_HE80; + break; + case WLAN_HE_6GHZ_CHWIDTH_160_80_80: + if (WLAN_IS_HE80_80(he_6g_params)) + phymode = WLAN_PHYMODE_11AXA_HE80_80; + else if (WLAN_IS_HE160(he_6g_params)) + phymode = WLAN_PHYMODE_11AXA_HE160; + else + phymode = WLAN_PHYMODE_11AXA_HE80; + break; + default: + scm_err("Invalid he_6g_params width: %d", he_6g_params->width); + phymode = WLAN_PHYMODE_11AXA_HE20; + break; + } + + if (he_6g_params->chan_freq_seg0) + scan_params->channel.cfreq0 = + wlan_reg_chan_band_to_freq(pdev, + he_6g_params->chan_freq_seg0, + band_mask); + if (he_6g_params->chan_freq_seg1) + scan_params->channel.cfreq1 = + wlan_reg_chan_band_to_freq(pdev, + he_6g_params->chan_freq_seg1, + band_mask); + + return phymode; +} +#else +static QDF_STATUS +util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev, + struct scan_cache_entry *scan_params, + qdf_freq_t *chan_freq, uint8_t band_mask) +{ + return QDF_STATUS_SUCCESS; +} +static inline enum wlan_phymode +util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev, + struct scan_cache_entry *scan_params) +{ + return WLAN_PHYMODE_AUTO; +} +#endif + +static inline +uint32_t util_scan_sec_chan_freq_from_htinfo(struct wlan_ie_htinfo_cmn *htinfo, + uint32_t primary_chan_freq) +{ + if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE) + return primary_chan_freq + WLAN_CHAN_SPACING_20MHZ; + else if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW) + return primary_chan_freq - WLAN_CHAN_SPACING_20MHZ; + + return 0; +} + +static enum wlan_phymode +util_scan_get_phymode_5g(struct wlan_objmgr_pdev *pdev, + struct scan_cache_entry *scan_params) { enum wlan_phymode phymode = WLAN_PHYMODE_AUTO; uint16_t ht_cap = 0; struct htcap_cmn_ie *htcap; struct wlan_ie_htinfo_cmn *htinfo; struct wlan_ie_vhtop *vhtop; + uint8_t band_mask = BIT(REG_BAND_5G); htcap = (struct htcap_cmn_ie *) util_scan_entry_htcap(scan_params); @@ -209,6 +392,10 @@ util_scan_get_phymode_5g(struct scan_cache_entry *scan_params) else phymode = WLAN_PHYMODE_11NA_HT20; + scan_params->channel.cfreq0 = + util_scan_sec_chan_freq_from_htinfo(htinfo, + scan_params->channel.chan_freq); + if (util_scan_entry_vhtcap(scan_params) && vhtop) { switch (vhtop->vht_op_chwidth) { case WLAN_VHTOP_CHWIDTH_2040: @@ -237,6 +424,16 @@ util_scan_get_phymode_5g(struct scan_cache_entry *scan_params) phymode = WLAN_PHYMODE_11AC_VHT20; break; } + if (vhtop->vht_op_ch_freq_seg1) + scan_params->channel.cfreq0 = + wlan_reg_chan_band_to_freq(pdev, + vhtop->vht_op_ch_freq_seg1, + band_mask); + if (vhtop->vht_op_ch_freq_seg2) + scan_params->channel.cfreq1 = + wlan_reg_chan_band_to_freq(pdev, + vhtop->vht_op_ch_freq_seg2, + band_mask); } if (!util_scan_entry_hecap(scan_params)) @@ -318,6 +515,10 @@ util_scan_get_phymode_2g(struct scan_cache_entry *scan_params) if (!IS_WLAN_PHYMODE_HT(phymode)) return phymode; + scan_params->channel.cfreq0 = + util_scan_sec_chan_freq_from_htinfo(htinfo, + scan_params->channel.chan_freq); + if (util_scan_entry_vhtcap(scan_params) && vhtop) { switch (vhtop->vht_op_chwidth) { case WLAN_VHTOP_CHWIDTH_2040: @@ -352,6 +553,18 @@ util_scan_get_phymode_2g(struct scan_cache_entry *scan_params) return phymode; } +static enum wlan_phymode +util_scan_get_phymode(struct wlan_objmgr_pdev *pdev, + struct scan_cache_entry *scan_params) +{ + if (WLAN_REG_IS_24GHZ_CH_FREQ(scan_params->channel.chan_freq)) + return util_scan_get_phymode_2g(scan_params); + else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(scan_params->channel.chan_freq)) + return util_scan_get_phymode_6g(pdev, scan_params); + else + return util_scan_get_phymode_5g(pdev, scan_params); +} + static QDF_STATUS util_scan_parse_chan_switch_wrapper_ie(struct scan_cache_entry *scan_params, struct ie_header *sub_ie, qdf_size_t sub_ie_len) @@ -418,6 +631,115 @@ util_scan_is_hidden_ssid(struct ie_ssid *ssid) return true; } +static QDF_STATUS +util_scan_update_rnr(struct rnr_bss_info *rnr, + struct neighbor_ap_info_field *ap_info, + uint8_t *data) +{ + uint8_t tbtt_info_length; + + tbtt_info_length = ap_info->tbtt_header.tbtt_info_length; + + switch (tbtt_info_length) { + case TBTT_NEIGHBOR_AP_OFFSET_ONLY: + /* Dont store it skip*/ + break; + + case TBTT_NEIGHBOR_AP_BSS_PARAM: + /* Dont store it skip*/ + break; + + case TBTT_NEIGHBOR_AP_SHORTSSID: + rnr->channel_number = ap_info->channel_number; + rnr->operating_class = ap_info->operting_class; + qdf_mem_copy(&rnr->short_ssid, &data[1], SHORT_SSID_LEN); + break; + + case TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM: + rnr->channel_number = ap_info->channel_number; + rnr->operating_class = ap_info->operting_class; + qdf_mem_copy(&rnr->short_ssid, &data[1], SHORT_SSID_LEN); + rnr->bss_params = data[5]; + break; + + case TBTT_NEIGHBOR_AP_BSSID: + rnr->channel_number = ap_info->channel_number; + rnr->operating_class = ap_info->operting_class; + qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE); + break; + + case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM: + rnr->channel_number = ap_info->channel_number; + rnr->operating_class = ap_info->operting_class; + qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE); + rnr->bss_params = data[7]; + break; + + case TBTT_NEIGHBOR_AP_BSSSID_S_SSID: + rnr->channel_number = ap_info->channel_number; + rnr->operating_class = ap_info->operting_class; + qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE); + qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN); + break; + + case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM: + rnr->channel_number = ap_info->channel_number; + rnr->operating_class = ap_info->operting_class; + qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE); + qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN); + rnr->bss_params = data[11]; + break; + + default: + scm_debug("Wrong fieldtype"); + } + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS +util_scan_parse_rnr_ie(struct scan_cache_entry *scan_entry, + struct ie_header *ie) +{ + uint32_t rnr_ie_len; + uint16_t tbtt_count, tbtt_length, i, fieldtype; + uint8_t *data; + struct neighbor_ap_info_field *neighbor_ap_info; + + rnr_ie_len = ie->ie_len; + data = (uint8_t *)ie + sizeof(struct ie_header); + + while ((data + sizeof(struct neighbor_ap_info_field)) <= + ((uint8_t *)ie + rnr_ie_len + 2)) { + neighbor_ap_info = (struct neighbor_ap_info_field *)data; + tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count; + tbtt_length = neighbor_ap_info->tbtt_header.tbtt_info_length; + fieldtype = neighbor_ap_info->tbtt_header.tbbt_info_fieldtype; + scm_debug("channel number %d, op class %d", + neighbor_ap_info->channel_number, + neighbor_ap_info->operting_class); + scm_debug("tbtt_count %d, tbtt_length %d, fieldtype %d", + tbtt_count, tbtt_length, fieldtype); + data += sizeof(struct neighbor_ap_info_field); + + if (tbtt_count > TBTT_INFO_COUNT) + break; + + for (i = 0; i < (tbtt_count + 1) && + (data + tbtt_length) <= + ((uint8_t *)ie + rnr_ie_len + 2); i++) { + if (i < MAX_RNR_BSS) + util_scan_update_rnr( + &scan_entry->rnr.bss_info[i], + neighbor_ap_info, + data); + data += tbtt_length; + } + } + + return QDF_STATUS_SUCCESS; +} + static QDF_STATUS util_scan_parse_extn_ie(struct scan_cache_entry *scan_params, struct ie_header *ie) @@ -434,6 +756,9 @@ util_scan_parse_extn_ie(struct scan_cache_entry *scan_params, scan_params->ie_list.srp = (uint8_t *)ie; break; case WLAN_EXTN_ELEMID_HECAP: + if ((extn_ie->ie_len < WLAN_MIN_HECAP_IE_LEN) || + (extn_ie->ie_len > WLAN_MAX_HECAP_IE_LEN)) + return QDF_STATUS_E_INVAL; scan_params->ie_list.hecap = (uint8_t *)ie; break; case WLAN_EXTN_ELEMID_HEOP: @@ -445,6 +770,9 @@ util_scan_parse_extn_ie(struct scan_cache_entry *scan_params, case WLAN_EXTN_ELEMID_MUEDCA: scan_params->ie_list.muedca = (uint8_t *)ie; break; + case WLAN_EXTN_ELEMID_HE_6G_CAP: + scan_params->ie_list.hecap_6g = (uint8_t *)ie; + break; default: break; } @@ -560,11 +888,28 @@ util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params, } static QDF_STATUS -util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params) +util_scan_populate_bcn_ie_list(struct wlan_objmgr_pdev *pdev, + struct scan_cache_entry *scan_params, + qdf_freq_t *chan_freq, uint8_t band_mask) { struct ie_header *ie, *sub_ie; uint32_t ie_len, sub_ie_len; QDF_STATUS status; + uint8_t chan_idx; + struct wlan_scan_obj *scan_obj; + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + scm_err("psoc is NULL"); + return QDF_STATUS_E_INVAL; + } + + scan_obj = wlan_psoc_get_scan_obj(psoc); + if (!scan_obj) { + scm_err("scan_obj is NULL"); + return QDF_STATUS_E_INVAL; + } ie_len = util_scan_entry_ie_len(scan_params); ie = (struct ie_header *) @@ -579,8 +924,15 @@ util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params) } if (ie_len < ie->ie_len) { - scm_debug("Incomplete corrupted IE:%x", - ie->ie_id); + if (scan_obj->allow_bss_with_incomplete_ie) { + scm_debug(QDF_MAC_ADDR_FMT": Scan allowed with incomplete corrupted IE:%x, ie_len: %d, ie->ie_len: %d, stop processing further", + QDF_MAC_ADDR_REF(scan_params->bssid.bytes), + ie->ie_id, ie_len, ie->ie_len); + break; + } + scm_debug(QDF_MAC_ADDR_FMT": Scan not allowed with incomplete corrupted IE:%x, ie_len: %d, ie->ie_len: %d, stop processing further", + QDF_MAC_ADDR_REF(scan_params->bssid.bytes), + ie->ie_id, ie_len, ie->ie_len); return QDF_STATUS_E_INVAL; } @@ -600,8 +952,18 @@ util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params) if (ie->ie_len != WLAN_DS_PARAM_IE_MAX_LEN) return QDF_STATUS_E_INVAL; scan_params->ie_list.ds_param = (uint8_t *)ie; - scan_params->channel.chan_idx = + chan_idx = ((struct ds_ie *)ie)->cur_chan; + *chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx, + band_mask); + /* Drop if invalid freq */ + if (scan_obj->drop_bcn_on_invalid_freq && + wlan_reg_is_disable_for_freq(pdev, *chan_freq)) { + scm_debug_rl(QDF_MAC_ADDR_FMT": Drop as invalid channel %d freq %d in DS IE", + scan_params->bssid.bytes, + chan_idx, *chan_freq); + return QDF_STATUS_E_INVAL; + } break; case WLAN_ELEMID_TIM: if (ie->ie_len < WLAN_TIM_IE_MIN_LENGTH) @@ -656,9 +1018,16 @@ util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params) (uint8_t *)&(((struct htcap_ie *)ie)->ie); break; case WLAN_ELEMID_RSN: - if (ie->ie_len < WLAN_RSN_IE_MIN_LEN) - goto err; - scan_params->ie_list.rsn = (uint8_t *)ie; + /* + * For security cert TC, RSNIE length can be 1 but if + * beacon is dropped, old entry will remain in scan + * cache and cause cert TC failure as connection with + * old entry with valid RSN IE will pass. + * So instead of dropping the frame, do not store the + * RSN pointer so that old entry is overwritten. + */ + if (ie->ie_len >= WLAN_RSN_IE_MIN_LEN) + scan_params->ie_list.rsn = (uint8_t *)ie; break; case WLAN_ELEMID_XRATES: scan_params->ie_list.xrates = (uint8_t *)ie; @@ -678,9 +1047,18 @@ util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params) goto err; scan_params->ie_list.htinfo = (uint8_t *)&(((struct wlan_ie_htinfo *) ie)->hi_ie); - scan_params->channel.chan_idx = - ((struct wlan_ie_htinfo_cmn *) - (scan_params->ie_list.htinfo))->hi_ctrlchannel; + chan_idx = ((struct wlan_ie_htinfo_cmn *) + (scan_params->ie_list.htinfo))->hi_ctrlchannel; + *chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx, + band_mask); + /* Drop if invalid freq */ + if (scan_obj->drop_bcn_on_invalid_freq && + wlan_reg_is_disable_for_freq(pdev, *chan_freq)) { + scm_debug_rl(QDF_MAC_ADDR_FMT": Drop as invalid channel %d freq %d in HT_INFO IE", + scan_params->bssid.bytes, + chan_idx, *chan_freq); + return QDF_STATUS_E_INVAL; + } break; case WLAN_ELEMID_WAPI: if (ie->ie_len < WLAN_WAPI_IE_MIN_LEN) @@ -738,11 +1116,24 @@ util_scan_populate_bcn_ie_list(struct scan_cache_entry *scan_params) goto err; scan_params->ie_list.fils_indication = (uint8_t *)ie; break; + case WLAN_ELEMID_RSNXE: + if (!ie->ie_len) + goto err; + scan_params->ie_list.rsnxe = (uint8_t *)ie; + break; case WLAN_ELEMID_EXTN_ELEM: status = util_scan_parse_extn_ie(scan_params, ie); if (QDF_IS_STATUS_ERROR(status)) goto err_status; break; + case WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT: + if (ie->ie_len < WLAN_RNR_IE_MIN_LEN) + goto err; + scan_params->ie_list.rnrie = (uint8_t *)ie; + status = util_scan_parse_rnr_ie(scan_params, ie); + if (QDF_IS_STATUS_ERROR(status)) + goto err_status; + break; default: break; } @@ -1131,6 +1522,8 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, struct qbss_load_ie *qbss_load; struct scan_cache_node *scan_node; uint8_t i; + qdf_freq_t chan_freq = 0; + uint8_t band_mask; scan_entry = qdf_mem_malloc_atomic(sizeof(*scan_entry)); if (!scan_entry) { @@ -1161,13 +1554,17 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, scan_entry->seq_num = (le16toh(*(uint16_t *)hdr->i_seq) >> WLAN_SEQ_SEQ_SHIFT); + scan_entry->snr = rx_param->snr; + scan_entry->avg_snr = WLAN_SNR_IN(scan_entry->snr); scan_entry->rssi_raw = rx_param->rssi; scan_entry->avg_rssi = WLAN_RSSI_IN(scan_entry->rssi_raw); scan_entry->tsf_delta = rx_param->tsf_delta; + scan_entry->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); /* Copy per chain rssi to scan entry */ qdf_mem_copy(scan_entry->per_chain_rssi, rx_param->rssi_ctl, WLAN_MGMT_TXRX_HOST_MAX_ANTENNA); + band_mask = BIT(wlan_reg_freq_to_band(rx_param->chan_freq)); if (!wlan_psoc_nif_fw_ext_cap_get(wlan_pdev_get_psoc(pdev), WLAN_SOC_CEXT_HW_DB2DBM)) { @@ -1204,9 +1601,11 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, scan_entry->raw_frame.len = frame_len; qdf_mem_copy(scan_entry->raw_frame.ptr, frame, frame_len); - status = util_scan_populate_bcn_ie_list(scan_entry); + status = util_scan_populate_bcn_ie_list(pdev, scan_entry, &chan_freq, + band_mask); if (QDF_IS_STATUS_ERROR(status)) { - scm_debug("failed to parse beacon IE"); + scm_debug(QDF_MAC_ADDR_FMT": failed to parse beacon IE", + scan_entry->bssid.bytes); qdf_mem_free(scan_entry->raw_frame.ptr); qdf_mem_free(scan_entry); return QDF_STATUS_E_FAILURE; @@ -1224,13 +1623,26 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, if (scan_entry->ie_list.p2p) scan_entry->is_p2p = true; + if (!chan_freq && util_scan_entry_hecap(scan_entry)) { + status = util_scan_get_chan_from_he_6g_params(pdev, scan_entry, + &chan_freq, + band_mask); + if (QDF_IS_STATUS_ERROR(status)) { + qdf_mem_free(scan_entry->raw_frame.ptr); + qdf_mem_free(scan_entry); + return QDF_STATUS_E_FAILURE; + } + } + + if (chan_freq) + scan_entry->channel.chan_freq = chan_freq; + /* If no channel info is present in beacon use meta channel */ - if (!scan_entry->channel.chan_idx) { - scan_entry->channel.chan_idx = - rx_param->channel; - } else if (rx_param->channel != - scan_entry->channel.chan_idx) { - if (!wlan_reg_chan_is_49ghz(pdev, scan_entry->channel.chan_idx)) + if (!scan_entry->channel.chan_freq) { + scan_entry->channel.chan_freq = rx_param->chan_freq; + } else if (rx_param->chan_freq != + scan_entry->channel.chan_freq) { + if (!wlan_reg_is_49ghz_freq(scan_entry->channel.chan_freq)) scan_entry->channel_mismatch = true; } @@ -1246,10 +1658,8 @@ util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev, } qdf_mem_copy(&scan_entry->mbssid_info, mbssid_info, sizeof(scan_entry->mbssid_info)); - if (WLAN_CHAN_IS_5GHZ(scan_entry->channel.chan_idx)) - scan_entry->phy_mode = util_scan_get_phymode_5g(scan_entry); - else - scan_entry->phy_mode = util_scan_get_phymode_2g(scan_entry); + + scan_entry->phy_mode = util_scan_get_phymode(pdev, scan_entry); scan_entry->nss = util_scan_scm_calc_nss_supported_by_ap(scan_entry); scm_fill_adaptive_11r_cap(scan_entry); @@ -1321,6 +1731,7 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, uint8_t *pos, *tmp; const uint8_t *tmp_old, *tmp_new; uint8_t *sub_copy; + size_t tmp_rem_len; /* copy subelement as we need to change its content to * mark an ie after it is processed. @@ -1335,8 +1746,10 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, /* new ssid */ tmp_new = util_scan_find_ie(WLAN_ELEMID_SSID, sub_copy, subie_len); if (tmp_new) { - qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); - pos += (tmp_new[1] + 2); + if ((pos + tmp_new[1] + 2) <= (new_ie + ielen)) { + qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); + pos += (tmp_new[1] + 2); + } } /* go through IEs in ie (skip SSID) and subelement, @@ -1356,8 +1769,12 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, if (!tmp) { /* ie in old ie but not in subelement */ if (tmp_old[0] != WLAN_ELEMID_MULTIPLE_BSSID) { - qdf_mem_copy(pos, tmp_old, tmp_old[1] + 2); - pos += tmp_old[1] + 2; + if ((pos + tmp_old[1] + 2) <= + (new_ie + ielen)) { + qdf_mem_copy(pos, tmp_old, + tmp_old[1] + 2); + pos += tmp_old[1] + 2; + } } } else { /* ie in transmitting ie also in subelement, @@ -1366,24 +1783,35 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, * vendor ie, compare OUI + type + subType to * determine if they are the same ie. */ - if (tmp_old[0] == WLAN_ELEMID_VENDOR) { + tmp_rem_len = subie_len - (tmp - sub_copy); + if (tmp_old[0] == WLAN_ELEMID_VENDOR && + tmp_rem_len >= 7) { if (!qdf_mem_cmp(tmp_old + 2, tmp + 2, 5)) { /* same vendor ie, copy from * subelement */ - qdf_mem_copy(pos, tmp, tmp[1] + 2); - pos += tmp[1] + 2; - tmp[0] = 0xff; + if ((pos + tmp[1] + 2) <= + (new_ie + ielen)) { + qdf_mem_copy(pos, tmp, + tmp[1] + 2); + pos += tmp[1] + 2; + tmp[0] = 0xff; + } } else { - qdf_mem_copy(pos, tmp_old, - tmp_old[1] + 2); - pos += tmp_old[1] + 2; + if ((pos + tmp_old[1] + 2) <= + (new_ie + ielen)) { + qdf_mem_copy(pos, tmp_old, + tmp_old[1] + 2); + pos += tmp_old[1] + 2; + } } } else { /* copy ie from subelement into new ie */ - qdf_mem_copy(pos, tmp, tmp[1] + 2); - pos += tmp[1] + 2; - tmp[0] = 0xff; + if ((pos + tmp[1] + 2) <= (new_ie + ielen)) { + qdf_mem_copy(pos, tmp, tmp[1] + 2); + pos += tmp[1] + 2; + tmp[0] = 0xff; + } } } @@ -1402,8 +1830,10 @@ static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen, tmp_new[0] == WLAN_ELEMID_SSID || tmp_new[0] == WLAN_ELEMID_MULTI_BSSID_IDX || tmp_new[0] == 0xff)) { - qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); - pos += tmp_new[1] + 2; + if ((pos + tmp_new[1] + 2) <= (new_ie + ielen)) { + qdf_mem_copy(pos, tmp_new, tmp_new[1] + 2); + pos += tmp_new[1] + 2; + } } if (tmp_new + tmp_new[1] + 2 - sub_copy == subie_len) break; @@ -1445,7 +1875,7 @@ static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev, pos = ie; - new_ie = qdf_mem_malloc(MAX_IE_LEN); + new_ie = qdf_mem_malloc(ielen); if (!new_ie) return QDF_STATUS_E_NOMEM; @@ -1563,9 +1993,9 @@ util_scan_parse_beacon_frame(struct wlan_objmgr_pdev *pdev, { struct wlan_bcn_frame *bcn; struct wlan_frame_hdr *hdr; - uint8_t *mbssid_ie = NULL; + uint8_t *mbssid_ie = NULL, *extcap_ie; uint32_t ie_len = 0; - QDF_STATUS status; + QDF_STATUS status = QDF_STATUS_E_FAILURE; struct scan_mbssid_info mbssid_info = { 0 }; hdr = (struct wlan_frame_hdr *)frame; @@ -1575,12 +2005,24 @@ util_scan_parse_beacon_frame(struct wlan_objmgr_pdev *pdev, sizeof(struct wlan_frame_hdr) - offsetof(struct wlan_bcn_frame, ie)); - mbssid_ie = util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, + extcap_ie = util_scan_find_ie(WLAN_ELEMID_XCAPS, (uint8_t *)&bcn->ie, ie_len); - if (mbssid_ie) { - qdf_mem_copy(&mbssid_info.trans_bssid, - hdr->i_addr3, QDF_MAC_ADDR_SIZE); - mbssid_info.profile_count = 1 << mbssid_ie[2]; + /* Process MBSSID when Multiple BSSID (Bit 22) is set in Ext Caps */ + if (extcap_ie && + extcap_ie[1] >= 3 && extcap_ie[1] <= WLAN_EXTCAP_IE_MAX_LEN && + (extcap_ie[4] & 0x40)) { + mbssid_ie = util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, + (uint8_t *)&bcn->ie, ie_len); + if (mbssid_ie) { + if (mbssid_ie[1] < 4) { + scm_debug("MBSSID IE length is wrong %d", + mbssid_ie[1]); + return status; + } + qdf_mem_copy(&mbssid_info.trans_bssid, + hdr->i_addr3, QDF_MAC_ADDR_SIZE); + mbssid_info.profile_count = 1 << mbssid_ie[2]; + } } status = util_scan_gen_scan_entry(pdev, frame, frame_len, diff --git a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/inc/wifi_pos_api.h b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/inc/wifi_pos_api.h index 022f0c8d32681887d2c2550f81027a3ce120f1d7..7b835438b9c0551ff6786efc69c1ed13a87c497b 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/inc/wifi_pos_api.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/inc/wifi_pos_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 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 @@ -24,9 +24,8 @@ #define _WIFI_POS_API_H_ /* Include files */ -#include "qdf_types.h" -#include "qdf_status.h" -#include "qdf_trace.h" +#include "wifi_pos_utils_pub.h" +#include "../src/wifi_pos_utils_i.h" /* forward reference */ struct wlan_objmgr_psoc; @@ -113,7 +112,7 @@ struct qdf_packed wifi_pos_ch_info_rsp { }; /** - * struct wmi_pos_peer_status_info - Status information for a given peer + * struct wifi_pos_peer_status_info - Status information for a given peer * @peer_mac_addr: peer mac address * @peer_status: peer status: 1: CONNECTED, 2: DISCONNECTED * @vdev_id: vdev_id for the peer mac @@ -121,7 +120,7 @@ struct qdf_packed wifi_pos_ch_info_rsp { * @reserved0: reserved0 * @peer_chan_info: channel info on which peer is connected */ -struct qdf_packed wmi_pos_peer_status_info { +struct qdf_packed wifi_pos_peer_status_info { uint8_t peer_mac_addr[ETH_ALEN]; uint8_t peer_status; uint8_t vdev_id; @@ -138,15 +137,17 @@ struct qdf_packed wmi_pos_peer_status_info { * @buf_len: request buffer length * @field_info_buf: buffer containing field info * @field_info_buf_len: length of field info buffer + * @rsp_version: nl type or ani type * */ struct wifi_pos_req_msg { - uint32_t msg_type; + enum wifi_pos_cmd_ids msg_type; uint32_t pid; uint8_t *buf; uint32_t buf_len; struct wifi_pos_field_info *field_info_buf; uint32_t field_info_buf_len; + uint32_t rsp_version; }; /** @@ -159,8 +160,8 @@ struct wifi_pos_req_msg { * Return: status of operation */ QDF_STATUS ucfg_wifi_pos_process_req(struct wlan_objmgr_psoc *psoc, - struct wifi_pos_req_msg *req, - void (*send_rsp_cb)(uint32_t, uint32_t, uint32_t, uint8_t *)); + struct wifi_pos_req_msg *req, + wifi_pos_send_rsp_handler send_rsp_cb); /** * wifi_pos_init: initializes WIFI POS component, called by dispatcher init @@ -304,6 +305,15 @@ void wifi_pos_set_current_dwell_time_max(struct wlan_objmgr_psoc *psoc, QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, struct wifi_pos_driver_caps *caps); +struct wlan_lmac_if_rx_ops; +/** + * wifi_pos_register_rx_ops: function to register with lmac rx ops + * @rx_ops: lmac rx ops struct object + * + * Return: None + */ +void wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops); + /** * ucfg_wifi_pos_get_ftm_cap: API to get fine timing measurement caps * @psoc: psoc object @@ -321,6 +331,24 @@ uint32_t ucfg_wifi_pos_get_ftm_cap(struct wlan_objmgr_psoc *psoc); */ void ucfg_wifi_pos_set_ftm_cap(struct wlan_objmgr_psoc *psoc, uint32_t val); +/** + * ucfg_wifi_pos_set_oem_6g_supported: API to set oem target 6g enabled/disabled + * @psoc: psoc object + * @val: value to set + * + * Return: None + */ +void ucfg_wifi_pos_set_oem_6g_supported(struct wlan_objmgr_psoc *psoc, + bool val); + +/** + * ucfg_wifi_pos_is_nl_rsp: API to check if response is nl or ani type + * @psoc: psoc object + * + * Return: true if response is nl type + */ +bool ucfg_wifi_pos_is_nl_rsp(struct wlan_objmgr_psoc *psoc); + /** * wifi_pos_get_app_pid: returns oem app pid. * @psoc: pointer to psoc object @@ -390,6 +418,19 @@ static inline QDF_STATUS wifi_pos_init_cir_cfr_rings( } #endif +/** + * wifi_pos_register_get_fw_phy_mode_for_freq_cb: API to register callback + * to get current PHY mode + * @psoc: pointer to psoc object + * @handler: callback to be registered + * + * Return: QDF_STATUS_SUCCESS in case of success, error codes in + * case of failure + */ +QDF_STATUS wifi_pos_register_get_fw_phy_mode_for_freq_cb( + struct wlan_objmgr_psoc *psoc, + void (*handler)(uint32_t, uint32_t, uint32_t *)); + /** * wifi_pos_register_get_phy_mode_cb: API to register callback to get * current PHY mode @@ -403,4 +444,33 @@ QDF_STATUS wifi_pos_register_get_phy_mode_cb( struct wlan_objmgr_psoc *psoc, void (*handler)(uint8_t, uint32_t, uint32_t *)); +/** + * wifi_pos_register_send_action: API to register callback to send + * action frames + * @psoc: pointer to psoc object + * @handler: callback to be registered + * + * Return: QDF_STATUS_SUCCESS in case of success, error codes in + * case of failure + */ +QDF_STATUS wifi_pos_register_send_action( + struct wlan_objmgr_psoc *psoc, + void (*handler)(struct wlan_objmgr_psoc *psoc, + uint32_t sub_type, + uint8_t *buf, + uint32_t buf_len)); + +/** + * wifi_pos_send_report_resp: Send report to osif + * @psoc: pointer to psoc object + * @req_id: Request id + * @dest_mac: destination mac address + * @err_code: Error code to be sent + * + * Return: QDF_STATUS_SUCCESS in case of success, error codes in + * case of failure + */ +QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc, + int req_id, uint8_t *dest_mac, + int err_code); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/inc/wifi_pos_utils_pub.h b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/inc/wifi_pos_utils_pub.h new file mode 100644 index 0000000000000000000000000000000000000000..9b1c66b1d7558e5358b9b9e4cbc6591fc5612917 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/inc/wifi_pos_utils_pub.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wifi_pos_utils_pub.h + * This file declares public utils of wifi positioning component + */ +#ifndef _WIFI_POS_UTILS_PUB_H_ +#define _WIFI_POS_UTILS_PUB_H_ + +/* Include files */ +#include "qdf_types.h" +#include "qdf_status.h" +#include "qdf_trace.h" + +#define WIFIPOS_RESERVE_BYTES 100 +#define OEM_TARGET_SIGNATURE_LEN 8 +#define OEM_TARGET_SIGNATURE "QUALCOMM" + +#define MAX_CHANNELS 255 +#define OEM_CAP_MAX_NUM_CHANNELS 128 + +#define WIFI_POS_RSP_V1_FLAT_MEMORY 0x00000001 +#define WIFI_POS_RSP_V2_NL 0x00000002 + +/** + * enum wifi_pos_cmd_ids + * @WIFI_POS_CMD_REGISTRATION: app registration + * @WIFI_POS_CMD_GET_CAPS: get driver capabilities + * @WIFI_POS_CMD_GET_CH_INFO: get channel info + * @WIFI_POS_CMD_OEM_DATA: oem data req/rsp + * @WIFI_POS_CMD_MAX: Max cld80211 vendor sub cmds + */ + +enum wifi_pos_cmd_ids { + WIFI_POS_CMD_INVALID = 0, + WIFI_POS_CMD_REGISTRATION = 1, + WIFI_POS_CMD_SET_CAPS = 2, + WIFI_POS_CMD_GET_CAPS = 3, + WIFI_POS_CMD_GET_CH_INFO = 4, + WIFI_POS_CMD_OEM_DATA = 5, + WIFI_POS_CMD_ERROR = 6, + WIFI_POS_PEER_STATUS_IND = 7, + /* keep last */ + WIFI_POS_CMD__AFTER_LAST, + WIFI_POS_CMD_MAX = + WIFI_POS_CMD__AFTER_LAST - 1 +}; + + +/** + * struct wifi_pos_driver_version - Driver version identifier (w.x.y.z) + * @major: Version ID major number + * @minor: Version ID minor number + * @patch: Version ID patch number + * @build: Version ID build number + */ +struct qdf_packed wifi_pos_driver_version { + uint8_t major; + uint8_t minor; + uint8_t patch; + uint8_t build; +}; + +/** + * struct wifi_pos_channel_power + * @center_freq: Channel Center Frequency + * @chan_num: channel number + * @tx_power: TX power + */ +struct wifi_pos_channel_power { + uint32_t center_freq; + uint32_t chan_num; + uint32_t tx_power; +}; + +/** + * struct wifi_pos_channel_list + * @valid_channels: no of valid channels + * @chan_info: channel info + */ +struct qdf_packed wifi_pos_channel_list { + uint16_t num_channels; + struct wifi_pos_channel_power chan_info[MAX_CHANNELS]; +}; + +/** + * struct wifi_pos_driver_caps - OEM Data Capabilities + * @oem_target_signature: Signature of chipset vendor + * @oem_target_type: Chip type + * @oem_fw_version: Firmware version + * @driver_version: Host software version + * @allowed_dwell_time_min: Channel dwell time - allowed minimum + * @allowed_dwell_time_max: Channel dwell time - allowed maximum + * @curr_dwell_time_min: Channel dwell time - current minimim + * @curr_dwell_time_max: Channel dwell time - current maximum + * @supported_bands: Supported bands, 2.4G or 5G Hz + * @num_channels: Num of channels IDs to follow + * @channel_list: List of channel IDs + */ +struct qdf_packed wifi_pos_driver_caps { + uint8_t oem_target_signature[OEM_TARGET_SIGNATURE_LEN]; + uint32_t oem_target_type; + uint32_t oem_fw_version; + struct wifi_pos_driver_version driver_version; + uint16_t allowed_dwell_time_min; + uint16_t allowed_dwell_time_max; + uint16_t curr_dwell_time_min; + uint16_t curr_dwell_time_max; + uint16_t supported_bands; + uint16_t num_channels; + uint8_t channel_list[OEM_CAP_MAX_NUM_CHANNELS]; +}; + +/** + * struct wifi_pos_user_defined_caps - OEM capability to be exchanged between + * host and userspace + * @ftm_rr: FTM range report capability bit + * @lci_capability: LCI capability bit + * @reserved1: reserved + * @reserved2: reserved + */ +struct wifi_pos_user_defined_caps { + uint32_t ftm_rr:1; + uint32_t lci_capability:1; + uint32_t reserved1:30; + uint32_t reserved2; +}; + +/** + * struct wifi_pos_oem_get_cap_rsp - capabilities set by userspace and target. + * @driver_cap: target capabilities + * @user_defined_cap: capabilities set by userspace via set request + */ +struct qdf_packed wifi_pos_oem_get_cap_rsp { + struct wifi_pos_driver_caps driver_cap; + struct wifi_pos_user_defined_caps user_defined_cap; +}; +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_api.c b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_api.c index b465b2a1fccd6a5fe3c16ed1379ba0d7058f1aef..60e714cfa6a4927236d759ddc6333889d6d29e41 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_api.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -91,7 +91,16 @@ QDF_STATUS wifi_pos_deinit(void) QDF_STATUS wifi_pos_psoc_enable(struct wlan_objmgr_psoc *psoc) { - QDF_STATUS status = target_if_wifi_pos_register_events(psoc); + QDF_STATUS status; + struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops; + + tx_ops = wifi_pos_get_tx_ops(psoc); + if (!tx_ops) { + wifi_pos_err("tx_ops is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + status = tx_ops->wifi_pos_register_events(psoc); if (QDF_IS_STATUS_ERROR(status)) wifi_pos_err("target_if_wifi_pos_register_events failed"); @@ -101,7 +110,16 @@ QDF_STATUS wifi_pos_psoc_enable(struct wlan_objmgr_psoc *psoc) QDF_STATUS wifi_pos_psoc_disable(struct wlan_objmgr_psoc *psoc) { - QDF_STATUS status = target_if_wifi_pos_deregister_events(psoc); + QDF_STATUS status; + struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops; + + tx_ops = wifi_pos_get_tx_ops(psoc); + if (!tx_ops) { + wifi_pos_err("tx_ops is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + status = tx_ops->wifi_pos_deregister_events(psoc); if (QDF_IS_STATUS_ERROR(status)) wifi_pos_err("target_if_wifi_pos_deregister_events failed"); @@ -332,3 +350,57 @@ QDF_STATUS wifi_pos_register_get_phy_mode_cb( return QDF_STATUS_SUCCESS; } +QDF_STATUS wifi_pos_register_get_fw_phy_mode_for_freq_cb( + struct wlan_objmgr_psoc *psoc, + void (*handler)(uint32_t, uint32_t, uint32_t *)) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc; + + if (!psoc) { + wifi_pos_err("psoc is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!handler) { + wifi_pos_err("Null callback"); + return QDF_STATUS_E_NULL_VALUE; + } + wifi_pos_psoc = wifi_pos_get_psoc_priv_obj(psoc); + if (!wifi_pos_psoc) { + wifi_pos_err("wifi_pos priv obj is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + wifi_pos_psoc->wifi_pos_get_fw_phy_mode_for_freq = handler; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wifi_pos_register_send_action( + struct wlan_objmgr_psoc *psoc, + void (*handler)(struct wlan_objmgr_psoc *psoc, + uint32_t sub_type, + uint8_t *buf, + uint32_t buf_len)) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc; + + if (!psoc) { + wifi_pos_err("psoc is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!handler) { + wifi_pos_err("Null callback"); + return QDF_STATUS_E_NULL_VALUE; + } + wifi_pos_psoc = wifi_pos_get_psoc_priv_obj(psoc); + if (!wifi_pos_psoc) { + wifi_pos_err("wifi_pos priv obj is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + wifi_pos_psoc->wifi_pos_send_action = handler; + + return QDF_STATUS_SUCCESS; +} diff --git a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main.c b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main.c index f371bdc1f3ce72aa8fe48d571731f9001b461c86..871b38cdd04e43cb470be71cf503e23e16097975 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 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 @@ -77,16 +77,88 @@ static bool wifi_pos_get_tlv_support(struct wlan_objmgr_psoc *psoc) return true; } +struct wlan_lmac_if_wifi_pos_tx_ops * + wifi_pos_get_tx_ops(struct wlan_objmgr_psoc *psoc) +{ + if (!psoc) { + wifi_pos_err("psoc is null"); + return NULL; + } + + return &psoc->soc_cb.tx_ops.wifi_pos_tx_ops; +} + +#ifdef CNSS_GENL +static uint8_t * +wifi_pos_prepare_reg_resp(uint32_t *rsp_len, + struct app_reg_rsp_vdev_info *vdevs_info) +{ + uint32_t *nl_sign; + uint8_t *resp_buf; + struct wifi_app_reg_rsp *app_reg_rsp; + + /* + * allocate ENHNC_FLAGS_LEN i.e. 4bytes extra memory in app_reg_resp + * to indicate NLA type response is supported for OEM request + * commands. + */ + *rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx) + + sizeof(uint8_t) + ENHNC_FLAGS_LEN; + resp_buf = qdf_mem_malloc(*rsp_len); + if (!resp_buf) + return NULL; + + app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf; + app_reg_rsp->num_inf = vdev_idx; + qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info, + sizeof(struct app_reg_rsp_vdev_info) * vdev_idx); + + nl_sign = (uint32_t *)&app_reg_rsp->vdevs[vdev_idx]; + *nl_sign |= NL_ENABLE_OEM_REQ_RSP; + + return resp_buf; +} +#else +static uint8_t * +wifi_pos_prepare_reg_resp(uint32_t *rsp_len, + struct app_reg_rsp_vdev_info *vdevs_info) +{ + uint8_t *resp_buf; + struct wifi_app_reg_rsp *app_reg_rsp; + + *rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx) + + sizeof(uint8_t); + resp_buf = qdf_mem_malloc(*rsp_len); + if (!resp_buf) + return NULL; + + app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf; + app_reg_rsp->num_inf = vdev_idx; + qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info, + sizeof(struct app_reg_rsp_vdev_info) * vdev_idx); + + return resp_buf; +} +#endif + static QDF_STATUS wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc, struct wifi_pos_req_msg *req) { uint8_t idx; uint32_t sub_type = 0; uint32_t channel_mhz = 0; - void *pdev_id = NULL; + uint32_t pdev_id = 0; uint32_t offset; struct oem_data_req data_req; struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops; + struct wlan_objmgr_pdev *pdev; + struct wifi_pos_psoc_priv_obj *wifi_pos_obj = + wifi_pos_get_psoc_priv_obj(psoc); + + if (!wifi_pos_obj) { + wifi_pos_err("wifi_pos priv obj is null"); + return QDF_STATUS_E_INVAL; + } wifi_pos_debug("Received data req pid(%d), len(%d)", req->pid, req->buf_len); @@ -113,7 +185,14 @@ static QDF_STATUS wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc, if (req->field_info_buf->fields[idx].id == WMIRTT_FIELD_ID_pdev) { - pdev_id = &req->buf[offset]; + pdev_id = *((uint32_t *)&req->buf[offset]); + /* pdev_id in FW starts from 1. So convert it to + * host id by decrementing it. + * zero has special meaning due to backward + * compatibility. Dont change it. + */ + if (pdev_id) + pdev_id -= 1; continue; } } @@ -132,25 +211,39 @@ static QDF_STATUS wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc, /* TBD */ break; case TARGET_OEM_CONFIGURE_FTMRR: - /* TBD */ + wifi_pos_debug("FTMRR request"); + if (wifi_pos_obj->wifi_pos_send_action) + wifi_pos_obj->wifi_pos_send_action(psoc, sub_type, + req->buf, + req->buf_len); break; case TARGET_OEM_CONFIGURE_WRU: - /* TBD */ + wifi_pos_debug("WRU request"); + if (wifi_pos_obj->wifi_pos_send_action) + wifi_pos_obj->wifi_pos_send_action(psoc, sub_type, + req->buf, + req->buf_len); break; default: wifi_pos_debug("invalid sub type or not passed"); - /* - * this is legacy MCL operation. pass whole msg to firmware as - * it is. - */ - tx_ops = target_if_wifi_pos_get_txops(psoc); + + tx_ops = wifi_pos_get_tx_ops(psoc); if (!tx_ops) { wifi_pos_err("tx ops null"); return QDF_STATUS_E_INVAL; } + + pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, + WLAN_WIFI_POS_CORE_ID); + if (!pdev) { + wifi_pos_err("pdev null"); + return QDF_STATUS_E_INVAL; + } data_req.data_len = req->buf_len; data_req.data = req->buf; - tx_ops->data_req_tx(psoc, &data_req); + tx_ops->data_req_tx(pdev, &data_req); + wlan_objmgr_pdev_release_ref(pdev, + WLAN_WIFI_POS_CORE_ID); break; } @@ -178,7 +271,7 @@ static QDF_STATUS wifi_pos_process_set_cap_req(struct wlan_objmgr_psoc *psoc, wifi_pos_obj->lci_capability = caps->lci_capability; error_code = qdf_status_to_os_return(QDF_STATUS_SUCCESS); wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid, - ANI_MSG_SET_OEM_CAP_RSP, + WIFI_POS_CMD_SET_CAPS, sizeof(error_code), (uint8_t *)&error_code); @@ -198,22 +291,77 @@ static QDF_STATUS wifi_pos_process_get_cap_req(struct wlan_objmgr_psoc *psoc, } wifi_pos_debug("Received get cap req pid(%d), len(%d)", - req->pid, req->buf_len); + req->pid, req->buf_len); wifi_pos_populate_caps(psoc, &cap_rsp.driver_cap); cap_rsp.user_defined_cap.ftm_rr = wifi_pos_obj->ftm_rr; cap_rsp.user_defined_cap.lci_capability = wifi_pos_obj->lci_capability; + wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid, - ANI_MSG_GET_OEM_CAP_RSP, + WIFI_POS_CMD_GET_CAPS, sizeof(cap_rsp), (uint8_t *)&cap_rsp); return QDF_STATUS_SUCCESS; } +QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc, + int req_id, uint8_t *dest_mac, + int err_code) +{ + struct wifi_pos_err_msg_report err_report = {0}; + struct wifi_pos_psoc_priv_obj *wifi_pos_obj = + wifi_pos_get_psoc_priv_obj(psoc); + + if (!wifi_pos_obj) { + wifi_pos_err("wifi_pos priv obj is null"); + return QDF_STATUS_E_INVAL; + } + + err_report.msg_tag_len = OEM_MSG_RSP_HEAD_TAG_ID << 16; + err_report.msg_tag_len |= (sizeof(err_report) - + sizeof(err_report.err_rpt)) & 0x0000FFFF; + err_report.msg_subtype = TARGET_OEM_ERROR_REPORT_RSP; + err_report.req_id = req_id & 0xFFFF; + err_report.req_id |= ((err_code & 0xFF) << 16); + err_report.req_id |= (0x1 << 24); + err_report.time_left = 0xFFFFFFFF; + err_report.err_rpt.tag_len = OEM_MEAS_RSP_HEAD_TAG_ID << 16; + err_report.err_rpt.tag_len |= + (sizeof(struct wifi_pos_err_rpt)) & 0x0000FFFF; + memcpy(&err_report.err_rpt.dest_mac, dest_mac, QDF_MAC_ADDR_SIZE); + + wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid, + WIFI_POS_CMD_OEM_DATA, + sizeof(err_report), + (uint8_t *)&err_report); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS wifi_pos_get_vht_ch_width(struct wlan_objmgr_psoc *psoc, + enum phy_ch_width *ch_width) +{ + struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops; + + tx_ops = wifi_pos_get_tx_ops(psoc); + if (!tx_ops) { + qdf_print("tx ops null"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!tx_ops->wifi_pos_get_vht_ch_width) { + wifi_pos_err("wifi pos get vht ch width is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + return tx_ops->wifi_pos_get_vht_ch_width( + psoc, ch_width); +} + static void wifi_update_channel_bw_info(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev, - uint16_t chan, + uint16_t freq, struct wifi_pos_ch_info_rsp *chan_info) { struct ch_params ch_params = {0}; @@ -221,33 +369,35 @@ static void wifi_update_channel_bw_info(struct wlan_objmgr_psoc *psoc, struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = wifi_pos_get_psoc_priv_obj(psoc); uint32_t phy_mode; + QDF_STATUS status; if (!wifi_pos_psoc) { wifi_pos_err("wifi_pos priv obj is null"); return; } - /* Passing CH_WIDTH_MAX will give the max bandwidth supported */ - ch_params.ch_width = CH_WIDTH_MAX; + status = wifi_pos_get_vht_ch_width(psoc, &ch_params.ch_width); - wlan_reg_set_channel_params(pdev, chan, sec_ch_2g, &ch_params); - if (ch_params.center_freq_seg0) - chan_info->band_center_freq1 = - wlan_reg_legacy_chan_to_freq( - pdev, - ch_params.center_freq_seg0); - - wifi_pos_psoc->wifi_pos_get_phy_mode(chan, ch_params.ch_width, - &phy_mode); + if (QDF_IS_STATUS_ERROR(status)) { + wifi_pos_err("can not get vht ch width"); + return; + } + wlan_reg_set_channel_params_for_freq(pdev, freq, + sec_ch_2g, &ch_params); + chan_info->band_center_freq1 = ch_params.mhz_freq_seg0; + wifi_pos_psoc->wifi_pos_get_fw_phy_mode_for_freq(freq, + ch_params.ch_width, + &phy_mode); REG_SET_CHANNEL_MODE(chan_info, phy_mode); } static void wifi_pos_get_reg_info(struct wlan_objmgr_pdev *pdev, - uint32_t chan_num, uint32_t *reg_info_1, + uint16_t freq, uint32_t *reg_info_1, uint32_t *reg_info_2) { - uint32_t reg_power = wlan_reg_get_channel_reg_power(pdev, chan_num); + uint32_t reg_power = wlan_reg_get_channel_reg_power_for_freq(pdev, + freq); *reg_info_1 = 0; *reg_info_2 = 0; @@ -278,20 +428,55 @@ static uint32_t wifi_pos_get_valid_channels(uint8_t *channels, uint32_t num_ch, return num_valid_channels; } +static void wifi_pos_pdev_iterator(struct wlan_objmgr_psoc *psoc, + void *obj, void *arg) +{ + QDF_STATUS status; + uint8_t num_channels; + struct wlan_objmgr_pdev *pdev = obj; + struct wifi_pos_channel_list *chan_list = arg; + struct channel_power *ch_info = NULL; + + if (!chan_list) { + wifi_pos_err("wifi_pos priv arg is null"); + return; + } + ch_info = (struct channel_power *)chan_list->chan_info; + status = wlan_reg_get_channel_list_with_power(pdev, ch_info, + &num_channels); + + if (QDF_IS_STATUS_ERROR(status)) { + wifi_pos_err("Failed to get valid channel list"); + return; + } + chan_list->num_channels = num_channels; +} + +static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc, + struct wifi_pos_channel_list *chan_list) +{ + wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, + wifi_pos_pdev_iterator, + chan_list, true, WLAN_WIFI_POS_CORE_ID); + wifi_pos_notice("num channels: %d", chan_list->num_channels); +} + static QDF_STATUS wifi_pos_process_ch_info_req(struct wlan_objmgr_psoc *psoc, struct wifi_pos_req_msg *req) { - uint8_t idx; + uint8_t idx, band_mask; uint8_t *buf; - uint32_t len; + uint32_t len, i, freq; uint32_t reg_info_1; uint32_t reg_info_2; + bool oem_6g_support_disable; uint8_t *channels = req->buf; struct wlan_objmgr_pdev *pdev; uint32_t num_ch = req->buf_len; uint8_t valid_channel_list[NUM_CHANNELS]; - uint32_t num_valid_channels; + uint32_t num_valid_channels = 0; struct wifi_pos_ch_info_rsp *ch_info; + struct wifi_pos_channel_list *ch_list; struct wifi_pos_psoc_priv_obj *wifi_pos_obj = wifi_pos_get_psoc_priv_obj(psoc); @@ -313,38 +498,68 @@ static QDF_STATUS wifi_pos_process_ch_info_req(struct wlan_objmgr_psoc *psoc, wifi_pos_err("Invalid number of channels"); return QDF_STATUS_E_INVAL; } - num_valid_channels = wifi_pos_get_valid_channels(channels, num_ch, + + ch_list = qdf_mem_malloc(sizeof(*ch_list)); + if (!ch_list) + return QDF_STATUS_E_NOMEM; + + if (num_ch == 0 && req->rsp_version == WIFI_POS_RSP_V2_NL) { + wifi_pos_get_ch_info(psoc, ch_list); + qdf_spin_lock_bh(&wifi_pos_obj->wifi_pos_lock); + oem_6g_support_disable = wifi_pos_obj->oem_6g_support_disable; + qdf_spin_unlock_bh(&wifi_pos_obj->wifi_pos_lock); + + /* ch_list has the frequencies in order of 2.4g, 5g & 6g */ + for (i = 0; i < ch_list->num_channels; i++) { + freq = ch_list->chan_info[i].center_freq; + if (oem_6g_support_disable && + WLAN_REG_IS_6GHZ_CHAN_FREQ(freq)) + continue; + num_valid_channels++; + } + } else { + /* v1 has ch_list with frequencies in order of 2.4g, 5g only */ + num_valid_channels = wifi_pos_get_valid_channels( + channels, num_ch, valid_channel_list); + band_mask = BIT(REG_BAND_5G) | BIT(REG_BAND_2G); + for (i = 0; i < num_valid_channels; i++) { + ch_list->chan_info[i].chan_num = valid_channel_list[i]; + ch_list->chan_info[i].center_freq = + wlan_reg_chan_band_to_freq( + pdev, + ch_list->chan_info[i].chan_num, + band_mask); + } + } len = sizeof(uint8_t) + sizeof(struct wifi_pos_ch_info_rsp) * num_valid_channels; buf = qdf_mem_malloc(len); if (!buf) { wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID); + qdf_mem_free(ch_list); return QDF_STATUS_E_NOMEM; } - qdf_mem_zero(buf, len); - /* First byte of message body will have num of channels */ buf[0] = num_valid_channels; ch_info = (struct wifi_pos_ch_info_rsp *)&buf[1]; for (idx = 0; idx < num_valid_channels; idx++) { - ch_info[idx].chan_id = valid_channel_list[idx]; - wifi_pos_get_reg_info(pdev, ch_info[idx].chan_id, - ®_info_1, ®_info_2); ch_info[idx].reserved0 = 0; - ch_info[idx].mhz = wlan_reg_get_channel_freq( - pdev, - valid_channel_list[idx]); + ch_info[idx].chan_id = ch_list->chan_info[idx].chan_num; + ch_info[idx].mhz = ch_list->chan_info[idx].center_freq; ch_info[idx].band_center_freq1 = ch_info[idx].mhz; ch_info[idx].band_center_freq2 = 0; ch_info[idx].info = 0; - if (wlan_reg_is_dfs_ch(pdev, valid_channel_list[idx])) + wifi_pos_get_reg_info(pdev, ch_info[idx].mhz, + ®_info_1, ®_info_2); + + if (wlan_reg_is_dfs_for_freq(pdev, ch_info[idx].mhz)) WIFI_POS_SET_DFS(ch_info[idx].info); wifi_update_channel_bw_info(psoc, pdev, - ch_info[idx].chan_id, + ch_info[idx].mhz, &ch_info[idx]); ch_info[idx].reg_info_1 = reg_info_1; @@ -352,9 +567,11 @@ static QDF_STATUS wifi_pos_process_ch_info_req(struct wlan_objmgr_psoc *psoc, } wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid, - ANI_MSG_CHANNEL_INFO_RSP, + WIFI_POS_CMD_GET_CH_INFO, len, buf); + qdf_mem_free(buf); + qdf_mem_free(ch_list); wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID); return QDF_STATUS_SUCCESS; @@ -374,10 +591,9 @@ static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc, struct wifi_pos_req_msg *req) { QDF_STATUS ret = QDF_STATUS_SUCCESS; - uint8_t err = 0; + uint8_t err = 0, *app_reg_rsp; uint32_t rsp_len; char *sign_str = NULL; - struct wifi_app_reg_rsp *app_reg_rsp; struct app_reg_rsp_vdev_info vdevs_info[WLAN_UMAC_PSOC_MAX_VDEVS] = { { 0 } }; struct wifi_pos_psoc_priv_obj *wifi_pos_obj = @@ -412,23 +628,19 @@ static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc, wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, wifi_pos_vdev_iterator, vdevs_info, true, WLAN_WIFI_POS_CORE_ID); - rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx) - + sizeof(uint8_t); - app_reg_rsp = qdf_mem_malloc(rsp_len); + + app_reg_rsp = wifi_pos_prepare_reg_resp(&rsp_len, vdevs_info); if (!app_reg_rsp) { ret = QDF_STATUS_E_NOMEM; err = OEM_ERR_NULL_CONTEXT; goto app_reg_failed; } - app_reg_rsp->num_inf = vdev_idx; - qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info, - sizeof(struct app_reg_rsp_vdev_info) * vdev_idx); if (!vdev_idx) wifi_pos_debug("no active vdev"); vdev_idx = 0; - wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_APP_REG_RSP, + wifi_pos_obj->wifi_pos_send_rsp(req->pid, WIFI_POS_CMD_REGISTRATION, rsp_len, (uint8_t *)app_reg_rsp); qdf_mem_free(app_reg_rsp); @@ -436,7 +648,7 @@ static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc, app_reg_failed: - wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_OEM_ERROR, + wifi_pos_obj->wifi_pos_send_rsp(req->pid, WIFI_POS_CMD_ERROR, sizeof(err), &err); return ret; } @@ -452,15 +664,15 @@ static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc, { wifi_pos_debug("enter: msg_type: %d", req->msg_type); switch (req->msg_type) { - case ANI_MSG_APP_REG_REQ: + case WIFI_POS_CMD_REGISTRATION: return wifi_pos_process_app_reg_req(psoc, req); - case ANI_MSG_OEM_DATA_REQ: + case WIFI_POS_CMD_OEM_DATA: return wifi_pos_process_data_req(psoc, req); - case ANI_MSG_CHANNEL_INFO_REQ: + case WIFI_POS_CMD_GET_CH_INFO: return wifi_pos_process_ch_info_req(psoc, req); - case ANI_MSG_SET_OEM_CAP_REQ: + case WIFI_POS_CMD_SET_CAPS: return wifi_pos_process_set_cap_req(psoc, req); - case ANI_MSG_GET_OEM_CAP_REQ: + case WIFI_POS_CMD_GET_CAPS: return wifi_pos_process_get_cap_req(psoc, req); default: wifi_pos_err("invalid request type"); @@ -582,7 +794,7 @@ int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc, uint32_t app_pid; struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc); - void (*wifi_pos_send_rsp)(uint32_t, uint32_t, uint32_t, uint8_t *); + wifi_pos_send_rsp_handler wifi_pos_send_rsp; if (!priv) { wifi_pos_err("private object is NULL"); @@ -620,51 +832,32 @@ int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc, qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len], oem_rsp->data_2, oem_rsp->rsp_len_2); - wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP, len, data); + wifi_pos_send_rsp(app_pid, WIFI_POS_CMD_OEM_DATA, len, data); qdf_mem_free(data); } else { - wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP, + wifi_pos_send_rsp(app_pid, WIFI_POS_CMD_OEM_DATA, oem_rsp->rsp_len_1, oem_rsp->data_1); } return 0; } -static void wifi_pos_pdev_iterator(struct wlan_objmgr_psoc *psoc, - void *obj, void *arg) +void wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) { - QDF_STATUS status; - uint8_t i, num_channels; - struct wlan_objmgr_pdev *pdev = obj; - struct wifi_pos_driver_caps *caps = arg; - struct channel_power ch_list[NUM_CHANNELS]; + struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops; - status = wlan_reg_get_channel_list_with_power(pdev, ch_list, - &num_channels); - - if (QDF_IS_STATUS_ERROR(status)) { - wifi_pos_err("Failed to get valid channel list"); - return; - } - for (i = 0; i < num_channels; i++) - caps->channel_list[i] = ch_list[i].chan_num; - caps->num_channels = num_channels; -} - -static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc, - struct wifi_pos_driver_caps *caps) -{ - wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, - wifi_pos_pdev_iterator, - caps, true, WLAN_WIFI_POS_CORE_ID); - wifi_pos_err("num channels: %d", caps->num_channels); + wifi_pos_rx_ops = &rx_ops->wifi_pos_rx_ops; + wifi_pos_rx_ops->oem_rsp_event_rx = wifi_pos_oem_rsp_handler; } QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, struct wifi_pos_driver_caps *caps) { + uint16_t i, count = 0; + uint32_t freq; struct wifi_pos_psoc_priv_obj *wifi_pos_obj = wifi_pos_get_psoc_priv_obj(psoc); + struct wifi_pos_channel_list *ch_list = NULL; wifi_pos_debug("Enter"); if (!wifi_pos_obj) { @@ -672,6 +865,10 @@ QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_NULL_VALUE; } + ch_list = qdf_mem_malloc(sizeof(*ch_list)); + if (!ch_list) + return QDF_STATUS_E_NOMEM; + strlcpy(caps->oem_target_signature, OEM_TARGET_SIGNATURE, OEM_TARGET_SIGNATURE_LEN); @@ -686,6 +883,16 @@ QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, caps->curr_dwell_time_min = wifi_pos_obj->current_dwell_time_min; caps->curr_dwell_time_max = wifi_pos_obj->current_dwell_time_max; caps->supported_bands = wlan_objmgr_psoc_get_band_capability(psoc); - wifi_pos_get_ch_info(psoc, caps); + wifi_pos_get_ch_info(psoc, ch_list); + + /* copy valid channels list to caps */ + for (i = 0; i < ch_list->num_channels; i++) { + freq = ch_list->chan_info[i].center_freq; + if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq)) + continue; + caps->channel_list[count++] = ch_list->chan_info[i].chan_num; + } + caps->num_channels = count; + qdf_mem_free(ch_list); return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main_i.h b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main_i.h index 1d423103d5f3dbd22fb20453c40d3a7714d5a427..227c2ceb1d4829c945fb31afc5c431f05b8b4c10 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main_i.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_main_i.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017, 2019-2020 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,6 +25,11 @@ #ifndef _WIFI_POS_MAIN_H_ #define _WIFI_POS_MAIN_H_ +#ifdef CNSS_GENL +#define ENHNC_FLAGS_LEN 4 +#define NL_ENABLE_OEM_REQ_RSP 0x00000001 +#endif + /* forward reference */ struct wlan_objmgr_psoc; @@ -65,4 +70,12 @@ QDF_STATUS wifi_pos_psoc_obj_destroyed_notification( int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc, struct oem_data_rsp *oem_rsp); +/** + * wifi_pos_get_tx_ops: api to get tx ops + * @psoc: pointer to psoc object + * + * Return: tx ops + */ +struct wlan_lmac_if_wifi_pos_tx_ops * + wifi_pos_get_tx_ops(struct wlan_objmgr_psoc *psoc); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_ucfg.c b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_ucfg.c index ba6fa8441de616d727d71e0171106ccef5f8e15e..00f82358380acf4027ab3a41dec122a38807a89e 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_ucfg.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_ucfg.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020 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 @@ -26,8 +26,8 @@ #include "wlan_ptt_sock_svc.h" QDF_STATUS ucfg_wifi_pos_process_req(struct wlan_objmgr_psoc *psoc, - struct wifi_pos_req_msg *req, - void (*send_rsp_cb)(uint32_t, uint32_t, uint32_t, uint8_t *)) + struct wifi_pos_req_msg *req, + wifi_pos_send_rsp_handler send_rsp_cb) { uint8_t err; uint32_t app_pid; @@ -46,21 +46,22 @@ QDF_STATUS ucfg_wifi_pos_process_req(struct wlan_objmgr_psoc *psoc, wifi_pos_psoc_obj->wifi_pos_send_rsp = send_rsp_cb; is_app_registered = wifi_pos_psoc_obj->is_app_registered; app_pid = wifi_pos_psoc_obj->app_pid; + wifi_pos_psoc_obj->rsp_version = req->rsp_version; qdf_spin_unlock_bh(&wifi_pos_psoc_obj->wifi_pos_lock); if (!wifi_pos_psoc_obj->wifi_pos_req_handler) { wifi_pos_err("wifi_pos_psoc_obj->wifi_pos_req_handler is null"); err = OEM_ERR_NULL_CONTEXT; - send_rsp_cb(app_pid, ANI_MSG_OEM_ERROR, sizeof(err), &err); + send_rsp_cb(app_pid, WIFI_POS_CMD_ERROR, sizeof(err), &err); return QDF_STATUS_E_NULL_VALUE; } - if (req->msg_type != ANI_MSG_APP_REG_REQ && + if (req->msg_type != WIFI_POS_CMD_REGISTRATION && (!is_app_registered || app_pid != req->pid)) { wifi_pos_err("requesting app is not registered, app_registered: %d, requesting pid: %d, stored pid: %d", is_app_registered, req->pid, app_pid); err = OEM_ERR_APP_NOT_REGISTERED; - send_rsp_cb(app_pid, ANI_MSG_OEM_ERROR, sizeof(err), &err); + send_rsp_cb(app_pid, WIFI_POS_CMD_ERROR, sizeof(err), &err); return QDF_STATUS_E_INVAL; } @@ -101,3 +102,40 @@ void ucfg_wifi_pos_set_ftm_cap(struct wlan_objmgr_psoc *psoc, uint32_t val) qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); } +void ucfg_wifi_pos_set_oem_6g_supported(struct wlan_objmgr_psoc *psoc, + bool val) +{ + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + if (!wifi_pos_psoc) { + wifi_pos_alert("unable to get wifi_pos psoc obj"); + return; + } + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + wifi_pos_psoc->oem_6g_support_disable = val; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); +} + +bool ucfg_wifi_pos_is_nl_rsp(struct wlan_objmgr_psoc *psoc) +{ + uint32_t val = 0; + struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = + wifi_pos_get_psoc_priv_obj(psoc); + + if (!wifi_pos_psoc) { + wifi_pos_alert("unable to get wifi_pos psoc obj"); + return false; + } + + qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock); + val = wifi_pos_psoc->rsp_version; + qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock); + + if (val == WIFI_POS_RSP_V2_NL) + return true; + else + return false; + +} + diff --git a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_ucfg_i.h b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_ucfg_i.h index a5dd1f4f878f389e04b965ec339e01ff9676507e..730be472f4104de06386f5f2912042099dc6d668 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_ucfg_i.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_ucfg_i.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017, 2020 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,7 +41,7 @@ struct wifi_pos_req_msg; * Return: status of operation */ QDF_STATUS ucfg_wifi_pos_process_req(struct wlan_objmgr_psoc *psoc, - struct wifi_pos_req_msg *req, - void (*send_rsp_cb)(uint32_t, uint32_t, uint32_t, uint8_t *)); + struct wifi_pos_req_msg *req, + wifi_pos_send_rsp_handler send_rsp_cb); #endif /* _WIFI_POS_UCFG_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_utils.c b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_utils.c index ce7a9adac411e4015067abcf30a371894ab5767f..d4144d01048e1eeb43fbd61f9882ae1ed6be762d 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_utils.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 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 @@ -59,6 +59,8 @@ struct wlan_objmgr_psoc *wifi_pos_get_psoc(void) return tmp; } +qdf_export_symbol(wifi_pos_get_psoc); + void wifi_pos_set_psoc(struct wlan_objmgr_psoc *psoc) { struct wlan_objmgr_psoc *tmp; @@ -103,3 +105,5 @@ struct wifi_pos_psoc_priv_obj *wifi_pos_get_psoc_priv_obj( return obj; } + +qdf_export_symbol(wifi_pos_get_psoc_priv_obj); diff --git a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_utils_i.h b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_utils_i.h index 0b1c5cdc0c4238bb3d10eb85b2f21f81f8e80957..465de82a8ef766aaa8de07e352b8f66f03e34df0 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_utils_i.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_utils_i.h @@ -30,6 +30,8 @@ #include "qdf_status.h" #include "ol_defines.h" #include "qdf_trace.h" +#include "qdf_module.h" +#include "wifi_pos_utils_pub.h" struct wlan_objmgr_psoc; struct wifi_pos_req_msg; @@ -59,11 +61,6 @@ struct wifi_pos_req_msg; #define OEM_APP_SIGNATURE_LEN 16 #define OEM_APP_SIGNATURE_STR "QUALCOMM-OEM-APP" -#define OEM_TARGET_SIGNATURE_LEN 8 -#define OEM_TARGET_SIGNATURE "QUALCOMM" - -#define OEM_CAP_MAX_NUM_CHANNELS 128 - #ifndef OEM_DATA_RSP_SIZE #define OEM_DATA_RSP_SIZE 1724 /* Header + VHT80 CIR * 2 chains */ @@ -123,70 +120,39 @@ struct oem_data_rsp { }; /** - * struct wifi_pos_driver_version - Driver version identifier (w.x.y.z) - * @major: Version ID major number - * @minor: Version ID minor number - * @patch: Version ID patch number - * @build: Version ID build number + * struct wifi_pos_err_rpt - Error report response for userspace. + * @tag_len: tlv header of the message. + * @info: Report info. Reserved for error report. + * @dest_mac: Mac address of the sta in the request. + * @reserved: Reserved in error report. */ -struct qdf_packed wifi_pos_driver_version { - uint8_t major; - uint8_t minor; - uint8_t patch; - uint8_t build; +struct qdf_packed wifi_pos_err_rpt { + uint32_t tag_len; + uint32_t info; + uint8_t dest_mac[QDF_MAC_ADDR_SIZE + 2]; + uint32_t reserved; }; +#define OEM_MSG_RSP_HEAD_TAG_ID 33 +#define OEM_MEAS_RSP_HEAD_TAG_ID 41 /** - * struct wifi_pos_driver_caps - OEM Data Capabilities - * @oem_target_signature: Signature of chipset vendor, e.g. QUALCOMM - * @oem_target_type: Chip type - * @oem_fw_version: Firmware version - * @driver_version: Host software version - * @allowed_dwell_time_min: Channel dwell time - allowed minimum - * @allowed_dwell_time_max: Channel dwell time - allowed maximum - * @curr_dwell_time_min: Channel dwell time - current minimim - * @curr_dwell_time_max: Channel dwell time - current maximum - * @supported_bands: Supported bands, 2.4G or 5G Hz - * @num_channels: Num of channels IDs to follow - * @channel_list: List of channel IDs + * struct wifi_pos_err_msg_report - Error report message + * @msg_tag_len: Message tlv header + * @msg_subtype: Message subtype + * @req_id: id corresponding to the request. + * @fragment_info: Valid only for fragments. + * @pdev_id: pdev_id of radion. + * @time_left: time left in the measurment req. + * @err_rpt: Error report data. */ -struct qdf_packed wifi_pos_driver_caps { - uint8_t oem_target_signature[OEM_TARGET_SIGNATURE_LEN]; - uint32_t oem_target_type; - uint32_t oem_fw_version; - struct wifi_pos_driver_version driver_version; - uint16_t allowed_dwell_time_min; - uint16_t allowed_dwell_time_max; - uint16_t curr_dwell_time_min; - uint16_t curr_dwell_time_max; - uint16_t supported_bands; - uint16_t num_channels; - uint8_t channel_list[OEM_CAP_MAX_NUM_CHANNELS]; -}; - -/** - * struct wifi_pos_user_defined_caps - OEM capability to be exchanged between - * host and userspace - * @ftm_rr: FTM range report capability bit - * @lci_capability: LCI capability bit - * @reserved1: reserved - * @reserved2: reserved - */ -struct wifi_pos_user_defined_caps { - uint32_t ftm_rr:1; - uint32_t lci_capability:1; - uint32_t reserved1:30; - uint32_t reserved2; -}; - -/** - * struct wifi_pos_oem_get_cap_rsp - capabilities set by userspace and target. - * @driver_cap: target capabilities - * @user_defined_cap: capabilities set by userspace via set request - */ -struct qdf_packed wifi_pos_oem_get_cap_rsp { - struct wifi_pos_driver_caps driver_cap; - struct wifi_pos_user_defined_caps user_defined_cap; +struct qdf_packed wifi_pos_err_msg_report { + uint32_t msg_tag_len; + uint32_t msg_subtype; + uint32_t req_id; + uint32_t fragment_info; + uint32_t pdev_id; + uint32_t time_left; + struct wifi_pos_err_rpt err_rpt; }; /** @@ -243,6 +209,9 @@ struct wifi_pos_dma_rings_cfg { void *srng; }; +typedef void (*wifi_pos_send_rsp_handler)(uint32_t, enum wifi_pos_cmd_ids, + uint32_t, uint8_t *); + /** * struct wifi_pos_psoc_priv_obj - psoc obj data for wifi_pos * @app_pid: pid of app registered to host driver @@ -266,8 +235,16 @@ struct wifi_pos_dma_rings_cfg { * @dma_buf_pool: DMA buffer pools maintained at host: this will be 2-D array * where with num_rows = number of rings num_elements in each row = ring depth * @wifi_pos_lock: lock to access wifi pos priv object + * @oem_6g_support_disable: oem target 6ghz support is disabled if set * @wifi_pos_req_handler: function pointer to handle TLV or non-TLV * @wifi_pos_send_rsp: function pointer to send msg to userspace APP + * @wifi_pos_get_phy_mode: function pointer to get wlan phymode for given + * channel, channel width + * @wifi_pos_get_fw_phy_mode_for_freq: function pointer to get fw phymode + * for given freq and channel width + * @wifi_pos_send_action: function pointer to send registered action frames + * to userspace APP + * @rsp_version: rsp version * * wifi pos request messages * <----- fine_time_meas_cap (in bits) -----> @@ -303,10 +280,17 @@ struct wifi_pos_psoc_priv_obj { struct wifi_pos_dma_buf_info **dma_buf_pool; qdf_spinlock_t wifi_pos_lock; + bool oem_6g_support_disable; QDF_STATUS (*wifi_pos_req_handler)(struct wlan_objmgr_psoc *psoc, struct wifi_pos_req_msg *req); - void (*wifi_pos_send_rsp)(uint32_t, uint32_t, uint32_t, uint8_t *); + wifi_pos_send_rsp_handler wifi_pos_send_rsp; void (*wifi_pos_get_phy_mode)(uint8_t, uint32_t, uint32_t *); + void (*wifi_pos_get_fw_phy_mode_for_freq)(uint32_t, uint32_t, + uint32_t *); + void (*wifi_pos_send_action)(struct wlan_objmgr_psoc *psoc, + uint32_t oem_subtype, uint8_t *buf, + uint32_t len); + uint32_t rsp_version; }; /** diff --git a/drivers/staging/qca-wifi-host-cmn/utils/epping/inc/epping_internal.h b/drivers/staging/qca-wifi-host-cmn/utils/epping/inc/epping_internal.h index 7b1e6e89dea644f895ec82b01533634820a7ecf7..ff1960e9423f28a6099f4528fa83d72953e9c16c 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/epping/inc/epping_internal.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/epping/inc/epping_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -60,6 +60,10 @@ #define EPPING_MAX_ADAPTERS 1 #define EPPING_LOG(level, args ...) QDF_TRACE(QDF_MODULE_ID_HDD, level, ## args) +#define EPPING_HEX_DUMP(level, data, len) qdf_trace_hex_dump( \ + QDF_MODULE_ID_HDD, \ + level, \ + data, buf_len) struct epping_cookie { HTC_PACKET HtcPkt; /* HTC packet wrapper */ @@ -79,7 +83,7 @@ typedef enum { #define MAX_COOKIE_SLOT_SIZE 512 #define MAX_TX_PKT_DUP_NUM 4 -#ifdef HIF_PCI +#if defined(HIF_PCI) || defined(HIF_IPCI) #define WLAN_EPPING_DELAY_TIMEOUT_US 10 #define EPPING_MAX_CE_NUMS 8 #define EPPING_MAX_WATER_MARK 8 @@ -110,7 +114,7 @@ typedef struct epping_context { unsigned int kperf_num_tx_acks[EPPING_MAX_NUM_EPIDS]; unsigned int total_rx_recv; unsigned int total_tx_acks; -#ifdef HIF_PCI +#if defined(HIF_PCI) || defined(HIF_IPCI) epping_poll_t epping_poll[EPPING_MAX_NUM_EPIDS]; #endif struct epping_cookie *cookie_list; @@ -181,12 +185,12 @@ epping_adapter_t *epping_add_adapter(epping_context_t *pEpping_ctx, bool rtnl_held); void epping_destroy_adapter(epping_adapter_t *adapter); int epping_connect_service(epping_context_t *pEpping_ctx); -#ifdef HIF_PCI +#if defined(HIF_PCI) || defined(HIF_IPCI) void epping_register_tx_copier(HTC_ENDPOINT_ID eid, epping_context_t *pEpping_ctx); void epping_unregister_tx_copier(HTC_ENDPOINT_ID eid, epping_context_t *pEpping_ctx); void epping_tx_copier_schedule(epping_context_t *pEpping_ctx, HTC_ENDPOINT_ID eid, qdf_nbuf_t skb); -#endif /* HIF_PCI */ +#endif /* HIF_PCI || HIF_IPCI */ #endif /* end #ifndef EPPING_INTERNAL_H */ diff --git a/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_helper.c b/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_helper.c index fe17d8241cc06d9a683e7de648f98d8a6921e801..a75878af451fc13554419669ed6e1b46dcdd9686 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_helper.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_helper.c @@ -127,24 +127,11 @@ void epping_get_dummy_mac_addr(tSirMacAddr macAddr) void epping_hex_dump(void *data, int buf_len, const char *str) { - char *buf = (char *)data; - int i; + EPPING_LOG(QDF_TRACE_LEVEL_FATAL, "%s: E, %s", __func__, str); - printk("%s: E, %s\n", __func__, str); - for (i = 0; (i + 7) < buf_len; i += 8) { - printk("%02x %02x %02x %02x %02x %02x %02x %02x\n", - buf[i], - buf[i + 1], - buf[i + 2], - buf[i + 3], - buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]); - } + EPPING_HEX_DUMP(QDF_TRACE_LEVEL_INFO, data, buf_len); - /* Dump the bytes in the last line */ - for (; i < buf_len; i++) { - printk("%02x ", buf[i]); - } - printk("\n%s: X %s\n", __func__, str); + EPPING_LOG(QDF_TRACE_LEVEL_FATAL, "%s: X %s", __func__, str); } void *epping_get_qdf_ctx(void) diff --git a/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_rx.c b/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_rx.c index 0a5ae0b2654b258054c58c6ef2b97386bcb9f13e..a273146fbdaf28a14eeeac3cbe84002294e85493 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_rx.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_rx.c @@ -114,7 +114,8 @@ void epping_rx(void *ctx, HTC_PACKET *pPacket) if (status != QDF_STATUS_SUCCESS) { if (status != QDF_STATUS_E_CANCELED) { - printk("%s: RX ERR (%d)\n", __func__, status); + EPPING_LOG(QDF_TRACE_LEVEL_ERROR, "%s: RX ERR (%d)", + __func__, status); } qdf_nbuf_free(pktSkb); return; diff --git a/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_tx.c b/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_tx.c index b1969382eb8d434c9d21d5dd9444480d6fb7f19a..202e02e56758ff062ddf02a0acd82983f83cdb58 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_tx.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_tx.c @@ -366,8 +366,9 @@ void epping_tx_complete(void *ctx, HTC_PACKET *htc_pkt) flushing = true; } if (status != QDF_STATUS_E_RESOURCES) { - printk("%s() -TX ERROR, status: 0x%x\n", - __func__, status); + EPPING_LOG(QDF_TRACE_LEVEL_ERROR, + "%s() -TX ERROR, status: 0x%x", + __func__, status); } } else { EPPING_LOG(QDF_TRACE_LEVEL_INFO, "%s: OK\n", __func__); diff --git a/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_txrx.c b/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_txrx.c index 5332f4a6ba138f1efd8211cbb788ecc550acbc3d..0200fd6f43105b1a7e547f1534bdef1c42a675c5 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_txrx.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/epping/src/epping_txrx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -419,7 +419,8 @@ int epping_connect_service(epping_context_t *pEpping_ctx) connect.EpCallbacks.EpRecvRefill = epping_refill; connect.EpCallbacks.EpSendFull = epping_tx_queue_full /* ar6000_tx_queue_full */; -#elif defined(HIF_USB) || defined(HIF_PCI) || defined(HIF_SNOC) +#elif defined(HIF_USB) || defined(HIF_PCI) || defined(HIF_SNOC) || \ + defined(HIF_IPCI) connect.EpCallbacks.EpRecvRefill = NULL /* provided by HIF */; connect.EpCallbacks.EpSendFull = NULL /* provided by HIF */; /* disable flow control for hw flow control */ @@ -440,7 +441,8 @@ int epping_connect_service(epping_context_t *pEpping_ctx) } pEpping_ctx->EppingEndpoint[0] = response.Endpoint; -#if defined(HIF_PCI) || defined(HIF_USB) || defined(HIF_SNOC) +#if defined(HIF_PCI) || defined(HIF_USB) || defined(HIF_SNOC) || \ + defined(HIF_IPCI) connect.service_id = WMI_DATA_BK_SVC; status = htc_connect_service(pEpping_ctx->HTCHandle, &connect, &response); if (QDF_IS_STATUS_ERROR(status)) { diff --git a/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.c b/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.c index cc98cdcf939af57a91c751a4e74e0720bcd64e09..c0889fd83db5af83c4bd40123c7ef8ec160f45f8 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -1328,6 +1328,16 @@ int dbglog_set_mod_log_lvl(wmi_unified_t wmi_handle, uint32_t mod_log_lvl) return 0; } +int dbglog_set_mod_wow_log_lvl(wmi_unified_t wmi_handle, uint32_t mod_log_lvl) +{ + /* set the global module level to log_lvl */ + wma_config_debug_module_cmd(wmi_handle, + WMI_DEBUG_LOG_PARAM_WOW_MOD_ENABLE_BITMAP, + mod_log_lvl, NULL, 0); + + return 0; +} + void dbglog_set_vap_enable_bitmap(wmi_unified_t wmi_handle, uint32_t vap_enable_bitmap) @@ -3590,8 +3600,9 @@ A_BOOL dbglog_coex_print_handler(uint32_t mod_id, dbglog_printf_no_line_break(timestamp, vap_id, "%s: %u", dbg_id_str, args[0]); for (i = 1; i < numargs; i++) - printk("%u", args[i]); - printk("\n"); + dbglog_printf_no_line_break(timestamp, vap_id, + "%u", args[i]); + dbglog_printf_no_line_break(timestamp, vap_id, "\n"); } else { return false; } diff --git a/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.h b/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.h index ea613def20f32e1f4896a092bbc4a3d3808d6472..93b21efea03a7a42c01d51dcf02a14d24ced32f4 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/fwlog/dbglog_host.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2020 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 @@ -102,7 +102,7 @@ int dbglog_set_timestamp_resolution(wmi_unified_t wmi_handle, uint16_t tsr); -/** Enable reporting. If it is set to false then Traget wont deliver +/** Enable reporting. If it is set to false then Target wont deliver * any debug information */ int @@ -129,6 +129,19 @@ dbglog_set_log_lvl(wmi_unified_t wmi_handle, DBGLOG_LOG_LVL log_lvl); int dbglog_set_mod_log_lvl(wmi_unified_t wmi_handle, uint32_t mod_id_lvl); +/* + * set the debug log level for wow module + * mod_id_lvl : the format is more user friendly. + * module_id = mod_id_lvl/10; + * log_level = mod_id_lvl%10; + * example : mod_id_lvl is 153. then module id is 15 and log level is 3. + * this format allows user to pass a sinlge value + * (which is the most convenient way for most of the OSs) + * to be passed from user to the driver. + */ +int +dbglog_set_mod_wow_log_lvl(wmi_unified_t wmi_handle, uint32_t mod_id_lvl); + /** Enable/Disable the logging for VAP */ int dbglog_vap_log_enable(wmi_unified_t wmi_handle, uint16_t vap_id, @@ -237,6 +250,12 @@ dbglog_set_mod_log_lvl(wmi_unified_t wmi_handle, uint32_t mod_id_lvl) { return A_OK; } + +static inline int +dbglog_set_mod_wow_log_lvl(wmi_unified_t wmi_handle, uint32_t mod_id_lvl) +{ + return A_OK; +} #endif /* FEATURE_FW_LOG_PARSING */ #ifdef __cplusplus diff --git a/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/host_diag_core_event.h b/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/host_diag_core_event.h index b07365dfd3b9e4b2b9b708915b64c563b7681d81..6a4ea97c72939fd6fe5d4786a058136b3929ed3e 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/host_diag_core_event.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/host_diag_core_event.h @@ -316,6 +316,7 @@ typedef struct { * @est_link_speed: link speed of connection, units in Mbps * @result_code: result code of connection success or failure * @reason_code: if failed then what is the reason + * @op_freq: channel frequency in MHz on which AP is connected */ struct host_event_wlan_connection_stats { int8_t rssi; @@ -333,6 +334,7 @@ struct host_event_wlan_connection_stats { uint32_t est_link_speed; uint16_t result_code; uint16_t reason_code; + uint32_t op_freq; } qdf_packed; /*------------------------------------------------------------------------- @@ -896,6 +898,7 @@ enum wifi_connectivity_events { * @WIFI_POWER_EVENT_WAKELOCK_IFACE_CHANGE_TIMER: iface change timer running * @WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE: Montitor mode wakelock * @WIFI_POWER_EVENT_WAKELOCK_DRIVER_IDLE_RESTART: Wakelock for Idle Restart + * @WIFI_POWER_EVENT_WAKELOCK_TDLS: Wakelock for TDLS * * Indicates the reason for which the wakelock was taken/released */ @@ -923,6 +926,7 @@ enum wake_lock_reason { WIFI_POWER_EVENT_WAKELOCK_IFACE_CHANGE_TIMER, WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE, WIFI_POWER_EVENT_WAKELOCK_DRIVER_IDLE_RESTART, + WIFI_POWER_EVENT_WAKELOCK_TDLS, }; /* The length of interface name should >= IFNAMSIZ */ diff --git a/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/host_diag_core_log.h b/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/host_diag_core_log.h index 70690efa870f436cc019f1fa3189f3fb5a14853f..a83a21446dd9b58fa0e0e68c34e2303dc39234a5 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/host_diag_core_log.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/host_diag_core_log.h @@ -100,6 +100,7 @@ typedef struct { uint8_t operatingChannel; uint8_t beaconInterval; uint8_t status; + uint32_t op_freq; } host_log_ibss_pkt_type; /*--------------------------------------------------------------------------- @@ -284,6 +285,271 @@ struct host_log_cold_boot_cal_data_type { uint8_t cb_cal_data[HOST_LOG_MAX_COLD_BOOT_CAL_DATA_SIZE]; }; +#define WLAN_MAX_ROAM_CANDIDATE_AP 9 +#define WLAN_MAX_ROAM_SCAN_CHAN 38 +#define WLAN_MAX_SSID_SIZE 32 + +/** + * host_log_wlan_mgmt_tx_rx_info: To capture TX/RX mgmt frames' payload + * @hdr: Log header + * @version: Version number of the payload + * @vdev_id: Vdev id + * @is_tx: 1 - TX frame, 0 - RX frame + * @mgmt_type: type of frames, value: enum wifi_frm_type + * @mgmt_subtype: subtype of mgmt frame, value: enum mgmt_frm_subtype + * @mgmt_frame_seq_num: Frame sequence number in 802.11 header + * @operating_freq: operating frequency of AP + * @ssid_len: length of SSID, max 32 bytes long as per standard + * @ssid: SSID of connected AP + * @self_mac_addr: mac address of self interface + * @bssid: BSSID for which frame is received + * @mac_failure_reason: Internal driver failure reason + * @mgmt_status_code: 802.11 management frame response status code from + * section 9.4.1.9 IEEE 802.11 - 2016 + * @auth_algo: Authentication algorithm number + * @auth_transaction_num: Authentication transaction sequence number + * @is_retry: Is retry frame + * @rssi: RSSI for the received frame + * @origin: 1- Sent by host. 2- sent by firmware + */ +struct host_log_wlan_mgmt_tx_rx_info { + log_hdr_type hdr; + uint8_t version; + uint8_t vdev_id; + bool is_tx; + uint8_t mgmt_type; + uint8_t mgmt_subtype; + uint16_t mgmt_frame_seq_num; + uint8_t operating_freq; + uint8_t ssid_len; + char ssid[WLAN_MAX_SSID_SIZE]; + uint8_t self_mac_addr[QDF_MAC_ADDR_SIZE]; + uint8_t bssid[QDF_MAC_ADDR_SIZE]; + uint16_t mac_failure_reason; + uint16_t mgmt_status_code; + uint8_t auth_algo; + uint8_t auth_transaction_num; + uint8_t is_retry; + uint32_t rssi; + uint8_t origin; +} qdf_packed; + +/** + * struct wlan_roam_btm_trigger_data - BTM roam trigger related information + * @btm_request_mode: BTM request mode - solicited/unsolicited + * @disassoc_timer: Number of TBTT before AP disassociates the STA in ms + * @validity_interval: Preferred candidate list validity interval in ms + * @candidate_list_count: Number of candidates in BTM request. + * @btm_resp_status: Status code of the BTM response. + */ +struct wlan_roam_btm_trigger_data { + uint8_t btm_request_mode; + uint32_t disassoc_timer; + uint32_t validity_interval; + uint16_t candidate_list_count; + uint16_t btm_resp_status; +} qdf_packed; + +/** + * struct wlan_roam_cu_trigger_data - BSS Load roam trigger parameters + * @cu_load: Connected AP CU load percentage + */ +struct wlan_roam_cu_trigger_data { + uint16_t cu_load; +} qdf_packed; + +/** + * Struct wlan_roam_rssi_trigger_data - RSSI roam trigger related + * parameters + * @threshold: RSSI threshold value in dBm for LOW rssi roam trigger + */ +struct wlan_roam_rssi_trigger_data { + uint32_t threshold; +} qdf_packed; + +/** + * struct wlan_roam_deauth_trigger_data - Deauth roaming trigger related + * parameters + * @type: 1- Deauthentication 2- Disassociation + * @reason: Status code of the Deauth/Disassoc received + */ +struct wlan_roam_deauth_trigger_data { + uint8_t type; + uint32_t reason; +} qdf_packed; + +/** + * struct host_log_wlan_roam_trigger_info - Roam trigger + * related info + * @hdr: Log header + * @version: Version number of the payload + * @vdev_id: Vdev id + * @trigger_reason: Roaming trigger reason + * @trigger_sub_reason: Roaming trigger sub reason + * @current_rssi: Current connected AP RSSI + * @timestamp: Host driver timestamp in msecs + * @btm_trig_data: BTM trigger related data + * @cu_load_data: CU load trigger related data + * @rssi_trig_data: RSSI roam trigger related data + * @deauth_trig_data: Deauth Roam trigger related data + */ +struct host_log_wlan_roam_trigger_info { + log_hdr_type hdr; + uint8_t version; + uint8_t vdev_id; + uint32_t trigger_reason; + uint32_t trigger_sub_reason; + uint32_t current_rssi; + uint32_t timestamp; + union { + struct wlan_roam_btm_trigger_data btm_trig_data; + struct wlan_roam_cu_trigger_data cu_load_data; + struct wlan_roam_rssi_trigger_data rssi_trig_data; + struct wlan_roam_deauth_trigger_data deauth_trig_data; + }; +} qdf_packed; + +/** + * struct host_log_wlan_roam_candidate_info - Roam scan candidate APs related + * info + * @version: Payload structure version + * @timestamp: Host timestamp in millisecs + * @type: 0 - Candidate AP; 1 - Current connected AP. + * @bssid: AP bssid. + * @freq: Channel frquency + * @cu_load: Channel utilization load of the AP. + * @cu_score: Channel Utilization score. + * @rssi: Candidate AP rssi + * @rssi_score: AP RSSI score + * @total_score: Total score of the candidate AP. + * @etp: Estimated throughput value of the AP in Mbps + */ +struct host_log_wlan_roam_candidate_info { + uint8_t version; + uint32_t timestamp; + uint8_t type; + uint8_t bssid[QDF_MAC_ADDR_SIZE]; + uint16_t freq; + uint32_t cu_load; + uint32_t cu_score; + uint32_t rssi; + uint32_t rssi_score; + uint32_t total_score; + uint32_t etp; +} qdf_packed; + +/** + * struct host_log_wlan_roam_scan_data - Roam scan event details + * @hdr: Log header + * @version: Version number of the diag log payload + * @vdev_id: Vdev ID + * @type: 0 - Partial roam scan; 1 - Full roam scan + * @num_ap: Number of candidate APs. + * @num_chan: Number of channels. + * @timestamp: Time of day in milliseconds at which scan was triggered + * @trigger_reason: Roam scan trigger reason + * @next_rssi_threshold: Next roam can trigger rssi threshold + * @chan_freq: List of frequencies scanned as part of roam scan + * @ap: List of candidate AP info + */ +struct host_log_wlan_roam_scan_data { + log_hdr_type hdr; + uint8_t version; + uint8_t vdev_id; + uint16_t type; + uint8_t num_ap; + uint8_t num_chan; + uint32_t timestamp; + uint32_t trigger_reason; + uint32_t next_rssi_threshold; + uint16_t chan_freq[WLAN_MAX_ROAM_SCAN_CHAN]; + struct host_log_wlan_roam_candidate_info ap[WLAN_MAX_ROAM_CANDIDATE_AP]; +} qdf_packed; + +/** + * struct host_log_wlan_roam_result_info - Roam result related info. + * @hdr: Log header + * @version: Payload strcuture version + * @vdev_id: Vdev Id + * @status: 0 - Roaming is success ; 1 - Roaming failed + * @timestamp: Host timestamp in millisecs + * @fail_reason: One of WMI_ROAM_FAIL_REASON_ID + */ +struct host_log_wlan_roam_result_info { + log_hdr_type hdr; + uint8_t version; + uint8_t vdev_id; + bool status; + uint32_t timestamp; + uint32_t fail_reason; +} qdf_packed; + +/** + * struct wlan_rrm_beacon_report - RRM beacon report related + * parameters + * @req_bssid: beacon report requestor BSSID + * @req_ssid: Requested SSID for beacon report + * @is_wildcard_bssid: Is the BSSID FF:FF:FF:FF:FF:FF + * @req_reg_class: Regulatory class mentioned in the request + * @req_measurement_mode: Measurement mode. Active/Passive/Beacon report Table + * @req_measurement_duration: Measurement duration requested. + * @num_reports_in_frame: Number of BSS scanned + * @is_last_frame_in_req: True if this frame is the last frame sent for the + * request + */ +struct wlan_rrm_beacon_report { + uint8_t req_bssid[QDF_MAC_ADDR_SIZE]; + uint8_t req_ssid[WLAN_MAX_SSID_SIZE]; + bool is_wildcard_bssid; + uint8_t req_reg_class; + uint16_t req_measurement_mode; + uint16_t req_measurement_duration; + uint8_t num_reports_in_frame; + bool is_last_frame_in_req; +} qdf_packed; + +/** + * struct host_log_wlan_rrm_tx_rx_info - RRM frame related details + * @hdr: Log header + * @version: Version of the payload struture + * @vdev_id: Vdev id + * @orgin: Sent by host or firmware + * @is_tx: Is Tx frame or RX frame + * @roam_result: Roaming result + * @timestamp: Time of the day in milliseconds + * @mgmt_frame_seq_num: Frame sequence number + * @received_chan_freq: Frame received channel frequency + * @action_category: Action frame category + * @rrm_action_code: Radio measurement/Noise measurement + * @radio_measurement_type: Neighbor report/Beacon report + * @bssid: BSSID field in frame + * @req_num_freq: Number of frequencies provided in request + * @req_freq: Frequencies requested + * @fail_reason_code: response TX failure status code + * @rssi: Rx frame rssi + * @bcn_rpt: Beacon report related parameters + */ +struct host_log_wlan_rrm_tx_rx_info { + log_hdr_type hdr; + uint8_t version; + uint8_t vdev_id; + uint8_t origin; + bool is_tx; + bool roam_result; + uint32_t timestamp; + uint16_t mgmt_frame_seq_num; + uint16_t received_chan_freq; + uint8_t action_category; + uint8_t rrm_action_code; + uint8_t radio_measurement_type; + uint8_t bssid[QDF_MAC_ADDR_SIZE]; + uint8_t req_num_freq; + uint16_t req_freq[WLAN_MAX_ROAM_SCAN_CHAN]; + uint8_t fail_reason_code; + uint32_t rssi; + struct wlan_rrm_beacon_report bcn_rpt; +} qdf_packed; + /** * struct host_event_proto_pkt_info - DP protocol pkt info * @hdr: Log header diff --git a/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/log_codes.h b/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/log_codes.h index 10f9f100852311854ca0f22bfd7580802208ac9a..ddc8301f8976b9d66feda905fed89564a098c92e 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/log_codes.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/inc/log_codes.h @@ -2003,6 +2003,12 @@ #define LOG_WLAN_COLD_BOOT_CAL_DATA_C ((0xA18) + LOG_1X_BASE_C) +#define LOG_WLAN_AUTH_ASSOC_TX_RX_INFO_C ((0xA19) + LOG_1X_BASE_C) +#define LOG_WLAN_ROAM_TRIGGER_INFO_C ((0xA1A) + LOG_1X_BASE_C) +#define LOG_WLAN_ROAM_SCAN_INFO_C ((0xA1B) + LOG_1X_BASE_C) +#define LOG_WLAN_ROAM_RESULT_INFO_C ((0xA1C) + LOG_1X_BASE_C) +#define LOG_WLAN_RRM_TX_RX_INFO_C ((0xA1D) + LOG_1X_BASE_C) + #define LOG_WLAN_DP_PROTO_PKT_INFO_C ((0xA1E) + LOG_1X_BASE_C) /* This is only here for old (pre equipment ID update) logging code */ diff --git a/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/src/host_diag_log.c b/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/src/host_diag_log.c index 97e51f6542b8de2e4095b5d387d0700a64b4a9df..f42743e9c8ac4fab5459113da3bf0d656e1b1414 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/src/host_diag_log.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/host_diag_log/src/host_diag_log.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -109,12 +109,8 @@ void host_diag_log_submit(void *plog_hdr_ptr) uint16_t data_len; uint16_t total_len; - if (cds_is_load_or_unload_in_progress()) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, - "%s: Unloading/Loading in Progress. Ignore!!!", - __func__); + if (cds_is_load_or_unload_in_progress()) return; - } if (nl_srv_is_initialized() != 0) return; @@ -201,12 +197,8 @@ void host_diag_event_report_payload(uint16_t event_Id, uint16_t length, event_report_t *pEvent_report; uint16_t total_len; - if (cds_is_load_or_unload_in_progress()) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, - "%s: Unloading/Loading in Progress. Ignore!!!", - __func__); + if (cds_is_load_or_unload_in_progress()) return; - } if (nl_srv_is_initialized() != 0) return; diff --git a/drivers/staging/qca-wifi-host-cmn/utils/logging/inc/wlan_logging_sock_svc.h b/drivers/staging/qca-wifi-host-cmn/utils/logging/inc/wlan_logging_sock_svc.h index 941fbe5ddae28280ecc603bdff3a8a6e1114ee7d..7db67a26664318c06a090d54d532d9f4e52d7775 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/logging/inc/wlan_logging_sock_svc.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/logging/inc/wlan_logging_sock_svc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2019 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 @@ -60,12 +60,36 @@ static inline void wlan_logging_set_active(bool active) {} static inline void wlan_logging_set_log_to_console(bool log_to_console) {} #endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ -#if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) && !defined(REMOVE_PKT_LOG) -void wlan_deregister_txrx_packetdump(void); -void wlan_register_txrx_packetdump(void); +#if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) && \ + defined(FEATURE_PKTLOG) && !defined(REMOVE_PKT_LOG) +/** + * wlan_deregister_txrx_packetdump() - tx/rx packet dump + * deregistration + * @pdev_id: id of the datapath pdev handle + * + * This function is used to deregister tx/rx packet dump callbacks + * with ol, pe and htt layers + * + * Return: None + * + */ +void wlan_deregister_txrx_packetdump(uint8_t pdev_id); + +/** + * wlan_register_txrx_packetdump() - tx/rx packet dump + * registration + * @pdev_id: id of the datapath pdev handle + * + * This function is used to register tx/rx packet dump callbacks + * with ol, pe and htt layers + * + * Return: None + * + */ +void wlan_register_txrx_packetdump(uint8_t pdev_id); #else -static inline void wlan_deregister_txrx_packetdump(void) {} -static inline void wlan_register_txrx_packetdump(void) {} +static inline void wlan_deregister_txrx_packetdump(uint8_t pdev_id) {} +static inline void wlan_register_txrx_packetdump(uint8_t pdev_id) {} #endif #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) && defined(FEATURE_WLAN_DIAG_SUPPORT) @@ -84,7 +108,8 @@ static inline void wlan_report_log_completion(uint32_t is_fatal, #endif /* FEATURE_WLAN_DIAG_SUPPORT */ -#if defined(CONFIG_MCL) && !defined(REMOVE_PKT_LOG) +#if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) && \ + defined(FEATURE_PKTLOG) && !defined(REMOVE_PKT_LOG) void wlan_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data); #else static inline diff --git a/drivers/staging/qca-wifi-host-cmn/utils/logging/inc/wlan_roam_debug.h b/drivers/staging/qca-wifi-host-cmn/utils/logging/inc/wlan_roam_debug.h index 09425b18be73b0e0761f5a5bd7a96393059323b3..9b66b843d7a31ad47e4f92c598987a0c3b217805 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/logging/inc/wlan_roam_debug.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/logging/inc/wlan_roam_debug.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 diff --git a/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_logging_sock_svc.c b/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_logging_sock_svc.c index d8e851662d1b939446b45f18a5b93d9d129b22ac..8eb9af23faeda44bd887c5b544feffc44c42d4c3 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_logging_sock_svc.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_logging_sock_svc.c @@ -23,16 +23,6 @@ #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE #include -#ifdef CONFIG_MCL -#include -#include -#include "cds_utils.h" -#include "csr_api.h" -#include "wma.h" -#include "ol_txrx_api.h" -#include "pktlog_ac.h" -#include -#endif #include #include #include @@ -43,11 +33,26 @@ #include #include #include "host_diag_core_log.h" +#include #ifdef CNSS_GENL #include #endif +#if defined(FEATURE_FW_LOG_PARSING) || defined(FEATURE_WLAN_DIAG_SUPPORT) || \ + defined(FEATURE_PKTLOG) +#include +#include "ani_global.h" +#endif + +#ifdef FEATURE_PKTLOG +#ifndef REMOVE_PKT_LOG +#include "wma.h" +#include "pktlog_ac.h" +#include +#endif +#endif + #define MAX_NUM_PKT_LOG 32 #define LOGGING_TRACE(level, args ...) \ @@ -63,6 +68,8 @@ #define MAX_LOGMSG_LENGTH 2048 #define MAX_SKBMSG_LENGTH 4096 +#define WLAN_LOG_BUFFER_SIZE 2048 +#if defined(FEATURE_PKTLOG) && !defined(REMOVE_PKT_LOG) /** * Buffer to accommodate - * pktlog buffer (2048 bytes) @@ -74,7 +81,6 @@ * HTT_T2H_MAX_MSG_SIZE. Adjust WLAN_LOG_BUFFER_SIZE * based on the above mentioned macros. */ -#define WLAN_LOG_BUFFER_SIZE 2048 #define ATH_PKTLOG_HDR_SIZE (sizeof(struct ath_pktlog_hdr)) #define PKT_DUMP_HDR_SIZE (sizeof(struct packet_dump)) #define EXTRA_PADDING 40 @@ -82,6 +88,9 @@ #define MAX_PKTSTATS_LENGTH \ ((WLAN_LOG_BUFFER_SIZE) + (ATH_PKTLOG_HDR_SIZE) + \ (PKT_DUMP_HDR_SIZE) + (EXTRA_PADDING)) +#else +#define MAX_PKTSTATS_LENGTH WLAN_LOG_BUFFER_SIZE +#endif /* FEATURE_PKTLOG */ #define MAX_PKTSTATS_BUFF 16 #define HOST_LOG_DRIVER_MSG 0x001 @@ -476,8 +485,9 @@ static int pkt_stats_fill_headers(struct sk_buff *skb) cds_pkt_size); if (unlikely(skb_headroom(skb) < cds_pkt_size)) { - pr_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", - __LINE__, skb->head, skb->data, sizeof(msg_header)); + qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", + __LINE__, skb->head, skb->data, + sizeof(msg_header)); return -EIO; } @@ -485,8 +495,9 @@ static int pkt_stats_fill_headers(struct sk_buff *skb) &cds_pktlog, cds_pkt_size); if (unlikely(skb_headroom(skb) < sizeof(int))) { - pr_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", - __LINE__, skb->head, skb->data, sizeof(int)); + qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", + __LINE__, skb->head, skb->data, + sizeof(int)); return -EIO; } @@ -507,8 +518,9 @@ static int pkt_stats_fill_headers(struct sk_buff *skb) msg_header.wmsg.length = cpu_to_be16(skb->len); if (unlikely(skb_headroom(skb) < sizeof(msg_header))) { - pr_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", - __LINE__, skb->head, skb->data, sizeof(msg_header)); + qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", + __LINE__, skb->head, skb->data, + sizeof(msg_header)); return -EIO; } @@ -558,8 +570,8 @@ static int pktlog_send_per_pkt_stats_to_user(void) skb_new = dev_alloc_skb(MAX_SKBMSG_LENGTH); if (!skb_new) { if (!rate_limit) { - pr_err("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u\n", - __func__, MAX_SKBMSG_LENGTH, + qdf_nofl_err("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u", + __func__, MAX_SKBMSG_LENGTH, gwlan_logging.drop_count); } rate_limit = 1; @@ -576,14 +588,15 @@ static int pktlog_send_per_pkt_stats_to_user(void) ret = pkt_stats_fill_headers(pstats_msg->skb); if (ret < 0) { - pr_err("%s failed to fill headers %d\n", __func__, ret); + qdf_nofl_err("%s failed to fill headers %d", + __func__, ret); free_old_skb = true; goto err; } ret = nl_srv_bcast_diag(pstats_msg->skb); if (ret < 0) { - pr_info("%s: Send Failed %d drop_count = %u\n", - __func__, ret, + qdf_nofl_info("%s: Send Failed %d drop_count = %u", + __func__, ret, ++gwlan_logging.pkt_stat_drop_cnt); } else { ret = 0; @@ -635,10 +648,9 @@ static int send_filled_buffers_to_user(void) skb = dev_alloc_skb(MAX_LOGMSG_LENGTH); if (!skb) { if (!rate_limit) { - pr_err - ("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u\n", - __func__, MAX_LOGMSG_LENGTH, - gwlan_logging.drop_count); + qdf_nofl_err("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u", + __func__, MAX_LOGMSG_LENGTH, + gwlan_logging.drop_count); } rate_limit = 1; ret = -ENOMEM; @@ -664,10 +676,10 @@ static int send_filled_buffers_to_user(void) list_add_tail(&plog_msg->node, &gwlan_logging.free_list); spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); - pr_err("%s: drop_count = %u\n", __func__, - ++gwlan_logging.drop_count); - pr_err("%s: nlmsg_put() failed for msg size[%d]\n", - __func__, tot_msg_len); + qdf_nofl_err("%s: drop_count = %u", __func__, + ++gwlan_logging.drop_count); + qdf_nofl_err("%s: nlmsg_put() failed for msg size[%d]", + __func__, tot_msg_len); dev_kfree_skb(skb); skb = NULL; ret = -EINVAL; @@ -686,8 +698,8 @@ static int send_filled_buffers_to_user(void) ret = nl_srv_bcast_host_logs(skb); /* print every 64th drop count */ if (ret < 0 && (!(gwlan_logging.drop_count % 0x40))) { - pr_err("%s: Send Failed %d drop_count = %u\n", - __func__, ret, ++gwlan_logging.drop_count); + qdf_nofl_err("%s: Send Failed %d drop_count = %u", + __func__, ret, ++gwlan_logging.drop_count); } } @@ -795,9 +807,8 @@ static int wlan_logging_thread(void *Arg) || gwlan_logging.exit)); if (ret_wait_status == -ERESTARTSYS) { - pr_err - ("%s: wait_event_interruptible returned -ERESTARTSYS", - __func__); + qdf_nofl_err("%s: wait_event_interruptible returned -ERESTARTSYS", + __func__); break; } @@ -930,8 +941,8 @@ int wlan_logging_sock_init_svc(void) gwlan_logging.buffer_length = MAX_LOGMSG_LENGTH; if (allocate_log_msg_buffer() != QDF_STATUS_SUCCESS) { - pr_err("%s: Could not allocate memory for log_msg\n", - __func__); + qdf_nofl_err("%s: Could not allocate memory for log_msg", + __func__); return -ENOMEM; } @@ -952,8 +963,8 @@ int wlan_logging_sock_init_svc(void) pkt_stats_size = sizeof(struct pkt_stats_msg); gpkt_stats_buffers = vmalloc(MAX_PKTSTATS_BUFF * pkt_stats_size); if (!gpkt_stats_buffers) { - pr_err("%s: Could not allocate memory for Pkt stats\n", - __func__); + qdf_nofl_err("%s: Could not allocate memory for Pkt stats", + __func__); goto err1; } qdf_mem_zero(gpkt_stats_buffers, @@ -969,7 +980,8 @@ int wlan_logging_sock_init_svc(void) for (i = 0; i < MAX_PKTSTATS_BUFF; i++) { gpkt_stats_buffers[i].skb = dev_alloc_skb(MAX_PKTSTATS_LENGTH); if (!gpkt_stats_buffers[i].skb) { - pr_err("%s: Memory alloc failed for skb", __func__); + qdf_nofl_err("%s: Memory alloc failed for skb", + __func__); /* free previously allocated skb and return */ for (j = 0; j < i ; j++) dev_kfree_skb(gpkt_stats_buffers[j].skb); @@ -996,8 +1008,8 @@ int wlan_logging_sock_init_svc(void) gwlan_logging.thread = kthread_create(wlan_logging_thread, NULL, "wlan_logging_thread"); if (IS_ERR(gwlan_logging.thread)) { - pr_err("%s: Could not Create LogMsg Thread Controller", - __func__); + qdf_nofl_err("%s: Could not Create LogMsg Thread Controller", + __func__); goto err3; } wake_up_process(gwlan_logging.thread); @@ -1044,12 +1056,10 @@ int wlan_logging_sock_deinit_svc(void) if (!gwlan_logging.pcur_node) return 0; -#ifdef CONFIG_MCL INIT_COMPLETION(gwlan_logging.shutdown_comp); -#endif gwlan_logging.exit = true; gwlan_logging.is_active = false; -#ifdef CONFIG_MCL +#if defined(FEATURE_FW_LOG_PARSING) || defined(FEATURE_WLAN_DIAG_SUPPORT) cds_set_multicast_logging(0); #endif gwlan_logging.is_flush_complete = false; @@ -1110,11 +1120,7 @@ void wlan_logging_set_per_pkt_stats(void) */ void wlan_logging_set_fw_flush_complete(void) { - if (gwlan_logging.is_active == false -#ifdef CONFIG_MCL - || !cds_is_fatal_event_enabled() -#endif - ) + if (!gwlan_logging.is_active) return; set_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); @@ -1133,23 +1139,17 @@ void wlan_flush_host_logs_for_fatal(void) { unsigned long flags; -#ifdef CONFIG_MCL - if (cds_is_log_report_in_progress()) { -#endif - if (gwlan_logging.flush_timer_period == 0) - pr_info("%s:flush all host logs Setting HOST_LOG_POST_MASK\n", - __func__); - spin_lock_irqsave(&gwlan_logging.spin_lock, flags); - wlan_queue_logmsg_for_app(); - spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); - set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); - wake_up_interruptible(&gwlan_logging.wait_queue); -#ifdef CONFIG_MCL - } -#endif + if (gwlan_logging.flush_timer_period == 0) + qdf_nofl_info("%s:flush all host logs Setting HOST_LOG_POST_MAS", + __func__); + spin_lock_irqsave(&gwlan_logging.spin_lock, flags); + wlan_queue_logmsg_for_app(); + spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); + set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); + wake_up_interruptible(&gwlan_logging.wait_queue); } -#ifdef CONFIG_MCL +#ifdef FEATURE_PKTLOG #ifndef REMOVE_PKT_LOG static uint8_t gtx_count; @@ -1188,8 +1188,8 @@ static int wlan_get_pkt_stats_free_node(void) if ( cds_is_multicast_logging() && (!(gwlan_logging.pkt_stat_drop_cnt % 0x40))) { - pr_err("%s: drop_count = %u\n", - __func__, gwlan_logging.pkt_stat_drop_cnt); + qdf_nofl_err("%s: drop_count = %u", + __func__, gwlan_logging.pkt_stat_drop_cnt); } list_del_init(gwlan_logging.pkt_stat_filled_list.next); ret = 1; @@ -1224,7 +1224,7 @@ void wlan_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data) pktlog_hdr = (struct ath_pktlog_hdr *)pl_hdr; if (!pktlog_hdr) { - pr_err("%s : Invalid pkt_stats_header\n", __func__); + qdf_nofl_err("%s : Invalid pkt_stats_header", __func__); return; } @@ -1315,7 +1315,7 @@ static void driver_hal_status_map(uint8_t *status) /* * send_packetdump() - send packet dump * @soc: soc handle - * @vdev: vdev handle + * @vdev_id: ID of the virtual device handle * @netbuf: netbuf * @status: status of tx packet * @type: type of packet @@ -1327,19 +1327,19 @@ static void driver_hal_status_map(uint8_t *status) * */ static void send_packetdump(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, qdf_nbuf_t netbuf, + uint8_t vdev_id, qdf_nbuf_t netbuf, uint8_t status, uint8_t type) { struct ath_pktlog_hdr pktlog_hdr = {0}; struct packet_dump pd_hdr = {0}; if (!netbuf) { - pr_err("%s: Invalid netbuf.\n", __func__); + qdf_nofl_err("%s: Invalid netbuf.", __func__); return; } /* Send packet dump only for STA interface */ - if (wlan_op_mode_sta != cdp_get_opmode(soc, vdev)) + if (wlan_op_mode_sta != cdp_get_opmode(soc, vdev_id)) return; #if defined(HELIUMPLUS) @@ -1392,17 +1392,7 @@ static void send_packetdump_monitor(uint8_t type) wlan_pkt_stats_to_logger_thread(&pktlog_hdr, &pd_hdr, NULL); } -/** - * wlan_deregister_txrx_packetdump() - tx/rx packet dump - * deregistration - * - * This function is used to deregister tx/rx packet dump callbacks - * with ol, pe and htt layers - * - * Return: None - * - */ -void wlan_deregister_txrx_packetdump(void) +void wlan_deregister_txrx_packetdump(uint8_t pdev_id) { void *soc = cds_get_context(QDF_MODULE_ID_SOC); @@ -1410,7 +1400,7 @@ void wlan_deregister_txrx_packetdump(void) return; if (gtx_count || grx_count) { - cdp_deregister_packetdump_cb(soc); + cdp_deregister_packetdump_cb(soc, pdev_id); wma_deregister_packetdump_callback(); send_packetdump_monitor(STOP_MONITOR); csr_packetdump_timer_stop(); @@ -1425,6 +1415,7 @@ void wlan_deregister_txrx_packetdump(void) /* * check_txrx_packetdump_count() - function to check * tx/rx packet dump global counts + * @pdev_id: datapath pdev identifier * * This function is used to check global counts of tx/rx * packet dump functionality. @@ -1433,14 +1424,14 @@ void wlan_deregister_txrx_packetdump(void) * 0 otherwise * */ -static bool check_txrx_packetdump_count(void) +static bool check_txrx_packetdump_count(uint8_t pdev_id) { if (gtx_count == MAX_NUM_PKT_LOG || grx_count == MAX_NUM_PKT_LOG) { LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG, "%s gtx_count: %d grx_count: %d deregister packetdump", __func__, gtx_count, grx_count); - wlan_deregister_txrx_packetdump(); + wlan_deregister_txrx_packetdump(pdev_id); return 1; } return 0; @@ -1449,7 +1440,8 @@ static bool check_txrx_packetdump_count(void) /* * tx_packetdump_cb() - tx packet dump callback * @soc: soc handle - * @vdev: vdev handle + * @pdev_id: datapath pdev id + * @vdev_id: vdev id * @netbuf: netbuf * @status: status of tx packet * @type: packet type @@ -1461,27 +1453,29 @@ static bool check_txrx_packetdump_count(void) * */ static void tx_packetdump_cb(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, qdf_nbuf_t netbuf, + uint8_t pdev_id, uint8_t vdev_id, + qdf_nbuf_t netbuf, uint8_t status, uint8_t type) { bool temp; - if (!soc || !vdev) + if (!soc) return; - temp = check_txrx_packetdump_count(); + temp = check_txrx_packetdump_count(pdev_id); if (temp) return; driver_hal_status_map(&status); - send_packetdump(soc, vdev, netbuf, status, type); + send_packetdump(soc, vdev_id, netbuf, status, type); } /* * rx_packetdump_cb() - rx packet dump callback * @soc: soc handle - * @vdev: vdev handle + * @pdev_id: datapath pdev id + * @vdev_id: vdev id * @netbuf: netbuf * @status: status of rx packet * @type: packet type @@ -1493,47 +1487,40 @@ static void tx_packetdump_cb(ol_txrx_soc_handle soc, * */ static void rx_packetdump_cb(ol_txrx_soc_handle soc, - struct cdp_vdev *vdev, qdf_nbuf_t netbuf, + uint8_t pdev_id, uint8_t vdev_id, + qdf_nbuf_t netbuf, uint8_t status, uint8_t type) { bool temp; - if (!soc || !vdev) + if (!soc) return; - temp = check_txrx_packetdump_count(); + temp = check_txrx_packetdump_count(pdev_id); if (temp) return; - send_packetdump(soc, vdev, netbuf, status, type); + send_packetdump(soc, vdev_id, netbuf, status, type); } - -/** - * wlan_register_txrx_packetdump() - tx/rx packet dump - * registration - * - * This function is used to register tx/rx packet dump callbacks - * with ol, pe and htt layers - * - * Return: None - * - */ -void wlan_register_txrx_packetdump(void) +void wlan_register_txrx_packetdump(uint8_t pdev_id) { void *soc = cds_get_context(QDF_MODULE_ID_SOC); if (!soc) return; - cdp_register_packetdump_cb(soc, tx_packetdump_cb, rx_packetdump_cb); + cdp_register_packetdump_cb(soc, pdev_id, + tx_packetdump_cb, rx_packetdump_cb); wma_register_packetdump_callback(tx_packetdump_cb, rx_packetdump_cb); send_packetdump_monitor(START_MONITOR); gtx_count = 0; grx_count = 0; + + csr_packetdump_timer_start(); } #endif /* REMOVE_PKT_LOG */ -#endif /* CONFIG_MCL */ +#endif /* FEATURE_PKTLOG */ #endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ diff --git a/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_roam_debug.c b/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_roam_debug.c index 8988282853a4efebfd9e597ec3008f8e2f007ec6..c6ced135050f351f689425338093af6a3854abb8 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_roam_debug.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/logging/src/wlan_roam_debug.c @@ -247,9 +247,10 @@ void wlan_roam_debug_dump_table(void) roam_debug("index = %5d timestamp = 0x%016llx delta ms = %-12u", i, dbg_rec->time, delta); - roam_debug("info = %-24s vdev_id = %-3d mac addr = %pM", + roam_debug("info = %-24s vdev_id = %-3d mac addr = "QDF_MAC_ADDR_FMT, wlan_roam_debug_string(dbg_rec->operation), - (int8_t)dbg_rec->vdev_id, dbg_rec->mac_addr.bytes); + (int8_t)dbg_rec->vdev_id, + QDF_MAC_ADDR_REF(dbg_rec->mac_addr.bytes)); roam_debug("peer obj = 0x%pK peer_id = %-4d", dbg_rec->peer_obj, (int8_t)dbg_rec->peer_id); roam_debug("arg1 = 0x%-8x arg2 = 0x%-8x", dbg_rec->arg1, diff --git a/drivers/staging/qca-wifi-host-cmn/utils/nlink/inc/wlan_nlink_common.h b/drivers/staging/qca-wifi-host-cmn/utils/nlink/inc/wlan_nlink_common.h index 6b43052389f1b5c1e008b5c6010276da448fb9d7..2ca6f2b0fb9a39c830962357736e75a40e7a383d 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/nlink/inc/wlan_nlink_common.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/nlink/inc/wlan_nlink_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2019 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 @@ -94,7 +94,7 @@ typedef enum eAniNlModuleTypes { ANI_NL_MSG_PUMAC = ANI_NL_MSG_BASE + 0x01, /* PTT Socket App */ ANI_NL_MSG_PTT = ANI_NL_MSG_BASE + 0x07, /* Quarky GUI */ WLAN_NL_MSG_OEM = ANI_NL_MSG_BASE + 0x09, - WLAN_NL_MSG_SVC, + WLAN_NL_MSG_SVC = ANI_NL_MSG_BASE + 0x0a, WLAN_NL_MSG_CNSS_DIAG = ANI_NL_MSG_BASE + 0x0B, /* Value needs to be 27 */ ANI_NL_MSG_LOG, WLAN_NL_MSG_SPECTRAL_SCAN, diff --git a/drivers/staging/qca-wifi-host-cmn/utils/nlink/inc/wlan_nlink_srv.h b/drivers/staging/qca-wifi-host-cmn/utils/nlink/inc/wlan_nlink_srv.h index 53c2d6e283382b61d98f9460ee187fdd3ea1ed59..c66b06b534566a422c908e4b7a214a5150b945b1 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/nlink/inc/wlan_nlink_srv.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/nlink/inc/wlan_nlink_srv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, 2019-2020 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 @@ -40,7 +40,36 @@ typedef int (*nl_srv_msg_callback)(struct sk_buff *skb); -int nl_srv_init(void *wiphy); +/** + * cld80211_oem_send_reply() - API to send cld80211 msg + * @skb: Sk buffer + * @hdr: nl80211hdr pointer + * @nest: pointer of vendor nested attribute + * @flags: Flags + * + * API to send cld80211 msg to applications + * + * Return: None + */ +void cld80211_oem_send_reply(struct sk_buff *msg, void *hdr, + struct nlattr *nest, int flags); + +/** + * nl80211hdr_put() - API to allocate skb for cld80211 msg + * @hdr: nl80211hdr pointer + * @portid: Port ID + * @nest: pointer of vendor nested attribute + * @flags: Flags + * + * API to allocate skb for cld80211 msg + * + * Return: Pointer to skbuff + */ + +struct sk_buff * +cld80211_oem_rsp_alloc_skb(uint32_t portid, void **hdr, struct nlattr **nest, + int *flags); +int nl_srv_init(void *wiphy, int proto); void nl_srv_exit(void); int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler); int nl_srv_unregister(tWlanNlModTypes msg_type, @@ -50,6 +79,21 @@ int nl_srv_unregister(tWlanNlModTypes msg_type, int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag, int app_id, int mcgroup_id); int nl_srv_bcast(struct sk_buff *skb, int mcgroup_id, int app_id); + +/** + * nl80211hdr_put() - API to fill genlmsg header + * @skb: Sk buffer + * @portid: Port ID + * @seq: Sequence number + * @flags: Flags + * @cmd: Command id + * + * API to fill genl message header for brodcast events to user space + * + * Return: Pointer to user specific header/payload + */ +void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid, + uint32_t seq, int flags, uint8_t cmd); #else int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag); int nl_srv_bcast(struct sk_buff *skb); diff --git a/drivers/staging/qca-wifi-host-cmn/utils/nlink/src/wlan_nlink_srv.c b/drivers/staging/qca-wifi-host-cmn/utils/nlink/src/wlan_nlink_srv.c index 171d599e10f0867a9b629b403b7e6e1150ad03f2..d0b79feb060bba5320ff8c7efcb88018b4296ba0 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/nlink/src/wlan_nlink_srv.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/nlink/src/wlan_nlink_srv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 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 @@ -48,6 +48,7 @@ static bool logger_initialized; /** * nl_srv_init() - wrapper function to register to cnss_logger * @wiphy: the pointer to the wiphy structure + * @proto: the host log netlink protocol * * The netlink socket is no longer initialized in the driver itself, instead * will be initialized in the cnss_logger module, the driver should register @@ -60,7 +61,7 @@ static bool logger_initialized; * * Return: radio index for success and -EINVAL for failure */ -int nl_srv_init(void *wiphy) +int nl_srv_init(void *wiphy, int proto) { if (logger_initialized) goto initialized; @@ -266,8 +267,56 @@ qdf_export_symbol(nl_srv_is_initialized); #include #include +void cld80211_oem_send_reply(struct sk_buff *msg, void *hdr, + struct nlattr *nest, int flags) +{ + struct genl_family *cld80211_fam = cld80211_get_genl_family(); + + nla_nest_end(msg, nest); + genlmsg_end(msg, hdr); + + genlmsg_multicast_netns(cld80211_fam, &init_net, msg, 0, + CLD80211_MCGRP_OEM_MSGS, flags); +} + +struct sk_buff * +cld80211_oem_rsp_alloc_skb(uint32_t portid, void **hdr, struct nlattr **nest, + int *flags) +{ + struct sk_buff *msg; + + if (in_interrupt() || irqs_disabled() || in_atomic()) + *flags = GFP_ATOMIC; + + msg = nlmsg_new(WLAN_CLD80211_MAX_SIZE, *flags); + if (!msg) { + QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, + "nlmsg malloc fails"); + return NULL; + } + + *hdr = nl80211hdr_put(msg, portid, 0, *flags, WLAN_NL_MSG_OEM); + if (*hdr == NULL) { + QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, + "nl80211 hdr put failed"); + goto nla_put_failure; + } + + *nest = nla_nest_start(msg, CLD80211_ATTR_VENDOR_DATA); + if (*nest == NULL) { + QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, + "nla_nest_start failed"); + goto nla_put_failure; + } + return msg; +nla_put_failure: + genlmsg_cancel(msg, *hdr); + nlmsg_free(msg); + return NULL; +} + /* For CNSS_GENL netlink sockets will be initialized by CNSS Kernel Module */ -int nl_srv_init(void *wiphy) +int nl_srv_init(void *wiphy, int proto) { return 0; } @@ -292,21 +341,8 @@ int nl_srv_unregister(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler) return 0; } - -/** - * nl80211hdr_put() - API to fill genlmsg header - * @skb: Sk buffer - * @portid: Port ID - * @seq: Sequence number - * @flags: Flags - * @cmd: Command id - * - * API to fill genl message header for brodcast events to user space - * - * Return: Pointer to user specific header/payload - */ -static inline void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid, - uint32_t seq, int flags, uint8_t cmd) +void *nl80211hdr_put(struct sk_buff *skb, uint32_t portid, + uint32_t seq, int flags, uint8_t cmd) { struct genl_family *cld80211_fam = cld80211_get_genl_family(); @@ -481,7 +517,7 @@ int nl_srv_ucast(struct sk_buff *skb, int dst_pid, int flag, return 0; } -#elif !defined(MULTI_IF_NAME) +#elif !defined(MULTI_IF_NAME) || defined(MULTI_IF_LOG) /* Global variables */ static DEFINE_MUTEX(nl_srv_sem); @@ -497,7 +533,7 @@ static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh); * Initialize the netlink service. * Netlink service is usable after this. */ -int nl_srv_init(void *wiphy) +int nl_srv_init(void *wiphy, int proto) { int retcode = 0; struct netlink_kernel_cfg cfg = { @@ -505,7 +541,7 @@ int nl_srv_init(void *wiphy) .input = nl_srv_rcv }; - nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_PROTO_FAMILY, + nl_srv_sock = netlink_kernel_create(&init_net, proto, &cfg); if (nl_srv_sock) { @@ -552,6 +588,8 @@ int nl_srv_register(tWlanNlModTypes msg_type, nl_srv_msg_callback msg_handler) return retcode; } +qdf_export_symbol(nl_srv_register); + /* * Unregister the message handler for a specified module. */ @@ -736,7 +774,7 @@ qdf_export_symbol(nl_srv_is_initialized); #else -int nl_srv_init(void *wiphy) +int nl_srv_init(void *wiphy, int proto) { return 0; } @@ -797,4 +835,6 @@ void nl_srv_ucast_oem(struct sk_buff *skb, int dst_pid, int flag) { nl_srv_ucast(skb, dst_pid, flag); } + +qdf_export_symbol(nl_srv_ucast_oem); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac.h b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac.h index 7dc1eaffe959aa25903b18de64dd01abab17f828..a7d46b728aec7507602c72adb9b084736b0df442 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 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 @@ -61,7 +61,15 @@ extern void pktlog_release_buf(struct hif_opaque_softc *scn); ssize_t pktlog_read_proc_entry(char *buf, size_t nbytes, loff_t *ppos, struct ath_pktlog_info *pl_info, bool *read_complete); -A_STATUS wdi_pktlog_unsubscribe(struct cdp_pdev *txrx_pdev, uint32_t log_state); + +/** + * wdi_pktlog_unsubscribe() - Unsubscribe pktlog callbacks + * @pdev_id: pdev id + * @log_state: Pktlog registration + * + * Return: zero on success, non-zero on failure + */ +A_STATUS wdi_pktlog_unsubscribe(uint8_t pdev_id, uint32_t log_state); struct ol_pl_arch_dep_funcs { void (*pktlog_init)(struct hif_opaque_softc *scn); @@ -93,6 +101,7 @@ struct pktlog_dev_t { struct ol_pl_arch_dep_funcs *pl_funcs; struct ath_pktlog_info *pl_info; ol_ath_generic_softc_handle scn; + uint8_t pdev_id; char *name; bool tgt_pktlog_alloced; bool is_pktlog_cb_subscribed; @@ -141,7 +150,17 @@ int pktlog_disable(struct hif_opaque_softc *scn); int pktlogmod_init(void *context); void pktlogmod_exit(void *context); int pktlog_htc_attach(void); -void pktlog_process_fw_msg(uint32_t *msg_word, uint32_t msg_len); + +/** + * pktlog_process_fw_msg() - process packetlog message + * @pdev_id: physical device instance id + * @msg_word: message buffer + * @msg_len: message length + * + * Return: None + */ +void pktlog_process_fw_msg(uint8_t pdev_id, uint32_t *msg_word, + uint32_t msg_len); void lit_pktlog_callback(void *context, enum WDI_EVENT event, void *log_data, u_int16_t peer_id, uint32_t status); @@ -204,7 +223,8 @@ static inline int pktlog_htc_attach(void) return 0; } -static inline void pktlog_process_fw_msg(uint32_t *msg_word, uint32_t msg_len) +static inline void pktlog_process_fw_msg(uint8_t pdev_id, uint32_t *msg_word, + uint32_t msg_len) { } #endif /* REMOVE_PKT_LOG */ #endif /* _PKTLOG_AC_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac_api.h b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac_api.h index 60226922fff6067302bbe8ebf0a056f0b9eb84eb..bc75425b93fbb2c2df8653c82fd8f2210c4f451c 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac_api.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac_api.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2012-2014, 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2016-2018, 2020 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 @@ -54,6 +55,7 @@ struct pktlog_dev_t; void pktlog_sethandle(struct pktlog_dev_t **pl_handle, hif_opaque_softc_handle scn); +void pktlog_set_pdev_id(struct pktlog_dev_t *pl_dev, uint8_t pdev_id); void *get_txrx_context(void); @@ -129,6 +131,12 @@ struct ath_pktlog_info { #endif /* _PKTLOG_INFO */ #else /* REMOVE_PKT_LOG */ typedef void *pktlog_dev_handle; +#define pktlog_set_pdev_id(pl_dev, pdev_id) \ + do { \ + (void)pl_dev; \ + (void)pdev_id; \ + } while (0) + #define pktlog_sethandle(pl_handle, scn) \ do { \ (void)pl_handle; \ diff --git a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac_i.h b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac_i.h index 2ca00ddf260e2b992abb97af6f139ce3334d9684..5f7d9beba2ff32c6abc0b25d305f0ee4c0780334 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac_i.h +++ b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_ac_i.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 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,6 +25,7 @@ #include +#define PKTLOG_TAG "ATH_PKTLOG" #define PKTLOG_DEFAULT_BUFSIZE (10 * 1024 * 1024) /* 10MB */ #define PKTLOG_DEFAULT_SACK_THR 3 #define PKTLOG_DEFAULT_TAIL_LENGTH 100 @@ -59,14 +60,72 @@ char *pktlog_getbuf(struct pktlog_dev_t *pl_dev, struct ath_pktlog_info *pl_info, size_t log_size, struct ath_pktlog_hdr *pl_hdr); -A_STATUS process_tx_info(struct cdp_pdev *pdev, void *data); -A_STATUS process_rx_info(void *pdev, void *data); -A_STATUS process_rx_info_remote(void *pdev, void *data); -A_STATUS process_rate_find(void *pdev, void *data); -A_STATUS process_rate_update(void *pdev, void *data); -A_STATUS process_sw_event(void *pdev, void *data); -int process_pktlog_lite(void *context, void *log_data, uint16_t log_type); -int process_rx_desc_remote(void *pdev, void *data); -A_STATUS process_offload_pktlog(struct cdp_pdev *pdev, void *data); +#ifdef PKTLOG_HAS_SPECIFIC_DATA +/** + * pktlog_hdr_set_specific_data() - set type specific data + * @log_hdr: pktlog header + * @type_specific_data: type specific data + * + * Return: None + */ +void +pktlog_hdr_set_specific_data(struct ath_pktlog_hdr *log_hdr, + uint32_t type_specific_data); + +/** + * pktlog_hdr_get_specific_data() - get type specific data + * @log_hdr: pktlog header + * @type_specific_data: type specific data + * + * Return: pktlog subtype + */ +uint32_t +pktlog_hdr_get_specific_data(struct ath_pktlog_hdr *log_hdr); + +/** + * pktlog_arg_set_specific_data() - set type specific data + * @log_hdr: pktlog arg + * @type_specific_data: type specific data + * + * Return: None + */ +void +pktlog_arg_set_specific_data(struct ath_pktlog_arg *plarg, + uint32_t type_specific_data); + +/** + * pktlog_arg_get_specific_data() - set type specific data + * @log_hdr: pktlog arg + * @type_specific_data: type specific data + * + * Return: pktlog subtype + */ +uint32_t +pktlog_arg_get_specific_data(struct ath_pktlog_arg *plarg); +#else +static inline void +pktlog_hdr_set_specific_data(struct ath_pktlog_hdr *log_hdr, + uint32_t type_specific_data) +{ +} + +static inline uint32_t +pktlog_hdr_get_specific_data(struct ath_pktlog_hdr *log_hdr) +{ + return 0; +} + +static inline void +pktlog_arg_set_specific_data(struct ath_pktlog_arg *plarg, + uint32_t type_specific_data) +{ +} + +static inline uint32_t +pktlog_arg_get_specific_data(struct ath_pktlog_arg *plarg) +{ + return 0; +} +#endif /* PKTLOG_HAS_SPECIFIC_DATA */ #endif /* REMOVE_PKT_LOG */ #endif diff --git a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_wifi2.h b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_wifi2.h new file mode 100644 index 0000000000000000000000000000000000000000..d24d52709539c0f2101361f1e72d3692a5911ad1 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_wifi2.h @@ -0,0 +1,164 @@ +/** + * Copyright (c) 2013-2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ol_txrx_types.h" +#include "ol_htt_tx_api.h" +#include "ol_tx_desc.h" +#include "qdf_mem.h" +#include "htt.h" +#include "htt_internal.h" +#include "pktlog_ac_i.h" +#include "wma_api.h" +#include "wlan_logging_sock_svc.h" + +#define TX_DESC_ID_LOW_MASK 0xffff +#define TX_DESC_ID_LOW_SHIFT 0 +#define TX_DESC_ID_HIGH_MASK 0xffff0000 +#define TX_DESC_ID_HIGH_SHIFT 16 + +#ifndef REMOVE_PKT_LOG +/** + * process_tx_info() - process tx pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data); + +/** + * process_rx_info_remote() - process rx pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +A_STATUS process_rx_info_remote(void *pdev, void *data); + +/** + * process_rx_info() - process rx pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +A_STATUS process_rx_info(void *pdev, void *data); + +/** + * process_rate_find() - process rate event pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +A_STATUS process_rate_find(void *pdev, void *data); + +/** + * process_rate_update() - process rate event pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +A_STATUS process_rate_update(void *pdev, void *data); + +/** + * process_sw_event() - process sw event pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +A_STATUS process_sw_event(void *pdev, void *data); +#else +static inline +A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data) +{ + return 0; +} + +static inline +A_STATUS process_rx_info_remote(void *pdev, void *data) +{ + return 0; +} + +static inline +A_STATUS process_rx_info(void *pdev, void *data) +{ + return 0; +} + +static inline +A_STATUS process_rate_find(void *pdev, void *data) +{ + return 0; +} + +static inline +A_STATUS process_rate_update(void *pdev, void *data) +{ + return 0; +} + +static inline +A_STATUS process_sw_event(void *pdev, void *data) +{ + return 0; +} +#endif /* REMOVE_PKT_LOG */ + +/** + * process_offload_pktlog_wifi3() - Process full pktlog events + * pdev: abstract pdev handle + * data: pktlog buffer + * + * Return: zero on success, non-zero on failure + */ +static inline A_STATUS +process_offload_pktlog_wifi3(struct cdp_pdev *pdev, void *data) +{ + return 0; +} + +/** + * process_rx_desc_remote_wifi3() - Process pktlog buffers received + * from monitor status ring + * @pdev: pdev handle + * @data: pktlog buffer pointer + * + * Return: 0 - success/non-zero - failure + */ +static inline int +process_rx_desc_remote_wifi3(void *pdev, void *data) +{ + return 0; +} + +/** + * process_pktlog_lite_wifi3() - Process pktlog buffers received + * from monitor status ring + * @pdev: pdev handle + * @data: pktlog buffer pointer + * + * Return: 0 - success/non-zero - failure + */ +static inline int +process_pktlog_lite_wifi3(void *context, void *log_data, + uint16_t log_type) +{ + return 0; +} diff --git a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_wifi3.h b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_wifi3.h new file mode 100644 index 0000000000000000000000000000000000000000..5ffe4f85f9c4e30f276ad3c4255a69c67556cb19 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/include/pktlog_wifi3.h @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2013-2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "pktlog_ac_i.h" +#include "wlan_logging_sock_svc.h" + +#ifndef REMOVE_PKT_LOG +/** + * process_offload_pktlog_wifi3() - Process full pktlog events + * pdev: abstract pdev handle + * data: pktlog buffer + * + * Return: zero on success, non-zero on failure + */ +A_STATUS +process_offload_pktlog_wifi3(struct cdp_pdev *pdev, void *data); + +/** + * process_rx_desc_remote_wifi3() - Process pktlog buffers received + * from monitor status ring + * @pdev: pdev handle + * @data: pktlog buffer pointer + * + * Return: 0 - success/non-zero - failure + */ +int process_rx_desc_remote_wifi3(void *pdev, void *data); + +/** + * process_pktlog_lite_wifi3() - Process pktlog buffers received + * from monitor status ring + * @pdev: pdev handle + * @data: pktlog buffer pointer + * + * Return: 0 - success/non-zero - failure + */ +int process_pktlog_lite_wifi3(void *context, void *log_data, + uint16_t log_type); +#else +static inline A_STATUS +process_offload_pktlog_wifi3(struct cdp_pdev *pdev, void *data) +{ + return 0; +} + +static inline +int process_rx_desc_remote_wifi3(void *pdev, void *data) +{ + return 0; +} + +static inline int +process_pktlog_lite_wifi3(void *context, void *log_data, + uint16_t log_type) +{ + return 0; +} +#endif /* REMOVE_PKT_LOG */ + +/** + * process_tx_info() - process tx pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +static inline +A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data) +{ + return 0; +} + +/** + * process_rx_info_remote() - process rx pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +static inline +A_STATUS process_rx_info_remote(void *pdev, void *data) +{ + return 0; +} + +/** + * process_rx_remote() - process rx pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +static inline +A_STATUS process_rx_info(void *pdev, void *data) +{ + return 0; +} + +/** + * process_rate_find() - process rate event pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +static inline +A_STATUS process_rate_find(void *pdev, void *data) +{ + return 0; +} + +/** + * process_rate_update() - process rate event pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +static inline +A_STATUS process_rate_update(void *pdev, void *data) +{ + return 0; +} + +/** + * process_sw_event() - process sw event pktlog buffers + * @txrx_pdev: ol pdev handle + * @data: pktlog buffer + * + * Return: 0 - success/non-zero - failure + */ +static inline +A_STATUS process_sw_event(void *pdev, void *data) +{ + return 0; +} diff --git a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/linux_ac.c b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/linux_ac.c index 269bdaef34342d5fd1877758c17dbac560c59a77..5fe1391612753f13fb9e6eb4452d70cb38489087 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/linux_ac.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/linux_ac.c @@ -37,7 +37,6 @@ #include "host_diag_core_log.h" #include "ani_global.h" -#define PKTLOG_TAG "ATH_PKTLOG" #define PKTLOG_DEVNAME_SIZE 32 #define MAX_WLANDEV 1 @@ -55,7 +54,7 @@ #ifndef __MOD_INC_USE_COUNT #define PKTLOG_MOD_INC_USE_COUNT do { \ if (!try_module_get(THIS_MODULE)) { \ - printk(KERN_WARNING "try_module_get failed\n"); \ + qdf_nofl_info("try_module_get failed"); \ } } while (0) #define PKTLOG_MOD_DEC_USE_COUNT module_put(THIS_MODULE) @@ -102,9 +101,8 @@ int pktlog_alloc_buf(struct hif_opaque_softc *scn) pl_dev = get_pktlog_handle(); if (!pl_dev) { - printk(PKTLOG_TAG - "%s: Unable to allocate buffer pdev_txrx_handle or pdev_txrx_handle->pl_dev is null\n", - __func__); + qdf_nofl_info(PKTLOG_TAG + "%s: pdev_txrx_handle->pl_dev is null", __func__); return -EINVAL; } @@ -115,16 +113,13 @@ int pktlog_alloc_buf(struct hif_opaque_softc *scn) qdf_spin_lock_bh(&pl_info->log_lock); if (pl_info->buf) { qdf_spin_unlock_bh(&pl_info->log_lock); - printk(PKTLOG_TAG "Buffer is already in use\n"); + qdf_nofl_info(PKTLOG_TAG "Buffer is already in use"); return -EINVAL; } qdf_spin_unlock_bh(&pl_info->log_lock); buffer = vmalloc((page_cnt + 2) * PAGE_SIZE); if (!buffer) { - printk(PKTLOG_TAG - "%s: Unable to allocate buffer " - "(%d pages)\n", __func__, page_cnt); return -ENOMEM; } @@ -204,7 +199,7 @@ qdf_sysctl_decl(ath_sysctl_pktlog_enable, ctl, write, filp, buffer, lenp, ppos) if (!scn) { mutex_unlock(&proc_mutex); - printk("%s: Invalid scn context\n", __func__); + qdf_nofl_info("%s: Invalid scn context", __func__); ASSERT(0); return -EINVAL; } @@ -213,7 +208,7 @@ qdf_sysctl_decl(ath_sysctl_pktlog_enable, ctl, write, filp, buffer, lenp, ppos) if (!pl_dev) { mutex_unlock(&proc_mutex); - printk("%s: Invalid pktlog context\n", __func__); + qdf_nofl_info("%s: Invalid pktlog context", __func__); ASSERT(0); return -ENODEV; } @@ -267,7 +262,7 @@ qdf_sysctl_decl(ath_sysctl_pktlog_size, ctl, write, filp, buffer, lenp, ppos) if (!scn) { mutex_unlock(&proc_mutex); - printk("%s: Invalid scn context\n", __func__); + qdf_nofl_info("%s: Invalid scn context", __func__); ASSERT(0); return -EINVAL; } @@ -276,7 +271,7 @@ qdf_sysctl_decl(ath_sysctl_pktlog_size, ctl, write, filp, buffer, lenp, ppos) if (!pl_dev) { mutex_unlock(&proc_mutex); - printk("%s: Invalid pktlog handle\n", __func__); + qdf_nofl_info("%s: Invalid pktlog handle", __func__); ASSERT(0); return -ENODEV; } @@ -397,7 +392,7 @@ static int pktlog_sysctl_register(struct hif_opaque_softc *scn) register_sysctl_table(pl_info_lnx->sysctls); if (!pl_info_lnx->sysctl_header) { - printk("%s: failed to register sysctls!\n", proc_name); + qdf_nofl_info("%s: failed to register sysctls!", proc_name); return -EINVAL; } @@ -455,16 +450,16 @@ static int pktlog_attach(struct hif_opaque_softc *scn) &pl_info_lnx->info); if (!proc_entry) { - printk(PKTLOG_TAG "%s: create_proc_entry failed for %s\n", - __func__, proc_name); + qdf_nofl_info(PKTLOG_TAG "%s: create_proc_entry failed for %s", + __func__, proc_name); goto attach_fail1; } pl_info_lnx->proc_entry = proc_entry; if (pktlog_sysctl_register(scn)) { - printk(PKTLOG_TAG "%s: sysctl register failed for %s\n", - __func__, proc_name); + qdf_nofl_info(PKTLOG_TAG "%s: sysctl register failed for %s", + __func__, proc_name); goto attach_fail2; } @@ -485,7 +480,7 @@ static void pktlog_sysctl_unregister(struct pktlog_dev_t *pl_dev) struct ath_pktlog_info_lnx *pl_info_lnx; if (!pl_dev) { - printk("%s: Invalid pktlog context\n", __func__); + qdf_nofl_info("%s: Invalid pktlog context", __func__); ASSERT(0); return; } @@ -505,7 +500,7 @@ static void pktlog_detach(struct hif_opaque_softc *scn) struct pktlog_dev_t *pl_dev = get_pktlog_handle(); if (!pl_dev) { - printk("%s: Invalid pktlog context\n", __func__); + qdf_nofl_info("%s: Invalid pktlog context", __func__); ASSERT(0); return; } @@ -1042,7 +1037,7 @@ int pktlogmod_init(void *context) g_pktlog_pde = proc_mkdir(PKTLOG_PROC_DIR, NULL); if (!g_pktlog_pde) { - printk(PKTLOG_TAG "%s: proc_mkdir failed\n", __func__); + qdf_nofl_info(PKTLOG_TAG "%s: proc_mkdir failed", __func__); return -EPERM; } diff --git a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_ac.c b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_ac.c index c1537a265a6bb7e74df4e9f2834ae22387f5b640..a7a0583e2217e71271e7f7321de7f2f6384ba6be 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_ac.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_ac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 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,6 +41,11 @@ #include "htc.h" #include #include +#ifdef PKTLOG_LEGACY +#include "pktlog_wifi2.h" +#else +#include "pktlog_wifi3.h" +#endif /* PKTLOG_LEGACY */ wdi_event_subscribe PKTLOG_TX_SUBSCRIBER; wdi_event_subscribe PKTLOG_RX_SUBSCRIBER; @@ -70,6 +75,11 @@ void pktlog_sethandle(struct pktlog_dev_t **pl_handle, *pl_handle = &pl_dev; } +void pktlog_set_pdev_id(struct pktlog_dev_t *pl_dev, uint8_t pdev_id) +{ + pl_dev->pdev_id = pdev_id; +} + void pktlog_set_callback_regtype( enum pktlog_callback_regtype callback_type) { @@ -85,19 +95,10 @@ void pktlog_set_callback_regtype( struct pktlog_dev_t *get_pktlog_handle(void) { - struct cdp_pdev *pdev_txrx_handle = - cds_get_context(QDF_MODULE_ID_TXRX); + uint8_t pdev_id = WMI_PDEV_ID_SOC; void *soc = cds_get_context(QDF_MODULE_ID_SOC); - return cdp_get_pldev(soc, pdev_txrx_handle); -} - -/* - * Get current txrx context - */ -void *get_txrx_context(void) -{ - return cds_get_context(QDF_MODULE_ID_TXRX); + return cdp_get_pldev(soc, pdev_id); } static A_STATUS pktlog_wma_post_msg(WMI_PKTLOG_EVENT event_types, @@ -165,56 +166,56 @@ pktlog_enable_tgt(struct hif_opaque_softc *_scn, uint32_t log_state, #ifdef PKTLOG_LEGACY /** * wdi_pktlog_subscribe() - Subscribe pktlog callbacks - * @cdp_pdev: abstract pdev handle + * @pdev_id: pdev id * @log_state: Pktlog registration * * Return: zero on success, non-zero on failure */ static inline A_STATUS -wdi_pktlog_subscribe(struct cdp_pdev *cdp_pdev, int32_t log_state) +wdi_pktlog_subscribe(uint8_t pdev_id, int32_t log_state) { void *soc = cds_get_context(QDF_MODULE_ID_SOC); - if (!cdp_pdev) { + if (pdev_id < 0) { qdf_print("Invalid pdev in %s", __func__); return A_ERROR; } if (log_state & ATH_PKTLOG_TX) { - if (cdp_wdi_event_sub(soc, cdp_pdev, &PKTLOG_TX_SUBSCRIBER, - WDI_EVENT_TX_STATUS)) { + if (cdp_wdi_event_sub(soc, pdev_id, &PKTLOG_TX_SUBSCRIBER, + WDI_EVENT_TX_STATUS)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_RX) { - if (cdp_wdi_event_sub(soc, cdp_pdev, &PKTLOG_RX_SUBSCRIBER, - WDI_EVENT_RX_DESC)) { + if (cdp_wdi_event_sub(soc, pdev_id, &PKTLOG_RX_SUBSCRIBER, + WDI_EVENT_RX_DESC)) { return A_ERROR; } - if (cdp_wdi_event_sub(soc, cdp_pdev, - &PKTLOG_RX_REMOTE_SUBSCRIBER, - WDI_EVENT_RX_DESC_REMOTE)) { + if (cdp_wdi_event_sub(soc, pdev_id, + &PKTLOG_RX_REMOTE_SUBSCRIBER, + WDI_EVENT_RX_DESC_REMOTE)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_RCFIND) { - if (cdp_wdi_event_sub(soc, cdp_pdev, - &PKTLOG_RCFIND_SUBSCRIBER, - WDI_EVENT_RATE_FIND)) { + if (cdp_wdi_event_sub(soc, pdev_id, + &PKTLOG_RCFIND_SUBSCRIBER, + WDI_EVENT_RATE_FIND)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_RCUPDATE) { - if (cdp_wdi_event_sub(soc, cdp_pdev, - &PKTLOG_RCUPDATE_SUBSCRIBER, - WDI_EVENT_RATE_UPDATE)) { + if (cdp_wdi_event_sub(soc, pdev_id, + &PKTLOG_RCUPDATE_SUBSCRIBER, + WDI_EVENT_RATE_UPDATE)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_SW_EVENT) { - if (cdp_wdi_event_sub(soc, cdp_pdev, - &PKTLOG_SW_EVENT_SUBSCRIBER, - WDI_EVENT_SW_EVENT)) { + if (cdp_wdi_event_sub(soc, pdev_id, + &PKTLOG_SW_EVENT_SUBSCRIBER, + WDI_EVENT_SW_EVENT)) { return A_ERROR; } } @@ -223,11 +224,11 @@ wdi_pktlog_subscribe(struct cdp_pdev *cdp_pdev, int32_t log_state) } #else static inline A_STATUS -wdi_pktlog_subscribe(struct cdp_pdev *cdp_pdev, int32_t log_state) +wdi_pktlog_subscribe(uint8_t pdev_id, int32_t log_state) { void *soc = cds_get_context(QDF_MODULE_ID_SOC); - if (!cdp_pdev) { + if (pdev_id < 0) { qdf_print("Invalid pdev in %s", __func__); return A_ERROR; } @@ -237,7 +238,7 @@ wdi_pktlog_subscribe(struct cdp_pdev *cdp_pdev, int32_t log_state) (log_state & ATH_PKTLOG_RCUPDATE) || (log_state & ATH_PKTLOG_SW_EVENT)) { if (cdp_wdi_event_sub(soc, - cdp_pdev, + pdev_id, &PKTLOG_OFFLOAD_SUBSCRIBER, WDI_EVENT_OFFLOAD_ALL)) { return A_ERROR; @@ -245,15 +246,15 @@ wdi_pktlog_subscribe(struct cdp_pdev *cdp_pdev, int32_t log_state) } if (log_state & ATH_PKTLOG_RX) { - if (cdp_wdi_event_sub(soc, cdp_pdev, - &PKTLOG_RX_SUBSCRIBER, - WDI_EVENT_RX_DESC)) { + if (cdp_wdi_event_sub(soc, pdev_id, + &PKTLOG_RX_SUBSCRIBER, + WDI_EVENT_RX_DESC)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_SW_EVENT) { - if (cdp_wdi_event_sub(soc, cdp_pdev, + if (cdp_wdi_event_sub(soc, pdev_id, &PKTLOG_SW_EVENT_SUBSCRIBER, WDI_EVENT_SW_EVENT)) { return A_ERROR; @@ -261,7 +262,7 @@ wdi_pktlog_subscribe(struct cdp_pdev *cdp_pdev, int32_t log_state) } if (log_state & ATH_PKTLOG_LITE_T2H) { - if (cdp_wdi_event_sub(soc, cdp_pdev, + if (cdp_wdi_event_sub(soc, pdev_id, &PKTLOG_LITE_T2H_SUBSCRIBER, WDI_EVENT_LITE_T2H)) { return A_ERROR; @@ -269,7 +270,7 @@ wdi_pktlog_subscribe(struct cdp_pdev *cdp_pdev, int32_t log_state) } if (log_state & ATH_PKTLOG_LITE_RX) { - if (cdp_wdi_event_sub(soc, cdp_pdev, + if (cdp_wdi_event_sub(soc, pdev_id, &PKTLOG_LITE_RX_SUBSCRIBER, WDI_EVENT_LITE_RX)) { return A_ERROR; @@ -286,7 +287,7 @@ void pktlog_callback(void *pdev, enum WDI_EVENT event, void *log_data, switch (event) { case WDI_EVENT_OFFLOAD_ALL: { - if (process_offload_pktlog(pdev, log_data)) { + if (process_offload_pktlog_wifi3(pdev, log_data)) { qdf_print("Unable to process offload info"); return; } @@ -370,7 +371,7 @@ lit_pktlog_callback(void *context, enum WDI_EVENT event, void *log_data, switch (event) { case WDI_EVENT_RX_DESC: { - if (process_rx_desc_remote(context, log_data)) { + if (process_rx_desc_remote_wifi3(context, log_data)) { qdf_print("Unable to process RX info"); return; } @@ -378,8 +379,8 @@ lit_pktlog_callback(void *context, enum WDI_EVENT event, void *log_data, } case WDI_EVENT_LITE_T2H: { - if (process_pktlog_lite(context, log_data, - PKTLOG_TYPE_LITE_T2H)) { + if (process_pktlog_lite_wifi3(context, log_data, + PKTLOG_TYPE_LITE_T2H)) { qdf_print("Unable to process lite_t2h"); return; } @@ -387,8 +388,8 @@ lit_pktlog_callback(void *context, enum WDI_EVENT event, void *log_data, } case WDI_EVENT_LITE_RX: { - if (process_pktlog_lite(context, log_data, - PKTLOG_TYPE_LITE_RX)) { + if (process_pktlog_lite_wifi3(context, log_data, + PKTLOG_TYPE_LITE_RX)) { qdf_print("Unable to process lite_rx"); return; } @@ -400,56 +401,50 @@ lit_pktlog_callback(void *context, enum WDI_EVENT event, void *log_data, } #ifdef PKTLOG_LEGACY -/** - * wdi_pktlog_unsubscribe() - Unsubscribe pktlog callbacks - * @cdp_pdev: abstract pdev handle - * @log_state: Pktlog registration - * - * Return: zero on success, non-zero on failure - */ A_STATUS -wdi_pktlog_unsubscribe(struct cdp_pdev *pdev, uint32_t log_state) +wdi_pktlog_unsubscribe(uint8_t pdev_id, uint32_t log_state) { void *soc = cds_get_context(QDF_MODULE_ID_SOC); /* TODO: WIN implementation to get soc */ if (log_state & ATH_PKTLOG_TX) { - if (cdp_wdi_event_unsub(soc, pdev, - &PKTLOG_TX_SUBSCRIBER, - WDI_EVENT_TX_STATUS)) { + if (cdp_wdi_event_unsub(soc, pdev_id, + &PKTLOG_TX_SUBSCRIBER, + WDI_EVENT_TX_STATUS)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_RX) { - if (cdp_wdi_event_unsub(soc, pdev, - &PKTLOG_RX_SUBSCRIBER, WDI_EVENT_RX_DESC)) { + if (cdp_wdi_event_unsub(soc, pdev_id, + &PKTLOG_RX_SUBSCRIBER, + WDI_EVENT_RX_DESC)) { return A_ERROR; } - if (cdp_wdi_event_unsub(soc, pdev, - &PKTLOG_RX_REMOTE_SUBSCRIBER, - WDI_EVENT_RX_DESC_REMOTE)) { + if (cdp_wdi_event_unsub(soc, pdev_id, + &PKTLOG_RX_REMOTE_SUBSCRIBER, + WDI_EVENT_RX_DESC_REMOTE)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_RCFIND) { - if (cdp_wdi_event_unsub(soc, pdev, - &PKTLOG_RCFIND_SUBSCRIBER, - WDI_EVENT_RATE_FIND)) { + if (cdp_wdi_event_unsub(soc, pdev_id, + &PKTLOG_RCFIND_SUBSCRIBER, + WDI_EVENT_RATE_FIND)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_RCUPDATE) { - if (cdp_wdi_event_unsub(soc, pdev, - &PKTLOG_RCUPDATE_SUBSCRIBER, - WDI_EVENT_RATE_UPDATE)) { + if (cdp_wdi_event_unsub(soc, pdev_id, + &PKTLOG_RCUPDATE_SUBSCRIBER, + WDI_EVENT_RATE_UPDATE)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_RCUPDATE) { - if (cdp_wdi_event_unsub(soc, pdev, - &PKTLOG_SW_EVENT_SUBSCRIBER, - WDI_EVENT_SW_EVENT)) { + if (cdp_wdi_event_unsub(soc, pdev_id, + &PKTLOG_SW_EVENT_SUBSCRIBER, + WDI_EVENT_SW_EVENT)) { return A_ERROR; } } @@ -458,7 +453,7 @@ wdi_pktlog_unsubscribe(struct cdp_pdev *pdev, uint32_t log_state) } #else A_STATUS -wdi_pktlog_unsubscribe(struct cdp_pdev *pdev, uint32_t log_state) +wdi_pktlog_unsubscribe(uint8_t pdev_id, uint32_t log_state) { void *soc = cds_get_context(QDF_MODULE_ID_SOC); @@ -467,28 +462,28 @@ wdi_pktlog_unsubscribe(struct cdp_pdev *pdev, uint32_t log_state) (log_state & ATH_PKTLOG_RCUPDATE) || (log_state & ATH_PKTLOG_SW_EVENT)) { if (cdp_wdi_event_unsub(soc, - pdev, + pdev_id, &PKTLOG_OFFLOAD_SUBSCRIBER, WDI_EVENT_OFFLOAD_ALL)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_RX) { - if (cdp_wdi_event_unsub(soc, pdev, + if (cdp_wdi_event_unsub(soc, pdev_id, &PKTLOG_RX_SUBSCRIBER, WDI_EVENT_RX_DESC)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_LITE_T2H) { - if (cdp_wdi_event_unsub(soc, pdev, + if (cdp_wdi_event_unsub(soc, pdev_id, &PKTLOG_LITE_T2H_SUBSCRIBER, WDI_EVENT_LITE_T2H)) { return A_ERROR; } } if (log_state & ATH_PKTLOG_LITE_RX) { - if (cdp_wdi_event_unsub(soc, pdev, + if (cdp_wdi_event_unsub(soc, pdev_id, &PKTLOG_LITE_RX_SUBSCRIBER, WDI_EVENT_LITE_RX)) { return A_ERROR; @@ -504,7 +499,7 @@ int pktlog_disable(struct hif_opaque_softc *scn) struct pktlog_dev_t *pl_dev; struct ath_pktlog_info *pl_info; uint8_t save_pktlog_state; - struct cdp_pdev *txrx_pdev = get_txrx_context(); + uint8_t pdev_id = WMI_PDEV_ID_SOC; pl_dev = get_pktlog_handle(); @@ -520,8 +515,8 @@ int pktlog_disable(struct hif_opaque_softc *scn) return -EINVAL; } - if (!txrx_pdev) { - qdf_print("Invalid cdp_pdev"); + if (pdev_id < 0) { + qdf_print("Invalid pdev"); return -EINVAL; } @@ -543,7 +538,7 @@ int pktlog_disable(struct hif_opaque_softc *scn) } if (pl_dev->is_pktlog_cb_subscribed && - wdi_pktlog_unsubscribe(txrx_pdev, pl_info->log_state)) { + wdi_pktlog_unsubscribe(pdev_id, pl_info->log_state)) { pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS; qdf_print("Cannot unsubscribe pktlog from the WDI"); return -EINVAL; @@ -637,7 +632,7 @@ int __pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state, { struct pktlog_dev_t *pl_dev; struct ath_pktlog_info *pl_info; - struct cdp_pdev *cdp_pdev; + uint8_t pdev_id; int error; if (!scn) { @@ -653,8 +648,8 @@ int __pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state, return -EINVAL; } - cdp_pdev = get_txrx_context(); - if (!cdp_pdev) { + pdev_id = WMI_PDEV_ID_SOC; + if (pdev_id < 0) { qdf_print("%s: Invalid txrx context", __func__); ASSERT(0); return -EINVAL; @@ -725,7 +720,7 @@ int __pktlog_enable(struct hif_opaque_softc *scn, int32_t log_state, if (log_state != 0) { /* WDI subscribe */ if (!pl_dev->is_pktlog_cb_subscribed) { - error = wdi_pktlog_subscribe(cdp_pdev, log_state); + error = wdi_pktlog_subscribe(pdev_id, log_state); if (error) { pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS; @@ -795,7 +790,7 @@ static int __pktlog_setsize(struct hif_opaque_softc *scn, int32_t size) { struct pktlog_dev_t *pl_dev; struct ath_pktlog_info *pl_info; - struct cdp_pdev *pdev; + uint8_t pdev_id = WMI_PDEV_ID_SOC; void *soc = cds_get_context(QDF_MODULE_ID_SOC); uint32_t buff_size; uint32_t max_allowed_buff_size; @@ -814,10 +809,8 @@ static int __pktlog_setsize(struct hif_opaque_softc *scn, int32_t size) return -EINVAL; } - pdev = get_txrx_context(); - - if (!pdev) { - qdf_print("%s: invalid pdev handle", __func__); + if (pdev_id < 0) { + qdf_print("%s: invalid pdev", __func__); return -EINVAL; } @@ -857,7 +850,7 @@ static int __pktlog_setsize(struct hif_opaque_softc *scn, int32_t size) qdf_spin_lock_bh(&pl_info->log_lock); if (pl_info->buf) { if (pl_dev->is_pktlog_cb_subscribed && - wdi_pktlog_unsubscribe(pdev, pl_info->log_state)) { + wdi_pktlog_unsubscribe(pdev_id, pl_info->log_state)) { pl_info->curr_pkt_state = PKTLOG_OPR_NOT_IN_PROGRESS; qdf_spin_unlock_bh(&pl_info->log_lock); @@ -972,21 +965,14 @@ int pktlog_clearbuff(struct hif_opaque_softc *scn, bool clear_buff) return 0; } -/** - * pktlog_process_fw_msg() - process packetlog message - * @buff: buffer - * - * Return: None - */ -void pktlog_process_fw_msg(uint32_t *buff, uint32_t len) +void pktlog_process_fw_msg(uint8_t pdev_id, uint32_t *buff, uint32_t len) { uint32_t *pl_hdr; uint32_t log_type; - struct cdp_pdev *pdev = get_txrx_context(); struct ol_fw_data pl_fw_data; - if (!pdev) { - qdf_print("%s: txrx_pdev is NULL", __func__); + if (pdev_id == OL_TXRX_INVALID_PDEV_ID) { + qdf_print("%s: txrx pdev_id is invalid", __func__); return; } pl_hdr = buff; @@ -1003,19 +989,19 @@ void pktlog_process_fw_msg(uint32_t *buff, uint32_t len) || (log_type == PKTLOG_TYPE_TX_FRM_HDR) || (log_type == PKTLOG_TYPE_TX_VIRT_ADDR)) wdi_event_handler(WDI_EVENT_TX_STATUS, - pdev, &pl_fw_data); + pdev_id, &pl_fw_data); else if (log_type == PKTLOG_TYPE_RC_FIND) wdi_event_handler(WDI_EVENT_RATE_FIND, - pdev, &pl_fw_data); + pdev_id, &pl_fw_data); else if (log_type == PKTLOG_TYPE_RC_UPDATE) wdi_event_handler(WDI_EVENT_RATE_UPDATE, - pdev, &pl_fw_data); + pdev_id, &pl_fw_data); else if (log_type == PKTLOG_TYPE_RX_STAT) wdi_event_handler(WDI_EVENT_RX_DESC, - pdev, &pl_fw_data); + pdev_id, &pl_fw_data); else if (log_type == PKTLOG_TYPE_SW_EVENT) wdi_event_handler(WDI_EVENT_SW_EVENT, - pdev, &pl_fw_data); + pdev_id, &pl_fw_data); } #if defined(QCA_WIFI_3_0_ADRASTEA) @@ -1066,7 +1052,7 @@ static void pktlog_t2h_msg_handler(void *context, HTC_PACKET *pkt) msg_word = (uint32_t *) qdf_nbuf_data(pktlog_t2h_msg); msg_len = qdf_nbuf_len(pktlog_t2h_msg); - pktlog_process_fw_msg(msg_word, msg_len); + pktlog_process_fw_msg(pdev->pdev_id, msg_word, msg_len); qdf_nbuf_free(pktlog_t2h_msg); } diff --git a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_internal.c b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_internal.c index dae0059a18265dd86eccfea46ef2302420a9f090..d028931f0145ff8b84f129c86ac864063a5b7096 100644 --- a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_internal.c +++ b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_internal.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 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 @@ -42,63 +42,33 @@ #include "wma_api.h" #include "wlan_logging_sock_svc.h" -#define TX_DESC_ID_LOW_MASK 0xffff -#define TX_DESC_ID_LOW_SHIFT 0 -#define TX_DESC_ID_HIGH_MASK 0xffff0000 -#define TX_DESC_ID_HIGH_SHIFT 16 - #ifdef PKTLOG_HAS_SPECIFIC_DATA -static inline void +void pktlog_hdr_set_specific_data(struct ath_pktlog_hdr *log_hdr, uint32_t type_specific_data) { log_hdr->type_specific_data = type_specific_data; } -static inline uint32_t +uint32_t pktlog_hdr_get_specific_data(struct ath_pktlog_hdr *log_hdr) { return log_hdr->type_specific_data; } -static inline void +void pktlog_arg_set_specific_data(struct ath_pktlog_arg *plarg, uint32_t type_specific_data) { plarg->type_specific_data = type_specific_data; } -static inline uint32_t +uint32_t pktlog_arg_get_specific_data(struct ath_pktlog_arg *plarg) { return plarg->type_specific_data; } - -#else -static inline void -pktlog_hdr_set_specific_data(struct ath_pktlog_hdr *log_hdr, - uint32_t type_specific_data) -{ -} - -static inline uint32_t -pktlog_hdr_get_specific_data(struct ath_pktlog_hdr *log_hdr) -{ - return 0; -} - -static inline void -pktlog_arg_set_specific_data(struct ath_pktlog_arg *plarg, - uint32_t type_specific_data) -{ -} - -static inline uint32_t -pktlog_arg_get_specific_data(struct ath_pktlog_arg *plarg) -{ - return 0; -} -#endif +#endif /* PKTLOG_HAS_SPECIFIC_DATA */ void pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg) { @@ -116,7 +86,7 @@ void pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg) #endif if (!plarg) { - printk("Invalid parg in %s\n", __func__); + qdf_nofl_info("Invalid parg in %s", __func__); return; } @@ -132,7 +102,7 @@ void pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg) flags = plarg->flags; if (!log_buf) { - printk("Invalid log_buf in %s\n", __func__); + qdf_nofl_info("Invalid log_buf in %s", __func__); return; } @@ -226,1340 +196,4 @@ char *pktlog_getbuf(struct pktlog_dev_t *pl_dev, return plarg.buf; } - -static struct txctl_frm_hdr frm_hdr; - -#ifndef HELIUMPLUS -static void process_ieee_hdr(void *data) -{ - uint8_t dir; - struct ieee80211_frame *wh = (struct ieee80211_frame *)(data); - - frm_hdr.framectrl = *(uint16_t *) (wh->i_fc); - frm_hdr.seqctrl = *(uint16_t *) (wh->i_seq); - dir = (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK); - - if (dir == IEEE80211_FC1_DIR_TODS) { - frm_hdr.bssid_tail = - (wh->i_addr1[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> - i_addr1 - [QDF_MAC_ADDR_SIZE - - 1]); - frm_hdr.sa_tail = - (wh->i_addr2[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> - i_addr2 - [QDF_MAC_ADDR_SIZE - - 1]); - frm_hdr.da_tail = - (wh->i_addr3[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> - i_addr3 - [QDF_MAC_ADDR_SIZE - - 1]); - } else if (dir == IEEE80211_FC1_DIR_FROMDS) { - frm_hdr.bssid_tail = - (wh->i_addr2[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> - i_addr2 - [QDF_MAC_ADDR_SIZE - - 1]); - frm_hdr.sa_tail = - (wh->i_addr3[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> - i_addr3 - [QDF_MAC_ADDR_SIZE - - 1]); - frm_hdr.da_tail = - (wh->i_addr1[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> - i_addr1 - [QDF_MAC_ADDR_SIZE - - 1]); - } else { - frm_hdr.bssid_tail = - (wh->i_addr3[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> - i_addr3 - [QDF_MAC_ADDR_SIZE - - 1]); - frm_hdr.sa_tail = - (wh->i_addr2[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> - i_addr2 - [QDF_MAC_ADDR_SIZE - - 1]); - frm_hdr.da_tail = - (wh->i_addr1[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> - i_addr1 - [QDF_MAC_ADDR_SIZE - - 1]); - } -} - -/** - * fill_ieee80211_hdr_data() - fill ieee802.11 data header - * @txrx_pdev: txrx pdev - * @pl_msdu_info: msdu info - * @data: data received from event - * - * Return: none - */ -/* TODO: Platform specific function */ -static void -fill_ieee80211_hdr_data(struct cdp_pdev *pdev, - struct ath_pktlog_msdu_info *pl_msdu_info, void *data) -{ - uint32_t i; - uint32_t *htt_tx_desc; - struct ol_tx_desc_t *tx_desc; - uint8_t msdu_id_offset = MSDU_ID_INFO_ID_OFFSET; - uint16_t tx_desc_id; - uint32_t *msdu_id_info = (uint32_t *) - ((void *)data + sizeof(struct ath_pktlog_hdr)); - uint32_t *msdu_id = (uint32_t *) ((char *)msdu_id_info + - msdu_id_offset); - uint8_t *addr, *vap_addr; - uint8_t vdev_id; - qdf_nbuf_t netbuf; - uint32_t len; - struct ol_txrx_pdev_t *txrx_pdev = (struct ol_txrx_pdev_t *)pdev; - - - pl_msdu_info->num_msdu = *msdu_id_info; - pl_msdu_info->priv_size = sizeof(uint32_t) * - pl_msdu_info->num_msdu + sizeof(uint32_t); - - if (pl_msdu_info->num_msdu > MAX_PKT_INFO_MSDU_ID) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "%s: Invalid num_msdu count", - __func__); - qdf_assert(0); - return; - } - for (i = 0; i < pl_msdu_info->num_msdu; i++) { - /* - * Handle big endianness - * Increment msdu_id once after retrieving - * lower 16 bits and uppper 16 bits - */ - if (!(i % 2)) { - tx_desc_id = ((*msdu_id & TX_DESC_ID_LOW_MASK) - >> TX_DESC_ID_LOW_SHIFT); - } else { - tx_desc_id = ((*msdu_id & TX_DESC_ID_HIGH_MASK) - >> TX_DESC_ID_HIGH_SHIFT); - msdu_id += 1; - } - if (tx_desc_id >= txrx_pdev->tx_desc.pool_size) { - QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, - "%s: drop due to invalid msdu id = %x", - __func__, tx_desc_id); - return; - } - tx_desc = ol_tx_desc_find(txrx_pdev, tx_desc_id); - qdf_assert(tx_desc); - netbuf = tx_desc->netbuf; - htt_tx_desc = (uint32_t *) tx_desc->htt_tx_desc; - qdf_assert(htt_tx_desc); - - qdf_nbuf_peek_header(netbuf, &addr, &len); - - if (len < (2 * QDF_MAC_ADDR_SIZE)) { - qdf_print("TX frame does not have a valid address"); - return; - } - /* Adding header information for the TX data frames */ - vdev_id = (uint8_t) (*(htt_tx_desc + - HTT_TX_VDEV_ID_WORD) >> - HTT_TX_VDEV_ID_SHIFT) & - HTT_TX_VDEV_ID_MASK; - - vap_addr = wma_get_vdev_address_by_vdev_id(vdev_id); - - frm_hdr.da_tail = (addr[QDF_MAC_ADDR_SIZE - 2] << 8) | - (addr[QDF_MAC_ADDR_SIZE - 1]); - frm_hdr.sa_tail = - (addr[2 * QDF_MAC_ADDR_SIZE - 2] << 8) | - (addr[2 * QDF_MAC_ADDR_SIZE - 1]); - if (vap_addr) { - frm_hdr.bssid_tail = - (vap_addr[QDF_MAC_ADDR_SIZE - 2] << 8) | - (vap_addr[QDF_MAC_ADDR_SIZE - 1]); - } else { - frm_hdr.bssid_tail = 0x0000; - } - pl_msdu_info->priv.msdu_len[i] = *(htt_tx_desc + - HTT_TX_MSDU_LEN_DWORD) - & HTT_TX_MSDU_LEN_MASK; - /* - * Add more information per MSDU - * e.g., protocol information - */ - } - -} -#endif - -#ifdef HELIUMPLUS -A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data) -{ - /* - * Must include to process different types - * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR - */ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_hdr pl_hdr; - struct ath_pktlog_info *pl_info; - uint32_t *pl_tgt_hdr; - struct ol_fw_data *fw_data; - uint32_t len; - - if (!txrx_pdev) { - printk("Invalid pdev in %s\n", __func__); - return A_ERROR; - } - - if (!pl_dev) { - pr_err("Invalid pktlog handle in %s\n", __func__); - qdf_assert(pl_dev); - return A_ERROR; - } - - qdf_assert(data); - - fw_data = (struct ol_fw_data *)data; - len = fw_data->len; - if (len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { - qdf_print("Invalid msdu len in %s", __func__); - qdf_assert(0); - return A_ERROR; - } - - pl_tgt_hdr = (uint32_t *)fw_data->data; - /* - * Makes the short words (16 bits) portable b/w little endian - * and big endian - */ - pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & - ATH_PKTLOG_HDR_FLAGS_MASK) >> - ATH_PKTLOG_HDR_FLAGS_SHIFT; - pl_hdr.flags |= PKTLOG_HDR_SIZE_16; - pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & - ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> - ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; - pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & - ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & - ATH_PKTLOG_HDR_MAC_ID_MASK) >> - ATH_PKTLOG_HDR_MAC_ID_SHIFT; - pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & - ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; - pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); - pl_hdr.type_specific_data = - *(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET); - pl_info = pl_dev->pl_info; - - if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { - qdf_assert(0); - return A_ERROR; - } - - if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) { - size_t log_size = sizeof(frm_hdr) + pl_hdr.size; - void *txdesc_hdr_ctl = (void *) - pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr); - qdf_assert(txdesc_hdr_ctl); - qdf_assert(pl_hdr.size < (370 * sizeof(u_int32_t))); - - qdf_mem_copy(txdesc_hdr_ctl, &frm_hdr, sizeof(frm_hdr)); - qdf_mem_copy((char *)txdesc_hdr_ctl + sizeof(frm_hdr), - ((void *)fw_data->data + - sizeof(struct ath_pktlog_hdr)), - pl_hdr.size); - pl_hdr.size = log_size; - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, - txdesc_hdr_ctl); - } - - if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) { - struct ath_pktlog_tx_status txstat_log; - size_t log_size = pl_hdr.size; - - txstat_log.ds_status = (void *) - pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - qdf_assert(txstat_log.ds_status); - qdf_mem_copy(txstat_log.ds_status, - ((void *)fw_data->data + - sizeof(struct ath_pktlog_hdr)), - pl_hdr.size); - /* TODO: MCL specific API */ - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, - txstat_log.ds_status); - } - return A_OK; -} -#else -A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data) -{ - /* - * Must include to process different types - * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR - */ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_hdr pl_hdr; - struct ath_pktlog_info *pl_info; - uint32_t *pl_tgt_hdr; - struct ol_fw_data *fw_data; - uint32_t len; - - if (!txrx_pdev) { - qdf_print("Invalid pdev in %s", __func__); - return A_ERROR; - } - - if (!pl_dev) { - pr_err("Invalid pktlog handle in %s\n", __func__); - qdf_assert(pl_dev); - return A_ERROR; - } - - qdf_assert(data); - - fw_data = (struct ol_fw_data *)data; - len = fw_data->len; - if (len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { - qdf_print("Invalid msdu len in %s", __func__); - qdf_assert(0); - return A_ERROR; - } - - pl_tgt_hdr = (uint32_t *)fw_data->data; - /* - * Makes the short words (16 bits) portable b/w little endian - * and big endian - */ - pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & - ATH_PKTLOG_HDR_FLAGS_MASK) >> - ATH_PKTLOG_HDR_FLAGS_SHIFT; - pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & - ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> - ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; - pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & - ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & - ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; - pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); - - pktlog_hdr_set_specific_data(&pl_hdr, - *(pl_tgt_hdr + - ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET)); - - pl_info = pl_dev->pl_info; - - if (pl_hdr.log_type == PKTLOG_TYPE_TX_FRM_HDR) { - /* Valid only for the TX CTL */ - process_ieee_hdr(fw_data->data + sizeof(pl_hdr)); - } - - if (pl_hdr.log_type == PKTLOG_TYPE_TX_VIRT_ADDR) { - uint32_t desc_id = (uint32_t) *((uint32_t *)(fw_data->data + - sizeof(pl_hdr))); - uint32_t vdev_id = desc_id; - - /* if the pkt log msg is for the bcn frame the vdev id - * is piggybacked in desc_id and the MSB of the desc ID - * would be set to FF - */ -#define BCN_DESC_ID 0xFF - if ((desc_id >> 24) == BCN_DESC_ID) { - void *data; - uint32_t buf_size; - - vdev_id &= 0x00FFFFFF; - /* TODO: MCL specific API */ - data = wma_get_beacon_buffer_by_vdev_id(vdev_id, - &buf_size); - if (data) { - /* TODO: platform specific API */ - process_ieee_hdr(data); - qdf_mem_free(data); - } - } else { - /* - * TODO: get the hdr content for mgmt frames from - * Tx mgmt desc pool - */ - } - } - - if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) { - struct ath_pktlog_txctl txctl_log; - size_t log_size = sizeof(txctl_log.priv); - - txctl_log.txdesc_hdr_ctl = (void *)pktlog_getbuf(pl_dev, - pl_info, - log_size, - &pl_hdr); - - if (!txctl_log.txdesc_hdr_ctl) { - printk - ("failed to get buf for txctl_log.txdesc_hdr_ctl\n"); - return A_ERROR; - } - - /* - * frm hdr is currently Valid only for local frames - * Add capability to include the fmr hdr for remote frames - */ - txctl_log.priv.frm_hdr = frm_hdr; - qdf_assert(txctl_log.priv.txdesc_ctl); - qdf_assert(pl_hdr.size < sizeof(txctl_log.priv.txdesc_ctl)); - pl_hdr.size = (pl_hdr.size > sizeof(txctl_log.priv.txdesc_ctl)) - ? sizeof(txctl_log.priv.txdesc_ctl) : - pl_hdr.size; - - if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { - qdf_assert(0); - return A_ERROR; - } - qdf_mem_copy((void *)&txctl_log.priv.txdesc_ctl, - ((void *)fw_data->data + - sizeof(struct ath_pktlog_hdr)), - pl_hdr.size); - qdf_assert(txctl_log.txdesc_hdr_ctl); - qdf_mem_copy(txctl_log.txdesc_hdr_ctl, &txctl_log.priv, - sizeof(txctl_log.priv)); - pl_hdr.size = log_size; - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, - txctl_log.txdesc_hdr_ctl); - /* Add Protocol information and HT specific information */ - } - - if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) { - struct ath_pktlog_tx_status txstat_log; - size_t log_size = pl_hdr.size; - - txstat_log.ds_status = (void *) - pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr); - qdf_assert(txstat_log.ds_status); - qdf_mem_copy(txstat_log.ds_status, - ((void *)fw_data->data + - sizeof(struct ath_pktlog_hdr)), - pl_hdr.size); - - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, - txstat_log.ds_status); - } - - if (pl_hdr.log_type == PKTLOG_TYPE_TX_MSDU_ID) { - struct ath_pktlog_msdu_info pl_msdu_info; - size_t log_size; - - qdf_mem_zero(&pl_msdu_info, sizeof(pl_msdu_info)); - log_size = sizeof(pl_msdu_info.priv); - - if (pl_dev->mt_pktlog_enabled == false) - fill_ieee80211_hdr_data(txrx_pdev, - &pl_msdu_info, fw_data->data); - - pl_msdu_info.ath_msdu_info = pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - qdf_mem_copy((void *)&pl_msdu_info.priv.msdu_id_info, - ((void *)fw_data->data + - sizeof(struct ath_pktlog_hdr)), - sizeof(pl_msdu_info.priv.msdu_id_info)); - qdf_mem_copy(pl_msdu_info.ath_msdu_info, &pl_msdu_info.priv, - sizeof(pl_msdu_info.priv)); - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, - pl_msdu_info.ath_msdu_info); - } - - return A_OK; -} -#endif - -/** - * process_offload_pktlog() - Process full pktlog events - * pdev: abstract pdev handle - * data: pktlog buffer - * - * Return: zero on success, non-zero on failure - */ -A_STATUS -process_offload_pktlog(struct cdp_pdev *pdev, void *data) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_info *pl_info; - struct ath_pktlog_hdr pl_hdr; - uint32_t *pl_tgt_hdr; - void *txdesc_hdr_ctl = NULL; - size_t log_size = 0; - size_t tmp_log_size = 0; - - if (!pl_dev) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "Invalid context in %s\n", __func__); - return A_ERROR; - } - - if (!data) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "Invalid data in %s\n", __func__); - return A_ERROR; - } - - pl_tgt_hdr = (uint32_t *)data; - - pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & - ATH_PKTLOG_HDR_FLAGS_MASK) >> - ATH_PKTLOG_HDR_FLAGS_SHIFT; - pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & - ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> - ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; - pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & - ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & - ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; - pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); - - pktlog_hdr_set_specific_data(&pl_hdr, - *(pl_tgt_hdr + - ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET)); - - if (pl_hdr.size > MAX_PKTLOG_RECV_BUF_SIZE) { - pl_dev->invalid_packets++; - return A_ERROR; - } - - /* - * Must include to process different types - * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR - */ - pl_info = pl_dev->pl_info; - tmp_log_size = sizeof(frm_hdr) + pl_hdr.size; - log_size = pl_hdr.size; - txdesc_hdr_ctl = - (void *)pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr); - if (!txdesc_hdr_ctl) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "Failed to allocate pktlog descriptor"); - return A_NO_MEMORY; - } - qdf_assert(txdesc_hdr_ctl); - qdf_assert(pl_hdr->size < PKTLOG_MAX_TX_WORDS * sizeof(u_int32_t)); - qdf_mem_copy(txdesc_hdr_ctl, - ((void *)data + sizeof(struct ath_pktlog_hdr)), - pl_hdr.size); - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, txdesc_hdr_ctl); - - return A_OK; -} - -/* TODO: hardware dependent function */ -A_STATUS process_rx_info_remote(void *pdev, void *data) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_info *pl_info; - struct htt_host_rx_desc_base *rx_desc; - struct ath_pktlog_hdr pl_hdr; - struct ath_pktlog_rx_info rxstat_log; - size_t log_size; - struct ol_rx_remote_data *r_data = (struct ol_rx_remote_data *)data; - qdf_nbuf_t msdu; - - if (!pdev || !r_data || !pl_dev) { - qdf_print("%s: Invalid handle", __func__); - return A_ERROR; - } - - pl_info = pl_dev->pl_info; - msdu = r_data->msdu; - - while (msdu) { - rx_desc = - (struct htt_host_rx_desc_base *)(qdf_nbuf_data(msdu)) - 1; - log_size = - sizeof(*rx_desc) - sizeof(struct htt_host_fw_desc_base); - - /* - * Construct the pktlog header pl_hdr - * Because desc is DMA'd to the host memory - */ - pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); - pl_hdr.missed_cnt = 0; -#if defined(HELIUMPLUS) - pl_hdr.macId = r_data->mac_id; - pl_hdr.log_type = PKTLOG_TYPE_RX_STAT; - pl_hdr.flags |= PKTLOG_HDR_SIZE_16; -#else - pl_hdr.log_type = PKTLOG_TYPE_RX_STAT; -#endif - pl_hdr.size = sizeof(*rx_desc) - - sizeof(struct htt_host_fw_desc_base); -#if defined(HELIUMPLUS) - pl_hdr.timestamp = - rx_desc->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32; - pl_hdr.type_specific_data = 0xDEADAA; -#else - pl_hdr.timestamp = rx_desc->ppdu_end.tsf_timestamp; -#endif /* !defined(HELIUMPLUS) */ - - pktlog_hdr_set_specific_data(&pl_hdr, 0xDEADAA); - - rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - qdf_mem_copy(rxstat_log.rx_desc, (void *)rx_desc + - sizeof(struct htt_host_fw_desc_base), pl_hdr.size); - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, - rxstat_log.rx_desc); - msdu = qdf_nbuf_next(msdu); - } - return A_OK; -} - -#ifdef HELIUMPLUS -A_STATUS process_rx_info(void *pdev, void *data) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_info *pl_info; - struct ath_pktlog_rx_info rxstat_log; - struct ath_pktlog_hdr pl_hdr; - size_t log_size; - uint32_t *pl_tgt_hdr; - struct ol_fw_data *fw_data; - uint32_t len; - - if (!pdev) { - printk("Invalid pdev in %s", __func__); - return A_ERROR; - } - - pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev; - if (!pl_dev) { - printk("Invalid pl_dev in %s", __func__); - return A_ERROR; - } - - fw_data = (struct ol_fw_data *)data; - len = fw_data->len; - if (len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { - qdf_print("Invalid msdu len in %s", __func__); - qdf_assert(0); - return A_ERROR; - } - - pl_info = pl_dev->pl_info; - pl_tgt_hdr = (uint32_t *)fw_data->data; - - qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); - pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & - ATH_PKTLOG_HDR_FLAGS_MASK) >> - ATH_PKTLOG_HDR_FLAGS_SHIFT; - pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & - ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> - ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; - pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & - ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & - ATH_PKTLOG_HDR_MAC_ID_MASK) >> - ATH_PKTLOG_HDR_MAC_ID_SHIFT; - pl_hdr.flags |= PKTLOG_HDR_SIZE_16; - pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & - ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; - pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); - if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { - qdf_assert(0); - return A_ERROR; - } - - log_size = pl_hdr.size; - rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - qdf_mem_copy(rxstat_log.rx_desc, - (void *)fw_data->data + sizeof(struct ath_pktlog_hdr), - pl_hdr.size); - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc); - - return A_OK; -} - -#else -A_STATUS process_rx_info(void *pdev, void *data) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_info *pl_info; - struct ath_pktlog_rx_info rxstat_log; - struct ath_pktlog_hdr pl_hdr; - size_t log_size; - uint32_t *pl_tgt_hdr; - struct ol_fw_data *fw_data; - uint32_t len; - - if (!pdev) { - printk("Invalid pdev in %s", __func__); - return A_ERROR; - } - - pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev; - if (!pl_dev) { - printk("Invalid pl_dev in %s", __func__); - return A_ERROR; - } - - fw_data = (struct ol_fw_data *)data; - len = fw_data->len; - if (len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { - qdf_print("Invalid msdu len in %s", __func__); - qdf_assert(0); - return A_ERROR; - } - - pl_info = pl_dev->pl_info; - pl_tgt_hdr = (uint32_t *)fw_data->data; - qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); - pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & - ATH_PKTLOG_HDR_FLAGS_MASK) >> - ATH_PKTLOG_HDR_FLAGS_SHIFT; - pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & - ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> - ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; - pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & - ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & - ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; - pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); - if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { - qdf_assert(0); - return A_ERROR; - } - - log_size = pl_hdr.size; - rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - qdf_mem_copy(rxstat_log.rx_desc, - (void *)fw_data->data + sizeof(struct ath_pktlog_hdr), - pl_hdr.size); - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc); - - return A_OK; -} -#endif - -#ifdef HELIUMPLUS -A_STATUS process_rate_find(void *pdev, void *data) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_hdr pl_hdr; - struct ath_pktlog_info *pl_info; - size_t log_size; - uint32_t len; - struct ol_fw_data *fw_data; - - /* - * Will be uncommented when the rate control find - * for pktlog is implemented in the firmware. - * Currently derived from the TX PPDU status - */ - struct ath_pktlog_rc_find rcf_log; - uint32_t *pl_tgt_hdr; - - if (!pdev || !data || !pl_dev) { - qdf_print("%s: Invalid handle", __func__); - return A_ERROR; - } - - fw_data = (struct ol_fw_data *)data; - len = fw_data->len; - if (len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { - qdf_print("Invalid msdu len in %s", __func__); - qdf_assert(0); - return A_ERROR; - } - - pl_tgt_hdr = (uint32_t *)fw_data->data; - /* - * Makes the short words (16 bits) portable b/w little endian - * and big endian - */ - - qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); - pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & - ATH_PKTLOG_HDR_FLAGS_MASK) >> - ATH_PKTLOG_HDR_FLAGS_SHIFT; - pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & - ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> - ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; - pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & - ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & - ATH_PKTLOG_HDR_MAC_ID_MASK) >> - ATH_PKTLOG_HDR_MAC_ID_SHIFT; - pl_hdr.flags |= PKTLOG_HDR_SIZE_16; - pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & - ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; - pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); - pl_info = pl_dev->pl_info; - log_size = pl_hdr.size; - rcf_log.rcFind = (void *)pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - - if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { - qdf_assert(0); - return A_ERROR; - } - qdf_mem_copy(rcf_log.rcFind, - ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), - pl_hdr.size); - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcf_log.rcFind); - - return A_OK; -} - -#else -A_STATUS process_rate_find(void *pdev, void *data) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_hdr pl_hdr; - struct ath_pktlog_info *pl_info; - size_t log_size; - uint32_t len; - struct ol_fw_data *fw_data; - - /* - * Will be uncommented when the rate control find - * for pktlog is implemented in the firmware. - * Currently derived from the TX PPDU status - */ - struct ath_pktlog_rc_find rcf_log; - uint32_t *pl_tgt_hdr; - - if (!pdev || !data || !pl_dev) { - qdf_print("%s: Invalid handle", __func__); - return A_ERROR; - } - - fw_data = (struct ol_fw_data *)data; - len = fw_data->len; - if (len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { - qdf_print("Invalid msdu len in %s", __func__); - qdf_assert(0); - return A_ERROR; - } - - pl_tgt_hdr = (uint32_t *)fw_data->data; - /* - * Makes the short words (16 bits) portable b/w little endian - * and big endian - */ - - qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); - pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & - ATH_PKTLOG_HDR_FLAGS_MASK) >> - ATH_PKTLOG_HDR_FLAGS_SHIFT; - pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & - ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> - ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; - pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & - ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & - ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; - pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); - pl_info = pl_dev->pl_info; - log_size = pl_hdr.size; - rcf_log.rcFind = (void *)pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - - if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { - qdf_assert(0); - return A_ERROR; - } - qdf_mem_copy(rcf_log.rcFind, - ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), - pl_hdr.size); - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcf_log.rcFind); - - return A_OK; -} -#endif - -#ifdef HELIUMPLUS -A_STATUS process_sw_event(void *pdev, void *data) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_hdr pl_hdr; - struct ath_pktlog_info *pl_info; - size_t log_size; - uint32_t len; - struct ol_fw_data *fw_data; - - /* - * Will be uncommented when the rate control find - * for pktlog is implemented in the firmware. - * Currently derived from the TX PPDU status - */ - struct ath_pktlog_sw_event sw_event; - uint32_t *pl_tgt_hdr; - - if (!pdev) { - qdf_print("Invalid pdev in %s", __func__); - return A_ERROR; - } - if (!data) { - qdf_print("Invalid data in %s", __func__); - return A_ERROR; - } - if (!pl_dev) { - qdf_print("Invalid pl_dev in %s", __func__); - return A_ERROR; - } - - fw_data = (struct ol_fw_data *)data; - len = fw_data->len; - if (len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { - qdf_print("Invalid msdu len in %s", __func__); - qdf_assert(0); - return A_ERROR; - } - - pl_tgt_hdr = (uint32_t *)fw_data->data; - /* - * Makes the short words (16 bits) portable b/w little endian - * and big endian - */ - pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & - ATH_PKTLOG_HDR_FLAGS_MASK) >> - ATH_PKTLOG_HDR_FLAGS_SHIFT; - pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & - ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> - ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; - pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & - ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & - ATH_PKTLOG_HDR_MAC_ID_MASK) >> - ATH_PKTLOG_HDR_MAC_ID_SHIFT; - pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & - ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; - pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); - - pl_hdr.type_specific_data = - *(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET); - pl_info = pl_dev->pl_info; - log_size = pl_hdr.size; - sw_event.sw_event = (void *)pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { - qdf_assert(0); - return A_ERROR; - } - qdf_mem_copy(sw_event.sw_event, - ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), - pl_hdr.size); - - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, sw_event.sw_event); - - return A_OK; -} - -#else -A_STATUS process_sw_event(void *pdev, void *data) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_hdr pl_hdr; - struct ath_pktlog_info *pl_info; - size_t log_size; - uint32_t len; - struct ol_fw_data *fw_data; - - /* - * Will be uncommented when the rate control find - * for pktlog is implemented in the firmware. - * Currently derived from the TX PPDU status - */ - struct ath_pktlog_sw_event sw_event; - uint32_t *pl_tgt_hdr; - - if (!pdev) { - qdf_print("Invalid pdev in %s", __func__); - return A_ERROR; - } - if (!data) { - qdf_print("Invalid data in %s", __func__); - return A_ERROR; - } - if (!pl_dev) { - qdf_print("Invalid pl_dev in %s", __func__); - return A_ERROR; - } - - fw_data = (struct ol_fw_data *)data; - len = fw_data->len; - if (len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { - qdf_print("Invalid msdu len in %s", __func__); - qdf_assert(0); - return A_ERROR; - } - - pl_tgt_hdr = (uint32_t *)fw_data->data; - /* - * Makes the short words (16 bits) portable b/w little endian - * and big endian - */ - pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & - ATH_PKTLOG_HDR_FLAGS_MASK) >> - ATH_PKTLOG_HDR_FLAGS_SHIFT; - pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & - ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> - ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; - pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & - ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & - ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; - pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); - - pktlog_hdr_set_specific_data(&pl_hdr, - *(pl_tgt_hdr + - ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET)); - - pl_info = pl_dev->pl_info; - log_size = pl_hdr.size; - sw_event.sw_event = (void *)pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { - qdf_assert(0); - return A_ERROR; - } - qdf_mem_copy(sw_event.sw_event, - ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), - pl_hdr.size); - - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, sw_event.sw_event); - - return A_OK; -} -#endif - -#ifdef HELIUMPLUS -A_STATUS process_rate_update(void *pdev, void *data) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_hdr pl_hdr; - size_t log_size; - struct ath_pktlog_info *pl_info; - struct ath_pktlog_rc_update rcu_log; - uint32_t *pl_tgt_hdr; - struct ol_fw_data *fw_data; - uint32_t len; - - if (!pdev || !data || !pl_dev) { - qdf_print("%s: Invalid handle", __func__); - return A_ERROR; - } - - fw_data = (struct ol_fw_data *)data; - len = fw_data->len; - if (len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { - qdf_print("Invalid msdu len in %s", __func__); - qdf_assert(0); - return A_ERROR; - } - - pl_tgt_hdr = (uint32_t *)fw_data->data; - /* - * Makes the short words (16 bits) portable b/w little endian - * and big endian - */ - qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); - pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & - ATH_PKTLOG_HDR_FLAGS_MASK) >> - ATH_PKTLOG_HDR_FLAGS_SHIFT; - pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & - ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> - ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; - pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & - ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & - ATH_PKTLOG_HDR_MAC_ID_MASK) >> - ATH_PKTLOG_HDR_MAC_ID_SHIFT; - pl_hdr.flags |= PKTLOG_HDR_SIZE_16; - pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & - ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; - pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); - log_size = pl_hdr.size; - pl_info = pl_dev->pl_info; - - /* - * Will be uncommented when the rate control update - * for pktlog is implemented in the firmware. - * Currently derived from the TX PPDU status - */ - rcu_log.txRateCtrl = (void *)pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { - qdf_assert(0); - return A_ERROR; - } - qdf_mem_copy(rcu_log.txRateCtrl, - ((char *)fw_data->data + - sizeof(struct ath_pktlog_hdr)), - pl_hdr.size); - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcu_log.txRateCtrl); - return A_OK; -} - -#else -A_STATUS process_rate_update(void *pdev, void *data) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_hdr pl_hdr; - size_t log_size; - struct ath_pktlog_info *pl_info; - struct ath_pktlog_rc_update rcu_log; - uint32_t *pl_tgt_hdr; - struct ol_fw_data *fw_data; - uint32_t len; - - if (!pdev || !data || !pl_dev) { - qdf_print("%s: Invalid handle", __func__); - return A_ERROR; - } - - fw_data = (struct ol_fw_data *)data; - len = fw_data->len; - if (len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || - len < (sizeof(uint32_t) * - (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { - qdf_print("Invalid msdu len in %s", __func__); - qdf_assert(0); - return A_ERROR; - } - - pl_tgt_hdr = (uint32_t *)fw_data->data; - /* - * Makes the short words (16 bits) portable b/w little endian - * and big endian - */ - qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); - pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & - ATH_PKTLOG_HDR_FLAGS_MASK) >> - ATH_PKTLOG_HDR_FLAGS_SHIFT; - pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & - ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> - ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; - pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & - ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> - ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; - pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & - ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; - pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); - log_size = pl_hdr.size; - pl_info = pl_dev->pl_info; - - /* - * Will be uncommented when the rate control update - * for pktlog is implemented in the firmware. - * Currently derived from the TX PPDU status - */ - rcu_log.txRateCtrl = (void *)pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { - qdf_assert(0); - return A_ERROR; - } - qdf_mem_copy(rcu_log.txRateCtrl, - ((char *)fw_data->data + - sizeof(struct ath_pktlog_hdr)), - pl_hdr.size); - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcu_log.txRateCtrl); - return A_OK; -} -#endif - -#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) -int process_rx_desc_remote(void *pdev, void *data) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_hdr pl_hdr; - struct ath_pktlog_rx_info rxstat_log; - size_t log_size; - struct ath_pktlog_info *pl_info; - qdf_nbuf_t log_nbuf = (qdf_nbuf_t)data; - - if (!pl_dev) { - qdf_err("Pktlog handle is NULL"); - return -EINVAL; - } - - pl_info = pl_dev->pl_info; - qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); - pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); - pl_hdr.missed_cnt = 0; - pl_hdr.log_type = 22; /*PKTLOG_TYPE_RX_STATBUF*/ - pl_hdr.size = qdf_nbuf_len(log_nbuf); - pl_hdr.timestamp = 0; - log_size = pl_hdr.size; - rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - - if (!rxstat_log.rx_desc) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, - "%s: Rx descriptor is NULL", __func__); - return -EINVAL; - } - - qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size); - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, - rxstat_log.rx_desc); - return 0; -} - -int -process_pktlog_lite(void *context, void *log_data, uint16_t log_type) -{ - struct pktlog_dev_t *pl_dev = get_pktlog_handle(); - struct ath_pktlog_info *pl_info; - struct ath_pktlog_hdr pl_hdr; - struct ath_pktlog_rx_info rxstat_log; - size_t log_size; - qdf_nbuf_t log_nbuf = (qdf_nbuf_t)log_data; - - if (!pl_dev) { - qdf_err("Pktlog handle is NULL"); - return -EINVAL; - } - - pl_info = pl_dev->pl_info; - qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); - pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); - pl_hdr.missed_cnt = 0; - pl_hdr.log_type = log_type; - pl_hdr.size = qdf_nbuf_len(log_nbuf); - pl_hdr.timestamp = 0; - log_size = pl_hdr.size; - rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, - log_size, &pl_hdr); - if (!rxstat_log.rx_desc) { - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, - "%s: Rx descriptor is NULL", __func__); - return -EINVAL; - } - - qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size); - - cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc); - return 0; -} -#else -int process_rx_desc_remote(void *pdev, void *data) -{ - return 0; -} -int -process_pktlog_lite(void *context, void *log_data, uint16_t log_type) -{ - return 0; -} -#endif #endif /*REMOVE_PKT_LOG */ diff --git a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_wifi2.c b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_wifi2.c new file mode 100644 index 0000000000000000000000000000000000000000..2cc8ae7866af19e12da69534be7cda7dffb48f3b --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_wifi2.c @@ -0,0 +1,1196 @@ +/** + * Copyright (c) 2013-2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* WIFI2 - Refers to legacy platforms */ +#include "pktlog_wifi2.h" + +#ifndef REMOVE_PKT_LOG +static struct txctl_frm_hdr frm_hdr; + +#ifndef HELIUMPLUS +/** + * process_ieee_hdr(): Process ieee header from the pktlog buffer + * @data: pktlog buffer + * + * Return: None + */ +static void process_ieee_hdr(void *data) +{ + uint8_t dir; + struct ieee80211_frame *wh = (struct ieee80211_frame *)(data); + + frm_hdr.framectrl = *(uint16_t *)(wh->i_fc); + frm_hdr.seqctrl = *(uint16_t *)(wh->i_seq); + dir = (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK); + + if (dir == IEEE80211_FC1_DIR_TODS) { + frm_hdr.bssid_tail = + (wh->i_addr1[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> + i_addr1 + [QDF_MAC_ADDR_SIZE + - 1]); + frm_hdr.sa_tail = + (wh->i_addr2[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> + i_addr2 + [QDF_MAC_ADDR_SIZE + - 1]); + frm_hdr.da_tail = + (wh->i_addr3[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> + i_addr3 + [QDF_MAC_ADDR_SIZE + - 1]); + } else if (dir == IEEE80211_FC1_DIR_FROMDS) { + frm_hdr.bssid_tail = + (wh->i_addr2[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> + i_addr2 + [QDF_MAC_ADDR_SIZE + - 1]); + frm_hdr.sa_tail = + (wh->i_addr3[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> + i_addr3 + [QDF_MAC_ADDR_SIZE + - 1]); + frm_hdr.da_tail = + (wh->i_addr1[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> + i_addr1 + [QDF_MAC_ADDR_SIZE + - 1]); + } else { + frm_hdr.bssid_tail = + (wh->i_addr3[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> + i_addr3 + [QDF_MAC_ADDR_SIZE + - 1]); + frm_hdr.sa_tail = + (wh->i_addr2[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> + i_addr2 + [QDF_MAC_ADDR_SIZE + - 1]); + frm_hdr.da_tail = + (wh->i_addr1[QDF_MAC_ADDR_SIZE - 2] << 8) | (wh-> + i_addr1 + [QDF_MAC_ADDR_SIZE + - 1]); + } +} + +/** + * fill_ieee80211_hdr_data() - fill ieee802.11 data header + * @txrx_pdev: txrx pdev + * @pl_msdu_info: msdu info + * @data: data received from event + * + * Return: none + */ +/* TODO: Platform specific function */ +static void +fill_ieee80211_hdr_data(struct cdp_pdev *pdev, + struct ath_pktlog_msdu_info *pl_msdu_info, + void *data) +{ + uint32_t i; + uint32_t *htt_tx_desc; + struct ol_tx_desc_t *tx_desc; + uint8_t msdu_id_offset = MSDU_ID_INFO_ID_OFFSET; + uint16_t tx_desc_id; + uint32_t *msdu_id_info = (uint32_t *) + ((void *)data + sizeof(struct ath_pktlog_hdr)); + uint32_t *msdu_id = (uint32_t *)((char *)msdu_id_info + + msdu_id_offset); + uint8_t *addr, *vap_addr; + uint8_t vdev_id; + qdf_nbuf_t netbuf; + uint32_t len; + struct ol_txrx_pdev_t *txrx_pdev = (struct ol_txrx_pdev_t *)pdev; + + pl_msdu_info->num_msdu = *msdu_id_info; + pl_msdu_info->priv_size = sizeof(uint32_t) * + pl_msdu_info->num_msdu + sizeof(uint32_t); + + if (pl_msdu_info->num_msdu > MAX_PKT_INFO_MSDU_ID) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: Invalid num_msdu count", + __func__); + qdf_assert(0); + return; + } + for (i = 0; i < pl_msdu_info->num_msdu; i++) { + /* + * Handle big endianness + * Increment msdu_id once after retrieving + * lower 16 bits and uppper 16 bits + */ + if (!(i % 2)) { + tx_desc_id = ((*msdu_id & TX_DESC_ID_LOW_MASK) + >> TX_DESC_ID_LOW_SHIFT); + } else { + tx_desc_id = ((*msdu_id & TX_DESC_ID_HIGH_MASK) + >> TX_DESC_ID_HIGH_SHIFT); + msdu_id += 1; + } + if (tx_desc_id >= txrx_pdev->tx_desc.pool_size) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, + "%s: drop due to invalid msdu id = %x", + __func__, tx_desc_id); + return; + } + tx_desc = ol_tx_desc_find(txrx_pdev, tx_desc_id); + qdf_assert(tx_desc); + netbuf = tx_desc->netbuf; + htt_tx_desc = (uint32_t *)tx_desc->htt_tx_desc; + qdf_assert(htt_tx_desc); + + qdf_nbuf_peek_header(netbuf, &addr, &len); + + if (len < (2 * QDF_MAC_ADDR_SIZE)) { + qdf_print("TX frame does not have a valid address"); + return; + } + /* Adding header information for the TX data frames */ + vdev_id = (uint8_t)(*(htt_tx_desc + + HTT_TX_VDEV_ID_WORD) >> + HTT_TX_VDEV_ID_SHIFT) & + HTT_TX_VDEV_ID_MASK; + + vap_addr = wma_get_vdev_address_by_vdev_id(vdev_id); + + frm_hdr.da_tail = (addr[QDF_MAC_ADDR_SIZE - 2] << 8) | + (addr[QDF_MAC_ADDR_SIZE - 1]); + frm_hdr.sa_tail = + (addr[2 * QDF_MAC_ADDR_SIZE - 2] << 8) | + (addr[2 * QDF_MAC_ADDR_SIZE - 1]); + if (vap_addr) { + frm_hdr.bssid_tail = + (vap_addr[QDF_MAC_ADDR_SIZE - 2] << 8) | + (vap_addr[QDF_MAC_ADDR_SIZE - 1]); + } else { + frm_hdr.bssid_tail = 0x0000; + } + pl_msdu_info->priv.msdu_len[i] = *(htt_tx_desc + + HTT_TX_MSDU_LEN_DWORD) + & HTT_TX_MSDU_LEN_MASK; + /* + * Add more information per MSDU + * e.g., protocol information + */ + } +} +#endif /* HELIUMPLUS */ + +#ifdef HELIUMPLUS +A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data) +{ + /* + * Must include to process different types + * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR + */ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_info *pl_info; + uint32_t *pl_tgt_hdr; + struct ol_fw_data *fw_data; + uint32_t len; + + if (!txrx_pdev) { + qdf_nofl_info("Invalid pdev in %s", __func__); + return A_ERROR; + } + + if (!pl_dev) { + qdf_nofl_err("Invalid pktlog handle in %s", __func__); + qdf_assert(pl_dev); + return A_ERROR; + } + + qdf_assert(data); + + fw_data = (struct ol_fw_data *)data; + len = fw_data->len; + if (len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { + qdf_print("Invalid msdu len in %s", __func__); + qdf_assert(0); + return A_ERROR; + } + + pl_tgt_hdr = (uint32_t *)fw_data->data; + /* + * Makes the short words (16 bits) portable b/w little endian + * and big endian + */ + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.flags |= PKTLOG_HDR_SIZE_16; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & + ATH_PKTLOG_HDR_MAC_ID_MASK) >> + ATH_PKTLOG_HDR_MAC_ID_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + pl_hdr.type_specific_data = + *(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET); + pl_info = pl_dev->pl_info; + + if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { + qdf_assert(0); + return A_ERROR; + } + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) { + size_t log_size = sizeof(frm_hdr) + pl_hdr.size; + void *txdesc_hdr_ctl = (void *) + pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + + qdf_assert(txdesc_hdr_ctl); + qdf_assert(pl_hdr.size < (370 * sizeof(u_int32_t))); + + qdf_mem_copy(txdesc_hdr_ctl, &frm_hdr, sizeof(frm_hdr)); + qdf_mem_copy((char *)txdesc_hdr_ctl + sizeof(frm_hdr), + ((void *)fw_data->data + + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + pl_hdr.size = log_size; + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, + txdesc_hdr_ctl); + } + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) { + struct ath_pktlog_tx_status txstat_log; + size_t log_size = pl_hdr.size; + + txstat_log.ds_status = (void *) + pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + qdf_assert(txstat_log.ds_status); + qdf_mem_copy(txstat_log.ds_status, + ((void *)fw_data->data + + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + /* TODO: MCL specific API */ + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, + txstat_log.ds_status); + } + return A_OK; +} +#else +A_STATUS process_tx_info(struct cdp_pdev *txrx_pdev, void *data) +{ + /* + * Must include to process different types + * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR + */ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_info *pl_info; + uint32_t *pl_tgt_hdr; + struct ol_fw_data *fw_data; + uint32_t len; + + if (!txrx_pdev) { + qdf_print("Invalid pdev in %s", __func__); + return A_ERROR; + } + + if (!pl_dev) { + qdf_nofl_err("Invalid pktlog handle in %s", __func__); + qdf_assert(pl_dev); + return A_ERROR; + } + + qdf_assert(data); + + fw_data = (struct ol_fw_data *)data; + len = fw_data->len; + if (len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { + qdf_print("Invalid msdu len in %s", __func__); + qdf_assert(0); + return A_ERROR; + } + + pl_tgt_hdr = (uint32_t *)fw_data->data; + /* + * Makes the short words (16 bits) portable b/w little endian + * and big endian + */ + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + + pktlog_hdr_set_specific_data(&pl_hdr, + *(pl_tgt_hdr + + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET)); + + pl_info = pl_dev->pl_info; + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_FRM_HDR) { + /* Valid only for the TX CTL */ + process_ieee_hdr(fw_data->data + sizeof(pl_hdr)); + } + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_VIRT_ADDR) { + uint32_t desc_id = (uint32_t)*((uint32_t *)(fw_data->data + + sizeof(pl_hdr))); + uint32_t vdev_id = desc_id; + + /* if the pkt log msg is for the bcn frame the vdev id + * is piggybacked in desc_id and the MSB of the desc ID + * would be set to FF + */ +#define BCN_DESC_ID 0xFF + if ((desc_id >> 24) == BCN_DESC_ID) { + void *data; + uint32_t buf_size; + + vdev_id &= 0x00FFFFFF; + /* TODO: MCL specific API */ + data = wma_get_beacon_buffer_by_vdev_id(vdev_id, + &buf_size); + if (data) { + /* TODO: platform specific API */ + process_ieee_hdr(data); + qdf_mem_free(data); + } + } else { + /* + * TODO: get the hdr content for mgmt frames from + * Tx mgmt desc pool + */ + } + } + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_CTRL) { + struct ath_pktlog_txctl txctl_log; + size_t log_size = sizeof(txctl_log.priv); + + txctl_log.txdesc_hdr_ctl = (void *)pktlog_getbuf(pl_dev, + pl_info, + log_size, + &pl_hdr); + + if (!txctl_log.txdesc_hdr_ctl) { + qdf_nofl_info + ("failed to get txctl_log.txdesc_hdr_ctl buf"); + return A_ERROR; + } + + /* + * frm hdr is currently Valid only for local frames + * Add capability to include the fmr hdr for remote frames + */ + txctl_log.priv.frm_hdr = frm_hdr; + qdf_assert(txctl_log.priv.txdesc_ctl); + qdf_assert(pl_hdr.size < sizeof(txctl_log.priv.txdesc_ctl)); + pl_hdr.size = (pl_hdr.size > sizeof(txctl_log.priv.txdesc_ctl)) + ? sizeof(txctl_log.priv.txdesc_ctl) : + pl_hdr.size; + + if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { + qdf_assert(0); + return A_ERROR; + } + qdf_mem_copy((void *)&txctl_log.priv.txdesc_ctl, + ((void *)fw_data->data + + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + qdf_assert(txctl_log.txdesc_hdr_ctl); + qdf_mem_copy(txctl_log.txdesc_hdr_ctl, &txctl_log.priv, + sizeof(txctl_log.priv)); + pl_hdr.size = log_size; + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, + txctl_log.txdesc_hdr_ctl); + /* Add Protocol information and HT specific information */ + } + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_STAT) { + struct ath_pktlog_tx_status txstat_log; + size_t log_size = pl_hdr.size; + + txstat_log.ds_status = (void *) + pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + qdf_assert(txstat_log.ds_status); + qdf_mem_copy(txstat_log.ds_status, + ((void *)fw_data->data + + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, + txstat_log.ds_status); + } + + if (pl_hdr.log_type == PKTLOG_TYPE_TX_MSDU_ID) { + struct ath_pktlog_msdu_info pl_msdu_info; + size_t log_size; + + qdf_mem_zero(&pl_msdu_info, sizeof(pl_msdu_info)); + log_size = sizeof(pl_msdu_info.priv); + + if (pl_dev->mt_pktlog_enabled == false) + fill_ieee80211_hdr_data(txrx_pdev, + &pl_msdu_info, fw_data->data); + + pl_msdu_info.ath_msdu_info = pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + qdf_mem_copy((void *)&pl_msdu_info.priv.msdu_id_info, + ((void *)fw_data->data + + sizeof(struct ath_pktlog_hdr)), + sizeof(pl_msdu_info.priv.msdu_id_info)); + qdf_mem_copy(pl_msdu_info.ath_msdu_info, &pl_msdu_info.priv, + sizeof(pl_msdu_info.priv)); + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, + pl_msdu_info.ath_msdu_info); + } + + return A_OK; +} +#endif /* HELIUMPLUS */ + +A_STATUS process_rx_info_remote(void *pdev, void *data) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_info *pl_info; + struct htt_host_rx_desc_base *rx_desc; + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_rx_info rxstat_log; + size_t log_size; + struct ol_rx_remote_data *r_data = (struct ol_rx_remote_data *)data; + qdf_nbuf_t msdu; + + if (!pdev || !r_data || !pl_dev) { + qdf_print("%s: Invalid handle", __func__); + return A_ERROR; + } + + pl_info = pl_dev->pl_info; + msdu = r_data->msdu; + + while (msdu) { + rx_desc = + (struct htt_host_rx_desc_base *)(qdf_nbuf_data(msdu)) - 1; + log_size = + sizeof(*rx_desc) - sizeof(struct htt_host_fw_desc_base); + + /* + * Construct the pktlog header pl_hdr + * Because desc is DMA'd to the host memory + */ + pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); + pl_hdr.missed_cnt = 0; +#if defined(HELIUMPLUS) + pl_hdr.macId = r_data->mac_id; + pl_hdr.log_type = PKTLOG_TYPE_RX_STAT; + pl_hdr.flags |= PKTLOG_HDR_SIZE_16; +#else + pl_hdr.log_type = PKTLOG_TYPE_RX_STAT; +#endif + pl_hdr.size = sizeof(*rx_desc) - + sizeof(struct htt_host_fw_desc_base); +#if defined(HELIUMPLUS) + pl_hdr.timestamp = + rx_desc->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32; + pl_hdr.type_specific_data = 0xDEADAA; +#else + pl_hdr.timestamp = rx_desc->ppdu_end.tsf_timestamp; +#endif /* !defined(HELIUMPLUS) */ + + pktlog_hdr_set_specific_data(&pl_hdr, 0xDEADAA); + + rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + qdf_mem_copy(rxstat_log.rx_desc, (void *)rx_desc + + sizeof(struct htt_host_fw_desc_base), pl_hdr.size); + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, + rxstat_log.rx_desc); + msdu = qdf_nbuf_next(msdu); + } + return A_OK; +} + +#ifdef HELIUMPLUS +A_STATUS process_rx_info(void *pdev, void *data) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_info *pl_info; + struct ath_pktlog_rx_info rxstat_log; + struct ath_pktlog_hdr pl_hdr; + size_t log_size; + uint32_t *pl_tgt_hdr; + struct ol_fw_data *fw_data; + uint32_t len; + + if (!pdev) { + qdf_nofl_info("Invalid pdev in %s", __func__); + return A_ERROR; + } + + pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev; + if (!pl_dev) { + qdf_nofl_info("Invalid pl_dev in %s", __func__); + return A_ERROR; + } + + fw_data = (struct ol_fw_data *)data; + len = fw_data->len; + if (len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { + qdf_print("Invalid msdu len in %s", __func__); + qdf_assert(0); + return A_ERROR; + } + + pl_info = pl_dev->pl_info; + pl_tgt_hdr = (uint32_t *)fw_data->data; + + qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & + ATH_PKTLOG_HDR_MAC_ID_MASK) >> + ATH_PKTLOG_HDR_MAC_ID_SHIFT; + pl_hdr.flags |= PKTLOG_HDR_SIZE_16; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { + qdf_assert(0); + return A_ERROR; + } + + log_size = pl_hdr.size; + rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + qdf_mem_copy(rxstat_log.rx_desc, + (void *)fw_data->data + sizeof(struct ath_pktlog_hdr), + pl_hdr.size); + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc); + + return A_OK; +} +#else +A_STATUS process_rx_info(void *pdev, void *data) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_info *pl_info; + struct ath_pktlog_rx_info rxstat_log; + struct ath_pktlog_hdr pl_hdr; + size_t log_size; + uint32_t *pl_tgt_hdr; + struct ol_fw_data *fw_data; + uint32_t len; + + if (!pdev) { + qdf_nofl_info("Invalid pdev in %s", __func__); + return A_ERROR; + } + + pl_dev = ((struct ol_txrx_pdev_t *)pdev)->pl_dev; + if (!pl_dev) { + qdf_nofl_info("Invalid pl_dev in %s", __func__); + return A_ERROR; + } + + fw_data = (struct ol_fw_data *)data; + len = fw_data->len; + if (len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { + qdf_print("Invalid msdu len in %s", __func__); + qdf_assert(0); + return A_ERROR; + } + + pl_info = pl_dev->pl_info; + pl_tgt_hdr = (uint32_t *)fw_data->data; + qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { + qdf_assert(0); + return A_ERROR; + } + + log_size = pl_hdr.size; + rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + qdf_mem_copy(rxstat_log.rx_desc, + (void *)fw_data->data + sizeof(struct ath_pktlog_hdr), + pl_hdr.size); + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc); + + return A_OK; +} +#endif /* HELIUMPLUS */ + +#ifdef HELIUMPLUS +A_STATUS process_rate_find(void *pdev, void *data) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_info *pl_info; + size_t log_size; + uint32_t len; + struct ol_fw_data *fw_data; + + /* + * Will be uncommented when the rate control find + * for pktlog is implemented in the firmware. + * Currently derived from the TX PPDU status + */ + struct ath_pktlog_rc_find rcf_log; + uint32_t *pl_tgt_hdr; + + if (!pdev || !data || !pl_dev) { + qdf_print("%s: Invalid handle", __func__); + return A_ERROR; + } + + fw_data = (struct ol_fw_data *)data; + len = fw_data->len; + if (len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { + qdf_print("Invalid msdu len in %s", __func__); + qdf_assert(0); + return A_ERROR; + } + + pl_tgt_hdr = (uint32_t *)fw_data->data; + /* + * Makes the short words (16 bits) portable b/w little endian + * and big endian + */ + + qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & + ATH_PKTLOG_HDR_MAC_ID_MASK) >> + ATH_PKTLOG_HDR_MAC_ID_SHIFT; + pl_hdr.flags |= PKTLOG_HDR_SIZE_16; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + pl_info = pl_dev->pl_info; + log_size = pl_hdr.size; + rcf_log.rcFind = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + + if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { + qdf_assert(0); + return A_ERROR; + } + qdf_mem_copy(rcf_log.rcFind, + ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcf_log.rcFind); + + return A_OK; +} + +#else +A_STATUS process_rate_find(void *pdev, void *data) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_info *pl_info; + size_t log_size; + uint32_t len; + struct ol_fw_data *fw_data; + + /* + * Will be uncommented when the rate control find + * for pktlog is implemented in the firmware. + * Currently derived from the TX PPDU status + */ + struct ath_pktlog_rc_find rcf_log; + uint32_t *pl_tgt_hdr; + + if (!pdev || !data || !pl_dev) { + qdf_print("%s: Invalid handle", __func__); + return A_ERROR; + } + + fw_data = (struct ol_fw_data *)data; + len = fw_data->len; + if (len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { + qdf_print("Invalid msdu len in %s", __func__); + qdf_assert(0); + return A_ERROR; + } + + pl_tgt_hdr = (uint32_t *)fw_data->data; + /* + * Makes the short words (16 bits) portable b/w little endian + * and big endian + */ + + qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + pl_info = pl_dev->pl_info; + log_size = pl_hdr.size; + rcf_log.rcFind = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + + if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { + qdf_assert(0); + return A_ERROR; + } + qdf_mem_copy(rcf_log.rcFind, + ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcf_log.rcFind); + + return A_OK; +} +#endif + +#ifdef HELIUMPLUS +A_STATUS process_rate_update(void *pdev, void *data) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_hdr pl_hdr; + size_t log_size; + struct ath_pktlog_info *pl_info; + struct ath_pktlog_rc_update rcu_log; + uint32_t *pl_tgt_hdr; + struct ol_fw_data *fw_data; + uint32_t len; + + if (!pdev || !data || !pl_dev) { + qdf_print("%s: Invalid handle", __func__); + return A_ERROR; + } + + fw_data = (struct ol_fw_data *)data; + len = fw_data->len; + if (len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { + qdf_print("Invalid msdu len in %s", __func__); + qdf_assert(0); + return A_ERROR; + } + + pl_tgt_hdr = (uint32_t *)fw_data->data; + /* + * Makes the short words (16 bits) portable b/w little endian + * and big endian + */ + qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & + ATH_PKTLOG_HDR_MAC_ID_MASK) >> + ATH_PKTLOG_HDR_MAC_ID_SHIFT; + pl_hdr.flags |= PKTLOG_HDR_SIZE_16; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + log_size = pl_hdr.size; + pl_info = pl_dev->pl_info; + + /* + * Will be uncommented when the rate control update + * for pktlog is implemented in the firmware. + * Currently derived from the TX PPDU status + */ + rcu_log.txRateCtrl = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { + qdf_assert(0); + return A_ERROR; + } + qdf_mem_copy(rcu_log.txRateCtrl, + ((char *)fw_data->data + + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcu_log.txRateCtrl); + return A_OK; +} +#else +A_STATUS process_rate_update(void *pdev, void *data) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_hdr pl_hdr; + size_t log_size; + struct ath_pktlog_info *pl_info; + struct ath_pktlog_rc_update rcu_log; + uint32_t *pl_tgt_hdr; + struct ol_fw_data *fw_data; + uint32_t len; + + if (!pdev || !data || !pl_dev) { + qdf_print("%s: Invalid handle", __func__); + return A_ERROR; + } + + fw_data = (struct ol_fw_data *)data; + len = fw_data->len; + if (len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { + qdf_print("Invalid msdu len in %s", __func__); + qdf_assert(0); + return A_ERROR; + } + + pl_tgt_hdr = (uint32_t *)fw_data->data; + /* + * Makes the short words (16 bits) portable b/w little endian + * and big endian + */ + qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + log_size = pl_hdr.size; + pl_info = pl_dev->pl_info; + + /* + * Will be uncommented when the rate control update + * for pktlog is implemented in the firmware. + * Currently derived from the TX PPDU status + */ + rcu_log.txRateCtrl = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { + qdf_assert(0); + return A_ERROR; + } + qdf_mem_copy(rcu_log.txRateCtrl, + ((char *)fw_data->data + + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rcu_log.txRateCtrl); + return A_OK; +} +#endif /* HELIUMPLUS */ + +#ifdef HELIUMPLUS +A_STATUS process_sw_event(void *pdev, void *data) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_info *pl_info; + size_t log_size; + uint32_t len; + struct ol_fw_data *fw_data; + + /* + * Will be uncommented when the rate control find + * for pktlog is implemented in the firmware. + * Currently derived from the TX PPDU status + */ + struct ath_pktlog_sw_event sw_event; + uint32_t *pl_tgt_hdr; + + if (!pdev) { + qdf_print("Invalid pdev in %s", __func__); + return A_ERROR; + } + if (!data) { + qdf_print("Invalid data in %s", __func__); + return A_ERROR; + } + if (!pl_dev) { + qdf_print("Invalid pl_dev in %s", __func__); + return A_ERROR; + } + + fw_data = (struct ol_fw_data *)data; + len = fw_data->len; + if (len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MAC_ID_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { + qdf_print("Invalid msdu len in %s", __func__); + qdf_assert(0); + return A_ERROR; + } + + pl_tgt_hdr = (uint32_t *)fw_data->data; + /* + * Makes the short words (16 bits) portable b/w little endian + * and big endian + */ + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.macId = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MAC_ID_OFFSET) & + ATH_PKTLOG_HDR_MAC_ID_MASK) >> + ATH_PKTLOG_HDR_MAC_ID_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + + pl_hdr.type_specific_data = + *(pl_tgt_hdr + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET); + pl_info = pl_dev->pl_info; + log_size = pl_hdr.size; + sw_event.sw_event = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { + qdf_assert(0); + return A_ERROR; + } + qdf_mem_copy(sw_event.sw_event, + ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, sw_event.sw_event); + + return A_OK; +} +#else +A_STATUS process_sw_event(void *pdev, void *data) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_info *pl_info; + size_t log_size; + uint32_t len; + struct ol_fw_data *fw_data; + + /* + * Will be uncommented when the rate control find + * for pktlog is implemented in the firmware. + * Currently derived from the TX PPDU status + */ + struct ath_pktlog_sw_event sw_event; + uint32_t *pl_tgt_hdr; + + if (!pdev) { + qdf_print("Invalid pdev in %s", __func__); + return A_ERROR; + } + if (!data) { + qdf_print("Invalid data in %s", __func__); + return A_ERROR; + } + if (!pl_dev) { + qdf_print("Invalid pl_dev in %s", __func__); + return A_ERROR; + } + + fw_data = (struct ol_fw_data *)data; + len = fw_data->len; + if (len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_FLAGS_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_MISSED_CNT_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_LOG_TYPE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_SIZE_OFFSET + 1)) || + len < (sizeof(uint32_t) * + (ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET + 1))) { + qdf_print("Invalid msdu len in %s", __func__); + qdf_assert(0); + return A_ERROR; + } + + pl_tgt_hdr = (uint32_t *)fw_data->data; + /* + * Makes the short words (16 bits) portable b/w little endian + * and big endian + */ + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + + pktlog_hdr_set_specific_data(&pl_hdr, + *(pl_tgt_hdr + + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET)); + + pl_info = pl_dev->pl_info; + log_size = pl_hdr.size; + sw_event.sw_event = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + if (sizeof(struct ath_pktlog_hdr) + pl_hdr.size > len) { + qdf_assert(0); + return A_ERROR; + } + qdf_mem_copy(sw_event.sw_event, + ((char *)fw_data->data + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, sw_event.sw_event); + + return A_OK; +} +#endif /* HELIUMPLUS */ +#endif /* REMOVE_PKT_LOG */ diff --git a/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_wifi3.c b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_wifi3.c new file mode 100644 index 0000000000000000000000000000000000000000..c74c7374aa6b85c9044cdd652c4b7535d7fd54be --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/utils/pktlog/pktlog_wifi3.c @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2013-2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* WIFI3 - Refers to platforms - 6290/6390/6490 */ +#include "pktlog_wifi3.h" + +#ifndef REMOVE_PKT_LOG +A_STATUS +process_offload_pktlog_wifi3(struct cdp_pdev *pdev, void *data) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_info *pl_info; + struct ath_pktlog_hdr pl_hdr; + uint32_t *pl_tgt_hdr; + void *txdesc_hdr_ctl = NULL; + size_t log_size = 0; + + if (!pl_dev) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "Invalid context in %s\n", __func__); + return A_ERROR; + } + + if (!data) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "Invalid data in %s\n", __func__); + return A_ERROR; + } + + pl_tgt_hdr = (uint32_t *)data; + + pl_hdr.flags = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_FLAGS_OFFSET) & + ATH_PKTLOG_HDR_FLAGS_MASK) >> + ATH_PKTLOG_HDR_FLAGS_SHIFT; + pl_hdr.missed_cnt = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_MISSED_CNT_OFFSET) & + ATH_PKTLOG_HDR_MISSED_CNT_MASK) >> + ATH_PKTLOG_HDR_MISSED_CNT_SHIFT; + pl_hdr.log_type = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_LOG_TYPE_OFFSET) & + ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> + ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; + pl_hdr.size = (*(pl_tgt_hdr + ATH_PKTLOG_HDR_SIZE_OFFSET) & + ATH_PKTLOG_HDR_SIZE_MASK) >> ATH_PKTLOG_HDR_SIZE_SHIFT; + pl_hdr.timestamp = *(pl_tgt_hdr + ATH_PKTLOG_HDR_TIMESTAMP_OFFSET); + + pl_hdr.type_specific_data = *(pl_tgt_hdr + + ATH_PKTLOG_HDR_TYPE_SPECIFIC_DATA_OFFSET); + + if (pl_hdr.size > MAX_PKTLOG_RECV_BUF_SIZE) { + pl_dev->invalid_packets++; + return A_ERROR; + } + + /* + * Must include to process different types + * TX_CTL, TX_STATUS, TX_MSDU_ID, TX_FRM_HDR + */ + pl_info = pl_dev->pl_info; + log_size = pl_hdr.size; + txdesc_hdr_ctl = + (void *)pktlog_getbuf(pl_dev, pl_info, log_size, &pl_hdr); + if (!txdesc_hdr_ctl) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "Failed to allocate pktlog descriptor"); + return A_NO_MEMORY; + } + qdf_assert(txdesc_hdr_ctl); + qdf_assert(pl_hdr->size < PKTLOG_MAX_TX_WORDS * sizeof(u_int32_t)); + qdf_mem_copy(txdesc_hdr_ctl, + ((void *)data + sizeof(struct ath_pktlog_hdr)), + pl_hdr.size); + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, txdesc_hdr_ctl); + + return A_OK; +} + +int process_rx_desc_remote_wifi3(void *pdev, void *data) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_rx_info rxstat_log; + size_t log_size; + struct ath_pktlog_info *pl_info; + qdf_nbuf_t log_nbuf = (qdf_nbuf_t)data; + + if (!pl_dev) { + qdf_err("Pktlog handle is NULL"); + return -EINVAL; + } + + pl_info = pl_dev->pl_info; + qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); + pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); + pl_hdr.missed_cnt = 0; + pl_hdr.log_type = PKTLOG_TYPE_RX_STATBUF; + pl_hdr.size = qdf_nbuf_len(log_nbuf); + pl_hdr.timestamp = 0; + log_size = pl_hdr.size; + rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + + if (!rxstat_log.rx_desc) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, + "%s: Rx descriptor is NULL", __func__); + return -EINVAL; + } + + qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size); + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, + rxstat_log.rx_desc); + return 0; +} + +int +process_pktlog_lite_wifi3(void *context, void *log_data, + uint16_t log_type) +{ + struct pktlog_dev_t *pl_dev = get_pktlog_handle(); + struct ath_pktlog_info *pl_info; + struct ath_pktlog_hdr pl_hdr; + struct ath_pktlog_rx_info rxstat_log; + size_t log_size; + qdf_nbuf_t log_nbuf = (qdf_nbuf_t)log_data; + + if (!pl_dev) { + qdf_err("Pktlog handle is NULL"); + return -EINVAL; + } + + pl_info = pl_dev->pl_info; + qdf_mem_zero(&pl_hdr, sizeof(pl_hdr)); + pl_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S); + pl_hdr.missed_cnt = 0; + pl_hdr.log_type = log_type; + pl_hdr.size = qdf_nbuf_len(log_nbuf); + pl_hdr.timestamp = 0; + log_size = pl_hdr.size; + rxstat_log.rx_desc = (void *)pktlog_getbuf(pl_dev, pl_info, + log_size, &pl_hdr); + if (!rxstat_log.rx_desc) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, + "%s: Rx descriptor is NULL", __func__); + return -EINVAL; + } + + qdf_mem_copy(rxstat_log.rx_desc, qdf_nbuf_data(log_nbuf), pl_hdr.size); + + cds_pkt_stats_to_logger_thread(&pl_hdr, NULL, rxstat_log.rx_desc); + return 0; +} +#endif /* REMOVE_PKT_LOG */ diff --git a/drivers/staging/qca-wifi-host-cmn/utils/qld/inc/qld_api.h b/drivers/staging/qca-wifi-host-cmn/utils/qld/inc/qld_api.h new file mode 100644 index 0000000000000000000000000000000000000000..9afdf28ebe274887c0c2625bfb5f92619ca7a3c4 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/utils/qld/inc/qld_api.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: qld_api.h + * QLD: This file provides public exposed functions + */ + +#ifndef _QLD_API_H_ +#define _QLD_API_H_ + +#define QLD_MAX_NAME 48 + +/** + * struct qld_entry - Individual entry in qld_event + * @addr: Start address of object to dump + * @size: Size of memory dump + * @name: Name of memory dump + */ +struct qld_entry { + uint64_t addr; + size_t size; + char name[QLD_MAX_NAME]; +}; + +/** + * typedef qld_iter_func - qld callback function + * @req: opaque pointer + * @qld_entry: qld_entry + * + * Return: 0 - OK -EINVAL - On failure + */ +typedef int (*qld_iter_func)(void *req, struct qld_entry *entry); + +/** + * qld_iterate_list() - qld list iteration routine + * @gen_table: callback function to genrate table + * @req: opaque request + * + * Return: 0 - OK -EINVAL - On failure + */ +int qld_iterate_list(qld_iter_func gen_table, void *req); + +/** + * qld_register() - Register qld for the given address + * @addr: starting address the dump + * @size: size of memory to dump + * @name: name identifier of dump + * + * Return: 0 - OK -EINVAL -ENOMEM - On failure + */ +int qld_register(void *addr, size_t size, char *name); + +/** + * qld_unregister() - Un-register qld for the given address + * @addr: starting address the dump + * + * Return: 0 - OK -EINVAL - On failure + */ +int qld_unregister(void *addr); + +/** + * qld_list_init() - Initialize qld list + * @max_list: maximum size list supports + * + * Return: 0 - OK -EINVAL -ENOMEM - On failure + */ +int qld_list_init(uint32_t max_list); + +/** + * qld_list_delete() - empty qld list + * + * Return: 0 - OK -EINVAL - On failure + */ +int qld_list_delete(void); + +/** + * qld_list_deinit() - De-initialize qld list + * + * Return: 0 - OK -EINVAL - On failure + */ +int qld_list_deinit(void); + +/** + * qld_get_list_count () - get size of qld list + * @list_count: list_count to set + * + * Return: 0 - OK -EINVAL - On failure + */ +int qld_get_list_count(uint32_t *list_count); + +/** + * is_qld_enable() - check if qld feature is set + * + * Return: true on success, false on failure + */ +bool is_qld_enable(void); + +#endif /* _QLD_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/utils/qld/inc/qld_priv.h b/drivers/staging/qca-wifi-host-cmn/utils/qld/inc/qld_priv.h new file mode 100644 index 0000000000000000000000000000000000000000..ebf7b56931a8157f1b268e0928998ff1c8204107 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/utils/qld/inc/qld_priv.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: qld_priv.h + * QLD: This file provies Private functions for qld + */ + +#ifndef _QLD_PRIV_H_ +#define _QLD_PRIV_H_ + +#include +#include +#include + +#define qld_alert(format, args...) \ + QDF_TRACE_FATAL(QDF_MODULE_ID_QLD, format, ## args) + +#define qld_err(format, args...) \ + QDF_TRACE_ERROR(QDF_MODULE_ID_QLD, format, ## args) + +#define qld_warn(format, args...) \ + QDF_TRACE_WARN(QDF_MODULE_ID_QLD, format, ## args) + +#define qld_info(format, args...) \ + QDF_TRACE_INFO(QDF_MODULE_ID_QLD, format, ## args) + +#define qld_debug(format, args...) \ + QDF_TRACE_DEBUG(QDF_MODULE_ID_QLD, format, ## args) + +/** + * struct qld_list_handle - Top level qld structure + * @qld_lock: Spinlock for structure + * @qld_list: linked list for linking + * @qld_max_list: maximum list size + */ +struct qld_list_handle { + qdf_spinlock_t qld_lock; + qdf_list_t qld_list; + uint32_t qld_max_list; +}; + +/** + * struct qld_node - qld node + * @node: single node of linked list + * @entry: single qld_entry in list + */ +struct qld_node { + qdf_list_node_t node; + struct qld_entry entry; +}; + +#endif /*_QLD_PRIV_H_*/ diff --git a/drivers/staging/qca-wifi-host-cmn/utils/qld/src/qld.c b/drivers/staging/qca-wifi-host-cmn/utils/qld/src/qld.c new file mode 100644 index 0000000000000000000000000000000000000000..d377d59a89dc00d2de518a58870efed46cb03e2a --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/utils/qld/src/qld.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2019 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: qld + * QLD: main file of QCA Live Dump (QLD) + */ + +#include "qld_priv.h" +#include "qld_api.h" +#include "qdf_module.h" + +/* Handle for qld structure */ +static struct qld_list_handle *qld_handle; + +bool is_qld_enable(void) +{ + if (!qld_handle) + return false; + + return true; +} + +qdf_export_symbol(is_qld_enable); + +int qld_list_init(uint32_t max_list) +{ + if (!max_list) + return -EINVAL; + + qld_handle = qdf_mem_malloc(sizeof(*qld_handle)); + + if (!qld_handle) + return -ENOMEM; + + qdf_spinlock_create(&qld_handle->qld_lock); + qld_handle->qld_max_list = max_list; + qdf_list_create(&qld_handle->qld_list, qld_handle->qld_max_list); + qld_debug("LIST init with max size of %u", qld_handle->qld_max_list); + return 0; +} + +qdf_export_symbol(qld_list_init); + +int qld_list_deinit(void) +{ + if (!qld_handle) { + qld_err("Handle NULL"); + return -EINVAL; + } + /* Delete the list */ + qld_list_delete(); + qdf_list_destroy(&qld_handle->qld_list); + qdf_spinlock_destroy(&qld_handle->qld_lock); + qdf_mem_free(qld_handle); + qld_handle = NULL; + qld_debug("LIST De-initialized"); + return 0; +} + +qdf_export_symbol(qld_list_deinit); + +int qld_list_delete(void) +{ + struct qld_node *qld; + qdf_list_node_t *node = NULL; + qdf_list_t *list; + + if (!qld_handle) { + qld_err("Handle NULL"); + return -EINVAL; + } + list = &qld_handle->qld_list; + qdf_spinlock_acquire(&qld_handle->qld_lock); + /* Check and remove the elements of list */ + while (qdf_list_remove_front(list, &node) == QDF_STATUS_SUCCESS) { + qld = qdf_container_of(node, struct qld_node, node); + qdf_mem_free(qld); + } + qdf_spinlock_release(&qld_handle->qld_lock); + qld_debug("LIST Emptied"); + return 0; +} + +qdf_export_symbol(qld_list_delete); + +int qld_register(void *addr, size_t size, char *name) +{ + struct qld_node *qld; + uint32_t list_count = 0; + + if (!qld_handle || !addr) { + qld_err("Handle or address is NULL"); + return -EINVAL; + } + + if ((qld_get_list_count(&list_count) != 0)) { + qdf_err("QLD: Invalid list count"); + return -EINVAL; + } + if (list_count >= qld_handle->qld_max_list) { + qld_err("List full,reg failed.Increase list size"); + return -EINVAL; + } + /* Check if data is already registered */ + qdf_spinlock_acquire(&qld_handle->qld_lock); + qdf_list_for_each(&qld_handle->qld_list, qld, node) { + if (qld->entry.addr == (uintptr_t)addr) { + qld_err("%s already registered", qld->entry.name); + qdf_spinlock_release(&qld_handle->qld_lock); + return -EINVAL; + } + } + qdf_spinlock_release(&qld_handle->qld_lock); + qld = qdf_mem_malloc(sizeof(*qld)); + if (!qld) + return -ENOMEM; + + qld_debug("Insert addr=%pK size=%zu name=%s", (void *)addr, size, name); + qdf_spinlock_acquire(&qld_handle->qld_lock); + qld->entry.addr = (uintptr_t)addr; + qld->entry.size = size; + qdf_snprintf(qld->entry.name, sizeof(qld->entry.name), "%s", name); + qdf_list_insert_front(&qld_handle->qld_list, &qld->node); + qdf_spinlock_release(&qld_handle->qld_lock); + return 0; +} + +qdf_export_symbol(qld_register); + +int qld_unregister(void *addr) +{ + struct qld_node *qld = NULL; + + if (!qld_handle || !addr) { + qld_err("Handle or address is NULL"); + return -EINVAL; + } + + qdf_spinlock_acquire(&qld_handle->qld_lock); + qdf_list_for_each(&qld_handle->qld_list, qld, node) { + if (qld->entry.addr == (uintptr_t)addr) + break; + } + qdf_list_remove_node(&qld_handle->qld_list, &qld->node); + qld_debug("Delete name=%s, size=%zu", qld->entry.name, qld->entry.size); + qdf_mem_free(qld); + qdf_spinlock_release(&qld_handle->qld_lock); + return 0; +} + +qdf_export_symbol(qld_unregister); + +int qld_iterate_list(qld_iter_func gen_table, void *qld_req) +{ + struct qld_node *qld = NULL; + + if (!qld_handle) + return -EINVAL; + + if (!qld_req || !gen_table) { + qld_err("req buffer or func is NULL %s", __func__); + return -EINVAL; + } + qdf_spinlock_acquire(&qld_handle->qld_lock); + qdf_list_for_each(&qld_handle->qld_list, qld, node) { + (gen_table)(qld_req, &qld->entry); + } + qdf_spinlock_release(&qld_handle->qld_lock); + return 0; +} + +qdf_export_symbol(qld_iterate_list); + +int qld_get_list_count(uint32_t *list_count) +{ + if (!qld_handle) { + qld_err("Handle NULL"); + return -EINVAL; + } + *list_count = qld_handle->qld_list.count; + return 0; +} + +qdf_export_symbol(qld_get_list_count); diff --git a/drivers/staging/qca-wifi-host-cmn/utils/sys/queue.h b/drivers/staging/qca-wifi-host-cmn/utils/sys/queue.h new file mode 100644 index 0000000000000000000000000000000000000000..23b184385378d8be99dcf8a5291cec870fef10fd --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/utils/sys/queue.h @@ -0,0 +1,592 @@ +/* +* Copyright (c) 1991, 1993 +* The Regents of the University of California. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* 4. Neither the name of the University nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* +* @(#)queue.h 8.5 (Berkeley) 8/20/94 +* $FreeBSD: src/sys/sys/queue.h,v 1.58 2004/04/07 04:19:49 imp Exp $ +*/ + +#ifndef _QUEUE_H_ +#define _QUEUE_H_ + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * + */ +#define QUEUE_MACRO_DEBUG 0 +#if QUEUE_MACRO_DEBUG +/* + * Store the last 2 places the queue element or head was altered + */ +struct qm_trace { + char *lastfile; + int lastline; + char *prevfile; + int prevline; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)NULL; } while (0) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRASHIT(x) do {(x) = (void *)0; } while (0) +#endif /* QUEUE_MACRO_DEBUG */ + +#ifdef ATHR_RNWF +/* + * NDIS contains a defn for SLIST_ENTRY and SINGLE_LIST_ENTRY + */ +#endif + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ + struct name { \ + struct type *slh_first; /* first element */ \ + } + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SING_LIST_ENTRY(type) \ + struct { \ + struct type *sle_next; /* next element */ \ + } + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = \ + SLIST_NEXT(SLIST_NEXT(curelm, field), field);\ + } \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), \ + field); \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ + struct name { \ + struct type *stqh_first; \ + struct type **stqh_last; \ + } + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ + struct { \ + struct type *stqe_next; /* next element */ \ + } + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for ((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), \ + field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == \ + NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *) \ + ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + if ((STAILQ_NEXT(curelm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(curelm, field), \ + field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((curelm),\ + field); \ + } \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if (STAILQ_NEXT(elm, field)) { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), \ + field)) == NULL) \ + (head)->stqh_last = \ + &STAILQ_NEXT((elm), field); \ + } \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == \ + NULL)\ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT((elm), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +/* + * List declarations. + */ +#define ATH_LIST_HEAD(name, type) \ + struct name { \ + struct type *lh_first; \ + } + +#ifndef LIST_HEAD +#define LIST_HEAD ATH_LIST_HEAD +#endif + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ + struct { \ + struct type *le_next; \ + struct type **le_prev; \ + } + +/* + * List functions. + */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if ((LIST_NEXT((elm), field) = \ + LIST_NEXT((listelm), field)) != NULL) \ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ +} while (0) + +/* + * Tail queue declarations. + */ +#ifndef TRACE_TX_LEAK +#define TRACE_TX_LEAK 0 +#endif + +#if TRACE_TX_LEAK +#define HEADNAME char headname[64]; +#define COPY_HEADNAME(head) OS_MEMCPY((head)->headname, #head, sizeof(#head)) +#else +#define HEADNAME +#define COPY_HEADNAME(head) +#endif + +#define TAILQ_HEAD(name, type) \ + struct name { \ + struct type *tqh_first; \ + struct type **tqh_last; \ + HEADNAME \ + TRACEBUF \ + } + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ + struct { \ + struct type *tqe_next; \ + struct type **tqe_prev; \ + TRACEBUF \ + } + +/* + * Tail queue functions. + */ + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + COPY_HEADNAME(head); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), \ + field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)\ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT((elm)->field.tqe_next); \ + TRASHIT((elm)->field.tqe_prev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;\ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + } \ +} while (0) + +#ifdef _KERNEL + +/* + * XXX insque() and remque() are an old way of handling certain queues. + * They bogusly assumes that all queue heads look alike. + */ + +struct quehead { + struct quehead *qh_link; + struct quehead *qh_rlink; +}; + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) + +static inline void insque(void *a, void *b) +{ + struct quehead *element = (struct quehead *)a, + *head = (struct quehead *)b; + + element->qh_link = head->qh_link; + element->qh_rlink = head; + head->qh_link = element; + element->qh_link->qh_rlink = element; +} + +static inline void remque(void *a) +{ + struct quehead *element = (struct quehead *)a; + + element->qh_link->qh_rlink = element->qh_rlink; + element->qh_rlink->qh_link = element->qh_link; + element->qh_rlink = 0; +} + +#else /* !(__GNUC__ || __INTEL_COMPILER) */ + +void insque(void *a, void *b); +void remque(void *a); + +#endif /* __GNUC__ || __INTEL_COMPILER */ + +#endif /* _KERNEL */ + +#endif /* _QUEUE_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/wlan_cfg/cfg_dp.h b/drivers/staging/qca-wifi-host-cmn/wlan_cfg/cfg_dp.h index fa439f6d8c7e22033aea146d836a09c3e428db7c..f9f61732bc988cb84df14d0046bf490f6865b8a7 100644 --- a/drivers/staging/qca-wifi-host-cmn/wlan_cfg/cfg_dp.h +++ b/drivers/staging/qca-wifi-host-cmn/wlan_cfg/cfg_dp.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -38,30 +39,37 @@ #define WLAN_CFG_NUM_TCL_DATA_RINGS_MIN 3 #define WLAN_CFG_NUM_TCL_DATA_RINGS_MAX 3 -#ifdef CONFIG_MCL -#ifdef QCA_LL_TX_FLOW_CONTROL_V2 +#if defined(QCA_LL_TX_FLOW_CONTROL_V2) || \ + defined(QCA_LL_PDEV_TX_FLOW_CONTROL) #define WLAN_CFG_TX_FLOW_START_QUEUE_OFFSET 10 #define WLAN_CFG_TX_FLOW_STOP_QUEUE_TH 15 #else #define WLAN_CFG_TX_FLOW_START_QUEUE_OFFSET 0 #define WLAN_CFG_TX_FLOW_STOP_QUEUE_TH 0 #endif -#else -#define WLAN_CFG_TX_FLOW_START_QUEUE_OFFSET 0 -#define WLAN_CFG_TX_FLOW_STOP_QUEUE_TH 0 -#endif #define WLAN_CFG_PER_PDEV_TX_RING_MIN 0 #define WLAN_CFG_PER_PDEV_TX_RING_MAX 1 -#ifdef CONFIG_MCL +#if defined(WLAN_MAX_PDEVS) && (WLAN_MAX_PDEVS == 1) #define WLAN_CFG_PER_PDEV_RX_RING 0 #define WLAN_CFG_PER_PDEV_LMAC_RING 0 #define WLAN_LRO_ENABLE 0 #define WLAN_CFG_MAC_PER_TARGET 2 #ifdef IPA_OFFLOAD +/* Using TCL data ring 2 for IPA Tx And + * WBM2SW ring 2 for Tx completion + */ +#define WLAN_CFG_IPA_TX_N_TXCMPL_RING 2 /* Size of TCL TX Ring */ +#if defined(TX_TO_NPEERS_INC_TX_DESCS) +#define WLAN_CFG_TX_RING_SIZE 2048 +#else #define WLAN_CFG_TX_RING_SIZE 1024 +#endif +#define WLAN_CFG_IPA_TX_RING_SIZE 1024 +#define WLAN_CFG_IPA_TX_COMP_RING_SIZE 1024 + #define WLAN_CFG_PER_PDEV_TX_RING 0 #define WLAN_CFG_IPA_UC_TX_BUF_SIZE 2048 #define WLAN_CFG_IPA_UC_TX_PARTITION_BASE 3000 @@ -73,11 +81,20 @@ #define WLAN_CFG_IPA_UC_TX_PARTITION_BASE 0 #define WLAN_CFG_IPA_UC_RX_IND_RING_COUNT 0 #endif + +#if defined(TX_TO_NPEERS_INC_TX_DESCS) +#define WLAN_CFG_TX_COMP_RING_SIZE 4096 + +/* Tx Descriptor and Tx Extension Descriptor pool sizes */ +#define WLAN_CFG_NUM_TX_DESC 4096 +#define WLAN_CFG_NUM_TX_EXT_DESC 4096 +#else #define WLAN_CFG_TX_COMP_RING_SIZE 1024 /* Tx Descriptor and Tx Extension Descriptor pool sizes */ #define WLAN_CFG_NUM_TX_DESC 1024 #define WLAN_CFG_NUM_TX_EXT_DESC 1024 +#endif /* Interrupt Mitigation - Batch threshold in terms of number of frames */ #define WLAN_CFG_INT_BATCH_THRESHOLD_TX 1 @@ -88,48 +105,15 @@ #define WLAN_CFG_INT_TIMER_THRESHOLD_TX 8 #define WLAN_CFG_INT_TIMER_THRESHOLD_RX 8 #define WLAN_CFG_INT_TIMER_THRESHOLD_OTHER 8 -#else -#define WLAN_CFG_PER_PDEV_TX_RING 0 -#define WLAN_CFG_IPA_UC_TX_BUF_SIZE 0 -#define WLAN_CFG_IPA_UC_TX_PARTITION_BASE 0 -#define WLAN_CFG_IPA_UC_RX_IND_RING_COUNT 0 #endif -#ifdef CONFIG_WIN -#define WLAN_CFG_PER_PDEV_RX_RING 0 -#define WLAN_CFG_PER_PDEV_LMAC_RING 1 -#define WLAN_LRO_ENABLE 0 -#define WLAN_CFG_MAC_PER_TARGET 3 -/* Tx Descriptor and Tx Extension Descriptor pool sizes */ -#ifndef QCA_WIFI_QCA8074_VP -#define WLAN_CFG_NUM_TX_DESC 0x320000 -#else -#define WLAN_CFG_NUM_TX_DESC (8 << 10) -#endif -#define WLAN_CFG_NUM_TX_EXT_DESC 0x80000 - -/* Interrupt Mitigation - Batch threshold in terms of number of frames */ -#define WLAN_CFG_INT_BATCH_THRESHOLD_TX 256 -#define WLAN_CFG_INT_BATCH_THRESHOLD_RX 128 -#define WLAN_CFG_INT_BATCH_THRESHOLD_OTHER 1 - -/* Interrupt Mitigation - Timer threshold in us */ -#define WLAN_CFG_INT_TIMER_THRESHOLD_TX 1000 -#define WLAN_CFG_INT_TIMER_THRESHOLD_RX 500 -#define WLAN_CFG_INT_TIMER_THRESHOLD_OTHER 1000 - -#define WLAN_CFG_TX_RING_SIZE 512 +#define WLAN_CFG_RX_PENDING_HL_THRESHOLD 0x60000 +#define WLAN_CFG_RX_PENDING_HL_THRESHOLD_MIN 0 +#define WLAN_CFG_RX_PENDING_HL_THRESHOLD_MAX 0x80000 -/* Size the completion ring using following 2 parameters - * - NAPI schedule latency (assuming 1 netdev competing for CPU) - * = 20 ms (2 jiffies) - * - Worst case PPS requirement = 400K PPS - * - * Ring size = 20 * 400 = 8000 - * 8192 is nearest power of 2 - */ -#define WLAN_CFG_TX_COMP_RING_SIZE 0x80000 -#endif +#define WLAN_CFG_RX_PENDING_LO_THRESHOLD 0x60000 +#define WLAN_CFG_RX_PENDING_LO_THRESHOLD_MIN 100 +#define WLAN_CFG_RX_PENDING_LO_THRESHOLD_MAX 0x80000 #define WLAN_CFG_INT_TIMER_THRESHOLD_WBM_RELEASE_RING 256 #define WLAN_CFG_INT_TIMER_THRESHOLD_REO_RING 512 @@ -141,7 +125,7 @@ #define WLAN_CFG_PER_PDEV_LMAC_RING_MAX 1 #define WLAN_CFG_TX_RING_SIZE_MIN 512 -#define WLAN_CFG_TX_RING_SIZE_MAX 2048 +#define WLAN_CFG_TX_RING_SIZE_MAX 0x80000 #define WLAN_CFG_TX_COMP_RING_SIZE_MIN 512 #define WLAN_CFG_TX_COMP_RING_SIZE_MAX 0x80000 @@ -250,13 +234,14 @@ #define WLAN_CFG_REO_DST_RING_SIZE_MIN 1024 #define WLAN_CFG_REO_DST_RING_SIZE_MAX 2048 -#define WLAN_CFG_REO_REINJECT_RING_SIZE 32 +#define WLAN_CFG_REO_REINJECT_RING_SIZE 128 #define WLAN_CFG_REO_REINJECT_RING_SIZE_MIN 32 -#define WLAN_CFG_REO_REINJECT_RING_SIZE_MAX 32 +#define WLAN_CFG_REO_REINJECT_RING_SIZE_MAX 128 #define WLAN_CFG_RX_RELEASE_RING_SIZE 1024 #define WLAN_CFG_RX_RELEASE_RING_SIZE_MIN 8 -#if defined(QCA_WIFI_QCA6390) +#if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490) || \ + defined(QCA_WIFI_QCA6750) #define WLAN_CFG_RX_RELEASE_RING_SIZE_MAX 1024 #else #define WLAN_CFG_RX_RELEASE_RING_SIZE_MAX 8192 @@ -270,7 +255,7 @@ #define WLAN_CFG_REO_CMD_RING_SIZE_MIN 64 #define WLAN_CFG_REO_CMD_RING_SIZE_MAX 128 -#define WLAN_CFG_REO_STATUS_RING_SIZE 256 +#define WLAN_CFG_REO_STATUS_RING_SIZE 128 #define WLAN_CFG_REO_STATUS_RING_SIZE_MIN 128 #define WLAN_CFG_REO_STATUS_RING_SIZE_MAX 2048 @@ -282,6 +267,26 @@ #define WLAN_CFG_RXDMA_REFILL_RING_SIZE_MIN 16 #define WLAN_CFG_RXDMA_REFILL_RING_SIZE_MAX 4096 +#define WLAN_CFG_TX_DESC_LIMIT_0 0 +#define WLAN_CFG_TX_DESC_LIMIT_0_MIN 4096 +#define WLAN_CFG_TX_DESC_LIMIT_0_MAX 32768 + +#define WLAN_CFG_TX_DESC_LIMIT_1 0 +#define WLAN_CFG_TX_DESC_LIMIT_1_MIN 4096 +#define WLAN_CFG_TX_DESC_LIMIT_1_MAX 32768 + +#define WLAN_CFG_TX_DESC_LIMIT_2 0 +#define WLAN_CFG_TX_DESC_LIMIT_2_MIN 4096 +#define WLAN_CFG_TX_DESC_LIMIT_2_MAX 32768 + +#define WLAN_CFG_TX_DEVICE_LIMIT 65536 +#define WLAN_CFG_TX_DEVICE_LIMIT_MIN 16384 +#define WLAN_CFG_TX_DEVICE_LIMIT_MAX 65536 + +#define WLAN_CFG_TX_SW_INTERNODE_QUEUE 1024 +#define WLAN_CFG_TX_SW_INTERNODE_QUEUE_MIN 128 +#define WLAN_CFG_TX_SW_INTERNODE_QUEUE_MAX 1024 + #define WLAN_CFG_RXDMA_MONITOR_BUF_RING_SIZE 4096 #define WLAN_CFG_RXDMA_MONITOR_BUF_RING_SIZE_MIN 16 #define WLAN_CFG_RXDMA_MONITOR_BUF_RING_SIZE_MAX 8192 @@ -302,6 +307,44 @@ #define WLAN_CFG_RXDMA_ERR_DST_RING_SIZE_MIN 1024 #define WLAN_CFG_RXDMA_ERR_DST_RING_SIZE_MAX 8192 +#define WLAN_CFG_RXDMA_MONITOR_RX_DROP_THRESH_SIZE 32 +#define WLAN_CFG_RXDMA_MONITOR_RX_DROP_THRESH_SIZE_MIN 0 +#define WLAN_CFG_RXDMA_MONITOR_RX_DROP_THRESH_SIZE_MAX 256 + +/** + * Allocate as many RX descriptors as buffers in the SW2RXDMA + * ring. This value may need to be tuned later. + */ +#if defined(QCA_HOST2FW_RXBUF_RING) +#define WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE 1 +#define WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE_MIN 1 +#define WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE_MAX 1 + +/** + * For low memory AP cases using 1 will reduce the rx descriptors memory req + */ +#elif defined(QCA_LOWMEM_CONFIG) || defined(QCA_512M_CONFIG) +#define WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE 1 +#define WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE_MIN 1 +#define WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE_MAX 3 + +/** + * AP use cases need to allocate more RX Descriptors than the number of + * entries avaialable in the SW2RXDMA buffer replenish ring. This is to account + * for frames sitting in REO queues, HW-HW DMA rings etc. Hence using a + * multiplication factor of 3, to allocate three times as many RX descriptors + * as RX buffers. + */ +#else +#define WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE 3 +#define WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE_MIN 1 +#define WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE_MAX 3 +#endif //QCA_HOST2FW_RXBUF_RING + +#define WLAN_CFG_RX_FLOW_SEARCH_TABLE_SIZE 16384 +#define WLAN_CFG_RX_FLOW_SEARCH_TABLE_SIZE_MIN 1 +#define WLAN_CFG_RX_FLOW_SEARCH_TABLE_SIZE_MAX 16384 + #define WLAN_CFG_PKTLOG_BUFFER_SIZE 10 #define WLAN_CFG_PKTLOG_MIN_BUFFER_SIZE 1 #define WLAN_CFG_PKTLOG_MAX_BUFFER_SIZE 10 @@ -475,6 +518,49 @@ WLAN_CFG_PER_PDEV_LMAC_RING_MAX, \ WLAN_CFG_PER_PDEV_LMAC_RING, \ CFG_VALUE_OR_DEFAULT, "DP pdev LMAC ring") +/* + * + * dp_rx_pending_hl_threshold - High threshold of frame number to start + * frame dropping scheme + * @Min: 0 + * @Max: 524288 + * @Default: 393216 + * + * This ini entry is used to set a high limit threshold to start frame + * dropping scheme + * + * Usage: External + * + * + */ +#define CFG_DP_RX_PENDING_HL_THRESHOLD \ + CFG_INI_UINT("dp_rx_pending_hl_threshold", \ + WLAN_CFG_RX_PENDING_HL_THRESHOLD_MIN, \ + WLAN_CFG_RX_PENDING_HL_THRESHOLD_MAX, \ + WLAN_CFG_RX_PENDING_HL_THRESHOLD, \ + CFG_VALUE_OR_DEFAULT, "DP rx pending hl threshold") + +/* + * + * dp_rx_pending_lo_threshold - Low threshold of frame number to stop + * frame dropping scheme + * @Min: 100 + * @Max: 524288 + * @Default: 393216 + * + * This ini entry is used to set a low limit threshold to stop frame + * dropping scheme + * + * Usage: External + * + * + */ +#define CFG_DP_RX_PENDING_LO_THRESHOLD \ + CFG_INI_UINT("dp_rx_pending_lo_threshold", \ + WLAN_CFG_RX_PENDING_LO_THRESHOLD_MIN, \ + WLAN_CFG_RX_PENDING_LO_THRESHOLD_MAX, \ + WLAN_CFG_RX_PENDING_LO_THRESHOLD, \ + CFG_VALUE_OR_DEFAULT, "DP rx pending lo threshold") #define CFG_DP_BASE_HW_MAC_ID \ CFG_INI_UINT("dp_base_hw_macid", \ @@ -493,13 +579,66 @@ CFG_INI_BOOL("LROEnable", WLAN_LRO_ENABLE, \ "DP LRO Enable") +/* + * + * CFG_DP_SG - Enable the SG feature standalonely + * @Min: 0 + * @Max: 1 + * @Default: 1 + * + * This ini entry is used to enable/disable SG feature standalonely. + * Also does Rome support SG on TX, lithium does not. + * For example the lithium does not support SG on UDP frames. + * Which is able to handle SG only for TSO frames(in case TSO is enabled). + * + * Usage: External + * + * + */ #define CFG_DP_SG \ CFG_INI_BOOL("dp_sg_support", false, \ "DP SG Enable") +#define WLAN_CFG_GRO_ENABLE_MIN 0 +#define WLAN_CFG_GRO_ENABLE_MAX 3 +#define WLAN_CFG_GRO_ENABLE_DEFAULT 0 +#define DP_GRO_ENABLE_BIT_SET BIT(0) +#define DP_TC_BASED_DYNAMIC_GRO BIT(1) + +/* + * + * CFG_DP_GRO - Enable the GRO feature standalonely + * @Min: 0 + * @Max: 3 + * @Default: 0 + * + * This ini entry is used to enable/disable GRO feature standalonely. + * Value 0: Disable GRO feature + * Value 1: Enable GRO feature always + * Value 3: Enable GRO dynamic feature where TC rule can control GRO + * behavior + * + * Usage: External + * + * + */ #define CFG_DP_GRO \ - CFG_INI_BOOL("GROEnable", false, \ - "DP GRO Enable") + CFG_INI_UINT("GROEnable", \ + WLAN_CFG_GRO_ENABLE_MIN, \ + WLAN_CFG_GRO_ENABLE_MAX, \ + WLAN_CFG_GRO_ENABLE_DEFAULT, \ + CFG_VALUE_OR_DEFAULT, "DP GRO Enable") + +#define WLAN_CFG_TC_INGRESS_PRIO_MIN 0 +#define WLAN_CFG_TC_INGRESS_PRIO_MAX 0xFFFF +#define WLAN_CFG_TC_INGRESS_PRIO_DEFAULT 0 + +#define CFG_DP_TC_INGRESS_PRIO \ + CFG_INI_UINT("tc_ingress_prio", \ + WLAN_CFG_TC_INGRESS_PRIO_MIN, \ + WLAN_CFG_TC_INGRESS_PRIO_MAX, \ + WLAN_CFG_TC_INGRESS_PRIO_DEFAULT, \ + CFG_VALUE_OR_DEFAULT, "DP tc ingress prio") #define CFG_DP_OL_TX_CSUM \ CFG_INI_BOOL("dp_offload_tx_csum_support", false, \ @@ -518,9 +657,55 @@ "DP peer flow ctrl Enable") #define CFG_DP_NAPI \ - CFG_INI_BOOL("dp_napi_enabled", MCL_OR_WIN_VALUE(true, false), \ + CFG_INI_BOOL("dp_napi_enabled", PLATFORM_VALUE(true, false), \ "DP Napi Enabled") +/* + * + * gEnableP2pIpTcpUdpChecksumOffload - Enable checksum offload for P2P mode + * @Min: 0 + * @Max: 1 + * @Default: 1 + * + * This ini entry is used to enable/disable TX checksum(UDP/TCP) for P2P modes. + * This includes P2P device mode, P2P client mode and P2P GO mode. + * The feature is enabled by default. To disable TX checksum for P2P, add the + * following entry in ini file: + * gEnableP2pIpTcpUdpChecksumOffload=0 + * + * Usage: External + * + * + */ +#define CFG_DP_P2P_TCP_UDP_CKSUM_OFFLOAD \ + CFG_INI_BOOL("gEnableP2pIpTcpUdpChecksumOffload", true, \ + "DP TCP UDP Checksum Offload for P2P mode (device/cli/go)") +/* + * + * gEnableNanIpTcpUdpChecksumOffload - Enable NAN checksum offload + * @Min: 0 + * @Max: 1 + * @Default: 1 + * + * Usage: External + * + * + */ +#define CFG_DP_NAN_TCP_UDP_CKSUM_OFFLOAD \ + CFG_INI_BOOL("gEnableNanIpTcpUdpChecksumOffload", true, \ + "DP TCP UDP Checksum Offload for NAN mode") + +/* + * + * gEnableIpTcpUdpChecksumOffload - Enable checksum offload + * @Min: 0 + * @Max: 1 + * @Default: 1 + * + * Usage: External + * + * + */ #define CFG_DP_TCP_UDP_CKSUM_OFFLOAD \ CFG_INI_BOOL("gEnableIpTcpUdpChecksumOffload", true, \ "DP TCP UDP Checksum Offload") @@ -599,6 +784,41 @@ WLAN_CFG_RXDMA_REFILL_RING_SIZE, \ CFG_VALUE_OR_DEFAULT, "DP RXDMA refilll ring") +#define CFG_DP_TX_DESC_LIMIT_0 \ + CFG_INI_UINT("dp_tx_desc_limit_0", \ + WLAN_CFG_TX_DESC_LIMIT_0_MIN, \ + WLAN_CFG_TX_DESC_LIMIT_0_MAX, \ + WLAN_CFG_TX_DESC_LIMIT_0, \ + CFG_VALUE_OR_DEFAULT, "DP TX DESC limit 0") + +#define CFG_DP_TX_DESC_LIMIT_1 \ + CFG_INI_UINT("dp_tx_desc_limit_1", \ + WLAN_CFG_TX_DESC_LIMIT_1_MIN, \ + WLAN_CFG_TX_DESC_LIMIT_1_MAX, \ + WLAN_CFG_TX_DESC_LIMIT_1, \ + CFG_VALUE_OR_DEFAULT, "DP TX DESC limit 1") + +#define CFG_DP_TX_DESC_LIMIT_2 \ + CFG_INI_UINT("dp_tx_desc_limit_2", \ + WLAN_CFG_TX_DESC_LIMIT_2_MIN, \ + WLAN_CFG_TX_DESC_LIMIT_2_MAX, \ + WLAN_CFG_TX_DESC_LIMIT_2, \ + CFG_VALUE_OR_DEFAULT, "DP TX DESC limit 2") + +#define CFG_DP_TX_DEVICE_LIMIT \ + CFG_INI_UINT("dp_tx_device_limit", \ + WLAN_CFG_TX_DEVICE_LIMIT_MIN, \ + WLAN_CFG_TX_DEVICE_LIMIT_MAX, \ + WLAN_CFG_TX_DEVICE_LIMIT, \ + CFG_VALUE_OR_DEFAULT, "DP TX DEVICE limit") + +#define CFG_DP_TX_SW_INTERNODE_QUEUE \ + CFG_INI_UINT("dp_tx_sw_internode_queue", \ + WLAN_CFG_TX_SW_INTERNODE_QUEUE_MIN, \ + WLAN_CFG_TX_SW_INTERNODE_QUEUE_MAX, \ + WLAN_CFG_TX_SW_INTERNODE_QUEUE, \ + CFG_VALUE_OR_DEFAULT, "DP TX SW internode queue") + #define CFG_DP_RXDMA_MONITOR_BUF_RING \ CFG_INI_UINT("dp_rxdma_monitor_buf_ring", \ WLAN_CFG_RXDMA_MONITOR_BUF_RING_SIZE_MIN, \ @@ -677,6 +897,61 @@ CFG_INI_BOOL("gEnableDataStallDetection", \ true, "Enable/Disable Data stall detection") +#define CFG_DP_RX_SW_DESC_WEIGHT \ + CFG_INI_UINT("dp_rx_sw_desc_weight", \ + WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE_MIN, \ + WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE_MAX, \ + WLAN_CFG_RX_SW_DESC_WEIGHT_SIZE, \ + CFG_VALUE_OR_DEFAULT, "DP RX SW DESC weight") + +#define CFG_DP_RX_FLOW_SEARCH_TABLE_SIZE \ + CFG_INI_UINT("dp_rx_flow_search_table_size", \ + WLAN_CFG_RX_FLOW_SEARCH_TABLE_SIZE_MIN, \ + WLAN_CFG_RX_FLOW_SEARCH_TABLE_SIZE_MAX, \ + WLAN_CFG_RX_FLOW_SEARCH_TABLE_SIZE, \ + CFG_VALUE_OR_DEFAULT, \ + "DP Rx Flow Search Table Size in number of entries") + +#define CFG_DP_RX_FLOW_TAG_ENABLE \ + CFG_INI_BOOL("dp_rx_flow_tag_enable", false, \ + "Enable/Disable DP Rx Flow Tag") + +#define CFG_DP_RX_FLOW_SEARCH_TABLE_PER_PDEV \ + CFG_INI_BOOL("dp_rx_per_pdev_flow_search", false, \ + "DP Rx Flow Search Table Is Per PDev") + +#define CFG_DP_RX_MON_PROTOCOL_FLOW_TAG_ENABLE \ + CFG_INI_BOOL("dp_rx_monitor_protocol_flow_tag_enable", true, \ + "Enable/Disable Rx Protocol & Flow tags in Monitor mode") + +/* + * + * dp_rx_fisa_enable - Control Rx datapath FISA + * @Min: 0 + * @Max: 1 + * @Default: 0 + * + * This ini is used to enable DP Rx FISA feature + * + * Related: dp_rx_flow_search_table_size + * + * Supported Feature: STA,P2P and SAP IPA disabled terminating + * + * Usage: Internal/External + * + * + */ +#define CFG_DP_RX_FISA_ENABLE \ + CFG_INI_BOOL("dp_rx_fisa_enable", false, \ + "Enable/Disable DP Rx FISA") + +#define CFG_DP_RXDMA_MONITOR_RX_DROP_THRESHOLD \ + CFG_INI_UINT("mon_drop_thresh", \ + WLAN_CFG_RXDMA_MONITOR_RX_DROP_THRESH_SIZE_MIN, \ + WLAN_CFG_RXDMA_MONITOR_RX_DROP_THRESH_SIZE_MAX, \ + WLAN_CFG_RXDMA_MONITOR_RX_DROP_THRESH_SIZE, \ + CFG_VALUE_OR_DEFAULT, "RXDMA monitor rx drop theshold") + #define CFG_DP_PKTLOG_BUFFER_SIZE \ CFG_INI_UINT("PktlogBufSize", \ WLAN_CFG_PKTLOG_MIN_BUFFER_SIZE, \ @@ -684,6 +959,64 @@ WLAN_CFG_PKTLOG_BUFFER_SIZE, \ CFG_VALUE_OR_DEFAULT, "Packet Log buffer size") +/* + * + * legacy_mode_csum_disable - Disable csum offload for legacy 802.11abg modes + * @Min: 0 + * @Max: 1 + * @Default: 0 + * + * This ini is used to disable HW checksum offload capability for legacy + * connections + * + * Related: gEnableIpTcpUdpChecksumOffload should be enabled + * + * Usage: Internal + * + * + */ + +#define CFG_DP_LEGACY_MODE_CSUM_DISABLE \ + CFG_INI_BOOL("legacy_mode_csum_disable", false, \ + "Enable/Disable legacy mode checksum") + +/* + * + * wow_check_rx_pending_enable - control to check RX frames pending in Wow + * @Min: 0 + * @Max: 1 + * @Default: 0 + * + * This ini is used to control DP Software to perform RX pending check + * before entering WoW mode + * + * Usage: Internal + * + * + */ +#define CFG_DP_WOW_CHECK_RX_PENDING \ + CFG_INI_BOOL("wow_check_rx_pending_enable", \ + false, \ + "enable rx frame pending check in WoW mode") + +/* + * + * gForceRX64BA - enable force 64 blockack mode for RX + * @Min: 0 + * @Max: 1 + * @Default: 0 + * + * This ini is used to control DP Software to use 64 blockack + * for RX direction forcibly + * + * Usage: Internal + * + * + */ +#define CFG_FORCE_RX_64_BA \ + CFG_INI_BOOL("gForceRX64BA", \ + false, "Enable/Disable force 64 blockack in RX side") + #define CFG_DP \ CFG(CFG_DP_HTT_PACKET_TYPE) \ CFG(CFG_DP_INT_BATCH_THRESHOLD_OTHER) \ @@ -713,12 +1046,15 @@ CFG(CFG_DP_LRO) \ CFG(CFG_DP_SG) \ CFG(CFG_DP_GRO) \ + CFG(CFG_DP_TC_INGRESS_PRIO) \ CFG(CFG_DP_OL_TX_CSUM) \ CFG(CFG_DP_OL_RX_CSUM) \ CFG(CFG_DP_RAWMODE) \ CFG(CFG_DP_PEER_FLOW_CTRL) \ CFG(CFG_DP_NAPI) \ CFG(CFG_DP_TCP_UDP_CKSUM_OFFLOAD) \ + CFG(CFG_DP_NAN_TCP_UDP_CKSUM_OFFLOAD) \ + CFG(CFG_DP_P2P_TCP_UDP_CKSUM_OFFLOAD) \ CFG(CFG_DP_DEFRAG_TIMEOUT_CHECK) \ CFG(CFG_DP_WBM_RELEASE_RING) \ CFG(CFG_DP_TCL_CMD_RING) \ @@ -730,6 +1066,11 @@ CFG(CFG_DP_REO_STATUS_RING) \ CFG(CFG_DP_RXDMA_BUF_RING) \ CFG(CFG_DP_RXDMA_REFILL_RING) \ + CFG(CFG_DP_TX_DESC_LIMIT_0) \ + CFG(CFG_DP_TX_DESC_LIMIT_1) \ + CFG(CFG_DP_TX_DESC_LIMIT_2) \ + CFG(CFG_DP_TX_DEVICE_LIMIT) \ + CFG(CFG_DP_TX_SW_INTERNODE_QUEUE) \ CFG(CFG_DP_RXDMA_MONITOR_BUF_RING) \ CFG(CFG_DP_RXDMA_MONITOR_DST_RING) \ CFG(CFG_DP_RXDMA_MONITOR_STATUS_RING) \ @@ -744,6 +1085,17 @@ CFG(CFG_DP_REORDER_OFFLOAD_SUPPORT) \ CFG(CFG_DP_AP_STA_SECURITY_SEPERATION) \ CFG(CFG_DP_ENABLE_DATA_STALL_DETECTION) \ - CFG(CFG_DP_PKTLOG_BUFFER_SIZE) - + CFG(CFG_DP_RX_SW_DESC_WEIGHT) \ + CFG(CFG_DP_RX_FLOW_SEARCH_TABLE_SIZE) \ + CFG(CFG_DP_RX_FLOW_TAG_ENABLE) \ + CFG(CFG_DP_RX_FLOW_SEARCH_TABLE_PER_PDEV) \ + CFG(CFG_DP_RX_MON_PROTOCOL_FLOW_TAG_ENABLE) \ + CFG(CFG_DP_RXDMA_MONITOR_RX_DROP_THRESHOLD) \ + CFG(CFG_DP_PKTLOG_BUFFER_SIZE) \ + CFG(CFG_DP_RX_FISA_ENABLE) \ + CFG(CFG_DP_LEGACY_MODE_CSUM_DISABLE) \ + CFG(CFG_DP_RX_PENDING_HL_THRESHOLD) \ + CFG(CFG_DP_RX_PENDING_LO_THRESHOLD) \ + CFG(CFG_DP_WOW_CHECK_RX_PENDING) \ + CFG(CFG_FORCE_RX_64_BA) #endif /* _CFG_DP_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/wlan_cfg/wlan_cfg.c b/drivers/staging/qca-wifi-host-cmn/wlan_cfg/wlan_cfg.c index 238f3ccddf02707313835ef721c57322db3848ac..e760e8fe8938372610c39448bd3217bf86003fa8 100644 --- a/drivers/staging/qca-wifi-host-cmn/wlan_cfg/wlan_cfg.c +++ b/drivers/staging/qca-wifi-host-cmn/wlan_cfg/wlan_cfg.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -28,6 +29,7 @@ #include "wlan_cfg.h" #include "cfg_ucfg_api.h" #include "hal_api.h" +#include "dp_types.h" /* * FIX THIS - @@ -90,49 +92,130 @@ #define WLAN_CFG_HOST2RXDMA_RING_MASK_2 0x4 #define WLAN_CFG_HOST2RXDMA_RING_MASK_3 0x0 -#ifdef CONFIG_MCL -static const int tx_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +#if defined(WLAN_MAX_PDEVS) && (WLAN_MAX_PDEVS == 1) +static const int tx_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_TX_RING_MASK_0, 0, 0, 0, 0, 0, 0}; #ifndef IPA_OFFLOAD -static const int rx_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rx_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, WLAN_CFG_RX_RING_MASK_0, WLAN_CFG_RX_RING_MASK_1, WLAN_CFG_RX_RING_MASK_2, WLAN_CFG_RX_RING_MASK_3, 0, 0}; #else -static const int rx_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rx_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, WLAN_CFG_RX_RING_MASK_0, WLAN_CFG_RX_RING_MASK_1, WLAN_CFG_RX_RING_MASK_2, 0, 0, 0}; #endif -static const int rx_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rx_mon_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, WLAN_CFG_RX_MON_RING_MASK_0, WLAN_CFG_RX_MON_RING_MASK_1, 0, 0, 0, 0}; -static const int host2rxdma_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int host2rxdma_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, 0, 0, 0, 0, 0, 0}; -static const int rxdma2host_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rxdma2host_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, 0, 0, 0, 0, WLAN_CFG_RXDMA2HOST_RING_MASK_0, WLAN_CFG_RXDMA2HOST_RING_MASK_1}; -static const int host2rxdma_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int host2rxdma_mon_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, 0, 0, 0, 0, 0, 0}; -static const int rxdma2host_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rxdma2host_mon_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, 0, 0, 0, 0, 0, 0}; -static const int rx_err_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rx_err_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, 0, 0, 0, 0, 0, WLAN_CFG_RX_ERR_RING_MASK_0}; -static const int rx_wbm_rel_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rx_wbm_rel_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, 0, 0, 0, 0, 0, WLAN_CFG_RX_WBM_REL_RING_MASK_0}; -static const int reo_status_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int reo_status_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, 0, 0, 0, 0, 0, WLAN_CFG_REO_STATUS_RING_MASK_0}; + +static const int tx_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0, 0, 0, 0}; + +static const int rx_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0, 0, 0, 0}; + +static const int rx_mon_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0, 0, 0, 0}; + +static const int host2rxdma_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0, 0, 0, 0}; + +static const int rxdma2host_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0, 0, 0, 0}; + +static const int host2rxdma_mon_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0, 0, 0, 0}; + +static const int rxdma2host_mon_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0, 0, 0, 0}; + +static const int rx_err_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0, 0, 0, 0}; + +static const int rx_wbm_rel_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0, 0, 0, 0}; + +static const int reo_status_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0, 0, 0, 0}; + #else -static const int tx_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { + +static const int tx_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_TX_RING_MASK_0, WLAN_CFG_TX_RING_MASK_1, WLAN_CFG_TX_RING_MASK_2, WLAN_CFG_TX_RING_MASK_3}; -static const int rx_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rx_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { + WLAN_CFG_RX_RING_MASK_0, + WLAN_CFG_RX_RING_MASK_1, + WLAN_CFG_RX_RING_MASK_2, + WLAN_CFG_RX_RING_MASK_3}; + +static const int rx_mon_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0}; + +static const int host2rxdma_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0}; + +static const int rxdma2host_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { + 0, 0, 0, 0}; + +static const int host2rxdma_mon_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { + WLAN_CFG_HOST2RXDMA_MON_RING_MASK_0, + WLAN_CFG_HOST2RXDMA_MON_RING_MASK_1, + WLAN_CFG_HOST2RXDMA_MON_RING_MASK_2}; + +static const int rxdma2host_mon_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { + WLAN_CFG_RXDMA2HOST_MON_RING_MASK_0, + WLAN_CFG_RXDMA2HOST_MON_RING_MASK_1, + WLAN_CFG_RXDMA2HOST_MON_RING_MASK_2}; + +static const int rx_err_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { + WLAN_CFG_RX_ERR_RING_MASK_0, + WLAN_CFG_RX_ERR_RING_MASK_1, + WLAN_CFG_RX_ERR_RING_MASK_2, + WLAN_CFG_RX_ERR_RING_MASK_3}; + +static const int rx_wbm_rel_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { + WLAN_CFG_RX_WBM_REL_RING_MASK_0, + WLAN_CFG_RX_WBM_REL_RING_MASK_1, + WLAN_CFG_RX_WBM_REL_RING_MASK_2, + WLAN_CFG_RX_WBM_REL_RING_MASK_3}; + +static const int reo_status_ring_mask_msi[WLAN_CFG_INT_NUM_CONTEXTS] = { + WLAN_CFG_REO_STATUS_RING_MASK_0, + WLAN_CFG_REO_STATUS_RING_MASK_1, + WLAN_CFG_REO_STATUS_RING_MASK_2, + WLAN_CFG_REO_STATUS_RING_MASK_3}; + +static const int tx_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { + WLAN_CFG_TX_RING_MASK_0, + WLAN_CFG_TX_RING_MASK_1, + WLAN_CFG_TX_RING_MASK_2, + WLAN_CFG_TX_RING_MASK_3}; + +static const int rx_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, 0, 0, @@ -145,7 +228,7 @@ static const int rx_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_RX_RING_MASK_2, WLAN_CFG_RX_RING_MASK_3}; -static const int rx_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rx_mon_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, 0, 0, @@ -154,19 +237,19 @@ static const int rx_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_RX_MON_RING_MASK_1, WLAN_CFG_RX_MON_RING_MASK_2}; -static const int host2rxdma_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int host2rxdma_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_HOST2RXDMA_RING_MASK_0, WLAN_CFG_HOST2RXDMA_RING_MASK_1, WLAN_CFG_HOST2RXDMA_RING_MASK_2, WLAN_CFG_HOST2RXDMA_RING_MASK_3}; -static const int rxdma2host_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rxdma2host_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_RXDMA2HOST_RING_MASK_0, WLAN_CFG_RXDMA2HOST_RING_MASK_1, WLAN_CFG_RXDMA2HOST_RING_MASK_2, WLAN_CFG_RXDMA2HOST_RING_MASK_3}; -static const int host2rxdma_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int host2rxdma_mon_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, 0, 0, @@ -175,7 +258,7 @@ static const int host2rxdma_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_HOST2RXDMA_MON_RING_MASK_1, WLAN_CFG_HOST2RXDMA_MON_RING_MASK_2}; -static const int rxdma2host_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rxdma2host_mon_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { 0, 0, 0, @@ -184,24 +267,24 @@ static const int rxdma2host_mon_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_RXDMA2HOST_MON_RING_MASK_1, WLAN_CFG_RXDMA2HOST_MON_RING_MASK_2}; -static const int rx_err_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rx_err_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_RX_ERR_RING_MASK_0, WLAN_CFG_RX_ERR_RING_MASK_1, WLAN_CFG_RX_ERR_RING_MASK_2, WLAN_CFG_RX_ERR_RING_MASK_3}; -static const int rx_wbm_rel_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int rx_wbm_rel_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_RX_WBM_REL_RING_MASK_0, WLAN_CFG_RX_WBM_REL_RING_MASK_1, WLAN_CFG_RX_WBM_REL_RING_MASK_2, WLAN_CFG_RX_WBM_REL_RING_MASK_3}; -static const int reo_status_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { +static const int reo_status_ring_mask_integrated[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_REO_STATUS_RING_MASK_0, WLAN_CFG_REO_STATUS_RING_MASK_1, WLAN_CFG_REO_STATUS_RING_MASK_2, WLAN_CFG_REO_STATUS_RING_MASK_3}; -#endif /*CONFIG_MCL*/ +#endif /* MAX_PDEV_CNT == 1 */ /** * g_wlan_srng_cfg[] - Per ring_type specific configuration @@ -279,17 +362,86 @@ void wlan_set_srng_cfg(struct wlan_srng_cfg **wlan_cfg) *wlan_cfg = g_wlan_srng_cfg; } +static const uint8_t rx_fst_toeplitz_key[WLAN_CFG_RX_FST_TOEPLITZ_KEYLEN] = { + 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, + 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, + 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4, + 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c, + 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa +}; + +void wlan_cfg_fill_interrupt_mask(struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx, + int interrupt_mode, + bool is_monitor_mode) { + int i = 0; + + if (interrupt_mode == DP_INTR_INTEGRATED) { + for (i = 0; i < WLAN_CFG_INT_NUM_CONTEXTS; i++) { + wlan_cfg_ctx->int_tx_ring_mask[i] = + tx_ring_mask_integrated[i]; + wlan_cfg_ctx->int_rx_ring_mask[i] = + rx_ring_mask_integrated[i]; + wlan_cfg_ctx->int_rx_mon_ring_mask[i] = + rx_mon_ring_mask_integrated[i]; + wlan_cfg_ctx->int_rx_err_ring_mask[i] = + rx_err_ring_mask_integrated[i]; + wlan_cfg_ctx->int_rx_wbm_rel_ring_mask[i] = + rx_wbm_rel_ring_mask_integrated[i]; + wlan_cfg_ctx->int_reo_status_ring_mask[i] = + reo_status_ring_mask_integrated[i]; + wlan_cfg_ctx->int_rxdma2host_ring_mask[i] = + rxdma2host_ring_mask_integrated[i]; + wlan_cfg_ctx->int_host2rxdma_ring_mask[i] = + host2rxdma_ring_mask_integrated[i]; + wlan_cfg_ctx->int_host2rxdma_mon_ring_mask[i] = + host2rxdma_mon_ring_mask_integrated[i]; + wlan_cfg_ctx->int_rxdma2host_mon_ring_mask[i] = + rxdma2host_mon_ring_mask_integrated[i]; + } + } else if (interrupt_mode == DP_INTR_MSI || interrupt_mode == + DP_INTR_POLL) { + for (i = 0; i < WLAN_CFG_INT_NUM_CONTEXTS; i++) { + wlan_cfg_ctx->int_tx_ring_mask[i] = tx_ring_mask_msi[i]; + wlan_cfg_ctx->int_rx_mon_ring_mask[i] = + rx_mon_ring_mask_msi[i]; + wlan_cfg_ctx->int_rx_err_ring_mask[i] = + rx_err_ring_mask_msi[i]; + wlan_cfg_ctx->int_rx_wbm_rel_ring_mask[i] = + rx_wbm_rel_ring_mask_msi[i]; + wlan_cfg_ctx->int_reo_status_ring_mask[i] = + reo_status_ring_mask_msi[i]; + if (is_monitor_mode) { + wlan_cfg_ctx->int_rx_ring_mask[i] = 0; + wlan_cfg_ctx->int_rxdma2host_ring_mask[i] = 0; + } else { + wlan_cfg_ctx->int_rx_ring_mask[i] = + rx_ring_mask_msi[i]; + wlan_cfg_ctx->int_rxdma2host_ring_mask[i] = + rxdma2host_ring_mask_msi[i]; + } + wlan_cfg_ctx->int_host2rxdma_ring_mask[i] = + host2rxdma_ring_mask_msi[i]; + wlan_cfg_ctx->int_host2rxdma_mon_ring_mask[i] = + host2rxdma_mon_ring_mask_msi[i]; + wlan_cfg_ctx->int_rxdma2host_mon_ring_mask[i] = + rxdma2host_mon_ring_mask_msi[i]; + } + } else { + qdf_err("Interrupt mode %d", interrupt_mode); + } +} + /** * wlan_cfg_soc_attach() - Allocate and prepare SoC configuration * @psoc - Object manager psoc * Return: wlan_cfg_ctx - Handle to Configuration context */ -struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach(void *psoc) +struct wlan_cfg_dp_soc_ctxt * +wlan_cfg_soc_attach(struct cdp_ctrl_objmgr_psoc *psoc) { - int i = 0; - struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx = qdf_mem_malloc(sizeof(struct wlan_cfg_dp_soc_ctxt)); + uint32_t gro_bit_set; if (!wlan_cfg_ctx) return NULL; @@ -334,32 +486,13 @@ struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach(void *psoc) wlan_cfg_ctx->pktlog_buffer_size = cfg_get(psoc, CFG_DP_PKTLOG_BUFFER_SIZE); - for (i = 0; i < WLAN_CFG_INT_NUM_CONTEXTS; i++) { - wlan_cfg_ctx->int_tx_ring_mask[i] = tx_ring_mask[i]; - wlan_cfg_ctx->int_rx_ring_mask[i] = rx_ring_mask[i]; - wlan_cfg_ctx->int_rx_mon_ring_mask[i] = rx_mon_ring_mask[i]; - wlan_cfg_ctx->int_rx_err_ring_mask[i] = rx_err_ring_mask[i]; - wlan_cfg_ctx->int_rx_wbm_rel_ring_mask[i] = - rx_wbm_rel_ring_mask[i]; - wlan_cfg_ctx->int_reo_status_ring_mask[i] = - reo_status_ring_mask[i]; - wlan_cfg_ctx->int_rxdma2host_ring_mask[i] = - rxdma2host_ring_mask[i]; - wlan_cfg_ctx->int_host2rxdma_ring_mask[i] = - host2rxdma_ring_mask[i]; - wlan_cfg_ctx->int_host2rxdma_mon_ring_mask[i] = - host2rxdma_mon_ring_mask[i]; - wlan_cfg_ctx->int_rxdma2host_mon_ring_mask[i] = - rxdma2host_mon_ring_mask[i]; - } - /* This is default mapping and can be overridden by HW config * received from FW */ - wlan_cfg_set_hw_macid(wlan_cfg_ctx, 0, 1); + wlan_cfg_set_hw_mac_idx(wlan_cfg_ctx, 0, 0); if (MAX_PDEV_CNT > 1) - wlan_cfg_set_hw_macid(wlan_cfg_ctx, 1, 3); + wlan_cfg_set_hw_mac_idx(wlan_cfg_ctx, 1, 2); if (MAX_PDEV_CNT > 2) - wlan_cfg_set_hw_macid(wlan_cfg_ctx, 2, 2); + wlan_cfg_set_hw_mac_idx(wlan_cfg_ctx, 2, 1); wlan_cfg_ctx->base_hw_macid = cfg_get(psoc, CFG_DP_BASE_HW_MAC_ID); @@ -367,16 +500,27 @@ struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach(void *psoc) wlan_cfg_ctx->tso_enabled = cfg_get(psoc, CFG_DP_TSO); wlan_cfg_ctx->lro_enabled = cfg_get(psoc, CFG_DP_LRO); wlan_cfg_ctx->sg_enabled = cfg_get(psoc, CFG_DP_SG); - wlan_cfg_ctx->gro_enabled = cfg_get(psoc, CFG_DP_GRO); + gro_bit_set = cfg_get(psoc, CFG_DP_GRO); + if (gro_bit_set & DP_GRO_ENABLE_BIT_SET) { + wlan_cfg_ctx->gro_enabled = true; + if (gro_bit_set & DP_TC_BASED_DYNAMIC_GRO) + wlan_cfg_ctx->tc_based_dynamic_gro = true; + } + wlan_cfg_ctx->tc_ingress_prio = cfg_get(psoc, CFG_DP_TC_INGRESS_PRIO); wlan_cfg_ctx->ol_tx_csum_enabled = cfg_get(psoc, CFG_DP_OL_TX_CSUM); wlan_cfg_ctx->ol_rx_csum_enabled = cfg_get(psoc, CFG_DP_OL_RX_CSUM); wlan_cfg_ctx->rawmode_enabled = cfg_get(psoc, CFG_DP_RAWMODE); wlan_cfg_ctx->peer_flow_ctrl_enabled = cfg_get(psoc, CFG_DP_PEER_FLOW_CTRL); wlan_cfg_ctx->napi_enabled = cfg_get(psoc, CFG_DP_NAPI); - /*Enable checksum offload by default*/ + wlan_cfg_ctx->p2p_tcp_udp_checksumoffload = + cfg_get(psoc, CFG_DP_P2P_TCP_UDP_CKSUM_OFFLOAD); + wlan_cfg_ctx->nan_tcp_udp_checksumoffload = + cfg_get(psoc, CFG_DP_NAN_TCP_UDP_CKSUM_OFFLOAD); wlan_cfg_ctx->tcp_udp_checksumoffload = cfg_get(psoc, CFG_DP_TCP_UDP_CKSUM_OFFLOAD); + wlan_cfg_ctx->legacy_mode_checksumoffload_disable = + cfg_get(psoc, CFG_DP_LEGACY_MODE_CSUM_DISABLE); wlan_cfg_ctx->per_pkt_trace = cfg_get(psoc, CFG_DP_PER_PKT_LOGGING); wlan_cfg_ctx->defrag_timeout_check = cfg_get(psoc, CFG_DP_DEFRAG_TIMEOUT_CHECK); @@ -401,16 +545,49 @@ struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach(void *psoc) CFG_DP_REO_STATUS_RING); wlan_cfg_ctx->rxdma_refill_ring = cfg_get(psoc, CFG_DP_RXDMA_REFILL_RING); + wlan_cfg_ctx->tx_desc_limit_0 = cfg_get(psoc, + CFG_DP_TX_DESC_LIMIT_0); + wlan_cfg_ctx->tx_desc_limit_1 = cfg_get(psoc, + CFG_DP_TX_DESC_LIMIT_1); + wlan_cfg_ctx->tx_desc_limit_2 = cfg_get(psoc, + CFG_DP_TX_DESC_LIMIT_2); + wlan_cfg_ctx->tx_device_limit = cfg_get(psoc, + CFG_DP_TX_DEVICE_LIMIT); + wlan_cfg_ctx->tx_sw_internode_queue = cfg_get(psoc, + CFG_DP_TX_SW_INTERNODE_QUEUE); wlan_cfg_ctx->rxdma_err_dst_ring = cfg_get(psoc, CFG_DP_RXDMA_ERR_DST_RING); wlan_cfg_ctx->enable_data_stall_detection = cfg_get(psoc, CFG_DP_ENABLE_DATA_STALL_DETECTION); + wlan_cfg_ctx->enable_force_rx_64_ba = + cfg_get(psoc, CFG_FORCE_RX_64_BA); wlan_cfg_ctx->tx_flow_start_queue_offset = cfg_get(psoc, CFG_DP_TX_FLOW_START_QUEUE_OFFSET); wlan_cfg_ctx->tx_flow_stop_queue_threshold = cfg_get(psoc, CFG_DP_TX_FLOW_STOP_QUEUE_TH); wlan_cfg_ctx->disable_intra_bss_fwd = cfg_get(psoc, CFG_DP_AP_STA_SECURITY_SEPERATION); + wlan_cfg_ctx->rx_sw_desc_weight = cfg_get(psoc, + CFG_DP_RX_SW_DESC_WEIGHT); + wlan_cfg_ctx->rx_toeplitz_hash_key = (uint8_t *)rx_fst_toeplitz_key; + wlan_cfg_ctx->rx_flow_max_search = WLAN_CFG_RX_FST_MAX_SEARCH; + wlan_cfg_ctx->is_rx_flow_tag_enabled = + cfg_get(psoc, CFG_DP_RX_FLOW_TAG_ENABLE); + wlan_cfg_ctx->is_rx_flow_search_table_per_pdev = + cfg_get(psoc, CFG_DP_RX_FLOW_SEARCH_TABLE_PER_PDEV); + wlan_cfg_ctx->rx_flow_search_table_size = + cfg_get(psoc, CFG_DP_RX_FLOW_SEARCH_TABLE_SIZE); + wlan_cfg_ctx->is_rx_mon_protocol_flow_tag_enabled = + cfg_get(psoc, CFG_DP_RX_MON_PROTOCOL_FLOW_TAG_ENABLE); + wlan_cfg_ctx->mon_drop_thresh = + cfg_get(psoc, CFG_DP_RXDMA_MONITOR_RX_DROP_THRESHOLD); + wlan_cfg_ctx->is_rx_fisa_enabled = cfg_get(psoc, CFG_DP_RX_FISA_ENABLE); + wlan_cfg_ctx->rx_pending_high_threshold = + cfg_get(psoc, CFG_DP_RX_PENDING_HL_THRESHOLD); + wlan_cfg_ctx->rx_pending_low_threshold = + cfg_get(psoc, CFG_DP_RX_PENDING_LO_THRESHOLD); + wlan_cfg_ctx->wow_check_rx_pending_enable = + cfg_get(psoc, CFG_DP_WOW_CHECK_RX_PENDING); return wlan_cfg_ctx; } @@ -420,7 +597,8 @@ void wlan_cfg_soc_detach(struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx) qdf_mem_free(wlan_cfg_ctx); } -struct wlan_cfg_dp_pdev_ctxt *wlan_cfg_pdev_attach(void *psoc) +struct wlan_cfg_dp_pdev_ctxt * +wlan_cfg_pdev_attach(struct cdp_ctrl_objmgr_psoc *psoc) { struct wlan_cfg_dp_pdev_ctxt *wlan_cfg_ctx = qdf_mem_malloc(sizeof(struct wlan_cfg_dp_pdev_ctxt)); @@ -449,6 +627,11 @@ void wlan_cfg_pdev_detach(struct wlan_cfg_dp_pdev_ctxt *wlan_cfg_ctx) qdf_mem_free(wlan_cfg_ctx); } +int wlan_cfg_get_mon_drop_thresh(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->mon_drop_thresh; +} + void wlan_cfg_set_num_contexts(struct wlan_cfg_dp_soc_ctxt *cfg, int num) { cfg->num_int_ctxts = num; @@ -535,23 +718,45 @@ int wlan_cfg_get_host2rxdma_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, return cfg->int_host2rxdma_ring_mask[context]; } -void wlan_cfg_set_hw_macid(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx, - int hw_macid) +void wlan_cfg_set_hw_mac_idx(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx, + int hw_macid) { qdf_assert_always(pdev_idx < MAX_PDEV_CNT); cfg->hw_macid[pdev_idx] = hw_macid; } -int wlan_cfg_get_hw_macid(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx) +int wlan_cfg_get_hw_mac_idx(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx) { qdf_assert_always(pdev_idx < MAX_PDEV_CNT); return cfg->hw_macid[pdev_idx]; } -int wlan_cfg_get_hw_mac_idx(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx) +int wlan_cfg_get_target_pdev_id(struct wlan_cfg_dp_soc_ctxt *cfg, + int hw_macid) +{ + int idx; + + for (idx = 0; idx < MAX_PDEV_CNT; idx++) { + if (cfg->hw_macid[idx] == hw_macid) + return (idx + 1); + } + qdf_assert_always(idx < MAX_PDEV_CNT); + return WLAN_INVALID_PDEV_ID; +} + +void wlan_cfg_set_pdev_idx(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx, + int hw_macid) { qdf_assert_always(pdev_idx < MAX_PDEV_CNT); - return cfg->hw_macid[pdev_idx] - cfg->base_hw_macid; + qdf_assert_always(hw_macid < MAX_NUM_LMAC_HW); + + cfg->hw_macid_pdev_id_map[hw_macid] = pdev_idx; +} + +int wlan_cfg_get_pdev_idx(struct wlan_cfg_dp_soc_ctxt *cfg, int hw_macid) +{ + qdf_assert_always(hw_macid < MAX_NUM_LMAC_HW); + return cfg->hw_macid_pdev_id_map[hw_macid]; } void wlan_cfg_set_ce_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, @@ -642,6 +847,18 @@ int wlan_cfg_per_pdev_tx_ring(struct wlan_cfg_dp_soc_ctxt *cfg) return cfg->per_pdev_tx_ring; } +uint32_t +wlan_cfg_rx_pending_hl_threshold(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->rx_pending_high_threshold; +} + +uint32_t +wlan_cfg_rx_pending_lo_threshold(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->rx_pending_low_threshold; +} + int wlan_cfg_per_pdev_lmac_ring(struct wlan_cfg_dp_soc_ctxt *cfg) { return cfg->per_pdev_lmac_ring; @@ -863,6 +1080,16 @@ int wlan_cfg_get_int_timer_threshold_mon(struct wlan_cfg_dp_soc_ctxt *cfg) return cfg->int_timer_threshold_mon; } +int wlan_cfg_get_p2p_checksum_offload(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->p2p_tcp_udp_checksumoffload; +} + +int wlan_cfg_get_nan_checksum_offload(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->nan_tcp_udp_checksumoffload; +} + int wlan_cfg_get_checksum_offload(struct wlan_cfg_dp_soc_ctxt *cfg) { return cfg->tcp_udp_checksumoffload; @@ -932,12 +1159,48 @@ wlan_cfg_get_dp_soc_rxdma_refill_ring_size(struct wlan_cfg_dp_soc_ctxt *cfg) return cfg->rxdma_refill_ring; } +int +wlan_cfg_get_dp_soc_tx_desc_limit_0(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->tx_desc_limit_0; +} + +int +wlan_cfg_get_dp_soc_tx_desc_limit_1(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->tx_desc_limit_1; +} + +int +wlan_cfg_get_dp_soc_tx_desc_limit_2(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->tx_desc_limit_2; +} + +int +wlan_cfg_get_dp_soc_tx_device_limit(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->tx_device_limit; +} + +int +wlan_cfg_get_dp_soc_tx_sw_internode_queue(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->tx_sw_internode_queue; +} + int wlan_cfg_get_dp_soc_rxdma_err_dst_ring_size(struct wlan_cfg_dp_soc_ctxt *cfg) { return cfg->rxdma_err_dst_ring; } +int +wlan_cfg_get_dp_soc_rx_sw_desc_weight(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->rx_sw_desc_weight; +} + bool wlan_cfg_get_dp_caps(struct wlan_cfg_dp_soc_ctxt *cfg, enum cdp_capabilities dp_caps) @@ -988,3 +1251,78 @@ int wlan_cfg_get_tx_flow_start_queue_offset(struct wlan_cfg_dp_soc_ctxt *cfg) return cfg->tx_flow_start_queue_offset; } #endif /* QCA_LL_TX_FLOW_CONTROL_V2 */ + +void wlan_cfg_set_rx_flow_tag_enabled(struct wlan_cfg_dp_soc_ctxt *cfg, + bool val) +{ + cfg->is_rx_flow_tag_enabled = val; +} + +uint8_t *wlan_cfg_rx_fst_get_hash_key(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->rx_toeplitz_hash_key; +} + +uint8_t wlan_cfg_rx_fst_get_max_search(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->rx_flow_max_search; +} + +bool wlan_cfg_is_rx_flow_tag_enabled(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->is_rx_flow_tag_enabled; +} + +#ifdef WLAN_SUPPORT_RX_FISA +bool wlan_cfg_is_rx_fisa_enabled(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return (bool)(cfg->is_rx_fisa_enabled); +} +#else +bool wlan_cfg_is_rx_fisa_enabled(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return false; +} +#endif + +void +wlan_cfg_set_rx_flow_search_table_per_pdev(struct wlan_cfg_dp_soc_ctxt *cfg, + bool val) +{ + cfg->is_rx_flow_search_table_per_pdev = val; +} + +bool wlan_cfg_is_rx_flow_search_table_per_pdev(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->is_rx_flow_search_table_per_pdev; +} + +void wlan_cfg_set_rx_flow_search_table_size(struct wlan_cfg_dp_soc_ctxt *cfg, + uint16_t val) +{ + cfg->rx_flow_search_table_size = val; +} + +uint16_t +wlan_cfg_get_rx_flow_search_table_size(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->rx_flow_search_table_size; +} + +void +wlan_cfg_set_rx_mon_protocol_flow_tag_enabled(struct wlan_cfg_dp_soc_ctxt *cfg, + bool val) +{ + cfg->is_rx_mon_protocol_flow_tag_enabled = val; +} + +bool +wlan_cfg_is_rx_mon_protocol_flow_tag_enabled(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->is_rx_mon_protocol_flow_tag_enabled; +} + +bool wlan_cfg_is_dp_force_rx_64_ba(struct wlan_cfg_dp_soc_ctxt *cfg) +{ + return cfg->enable_force_rx_64_ba; +} diff --git a/drivers/staging/qca-wifi-host-cmn/wlan_cfg/wlan_cfg.h b/drivers/staging/qca-wifi-host-cmn/wlan_cfg/wlan_cfg.h index f08823c8e6b48961433ea1ec514892b9da12d696..7fd657610af65d07597eca7acd4fe8169f86d686 100644 --- a/drivers/staging/qca-wifi-host-cmn/wlan_cfg/wlan_cfg.h +++ b/drivers/staging/qca-wifi-host-cmn/wlan_cfg/wlan_cfg.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -23,7 +24,7 @@ * Temporary place holders. These should come either from target config * or platform configuration */ -#if defined(CONFIG_MCL) +#if defined(WLAN_MAX_PDEVS) && (WLAN_MAX_PDEVS == 1) #define WLAN_CFG_DST_RING_CACHED_DESC 0 #define MAX_PDEV_CNT 1 #define WLAN_CFG_INT_NUM_CONTEXTS 7 @@ -35,26 +36,23 @@ #define DP_TX_NAPI_BUDGET_DIV_MASK 0 /* PPDU Stats Configuration - Configure bitmask for enabling tx ppdu tlv's */ -#define DP_PPDU_TXLITE_STATS_BITMASK_CFG 0x1FFF +#define DP_PPDU_TXLITE_STATS_BITMASK_CFG 0x3FFF #define NUM_RXDMA_RINGS_PER_PDEV 2 + +/*Maximum Number of LMAC instances*/ +#define MAX_NUM_LMAC_HW 2 #else #define WLAN_CFG_DST_RING_CACHED_DESC 1 #define MAX_PDEV_CNT 3 #define WLAN_CFG_INT_NUM_CONTEXTS 11 -#define WLAN_CFG_RXDMA1_ENABLE 1 -/* - * This mask defines how many transmit frames account for 1 NAPI work unit - * 0xFFFF means each 64K tx frame completions account for 1 unit of NAPI budget - */ -#define DP_TX_NAPI_BUDGET_DIV_MASK 0xFFFF - -/* PPDU Stats Configuration - Configure bitmask for enabling tx ppdu tlv's */ -#define DP_PPDU_TXLITE_STATS_BITMASK_CFG 0xFFFF - #define NUM_RXDMA_RINGS_PER_PDEV 1 +#define MAX_NUM_LMAC_HW 3 + #endif +#define WLAN_CFG_INT_NUM_CONTEXTS_MAX 11 + /* Tx configuration */ #define MAX_LINK_DESC_BANKS 8 #define MAX_TXDESC_POOLS 4 @@ -66,7 +64,7 @@ #define MAX_RX_MAC_RINGS 2 /* DP process status */ -#ifdef CONFIG_MCL +#if defined(MAX_PDEV_CNT) && (MAX_PDEV_CNT == 1) #define CONFIG_PROCESS_RX_STATUS 1 #define CONFIG_PROCESS_TX_STATUS 1 #else @@ -81,6 +79,10 @@ #define MAX_NUM_PEER_ID_PER_PEER 8 #define DP_MAX_TIDS 17 #define DP_NON_QOS_TID 16 +#define DP_NULL_DATA_TID 17 + +#define WLAN_CFG_RX_FST_MAX_SEARCH 2 +#define WLAN_CFG_RX_FST_TOEPLITZ_KEYLEN 40 struct wlan_cfg_dp_pdev_ctxt; @@ -132,12 +134,16 @@ struct wlan_srng_cfg { * @lro_enabled: enable/disable LRO feature * @sg_enabled: enable disable scatter gather feature * @gro_enabled: enable disable GRO feature + * @tc_based_dynamic_gro: enable/disable tc based dynamic gro + * @tc_ingress_prio: ingress prio to be checked for dynamic gro * @ipa_enabled: Flag indicating if IPA is enabled * @ol_tx_csum_enabled: Flag indicating if TX csum is enabled * @ol_rx_csum_enabled: Flag indicating if Rx csum is enabled * @rawmode_enabled: Flag indicating if RAW mode is enabled * @peer_flow_ctrl_enabled: Flag indicating if peer flow control is enabled * @napi_enabled: enable/disable interrupt mode for reaping tx and rx packets + * @p2p_tcp_udp_checksumoffload: enable/disable checksum offload for P2P mode + * @nan_tcp_udp_checksumoffload: enable/disable checksum offload for NAN mode * @tcp_udp_checksumoffload: enable/disable checksum offload * @nss_cfg: nss configuration * @rx_defrag_min_timeout: rx defrag minimum timeout @@ -153,16 +159,37 @@ struct wlan_srng_cfg { * @rxdma_err_dst_ring: rxdma error detination ring size * @raw_mode_war: enable/disable raw mode war * @enable_data_stall_detection: flag to enable data stall detection + * @enable_force_rx_64_ba: flag to enable force 64 blockack in RX * @disable_intra_bss_fwd: flag to disable intra bss forwarding * @rxdma1_enable: flag to indicate if rxdma1 is enabled + * @tx_desc_limit_0: tx_desc limit for 5G H + * @tx_desc_limit_1: tx_desc limit for 2G + * @tx_desc_limit_2: tx_desc limit for 5G L + * @tx_device_limit: tx device limit + * @tx_sw_internode_queue: tx sw internode queue * @tx_comp_loop_pkt_limit: Max # of packets to be processed in 1 tx comp loop * @rx_reap_loop_pkt_limit: Max # of packets to be processed in 1 rx reap loop * @rx_hp_oos_update_limit: Max # of HP OOS (out of sync) updates * @rx_enable_eol_data_check: flag to enable check for more ring data at end of * dp_rx_process loop - * tx_comp_enable_eol_data_check: flag to enable/disable checking for more data + * @tx_comp_enable_eol_data_check: flag to enable/disable checking for more data * at end of tx_comp_handler loop. + * @rx_sw_desc_weight: rx sw descriptor weight configuration + * @is_rx_mon_protocol_flow_tag_enabled: flag to enable/disable RX protocol or + * flow tagging in monitor/mon-lite mode + * @is_rx_flow_tag_enabled: flag to enable/disable RX flow tagging using FSE + * @is_rx_flow_search_table_per_pdev: flag to indicate if a per-SOC or per-pdev + * table should be used + * @rx_flow_search_table_size: indicates the number of flows in the flow search + * table + * @rx_flow_max_search: max skid length for each hash entry + * @rx_toeplitz_hash_key: toeplitz key pointer used for hash computation over + * 5 tuple flow entry * @pktlog_buffer_size: packet log buffer size + * @is_rx_fisa_enabled: flag to enable/disable FISA Rx + * @rx_pending_high_threshold: threshold of starting pkt drop + * @rx_pending_low_threshold: threshold of stopping pkt drop + * @wow_check_rx_pending_enable: Enable RX frame pending check in WoW */ struct wlan_cfg_dp_soc_ctxt { int num_int_ctxts; @@ -202,19 +229,25 @@ struct wlan_cfg_dp_soc_ctxt { int int_rxdma2host_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS]; int int_host2rxdma_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS]; int hw_macid[MAX_PDEV_CNT]; + int hw_macid_pdev_id_map[MAX_NUM_LMAC_HW]; int base_hw_macid; bool rx_hash; bool tso_enabled; bool lro_enabled; bool sg_enabled; bool gro_enabled; + bool tc_based_dynamic_gro; + uint32_t tc_ingress_prio; bool ipa_enabled; bool ol_tx_csum_enabled; bool ol_rx_csum_enabled; bool rawmode_enabled; bool peer_flow_ctrl_enabled; bool napi_enabled; + bool p2p_tcp_udp_checksumoffload; + bool nan_tcp_udp_checksumoffload; bool tcp_udp_checksumoffload; + bool legacy_mode_checksumoffload_disable; bool defrag_timeout_check; int nss_cfg; uint32_t tx_flow_stop_queue_threshold; @@ -234,9 +267,16 @@ struct wlan_cfg_dp_soc_ctxt { uint32_t per_pkt_trace; bool raw_mode_war; bool enable_data_stall_detection; + bool enable_force_rx_64_ba; bool disable_intra_bss_fwd; bool rxdma1_enable; int max_ast_idx; + int tx_desc_limit_0; + int tx_desc_limit_1; + int tx_desc_limit_2; + int tx_device_limit; + int tx_sw_internode_queue; + int mon_drop_thresh; #ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT uint32_t tx_comp_loop_pkt_limit; uint32_t rx_reap_loop_pkt_limit; @@ -244,7 +284,18 @@ struct wlan_cfg_dp_soc_ctxt { bool rx_enable_eol_data_check; bool tx_comp_enable_eol_data_check; #endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */ + int rx_sw_desc_weight; + bool is_rx_mon_protocol_flow_tag_enabled; + bool is_rx_flow_tag_enabled; + bool is_rx_flow_search_table_per_pdev; + uint16_t rx_flow_search_table_size; + uint16_t rx_flow_max_search; + uint8_t *rx_toeplitz_hash_key; uint8_t pktlog_buffer_size; + uint8_t is_rx_fisa_enabled; + uint32_t rx_pending_high_threshold; + uint32_t rx_pending_low_threshold; + bool wow_check_rx_pending_enable; }; /** @@ -275,7 +326,8 @@ struct wlan_cfg_dp_pdev_ctxt { * * Return: Handle to configuration context */ -struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach(void *ctrl_obj); +struct wlan_cfg_dp_soc_ctxt * +wlan_cfg_soc_attach(struct cdp_ctrl_objmgr_psoc *ctrl_obj); /** * wlan_cfg_soc_detach() - Detach soc configuration handle @@ -297,7 +349,8 @@ void wlan_cfg_soc_detach(struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx); * * Return: Handle to configuration context */ -struct wlan_cfg_dp_pdev_ctxt *wlan_cfg_pdev_attach(void *ctrl_obj); +struct wlan_cfg_dp_pdev_ctxt * +wlan_cfg_pdev_attach(struct cdp_ctrl_objmgr_psoc *ctrl_obj); /** * wlan_cfg_pdev_detach() Detach and free pdev configuration handle @@ -321,6 +374,7 @@ void wlan_cfg_set_rxbuf_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, int context, void wlan_cfg_set_max_peer_id(struct wlan_cfg_dp_soc_ctxt *cfg, uint32_t val); void wlan_cfg_set_max_ast_idx(struct wlan_cfg_dp_soc_ctxt *cfg, uint32_t val); int wlan_cfg_get_max_ast_idx(struct wlan_cfg_dp_soc_ctxt *cfg); +int wlan_cfg_get_mon_drop_thresh(struct wlan_cfg_dp_soc_ctxt *cfg); int wlan_cfg_set_rx_err_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, int context, int mask); int wlan_cfg_set_rx_wbm_rel_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, @@ -460,36 +514,61 @@ int wlan_cfg_get_rxdma2host_mon_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, int context); /** - * wlan_cfg_set_hw_macid() - Set HW MAC Id for the given PDEV index + * wlan_cfg_set_hw_macidx() - Set HW MAC Idx for the given PDEV index * * @wlan_cfg_ctx - Configuration Handle * @pdev_idx - Index of SW PDEV * @hw_macid - HW MAC Id * */ -void wlan_cfg_set_hw_macid(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx, - int hw_macid); +void wlan_cfg_set_hw_mac_idx + (struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx, int hw_macid); /** - * wlan_cfg_get_hw_macid() - Get HW MAC Id for the given PDEV index + * wlan_cfg_get_hw_mac_idx() - Get 0 based HW MAC index for the given + * PDEV index * * @wlan_cfg_ctx - Configuration Handle * @pdev_idx - Index of SW PDEV * - * Return: HW MAC Id + * Return: HW MAC index */ -int wlan_cfg_get_hw_macid(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx); +int wlan_cfg_get_hw_mac_idx(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx); /** - * wlan_cfg_get_hw_mac_idx() - Get 0 based HW MAC index for the given - * PDEV index + * wlan_cfg_get_target_pdev_id() - Get target PDEV ID for HW MAC ID + * + * @wlan_cfg_ctx - Configuration Handle + * @hw_macid - Index of hw mac + * + * Return: PDEV ID + */ +int +wlan_cfg_get_target_pdev_id(struct wlan_cfg_dp_soc_ctxt *cfg, int hw_macid); + +/** + * wlan_cfg_set_pdev_idx() - Set 0 based host PDEV index for the given + * hw mac index * * @wlan_cfg_ctx - Configuration Handle * @pdev_idx - Index of SW PDEV + * @hw_macid - Index of hw mac * - * Return: HW MAC index + * Return: PDEV index */ -int wlan_cfg_get_hw_mac_idx(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx); +void wlan_cfg_set_pdev_idx + (struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx, int hw_macid); + +/** + * wlan_cfg_get_pdev_idx() - Get 0 based PDEV index for the given + * hw mac index + * + * @wlan_cfg_ctx - Configuration Handle + * @hw_macid - Index of hw mac + * + * Return: PDEV index + */ +int wlan_cfg_get_pdev_idx(struct wlan_cfg_dp_soc_ctxt *cfg, int hw_macid); /** * wlan_cfg_get_rx_err_ring_mask() - Return Rx monitor ring interrupt mask @@ -770,6 +849,24 @@ wlan_cfg_get_dma_mon_desc_ring_size(struct wlan_cfg_dp_pdev_ctxt *cfg); int wlan_cfg_get_rx_dma_buf_ring_size( struct wlan_cfg_dp_pdev_ctxt *wlan_cfg_pdev_ctx); +/* + * wlan_cfg_rx_pending_hl_threshold() - Return high threshold of rx pending + * @wlan_cfg_pdev_ctx + * + * Return: rx_pending_high_threshold + */ +uint32_t +wlan_cfg_rx_pending_hl_threshold(struct wlan_cfg_dp_soc_ctxt *cfg); + +/* + * wlan_cfg_rx_pending_lo_threshold() - Return low threshold of rx pending + * @wlan_cfg_pdev_ctx + * + * Return: rx_pending_low_threshold + */ +uint32_t +wlan_cfg_rx_pending_lo_threshold(struct wlan_cfg_dp_soc_ctxt *cfg); + /* * wlan_cfg_get_num_mac_rings() - Return the number of MAC RX DMA rings * per pdev @@ -911,6 +1008,22 @@ int wlan_cfg_get_int_timer_threshold_mon(struct wlan_cfg_dp_soc_ctxt *cfg); */ int wlan_cfg_get_checksum_offload(struct wlan_cfg_dp_soc_ctxt *cfg); +/* + * wlan_cfg_get_nan_checksum_offload - Get checksum offload enable/disable val + * @wlan_cfg_soc_ctx + * + * Return: Checksum offload enable or disable value for NAN mode + */ +int wlan_cfg_get_nan_checksum_offload(struct wlan_cfg_dp_soc_ctxt *cfg); + +/* + * wlan_cfg_get_p2p_checksum_offload - Get checksum offload enable/disable val + * @wlan_cfg_soc_ctx + * + * Return: Checksum offload enable or disable value for P2P mode + */ +int wlan_cfg_get_p2p_checksum_offload(struct wlan_cfg_dp_soc_ctxt *cfg); + /* * wlan_cfg_tx_ring_size - Get Tx DMA ring size (TCL Data Ring) * @wlan_cfg_soc_ctx @@ -999,6 +1112,51 @@ wlan_cfg_get_dp_soc_reo_cmd_ring_size(struct wlan_cfg_dp_soc_ctxt *cfg); int wlan_cfg_get_dp_soc_reo_status_ring_size(struct wlan_cfg_dp_soc_ctxt *cfg); +/* + * wlan_cfg_get_dp_soc_tx_desc_limit_0 - Get tx desc limit for 5G H + * @wlan_cfg_soc_ctx + * + * Return: tx desc limit for 5G H + */ +int +wlan_cfg_get_dp_soc_tx_desc_limit_0(struct wlan_cfg_dp_soc_ctxt *cfg); + +/* + * wlan_cfg_get_dp_soc_tx_desc_limit_1 - Get tx desc limit for 2G + * @wlan_cfg_soc_ctx + * + * Return: tx desc limit for 2G + */ +int +wlan_cfg_get_dp_soc_tx_desc_limit_1(struct wlan_cfg_dp_soc_ctxt *cfg); + +/* + * wlan_cfg_get_dp_soc_tx_desc_limit_2 - Get tx desc limit for 5G L + * @wlan_cfg_soc_ctx + * + * Return: tx desc limit for 5G L + */ +int +wlan_cfg_get_dp_soc_tx_desc_limit_2(struct wlan_cfg_dp_soc_ctxt *cfg); + +/* + * wlan_cfg_get_dp_soc_tx_device_limit - Get tx device limit + * @wlan_cfg_soc_ctx + * + * Return: tx device limit + */ +int +wlan_cfg_get_dp_soc_tx_device_limit(struct wlan_cfg_dp_soc_ctxt *cfg); + +/* + * wlan_cfg_get_dp_soc_tx_sw_internode_queue - Get tx sw internode queue + * @wlan_cfg_soc_ctx + * + * Return: tx sw internode queue + */ +int +wlan_cfg_get_dp_soc_tx_sw_internode_queue(struct wlan_cfg_dp_soc_ctxt *cfg); + /* * wlan_cfg_get_dp_soc_rxdma_refill_ring_size - Get rxdma refill ring size * @wlan_cfg_soc_ctx @@ -1017,6 +1175,15 @@ wlan_cfg_get_dp_soc_rxdma_refill_ring_size(struct wlan_cfg_dp_soc_ctxt *cfg); int wlan_cfg_get_dp_soc_rxdma_err_dst_ring_size(struct wlan_cfg_dp_soc_ctxt *cfg); +/* + * wlan_cfg_get_dp_soc_rx_sw_desc_weight - Get rx sw desc weight + * @wlan_cfg_soc_ctx + * + * Return: rx_sw_desc_weight + */ +int +wlan_cfg_get_dp_soc_rx_sw_desc_weight(struct wlan_cfg_dp_soc_ctxt *cfg); + /* * wlan_cfg_get_dp_caps - Get dp capablities * @wlan_cfg_soc_ctx @@ -1046,4 +1213,138 @@ int wlan_cfg_get_rx_defrag_min_timeout(struct wlan_cfg_dp_soc_ctxt *cfg); int wlan_cfg_get_defrag_timeout_check(struct wlan_cfg_dp_soc_ctxt *cfg); +/** + * wlan_cfg_get_rx_flow_search_table_size() - Return the size of Rx FST + * in number of entries + * + * @wlan_cfg_dp_soc_ctxt: soc configuration context + * + * Return: rx_fst_size + */ +uint16_t +wlan_cfg_get_rx_flow_search_table_size(struct wlan_cfg_dp_soc_ctxt *cfg); + +/** + * wlan_cfg_rx_fst_get_max_search() - Return the max skid length for FST search + * + * @wlan_cfg_dp_soc_ctxt: soc configuration context + * + * Return: max_search + */ +uint8_t wlan_cfg_rx_fst_get_max_search(struct wlan_cfg_dp_soc_ctxt *cfg); + +/** + * wlan_cfg_rx_fst_get_hash_key() - Return Toeplitz Hash Key used for FST + * search + * + * @wlan_cfg_dp_soc_ctxt: soc configuration context + * + * Return: 320-bit Hash Key + */ +uint8_t *wlan_cfg_rx_fst_get_hash_key(struct wlan_cfg_dp_soc_ctxt *cfg); + +/** + * wlan_cfg_set_rx_flow_tag_enabled() - set rx flow tag enabled flag in + * DP soc context + * @wlan_cfg_dp_soc_ctxt: soc configuration context + * @val: Rx flow tag feature flag value + * + * Return: None + */ +void wlan_cfg_set_rx_flow_tag_enabled(struct wlan_cfg_dp_soc_ctxt *cfg, + bool val); + +/** + * wlan_cfg_is_rx_flow_tag_enabled() - get rx flow tag enabled flag from + * DP soc context + * @wlan_cfg_dp_soc_ctxt: soc configuration context + * + * Return: true if feature is enabled, else false + */ +bool wlan_cfg_is_rx_flow_tag_enabled(struct wlan_cfg_dp_soc_ctxt *cfg); + +/** + * wlan_cfg_set_rx_flow_search_table_per_pdev() - Set flag to indicate that + * Rx FST is per pdev + * @wlan_cfg_dp_soc_ctxt: soc configuration context + * @val: boolean flag indicating Rx FST per pdev or per SOC + * + * Return: None + */ +void +wlan_cfg_set_rx_flow_search_table_per_pdev(struct wlan_cfg_dp_soc_ctxt *cfg, + bool val); + +/** + * wlan_cfg_is_rx_flow_search_table_per_pdev() - get RX FST flag for per pdev + * @wlan_cfg_dp_soc_ctxt: soc configuration context + * + * Return: true if Rx FST is per pdev, else false + */ +bool +wlan_cfg_is_rx_flow_search_table_per_pdev(struct wlan_cfg_dp_soc_ctxt *cfg); + +/** + * wlan_cfg_set_rx_flow_search_table_size() - set RX FST size in DP SoC context + * @wlan_cfg_dp_soc_ctxt: soc configuration context + * @val: Rx FST size in number of entries + * + * Return: None + */ +void +wlan_cfg_set_rx_flow_search_table_size(struct wlan_cfg_dp_soc_ctxt *cfg, + uint16_t val); + +/** + * wlan_cfg_set_rx_mon_protocol_flow_tag_enabled() - set mon rx tag enabled flag + * in DP soc context + * @wlan_cfg_dp_soc_ctxt: soc configuration context + * @val: Rx protocol or flow tag feature flag value in monitor mode from INI + * + * Return: None + */ +void +wlan_cfg_set_rx_mon_protocol_flow_tag_enabled(struct wlan_cfg_dp_soc_ctxt *cfg, + bool val); + +/** + * wlan_cfg_is_rx_mon_protocol_flow_tag_enabled() - get mon rx tag enabled flag + * from DP soc context + * @wlan_cfg_dp_soc_ctxt: soc configuration context + * + * Return: true if feature is enabled in monitor mode for protocol or flow + * tagging in INI, false otherwise + */ +bool +wlan_cfg_is_rx_mon_protocol_flow_tag_enabled(struct wlan_cfg_dp_soc_ctxt *cfg); + +/** + * wlan_cfg_fill_interrupt_mask() - set interrupt mask + * + * @wlan_cfg_dp_soc_ctxt: soc configuration context + * @interrupt_mode: interrupt_mode: MSI/LEGACY + * @is_monitor_mode: is monitor mode enabled + * + * Return: void + */ +void wlan_cfg_fill_interrupt_mask(struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx, + int interrupt_mode, bool is_monitor_mode); + +/** + * wlan_cfg_is_rx_fisa_enabled() - Get Rx FISA enabled flag + * + * + * @cfg: soc configuration context + * + * Return: true if enabled, false otherwise. + */ +bool wlan_cfg_is_rx_fisa_enabled(struct wlan_cfg_dp_soc_ctxt *cfg); + +/** + * wlan_cfg_is_dp_force_rx_64_ba() - Get force use 64 BA flag + * @cfg: config context + * + * Return: force use 64 BA flag + */ +bool wlan_cfg_is_dp_force_rx_64_ba(struct wlan_cfg_dp_soc_ctxt *cfg); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_filtered_logging.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_filtered_logging.h new file mode 100644 index 0000000000000000000000000000000000000000..08700275701235b94697193e0ab032de271fd7c7 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_filtered_logging.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2015-2020 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef WMI_FILTERED_LOGGING_H +#define WMI_FILTERED_LOGGING_H + +#include +#include "wmi_unified_priv.h" + +#ifdef WMI_INTERFACE_FILTERED_EVENT_LOGGING +/** + * wmi_specific_cmd_record() - Record user specified command + * @wmi_handle: handle to WMI + * @id: cmd id + * @buf: buf containing cmd details + * + * Check if the command id is in target list, + * if found, record it. + * + * Context: the function will not sleep, caller is expected to hold + * proper locking. + * + * Return: none + */ +void wmi_specific_cmd_record(wmi_unified_t wmi_handle, + uint32_t id, uint8_t *buf); + +/** + * wmi_specific_evt_record() - Record user specified event + * @wmi_handle: handle to WMI + * @id: cmd id + * @buf: buf containing event details + * + * Check if the event id is in target list, + * if found, record it. + * + * Context: the function will not sleep, caller is expected to hold + * proper locking. + * + * Return: none + */ +void wmi_specific_evt_record(wmi_unified_t wmi_handle, + uint32_t id, uint8_t *buf); + +/** + * wmi_filtered_logging_init() - initialize filtered logging + * @wmi_handle: handle to WMI + * + * Context: the function will not sleep, no lock needed + * + * Return: none + */ +void wmi_filtered_logging_init(wmi_unified_t wmi_handle); + +/** + * wmi_filtered_logging_free() - free the buffers for filtered logging + * @wmi_handle: handle to WMI + * + * Context: the function will not sleep, no lock needed + * + * Return: none + */ +void wmi_filtered_logging_free(wmi_unified_t wmi_handle); + +/* + * Debugfs read/write functions + */ +/** + * debug_filtered_wmi_cmds_show() - debugfs read function for filtered_wmi_cmds + * @m: seq_file handle + * @v: not used, offset of read + * Return: number of bytes read + */ +int debug_filtered_wmi_cmds_show(qdf_debugfs_file_t m, void *v); + +/** + * debug_filtered_wmi_evts_show() - debugfs read function for filtered_wmi_evts + * @m: seq_file handle + * @v: not used, offset of read + * Return: number of bytes read + */ +int debug_filtered_wmi_evts_show(qdf_debugfs_file_t m, void *v); + +/** + * debug_wmi_filtered_command_log_show() - debugfs read function for + * wmi_filtered_command_log + * @m: seq_file handle + * @v: not used, offset of read + * Return: number of bytes read + */ +int debug_wmi_filtered_command_log_show(qdf_debugfs_file_t m, void *v); + +/** + * debug_wmi_filtered_event_log_show() - debugfs read function for + * wmi_filtered_event_log + * @m: seq_file handle + * @v: not used, offset of read + * Return: number of bytes read + */ +int debug_wmi_filtered_event_log_show(qdf_debugfs_file_t m, void *v); + +/** + * debug_wmi_filtered_wmi_cmds_write() - debugfs write for filtered_wmi_cmds + * + * @file: file handler to access wmi_handle + * @buf: received data buffer + * @count: length of received buffer + * @ppos: Not used + * + * Return: count + */ +ssize_t debug_filtered_wmi_cmds_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos); + +/** + * debug_wmi_filtered_wmi_evts_write() - debugfs write for filtered_wmi_evts + * + * @file: file handler to access wmi_handle + * @buf: received data buffer + * @count: length of received buffer + * @ppos: Not used + * + * Return: count + */ +ssize_t debug_filtered_wmi_evts_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos); + +/** + * debug_wmi_filtered_command_log_write() - debugfs write for + * filtered_command_log + * + * @file: file handler to access wmi_handle + * @buf: received data buffer + * @count: length of received buffer + * @ppos: Not used + * + * Return: count + */ +ssize_t debug_wmi_filtered_command_log_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos); + +/** + * debug_wmi_filtered_event_log_write() - debugfs write for filtered_event_log + * + * @file: file handler to access wmi_handle + * @buf: received data buffer + * @count: length of received buffer + * @ppos: Not used + * + * Return: count + */ +ssize_t debug_wmi_filtered_event_log_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos); + +#else /* WMI_INTERFACE_FILTERED_EVENT_LOGGING */ + +static inline void wmi_specific_cmd_record(wmi_unified_t wmi_handle, + uint32_t id, uint8_t *buf) +{ + /* do nothing */ +} + +static inline void wmi_specific_evt_record(wmi_unified_t wmi_handle, + uint32_t id, uint8_t *buf) +{ + /* do nothing */ +} + +static inline void wmi_filtered_logging_init(wmi_unified_t wmi_handle) +{ + /* do nothing */ +} + +static inline void wmi_filtered_logging_free(wmi_unified_t wmi_handle) +{ + /* do nothing */ +} +#endif /* end of WMI_INTERFACE_FILTERED_EVENT_LOGGING */ + +#endif /*WMI_FILTERED_LOGGING_H*/ diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_hang_event.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_hang_event.h new file mode 100644 index 0000000000000000000000000000000000000000..96127ea6f622c03e7716c7b1ee8900ed8b5754b7 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_hang_event.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef WMI_HANG_EVENT_H +#define WMI_HANG_EVENT_H + +#include +#ifdef WLAN_HANG_EVENT + +/** + * wmi_hang_event_notifier_register() - wmi hang event notifier register + * @wmi_hdl: WMI Handle + * + * This function registers wmi layer notifier for the hang event notifier chain. + * + * Return: QDF_STATUS + */ +QDF_STATUS wmi_hang_event_notifier_register(struct wmi_unified *wmi_hdl); + +/** + * wmi_hang_event_notifier_unregister() - wmi hang event notifier unregister + * @wmi_hdl: WMI Handle + * + * This function unregisters wmi layer notifier for the hang event notifier + * chain. + * + * Return: QDF_STATUS + */ +QDF_STATUS wmi_hang_event_notifier_unregister(void); +#else +static inline +QDF_STATUS wmi_hang_event_notifier_register(struct wmi_unified *wmi_hdl) +{ + return 0; +} + +static inline QDF_STATUS wmi_hang_event_notifier_unregister(void) +{ + return 0; +} +#endif +#endif diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_api.h index 45b51ec0832d617d4655ae759478e82930bc093c..7cbc50e104cdcc659009d1219b6df1857181872d 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_api.h +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_api.h @@ -25,9 +25,6 @@ #define _WMI_UNIFIED_API_H_ #include -#ifdef CONFIG_MCL -#include "wmi.h" -#endif #include "htc_api.h" #include "wmi_unified_param.h" #include "service_ready_param.h" @@ -37,9 +34,6 @@ #include "wmi_unified_pmo_api.h" #endif #include "wlan_scan_public_structs.h" -#ifdef WLAN_FEATURE_DISA -#include "wlan_disa_public_struct.h" -#endif #ifdef WLAN_FEATURE_ACTION_OUI #include "wlan_action_oui_public_struct.h" #endif @@ -106,10 +100,6 @@ #include "wmi_unified_fwol_api.h" #endif -#ifdef WLAN_FEATURE_PKT_CAPTURE -#include "wlan_pkt_capture_public_structs.h" -#endif - typedef qdf_nbuf_t wmi_buf_t; #define wmi_buf_data(_buf) qdf_nbuf_data(_buf) @@ -131,19 +121,6 @@ typedef qdf_nbuf_t wmi_buf_t; struct wmi_soc; struct policy_mgr_dual_mac_config; -/** - * struct wmi_rx_ops - handle to wmi rx ops - * @scn_handle: handle to scn - * @ev: event buffer - * @rx_ctx: rx execution context - * @wma_process_fw_event_handler_cbk: generic event handler callback - */ -struct wmi_rx_ops { - - int (*wma_process_fw_event_handler_cbk)(ol_scn_t scn_handle, - void *ev, - uint8_t rx_ctx); -}; /** * enum wmi_target_type - type of supported wmi command @@ -161,11 +138,26 @@ enum wmi_target_type { * enum wmi_rx_exec_ctx - wmi rx execution context * @WMI_RX_WORK_CTX: work queue context execution provided by WMI layer * @WMI_RX_UMAC_CTX: execution context provided by umac layer + * @WMI_RX_SERIALIZER_CTX: Execution context is serialized thread context * */ enum wmi_rx_exec_ctx { WMI_RX_WORK_CTX, - WMI_RX_UMAC_CTX + WMI_RX_UMAC_CTX, + WMI_RX_TASKLET_CTX = WMI_RX_UMAC_CTX, + WMI_RX_SERIALIZER_CTX = 2 +}; + +/** + * enum wmi_fw_mem_prio - defines FW Memory requirement type + * @WMI_FW_MEM_HIGH_PRIORITY: Memory requires contiguous memory allocation + * @WMI_FW_MEM_LOW_PRIORITY: Memory can be fragmented + * @WMI_FW_PRIORITY_MAX: Invalid type + */ +enum wmi_fw_mem_prio { + WMI_FW_MEM_HIGH_PRIORITY = 0, + WMI_FW_MEM_LOW_PRIORITY, + WMI_FW_PRIORITY_MAX }; /** @@ -184,7 +176,6 @@ struct wmi_unified_attach_params { enum wmi_target_type target_type; bool use_cookie; bool is_async_ep; - struct wmi_rx_ops *rx_ops; struct wlan_objmgr_psoc *psoc; uint16_t max_commands; uint32_t soc_id; @@ -227,10 +218,11 @@ void wmi_unified_detach(struct wmi_unified *wmi_handle); /** * API to sync time between host and firmware * - * @param wmi_handle : handle to WMI. - * @return void. + * @wmi_handle: handle to WMI. + * + * Return: none */ -void wmi_send_time_stamp_sync_cmd_tlv(void *wmi_hdl); +void wmi_send_time_stamp_sync_cmd_tlv(wmi_unified_t wmi_handle); void wmi_unified_remove_work(struct wmi_unified *wmi_handle); @@ -383,14 +375,15 @@ wmi_unified_unregister_event_handler(wmi_unified_t wmi_handle, wmi_conv_event_id event_id); /** - * request wmi to connet its htc service. - * @param wmi_handle : handle to WMI. - * @param htc_handle : handle to HTC. - * @return void + * wmi_unified_connect_htc_service() - WMI API to get connect to HTC service + * @wmi_handle: handle to WMI. + * @htc_handle: handle to HTC. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAULT for failure */ QDF_STATUS wmi_unified_connect_htc_service(struct wmi_unified *wmi_handle, - void *htc_handle); + HTC_HANDLE htc_handle); /* * WMI API to verify the host has enough credits to suspend @@ -430,6 +423,36 @@ void wmi_set_target_suspend(wmi_unified_t wmi_handle, bool val); */ bool wmi_is_target_suspended(struct wmi_unified *wmi_handle); +#ifdef WLAN_FEATURE_WMI_SEND_RECV_QMI +/** + * wmi_set_qmi_stats() - WMI API to set qmi stats enabled/disabled + * @wmi_handle: handle to WMI. + * @val: suspend state boolean + */ +void wmi_set_qmi_stats(wmi_unified_t wmi_handle, bool val); + +/** + * wmi_is_qmi_stats_enabled() - WMI API to check if periodic stats + * over qmi is enableid + * @wmi_handle: handle to WMI. + * + * WMI API to check if periodic stats over qmi is enabled + * + * Return: true if qmi stats is enabled, else false. + */ +bool wmi_is_qmi_stats_enabled(struct wmi_unified *wmi_handle); +#else +static inline +void wmi_set_qmi_stats(wmi_unified_t wmi_handle, bool val) +{} + +static inline +bool wmi_is_qmi_stats_enabled(struct wmi_unified *wmi_handle) +{ + return false; +} +#endif /* end if of WLAN_FEATURE_WMI_SEND_RECV_QMI */ + /** * WMI API to set bus suspend state * @param wmi_handle: handle to WMI. @@ -461,6 +484,14 @@ void wmi_set_tgt_assert(wmi_unified_t wmi_handle, bool val); int wmi_stop(wmi_unified_t wmi_handle); +/** + * generic function to start unified WMI command + * @param wmi_handle : handle to WMI. + * @return 0 on success and -ve on failure. + */ +int +wmi_start(wmi_unified_t wmi_handle); + /** * API to flush all the previous packets associated with the wmi endpoint * @@ -470,13 +501,18 @@ void wmi_flush_endpoint(wmi_unified_t wmi_handle); /** - * wmi_pdev_id_conversion_enable() - API to enable pdev_id conversion in WMI - * By default pdev_id conversion is not done in WMI. + * wmi_pdev_id_conversion_enable() - API to enable pdev_id and phy_id + * conversion in WMI. By default pdev_id and + * phyid conversion is not done in WMI. * This API can be used enable conversion in WMI. * @param wmi_handle : handle to WMI + * @param *pdev_id_map : pdev conversion map + * @param size : size of pdev_id_map * Return none */ -void wmi_pdev_id_conversion_enable(wmi_unified_t wmi_handle); +void wmi_pdev_id_conversion_enable(wmi_unified_t wmi_handle, + uint32_t *pdev_id_map, + uint8_t size); /** * API to handle wmi rx event after UMAC has taken care of execution @@ -514,6 +550,32 @@ void *wmi_unified_get_pdev_handle(struct wmi_soc *soc, uint32_t pdev_idx); void wmi_process_fw_event(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf); uint16_t wmi_get_max_msg_len(wmi_unified_t wmi_handle); +/** + * wmi_unified_soc_set_hw_mode_cmd() - Send WMI_SOC_SET_HW_MODE_CMDID to FW + * @wmi_handle: wmi handle + * @hw_mode_index: The HW_Mode field is a enumerated type that is selected + * from the HW_Mode table, which is returned in the WMI_SERVICE_READY_EVENTID. + * + * Request HardWare (HW) Mode change to WLAN firmware + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_soc_set_hw_mode_cmd(wmi_unified_t wmi_handle, + uint32_t hw_mode_index); + +/** + * wmi_extract_hw_mode_resp() - function to extract HW mode change response + * @wmi_hdl: WMI handle + * @evt_buf: Buffer holding event data + * @cmd_status: command status + * + * Return: QDF_STATUS_SUCCESS if success, else returns proper error code. + */ +QDF_STATUS +wmi_unified_extract_hw_mode_resp(wmi_unified_t wmi, + void *evt_buf, + uint32_t *cmd_status); + /** * wmi_unified_extract_roam_trigger_stats() - Extract roam trigger related * stats @@ -545,6 +607,7 @@ QDF_STATUS wmi_unified_extract_roam_scan_stats(wmi_unified_t wmi, void *evt_buf, struct wmi_roam_scan_data *dst, uint8_t idx, uint8_t chan_idx, uint8_t ap_idx); + /** * wmi_unified_extract_roam_result_stats() - Extract roam result related stats * @wmi: wmi handle @@ -573,13 +636,40 @@ QDF_STATUS wmi_unified_extract_roam_11kv_stats(wmi_unified_t wmi, void *evt_buf, struct wmi_neighbor_report_data *dst, uint8_t idx, uint8_t rpt_idx); +/** + * wmi_unified_extract_roam_msg_info() - Extract Roam msg stats + * @wmi: wmi handle + * @evt_buf: Pointer to the event buffer + * @dst: Pointer to destination structure to fill data + * @idx: TLV id + * + * Return: QDF_STATUS + */ +QDF_STATUS +wmi_unified_extract_roam_msg_info(wmi_unified_t wmi, void *evt_buf, + struct wmi_roam_msg_info *dst, uint8_t idx); -QDF_STATUS wmi_unified_vdev_create_send(void *wmi_hdl, - uint8_t macaddr[QDF_MAC_ADDR_SIZE], - struct vdev_create_params *param); +/** + * wmi_unified_vdev_create_send() - send VDEV create command to fw + * @wmi_handle: wmi handle + * @param: pointer to hold vdev create parameter + * @macaddr: vdev mac address + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_vdev_create_send(wmi_unified_t wmi_handle, + uint8_t macaddr[QDF_MAC_ADDR_SIZE], + struct vdev_create_params *param); -QDF_STATUS wmi_unified_vdev_delete_send(void *wmi_hdl, - uint8_t if_id); +/** + * wmi_unified_vdev_delete_send() - send VDEV delete command to fw + * @wmi_handle: wmi handle + * @if_id: vdev id + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_vdev_delete_send(wmi_unified_t wmi_handle, + uint8_t if_id); /** * wmi_unified_vdev_nss_chain_params_send() - send VDEV nss chain params to fw @@ -589,813 +679,2400 @@ QDF_STATUS wmi_unified_vdev_delete_send(void *wmi_hdl, * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_vdev_nss_chain_params_send(void *wmi_hdl, - uint8_t vdev_id, - struct vdev_nss_chains *nss_chains_user_cfg); +QDF_STATUS +wmi_unified_vdev_nss_chain_params_send( + wmi_unified_t wmi_handle, + uint8_t vdev_id, + struct vdev_nss_chains *nss_chains_user_cfg); + +/** + * wmi_unified_vdev_stop_send() - send vdev stop command to fw + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_vdev_stop_send(wmi_unified_t wmi_handle, + uint8_t vdev_id); -QDF_STATUS wmi_unified_vdev_stop_send(void *wmi_hdl, - uint8_t vdev_id); +/** + * wmi_unified_vdev_up_send() - send vdev up command in fw + * @wmi_handle: wmi handle + * @bssid: bssid + * @params: pointer to hold vdev up parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_vdev_up_send(wmi_unified_t wmi_handle, + uint8_t bssid[QDF_MAC_ADDR_SIZE], + struct vdev_up_params *params); -QDF_STATUS wmi_unified_vdev_up_send(void *wmi_hdl, - uint8_t bssid[QDF_MAC_ADDR_SIZE], - struct vdev_up_params *params); +/** + * wmi_unified_vdev_down_send() - send vdev down command to fw + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_vdev_down_send(wmi_unified_t wmi_handle, + uint8_t vdev_id); -QDF_STATUS wmi_unified_vdev_down_send(void *wmi_hdl, - uint8_t vdev_id); +/** + * wmi_unified_vdev_start_send() - send vdev start command to fw + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_vdev_start_send(wmi_unified_t wmi_handle, + struct vdev_start_params *req); -QDF_STATUS wmi_unified_vdev_start_send(void *wmi_hdl, - struct vdev_start_params *req); /** * wmi_unified_vdev_set_nac_rssi_send() - send NAC_RSSI command to fw - * @param wmi_handle : handle to WMI - * @param req : pointer to hold nac rssi request data + * @wmi_handle: handle to WMI + * @req: pointer to hold nac rssi request data * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_vdev_set_nac_rssi_send(void *wmi_hdl, - struct vdev_scan_nac_rssi_params *req); - -QDF_STATUS wmi_unified_hidden_ssid_vdev_restart_send(void *wmi_hdl, - struct hidden_ssid_vdev_restart_params *restart_params); +QDF_STATUS +wmi_unified_vdev_set_nac_rssi_send(wmi_unified_t wmi_handle, + struct vdev_scan_nac_rssi_params *req); -QDF_STATUS wmi_unified_vdev_set_param_send(void *wmi_hdl, +/** + * wmi_unified_vdev_set_param_send() - WMI vdev set parameter function + * @wmi_handle: handle to WMI. + * @macaddr: MAC address + * @param: pointer to hold vdev set parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_vdev_set_param_send(wmi_unified_t wmi_handle, struct vdev_set_params *param); -QDF_STATUS wmi_unified_sifs_trigger_send(void *wmi_hdl, +/** + * wmi_unified_sifs_trigger_send() - WMI vdev sifs trigger parameter function + * @wmi_handle: handle to WMI. + * @param: pointer to hold sifs trigger parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_sifs_trigger_send(wmi_unified_t wmi_handle, struct sifs_trigger_param *param); -QDF_STATUS wmi_unified_peer_delete_send(void *wmi_hdl, - uint8_t - peer_addr[QDF_MAC_ADDR_SIZE], - uint8_t vdev_id); - -QDF_STATUS wmi_unified_peer_flush_tids_send(void *wmi_hdl, - uint8_t peer_addr[QDF_MAC_ADDR_SIZE], - struct peer_flush_params *param); - -QDF_STATUS wmi_set_peer_param_send(void *wmi_hdl, - uint8_t peer_addr[QDF_MAC_ADDR_SIZE], - struct peer_set_params *param); - -QDF_STATUS wmi_unified_peer_create_send(void *wmi_hdl, - struct peer_create_params *param); - -QDF_STATUS wmi_unified_stats_request_send(wmi_unified_t wmi_handle, - uint8_t macaddr[QDF_MAC_ADDR_SIZE], - struct stats_request_params *param); - -QDF_STATUS wmi_unified_green_ap_ps_send(void *wmi_hdl, - uint32_t value, uint8_t pdev_id); - -QDF_STATUS wmi_unified_wow_enable_send(void *wmi_hdl, - struct wow_cmd_params *param, - uint8_t mac_id); - -QDF_STATUS wmi_unified_wow_wakeup_send(void *wmi_hdl); - -QDF_STATUS wmi_unified_wow_add_wakeup_event_send(void *wmi_hdl, - struct wow_add_wakeup_params *param); - -QDF_STATUS wmi_unified_wow_add_wakeup_pattern_send(void *wmi_hdl, - struct wow_add_wakeup_pattern_params *param); - -QDF_STATUS wmi_unified_wow_remove_wakeup_pattern_send(void *wmi_hdl, - struct wow_remove_wakeup_pattern_params *param); - -#ifndef CONFIG_MCL -QDF_STATUS wmi_unified_packet_log_enable_send(void *wmi_hdl, - WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT, uint8_t mac_id); - /** - * wmi_unified_peer_based_pktlog_send() - WMI request enable peer - * based filtering - * @wmi_handle: handle to WMI. - * @macaddr: PEER mac address to be filtered - * @mac_id: Mac id - * @enb_dsb: Enable or Disable peer based pktlog - * filtering + * wmi_unified_peer_delete_send() - send PEER delete command to fw + * @wmi_handle: wmi handle + * @peer_addr: peer mac addr + * @vdev_id: vdev id * - * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_peer_based_pktlog_send(void *wmi_hdl, - uint8_t *macaddr, - uint8_t mac_id, - uint8_t enb_dsb); -#else -QDF_STATUS wmi_unified_packet_log_enable_send(void *wmi_hdl, - uint8_t macaddr[QDF_MAC_ADDR_SIZE], - struct packet_enable_params *param); -#endif - -QDF_STATUS wmi_unified_packet_log_disable_send(void *wmi_hdl, uint8_t mac_id); - -QDF_STATUS wmi_unified_suspend_send(void *wmi_hdl, - struct suspend_params *param, - uint8_t mac_id); - -QDF_STATUS wmi_unified_resume_send(void *wmi_hdl, - uint8_t mac_id); - -QDF_STATUS -wmi_unified_pdev_param_send(void *wmi_hdl, - struct pdev_params *param, - uint8_t mac_id); - -QDF_STATUS wmi_unified_beacon_tmpl_send_cmd(void *wmi_hdl, - struct beacon_tmpl_params *param); - - -QDF_STATUS wmi_unified_peer_assoc_send(void *wmi_hdl, - struct peer_assoc_params *param); - -QDF_STATUS wmi_unified_sta_ps_cmd_send(void *wmi_hdl, - struct sta_ps_params *param); - -QDF_STATUS wmi_unified_ap_ps_cmd_send(void *wmi_hdl, - uint8_t macaddr[QDF_MAC_ADDR_SIZE], - struct ap_ps_params *param); - -QDF_STATUS wmi_unified_scan_start_cmd_send(void *wmi_hdl, - struct scan_req_params *param); - -QDF_STATUS wmi_unified_scan_stop_cmd_send(void *wmi_hdl, - struct scan_cancel_param *param); - -QDF_STATUS wmi_unified_scan_chan_list_cmd_send(void *wmi_hdl, - struct scan_chan_list_params *param); - - -QDF_STATUS wmi_crash_inject(void *wmi_hdl, - struct crash_inject *param); - -QDF_STATUS wmi_unified_pdev_utf_cmd_send(void *wmi_hdl, - struct pdev_utf_params *param, - uint8_t mac_id); - -#ifdef FEATURE_FW_LOG_PARSING -QDF_STATUS wmi_unified_dbglog_cmd_send(void *wmi_hdl, - struct dbglog_params *param); -#else -static inline QDF_STATUS -wmi_unified_dbglog_cmd_send(void *wmi_hdl, - struct dbglog_params *param) -{ - return QDF_STATUS_SUCCESS; -} -#endif - -QDF_STATUS wmi_mgmt_unified_cmd_send(void *wmi_hdl, - struct wmi_mgmt_params *param); - -QDF_STATUS wmi_offchan_data_tx_cmd_send(void *wmi_hdl, - struct wmi_offchan_data_tx_params *param); - -QDF_STATUS wmi_unified_modem_power_state(void *wmi_hdl, - uint32_t param_value); - -QDF_STATUS wmi_unified_set_sta_ps_mode(void *wmi_hdl, - uint32_t vdev_id, uint8_t val); QDF_STATUS -wmi_unified_set_sta_uapsd_auto_trig_cmd(void *wmi_hdl, - struct sta_uapsd_trig_params *param); - -QDF_STATUS wmi_unified_get_temperature(void *wmi_hdl); - -QDF_STATUS wmi_unified_set_smps_params(void *wmi_hdl, uint8_t vdev_id, - int value); - -QDF_STATUS wmi_unified_set_mimops(void *wmi_hdl, uint8_t vdev_id, int value); - -QDF_STATUS wmi_unified_lro_config_cmd(void *wmi_hdl, - struct wmi_lro_config_cmd_t *wmi_lro_cmd); - -QDF_STATUS wmi_unified_set_thermal_mgmt_cmd(void *wmi_hdl, - struct thermal_cmd_params *thermal_info); - -QDF_STATUS wmi_unified_peer_rate_report_cmd(void *wmi_hdl, - struct wmi_peer_rate_report_params *rate_report_params); - -QDF_STATUS wmi_unified_process_update_edca_param(void *wmi_hdl, - uint8_t vdev_id, bool mu_edca_param, - struct wmi_host_wme_vparams wmm_vparams[WMI_MAX_NUM_AC]); - -QDF_STATUS wmi_unified_probe_rsp_tmpl_send_cmd(void *wmi_hdl, - uint8_t vdev_id, - struct wmi_probe_resp_params *probe_rsp_info); - -QDF_STATUS wmi_unified_setup_install_key_cmd(void *wmi_hdl, - struct set_key_params *key_params); +wmi_unified_peer_delete_send(wmi_unified_t wmi_handle, + uint8_t peer_addr[QDF_MAC_ADDR_SIZE], + uint8_t vdev_id); -QDF_STATUS wmi_unified_p2p_go_set_beacon_ie_cmd(void *wmi_hdl, - uint32_t vdev_id, uint8_t *p2p_ie); - -QDF_STATUS wmi_unified_scan_probe_setoui_cmd(void *wmi_hdl, - struct scan_mac_oui *psetoui); - -#ifdef IPA_OFFLOAD -QDF_STATUS wmi_unified_ipa_offload_control_cmd(void *wmi_hdl, - struct ipa_uc_offload_control_params *ipa_offload); -#endif - -QDF_STATUS wmi_unified_pno_stop_cmd(void *wmi_hdl, uint8_t vdev_id); - -#ifdef FEATURE_WLAN_SCAN_PNO -QDF_STATUS wmi_unified_pno_start_cmd(void *wmi_hdl, - struct pno_scan_req_params *pno); -#endif - -QDF_STATUS wmi_unified_nlo_mawc_cmd(void *wmi_hdl, - struct nlo_mawc_params *params); - -#ifdef WLAN_FEATURE_LINK_LAYER_STATS /** - * wmi_unified_process_ll_stats_clear_cmd() - clear link layer stats + * wmi_unified_peer_flush_tids_send() - flush peer tids packets in fw * @wmi_handle: wmi handle - * @clear_req: ll stats clear request command params + * @peer_addr: peer mac address + * @param: pointer to hold peer flush tid parameter * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_process_ll_stats_clear_cmd(wmi_unified_t wmi_handle, - const struct ll_stats_clear_params *clear_req); +QDF_STATUS +wmi_unified_peer_flush_tids_send(wmi_unified_t wmi_handle, + uint8_t peer_addr[QDF_MAC_ADDR_SIZE], + struct peer_flush_params *param); /** - * wmi_unified_process_ll_stats_set_cmd() - link layer stats set request - * @wmi_handle: wmi handle - * @set_req: ll stats set request command params + * wmi_unified_peer_delete_all_send() - send PEER delete all command to fw + * @wmi_hdl: wmi handle + * @param: pointer to hold peer delete all parameters * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_process_ll_stats_set_cmd(wmi_unified_t wmi_handle, - const struct ll_stats_set_params *set_req); +QDF_STATUS wmi_unified_peer_delete_all_send( + wmi_unified_t wmi_hdl, + struct peer_delete_all_params *param); /** - * wmi_unified_process_ll_stats_get_cmd() - link layer stats get request + * wmi_set_peer_param() - set peer parameter in fw * @wmi_handle: wmi handle - * @get_req: ll stats get request command params + * @peer_addr: peer mac address + * @param: pointer to hold peer set parameter * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_process_ll_stats_get_cmd(wmi_unified_t wmi_handle, - const struct ll_stats_get_params *get_req); -#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ +QDF_STATUS +wmi_set_peer_param_send(wmi_unified_t wmi_handle, + uint8_t peer_addr[QDF_MAC_ADDR_SIZE], + struct peer_set_params *param); /** - * wmi_unified_congestion_request_cmd() - send request to fw to get CCA - * @wmi_hdl: wma handle + * wmi_unified_peer_create_send() - send peer create command to fw + * @wmi_handle: wmi handle + * @peer_addr: peer mac address + * @peer_type: peer type * @vdev_id: vdev id * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_congestion_request_cmd(void *wmi_hdl, - uint8_t vdev_id); - -QDF_STATUS wmi_unified_snr_request_cmd(void *wmi_hdl); +QDF_STATUS wmi_unified_peer_create_send(wmi_unified_t wmi_handle, + struct peer_create_params *param); -QDF_STATUS wmi_unified_snr_cmd(void *wmi_hdl, uint8_t vdev_id); +QDF_STATUS wmi_unified_stats_request_send(wmi_unified_t wmi_handle, + uint8_t macaddr[QDF_MAC_ADDR_SIZE], + struct stats_request_params *param); /** - * wmi_unified_link_status_req_cmd() - process link status request from UMAC + * wmi_unified_green_ap_ps_send() - enable green ap powersave command * @wmi_handle: wmi handle - * @params: get link status params + * @value: value + * @pdev_id: pdev id to have radio context * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_link_status_req_cmd(wmi_unified_t wmi_handle, - struct link_status_params *params); - -#ifdef WLAN_SUPPORT_GREEN_AP -QDF_STATUS wmi_unified_egap_conf_params_cmd(void *wmi_hdl, - struct wlan_green_ap_egap_params *egap_params); -#endif - -QDF_STATUS wmi_unified_csa_offload_enable(void *wmi_hdl, uint8_t vdev_id); +QDF_STATUS wmi_unified_green_ap_ps_send(wmi_unified_t wmi_handle, + uint32_t value, uint8_t pdev_id); -#ifdef WLAN_FEATURE_CIF_CFR /** - * wmi_unified_oem_dma_ring_cfg() - configure OEM DMA rings - * @wmi_handle: wmi handle - * @data_len: len of dma cfg req - * @data: dma cfg req + * wmi_unified_wow_enable_send() - WMI wow enable function + * @wmi_handle: handle to WMI. + * @param: pointer to hold wow enable parameter + * @mac_id: radio context * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_oem_dma_ring_cfg(void *wmi_hdl, - wmi_oem_dma_ring_cfg_req_fixed_param *cfg); -#endif +QDF_STATUS wmi_unified_wow_enable_send(wmi_unified_t wmi_handle, + struct wow_cmd_params *param, + uint8_t mac_id); /** - * wmi_unified_start_oem_data_cmd() - start oem data request to target - * @wmi_handle: wmi handle - * @data_len: the length of @data - * @data: the pointer to data buf - * - * This is legacy api for oem data request, using wmi command - * WMI_OEM_REQ_CMDID. + * wmi_unified_wow_wakeup_send() - WMI wow wakeup function + * @wmi_handle: handle to WMI. * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_start_oem_data_cmd(wmi_unified_t wmi_handle, - uint32_t data_len, - uint8_t *data); +QDF_STATUS wmi_unified_wow_wakeup_send(wmi_unified_t wmi_handle); -QDF_STATUS wmi_unified_dfs_phyerr_filter_offload_en_cmd(void *wmi_hdl, - bool dfs_phyerr_filter_offload); - -#ifdef CONFIG_MCL -QDF_STATUS wmi_unified_pktlog_wmi_send_cmd(void *wmi_hdl, - WMI_PKTLOG_EVENT pktlog_event, - uint32_t cmd_id, - uint8_t user_triggered); -#endif - -QDF_STATUS wmi_unified_stats_ext_req_cmd(void *wmi_hdl, - struct stats_ext_params *preq); - -QDF_STATUS wmi_unified_process_dhcpserver_offload_cmd(void *wmi_hdl, - struct dhcp_offload_info_params *params); +/** + * wmi_unified_wow_add_wakeup_event_send() - WMI wow wakeup function + * @wmi_handle: handle to WMI. + * @param: pointer to wow wakeup event parameter structure + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_wow_add_wakeup_event_send(wmi_unified_t wmi_handle, + struct wow_add_wakeup_params *param); -QDF_STATUS wmi_unified_send_regdomain_info_to_fw_cmd(void *wmi_hdl, - uint32_t reg_dmn, uint16_t regdmn2G, - uint16_t regdmn5G, uint8_t ctl2G, - uint8_t ctl5G); +/** + * wmi_unified_wow_add_wakeup_pattern_send() - WMI wow wakeup pattern function + * @wmi_handle: handle to WMI. + * @param: pointer to wow wakeup pattern parameter structure + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_wow_add_wakeup_pattern_send( + wmi_unified_t wmi_handle, + struct wow_add_wakeup_pattern_params *param); -QDF_STATUS wmi_unified_process_fw_mem_dump_cmd(void *wmi_hdl, - struct fw_dump_req_param *mem_dump_req); +/** + * wmi_unified_wow_remove_wakeup_pattern_send() - wow wakeup pattern function + * @wmi_handle: handle to WMI. + * @param: pointer to wow wakeup pattern parameter structure + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_wow_remove_wakeup_pattern_send( + wmi_unified_t wmi_handle, + struct wow_remove_wakeup_pattern_params *param); -QDF_STATUS wmi_unified_cfg_action_frm_tb_ppdu_cmd(void *wmi_hdl, - struct cfg_action_frm_tb_ppdu_param *cfg_info); +/** + * wmi_unified_packet_log_enable_send() - WMI request stats function + * @wmi_handle : handle to WMI. + * @PKTLOG_EVENT : PKTLOG Event + * @mac_id : MAC id corresponds to pdev id + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_packet_log_enable_send(wmi_unified_t wmi_handle, + WMI_HOST_PKTLOG_EVENT PKTLOG_EVENT, + uint8_t mac_id); -QDF_STATUS wmi_unified_save_fw_version_cmd(void *wmi_hdl, - void *evt_buf); +/** + * wmi_unified_peer_based_pktlog_send() - WMI request enable peer + * based filtering + * @wmi_handle: handle to WMI. + * @macaddr: PEER mac address to be filtered + * @mac_id: Mac id + * @enb_dsb: Enable or Disable peer based pktlog + * filtering + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_peer_based_pktlog_send(wmi_unified_t wmi_handle, + uint8_t *macaddr, + uint8_t mac_id, + uint8_t enb_dsb); -QDF_STATUS wmi_unified_log_supported_evt_cmd(void *wmi_hdl, - uint8_t *event, - uint32_t len); +/** + * wmi_unified_packet_log_disable__send() - WMI pktlog disable function + * @wmi_handle: handle to WMI. + * @PKTLOG_EVENT: packet log event + * + * @return QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_packet_log_disable_send(wmi_unified_t wmi_handle, + uint8_t mac_id); -QDF_STATUS wmi_unified_enable_specific_fw_logs_cmd(void *wmi_hdl, - struct wmi_wifi_start_log *start_log); +/** + * wmi_unified_suspend_send() - WMI suspend function + * @wmi_handle: handle to WMI. + * @param: pointer to hold suspend parameter + * @mac_id: radio context + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_suspend_send(wmi_unified_t wmi_handle, + struct suspend_params *param, + uint8_t mac_id); -QDF_STATUS wmi_unified_flush_logs_to_fw_cmd(void *wmi_hdl); +/** + * wmi_unified_resume_send - WMI resume function + * @wmi_handle : handle to WMI. + * @mac_id: radio context + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_resume_send(wmi_unified_t wmi_handle, + uint8_t mac_id); -QDF_STATUS wmi_unified_unit_test_cmd(void *wmi_hdl, - struct wmi_unit_test_cmd *wmi_utest); +/** + * wmi_unified_pdev_param_send() - set pdev parameters + * @wmi_handle: wmi handle + * @param: pointer to pdev parameter + * @mac_id: radio context + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failures, + * errno on failure + */ +QDF_STATUS +wmi_unified_pdev_param_send(wmi_unified_t wmi_handle, + struct pdev_params *param, + uint8_t mac_id); -#ifdef FEATURE_WLAN_APF /** - * wmi_unified_set_active_apf_mode_cmd() - config active APF mode in FW - * @wmi: the WMI handle - * @vdev_id: the Id of the vdev to apply the configuration to - * @ucast_mode: the active APF mode to configure for unicast packets - * @mcast_bcast_mode: the active APF mode to configure for multicast/broadcast - * packets + * wmi_unified_fd_tmpl_send_cmd() - WMI FILS Discovery send function + * @wmi_handle: handle to WMI. + * @param: pointer to hold FILS Discovery send cmd parameter + * + * @return QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ QDF_STATUS -wmi_unified_set_active_apf_mode_cmd(wmi_unified_t wmi, uint8_t vdev_id, - enum wmi_host_active_apf_mode ucast_mode, - enum wmi_host_active_apf_mode - mcast_bcast_mode); +wmi_unified_fd_tmpl_send_cmd(wmi_unified_t wmi_handle, + struct fils_discovery_tmpl_params *param); /** - * wmi_unified_send_apf_enable_cmd() - send apf enable/disable cmd - * @wmi: wmi handle - * @vdev_id: VDEV id - * @enable: true: enable, false: disable + * wmi_unified_beacon_tmpl_send_cmd() - WMI beacon send function + * @wmi_handle: handle to WMI. + * @macaddr: MAC address + * @param: pointer to hold beacon send cmd parameter * - * This function passes the apf enable command to fw + * @return QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_beacon_tmpl_send_cmd(wmi_unified_t wmi_handle, + struct beacon_tmpl_params *param); + +/** + * wmi_unified_peer_assoc_send() - WMI peer assoc function + * @wmi_handle: handle to WMI. + * @macaddr: MAC address + * @param: pointer to peer assoc parameter * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_send_apf_enable_cmd(wmi_unified_t wmi, - uint32_t vdev_id, bool enable); +QDF_STATUS wmi_unified_peer_assoc_send(wmi_unified_t wmi_handle, + struct peer_assoc_params *param); /** - * wmi_unified_send_apf_write_work_memory_cmd() - send cmd to write into the APF - * work memory. - * @wmi: wmi handle - * @write_params: parameters and buffer pointer for the write - * - * This function passes the write apf work mem command to fw + * wmi_unified_sta_ps_cmd_send() - set sta powersave parameters + * @wmi_handle: wmi handle + * @peer_addr: peer mac address + * @param: pointer to sta_ps parameter structure * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_send_apf_write_work_memory_cmd(wmi_unified_t wmi, - struct wmi_apf_write_memory_params *write_params); +QDF_STATUS wmi_unified_sta_ps_cmd_send(wmi_unified_t wmi_handle, + struct sta_ps_params *param); /** - * wmi_unified_send_apf_read_work_memory_cmd() - send cmd to read part of APF - * work memory - * @wmi: wmi handle - * @read_params: contains relative address and length to read from - * - * This function passes the read apf work mem command to fw + * wmi_unified_ap_ps_cmd_send() - set ap powersave parameters + * @wmi_handle: wmi handle + * @peer_addr: peer mac address + * @param: pointer to ap_ps parameter structure * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_send_apf_read_work_memory_cmd(wmi_unified_t wmi, - struct wmi_apf_read_memory_params *read_params); +QDF_STATUS wmi_unified_ap_ps_cmd_send(wmi_unified_t wmi_handle, + uint8_t macaddr[QDF_MAC_ADDR_SIZE], + struct ap_ps_params *param); /** - * wmi_extract_apf_read_memory_resp_event() - exctract read mem resp event - * @wmi: wmi handle - * @evt_buf: Pointer to the event buffer - * @resp: pointer to memory to extract event parameters into - * - * This function exctracts read mem response event into the given structure ptr + * wmi_unified_scan_start_cmd_send() - WMI scan start function + * @wmi_handle: handle to WMI. + * @macaddr: MAC address + * @param: pointer to hold scan start cmd parameter * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ QDF_STATUS -wmi_extract_apf_read_memory_resp_event(wmi_unified_t wmi, void *evt_buf, - struct wmi_apf_read_memory_resp_event_params - *read_mem_evt); -#endif /* FEATURE_WLAN_APF */ - -QDF_STATUS wmi_send_get_user_position_cmd(void *wmi_hdl, uint32_t value); - -QDF_STATUS wmi_send_get_peer_mumimo_tx_count_cmd(void *wmi_hdl, uint32_t value); - -QDF_STATUS wmi_send_reset_peer_mumimo_tx_count_cmd(void *wmi_hdl, - uint32_t value); - -QDF_STATUS wmi_unified_send_btcoex_wlan_priority_cmd(void *wmi_hdl, - struct btcoex_cfg_params *param); - -QDF_STATUS wmi_unified_send_btcoex_duty_cycle_cmd(void *wmi_hdl, - struct btcoex_cfg_params *param); - -QDF_STATUS wmi_unified_send_coex_ver_cfg_cmd(void *wmi_hdl, - coex_ver_cfg_t *param); - -QDF_STATUS wmi_unified_send_coex_config_cmd(void *wmi_hdl, - struct coex_config_params *param); - -QDF_STATUS wmi_unified_pdev_fips_cmd_send(void *wmi_hdl, - struct fips_params *param); - -QDF_STATUS wmi_unified_wlan_profile_enable_cmd_send(void *wmi_hdl, - struct wlan_profile_params *param); - -QDF_STATUS wmi_unified_wlan_profile_trigger_cmd_send(void *wmi_hdl, - struct wlan_profile_params *param); - -QDF_STATUS wmi_unified_set_chan_cmd_send(void *wmi_hdl, - struct channel_param *param); - -QDF_STATUS wmi_unified_set_ratepwr_table_cmd_send(void *wmi_hdl, - struct ratepwr_table_params *param); - -QDF_STATUS wmi_unified_get_ratepwr_table_cmd_send(void *wmi_hdl); - -QDF_STATUS wmi_unified_set_ratepwr_chainmsk_cmd_send(void *wmi_hdl, - struct ratepwr_chainmsk_params *param); - -QDF_STATUS wmi_unified_set_macaddr_cmd_send(void *wmi_hdl, - struct macaddr_params *param); - -QDF_STATUS wmi_unified_pdev_scan_start_cmd_send(void *wmi_hdl); - -QDF_STATUS wmi_unified_pdev_scan_end_cmd_send(void *wmi_hdl); - -QDF_STATUS wmi_unified_set_acparams_cmd_send(void *wmi_hdl, - struct acparams_params *param); - -QDF_STATUS wmi_unified_set_vap_dscp_tid_map_cmd_send(void *wmi_hdl, - struct vap_dscp_tid_map_params *param); - -QDF_STATUS wmi_unified_proxy_ast_reserve_cmd_send(void *wmi_hdl, - struct proxy_ast_reserve_params *param); +wmi_unified_scan_start_cmd_send(wmi_unified_t wmi_handle, + struct scan_req_params *param); /** - * wmi_unified_set_bridge_mac_addr_cmd_send() - WMI set bridge mac addr cmd function - * @param wmi_hdl : handle to WMI. - * @param param : pointer to hold bridge mac addr param + * wmi_unified_scan_stop_cmd_send() - WMI scan start function + * @wmi_handle: handle to WMI. + * @macaddr: MAC address + * @param: pointer to hold scan start cmd parameter * - * @return QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_set_bridge_mac_addr_cmd_send(void *wmi_hdl, - struct set_bridge_mac_addr_params *param); - - -QDF_STATUS wmi_unified_phyerr_enable_cmd_send(void *wmi_hdl); - -QDF_STATUS wmi_unified_phyerr_enable_cmd_send(void *wmi_hdl); - -QDF_STATUS wmi_unified_phyerr_disable_cmd_send(void *wmi_hdl); - -QDF_STATUS wmi_unified_smart_ant_enable_tx_feedback_cmd_send(void *wmi_hdl, - struct smart_ant_enable_tx_feedback_params *param); - -QDF_STATUS wmi_unified_vdev_spectral_configure_cmd_send(void *wmi_hdl, - struct vdev_spectral_configure_params *param); - -QDF_STATUS wmi_unified_vdev_spectral_enable_cmd_send(void *wmi_hdl, - struct vdev_spectral_enable_params *param); - -QDF_STATUS wmi_unified_bss_chan_info_request_cmd_send(void *wmi_hdl, - struct bss_chan_info_request_params *param); +QDF_STATUS +wmi_unified_scan_stop_cmd_send(wmi_unified_t wmi_handle, + struct scan_cancel_param *param); -QDF_STATUS wmi_unified_thermal_mitigation_param_cmd_send(void *wmi_hdl, - struct thermal_mitigation_params *param); +/** + * wmi_unified_scan_chan_list_cmd_send() - WMI scan channel list function + * @wmi_handle: handle to WMI. + * @macaddr: MAC address + * @param: pointer to hold scan channel list parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_scan_chan_list_cmd_send(wmi_unified_t wmi_handle, + struct scan_chan_list_params *param); -QDF_STATUS wmi_unified_vdev_set_fwtest_param_cmd_send(void *wmi_hdl, - struct set_fwtest_params *param); /** - * wmi_unified_vdev_set_custom_aggr_size_cmd_send() - WMI set custom aggr - * size command - * @param wmi_hdl : handle to WMI. - * @param param : pointer to hold custom aggr size param + * wmi_crash_inject() - inject fw crash + * @wmi_handle: wmi handle + * @param: ponirt to crash inject parameter structure * - * @return QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_vdev_set_custom_aggr_size_cmd_send(void *wmi_hdl, - struct set_custom_aggr_size_params *param); +QDF_STATUS wmi_crash_inject(wmi_unified_t wmi_handle, + struct crash_inject *param); /** - * wmi_unified_vdev_set_qdepth_thresh_cmd_send() - WMI set qdepth threshold - * @param wmi_hdl : handle to WMI. - * @param param : pointer to hold set qdepth thresh param + * wmi_unified_pdev_utf_cmd() - send utf command to fw + * @wmi_handle: wmi handle + * @param: pointer to pdev_utf_params + * @mac_id: mac id to have radio context * - * @return QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_vdev_set_qdepth_thresh_cmd_send(void *wmi_hdl, - struct set_qdepth_thresh_params *param); - -QDF_STATUS wmi_unified_pdev_set_regdomain_cmd_send(void *wmi_hdl, - struct pdev_set_regdomain_params *param); - -QDF_STATUS wmi_unified_set_beacon_filter_cmd_send(void *wmi_hdl, - struct set_beacon_filter_params *param); - -QDF_STATUS wmi_unified_remove_beacon_filter_cmd_send(void *wmi_hdl, - struct remove_beacon_filter_params *param); +QDF_STATUS wmi_unified_pdev_utf_cmd_send(wmi_unified_t wmi_handle, + struct pdev_utf_params *param, + uint8_t mac_id); -QDF_STATUS wmi_unified_addba_clearresponse_cmd_send(void *wmi_hdl, - uint8_t macaddr[QDF_MAC_ADDR_SIZE], - struct addba_clearresponse_params *param); - -QDF_STATUS wmi_unified_addba_send_cmd_send(void *wmi_hdl, - uint8_t macaddr[QDF_MAC_ADDR_SIZE], - struct addba_send_params *param); - -QDF_STATUS wmi_unified_delba_send_cmd_send(void *wmi_hdl, - uint8_t macaddr[QDF_MAC_ADDR_SIZE], - struct delba_send_params *param); - -QDF_STATUS wmi_unified_addba_setresponse_cmd_send(void *wmi_hdl, - uint8_t macaddr[QDF_MAC_ADDR_SIZE], - struct addba_setresponse_params *param); - -QDF_STATUS wmi_unified_singleamsdu_cmd_send(void *wmi_hdl, - uint8_t macaddr[QDF_MAC_ADDR_SIZE], - struct singleamsdu_params *param); - -QDF_STATUS wmi_unified_mu_scan_cmd_send(void *wmi_hdl, - struct mu_scan_params *param); - -QDF_STATUS wmi_unified_lteu_config_cmd_send(void *wmi_hdl, - struct lteu_config_params *param); - -QDF_STATUS wmi_unified_set_psmode_cmd_send(void *wmi_hdl, - struct set_ps_mode_params *param); +#ifdef FEATURE_FW_LOG_PARSING +/** + * wmi_unified_dbglog_cmd_send() - set debug log level + * @wmi_handle: handle to WMI. + * @param: pointer to hold dbglog level parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_dbglog_cmd_send(wmi_unified_t wmi_handle, + struct dbglog_params *param); +#else +static inline QDF_STATUS +wmi_unified_dbglog_cmd_send(wmi_unified_t wmi_handle, + struct dbglog_params *param) +{ + return QDF_STATUS_SUCCESS; +} +#endif -QDF_STATUS wmi_unified_init_cmd_send(void *wmi_hdl, - struct wmi_init_cmd_param *param); +/** + * wmi_mgmt_unified_cmd_send() - management cmd over wmi layer + * @wmi_handle: handle to WMI. + * @param: pointer to hold mgmt cmd parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_mgmt_unified_cmd_send(wmi_unified_t wmi_handle, + struct wmi_mgmt_params *param); -bool wmi_service_enabled(void *wmi_hdl, uint32_t service_id); +/** + * wmi_offchan_data_tx_cmd_send() - Send offchan data tx cmd over wmi layer + * @wmi_handle: handle to WMI. + * @param: pointer to hold offchan data cmd parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_offchan_data_tx_cmd_send( + wmi_unified_t wmi_handle, + struct wmi_offchan_data_tx_params *param); /** - * wmi_save_service_bitmap() - save service bitmap + * wmi_unified_modem_power_state() - set modem power state to fw * @wmi_handle: wmi handle - * @param evt_buf: pointer to event buffer + * @param_value: parameter value * - * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS failure code + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_save_service_bitmap(void *wmi_hdl, void *evt_buf, - void *bitmap_buf); +QDF_STATUS wmi_unified_modem_power_state(wmi_unified_t wmi_handle, + uint32_t param_value); /** - * wmi_save_ext_service_bitmap() - save extended service bitmap + * wmi_unified_set_sta_ps_mode() - set sta powersave params in fw * @wmi_handle: wmi handle - * @param evt_buf: pointer to event buffer + * @vdev_id: vdev id + * @val: value * - * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS failure code + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure. */ -QDF_STATUS wmi_save_ext_service_bitmap(void *wmi_hdl, void *evt_buf, - void *bitmap_buf); +QDF_STATUS wmi_unified_set_sta_ps_mode(wmi_unified_t wmi_handle, + uint32_t vdev_id, + uint8_t val); -QDF_STATUS wmi_save_fw_version(void *wmi_hdl, void *evt_buf); +/** + * wmi_unified_set_sta_uapsd_auto_trig_cmd() - set uapsd auto trigger command + * @wmi_handle: wmi handle + * @param: uapsd cmd parameter strcture + * + * This function sets the trigger + * uapsd params such as service interval, delay interval + * and suspend interval which will be used by the firmware + * to send trigger frames periodically when there is no + * traffic on the transmit side. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure. + */ +QDF_STATUS +wmi_unified_set_sta_uapsd_auto_trig_cmd(wmi_unified_t wmi_handle, + struct sta_uapsd_trig_params *param); -QDF_STATUS wmi_get_target_cap_from_service_ready(void *wmi_hdl, - void *evt_buf, - struct wlan_psoc_target_capability_info *ev); +/** + * wmi_get_temperature() - get pdev temperature req + * @wmi_handle: wmi handle + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure. + */ +QDF_STATUS wmi_unified_get_temperature(wmi_unified_t wmi_handle); -QDF_STATUS wmi_extract_hal_reg_cap(void *wmi_hdl, void *evt_buf, - struct wlan_psoc_hal_reg_capability *hal_reg_cap); +/** + * wmi_set_smps_params() - set smps params + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * @value: value + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure. + */ +QDF_STATUS wmi_unified_set_smps_params(wmi_unified_t wmi_handle, + uint8_t vdev_id, + int value); -host_mem_req *wmi_extract_host_mem_req_from_service_ready(void *wmi_hdl, - void *evt_buf, uint8_t *num_entries); +/** + * wmi_set_mimops() - set MIMO powersave + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * @value: value + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure. + */ +QDF_STATUS wmi_unified_set_mimops(wmi_unified_t wmi_handle, + uint8_t vdev_id, int value); -uint32_t wmi_ready_extract_init_status(void *wmi_hdl, void *ev); +/** + * wmi_unified_lro_config_cmd() - process the LRO config command + * @wmi_handle: Pointer to wmi handle + * @wmi_lro_cmd: Pointer to LRO configuration parameters + * + * This function sends down the LRO configuration parameters to + * the firmware to enable LRO, sets the TCP flags and sets the + * seed values for the toeplitz hash generation + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_lro_config_cmd(wmi_unified_t wmi_handle, + struct wmi_lro_config_cmd_t *wmi_lro_cmd); -QDF_STATUS wmi_ready_extract_mac_addr(void *wmi_hdl, - void *ev, uint8_t *macaddr); +/** + * wmi_unified_set_thermal_mgmt_cmd() - set thermal mgmt command to fw + * @wmi_handle: Pointer to wmi handle + * @thermal_info: Thermal command information + * + * This function sends the thermal management command + * to the firmware + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_set_thermal_mgmt_cmd(wmi_unified_t wmi_handle, + struct thermal_cmd_params *thermal_info); -wmi_host_mac_addr *wmi_ready_extract_mac_addr_list(void *wmi_hdl, void *ev, - uint8_t *num_mac_addr); +/** + * wmi_unified_peer_rate_report_cmd() - process the peer rate report command + * @wmi_handle: Pointer to wmi handle + * @rate_report_params: Pointer to peer rate report parameters + * + * + * Return: QDF_STATUS_SUCCESS for success otherwise failure + */ +QDF_STATUS +wmi_unified_peer_rate_report_cmd( + wmi_unified_t wmi_handle, + struct wmi_peer_rate_report_params *rate_report_params); /** - * wmi_extract_ready_params() - Extract data from ready event apart from - * status, macaddr and version. - * @wmi_handle: Pointer to WMI handle. - * @evt_buf: Pointer to Ready event buffer. - * @ev_param: Pointer to host defined struct to copy the data from event. + * wmi_unified_process_update_edca_param() - update EDCA params + * @wmi_handle: wmi handle + * @vdev_id: vdev id. + * @mu_edca_param: mu_edca_param. + * @wmm_vparams: edca parameters * - * Return: QDF_STATUS_SUCCESS on success. + * This function updates EDCA parameters to the target + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_extract_ready_event_params(void *wmi_hdl, - void *evt_buf, struct wmi_host_ready_ev_param *ev_param); +QDF_STATUS +wmi_unified_process_update_edca_param( + wmi_unified_t wmi_handle, + uint8_t vdev_id, + bool mu_edca_param, + struct wmi_host_wme_vparams wmm_vparams[WMI_MAX_NUM_AC]); -QDF_STATUS wmi_extract_fw_version(void *wmi_hdl, - void *ev, struct wmi_host_fw_ver *fw_ver); +/** + * wmi_unified_probe_rsp_tmpl_send_cmd() - send probe response template to fw + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * @probe_rsp_info: probe response info + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_probe_rsp_tmpl_send_cmd( + wmi_unified_t wmi_handle, + uint8_t vdev_id, + struct wmi_probe_resp_params *probe_rsp_info); + +/** + * wmi_unified_setup_install_key_cmd - send key to install to fw + * @wmi_handle: wmi handle + * @key_params: key parameters + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_setup_install_key_cmd(wmi_unified_t wmi_handle, + struct set_key_params *key_params); + +/** + * wmi_unified_get_pn_send_cmd() - send command to fw get PN for peer + * @wmi_handle: wmi handle + * @pn_params: PN parameters + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_get_pn_send_cmd(wmi_unified_t wmi_hdl, + struct peer_request_pn_param *pn_params); + +/** + * wmi_unified_p2p_go_set_beacon_ie_cmd() - set beacon IE for p2p go + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * @p2p_ie: p2p IE + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_p2p_go_set_beacon_ie_cmd(wmi_unified_t wmi_hdl, + uint32_t vdev_id, + uint8_t *p2p_ie); + +/** + * wmi_unified_scan_probe_setoui_cmd() - set scan probe OUI + * @wmi_handle: wmi handle + * @psetoui: OUI parameters + * + * set scan probe OUI parameters in firmware + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_scan_probe_setoui_cmd(wmi_unified_t wmi_handle, + struct scan_mac_oui *psetoui); + +#ifdef IPA_OFFLOAD +/** wmi_unified_ipa_offload_control_cmd() - ipa offload control parameter + * @wmi_handle: wmi handle + * @ipa_offload: ipa offload control parameter + * + * Returns: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failures, + * error number otherwise + */ +QDF_STATUS +wmi_unified_ipa_offload_control_cmd( + wmi_unified_t wmi_handle, + struct ipa_uc_offload_control_params *ipa_offload); +#endif + +/** + * wmi_unified_pno_stop_cmd() - PNO stop request + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * + * This function request FW to stop ongoing PNO operation. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_pno_stop_cmd(wmi_unified_t wmi_handle, uint8_t vdev_id); + +#ifdef FEATURE_WLAN_SCAN_PNO +/** + * wmi_unified_pno_start_cmd() - PNO start request + * @wmi_handle: wmi handle + * @pno: PNO request + * + * This function request FW to start PNO request. + * Request: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_pno_start_cmd(wmi_unified_t wmi_handle, + struct pno_scan_req_params *pno); +#endif + +/** + * wmi_unified_nlo_mawc_cmd() - NLO MAWC cmd configuration + * @wmi_handle: wmi handle + * @params: Configuration parameters + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_nlo_mawc_cmd(wmi_unified_t wmi_handle, + struct nlo_mawc_params *params); + +#ifdef WLAN_FEATURE_LINK_LAYER_STATS +/** + * wmi_unified_process_ll_stats_clear_cmd() - clear link layer stats + * @wmi_handle: wmi handle + * @clear_req: ll stats clear request command params + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_process_ll_stats_clear_cmd(wmi_unified_t wmi_handle, + const struct ll_stats_clear_params *clear_req); + +/** + * wmi_unified_process_ll_stats_set_cmd() - link layer stats set request + * @wmi_handle: wmi handle + * @set_req: ll stats set request command params + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_process_ll_stats_set_cmd(wmi_unified_t wmi_handle, + const struct ll_stats_set_params *set_req); + +/** + * wmi_unified_process_ll_stats_get_cmd() - link layer stats get request + * @wmi_handle: wmi handle + * @get_req: ll stats get request command params + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_process_ll_stats_get_cmd(wmi_unified_t wmi_handle, + const struct ll_stats_get_params *get_req); +#endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +/** + * wmi_unified_congestion_request_cmd() - send request to fw to get CCA + * @wmi_handle: wma handle + * @vdev_id: vdev id + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_congestion_request_cmd(wmi_unified_t wmi_handle, + uint8_t vdev_id); + +/** + * wmi_unified_snr_request_cmd() - send request to fw to get RSSI stats + * @wmi_handle: wmi handle + * @rssi_req: get RSSI request + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_snr_request_cmd(wmi_unified_t wmi_handle); + +/** + * wmi_unified_snr_cmd() - get RSSI from fw + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_snr_cmd(wmi_unified_t wmi_handle, uint8_t vdev_id); + +/** + * wmi_unified_link_status_req_cmd() - process link status request from UMAC + * @wmi_handle: wmi handle + * @params: get link status params + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_link_status_req_cmd(wmi_unified_t wmi_handle, + struct link_status_params *params); + +#ifdef WLAN_SUPPORT_GREEN_AP +/** + * wmi_unified_egap_conf_params_cmd() - send wmi cmd of egap config params + * @wmi_handle: wmi handler + * @egap_params: pointer to egap_params + * + * Return: 0 for success, otherwise appropriate error code + */ +QDF_STATUS +wmi_unified_egap_conf_params_cmd( + wmi_unified_t wmi_handle, + struct wlan_green_ap_egap_params *egap_params); +#endif + +/** + * wmi_unified_csa_offload_enable() - send CSA offload enable command + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_csa_offload_enable(wmi_unified_t wmi_handle, + uint8_t vdev_id); + +#ifdef WLAN_FEATURE_CIF_CFR +/** + * wmi_unified_oem_dma_ring_cfg() - configure OEM DMA rings + * @wmi_handle: wmi handle + * @data_len: len of dma cfg req + * @data: dma cfg req + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_oem_dma_ring_cfg(wmi_unified_t wmi_handle, + wmi_oem_dma_ring_cfg_req_fixed_param *cfg); +#endif + +/** + * wmi_unified_start_oem_data_cmd() - start oem data request to target + * @wmi_handle: wmi handle + * @data_len: the length of @data + * @data: the pointer to data buf + * + * This is legacy api for oem data request, using wmi command + * WMI_OEM_REQ_CMDID. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_start_oem_data_cmd(wmi_unified_t wmi_handle, + uint32_t data_len, + uint8_t *data); + +#ifdef FEATURE_OEM_DATA +/** + * wmi_unified_start_oemv2_data_cmd() - start oem data cmd to target + * @wmi_handle: wmi handle + * @params: oem data params + * + * This is common api for oem data, using wmi command WMI_OEM_DATA_CMDID. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_start_oemv2_data_cmd(wmi_unified_t wmi_handle, + struct oem_data *params); +#endif + +/** + * wmi_unified_dfs_phyerr_filter_offload_en_cmd() - enable dfs phyerr filter + * @wmi_handle: wmi handle + * @dfs_phyerr_filter_offload: is dfs phyerr filter offload + * + * Send WMI_DFS_PHYERR_FILTER_ENA_CMDID or + * WMI_DFS_PHYERR_FILTER_DIS_CMDID command + * to firmware based on phyerr filtering + * offload status. + * + * Return: 1 success, 0 failure + */ +QDF_STATUS +wmi_unified_dfs_phyerr_filter_offload_en_cmd(wmi_unified_t wmi_handle, + bool dfs_phyerr_filter_offload); + +#if !defined(REMOVE_PKT_LOG) && defined(FEATURE_PKTLOG) +/** + * wmi_unified_pktlog_wmi_send_cmd() - send pktlog event command to target + * @wmi_handle: wmi handle + * @pktlog_event: pktlog event + * @cmd_id: pktlog cmd id + * @user_triggered: user triggered input for PKTLOG enable mode + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_pktlog_wmi_send_cmd(wmi_unified_t wmi_handle, + WMI_PKTLOG_EVENT pktlog_event, + uint32_t cmd_id, + uint8_t user_triggered); +#endif + +/** + * wmi_unified_stats_ext_req_cmd() - request ext stats from fw + * @wmi_handle: wmi handle + * @preq: stats ext params + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_stats_ext_req_cmd(wmi_unified_t wmi_handle, + struct stats_ext_params *preq); + +/** + * wmi_unified_process_dhcpserver_offload_cmd() - enable DHCP server offload + * @wmi_handle: wmi handle + * @pDhcpSrvOffloadInfo: DHCP server offload info + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_process_dhcpserver_offload_cmd( + wmi_unified_t wmi_handle, + struct dhcp_offload_info_params *params); + +/** + * wmi_unified_send_regdomain_info_to_fw_cmd() - send regdomain info to fw + * @wmi_handle: wmi handle + * @reg_dmn: reg domain + * @regdmn2G: 2G reg domain + * @regdmn5G: 5G reg domain + * @ctl2G: 2G test limit + * @ctl5G: 5G test limit + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_send_regdomain_info_to_fw_cmd(wmi_unified_t wmi_handle, + uint32_t reg_dmn, + uint16_t regdmn2G, + uint16_t regdmn5G, + uint8_t ctl2G, + uint8_t ctl5G); + +QDF_STATUS +wmi_unified_process_fw_mem_dump_cmd(wmi_unified_t wmi_hdl, + struct fw_dump_req_param *mem_dump_req); + +/** + * wmi_unified_cfg_action_frm_tb_ppdu_cmd()-send action frame TB PPDU cfg to FW + * @wmi_handle: Pointer to WMi handle + * @cfg_info: Pointer to cfg msg + * + * This function sends action frame TB PPDU cfg to firmware + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + * + */ +QDF_STATUS +wmi_unified_cfg_action_frm_tb_ppdu_cmd( + wmi_unified_t wmi_handle, + struct cfg_action_frm_tb_ppdu_param *cfg_info); + +/** + * wmi_unified_save_fw_version_cmd() - save fw version + * @wmi_handle: pointer to wmi handle + * @evt_buf: Event buffer + * + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + * + */ +QDF_STATUS wmi_unified_save_fw_version_cmd(wmi_unified_t wmi_handle, + void *evt_buf); + +/** + * wmi_unified_log_supported_evt_cmd() - Enable/Disable FW diag/log events + * @wmi_handle: wmi handle + * @event: Event received from FW + * @len: Length of the event + * + * Enables the low frequency events and disables the high frequency + * events. Bit 17 indicates if the event if low/high frequency. + * 1 - high frequency, 0 - low frequency + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failures + */ +QDF_STATUS wmi_unified_log_supported_evt_cmd(wmi_unified_t wmi_handle, + uint8_t *event, + uint32_t len); + +/** + * wmi_unified_enable_specific_fw_logs_cmd() - Start/Stop logging of diag log id + * @wmi_handle: wmi handle + * @start_log: Start logging related parameters + * + * Send the command to the FW based on which specific logging of diag + * event/log id can be started/stopped + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_enable_specific_fw_logs_cmd(wmi_unified_t wmi_handle, + struct wmi_wifi_start_log *start_log); + +/** + * wmi_unified_flush_logs_to_fw_cmd() - Send log flush command to FW + * @wmi_handle: WMI handle + * + * This function is used to send the flush command to the FW, + * that will flush the fw logs that are residue in the FW + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_flush_logs_to_fw_cmd(wmi_unified_t wmi_handle); + +/** + * wmi_unified_unit_test_cmd() - send unit test command to fw. + * @wmi_handle: wmi handle + * @wmi_utest: unit test command + * + * This function send unit test command to fw. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_unit_test_cmd(wmi_unified_t wmi_handle, + struct wmi_unit_test_cmd *wmi_utest); + +#ifdef FEATURE_WLAN_APF +/** + * wmi_unified_set_active_apf_mode_cmd() - config active APF mode in FW + * @wmi: the WMI handle + * @vdev_id: the Id of the vdev to apply the configuration to + * @ucast_mode: the active APF mode to configure for unicast packets + * @mcast_bcast_mode: the active APF mode to configure for multicast/broadcast + * packets + */ +QDF_STATUS +wmi_unified_set_active_apf_mode_cmd(wmi_unified_t wmi, uint8_t vdev_id, + enum wmi_host_active_apf_mode ucast_mode, + enum wmi_host_active_apf_mode + mcast_bcast_mode); + +/** + * wmi_unified_send_apf_enable_cmd() - send apf enable/disable cmd + * @wmi: wmi handle + * @vdev_id: VDEV id + * @enable: true: enable, false: disable + * + * This function passes the apf enable command to fw + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_send_apf_enable_cmd(wmi_unified_t wmi, + uint32_t vdev_id, bool enable); + +/** + * wmi_unified_send_apf_write_work_memory_cmd() - send cmd to write into the APF + * work memory. + * @wmi: wmi handle + * @write_params: parameters and buffer pointer for the write + * + * This function passes the write apf work mem command to fw + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_send_apf_write_work_memory_cmd(wmi_unified_t wmi, + struct wmi_apf_write_memory_params *write_params); + +/** + * wmi_unified_send_apf_read_work_memory_cmd() - send cmd to read part of APF + * work memory + * @wmi: wmi handle + * @read_params: contains relative address and length to read from + * + * This function passes the read apf work mem command to fw + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_send_apf_read_work_memory_cmd(wmi_unified_t wmi, + struct wmi_apf_read_memory_params *read_params); + +/** + * wmi_extract_apf_read_memory_resp_event() - exctract read mem resp event + * @wmi: wmi handle + * @evt_buf: Pointer to the event buffer + * @resp: pointer to memory to extract event parameters into + * + * This function exctracts read mem response event into the given structure ptr + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_apf_read_memory_resp_event(wmi_unified_t wmi, void *evt_buf, + struct wmi_apf_read_memory_resp_event_params + *read_mem_evt); +#endif /* FEATURE_WLAN_APF */ + +/** + * wmi_send_get_user_position_cmd() - send get user position command to fw + * @wmi_handle: wmi handle + * @value: user pos value + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_send_get_user_position_cmd(wmi_unified_t wmi_handle, uint32_t value); + +/** + * wmi_send_get_peer_mumimo_tx_count_cmd() - send get mumio tx count + * command to fw + * @wmi_handle: wmi handle + * @value: user pos value + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_send_get_peer_mumimo_tx_count_cmd(wmi_unified_t wmi_handle, + uint32_t value); + +/** + * wmi_send_reset_peer_mumimo_tx_count_cmd() - send reset peer mumimo + * tx count to fw + * @wmi_handle: wmi handle + * @value: reset tx count value + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_send_reset_peer_mumimo_tx_count_cmd(wmi_unified_t wmi_handle, + uint32_t value); + +/* + * wmi_unified_send_btcoex_wlan_priority_cmd() - send btcoex priority commands + * @wmi_handle: wmi handle + * @param: wmi btcoex cfg params + * + * Send WMI_BTCOEX_CFG_CMDID parameters to fw. + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +wmi_unified_send_btcoex_wlan_priority_cmd(wmi_unified_t wmi_handle, + struct btcoex_cfg_params *param); + +/** + * wmi_unified_send_btcoex_duty_cycle_cmd() - send btcoex duty cycle commands + * @wmi_handle: wmi handle + * @param: wmi btcoex cfg params + * + * Send WMI_BTCOEX_CFG_CMDID parameters to fw. + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +wmi_unified_send_btcoex_duty_cycle_cmd(wmi_unified_t wmi_handle, + struct btcoex_cfg_params *param); + +/** + * wmi_unified_send_coex_ver_cfg_cmd() - send coex ver cfg command + * @wmi_handle: wmi handle + * @param: wmi coex ver cfg params + * + * Send WMI_COEX_VERSION_CFG_CMID parameters to fw. + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +wmi_unified_send_coex_ver_cfg_cmd(wmi_unified_t wmi_handle, + coex_ver_cfg_t *param); + +/** + * wmi_unified_send_coex_config_cmd() - send coex ver cfg command + * @wmi_handle: wmi handle + * @param: wmi coex cfg cmd params + * + * Send WMI_COEX_CFG_CMD parameters to fw. + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +wmi_unified_send_coex_config_cmd(wmi_unified_t wmi_handle, + struct coex_config_params *param); + +/** + * wmi_unified_pdev_fips_cmd_send() - WMI pdev fips cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold pdev fips param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_pdev_fips_cmd_send(wmi_unified_t wmi_handle, + struct fips_params *param); + +#ifdef WLAN_FEATURE_DISA +/** + * wmi_unified_encrypt_decrypt_send_cmd() - send encryptdecrypt cmd to fw + * @wmi_handle: wmi handle + * @params: encrypt/decrypt params + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_encrypt_decrypt_send_cmd(void *wmi_hdl, + struct disa_encrypt_decrypt_req_params + *params); +#endif /* WLAN_FEATURE_DISA */ + +/** + * wmi_unified_wlan_profile_enable_cmd_send() - WMI wlan profile enable + * cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold wlan profile param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_wlan_profile_enable_cmd_send(wmi_unified_t wmi_handle, + struct wlan_profile_params *param); + +/** + * wmi_unified_wlan_profile_trigger_cmd_send() - WMI wlan profile trigger + * cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold wlan profile param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_wlan_profile_trigger_cmd_send(wmi_unified_t wmi_handle, + struct wlan_profile_params *param); + +/** + * wmi_unified_set_chan_cmd_send() - WMI set channel cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold channel param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_set_chan_cmd_send(wmi_unified_t wmi_handle, + struct channel_param *param); + +/** + * wmi_unified_set_ratepwr_table_cmd_send() - WMI ratepwr table cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold ratepwr table param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_set_ratepwr_table_cmd_send(wmi_unified_t wmi_handle, + struct ratepwr_table_params *param); + +/** + * wmi_unified_get_ratepwr_table_cmd_send() - WMI ratepwr table cmd function + * @wmi_handle: handle to WMI. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_get_ratepwr_table_cmd_send(wmi_unified_t wmi_handle); + +/** + * wmi_unified_set_ratepwr_chainmsk_cmd_send() - WMI ratepwr + * chainmsk cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold ratepwr chainmsk param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_set_ratepwr_chainmsk_cmd_send(wmi_unified_t wmi_handle, + struct ratepwr_chainmsk_params + *param); + +/** + * wmi_unified_set_macaddr_cmd_send() - WMI set macaddr cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold macaddr param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_set_macaddr_cmd_send(wmi_unified_t wmi_handle, + struct macaddr_params *param); + +/** + * wmi_unified_pdev_scan_start_cmd_send() - WMI pdev scan start cmd function + * @wmi_handle: handle to WMI. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_pdev_scan_start_cmd_send(wmi_unified_t wmi_handle); + +/** + * wmi_unified_pdev_scan_end_cmd_send() - WMI pdev scan end cmd function + * @wmi_handle: handle to WMI. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_pdev_scan_end_cmd_send(wmi_unified_t wmi_handle); + +/** + * wmi_unified_set_acparams_cmd_send() - WMI set acparams cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold acparams param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_set_acparams_cmd_send(wmi_unified_t wmi_handle, + struct acparams_params *param); + +/** + * wmi_unified_set_vap_dscp_tid_map_cmd_send() - WMI set vap dscp + * tid map cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold dscp param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_set_vap_dscp_tid_map_cmd_send( + wmi_unified_t wmi_handle, + struct vap_dscp_tid_map_params *param); + +/** + * wmi_unified_proxy_ast_reserve_cmd_send() - WMI proxy ast + * reserve cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold ast param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_proxy_ast_reserve_cmd_send(wmi_unified_t wmi_handle, + struct proxy_ast_reserve_params *param); + +/** + * wmi_unified_set_bridge_mac_addr_cmd_send() - WMI set bridge mac + * addr cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold bridge mac addr param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_set_bridge_mac_addr_cmd_send( + wmi_unified_t wmi_handle, + struct set_bridge_mac_addr_params *param); + +/** + * wmi_unified_phyerr_enable_cmd_send() - WMI phyerr enable cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold phyerr enable param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_phyerr_enable_cmd_send(wmi_unified_t wmi_handle); + +/** + * wmi_unified_phyerr_disable_cmd_send() - WMI phyerr disable cmd function + * @wmi_handle: handle to WMI. + * @param: pointer to hold phyerr disable param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_phyerr_disable_cmd_send(wmi_unified_t wmi_handle); + +/** + * wmi_unified_smart_ant_enable_tx_feedback_cmd_send() - + * WMI set tx antenna function + * @wmi_handle: handle to WMI. + * @param: pointer to hold antenna param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_smart_ant_enable_tx_feedback_cmd_send( + wmi_unified_t wmi_handle, + struct smart_ant_enable_tx_feedback_params *param); + +/** + * wmi_unified_vdev_spectral_configure_cmd_send() - + * WMI set spectral config function + * @wmi_handle: handle to WMI. + * @param: pointer to hold spectral config param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_vdev_spectral_configure_cmd_send( + wmi_unified_t wmi_handle, + struct vdev_spectral_configure_params *param); + +/** + * wmi_unified_vdev_spectral_enable_cmd_send() - WMI enable spectral function + * @wmi_handle: handle to WMI. + * @param: pointer to hold enable spectral param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_vdev_spectral_enable_cmd_send( + wmi_unified_t wmi_handle, + struct vdev_spectral_enable_params *param); + +#if defined(WLAN_SUPPORT_FILS) || defined(CONFIG_BAND_6GHZ) +/** + * wmi_unified_vdev_fils_enable_cmd_send() - WMI send fils enable command + * @param wmi_handle: handle to WMI. + * @param config_fils_params: fils enable parameters + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_vdev_fils_enable_cmd_send(struct wmi_unified *wmi_handle, + struct config_fils_params *param); +#endif + +/** + * wmi_unified_bss_chan_info_request_cmd_send() - WMI bss chan info + * request function + * @wmi_handle: handle to WMI. + * @param: pointer to hold chan info param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_bss_chan_info_request_cmd_send( + wmi_unified_t wmi_handle, + struct bss_chan_info_request_params *param); + +/** + * wmi_unified_thermal_mitigation_param_cmd_send() - + * WMI thermal mitigation function + * @wmi_handle: handle to WMI. + * @param: pointer to hold thermal mitigation param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_thermal_mitigation_param_cmd_send( + wmi_unified_t wmi_handle, + struct thermal_mitigation_params *param); + +/** + * wmi_unified_vdev_set_fwtest_param_cmd_send() - WMI set fwtest function + * @wmi_handle: handle to WMI. + * @param: pointer to hold fwtest param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_vdev_set_fwtest_param_cmd_send( + wmi_unified_t wmi_handle, + struct set_fwtest_params *param); + +/** + * wmi_unified_vdev_set_custom_aggr_size_cmd_send() - WMI set custom aggr + * size command + * @wmi_handle: handle to WMI. + * @param: pointer to hold custom aggr size param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_vdev_set_custom_aggr_size_cmd_send( + wmi_unified_t wmi_handle, + struct set_custom_aggr_size_params *param); + +/** + * wmi_unified_vdev_set_qdepth_thresh_cmd_send() - WMI set qdepth threshold + * @wmi_handle: handle to WMI. + * @param: pointer to hold set qdepth thresh param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_vdev_set_qdepth_thresh_cmd_send( + wmi_unified_t wmi_handle, + struct set_qdepth_thresh_params *param); + +/** + * wmi_unified_pdev_set_regdomain_params_cmd_send() - WMI set regdomain + * function + * @wmi_handle: handle to WMI. + * @param: pointer to hold regdomain param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_pdev_set_regdomain_cmd_send( + wmi_unified_t wmi_handle, + struct pdev_set_regdomain_params *param); + +/** + * wmi_unified_set_beacon_filter_cmd_send() - WMI set beacon filter function + * @wmi_handle: handle to WMI. + * @param: pointer to hold beacon filter param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_set_beacon_filter_cmd_send( + wmi_unified_t wmi_handle, + struct set_beacon_filter_params *param); + +/** + * wmi_unified_remove_beacon_filter_cmd_send() - WMI set beacon filter function + * @wmi_handle: handle to WMI. + * @param: pointer to hold beacon filter param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_remove_beacon_filter_cmd_send( + wmi_unified_t wmi_handle, + struct remove_beacon_filter_params *param); + +/** + * wmi_unified_addba_clearresponse_cmd_send() - WMI addba resp cmd function + * @wmi_handle: handle to WMI. + * @macaddr: MAC address + * @param: pointer to hold addba resp parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_addba_clearresponse_cmd_send( + wmi_unified_t wmi_handle, + uint8_t macaddr[QDF_MAC_ADDR_SIZE], + struct addba_clearresponse_params *param); + +/** + * wmi_unified_addba_send_cmd_send() - WMI addba send function + * @wmi_handle: handle to WMI. + * @macaddr: MAC address + * @param: pointer to hold addba parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_addba_send_cmd_send(wmi_unified_t wmi_handle, + uint8_t macaddr[QDF_MAC_ADDR_SIZE], + struct addba_send_params *param); + +/** + * wmi_unified_delba_send_cmd_send() - WMI delba cmd function + * @wmi_handle: handle to WMI. + * @macaddr: MAC address + * @param: pointer to hold delba parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_delba_send_cmd_send(wmi_unified_t wmi_handle, + uint8_t macaddr[QDF_MAC_ADDR_SIZE], + struct delba_send_params *param); + +/** + * wmi_unified_addba_setresponse_cmd_send() - WMI addba set resp cmd function + * @wmi_handle: handle to WMI. + * @macaddr: MAC address + * @param: pointer to hold addba set resp parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_addba_setresponse_cmd_send(wmi_unified_t wmi_handle, + uint8_t macaddr[QDF_MAC_ADDR_SIZE], + struct addba_setresponse_params *param); + +/** + * wmi_unified_singleamsdu_cmd_send() - WMI singleamsdu function + * @wmi_handle: handle to WMI. + * @macaddr: MAC address + * @param: pointer to hold singleamsdu parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_singleamsdu_cmd_send(wmi_unified_t wmi_handle, + uint8_t macaddr[QDF_MAC_ADDR_SIZE], + struct singleamsdu_params *param); + +/** + * wmi_unified_mu_scan_cmd_send() - WMI set mu scan function + * @wmi_handle: handle to WMI. + * @param: pointer to hold mu scan param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_mu_scan_cmd_send(wmi_unified_t wmi_handle, + struct mu_scan_params *param); + +/** + * wmi_unified_lteu_config_cmd_send() - WMI set mu scan function + * @wmi_handle: handle to WMI. + * @param: pointer to hold mu scan param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_lteu_config_cmd_send(wmi_unified_t wmi_handle, + struct lteu_config_params *param); + +/** + * wmi_unified_set_psmode_cmd_send() - WMI set mu scan function + * @wmi_handle: handle to WMI. + * @param: pointer to hold mu scan param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_set_psmode_cmd_send(wmi_unified_t wmi_handle, + struct set_ps_mode_params *param); + +/** + * wmi_unified_init_cmd_send() - send initialization cmd to fw + * @wmi_handle: wmi handle + * @param: pointer to wmi init param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_init_cmd_send(wmi_unified_t wmi_handle, + struct wmi_init_cmd_param *param); + +/** + * wmi_service_enabled() - Check if service enabled + * @wmi_handle: wmi handle + * @service_id: service identifier + * + * Return: 1 enabled, 0 disabled + */ +bool wmi_service_enabled(wmi_unified_t wmi_handle, uint32_t service_id); + +/** + * wmi_save_service_bitmap() - save service bitmap + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @bitmap_buf: bitmap buffer + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS failure code + */ +QDF_STATUS wmi_save_service_bitmap(wmi_unified_t wmi_handle, void *evt_buf, + void *bitmap_buf); + +/** + * wmi_save_ext_service_bitmap() - save extended service bitmap + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS failure code + */ +QDF_STATUS wmi_save_ext_service_bitmap(wmi_unified_t wmi_handle, void *evt_buf, + void *bitmap_buf); + +/** + * wmi_save_fw_version() - Save fw version + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_save_fw_version(wmi_unified_t wmi_handle, void *evt_buf); + +/** + * wmi_get_target_cap_from_service_ready() - extract service ready event + * @wmi_handle: wmi handle + * @evt_buf: pointer to received event buffer + * @ev: pointer to hold target capability information extracted from even + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_get_target_cap_from_service_ready( + wmi_unified_t wmi_handle, void *evt_buf, + struct wlan_psoc_target_capability_info *ev); + +/** + * wmi_extract_hal_reg_cap() - extract HAL registered capabilities + * @wmi_handle: wmi handle + * @evt_buf: Pointer to event buffer + * @hal_reg_cap: pointer to hold HAL reg capabilities + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_hal_reg_cap(wmi_unified_t wmi_handle, void *evt_buf, + struct wlan_psoc_hal_reg_capability *hal_reg_cap); + +/** + * wmi_extract_num_mem_reqs_from_service_ready() - Extract number of memory + * entries requested + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * + * Return: Number of entries requested + */ +uint32_t wmi_extract_num_mem_reqs_from_service_ready( + wmi_unified_t wmi_handle, + void *evt_buf); + +/** + * wmi_extract_host_mem_req_from_service_ready() - Extract host memory + * request event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @mem_reqs: pointer to host memory request structure + * @num_active_peers: number of active peers for peer cache + * @num_peers: number of peers + * @fw_prio: FW priority + * @idx: Index for memory request + * + * Return: Host memory request parameters requested by target + */ +QDF_STATUS wmi_extract_host_mem_req_from_service_ready( + wmi_unified_t wmi_handle, void *evt_buf, host_mem_req *mem_reqs, + uint32_t num_active_peers, uint32_t num_peers, + enum wmi_fw_mem_prio fw_prio, uint16_t idx); + +/** + * wmi_ready_extract_init_status() - Extract init status from ready event + * @wmi_handle: wmi handle + * @ev: Pointer to event buffer + * + * Return: ready status + */ +uint32_t wmi_ready_extract_init_status(wmi_unified_t wmi_handle, void *ev); + +/** + * wmi_ready_extract_mac_addr() - extract mac address from ready event + * @wmi_handle: wmi handle + * @ev: pointer to event buffer + * @macaddr: Pointer to hold MAC address + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_ready_extract_mac_addr(wmi_unified_t wmi_handle, + void *ev, uint8_t *macaddr); + +/** + * wmi_ready_extract_mac_addr() - extract MAC address list from ready event + * @wmi_handle: wmi handle + * @ev: pointer to event buffer + * @num_mac_addr: Pointer to number of entries + * + * Return: address to start of mac addr list + */ +wmi_host_mac_addr +*wmi_ready_extract_mac_addr_list(wmi_unified_t wmi_handle, void *ev, + uint8_t *num_mac_addr); + +/** + * wmi_extract_ready_params() - Extract data from ready event apart from + * status, macaddr and version. + * @wmi_handle: Pointer to WMI handle. + * @evt_buf: Pointer to Ready event buffer. + * @ev_param: Pointer to host defined struct to copy the data from event. + * + * Return: QDF_STATUS_SUCCESS on success. + */ +QDF_STATUS wmi_extract_ready_event_params( + wmi_unified_t wmi_handle, void *evt_buf, + struct wmi_host_ready_ev_param *ev_param); + +/** + * wmi_extract_fw_version() - extract fw version + * @wmi_handle: wmi handle + * @ev: pointer to event buffer + * @fw_ver: Pointer to hold fw version + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_fw_version(wmi_unified_t wmi_handle, void *ev, + struct wmi_host_fw_ver *fw_ver); + +/** + * wmi_extract_fw_abi_version() - extract fw abi version + * @wmi_handle: wmi handle + * @ev: Pointer to event buffer + * @fw_ver: Pointer to hold fw abi version + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_fw_abi_version(wmi_unified_t wmi_handle, void *ev, + struct wmi_host_fw_abi_ver *fw_ver); + +/** + * wmi_check_and_update_fw_version() - Ready and fw version check + * @wmi_handle: wmi handle + * @ev: pointer to event buffer + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_check_and_update_fw_version(wmi_unified_t wmi_handle, void *ev); -QDF_STATUS wmi_extract_fw_abi_version(void *wmi_hdl, - void *ev, struct wmi_host_fw_abi_ver *fw_ver); +/** + * wmi_extract_dbglog_data_len() - extract debuglog data length + * @wmi_handle: wmi handle + * @evt_b: pointer to event buffer + * @len: length of buffer + * + * Return: length + */ +uint8_t *wmi_extract_dbglog_data_len(wmi_unified_t wmi_handle, + void *evt_b, uint32_t *len); + +/** + * wmi_send_ext_resource_config() - send extended resource configuration + * @wmi_handle: wmi handle + * @ext_cfg: pointer to extended resource configuration + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_send_ext_resource_config(wmi_unified_t wmi_handle, + wmi_host_ext_resource_config *ext_cfg); + +/** + * wmi_unified_rtt_meas_req_test_cmd_send() - WMI rtt meas req test function + * @wmi_handle: handle to WMI. + * @param: pointer to hold rtt meas req test param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_rtt_meas_req_test_cmd_send(wmi_unified_t wmi_handle, + struct rtt_meas_req_test_params *param); -QDF_STATUS wmi_check_and_update_fw_version(void *wmi_hdl, void *ev); +/** + * wmi_unified_rtt_meas_req_cmd_send() - WMI rtt meas req function + * @wmi_handle: handle to WMI. + * @param: pointer to hold rtt meas req param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_rtt_meas_req_cmd_send(wmi_unified_t wmi_handle, + struct rtt_meas_req_params *param); -uint8_t *wmi_extract_dbglog_data_len(void *wmi_hdl, - void *evt_b, uint32_t *len); +/** + * wmi_unified_rtt_keepalive_req_cmd_send() - WMI rtt meas req test function + * @wmi_handle: handle to WMI. + * @param: pointer to hold rtt meas req test param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_rtt_keepalive_req_cmd_send(wmi_unified_t wmi_handle, + struct rtt_keepalive_req_params *param); -QDF_STATUS wmi_send_ext_resource_config(void *wmi_hdl, - wmi_host_ext_resource_config *ext_cfg); +/** + * wmi_unified_lci_set_cmd_send() - WMI lci set function + * @wmi_handle: handle to WMI. + * @param: pointer to hold lci param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_lci_set_cmd_send(wmi_unified_t wmi_handle, + struct lci_set_params *param); -QDF_STATUS wmi_unified_rtt_meas_req_test_cmd_send(void *wmi_hdl, - struct rtt_meas_req_test_params *param); +/** + * wmi_unified_lcr_set_cmd_send() - WMI lcr set function + * @wmi_handle: handle to WMI. + * @param: pointer to hold lcr param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_lcr_set_cmd_send(wmi_unified_t wmi_handle, + struct lcr_set_params *param); -QDF_STATUS wmi_unified_rtt_meas_req_cmd_send(void *wmi_hdl, - struct rtt_meas_req_params *param); +/** + * wmi_unified_extract_pn() - extract pn event data + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: pointer to get pn event param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_extract_pn(wmi_unified_t wmi_hdl, void *evt_buf, + struct wmi_host_get_pn_event *param); -QDF_STATUS wmi_unified_rtt_keepalive_req_cmd_send(void *wmi_hdl, - struct rtt_keepalive_req_params *param); +/** + * wmi_unified_send_periodic_chan_stats_config_cmd() - send periodic chan + * stats cmd to fw + * @wmi_handle: wmi handle + * @param: pointer to hold periodic chan stats param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_send_periodic_chan_stats_config_cmd( + wmi_unified_t wmi_handle, + struct periodic_chan_stats_params *param); -QDF_STATUS wmi_unified_lci_set_cmd_send(void *wmi_hdl, - struct lci_set_params *param); +/* Extract APIs */ -QDF_STATUS wmi_unified_lcr_set_cmd_send(void *wmi_hdl, - struct lcr_set_params *param); +/** + * wmi_extract_fips_event_data() - extract fips event data + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: pointer to FIPS event param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_fips_event_data(wmi_unified_t wmi_handle, void *evt_buf, + struct wmi_host_fips_event_param *param); -QDF_STATUS wmi_unified_send_periodic_chan_stats_config_cmd(void *wmi_hdl, - struct periodic_chan_stats_params *param); +#ifdef WLAN_FEATURE_DISA +/** + * wmi_extract_encrypt_decrypt_resp_params() - + * extract encrypt decrypt resp params from event buffer + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @resp: encrypt decrypt resp params + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS +wmi_extract_encrypt_decrypt_resp_params(void *wmi_hdl, void *evt_buf, + struct disa_encrypt_decrypt_resp_params + *param); +#endif /* WLAN_FEATURE_DISA */ -/* Extract APIs */ +/** + * wmi_extract_mgmt_rx_params() - extract management rx params from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @hdr: Pointer to hold header + * @bufp: Pointer to hold pointer to rx param buffer + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_mgmt_rx_params(wmi_unified_t wmi_handle, void *evt_buf, + struct mgmt_rx_event_params *hdr, uint8_t **bufp); -QDF_STATUS wmi_extract_fips_event_data(void *wmi_hdl, void *evt_buf, - struct wmi_host_fips_event_param *param); +/** + * wmi_extract_vdev_roam_param() - extract vdev roam param from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @ev: Pointer to hold roam param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_vdev_roam_param(wmi_unified_t wmi_handle, void *evt_buf, + wmi_host_roam_event *ev); -QDF_STATUS wmi_extract_mgmt_rx_params(void *wmi_hdl, void *evt_buf, - struct mgmt_rx_event_params *hdr, uint8_t **bufp); +/** + * wmi_extract_vdev_scan_ev_param() - extract vdev scan param from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: Pointer to hold vdev scan param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_vdev_scan_ev_param(wmi_unified_t wmi_handle, void *evt_buf, + struct scan_event *param); -QDF_STATUS wmi_extract_vdev_roam_param(void *wmi_hdl, void *evt_buf, - wmi_host_roam_event *ev); +#ifdef FEATURE_WLAN_SCAN_PNO +/** + * wmi_extract_nlo_match_ev_param() - extract NLO match param from event + * @wmi_handle: pointer to WMI handle + * @evt_buf: pointer to WMI event buffer + * @param: pointer to scan event param for NLO match + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS +wmi_extract_nlo_match_ev_param(wmi_unified_t wmi_handle, void *evt_buf, + struct scan_event *param); -QDF_STATUS wmi_extract_vdev_scan_ev_param(void *wmi_hdl, void *evt_buf, - struct scan_event *param); +/** + * wmi_extract_nlo_complete_ev_param() - extract NLO complete param from event + * @wmi_handle: pointer to WMI handle + * @evt_buf: pointer to WMI event buffer + * @param: pointer to scan event param for NLO complete + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS +wmi_extract_nlo_complete_ev_param(wmi_unified_t wmi_handle, void *evt_buf, + struct scan_event *param); +#endif -QDF_STATUS wmi_extract_mu_ev_param(void *wmi_hdl, void *evt_buf, - wmi_host_mu_report_event *param); +/** + * wmi_extract_mu_ev_param() - extract mu param from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: Pointer to hold mu report + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_mu_ev_param(wmi_unified_t wmi_handle, void *evt_buf, + wmi_host_mu_report_event *param); -QDF_STATUS wmi_extract_mu_db_entry(void *wmi_hdl, void *evt_buf, - uint8_t idx, wmi_host_mu_db_entry *param); +/** + * wmi_extract_mu_db_entry() - extract mu db entry from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @idx: index + * @param: Pointer to hold mu db entry + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_mu_db_entry(wmi_unified_t wmi_handle, void *evt_buf, + uint8_t idx, wmi_host_mu_db_entry *param); -QDF_STATUS wmi_extract_mumimo_tx_count_ev_param(void *wmi_hdl, void *evt_buf, - wmi_host_peer_txmu_cnt_event *param); +/** + * wmi_extract_mumimo_tx_count_ev_param() - extract mumimo tx count from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: Pointer to hold mumimo tx count + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_mumimo_tx_count_ev_param(wmi_unified_t wmi_handle, void *evt_buf, + wmi_host_peer_txmu_cnt_event *param); -QDF_STATUS wmi_extract_peer_gid_userpos_list_ev_param(void *wmi_hdl, - void *evt_buf, wmi_host_peer_gid_userpos_list_event *param); +/** + * wmi_extract_peer_gid_userpos_list_ev_param() - extract peer userpos list + * from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: Pointer to hold peer gid userposition list + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_peer_gid_userpos_list_ev_param( + wmi_unified_t wmi_handle, + void *evt_buf, + wmi_host_peer_gid_userpos_list_event *param); +/** + * wmi_extract_esp_estimate_ev_param() - extract air time from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: Pointer to hold esp event + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ QDF_STATUS -wmi_extract_esp_estimate_ev_param(void *wmi_hdl, void *evt_buf, +wmi_extract_esp_estimate_ev_param(wmi_unified_t wmi_handle, void *evt_buf, struct esp_estimation_event *param); -QDF_STATUS wmi_extract_gpio_input_ev_param(void *wmi_hdl, - void *evt_buf, uint32_t *gpio_num); - -QDF_STATUS wmi_extract_pdev_reserve_ast_ev_param(void *wmi_hdl, - void *evt_buf, struct wmi_host_proxy_ast_reserve_param *param); +/** + * wmi_extract_gpio_input_ev_param() - extract gpio input param from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @gpio_num: Pointer to hold gpio number + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_gpio_input_ev_param(wmi_unified_t wmi_handle, + void *evt_buf, uint32_t *gpio_num); -QDF_STATUS wmi_extract_pdev_generic_buffer_ev_param(void *wmi_hdl, - void *evt_buf, +/** + * wmi_extract_pdev_reserve_ast_ev_param() - extract reserve ast entry + * param from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: Pointer to hold reserve ast entry param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_pdev_reserve_ast_ev_param( + wmi_unified_t wmi_handle, void *evt_buf, + struct wmi_host_proxy_ast_reserve_param *param); +/** + * wmi_extract_pdev_generic_buffer_ev_param() - extract pdev generic buffer + * from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: Pointer to generic buffer param + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_pdev_generic_buffer_ev_param( + wmi_unified_t wmi_handle, void *evt_buf, wmi_host_pdev_generic_buffer_event *param); -QDF_STATUS wmi_extract_peer_ratecode_list_ev(void *wmi_hdl, void *evt_buf, - uint8_t *peer_mac, wmi_sa_rate_cap *rate_cap); +/** + * wmi_extract_peer_ratecode_list_ev() - extract peer ratecode from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @peer_mac: Pointer to hold peer mac address + * @pdev_id: Pointer to hold pdev_id + * @rate_cap: Pointer to hold ratecode + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_peer_ratecode_list_ev( + wmi_unified_t wmi_handle, void *evt_buf, + uint8_t *peer_mac, uint32_t *pdev_id, + wmi_sa_rate_cap *rate_cap); -QDF_STATUS wmi_extract_bcnflt_stats(void *wmi_hdl, void *evt_buf, - uint32_t index, wmi_host_bcnflt_stats *bcnflt_stats); +/** + * wmi_extract_bcnflt_stats() - extract bcn fault stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @index: Index into bcn fault stats + * @bcnflt_stats: Pointer to hold bcn fault stats + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_bcnflt_stats( + wmi_unified_t wmi_handle, void *evt_buf, + uint32_t index, wmi_host_bcnflt_stats *bcnflt_stats); -QDF_STATUS wmi_extract_rtt_hdr(void *wmi_hdl, void *evt_buf, - wmi_host_rtt_event_hdr *ev); +/** + * wmi_extract_rtt_hdr() - extract rtt header from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @ev: Pointer to hold rtt header + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_rtt_hdr(wmi_unified_t wmi_handle, void *evt_buf, + wmi_host_rtt_event_hdr *ev); -QDF_STATUS wmi_extract_rtt_ev(void *wmi_hdl, void *evt_buf, - wmi_host_rtt_meas_event *ev, uint8_t *hdump, - uint16_t hdump_len); +/** + * wmi_extract_rtt_ev() - extract rtt event + * @wmi_handle: wmi handle + * @evt_buf: Pointer to event buffer + * @ev: Pointer to hold rtt event + * @hdump: Pointer to hold hex dump + * @hdump_len: hex dump length + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_rtt_ev(wmi_unified_t wmi_handle, void *evt_buf, + wmi_host_rtt_meas_event *ev, + uint8_t *hdump, uint16_t hdump_len); -QDF_STATUS wmi_extract_rtt_error_report_ev(void *wmi_hdl, void *evt_buf, - wmi_host_rtt_error_report_event *ev); +/** + * wmi_extract_rtt_error_report_ev() - extract rtt error report from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @ev: Pointer to hold rtt error report + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_rtt_error_report_ev(wmi_unified_t wmi_handle, void *evt_buf, + wmi_host_rtt_error_report_event *ev); -QDF_STATUS wmi_extract_chan_stats(void *wmi_hdl, void *evt_buf, - uint32_t index, wmi_host_chan_stats *chan_stats); +/** + * wmi_extract_chan_stats() - extract chan stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @index: Index into chan stats + * @chan_stats: Pointer to hold chan stats + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_chan_stats(wmi_unified_t wmi_handle, void *evt_buf, + uint32_t index, wmi_host_chan_stats *chan_stats); -QDF_STATUS wmi_extract_thermal_stats(void *wmi_hdl, void *evt_buf, - uint32_t *temp, uint32_t *level, uint32_t *pdev_id); +/** + * wmi_extract_thermal_stats() - extract thermal stats from event + * @wmi_handle: wmi handle + * @evt_buf: Pointer to event buffer + * @temp: Pointer to hold extracted temperature + * @level: Pointer to hold extracted level + * @pdev_id: Pointer to hold extracted pdev_id + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_thermal_stats(wmi_unified_t wmi_handle, void *evt_buf, + uint32_t *temp, uint32_t *level, + uint32_t *pdev_id); -QDF_STATUS wmi_extract_thermal_level_stats(void *wmi_hdl, void *evt_buf, - uint8_t idx, uint32_t *levelcount, uint32_t *dccount); +/** + * wmi_extract_thermal_level_stats() - extract thermal level stats from + * event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @idx: Index to level stats + * @levelcount: Pointer to hold levelcount + * @dccount: Pointer to hold dccount + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_thermal_level_stats(wmi_unified_t wmi_handle, void *evt_buf, + uint8_t idx, uint32_t *levelcount, + uint32_t *dccount); -QDF_STATUS wmi_extract_comb_phyerr(void *wmi_hdl, void *evt_buf, +/** + * wmi_extract_comb_phyerr() - extract comb phy error from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @datalen: data length of event buffer + * @buf_offset: Pointer to hold value of current event buffer offset + * post extraction + * @phyerr: Pointer to hold phyerr + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_comb_phyerr(wmi_unified_t wmi_handle, void *evt_buf, uint16_t datalen, uint16_t *buf_offset, wmi_host_phyerr_t *phyerr); -QDF_STATUS wmi_extract_single_phyerr(void *wmi_hdl, void *evt_buf, - uint16_t datalen, uint16_t *buf_offset, - wmi_host_phyerr_t *phyerr); +/** + * wmi_extract_single_phyerr() - extract single phy error from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @datalen: data length of event buffer + * @buf_offset: Pointer to hold value of current event buffer offset + * post extraction + * @phyerr: Pointer to hold phyerr + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_single_phyerr(wmi_unified_t wmi_handle, void *evt_buf, + uint16_t datalen, uint16_t *buf_offset, + wmi_host_phyerr_t *phyerr); -QDF_STATUS wmi_extract_composite_phyerr(void *wmi_hdl, void *evt_buf, - uint16_t datalen, wmi_host_phyerr_t *phyerr); +/** + * wmi_extract_composite_phyerr() - extract composite phy error from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @datalen: Length of event buffer + * @phyerr: Pointer to hold phy error + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_composite_phyerr(wmi_unified_t wmi_handle, void *evt_buf, + uint16_t datalen, wmi_host_phyerr_t *phyerr); -QDF_STATUS wmi_extract_profile_ctx(void *wmi_hdl, void *evt_buf, +/** + * wmi_extract_profile_ctx() - extract profile context from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @profile_ctx: Pointer to hold profile context + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_profile_ctx(wmi_unified_t wmi_handle, void *evt_buf, wmi_host_wlan_profile_ctx_t *profile_ctx); -QDF_STATUS wmi_extract_profile_data(void *wmi_hdl, void *evt_buf, uint8_t idx, - wmi_host_wlan_profile_t *profile_data); - -QDF_STATUS wmi_extract_stats_param(void *wmi_hdl, void *evt_buf, - wmi_host_stats_event *stats_param); +/** + * wmi_extract_profile_data() - extract profile data from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @idx: index of profile data + * @profile_data: Pointer to hold profile data + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_profile_data(wmi_unified_t wmi_handle, void *evt_buf, uint8_t idx, + wmi_host_wlan_profile_t *profile_data); -QDF_STATUS wmi_extract_pdev_stats(void *wmi_hdl, void *evt_buf, - uint32_t index, - wmi_host_pdev_stats *pdev_stats); +/** + * wmi_extract_stats_param() - extract all stats count from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @stats_param: Pointer to hold stats count + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_stats_param(wmi_unified_t wmi_handle, void *evt_buf, + wmi_host_stats_event *stats_param); -QDF_STATUS wmi_extract_unit_test(void *wmi_hdl, void *evt_buf, - wmi_unit_test_event *unit_test, uint32_t maxspace); +/** + * wmi_extract_pdev_stats() - extract pdev stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @index: Index into pdev stats + * @pdev_stats: Pointer to hold pdev stats + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_pdev_stats(wmi_unified_t wmi_handle, void *evt_buf, + uint32_t index, wmi_host_pdev_stats *pdev_stats); -QDF_STATUS wmi_extract_pdev_ext_stats(void *wmi_hdl, void *evt_buf, - uint32_t index, - wmi_host_pdev_ext_stats *pdev_ext_stats); +/** + * extract_unit_test() - extract unit test from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @unit_test: Pointer to hold unit-test header + * @maxspace: The amount of space in evt_buf + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_unit_test(wmi_unified_t wmi_handle, void *evt_buf, + wmi_unit_test_event *unit_test, uint32_t maxspace); -QDF_STATUS wmi_extract_peer_extd_stats(void *wmi_hdl, void *evt_buf, - uint32_t index, - wmi_host_peer_extd_stats *peer_extd_stats); +/** + * wmi_extract_pdev_ext_stats() - extract extended pdev stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @index: Index into extended pdev stats + * @pdev_ext_stats: Pointer to hold extended pdev stats + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_pdev_ext_stats(wmi_unified_t wmi_handle, void *evt_buf, + uint32_t index, + wmi_host_pdev_ext_stats *pdev_ext_stats); -QDF_STATUS wmi_extract_peer_adv_stats(wmi_unified_t wmi_handle, void *evt_buf, - struct wmi_host_peer_adv_stats - *peer_adv_stats); +/** + * wmi_extract_peer_extd_stats() - extract extended peer stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @index: Index into extended peer stats + * @peer_extd_stats: Pointer to hold extended peer stats + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_peer_extd_stats(wmi_unified_t wmi_handle, void *evt_buf, + uint32_t index, + wmi_host_peer_extd_stats *peer_extd_stats); -QDF_STATUS wmi_extract_bss_chan_info_event(void *wmi_hdl, void *evt_buf, - wmi_host_pdev_bss_chan_info_event *bss_chan_info); +/** + * wmi_extract_peer_adv_stats() - extract advance (extd2) peer stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @peer_adv_stats: Pointer to hold extended peer stats + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_peer_adv_stats( + wmi_unified_t wmi_handle, void *evt_buf, + struct wmi_host_peer_adv_stats *peer_adv_stats); -QDF_STATUS wmi_extract_peer_stats(void *wmi_hdl, void *evt_buf, - uint32_t index, wmi_host_peer_stats *peer_stats); +/** + * wmi_extract_bss_chan_info_event() - extract bss channel information + * from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @bss_chan_info: Pointer to hold bss channel information + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_bss_chan_info_event( + wmi_unified_t wmi_handle, void *evt_buf, + wmi_host_pdev_bss_chan_info_event *bss_chan_info); -QDF_STATUS wmi_extract_tx_data_traffic_ctrl_ev(void *wmi_hdl, void *evt_buf, - wmi_host_tx_data_traffic_ctrl_event *ev); +/** + * wmi_extract_peer_stats() - extract peer stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @index: Index into peer stats + * @peer_stats: Pointer to hold peer stats + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_peer_stats(wmi_unified_t wmi_handle, void *evt_buf, + uint32_t index, wmi_host_peer_stats *peer_stats); -QDF_STATUS wmi_extract_vdev_stats(void *wmi_hdl, void *evt_buf, - uint32_t index, wmi_host_vdev_stats *vdev_stats); +/** + * wmi_extract_tx_data_traffic_ctrl_ev() - extract tx data traffic control + * from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @ev: Pointer to hold data traffic control + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_tx_data_traffic_ctrl_ev(wmi_unified_t wmi_handle, void *evt_buf, + wmi_host_tx_data_traffic_ctrl_event *ev); -QDF_STATUS wmi_extract_per_chain_rssi_stats(void *wmi_hdl, void *evt_buf, - uint32_t index, struct wmi_host_per_chain_rssi_stats *rssi_stats); +/** + * wmi_extract_vdev_stats() - extract vdev stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @index: Index into vdev stats + * @vdev_stats: Pointer to hold vdev stats + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_vdev_stats(wmi_unified_t wmi_handle, void *evt_buf, + uint32_t index, wmi_host_vdev_stats *vdev_stats); -QDF_STATUS wmi_extract_vdev_extd_stats(void *wmi_hdl, void *evt_buf, - uint32_t index, wmi_host_vdev_extd_stats *vdev_extd_stats); +/** + * wmi_extract_per_chain_rssi_stats() - extract rssi stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @index: Index into rssi stats + * @rssi_stats: Pointer to hold rssi stats + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_per_chain_rssi_stats( + wmi_unified_t wmi_handle, void *evt_buf, + uint32_t index, + struct wmi_host_per_chain_rssi_stats *rssi_stats); -QDF_STATUS wmi_extract_bcn_stats(void *wmi_hdl, void *evt_buf, - uint32_t index, wmi_host_bcn_stats *vdev_bcn_stats); +#ifdef WLAN_FEATURE_MIB_STATS +/** + * wmi_extract_mib_stats() - extract mib stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @mib_stats: pointer to hold mib stats + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_extract_mib_stats(wmi_unified_t wmi_handle, void *evt_buf, + struct mib_stats_metrics *mib_stats); +#endif -#ifdef FEATURE_OEM_DATA /** - * wmi_unified_start_oemv2_data_cmd() - start oem data cmd to target + * wmi_extract_vdev_extd_stats() - extract extended vdev stats from event * @wmi_handle: wmi handle - * @params: oem data params + * @evt_buf: pointer to event buffer + * @index: Index into extended vdev stats + * @vdev_extd_stats: Pointer to hold extended vdev stats * - * This is common api for oem data, using wmi command WMI_OEM_DATA_CMDID. + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_vdev_extd_stats(wmi_unified_t wmi_handle, void *evt_buf, + uint32_t index, + wmi_host_vdev_extd_stats *vdev_extd_stats); + +/** + * wmi_extract_bcn_stats() - extract beacon stats from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @index: Index into beacon stats + * @vdev_bcn_stats: Pointer to hold beacon stats * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_start_oemv2_data_cmd(wmi_unified_t wmi_handle, - struct oem_data *params); -#endif +QDF_STATUS +wmi_extract_bcn_stats(wmi_unified_t wmi_handle, void *evt_buf, + uint32_t index, wmi_host_bcn_stats *vdev_bcn_stats); /** * wmi_extract_vdev_nac_rssi_stats() - extract NAC_RSSI stats from event * @wmi_handle: wmi handle - * @param evt_buf: pointer to event buffer - * @param vdev_extd_stats: Pointer to hold nac rssi stats + * @evt_buf: pointer to event buffer + * @vdev_extd_stats: Pointer to hold nac rssi stats * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_extract_vdev_nac_rssi_stats(void *wmi_hdl, void *evt_buf, +QDF_STATUS wmi_extract_vdev_nac_rssi_stats( + wmi_unified_t wmi_handle, void *evt_buf, struct wmi_host_vdev_nac_rssi_event *vdev_nac_rssi_stats); /** @@ -1407,35 +3084,82 @@ QDF_STATUS wmi_extract_vdev_nac_rssi_stats(void *wmi_hdl, void *evt_buf, * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_extract_peer_retry_stats(void *wmi_hdl, void *evt_buf, +QDF_STATUS wmi_extract_peer_retry_stats( + wmi_unified_t wmi_handle, void *evt_buf, uint32_t index, struct wmi_host_peer_retry_stats *peer_retry_stats); -QDF_STATUS wmi_unified_send_power_dbg_cmd(void *wmi_hdl, - struct wmi_power_dbg_params *param); +/** + * wmi_unified_send_power_dbg_cmd() - send power debug commands + * @wmi_handle: wmi handle + * @param: wmi power debug parameter + * + * Send WMI_POWER_DEBUG_CMDID parameters to fw. + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS wmi_unified_send_power_dbg_cmd(wmi_unified_t wmi_handle, + struct wmi_power_dbg_params *param); /** * wmi_extract_sar_cap_service_ready_ext() - extract SAR cap from * FW service ready event - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @evt_buf: event buffer received from firmware * @ext_param: extended target info * * Return: QDF_STATUS_SUCCESS for success or error code */ QDF_STATUS wmi_extract_sar_cap_service_ready_ext( - void *wmi_hdl, + wmi_unified_t wmi_handle, uint8_t *evt_buf, struct wlan_psoc_host_service_ext_param *ext_param); -QDF_STATUS wmi_unified_fw_test_cmd(void *wmi_hdl, +/** + * wmi_unified_fw_test_cmd() - send fw test command to fw. + * @wmi_handle: wmi handle + * @wmi_fwtest: fw test command + * + * This function sends fw test command to fw. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_fw_test_cmd(wmi_unified_t wmi_handle, struct set_fwtest_params *wmi_fwtest); -QDF_STATUS wmi_unified_peer_rx_reorder_queue_setup_send(void *wmi_hdl, - struct rx_reorder_queue_setup_params *param); -QDF_STATUS wmi_unified_peer_rx_reorder_queue_remove_send(void *wmi_hdl, - struct rx_reorder_queue_remove_params *param); +/** + * wmi_unified_peer_rx_reorder_queue_setup_send() - send rx reorder queue + * setup command to fw + * @wmi_handle: wmi handle + * @param: Rx reorder queue setup parameters + * + * Return: QDF_STATUS for success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_peer_rx_reorder_queue_setup_send( + wmi_unified_t wmi_handle, + struct rx_reorder_queue_setup_params *param); + +/** + * wmi_unified_peer_rx_reorder_queue_remove_send() - send rx reorder queue + * remove command to fw + * @wmi_handle: wmi handle + * @param: Rx reorder queue remove parameters + * + * Return: QDF_STATUS for success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_peer_rx_reorder_queue_remove_send( + wmi_unified_t wmi_handle, + struct rx_reorder_queue_remove_params *param); -QDF_STATUS wmi_extract_service_ready_ext(void *wmi_hdl, uint8_t *evt_buf, +/* + * wmi_extract_service_ready_ext() - extract extended service ready + * @wmi_handle: wmi handle + * @param: wmi power debug parameter + * + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS wmi_extract_service_ready_ext( + wmi_unified_t wmi_handle, uint8_t *evt_buf, struct wlan_psoc_host_service_ext_param *param); /* @@ -1451,18 +3175,52 @@ QDF_STATUS wmi_extract_service_ready_ext2( struct wmi_unified *wmi_handle, uint8_t *evt_buf, struct wlan_psoc_host_service_ext2_param *param); +/** + * wmi_extract_hw_mode_cap_service_ready_ext() - + * extract HW mode cap from service ready event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @hw_mode_idx: hw mode idx should be less than num_mode + * @param: Pointer to hold evt buf + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ QDF_STATUS wmi_extract_hw_mode_cap_service_ready_ext( - void *wmi_hdl, + wmi_unified_t wmi_handle, uint8_t *evt_buf, uint8_t hw_mode_idx, struct wlan_psoc_host_hw_mode_caps *param); + +/** + * wmi_extract_mac_phy_cap_service_ready_ext() - + * extract MAC phy cap from service ready event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @hw_mode_id: hw mode id of hw_mode_caps + * @phy_id: phy_id within hw_mode_cap + * @param: pointer to mac phy caps structure to hold the values from event + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ QDF_STATUS wmi_extract_mac_phy_cap_service_ready_ext( - void *wmi_hdl, + wmi_unified_t wmi_handle, uint8_t *evt_buf, uint8_t hw_mode_id, uint8_t phy_id, struct wlan_psoc_host_mac_phy_caps *param); -QDF_STATUS wmi_extract_reg_cap_service_ready_ext( - void *wmi_hdl, + +/** + * wmi_extract_reg_cap_service_ready_ext() - + * extract REG cap from service ready event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @phy_idx: phy idx should be less than num_mode + * @param: Pointer to hold evt buf + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS +wmi_extract_reg_cap_service_ready_ext( + wmi_unified_t wmi_handle, uint8_t *evt_buf, uint8_t phy_idx, struct wlan_psoc_host_hal_reg_capabilities_ext *param); @@ -1470,7 +3228,7 @@ QDF_STATUS wmi_extract_reg_cap_service_ready_ext( * wmi_extract_dbr_ring_cap_service_ready_ext: Extract direct buffer rx * capability received through * extended service ready event - * @wmi_hdl: WMI handle + * @wmi_handle: WMI handle * @evt_buf: Event buffer * @idx: Index of the module for which capability is received * @param: Pointer to direct buffer rx ring cap struct @@ -1478,7 +3236,23 @@ QDF_STATUS wmi_extract_reg_cap_service_ready_ext( * Return: QDF status of operation */ QDF_STATUS wmi_extract_dbr_ring_cap_service_ready_ext( - void *wmi_hdl, + wmi_unified_t wmi_handle, + uint8_t *evt_buf, uint8_t idx, + struct wlan_psoc_host_dbr_ring_caps *param); + +/** + * wmi_extract_dbr_ring_cap_service_ready_ext2: Extract direct buffer rx + * capability received through + * extended service ready2 event + * @wmi_handle: WMI handle + * @evt_buf: Event buffer + * @idx: Index of the module for which capability is received + * @param: Pointer to direct buffer rx ring cap struct + * + * Return: QDF status of operation + */ +QDF_STATUS wmi_extract_dbr_ring_cap_service_ready_ext2( + wmi_unified_t wmi_handle, uint8_t *evt_buf, uint8_t idx, struct wlan_psoc_host_dbr_ring_caps *param); @@ -1486,7 +3260,7 @@ QDF_STATUS wmi_extract_dbr_ring_cap_service_ready_ext( * wmi_extract_spectral_scaling_params_service_ready_ext: Extract Spectral * scaling params received through * extended service ready event - * @wmi_hdl: WMI handle + * @wmi_handle: WMI handle * @evt_buf: Event buffer * @idx: Index * @param: Pointer to Spectral scaling params @@ -1494,35 +3268,79 @@ QDF_STATUS wmi_extract_dbr_ring_cap_service_ready_ext( * Return: QDF status of operation */ QDF_STATUS wmi_extract_spectral_scaling_params_service_ready_ext( - void *wmi_hdl, + wmi_unified_t wmi_handle, uint8_t *evt_buf, uint8_t idx, struct wlan_psoc_host_spectral_scaling_params *param); -QDF_STATUS wmi_extract_pdev_utf_event(void *wmi_hdl, +/** + * wmi_extract_pdev_utf_event() - + * extract UTF data from pdev utf event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: Pointer to hold evt buf + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS wmi_extract_pdev_utf_event(wmi_unified_t wmi_handle, uint8_t *evt_buf, struct wmi_host_pdev_utf_event *param); -QDF_STATUS wmi_extract_pdev_qvit_event(void *wmi_hdl, - uint8_t *evt_buf, - struct wmi_host_pdev_qvit_event *param); +/** + * wmi_extract_pdev_qvit_event() - + * extract UTF data from pdev qvit event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @param: Pointer to hold evt buf + * + * Return: QDF_STATUS_SUCCESS for success or error code + */ +QDF_STATUS wmi_extract_pdev_qvit_event(wmi_unified_t wmi_handle, + uint8_t *evt_buf, + struct wmi_host_pdev_qvit_event *param); #ifdef WLAN_SUPPORT_RF_CHARACTERIZATION +/** + * wmi_extract_num_rf_characterziation_entries - Extract number of RF + * characterization metrics received from the RF characterization event. + * @wmi_hdl: WMI handle + * @evt_buf: Event buffer + * @num_rf_characterization_entries: Number of RF characterization metrics + * + * Return: QDF status of operation + */ +QDF_STATUS wmi_extract_num_rf_characterization_entries(wmi_unified_t wmi_hdl, + uint8_t *evt_buf, + uint32_t *num_rf_characterization_entries); + /** * wmi_extract_rf_characterziation_entries - Extract RF characterization metrics - * received through extended service ready event. + * received from the RF characterization event. * @wmi_hdl: WMI handle * @evt_buf: Event buffer + * @num_rf_characterization_entries: Number of RF characterization metrics * @rf_characterization_entries: Pointer to RF characterization metrics * * Return: QDF status of operation */ QDF_STATUS wmi_extract_rf_characterization_entries(wmi_unified_t wmi_hdl, uint8_t *evt_buf, - struct wlan_psoc_host_rf_characterization_entry *rf_characterization_entries); + uint32_t num_rf_characterization_entries, + struct wmi_host_rf_characterization_event_param *rf_characterization_entries); #endif -QDF_STATUS wmi_extract_chainmask_tables(void *wmi_hdl, uint8_t *evt_buf, +/* + * wmi_extract_chainmask_tables_tlv() - extract chain mask tables + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer. + * @chainmask_table: pointer to struct wlan_psoc_host_chainmask_table + * + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS wmi_extract_chainmask_tables( + wmi_unified_t wmi_handle, uint8_t *evt_buf, struct wlan_psoc_host_chainmask_table *chainmask_table); + /** * wmi_unified_dfs_phyerr_offload_en_cmd() - enable dfs phyerr offload * @wmi_handle: wmi handle @@ -1530,8 +3348,8 @@ QDF_STATUS wmi_extract_chainmask_tables(void *wmi_hdl, uint8_t *evt_buf, * * Return: QDF_STATUS */ -QDF_STATUS wmi_unified_dfs_phyerr_offload_en_cmd(void *wmi_hdl, - uint32_t pdev_id); +QDF_STATUS wmi_unified_dfs_phyerr_offload_en_cmd(wmi_unified_t wmi_handle, + uint32_t pdev_id); /** * wmi_unified_dfs_phyerr_offload_dis_cmd() - disable dfs phyerr offload @@ -1540,58 +3358,66 @@ QDF_STATUS wmi_unified_dfs_phyerr_offload_en_cmd(void *wmi_hdl, * * Return: QDF_STATUS */ -QDF_STATUS wmi_unified_dfs_phyerr_offload_dis_cmd(void *wmi_hdl, - uint32_t pdev_id); +QDF_STATUS wmi_unified_dfs_phyerr_offload_dis_cmd(wmi_unified_t wmi_handle, + uint32_t pdev_id); #ifdef QCA_SUPPORT_AGILE_DFS /** * wmi_unified_send_vdev_adfs_ch_cfg_cmd() - send adfs channel config command * @wmi_handle: wmi handle - * @vdev_adfs_ch_cfg_params: adfs channel config params + * @param: adfs channel config params * * Return: QDF_STATUS */ QDF_STATUS -wmi_unified_send_vdev_adfs_ch_cfg_cmd(void *wmi_hdl, +wmi_unified_send_vdev_adfs_ch_cfg_cmd(wmi_unified_t wmi_handle, struct vdev_adfs_ch_cfg_params *param); /** * wmi_unified_send_vdev_adfs_ocac_abort_cmd() - send adfs o-cac abort command * @wmi_handle: wmi handle - * @vdev_adfs_abort_params: adfs channel o-cac abort params + * @param: adfs channel o-cac abort params * * Return: QDF_STATUS */ QDF_STATUS -wmi_unified_send_vdev_adfs_ocac_abort_cmd(void *wmi_hdl, +wmi_unified_send_vdev_adfs_ocac_abort_cmd(wmi_unified_t wmi_handle, struct vdev_adfs_abort_params *param); #endif -QDF_STATUS wmi_unified_set_country_cmd_send(void *wmi_hdl, - struct set_country *param); +/** + * wmi_unified_set_country_cmd_send() - WMI set country function + * @wmi_handle : handle to WMI. + * @param : pointer to hold set country cmd parameter + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_set_country_cmd_send(wmi_unified_t wmi_handle, + struct set_country *param); #ifdef WLAN_FEATURE_ACTION_OUI /** * wmi_unified_send_action_oui_cmd() - send action oui cmd to fw - * @wmi_hdl: wma handle + * @wmi_handle: wma handle * @req: wmi action oui message to be send * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ QDF_STATUS -wmi_unified_send_action_oui_cmd(void *wmi_hdl, +wmi_unified_send_action_oui_cmd(wmi_unified_t wmi_handle, struct action_oui_request *req); #endif /* WLAN_FEATURE_ACTION_OUI */ /** * wmi_unified_send_request_get_rcpi_cmd() - command to request rcpi value - * @wmi_hdl: wma handle + * @wmi_handle: wma handle * @get_rcpi_param: rcpi params * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_send_request_get_rcpi_cmd(void *wmi_hdl, - struct rcpi_req *get_rcpi_param); +QDF_STATUS +wmi_unified_send_request_get_rcpi_cmd(wmi_unified_t wmi_handle, + struct rcpi_req *get_rcpi_param); /** * wmi_extract_rcpi_response_event - api to extract RCPI event params @@ -1602,8 +3428,9 @@ QDF_STATUS wmi_unified_send_request_get_rcpi_cmd(void *wmi_hdl, * Return: QDF_STATUS_SUCCESS for successful event parse * else QDF_STATUS_E_INVAL or QDF_STATUS_E_FAILURE */ -QDF_STATUS wmi_extract_rcpi_response_event(void *wmi_hdl, void *evt_buf, - struct rcpi_res *res); +QDF_STATUS +wmi_extract_rcpi_response_event(wmi_unified_t wmi_handle, void *evt_buf, + struct rcpi_res *res); #ifdef WMI_INTERFACE_EVENT_LOGGING void wmi_print_cmd_log(wmi_unified_t wmi, uint32_t count, @@ -1632,18 +3459,17 @@ void wmi_print_mgmt_event_log(wmi_unified_t wmi, uint32_t count, /** * wmi_unified_send_wds_entry_list_cmd() - WMI function to get list of * wds entries from FW - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * * Send WMI_PDEV_WDS_ENTRY_LIST_CMDID parameters to fw. * * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error */ - -QDF_STATUS wmi_unified_send_dump_wds_table_cmd(void *wmi_hdl); +QDF_STATUS wmi_unified_send_dump_wds_table_cmd(wmi_unified_t wmi_handle); /** * wmi_extract_wds_entry - api to extract wds entry - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @evt_buf: pointer to event buffer * @wds_entry: wds entry * @idx: index to point wds entry in event buffer @@ -1651,14 +3477,14 @@ QDF_STATUS wmi_unified_send_dump_wds_table_cmd(void *wmi_hdl); * Return: QDF_STATUS_SUCCESS for successful event parse * else QDF_STATUS_E_INVAL or QDF_STATUS_E_FAILURE */ - -QDF_STATUS wmi_extract_wds_entry(void *wmi_hdl, uint8_t *evt_buf, - struct wdsentry *wds_entry, u_int32_t idx); +QDF_STATUS +wmi_extract_wds_entry(wmi_unified_t wmi_handle, uint8_t *evt_buf, + struct wdsentry *wds_entry, u_int32_t idx); /** * wmi_unified_send_obss_detection_cfg_cmd() - WMI function to send obss * detection configuration to FW. - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @cfg: obss detection configuration * * Send WMI_SAP_OBSS_DETECTION_CFG_CMDID parameters to fw. @@ -1666,13 +3492,14 @@ QDF_STATUS wmi_extract_wds_entry(void *wmi_hdl, uint8_t *evt_buf, * Return: QDF_STATUS */ -QDF_STATUS wmi_unified_send_obss_detection_cfg_cmd(void *wmi_hdl, - struct wmi_obss_detection_cfg_param *cfg); +QDF_STATUS wmi_unified_send_obss_detection_cfg_cmd( + wmi_unified_t wmi_handle, + struct wmi_obss_detection_cfg_param *cfg); /** * wmi_unified_extract_obss_detection_info() - WMI function to extract obss * detection info from FW. - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @data: event data from firmware * @info: Pointer to hold obss detection info * @@ -1681,20 +3508,20 @@ QDF_STATUS wmi_unified_send_obss_detection_cfg_cmd(void *wmi_hdl, * Return: QDF_STATUS */ -QDF_STATUS wmi_unified_extract_obss_detection_info(void *wmi_hdl, - uint8_t *data, - struct wmi_obss_detect_info - *info); +QDF_STATUS wmi_unified_extract_obss_detection_info( + wmi_unified_t wmi_handle, + uint8_t *data, + struct wmi_obss_detect_info *info); #ifdef WLAN_SUPPORT_GREEN_AP QDF_STATUS wmi_extract_green_ap_egap_status_info( - void *wmi_hdl, uint8_t *evt_buf, - struct wlan_green_ap_egap_status_info *egap_status_info_params); + wmi_unified_t wmi_hdl, uint8_t *evt_buf, + struct wlan_green_ap_egap_status_info *egap_status_info_params); #endif /** * wmi_unified_send_roam_scan_stats_cmd() - Wrapper to request roam scan stats - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @params: request params * * This function is used to send the roam scan stats request command to @@ -1703,7 +3530,7 @@ QDF_STATUS wmi_extract_green_ap_egap_status_info( * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ QDF_STATUS -wmi_unified_send_roam_scan_stats_cmd(void *wmi_hdl, +wmi_unified_send_roam_scan_stats_cmd(wmi_unified_t wmi_handle, struct wmi_roam_scan_stats_req *params); /** @@ -1722,7 +3549,7 @@ wmi_extract_roam_scan_stats_res_evt(wmi_unified_t wmi, void *evt_buf, /** * wmi_extract_offload_bcn_tx_status_evt() - API to extract bcn tx status event - * @wmi: wmi handle + * @wmi_handle: wmi handle * @evt_buf: pointer to the event buffer * @vdev_id: output pointer to hold vdev id * @tx_status: output pointer to hold bcn tx status @@ -1730,17 +3557,17 @@ wmi_extract_roam_scan_stats_res_evt(wmi_unified_t wmi, void *evt_buf, * Return: QDF_STATUS */ QDF_STATUS -wmi_extract_offload_bcn_tx_status_evt(void *wmi_hdl, void *evt_buf, +wmi_extract_offload_bcn_tx_status_evt(wmi_unified_t wmi_handle, void *evt_buf, uint32_t *vdev_id, uint32_t *tx_status); /* wmi_get_ch_width_from_phy_mode() - convert phy mode to channel width - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @phymode: phy mode * * Return: wmi channel width */ -wmi_host_channel_width wmi_get_ch_width_from_phy_mode(void *wmi_hdl, - WMI_HOST_WLAN_PHY_MODE phymode); +wmi_host_channel_width wmi_get_ch_width_from_phy_mode( + wmi_unified_t wmi_handle, WMI_HOST_WLAN_PHY_MODE phymode); #ifdef QCA_SUPPORT_CP_STATS /** @@ -1759,7 +3586,7 @@ QDF_STATUS wmi_extract_cca_stats(wmi_unified_t wmi_handle, void *evt_buf, #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) /** * wmi_unified_dfs_send_avg_params_cmd() - send average radar parameters cmd. - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @params: radar found params * * This function passes the average radar parameters to fw @@ -1767,12 +3594,12 @@ QDF_STATUS wmi_extract_cca_stats(wmi_unified_t wmi_handle, void *evt_buf, * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ QDF_STATUS -wmi_unified_dfs_send_avg_params_cmd(void *wmi_hdl, +wmi_unified_dfs_send_avg_params_cmd(wmi_unified_t wmi_handle, struct dfs_radar_found_params *params); /** * wmi_extract_dfs_status_from_fw() - extract host dfs status from fw. - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @evt_buf: pointer to event buffer * @dfs_status_check: pointer to the host dfs status * @@ -1780,46 +3607,47 @@ wmi_unified_dfs_send_avg_params_cmd(void *wmi_hdl, * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_extract_dfs_status_from_fw(void *wmi_hdl, void *evt_buf, +QDF_STATUS wmi_extract_dfs_status_from_fw(wmi_unified_t wmi_handle, + void *evt_buf, uint32_t *dfs_status_check); #endif #ifdef OL_ATH_SMART_LOGGING /** * wmi_unified_send_smart_logging_enable_cmd() - send smart logging enable cmd - * @wmi_hdl: wmi handle - * @params: enable/disable + * @wmi_handle: wmi handle + * @param: enable/disable * * This function enables/disable the smart logging feature * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_send_smart_logging_enable_cmd(void *wmi_hdl, +QDF_STATUS wmi_unified_send_smart_logging_enable_cmd(wmi_unified_t wmi_handle, uint32_t param); /** * wmi_unified_send_smart_logging_fatal_cmd() - send smart logging fatal cmd - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @param: Fatal event * * This function sends the smart log fatal events to the FW * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_send_smart_logging_fatal_cmd - (void *wmi_hdl, - struct wmi_debug_fatal_events *param); +QDF_STATUS +wmi_unified_send_smart_logging_fatal_cmd(wmi_unified_t wmi_handle, + struct wmi_debug_fatal_events *param); /** * wmi_extract_smartlog_ev() - extract smartlog event info from event * @wmi_handle: wmi handle - * @param evt_buf: pointer to event buffer - * @param ev: Pointer to hold fatal events + * @evt_buf: pointer to event buffer + * @ev: Pointer to hold fatal events * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_extract_smartlog_ev - (void *wmi_hdl, void *evt_buf, - struct wmi_debug_fatal_events *ev); +QDF_STATUS +wmi_extract_smartlog_ev(wmi_unified_t wmi_handle, void *evt_buf, + struct wmi_debug_fatal_events *ev); #endif /* OL_ATH_SMART_LOGGING */ @@ -1841,16 +3669,15 @@ void wmi_process_fw_event_worker_thread_ctx(struct wmi_unified *wmi_handle, * wmi_extract_ctl_failsafe_check_ev_param() - extract ctl failsafe * status from event * @wmi_handle: wmi handle - * @param evt_buf: pointer to event buffer - * @param ev: Pointer to hold ctl status + * @evt_buf: pointer to event buffer + * @ev: Pointer to hold ctl status * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS -wmi_extract_ctl_failsafe_check_ev_param(void *wmi_hdl, - void *evt_buf, - struct wmi_host_pdev_ctl_failsafe_event - *param); +QDF_STATUS wmi_extract_ctl_failsafe_check_ev_param( + wmi_unified_t wmi_handle, + void *evt_buf, + struct wmi_host_pdev_ctl_failsafe_event *param); #ifdef OBSS_PD /** @@ -1860,7 +3687,8 @@ wmi_extract_ctl_failsafe_check_ev_param(void *wmi_hdl, * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_send_obss_spatial_reuse_set_cmd(void *wmi_handle, +QDF_STATUS wmi_unified_send_obss_spatial_reuse_set_cmd( + wmi_unified_t wmi_handle, struct wmi_host_obss_spatial_reuse_set_param *obss_spatial_reuse_param); /** @@ -1870,7 +3698,8 @@ QDF_STATUS wmi_unified_send_obss_spatial_reuse_set_cmd(void *wmi_handle, * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_send_obss_spatial_reuse_set_def_thresh_cmd(void *wmi_hdl, +QDF_STATUS wmi_unified_send_obss_spatial_reuse_set_def_thresh_cmd( + wmi_unified_t wmi_handle, struct wmi_host_obss_spatial_reuse_set_def_thresh *thresh); #endif /* OBSS_PD */ @@ -1879,20 +3708,20 @@ QDF_STATUS wmi_unified_send_obss_spatial_reuse_set_def_thresh_cmd(void *wmi_hdl, * wmi_convert_pdev_id_host_to_target() - Convert pdev_id from host to target * defines. For legacy there is not conversion required. Just return pdev_id as * it is. - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @host_pdev_id: host pdev_id to be converted. * @target_pdev_id: Output target pdev id. * * Return: QDF_STATUS */ -QDF_STATUS wmi_convert_pdev_id_host_to_target(void *wmi_hdl, +QDF_STATUS wmi_convert_pdev_id_host_to_target(wmi_unified_t wmi_handle, uint32_t host_pdev_id, uint32_t *target_pdev_id); /** * wmi_unified_send_bss_color_change_enable_cmd() - WMI function to send bss * color change enable to FW. - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @vdev_id: vdev ID * @enable: enable or disable color change handeling within firmware * @@ -1901,27 +3730,29 @@ QDF_STATUS wmi_convert_pdev_id_host_to_target(void *wmi_hdl, * * Return: QDF_STATUS */ -QDF_STATUS wmi_unified_send_bss_color_change_enable_cmd(void *wmi_hdl, - uint32_t vdev_id, - bool enable); +QDF_STATUS +wmi_unified_send_bss_color_change_enable_cmd(wmi_unified_t wmi_handle, + uint32_t vdev_id, + bool enable); /** * wmi_unified_send_obss_color_collision_cfg_cmd() - WMI function to send bss * color collision detection configuration to FW. - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @cfg: obss color collision detection configuration * * Send WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID parameters to fw. * * Return: QDF_STATUS */ -QDF_STATUS wmi_unified_send_obss_color_collision_cfg_cmd(void *wmi_hdl, +QDF_STATUS wmi_unified_send_obss_color_collision_cfg_cmd( + wmi_unified_t wmi_handle, struct wmi_obss_color_collision_cfg_param *cfg); /** * wmi_unified_extract_obss_color_collision_info() - WMI function to extract * obss color collision info from FW. - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @data: event data from firmware * @info: Pointer to hold bss color collision info * @@ -1929,7 +3760,8 @@ QDF_STATUS wmi_unified_send_obss_color_collision_cfg_cmd(void *wmi_hdl, * * Return: QDF_STATUS */ -QDF_STATUS wmi_unified_extract_obss_color_collision_info(void *wmi_hdl, +QDF_STATUS wmi_unified_extract_obss_color_collision_info( + wmi_unified_t wmi_handle, uint8_t *data, struct wmi_obss_color_collision_info *info); #ifdef CRYPTO_SET_KEY_CONVERGED @@ -1977,47 +3809,117 @@ QDF_STATUS wmi_unified_send_mws_coex_req_cmd(struct wmi_unified *wmi_handle, QDF_STATUS wmi_unified_send_idle_trigger_monitor(wmi_unified_t wmi_handle, uint8_t val); -#ifdef WLAN_CFR_ENABLE + +#ifdef WIFI_POS_CONVERGED /** - * wmi_unified_send_peer_cfr_capture_cmd() - WMI function to start CFR capture - * for a peer + * wmi_extract_oem_response_param() - WMI function to extract OEM response param * @wmi_hdl: WMI handle - * @param: configuration params for capture + * @resp_buf: Buffer holding response data + * @oem_resp_param: zero-filled structure pointer to hold oem response data * * Return: QDF_STATUS_SUCCESS if success, else returns proper error code. */ QDF_STATUS -wmi_unified_send_peer_cfr_capture_cmd(void *wmi_hdl, - struct peer_cfr_params *param); +wmi_extract_oem_response_param(wmi_unified_t wmi_hdl, void *resp_buf, + struct wmi_oem_response_param *oem_resp_param); +#endif /* WIFI_POS_CONVERGED */ /** - * wmi_extract_cfr_peer_tx_event_param() - WMI function to extract cfr tx event - * for a peer + * wmi_critical_events_in_flight() - get the number of critical events in flight + * * @wmi_hdl: WMI handle - * @evt_buf: Buffer holding event data - * @peer_tx_event: pointer to hold tx event data + * + * Return: the number of critical events in flight. + */ +uint32_t wmi_critical_events_in_flight(struct wmi_unified *wmi); + + +#ifdef FEATURE_ANI_LEVEL_REQUEST +/** + * wmi_unified_ani_level_cmd_send() - WMI function to send get ani level cmd + * @wmi_hdl: WMI handle + * @freqs: pointer to list of freqs for which ANI levels are to be fetched + * @num_freqs: number of freqs in the above parameter + * + * Return: QDF_STATUS_SUCCESS if success, else returns proper error code. + */ +QDF_STATUS wmi_unified_ani_level_cmd_send(wmi_unified_t wmi_handle, + uint32_t *freqs, + uint8_t num_freqs); + +/** + * wmi_unified_extract_ani_level() - WMI function to receive ani level cmd + * @wmi_hdl: WMI handle + * @info: pointer to ANI data received from the FW and stored in HOST + * @num_freqs: number of freqs in the above parameter * * Return: QDF_STATUS_SUCCESS if success, else returns proper error code. */ +QDF_STATUS wmi_unified_extract_ani_level(wmi_unified_t wmi_handle, + uint8_t *data, + struct wmi_host_ani_level_event **info, + uint32_t *num_freqs); +#endif /* FEATURE_ANI_LEVEL_REQUEST */ + +#ifdef FEATURE_WLAN_TIME_SYNC_FTM +/** + * wmi_unified_send_wlan_time_sync_ftm_trigger() - send ftm timesync trigger cmd + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * @burst_mode: mode reg getting time sync relation from FW + * + * This function indicates the FW to trigger wlan time sync using FTM + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_send_wlan_time_sync_ftm_trigger(wmi_unified_t wmi_handle, + uint32_t vdev_id, + bool burst_mode); + +/** + * wmi_unified_send_wlan_time_sync_qtime() - send ftm time sync qtime cmd. + * @wmi_handle: wmi handle + * @vdev_id: vdev id + * @lpass_ts: audio qtime + * + * This function sends the wmi cmd to FW having audio qtime + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ QDF_STATUS -wmi_extract_cfr_peer_tx_event_param(void *wmi_hdl, void *evt_buf, - wmi_cfr_peer_tx_event_param *peer_tx_event); +wmi_unified_send_wlan_time_sync_qtime(wmi_unified_t wmi_handle, + uint32_t vdev_id, uint64_t lpass_ts); -#endif /* WLAN_CFR_ENABLE */ +/** + * wmi_unified_extract_time_sync_ftm_start_stop_params() - extract FTM time sync + * params + * @wmi_handle: wmi handle + * @evt_buf: event buffer + * @param: params received in start stop ftm timesync event + * + * This function extracts the params from ftm timesync start stop event + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_unified_extract_time_sync_ftm_start_stop_params( + wmi_unified_t wmi_handle, void *evt_buf, + struct ftm_time_sync_start_stop_params *param); -#ifdef WLAN_FEATURE_PKT_CAPTURE /** - * wmi_unified_extract_vdev_mgmt_offload_event() - Extract mgmt offload params - * @wmi: WMI handle - * @evt_buf: Event buffer - * @params: Management offload event params + * wmi_unified_extract_time_sync_ftm_offset() - extract timesync FTM offset + * @wmi_handle: wmi handle + * @evt_buf: event buffer + * @param: params received in ftm timesync offset event * - * WMI function to extract management offload event params + * This function extracts the params from ftm timesync offset event * - * Return: QDF_STATUS + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ QDF_STATUS -wmi_unified_extract_vdev_mgmt_offload_event(wmi_unified_t wmi, void *evt_buf, - struct mgmt_offload_event_params *params); -#endif +wmi_unified_extract_time_sync_ftm_offset(wmi_unified_t wmi_handle, + void *evt_buf, + struct ftm_time_sync_offset *param); +#endif /* FEATURE_WLAN_TIME_SYNC_FTM */ #endif /* _WMI_UNIFIED_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_bcn_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_bcn_api.h index 1b5e25e5d319f1f86bca1bc34769d9128c57fe73..52cc48722f5d06bc3ecb39f6d2470d02de917ed6 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_bcn_api.h +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_bcn_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -30,14 +30,14 @@ /** * wmi_unified_bcn_buf_ll_cmd() - prepare and send beacon buffer to fw for LL - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @param: bcn ll cmd parameter * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ QDF_STATUS -wmi_unified_bcn_buf_ll_cmd(void *wmi_hdl, +wmi_unified_bcn_buf_ll_cmd(wmi_unified_t wmi_handle, wmi_bcn_send_from_host_cmd_fixed_param * param); #endif diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_cfr_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_cfr_api.h new file mode 100644 index 0000000000000000000000000000000000000000..aa457b905d47b8e81518a9fb7e9b6877a4ba180f --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_cfr_api.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _WMI_UNIFIED_CFR_API_H_ +#define _WMI_UNIFIED_CFR_API_H_ + +#include "wmi_unified_param.h" +#include "wmi_unified_cfr_param.h" + +#ifdef WLAN_CFR_ENABLE +/** + * wmi_unified_send_peer_cfr_capture_cmd() - WMI function to start CFR capture + * for a peer + * @wmi_handle: WMI handle + * @param: configuration params for capture + * + * Return: QDF_STATUS_SUCCESS if success, else returns proper error code. + */ +QDF_STATUS +wmi_unified_send_peer_cfr_capture_cmd(wmi_unified_t wmi_handle, + struct peer_cfr_params *param); +/** + * wmi_extract_cfr_peer_tx_event_param() - WMI function to extract cfr tx event + * for a peer + * @wmi_handle: WMI handle + * @evt_buf: Buffer holding event data + * @peer_tx_event: pointer to hold tx event data + * + * Return: QDF_STATUS_SUCCESS if success, else returns proper error code. + */ +QDF_STATUS +wmi_extract_cfr_peer_tx_event_param(wmi_unified_t wmi_handle, void *evt_buf, + wmi_cfr_peer_tx_event_param *peer_tx_event); + +#ifdef WLAN_ENH_CFR_ENABLE +/** + * wmi_unified_send_cfr_rcc_cmd() - WMI function to send CFR RCC param + * @wmi_handle: WMI handle + * @cfg: pointer to RCC param + * + * Return: QDF_STATUS_SUCCESS if success, else returns proper error code. + */ +QDF_STATUS wmi_unified_send_cfr_rcc_cmd(wmi_unified_t wmi_handle, + struct cfr_rcc_param *cfg); +#endif +#endif /* WLAN_CFR_ENABLE */ +#endif /* _WMI_UNIFIED_CFR_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_cfr_param.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_cfr_param.h new file mode 100644 index 0000000000000000000000000000000000000000..151d9f60b0e8a4ee9f4471269f93cff9c51c6087 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_cfr_param.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019, 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _WMI_UNIFIED_CFR_PARAM_H_ +#define _WMI_UNIFIED_CFR_PARAM_H_ + +#ifdef WLAN_CFR_ENABLE + +#define WMI_HOST_PEER_CFR_TIMER_ENABLE 1 +#define WMI_HOST_PEER_CFR_TIMER_DISABLE 0 + + +/** + * struct peer_cfr_params - peer cfr capture cmd parameter + * @request: enable/disable cfr capture + * @macaddr: macaddr of the client + * @vdev_id: vdev id + * @periodicity: cfr capture period + * @bandwidth: bandwidth of cfr capture + * @capture_method: cfr capture method/type + */ +struct peer_cfr_params { + uint32_t request; + uint8_t *macaddr; + uint32_t vdev_id; + uint32_t periodicity; + uint32_t bandwidth; + uint32_t capture_method; +}; + + +#endif /* WLAN_CFR_ENABLE */ +#endif /* _WMI_UNIFIED_CFR_PARAM_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_concurrency_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_concurrency_api.h index 3e2d06d35695da96fffe94193b016b60cdfe4a60..2f2e968ed427bff5c086f2f2926b20afbdeb484a 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_concurrency_api.h +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_concurrency_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -24,22 +24,22 @@ /** * wmi_unified_set_mcc_channel_time_quota_cmd() - set MCC channel time quota - * @wmi: wmi handle - * @adapter_1_chan_number: adapter 1 channel number + * @wmi_handle: wmi handle + * @adapter_1_chan_freq: adapter 1 channel number * @adapter_1_quota: adapter 1 quota - * @adapter_2_chan_number: adapter 2 channel number + * @adapter_2_chan_freq: adapter 2 channel number * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_set_mcc_channel_time_quota_cmd - (void *wmi_hdl, +QDF_STATUS wmi_unified_set_mcc_channel_time_quota_cmd( + wmi_unified_t wmi_handle, uint32_t adapter_1_chan_freq, uint32_t adapter_1_quota, uint32_t adapter_2_chan_freq); /** * wmi_unified_set_mcc_channel_time_latency_cmd() - set MCC channel time latency - * @wmi: wmi handle - * @mcc_channel: mcc channel + * @wmi_handle: wmi handle + * @mcc_channel_freq: mcc channel freq * @mcc_channel_time_latency: MCC channel time latency. * * Currently used to set time latency for an MCC vdev/adapter using operating @@ -48,8 +48,8 @@ QDF_STATUS wmi_unified_set_mcc_channel_time_quota_cmd * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_set_mcc_channel_time_latency_cmd - (void *wmi_hdl, +QDF_STATUS wmi_unified_set_mcc_channel_time_latency_cmd( + wmi_unified_t wmi_handle, uint32_t mcc_channel_freq, uint32_t mcc_channel_time_latency); /** @@ -57,13 +57,14 @@ QDF_STATUS wmi_unified_set_mcc_channel_time_latency_cmd * scheduler * @wmi_handle: wmi handle * @mcc_adaptive_scheduler: enable/disable + * @pdev_id: pdev id * * This function enable/disable mcc adaptive scheduler in fw. * * Return: QDF_STATUS_SUCCESS for success or error code */ QDF_STATUS wmi_unified_set_enable_disable_mcc_adaptive_scheduler_cmd( - void *wmi_hdl, uint32_t mcc_adaptive_scheduler, - uint32_t pdev_id); + wmi_unified_t wmi_handle, uint32_t mcc_adaptive_scheduler, + uint32_t pdev_id); #endif /* _WMI_UNIFIED_CONCURRENCY_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_crypto_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_crypto_api.h new file mode 100644 index 0000000000000000000000000000000000000000..3dce977c0bc2b38498e42ce030fd62d91e3ee7e1 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_crypto_api.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019, 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file contains the API definitions for the Unified Wireless Module + * Interface (WMI) specific to crypto component. + */ + +#ifndef _WMI_UNIFIED_CRYPTO_API_H_ +#define _WMI_UNIFIED_CRYPTO_API_H_ + +/* + * WMI_ADD_CIPHER_KEY_CMDID + */ +typedef enum { + PAIRWISE_USAGE = 0x00, + GROUP_USAGE = 0x01, + TX_USAGE = 0x02, /* default Tx Key - Static WEP only */ + PMK_USAGE = 0x04, /* PMK cache */ +} KEY_USAGE; + +/** + * wmi_extract_install_key_comp_event() - extract params of install key complete + * from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @len: length of the event buffer + * @params: Pointer to hold params of install key complete + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS +wmi_extract_install_key_comp_event(wmi_unified_t wmi_handle, + void *evt_buf, uint32_t len, + struct wmi_install_key_comp_event *param); +#endif + diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dbr_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dbr_api.h index 8039749715ad637cbbb39ce681793b3d62b6cf3a..de378415c55378d99779542e4d491ba3d1da3898 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dbr_api.h +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dbr_api.h @@ -26,32 +26,32 @@ /** * wmi_unified_dbr_ring_cfg: Configure direct buffer rx rings - * @wmi_hdl: WMI handle + * @wmi_handle: WMI handle * @cfg: pointer to direct buffer rx config request * * Return: QDF status of operation */ -QDF_STATUS wmi_unified_dbr_ring_cfg(void *wmi_hdl, - struct direct_buf_rx_cfg_req *cfg); +QDF_STATUS wmi_unified_dbr_ring_cfg(wmi_unified_t wmi_handle, + struct direct_buf_rx_cfg_req *cfg); /** * wmi_extract_dbr_buf_release_fixed : Extract direct buffer rx fixed param * from buffer release event - * @wmi_hdl: WMI handle + * @wmi_handle: WMI handle * @evt_buf: Event buffer * @param: Pointer to direct buffer rx response struct * * Return: QDF status of operation */ QDF_STATUS wmi_extract_dbr_buf_release_fixed( - void *wmi_hdl, + wmi_unified_t wmi_handle, uint8_t *evt_buf, struct direct_buf_rx_rsp *param); /** * wmi_extract_dbr_buf_release_entry: Extract direct buffer rx buffer tlv * - * @wmi_hdl: WMI handle + * @wmi_handle: WMI handle * @evt_buf: Event buffer * @idx: Index of the module for which capability is received * @param: Pointer to direct buffer rx entry @@ -59,14 +59,14 @@ QDF_STATUS wmi_extract_dbr_buf_release_fixed( * Return: QDF status of operation */ QDF_STATUS wmi_extract_dbr_buf_release_entry( - void *wmi_hdl, + wmi_unified_t wmi_handle, uint8_t *evt_buf, uint8_t idx, struct direct_buf_rx_entry *param); /** * wmi_extract_dbr_buf_metadata: Extract direct buffer metadata * - * @wmi_hdl: WMI handle + * @wmi_handle: WMI handle * @evt_buf: Event buffer * @idx: Index of the module for which capability is received * @param: Pointer to direct buffer metadata @@ -74,7 +74,7 @@ QDF_STATUS wmi_extract_dbr_buf_release_entry( * Return: QDF status of operation */ QDF_STATUS wmi_extract_dbr_buf_metadata( - void *wmi_hdl, + wmi_unified_t wmi_handle, uint8_t *evt_buf, uint8_t idx, struct direct_buf_rx_metadata *param); diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dbr_param.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dbr_param.h index f0f903287f8fd9fce516c6d32936f83c6d6be91d..ed7226b69801c02a1aa4092b2112de6e2a86abb4 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dbr_param.h +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dbr_param.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, 2020 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 @@ -20,7 +20,9 @@ #define _WMI_UNIFIED_DBR_PARAM_H_ #define WMI_HOST_DBR_RING_ADDR_LO_S 0 -#define WMI_HOST_DBR_RING_ADDR_LO 0xffffffff +#define WMI_HOST_DBR_RING_ADDR_LO_M 0xffffffff +#define WMI_HOST_DBR_RING_ADDR_LO \ + (WMI_HOST_DBR_RING_ADDR_LO_M << WMI_HOST_DBR_RING_ADDR_LO_S) #define WMI_HOST_DBR_RING_ADDR_LO_GET(dword) \ WMI_HOST_F_MS(dword, WMI_HOST_DBR_RING_ADDR_LO) @@ -28,7 +30,9 @@ WMI_HOST_F_RMW(dword, val, WMI_HOST_DBR_RING_ADDR_LO) #define WMI_HOST_DBR_RING_ADDR_HI_S 0 -#define WMI_HOST_DBR_RING_ADDR_HI 0xf +#define WMI_HOST_DBR_RING_ADDR_HI_M 0xf +#define WMI_HOST_DBR_RING_ADDR_HI \ + (WMI_HOST_DBR_RING_ADDR_HI_M << WMI_HOST_DBR_RING_ADDR_HI_S) #define WMI_HOST_DBR_RING_ADDR_HI_GET(dword) \ WMI_HOST_F_MS(dword, WMI_HOST_DBR_RING_ADDR_HI) @@ -36,7 +40,9 @@ WMI_HOST_F_RMW(dword, val, WMI_HOST_DBR_RING_ADDR_HI) #define WMI_HOST_DBR_DATA_ADDR_LO_S 0 -#define WMI_HOST_DBR_DATA_ADDR_LO 0xffffffff +#define WMI_HOST_DBR_DATA_ADDR_LO_M 0xffffffff +#define WMI_HOST_DBR_DATA_ADDR_LO \ + (WMI_HOST_DBR_DATA_ADDR_LO_M << WMI_HOST_DBR_DATA_ADDR_LO_S) #define WMI_HOST_DBR_DATA_ADDR_LO_GET(dword) \ WMI_HOST_F_MS(dword, WMI_HOST_DBR_DATA_ADDR_LO) @@ -44,7 +50,9 @@ WMI_HOST_F_RMW(dword, val, WMI_HOST_DBR_DATA_ADDR_LO) #define WMI_HOST_DBR_DATA_ADDR_HI_S 0 -#define WMI_HOST_DBR_DATA_ADDR_HI 0xf +#define WMI_HOST_DBR_DATA_ADDR_HI_M 0xf +#define WMI_HOST_DBR_DATA_ADDR_HI \ + (WMI_HOST_DBR_DATA_ADDR_HI_M << WMI_HOST_DBR_DATA_ADDR_HI_S) #define WMI_HOST_DBR_DATA_ADDR_HI_GET(dword) \ WMI_HOST_F_MS(dword, WMI_HOST_DBR_DATA_ADDR_HI) @@ -52,7 +60,10 @@ WMI_HOST_F_RMW(dword, val, WMI_HOST_DBR_DATA_ADDR_HI) #define WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_S 12 -#define WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA 0x7fffff +#define WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_M 0x7ffff +#define WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA \ + (WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_M << \ + WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_S) #define WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_GET(dword) \ WMI_HOST_F_MS(dword, WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA) diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dfs_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dfs_api.h index 932da83cb720990ebfb17f48ff70c8d5a1814fdb..cf8ccca9eeb665cd1f1a9e0fd052e6d73f1a7bc3 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dfs_api.h +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_dfs_api.h @@ -28,14 +28,15 @@ /** * wmi_extract_dfs_cac_complete_event() - function to handle cac complete event - * @handle: wma handle + * @wmi_handle: wmi handle * @event_buf: event buffer * @vdev_id: vdev id * @len: length of buffer * * Return: 0 for success or error code */ -QDF_STATUS wmi_extract_dfs_cac_complete_event(void *wmi_hdl, +QDF_STATUS wmi_extract_dfs_cac_complete_event( + wmi_unified_t wmi_handle, uint8_t *evt_buf, uint32_t *vdev_id, uint32_t len); @@ -43,27 +44,27 @@ QDF_STATUS wmi_extract_dfs_cac_complete_event(void *wmi_hdl, /** * wmi_extract_dfs_ocac_complete_event() - function to handle off channel * CAC complete event - * @handle: wmi handle + * @wmi_handle: wmi handle * @event_buf: event buffer - * @vdev_adfs_complete_status: off channel cac complete params + * @param: off channel cac complete params * * Return: 0 for success or error code */ QDF_STATUS -wmi_extract_dfs_ocac_complete_event(void *wmi_hdl, uint8_t *evt_buf, +wmi_extract_dfs_ocac_complete_event(wmi_unified_t wmi_handle, uint8_t *evt_buf, struct vdev_adfs_complete_status *param); /** * wmi_extract_dfs_radar_detection_event() - function to handle radar event - * @handle: wma handle + * @wmi_handle: wmi handle * @event_buf: event buffer * @radar_found: radar found event info - * @vdev_id: vdev id * @len: length of buffer * * Return: 0 for success or error code */ -QDF_STATUS wmi_extract_dfs_radar_detection_event(void *wmi_hdl, +QDF_STATUS wmi_extract_dfs_radar_detection_event( + wmi_unified_t wmi_handle, uint8_t *evt_buf, struct radar_found_info *radar_found, uint32_t len); @@ -71,14 +72,15 @@ QDF_STATUS wmi_extract_dfs_radar_detection_event(void *wmi_hdl, #ifdef QCA_MCL_DFS_SUPPORT /** * wmi_extract_wlan_radar_event_info() - function to handle radar pulse event. - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @evt_buf: event buffer * @wlan_radar_event: pointer to radar event info structure * @len: length of buffer * * Return: QDF_STATUS */ -QDF_STATUS wmi_extract_wlan_radar_event_info(void *wmi_hdl, +QDF_STATUS wmi_extract_wlan_radar_event_info( + wmi_unified_t wmi_handle, uint8_t *evt_buf, struct radar_event_info *wlan_radar_event, uint32_t len); @@ -87,38 +89,38 @@ QDF_STATUS wmi_extract_wlan_radar_event_info(void *wmi_hdl, #if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD) /** * wmi_send_usenol_pdev_param() - function to send usenol pdev param. - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @usenol: value of usenol * @pdev: pointer to objmgr_pdev structure * * Return: QDF_STATUS */ -QDF_STATUS wmi_send_usenol_pdev_param(void *wmi_hdl, bool usenol, +QDF_STATUS wmi_send_usenol_pdev_param(wmi_unified_t wmi_handle, bool usenol, struct wlan_objmgr_pdev *pdev); /** * wmi_send_subchan_marking_pdev_param() - Function to send subchannel * marking pdev param. - * @wmi_hdl: WMI handle. + * @wmi_handle: WMI handle. * @subchanmark: Value of use subchannel marking. * @pdev: Pointer to objmgr_pdev structure. * * Return: QDF_STATUS */ QDF_STATUS -wmi_send_subchan_marking_pdev_param(void *wmi_hdl, +wmi_send_subchan_marking_pdev_param(wmi_unified_t wmi_handle, bool subchanmark, struct wlan_objmgr_pdev *pdev); #else static inline QDF_STATUS -wmi_send_usenol_pdev_param(void *wmi_hdl, bool usenol, +wmi_send_usenol_pdev_param(wmi_unified_t wmi_hdl, bool usenol, struct wlan_objmgr_pdev *pdev) { return QDF_STATUS_SUCCESS; } static inline QDF_STATUS -wmi_send_subchan_marking_pdev_param(void *wmi_hdl, +wmi_send_subchan_marking_pdev_param(wmi_unified_t wmi_handle, bool subchanmark, struct wlan_objmgr_pdev *pdev) { diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_extscan_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_extscan_api.h index 12e6e93ebd39f3a6ccc49cd06464b17cdf356517..102efbceb4573e8fd2f1c5f2b13d7fd64d072e17 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_extscan_api.h +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_extscan_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -19,47 +19,151 @@ #ifndef _WMI_UNIFIED_EXTSCAN_API_H_ #define _WMI_UNIFIED_EXTSCAN_API_H_ -QDF_STATUS wmi_unified_reset_passpoint_network_list_cmd(void *wmi_hdl, - struct wifi_passpoint_req_param *req); +/** + * wmi_unified_reset_passpoint_network_list_cmd() - reset passpoint network list + * @wmi_handle: wmi handle + * @req: passpoint network request structure + * + * This function sends down WMI command with network id set to wildcard id. + * firmware shall clear all the config entries + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_reset_passpoint_network_list_cmd( + wmi_unified_t wmi_handle, + struct wifi_passpoint_req_param *req); + +/** + * wmi_unified_set_passpoint_network_list_cmd() - set passpoint network list + * @wmi_handle: wmi handle + * @req: passpoint network request structure + * + * This function reads the incoming @req and fill in the destination + * WMI structure and send down the passpoint configs down to the firmware + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ -QDF_STATUS wmi_unified_set_passpoint_network_list_cmd(void *wmi_hdl, - struct wifi_passpoint_req_param *req); +QDF_STATUS wmi_unified_set_passpoint_network_list_cmd( + wmi_unified_t wmi_handle, + struct wifi_passpoint_req_param *req); -QDF_STATUS wmi_unified_set_epno_network_list_cmd(void *wmi_hdl, +/** wmi_unified_set_epno_network_list_cmd() - set epno network list + * @wmi_handle: wmi handle + * @req: epno config params request structure + * + * This function reads the incoming epno config request structure + * and constructs the WMI message to the firmware. + * + * Returns: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failures, + * error number otherwise + */ +QDF_STATUS wmi_unified_set_epno_network_list_cmd( + wmi_unified_t wmi_handle, struct wifi_enhanced_pno_params *req); -QDF_STATUS wmi_unified_extscan_get_capabilities_cmd(void *wmi_hdl, - struct extscan_capabilities_params *pgetcapab); +/** + * wmi_unified_extscan_get_capabilities_cmd() - extscan get capabilities + * @wmi_handle: wmi handle + * @pgetcapab: get capabilities params + * + * This function send request to fw to get extscan capabilities. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_extscan_get_capabilities_cmd( + wmi_unified_t wmi_handle, + struct extscan_capabilities_params *pgetcapab); -QDF_STATUS wmi_unified_extscan_get_cached_results_cmd(void *wmi_hdl, - struct extscan_cached_result_params *pcached_results); +/** + * wmi_unified_extscan_get_cached_results_cmd() - extscan get cached results + * @wmi_handle: wmi handle + * @pcached_results: cached results parameters + * + * This function send request to fw to get cached results. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_extscan_get_cached_results_cmd( + wmi_unified_t wmi_handle, + struct extscan_cached_result_params *pcached_results); -QDF_STATUS wmi_unified_extscan_stop_change_monitor_cmd(void *wmi_hdl, - struct extscan_capabilities_reset_params *reset_req); +/** + * wmi_unified_extscan_stop_change_monitor_cmd() - send stop change monitor cmd + * @wmi_handle: wmi handle + * @reset_req: Reset change request params + * + * This function sends stop change monitor request to fw. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_extscan_stop_change_monitor_cmd( + wmi_unified_t wmi_handle, + struct extscan_capabilities_reset_params *reset_req); -QDF_STATUS wmi_unified_extscan_start_change_monitor_cmd(void *wmi_hdl, - struct extscan_set_sig_changereq_params * - psigchange); +/** + * wmi_unified_extscan_start_change_monitor_cmd() - start change monitor cmd + * @wmi_handle: wmi handle + * @psigchange: change monitor request params + * + * This function sends start change monitor request to fw. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_extscan_start_change_monitor_cmd( + wmi_unified_t wmi_handle, + struct extscan_set_sig_changereq_params *psigchange); -QDF_STATUS wmi_unified_extscan_stop_hotlist_monitor_cmd(void *wmi_hdl, - struct extscan_bssid_hotlist_reset_params *photlist_reset); +/** + * wmi_unified_extscan_stop_hotlist_monitor_cmd() - stop hotlist monitor + * @wmi_handle: wmi handle + * @photlist_reset: hotlist reset params + * + * This function configures hotlist monitor to stop in fw. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_extscan_stop_hotlist_monitor_cmd( + wmi_unified_t wmi_handle, + struct extscan_bssid_hotlist_reset_params *photlist_reset); /** * wmi_unified_extscan_start_hotlist_monitor_cmd() - start hotlist monitor - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @params: hotlist params * * This function configures hotlist monitor to start in fw. * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_extscan_start_hotlist_monitor_cmd(void *wmi_hdl, - struct extscan_bssid_hotlist_set_params *params); +QDF_STATUS wmi_unified_extscan_start_hotlist_monitor_cmd( + wmi_unified_t wmi_handle, + struct extscan_bssid_hotlist_set_params *params); -QDF_STATUS wmi_unified_stop_extscan_cmd(void *wmi_hdl, - struct extscan_stop_req_params *pstopcmd); +/** + * wmi_unified_stop_extscan_cmd() - stop extscan command to fw. + * @wmi_handle: wmi handle + * @pstopcmd: stop scan command request params + * + * This function sends stop extscan request to fw. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure. + */ +QDF_STATUS wmi_unified_stop_extscan_cmd( + wmi_unified_t wmi_handle, + struct extscan_stop_req_params *pstopcmd); -QDF_STATUS wmi_unified_start_extscan_cmd(void *wmi_hdl, - struct wifi_scan_cmd_req_params *pstart); +/** + * wmi_unified_start_extscan_cmd() - start extscan command to fw. + * @wmi_handle: wmi handle + * @pstart: scan command request params + * + * This function sends start extscan request to fw. + * + * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure. + */ +QDF_STATUS wmi_unified_start_extscan_cmd( + wmi_unified_t wmi_handle, + struct wifi_scan_cmd_req_params *pstart); #endif /* _WMI_UNIFIED_EXTSCAN_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_gpio_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_gpio_api.h new file mode 100644 index 0000000000000000000000000000000000000000..15f9bebf4cee0f3268a6be809e8a13a6b4b08477 --- /dev/null +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_gpio_api.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020-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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/** + * DOC: Implement API's specific to gpio component. + */ + +#ifndef _WMI_UNIFIED_GPIO_API_H_ +#define _WMI_UNIFIED_GPIO_API_H_ + +#include + +/** + * wmi_unified_gpio_config_cmd_send() - WMI gpio config function + * @wmi_handle: handle to WMI. + * @param: pointer to hold gpio config param + * + * Send WMI set gpio configuration to firmware. + * + * Return QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_gpio_config_cmd_send(wmi_unified_t wmi_handle, + struct gpio_config_params *param); + +/** + * wmi_unified_gpio_output_cmd_send() - WMI gpio output function + * @wmi_handle: handle to WMI. + * @param: pointer to hold gpio output param + * + * Send WMI set gpio output value to firmware. + * + * Return QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure + */ +QDF_STATUS wmi_unified_gpio_output_cmd_send(wmi_unified_t wmi_handle, + struct gpio_output_params *param); + +#endif /* _WMI_UNIFIED_GPIO_API_H_ */ diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_nan_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_nan_api.h index e357dc3079a32a0da93ade2ad083aba38bdad2d4..ee0fafd9999e39bf068d42fbf862d0521632b52c 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_nan_api.h +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_nan_api.h @@ -47,34 +47,34 @@ QDF_STATUS wmi_unified_nan_disable_req_cmd(wmi_unified_t wmi_handle, /** * wmi_unified_ndp_initiator_req_cmd_send - api to send initiator request to FW - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @req: pointer to request buffer * * Return: status of operation */ QDF_STATUS -wmi_unified_ndp_initiator_req_cmd_send(void *wmi_hdl, +wmi_unified_ndp_initiator_req_cmd_send(wmi_unified_t wmi_handle, struct nan_datapath_initiator_req *req); /** * wmi_unified_ndp_responder_req_cmd_send - api to send responder request to FW - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @req: pointer to request buffer * * Return: status of operation */ QDF_STATUS -wmi_unified_ndp_responder_req_cmd_send(void *wmi_hdl, +wmi_unified_ndp_responder_req_cmd_send(wmi_unified_t wmi_handle, struct nan_datapath_responder_req *req); /** * wmi_unified_ndp_end_req_cmd_send - api to send end request to FW - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @req: pointer to request buffer * * Return: status of operation */ -QDF_STATUS wmi_unified_ndp_end_req_cmd_send(void *wmi_hdl, +QDF_STATUS wmi_unified_ndp_end_req_cmd_send(wmi_unified_t wmi_handle, struct nan_datapath_end_req *req); /** diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_p2p_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_p2p_api.h index 3a571582a190bb0e007c539ddc5749c937313778..e5a5db3f8695b8cab595518d2ab222eed7911fe8 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_p2p_api.h +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_p2p_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2019 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 @@ -26,22 +26,22 @@ /** * wmi_unified_set_p2pgo_oppps_req() - send p2p go opp power save request to fw - * @wmi_hdl: wmi handle - * @opps: p2p opp power save parameters + * @wmi_handle: wmi handle + * @oppps: p2p opp power save parameters * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_set_p2pgo_oppps_req(void *wmi_hdl, +QDF_STATUS wmi_unified_set_p2pgo_oppps_req(wmi_unified_t wmi_handle, struct p2p_ps_params *oppps); /** * wmi_unified_set_p2pgo_noa_req_cmd() - send p2p go noa request to fw - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @noa: p2p power save parameters * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_set_p2pgo_noa_req_cmd(void *wmi_hdl, +QDF_STATUS wmi_unified_set_p2pgo_noa_req_cmd(wmi_unified_t wmi_handle, struct p2p_ps_params *noa); /** @@ -52,52 +52,54 @@ QDF_STATUS wmi_unified_set_p2pgo_noa_req_cmd(void *wmi_hdl, * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_extract_p2p_noa_ev_param(void *wmi_hdl, +QDF_STATUS wmi_extract_p2p_noa_ev_param(wmi_unified_t wmi_handle, void *evt_buf, struct p2p_noa_info *param); /** * wmi_send_set_mac_addr_rx_filter_cmd() - set mac addr rx filter cmd - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @param: Pointer to set mac filter struct * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ QDF_STATUS -wmi_send_set_mac_addr_rx_filter_cmd(void *wmi_hdl, +wmi_send_set_mac_addr_rx_filter_cmd(wmi_unified_t wmi_handle, struct p2p_set_mac_filter *param); /** * wmi_extract_mac_addr_rx_filter_evt_param() - extract mac addr rx filter evt - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @evt_buf: pointer to event buffer * @param: Pointer to extracted evt info * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ QDF_STATUS -wmi_extract_mac_addr_rx_filter_evt_param(void *wmi_hdl, void *evt_buf, +wmi_extract_mac_addr_rx_filter_evt_param(wmi_unified_t wmi_handle, + void *evt_buf, struct p2p_set_mac_filter_evt *param); #ifdef FEATURE_P2P_LISTEN_OFFLOAD /** * wmi_unified_p2p_lo_start_cmd() - send p2p lo start request to fw - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @param: p2p listen offload start parameters * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_p2p_lo_start_cmd(void *wmi_hdl, +QDF_STATUS wmi_unified_p2p_lo_start_cmd(wmi_unified_t wmi_handle, struct p2p_lo_start *param); /** * wmi_unified_p2p_lo_stop_cmd() - send p2p lo stop request to fw - * @wmi_hdl: wmi handle + * @wmi_handle: wmi handle * @vdev_id: vdev id * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_unified_p2p_lo_stop_cmd(void *wmi_hdl, uint8_t vdev_id); +QDF_STATUS wmi_unified_p2p_lo_stop_cmd(wmi_unified_t wmi_handle, + uint8_t vdev_id); /** * wmi_extract_p2p_lo_stop_ev_param() - extract p2p lo stop param from event @@ -107,7 +109,7 @@ QDF_STATUS wmi_unified_p2p_lo_stop_cmd(void *wmi_hdl, uint8_t vdev_id); * * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure */ -QDF_STATUS wmi_extract_p2p_lo_stop_ev_param(void *wmi_hdl, +QDF_STATUS wmi_extract_p2p_lo_stop_ev_param(wmi_unified_t wmi_handle, void *evt_buf, struct p2p_lo_event *param); #endif /* FEATURE_P2P_LISTEN_OFFLOAD */ diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_param.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_param.h index 8786fdb5faf9298174e0d928dd1c34f692f4be64..6384d3d58656d05a782bdce92266cdd64fafb170 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_param.h +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_param.h @@ -1,6 +1,5 @@ /* - * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. 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 @@ -374,6 +373,12 @@ #define WMI_HOST_TPC_REGINDEX_MAX 4 #define WMI_HOST_ARRAY_GAIN_NUM_STREAMS 2 +/* AST Index for flow override */ +#define WMI_CONFIG_MSDU_AST_INDEX_0 0x0 +#define WMI_CONFIG_MSDU_AST_INDEX_1 0x1 +#define WMI_CONFIG_MSDU_AST_INDEX_2 0x2 +#define WMI_CONFIG_MSDU_AST_INDEX_3 0x3 + #include "qdf_atomic.h" #ifdef BIG_ENDIAN_HOST @@ -462,16 +467,6 @@ typedef enum { WMI_HOST_MODE_MAX = 24 } WMI_HOST_WLAN_PHY_MODE; -#ifndef CMN_VDEV_MGR_TGT_IF_ENABLE -typedef enum { - WMI_HOST_VDEV_START_OK = 0, - WMI_HOST_VDEV_START_CHAN_INVALID, - WMI_HOST_VDEV_START_CHAN_BLOCKED, - WMI_HOST_VDEV_START_CHAN_DFS_VIOLATION, - WMI_HOST_VDEV_START_TIMEOUT, -} WMI_HOST_VDEV_START_STATUS; -#endif - /* * Needs to be removed and use channel_param based * on how it is processed @@ -583,6 +578,7 @@ typedef enum { * @WMI_HOST_CHAN_WIDTH_80P80: 80+80 MHz channel operating width * @WMI_HOST_CHAN_WIDTH_5: 5 MHz channel operating width * @WMI_HOST_CHAN_WIDTH_10: 10 MHz channel operating width + * @WMI_HOST_CHAN_WIDTH_165: 165 MHz channel operating width */ typedef enum { WMI_HOST_CHAN_WIDTH_20 = 0, @@ -592,6 +588,7 @@ typedef enum { WMI_HOST_CHAN_WIDTH_80P80 = 4, WMI_HOST_CHAN_WIDTH_5 = 5, WMI_HOST_CHAN_WIDTH_10 = 6, + WMI_HOST_CHAN_WIDTH_165 = 7, } wmi_host_channel_width; #define ATH_EXPONENT_TO_VALUE(v) ((1<