aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c28
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.h2
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c2
3 files changed, 22 insertions, 10 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index c5d6753a55ea..dfbd01eaaf34 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -3183,6 +3183,9 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work)
3183 unsigned long orig_trans_start = 0; 3183 unsigned long orig_trans_start = 0;
3184 3184
3185 mutex_lock(&bcm->mutex); 3185 mutex_lock(&bcm->mutex);
3186 /* keep from doing and rearming periodic work if shutting down */
3187 if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT)
3188 goto unlock_mutex;
3186 if (unlikely(bcm->periodic_state % 60 == 0)) { 3189 if (unlikely(bcm->periodic_state % 60 == 0)) {
3187 /* Periodic work will take a long time, so we want it to 3190 /* Periodic work will take a long time, so we want it to
3188 * be preemtible. 3191 * be preemtible.
@@ -3228,14 +3231,10 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work)
3228 mmiowb(); 3231 mmiowb();
3229 bcm->periodic_state++; 3232 bcm->periodic_state++;
3230 spin_unlock_irqrestore(&bcm->irq_lock, flags); 3233 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3234unlock_mutex:
3231 mutex_unlock(&bcm->mutex); 3235 mutex_unlock(&bcm->mutex);
3232} 3236}
3233 3237
3234void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
3235{
3236 cancel_rearming_delayed_work(&bcm->periodic_work);
3237}
3238
3239void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) 3238void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
3240{ 3239{
3241 struct delayed_work *work = &bcm->periodic_work; 3240 struct delayed_work *work = &bcm->periodic_work;
@@ -3285,6 +3284,14 @@ static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
3285 return err; 3284 return err;
3286} 3285}
3287 3286
3287void bcm43xx_cancel_work(struct bcm43xx_private *bcm)
3288{
3289 /* The system must be unlocked when this routine is entered.
3290 * If not, the next 2 steps may deadlock */
3291 cancel_work_sync(&bcm->restart_work);
3292 cancel_delayed_work_sync(&bcm->periodic_work);
3293}
3294
3288static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm) 3295static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
3289{ 3296{
3290 int ret = 0; 3297 int ret = 0;
@@ -3321,7 +3328,12 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3321{ 3328{
3322 bcm43xx_rng_exit(bcm); 3329 bcm43xx_rng_exit(bcm);
3323 bcm43xx_sysfs_unregister(bcm); 3330 bcm43xx_sysfs_unregister(bcm);
3324 bcm43xx_periodic_tasks_delete(bcm); 3331
3332 mutex_lock(&(bcm)->mutex);
3333 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
3334 mutex_unlock(&(bcm)->mutex);
3335
3336 bcm43xx_cancel_work(bcm);
3325 3337
3326 mutex_lock(&(bcm)->mutex); 3338 mutex_lock(&(bcm)->mutex);
3327 bcm43xx_shutdown_all_wireless_cores(bcm); 3339 bcm43xx_shutdown_all_wireless_cores(bcm);
@@ -4016,7 +4028,7 @@ static int bcm43xx_net_stop(struct net_device *net_dev)
4016 err = bcm43xx_disable_interrupts_sync(bcm); 4028 err = bcm43xx_disable_interrupts_sync(bcm);
4017 assert(!err); 4029 assert(!err);
4018 bcm43xx_free_board(bcm); 4030 bcm43xx_free_board(bcm);
4019 flush_scheduled_work(); 4031 bcm43xx_cancel_work(bcm);
4020 4032
4021 return 0; 4033 return 0;
4022} 4034}
@@ -4148,9 +4160,9 @@ static void bcm43xx_chip_reset(struct work_struct *work)
4148 struct bcm43xx_phyinfo *phy; 4160 struct bcm43xx_phyinfo *phy;
4149 int err = -ENODEV; 4161 int err = -ENODEV;
4150 4162
4163 bcm43xx_cancel_work(bcm);
4151 mutex_lock(&(bcm)->mutex); 4164 mutex_lock(&(bcm)->mutex);
4152 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { 4165 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
4153 bcm43xx_periodic_tasks_delete(bcm);
4154 phy = bcm43xx_current_phy(bcm); 4166 phy = bcm43xx_current_phy(bcm);
4155 err = bcm43xx_select_wireless_core(bcm, phy->type); 4167 err = bcm43xx_select_wireless_core(bcm, phy->type);
4156 if (!err) 4168 if (!err)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
index c8f3c532bab5..14cfbeb582ef 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
@@ -122,7 +122,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
122void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); 122void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
123void bcm43xx_mac_enable(struct bcm43xx_private *bcm); 123void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
124 124
125void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm); 125void bcm43xx_cancel_work(struct bcm43xx_private *bcm);
126void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm); 126void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm);
127 127
128void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); 128void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
index c71b998a3694..8ab5f93d192a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -327,7 +327,7 @@ static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
327 goto out; 327 goto out;
328 } 328 }
329 329
330 bcm43xx_periodic_tasks_delete(bcm); 330 bcm43xx_cancel_work(bcm);
331 mutex_lock(&(bcm)->mutex); 331 mutex_lock(&(bcm)->mutex);
332 err = bcm43xx_select_wireless_core(bcm, phytype); 332 err = bcm43xx_select_wireless_core(bcm, phytype);
333 if (!err) 333 if (!err)