diff options
Diffstat (limited to 'drivers/net/cops.c')
-rw-r--r-- | drivers/net/cops.c | 166 |
1 files changed, 74 insertions, 92 deletions
diff --git a/drivers/net/cops.c b/drivers/net/cops.c index c15a1937c..466705f9e 100644 --- a/drivers/net/cops.c +++ b/drivers/net/cops.c @@ -30,6 +30,7 @@ * cleanup of formatting and program * logic. Added emacs 'local-vars' * setup for Jay's brace style. + * 20000211 Alan Cox Cleaned up for softnet */ static const char *version = @@ -48,10 +49,8 @@ static const char *version = */ #include <linux/config.h> -#ifdef MODULE #include <linux/module.h> #include <linux/version.h> -#endif #include <linux/kernel.h> #include <linux/sched.h> @@ -180,7 +179,7 @@ static unsigned int cops_debug = COPS_DEBUG; struct cops_local { - struct enet_statistics stats; + struct net_device_stats stats; int board; /* Holds what board type is. */ int nodeid; /* Set to 1 once have nodeid. */ unsigned char node_acquire; /* Node ID when acquired. */ @@ -200,6 +199,7 @@ static int cops_nodeid (struct net_device *dev, int nodeid); static void cops_interrupt (int irq, void *dev_id, struct pt_regs *regs); static void cops_poll (unsigned long ltdev); +static void cops_timeout(struct net_device *dev); static void cops_rx (struct net_device *dev); static int cops_send_packet (struct sk_buff *skb, struct net_device *dev); static void set_multicast_list (struct net_device *dev); @@ -209,7 +209,7 @@ static int cops_hard_header (struct sk_buff *skb, struct net_device *dev, static int cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static int cops_close (struct net_device *dev); -static struct enet_statistics *cops_get_stats (struct net_device *dev); +static struct net_device_stats *cops_get_stats (struct net_device *dev); /* @@ -323,13 +323,15 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) /* Fill in the fields of the device structure with LocalTalk values. */ ltalk_setup(dev); - dev->hard_start_xmit = &cops_send_packet; + dev->hard_start_xmit = cops_send_packet; + dev->tx_timeout = cops_timeout; + dev->watchdog_timeo = HZ * 2; dev->hard_header = cops_hard_header; dev->get_stats = cops_get_stats; dev->open = cops_open; dev->stop = cops_close; - dev->do_ioctl = &cops_ioctl; - dev->set_multicast_list = &set_multicast_list; + dev->do_ioctl = cops_ioctl; + dev->set_multicast_list = set_multicast_list; dev->mc_list = NULL; /* Tell the user where the card is and what mode we're in. */ @@ -424,10 +426,7 @@ static int cops_open(struct net_device *dev) cops_jumpstart(dev); /* Start the card up. */ - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - + netif_start_queue(dev); #ifdef MODULE MOD_INC_USE_COUNT; #endif @@ -501,8 +500,7 @@ static void cops_reset(struct net_device *dev, int sleep) else udelay(333333); } - dev->tbusy=0; - + netif_wake_queue(dev); return; } @@ -673,6 +671,7 @@ static int cops_nodeid (struct net_device *dev, int nodeid) /* * Poll the Tangent type cards to see if we have work. */ + static void cops_poll(unsigned long ltdev) { int ioaddr, status; @@ -691,7 +690,7 @@ static void cops_poll(unsigned long ltdev) if(status & TANG_RX_READY) cops_rx(dev); if(status & TANG_TX_READY) - dev->tbusy = 0; + netif_wake_queue(dev); status = inb(ioaddr+TANG_CARD_STATUS); } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY))); @@ -712,14 +711,6 @@ static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs) int ioaddr, status; int boguscount = 0; - if(dev == NULL) - { - printk(KERN_WARNING "%s: irq %d for unknown device.\n", - cardname, irq); - return; - } - dev->interrupt = 1; - ioaddr = dev->base_addr; lp = (struct cops_local *)dev->priv; @@ -730,8 +721,7 @@ static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs) status=inb(ioaddr+DAYNA_CARD_STATUS); if((status&0x03)==DAYNA_RX_REQUEST) cops_rx(dev); - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue(dev); } while(++boguscount < 20); } else @@ -741,13 +731,11 @@ static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs) if(status & TANG_RX_READY) cops_rx(dev); if(status & TANG_TX_READY) - dev->tbusy = 0; + netif_wake_queue(dev); status=inb(ioaddr+TANG_CARD_STATUS); - } while((++boguscount < 20) && - (status&(TANG_RX_READY|TANG_TX_READY))); + } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY))); } - dev->interrupt = 0; return; } @@ -762,7 +750,10 @@ static void cops_rx(struct net_device *dev) struct cops_local *lp = (struct cops_local *)dev->priv; int ioaddr = dev->base_addr; int boguscount = 0; + unsigned long flags; + + save_flags(flags); cli(); /* Disable interrupts. */ if(lp->board==DAYNA) @@ -798,7 +789,7 @@ static void cops_rx(struct net_device *dev) skb = dev_alloc_skb(pkt_len); if(skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", + printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; while(pkt_len--) /* Discard packet */ @@ -814,12 +805,12 @@ static void cops_rx(struct net_device *dev) if(lp->board==DAYNA) outb(1, ioaddr+DAYNA_INT_CARD); /* Interrupt the card */ - sti(); /* Restore interrupts. */ + restore_flags(flags); /* Restore interrupts. */ /* Check for bad response length */ if(pkt_len < 0 || pkt_len > MAX_LLAP_SIZE) { - printk(KERN_NOTICE "%s: Bad packet length of %d bytes.\n", + printk(KERN_WARNING "%s: Bad packet length of %d bytes.\n", dev->name, pkt_len); lp->stats.tx_errors++; kfree_skb(skb); @@ -837,7 +828,7 @@ static void cops_rx(struct net_device *dev) /* One last check to make sure we have a good packet. */ if(rsp_type != LAP_RESPONSE) { - printk("%s: Bad packet type %d.\n", dev->name, rsp_type); + printk(KERN_WARNING "%s: Bad packet type %d.\n", dev->name, rsp_type); lp->stats.tx_errors++; kfree_skb(skb); return; @@ -857,79 +848,72 @@ static void cops_rx(struct net_device *dev) return; } +static void cops_timeout(struct net_device *dev) +{ + struct cops_local *lp = (struct cops_local *)dev->priv; + int ioaddr = dev->base_addr; + + lp->stats.tx_errors++; + if(lp->board==TANGENT) + { + if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) + printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name); + } + printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name); + cops_jumpstart(dev); /* Restart the card. */ + dev->trans_start = jiffies; + netif_wake_queue(dev); +} + + /* * Make the card transmit a LocalTalk packet. */ + static int cops_send_packet(struct sk_buff *skb, struct net_device *dev) { struct cops_local *lp = (struct cops_local *)dev->priv; int 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 < 5) - return 1; - lp->stats.tx_errors++; - if(lp->board==TANGENT) - { - if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) - printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name); - } - printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name); - cops_jumpstart(dev); /* Restart the card. */ - dev->tbusy=0; - dev->trans_start = jiffies; - } + unsigned long flags; /* - * Block a timer-based transmit from overlapping. This could better be - * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. + * Block a timer-based transmit from overlapping. */ - if(test_and_set_bit(0, (void*) &dev->tbusy) != 0) - printk(KERN_WARNING "%s: Transmitter access conflict.\n", - dev->name); - else - { - cli(); /* Disable interrupts. */ - if(lp->board == DAYNA) /* Wait for adapter transmit buffer. */ - while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); - if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */ - while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0); - - /* Output IO length. */ - outb(skb->len, ioaddr); - if(lp->board == DAYNA) - outb(skb->len >> 8, ioaddr); - else - outb((skb->len >> 8)&0x0FF, ioaddr); - - /* Output IO code. */ - outb(LAP_WRITE, ioaddr); + + netif_stop_queue(dev); + + save_flags(flags); + cli(); /* Disable interrupts. */ + if(lp->board == DAYNA) /* Wait for adapter transmit buffer. */ + while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); + if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */ + while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0); + + /* Output IO length. */ + outb(skb->len, ioaddr); + if(lp->board == DAYNA) + outb(skb->len >> 8, ioaddr); + else + outb((skb->len >> 8)&0x0FF, ioaddr); - if(lp->board == DAYNA) /* Check the transmit buffer again. */ - while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); + /* Output IO code. */ + outb(LAP_WRITE, ioaddr); - outsb(ioaddr, skb->data, skb->len); /* Send out the data. */ + if(lp->board == DAYNA) /* Check the transmit buffer again. */ + while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); - if(lp->board==DAYNA) /* Dayna requires you kick the card */ - outb(1, ioaddr+DAYNA_INT_CARD); + outsb(ioaddr, skb->data, skb->len); /* Send out the data. */ - sti(); /* Restore interrupts. */ + if(lp->board==DAYNA) /* Dayna requires you kick the card */ + outb(1, ioaddr+DAYNA_INT_CARD); - /* Done sending packet, update counters and cleanup. */ - lp->stats.tx_packets++; - lp->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; - } + restore_flags(flags); /* Restore interrupts. */ + /* Done sending packet, update counters and cleanup. */ + lp->stats.tx_packets++; + lp->stats.tx_bytes += skb->len; + dev->trans_start = jiffies; dev_kfree_skb (skb); - dev->tbusy = 0; - return 0; } @@ -1005,9 +989,7 @@ static int cops_close(struct net_device *dev) if(lp->board==TANGENT && dev->irq==0) del_timer(&cops_timer); - dev->tbusy = 1; - dev->start = 0; - + netif_stop_queue(dev); #ifdef MODULE MOD_DEC_USE_COUNT; #endif @@ -1019,7 +1001,7 @@ static int cops_close(struct net_device *dev) * Get the current statistics. * This may be called with the card open or closed. */ -static struct enet_statistics *cops_get_stats(struct net_device *dev) +static struct net_device_stats *cops_get_stats(struct net_device *dev) { struct cops_local *lp = (struct cops_local *)dev->priv; return &lp->stats; |