diff options
author | Riccardo Ghetta <birrachiara@tin.it> | 2009-06-04 05:05:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-06-08 03:15:14 -0400 |
commit | 1feede014bf3c58f60b35f91dcd8a2f89b3908ad (patch) | |
tree | a0e7058620a59c7e11931ed6769c774c2a502422 /drivers/net/sis190.c | |
parent | 856f8f41d44c9a310665213745bba655e52641fd (diff) |
sis190: fix gigabit negotiation
Fixes an initialization error; the chip negotiates gigabit, but
the driver mistakenly handled it as 100Mb.
Changes based on both SiS own GPL driver and forcedeth.
Hopefully should fix
http://bugzilla.kernel.org/show_bug.cgi?id=9735
http://bugzilla.kernel.org/show_bug.cgi?id=11149
Signed-off-by: Riccardo Ghetta <birrachiara@tin.it>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sis190.c')
-rw-r--r-- | drivers/net/sis190.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 75bd947d40bf..e2247669a495 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c | |||
@@ -47,7 +47,7 @@ | |||
47 | #define PHY_ID_ANY 0x1f | 47 | #define PHY_ID_ANY 0x1f |
48 | #define MII_REG_ANY 0x1f | 48 | #define MII_REG_ANY 0x1f |
49 | 49 | ||
50 | #define DRV_VERSION "1.2" | 50 | #define DRV_VERSION "1.3" |
51 | #define DRV_NAME "sis190" | 51 | #define DRV_NAME "sis190" |
52 | #define SIS190_DRIVER_NAME DRV_NAME " Gigabit Ethernet driver " DRV_VERSION | 52 | #define SIS190_DRIVER_NAME DRV_NAME " Gigabit Ethernet driver " DRV_VERSION |
53 | #define PFX DRV_NAME ": " | 53 | #define PFX DRV_NAME ": " |
@@ -943,9 +943,9 @@ static void sis190_phy_task(struct work_struct *work) | |||
943 | u32 ctl; | 943 | u32 ctl; |
944 | const char *msg; | 944 | const char *msg; |
945 | } reg31[] = { | 945 | } reg31[] = { |
946 | { LPA_1000XFULL | LPA_SLCT, 0x07000c00 | 0x00001000, | 946 | { LPA_1000FULL, 0x07000c00 | 0x00001000, |
947 | "1000 Mbps Full Duplex" }, | 947 | "1000 Mbps Full Duplex" }, |
948 | { LPA_1000XHALF | LPA_SLCT, 0x07000c00, | 948 | { LPA_1000HALF, 0x07000c00, |
949 | "1000 Mbps Half Duplex" }, | 949 | "1000 Mbps Half Duplex" }, |
950 | { LPA_100FULL, 0x04000800 | 0x00001000, | 950 | { LPA_100FULL, 0x04000800 | 0x00001000, |
951 | "100 Mbps Full Duplex" }, | 951 | "100 Mbps Full Duplex" }, |
@@ -956,22 +956,35 @@ static void sis190_phy_task(struct work_struct *work) | |||
956 | { LPA_10HALF, 0x04000400, | 956 | { LPA_10HALF, 0x04000400, |
957 | "10 Mbps Half Duplex" }, | 957 | "10 Mbps Half Duplex" }, |
958 | { 0, 0x04000400, "unknown" } | 958 | { 0, 0x04000400, "unknown" } |
959 | }, *p; | 959 | }, *p = NULL; |
960 | u16 adv; | 960 | u16 adv, autoexp, gigadv, gigrec; |
961 | 961 | ||
962 | val = mdio_read(ioaddr, phy_id, 0x1f); | 962 | val = mdio_read(ioaddr, phy_id, 0x1f); |
963 | net_link(tp, KERN_INFO "%s: mii ext = %04x.\n", dev->name, val); | 963 | net_link(tp, KERN_INFO "%s: mii ext = %04x.\n", dev->name, val); |
964 | 964 | ||
965 | val = mdio_read(ioaddr, phy_id, MII_LPA); | 965 | val = mdio_read(ioaddr, phy_id, MII_LPA); |
966 | adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE); | 966 | adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE); |
967 | net_link(tp, KERN_INFO "%s: mii lpa = %04x adv = %04x.\n", | 967 | autoexp = mdio_read(ioaddr, phy_id, MII_EXPANSION); |
968 | dev->name, val, adv); | 968 | net_link(tp, KERN_INFO "%s: mii lpa=%04x adv=%04x exp=%04x.\n", |
969 | 969 | dev->name, val, adv, autoexp); | |
970 | val &= adv; | 970 | |
971 | if (val & LPA_NPAGE && autoexp & EXPANSION_NWAY) { | ||
972 | /* check for gigabit speed */ | ||
973 | gigadv = mdio_read(ioaddr, phy_id, MII_CTRL1000); | ||
974 | gigrec = mdio_read(ioaddr, phy_id, MII_STAT1000); | ||
975 | val = (gigadv & (gigrec >> 2)); | ||
976 | if (val & ADVERTISE_1000FULL) | ||
977 | p = reg31; | ||
978 | else if (val & ADVERTISE_1000HALF) | ||
979 | p = reg31 + 1; | ||
980 | } | ||
981 | if (!p) { | ||
982 | val &= adv; | ||
971 | 983 | ||
972 | for (p = reg31; p->val; p++) { | 984 | for (p = reg31; p->val; p++) { |
973 | if ((val & p->val) == p->val) | 985 | if ((val & p->val) == p->val) |
974 | break; | 986 | break; |
987 | } | ||
975 | } | 988 | } |
976 | 989 | ||
977 | p->ctl |= SIS_R32(StationControl) & ~0x0f001c00; | 990 | p->ctl |= SIS_R32(StationControl) & ~0x0f001c00; |