mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-14 16:46:15 -04:00
qcacld-3.0: Add support of request peer stats info(part 3)
qcacld-2.0 to qcacld-3.0 propagation FW has limitation to support old WMI_REQUEST_STATS_CMDID and WMI_UPDATE_STATS_EVENTID interface on AP vDev. FW suggest to use new WMI_REQUEST_PEER_STATS_INFO_CMDID and WMI_PEER_STATS_INFO_EVENTID to get tx/rx rate. This checkin is about HDD layer, provide APIs/callbacks to upper layer to query rssi/tx/rx statistics of peer station associated with SAP, and provide a default disabled ini setting and checking FW's WMI_SERVICE_PEER_STATS_INFO capability to control this get peer info interface. Add/change iwpriv/QCA_NL80211_VENDOR_SUBCMD_GET_STATION/ cfg80211_ops.get_station interfaces to upper layer. Change-Id: Ib1571219faa16e3bc8c3eb1260137ae08b8b6016 CRs-Fixed: 2059507
This commit is contained in:
parent
dbc2d2f736
commit
496b36c936
16 changed files with 1992 additions and 194 deletions
|
|
@ -141,6 +141,7 @@ struct channel_list_info {
|
|||
#define QCSAP_SET_WLAN_RESUME 6
|
||||
|
||||
#define MAX_VAR_ARGS 7
|
||||
#define QCSAP_IOCTL_PRIV_GET_RSSI (SIOCIWFIRSTPRIV + 29)
|
||||
#define QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED (SIOCIWFIRSTPRIV + 31)
|
||||
|
||||
#define QCSAP_IOCTL_MAX_STR_LEN 1024
|
||||
|
|
|
|||
|
|
@ -5935,6 +5935,24 @@ enum hdd_link_speed_rpt_type {
|
|||
#define CFG_MAX_HT_MCS_FOR_TX_DATA_MAX (WNI_CFG_MAX_HT_MCS_TX_DATA_STAMAX)
|
||||
#define CFG_MAX_HT_MCS_FOR_TX_DATA_DEFAULT (WNI_CFG_MAX_HT_MCS_TX_DATA_STADEF)
|
||||
|
||||
/*
|
||||
* <ini>
|
||||
* gSapGetPeerInfo - Enable/Disable remote peer info query support
|
||||
* @Min: 0 - Disable remote peer info query support
|
||||
* @Max: 1 - Enable remote peer info query support
|
||||
* @Default: 0
|
||||
*
|
||||
* This ini is used to enable/disable remote peer info query support
|
||||
*
|
||||
* Usage: External
|
||||
*
|
||||
* </ini>
|
||||
*/
|
||||
#define CFG_SAP_GET_PEER_INFO "gSapGetPeerInfo"
|
||||
#define CFG_SAP_GET_PEER_INFO_MIN (0)
|
||||
#define CFG_SAP_GET_PEER_INFO_MAX (1)
|
||||
#define CFG_SAP_GET_PEER_INFO_DEFAULT (0)
|
||||
|
||||
/*
|
||||
* <ini>
|
||||
* gDisableABGRateForTxData - disable abg rate for tx data
|
||||
|
|
@ -12003,6 +12021,7 @@ struct hdd_config {
|
|||
bool gEnableOverLapCh;
|
||||
bool fRegChangeDefCountry;
|
||||
uint16_t max_ht_mcs_txdata;
|
||||
bool sap_get_peer_info;
|
||||
bool disable_abg_rate_txdata;
|
||||
uint8_t rate_for_tx_mgmt;
|
||||
uint8_t rate_for_tx_mgmt_2g;
|
||||
|
|
|
|||
|
|
@ -774,42 +774,118 @@ enum bss_stop_reason {
|
|||
BSS_STOP_DUE_TO_MCC_SCC_SWITCH = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* Per station structure kept in HDD for multiple station support for SoftAP
|
||||
/**
|
||||
* struct hdd_rate_info - rate_info in HDD
|
||||
* @rate: tx/rx rate (kbps)
|
||||
* @mode: 0->11abg legacy, 1->HT, 2->VHT (refer to sir_sme_phy_mode)
|
||||
* @nss: number of streams
|
||||
* @mcs: mcs index for HT/VHT mode
|
||||
* @rate_flags: rate flags for last tx/rx
|
||||
*
|
||||
* rate info in HDD
|
||||
*/
|
||||
struct hdd_rate_info {
|
||||
uint32_t rate;
|
||||
uint8_t mode;
|
||||
uint8_t nss;
|
||||
uint8_t mcs;
|
||||
uint8_t rate_flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hdd_fw_txrx_stats - fw txrx status in HDD
|
||||
* (refer to station_info struct in Kernel)
|
||||
* @tx_packets: packets transmitted to this station
|
||||
* @tx_bytes: bytes transmitted to this station
|
||||
* @rx_packets: packets received from this station
|
||||
* @rx_bytes: bytes received from this station
|
||||
* @rx_retries: cumulative retry counts
|
||||
* @tx_failed: number of failed transmissions
|
||||
* @rssi: The signal strength (dbm)
|
||||
* @tx_rate: last used tx rate info
|
||||
* @rx_rate: last used rx rate info
|
||||
*
|
||||
* fw txrx status in HDD
|
||||
*/
|
||||
struct hdd_fw_txrx_stats {
|
||||
uint32_t tx_packets;
|
||||
uint64_t tx_bytes;
|
||||
uint32_t rx_packets;
|
||||
uint64_t rx_bytes;
|
||||
uint32_t tx_retries;
|
||||
uint32_t tx_failed;
|
||||
int8_t rssi;
|
||||
struct hdd_rate_info tx_rate;
|
||||
struct hdd_rate_info rx_rate;
|
||||
};
|
||||
|
||||
/**
|
||||
* typedef struct hdd_station_info_t - Per station structure kept in HDD for
|
||||
* multiple station support for SoftAP
|
||||
* @isUsed: The station entry is used or not
|
||||
* @ucSTAId: Station ID reported back from HAL (through SAP).
|
||||
* Broadcast uses station ID zero by default.
|
||||
* @staType: Type of station i.e. p2p client or infrastructure station
|
||||
* @macAddrSTA: MAC address of the station
|
||||
* @tlSTAState: Current Station state so HDD knows how to deal with packet
|
||||
* queue. Most recent states used to change TLSHIM STA state.
|
||||
* @isQosEnabled: Track QoS status of station
|
||||
* @isDeauthInProgress: The station entry for which Deauth is in progress
|
||||
* @nss: Number of spatial streams supported
|
||||
* @rate_flags: Rate Flags for this connection
|
||||
* @ecsa_capable: Extended CSA capabilities
|
||||
* @max_phy_rate: Calcuated maximum phy rate based on mode, nss, mcs etc.
|
||||
* @tx_packets: Packets send to current station
|
||||
* @tx_bytes: Bytes send to current station
|
||||
* @rx_packets: Packets received from current station
|
||||
* @rx_bytes: Bytes received from current station
|
||||
* @last_tx_rx_ts: Last tx/rx timestamp with current station
|
||||
* @assoc_ts: Current station association timestamp
|
||||
* @tx_rate: Tx rate with current station reported from F/W
|
||||
* @rx_rate: Rx rate with current station reported from F/W
|
||||
* @ampdu: Ampdu enable or not of the station
|
||||
* @sgi_enable: Short GI enable or not of the station
|
||||
* @tx_stbc: Tx Space-time block coding enable/disable
|
||||
* @rx_stbc: Rx Space-time block coding enable/disable
|
||||
* @ch_width: Channel Width of the connection
|
||||
* @mode: Mode of the connection
|
||||
* @max_supp_idx: Max supported rate index of the station
|
||||
* @max_ext_idx: Max extended supported rate index of the station
|
||||
* @max_mcs_idx: Max supported mcs index of the station
|
||||
* @rx_mcs_map: VHT Rx mcs map
|
||||
* @tx_mcs_map: VHT Tx mcs map
|
||||
*/
|
||||
typedef struct {
|
||||
/** The station entry is used or not */
|
||||
bool isUsed;
|
||||
|
||||
/* Station ID reported back from HAL (through SAP).
|
||||
* Broadcast uses station ID zero by default
|
||||
*/
|
||||
uint8_t ucSTAId;
|
||||
|
||||
/* type of station i.e. p2p client or infrastructure station */
|
||||
eStationType staType;
|
||||
|
||||
/** MAC address of the station */
|
||||
struct qdf_mac_addr macAddrSTA;
|
||||
|
||||
/** Current Station state so HDD knows how to deal with packet
|
||||
* queue. Most recent states used to change TLSHIM STA state
|
||||
*/
|
||||
enum ol_txrx_peer_state tlSTAState;
|
||||
|
||||
/** Track QoS status of station */
|
||||
bool isQosEnabled;
|
||||
|
||||
/** The station entry for which Deauth is in progress */
|
||||
bool isDeauthInProgress;
|
||||
|
||||
/** Number of spatial streams supported */
|
||||
uint8_t nss;
|
||||
|
||||
/** Rate Flags for this connection */
|
||||
uint32_t rate_flags;
|
||||
/** Extended CSA */
|
||||
uint8_t ecsa_capable;
|
||||
uint32_t max_phy_rate;
|
||||
uint32_t tx_packets;
|
||||
uint64_t tx_bytes;
|
||||
uint32_t rx_packets;
|
||||
uint64_t rx_bytes;
|
||||
qdf_time_t last_tx_rx_ts;
|
||||
qdf_time_t assoc_ts;
|
||||
uint32_t tx_rate;
|
||||
uint32_t rx_rate;
|
||||
bool ampdu;
|
||||
bool sgi_enable;
|
||||
bool tx_stbc;
|
||||
bool rx_stbc;
|
||||
uint8_t ch_width;
|
||||
uint8_t mode;
|
||||
uint8_t max_supp_idx;
|
||||
uint8_t max_ext_idx;
|
||||
uint8_t max_mcs_idx;
|
||||
uint8_t rx_mcs_map;
|
||||
uint8_t tx_mcs_map;
|
||||
} hdd_station_info_t;
|
||||
|
||||
struct hdd_ap_ctx {
|
||||
|
|
@ -866,6 +942,9 @@ struct hdd_ap_ctx {
|
|||
bool vendor_acs_timer_initialized;
|
||||
|
||||
enum bss_stop_reason bss_stop_reason;
|
||||
|
||||
/* Fw txrx stats info */
|
||||
struct hdd_fw_txrx_stats txrx_stats;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -476,4 +476,32 @@ int hdd_check_standard_wext_control(struct hdd_context *hdd_ctx,
|
|||
int hdd_check_private_wext_control(struct hdd_context *hdd_ctx,
|
||||
struct iw_request_info *info);
|
||||
|
||||
/**
|
||||
* wlan_hdd_get_peer_rssi() - get station's rssi
|
||||
* @adapter: hostapd interface
|
||||
* @macaddress: peer sta mac address or ff:ff:ff:ff:ff:ff to query all peer
|
||||
* @peer_sta_info: output pointer which will fill by peer sta info
|
||||
*
|
||||
* This function will call sme_get_peer_info to get rssi
|
||||
*
|
||||
* Return: 0 on success, otherwise error value
|
||||
*/
|
||||
int wlan_hdd_get_peer_rssi(hdd_adapter_t *adapter,
|
||||
struct qdf_mac_addr *macaddress,
|
||||
struct sir_peer_sta_info *peer_sta_info);
|
||||
|
||||
/**
|
||||
* wlan_hdd_get_peer_info() - get peer info
|
||||
* @adapter: hostapd interface
|
||||
* @macaddress: request peer mac address
|
||||
* @peer_info_ext: one peer extended info retrieved
|
||||
*
|
||||
* This function will call sme_get_peer_info_ext to get peer info
|
||||
*
|
||||
* Return: 0 on success, otherwise error value
|
||||
*/
|
||||
int wlan_hdd_get_peer_info(hdd_adapter_t *adapter,
|
||||
struct qdf_mac_addr macaddress,
|
||||
struct sir_peer_info_ext *peer_info_ext);
|
||||
|
||||
#endif /* __WEXT_IW_H__ */
|
||||
|
|
|
|||
|
|
@ -2178,6 +2178,13 @@ struct reg_table_entry g_registry_table[] = {
|
|||
CFG_MAX_HT_MCS_FOR_TX_DATA_MIN,
|
||||
CFG_MAX_HT_MCS_FOR_TX_DATA_MAX),
|
||||
|
||||
REG_VARIABLE(CFG_SAP_GET_PEER_INFO, WLAN_PARAM_Integer,
|
||||
struct hdd_config, sap_get_peer_info,
|
||||
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
|
||||
CFG_SAP_GET_PEER_INFO_DEFAULT,
|
||||
CFG_SAP_GET_PEER_INFO_MIN,
|
||||
CFG_SAP_GET_PEER_INFO_MAX),
|
||||
|
||||
REG_VARIABLE(CFG_DISABLE_ABG_RATE_FOR_TX_DATA, WLAN_PARAM_Integer,
|
||||
struct hdd_config, disable_abg_rate_txdata,
|
||||
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
|
||||
|
|
|
|||
|
|
@ -112,44 +112,6 @@
|
|||
#include "wlan_utility.h"
|
||||
#include "wlan_reg_ucfg_api.h"
|
||||
|
||||
/* define short names for get station info attributes */
|
||||
#ifndef LINK_INFO_STANDARD_NL80211_ATTR
|
||||
#define LINK_INFO_STANDARD_NL80211_ATTR \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR
|
||||
#endif
|
||||
#ifndef AP_INFO_STANDARD_NL80211_ATTR
|
||||
#define AP_INFO_STANDARD_NL80211_ATTR \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_STANDARD_NL80211_ATTR
|
||||
#endif
|
||||
#ifndef INFO_ROAM_COUNT
|
||||
#define INFO_ROAM_COUNT \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT
|
||||
#endif
|
||||
#ifndef INFO_AKM
|
||||
#define INFO_AKM \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM
|
||||
#endif
|
||||
#ifndef WLAN802_11_MODE
|
||||
#define WLAN802_11_MODE \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE
|
||||
#endif
|
||||
#ifndef AP_INFO_HS20_INDICATION
|
||||
#define AP_INFO_HS20_INDICATION \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION
|
||||
#endif
|
||||
#ifndef HT_OPERATION
|
||||
#define HT_OPERATION \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION
|
||||
#endif
|
||||
#ifndef VHT_OPERATION
|
||||
#define VHT_OPERATION \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION
|
||||
#endif
|
||||
#ifndef INFO_ASSOC_FAIL_REASON
|
||||
#define INFO_ASSOC_FAIL_REASON \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_FAIL_REASON
|
||||
#endif
|
||||
|
||||
#define g_mode_rates_size (12)
|
||||
#define a_mode_rates_size (8)
|
||||
#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
|
||||
|
|
@ -4149,13 +4111,68 @@ static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
|
|||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
|
||||
#define STATION_ASSOC_FAIL_REASON \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
|
||||
#define STATION_REMOTE \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE
|
||||
#define STATION_MAX \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
|
||||
|
||||
/* define short names for get station info attributes */
|
||||
#define LINK_INFO_STANDARD_NL80211_ATTR \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR
|
||||
#define AP_INFO_STANDARD_NL80211_ATTR \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_STANDARD_NL80211_ATTR
|
||||
#define INFO_ROAM_COUNT \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT
|
||||
#define INFO_AKM \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM
|
||||
#define WLAN802_11_MODE \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE
|
||||
#define AP_INFO_HS20_INDICATION \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION
|
||||
#define HT_OPERATION \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION
|
||||
#define VHT_OPERATION \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION
|
||||
#define INFO_ASSOC_FAIL_REASON \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_FAIL_REASON
|
||||
#define REMOTE_MAX_PHY_RATE \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_MAX_PHY_RATE
|
||||
#define REMOTE_TX_PACKETS \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_PACKETS
|
||||
#define REMOTE_TX_BYTES \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_BYTES
|
||||
#define REMOTE_RX_PACKETS \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_PACKETS
|
||||
#define REMOTE_RX_BYTES \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BYTES
|
||||
#define REMOTE_LAST_TX_RATE \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_TX_RATE
|
||||
#define REMOTE_LAST_RX_RATE \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE
|
||||
#define REMOTE_WMM \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_WMM
|
||||
#define REMOTE_SUPPORTED_MODE \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SUPPORTED_MODE
|
||||
#define REMOTE_AMPDU \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_AMPDU
|
||||
#define REMOTE_TX_STBC \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_STBC
|
||||
#define REMOTE_RX_STBC \
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_STBC
|
||||
#define REMOTE_CH_WIDTH\
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH
|
||||
#define REMOTE_SGI_ENABLE\
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SGI_ENABLE
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
|
||||
#define REMOTE_PAD\
|
||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_PAD
|
||||
#endif
|
||||
|
||||
static const struct nla_policy
|
||||
hdd_get_station_policy[STATION_MAX + 1] = {
|
||||
[STATION_INFO] = {.type = NLA_FLAG},
|
||||
[STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
|
||||
[STATION_REMOTE] = {.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -4583,6 +4600,169 @@ fail:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_get_stainfo() - get stainfo for the specified peer
|
||||
* @adapter: hostapd interface
|
||||
* @mac_addr: mac address of requested peer
|
||||
*
|
||||
* This function find the stainfo for the peer with mac_addr
|
||||
*
|
||||
* Return: stainfo if found, NULL if not found
|
||||
*/
|
||||
static hdd_station_info_t *hdd_get_stainfo(hdd_adapter_t *adapter,
|
||||
struct qdf_mac_addr mac_addr)
|
||||
{
|
||||
hdd_station_info_t *stainfo = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
|
||||
if (!qdf_mem_cmp(&adapter->aStaInfo[i].macAddrSTA,
|
||||
&mac_addr,
|
||||
QDF_MAC_ADDR_SIZE))
|
||||
stainfo = &adapter->aStaInfo[i];
|
||||
}
|
||||
|
||||
return stainfo;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
|
||||
static inline int32_t remote_station_put_u64(struct sk_buff *skb,
|
||||
int32_t attrtype,
|
||||
uint64_t value)
|
||||
{
|
||||
return nla_put_u64_64bit(skb, attrtype, value, REMOTE_PAD);
|
||||
}
|
||||
#else
|
||||
static inline int32_t remote_station_put_u64(struct sk_buff *skb,
|
||||
int32_t attrtype,
|
||||
uint64_t value)
|
||||
{
|
||||
return nla_put_u64(skb, attrtype, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hdd_get_station_remote() - get remote peer's info
|
||||
* @hdd_ctx: hdd context
|
||||
* @adapter: hostapd interface
|
||||
* @mac_addr: mac address of requested peer
|
||||
*
|
||||
* This function collect and indicate the remote peer's info
|
||||
*
|
||||
* Return: 0 on success, otherwise error value
|
||||
*/
|
||||
static int hdd_get_station_remote(hdd_context_t *hdd_ctx,
|
||||
hdd_adapter_t *adapter,
|
||||
struct qdf_mac_addr mac_addr)
|
||||
{
|
||||
hdd_station_info_t *stainfo = hdd_get_stainfo(adapter, mac_addr);
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sir_peer_info_ext peer_info;
|
||||
uint32_t nl_buf_len;
|
||||
bool txrx_rate = true;
|
||||
|
||||
if (!stainfo) {
|
||||
hdd_err("peer " MAC_ADDRESS_STR " not found",
|
||||
MAC_ADDR_ARRAY(mac_addr.bytes));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nl_buf_len = NLMSG_HDRLEN;
|
||||
nl_buf_len += (sizeof(stainfo->max_phy_rate) + NLA_HDRLEN) +
|
||||
(sizeof(stainfo->tx_packets) + NLA_HDRLEN) +
|
||||
(sizeof(stainfo->tx_bytes) + NLA_HDRLEN) +
|
||||
(sizeof(stainfo->rx_packets) + NLA_HDRLEN) +
|
||||
(sizeof(stainfo->rx_bytes) + NLA_HDRLEN) +
|
||||
(sizeof(stainfo->isQosEnabled) + NLA_HDRLEN) +
|
||||
(sizeof(stainfo->mode) + NLA_HDRLEN);
|
||||
|
||||
if (!hdd_ctx->config->sap_get_peer_info ||
|
||||
wlan_hdd_get_peer_info(adapter, mac_addr, &peer_info)) {
|
||||
hdd_err("fail to get tx/rx rate");
|
||||
txrx_rate = false;
|
||||
} else {
|
||||
stainfo->tx_rate = peer_info.tx_rate;
|
||||
stainfo->rx_rate = peer_info.rx_rate;
|
||||
nl_buf_len += (sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
|
||||
(sizeof(stainfo->rx_rate) + NLA_HDRLEN);
|
||||
}
|
||||
|
||||
/* below info is only valid for HT/VHT mode */
|
||||
if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY)
|
||||
nl_buf_len += (sizeof(stainfo->ampdu) + NLA_HDRLEN) +
|
||||
(sizeof(stainfo->tx_stbc) + NLA_HDRLEN) +
|
||||
(sizeof(stainfo->rx_stbc) + NLA_HDRLEN) +
|
||||
(sizeof(stainfo->ch_width) + NLA_HDRLEN) +
|
||||
(sizeof(stainfo->sgi_enable) + NLA_HDRLEN);
|
||||
|
||||
hdd_info("buflen %d hdrlen %d", nl_buf_len, NLMSG_HDRLEN);
|
||||
|
||||
skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
|
||||
nl_buf_len);
|
||||
if (!skb) {
|
||||
hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hdd_info("stainfo");
|
||||
hdd_info("maxrate %x tx_pkts %x tx_bytes %llx",
|
||||
stainfo->max_phy_rate, stainfo->tx_packets,
|
||||
stainfo->tx_bytes);
|
||||
hdd_info("rx_pkts %x rx_bytes %llx mode %x",
|
||||
stainfo->rx_packets, stainfo->rx_bytes,
|
||||
stainfo->mode);
|
||||
if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
|
||||
hdd_info("ampdu %d tx_stbc %d rx_stbc %d",
|
||||
stainfo->ampdu, stainfo->tx_stbc,
|
||||
stainfo->rx_stbc);
|
||||
hdd_info("wmm %d chwidth %d sgi %d",
|
||||
stainfo->isQosEnabled,
|
||||
stainfo->ch_width,
|
||||
stainfo->sgi_enable);
|
||||
}
|
||||
|
||||
if (nla_put_u32(skb, REMOTE_MAX_PHY_RATE, stainfo->max_phy_rate) ||
|
||||
nla_put_u32(skb, REMOTE_TX_PACKETS, stainfo->tx_packets) ||
|
||||
remote_station_put_u64(skb, REMOTE_TX_BYTES, stainfo->tx_bytes) ||
|
||||
nla_put_u32(skb, REMOTE_RX_PACKETS, stainfo->rx_packets) ||
|
||||
remote_station_put_u64(skb, REMOTE_RX_BYTES, stainfo->rx_bytes) ||
|
||||
nla_put_u8(skb, REMOTE_WMM, stainfo->isQosEnabled) ||
|
||||
nla_put_u8(skb, REMOTE_SUPPORTED_MODE, stainfo->mode)) {
|
||||
hdd_err("put fail");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (txrx_rate) {
|
||||
if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate) ||
|
||||
nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
|
||||
hdd_err("put fail");
|
||||
goto fail;
|
||||
} else {
|
||||
hdd_info("tx_rate %x rx_rate %x",
|
||||
stainfo->tx_rate, stainfo->rx_rate);
|
||||
}
|
||||
}
|
||||
|
||||
if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
|
||||
if (nla_put_u8(skb, REMOTE_AMPDU, stainfo->ampdu) ||
|
||||
nla_put_u8(skb, REMOTE_TX_STBC, stainfo->tx_stbc) ||
|
||||
nla_put_u8(skb, REMOTE_RX_STBC, stainfo->rx_stbc) ||
|
||||
nla_put_u8(skb, REMOTE_CH_WIDTH, stainfo->ch_width) ||
|
||||
nla_put_u8(skb, REMOTE_SGI_ENABLE, stainfo->sgi_enable)) {
|
||||
hdd_err("put fail");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return cfg80211_vendor_cmd_reply(skb);
|
||||
|
||||
fail:
|
||||
if (skb)
|
||||
kfree_skb(skb);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
|
||||
* @wiphy: corestack handler
|
||||
|
|
@ -4631,6 +4811,23 @@ __hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
|
|||
status = hdd_get_station_info(hdd_ctx, adapter);
|
||||
} else if (tb[STATION_ASSOC_FAIL_REASON]) {
|
||||
status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
|
||||
} else if (tb[STATION_REMOTE]) {
|
||||
struct qdf_mac_addr mac_addr;
|
||||
|
||||
if (adapter->device_mode != QDF_SAP_MODE &&
|
||||
adapter->device_mode != QDF_P2P_GO_MODE) {
|
||||
hdd_err("invalid device_mode:%d", adapter->device_mode);
|
||||
status = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
nla_memcpy(mac_addr.bytes, tb[STATION_REMOTE],
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
|
||||
hdd_debug("STATION_REMOTE " MAC_ADDRESS_STR,
|
||||
MAC_ADDR_ARRAY(mac_addr.bytes));
|
||||
|
||||
status = hdd_get_station_remote(hdd_ctx, adapter, mac_addr);
|
||||
} else {
|
||||
hdd_err("get station info cmd type failed");
|
||||
status = -EINVAL;
|
||||
|
|
@ -4675,7 +4872,34 @@ hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
|
|||
#undef STATION_INVALID
|
||||
#undef STATION_INFO
|
||||
#undef STATION_ASSOC_FAIL_REASON
|
||||
#undef STATION_REMOTE
|
||||
#undef STATION_MAX
|
||||
#undef LINK_INFO_STANDARD_NL80211_ATTR
|
||||
#undef AP_INFO_STANDARD_NL80211_ATTR
|
||||
#undef INFO_ROAM_COUNT
|
||||
#undef INFO_AKM
|
||||
#undef WLAN802_11_MODE
|
||||
#undef AP_INFO_HS20_INDICATION
|
||||
#undef HT_OPERATION
|
||||
#undef VHT_OPERATION
|
||||
#undef INFO_ASSOC_FAIL_REASON
|
||||
#undef REMOTE_MAX_PHY_RATE
|
||||
#undef REMOTE_TX_PACKETS
|
||||
#undef REMOTE_TX_BYTES
|
||||
#undef REMOTE_RX_PACKETS
|
||||
#undef REMOTE_RX_BYTES
|
||||
#undef REMOTE_LAST_TX_RATE
|
||||
#undef REMOTE_LAST_RX_RATE
|
||||
#undef REMOTE_WMM
|
||||
#undef REMOTE_SUPPORTED_MODE
|
||||
#undef REMOTE_AMPDU
|
||||
#undef REMOTE_TX_STBC
|
||||
#undef REMOTE_RX_STBC
|
||||
#undef REMOTE_CH_WIDTH
|
||||
#undef REMOTE_SGI_ENABLE
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
|
||||
#undef REMOTE_PAD
|
||||
#endif
|
||||
|
||||
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -105,6 +105,91 @@
|
|||
#define SAP_24GHZ_CH_COUNT (14)
|
||||
#define ACS_SCAN_EXPIRY_TIMEOUT_S 4
|
||||
|
||||
/*
|
||||
* 11B, 11G Rate table include Basic rate and Extended rate
|
||||
* The IDX field is the rate index
|
||||
* The HI field is the rate when RSSI is strong or being ignored
|
||||
* (in this case we report actual rate)
|
||||
* The MID field is the rate when RSSI is moderate
|
||||
* (in this case we cap 11b rates at 5.5 and 11g rates at 24)
|
||||
* The LO field is the rate when RSSI is low
|
||||
* (in this case we don't report rates, actual current rate used)
|
||||
*/
|
||||
static const struct index_data_rate_type supported_data_rate[] = {
|
||||
/* IDX HI HM LM LO (RSSI-based index */
|
||||
{2, { 10, 10, 10, 0} },
|
||||
{4, { 20, 20, 10, 0} },
|
||||
{11, { 55, 20, 10, 0} },
|
||||
{12, { 60, 55, 20, 0} },
|
||||
{18, { 90, 55, 20, 0} },
|
||||
{22, {110, 55, 20, 0} },
|
||||
{24, {120, 90, 60, 0} },
|
||||
{36, {180, 120, 60, 0} },
|
||||
{44, {220, 180, 60, 0} },
|
||||
{48, {240, 180, 90, 0} },
|
||||
{66, {330, 180, 90, 0} },
|
||||
{72, {360, 240, 90, 0} },
|
||||
{96, {480, 240, 120, 0} },
|
||||
{108, {540, 240, 120, 0} }
|
||||
};
|
||||
|
||||
/* MCS Based rate table */
|
||||
/* HT MCS parameters with Nss = 1 */
|
||||
static const struct index_data_rate_type supported_mcs_rate_nss1[] = {
|
||||
/* MCS L20 L40 S20 S40 */
|
||||
{0, { 65, 135, 72, 150} },
|
||||
{1, { 130, 270, 144, 300} },
|
||||
{2, { 195, 405, 217, 450} },
|
||||
{3, { 260, 540, 289, 600} },
|
||||
{4, { 390, 810, 433, 900} },
|
||||
{5, { 520, 1080, 578, 1200} },
|
||||
{6, { 585, 1215, 650, 1350} },
|
||||
{7, { 650, 1350, 722, 1500} }
|
||||
};
|
||||
|
||||
/* HT MCS parameters with Nss = 2 */
|
||||
static const struct index_data_rate_type supported_mcs_rate_nss2[] = {
|
||||
/* MCS L20 L40 S20 S40 */
|
||||
{0, {130, 270, 144, 300} },
|
||||
{1, {260, 540, 289, 600} },
|
||||
{2, {390, 810, 433, 900} },
|
||||
{3, {520, 1080, 578, 1200} },
|
||||
{4, {780, 1620, 867, 1800} },
|
||||
{5, {1040, 2160, 1156, 2400} },
|
||||
{6, {1170, 2430, 1300, 2700} },
|
||||
{7, {1300, 2700, 1444, 3000} }
|
||||
};
|
||||
|
||||
/* MCS Based VHT rate table */
|
||||
/* MCS parameters with Nss = 1*/
|
||||
static const struct index_vht_data_rate_type supported_vht_mcs_rate_nss1[] = {
|
||||
/* MCS L80 S80 L40 S40 L20 S40*/
|
||||
{0, {293, 325}, {135, 150}, {65, 72} },
|
||||
{1, {585, 650}, {270, 300}, {130, 144} },
|
||||
{2, {878, 975}, {405, 450}, {195, 217} },
|
||||
{3, {1170, 1300}, {540, 600}, {260, 289} },
|
||||
{4, {1755, 1950}, {810, 900}, {390, 433} },
|
||||
{5, {2340, 2600}, {1080, 1200}, {520, 578} },
|
||||
{6, {2633, 2925}, {1215, 1350}, {585, 650} },
|
||||
{7, {2925, 3250}, {1350, 1500}, {650, 722} },
|
||||
{8, {3510, 3900}, {1620, 1800}, {780, 867} },
|
||||
{9, {3900, 4333}, {1800, 2000}, {780, 867} }
|
||||
};
|
||||
|
||||
/*MCS parameters with Nss = 2*/
|
||||
static const struct index_vht_data_rate_type supported_vht_mcs_rate_nss2[] = {
|
||||
/* MCS L80 S80 L40 S40 L20 S40*/
|
||||
{0, {585, 650}, {270, 300}, {130, 144} },
|
||||
{1, {1170, 1300}, {540, 600}, {260, 289} },
|
||||
{2, {1755, 1950}, {810, 900}, {390, 433} },
|
||||
{3, {2340, 2600}, {1080, 1200}, {520, 578} },
|
||||
{4, {3510, 3900}, {1620, 1800}, {780, 867} },
|
||||
{5, {4680, 5200}, {2160, 2400}, {1040, 1156} },
|
||||
{6, {5265, 5850}, {2430, 2700}, {1170, 1300} },
|
||||
{7, {5850, 6500}, {2700, 3000}, {1300, 1444} },
|
||||
{8, {7020, 7800}, {3240, 3600}, {1560, 1733} },
|
||||
{9, {7800, 8667}, {3600, 4000}, {1560, 1733} }
|
||||
};
|
||||
|
||||
/* Function definitions */
|
||||
|
||||
|
|
@ -1044,6 +1129,205 @@ static QDF_STATUS hdd_handle_acs_scan_event(tpSap_Event sap_event,
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* get_max_rate_vht() - calculate max rate for VHT mode
|
||||
* @nss: num of streams
|
||||
* @ch_width: channel width
|
||||
* @sgi: short gi
|
||||
* @vht_mcs_map: vht mcs map
|
||||
*
|
||||
* This function calculate max rate for VHT mode
|
||||
*
|
||||
* Return: max rate
|
||||
*/
|
||||
static int get_max_rate_vht(int nss, int ch_width, int sgi, int vht_mcs_map)
|
||||
{
|
||||
const struct index_vht_data_rate_type *supported_vht_mcs_rate;
|
||||
enum data_rate_11ac_max_mcs vht_max_mcs;
|
||||
int maxrate = 0;
|
||||
int maxidx;
|
||||
|
||||
if (nss == 1) {
|
||||
supported_vht_mcs_rate = supported_vht_mcs_rate_nss1;
|
||||
} else if (nss == 2) {
|
||||
supported_vht_mcs_rate = supported_vht_mcs_rate_nss2;
|
||||
} else {
|
||||
/* Not Supported */
|
||||
hdd_err("nss %d not supported", nss);
|
||||
return maxrate;
|
||||
}
|
||||
|
||||
vht_max_mcs =
|
||||
(enum data_rate_11ac_max_mcs)
|
||||
(vht_mcs_map & DATA_RATE_11AC_MCS_MASK);
|
||||
|
||||
if (vht_max_mcs == DATA_RATE_11AC_MAX_MCS_7) {
|
||||
maxidx = 7;
|
||||
} else if (vht_max_mcs == DATA_RATE_11AC_MAX_MCS_8) {
|
||||
maxidx = 8;
|
||||
} else if (vht_max_mcs == DATA_RATE_11AC_MAX_MCS_9) {
|
||||
if (ch_width == eHT_CHANNEL_WIDTH_20MHZ)
|
||||
/* MCS9 is not valid for VHT20 when nss=1,2 */
|
||||
maxidx = 8;
|
||||
else
|
||||
maxidx = 9;
|
||||
} else {
|
||||
hdd_err("vht mcs map %x not supported",
|
||||
vht_mcs_map & DATA_RATE_11AC_MCS_MASK);
|
||||
return maxrate;
|
||||
}
|
||||
|
||||
if (ch_width == eHT_CHANNEL_WIDTH_20MHZ) {
|
||||
maxrate =
|
||||
supported_vht_mcs_rate[maxidx].supported_VHT20_rate[sgi];
|
||||
} else if (ch_width == eHT_CHANNEL_WIDTH_40MHZ) {
|
||||
maxrate =
|
||||
supported_vht_mcs_rate[maxidx].supported_VHT40_rate[sgi];
|
||||
} else if (ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
|
||||
maxrate =
|
||||
supported_vht_mcs_rate[maxidx].supported_VHT80_rate[sgi];
|
||||
} else {
|
||||
hdd_err("ch_width %d not supported", ch_width);
|
||||
return maxrate;
|
||||
}
|
||||
|
||||
return maxrate;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate_max_phy_rate() - calcuate maximum phy rate (100kbps)
|
||||
* @mode: phymode: Legacy, 11a/b/g, HT, VHT
|
||||
* @nss: num of stream (maximum num is 2)
|
||||
* @ch_width: channel width
|
||||
* @sgi: short gi enabled or not
|
||||
* @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: maximum phy rate in 100kbps
|
||||
*/
|
||||
static int calcuate_max_phy_rate(int mode, int nss, int ch_width,
|
||||
int sgi, int supp_idx, int ext_idx,
|
||||
int ht_mcs_idx, int vht_mcs_map)
|
||||
{
|
||||
const struct index_data_rate_type *supported_mcs_rate;
|
||||
int maxidx = 12; /*default 6M mode*/
|
||||
int maxrate = 0, tmprate;
|
||||
int i;
|
||||
|
||||
/* 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;
|
||||
|
||||
for (i = 0; i < QDF_ARRAY_SIZE(supported_data_rate); i++) {
|
||||
if (supported_data_rate[i].beacon_rate_index == maxidx)
|
||||
maxrate = supported_data_rate[i].supported_rate[0];
|
||||
}
|
||||
|
||||
if (mode == SIR_SME_PHY_MODE_HT) {
|
||||
/* check for HT Mode */
|
||||
maxidx = ht_mcs_idx;
|
||||
if (nss == 1) {
|
||||
supported_mcs_rate = supported_mcs_rate_nss1;
|
||||
} else if (nss == 2) {
|
||||
supported_mcs_rate = supported_mcs_rate_nss2;
|
||||
} else {
|
||||
/* Not Supported */
|
||||
hdd_err("nss %d not supported", nss);
|
||||
return maxrate;
|
||||
}
|
||||
|
||||
if (ch_width == eHT_CHANNEL_WIDTH_20MHZ) {
|
||||
tmprate = sgi ?
|
||||
supported_mcs_rate[maxidx].supported_rate[2] :
|
||||
supported_mcs_rate[maxidx].supported_rate[0];
|
||||
} else if (ch_width == eHT_CHANNEL_WIDTH_40MHZ) {
|
||||
tmprate = sgi ?
|
||||
supported_mcs_rate[maxidx].supported_rate[3] :
|
||||
supported_mcs_rate[maxidx].supported_rate[1];
|
||||
} else {
|
||||
hdd_err("invalid mode %d ch_width %d",
|
||||
mode, ch_width);
|
||||
return maxrate;
|
||||
}
|
||||
|
||||
if (maxrate < tmprate)
|
||||
maxrate = tmprate;
|
||||
}
|
||||
|
||||
if (mode == SIR_SME_PHY_MODE_VHT) {
|
||||
/* check for VHT Mode */
|
||||
tmprate = get_max_rate_vht(nss, ch_width, sgi, vht_mcs_map);
|
||||
if (maxrate < tmprate)
|
||||
maxrate = tmprate;
|
||||
}
|
||||
|
||||
return maxrate;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_fill_station_info() - fill stainfo once connected
|
||||
* @stainfo: peer stainfo associate to SAP
|
||||
* @event: associate/reassociate event received
|
||||
*
|
||||
* The function is to update rate stats to stainfo
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void hdd_fill_station_info(hdd_station_info_t *stainfo,
|
||||
tSap_StationAssocReassocCompleteEvent *event)
|
||||
{
|
||||
stainfo->staType = event->staType;
|
||||
stainfo->nss = event->chan_info.nss;
|
||||
stainfo->rate_flags = event->chan_info.rate_flags;
|
||||
stainfo->ampdu = event->ampdu;
|
||||
stainfo->sgi_enable = event->sgi_enable;
|
||||
stainfo->tx_stbc = event->tx_stbc;
|
||||
stainfo->rx_stbc = event->rx_stbc;
|
||||
stainfo->ch_width = event->ch_width;
|
||||
stainfo->mode = event->mode;
|
||||
stainfo->max_supp_idx = event->max_supp_idx;
|
||||
stainfo->max_ext_idx = event->max_ext_idx;
|
||||
stainfo->max_mcs_idx = event->max_mcs_idx;
|
||||
stainfo->rx_mcs_map = event->rx_mcs_map;
|
||||
stainfo->tx_mcs_map = event->tx_mcs_map;
|
||||
stainfo->assoc_ts = qdf_system_ticks();
|
||||
stainfo->max_phy_rate =
|
||||
calcuate_max_phy_rate(stainfo->mode,
|
||||
stainfo->nss,
|
||||
stainfo->ch_width,
|
||||
stainfo->sgi_enable,
|
||||
stainfo->max_supp_idx,
|
||||
stainfo->max_ext_idx,
|
||||
stainfo->max_mcs_idx,
|
||||
stainfo->rx_mcs_map);
|
||||
/* expect max_phy_rate report in kbps */
|
||||
stainfo->max_phy_rate *= 100;
|
||||
hdd_debug("cap %d %d %d %d %d %d %d %d %d %x %d",
|
||||
stainfo->ampdu,
|
||||
stainfo->sgi_enable,
|
||||
stainfo->tx_stbc,
|
||||
stainfo->rx_stbc,
|
||||
stainfo->isQosEnabled,
|
||||
stainfo->ch_width,
|
||||
stainfo->mode,
|
||||
event->wmmEnabled,
|
||||
event->chan_info.nss,
|
||||
event->chan_info.rate_flags,
|
||||
stainfo->max_phy_rate);
|
||||
hdd_debug("rate info %d %d %d %d %d",
|
||||
stainfo->max_supp_idx,
|
||||
stainfo->max_ext_idx,
|
||||
stainfo->max_mcs_idx,
|
||||
stainfo->rx_mcs_map,
|
||||
stainfo->tx_mcs_map);
|
||||
}
|
||||
|
||||
QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
|
||||
void *usrDataForCallback)
|
||||
{
|
||||
|
|
@ -1075,6 +1359,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
|
|||
hdd_adapter_t *con_sap_adapter;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
struct hdd_chan_change_params chan_change;
|
||||
tSap_StationAssocReassocCompleteEvent *event;
|
||||
int ret = 0;
|
||||
struct ch_params sap_ch_param = {0};
|
||||
eCsrPhyMode phy_mode;
|
||||
|
|
@ -1533,10 +1818,10 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
|
|||
|
||||
case eSAP_STA_ASSOC_EVENT:
|
||||
case eSAP_STA_REASSOC_EVENT:
|
||||
event = &pSapEvent->sapevt.sapStationAssocReassocCompleteEvent;
|
||||
wrqu.addr.sa_family = ARPHRD_ETHER;
|
||||
memcpy(wrqu.addr.sa_data,
|
||||
&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.
|
||||
staMac, QDF_MAC_ADDR_SIZE);
|
||||
&event->staMac, QDF_MAC_ADDR_SIZE);
|
||||
hdd_notice(" associated " MAC_ADDRESS_STR,
|
||||
MAC_ADDR_ARRAY(wrqu.addr.sa_data));
|
||||
we_event = IWEVREGISTERED;
|
||||
|
|
@ -1558,14 +1843,10 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
|
|||
pHostapdAdapter,
|
||||
true,
|
||||
pHddApCtx->uPrivacy,
|
||||
pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
staId, 0, 0,
|
||||
event->staId, 0, 0,
|
||||
(struct qdf_mac_addr *)
|
||||
wrqu.addr.sa_data,
|
||||
pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
wmmEnabled);
|
||||
event->wmmEnabled);
|
||||
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
|
||||
hdd_err("Failed to register STA %d "
|
||||
MAC_ADDRESS_STR "", qdf_status,
|
||||
|
|
@ -1575,47 +1856,29 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
|
|||
pHostapdAdapter,
|
||||
false,
|
||||
pHddApCtx->uPrivacy,
|
||||
pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
staId, 0, 0,
|
||||
event->staId, 0, 0,
|
||||
(struct qdf_mac_addr *)
|
||||
wrqu.addr.sa_data,
|
||||
pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
wmmEnabled);
|
||||
event->wmmEnabled);
|
||||
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
|
||||
hdd_err("Failed to register STA %d "
|
||||
MAC_ADDRESS_STR "", qdf_status,
|
||||
MAC_ADDR_ARRAY(wrqu.addr.sa_data));
|
||||
}
|
||||
|
||||
staId =
|
||||
pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staId;
|
||||
staId = event->staId;
|
||||
if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
|
||||
pHostapdAdapter->aStaInfo[staId].nss =
|
||||
pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
chan_info.nss;
|
||||
pHostapdAdapter->aStaInfo[staId].rate_flags =
|
||||
pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
chan_info.rate_flags;
|
||||
pHostapdAdapter->aStaInfo[staId].staType =
|
||||
pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
staType;
|
||||
hdd_fill_station_info(
|
||||
&pHostapdAdapter->aStaInfo[staId],
|
||||
event);
|
||||
hdd_debug("hdd_hostapd_sap_event_cb, StaID: %d, StaType: %d",
|
||||
staId, pHostapdAdapter->aStaInfo[staId].staType);
|
||||
}
|
||||
|
||||
if (hdd_ipa_is_enabled(pHddCtx)) {
|
||||
status = hdd_ipa_wlan_evt(pHostapdAdapter,
|
||||
pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
staId, HDD_IPA_CLIENT_CONNECT_EX,
|
||||
pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
staMac.bytes);
|
||||
event->staId, HDD_IPA_CLIENT_CONNECT_EX,
|
||||
event->staMac.bytes);
|
||||
if (status) {
|
||||
hdd_err("WLAN_CLIENT_CONNECT_EX event failed");
|
||||
goto stopbss;
|
||||
|
|
@ -1666,9 +1929,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
|
|||
HDD_SAP_WAKE_LOCK_DURATION);
|
||||
{
|
||||
struct station_info *sta_info;
|
||||
uint16_t iesLen =
|
||||
pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.iesLen;
|
||||
uint16_t iesLen = event->iesLen;
|
||||
|
||||
sta_info = qdf_mem_malloc(sizeof(*sta_info));
|
||||
if (!sta_info) {
|
||||
|
|
@ -1677,8 +1938,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
|
|||
}
|
||||
if (iesLen <= MAX_ASSOC_IND_IE_LEN) {
|
||||
sta_info->assoc_req_ies =
|
||||
(const u8 *)&pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.ies[0];
|
||||
(const u8 *)&event->ies[0];
|
||||
sta_info->assoc_req_ies_len = iesLen;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
|
||||
/*
|
||||
|
|
@ -1690,10 +1950,8 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
|
|||
sta_info->filled |= STATION_INFO_ASSOC_REQ_IES;
|
||||
#endif
|
||||
cfg80211_new_sta(dev,
|
||||
(const u8 *)&pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
staMac.bytes[0], sta_info,
|
||||
GFP_KERNEL);
|
||||
(const u8 *)&event->staMac.bytes[0],
|
||||
sta_info, GFP_KERNEL);
|
||||
} else {
|
||||
hdd_err("Assoc Ie length is too long");
|
||||
}
|
||||
|
|
@ -1707,31 +1965,24 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
|
|||
}
|
||||
if (pHostapdAdapter->device_mode == QDF_P2P_GO_MODE) {
|
||||
/* send peer status indication to oem app */
|
||||
hdd_send_peer_status_ind_to_app(&pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
staMac, ePeerConnected,
|
||||
pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
timingMeasCap,
|
||||
pHostapdAdapter->sessionId,
|
||||
&pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
chan_info,
|
||||
pHostapdAdapter->device_mode);
|
||||
hdd_send_peer_status_ind_to_app(
|
||||
&event->staMac,
|
||||
ePeerConnected,
|
||||
event->timingMeasCap,
|
||||
pHostapdAdapter->sessionId,
|
||||
&event->chan_info,
|
||||
pHostapdAdapter->device_mode);
|
||||
}
|
||||
|
||||
ret = hdd_objmgr_add_peer_object(
|
||||
pHostapdAdapter->hdd_vdev,
|
||||
pHostapdAdapter->device_mode,
|
||||
pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.
|
||||
staMac.bytes,
|
||||
(pHostapdAdapter->aStaInfo[staId].staType
|
||||
event->staMac.bytes,
|
||||
(pHostapdAdapter->aStaInfo[event->staId].staType
|
||||
== eSTA_TYPE_P2P_CLI));
|
||||
if (ret)
|
||||
hdd_err("Peer object "MAC_ADDRESS_STR" add fails!",
|
||||
MAC_ADDR_ARRAY(pSapEvent->sapevt.
|
||||
sapStationAssocReassocCompleteEvent.
|
||||
staMac.bytes));
|
||||
MAC_ADDR_ARRAY(event->staMac.bytes));
|
||||
|
||||
hdd_green_ap_add_sta(pHddCtx);
|
||||
break;
|
||||
|
|
@ -5397,6 +5648,120 @@ iw_get_softap_linkspeed(struct net_device *dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* __iw_get_peer_rssi() - get station's rssi
|
||||
* @dev: net device
|
||||
* @info: iwpriv request information
|
||||
* @wrqu: iwpriv command parameter
|
||||
* @extra
|
||||
*
|
||||
* This function will call wlan_hdd_get_peer_rssi
|
||||
* to get rssi
|
||||
*
|
||||
* Return: 0 on success, otherwise error value
|
||||
*/
|
||||
static int
|
||||
__iw_get_peer_rssi(struct net_device *dev, struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
hdd_adapter_t *adapter = netdev_priv(dev);
|
||||
hdd_context_t *hddctx;
|
||||
char macaddrarray[MAC_ADDRESS_STR_LEN];
|
||||
struct qdf_mac_addr macaddress = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
|
||||
int ret;
|
||||
char *rssi_info_output = extra;
|
||||
struct sir_peer_sta_info peer_sta_info;
|
||||
struct sir_peer_info *rssi_info;
|
||||
int i;
|
||||
int buf;
|
||||
int length;
|
||||
|
||||
ENTER();
|
||||
|
||||
hddctx = WLAN_HDD_GET_CTX(adapter);
|
||||
ret = wlan_hdd_validate_context(hddctx);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = hdd_check_private_wext_control(hddctx, info);
|
||||
if (0 != ret)
|
||||
return ret;
|
||||
|
||||
hdd_debug("wrqu->data.length= %d", wrqu->data.length);
|
||||
|
||||
if (wrqu->data.length >= MAC_ADDRESS_STR_LEN - 1) {
|
||||
if (copy_from_user(macaddrarray,
|
||||
wrqu->data.pointer,
|
||||
MAC_ADDRESS_STR_LEN - 1)) {
|
||||
hdd_info("failed to copy data from user buffer");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
macaddrarray[MAC_ADDRESS_STR_LEN - 1] = '\0';
|
||||
hdd_debug("%s", macaddrarray);
|
||||
|
||||
if (!mac_pton(macaddrarray, macaddress.bytes))
|
||||
hdd_err("String to Hex conversion Failed");
|
||||
}
|
||||
|
||||
ret = wlan_hdd_get_peer_rssi(adapter, &macaddress, &peer_sta_info);
|
||||
if (ret) {
|
||||
hdd_err("Unable to retrieve peer rssi: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* The iwpriv tool default print is before mac addr and rssi.
|
||||
* Add '\n' before first rssi item to align the first rssi item
|
||||
* with others
|
||||
*
|
||||
* wlan getRSSI:
|
||||
* [macaddr1] [rssi1]
|
||||
* [macaddr2] [rssi2]
|
||||
* [macaddr3] [rssi3]
|
||||
*/
|
||||
length = scnprintf(rssi_info_output, WE_MAX_STR_LEN, "\n");
|
||||
rssi_info = &peer_sta_info.info[0];
|
||||
for (i = 0; i < peer_sta_info.sta_num; i++) {
|
||||
buf = scnprintf
|
||||
(
|
||||
rssi_info_output + length, WE_MAX_STR_LEN - length,
|
||||
"[%pM] [%d]\n",
|
||||
rssi_info[i].peer_macaddr.bytes,
|
||||
rssi_info[i].rssi
|
||||
);
|
||||
length += buf;
|
||||
}
|
||||
wrqu->data.length = length + 1;
|
||||
|
||||
EXIT();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iw_get_peer_rssi() - get station's rssi
|
||||
* @dev: net device
|
||||
* @info: iwpriv request information
|
||||
* @wrqu: iwpriv command parameter
|
||||
* @extra
|
||||
*
|
||||
* This function will call __iw_get_peer_rssi
|
||||
*
|
||||
* Return: 0 on success, otherwise error value
|
||||
*/
|
||||
static int
|
||||
iw_get_peer_rssi(struct net_device *dev, struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
int ret;
|
||||
|
||||
cds_ssr_protect(__func__);
|
||||
ret = __iw_get_peer_rssi(dev, info, wrqu, extra);
|
||||
cds_ssr_unprotect(__func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const iw_handler hostapd_handler[] = {
|
||||
(iw_handler) NULL, /* SIOCSIWCOMMIT */
|
||||
(iw_handler) NULL, /* SIOCGIWNAME */
|
||||
|
|
@ -5804,6 +6169,11 @@ static const struct iw_priv_args hostapd_private_args[] = {
|
|||
IW_PRIV_TYPE_CHAR | 18,
|
||||
IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed"
|
||||
}
|
||||
, {
|
||||
QCSAP_IOCTL_PRIV_GET_RSSI,
|
||||
IW_PRIV_TYPE_CHAR | 18,
|
||||
IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "getRSSI"
|
||||
}
|
||||
, {
|
||||
QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE,
|
||||
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, ""
|
||||
|
|
@ -6013,6 +6383,8 @@ static const iw_handler hostapd_private[] = {
|
|||
[QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED -
|
||||
SIOCIWFIRSTPRIV] =
|
||||
iw_get_softap_linkspeed,
|
||||
[QCSAP_IOCTL_PRIV_GET_RSSI - SIOCIWFIRSTPRIV] =
|
||||
iw_get_peer_rssi,
|
||||
[QCSAP_IOCTL_SET_TX_POWER - SIOCIWFIRSTPRIV] =
|
||||
iw_softap_set_tx_power,
|
||||
[QCSAP_IOCTL_SET_MAX_TX_POWER - SIOCIWFIRSTPRIV] =
|
||||
|
|
|
|||
|
|
@ -960,6 +960,7 @@ static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
|
|||
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
|
||||
config->isRoamOffloadEnabled &= cfg->en_roam_offload;
|
||||
#endif
|
||||
config->sap_get_peer_info &= cfg->get_peer_info_enabled;
|
||||
sme_update_tgt_services(hdd_ctx->hHal, cfg);
|
||||
|
||||
}
|
||||
|
|
@ -9823,6 +9824,13 @@ int hdd_wlan_startup(struct device *dev)
|
|||
set_value, PDEV_CMD);
|
||||
}
|
||||
|
||||
if (hdd_ctx->config->sap_get_peer_info) {
|
||||
set_value = hdd_ctx->config->sap_get_peer_info;
|
||||
sme_cli_set_command(0,
|
||||
(int)WMI_PDEV_PARAM_PEER_STATS_INFO_ENABLE,
|
||||
set_value, PDEV_CMD);
|
||||
}
|
||||
|
||||
num_11b_tx_chains = hdd_ctx->config->num_11b_tx_chains;
|
||||
num_11ag_tx_chains = hdd_ctx->config->num_11ag_tx_chains;
|
||||
if (!hdd_ctx->config->enable2x2) {
|
||||
|
|
|
|||
|
|
@ -256,6 +256,7 @@ static int __hdd_softap_hard_start_xmit(struct sk_buff *skb,
|
|||
hdd_ap_ctx_t *pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
|
||||
struct qdf_mac_addr *pDestMacAddress;
|
||||
uint8_t STAId;
|
||||
uint32_t num_seg;
|
||||
|
||||
++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;
|
||||
/* Prevent this function from being called during SSR since TL
|
||||
|
|
@ -395,11 +396,17 @@ static int __hdd_softap_hard_start_xmit(struct sk_buff *skb,
|
|||
qdf_net_buf_debug_acquire_skb(skb, __FILE__, __LINE__);
|
||||
|
||||
pAdapter->stats.tx_bytes += skb->len;
|
||||
pAdapter->aStaInfo[STAId].tx_bytes += skb->len;
|
||||
|
||||
if (qdf_nbuf_is_tso(skb))
|
||||
pAdapter->stats.tx_packets += qdf_nbuf_get_tso_num_seg(skb);
|
||||
else
|
||||
if (qdf_nbuf_is_tso(skb)) {
|
||||
num_seg = qdf_nbuf_get_tso_num_seg(skb);
|
||||
pAdapter->stats.tx_packets += num_seg;
|
||||
pAdapter->aStaInfo[STAId].tx_packets += num_seg;
|
||||
} else {
|
||||
++pAdapter->stats.tx_packets;
|
||||
pAdapter->aStaInfo[STAId].tx_packets++;
|
||||
}
|
||||
pAdapter->aStaInfo[STAId].last_tx_rx_ts = qdf_system_ticks();
|
||||
|
||||
hdd_event_eapol_log(skb, QDF_TX);
|
||||
qdf_dp_trace_log_pkt(pAdapter->sessionId, skb, QDF_TX,
|
||||
|
|
@ -686,6 +693,8 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
|
|||
struct sk_buff *skb = NULL;
|
||||
struct sk_buff *next = NULL;
|
||||
hdd_context_t *pHddCtx = NULL;
|
||||
struct qdf_mac_addr src_mac;
|
||||
uint8_t staid;
|
||||
|
||||
/* Sanity check on inputs */
|
||||
if (unlikely((NULL == context) || (NULL == rxBuf))) {
|
||||
|
|
@ -737,6 +746,17 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
|
|||
++pAdapter->stats.rx_packets;
|
||||
pAdapter->stats.rx_bytes += skb->len;
|
||||
|
||||
qdf_mem_copy(&src_mac, skb->data + QDF_NBUF_SRC_MAC_OFFSET,
|
||||
sizeof(src_mac));
|
||||
if (QDF_STATUS_SUCCESS ==
|
||||
hdd_softap_get_sta_id(pAdapter, &src_mac, &staid)) {
|
||||
if (staid < WLAN_MAX_STA_COUNT) {
|
||||
pAdapter->aStaInfo[staid].rx_packets++;
|
||||
pAdapter->aStaInfo[staid].rx_bytes += skb->len;
|
||||
pAdapter->aStaInfo[staid].last_tx_rx_ts =
|
||||
qdf_system_ticks();
|
||||
}
|
||||
}
|
||||
hdd_event_eapol_log(skb, QDF_RX);
|
||||
DPTRACE(qdf_dp_trace(skb,
|
||||
QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD,
|
||||
|
|
|
|||
|
|
@ -45,68 +45,22 @@
|
|||
* The LO field is the rate when RSSI is low
|
||||
* (in this case we don't report rates, actual current rate used)
|
||||
*/
|
||||
static const struct {
|
||||
uint8_t beacon_rate_index;
|
||||
uint16_t supported_rate[4];
|
||||
} supported_data_rate[] = {
|
||||
/* IDX HI HM LM LO (RSSI-based index */
|
||||
{
|
||||
2, {
|
||||
10, 10, 10, 0
|
||||
}
|
||||
}, {
|
||||
4, {
|
||||
20, 20, 10, 0
|
||||
}
|
||||
}, {
|
||||
11, {
|
||||
55, 20, 10, 0
|
||||
}
|
||||
}, {
|
||||
12, {
|
||||
60, 55, 20, 0
|
||||
}
|
||||
}, {
|
||||
18, {
|
||||
90, 55, 20, 0
|
||||
}
|
||||
}, {
|
||||
22, {
|
||||
110, 55, 20, 0
|
||||
}
|
||||
}, {
|
||||
24, {
|
||||
120, 90, 60, 0
|
||||
}
|
||||
}, {
|
||||
36, {
|
||||
180, 120, 60, 0
|
||||
}
|
||||
}, {
|
||||
44, {
|
||||
220, 180, 60, 0
|
||||
}
|
||||
}, {
|
||||
48, {
|
||||
240, 180, 90, 0
|
||||
}
|
||||
}, {
|
||||
66, {
|
||||
330, 180, 90, 0
|
||||
}
|
||||
}, {
|
||||
72, {
|
||||
360, 240, 90, 0
|
||||
}
|
||||
}, {
|
||||
96, {
|
||||
480, 240, 120, 0
|
||||
}
|
||||
}, {
|
||||
108, {
|
||||
540, 240, 120, 0
|
||||
}
|
||||
}
|
||||
static const struct index_data_rate_type supported_data_rate[] = {
|
||||
/* IDX HI HM LM LO (RSSI-based index */
|
||||
{2, { 10, 10, 10, 0} },
|
||||
{4, { 20, 20, 10, 0} },
|
||||
{11, { 55, 20, 10, 0} },
|
||||
{12, { 60, 55, 20, 0} },
|
||||
{18, { 90, 55, 20, 0} },
|
||||
{22, {110, 55, 20, 0} },
|
||||
{24, {120, 90, 60, 0} },
|
||||
{36, {180, 120, 60, 0} },
|
||||
{44, {220, 180, 60, 0} },
|
||||
{48, {240, 180, 90, 0} },
|
||||
{66, {330, 180, 90, 0} },
|
||||
{72, {360, 240, 90, 0} },
|
||||
{96, {480, 240, 120, 0} },
|
||||
{108, {540, 240, 120, 0} }
|
||||
};
|
||||
/* MCS Based rate table HT MCS parameters with Nss = 1 */
|
||||
static struct index_data_rate_type supported_mcs_rate_nss1[] = {
|
||||
|
|
@ -3083,6 +3037,840 @@ wlan_hdd_get_sap_stats(hdd_adapter_t *adapter, struct station_info *info)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_get_max_rate_legacy() - get max rate for legacy mode
|
||||
* @stainfo: stainfo pointer
|
||||
* @rssidx: rssi index
|
||||
*
|
||||
* This function will get max rate for legacy mode
|
||||
*
|
||||
* Return: max rate on success, otherwise 0
|
||||
*/
|
||||
static uint32_t hdd_get_max_rate_legacy(hdd_station_info_t *stainfo,
|
||||
uint8_t rssidx)
|
||||
{
|
||||
uint32_t maxrate = 0;
|
||||
/*Minimum max rate, 6Mbps*/
|
||||
int maxidx = 12;
|
||||
int i;
|
||||
|
||||
/* check supported rates */
|
||||
if (stainfo->max_supp_idx != 0xff &&
|
||||
maxidx < stainfo->max_supp_idx)
|
||||
maxidx = stainfo->max_supp_idx;
|
||||
|
||||
/* check extended rates */
|
||||
if (stainfo->max_ext_idx != 0xff &&
|
||||
maxidx < stainfo->max_ext_idx)
|
||||
maxidx = stainfo->max_ext_idx;
|
||||
|
||||
for (i = 0; QDF_ARRAY_SIZE(supported_data_rate); i++) {
|
||||
if (supported_data_rate[i].beacon_rate_index == maxidx)
|
||||
maxrate =
|
||||
supported_data_rate[i].supported_rate[rssidx];
|
||||
}
|
||||
|
||||
hdd_debug("maxrate %d", maxrate);
|
||||
|
||||
return maxrate;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_get_max_rate_ht() - get max rate for ht mode
|
||||
* @stainfo: stainfo pointer
|
||||
* @stats: fw txrx status pointer
|
||||
* @rate_flags: rate flags
|
||||
* @nss: number of streams
|
||||
* @maxrate: returned max rate buffer pointer
|
||||
* @max_mcs_idx: max mcs idx
|
||||
* @report_max: report max rate or actual rate
|
||||
*
|
||||
* This function will get max rate for ht mode
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_get_max_rate_ht(hdd_station_info_t *stainfo,
|
||||
struct hdd_fw_txrx_stats *stats,
|
||||
uint32_t rate_flags,
|
||||
uint8_t nss,
|
||||
uint32_t *maxrate,
|
||||
uint8_t *max_mcs_idx,
|
||||
bool report_max)
|
||||
{
|
||||
struct index_data_rate_type *supported_mcs_rate;
|
||||
uint32_t tmprate;
|
||||
uint8_t flag = 0, mcsidx;
|
||||
int8_t rssi = stats->rssi;
|
||||
int mode;
|
||||
int i;
|
||||
|
||||
if (rate_flags & eHAL_TX_RATE_HT40)
|
||||
mode = 1;
|
||||
else
|
||||
mode = 0;
|
||||
|
||||
if (rate_flags & eHAL_TX_RATE_HT40)
|
||||
flag |= 1;
|
||||
if (rate_flags & eHAL_TX_RATE_SGI)
|
||||
flag |= 2;
|
||||
|
||||
supported_mcs_rate = (struct index_data_rate_type *)
|
||||
((nss == 1) ? &supported_mcs_rate_nss1 :
|
||||
&supported_mcs_rate_nss2);
|
||||
|
||||
if (stainfo->max_mcs_idx == 0xff) {
|
||||
hdd_err("invalid max_mcs_idx");
|
||||
/* report real mcs idx */
|
||||
mcsidx = stats->tx_rate.mcs;
|
||||
} else {
|
||||
mcsidx = stainfo->max_mcs_idx;
|
||||
}
|
||||
|
||||
if (!report_max) {
|
||||
for (i = 0; i < mcsidx; i++) {
|
||||
if (rssi <= rssi_mcs_tbl[mode][i]) {
|
||||
mcsidx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mcsidx < stats->tx_rate.mcs)
|
||||
mcsidx = stats->tx_rate.mcs;
|
||||
}
|
||||
|
||||
tmprate = supported_mcs_rate[mcsidx].supported_rate[flag];
|
||||
|
||||
hdd_debug("tmprate %d mcsidx %d", tmprate, mcsidx);
|
||||
|
||||
*maxrate = tmprate;
|
||||
*max_mcs_idx = mcsidx;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_get_max_rate_vht() - get max rate for vht mode
|
||||
* @stainfo: stainfo pointer
|
||||
* @stats: fw txrx status pointer
|
||||
* @rate_flags: rate flags
|
||||
* @nss: number of streams
|
||||
* @maxrate: returned max rate buffer pointer
|
||||
* @max_mcs_idx: max mcs idx
|
||||
* @report_max: report max rate or actual rate
|
||||
*
|
||||
* This function will get max rate for vht mode
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_get_max_rate_vht(hdd_station_info_t *stainfo,
|
||||
struct hdd_fw_txrx_stats *stats,
|
||||
uint32_t rate_flags,
|
||||
uint8_t nss,
|
||||
uint32_t *maxrate,
|
||||
uint8_t *max_mcs_idx,
|
||||
bool report_max)
|
||||
{
|
||||
struct index_vht_data_rate_type *supported_vht_mcs_rate;
|
||||
uint32_t tmprate = 0;
|
||||
uint32_t vht_max_mcs;
|
||||
uint8_t flag = 0, mcsidx = INVALID_MCS_IDX;
|
||||
int8_t rssi = stats->rssi;
|
||||
int mode;
|
||||
int i;
|
||||
|
||||
supported_vht_mcs_rate = (struct index_vht_data_rate_type *)
|
||||
((nss == 1) ?
|
||||
&supported_vht_mcs_rate_nss1 :
|
||||
&supported_vht_mcs_rate_nss2);
|
||||
|
||||
if (rate_flags & eHAL_TX_RATE_VHT80)
|
||||
mode = 2;
|
||||
else if (rate_flags & eHAL_TX_RATE_VHT40)
|
||||
mode = 1;
|
||||
else
|
||||
mode = 0;
|
||||
|
||||
if (rate_flags &
|
||||
(eHAL_TX_RATE_VHT20 | eHAL_TX_RATE_VHT40 | eHAL_TX_RATE_VHT80)) {
|
||||
vht_max_mcs =
|
||||
(enum data_rate_11ac_max_mcs)
|
||||
(stainfo->tx_mcs_map & DATA_RATE_11AC_MCS_MASK);
|
||||
if (rate_flags & eHAL_TX_RATE_SGI)
|
||||
flag |= 1;
|
||||
|
||||
if (vht_max_mcs == DATA_RATE_11AC_MAX_MCS_7) {
|
||||
mcsidx = 7;
|
||||
} else if (vht_max_mcs == DATA_RATE_11AC_MAX_MCS_8) {
|
||||
mcsidx = 8;
|
||||
} else if (vht_max_mcs == DATA_RATE_11AC_MAX_MCS_9) {
|
||||
/*
|
||||
* 'IEEE_P802.11ac_2013.pdf' page 325, 326
|
||||
* - MCS9 is valid for VHT20 when Nss = 3 or Nss = 6
|
||||
* - MCS9 is not valid for VHT20 when Nss = 1,2,4,5,7,8
|
||||
*/
|
||||
if ((rate_flags & eHAL_TX_RATE_VHT20) &&
|
||||
(nss != 3 && nss != 6))
|
||||
mcsidx = 8;
|
||||
else
|
||||
mcsidx = 9;
|
||||
} else {
|
||||
hdd_err("invalid vht_max_mcs");
|
||||
/* report real mcs idx */
|
||||
mcsidx = stats->tx_rate.mcs;
|
||||
}
|
||||
|
||||
if (!report_max) {
|
||||
for (i = 0; i <= mcsidx; i++) {
|
||||
if (rssi <= rssi_mcs_tbl[mode][i]) {
|
||||
mcsidx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mcsidx < stats->tx_rate.mcs)
|
||||
mcsidx = stats->tx_rate.mcs;
|
||||
}
|
||||
|
||||
if (rate_flags & eHAL_TX_RATE_VHT80)
|
||||
tmprate =
|
||||
supported_vht_mcs_rate[mcsidx].supported_VHT80_rate[flag];
|
||||
else if (rate_flags & eHAL_TX_RATE_VHT40)
|
||||
tmprate =
|
||||
supported_vht_mcs_rate[mcsidx].supported_VHT40_rate[flag];
|
||||
else if (rate_flags & eHAL_TX_RATE_VHT20)
|
||||
tmprate =
|
||||
supported_vht_mcs_rate[mcsidx].supported_VHT20_rate[flag];
|
||||
}
|
||||
|
||||
hdd_debug("tmprate %d mcsidx %d", tmprate, mcsidx);
|
||||
|
||||
*maxrate = tmprate;
|
||||
*max_mcs_idx = mcsidx;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
|
||||
/**
|
||||
* hdd_fill_bw_mcs() - fill ch width and mcs flags
|
||||
* @stainfo: stainfo pointer
|
||||
* @rate_flags: HDD rate flags
|
||||
* @mcsidx: mcs index
|
||||
* @nss: number of streams
|
||||
* @vht: vht mode or not
|
||||
*
|
||||
* This function will fill ch width and mcs flags
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_fill_bw_mcs(struct station_info *sinfo,
|
||||
uint8_t rate_flags,
|
||||
uint8_t mcsidx,
|
||||
uint8_t nss,
|
||||
bool vht)
|
||||
{
|
||||
if (vht) {
|
||||
sinfo->txrate.nss = nss;
|
||||
sinfo->txrate.mcs = mcsidx;
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
|
||||
if (rate_flags & eHAL_TX_RATE_VHT80)
|
||||
sinfo->txrate.bw = RATE_INFO_BW_80;
|
||||
else if (rate_flags & eHAL_TX_RATE_VHT40)
|
||||
sinfo->txrate.bw = RATE_INFO_BW_40;
|
||||
else if (rate_flags & eHAL_TX_RATE_VHT20)
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
|
||||
} else {
|
||||
sinfo->txrate.mcs = (nss - 1) << 3;
|
||||
sinfo->txrate.mcs |= mcsidx;
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
|
||||
if (rate_flags & eHAL_TX_RATE_HT40)
|
||||
sinfo->txrate.bw = RATE_INFO_BW_40;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* hdd_fill_bw_mcs() - fill ch width and mcs flags
|
||||
* @stainfo: stainfo pointer
|
||||
* @rate_flags: HDD rate flags
|
||||
* @mcsidx: mcs index
|
||||
* @nss: number of streams
|
||||
* @vht: vht mode or not
|
||||
*
|
||||
* This function will fill ch width and mcs flags
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_fill_bw_mcs(struct station_info *sinfo,
|
||||
uint8_t rate_flags,
|
||||
uint8_t mcsidx,
|
||||
uint8_t nss,
|
||||
bool vht)
|
||||
{
|
||||
if (vht) {
|
||||
sinfo->txrate.nss = nss;
|
||||
sinfo->txrate.mcs = mcsidx;
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
|
||||
if (rate_flags & eHAL_TX_RATE_VHT80)
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
|
||||
else if (rate_flags & eHAL_TX_RATE_VHT40)
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
|
||||
else if (rate_flags & eHAL_TX_RATE_VHT20)
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
|
||||
} else {
|
||||
sinfo->txrate.mcs = (nss - 1) << 3;
|
||||
sinfo->txrate.mcs |= mcsidx;
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
|
||||
if (rate_flags & eHAL_TX_RATE_HT40)
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hdd_fill_bw_mcs_vht() - fill ch width and mcs flags for VHT mode
|
||||
* @stainfo: stainfo pointer
|
||||
* @rate_flags: HDD rate flags
|
||||
* @mcsidx: mcs index
|
||||
* @nss: number of streams
|
||||
*
|
||||
* This function will fill ch width and mcs flags for VHT mode
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_fill_bw_mcs_vht(struct station_info *sinfo,
|
||||
uint8_t rate_flags,
|
||||
uint8_t mcsidx,
|
||||
uint8_t nss)
|
||||
{
|
||||
hdd_fill_bw_mcs(sinfo, rate_flags, mcsidx, nss, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_fill_sinfo_rate_info() - fill rate info of sinfo struct
|
||||
* @sinfo: station_info struct pointer
|
||||
* @rate_flags: HDD rate flags
|
||||
* @mcsidx: mcs index
|
||||
* @nss: number of streams
|
||||
* @maxrate: data rate (kbps)
|
||||
*
|
||||
* This function will fill rate info of sinfo struct
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_fill_sinfo_rate_info(struct station_info *sinfo,
|
||||
uint32_t rate_flags,
|
||||
uint8_t mcsidx,
|
||||
uint8_t nss,
|
||||
uint32_t maxrate)
|
||||
{
|
||||
if (rate_flags & eHAL_TX_RATE_LEGACY) {
|
||||
/* provide to the UI in units of 100kbps */
|
||||
sinfo->txrate.legacy = maxrate;
|
||||
} else {
|
||||
/* must be MCS */
|
||||
if (rate_flags &
|
||||
(eHAL_TX_RATE_VHT80 |
|
||||
eHAL_TX_RATE_VHT40 |
|
||||
eHAL_TX_RATE_VHT20))
|
||||
hdd_fill_bw_mcs_vht(sinfo, rate_flags, mcsidx, nss);
|
||||
|
||||
if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40))
|
||||
hdd_fill_bw_mcs(sinfo, rate_flags, mcsidx, nss, false);
|
||||
|
||||
if (rate_flags & eHAL_TX_RATE_SGI) {
|
||||
if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_VHT_MCS))
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
}
|
||||
}
|
||||
|
||||
hdd_info("flag %x mcs %d legacy %d nss %d",
|
||||
sinfo->txrate.flags,
|
||||
sinfo->txrate.mcs,
|
||||
sinfo->txrate.legacy,
|
||||
sinfo->txrate.nss);
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_fill_station_info_flags() - fill flags of sinfo struct
|
||||
* @sinfo: station_info struct pointer
|
||||
*
|
||||
* This function will fill flags of sinfo struct
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_fill_station_info_flags(struct station_info *sinfo)
|
||||
{
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
|
||||
BIT(NL80211_STA_INFO_TX_BYTES) |
|
||||
BIT(NL80211_STA_INFO_TX_BYTES64) |
|
||||
BIT(NL80211_STA_INFO_TX_BITRATE) |
|
||||
BIT(NL80211_STA_INFO_TX_PACKETS) |
|
||||
BIT(NL80211_STA_INFO_TX_RETRIES) |
|
||||
BIT(NL80211_STA_INFO_TX_FAILED) |
|
||||
BIT(NL80211_STA_INFO_RX_BYTES) |
|
||||
BIT(NL80211_STA_INFO_RX_BYTES64) |
|
||||
BIT(NL80211_STA_INFO_RX_PACKETS) |
|
||||
BIT(NL80211_STA_INFO_INACTIVE_TIME) |
|
||||
BIT(NL80211_STA_INFO_CONNECTED_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_fill_rate_info() - fill rate info of sinfo
|
||||
* @sinfo: station_info struct pointer
|
||||
* @stainfo: stainfo pointer
|
||||
* @stats: fw txrx status pointer
|
||||
* @cfg: hdd config pointer
|
||||
*
|
||||
* This function will fill rate info of sinfo
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_fill_rate_info(struct station_info *sinfo,
|
||||
hdd_station_info_t *stainfo,
|
||||
struct hdd_fw_txrx_stats *stats,
|
||||
struct hdd_config *cfg)
|
||||
{
|
||||
uint8_t rate_flags;
|
||||
uint8_t mcsidx = 0xff;
|
||||
uint32_t myrate, maxrate, tmprate;
|
||||
int rssidx;
|
||||
int nss = 1;
|
||||
|
||||
hdd_info("reportMaxLinkSpeed %d", cfg->reportMaxLinkSpeed);
|
||||
|
||||
/* convert to 100kbps expected in rate table */
|
||||
myrate = stats->tx_rate.rate / 100;
|
||||
rate_flags = stainfo->rate_flags;
|
||||
if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
|
||||
nss = stainfo->nss;
|
||||
if (eHDD_LINK_SPEED_REPORT_ACTUAL == cfg->reportMaxLinkSpeed) {
|
||||
/* Get current rate flags if report actual */
|
||||
if (stats->tx_rate.rate_flags)
|
||||
rate_flags =
|
||||
stats->tx_rate.rate_flags;
|
||||
nss = stats->tx_rate.nss;
|
||||
}
|
||||
|
||||
if (stats->tx_rate.mcs == INVALID_MCS_IDX)
|
||||
rate_flags = eHAL_TX_RATE_LEGACY;
|
||||
}
|
||||
|
||||
if (eHDD_LINK_SPEED_REPORT_ACTUAL != cfg->reportMaxLinkSpeed) {
|
||||
/* we do not want to necessarily report the current speed */
|
||||
if (eHDD_LINK_SPEED_REPORT_MAX == cfg->reportMaxLinkSpeed) {
|
||||
/* report the max possible speed */
|
||||
rssidx = 0;
|
||||
} else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED ==
|
||||
cfg->reportMaxLinkSpeed) {
|
||||
/* report the max possible speed with RSSI scaling */
|
||||
if (stats->rssi >= cfg->linkSpeedRssiHigh) {
|
||||
/* report the max possible speed */
|
||||
rssidx = 0;
|
||||
} else if (stats->rssi >=
|
||||
cfg->linkSpeedRssiMid) {
|
||||
/* report middle speed */
|
||||
rssidx = 1;
|
||||
} else if (stats->rssi >=
|
||||
cfg->linkSpeedRssiLow) {
|
||||
/* report middle speed */
|
||||
rssidx = 2;
|
||||
} else {
|
||||
/* report actual speed */
|
||||
rssidx = 3;
|
||||
}
|
||||
} else {
|
||||
/* unknown, treat as eHDD_LINK_SPEED_REPORT_MAX */
|
||||
hdd_err("Invalid value for reportMaxLinkSpeed: %u",
|
||||
cfg->reportMaxLinkSpeed);
|
||||
rssidx = 0;
|
||||
}
|
||||
|
||||
maxrate = hdd_get_max_rate_legacy(stainfo, rssidx);
|
||||
|
||||
/*
|
||||
* Get MCS Rate Set --
|
||||
* Only if we are connected in non legacy mode and not
|
||||
* reporting actual speed
|
||||
*/
|
||||
if ((rssidx != 3) &&
|
||||
!(rate_flags & eHAL_TX_RATE_LEGACY)) {
|
||||
hdd_get_max_rate_vht(stainfo,
|
||||
stats,
|
||||
rate_flags,
|
||||
nss,
|
||||
&tmprate,
|
||||
&mcsidx,
|
||||
rssidx == 0);
|
||||
|
||||
if (maxrate < tmprate &&
|
||||
mcsidx != INVALID_MCS_IDX)
|
||||
maxrate = tmprate;
|
||||
|
||||
if (mcsidx == INVALID_MCS_IDX)
|
||||
hdd_get_max_rate_ht(stainfo,
|
||||
stats,
|
||||
rate_flags,
|
||||
nss,
|
||||
&tmprate,
|
||||
&mcsidx,
|
||||
rssidx == 0);
|
||||
|
||||
if (maxrate < tmprate &&
|
||||
mcsidx != INVALID_MCS_IDX)
|
||||
maxrate = tmprate;
|
||||
} else if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
|
||||
maxrate = myrate;
|
||||
mcsidx = stats->tx_rate.mcs;
|
||||
}
|
||||
|
||||
/*
|
||||
* make sure we report a value at least as big as our
|
||||
* current rate
|
||||
*/
|
||||
if ((maxrate < myrate) || (maxrate == 0)) {
|
||||
maxrate = myrate;
|
||||
if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
|
||||
mcsidx = stats->tx_rate.mcs;
|
||||
/*
|
||||
* 'IEEE_P802.11ac_2013.pdf' page 325, 326
|
||||
* - MCS9 is valid for VHT20 when Nss = 3 or
|
||||
* Nss = 6
|
||||
* - MCS9 is not valid for VHT20 when
|
||||
* Nss = 1,2,4,5,7,8
|
||||
*/
|
||||
if ((rate_flags & eHAL_TX_RATE_VHT20) &&
|
||||
(mcsidx > 8) &&
|
||||
(nss != 3 && nss != 6))
|
||||
mcsidx = 8;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* report current rate instead of max rate */
|
||||
maxrate = myrate;
|
||||
if (!(rate_flags & eHAL_TX_RATE_LEGACY))
|
||||
mcsidx = stats->tx_rate.mcs;
|
||||
}
|
||||
|
||||
hdd_fill_sinfo_rate_info(sinfo,
|
||||
rate_flags,
|
||||
mcsidx,
|
||||
nss,
|
||||
maxrate);
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_fill_station_info() - fill station_info struct
|
||||
* @sinfo: station_info struct pointer
|
||||
* @stainfo: stainfo pointer
|
||||
* @stats: fw txrx status pointer
|
||||
* @cfg: hdd config pointer
|
||||
*
|
||||
* This function will fill station_info struct
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void wlan_hdd_fill_station_info(struct station_info *sinfo,
|
||||
hdd_station_info_t *stainfo,
|
||||
struct hdd_fw_txrx_stats *stats,
|
||||
struct hdd_config *cfg)
|
||||
{
|
||||
qdf_time_t curr_time, dur;
|
||||
|
||||
curr_time = qdf_system_ticks();
|
||||
dur = curr_time - stainfo->assoc_ts;
|
||||
sinfo->connected_time = qdf_system_ticks_to_msecs(dur) / 1000;
|
||||
dur = curr_time - stainfo->last_tx_rx_ts;
|
||||
sinfo->inactive_time = qdf_system_ticks_to_msecs(dur);
|
||||
sinfo->signal = stats->rssi;
|
||||
sinfo->tx_bytes = stats->tx_bytes;
|
||||
sinfo->tx_packets = stats->tx_packets;
|
||||
sinfo->rx_bytes = stats->rx_bytes;
|
||||
sinfo->rx_packets = stats->rx_packets;
|
||||
sinfo->tx_failed = stats->tx_failed;
|
||||
sinfo->tx_retries = stats->tx_retries;
|
||||
|
||||
/* tx rate info */
|
||||
hdd_fill_rate_info(sinfo, stainfo, stats, cfg);
|
||||
|
||||
hdd_fill_station_info_flags(sinfo);
|
||||
|
||||
/* dump sta info*/
|
||||
hdd_info("dump stainfo");
|
||||
hdd_info("con_time %d inact_time %d tx_pkts %d rx_pkts %d",
|
||||
sinfo->connected_time, sinfo->inactive_time,
|
||||
sinfo->tx_packets, sinfo->rx_packets);
|
||||
hdd_info("failed %d retries %d tx_bytes %lld rx_bytes %lld",
|
||||
sinfo->tx_failed, sinfo->tx_retries,
|
||||
sinfo->tx_bytes, sinfo->rx_bytes);
|
||||
hdd_info("rssi %d mcs %d legacy %d nss %d flags %x",
|
||||
sinfo->signal, sinfo->txrate.mcs,
|
||||
sinfo->txrate.legacy, sinfo->txrate.nss,
|
||||
sinfo->txrate.flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_get_rate_flags_ht() - get HT rate flags based on rate, nss and mcs
|
||||
* @rate: Data rate (100 kbps)
|
||||
* @nss: Number of streams
|
||||
* @mcs: HT mcs index
|
||||
*
|
||||
* This function is used to construct HT rate flag with rate, nss and mcs
|
||||
*
|
||||
* Return: rate flags for success, 0 on failure.
|
||||
*/
|
||||
static uint8_t hdd_get_rate_flags_ht(uint32_t rate,
|
||||
uint8_t nss,
|
||||
uint8_t mcs)
|
||||
{
|
||||
struct index_data_rate_type *mcs_rate;
|
||||
uint8_t flags = 0;
|
||||
|
||||
mcs_rate = (struct index_data_rate_type *)
|
||||
((nss == 1) ? &supported_mcs_rate_nss1 :
|
||||
&supported_mcs_rate_nss2);
|
||||
|
||||
if (rate == mcs_rate[mcs].supported_rate[0]) {
|
||||
flags |= eHAL_TX_RATE_HT20;
|
||||
} else if (rate == mcs_rate[mcs].supported_rate[1]) {
|
||||
flags |= eHAL_TX_RATE_HT40;
|
||||
} else if (rate == mcs_rate[mcs].supported_rate[2]) {
|
||||
flags |= eHAL_TX_RATE_HT20;
|
||||
flags |= eHAL_TX_RATE_SGI;
|
||||
} else if (rate == mcs_rate[mcs].supported_rate[3]) {
|
||||
flags |= eHAL_TX_RATE_HT40;
|
||||
flags |= eHAL_TX_RATE_SGI;
|
||||
} else {
|
||||
hdd_err("invalid params rate %d nss %d mcs %d",
|
||||
rate, nss, mcs);
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_get_rate_flags_vht() - get VHT rate flags based on rate, nss and mcs
|
||||
* @rate: Data rate (100 kbps)
|
||||
* @nss: Number of streams
|
||||
* @mcs: VHT mcs index
|
||||
*
|
||||
* This function is used to construct VHT rate flag with rate, nss and mcs
|
||||
*
|
||||
* Return: rate flags for success, 0 on failure.
|
||||
*/
|
||||
static uint8_t hdd_get_rate_flags_vht(uint32_t rate,
|
||||
uint8_t nss,
|
||||
uint8_t mcs)
|
||||
{
|
||||
struct index_vht_data_rate_type *mcs_rate;
|
||||
uint8_t flags = 0;
|
||||
|
||||
mcs_rate = (struct index_vht_data_rate_type *)
|
||||
((nss == 1) ?
|
||||
&supported_vht_mcs_rate_nss1 :
|
||||
&supported_vht_mcs_rate_nss2);
|
||||
|
||||
if (rate == mcs_rate[mcs].supported_VHT80_rate[0]) {
|
||||
flags |= eHAL_TX_RATE_VHT80;
|
||||
} else if (rate == mcs_rate[mcs].supported_VHT80_rate[1]) {
|
||||
flags |= eHAL_TX_RATE_VHT80;
|
||||
flags |= eHAL_TX_RATE_SGI;
|
||||
} else if (rate == mcs_rate[mcs].supported_VHT40_rate[0]) {
|
||||
flags |= eHAL_TX_RATE_VHT40;
|
||||
} else if (rate == mcs_rate[mcs].supported_VHT40_rate[1]) {
|
||||
flags |= eHAL_TX_RATE_VHT40;
|
||||
flags |= eHAL_TX_RATE_SGI;
|
||||
} else if (rate == mcs_rate[mcs].supported_VHT20_rate[0]) {
|
||||
flags |= eHAL_TX_RATE_VHT20;
|
||||
} else if (rate == mcs_rate[mcs].supported_VHT20_rate[1]) {
|
||||
flags |= eHAL_TX_RATE_VHT20;
|
||||
flags |= eHAL_TX_RATE_SGI;
|
||||
} else {
|
||||
hdd_err("invalid params rate %d nss %d mcs %d",
|
||||
rate, nss, mcs);
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_get_rate_flags() - get HT/VHT rate flags based on rate, nss and mcs
|
||||
* @rate: Data rate (100 kbps)
|
||||
* @mode: Tx/Rx mode
|
||||
* @nss: Number of streams
|
||||
* @mcs: Mcs index
|
||||
*
|
||||
* This function is used to construct rate flag with rate, nss and mcs
|
||||
*
|
||||
* Return: rate flags for success, 0 on failure.
|
||||
*/
|
||||
static uint8_t hdd_get_rate_flags(uint32_t rate,
|
||||
uint8_t mode,
|
||||
uint8_t nss,
|
||||
uint8_t mcs)
|
||||
{
|
||||
uint8_t flags = 0;
|
||||
|
||||
if (mode == SIR_SME_PHY_MODE_HT)
|
||||
flags = hdd_get_rate_flags_ht(rate, nss, mcs);
|
||||
else if (mode == SIR_SME_PHY_MODE_VHT)
|
||||
flags = hdd_get_rate_flags_vht(rate, nss, mcs);
|
||||
else
|
||||
hdd_err("invalid mode param %d", mode);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_fill_rate_info() - fill HDD rate info from SIR peer info
|
||||
* @ap_ctx: AP Context
|
||||
* @peer_info: SIR peer info pointer
|
||||
*
|
||||
* This function is used to fill HDD rate info rom SIR peer info
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void wlan_hdd_fill_rate_info(hdd_ap_ctx_t *ap_ctx,
|
||||
struct sir_peer_info_ext *peer_info)
|
||||
{
|
||||
uint8_t flags;
|
||||
uint32_t rate_code;
|
||||
|
||||
/* tx rate info */
|
||||
ap_ctx->txrx_stats.tx_rate.rate = peer_info->tx_rate;
|
||||
rate_code = peer_info->tx_rate_code;
|
||||
|
||||
if ((WMI_GET_HW_RATECODE_PREAM_V1(rate_code)) ==
|
||||
WMI_RATE_PREAMBLE_HT)
|
||||
ap_ctx->txrx_stats.tx_rate.mode = SIR_SME_PHY_MODE_HT;
|
||||
else if ((WMI_GET_HW_RATECODE_PREAM_V1(rate_code)) ==
|
||||
WMI_RATE_PREAMBLE_VHT)
|
||||
ap_ctx->txrx_stats.tx_rate.mode = SIR_SME_PHY_MODE_VHT;
|
||||
else
|
||||
ap_ctx->txrx_stats.tx_rate.mode = SIR_SME_PHY_MODE_LEGACY;
|
||||
|
||||
ap_ctx->txrx_stats.tx_rate.nss =
|
||||
WMI_GET_HW_RATECODE_NSS_V1(rate_code) + 1;
|
||||
ap_ctx->txrx_stats.tx_rate.mcs =
|
||||
WMI_GET_HW_RATECODE_RATE_V1(rate_code);
|
||||
|
||||
flags = hdd_get_rate_flags(ap_ctx->txrx_stats.tx_rate.rate / 100,
|
||||
ap_ctx->txrx_stats.tx_rate.mode,
|
||||
ap_ctx->txrx_stats.tx_rate.nss,
|
||||
ap_ctx->txrx_stats.tx_rate.mcs);
|
||||
|
||||
ap_ctx->txrx_stats.tx_rate.rate_flags = flags;
|
||||
|
||||
hdd_debug("tx: mode %d nss %d mcs %d rate_flags %x flags %x",
|
||||
ap_ctx->txrx_stats.tx_rate.mode,
|
||||
ap_ctx->txrx_stats.tx_rate.nss,
|
||||
ap_ctx->txrx_stats.tx_rate.mcs,
|
||||
ap_ctx->txrx_stats.tx_rate.rate_flags,
|
||||
flags);
|
||||
|
||||
/* rx rate info */
|
||||
ap_ctx->txrx_stats.rx_rate.rate = peer_info->rx_rate;
|
||||
rate_code = peer_info->rx_rate_code;
|
||||
|
||||
if ((WMI_GET_HW_RATECODE_PREAM_V1(rate_code)) ==
|
||||
WMI_RATE_PREAMBLE_HT)
|
||||
ap_ctx->txrx_stats.rx_rate.mode = SIR_SME_PHY_MODE_HT;
|
||||
else if ((WMI_GET_HW_RATECODE_PREAM_V1(rate_code)) ==
|
||||
WMI_RATE_PREAMBLE_VHT)
|
||||
ap_ctx->txrx_stats.rx_rate.mode = SIR_SME_PHY_MODE_VHT;
|
||||
else
|
||||
ap_ctx->txrx_stats.rx_rate.mode = SIR_SME_PHY_MODE_LEGACY;
|
||||
|
||||
ap_ctx->txrx_stats.rx_rate.nss =
|
||||
WMI_GET_HW_RATECODE_NSS_V1(rate_code) + 1;
|
||||
ap_ctx->txrx_stats.rx_rate.mcs =
|
||||
WMI_GET_HW_RATECODE_RATE_V1(rate_code);
|
||||
|
||||
flags = hdd_get_rate_flags(ap_ctx->txrx_stats.rx_rate.rate / 100,
|
||||
ap_ctx->txrx_stats.rx_rate.mode,
|
||||
ap_ctx->txrx_stats.rx_rate.nss,
|
||||
ap_ctx->txrx_stats.rx_rate.mcs);
|
||||
|
||||
ap_ctx->txrx_stats.rx_rate.rate_flags = flags;
|
||||
|
||||
hdd_info("rx: mode %d nss %d mcs %d rate_flags %x flags %x",
|
||||
ap_ctx->txrx_stats.rx_rate.mode,
|
||||
ap_ctx->txrx_stats.rx_rate.nss,
|
||||
ap_ctx->txrx_stats.rx_rate.mcs,
|
||||
ap_ctx->txrx_stats.rx_rate.rate_flags,
|
||||
flags);
|
||||
}
|
||||
|
||||
int wlan_hdd_get_station_remote(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
const u8 *mac,
|
||||
struct station_info *sinfo);
|
||||
|
||||
/**
|
||||
* wlan_hdd_get_station_remote() - NL80211_CMD_GET_STATION handler for SoftAP
|
||||
* @wiphy: pointer to wiphy
|
||||
* @dev: pointer to net_device structure
|
||||
* @mac: request peer mac address
|
||||
* @sinfo: pointer to station_info struct
|
||||
*
|
||||
* This function will get remote peer info from fw and fill sinfo struct
|
||||
*
|
||||
* Return: 0 on success, otherwise error value
|
||||
*/
|
||||
int wlan_hdd_get_station_remote(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
const u8 *mac,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
|
||||
hdd_context_t *hddctx = (hdd_context_t *)wiphy_priv(wiphy);
|
||||
hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
|
||||
hdd_station_info_t *stainfo = NULL;
|
||||
struct hdd_config *cfg;
|
||||
struct qdf_mac_addr macaddr;
|
||||
struct sir_peer_info_ext peer_info;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
status = wlan_hdd_validate_context(hddctx);
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
cfg = hddctx->config;
|
||||
|
||||
hdd_debug("get peer %pM info", mac);
|
||||
|
||||
for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
|
||||
if (!qdf_mem_cmp(adapter->aStaInfo[i].macAddrSTA.bytes,
|
||||
mac,
|
||||
QDF_MAC_ADDR_SIZE)) {
|
||||
stainfo = &adapter->aStaInfo[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stainfo) {
|
||||
hdd_err("peer %pM not found", mac);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qdf_mem_copy(macaddr.bytes, mac, QDF_MAC_ADDR_SIZE);
|
||||
status = wlan_hdd_get_peer_info(adapter, macaddr, &peer_info);
|
||||
if (status) {
|
||||
hdd_err("fail to get peer info from fw");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
qdf_mem_zero(&ap_ctx->txrx_stats, sizeof(ap_ctx->txrx_stats));
|
||||
ap_ctx->txrx_stats.tx_packets = peer_info.tx_packets;
|
||||
ap_ctx->txrx_stats.tx_bytes = peer_info.tx_bytes;
|
||||
ap_ctx->txrx_stats.rx_packets = peer_info.rx_packets;
|
||||
ap_ctx->txrx_stats.rx_bytes = peer_info.rx_bytes;
|
||||
ap_ctx->txrx_stats.tx_retries = peer_info.tx_retries;
|
||||
ap_ctx->txrx_stats.tx_failed = peer_info.tx_failed;
|
||||
ap_ctx->txrx_stats.rssi =
|
||||
peer_info.rssi + WLAN_HDD_TGT_NOISE_FLOOR_DBM;
|
||||
wlan_hdd_fill_rate_info(ap_ctx, &peer_info);
|
||||
|
||||
wlan_hdd_fill_station_info(sinfo, stainfo, &ap_ctx->txrx_stats, cfg);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* __wlan_hdd_cfg80211_get_station() - get station statistics
|
||||
* @wiphy: Pointer to wiphy
|
||||
|
|
@ -3129,7 +3917,7 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
|
|||
#endif
|
||||
|
||||
uint32_t vht_mcs_map;
|
||||
enum eDataRate11ACMaxMcs vhtMaxMcs;
|
||||
enum data_rate_11ac_max_mcs vht_max_mcs;
|
||||
|
||||
ENTER_DEV(dev);
|
||||
|
||||
|
|
@ -3356,16 +4144,16 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
|
|||
sme_cfg_get_int(WLAN_HDD_GET_HAL_CTX(pAdapter),
|
||||
WNI_CFG_VHT_TX_MCS_MAP,
|
||||
&vht_mcs_map);
|
||||
vhtMaxMcs = (enum eDataRate11ACMaxMcs)
|
||||
vht_max_mcs = (enum data_rate_11ac_max_mcs)
|
||||
(vht_mcs_map & DATA_RATE_11AC_MCS_MASK);
|
||||
if (rate_flags & eHAL_TX_RATE_SGI)
|
||||
rateFlag |= 1;
|
||||
|
||||
if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
|
||||
if (DATA_RATE_11AC_MAX_MCS_7 == vht_max_mcs)
|
||||
maxMCSIdx = 7;
|
||||
else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
|
||||
else if (DATA_RATE_11AC_MAX_MCS_8 == vht_max_mcs)
|
||||
maxMCSIdx = 8;
|
||||
else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
|
||||
else if (DATA_RATE_11AC_MAX_MCS_9 == vht_max_mcs)
|
||||
maxMCSIdx = 9;
|
||||
|
||||
if (rssidx != 0) {
|
||||
|
|
|
|||
|
|
@ -57,13 +57,13 @@ struct index_vht_data_rate_type {
|
|||
};
|
||||
|
||||
/**
|
||||
* enum - eDataRate11ACMaxMcs
|
||||
* enum - data_rate_11ac_max_mcs
|
||||
* @DATA_RATE_11AC_MAX_MCS_7: MCS7 rate
|
||||
* @DATA_RATE_11AC_MAX_MCS_8: MCS8 rate
|
||||
* @DATA_RATE_11AC_MAX_MCS_9: MCS9 rate
|
||||
* @DATA_RATE_11AC_MAX_MCS_NA:i Not applicable
|
||||
*/
|
||||
enum eDataRate11ACMaxMcs {
|
||||
enum data_rate_11ac_max_mcs {
|
||||
DATA_RATE_11AC_MAX_MCS_7,
|
||||
DATA_RATE_11AC_MAX_MCS_8,
|
||||
DATA_RATE_11AC_MAX_MCS_9,
|
||||
|
|
|
|||
|
|
@ -3889,6 +3889,226 @@ int wlan_hdd_get_link_speed(hdd_adapter_t *sta_adapter, uint32_t *link_speed)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct peer_rssi_priv {
|
||||
struct sir_peer_sta_info peer_sta_info;
|
||||
};
|
||||
|
||||
/**
|
||||
* hdd_get_peer_rssi_cb() - get peer station's rssi callback
|
||||
* @sta_rssi: pointer of peer information
|
||||
* @context: get rssi callback context
|
||||
*
|
||||
* This function will fill rssi information to rssi priv
|
||||
* adapter
|
||||
*
|
||||
*/
|
||||
static void hdd_get_peer_rssi_cb(struct sir_peer_info_resp *sta_rssi,
|
||||
void *context)
|
||||
{
|
||||
struct hdd_request *request;
|
||||
struct peer_rssi_priv *priv;
|
||||
struct sir_peer_info *rssi_info;
|
||||
uint8_t peer_num;
|
||||
|
||||
if ((!sta_rssi) || (!context)) {
|
||||
hdd_err("Bad param, sta_rssi [%p] context [%p]",
|
||||
sta_rssi, context);
|
||||
return;
|
||||
}
|
||||
|
||||
request = hdd_request_get(context);
|
||||
if (!request) {
|
||||
hdd_err("Obsolete request");
|
||||
return;
|
||||
}
|
||||
|
||||
priv = hdd_request_priv(request);
|
||||
|
||||
peer_num = sta_rssi->count;
|
||||
rssi_info = sta_rssi->info;
|
||||
|
||||
hdd_debug("%d peers", peer_num);
|
||||
|
||||
if (peer_num > MAX_PEER_STA) {
|
||||
hdd_warn("Exceed max peer sta to handle one time %d", peer_num);
|
||||
peer_num = MAX_PEER_STA;
|
||||
}
|
||||
|
||||
qdf_mem_copy(priv->peer_sta_info.info, rssi_info,
|
||||
peer_num * sizeof(*rssi_info));
|
||||
priv->peer_sta_info.sta_num = peer_num;
|
||||
|
||||
hdd_request_complete(request);
|
||||
hdd_request_put(request);
|
||||
}
|
||||
|
||||
int wlan_hdd_get_peer_rssi(hdd_adapter_t *adapter,
|
||||
struct qdf_mac_addr *macaddress,
|
||||
struct sir_peer_sta_info *peer_sta_info)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
void *cookie;
|
||||
int ret;
|
||||
struct sir_peer_info_req rssi_req;
|
||||
struct hdd_request *request;
|
||||
struct peer_rssi_priv *priv;
|
||||
static const struct hdd_request_params params = {
|
||||
.priv_size = sizeof(*priv),
|
||||
.timeout_ms = WLAN_WAIT_TIME_STATS,
|
||||
};
|
||||
|
||||
if (!adapter || !macaddress || !peer_sta_info) {
|
||||
hdd_err("pAdapter [%p], macaddress [%p], peer_sta_info[%p]",
|
||||
adapter, macaddress, peer_sta_info);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
request = hdd_request_alloc(¶ms);
|
||||
if (!request) {
|
||||
hdd_err("Request allocation failure");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cookie = hdd_request_cookie(request);
|
||||
priv = hdd_request_priv(request);
|
||||
|
||||
qdf_mem_copy(&rssi_req.peer_macaddr, macaddress,
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
rssi_req.sessionid = adapter->sessionId;
|
||||
status = sme_get_peer_info(WLAN_HDD_GET_HAL_CTX(adapter),
|
||||
rssi_req,
|
||||
cookie,
|
||||
hdd_get_peer_rssi_cb);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
hdd_err("Unable to retrieve statistics for rssi");
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
ret = hdd_request_wait_for_response(request);
|
||||
if (ret) {
|
||||
hdd_err("SME timed out while retrieving rssi");
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
*peer_sta_info = priv->peer_sta_info;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
hdd_request_put(request);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct peer_info_priv {
|
||||
struct sir_peer_sta_ext_info peer_sta_ext_info;
|
||||
};
|
||||
|
||||
/**
|
||||
* wlan_hdd_get_peer_info_cb() - get peer info callback
|
||||
* @sta_info: pointer of peer information
|
||||
* @context: get peer info callback context
|
||||
*
|
||||
* This function will fill stats info to peer info priv
|
||||
*
|
||||
*/
|
||||
static void wlan_hdd_get_peer_info_cb(struct sir_peer_info_ext_resp *sta_info,
|
||||
void *context)
|
||||
{
|
||||
struct hdd_request *request;
|
||||
struct peer_info_priv *priv;
|
||||
uint8_t sta_num;
|
||||
|
||||
if ((!sta_info) || (!context)) {
|
||||
hdd_err("Bad param, sta_info [%p] context [%p]",
|
||||
sta_info, context);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sta_info->count) {
|
||||
hdd_err("Fail to get remote peer info");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sta_info->count > MAX_PEER_STA) {
|
||||
hdd_warn("Exceed max peer number %d", sta_info->count);
|
||||
sta_num = MAX_PEER_STA;
|
||||
} else {
|
||||
sta_num = sta_info->count;
|
||||
}
|
||||
|
||||
request = hdd_request_get(context);
|
||||
if (!request) {
|
||||
hdd_err("Obsolete request");
|
||||
return;
|
||||
}
|
||||
|
||||
priv = hdd_request_priv(request);
|
||||
|
||||
priv->peer_sta_ext_info.sta_num = sta_num;
|
||||
qdf_mem_copy(&priv->peer_sta_ext_info.info,
|
||||
sta_info->info,
|
||||
sta_num * sizeof(sta_info->info[0]));
|
||||
|
||||
hdd_request_complete(request);
|
||||
hdd_request_put(request);
|
||||
}
|
||||
|
||||
int wlan_hdd_get_peer_info(hdd_adapter_t *adapter,
|
||||
struct qdf_mac_addr macaddress,
|
||||
struct sir_peer_info_ext *peer_info_ext)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
void *cookie;
|
||||
int ret;
|
||||
struct sir_peer_info_ext_req peer_info_req;
|
||||
struct hdd_request *request;
|
||||
struct peer_info_priv *priv;
|
||||
static const struct hdd_request_params params = {
|
||||
.priv_size = sizeof(*priv),
|
||||
.timeout_ms = WLAN_WAIT_TIME_STATS,
|
||||
};
|
||||
|
||||
if (!adapter) {
|
||||
hdd_err("pAdapter is NULL");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
request = hdd_request_alloc(¶ms);
|
||||
if (!request) {
|
||||
hdd_err("Request allocation failure");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cookie = hdd_request_cookie(request);
|
||||
priv = hdd_request_priv(request);
|
||||
|
||||
qdf_mem_copy(&peer_info_req.peer_macaddr, &macaddress,
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
peer_info_req.sessionid = adapter->sessionId;
|
||||
peer_info_req.reset_after_request = 0;
|
||||
status = sme_get_peer_info_ext(WLAN_HDD_GET_HAL_CTX(adapter),
|
||||
&peer_info_req,
|
||||
cookie,
|
||||
wlan_hdd_get_peer_info_cb);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
hdd_err("Unable to retrieve statistics for peer info");
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
ret = hdd_request_wait_for_response(request);
|
||||
if (ret) {
|
||||
hdd_err("SME timed out while retrieving peer info");
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
/* only support one peer by now */
|
||||
*peer_info_ext = priv->peer_sta_ext_info.info[0];
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
hdd_request_put(request);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_statistics_cb() - "Get statistics" callback function
|
||||
* @pStats: statistics payload
|
||||
|
|
|
|||
|
|
@ -127,6 +127,9 @@ typedef uint8_t tSirVersionString[SIR_VERSION_STRING_LEN];
|
|||
/* Cache ID length */
|
||||
#define CACHE_ID_LEN 2
|
||||
|
||||
/* Maximum peer station number query one time */
|
||||
#define MAX_PEER_STA 12
|
||||
|
||||
/**
|
||||
* enum sir_conn_update_reason: Reason for conc connection update
|
||||
* @SIR_UPDATE_REASON_SET_OPER_CHAN: Set probable operating channel
|
||||
|
|
@ -3807,6 +3810,28 @@ struct sir_peer_info_ext_resp {
|
|||
struct sir_peer_info_ext info[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* @sta_num: number of peer station which has valid info
|
||||
* @info: peer information
|
||||
*
|
||||
* all SAP peer station's information retrieved
|
||||
*/
|
||||
struct sir_peer_sta_info {
|
||||
uint8_t sta_num;
|
||||
struct sir_peer_info info[MAX_PEER_STA];
|
||||
};
|
||||
|
||||
/**
|
||||
* @sta_num: number of peer station which has valid info
|
||||
* @info: peer extended information
|
||||
*
|
||||
* all SAP peer station's extended information retrieved
|
||||
*/
|
||||
struct sir_peer_sta_ext_info {
|
||||
uint8_t sta_num;
|
||||
struct sir_peer_info_ext info[MAX_PEER_STA];
|
||||
};
|
||||
|
||||
typedef struct sSirAddPeriodicTxPtrn {
|
||||
/* MAC Address for the adapter */
|
||||
struct qdf_mac_addr mac_address;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ struct wma_tgt_services {
|
|||
bool en_roam_offload;
|
||||
#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
|
||||
bool en_11ax;
|
||||
bool get_peer_info_enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -754,6 +754,8 @@ QDF_STATUS wma_get_peer_info(WMA_HANDLE handle,
|
|||
|
||||
cmd->stats_id = WMI_REQUEST_PEER_STAT;
|
||||
cmd->vdev_id = peer_info_req->sessionid;
|
||||
WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_info_req->peer_macaddr.bytes,
|
||||
&cmd->peer_macaddr);
|
||||
wma_handle->get_sta_peer_info = true;
|
||||
|
||||
if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
|
||||
|
|
|
|||
|
|
@ -4059,6 +4059,10 @@ static inline void wma_update_target_services(tp_wma_handle wh,
|
|||
}
|
||||
|
||||
wma_he_update_tgt_services(wh, cfg);
|
||||
|
||||
cfg->get_peer_info_enabled =
|
||||
WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap,
|
||||
WMI_SERVICE_PEER_STATS_INFO);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue