solos: Tidy up DMA handling a little. Still untested
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
909372317e
commit
eaf83e3935
1 changed files with 52 additions and 41 deletions
|
@ -68,6 +68,8 @@
|
||||||
#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2)
|
#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2)
|
||||||
#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE)
|
#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE)
|
||||||
|
|
||||||
|
#define RX_DMA_SIZE 2048
|
||||||
|
|
||||||
static int debug = 0;
|
static int debug = 0;
|
||||||
static int atmdebug = 0;
|
static int atmdebug = 0;
|
||||||
static int firmware_upgrade = 0;
|
static int firmware_upgrade = 0;
|
||||||
|
@ -608,17 +610,11 @@ void solos_bh(unsigned long card_arg)
|
||||||
|
|
||||||
if (card->using_dma) {
|
if (card->using_dma) {
|
||||||
skb = card->rx_skb[port];
|
skb = card->rx_skb[port];
|
||||||
pci_unmap_single(card->dev, SKB_CB(skb)->dma_addr, skb->len,
|
card->rx_skb[port] = NULL;
|
||||||
PCI_DMA_FROMDEVICE);
|
|
||||||
|
pci_unmap_single(card->dev, SKB_CB(skb)->dma_addr,
|
||||||
|
RX_DMA_SIZE, PCI_DMA_FROMDEVICE);
|
||||||
|
|
||||||
card->rx_skb[port] = alloc_skb(2048, GFP_ATOMIC);
|
|
||||||
if (card->rx_skb[port]) {
|
|
||||||
SKB_CB(card->rx_skb[port])->dma_addr =
|
|
||||||
pci_map_single(card->dev, skb->data, skb->len,
|
|
||||||
PCI_DMA_FROMDEVICE);
|
|
||||||
iowrite32(SKB_CB(card->rx_skb[port])->dma_addr,
|
|
||||||
card->config_regs + RX_DMA_ADDR(port));
|
|
||||||
}
|
|
||||||
header = (void *)skb->data;
|
header = (void *)skb->data;
|
||||||
size = le16_to_cpu(header->size);
|
size = le16_to_cpu(header->size);
|
||||||
skb_put(skb, size + sizeof(*header));
|
skb_put(skb, size + sizeof(*header));
|
||||||
|
@ -669,7 +665,7 @@ void solos_bh(unsigned long card_arg)
|
||||||
|
|
||||||
case PKT_STATUS:
|
case PKT_STATUS:
|
||||||
process_status(card, port, skb);
|
process_status(card, port, skb);
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb_any(skb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PKT_COMMAND:
|
case PKT_COMMAND:
|
||||||
|
@ -681,12 +677,32 @@ void solos_bh(unsigned long card_arg)
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
dev_warn(&card->dev->dev, "Dropping console response on port %d\n",
|
dev_warn(&card->dev->dev, "Dropping console response on port %d\n",
|
||||||
port);
|
port);
|
||||||
|
dev_kfree_skb_any(skb);
|
||||||
} else
|
} else
|
||||||
skb_queue_tail(&card->cli_queue[port], skb);
|
skb_queue_tail(&card->cli_queue[port], skb);
|
||||||
spin_unlock(&card->cli_queue_lock);
|
spin_unlock(&card->cli_queue_lock);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Allocate RX skbs for any ports which need them */
|
||||||
|
if (card->using_dma && card->atmdev[port] &&
|
||||||
|
!card->rx_skb[port]) {
|
||||||
|
struct sk_buff *skb = alloc_skb(RX_DMA_SIZE, GFP_ATOMIC);
|
||||||
|
if (skb) {
|
||||||
|
SKB_CB(skb)->dma_addr =
|
||||||
|
pci_map_single(card->dev, skb->data,
|
||||||
|
RX_DMA_SIZE, PCI_DMA_FROMDEVICE);
|
||||||
|
iowrite32(SKB_CB(skb)->dma_addr,
|
||||||
|
card->config_regs + RX_DMA_ADDR(port));
|
||||||
|
card->rx_skb[port] = skb;
|
||||||
|
} else {
|
||||||
|
if (net_ratelimit())
|
||||||
|
dev_warn(&card->dev->dev, "Failed to allocate RX skb");
|
||||||
|
|
||||||
|
/* We'll have to try again later */
|
||||||
|
tasklet_schedule(&card->tlet);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (rx_done)
|
if (rx_done)
|
||||||
iowrite32(rx_done, card->config_regs + FLAGS_ADDR);
|
iowrite32(rx_done, card->config_regs + FLAGS_ADDR);
|
||||||
|
@ -901,50 +917,45 @@ static int fpga_tx(struct solos_card *card)
|
||||||
|
|
||||||
for (port = 0; port < card->nr_ports; port++) {
|
for (port = 0; port < card->nr_ports; port++) {
|
||||||
if (card->atmdev[port] && !(tx_pending & (1 << port))) {
|
if (card->atmdev[port] && !(tx_pending & (1 << port))) {
|
||||||
|
struct sk_buff *oldskb = card->tx_skb[port];
|
||||||
|
|
||||||
|
if (oldskb)
|
||||||
|
pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr,
|
||||||
|
oldskb->len, PCI_DMA_TODEVICE);
|
||||||
|
|
||||||
spin_lock(&card->tx_queue_lock);
|
spin_lock(&card->tx_queue_lock);
|
||||||
skb = skb_dequeue(&card->tx_queue[port]);
|
skb = skb_dequeue(&card->tx_queue[port]);
|
||||||
spin_unlock(&card->tx_queue_lock);
|
spin_unlock(&card->tx_queue_lock);
|
||||||
|
|
||||||
if (!skb)
|
if (skb && !card->using_dma) {
|
||||||
|
memcpy_toio(TX_BUF(card, port), skb->data, skb->len);
|
||||||
|
tx_started |= 1 << port; //Set TX full flag
|
||||||
|
oldskb = skb; /* We're done with this skb already */
|
||||||
|
} else if (skb && card->using_dma) {
|
||||||
|
SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data,
|
||||||
|
skb->len, PCI_DMA_TODEVICE);
|
||||||
|
iowrite32(SKB_CB(skb)->dma_addr,
|
||||||
|
card->config_regs + TX_DMA_ADDR(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!oldskb)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Clean up and free oldskb now it's gone */
|
||||||
if (atmdebug) {
|
if (atmdebug) {
|
||||||
dev_info(&card->dev->dev, "Transmitted: port %d\n",
|
dev_info(&card->dev->dev, "Transmitted: port %d\n",
|
||||||
port);
|
port);
|
||||||
print_buffer(skb);
|
print_buffer(oldskb);
|
||||||
}
|
}
|
||||||
if (card->using_dma) {
|
|
||||||
if (card->tx_skb[port]) {
|
|
||||||
struct sk_buff *oldskb = card->tx_skb[port];
|
|
||||||
|
|
||||||
pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr,
|
vcc = SKB_CB(oldskb)->vcc;
|
||||||
oldskb->len, PCI_DMA_TODEVICE);
|
|
||||||
|
|
||||||
vcc = SKB_CB(oldskb)->vcc;
|
if (vcc) {
|
||||||
|
atomic_inc(&vcc->stats->tx);
|
||||||
|
solos_pop(vcc, oldskb);
|
||||||
|
} else
|
||||||
|
dev_kfree_skb_irq(oldskb);
|
||||||
|
|
||||||
if (vcc) {
|
|
||||||
atomic_inc(&vcc->stats->tx);
|
|
||||||
solos_pop(vcc, oldskb);
|
|
||||||
} else
|
|
||||||
dev_kfree_skb_irq(oldskb);
|
|
||||||
}
|
|
||||||
|
|
||||||
SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data,
|
|
||||||
skb->len, PCI_DMA_TODEVICE);
|
|
||||||
iowrite32(SKB_CB(skb)->dma_addr, card->config_regs + TX_DMA_ADDR(port));
|
|
||||||
} else {
|
|
||||||
memcpy_toio(TX_BUF(card, port), skb->data, skb->len);
|
|
||||||
tx_started |= 1 << port; //Set TX full flag
|
|
||||||
|
|
||||||
vcc = SKB_CB(skb)->vcc;
|
|
||||||
|
|
||||||
if (vcc) {
|
|
||||||
atomic_inc(&vcc->stats->tx);
|
|
||||||
solos_pop(vcc, skb);
|
|
||||||
} else
|
|
||||||
dev_kfree_skb_irq(skb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tx_started)
|
if (tx_started)
|
||||||
|
|
Loading…
Reference in a new issue