* [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup
@ 2012-09-13 19:11 Arend van Spriel
2012-09-13 19:11 ` [PATCH 01/10] brcmfmac: absorb brcmf_sendpkt into brcmf_netdev_start_xmit Arend van Spriel
` (9 more replies)
0 siblings, 10 replies; 15+ messages in thread
From: Arend van Spriel @ 2012-09-13 19:11 UTC (permalink / raw)
To: John W. Linville; +Cc: Linux Wireless List, Arend van Spriel
This series mainly contains rework of the sdio interrupt handling
which addresses issues with in-band sdio interrupts. These were
raised by people working on nvidia tegra platform.
This series is intended for v3.7 kernel and applies to wireless-next.
Arend van Spriel (2):
brcmfmac: add parameter check in brcmf_c_mkiovar()
brcmfmac: simplify handling e-scan result firmware event
Franky Lin (7):
brcmfmac: absorb brcmf_sendpkt into brcmf_netdev_start_xmit
brcmfmac: remove obsolete sdio bus sleep mechanism
brcmfmac: use atomic variable for interrupt pending flag
brcmfmac: convert SDIO dpc implementation to workqueue
brcmfmac: streamline SDIO dpc
brcmfmac: raise SDIO host lock to higher level
brcmfmac: clear status for in-band interrupt in brcmf_sdbrcm_isr
Hante Meuleman (1):
brcmfmac: fix bug causing errorneous free on exception.
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 39 +-
.../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 25 --
drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 4 -
.../net/wireless/brcm80211/brcmfmac/dhd_common.c | 6 +-
.../net/wireless/brcm80211/brcmfmac/dhd_linux.c | 41 +-
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 416 ++++++++------------
.../net/wireless/brcm80211/brcmfmac/sdio_host.h | 2 +
drivers/net/wireless/brcm80211/brcmfmac/usb.c | 6 +-
.../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 14 +-
9 files changed, 225 insertions(+), 328 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 01/10] brcmfmac: absorb brcmf_sendpkt into brcmf_netdev_start_xmit
2012-09-13 19:11 [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup Arend van Spriel
@ 2012-09-13 19:11 ` Arend van Spriel
2012-09-13 19:11 ` [PATCH 02/10] brcmfmac: remove obsolete sdio bus sleep mechanism Arend van Spriel
` (8 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Arend van Spriel @ 2012-09-13 19:11 UTC (permalink / raw)
To: John W. Linville; +Cc: Linux Wireless List, Franky Lin, Arend van Spriel
From: Franky Lin <frankyl@broadcom.com>
brcmf_sendpkt only called by brcmf_netdev_start_xmit now. Absorb it
to increase readability.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 4 --
.../net/wireless/brcm80211/brcmfmac/dhd_linux.c | 41 ++++++++------------
2 files changed, 16 insertions(+), 29 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 4766d9f..55e489d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -682,10 +682,6 @@ extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx,
extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx);
-/* Send packet to dongle via data channel */
-extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\
- struct sk_buff *pkt);
-
extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg);
extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg,
int enable, int master_mode);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index b08f347..d7c76ce 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -272,30 +272,6 @@ static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
schedule_work(&drvr->multicast_work);
}
-int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
-{
- /* Reject if down */
- if (!drvr->bus_if->drvr_up || (drvr->bus_if->state == BRCMF_BUS_DOWN))
- return -ENODEV;
-
- /* Update multicast statistic */
- if (pktbuf->len >= ETH_ALEN) {
- u8 *pktdata = (u8 *) (pktbuf->data);
- struct ethhdr *eh = (struct ethhdr *)pktdata;
-
- if (is_multicast_ether_addr(eh->h_dest))
- drvr->tx_multicast++;
- if (ntohs(eh->h_proto) == ETH_P_PAE)
- atomic_inc(&drvr->pend_8021x_cnt);
- }
-
- /* If the protocol uses a data header, apply it */
- brcmf_proto_hdrpush(drvr, ifidx, pktbuf);
-
- /* Use bus module to send data frame */
- return drvr->bus_if->brcmf_bus_txdata(drvr->dev, pktbuf);
-}
-
static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
int ret;
@@ -338,7 +314,22 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
}
- ret = brcmf_sendpkt(drvr, ifp->idx, skb);
+ /* Update multicast statistic */
+ if (skb->len >= ETH_ALEN) {
+ u8 *pktdata = (u8 *)(skb->data);
+ struct ethhdr *eh = (struct ethhdr *)pktdata;
+
+ if (is_multicast_ether_addr(eh->h_dest))
+ drvr->tx_multicast++;
+ if (ntohs(eh->h_proto) == ETH_P_PAE)
+ atomic_inc(&drvr->pend_8021x_cnt);
+ }
+
+ /* If the protocol uses a data header, apply it */
+ brcmf_proto_hdrpush(drvr, ifp->idx, skb);
+
+ /* Use bus module to send data frame */
+ ret = drvr->bus_if->brcmf_bus_txdata(drvr->dev, skb);
done:
if (ret)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 02/10] brcmfmac: remove obsolete sdio bus sleep mechanism
2012-09-13 19:11 [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup Arend van Spriel
2012-09-13 19:11 ` [PATCH 01/10] brcmfmac: absorb brcmf_sendpkt into brcmf_netdev_start_xmit Arend van Spriel
@ 2012-09-13 19:11 ` Arend van Spriel
2012-09-13 19:11 ` [PATCH 03/10] brcmfmac: use atomic variable for interrupt pending flag Arend van Spriel
` (7 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Arend van Spriel @ 2012-09-13 19:11 UTC (permalink / raw)
To: John W. Linville; +Cc: Linux Wireless List, Franky Lin, Arend van Spriel
From: Franky Lin <frankyl@broadcom.com>
Remove sdio bus sleep mechanism since it is never invoked.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 93 --------------------
1 file changed, 93 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 4580ff3..2ca9e8c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -549,7 +549,6 @@ struct brcmf_sdio {
s32 idleclock; /* How to set bus driver when idle */
s32 sd_rxchain;
bool use_rxchain; /* If brcmf should use PKT chains */
- bool sleeping; /* Is SDIO bus sleeping? */
bool rxflow_mode; /* Rx flow control mode */
bool rxflow; /* Is rx flow control on */
bool alp_only; /* Don't use HT clock (ALP only) */
@@ -853,81 +852,6 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
return 0;
}
-static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep)
-{
- int ret;
-
- brcmf_dbg(INFO, "request %s (currently %s)\n",
- sleep ? "SLEEP" : "WAKE",
- bus->sleeping ? "SLEEP" : "WAKE");
-
- /* Done if we're already in the requested state */
- if (sleep == bus->sleeping)
- return 0;
-
- /* Going to sleep: set the alarm and turn off the lights... */
- if (sleep) {
- /* Don't sleep if something is pending */
- if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
- return -EBUSY;
-
- /* Make sure the controller has the bus up */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- /* Tell device to start using OOB wakeup */
- ret = w_sdreg32(bus, SMB_USE_OOB,
- offsetof(struct sdpcmd_regs, tosbmailbox));
- if (ret != 0)
- brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n");
-
- /* Turn off our contribution to the HT clock request */
- brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
-
- brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
-
- /* Isolate the bus */
- brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
- SBSDIO_DEVCTL_PADS_ISO, NULL);
-
- /* Change state */
- bus->sleeping = true;
-
- } else {
- /* Waking up: bus power up is ok, set local state */
-
- brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- 0, NULL);
-
- /* Make sure the controller has the bus up */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-
- /* Send misc interrupt to indicate OOB not needed */
- ret = w_sdreg32(bus, 0,
- offsetof(struct sdpcmd_regs, tosbmailboxdata));
- if (ret == 0)
- ret = w_sdreg32(bus, SMB_DEV_INT,
- offsetof(struct sdpcmd_regs, tosbmailbox));
-
- if (ret != 0)
- brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n");
-
- /* Make sure we have SD bus access */
- brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
-
- /* Change state */
- bus->sleeping = false;
- }
-
- return 0;
-}
-
-static void bus_wake(struct brcmf_sdio *bus)
-{
- if (bus->sleeping)
- brcmf_sdbrcm_bussleep(bus, false);
-}
-
static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
{
u32 intstatus = 0;
@@ -2267,8 +2191,6 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
down(&bus->sdsem);
- bus_wake(bus);
-
/* Enable clock for device interrupts */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
@@ -2404,8 +2326,6 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
}
}
- bus_wake(bus);
-
/* Make sure backplane clock is on */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
if (bus->clkstate == CLK_PENDING)
@@ -2918,8 +2838,6 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
/* Need to lock here to protect txseq and SDIO tx calls */
down(&bus->sdsem);
- bus_wake(bus);
-
/* Make sure backplane clock is on */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
@@ -3776,12 +3694,6 @@ void brcmf_sdbrcm_isr(void *arg)
bus->sdcnt.intrcount++;
bus->ipend = true;
- /* Shouldn't get this interrupt if we're sleeping? */
- if (bus->sleeping) {
- brcmf_dbg(ERROR, "INTERRUPT WHILE SLEEPING??\n");
- return;
- }
-
/* Disable additional interrupts (is this needed now)? */
if (!bus->intr)
brcmf_dbg(ERROR, "isr w/o interrupt configured!\n");
@@ -3801,10 +3713,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
brcmf_dbg(TIMER, "Enter\n");
- /* Ignore the timer if simulating bus down */
- if (bus->sleeping)
- return false;
-
down(&bus->sdsem);
/* Poll period: check device if appropriate. */
@@ -4024,7 +3932,6 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
SDIO_FUNC_ENABLE_1, NULL);
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
- bus->sleeping = false;
bus->rxflow = false;
/* Done with backplane-dependent accesses, can drop clock... */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 03/10] brcmfmac: use atomic variable for interrupt pending flag
2012-09-13 19:11 [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup Arend van Spriel
2012-09-13 19:11 ` [PATCH 01/10] brcmfmac: absorb brcmf_sendpkt into brcmf_netdev_start_xmit Arend van Spriel
2012-09-13 19:11 ` [PATCH 02/10] brcmfmac: remove obsolete sdio bus sleep mechanism Arend van Spriel
@ 2012-09-13 19:11 ` Arend van Spriel
2012-09-13 19:12 ` [PATCH 04/10] brcmfmac: convert SDIO dpc implementation to workqueue Arend van Spriel
` (6 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Arend van Spriel @ 2012-09-13 19:11 UTC (permalink / raw)
To: John W. Linville; +Cc: Linux Wireless List, Franky Lin, Arend van Spriel
From: Franky Lin <frankyl@broadcom.com>
Interrupt pending flag used in SDIO bus layer could be used in
multiple processes in different context. Use atomic_t make sure
every interrupt is handled.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 2ca9e8c..b0794e8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -531,7 +531,7 @@ struct brcmf_sdio {
bool intr; /* Use interrupts */
bool poll; /* Use polling */
- bool ipend; /* Device interrupt is pending */
+ atomic_t ipend; /* Device interrupt is pending */
uint spurious; /* Count of spurious interrupts */
uint pollrate; /* Ticks between device polls */
uint polltick; /* Tick counter */
@@ -2151,7 +2151,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
if (ret != 0)
break;
if (intstatus & bus->hostintmask)
- bus->ipend = true;
+ atomic_set(&bus->ipend, 1);
}
}
@@ -2249,7 +2249,7 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
unsigned long flags;
spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
- if (!bus->sdiodev->irq_en && !bus->ipend) {
+ if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
enable_irq(bus->sdiodev->irq);
bus->sdiodev->irq_en = true;
}
@@ -2332,8 +2332,8 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
goto clkwait;
/* Pending interrupt indicates new device status */
- if (bus->ipend) {
- bus->ipend = false;
+ if (atomic_read(&bus->ipend) > 0) {
+ atomic_set(&bus->ipend, 0);
err = r_sdreg32(bus, &newstatus,
offsetof(struct sdpcmd_regs, intstatus));
bus->sdcnt.f1regdata++;
@@ -2478,7 +2478,7 @@ clkwait:
} else if (bus->clkstate == CLK_PENDING) {
brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n");
resched = true;
- } else if (bus->intstatus || bus->ipend ||
+ } else if (bus->intstatus || atomic_read(&bus->ipend) > 0 ||
(!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)
&& data_ok(bus)) || PKT_AVAILABLE()) {
resched = true;
@@ -3692,7 +3692,7 @@ void brcmf_sdbrcm_isr(void *arg)
}
/* Count the interrupt call */
bus->sdcnt.intrcount++;
- bus->ipend = true;
+ atomic_set(&bus->ipend, 1);
/* Disable additional interrupts (is this needed now)? */
if (!bus->intr)
@@ -3740,7 +3740,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
schedule the DPC */
if (intstatus) {
bus->sdcnt.pollcnt++;
- bus->ipend = true;
+ atomic_set(&bus->ipend, 1);
bus->dpc_sched = true;
if (bus->dpc_tsk) {
@@ -3784,7 +3784,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
up(&bus->sdsem);
- return bus->ipend;
+ return (atomic_read(&bus->ipend) > 0);
}
static bool brcmf_sdbrcm_chipmatch(u16 chipid)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 04/10] brcmfmac: convert SDIO dpc implementation to workqueue
2012-09-13 19:11 [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup Arend van Spriel
` (2 preceding siblings ...)
2012-09-13 19:11 ` [PATCH 03/10] brcmfmac: use atomic variable for interrupt pending flag Arend van Spriel
@ 2012-09-13 19:12 ` Arend van Spriel
2012-09-13 19:12 ` [PATCH 05/10] brcmfmac: streamline SDIO dpc Arend van Spriel
` (5 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Arend van Spriel @ 2012-09-13 19:12 UTC (permalink / raw)
To: John W. Linville; +Cc: Linux Wireless List, Franky Lin, Arend van Spriel
From: Franky Lin <frankyl@broadcom.com>
Switch SDIO dpc implementation from kernel thread to workqueue for
better performance and compatibility.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 185 +++++++++-----------
1 file changed, 83 insertions(+), 102 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index b0794e8..1d80e05 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -495,7 +495,6 @@ struct brcmf_sdio {
u32 hostintmask; /* Copy of Host Interrupt Mask */
u32 intstatus; /* Intstatus bits (events) pending */
- bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
bool fcstate; /* State of dongle flow-control */
uint blocksize; /* Block size of SDIO transfers */
@@ -569,8 +568,8 @@ struct brcmf_sdio {
bool wd_timer_valid;
uint save_ms;
- struct task_struct *dpc_tsk;
- struct completion dpc_wait;
+ struct workqueue_struct *brcmf_wq;
+ struct work_struct datawork;
struct list_head dpc_tsklst;
spinlock_t dpc_tl_lock;
@@ -2183,12 +2182,6 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
bus->watchdog_tsk = NULL;
}
- if (bus->dpc_tsk && bus->dpc_tsk != current) {
- send_sig(SIGTERM, bus->dpc_tsk, 1);
- kthread_stop(bus->dpc_tsk);
- bus->dpc_tsk = NULL;
- }
-
down(&bus->sdsem);
/* Enable clock for device interrupts */
@@ -2261,15 +2254,31 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
}
#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
-static bool brcmf_sdbrcm_dpc(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 void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
{
u32 intstatus, newstatus = 0;
uint rxlimit = bus->rxbound; /* Rx frames to read before resched */
uint txlimit = bus->txbound; /* Tx frames to send before resched */
uint framecnt = 0; /* Temporary counter of tx/rx frames */
bool rxdone = true; /* Flag for no more read data */
- bool resched = false; /* Flag indicating resched wanted */
- int err;
+ int err = 0;
brcmf_dbg(TRACE, "Enter\n");
@@ -2454,7 +2463,6 @@ clkwait:
if (ret == 0)
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
- brcmf_dbg(INFO, "Return_dpc value is : %d\n", ret);
bus->ctrl_frame_stat = false;
brcmf_sdbrcm_wait_event_wakeup(bus);
}
@@ -2477,15 +2485,13 @@ clkwait:
bus->intstatus = 0;
} else if (bus->clkstate == CLK_PENDING) {
brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n");
- resched = true;
+ brcmf_sdbrcm_adddpctsk(bus);
} else if (bus->intstatus || atomic_read(&bus->ipend) > 0 ||
(!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)
&& data_ok(bus)) || PKT_AVAILABLE()) {
- resched = true;
+ brcmf_sdbrcm_adddpctsk(bus);
}
- bus->dpc_sched = resched;
-
/* If we're done for now, turn off clock request. */
if ((bus->clkstate != CLK_PENDING)
&& bus->idletime == BRCMF_IDLE_IMMEDIATE) {
@@ -2494,65 +2500,6 @@ clkwait:
}
up(&bus->sdsem);
-
- return resched;
-}
-
-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_sdbrcm_dpc_thread(void *data)
-{
- struct brcmf_sdio *bus = (struct brcmf_sdio *) data;
- struct list_head *cur_hd, *tmp_hd;
- unsigned long flags;
-
- allow_signal(SIGTERM);
- /* Run until signal received */
- while (1) {
- if (kthread_should_stop())
- break;
-
- if (list_empty(&bus->dpc_tsklst))
- if (wait_for_completion_interruptible(&bus->dpc_wait))
- break;
-
- 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);
-
- if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
- /* after stopping the bus, exit thread */
- brcmf_sdbrcm_bus_stop(bus->sdiodev->dev);
- bus->dpc_tsk = NULL;
- spin_lock_irqsave(&bus->dpc_tl_lock, flags);
- break;
- }
-
- if (brcmf_sdbrcm_dpc(bus))
- brcmf_sdbrcm_adddpctsk(bus);
-
- spin_lock_irqsave(&bus->dpc_tl_lock, flags);
- list_del(cur_hd);
- kfree(cur_hd);
- }
- spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
- }
- return 0;
}
static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
@@ -2562,6 +2509,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
struct brcmf_sdio *bus = sdiodev->bus;
+ unsigned long flags;
brcmf_dbg(TRACE, "Enter\n");
@@ -2600,13 +2548,15 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
if (pktq_plen(&bus->txq, prec) > qcount[prec])
qcount[prec] = pktq_plen(&bus->txq, prec);
#endif
- /* Schedule DPC if needed to send queued packet(s) */
- if (!bus->dpc_sched) {
- bus->dpc_sched = true;
- if (bus->dpc_tsk) {
- brcmf_sdbrcm_adddpctsk(bus);
- complete(&bus->dpc_wait);
- }
+
+ spin_lock_irqsave(&bus->dpc_tl_lock, flags);
+ if (list_empty(&bus->dpc_tsklst)) {
+ spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
+
+ brcmf_sdbrcm_adddpctsk(bus);
+ queue_work(bus->brcmf_wq, &bus->datawork);
+ } else {
+ spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
}
return ret;
@@ -2802,6 +2752,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
struct brcmf_sdio *bus = sdiodev->bus;
+ unsigned long flags;
brcmf_dbg(TRACE, "Enter\n");
@@ -2885,9 +2836,15 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
} while (ret < 0 && retries++ < TXRETRIES);
}
- if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+ spin_lock_irqsave(&bus->dpc_tl_lock, flags);
+ if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) &&
+ list_empty(&bus->dpc_tsklst)) {
+ spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
+
bus->activity = false;
brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
+ } else {
+ spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
}
up(&bus->sdsem);
@@ -3698,11 +3655,8 @@ void brcmf_sdbrcm_isr(void *arg)
if (!bus->intr)
brcmf_dbg(ERROR, "isr w/o interrupt configured!\n");
- bus->dpc_sched = true;
- if (bus->dpc_tsk) {
- brcmf_sdbrcm_adddpctsk(bus);
- complete(&bus->dpc_wait);
- }
+ brcmf_sdbrcm_adddpctsk(bus);
+ queue_work(bus->brcmf_wq, &bus->datawork);
}
static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
@@ -3710,6 +3664,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
#ifdef DEBUG
struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev);
#endif /* DEBUG */
+ unsigned long flags;
brcmf_dbg(TIMER, "Enter\n");
@@ -3726,14 +3681,20 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
if (!bus->intr ||
(bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) {
- if (!bus->dpc_sched) {
+ spin_lock_irqsave(&bus->dpc_tl_lock, flags);
+ if (list_empty(&bus->dpc_tsklst)) {
u8 devpend;
+ spin_unlock_irqrestore(&bus->dpc_tl_lock,
+ flags);
devpend = brcmf_sdio_regrb(bus->sdiodev,
SDIO_CCCR_INTx,
NULL);
intstatus =
devpend & (INTR_STATUS_FUNC1 |
INTR_STATUS_FUNC2);
+ } else {
+ spin_unlock_irqrestore(&bus->dpc_tl_lock,
+ flags);
}
/* If there is something, make like the ISR and
@@ -3742,11 +3703,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->sdcnt.pollcnt++;
atomic_set(&bus->ipend, 1);
- bus->dpc_sched = true;
- if (bus->dpc_tsk) {
- brcmf_sdbrcm_adddpctsk(bus);
- complete(&bus->dpc_wait);
- }
+ brcmf_sdbrcm_adddpctsk(bus);
+ queue_work(bus->brcmf_wq, &bus->datawork);
}
}
@@ -3800,6 +3758,26 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid)
return false;
}
+static void brcmf_sdio_dataworker(struct work_struct *work)
+{
+ struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio,
+ 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);
+
+ brcmf_sdbrcm_dpc(bus);
+
+ 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)
{
brcmf_dbg(TRACE, "Enter\n");
@@ -4012,6 +3990,9 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
/* De-register interrupt handler */
brcmf_sdio_intr_unregister(bus->sdiodev);
+ cancel_work_sync(&bus->datawork);
+ destroy_workqueue(bus->brcmf_wq);
+
if (bus->sdiodev->bus_if->drvr) {
brcmf_detach(bus->sdiodev->dev);
brcmf_sdbrcm_release_dongle(bus);
@@ -4064,6 +4045,13 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
init_waitqueue_head(&bus->ctrl_wait);
init_waitqueue_head(&bus->dcmd_resp_wait);
+ bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq");
+ if (bus->brcmf_wq == NULL) {
+ brcmf_dbg(ERROR, "insufficient memory to create txworkqueue\n");
+ goto fail;
+ }
+ INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
+
/* Set up the watchdog timer */
init_timer(&bus->timer);
bus->timer.data = (unsigned long)bus;
@@ -4081,15 +4069,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
bus->watchdog_tsk = NULL;
}
/* Initialize DPC thread */
- init_completion(&bus->dpc_wait);
INIT_LIST_HEAD(&bus->dpc_tsklst);
spin_lock_init(&bus->dpc_tl_lock);
- bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
- bus, "brcmf_dpc");
- if (IS_ERR(bus->dpc_tsk)) {
- pr_warn("brcmf_dpc thread failed to start\n");
- bus->dpc_tsk = NULL;
- }
/* Assign bus interface call back */
bus->sdiodev->bus_if->brcmf_bus_stop = brcmf_sdbrcm_bus_stop;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 05/10] brcmfmac: streamline SDIO dpc
2012-09-13 19:11 [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup Arend van Spriel
` (3 preceding siblings ...)
2012-09-13 19:12 ` [PATCH 04/10] brcmfmac: convert SDIO dpc implementation to workqueue Arend van Spriel
@ 2012-09-13 19:12 ` Arend van Spriel
2012-09-13 19:12 ` [PATCH 06/10] brcmfmac: raise SDIO host lock to higher level Arend van Spriel
` (4 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Arend van Spriel @ 2012-09-13 19:12 UTC (permalink / raw)
To: John W. Linville; +Cc: Linux Wireless List, Franky Lin, Arend van Spriel
From: Franky Lin <frankyl@broadcom.com>
Streamline SDIO dpc by removing some unnecessary code path.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 27 +++++---------------
1 file changed, 7 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 1d80e05..90a3849 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -2330,15 +2330,11 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
}
bus->clkstate = CLK_AVAIL;
- } else {
- goto clkwait;
}
}
/* Make sure backplane clock is on */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
- if (bus->clkstate == CLK_PENDING)
- goto clkwait;
/* Pending interrupt indicates new device status */
if (atomic_read(&bus->ipend) > 0) {
@@ -2412,7 +2408,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
intstatus &= ~I_HMB_FRAME_IND;
/* On frame indication, read available frames */
- if (PKT_AVAILABLE()) {
+ if (PKT_AVAILABLE() && bus->clkstate == CLK_AVAIL) {
framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone);
if (rxdone || bus->rxskip)
intstatus &= ~I_HMB_FRAME_IND;
@@ -2422,22 +2418,21 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
/* Keep still-pending events for next scheduling */
bus->intstatus = intstatus;
-clkwait:
brcmf_sdbrcm_clrintr(bus);
if (data_ok(bus) && bus->ctrl_frame_stat &&
(bus->clkstate == CLK_AVAIL)) {
- int ret, i;
+ int i;
- ret = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
+ err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf,
(u32) bus->ctrl_frame_len);
- if (ret < 0) {
+ if (err < 0) {
/* On failure, abort the command and
terminate the frame */
brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n",
- ret);
+ err);
bus->sdcnt.tx_sderrs++;
brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2);
@@ -2459,10 +2454,9 @@ clkwait:
break;
}
- }
- if (ret == 0)
+ } else {
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
-
+ }
bus->ctrl_frame_stat = false;
brcmf_sdbrcm_wait_event_wakeup(bus);
}
@@ -2475,17 +2469,10 @@ clkwait:
txlimit -= framecnt;
}
- /* Resched if events or tx frames are pending,
- else await next interrupt */
- /* On failed register access, all bets are off:
- no resched or interrupts */
if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) {
brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation\n");
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
bus->intstatus = 0;
- } else if (bus->clkstate == CLK_PENDING) {
- brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n");
- brcmf_sdbrcm_adddpctsk(bus);
} else if (bus->intstatus || atomic_read(&bus->ipend) > 0 ||
(!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)
&& data_ok(bus)) || PKT_AVAILABLE()) {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 06/10] brcmfmac: raise SDIO host lock to higher level
2012-09-13 19:11 [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup Arend van Spriel
` (4 preceding siblings ...)
2012-09-13 19:12 ` [PATCH 05/10] brcmfmac: streamline SDIO dpc Arend van Spriel
@ 2012-09-13 19:12 ` Arend van Spriel
2012-09-13 19:12 ` [PATCH 07/10] brcmfmac: clear status for in-band interrupt in brcmf_sdbrcm_isr Arend van Spriel
` (3 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Arend van Spriel @ 2012-09-13 19:12 UTC (permalink / raw)
To: John W. Linville; +Cc: Linux Wireless List, Franky Lin, Arend van Spriel
From: Franky Lin <frankyl@broadcom.com>
Use SDIO host lock to protect the entire communication process
of register access or data read/write rather than function calls
to MMC/SDIO stack only. This can help to avoid unintentional
memory access and unexpected interruption.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 37 +++++++++++++++++---
.../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 25 -------------
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 4 +++
3 files changed, 36 insertions(+), 30 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 8e7e692..0c1d08a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -249,7 +249,9 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
int retval;
brcmf_dbg(INFO, "addr:0x%08x\n", addr);
+ sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
+ sdio_release_host(sdiodev->func[1]);
brcmf_dbg(INFO, "data:0x%02x\n", data);
if (ret)
@@ -264,7 +266,9 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
int retval;
brcmf_dbg(INFO, "addr:0x%08x\n", addr);
+ sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
+ sdio_release_host(sdiodev->func[1]);
brcmf_dbg(INFO, "data:0x%08x\n", data);
if (ret)
@@ -279,7 +283,9 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
int retval;
brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
+ sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
+ sdio_release_host(sdiodev->func[1]);
if (ret)
*ret = retval;
@@ -291,7 +297,9 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
int retval;
brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
+ sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
+ sdio_release_host(sdiodev->func[1]);
if (ret)
*ret = retval;
@@ -356,15 +364,20 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pkt->len);
+ sdio_claim_host(sdiodev->func[1]);
+
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
if (err)
- return err;
+ goto done;
incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
fn, addr, pkt);
+done:
+ sdio_release_host(sdiodev->func[1]);
+
return err;
}
@@ -378,15 +391,20 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pktq->qlen);
+ sdio_claim_host(sdiodev->func[1]);
+
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
if (err)
- return err;
+ goto done;
incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr,
pktq);
+done:
+ sdio_release_host(sdiodev->func[1]);
+
return err;
}
@@ -428,10 +446,12 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
if (flags & SDIO_REQ_ASYNC)
return -ENOTSUPP;
+ sdio_claim_host(sdiodev->func[1]);
+
if (bar0 != sdiodev->sbwad) {
err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
if (err)
- return err;
+ goto done;
sdiodev->sbwad = bar0;
}
@@ -443,8 +463,13 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
if (width == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
- addr, pkt);
+ err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
+ addr, pkt);
+
+done:
+ sdio_release_host(sdiodev->func[1]);
+
+ return err;
}
int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
@@ -485,8 +510,10 @@ int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
brcmf_dbg(TRACE, "Enter\n");
/* issue abort cmd52 command through F0 */
+ sdio_claim_host(sdiodev->func[1]);
brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
SDIO_CCCR_ABORT, &t_func);
+ sdio_release_host(sdiodev->func[1]);
brcmf_dbg(TRACE, "Exit\n");
return 0;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 372f74e..c3247d5 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -103,7 +103,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
if (regaddr == SDIO_CCCR_IOEx) {
sdfunc = sdiodev->func[2];
if (sdfunc) {
- sdio_claim_host(sdfunc);
if (*byte & SDIO_FUNC_ENABLE_2) {
/* Enable Function 2 */
err_ret = sdio_enable_func(sdfunc);
@@ -119,7 +118,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
"Disable F2 failed:%d\n",
err_ret);
}
- sdio_release_host(sdfunc);
}
} else if ((regaddr == SDIO_CCCR_ABORT) ||
(regaddr == SDIO_CCCR_IENx)) {
@@ -128,17 +126,13 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
if (!sdfunc)
return -ENOMEM;
sdfunc->num = 0;
- sdio_claim_host(sdfunc);
sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
- sdio_release_host(sdfunc);
kfree(sdfunc);
} else if (regaddr < 0xF0) {
brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
err_ret = -EPERM;
} else {
- sdio_claim_host(sdfunc);
sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
- sdio_release_host(sdfunc);
}
return err_ret;
@@ -159,7 +153,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
/* handle F0 separately */
err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
} else {
- sdio_claim_host(sdiodev->func[func]);
if (rw) /* CMD52 Write */
sdio_writeb(sdiodev->func[func], *byte, regaddr,
&err_ret);
@@ -170,7 +163,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
*byte = sdio_readb(sdiodev->func[func], regaddr,
&err_ret);
}
- sdio_release_host(sdiodev->func[func]);
}
if (err_ret)
@@ -197,8 +189,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
if (brcmf_pm_resume_error(sdiodev))
return -EIO;
- /* Claim host controller */
- sdio_claim_host(sdiodev->func[func]);
if (rw) { /* CMD52 Write */
if (nbytes == 4)
@@ -219,9 +209,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
}
- /* Release host controller */
- sdio_release_host(sdiodev->func[func]);
-
if (err_ret)
brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n",
rw ? "write" : "read", err_ret);
@@ -275,9 +262,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
if (brcmf_pm_resume_error(sdiodev))
return -EIO;
- /* Claim host controller */
- sdio_claim_host(sdiodev->func[func]);
-
skb_queue_walk(pktq, pkt) {
uint pkt_len = pkt->len;
pkt_len += 3;
@@ -300,9 +284,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
SGCount++;
}
- /* Release host controller */
- sdio_release_host(sdiodev->func[func]);
-
brcmf_dbg(TRACE, "Exit\n");
return err_ret;
}
@@ -328,9 +309,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
if (brcmf_pm_resume_error(sdiodev))
return -EIO;
- /* Claim host controller */
- sdio_claim_host(sdiodev->func[func]);
-
pkt_len += 3;
pkt_len &= (uint)~3;
@@ -344,9 +322,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
write ? "TX" : "RX", pkt, addr, pkt_len);
}
- /* Release host controller */
- sdio_release_host(sdiodev->func[func]);
-
return status;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 90a3849..619f3cd 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -2564,6 +2564,8 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
else
dsize = size;
+ sdio_claim_host(bus->sdiodev->func[1]);
+
/* Set the backplane window to include the start address */
bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address);
if (bcmerror) {
@@ -2605,6 +2607,8 @@ xfer_done:
brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n",
bus->sdiodev->sbwad);
+ sdio_release_host(bus->sdiodev->func[1]);
+
return bcmerror;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 07/10] brcmfmac: clear status for in-band interrupt in brcmf_sdbrcm_isr
2012-09-13 19:11 [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup Arend van Spriel
` (5 preceding siblings ...)
2012-09-13 19:12 ` [PATCH 06/10] brcmfmac: raise SDIO host lock to higher level Arend van Spriel
@ 2012-09-13 19:12 ` Arend van Spriel
2012-09-14 21:53 ` Stephen Warren
2012-09-13 19:12 ` [PATCH 08/10] brcmfmac: fix bug causing errorneous free on exception Arend van Spriel
` (2 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: Arend van Spriel @ 2012-09-13 19:12 UTC (permalink / raw)
To: John W. Linville
Cc: Linux Wireless List, Franky Lin, Wei Ni, Stephen Warren,
Arend van Spriel
From: Franky Lin <frankyl@broadcom.com>
SDIO in-band interrupt is level sensitive according to SDIO standard.
When the register interrupt handler gets called by SDIO stack it is
running in non interrupt context and expected to clear the interrupt
from the dongle. Therefore in-band and out-of-band interrupt need to
be handled differently.
Cc: Wei Ni <wni@nvidia.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Reported-by: Wei Ni <wni@nvidia.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 2 +-
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 97 +++++++++++++-------
.../net/wireless/brcm80211/brcmfmac/sdio_host.h | 2 +
3 files changed, 68 insertions(+), 33 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 0c1d08a..3b2c4c2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -185,7 +185,7 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
return err;
}
-static int
+int
brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
void *data, bool write)
{
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 619f3cd..ff7e829 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -494,8 +494,8 @@ struct brcmf_sdio {
u32 ramsize; /* Size of RAM in SOCRAM (bytes) */
u32 hostintmask; /* Copy of Host Interrupt Mask */
- u32 intstatus; /* Intstatus bits (events) pending */
- bool fcstate; /* State of dongle flow-control */
+ atomic_t intstatus; /* Intstatus bits (events) pending */
+ atomic_t fcstate; /* State of dongle flow-control */
uint blocksize; /* Block size of SDIO transfers */
uint roundup; /* Max roundup limit */
@@ -2271,20 +2271,53 @@ static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
}
+static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
+{
+ u8 idx;
+ u32 addr;
+ unsigned long val;
+ int n, ret;
+
+ idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
+ addr = bus->ci->c_inf[idx].base +
+ offsetof(struct sdpcmd_regs, intstatus);
+
+ ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, false);
+ bus->sdcnt.f1regdata++;
+ if (ret != 0)
+ val = 0;
+
+ val &= bus->hostintmask;
+ atomic_set(&bus->fcstate, !!(val & I_HMB_FC_STATE));
+
+ /* Clear interrupts */
+ if (val) {
+ ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, true);
+ bus->sdcnt.f1regdata++;
+ }
+
+ if (ret) {
+ atomic_set(&bus->intstatus, 0);
+ } else if (val) {
+ for_each_set_bit(n, &val, 32)
+ set_bit(n, (unsigned long *)&bus->intstatus.counter);
+ }
+
+ return ret;
+}
+
static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
{
- u32 intstatus, newstatus = 0;
+ u32 newstatus = 0;
+ unsigned long intstatus;
uint rxlimit = bus->rxbound; /* Rx frames to read before resched */
uint txlimit = bus->txbound; /* Tx frames to send before resched */
uint framecnt = 0; /* Temporary counter of tx/rx frames */
bool rxdone = true; /* Flag for no more read data */
- int err = 0;
+ int err = 0, n;
brcmf_dbg(TRACE, "Enter\n");
- /* Start with leftover status bits */
- intstatus = bus->intstatus;
-
down(&bus->sdsem);
/* If waiting for HTAVAIL, check status */
@@ -2339,24 +2372,13 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
/* Pending interrupt indicates new device status */
if (atomic_read(&bus->ipend) > 0) {
atomic_set(&bus->ipend, 0);
- err = r_sdreg32(bus, &newstatus,
- offsetof(struct sdpcmd_regs, intstatus));
- bus->sdcnt.f1regdata++;
- if (err != 0)
- newstatus = 0;
- newstatus &= bus->hostintmask;
- bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
- if (newstatus) {
- err = w_sdreg32(bus, newstatus,
- offsetof(struct sdpcmd_regs,
- intstatus));
- bus->sdcnt.f1regdata++;
- }
+ sdio_claim_host(bus->sdiodev->func[1]);
+ err = brcmf_sdio_intr_rstatus(bus);
+ sdio_release_host(bus->sdiodev->func[1]);
}
- /* Merge new bits with previous */
- intstatus |= newstatus;
- bus->intstatus = 0;
+ /* Start with leftover status bits */
+ intstatus = atomic_xchg(&bus->intstatus, 0);
/* Handle flow-control change: read new state in case our ack
* crossed another change interrupt. If change still set, assume
@@ -2370,8 +2392,8 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
err = r_sdreg32(bus, &newstatus,
offsetof(struct sdpcmd_regs, intstatus));
bus->sdcnt.f1regdata += 2;
- bus->fcstate =
- !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
+ atomic_set(&bus->fcstate,
+ !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)));
intstatus |= (newstatus & bus->hostintmask);
}
@@ -2416,7 +2438,10 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
}
/* Keep still-pending events for next scheduling */
- bus->intstatus = intstatus;
+ if (intstatus) {
+ for_each_set_bit(n, &intstatus, 32)
+ set_bit(n, (unsigned long *)&bus->intstatus.counter);
+ }
brcmf_sdbrcm_clrintr(bus);
@@ -2461,7 +2486,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
brcmf_sdbrcm_wait_event_wakeup(bus);
}
/* Send queued frames (limit 1 if rx may still be pending) */
- else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
+ else if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) &&
brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
&& data_ok(bus)) {
framecnt = rxdone ? txlimit : min(txlimit, bus->txminmax);
@@ -2472,10 +2497,12 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) {
brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation\n");
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
- bus->intstatus = 0;
- } else if (bus->intstatus || atomic_read(&bus->ipend) > 0 ||
- (!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)
- && data_ok(bus)) || PKT_AVAILABLE()) {
+ atomic_set(&bus->intstatus, 0);
+ } else if (atomic_read(&bus->intstatus) ||
+ atomic_read(&bus->ipend) > 0 ||
+ (!atomic_read(&bus->fcstate) &&
+ brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
+ data_ok(bus)) || PKT_AVAILABLE()) {
brcmf_sdbrcm_adddpctsk(bus);
}
@@ -3640,7 +3667,13 @@ void brcmf_sdbrcm_isr(void *arg)
}
/* Count the interrupt call */
bus->sdcnt.intrcount++;
- atomic_set(&bus->ipend, 1);
+ if (in_interrupt())
+ atomic_set(&bus->ipend, 1);
+ else
+ if (brcmf_sdio_intr_rstatus(bus)) {
+ brcmf_dbg(ERROR, "failed backplane access\n");
+ bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
+ }
/* Disable additional interrupts (is this needed now)? */
if (!bus->intr)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 29bf78d2..0d30afd 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -174,6 +174,8 @@ extern void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
u8 data, int *ret);
extern void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
u32 data, int *ret);
+extern int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
+ void *data, bool write);
/* Buffer transfer to/from device (client) core via cmd53.
* fn: function number
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 08/10] brcmfmac: fix bug causing errorneous free on exception.
2012-09-13 19:11 [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup Arend van Spriel
` (6 preceding siblings ...)
2012-09-13 19:12 ` [PATCH 07/10] brcmfmac: clear status for in-band interrupt in brcmf_sdbrcm_isr Arend van Spriel
@ 2012-09-13 19:12 ` Arend van Spriel
2012-09-13 19:12 ` [PATCH 09/10] brcmfmac: add parameter check in brcmf_c_mkiovar() Arend van Spriel
2012-09-13 19:12 ` [PATCH 10/10] brcmfmac: simplify handling e-scan result firmware event Arend van Spriel
9 siblings, 0 replies; 15+ messages in thread
From: Arend van Spriel @ 2012-09-13 19:12 UTC (permalink / raw)
To: John W. Linville; +Cc: Linux Wireless List, Hante Meuleman, Arend van Spriel
From: Hante Meuleman <meuleman@broadcom.com>
This patch fixes bug where driver frees resources twice when
an exception occurs.
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/usb.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index c6d5aeb..03f59cd 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -1340,10 +1340,8 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
struct device *dev = devinfo->dev;
bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ);
- if (!bus_pub) {
- ret = -ENODEV;
- goto fail;
- }
+ if (!bus_pub)
+ return -ENODEV;
bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
if (!bus) {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 09/10] brcmfmac: add parameter check in brcmf_c_mkiovar()
2012-09-13 19:11 [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup Arend van Spriel
` (7 preceding siblings ...)
2012-09-13 19:12 ` [PATCH 08/10] brcmfmac: fix bug causing errorneous free on exception Arend van Spriel
@ 2012-09-13 19:12 ` Arend van Spriel
2012-09-13 19:12 ` [PATCH 10/10] brcmfmac: simplify handling e-scan result firmware event Arend van Spriel
9 siblings, 0 replies; 15+ messages in thread
From: Arend van Spriel @ 2012-09-13 19:12 UTC (permalink / raw)
To: John W. Linville; +Cc: Linux Wireless List, Arend van Spriel
This patch assures data is only appended in output buffer when
data is not NULL and datalen is not zero.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
.../net/wireless/brcm80211/brcmfmac/dhd_common.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
index 8121dba..6afb26c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -80,8 +80,10 @@ brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
strncpy(buf, name, buflen);
/* append data onto the end of the name string */
- memcpy(&buf[len], data, datalen);
- len += datalen;
+ if (data && datalen) {
+ memcpy(&buf[len], data, datalen);
+ len += datalen;
+ }
return len;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 10/10] brcmfmac: simplify handling e-scan result firmware event
2012-09-13 19:11 [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup Arend van Spriel
` (8 preceding siblings ...)
2012-09-13 19:12 ` [PATCH 09/10] brcmfmac: add parameter check in brcmf_c_mkiovar() Arend van Spriel
@ 2012-09-13 19:12 ` Arend van Spriel
9 siblings, 0 replies; 15+ messages in thread
From: Arend van Spriel @ 2012-09-13 19:12 UTC (permalink / raw)
To: John W. Linville; +Cc: Linux Wireless List, Arend van Spriel
Upon handling an e-scan result event from the firmware in
brcmf_cfg80211_escan_handler() the status may indicate e-scan
is completed or aborted. If so brcmf_notify_escan_complete()
is called. However, that function and brcmf_cfg80211_escan_handler()
both log the same debug message and both enable MPC flag in the
firmware.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
.../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 32ee052..200a6c2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -2873,6 +2873,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv,
u32 bi_length;
struct brcmf_scan_results *list;
u32 i;
+ bool aborted;
status = be32_to_cpu(e->status);
@@ -2945,16 +2946,9 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv,
cfg_priv->bss_list = (struct brcmf_scan_results *)
cfg_priv->escan_info.escan_buf;
brcmf_inform_bss(cfg_priv);
- if (status == BRCMF_E_STATUS_SUCCESS) {
- WL_SCAN("ESCAN Completed\n");
- brcmf_notify_escan_complete(cfg_priv, ndev,
- false, false);
- } else {
- WL_ERR("ESCAN Aborted, Event 0x%x\n", status);
- brcmf_notify_escan_complete(cfg_priv, ndev,
- true, false);
- }
- brcmf_set_mpc(ndev, 1);
+ aborted = status != BRCMF_E_STATUS_SUCCESS;
+ brcmf_notify_escan_complete(cfg_priv, ndev, aborted,
+ false);
} else
WL_ERR("Unexpected scan result 0x%x\n", status);
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 07/10] brcmfmac: clear status for in-band interrupt in brcmf_sdbrcm_isr
2012-09-13 19:12 ` [PATCH 07/10] brcmfmac: clear status for in-band interrupt in brcmf_sdbrcm_isr Arend van Spriel
@ 2012-09-14 21:53 ` Stephen Warren
2012-09-15 9:19 ` Arend van Spriel
0 siblings, 1 reply; 15+ messages in thread
From: Stephen Warren @ 2012-09-14 21:53 UTC (permalink / raw)
To: Arend van Spriel
Cc: John W. Linville, Linux Wireless List, Franky Lin, Wei Ni
On 09/13/2012 01:12 PM, Arend van Spriel wrote:
> From: Franky Lin <frankyl@broadcom.com>
>
> SDIO in-band interrupt is level sensitive according to SDIO standard.
> When the register interrupt handler gets called by SDIO stack it is
> running in non interrupt context and expected to clear the interrupt
> from the dongle. Therefore in-band and out-of-band interrupt need to
> be handled differently.
Tested-by: Stephen Warren <swarren@wwwdotorg.org>
For reference, I took next-20120914, applied this patch series, applied
a few patches from Wei Ni to set up the SDIO HW on Tegra correctly, and
tested. The last time I tried this without any patches to the brcmfmac,
this test caused some system instability issues. This time around, I
observed no instability. I tested WPA PSK, ping (or flood ping) plus
playing audio through ALSA.
Is this series likely to make 3.7?
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 07/10] brcmfmac: clear status for in-band interrupt in brcmf_sdbrcm_isr
2012-09-14 21:53 ` Stephen Warren
@ 2012-09-15 9:19 ` Arend van Spriel
2012-09-15 17:12 ` Stephen Warren
0 siblings, 1 reply; 15+ messages in thread
From: Arend van Spriel @ 2012-09-15 9:19 UTC (permalink / raw)
To: Stephen Warren; +Cc: John W. Linville, Linux Wireless List, Franky Lin, Wei Ni
On 09/14/2012 11:53 PM, Stephen Warren wrote:
> On 09/13/2012 01:12 PM, Arend van Spriel wrote:
>> From: Franky Lin <frankyl@broadcom.com>
>>
>> SDIO in-band interrupt is level sensitive according to SDIO standard.
>> When the register interrupt handler gets called by SDIO stack it is
>> running in non interrupt context and expected to clear the interrupt
>> from the dongle. Therefore in-band and out-of-band interrupt need to
>> be handled differently.
>
> Tested-by: Stephen Warren <swarren@wwwdotorg.org>
>
> For reference, I took next-20120914, applied this patch series, applied
> a few patches from Wei Ni to set up the SDIO HW on Tegra correctly, and
> tested. The last time I tried this without any patches to the brcmfmac,
> this test caused some system instability issues. This time around, I
> observed no instability. I tested WPA PSK, ping (or flood ping) plus
> playing audio through ALSA.
>
> Is this series likely to make 3.7?
>
Thanks, Stephen
Good to hear. I suspect we are close to the 3.7 merge window, but we do
hope this will make it mainly for the tegra sdio issue that Wei Ni
raised. In general the series should resolve issues when used on
sdhci/mmc framework with in-band interrupt.
Do you still need the patches from Wei Ni and are they SDIO or brcmfmac
related?
Gr. AvS
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 07/10] brcmfmac: clear status for in-band interrupt in brcmf_sdbrcm_isr
2012-09-15 9:19 ` Arend van Spriel
@ 2012-09-15 17:12 ` Stephen Warren
2012-09-17 17:37 ` Stephen Warren
0 siblings, 1 reply; 15+ messages in thread
From: Stephen Warren @ 2012-09-15 17:12 UTC (permalink / raw)
To: Arend van Spriel
Cc: John W. Linville, Linux Wireless List, Franky Lin, Wei Ni
On 09/15/2012 03:19 AM, Arend van Spriel wrote:
> On 09/14/2012 11:53 PM, Stephen Warren wrote:
>> On 09/13/2012 01:12 PM, Arend van Spriel wrote:
>>> From: Franky Lin <frankyl@broadcom.com>
>>>
>>> SDIO in-band interrupt is level sensitive according to SDIO standard.
>>> When the register interrupt handler gets called by SDIO stack it is
>>> running in non interrupt context and expected to clear the interrupt
>>> from the dongle. Therefore in-band and out-of-band interrupt need to
>>> be handled differently.
>>
>> Tested-by: Stephen Warren <swarren@wwwdotorg.org>
>>
>> For reference, I took next-20120914, applied this patch series, applied
>> a few patches from Wei Ni to set up the SDIO HW on Tegra correctly, and
>> tested. The last time I tried this without any patches to the brcmfmac,
>> this test caused some system instability issues. This time around, I
>> observed no instability. I tested WPA PSK, ping (or flood ping) plus
>> playing audio through ALSA.
>>
>> Is this series likely to make 3.7?
>>
>
> Thanks, Stephen
>
> Good to hear. I suspect we are close to the 3.7 merge window, but we do
> hope this will make it mainly for the tegra sdio issue that Wei Ni
> raised. In general the series should resolve issues when used on
> sdhci/mmc framework with in-band interrupt.
>
> Do you still need the patches from Wei Ni and are they SDIO or brcmfmac
> related?
Some patches are needed, but they're all for Tegra-specific code to
configure the pinmux, GPIO, etc. on the Tegra SoC in order to correctly
communicate with the SDIO port, and to enable the controller. No patches
are required to the brcmfmac driver.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 07/10] brcmfmac: clear status for in-band interrupt in brcmf_sdbrcm_isr
2012-09-15 17:12 ` Stephen Warren
@ 2012-09-17 17:37 ` Stephen Warren
0 siblings, 0 replies; 15+ messages in thread
From: Stephen Warren @ 2012-09-17 17:37 UTC (permalink / raw)
To: Arend van Spriel, John W. Linville
Cc: Linux Wireless List, Franky Lin, Wei Ni
On 09/15/2012 11:12 AM, Stephen Warren wrote:
> On 09/15/2012 03:19 AM, Arend van Spriel wrote:
>> On 09/14/2012 11:53 PM, Stephen Warren wrote:
>>> On 09/13/2012 01:12 PM, Arend van Spriel wrote:
>>>> From: Franky Lin <frankyl@broadcom.com>
>>>>
>>>> SDIO in-band interrupt is level sensitive according to SDIO standard.
>>>> When the register interrupt handler gets called by SDIO stack it is
>>>> running in non interrupt context and expected to clear the interrupt
>>>> from the dongle. Therefore in-band and out-of-band interrupt need to
>>>> be handled differently.
>>>
>>> Tested-by: Stephen Warren <swarren@wwwdotorg.org>
>>>
>>> For reference, I took next-20120914, applied this patch series, applied
>>> a few patches from Wei Ni to set up the SDIO HW on Tegra correctly, and
>>> tested. The last time I tried this without any patches to the brcmfmac,
>>> this test caused some system instability issues. This time around, I
>>> observed no instability. I tested WPA PSK, ping (or flood ping) plus
>>> playing audio through ALSA.
>>>
>>> Is this series likely to make 3.7?
>>>
>>
>> Thanks, Stephen
>>
>> Good to hear. I suspect we are close to the 3.7 merge window, but we do
>> hope this will make it mainly for the tegra sdio issue that Wei Ni
>> raised. In general the series should resolve issues when used on
>> sdhci/mmc framework with in-band interrupt.
>>
>> Do you still need the patches from Wei Ni and are they SDIO or brcmfmac
>> related?
>
> Some patches are needed, but they're all for Tegra-specific code to
> configure the pinmux, GPIO, etc. on the Tegra SoC in order to correctly
> communicate with the SDIO port, and to enable the controller. No patches
> are required to the brcmfmac driver.
Just to be explicit here:
If this patch series (the one at the start of this email thread) makes
it into 3.7, I'll apply the Tegra patches to enable brcmfmac on Tegra
for 3.8, and everything will work out nicely.
If this patch series doesn't make it into 3.7, but gets into 3.8
instead, I'd still like to apply the Tegra patches for 3.8 as well.
However, I can't apply the Tegra patches to any branch that doesn't
include this patch series, or it'll cause system instability on Tegra.
To that end, if this patch series doesn't make 3.7, I'd like to request
that it be applied to a separate topic branch in the wireless tree, so
that it can be both merged into the wireless tree for any required
future work there, /and/ merged into the Tegra tree so that I can use it
as a baseline to enable wireless on Tegra.
Thanks!
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2012-09-17 17:37 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-13 19:11 [PATCH 00/10] brcmfmac: sdio dpc restructuring and cleanup Arend van Spriel
2012-09-13 19:11 ` [PATCH 01/10] brcmfmac: absorb brcmf_sendpkt into brcmf_netdev_start_xmit Arend van Spriel
2012-09-13 19:11 ` [PATCH 02/10] brcmfmac: remove obsolete sdio bus sleep mechanism Arend van Spriel
2012-09-13 19:11 ` [PATCH 03/10] brcmfmac: use atomic variable for interrupt pending flag Arend van Spriel
2012-09-13 19:12 ` [PATCH 04/10] brcmfmac: convert SDIO dpc implementation to workqueue Arend van Spriel
2012-09-13 19:12 ` [PATCH 05/10] brcmfmac: streamline SDIO dpc Arend van Spriel
2012-09-13 19:12 ` [PATCH 06/10] brcmfmac: raise SDIO host lock to higher level Arend van Spriel
2012-09-13 19:12 ` [PATCH 07/10] brcmfmac: clear status for in-band interrupt in brcmf_sdbrcm_isr Arend van Spriel
2012-09-14 21:53 ` Stephen Warren
2012-09-15 9:19 ` Arend van Spriel
2012-09-15 17:12 ` Stephen Warren
2012-09-17 17:37 ` Stephen Warren
2012-09-13 19:12 ` [PATCH 08/10] brcmfmac: fix bug causing errorneous free on exception Arend van Spriel
2012-09-13 19:12 ` [PATCH 09/10] brcmfmac: add parameter check in brcmf_c_mkiovar() Arend van Spriel
2012-09-13 19:12 ` [PATCH 10/10] brcmfmac: simplify handling e-scan result firmware event Arend van Spriel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).