diff options
| author | Jeff Garzik <jgarzik@mandrakesoft.com> | 2002-09-19 18:12:52 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@mandrakesoft.com> | 2002-09-19 18:12:52 -0400 |
| commit | 7ded02b37c8a8b220cf447133b253b3ff2b6fc2d (patch) | |
| tree | b74f4a5ec2ad3efa3c81e01a680c09ea08ee0089 | |
| parent | 5b73b398d4ef6c803a9cf1352d8d7ab796c76095 (diff) | |
Add new MII lib functions mii_check_link, mii_check_media.
Use them in 8139cp.
| -rw-r--r-- | drivers/net/8139cp.c | 7 | ||||
| -rw-r--r-- | drivers/net/mii.c | 72 | ||||
| -rw-r--r-- | include/linux/mii.h | 10 |
3 files changed, 84 insertions, 5 deletions
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index a029c68812b3..fd7b83bc2f6e 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -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 @@ static void cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs) 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 @@ static int cp_open (struct net_device *dev) 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 @@ static int cp_close (struct net_device *dev) 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 --git a/drivers/net/mii.c b/drivers/net/mii.c index e7ff531299c8..05dc7cafcb96 100644 --- a/drivers/net/mii.c +++ b/drivers/net/mii.c @@ -170,6 +170,75 @@ int mii_nway_restart (struct mii_if_info *mii) 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_link_ok); 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 --git a/include/linux/mii.h b/include/linux/mii.h index 4a3881211195..dc1b22a562ea 100644 --- a/include/linux/mii.h +++ b/include/linux/mii.h @@ -118,10 +118,12 @@ struct mii_if_info { 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 */ |
