|
| 1 | +From 3ac592da09acb47b728ef320e9fecde55c8e0824 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Phil Elwell <phil@raspberrypi.com> |
| 3 | +Date: Fri, 26 Jun 2020 11:51:05 +0100 |
| 4 | +Subject: [PATCH] brcmfmac: Prefer a ccode from OTP over nvram file |
| 5 | + |
| 6 | +Allow the nvram file to set a default ccode (regulatory domain) without |
| 7 | +overriding one set in OTP. |
| 8 | + |
| 9 | +Signed-off-by: Phil Elwell <phil@raspberrypi.com> |
| 10 | +--- |
| 11 | + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 39 +++++++++++++------ |
| 12 | + .../broadcom/brcm80211/brcmfmac/firmware.c | 21 +++++++++- |
| 13 | + 2 files changed, 47 insertions(+), 13 deletions(-) |
| 14 | + |
| 15 | +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c |
| 16 | ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c |
| 17 | +@@ -9,6 +9,7 @@ |
| 18 | + #include <linux/etherdevice.h> |
| 19 | + #include <linux/module.h> |
| 20 | + #include <linux/vmalloc.h> |
| 21 | ++#include <linux/ctype.h> |
| 22 | + #include <net/cfg80211.h> |
| 23 | + #include <net/netlink.h> |
| 24 | + #include <uapi/linux/if_arp.h> |
| 25 | +@@ -8212,31 +8213,45 @@ static void brcmf_cfg80211_reg_notifier( |
| 26 | + struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); |
| 27 | + struct brcmf_pub *drvr = cfg->pub; |
| 28 | + struct brcmf_fil_country_le ccreq; |
| 29 | ++ char *alpha2; |
| 30 | + s32 err; |
| 31 | + int i; |
| 32 | + |
| 33 | +- /* The country code gets set to "00" by default at boot, ignore */ |
| 34 | +- if (req->alpha2[0] == '0' && req->alpha2[1] == '0') |
| 35 | ++ err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq)); |
| 36 | ++ if (err) { |
| 37 | ++ bphy_err(drvr, "Country code iovar returned err = %d\n", err); |
| 38 | + return; |
| 39 | ++ } |
| 40 | ++ |
| 41 | ++ /* The country code gets set to "00" by default at boot - substitute |
| 42 | ++ * any saved ccode from the nvram file unless there is a valid code |
| 43 | ++ * already set. |
| 44 | ++ */ |
| 45 | ++ alpha2 = req->alpha2; |
| 46 | ++ if (alpha2[0] == '0' && alpha2[1] == '0') { |
| 47 | ++ extern char saved_ccode[2]; |
| 48 | ++ |
| 49 | ++ if ((isupper(ccreq.country_abbrev[0]) && |
| 50 | ++ isupper(ccreq.country_abbrev[1])) || |
| 51 | ++ !saved_ccode[0]) |
| 52 | ++ return; |
| 53 | ++ alpha2 = saved_ccode; |
| 54 | ++ pr_debug("brcmfmac: substituting saved ccode %c%c\n", |
| 55 | ++ alpha2[0], alpha2[1]); |
| 56 | ++ } |
| 57 | + |
| 58 | + /* ignore non-ISO3166 country codes */ |
| 59 | + for (i = 0; i < 2; i++) |
| 60 | +- if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { |
| 61 | ++ if (alpha2[i] < 'A' || alpha2[i] > 'Z') { |
| 62 | + bphy_err(drvr, "not an ISO3166 code (0x%02x 0x%02x)\n", |
| 63 | +- req->alpha2[0], req->alpha2[1]); |
| 64 | ++ alpha2[0], alpha2[1]); |
| 65 | + return; |
| 66 | + } |
| 67 | + |
| 68 | + brcmf_dbg(TRACE, "Enter: initiator=%d, alpha=%c%c\n", req->initiator, |
| 69 | +- req->alpha2[0], req->alpha2[1]); |
| 70 | +- |
| 71 | +- err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq)); |
| 72 | +- if (err) { |
| 73 | +- bphy_err(drvr, "Country code iovar returned err = %d\n", err); |
| 74 | +- return; |
| 75 | +- } |
| 76 | ++ alpha2[0], alpha2[1]); |
| 77 | + |
| 78 | +- err = brcmf_translate_country_code(ifp->drvr, req->alpha2, &ccreq); |
| 79 | ++ err = brcmf_translate_country_code(ifp->drvr, alpha2, &ccreq); |
| 80 | + if (err) |
| 81 | + return; |
| 82 | + |
| 83 | +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c |
| 84 | ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c |
| 85 | +@@ -10,6 +10,7 @@ |
| 86 | + #include <linux/firmware.h> |
| 87 | + #include <linux/module.h> |
| 88 | + #include <linux/bcm47xx_nvram.h> |
| 89 | ++#include <linux/ctype.h> |
| 90 | + |
| 91 | + #include "debug.h" |
| 92 | + #include "firmware.h" |
| 93 | +@@ -32,6 +33,8 @@ enum nvram_parser_state { |
| 94 | + END |
| 95 | + }; |
| 96 | + |
| 97 | ++char saved_ccode[2] = {}; |
| 98 | ++ |
| 99 | + /** |
| 100 | + * struct nvram_parser - internal info for parser. |
| 101 | + * |
| 102 | +@@ -562,11 +565,27 @@ static int brcmf_fw_request_nvram_done(c |
| 103 | + goto fail; |
| 104 | + } |
| 105 | + |
| 106 | +- if (data) |
| 107 | ++ if (data) { |
| 108 | ++ char *ccode = strnstr((char *)data, "ccode=", data_len); |
| 109 | ++ /* Ensure this is a whole token */ |
| 110 | ++ if (ccode && ((void *)ccode == (void *)data || isspace(ccode[-1]))) { |
| 111 | ++ /* Comment out the line */ |
| 112 | ++ ccode[0] = '#'; |
| 113 | ++ ccode += 6; |
| 114 | ++ if (isupper(ccode[0]) && isupper(ccode[1]) && |
| 115 | ++ isspace(ccode[2])) { |
| 116 | ++ pr_debug("brcmfmac: intercepting ccode=%c%c\n", |
| 117 | ++ ccode[0], ccode[1]); |
| 118 | ++ saved_ccode[0] = ccode[0]; |
| 119 | ++ saved_ccode[1] = ccode[1]; |
| 120 | ++ } |
| 121 | ++ }; |
| 122 | ++ |
| 123 | + nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length, |
| 124 | + fwctx->req->domain_nr, |
| 125 | + fwctx->req->bus_nr, |
| 126 | + fwctx->dev); |
| 127 | ++ } |
| 128 | + |
| 129 | + if (free_bcm47xx_nvram) |
| 130 | + bcm47xx_nvram_release_contents(data); |
0 commit comments