aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2014-01-13 16:20:29 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-01-16 14:55:41 -0500
commitbb350711ecb86568468b497d0ecd5c3fd7b45b1b (patch)
tree769a227a2d7cad25cf72fcedbbf555360b60eb3c /drivers/net/wireless
parent2668b0b16cb555abe1b35a1c3cdeb482799fb7cb (diff)
brcmfmac: handle SDIO card removal
When removing the card the driver still tries to access registers in the device. This patch adds another state for the bus that indicates the device is no longer reachable. This avoids errors accessing it while cleaning up the driver. Reviewed-by: Franky Lin <frankyl@broadcom.com> Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c40
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h21
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c120
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c4
5 files changed, 102 insertions, 87 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 34c993dd0602..fa35b23bbaa7 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -287,6 +287,9 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
287 s32 retry = 0; 287 s32 retry = 0;
288 int ret; 288 int ret;
289 289
290 if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM)
291 return -ENOMEDIUM;
292
290 /* 293 /*
291 * figure out how to read the register based on address range 294 * figure out how to read the register based on address range
292 * 0x00 ~ 0x7FF: function 0 CCCR and FBR 295 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
@@ -306,9 +309,12 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
306 usleep_range(1000, 2000); 309 usleep_range(1000, 2000);
307 ret = brcmf_sdiod_request_data(sdiodev, func_num, addr, regsz, 310 ret = brcmf_sdiod_request_data(sdiodev, func_num, addr, regsz,
308 data, write); 311 data, write);
309 } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); 312 } while (ret != 0 && ret != -ENOMEDIUM &&
313 retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
310 314
311 if (ret != 0) 315 if (ret == -ENOMEDIUM)
316 brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM);
317 else if (ret != 0)
312 brcmf_err("failed with %d\n", ret); 318 brcmf_err("failed with %d\n", ret);
313 319
314 return ret; 320 return ret;
@@ -320,6 +326,9 @@ brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
320 int err = 0, i; 326 int err = 0, i;
321 u8 addr[3]; 327 u8 addr[3];
322 328
329 if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM)
330 return -ENOMEDIUM;
331
323 addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; 332 addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK;
324 addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK; 333 addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK;
325 addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK; 334 addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK;
@@ -429,6 +438,7 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
429 bool write, u32 addr, struct sk_buff *pkt) 438 bool write, u32 addr, struct sk_buff *pkt)
430{ 439{
431 unsigned int req_sz; 440 unsigned int req_sz;
441 int err;
432 442
433 brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); 443 brcmf_sdiod_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
434 if (brcmf_sdiod_pm_resume_error(sdiodev)) 444 if (brcmf_sdiod_pm_resume_error(sdiodev))
@@ -439,18 +449,18 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
439 req_sz &= (uint)~3; 449 req_sz &= (uint)~3;
440 450
441 if (write) 451 if (write)
442 return sdio_memcpy_toio(sdiodev->func[fn], addr, 452 err = sdio_memcpy_toio(sdiodev->func[fn], addr,
443 ((u8 *)(pkt->data)), 453 ((u8 *)(pkt->data)), req_sz);
444 req_sz);
445 else if (fn == 1) 454 else if (fn == 1)
446 return sdio_memcpy_fromio(sdiodev->func[fn], 455 err = sdio_memcpy_fromio(sdiodev->func[fn], ((u8 *)(pkt->data)),
447 ((u8 *)(pkt->data)), 456 addr, req_sz);
448 addr, req_sz);
449 else 457 else
450 /* function 2 read is FIFO operation */ 458 /* function 2 read is FIFO operation */
451 return sdio_readsb(sdiodev->func[fn], 459 err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr,
452 ((u8 *)(pkt->data)), addr, 460 req_sz);
453 req_sz); 461 if (err == -ENOMEDIUM)
462 brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM);
463 return err;
454} 464}
455 465
456/** 466/**
@@ -593,7 +603,11 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
593 mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req); 603 mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req);
594 604
595 ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; 605 ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
596 if (ret != 0) { 606 if (ret == -ENOMEDIUM) {
607 brcmf_bus_change_state(sdiodev->bus_if,
608 BRCMF_BUS_NOMEDIUM);
609 break;
610 } else if (ret != 0) {
597 brcmf_err("CMD53 sg block %s failed %d\n", 611 brcmf_err("CMD53 sg block %s failed %d\n",
598 write ? "write" : "read", ret); 612 write ? "write" : "read", ret);
599 ret = -EIO; 613 ret = -EIO;
@@ -852,8 +866,6 @@ int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
852 866
853static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) 867static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
854{ 868{
855 sdiodev->bus_if->state = BRCMF_BUS_DOWN;
856
857 if (sdiodev->bus) { 869 if (sdiodev->bus) {
858 brcmf_sdio_remove(sdiodev->bus); 870 brcmf_sdio_remove(sdiodev->bus);
859 sdiodev->bus = NULL; 871 sdiodev->bus = NULL;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index 5c12a07673fa..c4535616064e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -17,8 +17,12 @@
17#ifndef _BRCMF_BUS_H_ 17#ifndef _BRCMF_BUS_H_
18#define _BRCMF_BUS_H_ 18#define _BRCMF_BUS_H_
19 19
20#include "dhd_dbg.h"
21
20/* The level of bus communication with the dongle */ 22/* The level of bus communication with the dongle */
21enum brcmf_bus_state { 23enum brcmf_bus_state {
24 BRCMF_BUS_UNKNOWN, /* Not determined yet */
25 BRCMF_BUS_NOMEDIUM, /* No medium access to dongle */
22 BRCMF_BUS_DOWN, /* Not ready for frame transfers */ 26 BRCMF_BUS_DOWN, /* Not ready for frame transfers */
23 BRCMF_BUS_LOAD, /* Download access only (CPU reset) */ 27 BRCMF_BUS_LOAD, /* Download access only (CPU reset) */
24 BRCMF_BUS_DATA /* Ready for frame transfers */ 28 BRCMF_BUS_DATA /* Ready for frame transfers */
@@ -144,6 +148,23 @@ struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus)
144 148
145 return bus->ops->gettxq(bus->dev); 149 return bus->ops->gettxq(bus->dev);
146} 150}
151
152static inline bool brcmf_bus_ready(struct brcmf_bus *bus)
153{
154 return bus->state == BRCMF_BUS_LOAD || bus->state == BRCMF_BUS_DATA;
155}
156
157static inline void brcmf_bus_change_state(struct brcmf_bus *bus,
158 enum brcmf_bus_state new_state)
159{
160 /* NOMEDIUM is permanent */
161 if (bus->state == BRCMF_BUS_NOMEDIUM)
162 return;
163
164 brcmf_dbg(TRACE, "%d -> %d\n", bus->state, new_state);
165 bus->state = new_state;
166}
167
147/* 168/*
148 * interface functions from common layer 169 * interface functions from common layer
149 */ 170 */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index af39edae8c62..d4d966beb840 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -934,7 +934,7 @@ int brcmf_bus_start(struct device *dev)
934 p2p_ifp = NULL; 934 p2p_ifp = NULL;
935 935
936 /* signal bus ready */ 936 /* signal bus ready */
937 bus_if->state = BRCMF_BUS_DATA; 937 brcmf_bus_change_state(bus_if, BRCMF_BUS_DATA);
938 938
939 /* Bus is ready, do any initialization */ 939 /* Bus is ready, do any initialization */
940 ret = brcmf_c_preinit_dcmds(ifp); 940 ret = brcmf_c_preinit_dcmds(ifp);
@@ -1029,6 +1029,8 @@ void brcmf_detach(struct device *dev)
1029 /* stop firmware event handling */ 1029 /* stop firmware event handling */
1030 brcmf_fweh_detach(drvr); 1030 brcmf_fweh_detach(drvr);
1031 1031
1032 brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
1033
1032 /* make sure primary interface removed last */ 1034 /* make sure primary interface removed last */
1033 for (i = BRCMF_MAX_IFS-1; i > -1; i--) 1035 for (i = BRCMF_MAX_IFS-1; i > -1; i--)
1034 if (drvr->iflist[i]) { 1036 if (drvr->iflist[i]) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index ef24a1bd24a7..3e991897d7ca 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1082,10 +1082,6 @@ static void brcmf_sdio_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
1082 1082
1083 /* Clear partial in any case */ 1083 /* Clear partial in any case */
1084 bus->cur_read.len = 0; 1084 bus->cur_read.len = 0;
1085
1086 /* If we can't reach the device, signal failure */
1087 if (err)
1088 bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
1089} 1085}
1090 1086
1091/* return total length of buffer chain */ 1087/* return total length of buffer chain */
@@ -1682,8 +1678,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
1682 bus->rxpending = true; 1678 bus->rxpending = true;
1683 1679
1684 for (rd->seq_num = bus->rx_seq, rxleft = maxframes; 1680 for (rd->seq_num = bus->rx_seq, rxleft = maxframes;
1685 !bus->rxskip && rxleft && 1681 !bus->rxskip && rxleft && brcmf_bus_ready(bus->sdiodev->bus_if);
1686 bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN;
1687 rd->seq_num++, rxleft--) { 1682 rd->seq_num++, rxleft--) {
1688 1683
1689 /* Handle glomming separately */ 1684 /* Handle glomming separately */
@@ -2232,39 +2227,37 @@ static void brcmf_sdio_bus_stop(struct device *dev)
2232 bus->watchdog_tsk = NULL; 2227 bus->watchdog_tsk = NULL;
2233 } 2228 }
2234 2229
2235 sdio_claim_host(bus->sdiodev->func[1]); 2230 if (bus_if->state == BRCMF_BUS_DOWN) {
2236 2231 sdio_claim_host(sdiodev->func[1]);
2237 /* Enable clock for device interrupts */ 2232
2238 brcmf_sdio_bus_sleep(bus, false, false); 2233 /* Enable clock for device interrupts */
2234 brcmf_sdio_bus_sleep(bus, false, false);
2235
2236 /* Disable and clear interrupts at the chip level also */
2237 w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask));
2238 local_hostintmask = bus->hostintmask;
2239 bus->hostintmask = 0;
2240
2241 /* Force backplane clocks to assure F2 interrupt propagates */
2242 saveclk = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
2243 &err);
2244 if (!err)
2245 brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
2246 (saveclk | SBSDIO_FORCE_HT), &err);
2247 if (err)
2248 brcmf_err("Failed to force clock for F2: err %d\n",
2249 err);
2239 2250
2240 /* Disable and clear interrupts at the chip level also */ 2251 /* Turn off the bus (F2), free any pending packets */
2241 w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); 2252 brcmf_dbg(INTR, "disable SDIO interrupts\n");
2242 local_hostintmask = bus->hostintmask; 2253 sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
2243 bus->hostintmask = 0;
2244 2254
2245 /* Change our idea of bus state */ 2255 /* Clear any pending interrupts now that F2 is disabled */
2246 bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; 2256 w_sdreg32(bus, local_hostintmask,
2257 offsetof(struct sdpcmd_regs, intstatus));
2247 2258
2248 /* Force clocks on backplane to be sure F2 interrupt propagates */ 2259 sdio_release_host(sdiodev->func[1]);
2249 saveclk = brcmf_sdiod_regrb(bus->sdiodev,
2250 SBSDIO_FUNC1_CHIPCLKCSR, &err);
2251 if (!err) {
2252 brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
2253 (saveclk | SBSDIO_FORCE_HT), &err);
2254 } 2260 }
2255 if (err)
2256 brcmf_err("Failed to force clock for F2: err %d\n", err);
2257
2258 /* Turn off the bus (F2), free any pending packets */
2259 brcmf_dbg(INTR, "disable SDIO interrupts\n");
2260 sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
2261
2262 /* Clear any pending interrupts now that F2 is disabled */
2263 w_sdreg32(bus, local_hostintmask,
2264 offsetof(struct sdpcmd_regs, intstatus));
2265
2266 sdio_release_host(bus->sdiodev->func[1]);
2267
2268 /* Clear the data packet queues */ 2261 /* Clear the data packet queues */
2269 brcmu_pktq_flush(&bus->txq, true, NULL, NULL); 2262 brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
2270 2263
@@ -2354,20 +2347,11 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
2354 /* Check for inconsistent device control */ 2347 /* Check for inconsistent device control */
2355 devctl = brcmf_sdiod_regrb(bus->sdiodev, 2348 devctl = brcmf_sdiod_regrb(bus->sdiodev,
2356 SBSDIO_DEVICE_CTL, &err); 2349 SBSDIO_DEVICE_CTL, &err);
2357 if (err) {
2358 brcmf_err("error reading DEVCTL: %d\n", err);
2359 bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
2360 }
2361#endif /* DEBUG */ 2350#endif /* DEBUG */
2362 2351
2363 /* Read CSR, if clock on switch to AVAIL, else ignore */ 2352 /* Read CSR, if clock on switch to AVAIL, else ignore */
2364 clkctl = brcmf_sdiod_regrb(bus->sdiodev, 2353 clkctl = brcmf_sdiod_regrb(bus->sdiodev,
2365 SBSDIO_FUNC1_CHIPCLKCSR, &err); 2354 SBSDIO_FUNC1_CHIPCLKCSR, &err);
2366 if (err) {
2367 brcmf_err("error reading CSR: %d\n",
2368 err);
2369 bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
2370 }
2371 2355
2372 brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", 2356 brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
2373 devctl, clkctl); 2357 devctl, clkctl);
@@ -2375,19 +2359,9 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
2375 if (SBSDIO_HTAV(clkctl)) { 2359 if (SBSDIO_HTAV(clkctl)) {
2376 devctl = brcmf_sdiod_regrb(bus->sdiodev, 2360 devctl = brcmf_sdiod_regrb(bus->sdiodev,
2377 SBSDIO_DEVICE_CTL, &err); 2361 SBSDIO_DEVICE_CTL, &err);
2378 if (err) {
2379 brcmf_err("error reading DEVCTL: %d\n",
2380 err);
2381 bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
2382 }
2383 devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; 2362 devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
2384 brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, 2363 brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
2385 devctl, &err); 2364 devctl, &err);
2386 if (err) {
2387 brcmf_err("error writing DEVCTL: %d\n",
2388 err);
2389 bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
2390 }
2391 bus->clkstate = CLK_AVAIL; 2365 bus->clkstate = CLK_AVAIL;
2392 } 2366 }
2393 } 2367 }
@@ -2522,9 +2496,8 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
2522 txlimit -= framecnt; 2496 txlimit -= framecnt;
2523 } 2497 }
2524 2498
2525 if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) { 2499 if (!brcmf_bus_ready(bus->sdiodev->bus_if) || (err != 0)) {
2526 brcmf_err("failed backplane access over SDIO, halting operation\n"); 2500 brcmf_err("failed backplane access over SDIO, halting operation\n");
2527 bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
2528 atomic_set(&bus->intstatus, 0); 2501 atomic_set(&bus->intstatus, 0);
2529 } else if (atomic_read(&bus->intstatus) || 2502 } else if (atomic_read(&bus->intstatus) ||
2530 atomic_read(&bus->ipend) > 0 || 2503 atomic_read(&bus->ipend) > 0 ||
@@ -3356,7 +3329,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus)
3356 } 3329 }
3357 3330
3358 /* Allow HT Clock now that the ARM is running. */ 3331 /* Allow HT Clock now that the ARM is running. */
3359 bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD; 3332 brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_LOAD);
3360 bcmerror = 0; 3333 bcmerror = 0;
3361 3334
3362err: 3335err:
@@ -3633,7 +3606,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus)
3633 return; 3606 return;
3634 } 3607 }
3635 3608
3636 if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) { 3609 if (!brcmf_bus_ready(bus->sdiodev->bus_if)) {
3637 brcmf_err("bus is down. we have nothing to do\n"); 3610 brcmf_err("bus is down. we have nothing to do\n");
3638 return; 3611 return;
3639 } 3612 }
@@ -3644,7 +3617,6 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus)
3644 else 3617 else
3645 if (brcmf_sdio_intr_rstatus(bus)) { 3618 if (brcmf_sdio_intr_rstatus(bus)) {
3646 brcmf_err("failed backplane access\n"); 3619 brcmf_err("failed backplane access\n");
3647 bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
3648 } 3620 }
3649 3621
3650 /* Disable additional interrupts (is this needed now)? */ 3622 /* Disable additional interrupts (is this needed now)? */
@@ -3781,6 +3753,11 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
3781 goto fail; 3753 goto fail;
3782 } 3754 }
3783 3755
3756 /* SDIO register access works so moving
3757 * state from UNKNOWN to DOWN.
3758 */
3759 brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_DOWN);
3760
3784 if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci)) { 3761 if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci)) {
3785 brcmf_err("brcmf_sdio_chip_attach failed!\n"); 3762 brcmf_err("brcmf_sdio_chip_attach failed!\n");
3786 goto fail; 3763 goto fail;
@@ -4004,7 +3981,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
4004 /* Disable F2 to clear any intermediate frame state on the dongle */ 3981 /* Disable F2 to clear any intermediate frame state on the dongle */
4005 sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]); 3982 sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
4006 3983
4007 bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
4008 bus->rxflow = false; 3984 bus->rxflow = false;
4009 3985
4010 /* Done with backplane-dependent accesses, can drop clock... */ 3986 /* Done with backplane-dependent accesses, can drop clock... */
@@ -4060,16 +4036,20 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
4060 } 4036 }
4061 4037
4062 if (bus->ci) { 4038 if (bus->ci) {
4063 sdio_claim_host(bus->sdiodev->func[1]); 4039 if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
4064 brcmf_sdio_clkctl(bus, CLK_AVAIL, false); 4040 sdio_claim_host(bus->sdiodev->func[1]);
4065 /* Leave the device in state where it is 'quiet'. This 4041 brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
4066 * is done by putting it in download_state which 4042 /* Leave the device in state where it is
4067 * essentially resets all necessary cores 4043 * 'quiet'. This is done by putting it in
4068 */ 4044 * download_state which essentially resets
4069 msleep(20); 4045 * all necessary cores.
4070 brcmf_sdio_chip_enter_download(bus->sdiodev, bus->ci); 4046 */
4071 brcmf_sdio_clkctl(bus, CLK_NONE, false); 4047 msleep(20);
4072 sdio_release_host(bus->sdiodev->func[1]); 4048 brcmf_sdio_chip_enter_download(bus->sdiodev,
4049 bus->ci);
4050 brcmf_sdio_clkctl(bus, CLK_NONE, false);
4051 sdio_release_host(bus->sdiodev->func[1]);
4052 }
4073 brcmf_sdio_chip_detach(&bus->ci); 4053 brcmf_sdio_chip_detach(&bus->ci);
4074 } 4054 }
4075 4055
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index c345c32eb631..24f65cd53859 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -522,10 +522,10 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
522 /* update state of upper layer */ 522 /* update state of upper layer */
523 if (state == BRCMFMAC_USB_STATE_DOWN) { 523 if (state == BRCMFMAC_USB_STATE_DOWN) {
524 brcmf_dbg(USB, "DBUS is down\n"); 524 brcmf_dbg(USB, "DBUS is down\n");
525 bcmf_bus->state = BRCMF_BUS_DOWN; 525 brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DOWN);
526 } else if (state == BRCMFMAC_USB_STATE_UP) { 526 } else if (state == BRCMFMAC_USB_STATE_UP) {
527 brcmf_dbg(USB, "DBUS is up\n"); 527 brcmf_dbg(USB, "DBUS is up\n");
528 bcmf_bus->state = BRCMF_BUS_DATA; 528 brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DATA);
529 } else { 529 } else {
530 brcmf_dbg(USB, "DBUS current state=%d\n", state); 530 brcmf_dbg(USB, "DBUS current state=%d\n", state);
531 } 531 }