Commit b88aafd3 authored by Herton Ronaldo Krzesinski's avatar Herton Ronaldo Krzesinski Committed by David S. Miller

sis190: fix cable detect via link status poll

Some sis190 devices don't report LinkChange, so do polling for
link status.

Fixes http://bugzilla.kernel.org/show_bug.cgi?id=11926Signed-off-by: default avatarHerton Ronaldo Krzesinski <herton@mandriva.com.br>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4ab408de
...@@ -285,6 +285,11 @@ struct sis190_private { ...@@ -285,6 +285,11 @@ struct sis190_private {
struct list_head first_phy; struct list_head first_phy;
u32 features; u32 features;
u32 negotiated_lpa; u32 negotiated_lpa;
enum {
LNK_OFF,
LNK_ON,
LNK_AUTONEG,
} link_status;
}; };
struct sis190_phy { struct sis190_phy {
...@@ -750,6 +755,7 @@ static irqreturn_t sis190_interrupt(int irq, void *__dev) ...@@ -750,6 +755,7 @@ static irqreturn_t sis190_interrupt(int irq, void *__dev)
if (status & LinkChange) { if (status & LinkChange) {
netif_info(tp, intr, dev, "link change\n"); netif_info(tp, intr, dev, "link change\n");
del_timer(&tp->timer);
schedule_work(&tp->phy_task); schedule_work(&tp->phy_task);
} }
...@@ -922,12 +928,15 @@ static void sis190_phy_task(struct work_struct *work) ...@@ -922,12 +928,15 @@ static void sis190_phy_task(struct work_struct *work)
if (val & BMCR_RESET) { if (val & BMCR_RESET) {
// FIXME: needlessly high ? -- FR 02/07/2005 // FIXME: needlessly high ? -- FR 02/07/2005
mod_timer(&tp->timer, jiffies + HZ/10); mod_timer(&tp->timer, jiffies + HZ/10);
} else if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) & goto out_unlock;
BMSR_ANEGCOMPLETE)) { }
val = mdio_read_latched(ioaddr, phy_id, MII_BMSR);
if (!(val & BMSR_ANEGCOMPLETE) && tp->link_status != LNK_AUTONEG) {
netif_carrier_off(dev); netif_carrier_off(dev);
netif_warn(tp, link, dev, "auto-negotiating...\n"); netif_warn(tp, link, dev, "auto-negotiating...\n");
mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT); tp->link_status = LNK_AUTONEG;
} else { } else if ((val & BMSR_LSTATUS) && tp->link_status != LNK_ON) {
/* Rejoice ! */ /* Rejoice ! */
struct { struct {
int val; int val;
...@@ -1000,7 +1009,10 @@ static void sis190_phy_task(struct work_struct *work) ...@@ -1000,7 +1009,10 @@ static void sis190_phy_task(struct work_struct *work)
netif_info(tp, link, dev, "link on %s mode\n", p->msg); netif_info(tp, link, dev, "link on %s mode\n", p->msg);
netif_carrier_on(dev); netif_carrier_on(dev);
} tp->link_status = LNK_ON;
} else if (!(val & BMSR_LSTATUS) && tp->link_status != LNK_AUTONEG)
tp->link_status = LNK_OFF;
mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
out_unlock: out_unlock:
rtnl_unlock(); rtnl_unlock();
...@@ -1513,6 +1525,7 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev) ...@@ -1513,6 +1525,7 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
tp->pci_dev = pdev; tp->pci_dev = pdev;
tp->mmio_addr = ioaddr; tp->mmio_addr = ioaddr;
tp->link_status = LNK_OFF;
sis190_irq_mask_and_ack(ioaddr); sis190_irq_mask_and_ack(ioaddr);
......
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