diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2009-01-28 18:51:11 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-01-28 18:51:11 -0500 |
commit | eaf83e39355a0a8933a003fa3b27b37d19901d64 (patch) | |
tree | fd254da17db437e25337767c2aeeb4b1c4ad40ec /drivers/atm | |
parent | 909372317e67bdbbfced5dab3ade3437e3f2b254 (diff) |
solos: Tidy up DMA handling a little. Still untested
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/atm')
-rw-r--r-- | drivers/atm/solos-pci.c | 95 |
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 | |||
71 | static int debug = 0; | 73 | static int debug = 0; |
72 | static int atmdebug = 0; | 74 | static int atmdebug = 0; |
73 | static int firmware_upgrade = 0; | 75 | static 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) |