Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.4.1 /drivers/net/3c59x.c

Filename:/drivers/net/3c59x.c
Lines Added:85
Lines Deleted:23
Also changed in: (Previous) 2.4.1-pre12  2.4.1-pre11  2.4.1-pre10  2.4.1-pre9  2.4.1-pre8  2.4.1-pre6 
(Following) 2.4.1-ac1  2.4.1-ac2  2.4.1-ac3  2.4.1-ac4  2.4.1-ac5  2.4.1-ac6 

Location
[  2.4.1
  [  drivers
    [  net
       o  3c59x.c

Patch

diff -u --recursive --new-file v2.4.0/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.4.0/linux/drivers/net/3c59x.c   Tue Nov 14 11:34:25 2000
+++ linux/drivers/net/3c59x.c   Sat Jan  6 09:27:42 2001
@@ -118,6 +118,14 @@
    LK1.1.11 13 Nov 2000 andrewm
     - Dump MOD_INC/DEC_USE_COUNT, use SET_MODULE_OWNER
 
+   LK1.1.12 1 Jan 2001 andrewm
+    - Call pci_enable_device before we request our IRQ (Tobias Ringstrom)
+    - Add 3c590 PCI latency timer hack to vortex_probe1 (from 0.99Ra)
+    - Added extended wait_for_completion for the 3c905CX.
+    - Look for an MII on PHY index 24 first (3c905CX oddity).
+    - Add HAS_NWAY to 3cSOHO100-TX (Brett Frankenberger)
+    - Don't free skbs we don't own on oom path in vortex_open().
+
     - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details.
     - Also see Documentation/networking/vortex.txt
 */
@@ -203,7 +211,7 @@
 #include <linux/delay.h>
 
 static char version[] __devinitdata =
-"3c59x.c:LK1.1.11 13 Nov 2000  Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.102.2.46 $\n";
+"3c59x.c:LK1.1.12 06 Jan 2000  Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.102.2.46 $\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("3Com 3c59x/3c90x/3c575 series Vortex/Boomerang/Cyclone driver");
@@ -424,7 +432,7 @@
     PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
 
    {"3cSOHO100-TX Hurricane",
-    PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+    PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, },
    {"3c555 Laptop Hurricane",
     PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT, 128, },
    {"3c556 Laptop Tornado",
@@ -843,10 +851,15 @@
 {
    int rc;
 
-   rc = vortex_probe1 (pdev, pci_resource_start (pdev, 0), pdev->irq,
-             ent->driver_data, vortex_cards_found);
-   if (rc == 0)
-      vortex_cards_found++;
+   /* wake up and enable device */      
+   if (pci_enable_device (pdev)) {
+      rc = -EIO;
+   } else {
+      rc = vortex_probe1 (pdev, pci_resource_start (pdev, 0), pdev->irq,
+                ent->driver_data, vortex_cards_found);
+      if (rc == 0)
+         vortex_cards_found++;
+   }
    return rc;
 }
 
@@ -863,7 +876,7 @@
    struct vortex_private *vp;
    int option;
    unsigned int eeprom[0x40], checksum = 0;      /* EEPROM contents */
-   int i;
+   int i, step;
    struct net_device *dev;
    static int printed_version;
    int retval;
@@ -889,7 +902,6 @@
           vci->name,
           ioaddr);
 
-   /* private struct aligned and zeroed by init_etherdev */
    vp = dev->priv;
    dev->base_addr = ioaddr;
    dev->irq = irq;
@@ -908,19 +920,29 @@
    if (pdev) {
       /* EISA resources already marked, so only PCI needs to do this here */
       /* Ignore return value, because Cardbus drivers already allocate for us */
-      if (request_region(ioaddr, vci->io_size, dev->name) != NULL) {
+      if (request_region(ioaddr, vci->io_size, dev->name) != NULL)
          vp->must_free_region = 1;
-      }
-
-      /* wake up and enable device */      
-      if (pci_enable_device (pdev)) {
-         retval = -EIO;
-         goto free_region;
-      }
 
       /* enable bus-mastering if necessary */      
       if (vci->flags & PCI_USES_MASTER)
          pci_set_master (pdev);
+
+      if (vci->drv_flags & IS_VORTEX) {
+         u8 pci_latency;
+         u8 new_latency = 248;
+
+         /* Check the PCI latency value.  On the 3c590 series the latency timer
+            must be set to the maximum value to avoid data corruption that occurs
+            when the timer expires during a transfer.  This bug exists the Vortex
+            chip only. */
+         pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
+         if (pci_latency < new_latency) {
+            printk(KERN_INFO "%s: Overriding PCI latency"
+               " timer (CFLT) setting of %d, new value is %d.\n",
+               dev->name, pci_latency, new_latency);
+               pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
+         }
+      }
    }
 
    spin_lock_init(&vp->lock);
@@ -1025,6 +1047,13 @@
             dev->irq);
 #endif
 
+   EL3WINDOW(4);
+   step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;
+   printk(KERN_INFO "  product code '%c%c' rev %02x.%d date %02d-"
+         "%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],
+         step, (eeprom[4]>>5) & 15, eeprom[4] & 31, eeprom[4]>>9);
+
+
    if (pdev && vci->drv_flags & HAS_CB_FNS) {
       unsigned long fn_st_addr;         /* Cardbus function status space */
       unsigned short n;
@@ -1089,8 +1118,19 @@
       mii_preamble_required++;
       mii_preamble_required++;
       mdio_read(dev, 24, 1);
-      for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) {
-         int mii_status, phyx = phy & 0x1f;
+      for (phy = 0; phy < 32 && phy_idx < 1; phy++) {
+         int mii_status, phyx;
+
+         /*
+          * For the 3c905CX we look at index 24 first, because it bogusly
+          * reports an external PHY at all indices
+          */
+         if (phy == 0)
+            phyx = 24;
+         else if (phy <= 24)
+            phyx = phy - 1;
+         else
+            phyx = phy;
          mii_status = mdio_read(dev, phyx, 1);
          if (mii_status  &&  mii_status != 0xffff) {
             vp->phys[phy_idx++] = phyx;
@@ -1135,12 +1175,13 @@
    dev->set_multicast_list = set_rx_mode;
    dev->tx_timeout = vortex_tx_timeout;
    dev->watchdog_timeo = (watchdog * HZ) / 1000;
-
+//   publish_netdev(dev);
    return 0;
 
 free_region:
    if (vp->must_free_region)
       release_region(ioaddr, vci->io_size);
+//   withdraw_netdev(dev);
    unregister_netdev(dev);
    kfree (dev);
    printk(KERN_ERR PFX "vortex_probe1 fails.  Returns %d\n", retval);
@@ -1150,13 +1191,23 @@
 
 static void wait_for_completion(struct net_device *dev, int cmd)
 {
-   int i = 4000;
+   int i;
 
    outw(cmd, dev->base_addr + EL3_CMD);
-   while (--i > 0) {
+   for (i = 0; i < 2000; i++) {
       if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress))
          return;
    }
+
+   /* OK, that didn't work.  Do it the slow way.  One second */
+   for (i = 0; i < 100000; i++) {
+      if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) {
+         printk(KERN_INFO "%s: command 0x%04x took %d usecs! Please tell andrewm@uow.edu.au\n",
+                  dev->name, cmd, i * 10);
+         return;
+      }
+      udelay(10);
+   }
    printk(KERN_ERR "%s: command 0x%04x did not complete! Status=0x%x\n",
             dev->name, cmd, inw(dev->base_addr + EL3_STATUS));
 }
@@ -1331,6 +1382,7 @@
    set_rx_mode(dev);
    outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
+//   wait_for_completion(dev, SetTxStart|0x07ff);
    outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
    outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
    /* Allow status bits to be seen. */
@@ -1384,7 +1436,8 @@
       }
       if (i != RX_RING_SIZE) {
          int j;
-         for (j = 0; j < RX_RING_SIZE; j++) {
+         printk(KERN_EMERG "%s: no memory for rx ring\n", dev->name);
+         for (j = 0; j < i; j++) {
             if (vp->rx_skbuff[j]) {
                dev_kfree_skb(vp->rx_skbuff[j]);
                vp->rx_skbuff[j] = 0;
@@ -1532,7 +1585,10 @@
    printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
          dev->name, inb(ioaddr + TxStatus),
          inw(ioaddr + EL3_STATUS));
-
+   EL3WINDOW(4);
+   printk(KERN_ERR "  diagnostics: net %04x media %04x dma %8.8x.\n",
+         inw(ioaddr + Wn4_NetDiag), inw(ioaddr + Wn4_Media),
+         inl(ioaddr + PktStatus));
    /* Slight code bloat to be user friendly. */
    if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
       printk(KERN_ERR "%s: Transmitter encountered 16 collisions --"
@@ -1663,6 +1719,12 @@
             dev->name, fifo_diag);
       /* Adapter failure requires Tx/Rx reset and reinit. */
       if (vp->full_bus_master_tx) {
+         int bus_status = inl(ioaddr + PktStatus);
+         /* 0x80000000 PCI master abort. */
+         /* 0x40000000 PCI target abort. */
+         if (vortex_debug)
+            printk(KERN_ERR "%s: PCI bus error, bus status %8.8x\n", dev->name, bus_status);
+
          /* In this case, blow the card away */
          vortex_down(dev);
          wait_for_completion(dev, TotalReset | 0xff);


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.