Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8da81e52 authored by Larry Finger's avatar Larry Finger Committed by John W. Linville
Browse files

[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: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 16bfa676
Loading
Loading
Loading
Loading
+23 −5
Original line number Diff line number Diff line
@@ -705,11 +705,30 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
	struct bcm43xx_dmaring *ring;
	int err = -ENOMEM;
	int dma64 = 0;
	u32 sbtmstatehi;
	u64 mask = bcm43xx_get_supported_dma_mask(bcm);
	int nobits;

	sbtmstatehi = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
	if (sbtmstatehi & BCM43xx_SBTMSTATEHIGH_DMA64BIT)
	if (mask == DMA_64BIT_MASK) {
		dma64 = 1;
		nobits = 64;
	} else if (mask == DMA_32BIT_MASK)
		nobits = 32;
	else
		nobits = 30;
	err = pci_set_dma_mask(bcm->pci_dev, mask);
	err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask);
	if (err) {
#ifdef CONFIG_BCM43XX_PIO
		printk(KERN_WARNING PFX "DMA not supported on this device."
					" Falling back to PIO.\n");
		bcm->__using_pio = 1;
		return -ENOSYS;
#else
		printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
				    "Please recompile the driver with PIO support.\n");
		return -ENODEV;
#endif /* CONFIG_BCM43XX_PIO */
	}

	/* setup TX DMA channels. */
	ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
@@ -755,8 +774,7 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
		dma->rx_ring3 = ring;
	}

	dprintk(KERN_INFO PFX "%s DMA initialized\n",
			dma64 ? "64-bit" : "32-bit");
	dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits);
	err = 0;
out:
	return err;
+17 −0
Original line number Diff line number Diff line
@@ -314,6 +314,23 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
		   struct ieee80211_txb *txb);
void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);

/* Helper function that returns the dma mask for this device. */
static inline
u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm)
{
	int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) &
				   BCM43xx_SBTMSTATEHIGH_DMA64BIT;
	u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0);
	u32 mask = BCM43xx_DMA32_TXADDREXT_MASK;

	if (dma64)
		return DMA_64BIT_MASK;
	bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask);
	if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask)
		return DMA_32BIT_MASK;
	return DMA_30BIT_MASK;
}

#else /* CONFIG_BCM43XX_DMA */


+6 −19
Original line number Diff line number Diff line
@@ -2925,10 +2925,13 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
		bcm43xx_write16(bcm, 0x043C, 0x000C);

	if (active_wlcore) {
		if (bcm43xx_using_pio(bcm))
		if (bcm43xx_using_pio(bcm)) {
			err = bcm43xx_pio_init(bcm);
		else
		} else {
			err = bcm43xx_dma_init(bcm);
			if (err == -ENOSYS)
				err = bcm43xx_pio_init(bcm);
		}
		if (err)
			goto err_chip_cleanup;
	}
@@ -3992,8 +3995,6 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
				struct net_device *net_dev,
				struct pci_dev *pci_dev)
{
	int err;

	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
	bcm->ieee = netdev_priv(net_dev);
	bcm->softmac = ieee80211_priv(net_dev);
@@ -4011,22 +4012,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
		     (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
		     (unsigned long)bcm);
	tasklet_disable_nosync(&bcm->isr_tasklet);
	if (modparam_pio) {
	if (modparam_pio)
		bcm->__using_pio = 1;
	} else {
		err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK);
		err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK);
		if (err) {
#ifdef CONFIG_BCM43XX_PIO
			printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n");
			bcm->__using_pio = 1;
#else
			printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
					    "Recompile the driver with PIO support, please.\n");
			return -ENODEV;
#endif /* CONFIG_BCM43XX_PIO */
		}
	}
	bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;

	/* default to sw encryption for now */