diff options
| -rw-r--r-- | drivers/net/sis190.c | 23 |
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 | ||
| 290 | struct sis190_phy { | 295 | struct 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 | ||
| 1005 | out_unlock: | 1017 | out_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 | ||
