aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2009-01-28 18:51:11 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-01-28 18:51:11 -0500
commiteaf83e39355a0a8933a003fa3b27b37d19901d64 (patch)
treefd254da17db437e25337767c2aeeb4b1c4ad40ec
parent909372317e67bdbbfced5dab3ade3437e3f2b254 (diff)
solos: Tidy up DMA handling a little. Still untested
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--drivers/atm/solos-pci.c95
1 files changed, 53 insertions, 42 deletions
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 63c9ad03aec8..acba08df5eb0 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -68,6 +68,8 @@
68#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2) 68#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2)
69#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE) 69#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE)
70 70
71#define RX_DMA_SIZE 2048
72
71static int debug = 0; 73static int debug = 0;
72static int atmdebug = 0; 74static int atmdebug = 0;
73static int firmware_upgrade = 0; 75static int firmware_upgrade = 0;
@@ -608,17 +610,11 @@ void solos_bh(unsigned long card_arg)
608 610
609 if (card->using_dma) { 611 if (card->using_dma) {
610 skb = card->rx_skb[port]; 612 skb = card->rx_skb[port];
611 pci_unmap_single(card->dev, SKB_CB(skb)->dma_addr, skb->len, 613 card->rx_skb[port] = NULL;
612 PCI_DMA_FROMDEVICE); 614
613 615 pci_unmap_single(card->dev, SKB_CB(skb)->dma_addr,
614 card->rx_skb[port] = alloc_skb(2048, GFP_ATOMIC); 616 RX_DMA_SIZE, PCI_DMA_FROMDEVICE);
615 if (card->rx_skb[port]) { 617
616 SKB_CB(card->rx_skb[port])->dma_addr =
617 pci_map_single(card->dev, skb->data, skb->len,
618 PCI_DMA_FROMDEVICE);
619 iowrite32(SKB_CB(card->rx_skb[port])->dma_addr,
620 card->config_regs + RX_DMA_ADDR(port));
621 }
622 header = (void *)skb->data; 618 header = (void *)skb->data;
623 size = le16_to_cpu(header->size); 619 size = le16_to_cpu(header->size);
624 skb_put(skb, size + sizeof(*header)); 620 skb_put(skb, size + sizeof(*header));
@@ -669,7 +665,7 @@ void solos_bh(unsigned long card_arg)
669 665
670 case PKT_STATUS: 666 case PKT_STATUS:
671 process_status(card, port, skb); 667 process_status(card, port, skb);
672 dev_kfree_skb(skb); 668 dev_kfree_skb_any(skb);
673 break; 669 break;
674 670
675 case PKT_COMMAND: 671 case PKT_COMMAND:
@@ -681,12 +677,32 @@ void solos_bh(unsigned long card_arg)
681 if (net_ratelimit()) 677 if (net_ratelimit())
682 dev_warn(&card->dev->dev, "Dropping console response on port %d\n", 678 dev_warn(&card->dev->dev, "Dropping console response on port %d\n",
683 port); 679 port);
680 dev_kfree_skb_any(skb);
684 } else 681 } else
685 skb_queue_tail(&card->cli_queue[port], skb); 682 skb_queue_tail(&card->cli_queue[port], skb);
686 spin_unlock(&card->cli_queue_lock); 683 spin_unlock(&card->cli_queue_lock);
687 break; 684 break;
688 } 685 }
689 } 686 }
687 /* Allocate RX skbs for any ports which need them */
688 if (card->using_dma && card->atmdev[port] &&
689 !card->rx_skb[port]) {
690 struct sk_buff *skb = alloc_skb(RX_DMA_SIZE, GFP_ATOMIC);
691 if (skb) {
692 SKB_CB(skb)->dma_addr =
693 pci_map_single(card->dev, skb->data,
694 RX_DMA_SIZE, PCI_DMA_FROMDEVICE);
695 iowrite32(SKB_CB(skb)->dma_addr,
696 card->config_regs + RX_DMA_ADDR(port));
697 card->rx_skb[port] = skb;
698 } else {
699 if (net_ratelimit())
700 dev_warn(&card->dev->dev, "Failed to allocate RX skb");
701
702 /* We'll have to try again later */
703 tasklet_schedule(&card->tlet);
704 }
705 }
690 } 706 }
691 if (rx_done) 707 if (rx_done)
692 iowrite32(rx_done, card->config_regs + FLAGS_ADDR); 708 iowrite32(rx_done, card->config_regs + FLAGS_ADDR);
@@ -901,50 +917,45 @@ static int fpga_tx(struct solos_card *card)
901 917
902 for (port = 0; port < card->nr_ports; port++) { 918 for (port = 0; port < card->nr_ports; port++) {
903 if (card->atmdev[port] && !(tx_pending & (1 << port))) { 919 if (card->atmdev[port] && !(tx_pending & (1 << port))) {
920 struct sk_buff *oldskb = card->tx_skb[port];
904 921
922 if (oldskb)
923 pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr,
924 oldskb->len, PCI_DMA_TODEVICE);
925
905 spin_lock(&card->tx_queue_lock); 926 spin_lock(&card->tx_queue_lock);
906 skb = skb_dequeue(&card->tx_queue[port]); 927 skb = skb_dequeue(&card->tx_queue[port]);
907 spin_unlock(&card->tx_queue_lock); 928 spin_unlock(&card->tx_queue_lock);
908 929
909 if (!skb) 930 if (skb && !card->using_dma) {
931 memcpy_toio(TX_BUF(card, port), skb->data, skb->len);
932 tx_started |= 1 << port; //Set TX full flag
933 oldskb = skb; /* We're done with this skb already */
934 } else if (skb && card->using_dma) {
935 SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data,
936 skb->len, PCI_DMA_TODEVICE);
937 iowrite32(SKB_CB(skb)->dma_addr,
938 card->config_regs + TX_DMA_ADDR(port));
939 }
940
941 if (!oldskb)
910 continue; 942 continue;
911 943
944 /* Clean up and free oldskb now it's gone */
912 if (atmdebug) { 945 if (atmdebug) {
913 dev_info(&card->dev->dev, "Transmitted: port %d\n", 946 dev_info(&card->dev->dev, "Transmitted: port %d\n",
914 port); 947 port);
915 print_buffer(skb); 948 print_buffer(oldskb);
916 } 949 }
917 if (card->using_dma) {
918 if (card->tx_skb[port]) {
919 struct sk_buff *oldskb = card->tx_skb[port];
920
921 pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr,
922 oldskb->len, PCI_DMA_TODEVICE);
923
924 vcc = SKB_CB(oldskb)->vcc;
925
926 if (vcc) {
927 atomic_inc(&vcc->stats->tx);
928 solos_pop(vcc, oldskb);
929 } else
930 dev_kfree_skb_irq(oldskb);
931 }
932 950
933 SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data, 951 vcc = SKB_CB(oldskb)->vcc;
934 skb->len, PCI_DMA_TODEVICE);
935 iowrite32(SKB_CB(skb)->dma_addr, card->config_regs + TX_DMA_ADDR(port));
936 } else {
937 memcpy_toio(TX_BUF(card, port), skb->data, skb->len);
938 tx_started |= 1 << port; //Set TX full flag
939 952
940 vcc = SKB_CB(skb)->vcc; 953 if (vcc) {
954 atomic_inc(&vcc->stats->tx);
955 solos_pop(vcc, oldskb);
956 } else
957 dev_kfree_skb_irq(oldskb);
941 958
942 if (vcc) {
943 atomic_inc(&vcc->stats->tx);
944 solos_pop(vcc, skb);
945 } else
946 dev_kfree_skb_irq(skb);
947 }
948 } 959 }
949 } 960 }
950 if (tx_started) 961 if (tx_started)