diff options
author | Don Fry <brazilnut@us.ibm.com> | 2006-06-29 16:55:27 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-07-05 14:07:15 -0400 |
commit | ac5bfe40f94cc8df512d247a5588897b0bc6dbea (patch) | |
tree | 04f03610d663f751782a3f4b9c8c51091c321033 | |
parent | df27f4a610e22e8c8c740286368cc13e0600f22c (diff) |
[PATCH] pcnet32: Cleanup rx buffers after loopback test.
More cleanup to pcnet32_loopback_test to release receive buffers if
device is not up. Created common routine to free rx buffers.
Tested ia32 and ppc64
Signed-off-by: Don Fry <brazilnut@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/net/pcnet32.c | 102 |
1 files changed, 43 insertions, 59 deletions
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index fe0558242835..4daafe303358 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c | |||
@@ -645,6 +645,25 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, | |||
645 | return; | 645 | return; |
646 | } | 646 | } |
647 | 647 | ||
648 | static void pcnet32_purge_rx_ring(struct net_device *dev) | ||
649 | { | ||
650 | struct pcnet32_private *lp = dev->priv; | ||
651 | int i; | ||
652 | |||
653 | /* free all allocated skbuffs */ | ||
654 | for (i = 0; i < lp->rx_ring_size; i++) { | ||
655 | lp->rx_ring[i].status = 0; /* CPU owns buffer */ | ||
656 | wmb(); /* Make sure adapter sees owner change */ | ||
657 | if (lp->rx_skbuff[i]) { | ||
658 | pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], | ||
659 | PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); | ||
660 | dev_kfree_skb_any(lp->rx_skbuff[i]); | ||
661 | } | ||
662 | lp->rx_skbuff[i] = NULL; | ||
663 | lp->rx_dma_addr[i] = 0; | ||
664 | } | ||
665 | } | ||
666 | |||
648 | #ifdef CONFIG_NET_POLL_CONTROLLER | 667 | #ifdef CONFIG_NET_POLL_CONTROLLER |
649 | static void pcnet32_poll_controller(struct net_device *dev) | 668 | static void pcnet32_poll_controller(struct net_device *dev) |
650 | { | 669 | { |
@@ -856,29 +875,27 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) | |||
856 | unsigned long flags; | 875 | unsigned long flags; |
857 | unsigned long ticks; | 876 | unsigned long ticks; |
858 | 877 | ||
859 | *data1 = 1; /* status of test, default to fail */ | ||
860 | rc = 1; /* default to fail */ | 878 | rc = 1; /* default to fail */ |
861 | 879 | ||
862 | if (netif_running(dev)) | 880 | if (netif_running(dev)) |
863 | pcnet32_close(dev); | 881 | pcnet32_close(dev); |
864 | 882 | ||
865 | spin_lock_irqsave(&lp->lock, flags); | 883 | spin_lock_irqsave(&lp->lock, flags); |
884 | lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */ | ||
885 | |||
886 | numbuffs = min(numbuffs, (int)min(lp->rx_ring_size, lp->tx_ring_size)); | ||
866 | 887 | ||
867 | /* Reset the PCNET32 */ | 888 | /* Reset the PCNET32 */ |
868 | lp->a.reset(ioaddr); | 889 | lp->a.reset(ioaddr); |
890 | lp->a.write_csr(ioaddr, CSR4, 0x0915); | ||
869 | 891 | ||
870 | /* switch pcnet32 to 32bit mode */ | 892 | /* switch pcnet32 to 32bit mode */ |
871 | lp->a.write_bcr(ioaddr, 20, 2); | 893 | lp->a.write_bcr(ioaddr, 20, 2); |
872 | 894 | ||
873 | lp->init_block.mode = | ||
874 | le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); | ||
875 | lp->init_block.filter[0] = 0; | ||
876 | lp->init_block.filter[1] = 0; | ||
877 | |||
878 | /* purge & init rings but don't actually restart */ | 895 | /* purge & init rings but don't actually restart */ |
879 | pcnet32_restart(dev, 0x0000); | 896 | pcnet32_restart(dev, 0x0000); |
880 | 897 | ||
881 | lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ | 898 | lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */ |
882 | 899 | ||
883 | /* Initialize Transmit buffers. */ | 900 | /* Initialize Transmit buffers. */ |
884 | size = data_len + 15; | 901 | size = data_len + 15; |
@@ -920,14 +937,15 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) | |||
920 | } | 937 | } |
921 | } | 938 | } |
922 | 939 | ||
923 | x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */ | 940 | x = a->read_bcr(ioaddr, 32); /* set internal loopback in BCR32 */ |
924 | x = x | 0x0002; | 941 | a->write_bcr(ioaddr, 32, x | 0x0002); |
925 | a->write_bcr(ioaddr, 32, x); | ||
926 | 942 | ||
927 | lp->a.write_csr(ioaddr, 15, 0x0044); /* set int loopback in CSR15 */ | 943 | /* set int loopback in CSR15 */ |
944 | x = a->read_csr(ioaddr, CSR15) & 0xfffc; | ||
945 | lp->a.write_csr(ioaddr, CSR15, x | 0x0044); | ||
928 | 946 | ||
929 | teststatus = le16_to_cpu(0x8000); | 947 | teststatus = le16_to_cpu(0x8000); |
930 | lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */ | 948 | lp->a.write_csr(ioaddr, CSR0, CSR0_START); /* Set STRT bit */ |
931 | 949 | ||
932 | /* Check status of descriptors */ | 950 | /* Check status of descriptors */ |
933 | for (x = 0; x < numbuffs; x++) { | 951 | for (x = 0; x < numbuffs; x++) { |
@@ -935,7 +953,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) | |||
935 | rmb(); | 953 | rmb(); |
936 | while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) { | 954 | while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) { |
937 | spin_unlock_irqrestore(&lp->lock, flags); | 955 | spin_unlock_irqrestore(&lp->lock, flags); |
938 | mdelay(1); | 956 | msleep(1); |
939 | spin_lock_irqsave(&lp->lock, flags); | 957 | spin_lock_irqsave(&lp->lock, flags); |
940 | rmb(); | 958 | rmb(); |
941 | ticks++; | 959 | ticks++; |
@@ -948,7 +966,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) | |||
948 | } | 966 | } |
949 | } | 967 | } |
950 | 968 | ||
951 | lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ | 969 | lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */ |
952 | wmb(); | 970 | wmb(); |
953 | if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) { | 971 | if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) { |
954 | printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name); | 972 | printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name); |
@@ -981,25 +999,24 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) | |||
981 | } | 999 | } |
982 | x++; | 1000 | x++; |
983 | } | 1001 | } |
984 | if (!rc) { | ||
985 | *data1 = 0; | ||
986 | } | ||
987 | 1002 | ||
988 | clean_up: | 1003 | clean_up: |
1004 | *data1 = rc; | ||
989 | pcnet32_purge_tx_ring(dev); | 1005 | pcnet32_purge_tx_ring(dev); |
990 | x = a->read_csr(ioaddr, 15) & 0xFFFF; | ||
991 | a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */ | ||
992 | 1006 | ||
993 | x = a->read_bcr(ioaddr, 32); /* reset internal loopback */ | 1007 | x = a->read_csr(ioaddr, CSR15); |
994 | x = x & ~0x0002; | 1008 | a->write_csr(ioaddr, CSR15, (x & ~0x0044)); /* reset bits 6 and 2 */ |
995 | a->write_bcr(ioaddr, 32, x); | ||
996 | 1009 | ||
997 | spin_unlock_irqrestore(&lp->lock, flags); | 1010 | x = a->read_bcr(ioaddr, 32); /* reset internal loopback */ |
1011 | a->write_bcr(ioaddr, 32, (x & ~0x0002)); | ||
998 | 1012 | ||
999 | if (netif_running(dev)) { | 1013 | if (netif_running(dev)) { |
1014 | spin_unlock_irqrestore(&lp->lock, flags); | ||
1000 | pcnet32_open(dev); | 1015 | pcnet32_open(dev); |
1001 | } else { | 1016 | } else { |
1017 | pcnet32_purge_rx_ring(dev); | ||
1002 | lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */ | 1018 | lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */ |
1019 | spin_unlock_irqrestore(&lp->lock, flags); | ||
1003 | } | 1020 | } |
1004 | 1021 | ||
1005 | return (rc); | 1022 | return (rc); |
@@ -1997,16 +2014,7 @@ static int pcnet32_open(struct net_device *dev) | |||
1997 | 2014 | ||
1998 | err_free_ring: | 2015 | err_free_ring: |
1999 | /* free any allocated skbuffs */ | 2016 | /* free any allocated skbuffs */ |
2000 | for (i = 0; i < lp->rx_ring_size; i++) { | 2017 | pcnet32_purge_rx_ring(dev); |
2001 | lp->rx_ring[i].status = 0; | ||
2002 | if (lp->rx_skbuff[i]) { | ||
2003 | pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], | ||
2004 | PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); | ||
2005 | dev_kfree_skb(lp->rx_skbuff[i]); | ||
2006 | } | ||
2007 | lp->rx_skbuff[i] = NULL; | ||
2008 | lp->rx_dma_addr[i] = 0; | ||
2009 | } | ||
2010 | 2018 | ||
2011 | /* | 2019 | /* |
2012 | * Switch back to 16bit mode to avoid problems with dumb | 2020 | * Switch back to 16bit mode to avoid problems with dumb |
@@ -2588,7 +2596,6 @@ static int pcnet32_close(struct net_device *dev) | |||
2588 | { | 2596 | { |
2589 | unsigned long ioaddr = dev->base_addr; | 2597 | unsigned long ioaddr = dev->base_addr; |
2590 | struct pcnet32_private *lp = dev->priv; | 2598 | struct pcnet32_private *lp = dev->priv; |
2591 | int i; | ||
2592 | unsigned long flags; | 2599 | unsigned long flags; |
2593 | 2600 | ||
2594 | del_timer_sync(&lp->watchdog_timer); | 2601 | del_timer_sync(&lp->watchdog_timer); |
@@ -2619,31 +2626,8 @@ static int pcnet32_close(struct net_device *dev) | |||
2619 | 2626 | ||
2620 | spin_lock_irqsave(&lp->lock, flags); | 2627 | spin_lock_irqsave(&lp->lock, flags); |
2621 | 2628 | ||
2622 | /* free all allocated skbuffs */ | 2629 | pcnet32_purge_rx_ring(dev); |
2623 | for (i = 0; i < lp->rx_ring_size; i++) { | 2630 | pcnet32_purge_tx_ring(dev); |
2624 | lp->rx_ring[i].status = 0; | ||
2625 | wmb(); /* Make sure adapter sees owner change */ | ||
2626 | if (lp->rx_skbuff[i]) { | ||
2627 | pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], | ||
2628 | PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); | ||
2629 | dev_kfree_skb(lp->rx_skbuff[i]); | ||
2630 | } | ||
2631 | lp->rx_skbuff[i] = NULL; | ||
2632 | lp->rx_dma_addr[i] = 0; | ||
2633 | } | ||
2634 | |||
2635 | for (i = 0; i < lp->tx_ring_size; i++) { | ||
2636 | lp->tx_ring[i].status = 0; /* CPU owns buffer */ | ||
2637 | wmb(); /* Make sure adapter sees owner change */ | ||
2638 | if (lp->tx_skbuff[i]) { | ||
2639 | pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], | ||
2640 | lp->tx_skbuff[i]->len, | ||
2641 | PCI_DMA_TODEVICE); | ||
2642 | dev_kfree_skb(lp->tx_skbuff[i]); | ||
2643 | } | ||
2644 | lp->tx_skbuff[i] = NULL; | ||
2645 | lp->tx_dma_addr[i] = 0; | ||
2646 | } | ||
2647 | 2631 | ||
2648 | spin_unlock_irqrestore(&lp->lock, flags); | 2632 | spin_unlock_irqrestore(&lp->lock, flags); |
2649 | 2633 | ||