* [PATCH] 8139cp: LinkChg support
@ 2002-09-20 2:00 Felipe W Damasio
2002-09-20 6:15 ` ALTPATCH: " Jeff Garzik
0 siblings, 1 reply; 4+ messages in thread
From: Felipe W Damasio @ 2002-09-20 2:00 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Linux Kernel Mailing List
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.orig Fri Sep 20 01:21:20 2002
+++ ./8139cp.c Fri Sep 20 01:35:05 2002
@@ -22,11 +22,11 @@
Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br>
PCI suspend/resume - Felipe Damasio <felipewd@terra.com.br>
+ LinkChg interrupt - Felipe Damasio <felipewd@terra.com.br>
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);
^ permalink raw reply [flat|nested] 4+ messages in thread* ALTPATCH: 8139cp: LinkChg support 2002-09-20 2:00 [PATCH] 8139cp: LinkChg support Felipe W Damasio @ 2002-09-20 6:15 ` Jeff Garzik 2002-09-20 4:09 ` Felipe W Damasio 0 siblings, 1 reply; 4+ messages in thread From: Jeff Garzik @ 2002-09-20 6:15 UTC (permalink / raw) To: Felipe W Damasio; +Cc: Linux Kernel Mailing List, netdev [-- Attachment #1: Type: text/plain, Size: 227 bytes --] 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 [-- Attachment #2: patch --] [-- Type: text/plain, Size: 4559 bytes --] diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c --- a/drivers/net/8139cp.c Fri Sep 20 02:13:15 2002 +++ b/drivers/net/8139cp.c Fri Sep 20 02:13:15 2002 @@ -22,11 +22,11 @@ Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br> PCI suspend/resume - Felipe Damasio <felipewd@terra.com.br> + LinkChg interrupt - Felipe Damasio <felipewd@terra.com.br> 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); diff -Nru a/drivers/net/mii.c b/drivers/net/mii.c --- a/drivers/net/mii.c Fri Sep 20 02:13:15 2002 +++ b/drivers/net/mii.c Fri Sep 20 02:13:15 2002 @@ -170,6 +170,75 @@ return r; } +void mii_check_link (struct mii_if_info *mii) +{ + 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; + + /* 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 */ + 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); + duplex = (media & (ADVERTISE_100FULL | ADVERTISE_10FULL)) ? 1 : 0; + + if (ok_to_print) + printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n", + mii->dev->name, + media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? + "100" : "10", + duplex ? "full" : "half", + lpa); + + if (mii->full_duplex != duplex) { + mii->full_duplex = duplex; + return 1; /* duplex changed */ + } + + return 0; /* duplex did not change */ +} + MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>"); MODULE_DESCRIPTION ("MII hardware support library"); MODULE_LICENSE("GPL"); @@ -178,3 +247,6 @@ EXPORT_SYMBOL(mii_nway_restart); EXPORT_SYMBOL(mii_ethtool_gset); EXPORT_SYMBOL(mii_ethtool_sset); +EXPORT_SYMBOL(mii_check_link); +EXPORT_SYMBOL(mii_check_media); + diff -Nru a/include/linux/mii.h b/include/linux/mii.h --- a/include/linux/mii.h Fri Sep 20 02:13:15 2002 +++ b/include/linux/mii.h Fri Sep 20 02:13:15 2002 @@ -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 */ ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: ALTPATCH: 8139cp: LinkChg support 2002-09-20 6:15 ` ALTPATCH: " Jeff Garzik @ 2002-09-20 4:09 ` Felipe W Damasio 2002-09-20 13:21 ` Jeff Garzik 0 siblings, 1 reply; 4+ messages in thread From: Felipe W Damasio @ 2002-09-20 4:09 UTC (permalink / raw) To: Jeff Garzik; +Cc: Linux Kernel Mailing List, netdev On Fri, 2002-09-20 at 06:15, Jeff Garzik wrote: > diff -Nru a/drivers/net/mii.c b/drivers/net/mii.c > --- a/drivers/net/mii.c Fri Sep 20 02:13:15 2002 > +++ b/drivers/net/mii.c Fri Sep 20 02:13:15 2002 > @@ -170,6 +170,75 @@ > return r; > } > > +void mii_check_link (struct mii_if_info *mii) > +{ > + 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? > + > + /* 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 */ > + 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. > + duplex = (media & (ADVERTISE_100FULL | ADVERTISE_10FULL)) ? 1 : 0; Or we could do duplex = (media & ADVERTISE_FULL) ? 1 : 0; Felipe ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: ALTPATCH: 8139cp: LinkChg support 2002-09-20 4:09 ` Felipe W Damasio @ 2002-09-20 13:21 ` Jeff Garzik 0 siblings, 0 replies; 4+ messages in thread From: Jeff Garzik @ 2002-09-20 13:21 UTC (permalink / raw) To: Felipe W Damasio; +Cc: Linux Kernel Mailing List, netdev Felipe W Damasio wrote: >>+ int advertise, lpa, media, duplex; > > > Shouldn't advertise and lpa be either "unsigned short" or u16? No, they don't need to be. >>+ 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. >>+ 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 ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2002-09-20 13:16 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2002-09-20 2:00 [PATCH] 8139cp: LinkChg support Felipe W Damasio 2002-09-20 6:15 ` ALTPATCH: " Jeff Garzik 2002-09-20 4:09 ` Felipe W Damasio 2002-09-20 13:21 ` Jeff Garzik
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox