diff options
Diffstat (limited to 'drivers/net/spider_net.c')
-rw-r--r-- | drivers/net/spider_net.c | 246 |
1 files changed, 148 insertions, 98 deletions
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 46a009085f7c..418138dd6c68 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c | |||
@@ -55,12 +55,13 @@ MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com> and Jens Osterkamp " \ | |||
55 | "<Jens.Osterkamp@de.ibm.com>"); | 55 | "<Jens.Osterkamp@de.ibm.com>"); |
56 | MODULE_DESCRIPTION("Spider Southbridge Gigabit Ethernet driver"); | 56 | MODULE_DESCRIPTION("Spider Southbridge Gigabit Ethernet driver"); |
57 | MODULE_LICENSE("GPL"); | 57 | MODULE_LICENSE("GPL"); |
58 | MODULE_VERSION(VERSION); | ||
58 | 59 | ||
59 | static int rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_DEFAULT; | 60 | static int rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_DEFAULT; |
60 | static int tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_DEFAULT; | 61 | static int tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_DEFAULT; |
61 | 62 | ||
62 | module_param(rx_descriptors, int, 0644); | 63 | module_param(rx_descriptors, int, 0444); |
63 | module_param(tx_descriptors, int, 0644); | 64 | module_param(tx_descriptors, int, 0444); |
64 | 65 | ||
65 | MODULE_PARM_DESC(rx_descriptors, "number of descriptors used " \ | 66 | MODULE_PARM_DESC(rx_descriptors, "number of descriptors used " \ |
66 | "in rx chains"); | 67 | "in rx chains"); |
@@ -300,7 +301,7 @@ static int | |||
300 | spider_net_init_chain(struct spider_net_card *card, | 301 | spider_net_init_chain(struct spider_net_card *card, |
301 | struct spider_net_descr_chain *chain, | 302 | struct spider_net_descr_chain *chain, |
302 | struct spider_net_descr *start_descr, | 303 | struct spider_net_descr *start_descr, |
303 | int direction, int no) | 304 | int no) |
304 | { | 305 | { |
305 | int i; | 306 | int i; |
306 | struct spider_net_descr *descr; | 307 | struct spider_net_descr *descr; |
@@ -315,7 +316,7 @@ spider_net_init_chain(struct spider_net_card *card, | |||
315 | 316 | ||
316 | buf = pci_map_single(card->pdev, descr, | 317 | buf = pci_map_single(card->pdev, descr, |
317 | SPIDER_NET_DESCR_SIZE, | 318 | SPIDER_NET_DESCR_SIZE, |
318 | direction); | 319 | PCI_DMA_BIDIRECTIONAL); |
319 | 320 | ||
320 | if (pci_dma_mapping_error(buf)) | 321 | if (pci_dma_mapping_error(buf)) |
321 | goto iommu_error; | 322 | goto iommu_error; |
@@ -329,11 +330,6 @@ spider_net_init_chain(struct spider_net_card *card, | |||
329 | (descr-1)->next = start_descr; | 330 | (descr-1)->next = start_descr; |
330 | start_descr->prev = descr-1; | 331 | start_descr->prev = descr-1; |
331 | 332 | ||
332 | descr = start_descr; | ||
333 | if (direction == PCI_DMA_FROMDEVICE) | ||
334 | for (i=0; i < no; i++, descr++) | ||
335 | descr->next_descr_addr = descr->next->bus_addr; | ||
336 | |||
337 | spin_lock_init(&chain->lock); | 333 | spin_lock_init(&chain->lock); |
338 | chain->head = start_descr; | 334 | chain->head = start_descr; |
339 | chain->tail = start_descr; | 335 | chain->tail = start_descr; |
@@ -346,7 +342,7 @@ iommu_error: | |||
346 | if (descr->bus_addr) | 342 | if (descr->bus_addr) |
347 | pci_unmap_single(card->pdev, descr->bus_addr, | 343 | pci_unmap_single(card->pdev, descr->bus_addr, |
348 | SPIDER_NET_DESCR_SIZE, | 344 | SPIDER_NET_DESCR_SIZE, |
349 | direction); | 345 | PCI_DMA_BIDIRECTIONAL); |
350 | return -ENOMEM; | 346 | return -ENOMEM; |
351 | } | 347 | } |
352 | 348 | ||
@@ -362,15 +358,15 @@ spider_net_free_rx_chain_contents(struct spider_net_card *card) | |||
362 | struct spider_net_descr *descr; | 358 | struct spider_net_descr *descr; |
363 | 359 | ||
364 | descr = card->rx_chain.head; | 360 | descr = card->rx_chain.head; |
365 | while (descr->next != card->rx_chain.head) { | 361 | do { |
366 | if (descr->skb) { | 362 | if (descr->skb) { |
367 | dev_kfree_skb(descr->skb); | 363 | dev_kfree_skb(descr->skb); |
368 | pci_unmap_single(card->pdev, descr->buf_addr, | 364 | pci_unmap_single(card->pdev, descr->buf_addr, |
369 | SPIDER_NET_MAX_FRAME, | 365 | SPIDER_NET_MAX_FRAME, |
370 | PCI_DMA_FROMDEVICE); | 366 | PCI_DMA_BIDIRECTIONAL); |
371 | } | 367 | } |
372 | descr = descr->next; | 368 | descr = descr->next; |
373 | } | 369 | } while (descr != card->rx_chain.head); |
374 | } | 370 | } |
375 | 371 | ||
376 | /** | 372 | /** |
@@ -645,26 +641,41 @@ static int | |||
645 | spider_net_prepare_tx_descr(struct spider_net_card *card, | 641 | spider_net_prepare_tx_descr(struct spider_net_card *card, |
646 | struct sk_buff *skb) | 642 | struct sk_buff *skb) |
647 | { | 643 | { |
648 | struct spider_net_descr *descr = card->tx_chain.head; | 644 | struct spider_net_descr *descr; |
649 | dma_addr_t buf; | 645 | dma_addr_t buf; |
646 | unsigned long flags; | ||
647 | int length; | ||
650 | 648 | ||
651 | buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); | 649 | length = skb->len; |
650 | if (length < ETH_ZLEN) { | ||
651 | if (skb_pad(skb, ETH_ZLEN-length)) | ||
652 | return 0; | ||
653 | length = ETH_ZLEN; | ||
654 | } | ||
655 | |||
656 | buf = pci_map_single(card->pdev, skb->data, length, PCI_DMA_TODEVICE); | ||
652 | if (pci_dma_mapping_error(buf)) { | 657 | if (pci_dma_mapping_error(buf)) { |
653 | if (netif_msg_tx_err(card) && net_ratelimit()) | 658 | if (netif_msg_tx_err(card) && net_ratelimit()) |
654 | pr_err("could not iommu-map packet (%p, %i). " | 659 | pr_err("could not iommu-map packet (%p, %i). " |
655 | "Dropping packet\n", skb->data, skb->len); | 660 | "Dropping packet\n", skb->data, length); |
656 | card->spider_stats.tx_iommu_map_error++; | 661 | card->spider_stats.tx_iommu_map_error++; |
657 | return -ENOMEM; | 662 | return -ENOMEM; |
658 | } | 663 | } |
659 | 664 | ||
665 | spin_lock_irqsave(&card->tx_chain.lock, flags); | ||
666 | descr = card->tx_chain.head; | ||
667 | card->tx_chain.head = descr->next; | ||
668 | |||
660 | descr->buf_addr = buf; | 669 | descr->buf_addr = buf; |
661 | descr->buf_size = skb->len; | 670 | descr->buf_size = length; |
662 | descr->next_descr_addr = 0; | 671 | descr->next_descr_addr = 0; |
663 | descr->skb = skb; | 672 | descr->skb = skb; |
664 | descr->data_status = 0; | 673 | descr->data_status = 0; |
665 | 674 | ||
666 | descr->dmac_cmd_status = | 675 | descr->dmac_cmd_status = |
667 | SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS; | 676 | SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS; |
677 | spin_unlock_irqrestore(&card->tx_chain.lock, flags); | ||
678 | |||
668 | if (skb->protocol == htons(ETH_P_IP)) | 679 | if (skb->protocol == htons(ETH_P_IP)) |
669 | switch (skb->nh.iph->protocol) { | 680 | switch (skb->nh.iph->protocol) { |
670 | case IPPROTO_TCP: | 681 | case IPPROTO_TCP: |
@@ -675,32 +686,51 @@ spider_net_prepare_tx_descr(struct spider_net_card *card, | |||
675 | break; | 686 | break; |
676 | } | 687 | } |
677 | 688 | ||
689 | /* Chain the bus address, so that the DMA engine finds this descr. */ | ||
678 | descr->prev->next_descr_addr = descr->bus_addr; | 690 | descr->prev->next_descr_addr = descr->bus_addr; |
679 | 691 | ||
692 | card->netdev->trans_start = jiffies; /* set netdev watchdog timer */ | ||
680 | return 0; | 693 | return 0; |
681 | } | 694 | } |
682 | 695 | ||
683 | /** | 696 | static int |
684 | * spider_net_release_tx_descr - processes a used tx descriptor | 697 | spider_net_set_low_watermark(struct spider_net_card *card) |
685 | * @card: card structure | ||
686 | * @descr: descriptor to release | ||
687 | * | ||
688 | * releases a used tx descriptor (unmapping, freeing of skb) | ||
689 | */ | ||
690 | static inline void | ||
691 | spider_net_release_tx_descr(struct spider_net_card *card) | ||
692 | { | 698 | { |
699 | unsigned long flags; | ||
700 | int status; | ||
701 | int cnt=0; | ||
702 | int i; | ||
693 | struct spider_net_descr *descr = card->tx_chain.tail; | 703 | struct spider_net_descr *descr = card->tx_chain.tail; |
694 | struct sk_buff *skb; | ||
695 | 704 | ||
696 | card->tx_chain.tail = card->tx_chain.tail->next; | 705 | /* Measure the length of the queue. Measurement does not |
697 | descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE; | 706 | * need to be precise -- does not need a lock. */ |
707 | while (descr != card->tx_chain.head) { | ||
708 | status = descr->dmac_cmd_status & SPIDER_NET_DESCR_NOT_IN_USE; | ||
709 | if (status == SPIDER_NET_DESCR_NOT_IN_USE) | ||
710 | break; | ||
711 | descr = descr->next; | ||
712 | cnt++; | ||
713 | } | ||
698 | 714 | ||
699 | /* unmap the skb */ | 715 | /* If TX queue is short, don't even bother with interrupts */ |
700 | skb = descr->skb; | 716 | if (cnt < card->num_tx_desc/4) |
701 | pci_unmap_single(card->pdev, descr->buf_addr, skb->len, | 717 | return cnt; |
702 | PCI_DMA_TODEVICE); | 718 | |
703 | dev_kfree_skb_any(skb); | 719 | /* Set low-watermark 3/4th's of the way into the queue. */ |
720 | descr = card->tx_chain.tail; | ||
721 | cnt = (cnt*3)/4; | ||
722 | for (i=0;i<cnt; i++) | ||
723 | descr = descr->next; | ||
724 | |||
725 | /* Set the new watermark, clear the old watermark */ | ||
726 | spin_lock_irqsave(&card->tx_chain.lock, flags); | ||
727 | descr->dmac_cmd_status |= SPIDER_NET_DESCR_TXDESFLG; | ||
728 | if (card->low_watermark && card->low_watermark != descr) | ||
729 | card->low_watermark->dmac_cmd_status = | ||
730 | card->low_watermark->dmac_cmd_status & ~SPIDER_NET_DESCR_TXDESFLG; | ||
731 | card->low_watermark = descr; | ||
732 | spin_unlock_irqrestore(&card->tx_chain.lock, flags); | ||
733 | return cnt; | ||
704 | } | 734 | } |
705 | 735 | ||
706 | /** | 736 | /** |
@@ -719,21 +749,29 @@ static int | |||
719 | spider_net_release_tx_chain(struct spider_net_card *card, int brutal) | 749 | spider_net_release_tx_chain(struct spider_net_card *card, int brutal) |
720 | { | 750 | { |
721 | struct spider_net_descr_chain *chain = &card->tx_chain; | 751 | struct spider_net_descr_chain *chain = &card->tx_chain; |
752 | struct spider_net_descr *descr; | ||
753 | struct sk_buff *skb; | ||
754 | u32 buf_addr; | ||
755 | unsigned long flags; | ||
722 | int status; | 756 | int status; |
723 | 757 | ||
724 | spider_net_read_reg(card, SPIDER_NET_GDTDMACCNTR); | ||
725 | |||
726 | while (chain->tail != chain->head) { | 758 | while (chain->tail != chain->head) { |
727 | status = spider_net_get_descr_status(chain->tail); | 759 | spin_lock_irqsave(&chain->lock, flags); |
760 | descr = chain->tail; | ||
761 | |||
762 | status = spider_net_get_descr_status(descr); | ||
728 | switch (status) { | 763 | switch (status) { |
729 | case SPIDER_NET_DESCR_COMPLETE: | 764 | case SPIDER_NET_DESCR_COMPLETE: |
730 | card->netdev_stats.tx_packets++; | 765 | card->netdev_stats.tx_packets++; |
731 | card->netdev_stats.tx_bytes += chain->tail->skb->len; | 766 | card->netdev_stats.tx_bytes += descr->skb->len; |
732 | break; | 767 | break; |
733 | 768 | ||
734 | case SPIDER_NET_DESCR_CARDOWNED: | 769 | case SPIDER_NET_DESCR_CARDOWNED: |
735 | if (!brutal) | 770 | if (!brutal) { |
771 | spin_unlock_irqrestore(&chain->lock, flags); | ||
736 | return 1; | 772 | return 1; |
773 | } | ||
774 | |||
737 | /* fallthrough, if we release the descriptors | 775 | /* fallthrough, if we release the descriptors |
738 | * brutally (then we don't care about | 776 | * brutally (then we don't care about |
739 | * SPIDER_NET_DESCR_CARDOWNED) */ | 777 | * SPIDER_NET_DESCR_CARDOWNED) */ |
@@ -750,11 +788,25 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal) | |||
750 | 788 | ||
751 | default: | 789 | default: |
752 | card->netdev_stats.tx_dropped++; | 790 | card->netdev_stats.tx_dropped++; |
753 | return 1; | 791 | if (!brutal) { |
792 | spin_unlock_irqrestore(&chain->lock, flags); | ||
793 | return 1; | ||
794 | } | ||
754 | } | 795 | } |
755 | spider_net_release_tx_descr(card); | ||
756 | } | ||
757 | 796 | ||
797 | chain->tail = descr->next; | ||
798 | descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE; | ||
799 | skb = descr->skb; | ||
800 | buf_addr = descr->buf_addr; | ||
801 | spin_unlock_irqrestore(&chain->lock, flags); | ||
802 | |||
803 | /* unmap the skb */ | ||
804 | if (skb) { | ||
805 | int len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; | ||
806 | pci_unmap_single(card->pdev, buf_addr, len, PCI_DMA_TODEVICE); | ||
807 | dev_kfree_skb(skb); | ||
808 | } | ||
809 | } | ||
758 | return 0; | 810 | return 0; |
759 | } | 811 | } |
760 | 812 | ||
@@ -763,8 +815,12 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal) | |||
763 | * @card: card structure | 815 | * @card: card structure |
764 | * @descr: descriptor address to enable TX processing at | 816 | * @descr: descriptor address to enable TX processing at |
765 | * | 817 | * |
766 | * spider_net_kick_tx_dma writes the current tx chain head as start address | 818 | * This routine will start the transmit DMA running if |
767 | * of the tx descriptor chain and enables the transmission DMA engine | 819 | * it is not already running. This routine ned only be |
820 | * called when queueing a new packet to an empty tx queue. | ||
821 | * Writes the current tx chain head as start address | ||
822 | * of the tx descriptor chain and enables the transmission | ||
823 | * DMA engine. | ||
768 | */ | 824 | */ |
769 | static inline void | 825 | static inline void |
770 | spider_net_kick_tx_dma(struct spider_net_card *card) | 826 | spider_net_kick_tx_dma(struct spider_net_card *card) |
@@ -804,65 +860,43 @@ out: | |||
804 | static int | 860 | static int |
805 | spider_net_xmit(struct sk_buff *skb, struct net_device *netdev) | 861 | spider_net_xmit(struct sk_buff *skb, struct net_device *netdev) |
806 | { | 862 | { |
863 | int cnt; | ||
807 | struct spider_net_card *card = netdev_priv(netdev); | 864 | struct spider_net_card *card = netdev_priv(netdev); |
808 | struct spider_net_descr_chain *chain = &card->tx_chain; | 865 | struct spider_net_descr_chain *chain = &card->tx_chain; |
809 | struct spider_net_descr *descr = chain->head; | ||
810 | unsigned long flags; | ||
811 | int result; | ||
812 | |||
813 | spin_lock_irqsave(&chain->lock, flags); | ||
814 | 866 | ||
815 | spider_net_release_tx_chain(card, 0); | 867 | spider_net_release_tx_chain(card, 0); |
816 | 868 | ||
817 | if (chain->head->next == chain->tail->prev) { | 869 | if ((chain->head->next == chain->tail->prev) || |
818 | card->netdev_stats.tx_dropped++; | 870 | (spider_net_prepare_tx_descr(card, skb) != 0)) { |
819 | result = NETDEV_TX_LOCKED; | ||
820 | goto out; | ||
821 | } | ||
822 | 871 | ||
823 | if (spider_net_get_descr_status(descr) != SPIDER_NET_DESCR_NOT_IN_USE) { | ||
824 | card->netdev_stats.tx_dropped++; | 872 | card->netdev_stats.tx_dropped++; |
825 | result = NETDEV_TX_LOCKED; | 873 | netif_stop_queue(netdev); |
826 | goto out; | 874 | return NETDEV_TX_BUSY; |
827 | } | 875 | } |
828 | 876 | ||
829 | if (spider_net_prepare_tx_descr(card, skb) != 0) { | 877 | cnt = spider_net_set_low_watermark(card); |
830 | card->netdev_stats.tx_dropped++; | 878 | if (cnt < 5) |
831 | result = NETDEV_TX_BUSY; | 879 | spider_net_kick_tx_dma(card); |
832 | goto out; | 880 | return NETDEV_TX_OK; |
833 | } | ||
834 | |||
835 | result = NETDEV_TX_OK; | ||
836 | |||
837 | spider_net_kick_tx_dma(card); | ||
838 | card->tx_chain.head = card->tx_chain.head->next; | ||
839 | |||
840 | out: | ||
841 | spin_unlock_irqrestore(&chain->lock, flags); | ||
842 | netif_wake_queue(netdev); | ||
843 | return result; | ||
844 | } | 881 | } |
845 | 882 | ||
846 | /** | 883 | /** |
847 | * spider_net_cleanup_tx_ring - cleans up the TX ring | 884 | * spider_net_cleanup_tx_ring - cleans up the TX ring |
848 | * @card: card structure | 885 | * @card: card structure |
849 | * | 886 | * |
850 | * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use | 887 | * spider_net_cleanup_tx_ring is called by either the tx_timer |
851 | * interrupts to cleanup our TX ring) and returns sent packets to the stack | 888 | * or from the NAPI polling routine. |
852 | * by freeing them | 889 | * This routine releases resources associted with transmitted |
890 | * packets, including updating the queue tail pointer. | ||
853 | */ | 891 | */ |
854 | static void | 892 | static void |
855 | spider_net_cleanup_tx_ring(struct spider_net_card *card) | 893 | spider_net_cleanup_tx_ring(struct spider_net_card *card) |
856 | { | 894 | { |
857 | unsigned long flags; | ||
858 | |||
859 | spin_lock_irqsave(&card->tx_chain.lock, flags); | ||
860 | |||
861 | if ((spider_net_release_tx_chain(card, 0) != 0) && | 895 | if ((spider_net_release_tx_chain(card, 0) != 0) && |
862 | (card->netdev->flags & IFF_UP)) | 896 | (card->netdev->flags & IFF_UP)) { |
863 | spider_net_kick_tx_dma(card); | 897 | spider_net_kick_tx_dma(card); |
864 | 898 | netif_wake_queue(card->netdev); | |
865 | spin_unlock_irqrestore(&card->tx_chain.lock, flags); | 899 | } |
866 | } | 900 | } |
867 | 901 | ||
868 | /** | 902 | /** |
@@ -1053,6 +1087,7 @@ spider_net_poll(struct net_device *netdev, int *budget) | |||
1053 | int packets_to_do, packets_done = 0; | 1087 | int packets_to_do, packets_done = 0; |
1054 | int no_more_packets = 0; | 1088 | int no_more_packets = 0; |
1055 | 1089 | ||
1090 | spider_net_cleanup_tx_ring(card); | ||
1056 | packets_to_do = min(*budget, netdev->quota); | 1091 | packets_to_do = min(*budget, netdev->quota); |
1057 | 1092 | ||
1058 | while (packets_to_do) { | 1093 | while (packets_to_do) { |
@@ -1243,12 +1278,15 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) | |||
1243 | case SPIDER_NET_PHYINT: | 1278 | case SPIDER_NET_PHYINT: |
1244 | case SPIDER_NET_GMAC2INT: | 1279 | case SPIDER_NET_GMAC2INT: |
1245 | case SPIDER_NET_GMAC1INT: | 1280 | case SPIDER_NET_GMAC1INT: |
1246 | case SPIDER_NET_GIPSINT: | ||
1247 | case SPIDER_NET_GFIFOINT: | 1281 | case SPIDER_NET_GFIFOINT: |
1248 | case SPIDER_NET_DMACINT: | 1282 | case SPIDER_NET_DMACINT: |
1249 | case SPIDER_NET_GSYSINT: | 1283 | case SPIDER_NET_GSYSINT: |
1250 | break; */ | 1284 | break; */ |
1251 | 1285 | ||
1286 | case SPIDER_NET_GIPSINT: | ||
1287 | show_error = 0; | ||
1288 | break; | ||
1289 | |||
1252 | case SPIDER_NET_GPWOPCMPINT: | 1290 | case SPIDER_NET_GPWOPCMPINT: |
1253 | /* PHY write operation completed */ | 1291 | /* PHY write operation completed */ |
1254 | show_error = 0; | 1292 | show_error = 0; |
@@ -1307,9 +1345,10 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) | |||
1307 | case SPIDER_NET_GDTDCEINT: | 1345 | case SPIDER_NET_GDTDCEINT: |
1308 | /* chain end. If a descriptor should be sent, kick off | 1346 | /* chain end. If a descriptor should be sent, kick off |
1309 | * tx dma | 1347 | * tx dma |
1310 | if (card->tx_chain.tail == card->tx_chain.head) | 1348 | if (card->tx_chain.tail != card->tx_chain.head) |
1311 | spider_net_kick_tx_dma(card); | 1349 | spider_net_kick_tx_dma(card); |
1312 | show_error = 0; */ | 1350 | */ |
1351 | show_error = 0; | ||
1313 | break; | 1352 | break; |
1314 | 1353 | ||
1315 | /* case SPIDER_NET_G1TMCNTINT: not used. print a message */ | 1354 | /* case SPIDER_NET_G1TMCNTINT: not used. print a message */ |
@@ -1354,7 +1393,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) | |||
1354 | if (netif_msg_intr(card)) | 1393 | if (netif_msg_intr(card)) |
1355 | pr_err("got descriptor chain end interrupt, " | 1394 | pr_err("got descriptor chain end interrupt, " |
1356 | "restarting DMAC %c.\n", | 1395 | "restarting DMAC %c.\n", |
1357 | 'D'+i-SPIDER_NET_GDDDCEINT); | 1396 | 'D'-(i-SPIDER_NET_GDDDCEINT)/3); |
1358 | spider_net_refill_rx_chain(card); | 1397 | spider_net_refill_rx_chain(card); |
1359 | spider_net_enable_rxdmac(card); | 1398 | spider_net_enable_rxdmac(card); |
1360 | show_error = 0; | 1399 | show_error = 0; |
@@ -1423,8 +1462,9 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) | |||
1423 | } | 1462 | } |
1424 | 1463 | ||
1425 | if ((show_error) && (netif_msg_intr(card))) | 1464 | if ((show_error) && (netif_msg_intr(card))) |
1426 | pr_err("Got error interrupt, GHIINT0STS = 0x%08x, " | 1465 | pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, " |
1427 | "GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n", | 1466 | "GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n", |
1467 | card->netdev->name, | ||
1428 | status_reg, error_reg1, error_reg2); | 1468 | status_reg, error_reg1, error_reg2); |
1429 | 1469 | ||
1430 | /* clear interrupt sources */ | 1470 | /* clear interrupt sources */ |
@@ -1460,6 +1500,8 @@ spider_net_interrupt(int irq, void *ptr) | |||
1460 | spider_net_rx_irq_off(card); | 1500 | spider_net_rx_irq_off(card); |
1461 | netif_rx_schedule(netdev); | 1501 | netif_rx_schedule(netdev); |
1462 | } | 1502 | } |
1503 | if (status_reg & SPIDER_NET_TXINT) | ||
1504 | netif_rx_schedule(netdev); | ||
1463 | 1505 | ||
1464 | if (status_reg & SPIDER_NET_ERRINT ) | 1506 | if (status_reg & SPIDER_NET_ERRINT ) |
1465 | spider_net_handle_error_irq(card, status_reg); | 1507 | spider_net_handle_error_irq(card, status_reg); |
@@ -1599,7 +1641,7 @@ spider_net_enable_card(struct spider_net_card *card) | |||
1599 | SPIDER_NET_INT2_MASK_VALUE); | 1641 | SPIDER_NET_INT2_MASK_VALUE); |
1600 | 1642 | ||
1601 | spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR, | 1643 | spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR, |
1602 | SPIDER_NET_GDTDCEIDIS); | 1644 | SPIDER_NET_GDTBSTA | SPIDER_NET_GDTDCEIDIS); |
1603 | } | 1645 | } |
1604 | 1646 | ||
1605 | /** | 1647 | /** |
@@ -1615,17 +1657,26 @@ int | |||
1615 | spider_net_open(struct net_device *netdev) | 1657 | spider_net_open(struct net_device *netdev) |
1616 | { | 1658 | { |
1617 | struct spider_net_card *card = netdev_priv(netdev); | 1659 | struct spider_net_card *card = netdev_priv(netdev); |
1618 | int result; | 1660 | struct spider_net_descr *descr; |
1661 | int i, result; | ||
1619 | 1662 | ||
1620 | result = -ENOMEM; | 1663 | result = -ENOMEM; |
1621 | if (spider_net_init_chain(card, &card->tx_chain, card->descr, | 1664 | if (spider_net_init_chain(card, &card->tx_chain, card->descr, |
1622 | PCI_DMA_TODEVICE, card->tx_desc)) | 1665 | card->num_tx_desc)) |
1623 | goto alloc_tx_failed; | 1666 | goto alloc_tx_failed; |
1667 | |||
1668 | card->low_watermark = NULL; | ||
1669 | |||
1670 | /* rx_chain is after tx_chain, so offset is descr + tx_count */ | ||
1624 | if (spider_net_init_chain(card, &card->rx_chain, | 1671 | if (spider_net_init_chain(card, &card->rx_chain, |
1625 | card->descr + card->rx_desc, | 1672 | card->descr + card->num_tx_desc, |
1626 | PCI_DMA_FROMDEVICE, card->rx_desc)) | 1673 | card->num_rx_desc)) |
1627 | goto alloc_rx_failed; | 1674 | goto alloc_rx_failed; |
1628 | 1675 | ||
1676 | descr = card->rx_chain.head; | ||
1677 | for (i=0; i < card->num_rx_desc; i++, descr++) | ||
1678 | descr->next_descr_addr = descr->next->bus_addr; | ||
1679 | |||
1629 | /* allocate rx skbs */ | 1680 | /* allocate rx skbs */ |
1630 | if (spider_net_alloc_rx_skbs(card)) | 1681 | if (spider_net_alloc_rx_skbs(card)) |
1631 | goto alloc_skbs_failed; | 1682 | goto alloc_skbs_failed; |
@@ -1878,10 +1929,7 @@ spider_net_stop(struct net_device *netdev) | |||
1878 | spider_net_disable_rxdmac(card); | 1929 | spider_net_disable_rxdmac(card); |
1879 | 1930 | ||
1880 | /* release chains */ | 1931 | /* release chains */ |
1881 | if (spin_trylock(&card->tx_chain.lock)) { | 1932 | spider_net_release_tx_chain(card, 1); |
1882 | spider_net_release_tx_chain(card, 1); | ||
1883 | spin_unlock(&card->tx_chain.lock); | ||
1884 | } | ||
1885 | 1933 | ||
1886 | spider_net_free_chain(card, &card->tx_chain); | 1934 | spider_net_free_chain(card, &card->tx_chain); |
1887 | spider_net_free_chain(card, &card->rx_chain); | 1935 | spider_net_free_chain(card, &card->rx_chain); |
@@ -2012,8 +2060,8 @@ spider_net_setup_netdev(struct spider_net_card *card) | |||
2012 | 2060 | ||
2013 | card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT; | 2061 | card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT; |
2014 | 2062 | ||
2015 | card->tx_desc = tx_descriptors; | 2063 | card->num_tx_desc = tx_descriptors; |
2016 | card->rx_desc = rx_descriptors; | 2064 | card->num_rx_desc = rx_descriptors; |
2017 | 2065 | ||
2018 | spider_net_setup_netdev_ops(netdev); | 2066 | spider_net_setup_netdev_ops(netdev); |
2019 | 2067 | ||
@@ -2252,6 +2300,8 @@ static struct pci_driver spider_net_driver = { | |||
2252 | */ | 2300 | */ |
2253 | static int __init spider_net_init(void) | 2301 | static int __init spider_net_init(void) |
2254 | { | 2302 | { |
2303 | printk(KERN_INFO "Spidernet version %s.\n", VERSION); | ||
2304 | |||
2255 | if (rx_descriptors < SPIDER_NET_RX_DESCRIPTORS_MIN) { | 2305 | if (rx_descriptors < SPIDER_NET_RX_DESCRIPTORS_MIN) { |
2256 | rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_MIN; | 2306 | rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_MIN; |
2257 | pr_info("adjusting rx descriptors to %i.\n", rx_descriptors); | 2307 | pr_info("adjusting rx descriptors to %i.\n", rx_descriptors); |