Commit 152a2a8b5e1d4cbe91a7c66f1028db15164a3766
Committed by
David S. Miller
1 parent
13af816469
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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>
Showing 1 changed file with 23 additions and 4 deletions Side-by-side Diff
drivers/atm/solos-pci.c
... | ... | @@ -128,9 +128,11 @@ |
128 | 128 | struct sk_buff_head cli_queue[4]; |
129 | 129 | struct sk_buff *tx_skb[4]; |
130 | 130 | struct sk_buff *rx_skb[4]; |
131 | + unsigned char *dma_bounce; | |
131 | 132 | wait_queue_head_t param_wq; |
132 | 133 | wait_queue_head_t fw_wq; |
133 | 134 | int using_dma; |
135 | + int dma_alignment; | |
134 | 136 | int fpga_version; |
135 | 137 | int buffer_size; |
136 | 138 | int atmel_flash; |
... | ... | @@ -1083,7 +1085,12 @@ |
1083 | 1085 | tx_started |= 1 << port; |
1084 | 1086 | oldskb = skb; /* We're done with this skb already */ |
1085 | 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 | 1094 | skb->len, PCI_DMA_TODEVICE); |
1088 | 1095 | card->tx_skb[port] = skb; |
1089 | 1096 | iowrite32(SKB_CB(skb)->dma_addr, |
1090 | 1097 | |
1091 | 1098 | |
... | ... | @@ -1261,18 +1268,27 @@ |
1261 | 1268 | else |
1262 | 1269 | card->atmel_flash = 0; |
1263 | 1270 | |
1271 | + data32 = ioread32(card->config_regs + PORTS); | |
1272 | + card->nr_ports = (data32 & 0x000000FF); | |
1273 | + | |
1264 | 1274 | if (card->fpga_version >= DMA_SUPPORTED) { |
1265 | 1275 | pci_set_master(dev); |
1266 | 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 | 1286 | } else { |
1268 | 1287 | card->using_dma = 0; |
1269 | 1288 | /* Set RX empty flag for all ports */ |
1270 | 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 | 1292 | pci_set_drvdata(dev, card); |
1277 | 1293 | |
1278 | 1294 | tasklet_init(&card->tlet, solos_bh, (unsigned long)card); |
... | ... | @@ -1319,6 +1335,7 @@ |
1319 | 1335 | tasklet_kill(&card->tlet); |
1320 | 1336 | |
1321 | 1337 | out_unmap_both: |
1338 | + kfree(card->dma_bounce); | |
1322 | 1339 | pci_set_drvdata(dev, NULL); |
1323 | 1340 | pci_iounmap(dev, card->buffers); |
1324 | 1341 | out_unmap_config: |
... | ... | @@ -1428,6 +1445,8 @@ |
1428 | 1445 | |
1429 | 1446 | free_irq(dev->irq, card); |
1430 | 1447 | tasklet_kill(&card->tlet); |
1448 | + | |
1449 | + kfree(card->dma_bounce); | |
1431 | 1450 | |
1432 | 1451 | /* Release device from reset */ |
1433 | 1452 | iowrite32(0, card->config_regs + FPGA_MODE); |