98 lines
4.1 KiB
Diff
98 lines
4.1 KiB
Diff
|
From 29ec3394f0bd85c22674ab6693d92da5e2324610 Mon Sep 17 00:00:00 2001
|
||
|
From: Hans de Goede <hdegoede@redhat.com>
|
||
|
Date: Thu, 11 Oct 2018 11:51:07 +0200
|
||
|
Subject: [PATCH] brcmfmac: Fix ccode from EFI nvram when necessary
|
||
|
|
||
|
In some cases the EFI-var stored nvram contains "ccode=ALL" or "ccode=XV"
|
||
|
to specify "worldwide" compatible settings, but these 2 ccode-s do not work
|
||
|
properly.
|
||
|
|
||
|
I've tested the different known "worldwide" ccode-s used in various nvram
|
||
|
sources with the latest firmwares from linux-firmware for various brcmfmac
|
||
|
models, here is a simplified (*) table with what each setting results in:
|
||
|
|
||
|
ALL: 12-14 disab, U-NII-1, U-NII-2 no-IR/radar, U-NII-3
|
||
|
XV: 12-14 no-IR, disables all 5G channels
|
||
|
XY: 12-13 enab, 14 disab, U-NII-1 enab, U-NII-2 no-IR/radar, U-NII-3 disab
|
||
|
X2: 12-13 no-IR, 14 dis, U-NII-1 no-IR, U-NII-2 no-IR/radar, U-NII-3 no-IR
|
||
|
|
||
|
Where 12,13,14 are 2.4G channels 12-14 and U-NII-1/2/3 are the 3 different
|
||
|
5G channel groups. no-IR is no-Initiate-Radiation, we will never send on
|
||
|
these channels without first having received valid wifi traffic there.
|
||
|
|
||
|
This immediately shows that both ALL and XV are not as worldwide as we want
|
||
|
them to be. ALL causes channels 12 and 13 to not be available and XV causes
|
||
|
all 5GHz channels to not be available. Also ALL unconditionally enables the
|
||
|
U-NII-1 and U-NII-3 5G groups, while we really should be using no-IR for
|
||
|
these.
|
||
|
|
||
|
This commit replace XV and ALL with X2, which allows usage of chan 12-13
|
||
|
and 5G channels, but only after receiving valid wifi traffic there first.
|
||
|
|
||
|
Note that this configure the firmware's channel limits, the kernels own
|
||
|
regulatory restrictions based on e.g. regulatory info received from the
|
||
|
access-point, will be applied on top of this.
|
||
|
|
||
|
This fixes channels 12+13 not working on the Asus T200TA and the Lenovo
|
||
|
Mixx 2 8 and 5G channels not working on the Asus T100HA.
|
||
|
|
||
|
This has been tested on the following models: Acer Iconia Tab8 w1-810,
|
||
|
Acer One 10, Asus T100CHI, Asus T100HA, Asus T100TA, Asus T200TA and a
|
||
|
Lenovo Mixx 2 8.
|
||
|
|
||
|
*) There are some exceptions to this table:
|
||
|
1) On really old firmware e.g. linux-firmware's 2011 brcmfmac4330-sdio.bin
|
||
|
ALL really means all, unconditionally enabling everything
|
||
|
2) The exact meaning might be influenced by setting the regrev nvram var.
|
||
|
Specifically using ccode=XV + regrev=1 on brcmfmac43241b4 leads to:
|
||
|
12-14 no-ir, U-NII-1 no-ir, U-NII-2 no-ir/radar, U-NII-3 no-ir
|
||
|
But only on the brcmfmac43241b4 and not on e.g. the brcmfmac43340
|
||
|
|
||
|
Tested-by: Hans de Goede <hdegoede@redhat.com>
|
||
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||
|
---
|
||
|
.../broadcom/brcm80211/brcmfmac/firmware.c | 24 ++++++++++++++++++++++
|
||
|
1 file changed, 24 insertions(+)
|
||
|
|
||
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||
|
@@ -447,6 +447,29 @@ struct brcmf_fw {
|
||
|
static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
|
||
|
|
||
|
#ifdef CONFIG_EFI
|
||
|
+/* In some cases the EFI-var stored nvram contains "ccode=ALL" or "ccode=XV"
|
||
|
+ * to specify "worldwide" compatible settings, but these 2 ccode-s do not work
|
||
|
+ * properly. "ccode=ALL" causes channels 12 and 13 to not be available,
|
||
|
+ * "ccode=XV" causes all 5GHz channels to not be available. So we replace both
|
||
|
+ * with "ccode=X2" which allows channels 12+13 and 5Ghz channels in
|
||
|
+ * no-Initiate-Radiation mode. This means that we will never send on these
|
||
|
+ * channels without first having received valid wifi traffic on the channel.
|
||
|
+ */
|
||
|
+static void brcmf_fw_fix_efi_nvram_ccode(char *data, unsigned long data_len)
|
||
|
+{
|
||
|
+ char *ccode;
|
||
|
+
|
||
|
+ ccode = strnstr((char *)data, "ccode=ALL", data_len);
|
||
|
+ if (!ccode)
|
||
|
+ ccode = strnstr((char *)data, "ccode=XV\r", data_len);
|
||
|
+ if (!ccode)
|
||
|
+ return;
|
||
|
+
|
||
|
+ ccode[6] = 'X';
|
||
|
+ ccode[7] = '2';
|
||
|
+ ccode[8] = '\r';
|
||
|
+}
|
||
|
+
|
||
|
static u8 *brcmf_fw_nvram_from_efi(size_t *data_len_ret)
|
||
|
{
|
||
|
const u16 name[] = { 'n', 'v', 'r', 'a', 'm', 0 };
|
||
|
@@ -476,6 +499,7 @@ static u8 *brcmf_fw_nvram_from_efi(size_
|
||
|
if (err)
|
||
|
goto fail;
|
||
|
|
||
|
+ brcmf_fw_fix_efi_nvram_ccode(data, data_len);
|
||
|
brcmf_info("Using nvram EFI variable\n");
|
||
|
|
||
|
kfree(nvram_efivar);
|