qcacld-3.0: Add vendor command to get sta info
Add subcmd QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO and related attributes. Change-Id: I2bd90d90666b95902dc0821d762adbc5c5e675c6 CRs-fixed: 2592863
This commit is contained in:
@@ -925,8 +925,9 @@ struct hdd_mic_work {
|
|||||||
* @tx_bytes: bytes transmitted to this station
|
* @tx_bytes: bytes transmitted to this station
|
||||||
* @rx_packets: packets received from this station
|
* @rx_packets: packets received from this station
|
||||||
* @rx_bytes: bytes received from this station
|
* @rx_bytes: bytes received from this station
|
||||||
* @rx_retries: cumulative retry counts
|
* @tx_retries: cumulative retry counts
|
||||||
* @tx_failed: number of failed transmissions
|
* @tx_failed: the number of failed frames
|
||||||
|
* @tx_succeed: the number of succeed frames
|
||||||
* @rssi: The signal strength (dbm)
|
* @rssi: The signal strength (dbm)
|
||||||
* @tx_rate: last used tx rate info
|
* @tx_rate: last used tx rate info
|
||||||
* @rx_rate: last used rx rate info
|
* @rx_rate: last used rx rate info
|
||||||
@@ -940,6 +941,7 @@ struct hdd_fw_txrx_stats {
|
|||||||
uint64_t rx_bytes;
|
uint64_t rx_bytes;
|
||||||
uint32_t tx_retries;
|
uint32_t tx_retries;
|
||||||
uint32_t tx_failed;
|
uint32_t tx_failed;
|
||||||
|
uint32_t tx_succeed;
|
||||||
int8_t rssi;
|
int8_t rssi;
|
||||||
struct hdd_rate_info tx_rate;
|
struct hdd_rate_info tx_rate;
|
||||||
struct hdd_rate_info rx_rate;
|
struct hdd_rate_info rx_rate;
|
||||||
|
@@ -174,7 +174,7 @@ char *sta_info_string_from_dbgid(wlan_sta_info_dbgid id);
|
|||||||
* @rate_flags: Rate Flags for this connection
|
* @rate_flags: Rate Flags for this connection
|
||||||
* @ecsa_capable: Extended CSA capabilities
|
* @ecsa_capable: Extended CSA capabilities
|
||||||
* @max_phy_rate: Calcuated maximum phy rate based on mode, nss, mcs etc.
|
* @max_phy_rate: Calcuated maximum phy rate based on mode, nss, mcs etc.
|
||||||
* @tx_packets: Packets send to current station
|
* @tx_packets: The number of frames from host to firmware
|
||||||
* @tx_bytes: Bytes send to current station
|
* @tx_bytes: Bytes send to current station
|
||||||
* @rx_packets: Packets received from current station
|
* @rx_packets: Packets received from current station
|
||||||
* @rx_bytes: Bytes received from current station
|
* @rx_bytes: Bytes received from current station
|
||||||
@@ -184,6 +184,7 @@ char *sta_info_string_from_dbgid(wlan_sta_info_dbgid id);
|
|||||||
* @rx_rate: Rx 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
|
* @ampdu: Ampdu enable or not of the station
|
||||||
* @sgi_enable: Short GI enable or not of the station
|
* @sgi_enable: Short GI enable or not of the station
|
||||||
|
* @guard_interval: Guard interval
|
||||||
* @tx_stbc: Tx Space-time block coding enable/disable
|
* @tx_stbc: Tx Space-time block coding enable/disable
|
||||||
* @rx_stbc: Rx Space-time block coding enable/disable
|
* @rx_stbc: Rx Space-time block coding enable/disable
|
||||||
* @ch_width: Channel Width of the connection
|
* @ch_width: Channel Width of the connection
|
||||||
@@ -211,6 +212,13 @@ char *sta_info_string_from_dbgid(wlan_sta_info_dbgid id);
|
|||||||
* MSB of rx_mc_bc_cnt indicates whether FW supports rx_mc_bc_cnt
|
* MSB of rx_mc_bc_cnt indicates whether FW supports rx_mc_bc_cnt
|
||||||
* feature or not, if first bit is 1 it indicates that FW supports this
|
* feature or not, if first bit is 1 it indicates that FW supports this
|
||||||
* feature, if it is 0 it indicates FW doesn't support this feature
|
* feature, if it is 0 it indicates FW doesn't support this feature
|
||||||
|
* @tx_retry_succeed: the number of frames retried but successfully transmit
|
||||||
|
* @tx_retry_exhaust: the number of frames retried but finally failed
|
||||||
|
* from host to firmware
|
||||||
|
* @tx_total_fw: the number of all frames from firmware to remote station
|
||||||
|
* @tx_retry_fw: the number of retried frames from firmware to remote station
|
||||||
|
* @tx_retry_exhaust_fw: the number of frames retried but finally failed from
|
||||||
|
* firmware to remote station
|
||||||
* @sta_info: The sta_info node for the station info list maintained in adapter
|
* @sta_info: The sta_info node for the station info list maintained in adapter
|
||||||
* @assoc_req_ies: Assoc request IEs of the peer station
|
* @assoc_req_ies: Assoc request IEs of the peer station
|
||||||
* @ref_cnt: Reference count to synchronize sta_info access
|
* @ref_cnt: Reference count to synchronize sta_info access
|
||||||
@@ -242,6 +250,7 @@ struct hdd_station_info {
|
|||||||
uint32_t rx_rate;
|
uint32_t rx_rate;
|
||||||
bool ampdu;
|
bool ampdu;
|
||||||
bool sgi_enable;
|
bool sgi_enable;
|
||||||
|
enum txrate_gi guard_interval;
|
||||||
bool tx_stbc;
|
bool tx_stbc;
|
||||||
bool rx_stbc;
|
bool rx_stbc;
|
||||||
tSirMacHTChannelWidth ch_width;
|
tSirMacHTChannelWidth ch_width;
|
||||||
@@ -265,6 +274,11 @@ struct hdd_station_info {
|
|||||||
uint8_t support_mode;
|
uint8_t support_mode;
|
||||||
uint32_t rx_retry_cnt;
|
uint32_t rx_retry_cnt;
|
||||||
uint32_t rx_mc_bc_cnt;
|
uint32_t rx_mc_bc_cnt;
|
||||||
|
uint32_t tx_retry_succeed;
|
||||||
|
uint32_t tx_retry_exhaust;
|
||||||
|
uint32_t tx_total_fw;
|
||||||
|
uint32_t tx_retry_fw;
|
||||||
|
uint32_t tx_retry_exhaust_fw;
|
||||||
qdf_list_node_t sta_node;
|
qdf_list_node_t sta_node;
|
||||||
struct wlan_ies assoc_req_ies;
|
struct wlan_ies assoc_req_ies;
|
||||||
qdf_atomic_t ref_cnt;
|
qdf_atomic_t ref_cnt;
|
||||||
|
@@ -38,6 +38,11 @@
|
|||||||
#include "wlan_hdd_sta_info.h"
|
#include "wlan_hdd_sta_info.h"
|
||||||
#include "wlan_hdd_object_manager.h"
|
#include "wlan_hdd_object_manager.h"
|
||||||
|
|
||||||
|
#include <cdp_txrx_handle.h>
|
||||||
|
#include <cdp_txrx_stats_struct.h>
|
||||||
|
#include <cdp_txrx_peer_ops.h>
|
||||||
|
#include <cdp_txrx_host_stats.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* define short names for the global vendor params
|
* define short names for the global vendor params
|
||||||
* used by __wlan_hdd_cfg80211_get_station_cmd()
|
* used by __wlan_hdd_cfg80211_get_station_cmd()
|
||||||
@@ -130,6 +135,12 @@ hdd_get_station_policy[STATION_MAX + 1] = {
|
|||||||
[STATION_REMOTE] = {.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
|
[STATION_REMOTE] = {.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct nla_policy
|
||||||
|
hdd_get_sta_policy[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1] = {
|
||||||
|
[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC] = {.type = NLA_BINARY,
|
||||||
|
.len = QDF_MAC_ADDR_SIZE},
|
||||||
|
};
|
||||||
|
|
||||||
static int hdd_get_sta_congestion(struct hdd_adapter *adapter,
|
static int hdd_get_sta_congestion(struct hdd_adapter *adapter,
|
||||||
uint32_t *congestion)
|
uint32_t *congestion)
|
||||||
{
|
{
|
||||||
@@ -1473,3 +1484,451 @@ int32_t hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
|
|||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hdd_get_peer_stats - get peer statistics information
|
||||||
|
* @adapter: pointer to adapter
|
||||||
|
* @stainfo: station information
|
||||||
|
*
|
||||||
|
* This function gets peer statistics information
|
||||||
|
*
|
||||||
|
* Return : 0 on success and errno on failure
|
||||||
|
*/
|
||||||
|
static int hdd_get_peer_stats(struct hdd_adapter *adapter,
|
||||||
|
struct hdd_station_info *stainfo)
|
||||||
|
{
|
||||||
|
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
|
||||||
|
struct cdp_peer_stats *peer_stats;
|
||||||
|
struct stats_event *stats;
|
||||||
|
QDF_STATUS status;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
peer_stats = qdf_mem_malloc(sizeof(*peer_stats));
|
||||||
|
if (!peer_stats)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
status = cdp_host_get_peer_stats(soc, adapter->vdev_id,
|
||||||
|
stainfo->sta_mac.bytes, peer_stats);
|
||||||
|
if (status != QDF_STATUS_SUCCESS) {
|
||||||
|
hdd_err("cdp_host_get_peer_stats failed");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stainfo->rx_retry_cnt = peer_stats->rx.rx_retries;
|
||||||
|
stainfo->rx_mc_bc_cnt = peer_stats->rx.multicast.num +
|
||||||
|
peer_stats->rx.bcast.num;
|
||||||
|
|
||||||
|
qdf_mem_free(peer_stats);
|
||||||
|
peer_stats = NULL;
|
||||||
|
|
||||||
|
stats = wlan_cfg80211_mc_cp_stats_get_peer_stats(adapter->vdev,
|
||||||
|
stainfo->sta_mac.bytes,
|
||||||
|
&ret);
|
||||||
|
if (ret || !stats) {
|
||||||
|
wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
|
||||||
|
hdd_err("Failed to get peer stats info");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stainfo->tx_retry_succeed = stats->peer_stats_info_ext->tx_retries -
|
||||||
|
stats->peer_stats_info_ext->tx_failed;
|
||||||
|
/* This host counter is not supported
|
||||||
|
* since currently tx retry is not done in host side
|
||||||
|
*/
|
||||||
|
stainfo->tx_retry_exhaust = 0;
|
||||||
|
stainfo->tx_total_fw = stats->peer_stats_info_ext->tx_packets;
|
||||||
|
stainfo->tx_retry_fw = stats->peer_stats_info_ext->tx_retries;
|
||||||
|
stainfo->tx_retry_exhaust_fw = stats->peer_stats_info_ext->tx_failed;
|
||||||
|
|
||||||
|
wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hdd_add_peer_stats_get_len - get data length used in
|
||||||
|
* hdd_add_peer_stats()
|
||||||
|
* @stainfo: station information
|
||||||
|
*
|
||||||
|
* This function calculates the data length used in
|
||||||
|
* hdd_add_peer_stats()
|
||||||
|
*
|
||||||
|
* Return: total data length used in hdd_add_peer_stats()
|
||||||
|
*/
|
||||||
|
static uint32_t
|
||||||
|
hdd_add_peer_stats_get_len(struct hdd_station_info *stainfo)
|
||||||
|
{
|
||||||
|
return (nla_attr_size(sizeof(stainfo->rx_retry_cnt)) +
|
||||||
|
nla_attr_size(sizeof(stainfo->rx_mc_bc_cnt)) +
|
||||||
|
nla_attr_size(sizeof(stainfo->tx_retry_succeed)) +
|
||||||
|
nla_attr_size(sizeof(stainfo->tx_retry_exhaust)) +
|
||||||
|
nla_attr_size(sizeof(stainfo->tx_total_fw)) +
|
||||||
|
nla_attr_size(sizeof(stainfo->tx_retry_fw)) +
|
||||||
|
nla_attr_size(sizeof(stainfo->tx_retry_exhaust_fw)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hdd_add_peer_stats - add peer statistics information
|
||||||
|
* @skb: pointer to response skb buffer
|
||||||
|
* @stainfo: station information
|
||||||
|
*
|
||||||
|
* This function adds peer statistics information to response skb buffer
|
||||||
|
*
|
||||||
|
* Return : 0 on success and errno on failure
|
||||||
|
*/
|
||||||
|
static int hdd_add_peer_stats(struct sk_buff *skb,
|
||||||
|
struct hdd_station_info *stainfo)
|
||||||
|
{
|
||||||
|
if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_RETRY_COUNT,
|
||||||
|
stainfo->rx_retry_cnt)) {
|
||||||
|
hdd_err("Failed to put rx_retry_cnt");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BC_MC_COUNT,
|
||||||
|
stainfo->rx_mc_bc_cnt)) {
|
||||||
|
hdd_err("Failed to put rx_mc_bc_cnt");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_SUCCEED,
|
||||||
|
stainfo->tx_retry_succeed)) {
|
||||||
|
hdd_err("Failed to put tx_retry_succeed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_put_u32(skb,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_EXHAUSTED,
|
||||||
|
stainfo->tx_retry_exhaust)) {
|
||||||
|
hdd_err("Failed to put tx_retry_exhaust");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_TOTAL,
|
||||||
|
stainfo->tx_total_fw)) {
|
||||||
|
hdd_err("Failed to put tx_total_fw");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY,
|
||||||
|
stainfo->tx_retry_fw)) {
|
||||||
|
hdd_err("Failed to put tx_retry_fw");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_put_u32(skb,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED,
|
||||||
|
stainfo->tx_retry_exhaust_fw)) {
|
||||||
|
hdd_err("Failed to put tx_retry_exhaust_fw");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
fail:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hdd_get_station_info_ex() - send STA info to userspace, for STA mode only
|
||||||
|
* @hdd_ctx: pointer to hdd context
|
||||||
|
* @adapter: pointer to adapter
|
||||||
|
* @mac_addr: self mac address
|
||||||
|
*
|
||||||
|
* Return: 0 if success else error status
|
||||||
|
*/
|
||||||
|
static int hdd_get_station_info_ex(struct hdd_context *hdd_ctx,
|
||||||
|
struct hdd_adapter *adapter,
|
||||||
|
struct qdf_mac_addr mac_addr)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb = NULL;
|
||||||
|
uint32_t nl_buf_len;
|
||||||
|
struct hdd_station_ctx *hdd_sta_ctx;
|
||||||
|
struct hdd_station_info stainfo;
|
||||||
|
|
||||||
|
hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
|
||||||
|
if (!hdd_sta_ctx) {
|
||||||
|
hdd_err_rl("Invalid hdd_sta_ctx");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qdf_is_macaddr_equal(&mac_addr, &adapter->mac_addr)) {
|
||||||
|
hdd_err_rl("Invalid MAC address");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_mem_copy(&stainfo.sta_mac, &mac_addr, sizeof(stainfo.sta_mac));
|
||||||
|
|
||||||
|
if (hdd_get_peer_stats(adapter, &stainfo)) {
|
||||||
|
hdd_err_rl("hdd_get_peer_stats fail");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nl_buf_len = NLMSG_HDRLEN;
|
||||||
|
nl_buf_len += nla_attr_size(QDF_MAC_ADDR_SIZE) +
|
||||||
|
hdd_add_peer_stats_get_len(&stainfo);
|
||||||
|
|
||||||
|
skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
|
||||||
|
if (!skb) {
|
||||||
|
hdd_err_rl("cfg80211_vendor_cmd_alloc_reply_skb failed");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC,
|
||||||
|
QDF_MAC_ADDR_SIZE, mac_addr.bytes)) {
|
||||||
|
hdd_err_rl("Failed to put MAC address");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdd_add_peer_stats(skb, &stainfo)) {
|
||||||
|
hdd_err_rl("hdd_add_peer_stats fail");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg80211_vendor_cmd_reply(skb);
|
||||||
|
fail:
|
||||||
|
if (skb)
|
||||||
|
kfree_skb(skb);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hdd_get_connected_station_info_ex() - get connected peer's info
|
||||||
|
* @hdd_ctx: hdd context
|
||||||
|
* @adapter: hostapd interface
|
||||||
|
* @stainfo: pointer to hdd_station_info
|
||||||
|
*
|
||||||
|
* This function collect and indicate the connected peer's info
|
||||||
|
*
|
||||||
|
* Return: 0 on success, otherwise error value
|
||||||
|
*/
|
||||||
|
static int hdd_get_connected_station_info_ex(struct hdd_context *hdd_ctx,
|
||||||
|
struct hdd_adapter *adapter,
|
||||||
|
struct hdd_station_info *stainfo)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb = NULL;
|
||||||
|
uint32_t nl_buf_len, guard_interval;
|
||||||
|
bool sap_get_peer_info;
|
||||||
|
struct nl80211_sta_flag_update sta_flags = {0};
|
||||||
|
QDF_STATUS status;
|
||||||
|
|
||||||
|
if (hdd_get_peer_stats(adapter, stainfo)) {
|
||||||
|
hdd_err_rl("hdd_get_peer_stats fail");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nl_buf_len = NLMSG_HDRLEN;
|
||||||
|
nl_buf_len += nla_attr_size(QDF_MAC_ADDR_SIZE);
|
||||||
|
|
||||||
|
status = ucfg_mlme_get_sap_get_peer_info(hdd_ctx->psoc,
|
||||||
|
&sap_get_peer_info);
|
||||||
|
if (status != QDF_STATUS_SUCCESS)
|
||||||
|
hdd_err_rl("Unable to fetch sap ger peer info");
|
||||||
|
|
||||||
|
if (sap_get_peer_info)
|
||||||
|
nl_buf_len += hdd_add_peer_stats_get_len(stainfo);
|
||||||
|
|
||||||
|
if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY)
|
||||||
|
nl_buf_len += nla_attr_size(sizeof(sta_flags)) +
|
||||||
|
nla_attr_size(sizeof(guard_interval));
|
||||||
|
|
||||||
|
skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
|
||||||
|
if (!skb) {
|
||||||
|
hdd_err_rl("cfg80211_vendor_cmd_alloc_reply_skb failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC,
|
||||||
|
QDF_MAC_ADDR_SIZE, stainfo->sta_mac.bytes)) {
|
||||||
|
hdd_err_rl("Failed to put MAC address");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sap_get_peer_info && hdd_add_peer_stats(skb, stainfo)) {
|
||||||
|
hdd_err_rl("hdd_add_peer_stats fail");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
|
||||||
|
sta_flags.mask = QCA_VENDOR_WLAN_STA_FLAG_AMPDU |
|
||||||
|
QCA_VENDOR_WLAN_STA_FLAG_TX_STBC |
|
||||||
|
QCA_VENDOR_WLAN_STA_FLAG_RX_STBC;
|
||||||
|
|
||||||
|
if (stainfo->ampdu)
|
||||||
|
sta_flags.set |= QCA_VENDOR_WLAN_STA_FLAG_AMPDU;
|
||||||
|
if (stainfo->tx_stbc)
|
||||||
|
sta_flags.set |= QCA_VENDOR_WLAN_STA_FLAG_TX_STBC;
|
||||||
|
if (stainfo->rx_stbc)
|
||||||
|
sta_flags.set |= QCA_VENDOR_WLAN_STA_FLAG_RX_STBC;
|
||||||
|
|
||||||
|
if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_FLAGS,
|
||||||
|
sizeof(sta_flags), &sta_flags)) {
|
||||||
|
hdd_err_rl("Failed to put STA flags");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (stainfo->guard_interval) {
|
||||||
|
case TXRATE_GI_0_8_US:
|
||||||
|
guard_interval = QCA_VENDOR_WLAN_STA_GI_800_NS;
|
||||||
|
break;
|
||||||
|
case TXRATE_GI_0_4_US:
|
||||||
|
guard_interval = QCA_VENDOR_WLAN_STA_GI_400_NS;
|
||||||
|
break;
|
||||||
|
case TXRATE_GI_1_6_US:
|
||||||
|
guard_interval = QCA_VENDOR_WLAN_STA_GI_1600_NS;
|
||||||
|
break;
|
||||||
|
case TXRATE_GI_3_2_US:
|
||||||
|
guard_interval = QCA_VENDOR_WLAN_STA_GI_3200_NS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
hdd_err_rl("Invalid guard_interval %d",
|
||||||
|
stainfo->guard_interval);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nla_put_u32(skb,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_GUARD_INTERVAL,
|
||||||
|
guard_interval)) {
|
||||||
|
hdd_err_rl("Failed to put guard_interval");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg80211_vendor_cmd_reply(skb);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (skb)
|
||||||
|
kfree_skb(skb);
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hdd_get_station_remote_ex() - get remote peer's info, for SAP/GO mode only
|
||||||
|
* @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_ex(struct hdd_context *hdd_ctx,
|
||||||
|
struct hdd_adapter *adapter,
|
||||||
|
struct qdf_mac_addr mac_addr)
|
||||||
|
{
|
||||||
|
bool is_associated = false;
|
||||||
|
struct hdd_station_info *stainfo =
|
||||||
|
hdd_get_sta_info_by_mac(&adapter->sta_info_list,
|
||||||
|
mac_addr.bytes,
|
||||||
|
STA_INFO_HDD_GET_STATION_REMOTE);
|
||||||
|
|
||||||
|
/* For now, only connected STAs are supported */
|
||||||
|
if (!stainfo) {
|
||||||
|
hdd_err_rl("Failed to get peer STA");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_associated = hdd_is_peer_associated(adapter, &mac_addr);
|
||||||
|
if (!is_associated) {
|
||||||
|
hdd_err_rl("Peer STA is not associated");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hdd_get_connected_station_info_ex(hdd_ctx, adapter, stainfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __hdd_cfg80211_get_sta_info_cmd() - Handle get sta info vendor cmd
|
||||||
|
* @wiphy: pointer to wireless phy
|
||||||
|
* @wdev: wireless device
|
||||||
|
* @data: data
|
||||||
|
* @data_len: data length
|
||||||
|
*
|
||||||
|
* Handles QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO.
|
||||||
|
* Validate cmd attributes and send the station info to upper layers.
|
||||||
|
*
|
||||||
|
* Return: Success(0) or reason code for failure
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
__hdd_cfg80211_get_sta_info_cmd(struct wiphy *wiphy,
|
||||||
|
struct wireless_dev *wdev,
|
||||||
|
const void *data,
|
||||||
|
int data_len)
|
||||||
|
{
|
||||||
|
struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
|
||||||
|
struct net_device *dev = wdev->netdev;
|
||||||
|
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
|
||||||
|
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1];
|
||||||
|
struct qdf_mac_addr mac_addr;
|
||||||
|
int32_t status;
|
||||||
|
|
||||||
|
hdd_enter_dev(dev);
|
||||||
|
|
||||||
|
if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE ||
|
||||||
|
hdd_get_conparam() == QDF_GLOBAL_MONITOR_MODE) {
|
||||||
|
hdd_err_rl("Command not allowed in FTM / Monitor mode");
|
||||||
|
status = -EPERM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = wlan_hdd_validate_context(hdd_ctx);
|
||||||
|
if (status != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
status = wlan_cfg80211_nla_parse(tb,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX,
|
||||||
|
data, data_len,
|
||||||
|
hdd_get_sta_policy);
|
||||||
|
if (status) {
|
||||||
|
hdd_err_rl("Invalid ATTR");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tb[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC]) {
|
||||||
|
hdd_err_rl("MAC address is not present");
|
||||||
|
status = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
nla_memcpy(mac_addr.bytes, tb[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC],
|
||||||
|
QDF_MAC_ADDR_SIZE);
|
||||||
|
hdd_debug("STA " QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(mac_addr.bytes));
|
||||||
|
|
||||||
|
switch (adapter->device_mode) {
|
||||||
|
case QDF_STA_MODE:
|
||||||
|
case QDF_P2P_CLIENT_MODE:
|
||||||
|
status = hdd_get_station_info_ex(hdd_ctx, adapter, mac_addr);
|
||||||
|
break;
|
||||||
|
case QDF_SAP_MODE:
|
||||||
|
case QDF_P2P_GO_MODE:
|
||||||
|
status = hdd_get_station_remote_ex(hdd_ctx, adapter, mac_addr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
hdd_err_rl("Invalid device_mode: %d", adapter->device_mode);
|
||||||
|
status = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdd_exit();
|
||||||
|
out:
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t hdd_cfg80211_get_sta_info_cmd(struct wiphy *wiphy,
|
||||||
|
struct wireless_dev *wdev,
|
||||||
|
const void *data,
|
||||||
|
int data_len)
|
||||||
|
{
|
||||||
|
struct osif_vdev_sync *vdev_sync;
|
||||||
|
int errno;
|
||||||
|
|
||||||
|
errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
|
||||||
|
if (errno)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
errno = __hdd_cfg80211_get_sta_info_cmd(wiphy, wdev, data, data_len);
|
||||||
|
|
||||||
|
osif_vdev_sync_op_stop(vdev_sync);
|
||||||
|
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -46,6 +46,26 @@ int32_t hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
|
|||||||
const void *data,
|
const void *data,
|
||||||
int data_len);
|
int data_len);
|
||||||
|
|
||||||
|
extern const struct nla_policy hdd_get_sta_policy[
|
||||||
|
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wlan_hdd_cfg80211_get_sta_info_cmd() - Handle get sta info vendor cmd
|
||||||
|
* @wiphy: corestack handler
|
||||||
|
* @wdev: wireless device
|
||||||
|
* @data: data
|
||||||
|
* @data_len: data length
|
||||||
|
*
|
||||||
|
* Handles QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO.
|
||||||
|
* Validate cmd attributes and send the station info to upper layers.
|
||||||
|
*
|
||||||
|
* Return: Success(0) or reason code for failure
|
||||||
|
*/
|
||||||
|
int32_t hdd_cfg80211_get_sta_info_cmd(struct wiphy *wiphy,
|
||||||
|
struct wireless_dev *wdev,
|
||||||
|
const void *data,
|
||||||
|
int data_len);
|
||||||
|
|
||||||
#define FEATURE_STATION_INFO_VENDOR_COMMANDS \
|
#define FEATURE_STATION_INFO_VENDOR_COMMANDS \
|
||||||
{ \
|
{ \
|
||||||
.info.vendor_id = QCA_NL80211_VENDOR_ID, \
|
.info.vendor_id = QCA_NL80211_VENDOR_ID, \
|
||||||
@@ -56,6 +76,16 @@ int32_t hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
|
|||||||
.doit = hdd_cfg80211_get_station_cmd, \
|
.doit = hdd_cfg80211_get_station_cmd, \
|
||||||
vendor_command_policy(hdd_get_station_policy, \
|
vendor_command_policy(hdd_get_station_policy, \
|
||||||
QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX) \
|
QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX) \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.info.vendor_id = QCA_NL80211_VENDOR_ID, \
|
||||||
|
.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO, \
|
||||||
|
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | \
|
||||||
|
WIPHY_VENDOR_CMD_NEED_NETDEV | \
|
||||||
|
WIPHY_VENDOR_CMD_NEED_RUNNING, \
|
||||||
|
.doit = hdd_cfg80211_get_sta_info_cmd, \
|
||||||
|
vendor_command_policy(hdd_get_sta_policy, \
|
||||||
|
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX) \
|
||||||
},
|
},
|
||||||
#else /* FEATURE_STATION_INFO */
|
#else /* FEATURE_STATION_INFO */
|
||||||
#define FEATURE_STATION_INFO_VENDOR_COMMANDS
|
#define FEATURE_STATION_INFO_VENDOR_COMMANDS
|
||||||
|
@@ -4274,11 +4274,11 @@ static uint8_t hdd_get_rate_flags(uint32_t rate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wlan_hdd_fill_rate_info() - fill HDD rate info from SIR peer info
|
* wlan_hdd_fill_rate_info() - fill HDD rate info from peer info
|
||||||
* @txrx_stats: pointer to txrx stats to be filled with rate info
|
* @txrx_stats: pointer to txrx stats to be filled with rate info
|
||||||
* @peer_info: SIR peer info pointer
|
* @peer_info: peer info pointer
|
||||||
*
|
*
|
||||||
* This function is used to fill HDD rate info rom SIR peer info
|
* This function is used to fill HDD rate info from peer info
|
||||||
*
|
*
|
||||||
* Return: None
|
* Return: None
|
||||||
*/
|
*/
|
||||||
@@ -4407,6 +4407,7 @@ static int wlan_hdd_get_station_remote(struct wiphy *wiphy,
|
|||||||
txrx_stats.rx_bytes = stats->peer_stats_info_ext->rx_bytes;
|
txrx_stats.rx_bytes = stats->peer_stats_info_ext->rx_bytes;
|
||||||
txrx_stats.tx_retries = stats->peer_stats_info_ext->tx_retries;
|
txrx_stats.tx_retries = stats->peer_stats_info_ext->tx_retries;
|
||||||
txrx_stats.tx_failed = stats->peer_stats_info_ext->tx_failed;
|
txrx_stats.tx_failed = stats->peer_stats_info_ext->tx_failed;
|
||||||
|
txrx_stats.tx_succeed = stats->peer_stats_info_ext->tx_succeed;
|
||||||
txrx_stats.rssi = stats->peer_stats_info_ext->rssi
|
txrx_stats.rssi = stats->peer_stats_info_ext->rssi
|
||||||
+ WLAN_HDD_TGT_NOISE_FLOOR_DBM;
|
+ WLAN_HDD_TGT_NOISE_FLOOR_DBM;
|
||||||
wlan_hdd_fill_rate_info(&txrx_stats, stats->peer_stats_info_ext);
|
wlan_hdd_fill_rate_info(&txrx_stats, stats->peer_stats_info_ext);
|
||||||
|
Reference in New Issue
Block a user