Commit ab4977f8 authored by Michael Buesch's avatar Michael Buesch Committed by John W. Linville

[PATCH] bcm43xx: rewrite and simplify the periodic task handling.

Signed-off-by: default avatarMichael Buesch <mbuesch@freenet.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent dcfd720b
...@@ -418,7 +418,6 @@ enum { ...@@ -418,7 +418,6 @@ enum {
struct net_device; struct net_device;
struct pci_dev; struct pci_dev;
struct workqueue_struct;
struct bcm43xx_dmaring; struct bcm43xx_dmaring;
struct bcm43xx_pioqueue; struct bcm43xx_pioqueue;
...@@ -706,18 +705,10 @@ struct bcm43xx_private { ...@@ -706,18 +705,10 @@ struct bcm43xx_private {
/* Interrupt Service Routine tasklet (bottom-half) */ /* Interrupt Service Routine tasklet (bottom-half) */
struct tasklet_struct isr_tasklet; struct tasklet_struct isr_tasklet;
/* Custom driver work queue. */
struct workqueue_struct *workqueue;
/* Periodic tasks */ /* Periodic tasks */
struct work_struct periodic_work0; struct timer_list periodic_tasks;
#define BCM43xx_PERIODIC_0_DELAY (HZ * 15) unsigned int periodic_state;
struct work_struct periodic_work1;
#define BCM43xx_PERIODIC_1_DELAY ((HZ * 60) + HZ / 2)
struct work_struct periodic_work2;
#define BCM43xx_PERIODIC_2_DELAY ((HZ * 120) + HZ)
struct work_struct periodic_work3;
#define BCM43xx_PERIODIC_3_DELAY ((HZ * 30) + HZ / 5)
struct work_struct restart_work; struct work_struct restart_work;
......
...@@ -2939,7 +2939,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) ...@@ -2939,7 +2939,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
core->phy->minlowsigpos[1] = 0; core->phy->minlowsigpos[1] = 0;
spin_lock_init(&core->phy->lock); spin_lock_init(&core->phy->lock);
core->radio = &bcm->radio[i]; core->radio = &bcm->radio[i];
core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
core->radio->channel = 0xFF; core->radio->channel = 0xFF;
core->radio->initial_channel = 0xFF; core->radio->initial_channel = 0xFF;
core->radio->lofcal = 0xFFFF; core->radio->lofcal = 0xFFFF;
...@@ -3261,144 +3261,104 @@ static void bcm43xx_softmac_init(struct bcm43xx_private *bcm) ...@@ -3261,144 +3261,104 @@ static void bcm43xx_softmac_init(struct bcm43xx_private *bcm)
ieee80211softmac_start(bcm->net_dev); ieee80211softmac_start(bcm->net_dev);
} }
static void bcm43xx_periodic_work0_handler(void *d) static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
{ {
struct bcm43xx_private *bcm = d; struct bcm43xx_phyinfo *phy = bcm->current_core->phy;
unsigned long flags;
//TODO: unsigned int aci_average;
spin_lock_irqsave(&bcm->lock, flags); if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2)
return;
if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) {
//FIXME: aci_average = bcm43xx_update_aci_average(bcm);
if (bcm->current_core->radio->aci_enable && bcm->current_core->radio->aci_wlan_automatic) {
bcm43xx_mac_suspend(bcm); bcm43xx_mac_suspend(bcm);
if (!bcm->current_core->radio->aci_enable && bcm43xx_phy_lo_g_measure(bcm);
1 /*FIXME: We are not scanning? */) {
/*FIXME: First add bcm43xx_update_aci_average() before
* uncommenting this: */
//if (bcm43xx_radio_aci_scan)
// bcm43xx_radio_set_interference_mitigation(bcm,
// BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
} else if (1/*FIXME*/) {
//if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm)))
// bcm43xx_radio_set_interference_mitigation(bcm,
// BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
}
bcm43xx_mac_enable(bcm); bcm43xx_mac_enable(bcm);
} else if (bcm->current_core->radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) {
if (bcm->current_core->phy->rev == 1) {
//FIXME: implement rev1 workaround
}
}
}
bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
//TODO for APHY (temperature?)
if (likely(!bcm->shutting_down)) {
queue_delayed_work(bcm->workqueue, &bcm->periodic_work0,
BCM43xx_PERIODIC_0_DELAY);
}
spin_unlock_irqrestore(&bcm->lock, flags);
} }
static void bcm43xx_periodic_work1_handler(void *d) static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm)
{ {
struct bcm43xx_private *bcm = d;
unsigned long flags;
spin_lock_irqsave(&bcm->lock, flags);
bcm43xx_phy_lo_mark_all_unused(bcm); bcm43xx_phy_lo_mark_all_unused(bcm);
if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
bcm43xx_mac_suspend(bcm); bcm43xx_mac_suspend(bcm);
bcm43xx_calc_nrssi_slope(bcm); bcm43xx_calc_nrssi_slope(bcm);
bcm43xx_mac_enable(bcm); bcm43xx_mac_enable(bcm);
} }
if (likely(!bcm->shutting_down)) {
queue_delayed_work(bcm->workqueue, &bcm->periodic_work1,
BCM43xx_PERIODIC_1_DELAY);
}
spin_unlock_irqrestore(&bcm->lock, flags);
} }
static void bcm43xx_periodic_work2_handler(void *d) static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm)
{ {
struct bcm43xx_private *bcm = d; /* Update device statistics. */
unsigned long flags; bcm43xx_calculate_link_quality(bcm);
}
spin_lock_irqsave(&bcm->lock, flags);
assert(bcm->current_core->phy->type == BCM43xx_PHYTYPE_G); static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
assert(bcm->current_core->phy->rev >= 2); {
struct bcm43xx_phyinfo *phy = bcm->current_core->phy;
struct bcm43xx_radioinfo *radio = bcm->current_core->radio;
if (phy->type == BCM43xx_PHYTYPE_G) {
//TODO: update_aci_moving_average
if (radio->aci_enable && radio->aci_wlan_automatic) {
bcm43xx_mac_suspend(bcm); bcm43xx_mac_suspend(bcm);
bcm43xx_phy_lo_g_measure(bcm); if (!radio->aci_enable && 1 /*TODO: not scanning? */) {
if (0 /*TODO: bunch of conditions*/) {
bcm43xx_radio_set_interference_mitigation(bcm,
BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
}
} else if (1/*TODO*/) {
/*
if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) {
bcm43xx_radio_set_interference_mitigation(bcm,
BCM43xx_RADIO_INTERFMODE_NONE);
}
*/
}
bcm43xx_mac_enable(bcm); bcm43xx_mac_enable(bcm);
} else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN &&
if (likely(!bcm->shutting_down)) { phy->rev == 1) {
queue_delayed_work(bcm->workqueue, &bcm->periodic_work2, //TODO: implement rev1 workaround
BCM43xx_PERIODIC_2_DELAY);
} }
spin_unlock_irqrestore(&bcm->lock, flags); }
bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
//TODO for APHY (temperature?)
} }
static void bcm43xx_periodic_work3_handler(void *d) static void bcm43xx_periodic_task_handler(unsigned long d)
{ {
struct bcm43xx_private *bcm = d; struct bcm43xx_private *bcm = (struct bcm43xx_private *)d;
unsigned long flags; unsigned long flags;
unsigned int state;
spin_lock_irqsave(&bcm->lock, flags); spin_lock_irqsave(&bcm->lock, flags);
/* Update device statistics. */ assert(bcm->initialized);
bcm43xx_calculate_link_quality(bcm); state = bcm->periodic_state;
if (state % 8 == 0)
bcm43xx_periodic_every120sec(bcm);
if (state % 4 == 0)
bcm43xx_periodic_every60sec(bcm);
if (state % 2 == 0)
bcm43xx_periodic_every30sec(bcm);
bcm43xx_periodic_every15sec(bcm);
bcm->periodic_state = state + 1;
mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15));
if (likely(!bcm->shutting_down)) {
queue_delayed_work(bcm->workqueue, &bcm->periodic_work3,
BCM43xx_PERIODIC_3_DELAY);
}
spin_unlock_irqrestore(&bcm->lock, flags); spin_unlock_irqrestore(&bcm->lock, flags);
} }
/* Delete all periodic tasks and make
* sure they are not running any longer
*/
static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
{ {
cancel_delayed_work(&bcm->periodic_work0); del_timer_sync(&bcm->periodic_tasks);
cancel_delayed_work(&bcm->periodic_work1);
cancel_delayed_work(&bcm->periodic_work2);
cancel_delayed_work(&bcm->periodic_work3);
flush_workqueue(bcm->workqueue);
} }
/* Setup all periodic tasks. */
static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
{ {
INIT_WORK(&bcm->periodic_work0, bcm43xx_periodic_work0_handler, bcm); struct timer_list *timer = &(bcm->periodic_tasks);
INIT_WORK(&bcm->periodic_work1, bcm43xx_periodic_work1_handler, bcm);
INIT_WORK(&bcm->periodic_work2, bcm43xx_periodic_work2_handler, bcm);
INIT_WORK(&bcm->periodic_work3, bcm43xx_periodic_work3_handler, bcm);
/* Periodic task 0: Delay ~15sec */ setup_timer(timer,
queue_delayed_work(bcm->workqueue, &bcm->periodic_work0, bcm43xx_periodic_task_handler,
BCM43xx_PERIODIC_0_DELAY); (unsigned long)bcm);
timer->expires = jiffies;
/* Periodic task 1: Delay ~60sec */ add_timer(timer);
queue_delayed_work(bcm->workqueue, &bcm->periodic_work1,
BCM43xx_PERIODIC_1_DELAY);
/* Periodic task 2: Delay ~120sec */
if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G &&
bcm->current_core->phy->rev >= 2) {
queue_delayed_work(bcm->workqueue, &bcm->periodic_work2,
BCM43xx_PERIODIC_2_DELAY);
}
/* Periodic task 3: Delay ~30sec */
queue_delayed_work(bcm->workqueue, &bcm->periodic_work3,
BCM43xx_PERIODIC_3_DELAY);
} }
static void bcm43xx_security_init(struct bcm43xx_private *bcm) static void bcm43xx_security_init(struct bcm43xx_private *bcm)
...@@ -3414,13 +3374,13 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) ...@@ -3414,13 +3374,13 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm)
int i, err; int i, err;
unsigned long flags; unsigned long flags;
bcm43xx_periodic_tasks_delete(bcm);
spin_lock_irqsave(&bcm->lock, flags); spin_lock_irqsave(&bcm->lock, flags);
bcm->initialized = 0; bcm->initialized = 0;
bcm->shutting_down = 1; bcm->shutting_down = 1;
spin_unlock_irqrestore(&bcm->lock, flags); spin_unlock_irqrestore(&bcm->lock, flags);
bcm43xx_periodic_tasks_delete(bcm);
for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE)) if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE))
continue; continue;
...@@ -4163,13 +4123,11 @@ static int bcm43xx_net_stop(struct net_device *net_dev) ...@@ -4163,13 +4123,11 @@ static int bcm43xx_net_stop(struct net_device *net_dev)
static int bcm43xx_init_private(struct bcm43xx_private *bcm, static int bcm43xx_init_private(struct bcm43xx_private *bcm,
struct net_device *net_dev, struct net_device *net_dev,
struct pci_dev *pci_dev, struct pci_dev *pci_dev)
struct workqueue_struct *wq)
{ {
bcm->ieee = netdev_priv(net_dev); bcm->ieee = netdev_priv(net_dev);
bcm->softmac = ieee80211_priv(net_dev); bcm->softmac = ieee80211_priv(net_dev);
bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
bcm->workqueue = wq;
#ifdef DEBUG_ENABLE_MMIO_PRINT #ifdef DEBUG_ENABLE_MMIO_PRINT
bcm43xx_mmioprint_initial(bcm, 1); bcm43xx_mmioprint_initial(bcm, 1);
...@@ -4226,7 +4184,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, ...@@ -4226,7 +4184,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
{ {
struct net_device *net_dev; struct net_device *net_dev;
struct bcm43xx_private *bcm; struct bcm43xx_private *bcm;
struct workqueue_struct *wq;
int err; int err;
#ifdef CONFIG_BCM947XX #ifdef CONFIG_BCM947XX
...@@ -4265,20 +4222,15 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, ...@@ -4265,20 +4222,15 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
/* initialize the bcm43xx_private struct */ /* initialize the bcm43xx_private struct */
bcm = bcm43xx_priv(net_dev); bcm = bcm43xx_priv(net_dev);
memset(bcm, 0, sizeof(*bcm)); memset(bcm, 0, sizeof(*bcm));
wq = create_workqueue(KBUILD_MODNAME "_wq"); err = bcm43xx_init_private(bcm, net_dev, pdev);
if (!wq) {
err = -ENOMEM;
goto err_free_netdev;
}
err = bcm43xx_init_private(bcm, net_dev, pdev, wq);
if (err) if (err)
goto err_destroy_wq; goto err_free_netdev;
pci_set_drvdata(pdev, net_dev); pci_set_drvdata(pdev, net_dev);
err = bcm43xx_attach_board(bcm); err = bcm43xx_attach_board(bcm);
if (err) if (err)
goto err_destroy_wq; goto err_free_netdev;
err = register_netdev(net_dev); err = register_netdev(net_dev);
if (err) { if (err) {
...@@ -4296,8 +4248,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, ...@@ -4296,8 +4248,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
err_detach_board: err_detach_board:
bcm43xx_detach_board(bcm); bcm43xx_detach_board(bcm);
err_destroy_wq:
destroy_workqueue(wq);
err_free_netdev: err_free_netdev:
free_ieee80211softmac(net_dev); free_ieee80211softmac(net_dev);
goto out; goto out;
...@@ -4312,7 +4262,6 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) ...@@ -4312,7 +4262,6 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
unregister_netdev(net_dev); unregister_netdev(net_dev);
bcm43xx_detach_board(bcm); bcm43xx_detach_board(bcm);
assert(bcm->ucode == NULL); assert(bcm->ucode == NULL);
destroy_workqueue(bcm->workqueue);
free_ieee80211softmac(net_dev); free_ieee80211softmac(net_dev);
} }
...@@ -4324,7 +4273,6 @@ static void bcm43xx_chip_reset(void *_bcm) ...@@ -4324,7 +4273,6 @@ static void bcm43xx_chip_reset(void *_bcm)
struct bcm43xx_private *bcm = _bcm; struct bcm43xx_private *bcm = _bcm;
struct net_device *net_dev = bcm->net_dev; struct net_device *net_dev = bcm->net_dev;
struct pci_dev *pci_dev = bcm->pci_dev; struct pci_dev *pci_dev = bcm->pci_dev;
struct workqueue_struct *wq = bcm->workqueue;
int err; int err;
int was_initialized = bcm->initialized; int was_initialized = bcm->initialized;
...@@ -4336,7 +4284,7 @@ static void bcm43xx_chip_reset(void *_bcm) ...@@ -4336,7 +4284,7 @@ static void bcm43xx_chip_reset(void *_bcm)
bcm43xx_free_board(bcm); bcm43xx_free_board(bcm);
bcm->firmware_norelease = 0; bcm->firmware_norelease = 0;
bcm43xx_detach_board(bcm); bcm43xx_detach_board(bcm);
err = bcm43xx_init_private(bcm, net_dev, pci_dev, wq); err = bcm43xx_init_private(bcm, net_dev, pci_dev);
if (err) if (err)
goto failure; goto failure;
err = bcm43xx_attach_board(bcm); err = bcm43xx_attach_board(bcm);
...@@ -4364,7 +4312,7 @@ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) ...@@ -4364,7 +4312,7 @@ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
queue_work(bcm->workqueue, &bcm->restart_work); schedule_work(&bcm->restart_work);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment