From 2811c97803e50e9964a2c23b9d8271f0265bcdca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 18 Jun 2018 07:09:14 +0200 Subject: mac80211: backport brcmfmac firmware & clm_blob loading rework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It backports remaining brcmfmac changes from 4.17. Signed-off-by: Rafał Miłecki (cherry picked from commit 7e8eb7f309a802ba10a13ddb807c6a31fecc9183) --- ...introduce-brcmf_fw_alloc_request-function.patch | 328 +++++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100644 package/kernel/mac80211/patches/327-v4.17-0008-brcmfmac-introduce-brcmf_fw_alloc_request-function.patch (limited to 'package/kernel/mac80211/patches/327-v4.17-0008-brcmfmac-introduce-brcmf_fw_alloc_request-function.patch') diff --git a/package/kernel/mac80211/patches/327-v4.17-0008-brcmfmac-introduce-brcmf_fw_alloc_request-function.patch b/package/kernel/mac80211/patches/327-v4.17-0008-brcmfmac-introduce-brcmf_fw_alloc_request-function.patch new file mode 100644 index 0000000000..408154ef0f --- /dev/null +++ b/package/kernel/mac80211/patches/327-v4.17-0008-brcmfmac-introduce-brcmf_fw_alloc_request-function.patch @@ -0,0 +1,328 @@ +From 2baa3aaee27f137b8db9a9224d0fe9b281d28e34 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +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 +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../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); -- cgit v1.2.3