diff --git a/components/son/dispatcher/inc/son_api.h b/components/son/dispatcher/inc/son_api.h index c4d6022d78..438de0fd39 100644 --- a/components/son/dispatcher/inc/son_api.h +++ b/components/son/dispatcher/inc/son_api.h @@ -206,6 +206,35 @@ QDF_STATUS wlan_son_register_mlme_deliver_cb(struct wlan_objmgr_psoc *psoc, mlme_deliver_cb cb, enum SON_MLME_DELIVER_CB_TYPE type); +/** + * wlan_son_peer_ext_stat_enable() - sends EXT stats command to FW + * @pdev: pointer to pdev + * @mac_addr: MAC address of the target peer + * @vdev: Pointer to vdev + * @stats_count: Stats count + * @enable: Enable / disable ext stats + * + * Return: QDF_STATUS_SUCCESS on success else failure + */ +QDF_STATUS wlan_son_peer_ext_stat_enable(struct wlan_objmgr_pdev *pdev, + uint8_t *mac_addr, + struct wlan_objmgr_vdev *vdev, + uint32_t stats_count, + uint32_t enable); + +/** + * wlan_son_peer_req_inst_stats() - Requests for instantaneous stats for + * the target mac_addr from FW via + * WMI_REQUEST_STATS_CMDID. + * @pdev: pointer to pdev + * @mac_addr: MAC address of the target peer + * @vdev: Pointer to vdev + * + * Return: QDF_STATUS_SUCCESS on success else failure + */ +QDF_STATUS wlan_son_peer_req_inst_stats(struct wlan_objmgr_pdev *pdev, + uint8_t *mac_addr, + struct wlan_objmgr_vdev *vdev); /** * wlan_son_get_chan_flag() - get chan flag diff --git a/components/son/dispatcher/src/son_api.c b/components/son/dispatcher/src/son_api.c index ff29d0efd8..753b18ed69 100644 --- a/components/son/dispatcher/src/son_api.c +++ b/components/son/dispatcher/src/son_api.c @@ -91,6 +91,65 @@ static void wlan_son_is_he_supported(struct wlan_objmgr_psoc *psoc, } #endif /*WLAN_FEATURE_11AX*/ +QDF_STATUS wlan_son_peer_ext_stat_enable(struct wlan_objmgr_pdev *pdev, + uint8_t *mac_addr, + struct wlan_objmgr_vdev *vdev, + uint32_t stats_count, + uint32_t enable) +{ + struct wlan_lmac_if_tx_ops *tx_ops; + struct wlan_objmgr_psoc *psoc; + + if (!pdev) { + qdf_err("invalid pdev"); + return QDF_STATUS_E_NULL_VALUE; + } + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + qdf_err("invalid psoc"); + return QDF_STATUS_E_NULL_VALUE; + } + tx_ops = wlan_psoc_get_lmac_if_txops(psoc); + if (!tx_ops) { + qdf_err("invalid tx_ops"); + return QDF_STATUS_E_NULL_VALUE; + } + if (tx_ops->son_tx_ops.peer_ext_stats_enable) + return tx_ops->son_tx_ops.peer_ext_stats_enable(pdev, + mac_addr, vdev, + stats_count, + enable); + + return QDF_STATUS_E_NULL_VALUE; +} + +QDF_STATUS wlan_son_peer_req_inst_stats(struct wlan_objmgr_pdev *pdev, + uint8_t *mac_addr, + struct wlan_objmgr_vdev *vdev) +{ + struct wlan_lmac_if_tx_ops *tx_ops; + struct wlan_objmgr_psoc *psoc; + + if (!pdev) { + qdf_err("invalid pdev"); + return QDF_STATUS_E_NULL_VALUE; + } + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + qdf_err("invalid psoc"); + return QDF_STATUS_E_NULL_VALUE; + } + tx_ops = wlan_psoc_get_lmac_if_txops(psoc); + if (!tx_ops) { + qdf_err("invalid tx_ops"); + return QDF_STATUS_E_NULL_VALUE; + } + if (tx_ops->son_tx_ops.son_send_null) + return tx_ops->son_tx_ops.son_send_null(pdev, mac_addr, vdev); + + return QDF_STATUS_E_NULL_VALUE; +} + uint32_t wlan_son_get_chan_flag(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq, bool flag_160, struct ch_params *chan_params) diff --git a/core/hdd/src/wlan_hdd_son.c b/core/hdd/src/wlan_hdd_son.c index bbed354ebd..c0050e4564 100644 --- a/core/hdd/src/wlan_hdd_son.c +++ b/core/hdd/src/wlan_hdd_son.c @@ -2372,6 +2372,37 @@ static QDF_STATUS hdd_son_get_peer_capability(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_SUCCESS; } +uint32_t hdd_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer) +{ + uint32_t ret = 0; + struct hdd_station_info *sta_info = NULL; + struct hdd_adapter *adapter = NULL; + + adapter = wlan_hdd_get_adapter_from_objmgr(vdev); + if (!adapter) { + hdd_err("null adapter"); + return ret; + } + + sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, + peer->macaddr, + STA_INFO_SOFTAP_GET_STA_INFO); + if (!sta_info) { + hdd_err("sta_info NULL"); + return ret; + } + + ret = sta_info->max_mcs_idx; + + hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true, + STA_INFO_SOFTAP_GET_STA_INFO); + hdd_debug("Peer " QDF_MAC_ADDR_FMT " max MCS index: %u", + QDF_MAC_ADDR_REF(peer->macaddr), ret); + + return ret; +} + void hdd_son_register_callbacks(struct hdd_context *hdd_ctx) { struct son_callbacks cb_obj = {0}; @@ -2409,6 +2440,7 @@ void hdd_son_register_callbacks(struct hdd_context *hdd_ctx) cb_obj.os_if_get_acs_report = hdd_son_get_acs_report; cb_obj.os_if_get_node_info = hdd_son_get_node_info; cb_obj.os_if_get_peer_capability = hdd_son_get_peer_capability; + cb_obj.os_if_get_peer_max_mcs_idx = hdd_son_get_peer_max_mcs_idx; os_if_son_register_hdd_callbacks(hdd_ctx->psoc, &cb_obj); diff --git a/core/hdd/src/wlan_hdd_son.h b/core/hdd/src/wlan_hdd_son.h index 0c4f915ac6..64b0829274 100644 --- a/core/hdd/src/wlan_hdd_son.h +++ b/core/hdd/src/wlan_hdd_son.h @@ -112,6 +112,15 @@ int hdd_son_send_get_wifi_generic_command(struct wiphy *wiphy, struct wireless_dev *wdev, struct nlattr **tb); +/** + * hdd_son_get_peer_max_mcs_idx() - Get peer max mcs index + * @vdev: vdev object + * @peer: peer obj + * + * Return: number of max mcs on succes or 0 on failure + */ +uint32_t hdd_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer); #else static inline void hdd_son_register_callbacks(struct hdd_context *hdd_ctx) @@ -161,5 +170,13 @@ int hdd_son_send_get_wifi_generic_command(struct wiphy *wiphy, { return -EINVAL; } + +static inline +uint32_t hdd_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer) +{ + return 0; +} + #endif /* WLAN_FEATURE_SON */ #endif diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 2d7c7f3582..5cf93a65d1 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -290,6 +290,12 @@ #define WMA_DEFAULT_HW_MODE_INDEX 0xFFFF #define TWO_THIRD (2/3) +#ifdef WLAN_FEATURE_SON +#define WMA_SON_MAX_PEER_EXT_STATS 16 +#else +#define WMA_SON_MAX_PEER_EXT_STATS 0 +#endif + /** * WMA hardware mode list bit-mask definitions. * Bits 4:0, 31:29 are unused. diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index e41ebcfb72..bbf0be4354 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -6923,6 +6923,7 @@ int wma_rx_service_ready_ext_event(void *handle, uint8_t *event, wlan_res_cfg->pktcapture_support = true; else wlan_res_cfg->pktcapture_support = false; + wlan_res_cfg->max_peer_ext_stats = WMA_SON_MAX_PEER_EXT_STATS; if (wmi_service_enabled(wmi_handle, wmi_service_sae_eapol_offload_support)) diff --git a/os_if/son/inc/os_if_son.h b/os_if/son/inc/os_if_son.h index 797cd2c655..8da72a9433 100644 --- a/os_if/son/inc/os_if_son.h +++ b/os_if/son/inc/os_if_son.h @@ -68,6 +68,7 @@ * @os_if_get_acs_report: Gets the ACS report * @os_if_get_node_info: Gets the datarate info for node * @os_if_get_peer_capability: Gets peer capability + * @os_if_get_peer_max_mcs_idx: Gets peer max MCS index */ struct son_callbacks { uint32_t (*os_if_is_acs_in_progress)(struct wlan_objmgr_vdev *vdev); @@ -133,6 +134,8 @@ struct son_callbacks { QDF_STATUS (*os_if_get_peer_capability)(struct wlan_objmgr_vdev *vdev, struct wlan_objmgr_peer *peer, wlan_peer_cap *cap); + uint32_t (*os_if_get_peer_max_mcs_idx)(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer); }; /** @@ -764,4 +767,14 @@ int os_if_son_parse_generic_nl_cmd(struct wiphy *wiphy, QDF_STATUS os_if_son_get_node_datarate_info(struct wlan_objmgr_vdev *vdev, uint8_t *mac_addr, wlan_node_info *node_info); + +/** + * os_if_son_get_peer_max_mcs_idx() - Get max mcs index of the peer + * @vdev: vdev obj + * @peer: peer obj + * + * Return: max mcs index on success / 0 on failure + */ +uint32_t os_if_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer); #endif diff --git a/os_if/son/src/os_if_son.c b/os_if/son/src/os_if_son.c index 47c2cdd72d..f7b44f61a0 100644 --- a/os_if/son/src/os_if_son.c +++ b/os_if/son/src/os_if_son.c @@ -975,6 +975,9 @@ QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer, struct wlan_objmgr_pdev *pdev; struct wlan_objmgr_psoc *psoc; QDF_STATUS status = QDF_STATUS_SUCCESS; + struct qdf_mac_addr mac; + int ret_val; + static uint32_t peer_ext_stats_count; if (!peer) { osif_err("null peer"); @@ -1000,6 +1003,18 @@ QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer, osif_debug("type %d", type); /* All PEER MLME operations exported to SON component */ switch (type) { + /* SET/CLR API start */ + case PEER_SET_KICKOUT: + qdf_mem_copy(&mac.bytes, peer->macaddr, QDF_MAC_ADDR_SIZE); + ret_val = + g_son_os_if_cb.os_if_kickout_mac(vdev->vdev_objmgr.vdev_id, + &mac); + if (ret_val) { + osif_err("Failed to kickout peer " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(peer->macaddr)); + return QDF_STATUS_E_INVAL; + } + break; case PEER_SET_KICKOUT_ALLOW: if (!in) { osif_err("invalid input parameter"); @@ -1007,6 +1022,38 @@ QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer, } status = ucfg_son_set_peer_kickout_allow(vdev, peer, in->enable); + osif_debug("kickout allow %d, status %d", in->enable, status); + break; + case PEER_SET_EXT_STATS: + if (!in) + return QDF_STATUS_E_INVAL; + ret_val = wlan_peer_mlme_flag_get(peer, WLAN_PEER_F_EXT_STATS); + osif_debug("Enable: %d peer_ext_stats_count: %u ret_val: %d", + in->enable, peer_ext_stats_count, ret_val); + if ((!!ret_val) != in->enable) { + status = + wlan_son_peer_ext_stat_enable(pdev, peer->macaddr, + vdev, + peer_ext_stats_count, + in->enable); + osif_debug("status: %u", status); + if (status == QDF_STATUS_SUCCESS) { + peer_ext_stats_count++; + wlan_peer_mlme_flag_set(peer, + WLAN_PEER_F_EXT_STATS); + } else { + if (peer_ext_stats_count) + peer_ext_stats_count--; + wlan_peer_mlme_flag_clear + (peer, WLAN_PEER_F_EXT_STATS); + } + } + break; + case PEER_REQ_INST_STAT: + status = wlan_son_peer_req_inst_stats(pdev, peer->macaddr, + vdev); + if (status != QDF_STATUS_SUCCESS) + osif_err("Type: %d is failed", type); break; case PEER_GET_CAPABILITY: if (!out) @@ -1014,6 +1061,11 @@ QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer, status = os_if_son_get_peer_capability(vdev, peer, &out->peercap); break; + case PEER_GET_MAX_MCS: + if (!out) + return QDF_STATUS_E_INVAL; + out->mcs = os_if_son_get_peer_max_mcs_idx(vdev, peer); + break; default: osif_err("invalid type: %d", type); status = QDF_STATUS_E_INVAL; @@ -1644,3 +1696,12 @@ QDF_STATUS os_if_son_get_node_datarate_info(struct wlan_objmgr_vdev *vdev, } return status; } + +uint32_t os_if_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer) +{ + if (g_son_os_if_cb.os_if_get_peer_max_mcs_idx) + return g_son_os_if_cb.os_if_get_peer_max_mcs_idx(vdev, peer); + + return 0; +}