2009-05-14 23:21:29

by Larry Finger

[permalink] [raw]
Subject: [PATCH 2/2] b43legacy: Fix locking problem

Commit abb1d2bca0fc429c136747a64e675dd4d8906f36 introduced a locking
problem in b43legacy that caused the system to freeze upon booting.

Signed-off-by: Larry [email protected]
---

John,

This is 2.6.31 material. I hope that you do not have trouble with
this patch. While on the road, my normal method is not available.

Larry
---

Index: wireless-testing/drivers/net/wireless/b43legacy/main.c
===================================================================
--- wireless-testing.orig/drivers/net/wireless/b43legacy/main.c
+++ wireless-testing/drivers/net/wireless/b43legacy/main.c
@@ -2771,29 +2771,18 @@ static void b43legacy_op_bss_info_change
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
- struct b43legacy_phy *phy;
unsigned long flags;

mutex_lock(&wl->mutex);
- B43legacy_WARN_ON(wl->vif != vif);

dev = wl->current_dev;
- phy = &dev->phy;
-
- /* Disable IRQs while reconfiguring the device.
- * This makes it possible to drop the spinlock throughout
- * the reconfiguration process. */
- spin_lock_irqsave(&wl->irq_lock, flags);
- if (b43legacy_status(dev) < B43legacy_STAT_STARTED) {
- spin_unlock_irqrestore(&wl->irq_lock, flags);
+ if (!dev || b43legacy_status(dev) < B43legacy_STAT_STARTED)
goto out_unlock_mutex;
- }
- b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);

- if (changed & BSS_CHANGED_BSSID) {
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- b43legacy_synchronize_irq(dev);
+ B43legacy_WARN_ON(wl->vif != vif);

+ if (changed & BSS_CHANGED_BSSID) {
+ spin_lock_irqsave(&wl->irq_lock, flags);
if (conf->bssid)
memcpy(wl->bssid, conf->bssid, ETH_ALEN);
else
@@ -2831,12 +2820,6 @@ static void b43legacy_op_bss_info_change
}

b43legacy_mac_enable(dev);
-
- spin_lock_irqsave(&wl->irq_lock, flags);
- b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
- /* XXX: why? */
- mmiowb();
- spin_unlock_irqrestore(&wl->irq_lock, flags);
out_unlock_mutex:
mutex_unlock(&wl->mutex);
}