aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichael Buesch <mbuesch@freenet.de>2006-02-12 16:40:39 -0500
committerJohn W. Linville <linville@tuxdriver.com>2006-03-27 11:18:35 -0500
commitab4977f881fc23cb02ef6f20d1e8ebbdcfef75ad (patch)
tree3889653e5a05fb129fd5b185eb6b192f5b356804 /drivers
parentdcfd720bd733544606b053e8e68b7419211ace72 (diff)
[PATCH] bcm43xx: rewrite and simplify the periodic task handling.
Signed-off-by: Michael Buesch <mbuesch@freenet.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h13
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c194
2 files changed, 73 insertions, 134 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 3d8ac7e952cc..99b2e72281ea 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -418,7 +418,6 @@ enum {
418 418
419struct net_device; 419struct net_device;
420struct pci_dev; 420struct pci_dev;
421struct workqueue_struct;
422struct bcm43xx_dmaring; 421struct bcm43xx_dmaring;
423struct bcm43xx_pioqueue; 422struct bcm43xx_pioqueue;
424 423
@@ -706,18 +705,10 @@ struct bcm43xx_private {
706 705
707 /* Interrupt Service Routine tasklet (bottom-half) */ 706 /* Interrupt Service Routine tasklet (bottom-half) */
708 struct tasklet_struct isr_tasklet; 707 struct tasklet_struct isr_tasklet;
709 /* Custom driver work queue. */
710 struct workqueue_struct *workqueue;
711 708
712 /* Periodic tasks */ 709 /* Periodic tasks */
713 struct work_struct periodic_work0; 710 struct timer_list periodic_tasks;
714#define BCM43xx_PERIODIC_0_DELAY (HZ * 15) 711 unsigned int periodic_state;
715 struct work_struct periodic_work1;
716#define BCM43xx_PERIODIC_1_DELAY ((HZ * 60) + HZ / 2)
717 struct work_struct periodic_work2;
718#define BCM43xx_PERIODIC_2_DELAY ((HZ * 120) + HZ)
719 struct work_struct periodic_work3;
720#define BCM43xx_PERIODIC_3_DELAY ((HZ * 30) + HZ / 5)
721 712
722 struct work_struct restart_work; 713 struct work_struct restart_work;
723 714
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index fbf931d4a135..18152b0b2dd5 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -2939,7 +2939,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
2939 core->phy->minlowsigpos[1] = 0; 2939 core->phy->minlowsigpos[1] = 0;
2940 spin_lock_init(&core->phy->lock); 2940 spin_lock_init(&core->phy->lock);
2941 core->radio = &bcm->radio[i]; 2941 core->radio = &bcm->radio[i];
2942 core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; 2942 core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
2943 core->radio->channel = 0xFF; 2943 core->radio->channel = 0xFF;
2944 core->radio->initial_channel = 0xFF; 2944 core->radio->initial_channel = 0xFF;
2945 core->radio->lofcal = 0xFFFF; 2945 core->radio->lofcal = 0xFFFF;
@@ -3261,144 +3261,104 @@ static void bcm43xx_softmac_init(struct bcm43xx_private *bcm)
3261 ieee80211softmac_start(bcm->net_dev); 3261 ieee80211softmac_start(bcm->net_dev);
3262} 3262}
3263 3263
3264static void bcm43xx_periodic_work0_handler(void *d) 3264static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
3265{ 3265{
3266 struct bcm43xx_private *bcm = d; 3266 struct bcm43xx_phyinfo *phy = bcm->current_core->phy;
3267 unsigned long flags;
3268 //TODO: unsigned int aci_average;
3269
3270 spin_lock_irqsave(&bcm->lock, flags);
3271 3267
3272 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { 3268 if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2)
3273 //FIXME: aci_average = bcm43xx_update_aci_average(bcm); 3269 return;
3274 if (bcm->current_core->radio->aci_enable && bcm->current_core->radio->aci_wlan_automatic) {
3275 bcm43xx_mac_suspend(bcm);
3276 if (!bcm->current_core->radio->aci_enable &&
3277 1 /*FIXME: We are not scanning? */) {
3278 /*FIXME: First add bcm43xx_update_aci_average() before
3279 * uncommenting this: */
3280 //if (bcm43xx_radio_aci_scan)
3281 // bcm43xx_radio_set_interference_mitigation(bcm,
3282 // BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
3283 } else if (1/*FIXME*/) {
3284 //if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm)))
3285 // bcm43xx_radio_set_interference_mitigation(bcm,
3286 // BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
3287 }
3288 bcm43xx_mac_enable(bcm);
3289 } else if (bcm->current_core->radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) {
3290 if (bcm->current_core->phy->rev == 1) {
3291 //FIXME: implement rev1 workaround
3292 }
3293 }
3294 }
3295 bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
3296 //TODO for APHY (temperature?)
3297 3270
3298 if (likely(!bcm->shutting_down)) { 3271 bcm43xx_mac_suspend(bcm);
3299 queue_delayed_work(bcm->workqueue, &bcm->periodic_work0, 3272 bcm43xx_phy_lo_g_measure(bcm);
3300 BCM43xx_PERIODIC_0_DELAY); 3273 bcm43xx_mac_enable(bcm);
3301 }
3302 spin_unlock_irqrestore(&bcm->lock, flags);
3303} 3274}
3304 3275
3305static void bcm43xx_periodic_work1_handler(void *d) 3276static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm)
3306{ 3277{
3307 struct bcm43xx_private *bcm = d;
3308 unsigned long flags;
3309
3310 spin_lock_irqsave(&bcm->lock, flags);
3311
3312 bcm43xx_phy_lo_mark_all_unused(bcm); 3278 bcm43xx_phy_lo_mark_all_unused(bcm);
3313 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { 3279 if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
3314 bcm43xx_mac_suspend(bcm); 3280 bcm43xx_mac_suspend(bcm);
3315 bcm43xx_calc_nrssi_slope(bcm); 3281 bcm43xx_calc_nrssi_slope(bcm);
3316 bcm43xx_mac_enable(bcm); 3282 bcm43xx_mac_enable(bcm);
3317 } 3283 }
3318
3319 if (likely(!bcm->shutting_down)) {
3320 queue_delayed_work(bcm->workqueue, &bcm->periodic_work1,
3321 BCM43xx_PERIODIC_1_DELAY);
3322 }
3323 spin_unlock_irqrestore(&bcm->lock, flags);
3324} 3284}
3325 3285
3326static void bcm43xx_periodic_work2_handler(void *d) 3286static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm)
3327{ 3287{
3328 struct bcm43xx_private *bcm = d; 3288 /* Update device statistics. */
3329 unsigned long flags; 3289 bcm43xx_calculate_link_quality(bcm);
3330 3290}
3331 spin_lock_irqsave(&bcm->lock, flags);
3332
3333 assert(bcm->current_core->phy->type == BCM43xx_PHYTYPE_G);
3334 assert(bcm->current_core->phy->rev >= 2);
3335 3291
3336 bcm43xx_mac_suspend(bcm); 3292static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
3337 bcm43xx_phy_lo_g_measure(bcm); 3293{
3338 bcm43xx_mac_enable(bcm); 3294 struct bcm43xx_phyinfo *phy = bcm->current_core->phy;
3295 struct bcm43xx_radioinfo *radio = bcm->current_core->radio;
3339 3296
3340 if (likely(!bcm->shutting_down)) { 3297 if (phy->type == BCM43xx_PHYTYPE_G) {
3341 queue_delayed_work(bcm->workqueue, &bcm->periodic_work2, 3298 //TODO: update_aci_moving_average
3342 BCM43xx_PERIODIC_2_DELAY); 3299 if (radio->aci_enable && radio->aci_wlan_automatic) {
3300 bcm43xx_mac_suspend(bcm);
3301 if (!radio->aci_enable && 1 /*TODO: not scanning? */) {
3302 if (0 /*TODO: bunch of conditions*/) {
3303 bcm43xx_radio_set_interference_mitigation(bcm,
3304 BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
3305 }
3306 } else if (1/*TODO*/) {
3307 /*
3308 if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) {
3309 bcm43xx_radio_set_interference_mitigation(bcm,
3310 BCM43xx_RADIO_INTERFMODE_NONE);
3311 }
3312 */
3313 }
3314 bcm43xx_mac_enable(bcm);
3315 } else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN &&
3316 phy->rev == 1) {
3317 //TODO: implement rev1 workaround
3318 }
3343 } 3319 }
3344 spin_unlock_irqrestore(&bcm->lock, flags); 3320 bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
3321 //TODO for APHY (temperature?)
3345} 3322}
3346 3323
3347static void bcm43xx_periodic_work3_handler(void *d) 3324static void bcm43xx_periodic_task_handler(unsigned long d)
3348{ 3325{
3349 struct bcm43xx_private *bcm = d; 3326 struct bcm43xx_private *bcm = (struct bcm43xx_private *)d;
3350 unsigned long flags; 3327 unsigned long flags;
3328 unsigned int state;
3351 3329
3352 spin_lock_irqsave(&bcm->lock, flags); 3330 spin_lock_irqsave(&bcm->lock, flags);
3353 3331
3354 /* Update device statistics. */ 3332 assert(bcm->initialized);
3355 bcm43xx_calculate_link_quality(bcm); 3333 state = bcm->periodic_state;
3334 if (state % 8 == 0)
3335 bcm43xx_periodic_every120sec(bcm);
3336 if (state % 4 == 0)
3337 bcm43xx_periodic_every60sec(bcm);
3338 if (state % 2 == 0)
3339 bcm43xx_periodic_every30sec(bcm);
3340 bcm43xx_periodic_every15sec(bcm);
3341 bcm->periodic_state = state + 1;
3342
3343 mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15));
3356 3344
3357 if (likely(!bcm->shutting_down)) {
3358 queue_delayed_work(bcm->workqueue, &bcm->periodic_work3,
3359 BCM43xx_PERIODIC_3_DELAY);
3360 }
3361 spin_unlock_irqrestore(&bcm->lock, flags); 3345 spin_unlock_irqrestore(&bcm->lock, flags);
3362} 3346}
3363 3347
3364/* Delete all periodic tasks and make
3365 * sure they are not running any longer
3366 */
3367static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) 3348static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
3368{ 3349{
3369 cancel_delayed_work(&bcm->periodic_work0); 3350 del_timer_sync(&bcm->periodic_tasks);
3370 cancel_delayed_work(&bcm->periodic_work1);
3371 cancel_delayed_work(&bcm->periodic_work2);
3372 cancel_delayed_work(&bcm->periodic_work3);
3373 flush_workqueue(bcm->workqueue);
3374} 3351}
3375 3352
3376/* Setup all periodic tasks. */
3377static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) 3353static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
3378{ 3354{
3379 INIT_WORK(&bcm->periodic_work0, bcm43xx_periodic_work0_handler, bcm); 3355 struct timer_list *timer = &(bcm->periodic_tasks);
3380 INIT_WORK(&bcm->periodic_work1, bcm43xx_periodic_work1_handler, bcm);
3381 INIT_WORK(&bcm->periodic_work2, bcm43xx_periodic_work2_handler, bcm);
3382 INIT_WORK(&bcm->periodic_work3, bcm43xx_periodic_work3_handler, bcm);
3383
3384 /* Periodic task 0: Delay ~15sec */
3385 queue_delayed_work(bcm->workqueue, &bcm->periodic_work0,
3386 BCM43xx_PERIODIC_0_DELAY);
3387
3388 /* Periodic task 1: Delay ~60sec */
3389 queue_delayed_work(bcm->workqueue, &bcm->periodic_work1,
3390 BCM43xx_PERIODIC_1_DELAY);
3391 3356
3392 /* Periodic task 2: Delay ~120sec */ 3357 setup_timer(timer,
3393 if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && 3358 bcm43xx_periodic_task_handler,
3394 bcm->current_core->phy->rev >= 2) { 3359 (unsigned long)bcm);
3395 queue_delayed_work(bcm->workqueue, &bcm->periodic_work2, 3360 timer->expires = jiffies;
3396 BCM43xx_PERIODIC_2_DELAY); 3361 add_timer(timer);
3397 }
3398
3399 /* Periodic task 3: Delay ~30sec */
3400 queue_delayed_work(bcm->workqueue, &bcm->periodic_work3,
3401 BCM43xx_PERIODIC_3_DELAY);
3402} 3362}
3403 3363
3404static void bcm43xx_security_init(struct bcm43xx_private *bcm) 3364static void bcm43xx_security_init(struct bcm43xx_private *bcm)
@@ -3414,13 +3374,13 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3414 int i, err; 3374 int i, err;
3415 unsigned long flags; 3375 unsigned long flags;
3416 3376
3377 bcm43xx_periodic_tasks_delete(bcm);
3378
3417 spin_lock_irqsave(&bcm->lock, flags); 3379 spin_lock_irqsave(&bcm->lock, flags);
3418 bcm->initialized = 0; 3380 bcm->initialized = 0;
3419 bcm->shutting_down = 1; 3381 bcm->shutting_down = 1;
3420 spin_unlock_irqrestore(&bcm->lock, flags); 3382 spin_unlock_irqrestore(&bcm->lock, flags);
3421 3383
3422 bcm43xx_periodic_tasks_delete(bcm);
3423
3424 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { 3384 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3425 if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE)) 3385 if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE))
3426 continue; 3386 continue;
@@ -4163,13 +4123,11 @@ static int bcm43xx_net_stop(struct net_device *net_dev)
4163 4123
4164static int bcm43xx_init_private(struct bcm43xx_private *bcm, 4124static int bcm43xx_init_private(struct bcm43xx_private *bcm,
4165 struct net_device *net_dev, 4125 struct net_device *net_dev,
4166 struct pci_dev *pci_dev, 4126 struct pci_dev *pci_dev)
4167 struct workqueue_struct *wq)
4168{ 4127{
4169 bcm->ieee = netdev_priv(net_dev); 4128 bcm->ieee = netdev_priv(net_dev);
4170 bcm->softmac = ieee80211_priv(net_dev); 4129 bcm->softmac = ieee80211_priv(net_dev);
4171 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; 4130 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
4172 bcm->workqueue = wq;
4173 4131
4174#ifdef DEBUG_ENABLE_MMIO_PRINT 4132#ifdef DEBUG_ENABLE_MMIO_PRINT
4175 bcm43xx_mmioprint_initial(bcm, 1); 4133 bcm43xx_mmioprint_initial(bcm, 1);
@@ -4226,7 +4184,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
4226{ 4184{
4227 struct net_device *net_dev; 4185 struct net_device *net_dev;
4228 struct bcm43xx_private *bcm; 4186 struct bcm43xx_private *bcm;
4229 struct workqueue_struct *wq;
4230 int err; 4187 int err;
4231 4188
4232#ifdef CONFIG_BCM947XX 4189#ifdef CONFIG_BCM947XX
@@ -4265,20 +4222,15 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
4265 /* initialize the bcm43xx_private struct */ 4222 /* initialize the bcm43xx_private struct */
4266 bcm = bcm43xx_priv(net_dev); 4223 bcm = bcm43xx_priv(net_dev);
4267 memset(bcm, 0, sizeof(*bcm)); 4224 memset(bcm, 0, sizeof(*bcm));
4268 wq = create_workqueue(KBUILD_MODNAME "_wq"); 4225 err = bcm43xx_init_private(bcm, net_dev, pdev);
4269 if (!wq) {
4270 err = -ENOMEM;
4271 goto err_free_netdev;
4272 }
4273 err = bcm43xx_init_private(bcm, net_dev, pdev, wq);
4274 if (err) 4226 if (err)
4275 goto err_destroy_wq; 4227 goto err_free_netdev;
4276 4228
4277 pci_set_drvdata(pdev, net_dev); 4229 pci_set_drvdata(pdev, net_dev);
4278 4230
4279 err = bcm43xx_attach_board(bcm); 4231 err = bcm43xx_attach_board(bcm);
4280 if (err) 4232 if (err)
4281 goto err_destroy_wq; 4233 goto err_free_netdev;
4282 4234
4283 err = register_netdev(net_dev); 4235 err = register_netdev(net_dev);
4284 if (err) { 4236 if (err) {
@@ -4296,8 +4248,6 @@ out:
4296 4248
4297err_detach_board: 4249err_detach_board:
4298 bcm43xx_detach_board(bcm); 4250 bcm43xx_detach_board(bcm);
4299err_destroy_wq:
4300 destroy_workqueue(wq);
4301err_free_netdev: 4251err_free_netdev:
4302 free_ieee80211softmac(net_dev); 4252 free_ieee80211softmac(net_dev);
4303 goto out; 4253 goto out;
@@ -4312,7 +4262,6 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
4312 unregister_netdev(net_dev); 4262 unregister_netdev(net_dev);
4313 bcm43xx_detach_board(bcm); 4263 bcm43xx_detach_board(bcm);
4314 assert(bcm->ucode == NULL); 4264 assert(bcm->ucode == NULL);
4315 destroy_workqueue(bcm->workqueue);
4316 free_ieee80211softmac(net_dev); 4265 free_ieee80211softmac(net_dev);
4317} 4266}
4318 4267
@@ -4324,7 +4273,6 @@ static void bcm43xx_chip_reset(void *_bcm)
4324 struct bcm43xx_private *bcm = _bcm; 4273 struct bcm43xx_private *bcm = _bcm;
4325 struct net_device *net_dev = bcm->net_dev; 4274 struct net_device *net_dev = bcm->net_dev;
4326 struct pci_dev *pci_dev = bcm->pci_dev; 4275 struct pci_dev *pci_dev = bcm->pci_dev;
4327 struct workqueue_struct *wq = bcm->workqueue;
4328 int err; 4276 int err;
4329 int was_initialized = bcm->initialized; 4277 int was_initialized = bcm->initialized;
4330 4278
@@ -4336,7 +4284,7 @@ static void bcm43xx_chip_reset(void *_bcm)
4336 bcm43xx_free_board(bcm); 4284 bcm43xx_free_board(bcm);
4337 bcm->firmware_norelease = 0; 4285 bcm->firmware_norelease = 0;
4338 bcm43xx_detach_board(bcm); 4286 bcm43xx_detach_board(bcm);
4339 err = bcm43xx_init_private(bcm, net_dev, pci_dev, wq); 4287 err = bcm43xx_init_private(bcm, net_dev, pci_dev);
4340 if (err) 4288 if (err)
4341 goto failure; 4289 goto failure;
4342 err = bcm43xx_attach_board(bcm); 4290 err = bcm43xx_attach_board(bcm);
@@ -4364,7 +4312,7 @@ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
4364 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 4312 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
4365 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); 4313 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
4366 INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); 4314 INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
4367 queue_work(bcm->workqueue, &bcm->restart_work); 4315 schedule_work(&bcm->restart_work);
4368} 4316}
4369 4317
4370#ifdef CONFIG_PM 4318#ifdef CONFIG_PM