diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2008-11-03 19:54:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-03 19:54:56 -0500 |
commit | 9c61d6bc56bf0a5fb1ebfcf4c168cc5ce30e153b (patch) | |
tree | 7e5f3e66d24b7456d98a5aa9f9a0ca3f0db63130 | |
parent | 0a459aac9d151c2e36ec65723b9b845b24c5cbc3 (diff) |
tg3: Refine phylib support
This patch refines the phylib support in the tg3 driver. The patch does
the following things :
* Rename tg3_mdio_config() to tg3_mdio_config_5785(). The 5785 will be
the only device that will use it so the name might as well reflect
that.
* Fix a memory leak if mdiobus_register() fails.
* Add code to deal with phy device detection failures.
* Add code to correct the supported list of phy features based on the
MAC <=> PHY interface.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/tg3.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d0f314c6dbb0..03a930ef5d60 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -877,7 +877,7 @@ static int tg3_mdio_reset(struct mii_bus *bp) | |||
877 | return 0; | 877 | return 0; |
878 | } | 878 | } |
879 | 879 | ||
880 | static void tg3_mdio_config(struct tg3 *tp) | 880 | static void tg3_mdio_config_5785(struct tg3 *tp) |
881 | { | 881 | { |
882 | u32 val; | 882 | u32 val; |
883 | 883 | ||
@@ -934,8 +934,9 @@ static void tg3_mdio_start(struct tg3 *tp) | |||
934 | tw32_f(MAC_MI_MODE, tp->mi_mode); | 934 | tw32_f(MAC_MI_MODE, tp->mi_mode); |
935 | udelay(80); | 935 | udelay(80); |
936 | 936 | ||
937 | if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) | 937 | if ((tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) && |
938 | tg3_mdio_config(tp); | 938 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) |
939 | tg3_mdio_config_5785(tp); | ||
939 | } | 940 | } |
940 | 941 | ||
941 | static void tg3_mdio_stop(struct tg3 *tp) | 942 | static void tg3_mdio_stop(struct tg3 *tp) |
@@ -989,14 +990,20 @@ static int tg3_mdio_init(struct tg3 *tp) | |||
989 | if (i) { | 990 | if (i) { |
990 | printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n", | 991 | printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n", |
991 | tp->dev->name, i); | 992 | tp->dev->name, i); |
993 | mdiobus_free(tp->mdio_bus); | ||
992 | return i; | 994 | return i; |
993 | } | 995 | } |
994 | 996 | ||
995 | tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED; | ||
996 | |||
997 | phydev = tp->mdio_bus->phy_map[PHY_ADDR]; | 997 | phydev = tp->mdio_bus->phy_map[PHY_ADDR]; |
998 | 998 | ||
999 | switch (phydev->phy_id) { | 999 | if (!phydev || !phydev->drv) { |
1000 | printk(KERN_WARNING "%s: No PHY devices\n", tp->dev->name); | ||
1001 | mdiobus_unregister(tp->mdio_bus); | ||
1002 | mdiobus_free(tp->mdio_bus); | ||
1003 | return -ENODEV; | ||
1004 | } | ||
1005 | |||
1006 | switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) { | ||
1000 | case TG3_PHY_ID_BCM50610: | 1007 | case TG3_PHY_ID_BCM50610: |
1001 | phydev->interface = PHY_INTERFACE_MODE_RGMII; | 1008 | phydev->interface = PHY_INTERFACE_MODE_RGMII; |
1002 | if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) | 1009 | if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) |
@@ -1011,7 +1018,10 @@ static int tg3_mdio_init(struct tg3 *tp) | |||
1011 | break; | 1018 | break; |
1012 | } | 1019 | } |
1013 | 1020 | ||
1014 | tg3_mdio_config(tp); | 1021 | tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED; |
1022 | |||
1023 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) | ||
1024 | tg3_mdio_config_5785(tp); | ||
1015 | 1025 | ||
1016 | return 0; | 1026 | return 0; |
1017 | } | 1027 | } |
@@ -1351,12 +1361,25 @@ static int tg3_phy_init(struct tg3 *tp) | |||
1351 | return PTR_ERR(phydev); | 1361 | return PTR_ERR(phydev); |
1352 | } | 1362 | } |
1353 | 1363 | ||
1354 | tp->tg3_flags3 |= TG3_FLG3_PHY_CONNECTED; | ||
1355 | |||
1356 | /* Mask with MAC supported features. */ | 1364 | /* Mask with MAC supported features. */ |
1357 | phydev->supported &= (PHY_GBIT_FEATURES | | 1365 | switch (phydev->interface) { |
1358 | SUPPORTED_Pause | | 1366 | case PHY_INTERFACE_MODE_GMII: |
1359 | SUPPORTED_Asym_Pause); | 1367 | case PHY_INTERFACE_MODE_RGMII: |
1368 | phydev->supported &= (PHY_GBIT_FEATURES | | ||
1369 | SUPPORTED_Pause | | ||
1370 | SUPPORTED_Asym_Pause); | ||
1371 | break; | ||
1372 | case PHY_INTERFACE_MODE_MII: | ||
1373 | phydev->supported &= (PHY_BASIC_FEATURES | | ||
1374 | SUPPORTED_Pause | | ||
1375 | SUPPORTED_Asym_Pause); | ||
1376 | break; | ||
1377 | default: | ||
1378 | phy_disconnect(tp->mdio_bus->phy_map[PHY_ADDR]); | ||
1379 | return -EINVAL; | ||
1380 | } | ||
1381 | |||
1382 | tp->tg3_flags3 |= TG3_FLG3_PHY_CONNECTED; | ||
1360 | 1383 | ||
1361 | phydev->advertising = phydev->supported; | 1384 | phydev->advertising = phydev->supported; |
1362 | 1385 | ||