diff options
author | Arend van Spriel <arend@broadcom.com> | 2013-06-18 07:29:26 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-06-18 14:46:50 -0400 |
commit | fccfe93036312f3ad35d37c2ca960f104c6e7f21 (patch) | |
tree | f7a089b5fcaeb2324f2dd7e0edcf1eabbc83eeea /drivers/net/wireless/brcm80211/brcmfmac | |
parent | 1ab083a3752760ec7751a7fa43db555d2d6f1e6a (diff) |
brcmfmac: simplify dpc handling using atomic operations
Instead of allocating an empty list item and queue that for
the dpc data worker to dequeue an atomic counter is used.
Reviewed-by: Franky (Zhenhui) 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/brcm80211/brcmfmac')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 70 |
1 files changed, 12 insertions, 58 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 6f3d181659ef..d4db0c7cd692 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -495,8 +495,7 @@ struct brcmf_sdio { | |||
495 | 495 | ||
496 | struct workqueue_struct *brcmf_wq; | 496 | struct workqueue_struct *brcmf_wq; |
497 | struct work_struct datawork; | 497 | struct work_struct datawork; |
498 | struct list_head dpc_tsklst; | 498 | atomic_t dpc_tskcnt; |
499 | spinlock_t dpc_tl_lock; | ||
500 | 499 | ||
501 | const struct firmware *firmware; | 500 | const struct firmware *firmware; |
502 | u32 fw_ptr; | 501 | u32 fw_ptr; |
@@ -2061,23 +2060,6 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | |||
2061 | } | 2060 | } |
2062 | } | 2061 | } |
2063 | 2062 | ||
2064 | static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) | ||
2065 | { | ||
2066 | struct list_head *new_hd; | ||
2067 | unsigned long flags; | ||
2068 | |||
2069 | if (in_interrupt()) | ||
2070 | new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC); | ||
2071 | else | ||
2072 | new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL); | ||
2073 | if (new_hd == NULL) | ||
2074 | return; | ||
2075 | |||
2076 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2077 | list_add_tail(new_hd, &bus->dpc_tsklst); | ||
2078 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2079 | } | ||
2080 | |||
2081 | static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) | 2063 | static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) |
2082 | { | 2064 | { |
2083 | u8 idx; | 2065 | u8 idx; |
@@ -2312,7 +2294,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2312 | (!atomic_read(&bus->fcstate) && | 2294 | (!atomic_read(&bus->fcstate) && |
2313 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && | 2295 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && |
2314 | data_ok(bus)) || PKT_AVAILABLE()) { | 2296 | data_ok(bus)) || PKT_AVAILABLE()) { |
2315 | brcmf_sdbrcm_adddpctsk(bus); | 2297 | atomic_inc(&bus->dpc_tskcnt); |
2316 | } | 2298 | } |
2317 | 2299 | ||
2318 | /* If we're done for now, turn off clock request. */ | 2300 | /* If we're done for now, turn off clock request. */ |
@@ -2342,7 +2324,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2342 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2324 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2343 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2325 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
2344 | struct brcmf_sdio *bus = sdiodev->bus; | 2326 | struct brcmf_sdio *bus = sdiodev->bus; |
2345 | unsigned long flags; | ||
2346 | 2327 | ||
2347 | brcmf_dbg(TRACE, "Enter\n"); | 2328 | brcmf_dbg(TRACE, "Enter\n"); |
2348 | 2329 | ||
@@ -2381,14 +2362,9 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2381 | qcount[prec] = pktq_plen(&bus->txq, prec); | 2362 | qcount[prec] = pktq_plen(&bus->txq, prec); |
2382 | #endif | 2363 | #endif |
2383 | 2364 | ||
2384 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | 2365 | if (atomic_read(&bus->dpc_tskcnt) == 0) { |
2385 | if (list_empty(&bus->dpc_tsklst)) { | 2366 | atomic_inc(&bus->dpc_tskcnt); |
2386 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2387 | |||
2388 | brcmf_sdbrcm_adddpctsk(bus); | ||
2389 | queue_work(bus->brcmf_wq, &bus->datawork); | 2367 | queue_work(bus->brcmf_wq, &bus->datawork); |
2390 | } else { | ||
2391 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2392 | } | 2368 | } |
2393 | 2369 | ||
2394 | return ret; | 2370 | return ret; |
@@ -2525,7 +2501,6 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2525 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2501 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2526 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2502 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
2527 | struct brcmf_sdio *bus = sdiodev->bus; | 2503 | struct brcmf_sdio *bus = sdiodev->bus; |
2528 | unsigned long flags; | ||
2529 | 2504 | ||
2530 | brcmf_dbg(TRACE, "Enter\n"); | 2505 | brcmf_dbg(TRACE, "Enter\n"); |
2531 | 2506 | ||
@@ -2612,18 +2587,13 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2612 | } while (ret < 0 && retries++ < TXRETRIES); | 2587 | } while (ret < 0 && retries++ < TXRETRIES); |
2613 | } | 2588 | } |
2614 | 2589 | ||
2615 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2616 | if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && | 2590 | if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && |
2617 | list_empty(&bus->dpc_tsklst)) { | 2591 | atomic_read(&bus->dpc_tskcnt) == 0) { |
2618 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2619 | |||
2620 | bus->activity = false; | 2592 | bus->activity = false; |
2621 | sdio_claim_host(bus->sdiodev->func[1]); | 2593 | sdio_claim_host(bus->sdiodev->func[1]); |
2622 | brcmf_dbg(INFO, "idle\n"); | 2594 | brcmf_dbg(INFO, "idle\n"); |
2623 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); | 2595 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); |
2624 | sdio_release_host(bus->sdiodev->func[1]); | 2596 | sdio_release_host(bus->sdiodev->func[1]); |
2625 | } else { | ||
2626 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2627 | } | 2597 | } |
2628 | 2598 | ||
2629 | if (ret) | 2599 | if (ret) |
@@ -3451,7 +3421,7 @@ void brcmf_sdbrcm_isr(void *arg) | |||
3451 | if (!bus->intr) | 3421 | if (!bus->intr) |
3452 | brcmf_err("isr w/o interrupt configured!\n"); | 3422 | brcmf_err("isr w/o interrupt configured!\n"); |
3453 | 3423 | ||
3454 | brcmf_sdbrcm_adddpctsk(bus); | 3424 | atomic_inc(&bus->dpc_tskcnt); |
3455 | queue_work(bus->brcmf_wq, &bus->datawork); | 3425 | queue_work(bus->brcmf_wq, &bus->datawork); |
3456 | } | 3426 | } |
3457 | 3427 | ||
@@ -3460,7 +3430,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3460 | #ifdef DEBUG | 3430 | #ifdef DEBUG |
3461 | struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); | 3431 | struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); |
3462 | #endif /* DEBUG */ | 3432 | #endif /* DEBUG */ |
3463 | unsigned long flags; | ||
3464 | 3433 | ||
3465 | brcmf_dbg(TIMER, "Enter\n"); | 3434 | brcmf_dbg(TIMER, "Enter\n"); |
3466 | 3435 | ||
@@ -3476,11 +3445,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3476 | if (!bus->intr || | 3445 | if (!bus->intr || |
3477 | (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { | 3446 | (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { |
3478 | 3447 | ||
3479 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | 3448 | if (atomic_read(&bus->dpc_tskcnt) == 0) { |
3480 | if (list_empty(&bus->dpc_tsklst)) { | ||
3481 | u8 devpend; | 3449 | u8 devpend; |
3482 | spin_unlock_irqrestore(&bus->dpc_tl_lock, | 3450 | |
3483 | flags); | ||
3484 | sdio_claim_host(bus->sdiodev->func[1]); | 3451 | sdio_claim_host(bus->sdiodev->func[1]); |
3485 | devpend = brcmf_sdio_regrb(bus->sdiodev, | 3452 | devpend = brcmf_sdio_regrb(bus->sdiodev, |
3486 | SDIO_CCCR_INTx, | 3453 | SDIO_CCCR_INTx, |
@@ -3489,9 +3456,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3489 | intstatus = | 3456 | intstatus = |
3490 | devpend & (INTR_STATUS_FUNC1 | | 3457 | devpend & (INTR_STATUS_FUNC1 | |
3491 | INTR_STATUS_FUNC2); | 3458 | INTR_STATUS_FUNC2); |
3492 | } else { | ||
3493 | spin_unlock_irqrestore(&bus->dpc_tl_lock, | ||
3494 | flags); | ||
3495 | } | 3459 | } |
3496 | 3460 | ||
3497 | /* If there is something, make like the ISR and | 3461 | /* If there is something, make like the ISR and |
@@ -3500,7 +3464,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3500 | bus->sdcnt.pollcnt++; | 3464 | bus->sdcnt.pollcnt++; |
3501 | atomic_set(&bus->ipend, 1); | 3465 | atomic_set(&bus->ipend, 1); |
3502 | 3466 | ||
3503 | brcmf_sdbrcm_adddpctsk(bus); | 3467 | atomic_inc(&bus->dpc_tskcnt); |
3504 | queue_work(bus->brcmf_wq, &bus->datawork); | 3468 | queue_work(bus->brcmf_wq, &bus->datawork); |
3505 | } | 3469 | } |
3506 | } | 3470 | } |
@@ -3566,20 +3530,11 @@ static void brcmf_sdio_dataworker(struct work_struct *work) | |||
3566 | { | 3530 | { |
3567 | struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, | 3531 | struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, |
3568 | datawork); | 3532 | datawork); |
3569 | struct list_head *cur_hd, *tmp_hd; | ||
3570 | unsigned long flags; | ||
3571 | |||
3572 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
3573 | list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) { | ||
3574 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
3575 | 3533 | ||
3534 | while (atomic_read(&bus->dpc_tskcnt)) { | ||
3576 | brcmf_sdbrcm_dpc(bus); | 3535 | brcmf_sdbrcm_dpc(bus); |
3577 | 3536 | atomic_dec(&bus->dpc_tskcnt); | |
3578 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
3579 | list_del(cur_hd); | ||
3580 | kfree(cur_hd); | ||
3581 | } | 3537 | } |
3582 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
3583 | } | 3538 | } |
3584 | 3539 | ||
3585 | static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) | 3540 | static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) |
@@ -3927,8 +3882,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
3927 | bus->watchdog_tsk = NULL; | 3882 | bus->watchdog_tsk = NULL; |
3928 | } | 3883 | } |
3929 | /* Initialize DPC thread */ | 3884 | /* Initialize DPC thread */ |
3930 | INIT_LIST_HEAD(&bus->dpc_tsklst); | 3885 | atomic_set(&bus->dpc_tskcnt, 0); |
3931 | spin_lock_init(&bus->dpc_tl_lock); | ||
3932 | 3886 | ||
3933 | /* Assign bus interface call back */ | 3887 | /* Assign bus interface call back */ |
3934 | bus->sdiodev->bus_if->dev = bus->sdiodev->dev; | 3888 | bus->sdiodev->bus_if->dev = bus->sdiodev->dev; |