diff options
author | Sergey Lapin <slapin@ossfans.org> | 2008-12-04 01:28:47 +0300 |
---|---|---|
committer | Sergey Lapin <slapin@ossfans.org> | 2008-12-04 01:36:42 +0300 |
commit | dde71280ca0a91bd8393590f1fa07251645dc21b (patch) | |
tree | ec9d96b0b0e750453ad344f7db798d068bbb7ed2 /packages/linux/linux-2.6.27+2.6.28-rc6/afeb9260/0002-SRAM-TX-buffers-implementation-from-atmel-to-fix-TX.patch | |
parent | 6ae987b688c82aa1852b5a7bb691b7138c3ebd51 (diff) |
linux_2.6.28: made source fetchable after Koen's fix
Diffstat (limited to 'packages/linux/linux-2.6.27+2.6.28-rc6/afeb9260/0002-SRAM-TX-buffers-implementation-from-atmel-to-fix-TX.patch')
-rw-r--r-- | packages/linux/linux-2.6.27+2.6.28-rc6/afeb9260/0002-SRAM-TX-buffers-implementation-from-atmel-to-fix-TX.patch | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/packages/linux/linux-2.6.27+2.6.28-rc6/afeb9260/0002-SRAM-TX-buffers-implementation-from-atmel-to-fix-TX.patch b/packages/linux/linux-2.6.27+2.6.28-rc6/afeb9260/0002-SRAM-TX-buffers-implementation-from-atmel-to-fix-TX.patch new file mode 100644 index 0000000000..9a280d666a --- /dev/null +++ b/packages/linux/linux-2.6.27+2.6.28-rc6/afeb9260/0002-SRAM-TX-buffers-implementation-from-atmel-to-fix-TX.patch @@ -0,0 +1,310 @@ +From 856f17b89eb0e943d36f36d0c760e1226db9d716 Mon Sep 17 00:00:00 2001 +From: Sergey Lapin <slapin@ossfans.org> +Date: Fri, 4 Jul 2008 01:52:39 +0400 +Subject: [PATCH] SRAM TX buffers implementation from atmel to fix TX underrun errors + +Signed-off-by: Sergey Lapin <slapin@ossfans.org> +--- + arch/arm/mach-at91/at91sam9260_devices.c | 7 ++ + drivers/net/Kconfig | 6 ++ + drivers/net/macb.c | 108 ++++++++++++++++++++++-------- + drivers/net/macb.h | 7 ++- + 4 files changed, 99 insertions(+), 29 deletions(-) + +diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c +index f5fec0a..681cd40 100644 +--- a/arch/arm/mach-at91/at91sam9260_devices.c ++++ b/arch/arm/mach-at91/at91sam9260_devices.c +@@ -141,6 +141,13 @@ static struct resource eth_resources[] = { + .end = AT91SAM9260_ID_EMAC, + .flags = IORESOURCE_IRQ, + }, ++#if defined(CONFIG_MACB_TX_SRAM) ++ [2] = { ++ .start = AT91SAM9260_SRAM1_BASE, ++ .end = AT91SAM9260_SRAM1_BASE + AT91SAM9260_SRAM1_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++#endif + }; + + static struct platform_device at91sam9260_eth_device = { +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index 8a03875..a9a46a8 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -218,6 +218,12 @@ config MACB + To compile this driver as a module, choose M here: the module + will be called macb. + ++config MACB_TX_SRAM ++ bool "Use internal SRAM for EMAC (Ethernet) transmit buffers" ++ depends on (ARCH_AT91SAM9263 || ARCH_AT91SAM9260) && MACB ++ help ++ Select this if you are using internal SRAM for EMAC transmit buffers. ++ + source "drivers/net/arm/Kconfig" + + config AX88796 +diff --git a/drivers/net/macb.c b/drivers/net/macb.c +index daba82b..55063dc 100644 +--- a/drivers/net/macb.c ++++ b/drivers/net/macb.c +@@ -33,22 +33,27 @@ + /* Make the IP header word-aligned (the ethernet header is 14 bytes) */ + #define RX_OFFSET 2 + +-#define TX_RING_SIZE 128 +-#define DEF_TX_RING_PENDING (TX_RING_SIZE - 1) +-#define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE) ++#define TX_MAX_PKT_SIZE 1536 ++#define TX_DEFAULT_RING_SIZE 128 ++#define DEF_TX_RING_PENDING(bp) ((bp)->tx_ring_size - 1) ++ ++#define TX_RING_BYTES(bp) (sizeof(struct dma_desc) * \ ++ (bp)->tx_ring_size) + + #define TX_RING_GAP(bp) \ +- (TX_RING_SIZE - (bp)->tx_pending) ++ ((bp)->tx_ring_size - (bp)->tx_pending) ++ + #define TX_BUFFS_AVAIL(bp) \ + (((bp)->tx_tail <= (bp)->tx_head) ? \ + (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head : \ + (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp)) +-#define NEXT_TX(n) (((n) + 1) & (TX_RING_SIZE - 1)) + +-#define NEXT_RX(n) (((n) + 1) & (RX_RING_SIZE - 1)) ++#define NEXT_TX(bp, n) (((n) + 1) % ((bp)->tx_ring_size)) ++#define NEXT_RX(n) (((n) + 1) % (RX_RING_SIZE)) ++ + + /* minimum number of free TX descriptors before waking up TX process */ +-#define MACB_TX_WAKEUP_THRESH (TX_RING_SIZE / 4) ++#define MACB_TX_WAKEUP_THRESH(bp) ((bp)->tx_ring_size / 4) + + #define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \ + | MACB_BIT(ISR_ROVR)) +@@ -316,11 +321,11 @@ static void macb_tx(struct macb *bp) + head = bp->tx_head; + + /*Mark all the buffer as used to avoid sending a lost buffer*/ +- for (i = 0; i < TX_RING_SIZE; i++) ++ for (i = 0; i < bp->tx_ring_size; i++) + bp->tx_ring[i].ctrl = MACB_BIT(TX_USED); + + /* free transmit buffer in upper layer*/ +- for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) { ++ for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(bp, tail)) { + struct ring_info *rp = &bp->tx_skb[tail]; + struct sk_buff *skb = rp->skb; + +@@ -346,7 +351,7 @@ static void macb_tx(struct macb *bp) + return; + + head = bp->tx_head; +- for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) { ++ for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(bp, tail)) { + struct ring_info *rp = &bp->tx_skb[tail]; + struct sk_buff *skb = rp->skb; + u32 bufstat; +@@ -371,7 +376,7 @@ static void macb_tx(struct macb *bp) + + bp->tx_tail = tail; + if (netif_queue_stopped(bp->dev) && +- TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH) ++ TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH(bp)) + netif_wake_queue(bp->dev); + } + +@@ -401,6 +406,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, + } + + skb_reserve(skb, RX_OFFSET); ++ skb->dev = bp->dev; + skb->ip_summed = CHECKSUM_NONE; + skb_put(skb, len); + +@@ -637,8 +643,15 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) + + entry = bp->tx_head; + dev_dbg(&bp->pdev->dev, "Allocated ring entry %u\n", entry); +- mapping = dma_map_single(&bp->pdev->dev, skb->data, ++ if (bp->smem_start) { ++ mapping = bp->tx_ring[entry].addr; ++ memcpy(bp->tx_buffers + entry * TX_MAX_PKT_SIZE, ++ skb->data, len); ++ } else { ++ mapping = dma_map_single(&bp->pdev->dev, skb->data, + len, DMA_TO_DEVICE); ++ bp->tx_ring[entry].addr = mapping; ++ } + bp->tx_skb[entry].skb = skb; + bp->tx_skb[entry].mapping = mapping; + dev_dbg(&bp->pdev->dev, "Mapped skb data %p to DMA addr %08lx\n", +@@ -646,14 +659,13 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) + + ctrl = MACB_BF(TX_FRMLEN, len); + ctrl |= MACB_BIT(TX_LAST); +- if (entry == (TX_RING_SIZE - 1)) ++ if (entry == (bp->tx_ring_size - 1)) + ctrl |= MACB_BIT(TX_WRAP); + +- bp->tx_ring[entry].addr = mapping; + bp->tx_ring[entry].ctrl = ctrl; + wmb(); + +- entry = NEXT_TX(entry); ++ entry = NEXT_TX(bp, entry); + bp->tx_head = entry; + + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); +@@ -680,7 +692,8 @@ static void macb_free_consistent(struct macb *bp) + bp->rx_ring = NULL; + } + if (bp->tx_ring) { +- dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES, ++ if (!bp->smem_start) ++ dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES(bp), + bp->tx_ring, bp->tx_ring_dma); + bp->tx_ring = NULL; + } +@@ -690,13 +703,16 @@ static void macb_free_consistent(struct macb *bp) + bp->rx_buffers, bp->rx_buffers_dma); + bp->rx_buffers = NULL; + } ++ ++ if (bp->smem_start && bp->tx_ring_dma) ++ release_mem_region(bp->tx_ring_dma, bp->smem_size); + } + + static int macb_alloc_consistent(struct macb *bp) + { + int size; + +- size = TX_RING_SIZE * sizeof(struct ring_info); ++ size = bp->tx_ring_size * sizeof(struct ring_info); + bp->tx_skb = kmalloc(size, GFP_KERNEL); + if (!bp->tx_skb) + goto out_err; +@@ -710,14 +726,30 @@ static int macb_alloc_consistent(struct macb *bp) + "Allocated RX ring of %d bytes at %08lx (mapped %p)\n", + size, (unsigned long)bp->rx_ring_dma, bp->rx_ring); + +- size = TX_RING_BYTES; +- bp->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size, ++ if (bp->smem_start) { ++ if (request_mem_region(bp->smem_start, ++ bp->smem_size, "macb")) { ++ bp->tx_ring_dma = bp->smem_start; ++ } ++ bp->tx_ring = ioremap(bp->tx_ring_dma, bp->smem_size); ++ if (bp->tx_ring) { ++ bp->tx_buffers_dma = bp->tx_ring_dma + ++ TX_RING_BYTES(bp); ++ bp->tx_buffers = (char *) bp->tx_ring + ++ TX_RING_BYTES(bp); ++ } ++ } ++ ++ if (!bp->tx_ring) { ++ size = TX_RING_BYTES(bp); ++ bp->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size, + &bp->tx_ring_dma, GFP_KERNEL); +- if (!bp->tx_ring) +- goto out_err; +- dev_dbg(&bp->pdev->dev, +- "Allocated TX ring of %d bytes at %08lx (mapped %p)\n", +- size, (unsigned long)bp->tx_ring_dma, bp->tx_ring); ++ if (!bp->tx_ring) ++ goto out_err; ++ dev_dbg(&bp->pdev->dev, ++ "Allocated TX ring of %d bytes at %08lx (mapped %p)\n", ++ size, (unsigned long)bp->tx_ring_dma, bp->tx_ring); ++ } + + size = RX_RING_SIZE * RX_BUFFER_SIZE; + bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size, +@@ -748,11 +780,14 @@ static void macb_init_rings(struct macb *bp) + } + bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP); + +- for (i = 0; i < TX_RING_SIZE; i++) { +- bp->tx_ring[i].addr = 0; ++ for (i = 0; i < bp->tx_ring_size; i++) { ++ bp->tx_ring[i].addr = (bp->smem_start) ? ++ bp->tx_buffers_dma + i * TX_MAX_PKT_SIZE : 0; + bp->tx_ring[i].ctrl = MACB_BIT(TX_USED); ++ bp->tx_ring[i].addr = (u32) (bp->tx_buffers_dma + ++ (i * TX_MAX_PKT_SIZE)); + } +- bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP); ++ bp->tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP); + + bp->rx_tail = bp->tx_head = bp->tx_tail = 0; + } +@@ -1090,6 +1125,7 @@ static int __init macb_probe(struct platform_device *pdev) + { + struct eth_platform_data *pdata; + struct resource *regs; ++ struct resource *smem; + struct net_device *dev; + struct macb *bp; + struct phy_device *phydev; +@@ -1201,7 +1237,23 @@ static int __init macb_probe(struct platform_device *pdev) + macb_writel(bp, USRIO, MACB_BIT(MII)); + #endif + +- bp->tx_pending = DEF_TX_RING_PENDING; ++ /* Check mem region for TX buffers */ ++ smem = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (smem) { ++ bp->smem_start = smem->start; ++ bp->smem_size = smem->end - smem->start + 1; ++ bp->tx_ring_size = bp->smem_size / (TX_MAX_PKT_SIZE + ++ sizeof(struct dma_desc)); ++ } ++ ++ /* if ring_size == 0 then mem is too ++ small and use standard memory */ ++ if (!bp->tx_ring_size) { ++ bp->smem_start = 0; ++ bp->tx_ring_size = TX_DEFAULT_RING_SIZE; ++ } ++ ++ bp->tx_pending = DEF_TX_RING_PENDING(bp); + + err = register_netdev(dev); + if (err) { +diff --git a/drivers/net/macb.h b/drivers/net/macb.h +index 57b85ac..faa5a9d 100644 +--- a/drivers/net/macb.h ++++ b/drivers/net/macb.h +@@ -364,11 +364,15 @@ struct macb { + unsigned int rx_tail; + struct dma_desc *rx_ring; + void *rx_buffers; +- ++ void *tx_buffers; ++ unsigned int tx_ring_size; + unsigned int tx_head, tx_tail; + struct dma_desc *tx_ring; + struct ring_info *tx_skb; + ++ unsigned int smem_start; ++ unsigned int smem_size; ++ + spinlock_t lock; + struct platform_device *pdev; + struct clk *pclk; +@@ -381,6 +385,7 @@ struct macb { + dma_addr_t rx_ring_dma; + dma_addr_t tx_ring_dma; + dma_addr_t rx_buffers_dma; ++ dma_addr_t tx_buffers_dma; + + unsigned int rx_pending, tx_pending; + +-- +1.5.4.1 + |