mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-30 18:47:06 +00:00
329 lines
10 KiB
Diff
329 lines
10 KiB
Diff
|
From 2baa3aaee27f137b8db9a9224d0fe9b281d28e34 Mon Sep 17 00:00:00 2001
|
||
|
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||
|
Date: Thu, 22 Mar 2018 21:28:27 +0100
|
||
|
Subject: [PATCH] brcmfmac: introduce brcmf_fw_alloc_request() function
|
||
|
|
||
|
The function brcmf_fw_alloc_request() takes a list of required files
|
||
|
and allocated the struct brcmf_fw_request instance accordingly. The
|
||
|
request can be modified by the caller before being passed to the
|
||
|
brcmf_fw_request_firmwares() function.
|
||
|
|
||
|
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
||
|
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
||
|
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
||
|
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
||
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||
|
---
|
||
|
.../broadcom/brcm80211/brcmfmac/firmware.c | 58 ++++++++++++++++++++++
|
||
|
.../broadcom/brcm80211/brcmfmac/firmware.h | 11 ++++
|
||
|
.../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 58 ++++++++++++----------
|
||
|
.../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 38 ++++++++------
|
||
|
.../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 42 +++++++++-------
|
||
|
5 files changed, 147 insertions(+), 60 deletions(-)
|
||
|
|
||
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||
|
@@ -688,3 +688,61 @@ int brcmf_fw_map_chip_to_name(u32 chip,
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+struct brcmf_fw_request *
|
||
|
+brcmf_fw_alloc_request(u32 chip, u32 chiprev,
|
||
|
+ struct brcmf_firmware_mapping mapping_table[],
|
||
|
+ u32 table_size, struct brcmf_fw_name *fwnames,
|
||
|
+ u32 n_fwnames)
|
||
|
+{
|
||
|
+ struct brcmf_fw_request *fwreq;
|
||
|
+ char chipname[12];
|
||
|
+ const char *mp_path;
|
||
|
+ u32 i, j;
|
||
|
+ char end;
|
||
|
+ size_t reqsz;
|
||
|
+
|
||
|
+ for (i = 0; i < table_size; i++) {
|
||
|
+ if (mapping_table[i].chipid == chip &&
|
||
|
+ mapping_table[i].revmask & BIT(chiprev))
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (i == table_size) {
|
||
|
+ brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ reqsz = sizeof(*fwreq) + n_fwnames * sizeof(struct brcmf_fw_item);
|
||
|
+ fwreq = kzalloc(reqsz, GFP_KERNEL);
|
||
|
+ if (!fwreq)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname));
|
||
|
+
|
||
|
+ brcmf_info("using %s for chip %s\n",
|
||
|
+ mapping_table[i].fw_base, chipname);
|
||
|
+
|
||
|
+ mp_path = brcmf_mp_global.firmware_path;
|
||
|
+ end = mp_path[strlen(mp_path) - 1];
|
||
|
+ fwreq->n_items = n_fwnames;
|
||
|
+
|
||
|
+ for (j = 0; j < n_fwnames; j++) {
|
||
|
+ fwreq->items[j].path = fwnames[j].path;
|
||
|
+ /* check if firmware path is provided by module parameter */
|
||
|
+ if (brcmf_mp_global.firmware_path[0] != '\0') {
|
||
|
+ strlcpy(fwnames[j].path, mp_path,
|
||
|
+ BRCMF_FW_NAME_LEN);
|
||
|
+
|
||
|
+ if (end != '/') {
|
||
|
+ strlcat(fwnames[j].path, "/",
|
||
|
+ BRCMF_FW_NAME_LEN);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ brcmf_fw_get_full_name(fwnames[j].path,
|
||
|
+ mapping_table[i].fw_base,
|
||
|
+ fwnames[j].extension);
|
||
|
+ fwreq->items[j].path = fwnames[j].path;
|
||
|
+ }
|
||
|
+
|
||
|
+ return fwreq;
|
||
|
+}
|
||
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
|
||
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
|
||
|
@@ -77,6 +77,17 @@ struct brcmf_fw_request {
|
||
|
struct brcmf_fw_item items[0];
|
||
|
};
|
||
|
|
||
|
+struct brcmf_fw_name {
|
||
|
+ const char *extension;
|
||
|
+ char *path;
|
||
|
+};
|
||
|
+
|
||
|
+struct brcmf_fw_request *
|
||
|
+brcmf_fw_alloc_request(u32 chip, u32 chiprev,
|
||
|
+ struct brcmf_firmware_mapping mapping_table[],
|
||
|
+ u32 table_size, struct brcmf_fw_name *fwnames,
|
||
|
+ u32 n_fwnames);
|
||
|
+
|
||
|
/*
|
||
|
* Request firmware(s) asynchronously. When the asynchronous request
|
||
|
* fails it will not use the callback, but call device_release_driver()
|
||
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
|
||
|
@@ -1735,6 +1735,31 @@ fail:
|
||
|
device_release_driver(dev);
|
||
|
}
|
||
|
|
||
|
+static struct brcmf_fw_request *
|
||
|
+brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
|
||
|
+{
|
||
|
+ struct brcmf_fw_request *fwreq;
|
||
|
+ struct brcmf_fw_name fwnames[] = {
|
||
|
+ { ".bin", devinfo->fw_name },
|
||
|
+ { ".txt", devinfo->nvram_name },
|
||
|
+ };
|
||
|
+
|
||
|
+ fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
|
||
|
+ brcmf_pcie_fwnames,
|
||
|
+ ARRAY_SIZE(brcmf_pcie_fwnames),
|
||
|
+ fwnames, ARRAY_SIZE(fwnames));
|
||
|
+ if (!fwreq)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ 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->domain_nr = pci_domain_nr(devinfo->pdev->bus);
|
||
|
+ fwreq->bus_nr = devinfo->pdev->bus->number;
|
||
|
+
|
||
|
+ return fwreq;
|
||
|
+}
|
||
|
+
|
||
|
static int
|
||
|
brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||
|
{
|
||
|
@@ -1743,13 +1768,8 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
|
||
|
struct brcmf_pciedev_info *devinfo;
|
||
|
struct brcmf_pciedev *pcie_bus_dev;
|
||
|
struct brcmf_bus *bus;
|
||
|
- u16 domain_nr;
|
||
|
- u16 bus_nr;
|
||
|
|
||
|
- domain_nr = pci_domain_nr(pdev->bus) + 1;
|
||
|
- bus_nr = pdev->bus->number;
|
||
|
- brcmf_dbg(PCIE, "Enter %x:%x (%d/%d)\n", pdev->vendor, pdev->device,
|
||
|
- domain_nr, bus_nr);
|
||
|
+ brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
|
||
|
|
||
|
ret = -ENOMEM;
|
||
|
devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
|
||
|
@@ -1803,33 +1823,19 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
|
||
|
bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot);
|
||
|
dev_set_drvdata(&pdev->dev, bus);
|
||
|
|
||
|
- ret = brcmf_fw_map_chip_to_name(devinfo->ci->chip, devinfo->ci->chiprev,
|
||
|
- brcmf_pcie_fwnames,
|
||
|
- ARRAY_SIZE(brcmf_pcie_fwnames),
|
||
|
- devinfo->fw_name, devinfo->nvram_name);
|
||
|
- if (ret)
|
||
|
- goto fail_bus;
|
||
|
-
|
||
|
- fwreq = kzalloc(sizeof(*fwreq) + 2 * sizeof(struct brcmf_fw_item),
|
||
|
- GFP_KERNEL);
|
||
|
+ fwreq = brcmf_pcie_prepare_fw_request(devinfo);
|
||
|
if (!fwreq) {
|
||
|
ret = -ENOMEM;
|
||
|
goto fail_bus;
|
||
|
}
|
||
|
|
||
|
- fwreq->items[BRCMF_PCIE_FW_CODE].path = devinfo->fw_name;
|
||
|
- fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
|
||
|
- fwreq->items[BRCMF_PCIE_FW_NVRAM].path = devinfo->nvram_name;
|
||
|
- fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
|
||
|
- fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
|
||
|
- fwreq->n_items = 2;
|
||
|
- fwreq->domain_nr = domain_nr;
|
||
|
- fwreq->bus_nr = bus_nr;
|
||
|
ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
|
||
|
- if (ret == 0)
|
||
|
- return 0;
|
||
|
+ if (ret < 0) {
|
||
|
+ kfree(fwreq);
|
||
|
+ goto fail_bus;
|
||
|
+ }
|
||
|
+ return 0;
|
||
|
|
||
|
- kfree(fwreq);
|
||
|
fail_bus:
|
||
|
kfree(bus->msgbuf);
|
||
|
kfree(bus);
|
||
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
||
|
@@ -4155,6 +4155,28 @@ fail:
|
||
|
device_release_driver(dev);
|
||
|
}
|
||
|
|
||
|
+static struct brcmf_fw_request *
|
||
|
+brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
|
||
|
+{
|
||
|
+ struct brcmf_fw_request *fwreq;
|
||
|
+ struct brcmf_fw_name fwnames[] = {
|
||
|
+ { ".bin", bus->sdiodev->fw_name },
|
||
|
+ { ".txt", bus->sdiodev->nvram_name },
|
||
|
+ };
|
||
|
+
|
||
|
+ fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
|
||
|
+ brcmf_sdio_fwnames,
|
||
|
+ ARRAY_SIZE(brcmf_sdio_fwnames),
|
||
|
+ fwnames, ARRAY_SIZE(fwnames));
|
||
|
+ if (!fwreq)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
|
||
|
+ fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
|
||
|
+
|
||
|
+ return fwreq;
|
||
|
+}
|
||
|
+
|
||
|
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
|
||
|
{
|
||
|
int ret;
|
||
|
@@ -4244,26 +4266,12 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
|
||
|
|
||
|
brcmf_dbg(INFO, "completed!!\n");
|
||
|
|
||
|
- ret = brcmf_fw_map_chip_to_name(bus->ci->chip, bus->ci->chiprev,
|
||
|
- brcmf_sdio_fwnames,
|
||
|
- ARRAY_SIZE(brcmf_sdio_fwnames),
|
||
|
- sdiodev->fw_name, sdiodev->nvram_name);
|
||
|
- if (ret)
|
||
|
- goto fail;
|
||
|
-
|
||
|
- fwreq = kzalloc(sizeof(fwreq) + 2 * sizeof(struct brcmf_fw_item),
|
||
|
- GFP_KERNEL);
|
||
|
+ fwreq = brcmf_sdio_prepare_fw_request(bus);
|
||
|
if (!fwreq) {
|
||
|
ret = -ENOMEM;
|
||
|
goto fail;
|
||
|
}
|
||
|
|
||
|
- fwreq->items[BRCMF_SDIO_FW_CODE].path = sdiodev->fw_name;
|
||
|
- fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
|
||
|
- fwreq->items[BRCMF_SDIO_FW_NVRAM].path = sdiodev->nvram_name;
|
||
|
- fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
|
||
|
- fwreq->n_items = 2;
|
||
|
-
|
||
|
ret = brcmf_fw_get_firmwares(sdiodev->dev, fwreq,
|
||
|
brcmf_sdio_firmware_callback);
|
||
|
if (ret != 0) {
|
||
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
|
||
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
|
||
|
@@ -1200,6 +1200,27 @@ error:
|
||
|
device_release_driver(dev);
|
||
|
}
|
||
|
|
||
|
+static struct brcmf_fw_request *
|
||
|
+brcmf_usb_prepare_fw_request(struct brcmf_usbdev_info *devinfo)
|
||
|
+{
|
||
|
+ struct brcmf_fw_request *fwreq;
|
||
|
+ struct brcmf_fw_name fwnames[] = {
|
||
|
+ { ".bin", devinfo->fw_name },
|
||
|
+ };
|
||
|
+
|
||
|
+ fwreq = brcmf_fw_alloc_request(devinfo->bus_pub.devid,
|
||
|
+ devinfo->bus_pub.chiprev,
|
||
|
+ brcmf_usb_fwnames,
|
||
|
+ ARRAY_SIZE(brcmf_usb_fwnames),
|
||
|
+ fwnames, ARRAY_SIZE(fwnames));
|
||
|
+ if (!fwreq)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
|
||
|
+
|
||
|
+ return fwreq;
|
||
|
+}
|
||
|
+
|
||
|
static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
|
||
|
{
|
||
|
struct brcmf_bus *bus = NULL;
|
||
|
@@ -1249,24 +1270,12 @@ static int brcmf_usb_probe_cb(struct brc
|
||
|
bus->chip = bus_pub->devid;
|
||
|
bus->chiprev = bus_pub->chiprev;
|
||
|
|
||
|
- ret = brcmf_fw_map_chip_to_name(bus_pub->devid, bus_pub->chiprev,
|
||
|
- brcmf_usb_fwnames,
|
||
|
- ARRAY_SIZE(brcmf_usb_fwnames),
|
||
|
- devinfo->fw_name, NULL);
|
||
|
- if (ret)
|
||
|
- goto fail;
|
||
|
-
|
||
|
- fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
|
||
|
- GFP_KERNEL);
|
||
|
+ fwreq = brcmf_usb_prepare_fw_request(devinfo);
|
||
|
if (!fwreq) {
|
||
|
ret = -ENOMEM;
|
||
|
goto fail;
|
||
|
}
|
||
|
|
||
|
- fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
|
||
|
- fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
|
||
|
- fwreq->n_items = 1;
|
||
|
-
|
||
|
/* request firmware here */
|
||
|
ret = brcmf_fw_get_firmwares(dev, fwreq, brcmf_usb_probe_phase2);
|
||
|
if (ret) {
|
||
|
@@ -1469,15 +1478,10 @@ static int brcmf_usb_reset_resume(struct
|
||
|
|
||
|
brcmf_dbg(USB, "Enter\n");
|
||
|
|
||
|
- fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
|
||
|
- GFP_KERNEL);
|
||
|
+ fwreq = brcmf_usb_prepare_fw_request(devinfo);
|
||
|
if (!fwreq)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
- fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
|
||
|
- fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
|
||
|
- fwreq->n_items = 1;
|
||
|
-
|
||
|
ret = brcmf_fw_get_firmwares(&usb->dev, fwreq, brcmf_usb_probe_phase2);
|
||
|
if (ret < 0)
|
||
|
kfree(fwreq);
|