From 03ba4131783cc9e872f8bb26a03f15bc11f27564 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 19 Sep 1998 19:15:08 +0000 Subject: - Merge with Linux 2.1.121. - Bugfixes. --- drivers/net/pcnet32.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) (limited to 'drivers/net/pcnet32.c') diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index db00ab8c5..a80d460d0 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -13,7 +13,7 @@ * This driver is for PCnet32 and PCnetPCI based ethercards */ -static const char *version = "pcnet32.c:v1.00 30.5.98 tsbogend@alpha.franken.de\n"; +static const char *version = "pcnet32.c:v1.02 3.9.98 tsbogend@alpha.franken.de\n"; #include #include @@ -103,6 +103,9 @@ static const int rx_copybreak = 200; * back port to 2.0.x * v1.00: added some stuff from Donald Becker's 2.0.34 version * added support for byte counters in net_dev_stats + * v1.01: do ring dumps, only when debugging the driver + * increased the transmit timeout + * v1.02: fixed memory leak in pcnet32_init_ring() */ @@ -188,7 +191,7 @@ struct pcnet32_private { int pcnet32_probe(struct device *dev); static int pcnet32_probe1(struct device *dev, unsigned int ioaddr, unsigned char irq_line, int shared); static int pcnet32_open(struct device *dev); -static void pcnet32_init_ring(struct device *dev); +static int pcnet32_init_ring(struct device *dev); static int pcnet32_start_xmit(struct sk_buff *skb, struct device *dev); static int pcnet32_rx(struct device *dev); static void pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs); @@ -460,7 +463,8 @@ pcnet32_open(struct device *dev) lp->init_block.mode = 0x0000; lp->init_block.filter[0] = 0x00000000; lp->init_block.filter[1] = 0x00000000; - pcnet32_init_ring(dev); + if (pcnet32_init_ring(dev)) + return -ENOMEM; /* Re-initialize the PCNET32, and start it when done. */ outw(0x0001, ioaddr+PCNET32_ADDR); @@ -525,28 +529,28 @@ pcnet32_purge_tx_ring(struct device *dev) /* Initialize the PCNET32 Rx and Tx rings. */ -static void +static int pcnet32_init_ring(struct device *dev) { struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv; int i; - struct sk_buff *skb; lp->lock = 0, lp->tx_full = 0; lp->cur_rx = lp->cur_tx = 0; lp->dirty_rx = lp->dirty_tx = 0; for (i = 0; i < RX_RING_SIZE; i++) { - skb = dev_alloc_skb (PKT_BUF_SZ); - if (skb) { - lp->rx_skbuff[i] = skb; - skb_reserve (skb, 2); - lp->rx_ring[i].base = (u32)le32_to_cpu(virt_to_bus(skb->tail)); - lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ); - lp->rx_ring[i].status = le16_to_cpu(0x8000); + if (lp->rx_skbuff[i] == NULL) { + if (!(lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) { + /* there is not much, we can do at this point */ + printk ("%s: pcnet32_init_ring dev_alloc_skb failed.\n",dev->name); + return -1; + } + skb_reserve (lp->rx_skbuff[i], 2); } - else - break; + lp->rx_ring[i].base = (u32)le32_to_cpu(virt_to_bus(lp->rx_skbuff[i]->tail)); + lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ); + lp->rx_ring[i].status = le16_to_cpu(0x8000); } /* The Tx buffer address is filled in as needed, but we do need to clear the upper ownership bit. */ @@ -560,6 +564,7 @@ pcnet32_init_ring(struct device *dev) lp->init_block.phys_addr[i] = dev->dev_addr[i]; lp->init_block.rx_ring = (u32)le32_to_cpu(virt_to_bus(lp->rx_ring)); lp->init_block.tx_ring = (u32)le32_to_cpu(virt_to_bus(lp->tx_ring)); + return 0; } static void @@ -569,7 +574,8 @@ pcnet32_restart(struct device *dev, unsigned int csr0_bits) unsigned int ioaddr = dev->base_addr; pcnet32_purge_tx_ring(dev); - pcnet32_init_ring(dev); + if (pcnet32_init_ring(dev)) + return; outw(0x0000, ioaddr + PCNET32_ADDR); /* ReInit Ring */ @@ -593,15 +599,14 @@ pcnet32_start_xmit(struct sk_buff *skb, struct device *dev) /* Transmitter timeout, serious problems. */ if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 20) + if (tickssofar < HZ/2) return 1; outw(0, ioaddr+PCNET32_ADDR); printk("%s: transmit timed out, status %4.4x, resetting.\n", dev->name, inw(ioaddr+PCNET32_DATA)); outw(0x0004, ioaddr+PCNET32_DATA); lp->stats.tx_errors++; -#ifndef final_version - { + if (pcnet32_debug > 2) { int i; printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", @@ -616,12 +621,11 @@ pcnet32_start_xmit(struct sk_buff *skb, struct device *dev) lp->tx_ring[i].misc, (unsigned)lp->tx_ring[i].status); printk("\n"); } -#endif pcnet32_restart(dev, 0x0042); dev->tbusy = 0; dev->trans_start = jiffies; - + dev_kfree_skb(skb); return 0; } -- cgit v1.2.3