Commit fccfe930 authored by Arend van Spriel's avatar Arend van Spriel Committed by John W. Linville

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: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 1ab083a3
...@@ -495,8 +495,7 @@ struct brcmf_sdio { ...@@ -495,8 +495,7 @@ struct brcmf_sdio {
struct workqueue_struct *brcmf_wq; struct workqueue_struct *brcmf_wq;
struct work_struct datawork; struct work_struct datawork;
struct list_head dpc_tsklst; atomic_t dpc_tskcnt;
spinlock_t dpc_tl_lock;
const struct firmware *firmware; const struct firmware *firmware;
u32 fw_ptr; u32 fw_ptr;
...@@ -2061,23 +2060,6 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) ...@@ -2061,23 +2060,6 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
} }
} }
static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
{
struct list_head *new_hd;
unsigned long flags;
if (in_interrupt())
new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC);
else
new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL);
if (new_hd == NULL)
return;
spin_lock_irqsave(&bus->dpc_tl_lock, flags);
list_add_tail(new_hd, &bus->dpc_tsklst);
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
}
static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
{ {
u8 idx; u8 idx;
...@@ -2312,7 +2294,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) ...@@ -2312,7 +2294,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
(!atomic_read(&bus->fcstate) && (!atomic_read(&bus->fcstate) &&
brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
data_ok(bus)) || PKT_AVAILABLE()) { data_ok(bus)) || PKT_AVAILABLE()) {
brcmf_sdbrcm_adddpctsk(bus); atomic_inc(&bus->dpc_tskcnt);
} }
/* If we're done for now, turn off clock request. */ /* 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,7 +2324,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
struct brcmf_sdio *bus = sdiodev->bus; struct brcmf_sdio *bus = sdiodev->bus;
unsigned long flags;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
...@@ -2381,14 +2362,9 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) ...@@ -2381,14 +2362,9 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
qcount[prec] = pktq_plen(&bus->txq, prec); qcount[prec] = pktq_plen(&bus->txq, prec);
#endif #endif
spin_lock_irqsave(&bus->dpc_tl_lock, flags); if (atomic_read(&bus->dpc_tskcnt) == 0) {
if (list_empty(&bus->dpc_tsklst)) { atomic_inc(&bus->dpc_tskcnt);
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
brcmf_sdbrcm_adddpctsk(bus);
queue_work(bus->brcmf_wq, &bus->datawork); queue_work(bus->brcmf_wq, &bus->datawork);
} else {
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
} }
return ret; return ret;
...@@ -2525,7 +2501,6 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) ...@@ -2525,7 +2501,6 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
struct brcmf_sdio *bus = sdiodev->bus; struct brcmf_sdio *bus = sdiodev->bus;
unsigned long flags;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
...@@ -2612,18 +2587,13 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) ...@@ -2612,18 +2587,13 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
} while (ret < 0 && retries++ < TXRETRIES); } while (ret < 0 && retries++ < TXRETRIES);
} }
spin_lock_irqsave(&bus->dpc_tl_lock, flags);
if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) &&
list_empty(&bus->dpc_tsklst)) { atomic_read(&bus->dpc_tskcnt) == 0) {
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
bus->activity = false; bus->activity = false;
sdio_claim_host(bus->sdiodev->func[1]); sdio_claim_host(bus->sdiodev->func[1]);
brcmf_dbg(INFO, "idle\n"); brcmf_dbg(INFO, "idle\n");
brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
sdio_release_host(bus->sdiodev->func[1]); sdio_release_host(bus->sdiodev->func[1]);
} else {
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
} }
if (ret) if (ret)
...@@ -3451,7 +3421,7 @@ void brcmf_sdbrcm_isr(void *arg) ...@@ -3451,7 +3421,7 @@ void brcmf_sdbrcm_isr(void *arg)
if (!bus->intr) if (!bus->intr)
brcmf_err("isr w/o interrupt configured!\n"); brcmf_err("isr w/o interrupt configured!\n");
brcmf_sdbrcm_adddpctsk(bus); atomic_inc(&bus->dpc_tskcnt);
queue_work(bus->brcmf_wq, &bus->datawork); queue_work(bus->brcmf_wq, &bus->datawork);
} }
...@@ -3460,7 +3430,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) ...@@ -3460,7 +3430,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
#ifdef DEBUG #ifdef DEBUG
struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev);
#endif /* DEBUG */ #endif /* DEBUG */
unsigned long flags;
brcmf_dbg(TIMER, "Enter\n"); brcmf_dbg(TIMER, "Enter\n");
...@@ -3476,11 +3445,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) ...@@ -3476,11 +3445,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
if (!bus->intr || if (!bus->intr ||
(bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) {
spin_lock_irqsave(&bus->dpc_tl_lock, flags); if (atomic_read(&bus->dpc_tskcnt) == 0) {
if (list_empty(&bus->dpc_tsklst)) {
u8 devpend; u8 devpend;
spin_unlock_irqrestore(&bus->dpc_tl_lock,
flags);
sdio_claim_host(bus->sdiodev->func[1]); sdio_claim_host(bus->sdiodev->func[1]);
devpend = brcmf_sdio_regrb(bus->sdiodev, devpend = brcmf_sdio_regrb(bus->sdiodev,
SDIO_CCCR_INTx, SDIO_CCCR_INTx,
...@@ -3489,9 +3456,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) ...@@ -3489,9 +3456,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
intstatus = intstatus =
devpend & (INTR_STATUS_FUNC1 | devpend & (INTR_STATUS_FUNC1 |
INTR_STATUS_FUNC2); INTR_STATUS_FUNC2);
} else {
spin_unlock_irqrestore(&bus->dpc_tl_lock,
flags);
} }
/* If there is something, make like the ISR and /* If there is something, make like the ISR and
...@@ -3500,7 +3464,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) ...@@ -3500,7 +3464,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->sdcnt.pollcnt++; bus->sdcnt.pollcnt++;
atomic_set(&bus->ipend, 1); atomic_set(&bus->ipend, 1);
brcmf_sdbrcm_adddpctsk(bus); atomic_inc(&bus->dpc_tskcnt);
queue_work(bus->brcmf_wq, &bus->datawork); queue_work(bus->brcmf_wq, &bus->datawork);
} }
} }
...@@ -3566,20 +3530,11 @@ static void brcmf_sdio_dataworker(struct work_struct *work) ...@@ -3566,20 +3530,11 @@ static void brcmf_sdio_dataworker(struct work_struct *work)
{ {
struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio,
datawork); datawork);
struct list_head *cur_hd, *tmp_hd;
unsigned long flags;
spin_lock_irqsave(&bus->dpc_tl_lock, flags);
list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) {
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
while (atomic_read(&bus->dpc_tskcnt)) {
brcmf_sdbrcm_dpc(bus); brcmf_sdbrcm_dpc(bus);
atomic_dec(&bus->dpc_tskcnt);
spin_lock_irqsave(&bus->dpc_tl_lock, flags);
list_del(cur_hd);
kfree(cur_hd);
} }
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
} }
static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) 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,8 +3882,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
bus->watchdog_tsk = NULL; bus->watchdog_tsk = NULL;
} }
/* Initialize DPC thread */ /* Initialize DPC thread */
INIT_LIST_HEAD(&bus->dpc_tsklst); atomic_set(&bus->dpc_tskcnt, 0);
spin_lock_init(&bus->dpc_tl_lock);
/* Assign bus interface call back */ /* Assign bus interface call back */
bus->sdiodev->bus_if->dev = bus->sdiodev->dev; bus->sdiodev->bus_if->dev = bus->sdiodev->dev;
......
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