c2fd620d6c95c9fbb884f04cabaa0b68396611e7
[openwrt/staging/luka.git] /
1 From 29ec3394f0bd85c22674ab6693d92da5e2324610 Mon Sep 17 00:00:00 2001
2 From: Hans de Goede <hdegoede@redhat.com>
3 Date: Thu, 11 Oct 2018 11:51:07 +0200
4 Subject: [PATCH] brcmfmac: Fix ccode from EFI nvram when necessary
5
6 In some cases the EFI-var stored nvram contains "ccode=ALL" or "ccode=XV"
7 to specify "worldwide" compatible settings, but these 2 ccode-s do not work
8 properly.
9
10 I've tested the different known "worldwide" ccode-s used in various nvram
11 sources with the latest firmwares from linux-firmware for various brcmfmac
12 models, here is a simplified (*) table with what each setting results in:
13
14 ALL: 12-14 disab, U-NII-1, U-NII-2 no-IR/radar, U-NII-3
15 XV: 12-14 no-IR, disables all 5G channels
16 XY: 12-13 enab, 14 disab, U-NII-1 enab, U-NII-2 no-IR/radar, U-NII-3 disab
17 X2: 12-13 no-IR, 14 dis, U-NII-1 no-IR, U-NII-2 no-IR/radar, U-NII-3 no-IR
18
19 Where 12,13,14 are 2.4G channels 12-14 and U-NII-1/2/3 are the 3 different
20 5G channel groups. no-IR is no-Initiate-Radiation, we will never send on
21 these channels without first having received valid wifi traffic there.
22
23 This immediately shows that both ALL and XV are not as worldwide as we want
24 them to be. ALL causes channels 12 and 13 to not be available and XV causes
25 all 5GHz channels to not be available. Also ALL unconditionally enables the
26 U-NII-1 and U-NII-3 5G groups, while we really should be using no-IR for
27 these.
28
29 This commit replace XV and ALL with X2, which allows usage of chan 12-13
30 and 5G channels, but only after receiving valid wifi traffic there first.
31
32 Note that this configure the firmware's channel limits, the kernels own
33 regulatory restrictions based on e.g. regulatory info received from the
34 access-point, will be applied on top of this.
35
36 This fixes channels 12+13 not working on the Asus T200TA and the Lenovo
37 Mixx 2 8 and 5G channels not working on the Asus T100HA.
38
39 This has been tested on the following models: Acer Iconia Tab8 w1-810,
40 Acer One 10, Asus T100CHI, Asus T100HA, Asus T100TA, Asus T200TA and a
41 Lenovo Mixx 2 8.
42
43 *) There are some exceptions to this table:
44 1) On really old firmware e.g. linux-firmware's 2011 brcmfmac4330-sdio.bin
45 ALL really means all, unconditionally enabling everything
46 2) The exact meaning might be influenced by setting the regrev nvram var.
47 Specifically using ccode=XV + regrev=1 on brcmfmac43241b4 leads to:
48 12-14 no-ir, U-NII-1 no-ir, U-NII-2 no-ir/radar, U-NII-3 no-ir
49 But only on the brcmfmac43241b4 and not on e.g. the brcmfmac43340
50
51 Tested-by: Hans de Goede <hdegoede@redhat.com>
52 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
53 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
54 ---
55 .../broadcom/brcm80211/brcmfmac/firmware.c | 24 ++++++++++++++++++++++
56 1 file changed, 24 insertions(+)
57
58 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
59 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
60 @@ -447,6 +447,29 @@ struct brcmf_fw {
61 static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
62
63 #ifdef CONFIG_EFI
64 +/* In some cases the EFI-var stored nvram contains "ccode=ALL" or "ccode=XV"
65 + * to specify "worldwide" compatible settings, but these 2 ccode-s do not work
66 + * properly. "ccode=ALL" causes channels 12 and 13 to not be available,
67 + * "ccode=XV" causes all 5GHz channels to not be available. So we replace both
68 + * with "ccode=X2" which allows channels 12+13 and 5Ghz channels in
69 + * no-Initiate-Radiation mode. This means that we will never send on these
70 + * channels without first having received valid wifi traffic on the channel.
71 + */
72 +static void brcmf_fw_fix_efi_nvram_ccode(char *data, unsigned long data_len)
73 +{
74 + char *ccode;
75 +
76 + ccode = strnstr((char *)data, "ccode=ALL", data_len);
77 + if (!ccode)
78 + ccode = strnstr((char *)data, "ccode=XV\r", data_len);
79 + if (!ccode)
80 + return;
81 +
82 + ccode[6] = 'X';
83 + ccode[7] = '2';
84 + ccode[8] = '\r';
85 +}
86 +
87 static u8 *brcmf_fw_nvram_from_efi(size_t *data_len_ret)
88 {
89 const u16 name[] = { 'n', 'v', 'r', 'a', 'm', 0 };
90 @@ -476,6 +499,7 @@ static u8 *brcmf_fw_nvram_from_efi(size_
91 if (err)
92 goto fail;
93
94 + brcmf_fw_fix_efi_nvram_ccode(data, data_len);
95 brcmf_info("Using nvram EFI variable\n");
96
97 kfree(nvram_efivar);