From: Michael Buesch Date: Thu, 18 Dec 2008 21:13:39 +0000 (+0100) Subject: b43: Fix some MAC locking X-Git-Tag: v2.6.29-rc1~581^2~105^2~6 X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=d10d0e5707fb7b8afa7e68a14d69e752604ee294;p=~emulex%2Finfiniband.git b43: Fix some MAC locking 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 Signed-off-by: John W. Linville --- diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ba7a5ab7fe1..07dc9886d96 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -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; diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index af37abccccb..2ebfc7d1508 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -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); } diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index 232181f6333..3b1d673796c 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c @@ -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)