aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sundance.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.osdl.org>2006-12-02 18:08:32 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-02 18:08:32 -0500
commit97be852f81c5bb114aab31974af2c061eb86a6de (patch)
tree701a9c88eef7fc3692150f5dd7edb226a6089173 /drivers/net/sundance.c
parentcdb54fac35812a21943f0e506e8e3b94b469a77c (diff)
parentaae343d493df965ac3abec1bd97cccfe44a7d920 (diff)
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (118 commits) [netdrvr] skge: build fix [PATCH] NetXen: driver cleanup, removed unnecessary __iomem type casts [PATCH] PHY: Add support for configuring the PHY connection interface [PATCH] chelesio: transmit locking (plus bug fix). [PATCH] chelsio: statistics improvement [PATCH] chelsio: add MSI support [PATCH] chelsio: use standard CRC routines [PATCH] chelsio: cleanup pm3393 code [PATCH] chelsio: add 1G swcixw aupport [PATCH] chelsio: add support for other 10G boards [PATCH] chelsio: remove unused mutex [PATCH] chelsio: use kzalloc [PATCH] chelsio: whitespace fixes [PATCH] amd8111e use standard CRC lib [PATCH] sky2: msi enhancements. [PATCH] sky2: kfree_skb_any needed [PATCH] sky2: fixes for Yukon EC_U chip revisions [PATCH] sky2: add Dlink 560SX id [PATCH] sky2: receive error handling fix [PATCH] skge: don't clear MC state on link down ...
Diffstat (limited to 'drivers/net/sundance.c')
-rw-r--r--drivers/net/sundance.c58
1 files changed, 47 insertions, 11 deletions
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 41c503d8bac4..c06ecc8002b9 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -264,8 +264,6 @@ enum alta_offsets {
264 ASICCtrl = 0x30, 264 ASICCtrl = 0x30,
265 EEData = 0x34, 265 EEData = 0x34,
266 EECtrl = 0x36, 266 EECtrl = 0x36,
267 TxStartThresh = 0x3c,
268 RxEarlyThresh = 0x3e,
269 FlashAddr = 0x40, 267 FlashAddr = 0x40,
270 FlashData = 0x44, 268 FlashData = 0x44,
271 TxStatus = 0x46, 269 TxStatus = 0x46,
@@ -790,6 +788,7 @@ static int netdev_open(struct net_device *dev)
790{ 788{
791 struct netdev_private *np = netdev_priv(dev); 789 struct netdev_private *np = netdev_priv(dev);
792 void __iomem *ioaddr = np->base; 790 void __iomem *ioaddr = np->base;
791 unsigned long flags;
793 int i; 792 int i;
794 793
795 /* Do we need to reset the chip??? */ 794 /* Do we need to reset the chip??? */
@@ -834,6 +833,10 @@ static int netdev_open(struct net_device *dev)
834 iowrite8(0x01, ioaddr + DebugCtrl1); 833 iowrite8(0x01, ioaddr + DebugCtrl1);
835 netif_start_queue(dev); 834 netif_start_queue(dev);
836 835
836 spin_lock_irqsave(&np->lock, flags);
837 reset_tx(dev);
838 spin_unlock_irqrestore(&np->lock, flags);
839
837 iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); 840 iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
838 841
839 if (netif_msg_ifup(np)) 842 if (netif_msg_ifup(np))
@@ -1081,6 +1084,8 @@ reset_tx (struct net_device *dev)
1081 1084
1082 /* free all tx skbuff */ 1085 /* free all tx skbuff */
1083 for (i = 0; i < TX_RING_SIZE; i++) { 1086 for (i = 0; i < TX_RING_SIZE; i++) {
1087 np->tx_ring[i].next_desc = 0;
1088
1084 skb = np->tx_skbuff[i]; 1089 skb = np->tx_skbuff[i];
1085 if (skb) { 1090 if (skb) {
1086 pci_unmap_single(np->pci_dev, 1091 pci_unmap_single(np->pci_dev,
@@ -1096,6 +1101,10 @@ reset_tx (struct net_device *dev)
1096 } 1101 }
1097 np->cur_tx = np->dirty_tx = 0; 1102 np->cur_tx = np->dirty_tx = 0;
1098 np->cur_task = 0; 1103 np->cur_task = 0;
1104
1105 np->last_tx = NULL;
1106 iowrite8(127, ioaddr + TxDMAPollPeriod);
1107
1099 iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); 1108 iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
1100 return 0; 1109 return 0;
1101} 1110}
@@ -1111,6 +1120,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
1111 int tx_cnt; 1120 int tx_cnt;
1112 int tx_status; 1121 int tx_status;
1113 int handled = 0; 1122 int handled = 0;
1123 int i;
1114 1124
1115 1125
1116 do { 1126 do {
@@ -1153,21 +1163,24 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
1153 np->stats.tx_fifo_errors++; 1163 np->stats.tx_fifo_errors++;
1154 if (tx_status & 0x02) 1164 if (tx_status & 0x02)
1155 np->stats.tx_window_errors++; 1165 np->stats.tx_window_errors++;
1166
1156 /* 1167 /*
1157 ** This reset has been verified on 1168 ** This reset has been verified on
1158 ** DFE-580TX boards ! phdm@macqel.be. 1169 ** DFE-580TX boards ! phdm@macqel.be.
1159 */ 1170 */
1160 if (tx_status & 0x10) { /* TxUnderrun */ 1171 if (tx_status & 0x10) { /* TxUnderrun */
1161 unsigned short txthreshold;
1162
1163 txthreshold = ioread16 (ioaddr + TxStartThresh);
1164 /* Restart Tx FIFO and transmitter */ 1172 /* Restart Tx FIFO and transmitter */
1165 sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16); 1173 sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16);
1166 iowrite16 (txthreshold, ioaddr + TxStartThresh);
1167 /* No need to reset the Tx pointer here */ 1174 /* No need to reset the Tx pointer here */
1168 } 1175 }
1169 /* Restart the Tx. */ 1176 /* Restart the Tx. Need to make sure tx enabled */
1170 iowrite16 (TxEnable, ioaddr + MACCtrl1); 1177 i = 10;
1178 do {
1179 iowrite16(ioread16(ioaddr + MACCtrl1) | TxEnable, ioaddr + MACCtrl1);
1180 if (ioread16(ioaddr + MACCtrl1) & TxEnabled)
1181 break;
1182 mdelay(1);
1183 } while (--i);
1171 } 1184 }
1172 /* Yup, this is a documentation bug. It cost me *hours*. */ 1185 /* Yup, this is a documentation bug. It cost me *hours*. */
1173 iowrite16 (0, ioaddr + TxStatus); 1186 iowrite16 (0, ioaddr + TxStatus);
@@ -1629,6 +1642,14 @@ static int netdev_close(struct net_device *dev)
1629 struct sk_buff *skb; 1642 struct sk_buff *skb;
1630 int i; 1643 int i;
1631 1644
1645 /* Wait and kill tasklet */
1646 tasklet_kill(&np->rx_tasklet);
1647 tasklet_kill(&np->tx_tasklet);
1648 np->cur_tx = 0;
1649 np->dirty_tx = 0;
1650 np->cur_task = 0;
1651 np->last_tx = NULL;
1652
1632 netif_stop_queue(dev); 1653 netif_stop_queue(dev);
1633 1654
1634 if (netif_msg_ifdown(np)) { 1655 if (netif_msg_ifdown(np)) {
@@ -1643,12 +1664,26 @@ static int netdev_close(struct net_device *dev)
1643 /* Disable interrupts by clearing the interrupt mask. */ 1664 /* Disable interrupts by clearing the interrupt mask. */
1644 iowrite16(0x0000, ioaddr + IntrEnable); 1665 iowrite16(0x0000, ioaddr + IntrEnable);
1645 1666
1667 /* Disable Rx and Tx DMA for safely release resource */
1668 iowrite32(0x500, ioaddr + DMACtrl);
1669
1646 /* Stop the chip's Tx and Rx processes. */ 1670 /* Stop the chip's Tx and Rx processes. */
1647 iowrite16(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1); 1671 iowrite16(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1);
1648 1672
1649 /* Wait and kill tasklet */ 1673 for (i = 2000; i > 0; i--) {
1650 tasklet_kill(&np->rx_tasklet); 1674 if ((ioread32(ioaddr + DMACtrl) & 0xc000) == 0)
1651 tasklet_kill(&np->tx_tasklet); 1675 break;
1676 mdelay(1);
1677 }
1678
1679 iowrite16(GlobalReset | DMAReset | FIFOReset | NetworkReset,
1680 ioaddr +ASICCtrl + 2);
1681
1682 for (i = 2000; i > 0; i--) {
1683 if ((ioread16(ioaddr + ASICCtrl +2) & ResetBusy) == 0)
1684 break;
1685 mdelay(1);
1686 }
1652 1687
1653#ifdef __i386__ 1688#ifdef __i386__
1654 if (netif_msg_hw(np)) { 1689 if (netif_msg_hw(np)) {
@@ -1686,6 +1721,7 @@ static int netdev_close(struct net_device *dev)
1686 } 1721 }
1687 } 1722 }
1688 for (i = 0; i < TX_RING_SIZE; i++) { 1723 for (i = 0; i < TX_RING_SIZE; i++) {
1724 np->tx_ring[i].next_desc = 0;
1689 skb = np->tx_skbuff[i]; 1725 skb = np->tx_skbuff[i];
1690 if (skb) { 1726 if (skb) {
1691 pci_unmap_single(np->pci_dev, 1727 pci_unmap_single(np->pci_dev,