Skip to content

Commit

Permalink
wifi: brcmfmac: pcie/sdio/usb: Get CLM blob via standard firmware mec…
Browse files Browse the repository at this point in the history
…hanism

Now that the firmware fetcher can handle per-board CLM files, load the
CLM blob alongside the other firmware files and change the bus API to
just return the existing blob, instead of fetching the filename.

This enables per-board CLM blobs, which are required on Apple platforms.

Acked-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Hector Martin <marcan@marcan.st>
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/E1oZDnY-0077aA-8f@rmk-PC.armlinux.org.uk
  • Loading branch information
Hector Martin authored and Kalle Valo committed Sep 19, 2022
1 parent e263d72 commit a1b5a90
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 62 deletions.
19 changes: 13 additions & 6 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#ifndef BRCMFMAC_BUS_H
#define BRCMFMAC_BUS_H

#include <linux/kernel.h>
#include <linux/firmware.h>
#include "debug.h"

/* IDs of the 6 default common rings of msgbuf protocol */
Expand Down Expand Up @@ -34,6 +36,11 @@ enum brcmf_bus_protocol_type {
BRCMF_PROTO_MSGBUF
};

/* Firmware blobs that may be available */
enum brcmf_blob_type {
BRCMF_BLOB_CLM,
};

struct brcmf_mp_device;

struct brcmf_bus_dcmd {
Expand All @@ -60,7 +67,7 @@ struct brcmf_bus_dcmd {
* @wowl_config: specify if dongle is configured for wowl when going to suspend
* @get_ramsize: obtain size of device memory.
* @get_memdump: obtain device memory dump in provided buffer.
* @get_fwname: obtain firmware name.
* @get_blob: obtain a firmware blob.
*
* This structure provides an abstract interface towards the
* bus specific driver. For control messages to common driver
Expand All @@ -77,8 +84,8 @@ struct brcmf_bus_ops {
void (*wowl_config)(struct device *dev, bool enabled);
size_t (*get_ramsize)(struct device *dev);
int (*get_memdump)(struct device *dev, void *data, size_t len);
int (*get_fwname)(struct device *dev, const char *ext,
unsigned char *fw_name);
int (*get_blob)(struct device *dev, const struct firmware **fw,
enum brcmf_blob_type type);
void (*debugfs_create)(struct device *dev);
int (*reset)(struct device *dev);
};
Expand Down Expand Up @@ -220,10 +227,10 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len)
}

static inline
int brcmf_bus_get_fwname(struct brcmf_bus *bus, const char *ext,
unsigned char *fw_name)
int brcmf_bus_get_blob(struct brcmf_bus *bus, const struct firmware **fw,
enum brcmf_blob_type type)
{
return bus->ops->get_fwname(bus->dev, ext, fw_name);
return bus->ops->get_blob(bus->dev, fw, type);
}

static inline
Expand Down
12 changes: 2 additions & 10 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
struct brcmf_bus *bus = drvr->bus_if;
struct brcmf_dload_data_le *chunk_buf;
const struct firmware *clm = NULL;
u8 clm_name[BRCMF_FW_NAME_LEN];
u32 chunk_len;
u32 datalen;
u32 cumulative_len;
Expand All @@ -133,15 +132,8 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)

brcmf_dbg(TRACE, "Enter\n");

memset(clm_name, 0, sizeof(clm_name));
err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name);
if (err) {
bphy_err(drvr, "get CLM blob file name failed (%d)\n", err);
return err;
}

err = firmware_request_nowarn(&clm, clm_name, bus->dev);
if (err) {
err = brcmf_bus_get_blob(bus, &clm, BRCMF_BLOB_CLM);
if (err || !clm) {
brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
err);
return 0;
Expand Down
39 changes: 25 additions & 14 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt");

/* per-board firmware binaries */
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin");
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.clm_blob");

static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
Expand Down Expand Up @@ -261,6 +262,8 @@ struct brcmf_pciedev_info {
struct pci_dev *pdev;
char fw_name[BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_NAME_LEN];
char clm_name[BRCMF_FW_NAME_LEN];
const struct firmware *clm_fw;
void __iomem *regs;
void __iomem *tcm;
u32 ram_base;
Expand Down Expand Up @@ -1382,23 +1385,25 @@ static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)
return 0;
}

static
int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
static int brcmf_pcie_get_blob(struct device *dev, const struct firmware **fw,
enum brcmf_blob_type type)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_fw_request *fwreq;
struct brcmf_fw_name fwnames[] = {
{ ext, fw_name },
};
struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
struct brcmf_pciedev_info *devinfo = buspub->devinfo;

fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
brcmf_pcie_fwnames,
ARRAY_SIZE(brcmf_pcie_fwnames),
fwnames, ARRAY_SIZE(fwnames));
if (!fwreq)
return -ENOMEM;
switch (type) {
case BRCMF_BLOB_CLM:
*fw = devinfo->clm_fw;
devinfo->clm_fw = NULL;
break;
default:
return -ENOENT;
}

if (!*fw)
return -ENOENT;

kfree(fwreq);
return 0;
}

Expand Down Expand Up @@ -1445,7 +1450,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
.wowl_config = brcmf_pcie_wowl_config,
.get_ramsize = brcmf_pcie_get_ramsize,
.get_memdump = brcmf_pcie_get_memdump,
.get_fwname = brcmf_pcie_get_fwname,
.get_blob = brcmf_pcie_get_blob,
.reset = brcmf_pcie_reset,
};

Expand Down Expand Up @@ -1731,6 +1736,7 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {

#define BRCMF_PCIE_FW_CODE 0
#define BRCMF_PCIE_FW_NVRAM 1
#define BRCMF_PCIE_FW_CLM 2

static void brcmf_pcie_setup(struct device *dev, int ret,
struct brcmf_fw_request *fwreq)
Expand All @@ -1755,6 +1761,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary;
nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
devinfo->clm_fw = fwreq->items[BRCMF_PCIE_FW_CLM].binary;
kfree(fwreq);

ret = brcmf_chip_get_raminfo(devinfo->ci);
Expand Down Expand Up @@ -1830,6 +1837,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
struct brcmf_fw_name fwnames[] = {
{ ".bin", devinfo->fw_name },
{ ".txt", devinfo->nvram_name },
{ ".clm_blob", devinfo->clm_name },
};

fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
Expand All @@ -1842,6 +1850,8 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
fwreq->board_type = devinfo->settings->board_type;
/* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */
fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
Expand Down Expand Up @@ -1981,6 +1991,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
brcmf_pcie_release_ringbuffers(devinfo);
brcmf_pcie_reset_device(devinfo);
brcmf_pcie_release_resource(devinfo);
release_firmware(devinfo->clm_fw);

if (devinfo->ci)
brcmf_chip_detach(devinfo->ci);
Expand Down
36 changes: 22 additions & 14 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -4131,23 +4131,24 @@ brcmf_sdio_watchdog(struct timer_list *t)
}
}

static
int brcmf_sdio_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
static int brcmf_sdio_get_blob(struct device *dev, const struct firmware **fw,
enum brcmf_blob_type type)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_fw_request *fwreq;
struct brcmf_fw_name fwnames[] = {
{ ext, fw_name },
};
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;

fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
brcmf_sdio_fwnames,
ARRAY_SIZE(brcmf_sdio_fwnames),
fwnames, ARRAY_SIZE(fwnames));
if (!fwreq)
return -ENOMEM;
switch (type) {
case BRCMF_BLOB_CLM:
*fw = sdiodev->clm_fw;
sdiodev->clm_fw = NULL;
break;
default:
return -ENOENT;
}

if (!*fw)
return -ENOENT;

kfree(fwreq);
return 0;
}

Expand Down Expand Up @@ -4182,13 +4183,14 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.wowl_config = brcmf_sdio_wowl_config,
.get_ramsize = brcmf_sdio_bus_get_ramsize,
.get_memdump = brcmf_sdio_bus_get_memdump,
.get_fwname = brcmf_sdio_get_fwname,
.get_blob = brcmf_sdio_get_blob,
.debugfs_create = brcmf_sdio_debugfs_create,
.reset = brcmf_sdio_bus_reset
};

#define BRCMF_SDIO_FW_CODE 0
#define BRCMF_SDIO_FW_NVRAM 1
#define BRCMF_SDIO_FW_CLM 2

static void brcmf_sdio_firmware_callback(struct device *dev, int err,
struct brcmf_fw_request *fwreq)
Expand All @@ -4211,6 +4213,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
code = fwreq->items[BRCMF_SDIO_FW_CODE].binary;
nvram = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.data;
nvram_len = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.len;
sdiod->clm_fw = fwreq->items[BRCMF_SDIO_FW_CLM].binary;
kfree(fwreq);

/* try to download image and nvram to the dongle */
Expand Down Expand Up @@ -4409,6 +4412,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
struct brcmf_fw_name fwnames[] = {
{ ".bin", bus->sdiodev->fw_name },
{ ".txt", bus->sdiodev->nvram_name },
{ ".clm_blob", bus->sdiodev->clm_name },
};

fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
Expand All @@ -4420,6 +4424,8 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)

fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
fwreq->items[BRCMF_SDIO_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_SDIO_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
fwreq->board_type = bus->sdiodev->settings->board_type;

return fwreq;
Expand Down Expand Up @@ -4576,6 +4582,8 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
if (bus->sdiodev->settings)
brcmf_release_module_param(bus->sdiodev->settings);

release_firmware(bus->sdiodev->clm_fw);
bus->sdiodev->clm_fw = NULL;
kfree(bus->rxbuf);
kfree(bus->hdrbuf);
kfree(bus);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,11 @@ struct brcmf_sdio_dev {
struct sg_table sgtable;
char fw_name[BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_NAME_LEN];
char clm_name[BRCMF_FW_NAME_LEN];
bool wowl_enabled;
enum brcmf_sdiod_state state;
struct brcmf_sdiod_freezer *freezer;
const struct firmware *clm_fw;
};

/* sdio core registers */
Expand Down
23 changes: 5 additions & 18 deletions drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1154,24 +1154,11 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
return NULL;
}

static
int brcmf_usb_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
static int brcmf_usb_get_blob(struct device *dev, const struct firmware **fw,
enum brcmf_blob_type type)
{
struct brcmf_bus *bus = dev_get_drvdata(dev);
struct brcmf_fw_request *fwreq;
struct brcmf_fw_name fwnames[] = {
{ ext, fw_name },
};

fwreq = brcmf_fw_alloc_request(bus->chip, bus->chiprev,
brcmf_usb_fwnames,
ARRAY_SIZE(brcmf_usb_fwnames),
fwnames, ARRAY_SIZE(fwnames));
if (!fwreq)
return -ENOMEM;

kfree(fwreq);
return 0;
/* No blobs for USB devices... */
return -ENOENT;
}

static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
Expand All @@ -1180,7 +1167,7 @@ static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
.txdata = brcmf_usb_tx,
.txctl = brcmf_usb_tx_ctlpkt,
.rxctl = brcmf_usb_rx_ctlpkt,
.get_fwname = brcmf_usb_get_fwname,
.get_blob = brcmf_usb_get_blob,
};

#define BRCMF_USB_FW_CODE 0
Expand Down

0 comments on commit a1b5a90

Please sign in to comment.