Skip to content

Commit 152a2a8

Browse files
David Woodhousedavem330
authored andcommitted
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>
1 parent 13af816 commit 152a2a8

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

drivers/atm/solos-pci.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,11 @@ struct solos_card {
128128
struct sk_buff_head cli_queue[4];
129129
struct sk_buff *tx_skb[4];
130130
struct sk_buff *rx_skb[4];
131+
unsigned char *dma_bounce;
131132
wait_queue_head_t param_wq;
132133
wait_queue_head_t fw_wq;
133134
int using_dma;
135+
int dma_alignment;
134136
int fpga_version;
135137
int buffer_size;
136138
int atmel_flash;
@@ -1083,7 +1085,12 @@ static uint32_t fpga_tx(struct solos_card *card)
10831085
tx_started |= 1 << port;
10841086
oldskb = skb; /* We're done with this skb already */
10851087
} 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,
10871094
skb->len, PCI_DMA_TODEVICE);
10881095
card->tx_skb[port] = skb;
10891096
iowrite32(SKB_CB(skb)->dma_addr,
@@ -1261,18 +1268,27 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
12611268
else
12621269
card->atmel_flash = 0;
12631270

1271+
data32 = ioread32(card->config_regs + PORTS);
1272+
card->nr_ports = (data32 & 0x000000FF);
1273+
12641274
if (card->fpga_version >= DMA_SUPPORTED) {
12651275
pci_set_master(dev);
12661276
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+
}
12671286
} else {
12681287
card->using_dma = 0;
12691288
/* Set RX empty flag for all ports */
12701289
iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
12711290
}
12721291

1273-
data32 = ioread32(card->config_regs + PORTS);
1274-
card->nr_ports = (data32 & 0x000000FF);
1275-
12761292
pci_set_drvdata(dev, card);
12771293

12781294
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)
13191335
tasklet_kill(&card->tlet);
13201336

13211337
out_unmap_both:
1338+
kfree(card->dma_bounce);
13221339
pci_set_drvdata(dev, NULL);
13231340
pci_iounmap(dev, card->buffers);
13241341
out_unmap_config:
@@ -1429,6 +1446,8 @@ static void fpga_remove(struct pci_dev *dev)
14291446
free_irq(dev->irq, card);
14301447
tasklet_kill(&card->tlet);
14311448

1449+
kfree(card->dma_bounce);
1450+
14321451
/* Release device from reset */
14331452
iowrite32(0, card->config_regs + FPGA_MODE);
14341453
(void)ioread32(card->config_regs + FPGA_MODE);

0 commit comments

Comments
 (0)