Commit 152a2a8b authored by David Woodhouse's avatar David Woodhouse Committed by David S. Miller

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: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 13af8164
...@@ -128,9 +128,11 @@ struct solos_card { ...@@ -128,9 +128,11 @@ struct solos_card {
struct sk_buff_head cli_queue[4]; struct sk_buff_head cli_queue[4];
struct sk_buff *tx_skb[4]; struct sk_buff *tx_skb[4];
struct sk_buff *rx_skb[4]; struct sk_buff *rx_skb[4];
unsigned char *dma_bounce;
wait_queue_head_t param_wq; wait_queue_head_t param_wq;
wait_queue_head_t fw_wq; wait_queue_head_t fw_wq;
int using_dma; int using_dma;
int dma_alignment;
int fpga_version; int fpga_version;
int buffer_size; int buffer_size;
int atmel_flash; int atmel_flash;
...@@ -1083,7 +1085,12 @@ static uint32_t fpga_tx(struct solos_card *card) ...@@ -1083,7 +1085,12 @@ static uint32_t fpga_tx(struct solos_card *card)
tx_started |= 1 << port; tx_started |= 1 << port;
oldskb = skb; /* We're done with this skb already */ oldskb = skb; /* We're done with this skb already */
} else if (skb && card->using_dma) { } else if (skb && card->using_dma) {
SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data, unsigned char *data = skb->data;
if ((unsigned long)data & card->dma_alignment) {
data = card->dma_bounce + (BUF_SIZE * port);
memcpy(data, skb->data, skb->len);
}
SKB_CB(skb)->dma_addr = pci_map_single(card->dev, data,
skb->len, PCI_DMA_TODEVICE); skb->len, PCI_DMA_TODEVICE);
card->tx_skb[port] = skb; card->tx_skb[port] = skb;
iowrite32(SKB_CB(skb)->dma_addr, 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,18 +1268,27 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
else else
card->atmel_flash = 0; card->atmel_flash = 0;
data32 = ioread32(card->config_regs + PORTS);
card->nr_ports = (data32 & 0x000000FF);
if (card->fpga_version >= DMA_SUPPORTED) { if (card->fpga_version >= DMA_SUPPORTED) {
pci_set_master(dev); pci_set_master(dev);
card->using_dma = 1; card->using_dma = 1;
if (1) { /* All known FPGA versions so far */
card->dma_alignment = 3;
card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL);
if (!card->dma_bounce) {
dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n");
/* Fallback to MMIO doesn't work */
goto out_unmap_both;
}
}
} else { } else {
card->using_dma = 0; card->using_dma = 0;
/* Set RX empty flag for all ports */ /* Set RX empty flag for all ports */
iowrite32(0xF0, card->config_regs + FLAGS_ADDR); iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
} }
data32 = ioread32(card->config_regs + PORTS);
card->nr_ports = (data32 & 0x000000FF);
pci_set_drvdata(dev, card); pci_set_drvdata(dev, card);
tasklet_init(&card->tlet, solos_bh, (unsigned long)card); 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,6 +1335,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
tasklet_kill(&card->tlet); tasklet_kill(&card->tlet);
out_unmap_both: out_unmap_both:
kfree(card->dma_bounce);
pci_set_drvdata(dev, NULL); pci_set_drvdata(dev, NULL);
pci_iounmap(dev, card->buffers); pci_iounmap(dev, card->buffers);
out_unmap_config: out_unmap_config:
...@@ -1429,6 +1446,8 @@ static void fpga_remove(struct pci_dev *dev) ...@@ -1429,6 +1446,8 @@ static void fpga_remove(struct pci_dev *dev)
free_irq(dev->irq, card); free_irq(dev->irq, card);
tasklet_kill(&card->tlet); tasklet_kill(&card->tlet);
kfree(card->dma_bounce);
/* Release device from reset */ /* Release device from reset */
iowrite32(0, card->config_regs + FPGA_MODE); iowrite32(0, card->config_regs + FPGA_MODE);
(void)ioread32(card->config_regs + FPGA_MODE); (void)ioread32(card->config_regs + FPGA_MODE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment