b43: Fix some MAC locking
authorMichael Buesch <mb@bu3sch.de>
Thu, 18 Dec 2008 21:13:39 +0000 (22:13 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 19 Dec 2008 20:23:56 +0000 (15:23 -0500)
This fixes some locking w.r.t. the lower MAC (firmware).
It also removes a lot of ancient IRQ-locking that's not needed anymore.
We simply suspend the MAC. That's easier and causes less trouble.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/phy_common.c
drivers/net/wireless/b43/phy_g.c

index ba7a5ab7fe1d8f9c44bd5d961bff1b06a4eb8bda..07dc9886d9688cf473ba33ed395b048ff39c483a 100644 (file)
@@ -3324,7 +3324,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
        unsigned long flags;
        int antenna;
        int err = 0;
-       u32 savedirqs;
 
        mutex_lock(&wl->mutex);
 
@@ -3335,24 +3334,14 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
        dev = wl->current_dev;
        phy = &dev->phy;
 
+       b43_mac_suspend(dev);
+
        if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
                b43_set_retry_limits(dev, conf->short_frame_max_tx_count,
                                          conf->long_frame_max_tx_count);
        changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS;
        if (!changed)
-               goto out_unlock_mutex;
-
-       /* 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 (b43_status(dev) < B43_STAT_STARTED) {
-               spin_unlock_irqrestore(&wl->irq_lock, flags);
-               goto out_unlock_mutex;
-       }
-       savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL);
-       spin_unlock_irqrestore(&wl->irq_lock, flags);
-       b43_synchronize_irq(dev);
+               goto out_mac_enable;
 
        /* Switch to the requested channel.
         * The firmware takes care of races with the TX handler. */
@@ -3399,11 +3388,9 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
                }
        }
 
-       spin_lock_irqsave(&wl->irq_lock, flags);
-       b43_interrupt_enable(dev, savedirqs);
-       mmiowb();
-       spin_unlock_irqrestore(&wl->irq_lock, flags);
-      out_unlock_mutex:
+out_mac_enable:
+       b43_mac_enable(dev);
+out_unlock_mutex:
        mutex_unlock(&wl->mutex);
 
        return err;
@@ -3461,27 +3448,12 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev;
-       struct b43_phy *phy;
-       unsigned long flags;
-       u32 savedirqs;
 
        mutex_lock(&wl->mutex);
 
        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 (b43_status(dev) < B43_STAT_STARTED) {
-               spin_unlock_irqrestore(&wl->irq_lock, flags);
+       if (!dev || b43_status(dev) < B43_STAT_STARTED)
                goto out_unlock_mutex;
-       }
-       savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL);
-       spin_unlock_irqrestore(&wl->irq_lock, flags);
-       b43_synchronize_irq(dev);
-
        b43_mac_suspend(dev);
 
        if (changed & BSS_CHANGED_BASIC_RATES)
@@ -3495,13 +3467,7 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
        }
 
        b43_mac_enable(dev);
-
-       spin_lock_irqsave(&wl->irq_lock, flags);
-       b43_interrupt_enable(dev, savedirqs);
-       /* XXX: why? */
-       mmiowb();
-       spin_unlock_irqrestore(&wl->irq_lock, flags);
- out_unlock_mutex:
+out_unlock_mutex:
        mutex_unlock(&wl->mutex);
 
        return;
index af37abccccb39e4f3ca7f7c1bcd465ef5fc10ac1..2ebfc7d1508be1ba56464bcb39b63c58140f65cf 100644 (file)
@@ -178,13 +178,27 @@ void b43_phy_unlock(struct b43_wldev *dev)
                b43_power_saving_ctl_bits(dev, 0);
 }
 
+static inline void assert_mac_suspended(struct b43_wldev *dev)
+{
+       if (!B43_DEBUG)
+               return;
+       if ((b43_status(dev) >= B43_STAT_INITIALIZED) &&
+           (dev->mac_suspended <= 0)) {
+               b43dbg(dev->wl, "PHY/RADIO register access with "
+                      "enabled MAC.\n");
+               dump_stack();
+       }
+}
+
 u16 b43_radio_read(struct b43_wldev *dev, u16 reg)
 {
+       assert_mac_suspended(dev);
        return dev->phy.ops->radio_read(dev, reg);
 }
 
 void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
 {
+       assert_mac_suspended(dev);
        dev->phy.ops->radio_write(dev, reg, value);
 }
 
@@ -208,11 +222,13 @@ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
 
 u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
 {
+       assert_mac_suspended(dev);
        return dev->phy.ops->phy_read(dev, reg);
 }
 
 void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
 {
+       assert_mac_suspended(dev);
        dev->phy.ops->phy_write(dev, reg, value);
 }
 
index 232181f6333c453eb6d0f030c07d60da1d0f2c73..3b1d673796cccb2b3ace45ce2f43916cfe796f6c 100644 (file)
@@ -3047,6 +3047,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
        int rfatt, bbatt;
        u8 tx_control;
 
+       b43_mac_suspend(dev);
+
        spin_lock_irq(&dev->wl->irq_lock);
 
        /* Calculate the new attenuation values. */
@@ -3103,6 +3105,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
                          gphy->tx_control);
        b43_radio_unlock(dev);
        b43_phy_unlock(dev);
+
+       b43_mac_enable(dev);
 }
 
 static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
@@ -3215,9 +3219,9 @@ static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev)
        struct b43_phy *phy = &dev->phy;
        struct b43_phy_g *gphy = phy->g;
 
+       b43_mac_suspend(dev);
        //TODO: update_aci_moving_average
        if (gphy->aci_enable && gphy->aci_wlan_automatic) {
-               b43_mac_suspend(dev);
                if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) {
                        if (0 /*TODO: bunch of conditions */ ) {
                                phy->ops->interf_mitigation(dev,
@@ -3227,12 +3231,12 @@ static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev)
                           if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev))
                                phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);
                }
-               b43_mac_enable(dev);
        } else if (gphy->interfmode == B43_INTERFMODE_NONWLAN &&
                   phy->rev == 1) {
                //TODO: implement rev1 workaround
        }
        b43_lo_g_maintanance_work(dev);
+       b43_mac_enable(dev);
 }
 
 static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)