Commit afd64631 authored by David S. Miller's avatar David S. Miller

Merge tag 'wireless-drivers-for-davem-2017-06-20' of...

Merge tag 'wireless-drivers-for-davem-2017-06-20' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers

Kalle Valo says:

====================
wireless-drivers fixes for 4.12

Two important fixes for brcmfmac. The rest of the brcmfmac patches are
either code preparation and fixing a new build warning.

brcmfmac

* fix a NULL pointer dereference during resume

* fix a NULL pointer dereference with USB devices, a regression from
  v4.12-rc1
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 05cf0d1b 35abcd4f
...@@ -442,7 +442,7 @@ struct brcmf_fw { ...@@ -442,7 +442,7 @@ struct brcmf_fw {
const char *nvram_name; const char *nvram_name;
u16 domain_nr; u16 domain_nr;
u16 bus_nr; u16 bus_nr;
void (*done)(struct device *dev, const struct firmware *fw, void (*done)(struct device *dev, int err, const struct firmware *fw,
void *nvram_image, u32 nvram_len); void *nvram_image, u32 nvram_len);
}; };
...@@ -477,52 +477,51 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) ...@@ -477,52 +477,51 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
goto fail; goto fail;
fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length); fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length);
kfree(fwctx); kfree(fwctx);
return; return;
fail: fail:
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
release_firmware(fwctx->code); release_firmware(fwctx->code);
device_release_driver(fwctx->dev); fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0);
kfree(fwctx); kfree(fwctx);
} }
static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx) static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
{ {
struct brcmf_fw *fwctx = ctx; struct brcmf_fw *fwctx = ctx;
int ret; int ret = 0;
brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev)); brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
if (!fw) if (!fw) {
ret = -ENOENT;
goto fail; goto fail;
/* only requested code so done here */
if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
fwctx->done(fwctx->dev, fw, NULL, 0);
kfree(fwctx);
return;
} }
/* only requested code so done here */
if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM))
goto done;
fwctx->code = fw; fwctx->code = fw;
ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name, ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
fwctx->dev, GFP_KERNEL, fwctx, fwctx->dev, GFP_KERNEL, fwctx,
brcmf_fw_request_nvram_done); brcmf_fw_request_nvram_done);
if (!ret) /* pass NULL to nvram callback for bcm47xx fallback */
return; if (ret)
brcmf_fw_request_nvram_done(NULL, fwctx); brcmf_fw_request_nvram_done(NULL, fwctx);
return; return;
fail: fail:
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
device_release_driver(fwctx->dev); done:
fwctx->done(fwctx->dev, ret, fw, NULL, 0);
kfree(fwctx); kfree(fwctx);
} }
int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
const char *code, const char *nvram, const char *code, const char *nvram,
void (*fw_cb)(struct device *dev, void (*fw_cb)(struct device *dev, int err,
const struct firmware *fw, const struct firmware *fw,
void *nvram_image, u32 nvram_len), void *nvram_image, u32 nvram_len),
u16 domain_nr, u16 bus_nr) u16 domain_nr, u16 bus_nr)
...@@ -555,7 +554,7 @@ int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, ...@@ -555,7 +554,7 @@ int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
int brcmf_fw_get_firmwares(struct device *dev, u16 flags, int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
const char *code, const char *nvram, const char *code, const char *nvram,
void (*fw_cb)(struct device *dev, void (*fw_cb)(struct device *dev, int err,
const struct firmware *fw, const struct firmware *fw,
void *nvram_image, u32 nvram_len)) void *nvram_image, u32 nvram_len))
{ {
......
...@@ -73,13 +73,13 @@ void brcmf_fw_nvram_free(void *nvram); ...@@ -73,13 +73,13 @@ void brcmf_fw_nvram_free(void *nvram);
*/ */
int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
const char *code, const char *nvram, const char *code, const char *nvram,
void (*fw_cb)(struct device *dev, void (*fw_cb)(struct device *dev, int err,
const struct firmware *fw, const struct firmware *fw,
void *nvram_image, u32 nvram_len), void *nvram_image, u32 nvram_len),
u16 domain_nr, u16 bus_nr); u16 domain_nr, u16 bus_nr);
int brcmf_fw_get_firmwares(struct device *dev, u16 flags, int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
const char *code, const char *nvram, const char *code, const char *nvram,
void (*fw_cb)(struct device *dev, void (*fw_cb)(struct device *dev, int err,
const struct firmware *fw, const struct firmware *fw,
void *nvram_image, u32 nvram_len)); void *nvram_image, u32 nvram_len));
......
...@@ -2145,7 +2145,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp) ...@@ -2145,7 +2145,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr); struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
struct brcmf_fws_mac_descriptor *entry; struct brcmf_fws_mac_descriptor *entry;
if (!ifp->ndev || fws->fcmode == BRCMF_FWS_FCMODE_NONE) if (!ifp->ndev || !brcmf_fws_queue_skbs(fws))
return; return;
entry = &fws->desc.iface[ifp->ifidx]; entry = &fws->desc.iface[ifp->ifidx];
......
...@@ -1650,16 +1650,23 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { ...@@ -1650,16 +1650,23 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
.write32 = brcmf_pcie_buscore_write32, .write32 = brcmf_pcie_buscore_write32,
}; };
static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw, static void brcmf_pcie_setup(struct device *dev, int ret,
const struct firmware *fw,
void *nvram, u32 nvram_len) void *nvram, u32 nvram_len)
{ {
struct brcmf_bus *bus = dev_get_drvdata(dev); struct brcmf_bus *bus;
struct brcmf_pciedev *pcie_bus_dev = bus->bus_priv.pcie; struct brcmf_pciedev *pcie_bus_dev;
struct brcmf_pciedev_info *devinfo = pcie_bus_dev->devinfo; struct brcmf_pciedev_info *devinfo;
struct brcmf_commonring **flowrings; struct brcmf_commonring **flowrings;
int ret;
u32 i; u32 i;
/* check firmware loading result */
if (ret)
goto fail;
bus = dev_get_drvdata(dev);
pcie_bus_dev = bus->bus_priv.pcie;
devinfo = pcie_bus_dev->devinfo;
brcmf_pcie_attach(devinfo); brcmf_pcie_attach(devinfo);
/* Some of the firmwares have the size of the memory of the device /* Some of the firmwares have the size of the memory of the device
......
...@@ -3982,21 +3982,26 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { ...@@ -3982,21 +3982,26 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.get_memdump = brcmf_sdio_bus_get_memdump, .get_memdump = brcmf_sdio_bus_get_memdump,
}; };
static void brcmf_sdio_firmware_callback(struct device *dev, static void brcmf_sdio_firmware_callback(struct device *dev, int err,
const struct firmware *code, const struct firmware *code,
void *nvram, u32 nvram_len) void *nvram, u32 nvram_len)
{ {
struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_bus *bus_if;
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio_dev *sdiodev;
struct brcmf_sdio *bus = sdiodev->bus; struct brcmf_sdio *bus;
int err = 0;
u8 saveclk; u8 saveclk;
brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev)); brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
bus_if = dev_get_drvdata(dev);
sdiodev = bus_if->bus_priv.sdio;
if (err)
goto fail;
if (!bus_if->drvr) if (!bus_if->drvr)
return; return;
bus = sdiodev->bus;
/* try to download image and nvram to the dongle */ /* try to download image and nvram to the dongle */
bus->alp_only = true; bus->alp_only = true;
err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len); err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
...@@ -4083,6 +4088,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, ...@@ -4083,6 +4088,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev,
fail: fail:
brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err); brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err);
device_release_driver(dev); device_release_driver(dev);
device_release_driver(&sdiodev->func[2]->dev);
} }
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
......
...@@ -1159,17 +1159,18 @@ static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo) ...@@ -1159,17 +1159,18 @@ static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo)
return ret; return ret;
} }
static void brcmf_usb_probe_phase2(struct device *dev, static void brcmf_usb_probe_phase2(struct device *dev, int ret,
const struct firmware *fw, const struct firmware *fw,
void *nvram, u32 nvlen) void *nvram, u32 nvlen)
{ {
struct brcmf_bus *bus = dev_get_drvdata(dev); struct brcmf_bus *bus = dev_get_drvdata(dev);
struct brcmf_usbdev_info *devinfo; struct brcmf_usbdev_info *devinfo = bus->bus_priv.usb->devinfo;
int ret;
if (ret)
goto error;
brcmf_dbg(USB, "Start fw downloading\n"); brcmf_dbg(USB, "Start fw downloading\n");
devinfo = bus->bus_priv.usb->devinfo;
ret = check_file(fw->data); ret = check_file(fw->data);
if (ret < 0) { if (ret < 0) {
brcmf_err("invalid firmware\n"); brcmf_err("invalid firmware\n");
......
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