Michael Buesch wrote: > On Tuesday 04 September 2007, Larry Finger wrote: >> A crash upon booting that is caused by bcm43xx has been reported [1] and >> found to be due to a work queue being reinitialized while work on that >> queue is still pending. This fix modifies the shutdown of work queues and >> prevents periodic work from being requeued during shutdown. With this patch, >> no more crashes on reboot were observed by the original reporter. I do not >> get that particular failure on my system; however, when running a large >> number of ifdown/ifup sequences, my system would occasionally hang with the >> 'caps lock' light blinking at roughly a 1 Hz rate. In addition, there were >> infrequent failures in the firmware that resulted in 'IRQ READY TIMEOUT' >> errors. With this patch, no more of the first type of failure occur, and >> incidence of the second type is greatly reduced. >> >> [1] http://bugzilla.kernel.org/show_bug.cgi?id=8937 >> >> Signed-off-by: Larry Finger <[EMAIL PROTECTED]> >> --- >> >> Michael, >> >> The version I sent as 'RFC V2' had even more problems than the one you noted >> as it suffered from the total crash with the blinking caps lock light. This >> patch is a lot more solid. >> >> Larry >> >> >> drivers/net/wireless/bcm43xx/bcm43xx_main.c | 28 >> +++++++++++++++++++-------- >> drivers/net/wireless/bcm43xx/bcm43xx_main.h | 2 - >> drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 3 +- >> 3 files changed, 23 insertions(+), 10 deletions(-) >> >> Index: linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_main.c >> =================================================================== >> --- linux-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_main.c >> +++ linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_main.c >> @@ -3197,6 +3197,9 @@ static void bcm43xx_periodic_work_handle >> unsigned long orig_trans_start = 0; >> >> mutex_lock(&bcm->mutex); >> + /* keep from doing and rearming periodic work if shutting down */ >> + if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT) >> + goto unlock_mutex; >> if (unlikely(bcm->periodic_state % 60 == 0)) { >> /* Periodic work will take a long time, so we want it to >> * be preemtible. >> @@ -3242,14 +3245,10 @@ static void bcm43xx_periodic_work_handle >> mmiowb(); >> bcm->periodic_state++; >> spin_unlock_irqrestore(&bcm->irq_lock, flags); >> +unlock_mutex: >> mutex_unlock(&bcm->mutex); >> } >> >> -void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) >> -{ >> - cancel_rearming_delayed_work(&bcm->periodic_work); >> -} >> - >> void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) >> { >> struct delayed_work *work = &bcm->periodic_work; >> @@ -3299,6 +3298,14 @@ static int bcm43xx_rng_init(struct bcm43 >> return err; >> } >> >> +void bcm43xx_cancel_work(struct bcm43xx_private *bcm) >> +{ >> + /* The system must be unlocked when this routine is entered. >> + * If not, the next 2 steps may deadlock */ >> + cancel_work_sync(&bcm->restart_work); >> + cancel_delayed_work_sync(&bcm->periodic_work); >> +} >> + >> static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm) >> { >> int ret = 0; >> @@ -3335,7 +3342,12 @@ static void bcm43xx_free_board(struct bc >> { >> bcm43xx_rng_exit(bcm); >> bcm43xx_sysfs_unregister(bcm); >> - bcm43xx_periodic_tasks_delete(bcm); >> + >> + mutex_lock(&(bcm)->mutex); >> + bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); >> + mutex_unlock(&(bcm)->mutex); >> + >> + bcm43xx_cancel_work(bcm); >> >> mutex_lock(&(bcm)->mutex); >> bcm43xx_shutdown_all_wireless_cores(bcm); >> @@ -4030,7 +4042,7 @@ static int bcm43xx_net_stop(struct net_d >> err = bcm43xx_disable_interrupts_sync(bcm); >> assert(!err); >> bcm43xx_free_board(bcm); >> - flush_scheduled_work(); >> + bcm43xx_cancel_work(bcm); >> >> return 0; >> } >> @@ -4162,9 +4174,9 @@ static void bcm43xx_chip_reset(struct wo >> struct bcm43xx_phyinfo *phy; >> int err = -ENODEV; >> >> + bcm43xx_cancel_work(bcm); >> mutex_lock(&(bcm)->mutex); >> if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { >> - bcm43xx_periodic_tasks_delete(bcm); >> phy = bcm43xx_current_phy(bcm); >> err = bcm43xx_select_wireless_core(bcm, phy->type); >> if (!err) >> Index: linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_main.h >> =================================================================== >> --- linux-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_main.h >> +++ linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_main.h >> @@ -122,7 +122,7 @@ void bcm43xx_wireless_core_reset(struct >> void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); >> void bcm43xx_mac_enable(struct bcm43xx_private *bcm); >> >> -void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm); >> +void bcm43xx_cancel_work(struct bcm43xx_private *bcm); >> void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm); >> >> void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char >> *reason); >> Index: linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c >> =================================================================== >> --- linux-2.6.orig/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c >> +++ linux-2.6/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c >> @@ -327,8 +327,9 @@ static ssize_t bcm43xx_attr_phymode_stor >> goto out; >> } >> >> - bcm43xx_periodic_tasks_delete(bcm); >> + bcm43xx_cancel_work(bcm); >> mutex_lock(&(bcm)->mutex); >> + bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); > > No, Don't change the status. > I doubt that two many people are changing phy modes anyway. I certainly have not tested this code. As the BCM4306/2 devices are having a problem with OFDM rates, would writing a 'b' to this file limit those cards to CCCK rates? I'll have to try this one later.
Larry _______________________________________________ Bcm43xx-dev mailing list [email protected] https://lists.berlios.de/mailman/listinfo/bcm43xx-dev
