1 From 856f17b89eb0e943d36f36d0c760e1226db9d716 Mon Sep 17 00:00:00 2001
2 From: Sergey Lapin <slapin@ossfans.org>
3 Date: Fri, 4 Jul 2008 01:52:39 +0400
4 Subject: [PATCH] SRAM TX buffers implementation from atmel to fix TX underrun errors
6 Signed-off-by: Sergey Lapin <slapin@ossfans.org>
8 arch/arm/mach-at91/at91sam9260_devices.c | 7 ++
9 drivers/net/Kconfig | 6 ++
10 drivers/net/macb.c | 108 ++++++++++++++++++++++--------
11 drivers/net/macb.h | 7 ++-
12 4 files changed, 99 insertions(+), 29 deletions(-)
14 diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
15 index f5fec0a..681cd40 100644
16 --- a/arch/arm/mach-at91/at91sam9260_devices.c
17 +++ b/arch/arm/mach-at91/at91sam9260_devices.c
18 @@ -141,6 +141,13 @@ static struct resource eth_resources[] = {
19 .end = AT91SAM9260_ID_EMAC,
20 .flags = IORESOURCE_IRQ,
22 +#if defined(CONFIG_MACB_TX_SRAM)
24 + .start = AT91SAM9260_SRAM1_BASE,
25 + .end = AT91SAM9260_SRAM1_BASE + AT91SAM9260_SRAM1_SIZE - 1,
26 + .flags = IORESOURCE_MEM,
31 static struct platform_device at91sam9260_eth_device = {
32 diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
33 index 8a03875..a9a46a8 100644
34 --- a/drivers/net/Kconfig
35 +++ b/drivers/net/Kconfig
36 @@ -218,6 +218,12 @@ config MACB
37 To compile this driver as a module, choose M here: the module
41 + bool "Use internal SRAM for EMAC (Ethernet) transmit buffers"
42 + depends on (ARCH_AT91SAM9263 || ARCH_AT91SAM9260) && MACB
44 + Select this if you are using internal SRAM for EMAC transmit buffers.
46 source "drivers/net/arm/Kconfig"
49 diff --git a/drivers/net/macb.c b/drivers/net/macb.c
50 index daba82b..55063dc 100644
51 --- a/drivers/net/macb.c
52 +++ b/drivers/net/macb.c
54 /* Make the IP header word-aligned (the ethernet header is 14 bytes) */
57 -#define TX_RING_SIZE 128
58 -#define DEF_TX_RING_PENDING (TX_RING_SIZE - 1)
59 -#define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE)
60 +#define TX_MAX_PKT_SIZE 1536
61 +#define TX_DEFAULT_RING_SIZE 128
62 +#define DEF_TX_RING_PENDING(bp) ((bp)->tx_ring_size - 1)
64 +#define TX_RING_BYTES(bp) (sizeof(struct dma_desc) * \
67 #define TX_RING_GAP(bp) \
68 - (TX_RING_SIZE - (bp)->tx_pending)
69 + ((bp)->tx_ring_size - (bp)->tx_pending)
71 #define TX_BUFFS_AVAIL(bp) \
72 (((bp)->tx_tail <= (bp)->tx_head) ? \
73 (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head : \
74 (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp))
75 -#define NEXT_TX(n) (((n) + 1) & (TX_RING_SIZE - 1))
77 -#define NEXT_RX(n) (((n) + 1) & (RX_RING_SIZE - 1))
78 +#define NEXT_TX(bp, n) (((n) + 1) % ((bp)->tx_ring_size))
79 +#define NEXT_RX(n) (((n) + 1) % (RX_RING_SIZE))
82 /* minimum number of free TX descriptors before waking up TX process */
83 -#define MACB_TX_WAKEUP_THRESH (TX_RING_SIZE / 4)
84 +#define MACB_TX_WAKEUP_THRESH(bp) ((bp)->tx_ring_size / 4)
86 #define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
88 @@ -316,11 +321,11 @@ static void macb_tx(struct macb *bp)
91 /*Mark all the buffer as used to avoid sending a lost buffer*/
92 - for (i = 0; i < TX_RING_SIZE; i++)
93 + for (i = 0; i < bp->tx_ring_size; i++)
94 bp->tx_ring[i].ctrl = MACB_BIT(TX_USED);
96 /* free transmit buffer in upper layer*/
97 - for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
98 + for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(bp, tail)) {
99 struct ring_info *rp = &bp->tx_skb[tail];
100 struct sk_buff *skb = rp->skb;
102 @@ -346,7 +351,7 @@ static void macb_tx(struct macb *bp)
106 - for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
107 + for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(bp, tail)) {
108 struct ring_info *rp = &bp->tx_skb[tail];
109 struct sk_buff *skb = rp->skb;
111 @@ -371,7 +376,7 @@ static void macb_tx(struct macb *bp)
114 if (netif_queue_stopped(bp->dev) &&
115 - TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH)
116 + TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH(bp))
117 netif_wake_queue(bp->dev);
120 @@ -401,6 +406,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
123 skb_reserve(skb, RX_OFFSET);
124 + skb->dev = bp->dev;
125 skb->ip_summed = CHECKSUM_NONE;
128 @@ -637,8 +643,15 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
131 dev_dbg(&bp->pdev->dev, "Allocated ring entry %u\n", entry);
132 - mapping = dma_map_single(&bp->pdev->dev, skb->data,
133 + if (bp->smem_start) {
134 + mapping = bp->tx_ring[entry].addr;
135 + memcpy(bp->tx_buffers + entry * TX_MAX_PKT_SIZE,
138 + mapping = dma_map_single(&bp->pdev->dev, skb->data,
140 + bp->tx_ring[entry].addr = mapping;
142 bp->tx_skb[entry].skb = skb;
143 bp->tx_skb[entry].mapping = mapping;
144 dev_dbg(&bp->pdev->dev, "Mapped skb data %p to DMA addr %08lx\n",
145 @@ -646,14 +659,13 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
147 ctrl = MACB_BF(TX_FRMLEN, len);
148 ctrl |= MACB_BIT(TX_LAST);
149 - if (entry == (TX_RING_SIZE - 1))
150 + if (entry == (bp->tx_ring_size - 1))
151 ctrl |= MACB_BIT(TX_WRAP);
153 - bp->tx_ring[entry].addr = mapping;
154 bp->tx_ring[entry].ctrl = ctrl;
157 - entry = NEXT_TX(entry);
158 + entry = NEXT_TX(bp, entry);
161 macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
162 @@ -680,7 +692,8 @@ static void macb_free_consistent(struct macb *bp)
166 - dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES,
167 + if (!bp->smem_start)
168 + dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES(bp),
169 bp->tx_ring, bp->tx_ring_dma);
172 @@ -690,13 +703,16 @@ static void macb_free_consistent(struct macb *bp)
173 bp->rx_buffers, bp->rx_buffers_dma);
174 bp->rx_buffers = NULL;
177 + if (bp->smem_start && bp->tx_ring_dma)
178 + release_mem_region(bp->tx_ring_dma, bp->smem_size);
181 static int macb_alloc_consistent(struct macb *bp)
185 - size = TX_RING_SIZE * sizeof(struct ring_info);
186 + size = bp->tx_ring_size * sizeof(struct ring_info);
187 bp->tx_skb = kmalloc(size, GFP_KERNEL);
190 @@ -710,14 +726,30 @@ static int macb_alloc_consistent(struct macb *bp)
191 "Allocated RX ring of %d bytes at %08lx (mapped %p)\n",
192 size, (unsigned long)bp->rx_ring_dma, bp->rx_ring);
194 - size = TX_RING_BYTES;
195 - bp->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
196 + if (bp->smem_start) {
197 + if (request_mem_region(bp->smem_start,
198 + bp->smem_size, "macb")) {
199 + bp->tx_ring_dma = bp->smem_start;
201 + bp->tx_ring = ioremap(bp->tx_ring_dma, bp->smem_size);
203 + bp->tx_buffers_dma = bp->tx_ring_dma +
205 + bp->tx_buffers = (char *) bp->tx_ring +
210 + if (!bp->tx_ring) {
211 + size = TX_RING_BYTES(bp);
212 + bp->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
213 &bp->tx_ring_dma, GFP_KERNEL);
216 - dev_dbg(&bp->pdev->dev,
217 - "Allocated TX ring of %d bytes at %08lx (mapped %p)\n",
218 - size, (unsigned long)bp->tx_ring_dma, bp->tx_ring);
221 + dev_dbg(&bp->pdev->dev,
222 + "Allocated TX ring of %d bytes at %08lx (mapped %p)\n",
223 + size, (unsigned long)bp->tx_ring_dma, bp->tx_ring);
226 size = RX_RING_SIZE * RX_BUFFER_SIZE;
227 bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size,
228 @@ -748,11 +780,14 @@ static void macb_init_rings(struct macb *bp)
230 bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
232 - for (i = 0; i < TX_RING_SIZE; i++) {
233 - bp->tx_ring[i].addr = 0;
234 + for (i = 0; i < bp->tx_ring_size; i++) {
235 + bp->tx_ring[i].addr = (bp->smem_start) ?
236 + bp->tx_buffers_dma + i * TX_MAX_PKT_SIZE : 0;
237 bp->tx_ring[i].ctrl = MACB_BIT(TX_USED);
238 + bp->tx_ring[i].addr = (u32) (bp->tx_buffers_dma +
239 + (i * TX_MAX_PKT_SIZE));
241 - bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
242 + bp->tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
244 bp->rx_tail = bp->tx_head = bp->tx_tail = 0;
246 @@ -1090,6 +1125,7 @@ static int __init macb_probe(struct platform_device *pdev)
248 struct eth_platform_data *pdata;
249 struct resource *regs;
250 + struct resource *smem;
251 struct net_device *dev;
253 struct phy_device *phydev;
254 @@ -1201,7 +1237,23 @@ static int __init macb_probe(struct platform_device *pdev)
255 macb_writel(bp, USRIO, MACB_BIT(MII));
258 - bp->tx_pending = DEF_TX_RING_PENDING;
259 + /* Check mem region for TX buffers */
260 + smem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
262 + bp->smem_start = smem->start;
263 + bp->smem_size = smem->end - smem->start + 1;
264 + bp->tx_ring_size = bp->smem_size / (TX_MAX_PKT_SIZE +
265 + sizeof(struct dma_desc));
268 + /* if ring_size == 0 then mem is too
269 + small and use standard memory */
270 + if (!bp->tx_ring_size) {
271 + bp->smem_start = 0;
272 + bp->tx_ring_size = TX_DEFAULT_RING_SIZE;
275 + bp->tx_pending = DEF_TX_RING_PENDING(bp);
277 err = register_netdev(dev);
279 diff --git a/drivers/net/macb.h b/drivers/net/macb.h
280 index 57b85ac..faa5a9d 100644
281 --- a/drivers/net/macb.h
282 +++ b/drivers/net/macb.h
283 @@ -364,11 +364,15 @@ struct macb {
284 unsigned int rx_tail;
285 struct dma_desc *rx_ring;
289 + unsigned int tx_ring_size;
290 unsigned int tx_head, tx_tail;
291 struct dma_desc *tx_ring;
292 struct ring_info *tx_skb;
294 + unsigned int smem_start;
295 + unsigned int smem_size;
298 struct platform_device *pdev;
300 @@ -381,6 +385,7 @@ struct macb {
301 dma_addr_t rx_ring_dma;
302 dma_addr_t tx_ring_dma;
303 dma_addr_t rx_buffers_dma;
304 + dma_addr_t tx_buffers_dma;
306 unsigned int rx_pending, tx_pending;