Commit eb4764c3 authored by Ben Hutchings's avatar Ben Hutchings Committed by Greg Kroah-Hartman

staging: brcm80211: Fix some initialisation failure paths

Initialise wl_info::tasklet early so that it's safe to tasklet_kill()
it in wl_free().

Remove assertions from wl_free() that may not be true in case of
initialisation failure.

Call wl_release_fw() in case of failure after wl_request_fw().
Don't rely on wl_firmware::fw_cnt in wl_release_fw().
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
Signed-off-by: default avatarHenry Ptasinski <henryp@broadcom.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 6b5e0736
...@@ -25,7 +25,6 @@ Bugs ...@@ -25,7 +25,6 @@ Bugs
- Various occasional asserts/hangs - Various occasional asserts/hangs
- Scanning during data transfer sometimes causes major slowdowns. Sometimes - Scanning during data transfer sometimes causes major slowdowns. Sometimes
revcovers when scan is done, other times not. revcovers when scan is done, other times not.
- Driver does not handle missing firmware gracefully.
- Mac80211 API not completely implemented (ie ops_bss_info_changed, - Mac80211 API not completely implemented (ie ops_bss_info_changed,
ops_get_stats, etc) ops_get_stats, etc)
......
...@@ -837,6 +837,9 @@ static wl_info_t *wl_attach(uint16 vendor, uint16 device, ulong regs, ...@@ -837,6 +837,9 @@ static wl_info_t *wl_attach(uint16 vendor, uint16 device, ulong regs,
wl->osh = osh; wl->osh = osh;
atomic_set(&wl->callbacks, 0); atomic_set(&wl->callbacks, 0);
/* setup the bottom half handler */
tasklet_init(&wl->tasklet, wl_dpc, (ulong) wl);
#ifdef WLC_HIGH_ONLY #ifdef WLC_HIGH_ONLY
wl->rpc_th = bcm_rpc_tp_attach(osh, NULL); wl->rpc_th = bcm_rpc_tp_attach(osh, NULL);
if (wl->rpc_th == NULL) { if (wl->rpc_th == NULL) {
...@@ -905,17 +908,16 @@ static wl_info_t *wl_attach(uint16 vendor, uint16 device, ulong regs, ...@@ -905,17 +908,16 @@ static wl_info_t *wl_attach(uint16 vendor, uint16 device, ulong regs,
#endif #endif
/* common load-time initialization */ /* common load-time initialization */
if (! wl->wlc = wlc_attach((void *)wl, vendor, device, unit, wl->piomode, osh,
(wl->wlc = wl->regsva, wl->bcm_bustype, btparam, &err);
wlc_attach((void *)wl, vendor, device, unit, wl->piomode, osh, #ifndef WLC_HIGH_ONLY
wl->regsva, wl->bcm_bustype, btparam, &err))) { wl_release_fw(wl);
#endif
if (!wl->wlc) {
printf("%s: %s driver failed with code %d\n", KBUILD_MODNAME, printf("%s: %s driver failed with code %d\n", KBUILD_MODNAME,
EPI_VERSION_STR, err); EPI_VERSION_STR, err);
goto fail; goto fail;
} }
#ifndef WLC_HIGH_ONLY
wl_release_fw(wl);
#endif
wl->pub = wlc_pub(wl->wlc); wl->pub = wlc_pub(wl->wlc);
wl->pub->ieee_hw = hw; wl->pub->ieee_hw = hw;
...@@ -942,9 +944,6 @@ static wl_info_t *wl_attach(uint16 vendor, uint16 device, ulong regs, ...@@ -942,9 +944,6 @@ static wl_info_t *wl_attach(uint16 vendor, uint16 device, ulong regs,
wlc_iovar_setint(wl->wlc, "sd_drivestrength", sd_drivestrength); wlc_iovar_setint(wl->wlc, "sd_drivestrength", sd_drivestrength);
#endif #endif
/* setup the bottom half handler */
tasklet_init(&wl->tasklet, wl_dpc, (ulong) wl);
#ifdef WLC_LOW #ifdef WLC_LOW
/* register our interrupt handler */ /* register our interrupt handler */
if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
...@@ -1710,11 +1709,9 @@ void wl_free(wl_info_t * wl) ...@@ -1710,11 +1709,9 @@ void wl_free(wl_info_t * wl)
ASSERT(wl); ASSERT(wl);
#ifndef WLC_HIGH_ONLY #ifndef WLC_HIGH_ONLY
ASSERT(wl->irq); /* bmac does not use direct interrupt */
/* free ucode data */ /* free ucode data */
if (wl->fw.fw_cnt) if (wl->fw.fw_cnt)
wl_ucode_data_free(); wl_ucode_data_free();
ASSERT(wl->wlc);
if (wl->irq) if (wl->irq)
free_irq(wl->irq, wl); free_irq(wl->irq, wl);
#endif #endif
...@@ -2509,6 +2506,7 @@ static int wl_request_fw(wl_info_t * wl, struct pci_dev *pdev) ...@@ -2509,6 +2506,7 @@ static int wl_request_fw(wl_info_t * wl, struct pci_dev *pdev)
status = request_firmware(&wl->fw.fw_bin[i], fw_name, device); status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
if (status) { if (status) {
printf("fail to request firmware %s\n", fw_name); printf("fail to request firmware %s\n", fw_name);
wl_release_fw(wl);
return status; return status;
} }
WL_NONE(("request fw %s\n", fw_name)); WL_NONE(("request fw %s\n", fw_name));
...@@ -2517,6 +2515,7 @@ static int wl_request_fw(wl_info_t * wl, struct pci_dev *pdev) ...@@ -2517,6 +2515,7 @@ static int wl_request_fw(wl_info_t * wl, struct pci_dev *pdev)
status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device); status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
if (status) { if (status) {
printf("fail to request firmware %s\n", fw_name); printf("fail to request firmware %s\n", fw_name);
wl_release_fw(wl);
return status; return status;
} }
wl->fw.hdr_num_entries[i] = wl->fw.hdr_num_entries[i] =
...@@ -2539,7 +2538,7 @@ void wl_ucode_free_buf(void *p) ...@@ -2539,7 +2538,7 @@ void wl_ucode_free_buf(void *p)
static void wl_release_fw(wl_info_t * wl) static void wl_release_fw(wl_info_t * wl)
{ {
int i; int i;
for (i = 0; i < wl->fw.fw_cnt; i++) { for (i = 0; i < WL_MAX_FW; i++) {
release_firmware(wl->fw.fw_bin[i]); release_firmware(wl->fw.fw_bin[i]);
release_firmware(wl->fw.fw_hdr[i]); release_firmware(wl->fw.fw_hdr[i]);
} }
......
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