diff options
author | Stefano Brivio <stefano.brivio@polimi.it> | 2007-11-25 11:10:33 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 15:05:01 -0800 |
commit | 00e0b8cb74ed7c16b2bc41eb33a16eae5b6e2d5c (patch) | |
tree | d8cd9b1ecb6ad15523a35191a6c1eabaf01c04b8 | |
parent | d8be11ee95be9ec9eabfec9f635e0feac972369b (diff) |
b43: reinit on too many PHY TX errors
Restart the hardware on too many PHY TX errors. A thousand PHY TX errors
per 15 seconds means we won't be able to recover for sure.
Signed-off-by: Stefano Brivio <stefano.brivio@polimi.it>
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/b43/b43.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 17 |
2 files changed, 21 insertions, 1 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 97ea96320c7..d07b56e5ea6 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -393,6 +393,8 @@ enum { #define B43_DEFAULT_SHORT_RETRY_LIMIT 7 #define B43_DEFAULT_LONG_RETRY_LIMIT 4 +#define B43_PHY_TX_BADNESS_LIMIT 1000 + /* Max size of a security key */ #define B43_SEC_KEYSIZE 16 /* Security algorithms. */ @@ -548,6 +550,9 @@ struct b43_phy { /* OFDM address read/write caching for hardware auto-increment. */ u16 ofdm_addr; u8 ofdm_valid; /* 0: invalid, 1: read, 2: write */ + + /* PHY TX errors counter. */ + atomic_t txerr_cnt; }; /* Data structures for DMA transmission, per 80211 core. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 69c68c29dd9..084bbac0173 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1394,8 +1394,17 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev) if (unlikely(reason & B43_IRQ_MAC_TXERR)) b43err(dev->wl, "MAC transmission error\n"); - if (unlikely(reason & B43_IRQ_PHY_TXERR)) + if (unlikely(reason & B43_IRQ_PHY_TXERR)) { b43err(dev->wl, "PHY transmission error\n"); + rmb(); + if (unlikely(atomic_dec_and_test(&dev->phy.txerr_cnt))) { + atomic_set(&dev->phy.txerr_cnt, + B43_PHY_TX_BADNESS_LIMIT); + b43err(dev->wl, "Too many PHY TX errors, " + "restarting the controller\n"); + b43_controller_restart(dev, "PHY TX errors"); + } + } if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK | B43_DMAIRQ_NONFATALMASK))) { @@ -2257,6 +2266,9 @@ static int b43_chip_init(struct b43_wldev *dev) /* OFDM address caching. */ phy->ofdm_valid = 0; + /* PHY TX errors counter. */ + atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); + err = 0; b43dbg(dev->wl, "Chip initialized\n"); out: @@ -2341,6 +2353,9 @@ static void b43_periodic_every15sec(struct b43_wldev *dev) } b43_phy_xmitpower(dev); //FIXME: unless scanning? //TODO for APHY (temperature?) + + atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); + wmb(); } static void do_periodic_work(struct b43_wldev *dev) |