Commit 2baa3aae authored by Arend Van Spriel's avatar Arend Van Spriel Committed by Kalle Valo

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: default avatarHante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: default avatarFranky Lin <franky.lin@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent d09ae51a
...@@ -688,3 +688,61 @@ int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev, ...@@ -688,3 +688,61 @@ int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
return 0; 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;
}
...@@ -77,6 +77,17 @@ struct brcmf_fw_request { ...@@ -77,6 +77,17 @@ struct brcmf_fw_request {
struct brcmf_fw_item items[0]; 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 * Request firmware(s) asynchronously. When the asynchronous request
* fails it will not use the callback, but call device_release_driver() * fails it will not use the callback, but call device_release_driver()
......
...@@ -1735,6 +1735,31 @@ static void brcmf_pcie_setup(struct device *dev, int ret, ...@@ -1735,6 +1735,31 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
device_release_driver(dev); 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 static int
brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
...@@ -1743,13 +1768,8 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1743,13 +1768,8 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct brcmf_pciedev_info *devinfo; struct brcmf_pciedev_info *devinfo;
struct brcmf_pciedev *pcie_bus_dev; struct brcmf_pciedev *pcie_bus_dev;
struct brcmf_bus *bus; struct brcmf_bus *bus;
u16 domain_nr;
u16 bus_nr;
domain_nr = pci_domain_nr(pdev->bus) + 1; brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
bus_nr = pdev->bus->number;
brcmf_dbg(PCIE, "Enter %x:%x (%d/%d)\n", pdev->vendor, pdev->device,
domain_nr, bus_nr);
ret = -ENOMEM; ret = -ENOMEM;
devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
...@@ -1803,33 +1823,19 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1803,33 +1823,19 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot); bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot);
dev_set_drvdata(&pdev->dev, bus); dev_set_drvdata(&pdev->dev, bus);
ret = brcmf_fw_map_chip_to_name(devinfo->ci->chip, devinfo->ci->chiprev, fwreq = brcmf_pcie_prepare_fw_request(devinfo);
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);
if (!fwreq) { if (!fwreq) {
ret = -ENOMEM; ret = -ENOMEM;
goto fail_bus; 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); ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
if (ret == 0) if (ret < 0) {
return 0; kfree(fwreq);
goto fail_bus;
}
return 0;
kfree(fwreq);
fail_bus: fail_bus:
kfree(bus->msgbuf); kfree(bus->msgbuf);
kfree(bus); kfree(bus);
......
...@@ -4155,6 +4155,28 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, ...@@ -4155,6 +4155,28 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
device_release_driver(dev); 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) struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
{ {
int ret; int ret;
...@@ -4243,26 +4265,12 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) ...@@ -4243,26 +4265,12 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
brcmf_dbg(INFO, "completed!!\n"); brcmf_dbg(INFO, "completed!!\n");
ret = brcmf_fw_map_chip_to_name(bus->ci->chip, bus->ci->chiprev, fwreq = brcmf_sdio_prepare_fw_request(bus);
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);
if (!fwreq) { if (!fwreq) {
ret = -ENOMEM; ret = -ENOMEM;
goto fail; 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, ret = brcmf_fw_get_firmwares(sdiodev->dev, fwreq,
brcmf_sdio_firmware_callback); brcmf_sdio_firmware_callback);
if (ret != 0) { if (ret != 0) {
......
...@@ -1200,6 +1200,27 @@ static void brcmf_usb_probe_phase2(struct device *dev, int ret, ...@@ -1200,6 +1200,27 @@ static void brcmf_usb_probe_phase2(struct device *dev, int ret,
device_release_driver(dev); 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) static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
{ {
struct brcmf_bus *bus = NULL; struct brcmf_bus *bus = NULL;
...@@ -1249,24 +1270,12 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) ...@@ -1249,24 +1270,12 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
bus->chip = bus_pub->devid; bus->chip = bus_pub->devid;
bus->chiprev = bus_pub->chiprev; bus->chiprev = bus_pub->chiprev;
ret = brcmf_fw_map_chip_to_name(bus_pub->devid, bus_pub->chiprev, fwreq = brcmf_usb_prepare_fw_request(devinfo);
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);
if (!fwreq) { if (!fwreq) {
ret = -ENOMEM; ret = -ENOMEM;
goto fail; 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 */ /* request firmware here */
ret = brcmf_fw_get_firmwares(dev, fwreq, brcmf_usb_probe_phase2); ret = brcmf_fw_get_firmwares(dev, fwreq, brcmf_usb_probe_phase2);
if (ret) { if (ret) {
...@@ -1469,15 +1478,10 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf) ...@@ -1469,15 +1478,10 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf)
brcmf_dbg(USB, "Enter\n"); brcmf_dbg(USB, "Enter\n");
fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item), fwreq = brcmf_usb_prepare_fw_request(devinfo);
GFP_KERNEL);
if (!fwreq) if (!fwreq)
return -ENOMEM; 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); ret = brcmf_fw_get_firmwares(&usb->dev, fwreq, brcmf_usb_probe_phase2);
if (ret < 0) if (ret < 0)
kfree(fwreq); kfree(fwreq);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment