Skip to content

Commit

Permalink
b43: Fix beacon BH update
Browse files Browse the repository at this point in the history
This fixes beacon updating in the bottomhalf.
In case the device is busy, we will defer to later in the IRQ handler.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Michael Buesch authored and John W. Linville committed Apr 8, 2008
1 parent 84363e6 commit c97a4cc
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 42 deletions.
1 change: 0 additions & 1 deletion drivers/net/wireless/b43/b43.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,6 @@ enum {

#define B43_IRQ_ALL 0xFFFFFFFF
#define B43_IRQ_MASKTEMPLATE (B43_IRQ_MAC_SUSPENDED | \
B43_IRQ_BEACON | \
B43_IRQ_TBTT_INDI | \
B43_IRQ_ATIM_END | \
B43_IRQ_PMQ | \
Expand Down
95 changes: 54 additions & 41 deletions drivers/net/wireless/b43/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1448,6 +1448,53 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
kfree(probe_resp_data);
}

static void handle_irq_beacon(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
u32 cmd, beacon0_valid, beacon1_valid;

if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
return;

/* This is the bottom half of the asynchronous beacon update. */

/* Ignore interrupt in the future. */
dev->irq_savedstate &= ~B43_IRQ_BEACON;

cmd = b43_read32(dev, B43_MMIO_MACCMD);
beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
beacon1_valid = (cmd & B43_MACCMD_BEACON1_VALID);

/* Schedule interrupt manually, if busy. */
if (beacon0_valid && beacon1_valid) {
b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
dev->irq_savedstate |= B43_IRQ_BEACON;
return;
}

if (!beacon0_valid) {
if (!wl->beacon0_uploaded) {
b43_write_beacon_template(dev, 0x68, 0x18,
B43_CCK_RATE_1MB);
b43_write_probe_resp_template(dev, 0x268, 0x4A,
&__b43_ratetable[3]);
wl->beacon0_uploaded = 1;
}
cmd = b43_read32(dev, B43_MMIO_MACCMD);
cmd |= B43_MACCMD_BEACON0_VALID;
b43_write32(dev, B43_MMIO_MACCMD, cmd);
} else if (!beacon1_valid) {
if (!wl->beacon1_uploaded) {
b43_write_beacon_template(dev, 0x468, 0x1A,
B43_CCK_RATE_1MB);
wl->beacon1_uploaded = 1;
}
cmd = b43_read32(dev, B43_MMIO_MACCMD);
cmd |= B43_MACCMD_BEACON1_VALID;
b43_write32(dev, B43_MMIO_MACCMD, cmd);
}
}

static void b43_beacon_update_trigger_work(struct work_struct *work)
{
struct b43_wl *wl = container_of(work, struct b43_wl,
Expand All @@ -1457,13 +1504,14 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
/* Force the microcode to trigger the
* beacon update bottom-half IRQ. */
spin_lock_irq(&wl->irq_lock);
b43_write32(dev, B43_MMIO_MACCMD,
b43_read32(dev, B43_MMIO_MACCMD)
| B43_MACCMD_BEACON0_VALID
| B43_MACCMD_BEACON1_VALID);
/* update beacon right away or defer to irq */
dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
handle_irq_beacon(dev);
/* The handler might have updated the IRQ mask. */
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK,
dev->irq_savedstate);
mmiowb();
spin_unlock_irq(&wl->irq_lock);
}
mutex_unlock(&wl->mutex);
Expand Down Expand Up @@ -1520,41 +1568,6 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int);
}

static void handle_irq_beacon(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
u32 cmd, beacon0_valid, beacon1_valid;

if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
return;

/* This is the bottom half of the asynchronous beacon update. */

cmd = b43_read32(dev, B43_MMIO_MACCMD);
beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
beacon1_valid = (cmd & B43_MACCMD_BEACON1_VALID);
cmd &= ~(B43_MACCMD_BEACON0_VALID | B43_MACCMD_BEACON1_VALID);

if (!beacon0_valid) {
if (!wl->beacon0_uploaded) {
b43_write_beacon_template(dev, 0x68, 0x18,
B43_CCK_RATE_1MB);
b43_write_probe_resp_template(dev, 0x268, 0x4A,
&__b43_ratetable[3]);
wl->beacon0_uploaded = 1;
}
cmd |= B43_MACCMD_BEACON0_VALID;
} else if (!beacon1_valid) {
if (!wl->beacon1_uploaded) {
b43_write_beacon_template(dev, 0x468, 0x1A,
B43_CCK_RATE_1MB);
wl->beacon1_uploaded = 1;
}
cmd |= B43_MACCMD_BEACON1_VALID;
}
b43_write32(dev, B43_MMIO_MACCMD, cmd);
}

static void handle_irq_ucode_debug(struct b43_wldev *dev)
{
//TODO
Expand Down

0 comments on commit c97a4cc

Please sign in to comment.