Skip to content

Commit bf35443

Browse files
Avinash Patillinvjw
authored andcommitted
mwifiex: channel statistics support for mwifiex
This patch adds support to record channel statistics during scan. With extended scan, scan results are returned as events from FW while channel statistics are part of scan command response. We store these channel statistics in adapter. Signed-off-by: Avinash Patil <[email protected]> Signed-off-by: Xinmin Hu <[email protected]> Signed-off-by: Cathy Luo <[email protected]> Signed-off-by: John W. Linville <[email protected]>
1 parent 15a892e commit bf35443

File tree

7 files changed

+132
-3
lines changed

7 files changed

+132
-3
lines changed

drivers/net/wireless/mwifiex/cfg80211.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2840,6 +2840,25 @@ static const struct wiphy_coalesce_support mwifiex_coalesce_support = {
28402840
.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
28412841
};
28422842

2843+
int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
2844+
{
2845+
u32 n_channels_bg, n_channels_a = 0;
2846+
2847+
n_channels_bg = mwifiex_band_2ghz.n_channels;
2848+
2849+
if (adapter->config_bands & BAND_A)
2850+
n_channels_a = mwifiex_band_5ghz.n_channels;
2851+
2852+
adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a);
2853+
adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) *
2854+
adapter->num_in_chan_stats);
2855+
2856+
if (!adapter->chan_stats)
2857+
return -ENOMEM;
2858+
2859+
return 0;
2860+
}
2861+
28432862
/*
28442863
* This function registers the device with CFG802.11 subsystem.
28452864
*

drivers/net/wireless/mwifiex/decl.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,14 @@ struct mwifiex_arp_eth_header {
185185
u8 ar_tha[ETH_ALEN];
186186
u8 ar_tip[4];
187187
} __packed;
188+
189+
struct mwifiex_chan_stats {
190+
u8 chan_num;
191+
u8 bandcfg;
192+
u8 flags;
193+
s8 noise;
194+
u16 total_bss;
195+
u16 cca_scan_dur;
196+
u16 cca_busy_dur;
197+
} __packed;
188198
#endif /* !_MWIFIEX_DECL_H_ */

drivers/net/wireless/mwifiex/fw.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
172172
#define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194)
173173
#define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197)
174174
#define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199)
175+
#define TLV_TYPE_CHANNEL_STATS (PROPRIETARY_TLV_BASE_ID + 198)
175176

176177
#define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048
177178

@@ -611,6 +612,16 @@ struct uap_rxpd {
611612
u8 reserved1;
612613
};
613614

615+
struct mwifiex_fw_chan_stats {
616+
u8 chan_num;
617+
u8 bandcfg;
618+
u8 flags;
619+
s8 noise;
620+
__le16 total_bss;
621+
__le16 cca_scan_dur;
622+
__le16 cca_busy_dur;
623+
} __packed;
624+
614625
enum mwifiex_chan_scan_mode_bitmasks {
615626
MWIFIEX_PASSIVE_SCAN = BIT(0),
616627
MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
@@ -660,6 +671,11 @@ struct mwifiex_ie_types_scan_chan_gap {
660671
__le16 chan_gap;
661672
} __packed;
662673

674+
struct mwifiex_ietypes_chanstats {
675+
struct mwifiex_ie_types_header header;
676+
struct mwifiex_fw_chan_stats chanstats[0];
677+
} __packed;
678+
663679
struct mwifiex_ie_types_wildcard_ssid_params {
664680
struct mwifiex_ie_types_header header;
665681
u8 max_ssid_length;

drivers/net/wireless/mwifiex/main.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter)
122122
}
123123
}
124124

125+
vfree(adapter->chan_stats);
125126
kfree(adapter);
126127
return 0;
127128
}
@@ -447,6 +448,11 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
447448
goto err_init_fw;
448449
}
449450

451+
if (mwifiex_init_channel_scan_gap(adapter)) {
452+
dev_err(adapter->dev, "could not init channel stats table\n");
453+
goto err_init_fw;
454+
}
455+
450456
rtnl_lock();
451457
/* Create station interface by default */
452458
wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d",

drivers/net/wireless/mwifiex/main.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,9 @@ struct mwifiex_adapter {
844844
u8 curr_mem_idx;
845845
bool scan_chan_gap_enabled;
846846
struct sk_buff_head rx_data_q;
847+
struct mwifiex_chan_stats *chan_stats;
848+
u32 num_in_chan_stats;
849+
int survey_idx;
847850
};
848851

849852
int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -1030,7 +1033,8 @@ void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv);
10301033
int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
10311034
struct host_cmd_ds_command *cmd,
10321035
void *data_buf);
1033-
int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv);
1036+
int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
1037+
struct host_cmd_ds_command *resp);
10341038
int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
10351039
void *buf);
10361040

drivers/net/wireless/mwifiex/scan.c

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,7 @@ static void mwifiex_complete_scan(struct mwifiex_private *priv)
17551755
{
17561756
struct mwifiex_adapter *adapter = priv->adapter;
17571757

1758+
adapter->survey_idx = 0;
17581759
if (adapter->curr_cmd->wait_q_enabled) {
17591760
adapter->cmd_wait_q.status = 0;
17601761
if (!priv->scan_request) {
@@ -1976,17 +1977,90 @@ int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
19761977
return 0;
19771978
}
19781979

1980+
static void
1981+
mwifiex_update_chan_statistics(struct mwifiex_private *priv,
1982+
struct mwifiex_ietypes_chanstats *tlv_stat)
1983+
{
1984+
struct mwifiex_adapter *adapter = priv->adapter;
1985+
u8 i, num_chan;
1986+
struct mwifiex_fw_chan_stats *fw_chan_stats;
1987+
struct mwifiex_chan_stats chan_stats;
1988+
1989+
fw_chan_stats = (void *)((u8 *)tlv_stat +
1990+
sizeof(struct mwifiex_ie_types_header));
1991+
num_chan = le16_to_cpu(tlv_stat->header.len) /
1992+
sizeof(struct mwifiex_chan_stats);
1993+
1994+
for (i = 0 ; i < num_chan; i++) {
1995+
chan_stats.chan_num = fw_chan_stats->chan_num;
1996+
chan_stats.bandcfg = fw_chan_stats->bandcfg;
1997+
chan_stats.flags = fw_chan_stats->flags;
1998+
chan_stats.noise = fw_chan_stats->noise;
1999+
chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
2000+
chan_stats.cca_scan_dur =
2001+
le16_to_cpu(fw_chan_stats->cca_scan_dur);
2002+
chan_stats.cca_busy_dur =
2003+
le16_to_cpu(fw_chan_stats->cca_busy_dur);
2004+
dev_dbg(adapter->dev,
2005+
"chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
2006+
chan_stats.chan_num,
2007+
chan_stats.noise,
2008+
chan_stats.total_bss,
2009+
chan_stats.cca_scan_dur,
2010+
chan_stats.cca_busy_dur);
2011+
memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
2012+
sizeof(struct mwifiex_chan_stats));
2013+
fw_chan_stats++;
2014+
}
2015+
}
2016+
19792017
/* This function handles the command response of extended scan */
1980-
int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv)
2018+
int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
2019+
struct host_cmd_ds_command *resp)
19812020
{
19822021
struct mwifiex_adapter *adapter = priv->adapter;
2022+
struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
2023+
struct mwifiex_ie_types_header *tlv;
2024+
struct mwifiex_ietypes_chanstats *tlv_stat;
2025+
u16 buf_left, type, len;
2026+
19832027
struct host_cmd_ds_command *cmd_ptr;
19842028
struct cmd_ctrl_node *cmd_node;
19852029
unsigned long cmd_flags, scan_flags;
19862030
bool complete_scan = false;
19872031

19882032
dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n");
19892033

2034+
ext_scan_resp = &resp->params.ext_scan;
2035+
2036+
tlv = (void *)ext_scan_resp->tlv_buffer;
2037+
buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
2038+
- 1);
2039+
2040+
while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
2041+
type = le16_to_cpu(tlv->type);
2042+
len = le16_to_cpu(tlv->len);
2043+
2044+
if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
2045+
dev_err(adapter->dev,
2046+
"error processing scan response TLVs");
2047+
break;
2048+
}
2049+
2050+
switch (type) {
2051+
case TLV_TYPE_CHANNEL_STATS:
2052+
tlv_stat = (void *)tlv;
2053+
mwifiex_update_chan_statistics(priv, tlv_stat);
2054+
break;
2055+
default:
2056+
break;
2057+
}
2058+
2059+
buf_left -= len + sizeof(struct mwifiex_ie_types_header);
2060+
tlv = (void *)((u8 *)tlv + len +
2061+
sizeof(struct mwifiex_ie_types_header));
2062+
}
2063+
19902064
spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
19912065
spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
19922066
if (list_empty(&adapter->scan_pending_q)) {

drivers/net/wireless/mwifiex/sta_cmdresp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
983983
adapter->curr_cmd->wait_q_enabled = false;
984984
break;
985985
case HostCmd_CMD_802_11_SCAN_EXT:
986-
ret = mwifiex_ret_802_11_scan_ext(priv);
986+
ret = mwifiex_ret_802_11_scan_ext(priv, resp);
987987
adapter->curr_cmd->wait_q_enabled = false;
988988
break;
989989
case HostCmd_CMD_802_11_BG_SCAN_QUERY:

0 commit comments

Comments
 (0)