aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sis190.c
diff options
context:
space:
mode:
authorHerton Ronaldo Krzesinski <herton@mandriva.com.br>2010-03-02 06:44:41 -0500
committerDavid S. Miller <davem@davemloft.net>2010-03-02 06:44:41 -0500
commitb88aafd365bc6a2222e2d03ff320adea3a37f628 (patch)
tree519c4893ca656ff997bdd3e016d6bb4172faeec2 /drivers/net/sis190.c
parent4ab408dea0f0dba4dec0555f4f35b7ae703f5e91 (diff)
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=11926 Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sis190.c')
-rw-r--r--drivers/net/sis190.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 80af4a44580e..760d9e83a465 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -285,6 +285,11 @@ struct sis190_private {
285 struct list_head first_phy; 285 struct list_head first_phy;
286 u32 features; 286 u32 features;
287 u32 negotiated_lpa; 287 u32 negotiated_lpa;
288 enum {
289 LNK_OFF,
290 LNK_ON,
291 LNK_AUTONEG,
292 } link_status;
288}; 293};
289 294
290struct sis190_phy { 295struct sis190_phy {
@@ -750,6 +755,7 @@ static irqreturn_t sis190_interrupt(int irq, void *__dev)
750 755
751 if (status & LinkChange) { 756 if (status & LinkChange) {
752 netif_info(tp, intr, dev, "link change\n"); 757 netif_info(tp, intr, dev, "link change\n");
758 del_timer(&tp->timer);
753 schedule_work(&tp->phy_task); 759 schedule_work(&tp->phy_task);
754 } 760 }
755 761
@@ -922,12 +928,15 @@ static void sis190_phy_task(struct work_struct *work)
922 if (val & BMCR_RESET) { 928 if (val & BMCR_RESET) {
923 // FIXME: needlessly high ? -- FR 02/07/2005 929 // FIXME: needlessly high ? -- FR 02/07/2005
924 mod_timer(&tp->timer, jiffies + HZ/10); 930 mod_timer(&tp->timer, jiffies + HZ/10);
925 } else if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) & 931 goto out_unlock;
926 BMSR_ANEGCOMPLETE)) { 932 }
933
934 val = mdio_read_latched(ioaddr, phy_id, MII_BMSR);
935 if (!(val & BMSR_ANEGCOMPLETE) && tp->link_status != LNK_AUTONEG) {
927 netif_carrier_off(dev); 936 netif_carrier_off(dev);
928 netif_warn(tp, link, dev, "auto-negotiating...\n"); 937 netif_warn(tp, link, dev, "auto-negotiating...\n");
929 mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT); 938 tp->link_status = LNK_AUTONEG;
930 } else { 939 } else if ((val & BMSR_LSTATUS) && tp->link_status != LNK_ON) {
931 /* Rejoice ! */ 940 /* Rejoice ! */
932 struct { 941 struct {
933 int val; 942 int val;
@@ -1000,7 +1009,10 @@ static void sis190_phy_task(struct work_struct *work)
1000 1009
1001 netif_info(tp, link, dev, "link on %s mode\n", p->msg); 1010 netif_info(tp, link, dev, "link on %s mode\n", p->msg);
1002 netif_carrier_on(dev); 1011 netif_carrier_on(dev);
1003 } 1012 tp->link_status = LNK_ON;
1013 } else if (!(val & BMSR_LSTATUS) && tp->link_status != LNK_AUTONEG)
1014 tp->link_status = LNK_OFF;
1015 mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
1004 1016
1005out_unlock: 1017out_unlock:
1006 rtnl_unlock(); 1018 rtnl_unlock();
@@ -1513,6 +1525,7 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
1513 1525
1514 tp->pci_dev = pdev; 1526 tp->pci_dev = pdev;
1515 tp->mmio_addr = ioaddr; 1527 tp->mmio_addr = ioaddr;
1528 tp->link_status = LNK_OFF;
1516 1529
1517 sis190_irq_mask_and_ack(ioaddr); 1530 sis190_irq_mask_and_ack(ioaddr);
1518 1531