aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/bcm43xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/bcm43xx')
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.c28
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.h18
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_leds.c9
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_leds.h6
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c72
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.c2
6 files changed, 102 insertions, 33 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index 76e3aed4b471..978ed099e285 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -705,11 +705,30 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
705 struct bcm43xx_dmaring *ring; 705 struct bcm43xx_dmaring *ring;
706 int err = -ENOMEM; 706 int err = -ENOMEM;
707 int dma64 = 0; 707 int dma64 = 0;
708 u32 sbtmstatehi; 708 u64 mask = bcm43xx_get_supported_dma_mask(bcm);
709 int nobits;
709 710
710 sbtmstatehi = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); 711 if (mask == DMA_64BIT_MASK) {
711 if (sbtmstatehi & BCM43xx_SBTMSTATEHIGH_DMA64BIT)
712 dma64 = 1; 712 dma64 = 1;
713 nobits = 64;
714 } else if (mask == DMA_32BIT_MASK)
715 nobits = 32;
716 else
717 nobits = 30;
718 err = pci_set_dma_mask(bcm->pci_dev, mask);
719 err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask);
720 if (err) {
721#ifdef CONFIG_BCM43XX_PIO
722 printk(KERN_WARNING PFX "DMA not supported on this device."
723 " Falling back to PIO.\n");
724 bcm->__using_pio = 1;
725 return -ENOSYS;
726#else
727 printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
728 "Please recompile the driver with PIO support.\n");
729 return -ENODEV;
730#endif /* CONFIG_BCM43XX_PIO */
731 }
713 732
714 /* setup TX DMA channels. */ 733 /* setup TX DMA channels. */
715 ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64); 734 ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
@@ -755,8 +774,7 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
755 dma->rx_ring3 = ring; 774 dma->rx_ring3 = ring;
756 } 775 }
757 776
758 dprintk(KERN_INFO PFX "%s DMA initialized\n", 777 dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits);
759 dma64 ? "64-bit" : "32-bit");
760 err = 0; 778 err = 0;
761out: 779out:
762 return err; 780 return err;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
index e04bcaddd1d0..d1105e569a41 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
@@ -4,6 +4,7 @@
4#include <linux/list.h> 4#include <linux/list.h>
5#include <linux/spinlock.h> 5#include <linux/spinlock.h>
6#include <linux/workqueue.h> 6#include <linux/workqueue.h>
7#include <linux/dma-mapping.h>
7#include <linux/linkage.h> 8#include <linux/linkage.h>
8#include <asm/atomic.h> 9#include <asm/atomic.h>
9 10
@@ -314,6 +315,23 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
314 struct ieee80211_txb *txb); 315 struct ieee80211_txb *txb);
315void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); 316void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
316 317
318/* Helper function that returns the dma mask for this device. */
319static inline
320u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm)
321{
322 int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) &
323 BCM43xx_SBTMSTATEHIGH_DMA64BIT;
324 u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0);
325 u32 mask = BCM43xx_DMA32_TXADDREXT_MASK;
326
327 if (dma64)
328 return DMA_64BIT_MASK;
329 bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask);
330 if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask)
331 return DMA_32BIT_MASK;
332 return DMA_30BIT_MASK;
333}
334
317#else /* CONFIG_BCM43XX_DMA */ 335#else /* CONFIG_BCM43XX_DMA */
318 336
319 337
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
index c3f90c8563d9..7d383a27b927 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
@@ -189,20 +189,24 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
189 case BCM43xx_LED_INACTIVE: 189 case BCM43xx_LED_INACTIVE:
190 continue; 190 continue;
191 case BCM43xx_LED_OFF: 191 case BCM43xx_LED_OFF:
192 case BCM43xx_LED_BCM4303_3:
192 break; 193 break;
193 case BCM43xx_LED_ON: 194 case BCM43xx_LED_ON:
194 turn_on = 1; 195 turn_on = 1;
195 break; 196 break;
196 case BCM43xx_LED_ACTIVITY: 197 case BCM43xx_LED_ACTIVITY:
198 case BCM43xx_LED_BCM4303_0:
197 turn_on = activity; 199 turn_on = activity;
198 break; 200 break;
199 case BCM43xx_LED_RADIO_ALL: 201 case BCM43xx_LED_RADIO_ALL:
200 turn_on = radio->enabled; 202 turn_on = radio->enabled;
201 break; 203 break;
202 case BCM43xx_LED_RADIO_A: 204 case BCM43xx_LED_RADIO_A:
205 case BCM43xx_LED_BCM4303_2:
203 turn_on = (radio->enabled && phy->type == BCM43xx_PHYTYPE_A); 206 turn_on = (radio->enabled && phy->type == BCM43xx_PHYTYPE_A);
204 break; 207 break;
205 case BCM43xx_LED_RADIO_B: 208 case BCM43xx_LED_RADIO_B:
209 case BCM43xx_LED_BCM4303_1:
206 turn_on = (radio->enabled && 210 turn_on = (radio->enabled &&
207 (phy->type == BCM43xx_PHYTYPE_B || 211 (phy->type == BCM43xx_PHYTYPE_B ||
208 phy->type == BCM43xx_PHYTYPE_G)); 212 phy->type == BCM43xx_PHYTYPE_G));
@@ -242,7 +246,7 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
242 //TODO 246 //TODO
243 break; 247 break;
244 case BCM43xx_LED_ASSOC: 248 case BCM43xx_LED_ASSOC:
245 if (bcm->softmac->associated) 249 if (bcm->softmac->associnfo.associated)
246 turn_on = 1; 250 turn_on = 1;
247 break; 251 break;
248#ifdef CONFIG_BCM43XX_DEBUG 252#ifdef CONFIG_BCM43XX_DEBUG
@@ -257,7 +261,8 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
257 continue; 261 continue;
258#endif /* CONFIG_BCM43XX_DEBUG */ 262#endif /* CONFIG_BCM43XX_DEBUG */
259 default: 263 default:
260 assert(0); 264 dprintkl(KERN_INFO PFX "Bad value in leds_update,"
265 " led->behaviour: 0x%x\n", led->behaviour);
261 }; 266 };
262 267
263 if (led->activelow) 268 if (led->activelow)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
index d3716cf3aebc..811e14a81198 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
@@ -46,6 +46,12 @@ enum { /* LED behaviour values */
46 BCM43xx_LED_TEST_BLINKSLOW, 46 BCM43xx_LED_TEST_BLINKSLOW,
47 BCM43xx_LED_TEST_BLINKMEDIUM, 47 BCM43xx_LED_TEST_BLINKMEDIUM,
48 BCM43xx_LED_TEST_BLINKFAST, 48 BCM43xx_LED_TEST_BLINKFAST,
49
50 /* Misc values for BCM4303 */
51 BCM43xx_LED_BCM4303_0 = 0x2B,
52 BCM43xx_LED_BCM4303_1 = 0x78,
53 BCM43xx_LED_BCM4303_2 = 0x2E,
54 BCM43xx_LED_BCM4303_3 = 0x19,
49}; 55};
50 56
51int bcm43xx_leds_init(struct bcm43xx_private *bcm); 57int bcm43xx_leds_init(struct bcm43xx_private *bcm);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index bad3452ea893..a1b783813d8e 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -746,7 +746,7 @@ int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
746 if (err) 746 if (err)
747 goto err_ctlreg; 747 goto err_ctlreg;
748 spromctl |= 0x10; /* SPROM WRITE enable. */ 748 spromctl |= 0x10; /* SPROM WRITE enable. */
749 bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); 749 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
750 if (err) 750 if (err)
751 goto err_ctlreg; 751 goto err_ctlreg;
752 /* We must burn lots of CPU cycles here, but that does not 752 /* We must burn lots of CPU cycles here, but that does not
@@ -768,7 +768,7 @@ int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
768 mdelay(20); 768 mdelay(20);
769 } 769 }
770 spromctl &= ~0x10; /* SPROM WRITE enable. */ 770 spromctl &= ~0x10; /* SPROM WRITE enable. */
771 bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); 771 err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
772 if (err) 772 if (err)
773 goto err_ctlreg; 773 goto err_ctlreg;
774 mdelay(500); 774 mdelay(500);
@@ -1463,6 +1463,23 @@ static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
1463 } 1463 }
1464} 1464}
1465 1465
1466static void drain_txstatus_queue(struct bcm43xx_private *bcm)
1467{
1468 u32 dummy;
1469
1470 if (bcm->current_core->rev < 5)
1471 return;
1472 /* Read all entries from the microcode TXstatus FIFO
1473 * and throw them away.
1474 */
1475 while (1) {
1476 dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
1477 if (!dummy)
1478 break;
1479 dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
1480 }
1481}
1482
1466static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) 1483static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm)
1467{ 1484{
1468 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F); 1485 bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F);
@@ -2925,10 +2942,13 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
2925 bcm43xx_write16(bcm, 0x043C, 0x000C); 2942 bcm43xx_write16(bcm, 0x043C, 0x000C);
2926 2943
2927 if (active_wlcore) { 2944 if (active_wlcore) {
2928 if (bcm43xx_using_pio(bcm)) 2945 if (bcm43xx_using_pio(bcm)) {
2929 err = bcm43xx_pio_init(bcm); 2946 err = bcm43xx_pio_init(bcm);
2930 else 2947 } else {
2931 err = bcm43xx_dma_init(bcm); 2948 err = bcm43xx_dma_init(bcm);
2949 if (err == -ENOSYS)
2950 err = bcm43xx_pio_init(bcm);
2951 }
2932 if (err) 2952 if (err)
2933 goto err_chip_cleanup; 2953 goto err_chip_cleanup;
2934 } 2954 }
@@ -3160,17 +3180,30 @@ static int estimate_periodic_work_badness(unsigned int state)
3160static void bcm43xx_periodic_work_handler(void *d) 3180static void bcm43xx_periodic_work_handler(void *d)
3161{ 3181{
3162 struct bcm43xx_private *bcm = d; 3182 struct bcm43xx_private *bcm = d;
3183 struct net_device *net_dev = bcm->net_dev;
3163 unsigned long flags; 3184 unsigned long flags;
3164 u32 savedirqs = 0; 3185 u32 savedirqs = 0;
3165 int badness; 3186 int badness;
3187 unsigned long orig_trans_start = 0;
3166 3188
3189 mutex_lock(&bcm->mutex);
3167 badness = estimate_periodic_work_badness(bcm->periodic_state); 3190 badness = estimate_periodic_work_badness(bcm->periodic_state);
3168 if (badness > BADNESS_LIMIT) { 3191 if (badness > BADNESS_LIMIT) {
3169 /* Periodic work will take a long time, so we want it to 3192 /* Periodic work will take a long time, so we want it to
3170 * be preemtible. 3193 * be preemtible.
3171 */ 3194 */
3172 mutex_lock(&bcm->mutex); 3195
3173 netif_tx_disable(bcm->net_dev); 3196 netif_tx_lock_bh(net_dev);
3197 /* We must fake a started transmission here, as we are going to
3198 * disable TX. If we wouldn't fake a TX, it would be possible to
3199 * trigger the netdev watchdog, if the last real TX is already
3200 * some time on the past (slightly less than 5secs)
3201 */
3202 orig_trans_start = net_dev->trans_start;
3203 net_dev->trans_start = jiffies;
3204 netif_stop_queue(net_dev);
3205 netif_tx_unlock_bh(net_dev);
3206
3174 spin_lock_irqsave(&bcm->irq_lock, flags); 3207 spin_lock_irqsave(&bcm->irq_lock, flags);
3175 bcm43xx_mac_suspend(bcm); 3208 bcm43xx_mac_suspend(bcm);
3176 if (bcm43xx_using_pio(bcm)) 3209 if (bcm43xx_using_pio(bcm))
@@ -3182,7 +3215,6 @@ static void bcm43xx_periodic_work_handler(void *d)
3182 /* Periodic work should take short time, so we want low 3215 /* Periodic work should take short time, so we want low
3183 * locking overhead. 3216 * locking overhead.
3184 */ 3217 */
3185 mutex_lock(&bcm->mutex);
3186 spin_lock_irqsave(&bcm->irq_lock, flags); 3218 spin_lock_irqsave(&bcm->irq_lock, flags);
3187 } 3219 }
3188 3220
@@ -3196,6 +3228,7 @@ static void bcm43xx_periodic_work_handler(void *d)
3196 bcm43xx_pio_thaw_txqueues(bcm); 3228 bcm43xx_pio_thaw_txqueues(bcm);
3197 bcm43xx_mac_enable(bcm); 3229 bcm43xx_mac_enable(bcm);
3198 netif_wake_queue(bcm->net_dev); 3230 netif_wake_queue(bcm->net_dev);
3231 net_dev->trans_start = orig_trans_start;
3199 } 3232 }
3200 mmiowb(); 3233 mmiowb();
3201 spin_unlock_irqrestore(&bcm->irq_lock, flags); 3234 spin_unlock_irqrestore(&bcm->irq_lock, flags);
@@ -3516,6 +3549,7 @@ int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
3516 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); 3549 bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
3517 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); 3550 bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
3518 bcm43xx_security_init(bcm); 3551 bcm43xx_security_init(bcm);
3552 drain_txstatus_queue(bcm);
3519 ieee80211softmac_start(bcm->net_dev); 3553 ieee80211softmac_start(bcm->net_dev);
3520 3554
3521 /* Let's go! Be careful after enabling the IRQs. 3555 /* Let's go! Be careful after enabling the IRQs.
@@ -3993,8 +4027,6 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
3993 struct net_device *net_dev, 4027 struct net_device *net_dev,
3994 struct pci_dev *pci_dev) 4028 struct pci_dev *pci_dev)
3995{ 4029{
3996 int err;
3997
3998 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); 4030 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
3999 bcm->ieee = netdev_priv(net_dev); 4031 bcm->ieee = netdev_priv(net_dev);
4000 bcm->softmac = ieee80211_priv(net_dev); 4032 bcm->softmac = ieee80211_priv(net_dev);
@@ -4012,22 +4044,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
4012 (void (*)(unsigned long))bcm43xx_interrupt_tasklet, 4044 (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
4013 (unsigned long)bcm); 4045 (unsigned long)bcm);
4014 tasklet_disable_nosync(&bcm->isr_tasklet); 4046 tasklet_disable_nosync(&bcm->isr_tasklet);
4015 if (modparam_pio) { 4047 if (modparam_pio)
4016 bcm->__using_pio = 1; 4048 bcm->__using_pio = 1;
4017 } else {
4018 err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK);
4019 err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK);
4020 if (err) {
4021#ifdef CONFIG_BCM43XX_PIO
4022 printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n");
4023 bcm->__using_pio = 1;
4024#else
4025 printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
4026 "Recompile the driver with PIO support, please.\n");
4027 return -ENODEV;
4028#endif /* CONFIG_BCM43XX_PIO */
4029 }
4030 }
4031 bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; 4049 bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
4032 4050
4033 /* default to sw encryption for now */ 4051 /* default to sw encryption for now */
@@ -4208,7 +4226,11 @@ static int bcm43xx_resume(struct pci_dev *pdev)
4208 dprintk(KERN_INFO PFX "Resuming...\n"); 4226 dprintk(KERN_INFO PFX "Resuming...\n");
4209 4227
4210 pci_set_power_state(pdev, 0); 4228 pci_set_power_state(pdev, 0);
4211 pci_enable_device(pdev); 4229 err = pci_enable_device(pdev);
4230 if (err) {
4231 printk(KERN_ERR PFX "Failure with pci_enable_device!\n");
4232 return err;
4233 }
4212 pci_restore_state(pdev); 4234 pci_restore_state(pdev);
4213 4235
4214 bcm43xx_chipset_attach(bcm); 4236 bcm43xx_chipset_attach(bcm);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index 9b7b15cf6561..d27016f8c736 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -847,7 +847,7 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d
847 unsigned long flags; 847 unsigned long flags;
848 848
849 wstats = &bcm->stats.wstats; 849 wstats = &bcm->stats.wstats;
850 if (!mac->associated) { 850 if (!mac->associnfo.associated) {
851 wstats->miss.beacon = 0; 851 wstats->miss.beacon = 0;
852// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here? 852// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
853 wstats->discard.retries = 0; 853 wstats->discard.retries = 0;