mac80211: backport some brcmfmac patches
[openwrt/staging/chunkeey.git] / package / kernel / mac80211 / patches / 391-brcmfmac-rework-.get_station-callback.patch
1 From: Arend van Spriel <arend@broadcom.com>
2 Date: Thu, 11 Jun 2015 00:12:19 +0200
3 Subject: [PATCH] brcmfmac: rework .get_station() callback
4
5 The .get_station() cfg80211 callback is used in several scenarios. In
6 managed mode it can obtain information about the access-point and its
7 BSS parameters. In managed mode it can also obtain information about
8 TDLS peers. In AP mode it can obtain information about connected
9 clients.
10
11 Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
12 Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
13 Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
14 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
15 Signed-off-by: Arend van Spriel <arend@broadcom.com>
16 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
17 ---
18
19 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
20 +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
21 @@ -2395,27 +2395,80 @@ brcmf_cfg80211_reconfigure_wep(struct br
22 brcmf_err("set wsec error (%d)\n", err);
23 }
24
25 +static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si)
26 +{
27 + struct nl80211_sta_flag_update *sfu;
28 +
29 + brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags);
30 + si->filled |= BIT(NL80211_STA_INFO_STA_FLAGS);
31 + sfu = &si->sta_flags;
32 + sfu->mask = BIT(NL80211_STA_FLAG_WME) |
33 + BIT(NL80211_STA_FLAG_AUTHENTICATED) |
34 + BIT(NL80211_STA_FLAG_ASSOCIATED) |
35 + BIT(NL80211_STA_FLAG_AUTHORIZED);
36 + if (fw_sta_flags & BRCMF_STA_WME)
37 + sfu->set |= BIT(NL80211_STA_FLAG_WME);
38 + if (fw_sta_flags & BRCMF_STA_AUTHE)
39 + sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
40 + if (fw_sta_flags & BRCMF_STA_ASSOC)
41 + sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
42 + if (fw_sta_flags & BRCMF_STA_AUTHO)
43 + sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
44 +}
45 +
46 +static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)
47 +{
48 + struct {
49 + __le32 len;
50 + struct brcmf_bss_info_le bss_le;
51 + } *buf;
52 + u16 capability;
53 + int err;
54 +
55 + buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
56 + if (!buf)
57 + return;
58 +
59 + buf->len = cpu_to_le32(WL_BSS_INFO_MAX);
60 + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf,
61 + WL_BSS_INFO_MAX);
62 + if (err) {
63 + brcmf_err("Failed to get bss info (%d)\n", err);
64 + return;
65 + }
66 + si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
67 + si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period);
68 + si->bss_param.dtim_period = buf->bss_le.dtim_period;
69 + capability = le16_to_cpu(buf->bss_le.capability);
70 + if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT)
71 + si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
72 + if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
73 + si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
74 + if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
75 + si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
76 +}
77 +
78 static s32
79 brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
80 const u8 *mac, struct station_info *sinfo)
81 {
82 struct brcmf_if *ifp = netdev_priv(ndev);
83 - struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
84 - struct brcmf_scb_val_le scb_val;
85 - int rssi;
86 - s32 rate;
87 s32 err = 0;
88 - u8 *bssid = profile->bssid;
89 struct brcmf_sta_info_le sta_info_le;
90 - u32 beacon_period;
91 - u32 dtim_period;
92 + u32 sta_flags;
93 + u32 is_tdls_peer;
94
95 brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
96 if (!check_vif_up(ifp->vif))
97 return -EIO;
98
99 - if (brcmf_is_apmode(ifp->vif)) {
100 - memcpy(&sta_info_le, mac, ETH_ALEN);
101 + memset(&sta_info_le, 0, sizeof(sta_info_le));
102 + memcpy(&sta_info_le, mac, ETH_ALEN);
103 + err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info",
104 + &sta_info_le,
105 + sizeof(sta_info_le));
106 + is_tdls_peer = !err;
107 + if (err) {
108 err = brcmf_fil_iovar_data_get(ifp, "sta_info",
109 &sta_info_le,
110 sizeof(sta_info_le));
111 @@ -2423,73 +2476,48 @@ brcmf_cfg80211_get_station(struct wiphy
112 brcmf_err("GET STA INFO failed, %d\n", err);
113 goto done;
114 }
115 - sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
116 - sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
117 - if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
118 - sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
119 - sinfo->connected_time = le32_to_cpu(sta_info_le.in);
120 - }
121 - brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
122 - sinfo->inactive_time, sinfo->connected_time);
123 - } else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) {
124 - if (memcmp(mac, bssid, ETH_ALEN)) {
125 - brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
126 - mac, bssid);
127 - err = -ENOENT;
128 - goto done;
129 - }
130 - /* Report the current tx rate */
131 - err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
132 - if (err) {
133 - brcmf_err("Could not get rate (%d)\n", err);
134 - goto done;
135 - } else {
136 + }
137 + brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
138 + sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
139 + sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
140 + sta_flags = le32_to_cpu(sta_info_le.flags);
141 + brcmf_convert_sta_flags(sta_flags, sinfo);
142 + sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
143 + if (is_tdls_peer)
144 + sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
145 + else
146 + sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
147 + if (sta_flags & BRCMF_STA_ASSOC) {
148 + sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
149 + sinfo->connected_time = le32_to_cpu(sta_info_le.in);
150 + brcmf_fill_bss_param(ifp, sinfo);
151 + }
152 + if (sta_flags & BRCMF_STA_SCBSTATS) {
153 + sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED);
154 + sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures);
155 + sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
156 + sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts);
157 + sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts);
158 + sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
159 + sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts);
160 + sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts);
161 + if (sinfo->tx_packets) {
162 sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
163 - sinfo->txrate.legacy = rate * 5;
164 - brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2);
165 + sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate);
166 + sinfo->txrate.legacy /= 100;
167 }
168 -
169 - if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
170 - &ifp->vif->sme_state)) {
171 - memset(&scb_val, 0, sizeof(scb_val));
172 - err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
173 - &scb_val, sizeof(scb_val));
174 - if (err) {
175 - brcmf_err("Could not get rssi (%d)\n", err);
176 - goto done;
177 - } else {
178 - rssi = le32_to_cpu(scb_val.val);
179 - sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
180 - sinfo->signal = rssi;
181 - brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
182 - }
183 - err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD,
184 - &beacon_period);
185 - if (err) {
186 - brcmf_err("Could not get beacon period (%d)\n",
187 - err);
188 - goto done;
189 - } else {
190 - sinfo->bss_param.beacon_interval =
191 - beacon_period;
192 - brcmf_dbg(CONN, "Beacon peroid %d\n",
193 - beacon_period);
194 - }
195 - err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD,
196 - &dtim_period);
197 - if (err) {
198 - brcmf_err("Could not get DTIM period (%d)\n",
199 - err);
200 - goto done;
201 - } else {
202 - sinfo->bss_param.dtim_period = dtim_period;
203 - brcmf_dbg(CONN, "DTIM peroid %d\n",
204 - dtim_period);
205 - }
206 - sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
207 + if (sinfo->rx_packets) {
208 + sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
209 + sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate);
210 + sinfo->rxrate.legacy /= 100;
211 + }
212 + if (le16_to_cpu(sta_info_le.ver) >= 4) {
213 + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES);
214 + sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
215 + sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES);
216 + sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
217 }
218 - } else
219 - err = -EPERM;
220 + }
221 done:
222 brcmf_dbg(TRACE, "Exit\n");
223 return err;
224 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
225 +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
226 @@ -32,7 +32,11 @@
227 #define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */
228 #define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002
229
230 -#define BRCMF_STA_ASSOC 0x10 /* Associated */
231 +#define BRCMF_STA_WME 0x00000002 /* WMM association */
232 +#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */
233 +#define BRCMF_STA_ASSOC 0x00000010 /* Associated */
234 +#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */
235 +#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
236
237 /* size of brcmf_scan_params not including variable length array */
238 #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
239 @@ -113,6 +117,7 @@
240 #define BRCMF_WOWL_MAXPATTERNSIZE 128
241
242 #define BRCMF_COUNTRY_BUF_SZ 4
243 +#define BRCMF_ANT_MAX 4
244
245 /* join preference types for join_pref iovar */
246 enum brcmf_join_pref_types {
247 @@ -456,25 +461,61 @@ struct brcmf_channel_info_le {
248 };
249
250 struct brcmf_sta_info_le {
251 - __le16 ver; /* version of this struct */
252 - __le16 len; /* length in bytes of this structure */
253 - __le16 cap; /* sta's advertised capabilities */
254 - __le32 flags; /* flags defined below */
255 - __le32 idle; /* time since data pkt rx'd from sta */
256 - u8 ea[ETH_ALEN]; /* Station address */
257 - __le32 count; /* # rates in this set */
258 - u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
259 + __le16 ver; /* version of this struct */
260 + __le16 len; /* length in bytes of this structure */
261 + __le16 cap; /* sta's advertised capabilities */
262 + __le32 flags; /* flags defined below */
263 + __le32 idle; /* time since data pkt rx'd from sta */
264 + u8 ea[ETH_ALEN]; /* Station address */
265 + __le32 count; /* # rates in this set */
266 + u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
267 /* w/hi bit set if basic */
268 - __le32 in; /* seconds elapsed since associated */
269 - __le32 listen_interval_inms; /* Min Listen interval in ms for STA */
270 - __le32 tx_pkts; /* # of packets transmitted */
271 - __le32 tx_failures; /* # of packets failed */
272 - __le32 rx_ucast_pkts; /* # of unicast packets received */
273 - __le32 rx_mcast_pkts; /* # of multicast packets received */
274 - __le32 tx_rate; /* Rate of last successful tx frame */
275 - __le32 rx_rate; /* Rate of last successful rx frame */
276 - __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
277 - __le32 rx_decrypt_failures; /* # of packet decrypted failed */
278 + __le32 in; /* seconds elapsed since associated */
279 + __le32 listen_interval_inms; /* Min Listen interval in ms for STA */
280 + __le32 tx_pkts; /* # of packets transmitted */
281 + __le32 tx_failures; /* # of packets failed */
282 + __le32 rx_ucast_pkts; /* # of unicast packets received */
283 + __le32 rx_mcast_pkts; /* # of multicast packets received */
284 + __le32 tx_rate; /* Rate of last successful tx frame */
285 + __le32 rx_rate; /* Rate of last successful rx frame */
286 + __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
287 + __le32 rx_decrypt_failures; /* # of packet decrypted failed */
288 + __le32 tx_tot_pkts; /* # of tx pkts (ucast + mcast) */
289 + __le32 rx_tot_pkts; /* # of data packets recvd (uni + mcast) */
290 + __le32 tx_mcast_pkts; /* # of mcast pkts txed */
291 + __le64 tx_tot_bytes; /* data bytes txed (ucast + mcast) */
292 + __le64 rx_tot_bytes; /* data bytes recvd (ucast + mcast) */
293 + __le64 tx_ucast_bytes; /* data bytes txed (ucast) */
294 + __le64 tx_mcast_bytes; /* # data bytes txed (mcast) */
295 + __le64 rx_ucast_bytes; /* data bytes recvd (ucast) */
296 + __le64 rx_mcast_bytes; /* data bytes recvd (mcast) */
297 + s8 rssi[BRCMF_ANT_MAX]; /* per antenna rssi */
298 + s8 nf[BRCMF_ANT_MAX]; /* per antenna noise floor */
299 + __le16 aid; /* association ID */
300 + __le16 ht_capabilities; /* advertised ht caps */
301 + __le16 vht_flags; /* converted vht flags */
302 + __le32 tx_pkts_retry_cnt; /* # of frames where a retry was
303 + * exhausted.
304 + */
305 + __le32 tx_pkts_retry_exhausted; /* # of user frames where a retry
306 + * was exhausted
307 + */
308 + s8 rx_lastpkt_rssi[BRCMF_ANT_MAX]; /* Per antenna RSSI of last
309 + * received data frame.
310 + */
311 + /* TX WLAN retry/failure statistics:
312 + * Separated for host requested frames and locally generated frames.
313 + * Include unicast frame only where the retries/failures can be counted.
314 + */
315 + __le32 tx_pkts_total; /* # user frames sent successfully */
316 + __le32 tx_pkts_retries; /* # user frames retries */
317 + __le32 tx_pkts_fw_total; /* # FW generated sent successfully */
318 + __le32 tx_pkts_fw_retries; /* # retries for FW generated frames */
319 + __le32 tx_pkts_fw_retry_exhausted; /* # FW generated where a retry
320 + * was exhausted
321 + */
322 + __le32 rx_pkts_retried; /* # rx with retry bit set */
323 + __le32 tx_rate_fallback; /* lowest fallback TX rate */
324 };
325
326 struct brcmf_chanspec_list {