Root/target/linux/generic/patches-3.3/132-solos-dma.patch

1commit b4bd8ad9bb311e8536f726f7a633620ccd358cde
2Author: David Woodhouse <dwmw2@infradead.org>
3Date: Thu May 24 04:58:27 2012 +0000
4
5    solos-pci: Fix DMA support
6    
7    DMA support has finally made its way to the top of the TODO list, having
8    realised that a Geode using MMIO can't keep up with two ADSL2+ lines
9    each running at 21Mb/s.
10    
11    This patch fixes a couple of bugs in the DMA support in the driver, so
12    once the corresponding FPGA update is complete and tested everything
13    should work properly.
14    
15    We weren't storing the currently-transmitting skb, so we were never
16    unmapping it and never freeing/popping it when the TX was done.
17    And the addition of pci_set_master() is fairly self-explanatory.
18    
19    Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
20    Cc: stable@kernel.org
21    Signed-off-by: David S. Miller <davem@davemloft.net>
22
23commit 152a2a8b5e1d4cbe91a7c66f1028db15164a3766
24Author: David Woodhouse <David.Woodhouse@intel.com>
25Date: Wed Dec 19 11:01:21 2012 +0000
26
27    solos-pci: ensure all TX packets are aligned to 4 bytes
28    
29    The FPGA can't handled unaligned DMA (yet). So copy into an aligned buffer,
30    if skb->data isn't suitably aligned.
31    
32    Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
33    Signed-off-by: David S. Miller <davem@davemloft.net>
34
35commit 13af816469db3449c072afbae6c4c1bd9ccecccb
36Author: Nathan Williams <nathan@traverse.com.au>
37Date: Wed Dec 19 11:01:20 2012 +0000
38
39    solos-pci: add firmware upgrade support for new models
40    
41    Signed-off-by: Nathan Williams <nathan@traverse.com.au>
42    Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
43    Signed-off-by: David S. Miller <davem@davemloft.net>
44
45commit 7fbdadb5e951e4f0c0fc991ff5f50295568786e6
46Author: Nathan Williams <nathan@traverse.com.au>
47Date: Wed Dec 19 11:01:19 2012 +0000
48
49    solos-pci: remove superfluous debug output
50    
51    Signed-off-by: Nathan Williams <nathan@traverse.com.au>
52    Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
53    Signed-off-by: David S. Miller <davem@davemloft.net>
54
55commit f9baad02e7411d9f38d5ebe1a1cdcde4ceec100d
56Author: Nathan Williams <nathan@traverse.com.au>
57Date: Wed Dec 19 11:01:18 2012 +0000
58
59    solos-pci: add GPIO support for newer versions on Geos board
60    
61    dwmw2: Tidy up a little, simpler matching on which GPIO is being accessed,
62           only register on newer boards, register under PCI device instead of
63           duplicating them under each ATM device.
64    
65    Signed-off-by: Nathan Williams <nathan@traverse.com.au>
66    Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
67    Signed-off-by: David S. Miller <davem@davemloft.net>
68
69commit cae49ede00ec3d0cda290b03fee55b72b49efc11
70Author: David Woodhouse <dwmw2@infradead.org>
71Date: Tue Dec 11 14:57:14 2012 +0000
72
73    solos-pci: fix double-free of TX skb in DMA mode
74    
75    We weren't clearing card->tx_skb[port] when processing the TX done interrupt.
76    If there wasn't another skb ready to transmit immediately, this led to a
77    double-free because we'd free it *again* next time we did have a packet to
78    send.
79    
80    Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
81    Cc: stable@kernel.org
82    Signed-off-by: David S. Miller <davem@davemloft.net>
83
84==
85There is a typo here so we do a double lock instead of an unlock.
86
87Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
88---
89Only needed in linux-next. Introduced in f9baad02e7411d9 [14/17]
90solos-pci: add GPIO support for newer versions on Geos board
91
92
93--- a/drivers/atm/solos-pci.c
94+++ b/drivers/atm/solos-pci.c
95@@ -42,7 +42,8 @@
96 #include <linux/swab.h>
97 #include <linux/slab.h>
98 
99-#define VERSION "0.07"
100+#define VERSION "1.04"
101+#define DRIVER_VERSION 0x01
102 #define PTAG "solos-pci"
103 
104 #define CONFIG_RAM_SIZE 128
105@@ -56,16 +57,21 @@
106 #define FLASH_BUSY 0x60
107 #define FPGA_MODE 0x5C
108 #define FLASH_MODE 0x58
109+#define GPIO_STATUS 0x54
110+#define DRIVER_VER 0x50
111 #define TX_DMA_ADDR(port) (0x40 + (4 * (port)))
112 #define RX_DMA_ADDR(port) (0x30 + (4 * (port)))
113 
114 #define DATA_RAM_SIZE 32768
115 #define BUF_SIZE 2048
116 #define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/
117-#define FPGA_PAGE 528 /* FPGA flash page size*/
118-#define SOLOS_PAGE 512 /* Solos flash page size*/
119-#define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/
120-#define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/
121+/* Old boards use ATMEL AD45DB161D flash */
122+#define ATMEL_FPGA_PAGE 528 /* FPGA flash page size*/
123+#define ATMEL_SOLOS_PAGE 512 /* Solos flash page size*/
124+#define ATMEL_FPGA_BLOCK (ATMEL_FPGA_PAGE * 8) /* FPGA block size*/
125+#define ATMEL_SOLOS_BLOCK (ATMEL_SOLOS_PAGE * 8) /* Solos block size*/
126+/* Current boards use M25P/M25PE SPI flash */
127+#define SPI_FLASH_BLOCK (256 * 64)
128 
129 #define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2)
130 #define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size))
131@@ -123,11 +129,14 @@ struct solos_card {
132     struct sk_buff_head cli_queue[4];
133     struct sk_buff *tx_skb[4];
134     struct sk_buff *rx_skb[4];
135+ unsigned char *dma_bounce;
136     wait_queue_head_t param_wq;
137     wait_queue_head_t fw_wq;
138     int using_dma;
139+ int dma_alignment;
140     int fpga_version;
141     int buffer_size;
142+ int atmel_flash;
143 };
144 
145 
146@@ -452,7 +461,6 @@ static ssize_t console_show(struct devic
147 
148     len = skb->len;
149     memcpy(buf, skb->data, len);
150- dev_dbg(&card->dev->dev, "len: %d\n", len);
151 
152     kfree_skb(skb);
153     return len;
154@@ -499,6 +507,78 @@ static ssize_t console_store(struct devi
155     return err?:count;
156 }
157 
158+struct geos_gpio_attr {
159+ struct device_attribute attr;
160+ int offset;
161+};
162+
163+#define SOLOS_GPIO_ATTR(_name, _mode, _show, _store, _offset) \
164+ struct geos_gpio_attr gpio_attr_##_name = { \
165+ .attr = __ATTR(_name, _mode, _show, _store), \
166+ .offset = _offset }
167+
168+static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr,
169+ const char *buf, size_t count)
170+{
171+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
172+ struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
173+ struct solos_card *card = pci_get_drvdata(pdev);
174+ uint32_t data32;
175+
176+ if (count != 1 && (count != 2 || buf[1] != '\n'))
177+ return -EINVAL;
178+
179+ spin_lock_irq(&card->param_queue_lock);
180+ data32 = ioread32(card->config_regs + GPIO_STATUS);
181+ if (buf[0] == '1') {
182+ data32 |= 1 << gattr->offset;
183+ iowrite32(data32, card->config_regs + GPIO_STATUS);
184+ } else if (buf[0] == '0') {
185+ data32 &= ~(1 << gattr->offset);
186+ iowrite32(data32, card->config_regs + GPIO_STATUS);
187+ } else {
188+ count = -EINVAL;
189+ }
190+ spin_unlock_irq(&card->param_queue_lock);
191+ return count;
192+}
193+
194+static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr,
195+ char *buf)
196+{
197+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
198+ struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
199+ struct solos_card *card = pci_get_drvdata(pdev);
200+ uint32_t data32;
201+
202+ data32 = ioread32(card->config_regs + GPIO_STATUS);
203+ data32 = (data32 >> gattr->offset) & 1;
204+
205+ return sprintf(buf, "%d\n", data32);
206+}
207+
208+static ssize_t hardware_show(struct device *dev, struct device_attribute *attr,
209+ char *buf)
210+{
211+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
212+ struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
213+ struct solos_card *card = pci_get_drvdata(pdev);
214+ uint32_t data32;
215+
216+ data32 = ioread32(card->config_regs + GPIO_STATUS);
217+ switch (gattr->offset) {
218+ case 0:
219+ /* HardwareVersion */
220+ data32 = data32 & 0x1F;
221+ break;
222+ case 1:
223+ /* HardwareVariant */
224+ data32 = (data32 >> 5) & 0x0F;
225+ break;
226+ }
227+ return sprintf(buf, "%d\n", data32);
228+}
229+
230 static DEVICE_ATTR(console, 0644, console_show, console_store);
231 
232 
233@@ -507,6 +587,14 @@ static DEVICE_ATTR(console, 0644, consol
234 
235 #include "solos-attrlist.c"
236 
237+static SOLOS_GPIO_ATTR(GPIO1, 0644, geos_gpio_show, geos_gpio_store, 9);
238+static SOLOS_GPIO_ATTR(GPIO2, 0644, geos_gpio_show, geos_gpio_store, 10);
239+static SOLOS_GPIO_ATTR(GPIO3, 0644, geos_gpio_show, geos_gpio_store, 11);
240+static SOLOS_GPIO_ATTR(GPIO4, 0644, geos_gpio_show, geos_gpio_store, 12);
241+static SOLOS_GPIO_ATTR(GPIO5, 0644, geos_gpio_show, geos_gpio_store, 13);
242+static SOLOS_GPIO_ATTR(PushButton, 0444, geos_gpio_show, NULL, 14);
243+static SOLOS_GPIO_ATTR(HardwareVersion, 0444, hardware_show, NULL, 0);
244+static SOLOS_GPIO_ATTR(HardwareVariant, 0444, hardware_show, NULL, 1);
245 #undef SOLOS_ATTR_RO
246 #undef SOLOS_ATTR_RW
247 
248@@ -523,6 +611,23 @@ static struct attribute_group solos_attr
249     .name = "parameters",
250 };
251 
252+static struct attribute *gpio_attrs[] = {
253+ &gpio_attr_GPIO1.attr.attr,
254+ &gpio_attr_GPIO2.attr.attr,
255+ &gpio_attr_GPIO3.attr.attr,
256+ &gpio_attr_GPIO4.attr.attr,
257+ &gpio_attr_GPIO5.attr.attr,
258+ &gpio_attr_PushButton.attr.attr,
259+ &gpio_attr_HardwareVersion.attr.attr,
260+ &gpio_attr_HardwareVariant.attr.attr,
261+ NULL
262+};
263+
264+static struct attribute_group gpio_attr_group = {
265+ .attrs = gpio_attrs,
266+ .name = "gpio",
267+};
268+
269 static int flash_upgrade(struct solos_card *card, int chip)
270 {
271     const struct firmware *fw;
272@@ -534,16 +639,25 @@ static int flash_upgrade(struct solos_ca
273     switch (chip) {
274     case 0:
275         fw_name = "solos-FPGA.bin";
276- blocksize = FPGA_BLOCK;
277+ if (card->atmel_flash)
278+ blocksize = ATMEL_FPGA_BLOCK;
279+ else
280+ blocksize = SPI_FLASH_BLOCK;
281         break;
282     case 1:
283         fw_name = "solos-Firmware.bin";
284- blocksize = SOLOS_BLOCK;
285+ if (card->atmel_flash)
286+ blocksize = ATMEL_SOLOS_BLOCK;
287+ else
288+ blocksize = SPI_FLASH_BLOCK;
289         break;
290     case 2:
291         if (card->fpga_version > LEGACY_BUFFERS){
292             fw_name = "solos-db-FPGA.bin";
293- blocksize = FPGA_BLOCK;
294+ if (card->atmel_flash)
295+ blocksize = ATMEL_FPGA_BLOCK;
296+ else
297+ blocksize = SPI_FLASH_BLOCK;
298         } else {
299             dev_info(&card->dev->dev, "FPGA version doesn't support"
300                     " daughter board upgrades\n");
301@@ -553,7 +667,10 @@ static int flash_upgrade(struct solos_ca
302     case 3:
303         if (card->fpga_version > LEGACY_BUFFERS){
304             fw_name = "solos-Firmware.bin";
305- blocksize = SOLOS_BLOCK;
306+ if (card->atmel_flash)
307+ blocksize = ATMEL_SOLOS_BLOCK;
308+ else
309+ blocksize = SPI_FLASH_BLOCK;
310         } else {
311             dev_info(&card->dev->dev, "FPGA version doesn't support"
312                     " daughter board upgrades\n");
313@@ -569,6 +686,9 @@ static int flash_upgrade(struct solos_ca
314 
315     dev_info(&card->dev->dev, "Flash upgrade starting\n");
316 
317+ /* New FPGAs require driver version before permitting flash upgrades */
318+ iowrite32(DRIVER_VERSION, card->config_regs + DRIVER_VER);
319+
320     numblocks = fw->size / blocksize;
321     dev_info(&card->dev->dev, "Firmware size: %zd\n", fw->size);
322     dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks);
323@@ -598,9 +718,13 @@ static int flash_upgrade(struct solos_ca
324         /* dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n"); */
325         iowrite32(((chip * 2) + 1), card->config_regs + FLASH_MODE);
326 
327- /* Copy block to buffer, swapping each 16 bits */
328+ /* Copy block to buffer, swapping each 16 bits for Atmel flash */
329         for(i = 0; i < blocksize; i += 4) {
330- uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i));
331+ uint32_t word;
332+ if (card->atmel_flash)
333+ word = swahb32p((uint32_t *)(fw->data + offset + i));
334+ else
335+ word = *(uint32_t *)(fw->data + offset + i);
336             if(card->fpga_version > LEGACY_BUFFERS)
337                 iowrite32(word, FLASH_BUF + i);
338             else
339@@ -945,10 +1069,11 @@ static uint32_t fpga_tx(struct solos_car
340     for (port = 0; tx_pending; tx_pending >>= 1, port++) {
341         if (tx_pending & 1) {
342             struct sk_buff *oldskb = card->tx_skb[port];
343- if (oldskb)
344+ if (oldskb) {
345                 pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr,
346                          oldskb->len, PCI_DMA_TODEVICE);
347-
348+ card->tx_skb[port] = NULL;
349+ }
350             spin_lock(&card->tx_queue_lock);
351             skb = skb_dequeue(&card->tx_queue[port]);
352             if (!skb)
353@@ -960,8 +1085,14 @@ static uint32_t fpga_tx(struct solos_car
354                 tx_started |= 1 << port;
355                 oldskb = skb; /* We're done with this skb already */
356             } else if (skb && card->using_dma) {
357- SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data,
358+ unsigned char *data = skb->data;
359+ if ((unsigned long)data & card->dma_alignment) {
360+ data = card->dma_bounce + (BUF_SIZE * port);
361+ memcpy(data, skb->data, skb->len);
362+ }
363+ SKB_CB(skb)->dma_addr = pci_map_single(card->dev, data,
364                                        skb->len, PCI_DMA_TODEVICE);
365+ card->tx_skb[port] = skb;
366                 iowrite32(SKB_CB(skb)->dma_addr,
367                       card->config_regs + TX_DMA_ADDR(port));
368             }
369@@ -1133,17 +1264,33 @@ static int fpga_probe(struct pci_dev *de
370         db_fpga_upgrade = db_firmware_upgrade = 0;
371     }
372 
373- if (card->fpga_version >= DMA_SUPPORTED){
374+ /* Stopped using Atmel flash after 0.03-38 */
375+ if (fpga_ver < 39)
376+ card->atmel_flash = 1;
377+ else
378+ card->atmel_flash = 0;
379+
380+ data32 = ioread32(card->config_regs + PORTS);
381+ card->nr_ports = (data32 & 0x000000FF);
382+
383+ if (card->fpga_version >= DMA_SUPPORTED) {
384+ pci_set_master(dev);
385         card->using_dma = 1;
386+ if (1) { /* All known FPGA versions so far */
387+ card->dma_alignment = 3;
388+ card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL);
389+ if (!card->dma_bounce) {
390+ dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n");
391+ /* Fallback to MMIO doesn't work */
392+ goto out_unmap_both;
393+ }
394+ }
395     } else {
396         card->using_dma = 0;
397         /* Set RX empty flag for all ports */
398         iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
399     }
400 
401- data32 = ioread32(card->config_regs + PORTS);
402- card->nr_ports = (data32 & 0x000000FF);
403-
404     pci_set_drvdata(dev, card);
405 
406     tasklet_init(&card->tlet, solos_bh, (unsigned long)card);
407@@ -1178,6 +1325,10 @@ static int fpga_probe(struct pci_dev *de
408     if (err)
409         goto out_free_irq;
410 
411+ if (card->fpga_version >= DMA_SUPPORTED &&
412+ sysfs_create_group(&card->dev->dev.kobj, &gpio_attr_group))
413+ dev_err(&card->dev->dev, "Could not register parameter group for GPIOs\n");
414+
415     return 0;
416 
417  out_free_irq:
418@@ -1186,6 +1337,7 @@ static int fpga_probe(struct pci_dev *de
419     tasklet_kill(&card->tlet);
420     
421  out_unmap_both:
422+ kfree(card->dma_bounce);
423     pci_set_drvdata(dev, NULL);
424     pci_iounmap(dev, card->buffers);
425  out_unmap_config:
426@@ -1288,11 +1440,16 @@ static void fpga_remove(struct pci_dev *
427     iowrite32(1, card->config_regs + FPGA_MODE);
428     (void)ioread32(card->config_regs + FPGA_MODE);
429 
430+ if (card->fpga_version >= DMA_SUPPORTED)
431+ sysfs_remove_group(&card->dev->dev.kobj, &gpio_attr_group);
432+
433     atm_remove(card);
434 
435     free_irq(dev->irq, card);
436     tasklet_kill(&card->tlet);
437 
438+ kfree(card->dma_bounce);
439+
440     /* Release device from reset */
441     iowrite32(0, card->config_regs + FPGA_MODE);
442     (void)ioread32(card->config_regs + FPGA_MODE);
443

Archive Download this file



interactive