Skip to content

Commit 1f0dc59

Browse files
Arend van SprielKalle Valo
authored andcommitted
brcmfmac: rework .get_station() callback
The .get_station() cfg80211 callback is used in several scenarios. In managed mode it can obtain information about the access-point and its BSS parameters. In managed mode it can also obtain information about TDLS peers. In AP mode it can obtain information about connected clients. Reviewed-by: Hante Meuleman <[email protected]> Reviewed-by: Daniel (Deognyoun) Kim <[email protected]> Reviewed-by: Franky (Zhenhui) Lin <[email protected]> Reviewed-by: Pieter-Paul Giesberts <[email protected]> Signed-off-by: Arend van Spriel <[email protected]> Signed-off-by: Kalle Valo <[email protected]>
1 parent 2e5f66f commit 1f0dc59

File tree

2 files changed

+161
-92
lines changed

2 files changed

+161
-92
lines changed

drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c

Lines changed: 101 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,101 +2396,129 @@ brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp)
23962396
brcmf_err("set wsec error (%d)\n", err);
23972397
}
23982398

2399+
static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si)
2400+
{
2401+
struct nl80211_sta_flag_update *sfu;
2402+
2403+
brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags);
2404+
si->filled |= BIT(NL80211_STA_INFO_STA_FLAGS);
2405+
sfu = &si->sta_flags;
2406+
sfu->mask = BIT(NL80211_STA_FLAG_WME) |
2407+
BIT(NL80211_STA_FLAG_AUTHENTICATED) |
2408+
BIT(NL80211_STA_FLAG_ASSOCIATED) |
2409+
BIT(NL80211_STA_FLAG_AUTHORIZED);
2410+
if (fw_sta_flags & BRCMF_STA_WME)
2411+
sfu->set |= BIT(NL80211_STA_FLAG_WME);
2412+
if (fw_sta_flags & BRCMF_STA_AUTHE)
2413+
sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
2414+
if (fw_sta_flags & BRCMF_STA_ASSOC)
2415+
sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
2416+
if (fw_sta_flags & BRCMF_STA_AUTHO)
2417+
sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
2418+
}
2419+
2420+
static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)
2421+
{
2422+
struct {
2423+
__le32 len;
2424+
struct brcmf_bss_info_le bss_le;
2425+
} *buf;
2426+
u16 capability;
2427+
int err;
2428+
2429+
buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2430+
if (!buf)
2431+
return;
2432+
2433+
buf->len = cpu_to_le32(WL_BSS_INFO_MAX);
2434+
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf,
2435+
WL_BSS_INFO_MAX);
2436+
if (err) {
2437+
brcmf_err("Failed to get bss info (%d)\n", err);
2438+
return;
2439+
}
2440+
si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
2441+
si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period);
2442+
si->bss_param.dtim_period = buf->bss_le.dtim_period;
2443+
capability = le16_to_cpu(buf->bss_le.capability);
2444+
if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT)
2445+
si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
2446+
if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
2447+
si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
2448+
if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
2449+
si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
2450+
}
2451+
23992452
static s32
24002453
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
24012454
const u8 *mac, struct station_info *sinfo)
24022455
{
24032456
struct brcmf_if *ifp = netdev_priv(ndev);
2404-
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
2405-
struct brcmf_scb_val_le scb_val;
2406-
int rssi;
2407-
s32 rate;
24082457
s32 err = 0;
2409-
u8 *bssid = profile->bssid;
24102458
struct brcmf_sta_info_le sta_info_le;
2411-
u32 beacon_period;
2412-
u32 dtim_period;
2459+
u32 sta_flags;
2460+
u32 is_tdls_peer;
24132461

24142462
brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
24152463
if (!check_vif_up(ifp->vif))
24162464
return -EIO;
24172465

2418-
if (brcmf_is_apmode(ifp->vif)) {
2419-
memcpy(&sta_info_le, mac, ETH_ALEN);
2466+
memset(&sta_info_le, 0, sizeof(sta_info_le));
2467+
memcpy(&sta_info_le, mac, ETH_ALEN);
2468+
err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info",
2469+
&sta_info_le,
2470+
sizeof(sta_info_le));
2471+
is_tdls_peer = !err;
2472+
if (err) {
24202473
err = brcmf_fil_iovar_data_get(ifp, "sta_info",
24212474
&sta_info_le,
24222475
sizeof(sta_info_le));
24232476
if (err < 0) {
24242477
brcmf_err("GET STA INFO failed, %d\n", err);
24252478
goto done;
24262479
}
2427-
sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
2428-
sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
2429-
if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
2430-
sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
2431-
sinfo->connected_time = le32_to_cpu(sta_info_le.in);
2432-
}
2433-
brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
2434-
sinfo->inactive_time, sinfo->connected_time);
2435-
} else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) {
2436-
if (memcmp(mac, bssid, ETH_ALEN)) {
2437-
brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
2438-
mac, bssid);
2439-
err = -ENOENT;
2440-
goto done;
2441-
}
2442-
/* Report the current tx rate */
2443-
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
2444-
if (err) {
2445-
brcmf_err("Could not get rate (%d)\n", err);
2446-
goto done;
2447-
} else {
2480+
}
2481+
brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
2482+
sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
2483+
sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
2484+
sta_flags = le32_to_cpu(sta_info_le.flags);
2485+
brcmf_convert_sta_flags(sta_flags, sinfo);
2486+
sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
2487+
if (is_tdls_peer)
2488+
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
2489+
else
2490+
sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
2491+
if (sta_flags & BRCMF_STA_ASSOC) {
2492+
sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
2493+
sinfo->connected_time = le32_to_cpu(sta_info_le.in);
2494+
brcmf_fill_bss_param(ifp, sinfo);
2495+
}
2496+
if (sta_flags & BRCMF_STA_SCBSTATS) {
2497+
sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED);
2498+
sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures);
2499+
sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
2500+
sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts);
2501+
sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts);
2502+
sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
2503+
sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts);
2504+
sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts);
2505+
if (sinfo->tx_packets) {
24482506
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
2449-
sinfo->txrate.legacy = rate * 5;
2450-
brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2);
2507+
sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate);
2508+
sinfo->txrate.legacy /= 100;
24512509
}
2452-
2453-
if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
2454-
&ifp->vif->sme_state)) {
2455-
memset(&scb_val, 0, sizeof(scb_val));
2456-
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
2457-
&scb_val, sizeof(scb_val));
2458-
if (err) {
2459-
brcmf_err("Could not get rssi (%d)\n", err);
2460-
goto done;
2461-
} else {
2462-
rssi = le32_to_cpu(scb_val.val);
2463-
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
2464-
sinfo->signal = rssi;
2465-
brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
2466-
}
2467-
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD,
2468-
&beacon_period);
2469-
if (err) {
2470-
brcmf_err("Could not get beacon period (%d)\n",
2471-
err);
2472-
goto done;
2473-
} else {
2474-
sinfo->bss_param.beacon_interval =
2475-
beacon_period;
2476-
brcmf_dbg(CONN, "Beacon peroid %d\n",
2477-
beacon_period);
2478-
}
2479-
err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD,
2480-
&dtim_period);
2481-
if (err) {
2482-
brcmf_err("Could not get DTIM period (%d)\n",
2483-
err);
2484-
goto done;
2485-
} else {
2486-
sinfo->bss_param.dtim_period = dtim_period;
2487-
brcmf_dbg(CONN, "DTIM peroid %d\n",
2488-
dtim_period);
2489-
}
2490-
sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
2510+
if (sinfo->rx_packets) {
2511+
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
2512+
sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate);
2513+
sinfo->rxrate.legacy /= 100;
24912514
}
2492-
} else
2493-
err = -EPERM;
2515+
if (le16_to_cpu(sta_info_le.ver) >= 4) {
2516+
sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES);
2517+
sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
2518+
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES);
2519+
sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
2520+
}
2521+
}
24942522
done:
24952523
brcmf_dbg(TRACE, "Exit\n");
24962524
return err;

drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@
3232
#define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */
3333
#define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002
3434

35-
#define BRCMF_STA_ASSOC 0x10 /* Associated */
35+
#define BRCMF_STA_WME 0x00000002 /* WMM association */
36+
#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */
37+
#define BRCMF_STA_ASSOC 0x00000010 /* Associated */
38+
#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */
39+
#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
3640

3741
/* size of brcmf_scan_params not including variable length array */
3842
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
@@ -113,6 +117,7 @@
113117
#define BRCMF_WOWL_MAXPATTERNSIZE 128
114118

115119
#define BRCMF_COUNTRY_BUF_SZ 4
120+
#define BRCMF_ANT_MAX 4
116121

117122
/* join preference types for join_pref iovar */
118123
enum brcmf_join_pref_types {
@@ -456,25 +461,61 @@ struct brcmf_channel_info_le {
456461
};
457462

458463
struct brcmf_sta_info_le {
459-
__le16 ver; /* version of this struct */
460-
__le16 len; /* length in bytes of this structure */
461-
__le16 cap; /* sta's advertised capabilities */
462-
__le32 flags; /* flags defined below */
463-
__le32 idle; /* time since data pkt rx'd from sta */
464-
u8 ea[ETH_ALEN]; /* Station address */
465-
__le32 count; /* # rates in this set */
466-
u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
464+
__le16 ver; /* version of this struct */
465+
__le16 len; /* length in bytes of this structure */
466+
__le16 cap; /* sta's advertised capabilities */
467+
__le32 flags; /* flags defined below */
468+
__le32 idle; /* time since data pkt rx'd from sta */
469+
u8 ea[ETH_ALEN]; /* Station address */
470+
__le32 count; /* # rates in this set */
471+
u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
467472
/* w/hi bit set if basic */
468-
__le32 in; /* seconds elapsed since associated */
469-
__le32 listen_interval_inms; /* Min Listen interval in ms for STA */
470-
__le32 tx_pkts; /* # of packets transmitted */
471-
__le32 tx_failures; /* # of packets failed */
472-
__le32 rx_ucast_pkts; /* # of unicast packets received */
473-
__le32 rx_mcast_pkts; /* # of multicast packets received */
474-
__le32 tx_rate; /* Rate of last successful tx frame */
475-
__le32 rx_rate; /* Rate of last successful rx frame */
476-
__le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
477-
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
473+
__le32 in; /* seconds elapsed since associated */
474+
__le32 listen_interval_inms; /* Min Listen interval in ms for STA */
475+
__le32 tx_pkts; /* # of packets transmitted */
476+
__le32 tx_failures; /* # of packets failed */
477+
__le32 rx_ucast_pkts; /* # of unicast packets received */
478+
__le32 rx_mcast_pkts; /* # of multicast packets received */
479+
__le32 tx_rate; /* Rate of last successful tx frame */
480+
__le32 rx_rate; /* Rate of last successful rx frame */
481+
__le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
482+
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
483+
__le32 tx_tot_pkts; /* # of tx pkts (ucast + mcast) */
484+
__le32 rx_tot_pkts; /* # of data packets recvd (uni + mcast) */
485+
__le32 tx_mcast_pkts; /* # of mcast pkts txed */
486+
__le64 tx_tot_bytes; /* data bytes txed (ucast + mcast) */
487+
__le64 rx_tot_bytes; /* data bytes recvd (ucast + mcast) */
488+
__le64 tx_ucast_bytes; /* data bytes txed (ucast) */
489+
__le64 tx_mcast_bytes; /* # data bytes txed (mcast) */
490+
__le64 rx_ucast_bytes; /* data bytes recvd (ucast) */
491+
__le64 rx_mcast_bytes; /* data bytes recvd (mcast) */
492+
s8 rssi[BRCMF_ANT_MAX]; /* per antenna rssi */
493+
s8 nf[BRCMF_ANT_MAX]; /* per antenna noise floor */
494+
__le16 aid; /* association ID */
495+
__le16 ht_capabilities; /* advertised ht caps */
496+
__le16 vht_flags; /* converted vht flags */
497+
__le32 tx_pkts_retry_cnt; /* # of frames where a retry was
498+
* exhausted.
499+
*/
500+
__le32 tx_pkts_retry_exhausted; /* # of user frames where a retry
501+
* was exhausted
502+
*/
503+
s8 rx_lastpkt_rssi[BRCMF_ANT_MAX]; /* Per antenna RSSI of last
504+
* received data frame.
505+
*/
506+
/* TX WLAN retry/failure statistics:
507+
* Separated for host requested frames and locally generated frames.
508+
* Include unicast frame only where the retries/failures can be counted.
509+
*/
510+
__le32 tx_pkts_total; /* # user frames sent successfully */
511+
__le32 tx_pkts_retries; /* # user frames retries */
512+
__le32 tx_pkts_fw_total; /* # FW generated sent successfully */
513+
__le32 tx_pkts_fw_retries; /* # retries for FW generated frames */
514+
__le32 tx_pkts_fw_retry_exhausted; /* # FW generated where a retry
515+
* was exhausted
516+
*/
517+
__le32 rx_pkts_retried; /* # rx with retry bit set */
518+
__le32 tx_rate_fallback; /* lowest fallback TX rate */
478519
};
479520

480521
struct brcmf_chanspec_list {

0 commit comments

Comments
 (0)