diff --git a/components/son/dispatcher/inc/son_api.h b/components/son/dispatcher/inc/son_api.h index 24e98f30ed..c4d6022d78 100644 --- a/components/son/dispatcher/inc/son_api.h +++ b/components/son/dispatcher/inc/son_api.h @@ -397,6 +397,38 @@ int wlan_son_anqp_frame(struct wlan_objmgr_vdev *vdev, int subtype, uint8_t *frame, uint16_t frame_len, void *action_hdr, uint8_t *macaddr); +/** + * wlan_son_get_node_tx_power() - Gets the max transmit power for peer + * @assoc_req_ies: assoc req ies + * + * Return: Returns the max tx power + */ +uint8_t wlan_son_get_node_tx_power(struct element_info assoc_req_ies); + +/** + * wlan_son_get_max_mcs() - calculate the max mcs supported by the node + * @mode: current phymode + * @supp_idx: max supported idx + * @ext_idx: max extended idx + * @ht_mcs_idx: max mcs index for HT + * @vht_mcs_map: mcs map for VHT + * + * return: max_mcs for the node + */ +uint8_t wlan_son_get_max_mcs(uint8_t mode, uint8_t supp_idx, uint8_t ext_idx, + uint8_t ht_mcs_idx, uint8_t vht_mcs_map); + +/** + * wlan_son_get_peer_rrm_info() - Get RRM info for peer + * @assoc_req_ies: assoc req ies + * @rrmcaps: rrm capabilities + * @is_beacon_meas_supported: if beacon meas is supported + * + * Return: Returns QDF_STATUS_SUCCESS if succeed + */ +QDF_STATUS wlan_son_get_peer_rrm_info(struct element_info assoc_req_ies, + uint8_t *rrmcaps, + bool *is_beacon_meas_supported); #else static inline bool wlan_son_peer_is_kickout_allow(struct wlan_objmgr_vdev *vdev, @@ -468,5 +500,25 @@ int wlan_son_anqp_frame(struct wlan_objmgr_vdev *vdev, int subtype, return -EINVAL; } +static inline +uint8_t wlan_son_get_node_tx_power(struct element_info assoc_req_ies) +{ + return 0; +} + +static inline +uint8_t wlan_son_get_max_mcs(uint8_t mode, uint8_t supp_idx, uint8_t ext_idx, + uint8_t ht_mcs_idx, uint8_t vht_mcs_map) +{ + return 0; +} + +static inline +QDF_STATUS wlan_son_get_peer_rrm_info(struct element_info assoc_req_ies, + uint8_t *rrmcaps, + bool *is_beacon_meas_supported) +{ + return QDF_STATUS_E_INVAL; +} #endif /*WLAN_FEATURE_SON*/ #endif diff --git a/components/son/dispatcher/inc/son_ucfg_api.h b/components/son/dispatcher/inc/son_ucfg_api.h index 6edd914b5b..11281336dc 100644 --- a/components/son/dispatcher/inc/son_ucfg_api.h +++ b/components/son/dispatcher/inc/son_ucfg_api.h @@ -170,6 +170,39 @@ int ucfg_son_set_cbs_wait_time(struct wlan_objmgr_vdev *vdev, int ucfg_son_set_cbs_dwell_split_time(struct wlan_objmgr_vdev *vdev, uint32_t val); +/** + * ucfg_son_get_max_tx_power() - Gets the max transmit power for peer + * @assoc_req_ies: assoc req ies + * + * Return: Returns the max tx power + */ +uint8_t ucfg_son_get_tx_power(struct element_info assoc_req_ies); + +/** + * ucfg_get_max_mcs() - calculate the max mcs supported by the node + * @mode: current phy mode + * @supp_idx: max supported idx + * @ext_idx: max extended idx + * @ht_mcs_idx: max mcs index for HT + * @vht_mcs_map: mcs map for VHT + * + * Return: max_mcs for the node + */ +uint8_t ucfg_son_get_max_mcs(uint8_t mode, uint8_t supp_idx, uint8_t ext_idx, + uint8_t ht_mcs_idx, uint8_t vht_mcs_map); + +/** + * ucfg_son_get_peer_rrm_info() - Get RRM info for peer + * @assoc_req_ies: assoc req ies + * @rrmcaps: rrm capabiities + * @is_beacon_meas_supported: if beacon meas is supported + * + * Return: Returns QDF_STATUS_SUCCESS if succeed + */ +QDF_STATUS ucfg_son_get_peer_rrm_info(struct element_info assoc_req_ies, + uint8_t *rrmcaps, + bool *is_beacon_meas_supported); + #ifdef WLAN_FEATURE_SON /* ucfg_son_disable_cbs() - son cbs disable * @vdev: vdev pointer diff --git a/components/son/dispatcher/src/son_api.c b/components/son/dispatcher/src/son_api.c index ec7eceaa5d..ff29d0efd8 100644 --- a/components/son/dispatcher/src/son_api.c +++ b/components/son/dispatcher/src/son_api.c @@ -1263,3 +1263,60 @@ int wlan_son_set_cbs_dwell_split_time(struct wlan_objmgr_vdev *vdev, return 0; } + +uint8_t wlan_son_get_node_tx_power(struct element_info assoc_req_ies) +{ + const uint8_t *power_cap_ie_data; + + power_cap_ie_data = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_PWRCAP, + assoc_req_ies.ptr, + assoc_req_ies.len); + if (power_cap_ie_data) + return *(power_cap_ie_data + 3); + else + return 0; +} + +uint8_t wlan_son_get_max_mcs(uint8_t mode, uint8_t supp_idx, uint8_t ext_idx, + uint8_t ht_mcs_idx, uint8_t vht_mcs_map) +{ + uint8_t maxidx = MAX_HE_MCS_IDX; + + /* check supported rates */ + if (supp_idx != 0xff && maxidx < supp_idx) + maxidx = supp_idx; + + /* check extended rates */ + if (ext_idx != 0xff && maxidx < ext_idx) + maxidx = ext_idx; + + /* check for HT Mode */ + if (mode == SIR_SME_PHY_MODE_HT) + maxidx = ht_mcs_idx; + + if (mode == SIR_SME_PHY_MODE_VHT) + maxidx = (vht_mcs_map & DATA_RATE_11AC_MCS_MASK); + + return maxidx; +} + +QDF_STATUS wlan_son_get_peer_rrm_info(struct element_info assoc_req_ies, + uint8_t *rrmcaps, + bool *is_beacon_meas_supported) +{ + const uint8_t *eid; + + eid = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RRM, + assoc_req_ies.ptr, + assoc_req_ies.len); + if (eid) { + qdf_mem_copy(rrmcaps, &eid[2], eid[1]); + if ((rrmcaps[0] & + IEEE80211_RRM_CAPS_BEACON_REPORT_PASSIVE) || + (rrmcaps[0] & + IEEE80211_RRM_CAPS_BEACON_REPORT_ACTIVE)) + *is_beacon_meas_supported = true; + return QDF_STATUS_SUCCESS; + } + return QDF_STATUS_E_RESOURCES; +} diff --git a/components/son/dispatcher/src/son_ucfg_api.c b/components/son/dispatcher/src/son_ucfg_api.c index 16632aabe1..88bd355a21 100644 --- a/components/son/dispatcher/src/son_ucfg_api.c +++ b/components/son/dispatcher/src/son_ucfg_api.c @@ -124,3 +124,23 @@ int ucfg_son_disable_cbs(struct wlan_objmgr_vdev *vdev) { return wlan_son_cbs_disable(vdev); } + +uint8_t ucfg_son_get_tx_power(struct element_info assoc_req_ies) +{ + return wlan_son_get_node_tx_power(assoc_req_ies); +} + +uint8_t ucfg_son_get_max_mcs(uint8_t mode, uint8_t supp_idx, uint8_t ext_idx, + uint8_t ht_mcs_idx, uint8_t vht_mcs_map) +{ + return wlan_son_get_max_mcs(mode, supp_idx, ext_idx, ht_mcs_idx, + vht_mcs_map); +} + +QDF_STATUS ucfg_son_get_peer_rrm_info(struct element_info assoc_req_ies, + uint8_t *rrmcaps, + bool *is_beacon_meas_supported) +{ + return wlan_son_get_peer_rrm_info(assoc_req_ies, rrmcaps, + is_beacon_meas_supported); +} diff --git a/core/hdd/src/wlan_hdd_son.c b/core/hdd/src/wlan_hdd_son.c index f2f1bc1634..487a00b26e 100644 --- a/core/hdd/src/wlan_hdd_son.c +++ b/core/hdd/src/wlan_hdd_son.c @@ -31,6 +31,8 @@ #include #include #include +#include + /** * hdd_son_is_acs_in_progress() - whether acs is in progress or not @@ -2215,6 +2217,161 @@ end: return ret; } +static const uint8_t wlanphymode2ieeephymode[WLAN_PHYMODE_MAX] = { + [WLAN_PHYMODE_AUTO] = IEEE80211_MODE_AUTO, + [WLAN_PHYMODE_11A] = IEEE80211_MODE_11A, + [WLAN_PHYMODE_11B] = IEEE80211_MODE_11B, + [WLAN_PHYMODE_11G] = IEEE80211_MODE_11G, + [WLAN_PHYMODE_11G_ONLY] = 0, + [WLAN_PHYMODE_11NA_HT20] = IEEE80211_MODE_11NA_HT20, + [WLAN_PHYMODE_11NG_HT20] = IEEE80211_MODE_11NG_HT20, + [WLAN_PHYMODE_11NA_HT40] = IEEE80211_MODE_11NA_HT40, + [WLAN_PHYMODE_11NG_HT40PLUS] = IEEE80211_MODE_11NG_HT40PLUS, + [WLAN_PHYMODE_11NG_HT40MINUS] = IEEE80211_MODE_11NG_HT40MINUS, + [WLAN_PHYMODE_11NG_HT40] = IEEE80211_MODE_11NG_HT40, + [WLAN_PHYMODE_11AC_VHT20] = IEEE80211_MODE_11AC_VHT20, + [WLAN_PHYMODE_11AC_VHT20_2G] = 0, + [WLAN_PHYMODE_11AC_VHT40] = IEEE80211_MODE_11AC_VHT40, + [WLAN_PHYMODE_11AC_VHT40PLUS_2G] = IEEE80211_MODE_11AC_VHT40PLUS, + [WLAN_PHYMODE_11AC_VHT40MINUS_2G] = IEEE80211_MODE_11AC_VHT40MINUS, + [WLAN_PHYMODE_11AC_VHT40_2G] = 0, + [WLAN_PHYMODE_11AC_VHT80] = IEEE80211_MODE_11AC_VHT80, + [WLAN_PHYMODE_11AC_VHT80_2G] = 0, + [WLAN_PHYMODE_11AC_VHT160] = IEEE80211_MODE_11AC_VHT160, + [WLAN_PHYMODE_11AC_VHT80_80] = IEEE80211_MODE_11AC_VHT80_80, + [WLAN_PHYMODE_11AXA_HE20] = IEEE80211_MODE_11AXA_HE20, + [WLAN_PHYMODE_11AXG_HE20] = IEEE80211_MODE_11AXG_HE20, + [WLAN_PHYMODE_11AXA_HE40MINUS] = IEEE80211_MODE_11AXA_HE40, + [WLAN_PHYMODE_11AXG_HE40PLUS] = IEEE80211_MODE_11AXG_HE40PLUS, + [WLAN_PHYMODE_11AXG_HE40MINUS] = IEEE80211_MODE_11AXG_HE40MINUS, + [WLAN_PHYMODE_11AXG_HE40] = IEEE80211_MODE_11AXG_HE40, + [WLAN_PHYMODE_11AXA_HE80] = IEEE80211_MODE_11AXA_HE80, + [WLAN_PHYMODE_11AXA_HE80] = 0, + [WLAN_PHYMODE_11AXA_HE160] = IEEE80211_MODE_11AXA_HE160, + [WLAN_PHYMODE_11AXA_HE80_80] = IEEE80211_MODE_11AXA_HE80_80, +#ifdef WLAN_FEATURE_11BE + [WLAN_PHYMODE_11BEA_EHT20] = IEEE80211_MODE_11BEA_EHT20, + [WLAN_PHYMODE_11BEG_EHT20] = IEEE80211_MODE_11BEG_EHT20, + [WLAN_PHYMODE_11BEA_EHT40MINUS] = IEEE80211_MODE_11BEA_EHT40, + [WLAN_PHYMODE_11BEG_EHT40PLUS] = IEEE80211_MODE_11BEG_EHT40PLUS, + [WLAN_PHYMODE_11BEG_EHT40MINUS] = IEEE80211_MODE_11BEG_EHT40MINUS, + [WLAN_PHYMODE_11BEG_EHT40] = IEEE80211_MODE_11BEG_EHT40, + [WLAN_PHYMODE_11BEA_EHT80] = IEEE80211_MODE_11BEA_EHT80, + [WLAN_PHYMODE_11BEG_EHT80] = 0, + [WLAN_PHYMODE_11BEA_EHT160] = IEEE80211_MODE_11BEA_EHT160, + [WLAN_PHYMODE_11BEA_EHT320] = IEEE80211_MODE_11BEA_EHT320, +#endif /* WLAN_FEATURE_11BE */ +}; + +static enum ieee80211_phymode +wlan_hdd_son_get_ieee_phymode(enum wlan_phymode wlan_phymode) +{ + if (wlan_phymode >= WLAN_PHYMODE_MAX) + return IEEE80211_MODE_AUTO; + + return wlanphymode2ieeephymode[wlan_phymode]; +} + +static QDF_STATUS hdd_son_get_node_info(struct wlan_objmgr_vdev *vdev, + uint8_t *mac_addr, + wlan_node_info *node_info) +{ + struct hdd_adapter *adapter = wlan_hdd_get_adapter_from_objmgr(vdev); + struct hdd_station_info *sta_info; + enum wlan_phymode peer_phymode; + struct wlan_objmgr_psoc *psoc; + + sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list, mac_addr, + STA_INFO_SON_GET_DATRATE_INFO); + if (!sta_info) { + hdd_err("Sta info is null"); + return QDF_STATUS_E_FAILURE; + } + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + hdd_err("null psoc"); + return QDF_STATUS_E_FAILURE; + } + + node_info->max_chwidth = + hdd_chan_width_to_son_chwidth(sta_info->ch_width); + node_info->num_streams = (sta_info->max_mcs_idx >= 8) ? 2 : 1; + ucfg_mlme_get_peer_phymode(psoc, mac_addr, &peer_phymode); + node_info->phymode = wlan_hdd_son_get_ieee_phymode(peer_phymode); + node_info->max_txpower = ucfg_son_get_tx_power(sta_info->assoc_req_ies); + node_info->max_MCS = ucfg_son_get_max_mcs(sta_info->mode, + sta_info->max_supp_idx, + sta_info->max_ext_idx, + sta_info->max_mcs_idx, + sta_info->rx_mcs_map); + if (sta_info->vht_present) + node_info->is_mu_mimo_supported = + sta_info->vht_caps.vht_cap_info + & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; + if (sta_info->ht_present) + node_info->is_static_smps = ((sta_info->ht_caps.cap_info + & IEEE80211_HTCAP_C_SM_MASK) == + IEEE80211_HTCAP_C_SMPOWERSAVE_STATIC); + hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true, + STA_INFO_SON_GET_DATRATE_INFO); + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS hdd_son_get_peer_capability(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer, + wlan_peer_cap *peer_cap) +{ + struct hdd_station_info *sta_info; + struct hdd_adapter *adapter; + bool b_meas_supported; + QDF_STATUS status; + + adapter = wlan_hdd_get_adapter_from_objmgr(vdev); + if (!adapter) { + hdd_err("null adapter"); + return QDF_STATUS_E_FAILURE; + } + + 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 QDF_STATUS_E_FAILURE; + } + + hdd_info("Getting peer capability from sta_info"); + qdf_mem_copy(peer_cap->bssid, vdev->vdev_mlme.macaddr, + QDF_MAC_ADDR_SIZE); + peer_cap->is_BTM_Supported = !!(sta_info->ext_cap & + BIT(19/*BSS_TRANSITION*/)); + peer_cap->is_RRM_Supported = !!(sta_info->capability & + WLAN_CAPABILITY_RADIO_MEASURE); + + peer_cap->band_cap = sta_info->supported_band; + if (sta_info->assoc_req_ies.len) { + status = ucfg_son_get_peer_rrm_info(sta_info->assoc_req_ies, + peer_cap->rrmcaps, + &(b_meas_supported)); + if (status == QDF_STATUS_SUCCESS) + peer_cap->is_beacon_meas_supported = b_meas_supported; + } + if (sta_info->ht_present) + peer_cap->htcap = sta_info->ht_caps.cap_info; + if (sta_info->vht_present) + peer_cap->vhtcap = sta_info->vht_caps.vht_cap_info; + + qdf_mem_zero(&peer_cap->hecap, sizeof(wlan_client_he_capabilities)); + + os_if_son_get_node_datarate_info(vdev, peer->macaddr, + &peer_cap->info); + + hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true, + STA_INFO_SOFTAP_GET_STA_INFO); + + return QDF_STATUS_SUCCESS; +} + void hdd_son_register_callbacks(struct hdd_context *hdd_ctx) { struct son_callbacks cb_obj = {0}; @@ -2250,6 +2407,8 @@ void hdd_son_register_callbacks(struct hdd_context *hdd_ctx) cb_obj.os_if_start_acs = hdd_son_start_acs; cb_obj.os_if_set_acs_channels = hdd_son_set_acs_channels; 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; os_if_son_register_hdd_callbacks(hdd_ctx->psoc, &cb_obj); diff --git a/core/hdd/src/wlan_hdd_sta_info.c b/core/hdd/src/wlan_hdd_sta_info.c index 0f22def928..d72d158647 100644 --- a/core/hdd/src/wlan_hdd_sta_info.c +++ b/core/hdd/src/wlan_hdd_sta_info.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-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 @@ -64,6 +64,7 @@ char *sta_info_string_from_dbgid(wlan_sta_info_dbgid id) "STA_INFO_SHOW", "STA_INFO_SOFTAP_IPA_RX_PKT_CALLBACK", "STA_INFO_WLAN_HDD_CFG80211_DUMP_STATION", + "STA_INFO_SON_GET_DATRATE_INFO", "STA_INFO_ID_MAX"}; int32_t num_dbg_strings = QDF_ARRAY_SIZE(strings); diff --git a/core/hdd/src/wlan_hdd_sta_info.h b/core/hdd/src/wlan_hdd_sta_info.h index d1fe1788d4..b6221d8c8c 100644 --- a/core/hdd/src/wlan_hdd_sta_info.h +++ b/core/hdd/src/wlan_hdd_sta_info.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-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 @@ -111,6 +111,7 @@ enum dhcp_nego_status { * @STA_INFO_SOFTAP_IPA_RX_PKT_CALLBACK: Update rx mcbc stats for IPA case * @STA_INFO_WLAN_HDD_CFG80211_DUMP_STATION: NL80211_CMD_GET_STATION dumpit * handler for SoftAP + * @STA_INFO_SON_GET_DATRATE_INFO: gets datarate info for a SON node * */ /* @@ -150,7 +151,7 @@ typedef enum { STA_INFO_SHOW = 29, STA_INFO_SOFTAP_IPA_RX_PKT_CALLBACK = 30, STA_INFO_WLAN_HDD_CFG80211_DUMP_STATION = 31, - + STA_INFO_SON_GET_DATRATE_INFO = 32, STA_INFO_ID_MAX, } wlan_sta_info_dbgid; diff --git a/os_if/son/inc/os_if_son.h b/os_if/son/inc/os_if_son.h index 124182b21d..797cd2c655 100644 --- a/os_if/son/inc/os_if_son.h +++ b/os_if/son/inc/os_if_son.h @@ -66,6 +66,8 @@ * @os_if_start_acs: Trigger ACS * @os_if_set_acs_channels: Set channel list for ACS * @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 */ struct son_callbacks { uint32_t (*os_if_is_acs_in_progress)(struct wlan_objmgr_vdev *vdev); @@ -125,6 +127,12 @@ struct son_callbacks { struct ieee80211req_athdbg *req); int (*os_if_get_acs_report)(struct wlan_objmgr_vdev *vdev, struct ieee80211_acs_dbg *acs_r); + QDF_STATUS (*os_if_get_node_info)(struct wlan_objmgr_vdev *vdev, + uint8_t *mac_addr, + wlan_node_info *nodeinfo); + QDF_STATUS (*os_if_get_peer_capability)(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer, + wlan_peer_cap *cap); }; /** @@ -745,4 +753,15 @@ int os_if_son_parse_generic_nl_cmd(struct wiphy *wiphy, struct nlattr **tb, enum os_if_son_vendor_cmd_type type); +/** + * os_if_son_get_node_datarate_info() - Get datarate info about given mac + * @vdev: vdev_obj + * @mac_addr: mac_address to get datarate information + * @node_info: object to store datarate information + * + * Return: void + */ +QDF_STATUS os_if_son_get_node_datarate_info(struct wlan_objmgr_vdev *vdev, + uint8_t *mac_addr, + wlan_node_info *node_info); #endif diff --git a/os_if/son/src/os_if_son.c b/os_if/son/src/os_if_son.c index b0392a7429..62a38ac060 100644 --- a/os_if/son/src/os_if_son.c +++ b/os_if/son/src/os_if_son.c @@ -884,11 +884,88 @@ QDF_STATUS os_if_son_vdev_ops(struct wlan_objmgr_vdev *vdev, enum wlan_mlme_vdev_param type, void *data, void *ret) { + union wlan_mlme_vdev_data *in = (union wlan_mlme_vdev_data *)data; + union wlan_mlme_vdev_data *out = (union wlan_mlme_vdev_data *)ret; + + if (!vdev) + return QDF_STATUS_E_INVAL; + switch (type) { + case VDEV_SET_IE: + break; + case VDEV_CLR_IE: + break; + case VDEV_SET_ACL: + break; + case VDEV_CLR_ACL: + break; + case VDEV_SET_ACL_TIMER: + break; + case VDEV_SET_PEER_ACT_STATS: + break; + case VDEV_SET_SEC_STA_WDS: + break; + case VDEV_SET_MEC: + break; + case VDEV_SET_MBO_IE_BSTM: + break; + case VDEV_SET_WPS_ACL_ENABLE: + break; + case VDEV_SET_WNM_BSS_PREF: + break; + case VDEV_GET_NSS: + break; + case VDEV_GET_CHAN: + if (!out) + return QDF_STATUS_E_INVAL; + qdf_mem_copy(&out->chan, + wlan_vdev_get_active_channel(vdev), + sizeof(out->chan)); + break; + case VDEV_GET_CHAN_WIDTH: + break; + case VDEV_GET_CHAN_UTIL: + if (!out) + return QDF_STATUS_E_INVAL; + out->chan_util = os_if_son_get_chan_uti(vdev, NULL); + break; + case VDEV_GET_APCAP: + break; + case VDEV_GET_CONNECT_N_TX: + break; + case VDEV_GET_SSID: + break; + case VDEV_GET_MAX_PHYRATE: + break; + case VDEV_GET_ACL: + break; + case VDEV_GET_ACL_RSSI_THRESHOLDS: + break; + case VDEV_GET_NODE_CAP: + if (!out || !in) + return QDF_STATUS_E_INVAL; + os_if_son_get_node_datarate_info(vdev, in->mac, &out->nodeinfo); + break; + case VDEV_GET_WDS: + break; + default: + return QDF_STATUS_E_INVAL; + } + return QDF_STATUS_SUCCESS; } qdf_export_symbol(os_if_son_vdev_ops); +static QDF_STATUS os_if_son_get_peer_capability(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer, + wlan_peer_cap *peer_cap) +{ + if (g_son_os_if_cb.os_if_get_peer_capability) + return g_son_os_if_cb.os_if_get_peer_capability(vdev, peer, + peer_cap); + return QDF_STATUS_E_INVAL; +} + QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer, enum wlan_mlme_peer_param type, union wlan_mlme_peer_data *in, @@ -931,6 +1008,12 @@ QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer, status = ucfg_son_set_peer_kickout_allow(vdev, peer, in->enable); break; + case PEER_GET_CAPABILITY: + if (!out) + return QDF_STATUS_E_INVAL; + status = os_if_son_get_peer_capability(vdev, peer, + &out->peercap); + break; default: osif_err("invalid type: %d", type); status = QDF_STATUS_E_INVAL; @@ -1522,3 +1605,42 @@ int os_if_son_parse_generic_nl_cmd(struct wiphy *wiphy, return rx_ops->parse_generic_nl_cmd(wiphy, wdev, ¶m, type); } + +QDF_STATUS os_if_son_get_node_datarate_info(struct wlan_objmgr_vdev *vdev, + uint8_t *mac_addr, + wlan_node_info *node_info) +{ + int8_t max_tx_power; + int8_t min_tx_power; + struct wlan_objmgr_psoc *psoc; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + osif_err("null posc"); + return QDF_STATUS_E_INVAL; + } + + if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), mac_addr) == + QDF_STATUS_SUCCESS) { + node_info->max_chwidth = os_if_son_get_chwidth(vdev); + node_info->phymode = os_if_son_get_phymode(vdev); + node_info->num_streams = os_if_son_get_rx_streams(vdev); + ucfg_son_get_min_and_max_power(psoc, &max_tx_power, + &min_tx_power); + node_info->max_txpower = max_tx_power; + node_info->max_MCS = MAX_HE_MCS_IDX; + osif_debug("node info: max_chwidth: %u, phymode: %u, num_streams: %d, max_mcs: %d, max_txpower: %d", + node_info->max_chwidth, node_info->phymode, + node_info->num_streams, node_info->max_MCS, + node_info->max_txpower); + } else { + if (!g_son_os_if_cb.os_if_get_node_info) { + osif_err("Callback not registered"); + return QDF_STATUS_E_INVAL; + } + status = g_son_os_if_cb.os_if_get_node_info(vdev, mac_addr, + node_info); + } + return status; +}