diff options
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 40 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 120 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/usb.c | 4 |
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 | ||
853 | static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) | 867 | static 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 */ |
21 | enum brcmf_bus_state { | 23 | enum 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 | |||
152 | static inline bool brcmf_bus_ready(struct brcmf_bus *bus) | ||
153 | { | ||
154 | return bus->state == BRCMF_BUS_LOAD || bus->state == BRCMF_BUS_DATA; | ||
155 | } | ||
156 | |||
157 | static 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 | ||
3362 | err: | 3335 | err: |
@@ -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 | } |