Skip to contentSkip to conversation

8139cp: LinkChg support

PATCH In review Felipe W Damasio 2 participants 4 messages Sep 20, 2002

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 8139cp: LinkChg support

	Hi,

	This patch adds LinkChg support to the 8139cp ethernet driver.

	Patch against 2.5.36.

	Please consider pulling it from:

http://cscience.org/~felipewd/linux/patches-fwd/2.5/8139cp-linkchg.patch

Felipe

8139cp.c renamed from 8139cp.c.orig +27 -1
@@ -22,11 +22,11 @@
 	
 		Wake-on-LAN support - Felipe Damasio <[email protected]>
 		PCI suspend/resume  - Felipe Damasio <[email protected]>
+		LinkChg interrupt   - Felipe Damasio <[email protected]>
 			
 	TODO, in rough priority order:
 	* Test Tx checksumming thoroughly
 	* dev->tx_timeout
-	* LinkChg interrupt
 	* Support forcing media type with a module parameter,
 	  like dl2k.c/sundance.c
 	* Constants (module parms?) for Rx work limit
@@ -396,6 +396,8 @@
 static void __cp_set_rx_mode (struct net_device *dev);
 static void cp_tx (struct cp_private *cp);
 static void cp_clean_rings (struct cp_private *cp);
+static int mdio_read (struct net_device *dev, int phy_id, int location);
+static void mdio_write (struct net_device *dev, int phy_id, int location, int value);
 
 enum board_type {
 	RTL8139Cp,
@@ -655,6 +657,24 @@
 	cp->rx_tail = rx_tail;
 }
 
+static inline void cp_linkchg (struct net_device *dev)
+{
+	struct cp_private *cp = dev->priv;
+	
+	if (mii_link_ok (&cp->mii_if)) {
+		if (netif_msg_link (cp)) {
+			u16 bmcr = mdio_read (dev, cp->mii_if.phy_id, MII_BMCR);
+
+			printk (PFX "Link Changed: %dMbps, %s duplex\n",
+				bmcr & BMCR_SPEED100 ? 100 : 10,
+				bmcr & BMCR_FULLDPLX ? "full" : "half"
+			       );
+		}
+		netif_carrier_on (dev);
+	}
+	else netif_carrier_off (dev); /* Link is down */
+}
+
 static void cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_instance;
@@ -675,6 +695,8 @@
 		cp_rx(cp);
 	if (status & (TxOK | TxErr | TxEmpty | SWInt))
 		cp_tx(cp);
+	if (status & LinkChg)
+		cp_linkchg (dev);
 
 	cpw16_f(IntrStatus, status);
 
@@ -1190,6 +1212,9 @@
 	if (rc)
 		goto err_out_hw;
 
+	if (mii_link_ok (&cp->mii_if))
+		netif_carrier_on  (dev);
+	else    netif_carrier_off (dev);
 	netif_start_queue(dev);
 
 	return 0;
@@ -1208,6 +1233,7 @@
 		printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
 
 	netif_stop_queue(dev);
+	netif_carrier_off (dev);
 	cp_stop_hw(cp);
 	free_irq(dev->irq, dev);
 	cp_free_rings(cp);
#1 lore raw

ALTPATCH: 8139cp: LinkChg support

Felipe,

Here is the patch I just committed, instead of your patch. I wanted a more generic solution, that is easily pluggable into other drivers.

Please test and let me know if you find bugs, or want additions...

Jeff

drivers/net/8139cp.c +6 -1
diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c
@@ -22,11 +22,11 @@
 	
 		Wake-on-LAN support - Felipe Damasio <[email protected]>
 		PCI suspend/resume  - Felipe Damasio <[email protected]>
+		LinkChg interrupt   - Felipe Damasio <[email protected]>
 			
 	TODO, in rough priority order:
 	* Test Tx checksumming thoroughly
 	* dev->tx_timeout
-	* LinkChg interrupt
 	* Support forcing media type with a module parameter,
 	  like dl2k.c/sundance.c
 	* Constants (module parms?) for Rx work limit
@@ -677,6 +677,8 @@
 		cp_rx(cp);
 	if (status & (TxOK | TxErr | TxEmpty | SWInt))
 		cp_tx(cp);
+	if (status & LinkChg)
+		mii_check_media(&cp->mii_if, netif_msg_link(cp));
 
 	if (status & PciErr) {
 		u16 pci_status;
@@ -1192,6 +1194,8 @@
 	if (rc)
 		goto err_out_hw;
 
+	netif_carrier_off(dev);
+	mii_check_media(&cp->mii_if, netif_msg_link(cp));
 	netif_start_queue(dev);
 
 	return 0;
@@ -1210,6 +1214,7 @@
 		printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
 
 	netif_stop_queue(dev);
+	netif_carrier_off(dev);
 
 	spin_lock_irq(&cp->lock);
 	cp_stop_hw(cp);
drivers/net/mii.c +72 -0

81 lines not on this page · raw message

include/linux/mii.h +6 -4
diff -Nru a/include/linux/mii.h b/include/linux/mii.h
@@ -118,10 +118,12 @@
 
 struct ethtool_cmd;
 
-int mii_link_ok (struct mii_if_info *mii);
-int mii_nway_restart (struct mii_if_info *mii);
-int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
-int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern int mii_link_ok (struct mii_if_info *mii);
+extern int mii_nway_restart (struct mii_if_info *mii);
+extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern void mii_check_link (struct mii_if_info *mii);
+extern unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print);
 
 
 /* This structure is used in all SIOCxMIIxxx ioctl calls */
#2 lore raw

Re: ALTPATCH: 8139cp: LinkChg support

Quoted 9 lines · Jeff Garzik

diff -Nru a/drivers/net/mii.c b/drivers/net/mii.c

drivers/net/mii.c +2 -0
@@ -170,6 +170,75 @@
 	return r;
 }
 
+void mii_check_link (struct mii_if_info *mii)
+{

drivers/net/mii.c line 184

Quoted 10 lines
drivers/net/mii.c +10 -0
+	if (mii_link_ok(mii))
+		netif_carrier_on(mii->dev);
+	else
+		netif_carrier_off(mii->dev);
+}
+
+unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print)
+{
+	unsigned int old_carrier, new_carrier;
+	int advertise, lpa, media, duplex;

Shouldn't advertise and lpa be either "unsigned short" or u16?

Quoted 29 lines
drivers/net/mii.c +29 -0
+
+	/* if forced media, go no further */
+	if (mii->duplex_lock)
+		return 0; /* duplex did not change */
+
+	/* check current and old link status */
+	old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;
+	new_carrier = (unsigned int) mii_link_ok(mii);
+
+	/* if carrier state did not change, this is a "bounce",
+	 * just exit as everything is already set correctly
+	 */
+	if (old_carrier == new_carrier)
+		return 0; /* duplex did not change */
+
+	/* no carrier, nothing much to do */
+	if (!new_carrier) {
+		netif_carrier_off(mii->dev);
+		if (ok_to_print)
+			printk(KERN_INFO "%s: link down\n", mii->dev->name);
+		return 0; /* duplex did not change */
+	}
+
+	/*
+	 * we have carrier, see who's on the other end
+	 */
+	netif_carrier_on(mii->dev);
+
+	/* get MII advertise and LPA values */

drivers/net/mii.c line 223

Quoted 10 lines
drivers/net/mii.c +10 -0
+	if (mii->advertising)
+		advertise = mii->advertising;
+	else {
+		advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
+		mii->advertising = advertise;
+	}
+	lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
+
+	/* figure out media and duplex from advertise and LPA values */
+	media = mii_nway_result(lpa & advertise);

^^^^^^^^^^^^^^^^^^^^^^^

mii_nway_result returns a "unsigned int", so media also doesn't look
good.

drivers/net/mii.c line 224

Quoted 1 line
drivers/net/mii.c +1 -0
+	duplex = (media & (ADVERTISE_100FULL | ADVERTISE_10FULL)) ? 1 : 0;
	Or we could do

	duplex = (media & ADVERTISE_FULL) ? 1 : 0;

Felipe

#3 lore raw

Re: ALTPATCH: 8139cp: LinkChg support

Quoted 4 lines · Felipe W Damasio

drivers/net/mii.c line 184

Quoted 1 line
drivers/net/mii.c +1 -0
+	int advertise, lpa, media, duplex;

Shouldn't advertise and lpa be either "unsigned short" or u16?

No, they don't need to be.

Quoted 9 lines

drivers/net/mii.c line 223

Quoted 4 lines
drivers/net/mii.c +4 -0
+	lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
+
+	/* figure out media and duplex from advertise and LPA values */
+	media = mii_nway_result(lpa & advertise);

^^^^^^^^^^^^^^^^^^^^^^^

mii_nway_result returns a "unsigned int", so media also doesn't look
good.

mii_nway_result _really_ returns a small bitmapped value, so it doesn't matter.

Quoted 6 lines

drivers/net/mii.c line 224

Quoted 1 line
drivers/net/mii.c +1 -0
+	duplex = (media & (ADVERTISE_100FULL | ADVERTISE_10FULL)) ? 1 : 0;
	Or we could do

	duplex = (media & ADVERTISE_FULL) ? 1 : 0;

True. I forgot about that constant...

Jeff