PATCH: Out-of-sync dirty pointer with 2.3.44 and epic100

From: Jeff Garzik (jgarzik@mandrakesoft.com)
Date: Sun Feb 13 2000 - 12:39:07 EST


Jani,

Can you tell me if the attached patch, against 2.3.44, fixes the
problem?

Regards,

        Jeff

-- 
Jeff Garzik         | "Vegetarian" is the Indian word
Building 1024       | for 'lousy hunter.'
MandrakeSoft, Inc.  |

Index: drivers/net/epic100.c =================================================================== RCS file: /g/cvslan/linux_2_3/drivers/net/epic100.c,v retrieving revision 1.1.1.7 retrieving revision 1.1.1.7.12.3 diff -u -r1.1.1.7 -r1.1.1.7.12.3 --- drivers/net/epic100.c 2000/02/10 22:10:27 1.1.1.7 +++ drivers/net/epic100.c 2000/02/13 17:37:10 1.1.1.7.12.3 @@ -79,7 +79,6 @@ MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(max_interrupt_work, "i"); -#define DEV_FREE_SKB(skb) dev_kfree_skb(skb); /* The I/O extent. */ #define EPIC_TOTAL_SIZE 0x100 @@ -425,6 +424,8 @@ dev->do_ioctl = &mii_ioctl; dev->tx_timeout = epic_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + + netif_stop_queue (dev); return dev; } @@ -527,13 +528,15 @@ int mii_reg5; ep->full_duplex = ep->force_fd; + MOD_INC_USE_COUNT; + /* Soft reset the chip. */ outl(0x4001, ioaddr + GENCTL); - if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, "SMC EPIC/100", dev)) - return -EAGAIN; - - MOD_INC_USE_COUNT; + if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, "SMC EPIC/100", dev)) { + MOD_DEC_USE_COUNT; + return -EBUSY; + } epic_init_ring(dev); @@ -581,8 +584,6 @@ set_rx_mode(dev); outl(0x000A, ioaddr + COMMAND); - netif_start_queue(dev); - /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170) | CntFull | TxUnderrun | TxDone @@ -595,10 +596,12 @@ dev->name, ioaddr, dev->irq, inl(ioaddr + GENCTL), ep->full_duplex ? "full" : "half"); + netif_start_queue(dev); + /* Set the timer to switch to check for link beat and perhaps switch to an alternate media type. */ init_timer(&ep->timer); - ep->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */ + ep->timer.expires = RUN_AT(3*HZ); /* 3 sec. */ ep->timer.data = (unsigned long)dev; ep->timer.function = &epic_timer; /* timer handler */ add_timer(&ep->timer); @@ -613,6 +616,8 @@ long ioaddr = dev->base_addr; struct epic_private *ep = (struct epic_private *)dev->priv; + netif_stop_queue (dev); + /* Disable interrupts by clearing the interrupt mask. */ outl(0x00000000, ioaddr + INTMASK); /* Stop the chip's Tx and Rx DMA processes. */ @@ -671,11 +676,13 @@ | CntFull | TxUnderrun | TxDone | RxError | RxOverflow | RxFull | RxHeader | RxDone, ioaddr + INTMASK); + + netif_start_queue (dev); + printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x" " interrupt %4.4x.\n", dev->name, inl(ioaddr + COMMAND), inl(ioaddr + GENCTL), inl(ioaddr + INTSTAT)); - return; } static void epic_timer(unsigned long data) @@ -738,7 +745,8 @@ dev->trans_start = jiffies; ep->stats.tx_errors++; - return; + + netif_start_queue (dev); } /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ @@ -790,6 +798,8 @@ int entry; u32 flag; + netif_stop_queue (dev); + /* Caution: the write order is important here, set the base address with the "ownership" bits last. */ @@ -806,13 +816,10 @@ if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */ flag = 0x10; /* No interrupt */ - netif_start_queue(dev); } else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) { flag = 0x14; /* Tx-done intr. */ - netif_start_queue(dev); } else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) { flag = 0x10; /* No Tx-done intr. */ - netif_start_queue(dev); } else { /* Leave room for two additional entries. */ flag = 0x14; /* Tx-done intr. */ @@ -826,6 +833,10 @@ outl(0x0004, dev->base_addr + COMMAND); dev->trans_start = jiffies; + + if (! ep->tx_full) + netif_start_queue (dev); + if (epic_debug > 4) printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, " "flag %2.2x Tx status %8.8x.\n", @@ -895,7 +906,7 @@ } /* Free the original skb. */ - DEV_FREE_SKB(ep->tx_skbuff[entry]); + dev_kfree_skb_irq(ep->tx_skbuff[entry]); ep->tx_skbuff[entry] = 0; } @@ -912,8 +923,12 @@ dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) { /* The ring is no longer full, clear tbusy. */ ep->tx_full = 0; - netif_wake_queue (dev); } + + if (ep->tx_full) + netif_stop_queue (dev); + else + netif_wake_queue (dev); ep->dirty_tx = dirty_tx; } @@ -1073,12 +1088,12 @@ ep->rx_ring[i].buflength = 0; ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */ if (skb) { - DEV_FREE_SKB(skb); + dev_kfree_skb(skb); } } for (i = 0; i < TX_RING_SIZE; i++) { if (ep->tx_skbuff[i]) - DEV_FREE_SKB(ep->tx_skbuff[i]); + dev_kfree_skb(ep->tx_skbuff[i]); ep->tx_skbuff[i] = 0; } @@ -1224,13 +1239,14 @@ struct net_device *dev; u16 dev_id; u32 io; - u8 bus, devfn, irq; + u8 irq; struct pci_dev *pdev; if (loc->bus != LOC_PCI) return NULL; pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn); if (!pdev) return NULL; - printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn); + printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", + pdev->bus->number, pdev->devfn); io = pdev->resource[0].start; irq = pdev->irq; dev_id = pdev->device; @@ -1241,7 +1257,7 @@ io == 0 ? "I/O address" : "IRQ"); return NULL; } - dev = epic_probe1(bus, devfn, io, irq, 2, -1); + dev = epic_probe1(pdev, io, irq, 2, -1); if (dev) { dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); strcpy(node->dev_name, dev->name);

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue Feb 15 2000 - 21:00:25 EST