132-solos-dma.patch 14 KB

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