diff options
author | Arend Van Spriel <arend.vanspriel@broadcom.com> | 2017-06-12 07:47:34 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2017-06-15 12:06:53 -0400 |
commit | 7a51461fc2da82a6c565a3ee65c41c197f28225d (patch) | |
tree | c40c8a7d19b4196c6583cee08af04c1adc5adc8e | |
parent | 03fb0e8393fae8ebb6710a99387853ed0becbc8e (diff) |
brcmfmac: unbind all devices upon failure in firmware callback
When request firmware fails, brcmf_ops_sdio_remove is being called and
brcmf_bus freed. In such circumstancies if you do a suspend/resume cycle
the kernel hangs on resume due a NULL pointer dereference in resume
function. So in brcmf_sdio_firmware_callback() we need to unbind the
driver from both sdio_func devices when firmware load failure is indicated.
Cc: stable@vger.kernel.org # 4.9.x-
Tested-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
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>
-rw-r--r-- | drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 6e1fcdcde11c..5653d6dd38f6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | |||
@@ -3992,14 +3992,14 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, | |||
3992 | u8 saveclk; | 3992 | u8 saveclk; |
3993 | 3993 | ||
3994 | brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); | 3994 | brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); |
3995 | bus_if = dev_get_drvdata(dev); | ||
3996 | sdiodev = bus_if->bus_priv.sdio; | ||
3995 | if (err) | 3997 | if (err) |
3996 | goto fail; | 3998 | goto fail; |
3997 | 3999 | ||
3998 | bus_if = dev_get_drvdata(dev); | ||
3999 | if (!bus_if->drvr) | 4000 | if (!bus_if->drvr) |
4000 | return; | 4001 | return; |
4001 | 4002 | ||
4002 | sdiodev = bus_if->bus_priv.sdio; | ||
4003 | bus = sdiodev->bus; | 4003 | bus = sdiodev->bus; |
4004 | 4004 | ||
4005 | /* try to download image and nvram to the dongle */ | 4005 | /* try to download image and nvram to the dongle */ |
@@ -4088,6 +4088,7 @@ release: | |||
4088 | fail: | 4088 | fail: |
4089 | brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err); | 4089 | brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err); |
4090 | device_release_driver(dev); | 4090 | device_release_driver(dev); |
4091 | device_release_driver(&sdiodev->func[2]->dev); | ||
4091 | } | 4092 | } |
4092 | 4093 | ||
4093 | struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | 4094 | struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) |