mac80211: update brcmfmac including missing boardrev workaround
[openwrt.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 */