NVRAM may contain info about device country. Example from SR40ac (US): wl_country_code=US wl0_country_code=US wl1_country_code=US or Netgear R8000 (Canada): wl0_country_code=CA wl1_country_code=CA wl2_country_code=CA Read it when parsing NVRAM and provide to regulatory. Signed-off-by: Rafał Miłecki <zajec5@xxxxxxxxx> --- This is HACKy code, do not apply! Hi, I wanted to post this suggestion for improving brcmfmac. It's bothering OpenWrt users that have to set country manually. This code is ugly. I think done callback is getting too complex and I don't like the way of referencing wiphy in pcie.c. But it gives a basic idea and I'd like to see if there will be any comments. --- .../broadcom/brcm80211/brcmfmac/cfg80211.h | 3 ++ .../broadcom/brcm80211/brcmfmac/firmware.c | 53 ++++++++++++++-------- .../broadcom/brcm80211/brcmfmac/firmware.h | 6 ++- .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 16 ++++++- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 3 +- .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 3 +- 6 files changed, 59 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index c17b6d5..cb96f68 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h @@ -20,6 +20,9 @@ /* for brcmu_d11inf */ #include <brcmu_d11.h> +#include "fwil_types.h" +#include "p2p.h" + #define WL_NUM_SCAN_MAX 10 #define WL_TLV_INFO_MAX 1024 #define WL_BSS_INFO_MAX 2048 diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 1e4d5f6..6692ef1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -32,6 +32,19 @@ static char brcmf_firmware_path[BRCMF_FW_NAME_LEN]; module_param_string(alternative_fw_path, brcmf_firmware_path, BRCMF_FW_NAME_LEN, 0440); +struct brcmf_fw { + struct device *dev; + u16 flags; + const struct firmware *code; + const char *nvram_name; + u16 domain_nr; + u16 bus_nr; + char alpha2[2]; + void (*done)(struct device *dev, const struct firmware *fw, + void *nvram_image, u32 nvram_len, const char *alpha2); + struct completion *completion; +}; + enum nvram_parser_state { IDLE, KEY, @@ -65,6 +78,7 @@ struct nvram_parser { u32 entry; bool multi_dev_v1; bool multi_dev_v2; + char alpha2[2]; }; /** @@ -127,6 +141,11 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp) nvp->multi_dev_v1 = true; if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0) nvp->multi_dev_v2 = true; + /* TODO: Use wl%d_country_code */ + if (!strncmp(&nvp->data[nvp->entry], "wl0_country_code", 16)) { + nvp->alpha2[0] = nvp->data[nvp->pos + 1]; + nvp->alpha2[1] = nvp->data[nvp->pos + 2]; + } } else if (!is_nvram_char(c) || c == ' ') { brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", nvp->line, nvp->column); @@ -364,7 +383,7 @@ fail: * End of buffer is completed with token identifying length of buffer. */ static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len, - u32 *new_length, u16 domain_nr, u16 bus_nr) + u32 *new_length, struct brcmf_fw *fwctx) { struct nvram_parser nvp; u32 pad; @@ -380,9 +399,14 @@ static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len, break; } if (nvp.multi_dev_v1) - brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr); + brcmf_fw_strip_multi_v1(&nvp, fwctx->domain_nr, fwctx->bus_nr); else if (nvp.multi_dev_v2) - brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr); + brcmf_fw_strip_multi_v2(&nvp, fwctx->domain_nr, fwctx->bus_nr); + + if (nvp.alpha2[0]) { + fwctx->alpha2[0] = nvp.alpha2[0]; + fwctx->alpha2[1] = nvp.alpha2[1]; + } if (nvp.nvram_len == 0) { kfree(nvp.nvram); @@ -411,17 +435,6 @@ void brcmf_fw_nvram_free(void *nvram) kfree(nvram); } -struct brcmf_fw { - struct device *dev; - u16 flags; - const struct firmware *code; - const char *nvram_name; - u16 domain_nr; - u16 bus_nr; - void (*done)(struct device *dev, const struct firmware *fw, - void *nvram_image, u32 nvram_len); -}; - static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) { struct brcmf_fw *fwctx = ctx; @@ -445,7 +458,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) if (data) nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length, - fwctx->domain_nr, fwctx->bus_nr); + fwctx); if (raw_nvram) bcm47xx_nvram_release_contents(data); @@ -453,7 +466,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) goto fail; - fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length); + fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length, fwctx->alpha2[0] ? fwctx->alpha2 : NULL); kfree(fwctx); return; @@ -475,7 +488,7 @@ static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx) /* only requested code so done here */ if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) { - fwctx->done(fwctx->dev, fw, NULL, 0); + fwctx->done(fwctx->dev, fw, NULL, 0, NULL); kfree(fwctx); return; } @@ -500,7 +513,8 @@ int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, const char *code, const char *nvram, void (*fw_cb)(struct device *dev, const struct firmware *fw, - void *nvram_image, u32 nvram_len), + void *nvram_image, u32 nvram_len, + const char *alpha2), u16 domain_nr, u16 bus_nr) { struct brcmf_fw *fwctx; @@ -533,7 +547,8 @@ int brcmf_fw_get_firmwares(struct device *dev, u16 flags, const char *code, const char *nvram, void (*fw_cb)(struct device *dev, const struct firmware *fw, - void *nvram_image, u32 nvram_len)) + void *nvram_image, u32 nvram_len, + const char *alpha2)) { return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0, 0); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h index ef06f57..963e929 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h @@ -76,12 +76,14 @@ int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, const char *code, const char *nvram, void (*fw_cb)(struct device *dev, const struct firmware *fw, - void *nvram_image, u32 nvram_len), + void *nvram_image, u32 nvram_len, + const char *alpha2), u16 domain_nr, u16 bus_nr); int brcmf_fw_get_firmwares(struct device *dev, u16 flags, const char *code, const char *nvram, void (*fw_cb)(struct device *dev, const struct firmware *fw, - void *nvram_image, u32 nvram_len)); + void *nvram_image, u32 nvram_len, + const char *alpha2)); #endif /* BRCMFMAC_FIRMWARE_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 3d2d790..1980416 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1682,8 +1682,11 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { .write32 = brcmf_pcie_buscore_write32, }; +#include "core.h" +#include "cfg80211.h" + static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw, - void *nvram, u32 nvram_len) + void *nvram, u32 nvram_len, const char *alpha2) { struct brcmf_bus *bus = dev_get_drvdata(dev); struct brcmf_pciedev *pcie_bus_dev = bus->bus_priv.pcie; @@ -1734,8 +1737,17 @@ static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw, init_waitqueue_head(&devinfo->mbdata_resp_wait); brcmf_pcie_intr_enable(devinfo); - if (brcmf_pcie_attach_bus(bus->dev) == 0) + if (brcmf_pcie_attach_bus(bus->dev) == 0) { + if (alpha2) { + struct brcmf_bus *bus_if = dev_get_drvdata(bus->dev); + struct brcmf_pub *drvr = bus_if->drvr; + struct brcmf_cfg80211_info *cfg = drvr->config; + + regulatory_hint(cfg->wiphy, alpha2); + } + return; + } brcmf_pcie_bus_console_read(devinfo); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index ceb2a75..e8552ac 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -3928,7 +3928,8 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { static void brcmf_sdio_firmware_callback(struct device *dev, const struct firmware *code, - void *nvram, u32 nvram_len) + void *nvram, u32 nvram_len, + const char *alpha2) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 66c26a9..78ae9d3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -1159,7 +1159,8 @@ fail: static void brcmf_usb_probe_phase2(struct device *dev, const struct firmware *fw, - void *nvram, u32 nvlen) + void *nvram, u32 nvlen, + const char *alpha2) { struct brcmf_bus *bus = dev_get_drvdata(dev); struct brcmf_usbdev_info *devinfo; -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html