aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2006-06-12 11:02:22 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-07-27 18:19:02 -0400
commit062caf43d803771b660defe6b147711d8b730364 (patch)
tree5e3446bd4cedbd98f70d35f08b0b37ffc11e0bf8 /drivers
parent8f0f850e240df5bea027caeb1723142c50e37e57 (diff)
[PATCH] bcm43xx: suspend MAC while executing long pwork
Suspend MAC (and make MAC-suspend refcounting) when doing long periodic work. On long periodic work, we disable IRQs on the device, so we don't want the MAC to stay operating and probably miss packets due do non-delivery of interrupts. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h2
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c49
2 files changed, 33 insertions, 18 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index ee6571ed706d..bee84b58060c 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -737,6 +737,8 @@ struct bcm43xx_private {
737 u32 irq_savedstate; 737 u32 irq_savedstate;
738 /* Link Quality calculation context. */ 738 /* Link Quality calculation context. */
739 struct bcm43xx_noise_calculation noisecalc; 739 struct bcm43xx_noise_calculation noisecalc;
740 /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
741 int mac_suspended;
740 742
741 /* Threshold values. */ 743 /* Threshold values. */
742 //TODO: The RTS thr has to be _used_. Currently, it is only set via WX. 744 //TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index ab3a0ee9fac8..1af330d496fc 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -2298,13 +2298,17 @@ static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
2298/* http://bcm-specs.sipsolutions.net/EnableMac */ 2298/* http://bcm-specs.sipsolutions.net/EnableMac */
2299void bcm43xx_mac_enable(struct bcm43xx_private *bcm) 2299void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
2300{ 2300{
2301 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 2301 bcm->mac_suspended--;
2302 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) 2302 assert(bcm->mac_suspended >= 0);
2303 | BCM43xx_SBF_MAC_ENABLED); 2303 if (bcm->mac_suspended == 0) {
2304 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY); 2304 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2305 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ 2305 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2306 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ 2306 | BCM43xx_SBF_MAC_ENABLED);
2307 bcm43xx_power_saving_ctl_bits(bcm, -1, -1); 2307 bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
2308 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
2309 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2310 bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
2311 }
2308} 2312}
2309 2313
2310/* http://bcm-specs.sipsolutions.net/SuspendMAC */ 2314/* http://bcm-specs.sipsolutions.net/SuspendMAC */
@@ -2313,18 +2317,23 @@ void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
2313 int i; 2317 int i;
2314 u32 tmp; 2318 u32 tmp;
2315 2319
2316 bcm43xx_power_saving_ctl_bits(bcm, -1, 1); 2320 assert(bcm->mac_suspended >= 0);
2317 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 2321 if (bcm->mac_suspended == 0) {
2318 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) 2322 bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
2319 & ~BCM43xx_SBF_MAC_ENABLED); 2323 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
2320 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ 2324 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
2321 for (i = 100000; i; i--) { 2325 & ~BCM43xx_SBF_MAC_ENABLED);
2322 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); 2326 bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
2323 if (tmp & BCM43xx_IRQ_READY) 2327 for (i = 100000; i; i--) {
2324 return; 2328 tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
2325 udelay(10); 2329 if (tmp & BCM43xx_IRQ_READY)
2330 goto out;
2331 udelay(10);
2332 }
2333 printkl(KERN_ERR PFX "MAC suspend failed\n");
2326 } 2334 }
2327 printkl(KERN_ERR PFX "MAC suspend failed\n"); 2335out:
2336 bcm->mac_suspended++;
2328} 2337}
2329 2338
2330void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, 2339void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
@@ -3183,7 +3192,9 @@ static void bcm43xx_periodic_work_handler(void *d)
3183 * be preemtible. 3192 * be preemtible.
3184 */ 3193 */
3185 netif_stop_queue(bcm->net_dev); 3194 netif_stop_queue(bcm->net_dev);
3195 synchronize_net();
3186 spin_lock_irqsave(&bcm->irq_lock, flags); 3196 spin_lock_irqsave(&bcm->irq_lock, flags);
3197 bcm43xx_mac_suspend(bcm);
3187 if (bcm43xx_using_pio(bcm)) 3198 if (bcm43xx_using_pio(bcm))
3188 bcm43xx_pio_freeze_txqueues(bcm); 3199 bcm43xx_pio_freeze_txqueues(bcm);
3189 savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 3200 savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
@@ -3207,6 +3218,7 @@ static void bcm43xx_periodic_work_handler(void *d)
3207 bcm43xx_interrupt_enable(bcm, savedirqs); 3218 bcm43xx_interrupt_enable(bcm, savedirqs);
3208 if (bcm43xx_using_pio(bcm)) 3219 if (bcm43xx_using_pio(bcm))
3209 bcm43xx_pio_thaw_txqueues(bcm); 3220 bcm43xx_pio_thaw_txqueues(bcm);
3221 bcm43xx_mac_enable(bcm);
3210 } 3222 }
3211 netif_wake_queue(bcm->net_dev); 3223 netif_wake_queue(bcm->net_dev);
3212 } 3224 }
@@ -3820,6 +3832,7 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
3820 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; 3832 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
3821 3833
3822 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; 3834 bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
3835 bcm->mac_suspended = 1;
3823 bcm->pci_dev = pci_dev; 3836 bcm->pci_dev = pci_dev;
3824 bcm->net_dev = net_dev; 3837 bcm->net_dev = net_dev;
3825 bcm->bad_frames_preempt = modparam_bad_frames_preempt; 3838 bcm->bad_frames_preempt = modparam_bad_frames_preempt;