Commit c0a87c22 authored by Ondrej Zary's avatar Ondrej Zary Committed by David S. Miller

tlan: Enable link monitoring

Enable old link monitoring code and modify it:
 - control LINK LED
 - use separate timer so it does not interfere with ACT LED

Tested with Olicom OC-2326.
Signed-off-by: default avatarOndrej Zary <linux@rainbow-software.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eb522bb4
...@@ -69,10 +69,6 @@ MODULE_AUTHOR("Maintainer: Samuel Chessman <chessman@tux.org>"); ...@@ -69,10 +69,6 @@ MODULE_AUTHOR("Maintainer: Samuel Chessman <chessman@tux.org>");
MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters"); MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* Define this to enable Link beat monitoring */
#undef MONITOR
/* Turn on debugging. See Documentation/networking/tlan.txt for details */ /* Turn on debugging. See Documentation/networking/tlan.txt for details */
static int debug; static int debug;
module_param(debug, int, 0); module_param(debug, int, 0);
...@@ -194,9 +190,7 @@ static void tlan_phy_power_up(struct net_device *); ...@@ -194,9 +190,7 @@ static void tlan_phy_power_up(struct net_device *);
static void tlan_phy_reset(struct net_device *); static void tlan_phy_reset(struct net_device *);
static void tlan_phy_start_link(struct net_device *); static void tlan_phy_start_link(struct net_device *);
static void tlan_phy_finish_auto_neg(struct net_device *); static void tlan_phy_finish_auto_neg(struct net_device *);
#ifdef MONITOR static void tlan_phy_monitor(unsigned long);
static void tlan_phy_monitor(struct net_device *);
#endif
/* /*
static int tlan_phy_nop(struct net_device *); static int tlan_phy_nop(struct net_device *);
...@@ -339,6 +333,7 @@ static void tlan_stop(struct net_device *dev) ...@@ -339,6 +333,7 @@ static void tlan_stop(struct net_device *dev)
{ {
struct tlan_priv *priv = netdev_priv(dev); struct tlan_priv *priv = netdev_priv(dev);
del_timer_sync(&priv->media_timer);
tlan_read_and_clear_stats(dev, TLAN_RECORD); tlan_read_and_clear_stats(dev, TLAN_RECORD);
outl(TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD); outl(TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD);
/* Reset and power down phy */ /* Reset and power down phy */
...@@ -888,6 +883,7 @@ static int tlan_open(struct net_device *dev) ...@@ -888,6 +883,7 @@ static int tlan_open(struct net_device *dev)
} }
init_timer(&priv->timer); init_timer(&priv->timer);
init_timer(&priv->media_timer);
tlan_start(dev); tlan_start(dev);
...@@ -1810,11 +1806,6 @@ static void tlan_timer(unsigned long data) ...@@ -1810,11 +1806,6 @@ static void tlan_timer(unsigned long data)
priv->timer.function = NULL; priv->timer.function = NULL;
switch (priv->timer_type) { switch (priv->timer_type) {
#ifdef MONITOR
case TLAN_TIMER_LINK_BEAT:
tlan_phy_monitor(dev);
break;
#endif
case TLAN_TIMER_PHY_PDOWN: case TLAN_TIMER_PHY_PDOWN:
tlan_phy_power_down(dev); tlan_phy_power_down(dev);
break; break;
...@@ -1858,8 +1849,6 @@ static void tlan_timer(unsigned long data) ...@@ -1858,8 +1849,6 @@ static void tlan_timer(unsigned long data)
} }
/***************************************************************************** /*****************************************************************************
****************************************************************************** ******************************************************************************
...@@ -2257,42 +2246,39 @@ tlan_finish_reset(struct net_device *dev) ...@@ -2257,42 +2246,39 @@ tlan_finish_reset(struct net_device *dev)
tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status); tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
udelay(1000); udelay(1000);
tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status); tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
if ((status & MII_GS_LINK) && if (status & MII_GS_LINK) {
/* We only support link info on Nat.Sem. PHY's */ /* We only support link info on Nat.Sem. PHY's */
(tlphy_id1 == NAT_SEM_ID1) && if ((tlphy_id1 == NAT_SEM_ID1) &&
(tlphy_id2 == NAT_SEM_ID2)) { (tlphy_id2 == NAT_SEM_ID2)) {
tlan_mii_read_reg(dev, phy, MII_AN_LPA, &partner); tlan_mii_read_reg(dev, phy, MII_AN_LPA,
tlan_mii_read_reg(dev, phy, TLAN_TLPHY_PAR, &tlphy_par); &partner);
tlan_mii_read_reg(dev, phy, TLAN_TLPHY_PAR,
netdev_info(dev, &tlphy_par);
"Link active with %s %uMbps %s-Duplex\n",
!(tlphy_par & TLAN_PHY_AN_EN_STAT) netdev_info(dev,
? "forced" : "Autonegotiation enabled,", "Link active, %s %uMbps %s-Duplex\n",
tlphy_par & TLAN_PHY_SPEED_100 !(tlphy_par & TLAN_PHY_AN_EN_STAT)
? 100 : 10, ? "forced" : "Autonegotiation enabled,",
tlphy_par & TLAN_PHY_DUPLEX_FULL tlphy_par & TLAN_PHY_SPEED_100
? "Full" : "Half"); ? 100 : 10,
tlphy_par & TLAN_PHY_DUPLEX_FULL
if (tlphy_par & TLAN_PHY_AN_EN_STAT) { ? "Full" : "Half");
netdev_info(dev, "Partner capability:");
for (i = 5; i < 10; i++) if (tlphy_par & TLAN_PHY_AN_EN_STAT) {
if (partner & (1 << i)) netdev_info(dev, "Partner capability:");
pr_cont(" %s", media[i-5]); for (i = 5; i < 10; i++)
pr_cont("\n"); if (partner & (1 << i))
} pr_cont(" %s",
media[i-5]);
tlan_dio_write8(dev->base_addr, TLAN_LED_REG, pr_cont("\n");
TLAN_LED_LINK); }
#ifdef MONITOR } else
/* We have link beat..for now anyway */ netdev_info(dev, "Link active\n");
priv->link = 1; /* Enabling link beat monitoring */
/*Enabling link beat monitoring */ priv->media_timer.function = tlan_phy_monitor;
tlan_set_timer(dev, (10*HZ), TLAN_TIMER_LINK_BEAT); priv->media_timer.data = (unsigned long) dev;
#endif priv->media_timer.expires = jiffies + HZ;
} else if (status & MII_GS_LINK) { add_timer(&priv->media_timer);
netdev_info(dev, "Link active\n");
tlan_dio_write8(dev->base_addr, TLAN_LED_REG,
TLAN_LED_LINK);
} }
} }
...@@ -2314,6 +2300,7 @@ tlan_finish_reset(struct net_device *dev) ...@@ -2314,6 +2300,7 @@ tlan_finish_reset(struct net_device *dev)
dev->base_addr + TLAN_HOST_CMD + 1); dev->base_addr + TLAN_HOST_CMD + 1);
outl(priv->rx_list_dma, dev->base_addr + TLAN_CH_PARM); outl(priv->rx_list_dma, dev->base_addr + TLAN_CH_PARM);
outl(TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD); outl(TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD);
tlan_dio_write8(dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK);
netif_carrier_on(dev); netif_carrier_on(dev);
} else { } else {
netdev_info(dev, "Link inactive, will retry in 10 secs...\n"); netdev_info(dev, "Link inactive, will retry in 10 secs...\n");
...@@ -2719,7 +2706,6 @@ static void tlan_phy_finish_auto_neg(struct net_device *dev) ...@@ -2719,7 +2706,6 @@ static void tlan_phy_finish_auto_neg(struct net_device *dev)
} }
#ifdef MONITOR
/********************************************************************* /*********************************************************************
* *
...@@ -2729,18 +2715,18 @@ static void tlan_phy_finish_auto_neg(struct net_device *dev) ...@@ -2729,18 +2715,18 @@ static void tlan_phy_finish_auto_neg(struct net_device *dev)
* None * None
* *
* Params: * Params:
* dev The device structure of this device. * data The device structure of this device.
* *
* *
* This function monitors PHY condition by reading the status * This function monitors PHY condition by reading the status
* register via the MII bus. This can be used to give info * register via the MII bus, controls LINK LED and notifies the
* about link changes (up/down), and possible switch to alternate * kernel about link state.
* media.
* *
*******************************************************************/ *******************************************************************/
void tlan_phy_monitor(struct net_device *dev) static void tlan_phy_monitor(unsigned long data)
{ {
struct net_device *dev = (struct net_device *) data;
struct tlan_priv *priv = netdev_priv(dev); struct tlan_priv *priv = netdev_priv(dev);
u16 phy; u16 phy;
u16 phy_status; u16 phy_status;
...@@ -2752,30 +2738,25 @@ void tlan_phy_monitor(struct net_device *dev) ...@@ -2752,30 +2738,25 @@ void tlan_phy_monitor(struct net_device *dev)
/* Check if link has been lost */ /* Check if link has been lost */
if (!(phy_status & MII_GS_LINK)) { if (!(phy_status & MII_GS_LINK)) {
if (priv->link) { if (netif_carrier_ok(dev)) {
priv->link = 0;
printk(KERN_DEBUG "TLAN: %s has lost link\n", printk(KERN_DEBUG "TLAN: %s has lost link\n",
dev->name); dev->name);
tlan_dio_write8(dev->base_addr, TLAN_LED_REG, 0);
netif_carrier_off(dev); netif_carrier_off(dev);
tlan_set_timer(dev, (2*HZ), TLAN_TIMER_LINK_BEAT);
return;
} }
} }
/* Link restablished? */ /* Link restablished? */
if ((phy_status & MII_GS_LINK) && !priv->link) { if ((phy_status & MII_GS_LINK) && !netif_carrier_ok(dev)) {
priv->link = 1; tlan_dio_write8(dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK);
printk(KERN_DEBUG "TLAN: %s has reestablished link\n", printk(KERN_DEBUG "TLAN: %s has reestablished link\n",
dev->name); dev->name);
netif_carrier_on(dev); netif_carrier_on(dev);
} }
priv->media_timer.expires = jiffies + HZ;
/* Setup a new monitor */ add_timer(&priv->media_timer);
tlan_set_timer(dev, (2*HZ), TLAN_TIMER_LINK_BEAT);
} }
#endif /* MONITOR */
/***************************************************************************** /*****************************************************************************
****************************************************************************** ******************************************************************************
......
...@@ -195,6 +195,7 @@ struct tlan_priv { ...@@ -195,6 +195,7 @@ struct tlan_priv {
u32 timer_set_at; u32 timer_set_at;
u32 timer_type; u32 timer_type;
struct timer_list timer; struct timer_list timer;
struct timer_list media_timer;
struct board *adapter; struct board *adapter;
u32 adapter_rev; u32 adapter_rev;
u32 aui; u32 aui;
...@@ -206,7 +207,6 @@ struct tlan_priv { ...@@ -206,7 +207,6 @@ struct tlan_priv {
u8 tlan_rev; u8 tlan_rev;
u8 tlan_full_duplex; u8 tlan_full_duplex;
spinlock_t lock; spinlock_t lock;
u8 link;
struct work_struct tlan_tqueue; struct work_struct tlan_tqueue;
u8 neg_be_verbose; u8 neg_be_verbose;
}; };
...@@ -219,7 +219,6 @@ struct tlan_priv { ...@@ -219,7 +219,6 @@ struct tlan_priv {
* *
****************************************************************/ ****************************************************************/
#define TLAN_TIMER_LINK_BEAT 1
#define TLAN_TIMER_ACTIVITY 2 #define TLAN_TIMER_ACTIVITY 2
#define TLAN_TIMER_PHY_PDOWN 3 #define TLAN_TIMER_PHY_PDOWN 3
#define TLAN_TIMER_PHY_PUP 4 #define TLAN_TIMER_PHY_PUP 4
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment