mac80211: backport brcmfmac patchset with driver setting concept
[openwrt/staging/lynxis/omap.git] / package / kernel / mac80211 / patches / 344-0004-brcmfmac-Configure-country-code-using-device-specifi.patch
1 From: Hante Meuleman <meuleman@broadcom.com>
2 Date: Wed, 17 Feb 2016 11:26:53 +0100
3 Subject: [PATCH] brcmfmac: Configure country code using device specific
4 settings
5
6 Country code configuration in a device is a device specific
7 operation. For this the country code as specified by reg notifier
8 (iso3166 alpha2) needs to be translated to a device specific
9 country locale and revision number. This patch adds this
10 translation and puts a placeholder in the device specific settings
11 where the translation table can be stored. Additional patches will
12 be needed to read these tables from for example device platform
13 data.
14
15 Reviewed-by: Arend Van Spriel <arend@broadcom.com>
16 Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
17 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
18 Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
19 Signed-off-by: Arend van Spriel <arend@broadcom.com>
20 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
21 ---
22
23 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
24 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
25 @@ -6405,28 +6405,85 @@ int brcmf_cfg80211_wait_vif_event(struct
26 vif_event_equals(event, action), timeout);
27 }
28
29 +static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2],
30 + struct brcmf_fil_country_le *ccreq)
31 +{
32 + struct cc_translate *country_codes;
33 + struct cc_entry *cc;
34 + s32 found_index;
35 + int i;
36 +
37 + country_codes = drvr->settings->country_codes;
38 + if (!country_codes) {
39 + brcmf_dbg(TRACE, "No country codes configured for device\n");
40 + return -EINVAL;
41 + }
42 +
43 + if ((alpha2[0] == ccreq->country_abbrev[0]) &&
44 + (alpha2[1] == ccreq->country_abbrev[1])) {
45 + brcmf_dbg(TRACE, "Country code already set\n");
46 + return -EAGAIN;
47 + }
48 +
49 + found_index = -1;
50 + for (i = 0; i < country_codes->table_size; i++) {
51 + cc = &country_codes->table[i];
52 + if ((cc->iso3166[0] == '\0') && (found_index == -1))
53 + found_index = i;
54 + if ((cc->iso3166[0] == alpha2[0]) &&
55 + (cc->iso3166[1] == alpha2[1])) {
56 + found_index = i;
57 + break;
58 + }
59 + }
60 + if (found_index == -1) {
61 + brcmf_dbg(TRACE, "No country code match found\n");
62 + return -EINVAL;
63 + }
64 + memset(ccreq, 0, sizeof(*ccreq));
65 + ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev);
66 + memcpy(ccreq->ccode, country_codes->table[found_index].cc,
67 + BRCMF_COUNTRY_BUF_SZ);
68 + ccreq->country_abbrev[0] = alpha2[0];
69 + ccreq->country_abbrev[1] = alpha2[1];
70 + ccreq->country_abbrev[2] = 0;
71 +
72 + return 0;
73 +}
74 +
75 static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
76 struct regulatory_request *req)
77 {
78 struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
79 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
80 struct brcmf_fil_country_le ccreq;
81 + s32 err;
82 int i;
83
84 - brcmf_dbg(TRACE, "enter: initiator=%d, alpha=%c%c\n", req->initiator,
85 - req->alpha2[0], req->alpha2[1]);
86 -
87 /* ignore non-ISO3166 country codes */
88 for (i = 0; i < sizeof(req->alpha2); i++)
89 if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
90 - brcmf_err("not a ISO3166 code\n");
91 + brcmf_err("not a ISO3166 code (0x%02x 0x%02x)\n",
92 + req->alpha2[0], req->alpha2[1]);
93 return;
94 }
95 - memset(&ccreq, 0, sizeof(ccreq));
96 - ccreq.rev = cpu_to_le32(-1);
97 - memcpy(ccreq.ccode, req->alpha2, sizeof(req->alpha2));
98 - if (brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq))) {
99 - brcmf_err("firmware rejected country setting\n");
100 +
101 + brcmf_dbg(TRACE, "Enter: initiator=%d, alpha=%c%c\n", req->initiator,
102 + req->alpha2[0], req->alpha2[1]);
103 +
104 + err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq));
105 + if (err) {
106 + brcmf_err("Country code iovar returned err = %d\n", err);
107 + return;
108 + }
109 +
110 + err = brcmf_translate_country_code(ifp->drvr, req->alpha2, &ccreq);
111 + if (err)
112 + return;
113 +
114 + err = brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq));
115 + if (err) {
116 + brcmf_err("Firmware rejected country setting\n");
117 return;
118 }
119 brcmf_setup_wiphybands(wiphy);
120 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
121 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
122 @@ -230,10 +230,8 @@ void brcmf_mp_attach(void)
123 int brcmf_mp_device_attach(struct brcmf_pub *drvr)
124 {
125 drvr->settings = kzalloc(sizeof(*drvr->settings), GFP_ATOMIC);
126 - if (!drvr->settings) {
127 - brcmf_err("Failed to alloca storage space for settings\n");
128 + if (!drvr->settings)
129 return -ENOMEM;
130 - }
131
132 drvr->settings->sdiod_txglomsz = brcmf_sdiod_txglomsz;
133 drvr->settings->p2p_enable = !!brcmf_p2p_enable;
134 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
135 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
136 @@ -15,6 +15,8 @@
137 #ifndef BRCMFMAC_COMMON_H
138 #define BRCMFMAC_COMMON_H
139
140 +#include "fwil_types.h"
141 +
142 extern const u8 ALLFFMAC[ETH_ALEN];
143
144 #define BRCMF_FW_ALTPATH_LEN 256
145 @@ -39,6 +41,33 @@ struct brcmf_mp_global_t {
146 extern struct brcmf_mp_global_t brcmf_mp_global;
147
148 /**
149 + * struct cc_entry - Struct for translating user space country code (iso3166) to
150 + * firmware country code and revision.
151 + *
152 + * @iso3166: iso3166 alpha 2 country code string.
153 + * @cc: firmware country code string.
154 + * @rev: firmware country code revision.
155 + */
156 +struct cc_entry {
157 + char iso3166[BRCMF_COUNTRY_BUF_SZ];
158 + char cc[BRCMF_COUNTRY_BUF_SZ];
159 + s32 rev;
160 +};
161 +
162 +/**
163 + * struct cc_translate - Struct for translating country codes as set by user
164 + * space to a country code and rev which can be used by
165 + * firmware.
166 + *
167 + * @table_size: number of entries in table (> 0)
168 + * @table: dynamic array of 1 or more elements with translation information.
169 + */
170 +struct cc_translate {
171 + int table_size;
172 + struct cc_entry table[0];
173 +};
174 +
175 +/**
176 * struct brcmf_mp_device - Device module paramaters.
177 *
178 * @sdiod_txglomsz: SDIO txglom size.
179 @@ -47,6 +76,7 @@ extern struct brcmf_mp_global_t brcmf_mp
180 * @feature_disable: Feature_disable bitmask.
181 * @fcmode: FWS flow control.
182 * @roamoff: Firmware roaming off?
183 + * @country_codes: If available, pointer to struct for translating country codes
184 */
185 struct brcmf_mp_device {
186 int sdiod_txglomsz;
187 @@ -56,6 +86,7 @@ struct brcmf_mp_device {
188 int fcmode;
189 bool roamoff;
190 bool ignore_probe_fail;
191 + struct cc_translate *country_codes;
192 };
193
194 void brcmf_mp_attach(void);
195 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
196 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
197 @@ -134,6 +134,8 @@
198 #define BRCMF_PFN_MAC_OUI_ONLY BIT(0)
199 #define BRCMF_PFN_SET_MAC_UNASSOC BIT(1)
200
201 +#define BRCMF_MCSSET_LEN 16
202 +
203 /* join preference types for join_pref iovar */
204 enum brcmf_join_pref_types {
205 BRCMF_JOIN_PREF_RSSI = 1,
206 @@ -279,7 +281,7 @@ struct brcmf_bss_info_le {
207 __le32 reserved32[1]; /* Reserved for expansion of BSS properties */
208 u8 flags; /* flags */
209 u8 reserved[3]; /* Reserved for expansion of BSS properties */
210 - u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */
211 + u8 basic_mcs[BRCMF_MCSSET_LEN]; /* 802.11N BSS required MCS set */
212
213 __le16 ie_offset; /* offset at which IEs start, from beginning */
214 __le32 ie_length; /* byte length of Information Elements */