9a280d666a953e5c5b0115ae2e0556e7cb12b0f8
[openembedded.git] /
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
5
6 Signed-off-by: Sergey Lapin <slapin@ossfans.org>
7 ---
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(-)
13
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,
21         },
22 +#if defined(CONFIG_MACB_TX_SRAM)
23 +       [2] = {
24 +               .start  = AT91SAM9260_SRAM1_BASE,
25 +               .end    = AT91SAM9260_SRAM1_BASE + AT91SAM9260_SRAM1_SIZE - 1,
26 +               .flags  = IORESOURCE_MEM,
27 +       },
28 +#endif
29  };
30  
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
38           will be called macb.
39  
40 +config MACB_TX_SRAM
41 +       bool "Use internal SRAM for EMAC (Ethernet) transmit buffers"
42 +       depends on (ARCH_AT91SAM9263 || ARCH_AT91SAM9260) && MACB
43 +       help
44 +         Select this if you are using internal SRAM for EMAC transmit buffers.
45 +
46  source "drivers/net/arm/Kconfig"
47  
48  config AX88796
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
53 @@ -33,22 +33,27 @@
54  /* Make the IP header word-aligned (the ethernet header is 14 bytes) */
55  #define RX_OFFSET              2
56  
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)
63 +
64 +#define TX_RING_BYTES(bp)              (sizeof(struct dma_desc) * \
65 +                                               (bp)->tx_ring_size)
66  
67  #define TX_RING_GAP(bp)                                                \
68 -       (TX_RING_SIZE - (bp)->tx_pending)
69 +       ((bp)->tx_ring_size - (bp)->tx_pending)
70 +
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))
76  
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)) 
80
81  
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)
85  
86  #define MACB_RX_INT_FLAGS      (MACB_BIT(RCOMP) | MACB_BIT(RXUBR)      \
87                                  | MACB_BIT(ISR_ROVR))
88 @@ -316,11 +321,11 @@ static void macb_tx(struct macb *bp)
89                 head = bp->tx_head;
90  
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);
95  
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;
101  
102 @@ -346,7 +351,7 @@ static void macb_tx(struct macb *bp)
103                 return;
104  
105         head = bp->tx_head;
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;
110                 u32 bufstat;
111 @@ -371,7 +376,7 @@ static void macb_tx(struct macb *bp)
112  
113         bp->tx_tail = tail;
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);
118  }
119  
120 @@ -401,6 +406,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
121         }
122  
123         skb_reserve(skb, RX_OFFSET);
124 +       skb->dev = bp->dev;
125         skb->ip_summed = CHECKSUM_NONE;
126         skb_put(skb, len);
127  
128 @@ -637,8 +643,15 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
129  
130         entry = bp->tx_head;
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,
136 +                       skb->data, len);
137 +       } else {
138 +               mapping = dma_map_single(&bp->pdev->dev, skb->data,
139                                  len, DMA_TO_DEVICE);
140 +               bp->tx_ring[entry].addr = mapping;
141 +       }
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)
146  
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);
152  
153 -       bp->tx_ring[entry].addr = mapping;
154         bp->tx_ring[entry].ctrl = ctrl;
155         wmb();
156  
157 -       entry = NEXT_TX(entry);
158 +       entry = NEXT_TX(bp, entry);
159         bp->tx_head = entry;
160  
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)
163                 bp->rx_ring = NULL;
164         }
165         if (bp->tx_ring) {
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);
170                 bp->tx_ring = NULL;
171         }
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;
175         }
176 +
177 +       if (bp->smem_start && bp->tx_ring_dma)
178 +               release_mem_region(bp->tx_ring_dma, bp->smem_size);
179  }
180  
181  static int macb_alloc_consistent(struct macb *bp)
182  {
183         int size;
184  
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);
188         if (!bp->tx_skb)
189                 goto out_err;
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);
193  
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;
200 +               }
201 +               bp->tx_ring = ioremap(bp->tx_ring_dma, bp->smem_size);
202 +               if (bp->tx_ring) {
203 +                       bp->tx_buffers_dma = bp->tx_ring_dma +
204 +                       TX_RING_BYTES(bp);
205 +                       bp->tx_buffers = (char *) bp->tx_ring +
206 +                       TX_RING_BYTES(bp);
207 +               }
208 +       }
209 +
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);
214 -       if (!bp->tx_ring)
215 -               goto out_err;
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);
219 +               if (!bp->tx_ring)
220 +                       goto out_err;
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);
224 +       }
225  
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)
229         }
230         bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
231  
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));
240         }
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);
243  
244         bp->rx_tail = bp->tx_head = bp->tx_tail = 0;
245  }
246 @@ -1090,6 +1125,7 @@ static int __init macb_probe(struct platform_device *pdev)
247  {
248         struct eth_platform_data *pdata;
249         struct resource *regs;
250 +       struct resource *smem;
251         struct net_device *dev;
252         struct macb *bp;
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));
256  #endif
257  
258 -       bp->tx_pending = DEF_TX_RING_PENDING;
259 +       /* Check  mem region for TX buffers */
260 +       smem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
261 +       if (smem) {
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));
266 +       }
267 +
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;
273 +       }
274 +
275 +       bp->tx_pending = DEF_TX_RING_PENDING(bp);
276  
277         err = register_netdev(dev);
278         if (err) {
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;
286         void                    *rx_buffers;
287 -
288 +       void                    *tx_buffers;
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;
293  
294 +       unsigned int            smem_start;
295 +       unsigned int            smem_size;
296 +
297         spinlock_t              lock;
298         struct platform_device  *pdev;
299         struct clk              *pclk;
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;
305  
306         unsigned int            rx_pending, tx_pending;
307  
308 -- 
309 1.5.4.1
310