diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2012-12-19 06:01:21 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-12-19 17:53:53 -0500 |
commit | 152a2a8b5e1d4cbe91a7c66f1028db15164a3766 (patch) | |
tree | 2a3cc4287755749cc5e4e6a7fe837ab69b6a5703 /drivers | |
parent | 13af816469db3449c072afbae6c4c1bd9ccecccb (diff) |
solos-pci: ensure all TX packets are aligned to 4 bytes
The FPGA can't handled unaligned DMA (yet). So copy into an aligned buffer,
if skb->data isn't suitably aligned.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/atm/solos-pci.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index aa4f35d52a92..d70abe77f737 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c | |||
@@ -128,9 +128,11 @@ struct solos_card { | |||
128 | struct sk_buff_head cli_queue[4]; | 128 | struct sk_buff_head cli_queue[4]; |
129 | struct sk_buff *tx_skb[4]; | 129 | struct sk_buff *tx_skb[4]; |
130 | struct sk_buff *rx_skb[4]; | 130 | struct sk_buff *rx_skb[4]; |
131 | unsigned char *dma_bounce; | ||
131 | wait_queue_head_t param_wq; | 132 | wait_queue_head_t param_wq; |
132 | wait_queue_head_t fw_wq; | 133 | wait_queue_head_t fw_wq; |
133 | int using_dma; | 134 | int using_dma; |
135 | int dma_alignment; | ||
134 | int fpga_version; | 136 | int fpga_version; |
135 | int buffer_size; | 137 | int buffer_size; |
136 | int atmel_flash; | 138 | int atmel_flash; |
@@ -1083,7 +1085,12 @@ static uint32_t fpga_tx(struct solos_card *card) | |||
1083 | tx_started |= 1 << port; | 1085 | tx_started |= 1 << port; |
1084 | oldskb = skb; /* We're done with this skb already */ | 1086 | oldskb = skb; /* We're done with this skb already */ |
1085 | } else if (skb && card->using_dma) { | 1087 | } else if (skb && card->using_dma) { |
1086 | SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data, | 1088 | unsigned char *data = skb->data; |
1089 | if ((unsigned long)data & card->dma_alignment) { | ||
1090 | data = card->dma_bounce + (BUF_SIZE * port); | ||
1091 | memcpy(data, skb->data, skb->len); | ||
1092 | } | ||
1093 | SKB_CB(skb)->dma_addr = pci_map_single(card->dev, data, | ||
1087 | skb->len, PCI_DMA_TODEVICE); | 1094 | skb->len, PCI_DMA_TODEVICE); |
1088 | card->tx_skb[port] = skb; | 1095 | card->tx_skb[port] = skb; |
1089 | iowrite32(SKB_CB(skb)->dma_addr, | 1096 | iowrite32(SKB_CB(skb)->dma_addr, |
@@ -1261,18 +1268,27 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1261 | else | 1268 | else |
1262 | card->atmel_flash = 0; | 1269 | card->atmel_flash = 0; |
1263 | 1270 | ||
1271 | data32 = ioread32(card->config_regs + PORTS); | ||
1272 | card->nr_ports = (data32 & 0x000000FF); | ||
1273 | |||
1264 | if (card->fpga_version >= DMA_SUPPORTED) { | 1274 | if (card->fpga_version >= DMA_SUPPORTED) { |
1265 | pci_set_master(dev); | 1275 | pci_set_master(dev); |
1266 | card->using_dma = 1; | 1276 | card->using_dma = 1; |
1277 | if (1) { /* All known FPGA versions so far */ | ||
1278 | card->dma_alignment = 3; | ||
1279 | card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL); | ||
1280 | if (!card->dma_bounce) { | ||
1281 | dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n"); | ||
1282 | /* Fallback to MMIO doesn't work */ | ||
1283 | goto out_unmap_both; | ||
1284 | } | ||
1285 | } | ||
1267 | } else { | 1286 | } else { |
1268 | card->using_dma = 0; | 1287 | card->using_dma = 0; |
1269 | /* Set RX empty flag for all ports */ | 1288 | /* Set RX empty flag for all ports */ |
1270 | iowrite32(0xF0, card->config_regs + FLAGS_ADDR); | 1289 | iowrite32(0xF0, card->config_regs + FLAGS_ADDR); |
1271 | } | 1290 | } |
1272 | 1291 | ||
1273 | data32 = ioread32(card->config_regs + PORTS); | ||
1274 | card->nr_ports = (data32 & 0x000000FF); | ||
1275 | |||
1276 | pci_set_drvdata(dev, card); | 1292 | pci_set_drvdata(dev, card); |
1277 | 1293 | ||
1278 | tasklet_init(&card->tlet, solos_bh, (unsigned long)card); | 1294 | tasklet_init(&card->tlet, solos_bh, (unsigned long)card); |
@@ -1319,6 +1335,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1319 | tasklet_kill(&card->tlet); | 1335 | tasklet_kill(&card->tlet); |
1320 | 1336 | ||
1321 | out_unmap_both: | 1337 | out_unmap_both: |
1338 | kfree(card->dma_bounce); | ||
1322 | pci_set_drvdata(dev, NULL); | 1339 | pci_set_drvdata(dev, NULL); |
1323 | pci_iounmap(dev, card->buffers); | 1340 | pci_iounmap(dev, card->buffers); |
1324 | out_unmap_config: | 1341 | out_unmap_config: |
@@ -1429,6 +1446,8 @@ static void fpga_remove(struct pci_dev *dev) | |||
1429 | free_irq(dev->irq, card); | 1446 | free_irq(dev->irq, card); |
1430 | tasklet_kill(&card->tlet); | 1447 | tasklet_kill(&card->tlet); |
1431 | 1448 | ||
1449 | kfree(card->dma_bounce); | ||
1450 | |||
1432 | /* Release device from reset */ | 1451 | /* Release device from reset */ |
1433 | iowrite32(0, card->config_regs + FPGA_MODE); | 1452 | iowrite32(0, card->config_regs + FPGA_MODE); |
1434 | (void)ioread32(card->config_regs + FPGA_MODE); | 1453 | (void)ioread32(card->config_regs + FPGA_MODE); |