diff options
Diffstat (limited to 'drivers/net/wireless/broadcom/brcm80211')
15 files changed, 363 insertions, 42 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile index 9b15bc3f6054..13c13504a6e8 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile @@ -23,7 +23,8 @@ brcmfmac-objs += \ feature.o \ btcoex.o \ vendor.o \ - pno.o + pno.o \ + xtlv.o brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \ bcdc.o \ fwsignal.o diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 633d0ab19031..ac02244a6fdf 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -128,7 +128,8 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) if (sdiodev->bus_if->chip == BRCM_CC_43362_CHIP_ID) { /* assign GPIO to SDIO core */ - addr = CORE_CC_REG(SI_ENUM_BASE, gpiocontrol); + addr = brcmf_chip_enum_base(sdiodev->func1->device); + addr = CORE_CC_REG(addr, gpiocontrol); gpiocontrol = brcmf_sdiod_readl(sdiodev, addr, &ret); gpiocontrol |= 0x2; brcmf_sdiod_writel(sdiodev, addr, gpiocontrol, &ret); @@ -990,6 +991,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4359), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359), { /* end: all zeroes */ } }; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index cedba56fc448..f7b96cd69242 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -1829,6 +1829,14 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE; } break; + case WLAN_AKM_SUITE_FT_OVER_SAE: + val = WPA3_AUTH_SAE_PSK | WPA2_AUTH_FT; + profile->is_ft = true; + if (sme->crypto.sae_pwd) { + brcmf_dbg(INFO, "using SAE offload\n"); + profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE; + } + break; default: bphy_err(drvr, "invalid cipher group (%d)\n", sme->crypto.cipher_group); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 45037decba40..1ee49f9e325d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -139,6 +139,8 @@ struct sbconfig { u32 sbidhigh; /* identification */ }; +#define INVALID_RAMBASE ((u32)(~0)) + /* bankidx and bankinfo reg defines corerev >= 8 */ #define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000 #define SOCRAM_BANKINFO_SZMASK 0x0000007f @@ -527,7 +529,7 @@ static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) int idx = 1; list_for_each_entry(core, &ci->cores, list) { - brcmf_dbg(INFO, " [%-2d] core 0x%x:%-2d base 0x%08x wrap 0x%08x\n", + brcmf_dbg(INFO, " [%-2d] core 0x%x:%-3d base 0x%08x wrap 0x%08x\n", idx++, core->pub.id, core->pub.rev, core->pub.base, core->wrapbase); @@ -727,11 +729,13 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) case BRCM_CC_4364_CHIP_ID: case CY_CC_4373_CHIP_ID: return 0x160000; + case CY_CC_43752_CHIP_ID: + return 0x170000; default: brcmf_err("unknown chip: %s\n", ci->pub.name); break; } - return 0; + return INVALID_RAMBASE; } int brcmf_chip_get_raminfo(struct brcmf_chip *pub) @@ -746,7 +750,7 @@ int brcmf_chip_get_raminfo(struct brcmf_chip *pub) mem_core = container_of(mem, struct brcmf_core_priv, pub); ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core); ci->pub.rambase = brcmf_chip_tcm_rambase(ci); - if (!ci->pub.rambase) { + if (ci->pub.rambase == INVALID_RAMBASE) { brcmf_err("RAM base not provided with ARM CR4 core\n"); return -EINVAL; } @@ -757,7 +761,7 @@ int brcmf_chip_get_raminfo(struct brcmf_chip *pub) pub); ci->pub.ramsize = brcmf_chip_sysmem_ramsize(mem_core); ci->pub.rambase = brcmf_chip_tcm_rambase(ci); - if (!ci->pub.rambase) { + if (ci->pub.rambase == INVALID_RAMBASE) { brcmf_err("RAM base not provided with ARM CA7 core\n"); return -EINVAL; } @@ -894,7 +898,8 @@ int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci) u32 base, wrap; int err; - eromaddr = ci->ops->read32(ci->ctx, CORE_CC_REG(SI_ENUM_BASE, eromptr)); + eromaddr = ci->ops->read32(ci->ctx, + CORE_CC_REG(ci->pub.enum_base, eromptr)); while (desc_type != DMP_DESC_EOT) { val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type); @@ -942,6 +947,11 @@ int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci) return 0; } +u32 brcmf_chip_enum_base(u16 devid) +{ + return SI_ENUM_BASE_DEFAULT; +} + static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) { struct brcmf_core *core; @@ -954,7 +964,8 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) * For different chiptypes or old sdio hosts w/o chipcommon, * other ways of recognition should be added here. */ - regdata = ci->ops->read32(ci->ctx, CORE_CC_REG(SI_ENUM_BASE, chipid)); + regdata = ci->ops->read32(ci->ctx, + CORE_CC_REG(ci->pub.enum_base, chipid)); ci->pub.chip = regdata & CID_ID_MASK; ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; @@ -974,7 +985,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) ci->resetcore = brcmf_chip_sb_resetcore; core = brcmf_chip_add_core(ci, BCMA_CORE_CHIPCOMMON, - SI_ENUM_BASE, 0); + SI_ENUM_BASE_DEFAULT, 0); brcmf_chip_sb_corerev(ci, core); core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV, BCM4329_CORE_BUS_BASE, 0); @@ -1088,7 +1099,7 @@ static int brcmf_chip_setup(struct brcmf_chip_priv *chip) return ret; } -struct brcmf_chip *brcmf_chip_attach(void *ctx, +struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid, const struct brcmf_buscore_ops *ops) { struct brcmf_chip_priv *chip; @@ -1113,6 +1124,7 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, chip->num_cores = 0; chip->ops = ops; chip->ctx = ctx; + chip->pub.enum_base = brcmf_chip_enum_base(devid); err = ops->prepare(ctx); if (err < 0) @@ -1411,6 +1423,7 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) reg = chip->ops->read32(chip->ctx, addr); return (reg & CC_SR_CTL0_ENABLE_MASK) != 0; case BRCM_CC_4359_CHIP_ID: + case CY_CC_43752_CHIP_ID: case CY_CC_43012_CHIP_ID: addr = CORE_CC_REG(pmu->base, retention_ctl); reg = chip->ops->read32(chip->ctx, addr); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h index 8fa38658e727..d69f101f5834 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h @@ -15,6 +15,7 @@ * * @chip: chip identifier. * @chiprev: chip revision. + * @enum_base: base address of core enumeration space. * @cc_caps: chipcommon core capabilities. * @cc_caps_ext: chipcommon core extended capabilities. * @pmucaps: PMU capabilities. @@ -27,6 +28,7 @@ struct brcmf_chip { u32 chip; u32 chiprev; + u32 enum_base; u32 cc_caps; u32 cc_caps_ext; u32 pmucaps; @@ -70,7 +72,7 @@ struct brcmf_buscore_ops { }; int brcmf_chip_get_raminfo(struct brcmf_chip *pub); -struct brcmf_chip *brcmf_chip_attach(void *ctx, +struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid, const struct brcmf_buscore_ops *ops); void brcmf_chip_detach(struct brcmf_chip *chip); struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid); @@ -85,5 +87,6 @@ void brcmf_chip_set_passive(struct brcmf_chip *ci); bool brcmf_chip_set_active(struct brcmf_chip *ci, u32 rstvec); bool brcmf_chip_sr_capable(struct brcmf_chip *pub); char *brcmf_chip_name(u32 chipid, u32 chiprev, char *buf, uint len); +u32 brcmf_chip_enum_base(u16 devid); #endif /* BRCMF_AXIDMP_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index d40104b8df55..0eb13e5df517 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -431,8 +431,6 @@ struct brcmf_fw { void (*done)(struct device *dev, int err, struct brcmf_fw_request *req); }; -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 @@ -594,28 +592,47 @@ static int brcmf_fw_complete_request(const struct firmware *fw, return (cur->flags & BRCMF_FW_REQF_OPTIONAL) ? 0 : ret; } +static char *brcm_alt_fw_path(const char *path, const char *board_type) +{ + char alt_path[BRCMF_FW_NAME_LEN]; + char suffix[5]; + + strscpy(alt_path, path, BRCMF_FW_NAME_LEN); + /* At least one character + suffix */ + if (strlen(alt_path) < 5) + return NULL; + + /* strip .txt or .bin at the end */ + strscpy(suffix, alt_path + strlen(alt_path) - 4, 5); + alt_path[strlen(alt_path) - 4] = 0; + strlcat(alt_path, ".", BRCMF_FW_NAME_LEN); + strlcat(alt_path, board_type, BRCMF_FW_NAME_LEN); + strlcat(alt_path, suffix, BRCMF_FW_NAME_LEN); + + return kstrdup(alt_path, GFP_KERNEL); +} + static int brcmf_fw_request_firmware(const struct firmware **fw, struct brcmf_fw *fwctx) { struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos]; int ret; - /* nvram files are board-specific, first try a board-specific path */ + /* Files can be board-specific, first try a board-specific path */ if (cur->type == BRCMF_FW_TYPE_NVRAM && fwctx->req->board_type) { - char alt_path[BRCMF_FW_NAME_LEN]; + char *alt_path; - strlcpy(alt_path, cur->path, BRCMF_FW_NAME_LEN); - /* strip .txt at the end */ - alt_path[strlen(alt_path) - 4] = 0; - strlcat(alt_path, ".", BRCMF_FW_NAME_LEN); - strlcat(alt_path, fwctx->req->board_type, BRCMF_FW_NAME_LEN); - strlcat(alt_path, ".txt", BRCMF_FW_NAME_LEN); + alt_path = brcm_alt_fw_path(cur->path, fwctx->req->board_type); + if (!alt_path) + goto fallback; ret = request_firmware(fw, alt_path, fwctx->dev); + kfree(alt_path); if (ret == 0) return ret; } +fallback: return request_firmware(fw, cur->path, fwctx->dev); } @@ -639,6 +656,22 @@ static void brcmf_fw_request_done(const struct firmware *fw, void *ctx) kfree(fwctx); } +static void brcmf_fw_request_done_alt_path(const struct firmware *fw, void *ctx) +{ + struct brcmf_fw *fwctx = ctx; + struct brcmf_fw_item *first = &fwctx->req->items[0]; + int ret = 0; + + /* Fall back to canonical path if board firmware not found */ + if (!fw) + ret = request_firmware_nowait(THIS_MODULE, true, first->path, + fwctx->dev, GFP_KERNEL, fwctx, + brcmf_fw_request_done); + + if (fw || ret < 0) + brcmf_fw_request_done(fw, ctx); +} + static bool brcmf_fw_request_is_valid(struct brcmf_fw_request *req) { struct brcmf_fw_item *item; @@ -660,6 +693,7 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req, { struct brcmf_fw_item *first = &req->items[0]; struct brcmf_fw *fwctx; + char *alt_path; int ret; brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev)); @@ -677,9 +711,18 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req, fwctx->req = req; fwctx->done = fw_cb; - ret = request_firmware_nowait(THIS_MODULE, true, first->path, - fwctx->dev, GFP_KERNEL, fwctx, - brcmf_fw_request_done); + /* First try alternative board-specific path if any */ + alt_path = brcm_alt_fw_path(first->path, fwctx->req->board_type); + if (alt_path) { + ret = request_firmware_nowait(THIS_MODULE, true, alt_path, + fwctx->dev, GFP_KERNEL, fwctx, + brcmf_fw_request_done_alt_path); + kfree(alt_path); + } else { + ret = request_firmware_nowait(THIS_MODULE, true, first->path, + fwctx->dev, GFP_KERNEL, fwctx, + brcmf_fw_request_done); + } if (ret < 0) brcmf_fw_request_done(NULL, fwctx); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c index 9ed85420f3ca..d5578ca681bb 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c @@ -15,6 +15,7 @@ #include "bus.h" #include "debug.h" #include "tracepoint.h" +#include "xtlv.h" #include "fwil.h" #include "proto.h" @@ -150,7 +151,8 @@ brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len) mutex_lock(&ifp->drvr->proto_block); err = brcmf_fil_cmd_data(ifp, cmd, data, len, false); - brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len); + brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d, err=%d\n", ifp->ifidx, cmd, + len, err); brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); @@ -260,7 +262,8 @@ brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, bphy_err(drvr, "Creating iovar failed\n"); } - brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len); + brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d, err=%d\n", ifp->ifidx, name, + len, err); brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); @@ -383,14 +386,13 @@ brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, err = -EPERM; bphy_err(drvr, "Creating bsscfg failed\n"); } - brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx, - ifp->bsscfgidx, name, len); + brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d, err=%d\n", + ifp->ifidx, ifp->bsscfgidx, name, len, err); brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); mutex_unlock(&drvr->proto_block); return err; - } s32 @@ -414,3 +416,117 @@ brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data) *data = le32_to_cpu(data_le); return err; } + +static u32 brcmf_create_xtlv(char *name, u16 id, char *data, u32 len, + char *buf, u32 buflen) +{ + u32 iolen; + u32 nmlen; + + nmlen = strlen(name) + 1; + iolen = nmlen + brcmf_xtlv_data_size(len, BRCMF_XTLV_OPTION_ALIGN32); + + if (iolen > buflen) { + brcmf_err("buffer is too short\n"); + return 0; + } + + memcpy(buf, name, nmlen); + brcmf_xtlv_pack_header((void *)(buf + nmlen), id, len, data, + BRCMF_XTLV_OPTION_ALIGN32); + + return iolen; +} + +s32 brcmf_fil_xtlv_data_set(struct brcmf_if *ifp, char *name, u16 id, + void *data, u32 len) +{ + struct brcmf_pub *drvr = ifp->drvr; + s32 err; + u32 buflen; + + mutex_lock(&drvr->proto_block); + + brcmf_dbg(FIL, "ifidx=%d, name=%s, id=%u, len=%u\n", ifp->ifidx, name, + id, len); + brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, + min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); + + buflen = brcmf_create_xtlv(name, id, data, len, + drvr->proto_buf, sizeof(drvr->proto_buf)); + if (buflen) { + err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf, + buflen, true); + } else { + err = -EPERM; + bphy_err(drvr, "Creating xtlv failed\n"); + } + + mutex_unlock(&drvr->proto_block); + return err; +} + +s32 brcmf_fil_xtlv_data_get(struct brcmf_if *ifp, char *name, u16 id, + void *data, u32 len) +{ + struct brcmf_pub *drvr = ifp->drvr; + s32 err; + u32 buflen; + + mutex_lock(&drvr->proto_block); + + buflen = brcmf_create_xtlv(name, id, data, len, + drvr->proto_buf, sizeof(drvr->proto_buf)); + if (buflen) { + err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf, + buflen, false); + if (err == 0) + memcpy(data, drvr->proto_buf, len); + } else { + err = -EPERM; + bphy_err(drvr, "Creating bsscfg failed\n"); + } + brcmf_dbg(FIL, "ifidx=%d, name=%s, id=%u, len=%u, err=%d\n", + ifp->ifidx, name, id, len, err); + brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, + min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); + + mutex_unlock(&drvr->proto_block); + return err; +} + +s32 brcmf_fil_xtlv_int_set(struct brcmf_if *ifp, char *name, u16 id, u32 data) +{ + __le32 data_le = cpu_to_le32(data); + + return brcmf_fil_xtlv_data_set(ifp, name, id, &data_le, + sizeof(data_le)); +} + +s32 brcmf_fil_xtlv_int_get(struct brcmf_if *ifp, char *name, u16 id, u32 *data) +{ + __le32 data_le = cpu_to_le32(*data); + s32 err; + + err = brcmf_fil_xtlv_data_get(ifp, name, id, &data_le, sizeof(data_le)); + if (err == 0) + *data = le32_to_cpu(data_le); + return err; +} + +s32 brcmf_fil_xtlv_int8_get(struct brcmf_if *ifp, char *name, u16 id, u8 *data) +{ + return brcmf_fil_xtlv_data_get(ifp, name, id, data, sizeof(*data)); +} + +s32 brcmf_fil_xtlv_int16_get(struct brcmf_if *ifp, char *name, u16 id, u16 *data) +{ + __le16 data_le = cpu_to_le16(*data); + s32 err; + + err = brcmf_fil_xtlv_data_get(ifp, name, id, &data_le, sizeof(data_le)); + if (err == 0) + *data = le16_to_cpu(data_le); + return err; +} + diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h index ae4cf4372908..cb26f8c59c21 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h @@ -97,5 +97,13 @@ s32 brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, void *data, u32 len); s32 brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data); s32 brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data); +s32 brcmf_fil_xtlv_data_set(struct brcmf_if *ifp, char *name, u16 id, + void *data, u32 len); +s32 brcmf_fil_xtlv_data_get(struct brcmf_if *ifp, char *name, u16 id, + void *data, u32 len); +s32 brcmf_fil_xtlv_int_set(struct brcmf_if *ifp, char *name, u16 id, u32 data); +s32 brcmf_fil_xtlv_int_get(struct brcmf_if *ifp, char *name, u16 id, u32 *data); +s32 brcmf_fil_xtlv_int8_get(struct brcmf_if *ifp, char *name, u16 id, u8 *data); +s32 brcmf_fil_xtlv_int16_get(struct brcmf_if *ifp, char *name, u16 id, u16 *data); #endif /* _fwil_h_ */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index c49dd0c36ae4..8b149996fc00 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1886,7 +1886,8 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) devinfo->pdev = pdev; pcie_bus_dev = NULL; - devinfo->ci = brcmf_chip_attach(devinfo, &brcmf_pcie_buscore_ops); + devinfo->ci = brcmf_chip_attach(devinfo, pdev->device, + &brcmf_pcie_buscore_ops); if (IS_ERR(devinfo->ci)) { ret = PTR_ERR(devinfo->ci); devinfo->ci = NULL; @@ -2075,7 +2076,7 @@ cleanup: err = brcmf_pcie_probe(pdev, NULL); if (err) - brcmf_err(bus, "probe after resume failed, err=%d\n", err); + __brcmf_err(NULL, __func__, "probe after resume failed, err=%d\n", err); return err; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 97ee9e2e2e35..8effeb7a7269 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -617,6 +617,7 @@ BRCMF_FW_DEF(4339, "brcmfmac4339-sdio"); BRCMF_FW_DEF(43430A0, "brcmfmac43430a0-sdio"); /* Note the names are not postfixed with a1 for backward compatibility */ BRCMF_FW_CLM_DEF(43430A1, "brcmfmac43430-sdio"); +BRCMF_FW_DEF(43430B0, "brcmfmac43430b0-sdio"); BRCMF_FW_CLM_DEF(43455, "brcmfmac43455-sdio"); BRCMF_FW_DEF(43456, "brcmfmac43456-sdio"); BRCMF_FW_CLM_DEF(4354, "brcmfmac4354-sdio"); @@ -624,11 +625,15 @@ BRCMF_FW_CLM_DEF(4356, "brcmfmac4356-sdio"); BRCMF_FW_DEF(4359, "brcmfmac4359-sdio"); BRCMF_FW_CLM_DEF(4373, "brcmfmac4373-sdio"); BRCMF_FW_CLM_DEF(43012, "brcmfmac43012-sdio"); +BRCMF_FW_CLM_DEF(43752, "brcmfmac43752-sdio"); /* firmware config files */ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.txt"); MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt"); +/* per-board firmware binaries */ +MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.bin"); + static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143), BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0), @@ -643,14 +648,16 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { BRCMF_FW_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), BRCMF_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0), - BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1), + BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000002, 43430A1), + BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFC, 43430B0), BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0x00000200, 43456), BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFDC0, 43455), BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354), BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356), BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359), BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373), - BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012) + BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012), + BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752) }; #define TXCTL_CREDITS 2 @@ -3416,7 +3423,8 @@ err: static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus) { - if (bus->ci->chip == CY_CC_43012_CHIP_ID) + if (bus->ci->chip == CY_CC_43012_CHIP_ID || + bus->ci->chip == CY_CC_43752_CHIP_ID) return true; else return false; @@ -3907,7 +3915,7 @@ static u32 brcmf_sdio_buscore_read32(void *ctx, u32 addr) * It can be identified as 4339 by looking at the chip revision. It * is corrected here so the chip.c module has the right info. */ - if (addr == CORE_CC_REG(SI_ENUM_BASE, chipid) && + if (addr == CORE_CC_REG(SI_ENUM_BASE_DEFAULT, chipid) && (sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4339 || sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) { rev = (val & CID_REV_MASK) >> CID_REV_SHIFT; @@ -3943,12 +3951,15 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) int reg_addr; u32 reg_val; u32 drivestrength; + u32 enum_base; sdiodev = bus->sdiodev; sdio_claim_host(sdiodev->func1); - pr_debug("F1 signature read @0x18000000=0x%4x\n", - brcmf_sdiod_readl(sdiodev, SI_ENUM_BASE, NULL)); + enum_base = brcmf_chip_enum_base(sdiodev->func1->device); + + pr_debug("F1 signature read @0x%08x=0x%4x\n", enum_base, + brcmf_sdiod_readl(sdiodev, enum_base, NULL)); /* * Force PLL off until brcmf_chip_attach() @@ -3967,7 +3978,8 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) goto fail; } - bus->ci = brcmf_chip_attach(sdiodev, &brcmf_sdio_buscore_ops); + bus->ci = brcmf_chip_attach(sdiodev, sdiodev->func1->device, + &brcmf_sdio_buscore_ops); if (IS_ERR(bus->ci)) { brcmf_err("brcmf_chip_attach failed!\n"); bus->ci = NULL; @@ -4257,6 +4269,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, switch (sdiod->func1->device) { case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373: + case SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752: brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n", CY_4373_F2_WATERMARK); brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, @@ -4442,7 +4455,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) bus->tx_seq = SDPCM_SEQ_WRAP - 1; /* single-threaded workqueue */ - wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM, + wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM | WQ_HIGHPRI, dev_name(&sdiodev->func1->dev)); if (!wq) { brcmf_err("insufficient memory to create txworkqueue\n"); @@ -4616,4 +4629,3 @@ int brcmf_sdio_sleep(struct brcmf_sdio *bus, bool sleep) return ret; } - diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/xtlv.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/xtlv.c new file mode 100644 index 000000000000..2f3c451148db --- /dev/null +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/xtlv.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (c) 2019 Broadcom + */ + +#include <asm/unaligned.h> +#include <linux/string.h> +#include <linux/bug.h> + +#include "xtlv.h" + +static int brcmf_xtlv_header_size(u16 opts) +{ + int len = (int)offsetof(struct brcmf_xtlv, data); + + if (opts & BRCMF_XTLV_OPTION_IDU8) + --len; + if (opts & BRCMF_XTLV_OPTION_LENU8) + --len; + + return len; +} + +int brcmf_xtlv_data_size(int dlen, u16 opts) +{ + int hsz; + + hsz = brcmf_xtlv_header_size(opts); + if (opts & BRCMF_XTLV_OPTION_ALIGN32) + return roundup(dlen + hsz, 4); + + return dlen + hsz; +} + +void brcmf_xtlv_pack_header(struct brcmf_xtlv *xtlv, u16 id, u16 len, + const u8 *data, u16 opts) +{ + u8 *data_buf; + u16 mask = BRCMF_XTLV_OPTION_IDU8 | BRCMF_XTLV_OPTION_LENU8; + + if (!(opts & mask)) { + u8 *idp = (u8 *)xtlv; + u8 *lenp = idp + sizeof(xtlv->id); + + put_unaligned_le16(id, idp); + put_unaligned_le16(len, lenp); + data_buf = lenp + sizeof(u16); + } else if ((opts & mask) == mask) { /* u8 id and u8 len */ + u8 *idp = (u8 *)xtlv; + u8 *lenp = idp + 1; + + *idp = (u8)id; + *lenp = (u8)len; + data_buf = lenp + sizeof(u8); + } else if (opts & BRCMF_XTLV_OPTION_IDU8) { /* u8 id, u16 len */ + u8 *idp = (u8 *)xtlv; + u8 *lenp = idp + 1; + + *idp = (u8)id; + put_unaligned_le16(len, lenp); + data_buf = lenp + sizeof(u16); + } else if (opts & BRCMF_XTLV_OPTION_LENU8) { /* u16 id, u8 len */ + u8 *idp = (u8 *)xtlv; + u8 *lenp = idp + sizeof(u16); + + put_unaligned_le16(id, idp); + *lenp = (u8)len; + data_buf = lenp + sizeof(u8); + } else { + WARN(true, "Unexpected xtlv option"); + return; + } + + if (opts & BRCMF_XTLV_OPTION_LENU8) { + WARN_ON(len > 0x00ff); + len &= 0xff; + } + + if (data) + memcpy(data_buf, data, len); +} + diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/xtlv.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/xtlv.h new file mode 100644 index 000000000000..e1930ce1b642 --- /dev/null +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/xtlv.h @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (c) 2019 Broadcom + */ +#ifndef __BRCMF_XTLV_H +#define __BRCMF_XTLV_H + +#include <linux/types.h> +#include <linux/bits.h> + +/* bcm type(id), length, value with w/16 bit id/len. The structure below + * is nominal, and is used to support variable length id and type. See + * xtlv options below. + */ +struct brcmf_xtlv { + u16 id; + u16 len; + u8 data[0]; +}; + +enum brcmf_xtlv_option { + BRCMF_XTLV_OPTION_ALIGN32 = BIT(0), + BRCMF_XTLV_OPTION_IDU8 = BIT(1), + BRCMF_XTLV_OPTION_LENU8 = BIT(2), +}; + +int brcmf_xtlv_data_size(int dlen, u16 opts); +void brcmf_xtlv_pack_header(struct brcmf_xtlv *xtlv, u16 id, u16 len, + const u8 *data, u16 opts); + +#endif /* __BRCMF_XTLV_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c index 26de1bd7fee9..8ddfc3d06687 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c @@ -704,7 +704,7 @@ static void brcms_c_write_inits(struct brcms_hardware *wlc_hw, static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs) { u8 idx; - u16 addr[] = { + static const u16 addr[] = { M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4, M_HOST_FLAGS5 }; diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h index 00309b272a0e..9d81320164ce 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h @@ -52,6 +52,7 @@ #define BRCM_CC_4371_CHIP_ID 0x4371 #define CY_CC_4373_CHIP_ID 0x4373 #define CY_CC_43012_CHIP_ID 43012 +#define CY_CC_43752_CHIP_ID 43752 /* USB Device IDs */ #define BRCM_USB_43143_DEVICE_ID 0xbd1e diff --git a/drivers/net/wireless/broadcom/brcm80211/include/soc.h b/drivers/net/wireless/broadcom/brcm80211/include/soc.h index 92d942b44f2c..824921191366 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/soc.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/soc.h @@ -6,7 +6,7 @@ #ifndef _BRCM_SOC_H #define _BRCM_SOC_H -#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ +#define SI_ENUM_BASE_DEFAULT 0x18000000 /* Common core control flags */ #define SICF_BIST_EN 0x8000 |