All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pekka Pietikainen <pp@ee.oulu.fi>
To: "David S. Miller" <davem@davemloft.net>
Cc: Andrew Morton <akpm@osdl.org>, netdev@oss.sgi.com
Subject: Re: Fw: b44 ifconfig fails with ENOMEM
Date: Sat, 8 Jan 2005 00:02:33 +0200	[thread overview]
Message-ID: <20050107220233.GA9639@ee.oulu.fi> (raw)
In-Reply-To: <20050104142026.000be2e8.davem@davemloft.net>

On Tue, Jan 04, 2005 at 02:20:26PM -0800, David S. Miller wrote:
> On Mon, 3 Jan 2005 19:18:36 -0800
> Andrew Morton <akpm@osdl.org> wrote:
> 
> > b44 requires an order-8 allocation?  Good luck...
> 
> Yes, it allocates a full TX ring worth of bounce buffers
> to work around a DMA addressing limitation.  It should do
> a bunch of smaller consistent allocations instead of one
> huge one, that's for sure.
-ENOHARDWARE (Santa got me an Athlon64 with dual GigE) so someone else will
have to pick up the ball. Shouldn't be too difficult, quickly thinking
something like:

X-It-Compiles-Lets-Ship-It: pp@ee.oulu.fi
--- ./b44.c.orig	2005-01-05 12:15:30.000000000 +0200
+++ ./b44.c	2005-01-08 00:00:49.974949992 +0200
@@ -68,6 +68,8 @@
 	  (BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
 #define NEXT_TX(N)		(((N) + 1) & (B44_TX_RING_SIZE - 1))
 
+#define B44_BOUNCEBUF(ENTRY) (bp->tx_bufs[(ENTRY)&(B44_NUM_BOUNCEBUFS-1)]+((ENTRY)>>B44_BOUNCEBUF_SHIFT)*TX_PKT_BUF_SZ)
+
 #define RX_PKT_BUF_SZ		(1536 + bp->rx_offset + 64)
 #define TX_PKT_BUF_SZ		(B44_MAX_MTU + ETH_HLEN + 8)
 
@@ -927,8 +929,8 @@
 	if(mapping+len > B44_DMA_MASK) {
 		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
 		pci_unmap_single(bp->pdev, mapping, len,PCI_DMA_TODEVICE);
-		memcpy(bp->tx_bufs+entry*TX_PKT_BUF_SZ,skb->data,skb->len);
-		mapping = pci_map_single(bp->pdev, bp->tx_bufs+entry*TX_PKT_BUF_SZ, len, PCI_DMA_TODEVICE);
+		memcpy(B44_BOUNCEBUF(entry),skb->data,skb->len);
+		mapping = pci_map_single(bp->pdev, B44_BOUNCEBUF(entry), len, PCI_DMA_TODEVICE);
 	}
 
 	bp->tx_buffers[entry].skb = skb;
@@ -1059,6 +1061,7 @@
  */
 static void b44_free_consistent(struct b44 *bp)
 {
+	int i;
 	if (bp->rx_buffers) {
 		kfree(bp->rx_buffers);
 		bp->rx_buffers = NULL;
@@ -1077,10 +1080,12 @@
 				    bp->tx_ring, bp->tx_ring_dma);
 		bp->tx_ring = NULL;
 	}
-	if (bp->tx_bufs) {
-		pci_free_consistent(bp->pdev, B44_TX_RING_SIZE * TX_PKT_BUF_SZ,
-				    bp->tx_bufs, bp->tx_bufs_dma);
-		bp->tx_bufs = NULL;
+	for(i = 0; i < B44_NUM_BOUNCEBUFS; i++) {
+		if (bp->tx_bufs[i]) {
+			pci_free_consistent(bp->pdev, B44_TX_RING_SIZE * TX_PKT_BUF_SZ / B44_NUM_BOUNCEBUFS,
+					    bp->tx_bufs[i], bp->tx_bufs_dma[i]);
+			bp->tx_bufs[i] = NULL;
+		}
 	}
 }
 
@@ -1090,7 +1095,7 @@
  */
 static int b44_alloc_consistent(struct b44 *bp)
 {
-	int size;
+	int i,size;
 
 	size  = B44_RX_RING_SIZE * sizeof(struct ring_info);
 	bp->rx_buffers = kmalloc(size, GFP_KERNEL);
@@ -1104,11 +1109,13 @@
 		goto out_err;
 	memset(bp->tx_buffers, 0, size);
 
-	size = B44_TX_RING_SIZE * TX_PKT_BUF_SZ;
-	bp->tx_bufs = pci_alloc_consistent(bp->pdev, size, &bp->tx_bufs_dma);
-	if (!bp->tx_bufs)
+	size = (B44_TX_RING_SIZE * TX_PKT_BUF_SZ) / B44_NUM_BOUNCEBUFS;
+	for(i = 0; i < B44_NUM_BOUNCEBUFS; i++) {
+	   bp->tx_bufs[i] = pci_alloc_consistent(bp->pdev, size, &bp->tx_bufs_dma[i]);
+	   if (!bp->tx_bufs[i])
 		goto out_err;
-	memset(bp->tx_bufs, 0, size);
+	   memset(bp->tx_bufs[i], 0, size);
+	}
 
 	size = DMA_TABLE_BYTES;
 	bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
--- ./b44.h.orig	2005-01-05 12:15:33.000000000 +0200
+++ ./b44.h	2005-01-07 23:53:07.234297264 +0200
@@ -359,6 +359,8 @@
 };
 
 #define B44_MCAST_TABLE_SIZE	32
+#define B44_BOUNCEBUF_SHIFT	3
+#define B44_NUM_BOUNCEBUFS	(1 << B44_BOUNCEBUF_SHIFT)
 
 /* SW copy of device statistics, kept up to date by periodic timer
  * which probes HW values.  Must have same relative layout as HW
@@ -397,7 +399,7 @@
 
 	struct ring_info	*rx_buffers;
 	struct ring_info	*tx_buffers;
-	unsigned char		*tx_bufs; 
+	unsigned char		*tx_bufs[B44_NUM_BOUNCEBUFS]; 
 
 	u32			dma_offset;
 	u32			flags;
@@ -429,7 +431,8 @@
 	struct pci_dev		*pdev;
 	struct net_device	*dev;
 
-	dma_addr_t		rx_ring_dma, tx_ring_dma,tx_bufs_dma;
+	dma_addr_t		rx_ring_dma, tx_ring_dma;
+	dma_addr_t		tx_bufs_dma[B44_NUM_BOUNCEBUFS];
 
 	u32			rx_pending;
 	u32			tx_pending;

  reply	other threads:[~2005-01-07 22:02 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-01-04  3:18 Fw: b44 ifconfig fails with ENOMEM Andrew Morton
2005-01-04 22:20 ` David S. Miller
2005-01-07 22:02   ` Pekka Pietikainen [this message]
2005-01-21  0:32     ` Pekka Pietikainen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20050107220233.GA9639@ee.oulu.fi \
    --to=pp@ee.oulu.fi \
    --cc=akpm@osdl.org \
    --cc=davem@davemloft.net \
    --cc=netdev@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.