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

Commit 639b421b authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds
Browse files

[PATCH] x86_64: Check for bad dma address in b44 1GB DMA workaround



Needed for interaction with the nommu code in x86-64 which
will return bad_dma_address if the address exceeds dma_mask.

Cc: netdev@vger.kernel.org
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent c4694c76
Loading
Loading
Loading
Loading
+18 −10
Original line number Original line Diff line number Diff line
@@ -650,8 +650,10 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)


	/* Hardware bug work-around, the chip is unable to do PCI DMA
	/* Hardware bug work-around, the chip is unable to do PCI DMA
	   to/from anything above 1GB :-( */
	   to/from anything above 1GB :-( */
	if (mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
	if (dma_mapping_error(mapping) ||
		mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
		/* Sigh... */
		/* Sigh... */
		if (!dma_mapping_error(mapping))
			pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
			pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
		dev_kfree_skb_any(skb);
		dev_kfree_skb_any(skb);
		skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
		skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
@@ -660,7 +662,9 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
		mapping = pci_map_single(bp->pdev, skb->data,
		mapping = pci_map_single(bp->pdev, skb->data,
					 RX_PKT_BUF_SZ,
					 RX_PKT_BUF_SZ,
					 PCI_DMA_FROMDEVICE);
					 PCI_DMA_FROMDEVICE);
		if (mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
		if (dma_mapping_error(mapping) ||
			mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
			if (!dma_mapping_error(mapping))
				pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
				pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
			dev_kfree_skb_any(skb);
			dev_kfree_skb_any(skb);
			return -ENOMEM;
			return -ENOMEM;
@@ -967,8 +971,9 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
	}
	}


	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
	if (mapping + len > B44_DMA_MASK) {
	if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
		if (!dma_mapping_error(mapping))
			pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
			pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);


		bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
		bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
@@ -978,7 +983,8 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)


		mapping = pci_map_single(bp->pdev, bounce_skb->data,
		mapping = pci_map_single(bp->pdev, bounce_skb->data,
					 len, PCI_DMA_TODEVICE);
					 len, PCI_DMA_TODEVICE);
		if (mapping + len > B44_DMA_MASK) {
		if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
			if (!dma_mapping_error(mapping))
				pci_unmap_single(bp->pdev, mapping,
				pci_unmap_single(bp->pdev, mapping,
					 len, PCI_DMA_TODEVICE);
					 len, PCI_DMA_TODEVICE);
			dev_kfree_skb_any(bounce_skb);
			dev_kfree_skb_any(bounce_skb);
@@ -1203,7 +1209,8 @@ static int b44_alloc_consistent(struct b44 *bp)
		                             DMA_TABLE_BYTES,
		                             DMA_TABLE_BYTES,
		                             DMA_BIDIRECTIONAL);
		                             DMA_BIDIRECTIONAL);


		if (rx_ring_dma + size > B44_DMA_MASK) {
		if (dma_mapping_error(rx_ring_dma) ||
			rx_ring_dma + size > B44_DMA_MASK) {
			kfree(rx_ring);
			kfree(rx_ring);
			goto out_err;
			goto out_err;
		}
		}
@@ -1229,7 +1236,8 @@ static int b44_alloc_consistent(struct b44 *bp)
		                             DMA_TABLE_BYTES,
		                             DMA_TABLE_BYTES,
		                             DMA_TO_DEVICE);
		                             DMA_TO_DEVICE);


		if (tx_ring_dma + size > B44_DMA_MASK) {
		if (dma_mapping_error(tx_ring_dma) ||
			tx_ring_dma + size > B44_DMA_MASK) {
			kfree(tx_ring);
			kfree(tx_ring);
			goto out_err;
			goto out_err;
		}
		}