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 <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
0e7690f1e9
commit
d10d0e5707
|
@ -3324,7 +3324,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int antenna;
|
int antenna;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
u32 savedirqs;
|
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
|
@ -3335,24 +3334,14 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||||
dev = wl->current_dev;
|
dev = wl->current_dev;
|
||||||
phy = &dev->phy;
|
phy = &dev->phy;
|
||||||
|
|
||||||
|
b43_mac_suspend(dev);
|
||||||
|
|
||||||
if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
|
if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
|
||||||
b43_set_retry_limits(dev, conf->short_frame_max_tx_count,
|
b43_set_retry_limits(dev, conf->short_frame_max_tx_count,
|
||||||
conf->long_frame_max_tx_count);
|
conf->long_frame_max_tx_count);
|
||||||
changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS;
|
changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS;
|
||||||
if (!changed)
|
if (!changed)
|
||||||
goto out_unlock_mutex;
|
goto out_mac_enable;
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* Switch to the requested channel.
|
/* Switch to the requested channel.
|
||||||
* The firmware takes care of races with the TX handler. */
|
* 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);
|
out_mac_enable:
|
||||||
b43_interrupt_enable(dev, savedirqs);
|
b43_mac_enable(dev);
|
||||||
mmiowb();
|
out_unlock_mutex:
|
||||||
spin_unlock_irqrestore(&wl->irq_lock, flags);
|
|
||||||
out_unlock_mutex:
|
|
||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
|
|
||||||
return err;
|
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_wl *wl = hw_to_b43_wl(hw);
|
||||||
struct b43_wldev *dev;
|
struct b43_wldev *dev;
|
||||||
struct b43_phy *phy;
|
|
||||||
unsigned long flags;
|
|
||||||
u32 savedirqs;
|
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
dev = wl->current_dev;
|
dev = wl->current_dev;
|
||||||
phy = &dev->phy;
|
if (!dev || b43_status(dev) < B43_STAT_STARTED)
|
||||||
|
|
||||||
/* 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;
|
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);
|
b43_mac_suspend(dev);
|
||||||
|
|
||||||
if (changed & BSS_CHANGED_BASIC_RATES)
|
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);
|
b43_mac_enable(dev);
|
||||||
|
out_unlock_mutex:
|
||||||
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:
|
|
||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -178,13 +178,27 @@ void b43_phy_unlock(struct b43_wldev *dev)
|
||||||
b43_power_saving_ctl_bits(dev, 0);
|
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)
|
u16 b43_radio_read(struct b43_wldev *dev, u16 reg)
|
||||||
{
|
{
|
||||||
|
assert_mac_suspended(dev);
|
||||||
return dev->phy.ops->radio_read(dev, reg);
|
return dev->phy.ops->radio_read(dev, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
|
void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
|
||||||
{
|
{
|
||||||
|
assert_mac_suspended(dev);
|
||||||
dev->phy.ops->radio_write(dev, reg, value);
|
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)
|
u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
|
||||||
{
|
{
|
||||||
|
assert_mac_suspended(dev);
|
||||||
return dev->phy.ops->phy_read(dev, reg);
|
return dev->phy.ops->phy_read(dev, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
|
void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
|
||||||
{
|
{
|
||||||
|
assert_mac_suspended(dev);
|
||||||
dev->phy.ops->phy_write(dev, reg, value);
|
dev->phy.ops->phy_write(dev, reg, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3047,6 +3047,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
|
||||||
int rfatt, bbatt;
|
int rfatt, bbatt;
|
||||||
u8 tx_control;
|
u8 tx_control;
|
||||||
|
|
||||||
|
b43_mac_suspend(dev);
|
||||||
|
|
||||||
spin_lock_irq(&dev->wl->irq_lock);
|
spin_lock_irq(&dev->wl->irq_lock);
|
||||||
|
|
||||||
/* Calculate the new attenuation values. */
|
/* Calculate the new attenuation values. */
|
||||||
|
@ -3103,6 +3105,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
|
||||||
gphy->tx_control);
|
gphy->tx_control);
|
||||||
b43_radio_unlock(dev);
|
b43_radio_unlock(dev);
|
||||||
b43_phy_unlock(dev);
|
b43_phy_unlock(dev);
|
||||||
|
|
||||||
|
b43_mac_enable(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *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 *phy = &dev->phy;
|
||||||
struct b43_phy_g *gphy = phy->g;
|
struct b43_phy_g *gphy = phy->g;
|
||||||
|
|
||||||
|
b43_mac_suspend(dev);
|
||||||
//TODO: update_aci_moving_average
|
//TODO: update_aci_moving_average
|
||||||
if (gphy->aci_enable && gphy->aci_wlan_automatic) {
|
if (gphy->aci_enable && gphy->aci_wlan_automatic) {
|
||||||
b43_mac_suspend(dev);
|
|
||||||
if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) {
|
if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) {
|
||||||
if (0 /*TODO: bunch of conditions */ ) {
|
if (0 /*TODO: bunch of conditions */ ) {
|
||||||
phy->ops->interf_mitigation(dev,
|
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))
|
if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev))
|
||||||
phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);
|
phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);
|
||||||
}
|
}
|
||||||
b43_mac_enable(dev);
|
|
||||||
} else if (gphy->interfmode == B43_INTERFMODE_NONWLAN &&
|
} else if (gphy->interfmode == B43_INTERFMODE_NONWLAN &&
|
||||||
phy->rev == 1) {
|
phy->rev == 1) {
|
||||||
//TODO: implement rev1 workaround
|
//TODO: implement rev1 workaround
|
||||||
}
|
}
|
||||||
b43_lo_g_maintanance_work(dev);
|
b43_lo_g_maintanance_work(dev);
|
||||||
|
b43_mac_enable(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
|
static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
|
||||||
|
|
Loading…
Reference in New Issue