diff options
| author | Larry Finger <Larry.Finger@lwfinger.net> | 2006-10-03 00:48:54 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2006-10-16 20:09:48 -0400 |
| commit | 8da81e52b743edac0bfbb7d0c1286f919b2f209b (patch) | |
| tree | 7b55c4c8e26be4ecedcbe404139d16ae05b53e9f | |
| parent | 16bfa676a7cc64695f7e9694c380ebd26c461ae5 (diff) | |
[PATCH] bcm43xx-softmac: Fix system hang for x86-64 with >1GB RAM
The bcm43xx-softmac software currently fails when running on x86_64 systems
with more than 1GB RAM and one of the card variants with 30-bit DMA addressing.
This patch uses the address extension bits in the hardware to set the correct
DMA mask for the specific card in use.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
| -rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 28 | ||||
| -rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 17 | ||||
| -rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_main.c | 25 |
3 files changed, 46 insertions, 24 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; |
| 761 | out: | 779 | out: |
| 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..ea16078cfe98 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h | |||
| @@ -314,6 +314,23 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, | |||
| 314 | struct ieee80211_txb *txb); | 314 | struct ieee80211_txb *txb); |
| 315 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); | 315 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); |
| 316 | 316 | ||
| 317 | /* Helper function that returns the dma mask for this device. */ | ||
| 318 | static inline | ||
| 319 | u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm) | ||
| 320 | { | ||
| 321 | int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) & | ||
| 322 | BCM43xx_SBTMSTATEHIGH_DMA64BIT; | ||
| 323 | u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0); | ||
| 324 | u32 mask = BCM43xx_DMA32_TXADDREXT_MASK; | ||
| 325 | |||
| 326 | if (dma64) | ||
| 327 | return DMA_64BIT_MASK; | ||
| 328 | bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask); | ||
| 329 | if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask) | ||
| 330 | return DMA_32BIT_MASK; | ||
| 331 | return DMA_30BIT_MASK; | ||
| 332 | } | ||
| 333 | |||
| 317 | #else /* CONFIG_BCM43XX_DMA */ | 334 | #else /* CONFIG_BCM43XX_DMA */ |
| 318 | 335 | ||
| 319 | 336 | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 7776b5c42ac7..a94c6d8826f8 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c | |||
| @@ -2925,10 +2925,13 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm, | |||
| 2925 | bcm43xx_write16(bcm, 0x043C, 0x000C); | 2925 | bcm43xx_write16(bcm, 0x043C, 0x000C); |
| 2926 | 2926 | ||
| 2927 | if (active_wlcore) { | 2927 | if (active_wlcore) { |
| 2928 | if (bcm43xx_using_pio(bcm)) | 2928 | if (bcm43xx_using_pio(bcm)) { |
| 2929 | err = bcm43xx_pio_init(bcm); | 2929 | err = bcm43xx_pio_init(bcm); |
| 2930 | else | 2930 | } else { |
| 2931 | err = bcm43xx_dma_init(bcm); | 2931 | err = bcm43xx_dma_init(bcm); |
| 2932 | if (err == -ENOSYS) | ||
| 2933 | err = bcm43xx_pio_init(bcm); | ||
| 2934 | } | ||
| 2932 | if (err) | 2935 | if (err) |
| 2933 | goto err_chip_cleanup; | 2936 | goto err_chip_cleanup; |
| 2934 | } | 2937 | } |
| @@ -3992,8 +3995,6 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, | |||
| 3992 | struct net_device *net_dev, | 3995 | struct net_device *net_dev, |
| 3993 | struct pci_dev *pci_dev) | 3996 | struct pci_dev *pci_dev) |
| 3994 | { | 3997 | { |
| 3995 | int err; | ||
| 3996 | |||
| 3997 | bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); | 3998 | bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); |
| 3998 | bcm->ieee = netdev_priv(net_dev); | 3999 | bcm->ieee = netdev_priv(net_dev); |
| 3999 | bcm->softmac = ieee80211_priv(net_dev); | 4000 | bcm->softmac = ieee80211_priv(net_dev); |
| @@ -4011,22 +4012,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, | |||
| 4011 | (void (*)(unsigned long))bcm43xx_interrupt_tasklet, | 4012 | (void (*)(unsigned long))bcm43xx_interrupt_tasklet, |
| 4012 | (unsigned long)bcm); | 4013 | (unsigned long)bcm); |
| 4013 | tasklet_disable_nosync(&bcm->isr_tasklet); | 4014 | tasklet_disable_nosync(&bcm->isr_tasklet); |
| 4014 | if (modparam_pio) { | 4015 | if (modparam_pio) |
| 4015 | bcm->__using_pio = 1; | 4016 | bcm->__using_pio = 1; |
| 4016 | } else { | ||
| 4017 | err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK); | ||
| 4018 | err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK); | ||
| 4019 | if (err) { | ||
| 4020 | #ifdef CONFIG_BCM43XX_PIO | ||
| 4021 | printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n"); | ||
| 4022 | bcm->__using_pio = 1; | ||
| 4023 | #else | ||
| 4024 | printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. " | ||
| 4025 | "Recompile the driver with PIO support, please.\n"); | ||
| 4026 | return -ENODEV; | ||
| 4027 | #endif /* CONFIG_BCM43XX_PIO */ | ||
| 4028 | } | ||
| 4029 | } | ||
| 4030 | bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; | 4017 | bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; |
| 4031 | 4018 | ||
| 4032 | /* default to sw encryption for now */ | 4019 | /* default to sw encryption for now */ |
