Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 328222
b: refs/heads/master
c: 4531603
h: refs/heads/master
v: v3
  • Loading branch information
Franky Lin authored and John W. Linville committed Sep 24, 2012
1 parent f3391d4 commit fcadd12
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 34 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7057fd00da45c31a5a927a742d0f43efe4470173
refs/heads/master: 4531603a7acb1463ec0b466dcfedc6682e7a1718
2 changes: 1 addition & 1 deletion trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
97 changes: 65 additions & 32 deletions trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand All @@ -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);
}

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand All @@ -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);
}

Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit fcadd12

Please sign in to comment.