diff options
author | Michael Buesch <mb@bu3sch.de> | 2008-12-18 16:13:39 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-12-19 15:23:56 -0500 |
commit | d10d0e5707fb7b8afa7e68a14d69e752604ee294 (patch) | |
tree | 796e53908137310e3467e2c15703304857fab506 /drivers/net/wireless | |
parent | 0e7690f1e9ee1e762f27678d2ea10e4c1fde3236 (diff) |
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>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/b43/main.c | 50 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_common.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_g.c | 8 |
3 files changed, 30 insertions, 44 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ba7a5ab7fe1d..07dc9886d968 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) | |||
3324 | unsigned long flags; | 3324 | unsigned long flags; |
3325 | int antenna; | 3325 | int antenna; |
3326 | int err = 0; | 3326 | int err = 0; |
3327 | u32 savedirqs; | ||
3328 | 3327 | ||
3329 | mutex_lock(&wl->mutex); | 3328 | mutex_lock(&wl->mutex); |
3330 | 3329 | ||
@@ -3335,24 +3334,14 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) | |||
3335 | dev = wl->current_dev; | 3334 | dev = wl->current_dev; |
3336 | phy = &dev->phy; | 3335 | phy = &dev->phy; |
3337 | 3336 | ||
3337 | b43_mac_suspend(dev); | ||
3338 | |||
3338 | if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) | 3339 | if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) |
3339 | b43_set_retry_limits(dev, conf->short_frame_max_tx_count, | 3340 | b43_set_retry_limits(dev, conf->short_frame_max_tx_count, |
3340 | conf->long_frame_max_tx_count); | 3341 | conf->long_frame_max_tx_count); |
3341 | changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; | 3342 | changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; |
3342 | if (!changed) | 3343 | if (!changed) |
3343 | goto out_unlock_mutex; | 3344 | goto out_mac_enable; |
3344 | |||
3345 | /* Disable IRQs while reconfiguring the device. | ||
3346 | * This makes it possible to drop the spinlock throughout | ||
3347 | * the reconfiguration process. */ | ||
3348 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3349 | if (b43_status(dev) < B43_STAT_STARTED) { | ||
3350 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3351 | goto out_unlock_mutex; | ||
3352 | } | ||
3353 | savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL); | ||
3354 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3355 | b43_synchronize_irq(dev); | ||
3356 | 3345 | ||
3357 | /* Switch to the requested channel. | 3346 | /* Switch to the requested channel. |
3358 | * The firmware takes care of races with the TX handler. */ | 3347 | * 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) | |||
3399 | } | 3388 | } |
3400 | } | 3389 | } |
3401 | 3390 | ||
3402 | spin_lock_irqsave(&wl->irq_lock, flags); | 3391 | out_mac_enable: |
3403 | b43_interrupt_enable(dev, savedirqs); | 3392 | b43_mac_enable(dev); |
3404 | mmiowb(); | 3393 | out_unlock_mutex: |
3405 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3406 | out_unlock_mutex: | ||
3407 | mutex_unlock(&wl->mutex); | 3394 | mutex_unlock(&wl->mutex); |
3408 | 3395 | ||
3409 | return err; | 3396 | return err; |
@@ -3461,27 +3448,12 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw, | |||
3461 | { | 3448 | { |
3462 | struct b43_wl *wl = hw_to_b43_wl(hw); | 3449 | struct b43_wl *wl = hw_to_b43_wl(hw); |
3463 | struct b43_wldev *dev; | 3450 | struct b43_wldev *dev; |
3464 | struct b43_phy *phy; | ||
3465 | unsigned long flags; | ||
3466 | u32 savedirqs; | ||
3467 | 3451 | ||
3468 | mutex_lock(&wl->mutex); | 3452 | mutex_lock(&wl->mutex); |
3469 | 3453 | ||
3470 | dev = wl->current_dev; | 3454 | dev = wl->current_dev; |
3471 | phy = &dev->phy; | 3455 | if (!dev || b43_status(dev) < B43_STAT_STARTED) |
3472 | |||
3473 | /* Disable IRQs while reconfiguring the device. | ||
3474 | * This makes it possible to drop the spinlock throughout | ||
3475 | * the reconfiguration process. */ | ||
3476 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3477 | if (b43_status(dev) < B43_STAT_STARTED) { | ||
3478 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3479 | goto out_unlock_mutex; | 3456 | goto out_unlock_mutex; |
3480 | } | ||
3481 | savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL); | ||
3482 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3483 | b43_synchronize_irq(dev); | ||
3484 | |||
3485 | b43_mac_suspend(dev); | 3457 | b43_mac_suspend(dev); |
3486 | 3458 | ||
3487 | if (changed & BSS_CHANGED_BASIC_RATES) | 3459 | if (changed & BSS_CHANGED_BASIC_RATES) |
@@ -3495,13 +3467,7 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw, | |||
3495 | } | 3467 | } |
3496 | 3468 | ||
3497 | b43_mac_enable(dev); | 3469 | b43_mac_enable(dev); |
3498 | 3470 | out_unlock_mutex: | |
3499 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3500 | b43_interrupt_enable(dev, savedirqs); | ||
3501 | /* XXX: why? */ | ||
3502 | mmiowb(); | ||
3503 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3504 | out_unlock_mutex: | ||
3505 | mutex_unlock(&wl->mutex); | 3471 | mutex_unlock(&wl->mutex); |
3506 | 3472 | ||
3507 | return; | 3473 | return; |
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index af37abccccb3..2ebfc7d1508b 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) | |||
178 | b43_power_saving_ctl_bits(dev, 0); | 178 | b43_power_saving_ctl_bits(dev, 0); |
179 | } | 179 | } |
180 | 180 | ||
181 | static inline void assert_mac_suspended(struct b43_wldev *dev) | ||
182 | { | ||
183 | if (!B43_DEBUG) | ||
184 | return; | ||
185 | if ((b43_status(dev) >= B43_STAT_INITIALIZED) && | ||
186 | (dev->mac_suspended <= 0)) { | ||
187 | b43dbg(dev->wl, "PHY/RADIO register access with " | ||
188 | "enabled MAC.\n"); | ||
189 | dump_stack(); | ||
190 | } | ||
191 | } | ||
192 | |||
181 | u16 b43_radio_read(struct b43_wldev *dev, u16 reg) | 193 | u16 b43_radio_read(struct b43_wldev *dev, u16 reg) |
182 | { | 194 | { |
195 | assert_mac_suspended(dev); | ||
183 | return dev->phy.ops->radio_read(dev, reg); | 196 | return dev->phy.ops->radio_read(dev, reg); |
184 | } | 197 | } |
185 | 198 | ||
186 | void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | 199 | void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value) |
187 | { | 200 | { |
201 | assert_mac_suspended(dev); | ||
188 | dev->phy.ops->radio_write(dev, reg, value); | 202 | dev->phy.ops->radio_write(dev, reg, value); |
189 | } | 203 | } |
190 | 204 | ||
@@ -208,11 +222,13 @@ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) | |||
208 | 222 | ||
209 | u16 b43_phy_read(struct b43_wldev *dev, u16 reg) | 223 | u16 b43_phy_read(struct b43_wldev *dev, u16 reg) |
210 | { | 224 | { |
225 | assert_mac_suspended(dev); | ||
211 | return dev->phy.ops->phy_read(dev, reg); | 226 | return dev->phy.ops->phy_read(dev, reg); |
212 | } | 227 | } |
213 | 228 | ||
214 | void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) | 229 | void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) |
215 | { | 230 | { |
231 | assert_mac_suspended(dev); | ||
216 | dev->phy.ops->phy_write(dev, reg, value); | 232 | dev->phy.ops->phy_write(dev, reg, value); |
217 | } | 233 | } |
218 | 234 | ||
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index 232181f6333c..3b1d673796cc 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) | |||
3047 | int rfatt, bbatt; | 3047 | int rfatt, bbatt; |
3048 | u8 tx_control; | 3048 | u8 tx_control; |
3049 | 3049 | ||
3050 | b43_mac_suspend(dev); | ||
3051 | |||
3050 | spin_lock_irq(&dev->wl->irq_lock); | 3052 | spin_lock_irq(&dev->wl->irq_lock); |
3051 | 3053 | ||
3052 | /* Calculate the new attenuation values. */ | 3054 | /* Calculate the new attenuation values. */ |
@@ -3103,6 +3105,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev) | |||
3103 | gphy->tx_control); | 3105 | gphy->tx_control); |
3104 | b43_radio_unlock(dev); | 3106 | b43_radio_unlock(dev); |
3105 | b43_phy_unlock(dev); | 3107 | b43_phy_unlock(dev); |
3108 | |||
3109 | b43_mac_enable(dev); | ||
3106 | } | 3110 | } |
3107 | 3111 | ||
3108 | static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, | 3112 | 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) | |||
3215 | struct b43_phy *phy = &dev->phy; | 3219 | struct b43_phy *phy = &dev->phy; |
3216 | struct b43_phy_g *gphy = phy->g; | 3220 | struct b43_phy_g *gphy = phy->g; |
3217 | 3221 | ||
3222 | b43_mac_suspend(dev); | ||
3218 | //TODO: update_aci_moving_average | 3223 | //TODO: update_aci_moving_average |
3219 | if (gphy->aci_enable && gphy->aci_wlan_automatic) { | 3224 | if (gphy->aci_enable && gphy->aci_wlan_automatic) { |
3220 | b43_mac_suspend(dev); | ||
3221 | if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) { | 3225 | if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) { |
3222 | if (0 /*TODO: bunch of conditions */ ) { | 3226 | if (0 /*TODO: bunch of conditions */ ) { |
3223 | phy->ops->interf_mitigation(dev, | 3227 | phy->ops->interf_mitigation(dev, |
@@ -3227,12 +3231,12 @@ static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev) | |||
3227 | if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev)) | 3231 | if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev)) |
3228 | phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); | 3232 | phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); |
3229 | } | 3233 | } |
3230 | b43_mac_enable(dev); | ||
3231 | } else if (gphy->interfmode == B43_INTERFMODE_NONWLAN && | 3234 | } else if (gphy->interfmode == B43_INTERFMODE_NONWLAN && |
3232 | phy->rev == 1) { | 3235 | phy->rev == 1) { |
3233 | //TODO: implement rev1 workaround | 3236 | //TODO: implement rev1 workaround |
3234 | } | 3237 | } |
3235 | b43_lo_g_maintanance_work(dev); | 3238 | b43_lo_g_maintanance_work(dev); |
3239 | b43_mac_enable(dev); | ||
3236 | } | 3240 | } |
3237 | 3241 | ||
3238 | static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev) | 3242 | static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev) |