Commit 152a2a8b5e1d4cbe91a7c66f1028db15164a3766

Authored by David Woodhouse
Committed by David S. Miller
1 parent 13af816469

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);