[PATCH] pcnet32: break in 2.6.18-rc1 identified
authorDon Fry <brazilnut@us.ibm.com>
Tue, 22 Aug 2006 17:22:37 +0000 (10:22 -0700)
committerJeff Garzik <jeff@garzik.org>
Thu, 24 Aug 2006 04:40:03 +0000 (00:40 -0400)
A change I made for 2.6.17 and another for 2.6.18 do not work on older
pcnet32 chips which I do not have access to.  If the chip is a 79C970 or
79C965, do not try and suspend or check the link status.
I have tested with a 79C970A, 79C971, 79C972, 79C973, 79C975, 79C976,
and 79C978.

Signed-off-by: Don Fry <brazilnut@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/net/pcnet32.c

index 4daafe3033589c49c6637baf95c004e20d5982fc..d50bcb89dd2898564b6c86a8e516113f59c263ef 100644 (file)
@@ -202,6 +202,8 @@ static int homepna[MAX_UNITS];
 #define CSR15          15
 #define PCNET32_MC_FILTER      8
 
+#define PCNET32_79C970A        0x2621
+
 /* The PCNET32 Rx and Tx ring descriptors. */
 struct pcnet32_rx_head {
        u32     base;
@@ -289,6 +291,7 @@ struct pcnet32_private {
 
        /* each bit indicates an available PHY */
        u32                     phymask;
+       unsigned short          chip_version;   /* which variant this is */
 };
 
 static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
@@ -724,9 +727,11 @@ static u32 pcnet32_get_link(struct net_device *dev)
        spin_lock_irqsave(&lp->lock, flags);
        if (lp->mii) {
                r = mii_link_ok(&lp->mii_if);
-       } else {
+       } else if (lp->chip_version >= PCNET32_79C970A) {
                ulong ioaddr = dev->base_addr;  /* card base I/O address */
                r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
+       } else {        /* can not detect link on really old chips */
+               r = 1;
        }
        spin_unlock_irqrestore(&lp->lock, flags);
 
@@ -1091,6 +1096,10 @@ static int pcnet32_suspend(struct net_device *dev, unsigned long *flags,
        ulong ioaddr = dev->base_addr;
        int ticks;
 
+       /* really old chips have to be stopped. */
+       if (lp->chip_version < PCNET32_79C970A)
+               return 0;
+
        /* set SUSPEND (SPND) - CSR5 bit 0 */
        csr5 = a->read_csr(ioaddr, CSR5);
        a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
@@ -1529,6 +1538,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
        lp->mii_if.reg_num_mask = 0x1f;
        lp->dxsuflo = dxsuflo;
        lp->mii = mii;
+       lp->chip_version = chip_version;
        lp->msg_enable = pcnet32_debug;
        if ((cards_found >= MAX_UNITS)
            || (options[cards_found] > sizeof(options_mapping)))
@@ -1839,10 +1849,7 @@ static int pcnet32_open(struct net_device *dev)
                                val |= 2;
                } else if (lp->options & PCNET32_PORT_ASEL) {
                        /* workaround of xSeries250, turn on for 79C975 only */
-                       i = ((lp->a.read_csr(ioaddr, 88) |
-                             (lp->a.
-                              read_csr(ioaddr, 89) << 16)) >> 12) & 0xffff;
-                       if (i == 0x2627)
+                       if (lp->chip_version == 0x2627)
                                val |= 3;
                }
                lp->a.write_bcr(ioaddr, 9, val);
@@ -1986,9 +1993,11 @@ static int pcnet32_open(struct net_device *dev)
 
        netif_start_queue(dev);
 
-       /* Print the link status and start the watchdog */
-       pcnet32_check_media(dev, 1);
-       mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+       if (lp->chip_version >= PCNET32_79C970A) {
+               /* Print the link status and start the watchdog */
+               pcnet32_check_media(dev, 1);
+               mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+       }
 
        i = 0;
        while (i++ < 100)