summaryrefslogtreecommitdiffstats
path: root/drivers/net/sunlance.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-23 00:40:54 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-23 00:40:54 +0000
commit529c593ece216e4aaffd36bd940cb94f1fa63129 (patch)
tree78f1c0b805f5656aa7b0417a043c5346f700a2cf /drivers/net/sunlance.c
parent0bd079751d25808d1972baee5c4eaa1db2227257 (diff)
Merge with 2.3.43. I did ignore all modifications to the qlogicisp.c
driver due to the Origin A64 hacks.
Diffstat (limited to 'drivers/net/sunlance.c')
-rw-r--r--drivers/net/sunlance.c148
1 files changed, 72 insertions, 76 deletions
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 45b671ae7..c7630dba3 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.93 2000/01/28 13:42:31 jj Exp $
+/* $Id: sunlance.c,v 1.94 2000/02/09 11:15:40 davem Exp $
* lance.c: Linux/Sparc/Lance driver
*
* Written 1995, 1996 by Miguel de Icaza
@@ -240,6 +240,8 @@ struct lance_private {
unsigned long dregs; /* DMA controller regs. */
volatile struct lance_init_block *init_block;
+ spinlock_t lock;
+
int rx_new, tx_new;
int rx_old, tx_old;
@@ -317,7 +319,6 @@ static void load_csrs(struct lance_private *lp)
}
/* Setup the Lance Rx and Tx rings */
-/* Sets dev->tbusy */
static void lance_init_ring_dvma(struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *) dev->priv;
@@ -327,7 +328,7 @@ static void lance_init_ring_dvma(struct net_device *dev)
int i;
/* Lock out other processes while setting up hardware */
- dev->tbusy = 1;
+ netif_stop_queue(dev);
lp->rx_new = lp->tx_new = 0;
lp->rx_old = lp->tx_old = 0;
@@ -383,7 +384,7 @@ static void lance_init_ring_pio(struct net_device *dev)
int i;
/* Lock out other processes while setting up hardware */
- dev->tbusy = 1;
+ netif_stop_queue(dev);
lp->rx_new = lp->tx_new = 0;
lp->rx_old = lp->tx_old = 0;
@@ -573,6 +574,8 @@ static void lance_tx_dvma(struct net_device *dev)
volatile struct lance_init_block *ib = lp->init_block;
int i, j;
+ spin_lock(&lp->lock);
+
j = lp->tx_old;
for (i = j; i != lp->tx_new; i = j) {
volatile struct lance_tx_desc *td = &ib->btx_ring [i];
@@ -637,6 +640,12 @@ static void lance_tx_dvma(struct net_device *dev)
j = TX_NEXT(j);
}
lp->tx_old = j;
+
+ if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+ TX_BUFFS_AVAIL > 0)
+ netif_wake_queue(dev);
+
+ spin_unlock(&lp->lock);
}
static void lance_piocopy_to_skb(struct sk_buff *skb, volatile void *piobuf, int len)
@@ -736,6 +745,8 @@ static void lance_tx_pio(struct net_device *dev)
volatile struct lance_init_block *ib = lp->init_block;
int i, j;
+ spin_lock(&lp->lock);
+
j = lp->tx_old;
for (i = j; i != lp->tx_new; i = j) {
volatile struct lance_tx_desc *td = &ib->btx_ring [i];
@@ -800,6 +811,12 @@ static void lance_tx_pio(struct net_device *dev)
j = TX_NEXT(j);
}
lp->tx_old = j;
+
+ if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+ TX_BUFFS_AVAIL > 0)
+ netif_wake_queue(dev);
+
+ spin_unlock(&lp->lock);
}
static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -808,11 +825,6 @@ static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct lance_private *lp = (struct lance_private *)dev->priv;
int csr0;
- if (dev->interrupt)
- printk(KERN_ERR "%s: again", dev->name);
-
- dev->interrupt = 1;
-
sbus_writew(LE_CSR0, lp->lregs + RAP);
csr0 = sbus_readw(lp->lregs + RDP);
@@ -833,11 +845,6 @@ static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (csr0 & LE_C0_TINT)
lp->tx(dev);
- if ((TX_BUFFS_AVAIL > 0) && dev->tbusy) {
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
-
if (csr0 & LE_C0_BABL)
lp->stats.tx_errors++;
@@ -867,11 +874,10 @@ static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs)
lp->init_ring(dev);
load_csrs(lp);
init_restart_lance(lp);
- dev->tbusy = 0;
+ netif_wake_queue(dev);
}
sbus_writew(LE_C0_INEA, lp->lregs + RDP);
- dev->interrupt = 0;
}
/* Build a fake network packet and send it to ourselves. */
@@ -953,9 +959,7 @@ static int lance_open(struct net_device *dev)
lp->init_ring(dev);
load_csrs(lp);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
status = init_restart_lance(lp);
if (!status && lp->auto_select) {
@@ -973,9 +977,8 @@ static int lance_close(struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *) dev->priv;
- dev->start = 0;
- dev->tbusy = 1;
- del_timer(&lp->multicast_timer);
+ netif_stop_queue(dev);
+ del_timer_sync(&lp->multicast_timer);
STOP_LANCE(lp);
@@ -1007,9 +1010,6 @@ static int lance_reset(struct net_device *dev)
lp->init_ring(dev);
load_csrs(lp);
dev->trans_start = jiffies;
- dev->interrupt = 0;
- dev->start = 1;
- dev->tbusy = 0;
status = init_restart_lance(lp);
return status;
}
@@ -1108,40 +1108,30 @@ static void lance_piozero(volatile void *dest, int len)
sbus_writeb(0, piobuf);
}
+static void lance_tx_timeout(struct net_device *dev)
+{
+ struct lance_private *lp = (struct lance_private *) dev->priv;
+
+ printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
+ dev->name, sbus_readw(lp->lregs + RDP));
+ lance_reset(dev);
+ netif_wake_queue(dev);
+}
+
static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *) dev->priv;
volatile struct lance_init_block *ib = lp->init_block;
- unsigned long flags;
int entry, skblen, len;
- if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
- int tickssofar = jiffies - dev->trans_start;
-
- if (tickssofar < 100)
- return 1;
-
- printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
- dev->name, sbus_readw(lp->lregs + RDP));
- lp->stats.tx_errors++;
- lance_reset(dev);
-
- return 1;
- }
-
skblen = skb->len;
- save_and_cli(flags);
-
- if (!TX_BUFFS_AVAIL) {
- restore_flags(flags);
- return 1;
- }
-
len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
lp->stats.tx_bytes += len;
+ spin_lock_irq(&lp->lock);
+
entry = lp->tx_new & TX_RING_MOD_MASK;
if (lp->pio_buffer) {
sbus_writew((-len) | 0xf000, &ib->btx_ring[entry].length);
@@ -1161,21 +1151,22 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
lp->tx_new = TX_NEXT(entry);
+ if (TX_BUFFS_AVAIL <= 0)
+ netif_stop_queue(dev);
+
+ spin_unlock_irq(&lp->lock);
+
/* Kick the lance: transmit now */
sbus_writew(LE_C0_INEA | LE_C0_TDMD, lp->lregs + RDP);
dev->trans_start = jiffies;
dev_kfree_skb(skb);
- if (TX_BUFFS_AVAIL)
- dev->tbusy = 0;
-
/* Read back CSR to invalidate the E-Cache.
* This is needed, because DMA_DSBL_WR_INV is set.
*/
if (lp->dregs)
sbus_readw(lp->lregs + RDP);
- restore_flags(flags);
return 0;
}
@@ -1255,20 +1246,17 @@ static void lance_set_multicast(struct net_device *dev)
volatile struct lance_init_block *ib = lp->init_block;
u16 mode;
- if (!dev->start)
+ if (!test_bit(LINK_STATE_START, &dev->state))
return;
- if (test_and_set_bit(0, (void *)&dev->tbusy)) {
- mod_timer(&lp->multicast_timer, jiffies + 2);
- return;
- }
-
if (lp->tx_old != lp->tx_new) {
mod_timer(&lp->multicast_timer, jiffies + 4);
- dev->tbusy = 0;
+ netif_wake_queue(dev);
return;
}
+ netif_stop_queue(dev);
+
STOP_LANCE(lp);
lp->init_ring(dev);
@@ -1292,8 +1280,14 @@ static void lance_set_multicast(struct net_device *dev)
}
load_csrs(lp);
init_restart_lance(lp);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
+}
+
+static void lance_set_multicast_retry(unsigned long _opaque)
+{
+ struct net_device *dev = (struct net_device *) _opaque;
+
+ lance_set_multicast(dev);
}
static void lance_free_hwresources(struct lance_private *lp)
@@ -1476,6 +1470,8 @@ no_link_test:
dev->open = &lance_open;
dev->stop = &lance_close;
dev->hard_start_xmit = &lance_start_xmit;
+ dev->tx_timeout = &lance_tx_timeout;
+ dev->watchdog_timeo = 5*HZ;
dev->get_stats = &lance_get_stats;
dev->set_multicast_list = &lance_set_multicast;
@@ -1491,8 +1487,7 @@ no_link_test:
*/
init_timer(&lp->multicast_timer);
lp->multicast_timer.data = (unsigned long) dev;
- lp->multicast_timer.function =
- (void (*)(unsigned long)) &lance_set_multicast;
+ lp->multicast_timer.function = &lance_set_multicast_retry;
#ifdef MODULE
dev->ifindex = dev_new_index();
@@ -1524,11 +1519,15 @@ static inline struct sbus_dma *find_ledma(struct sbus_dev *sdev)
#include <asm/sun4paddr.h>
/* Find all the lance cards on the system and initialize them */
-int __init sparc_lance_probe(void)
+static int __init sparc_lance_probe(void)
{
static struct sbus_dev sdev;
static int called = 0;
+#ifdef MODULE
+ root_lance_dev = NULL;
+#endif
+
if (called)
return ENODEV;
called++;
@@ -1546,7 +1545,7 @@ int __init sparc_lance_probe(void)
#else /* !CONFIG_SUN4 */
/* Find all the lance cards on the system and initialize them */
-int __init sparc_lance_probe(void)
+static int __init sparc_lance_probe(void)
{
struct sbus_bus *bus;
struct sbus_dev *sdev = 0;
@@ -1555,6 +1554,10 @@ int __init sparc_lance_probe(void)
static int called = 0;
int cards = 0, v;
+#ifdef MODULE
+ root_lance_dev = NULL;
+#endif
+
if (called)
return ENODEV;
called++;
@@ -1592,18 +1595,9 @@ int __init sparc_lance_probe(void)
}
#endif /* !CONFIG_SUN4 */
-#ifdef MODULE
-
-int
-init_module(void)
-{
- root_lance_dev = NULL;
- return sparc_lance_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit sparc_lance_cleanup(void)
{
+#ifdef MODULE
struct lance_private *lp;
while (root_lance_dev) {
@@ -1614,6 +1608,8 @@ cleanup_module(void)
kfree(root_lance_dev->dev);
root_lance_dev = lp;
}
+#endif /* MODULE */
}
-#endif /* MODULE */
+module_init(sparc_lance_probe);
+module_exit(sparc_lance_cleanup);