Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d916266 authored by Don Fry's avatar Don Fry Committed by Jeff Garzik
Browse files

[PATCH] pcnet32: break in 2.6.18-rc1 identified



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: default avatarDon Fry <brazilnut@us.ibm.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 9a469abe
Loading
Loading
Loading
Loading
+17 −8
Original line number Original line Diff line number Diff line
@@ -202,6 +202,8 @@ static int homepna[MAX_UNITS];
#define CSR15		15
#define CSR15		15
#define PCNET32_MC_FILTER	8
#define PCNET32_MC_FILTER	8


#define PCNET32_79C970A	0x2621

/* The PCNET32 Rx and Tx ring descriptors. */
/* The PCNET32 Rx and Tx ring descriptors. */
struct pcnet32_rx_head {
struct pcnet32_rx_head {
	u32	base;
	u32	base;
@@ -289,6 +291,7 @@ struct pcnet32_private {


	/* each bit indicates an available PHY */
	/* each bit indicates an available PHY */
	u32			phymask;
	u32			phymask;
	unsigned short		chip_version;	/* which variant this is */
};
};


static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
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);
	spin_lock_irqsave(&lp->lock, flags);
	if (lp->mii) {
	if (lp->mii) {
		r = mii_link_ok(&lp->mii_if);
		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 */
		ulong ioaddr = dev->base_addr;	/* card base I/O address */
		r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
		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);
	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;
	ulong ioaddr = dev->base_addr;
	int ticks;
	int ticks;


	/* really old chips have to be stopped. */
	if (lp->chip_version < PCNET32_79C970A)
		return 0;

	/* set SUSPEND (SPND) - CSR5 bit 0 */
	/* set SUSPEND (SPND) - CSR5 bit 0 */
	csr5 = a->read_csr(ioaddr, CSR5);
	csr5 = a->read_csr(ioaddr, CSR5);
	a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
	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->mii_if.reg_num_mask = 0x1f;
	lp->dxsuflo = dxsuflo;
	lp->dxsuflo = dxsuflo;
	lp->mii = mii;
	lp->mii = mii;
	lp->chip_version = chip_version;
	lp->msg_enable = pcnet32_debug;
	lp->msg_enable = pcnet32_debug;
	if ((cards_found >= MAX_UNITS)
	if ((cards_found >= MAX_UNITS)
	    || (options[cards_found] > sizeof(options_mapping)))
	    || (options[cards_found] > sizeof(options_mapping)))
@@ -1839,10 +1849,7 @@ static int pcnet32_open(struct net_device *dev)
				val |= 2;
				val |= 2;
		} else if (lp->options & PCNET32_PORT_ASEL) {
		} else if (lp->options & PCNET32_PORT_ASEL) {
			/* workaround of xSeries250, turn on for 79C975 only */
			/* workaround of xSeries250, turn on for 79C975 only */
			i = ((lp->a.read_csr(ioaddr, 88) |
			if (lp->chip_version == 0x2627)
			      (lp->a.
			       read_csr(ioaddr, 89) << 16)) >> 12) & 0xffff;
			if (i == 0x2627)
				val |= 3;
				val |= 3;
		}
		}
		lp->a.write_bcr(ioaddr, 9, val);
		lp->a.write_bcr(ioaddr, 9, val);
@@ -1986,9 +1993,11 @@ static int pcnet32_open(struct net_device *dev)


	netif_start_queue(dev);
	netif_start_queue(dev);


	if (lp->chip_version >= PCNET32_79C970A) {
		/* Print the link status and start the watchdog */
		/* Print the link status and start the watchdog */
		pcnet32_check_media(dev, 1);
		pcnet32_check_media(dev, 1);
		mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
		mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
	}


	i = 0;
	i = 0;
	while (i++ < 100)
	while (i++ < 100)