patch-2.3.45 linux/drivers/net/pcmcia/fmvj18x_cs.c
Next file: linux/drivers/net/pcmcia/netwave_cs.c
Previous file: linux/drivers/net/pcmcia/aironet4500_cs.c
Back to the patch index
Back to the overall index
- Lines: 258
- Date:
Sun Feb 13 18:24:12 2000
- Orig file:
v2.3.44/linux/drivers/net/pcmcia/fmvj18x_cs.c
- Orig date:
Fri Jan 21 18:19:16 2000
diff -u --recursive --new-file v2.3.44/linux/drivers/net/pcmcia/fmvj18x_cs.c linux/drivers/net/pcmcia/fmvj18x_cs.c
@@ -115,6 +115,7 @@
static void fjn_reset(struct net_device *dev);
static struct net_device_stats *fjn_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
+static void fjn_tx_timeout (struct net_device *dev);
static dev_info_t dev_info = "fmvj18x_cs";
static dev_link_t *dev_list = NULL;
@@ -139,6 +140,7 @@
cardtype_t cardtype;
u_short sent;
u_char mc_filter[8];
+ spinlock_t lock;
} local_info_t;
#define MC_FILTERBREAK 64
@@ -235,6 +237,8 @@
#define INTR_OFF 0x0d /* LAN controler ignores interrupts */
#define INTR_ON 0x1d /* LAN controler will catch interrupts */
+#define TX_TIMEOUT 10
+
/*======================================================================
This bit of code is used to avoid unregistering network devices
@@ -278,6 +282,8 @@
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if (!lp) return NULL;
memset(lp, 0, sizeof(*lp));
+
+ lp->lock = SPIN_LOCK_UNLOCKED;
link = &lp->link; dev = &lp->dev;
link->priv = dev->priv = link->irq.Instance = lp;
@@ -314,7 +320,9 @@
dev->init = &fmvj18x_init;
dev->open = &fjn_open;
dev->stop = &fjn_close;
- dev->tbusy = 0xFF;
+ dev->tx_timeout = fjn_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ netif_start_queue (dev);
/* Register with Card Services */
link->next = dev_list;
@@ -462,7 +470,7 @@
CS_CHECK(RequestConfiguration, link->handle, &link->conf);
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- dev->tbusy = 0;
+ netif_start_queue (dev);
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
goto failed;
@@ -585,8 +593,7 @@
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- dev->tbusy = 0xFF;
- dev->start = 0;
+ netif_stop_queue (dev);
link->release.expires = jiffies + HZ/20;
add_timer(&link->release);
}
@@ -601,8 +608,7 @@
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
if (link->open) {
- dev->tbusy = 0xFF;
- dev->start = 0;
+ netif_stop_queue (dev);
}
CardServices(ReleaseConfiguration, link->handle);
}
@@ -614,9 +620,8 @@
if (link->state & DEV_CONFIG) {
CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) {
- dev->tbusy = 0;
- dev->start = 1;
fjn_reset(dev);
+ netif_start_queue (dev);
}
}
break;
@@ -670,12 +675,9 @@
"unknown device.\n", irq);
return;
}
- if (dev->interrupt) {
- printk(KERN_NOTICE "%s: re-entering the interrupt handler.\n",
- dev->name);
- return;
- }
- dev->interrupt = 1;
+
+ spin_lock (&lp->lock);
+
ioaddr = dev->base_addr;
/* avoid multiple interrupts */
@@ -708,71 +710,65 @@
lp->tx_queue = 0;
lp->tx_queue_len = 0;
dev->trans_start = jiffies;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue (dev);
} else {
lp->tx_started = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_stop_queue (dev);
}
}
DEBUG(4, "%s: exiting interrupt,\n", dev->name);
DEBUG(4, " tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
- dev->interrupt = 0;
outb(D_TX_INTR, ioaddr + TX_INTR);
outb(D_RX_INTR, ioaddr + RX_INTR);
- return;
+ spin_unlock (&lp->lock);
+
} /* fjn_interrupt */
/*====================================================================*/
-
-static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void fjn_tx_timeout (struct net_device *dev)
{
- struct local_info_t *lp = (struct local_info_t *)dev->priv;
- ioaddr_t ioaddr = dev->base_addr;
-
- if (dev->tbusy) {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 10)
- return 1;
- printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
- dev->name, htons(inw(ioaddr + TX_STATUS)),
- inb(ioaddr + TX_STATUS) & F_TMT_RDY
- ? "IRQ conflict" : "network cable problem");
- printk(KERN_NOTICE "%s: timeout registers: %04x %04x %04x "
- "%04x %04x %04x %04x %04x.\n",
- dev->name, htons(inw(ioaddr + 0)),
- htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
- htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
- htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
- htons(inw(ioaddr +14)));
+ struct local_info_t *lp = (struct local_info_t *) dev->priv;
+ ioaddr_t ioaddr = dev->base_addr;
+ unsigned long flags;
+
+ printk (KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
+ dev->name, htons (inw (ioaddr + TX_STATUS)),
+ inb (ioaddr + TX_STATUS) & F_TMT_RDY
+ ? "IRQ conflict" : "network cable problem");
+ printk (KERN_NOTICE "%s: timeout registers: %04x %04x %04x "
+ "%04x %04x %04x %04x %04x.\n",
+ dev->name, htons (inw (ioaddr + 0)),
+ htons (inw (ioaddr + 2)), htons (inw (ioaddr + 4)),
+ htons (inw (ioaddr + 6)), htons (inw (ioaddr + 8)),
+ htons (inw (ioaddr + 10)), htons (inw (ioaddr + 12)),
+ htons (inw (ioaddr + 14)));
lp->stats.tx_errors++;
+
/* ToDo: We should try to restart the adaptor... */
- cli();
+ spin_lock_irqsave (&lp->lock, flags);
- fjn_reset(dev);
+ fjn_reset (dev);
lp->tx_started = 0;
lp->tx_queue = 0;
lp->tx_queue_len = 0;
lp->sent = 0;
lp->open_time = jiffies;
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
-
- sti();
- }
+ netif_start_queue (dev);
+
+ spin_unlock_irqrestore (&lp->lock, flags);
+}
+
+
+static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct local_info_t *lp = (struct local_info_t *)dev->priv;
+ ioaddr_t ioaddr = dev->base_addr;
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk(KERN_NOTICE "%s: Transmitter access conflict.\n", dev->name);
- else {
+ netif_stop_queue (dev);
+ if (1) {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = skb->data;
@@ -806,17 +802,17 @@
lp->tx_queue_len = 0;
dev->trans_start = jiffies;
lp->tx_started = 1;
- dev->tbusy = 0;
+ netif_start_queue (dev);
} else {
if( sram_config == 0 ) {
if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) )
/* Yes, there is room for one more packet. */
- dev->tbusy = 0;
+ netif_start_queue (dev);
} else {
if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) &&
lp->tx_queue < 127 )
/* Yes, there is room for one more packet. */
- dev->tbusy = 0;
+ netif_start_queue (dev);
}
}
@@ -1025,9 +1021,7 @@
lp->tx_queue = 0;
lp->tx_queue_len = 0;
lp->open_time = jiffies;
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
+ netif_start_queue (dev);
MOD_INC_USE_COUNT;
@@ -1045,8 +1039,7 @@
DEBUG(4, "fjn_close('%s').\n", dev->name);
lp->open_time = 0;
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue (dev);
/* Set configuration register 0 to disable Tx and Rx. */
if( sram_config == 0 )
@@ -1064,7 +1057,6 @@
outb(INTR_OFF, ioaddr + LAN_CTRL);
link->open--;
- dev->start = 0;
if (link->state & DEV_STALE_CONFIG) {
link->release.expires = jiffies + HZ/20;
link->state |= DEV_RELEASE_PENDING;
FUNET's LINUX-ADM group, [email protected]
TCL-scripts by Sam Shen (who was at: [email protected])