From: Felix Fietkau Date: Thu, 27 Nov 2014 18:26:00 +0000 (+0000) Subject: kernel: backport patches for overriding PHY reset to 3.14 X-Git-Tag: reboot~5215 X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=77e1a3675ad9d97ca6b564c759b2aaa6437c6d8b;p=openwrt%2Fstaging%2Fxback.git kernel: backport patches for overriding PHY reset to 3.14 Signed-off-by: Felix Fietkau SVN-Revision: 43409 --- diff --git a/target/linux/generic/patches-3.14/070-net-phy-move-PHY-software-reset.patch b/target/linux/generic/patches-3.14/070-net-phy-move-PHY-software-reset.patch new file mode 100644 index 0000000000..007a7aad3d --- /dev/null +++ b/target/linux/generic/patches-3.14/070-net-phy-move-PHY-software-reset.patch @@ -0,0 +1,71 @@ +commit 797ac07137d9ae8572008e21e6123a9ae17dae50 +Author: Florian Fainelli +Date: Mon Feb 17 13:34:02 2014 -0800 + + net: phy: move PHY software reset to genphy_soft_reset + + As pointed out by Shaohui, this function is generic for 10/100/1000 + PHYs, but 10G PHYs might have a slightly different reset sequence which + prevents most of them from using this function. + + Move the BMCR_RESET based software resent sequence to + genphy_soft_reset() in preparation for allowing PHY drivers to implement + a soft_reset() callback. + + Reported-by: Shaohui Xie + Signed-off-by: Florian Fainelli + Signed-off-by: David S. Miller + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -539,11 +539,7 @@ int phy_init_hw(struct phy_device *phyde + if (!phydev->drv || !phydev->drv->config_init) + return 0; + +- ret = phy_write(phydev, MII_BMCR, BMCR_RESET); +- if (ret < 0) +- return ret; +- +- ret = phy_poll_reset(phydev); ++ ret = genphy_soft_reset(phydev); + if (ret < 0) + return ret; + +@@ -1029,6 +1025,27 @@ static int gen10g_read_status(struct phy + return 0; + } + ++/** ++ * genphy_soft_reset - software reset the PHY via BMCR_RESET bit ++ * @phydev: target phy_device struct ++ * ++ * Description: Perform a software PHY reset using the standard ++ * BMCR_RESET bit and poll for the reset bit to be cleared. ++ * ++ * Returns: 0 on success, < 0 on failure ++ */ ++int genphy_soft_reset(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, MII_BMCR, BMCR_RESET); ++ if (ret < 0) ++ return ret; ++ ++ return phy_poll_reset(phydev); ++} ++EXPORT_SYMBOL(genphy_soft_reset); ++ + static int genphy_config_init(struct phy_device *phydev) + { + int val; +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -616,6 +616,7 @@ int genphy_update_link(struct phy_device + int genphy_read_status(struct phy_device *phydev); + int genphy_suspend(struct phy_device *phydev); + int genphy_resume(struct phy_device *phydev); ++int genphy_soft_reset(struct phy_device *phydev); + void phy_driver_unregister(struct phy_driver *drv); + void phy_drivers_unregister(struct phy_driver *drv, int n); + int phy_driver_register(struct phy_driver *new_driver); diff --git a/target/linux/generic/patches-3.14/071-net-phy-override-PHY-reset.patch b/target/linux/generic/patches-3.14/071-net-phy-override-PHY-reset.patch new file mode 100644 index 0000000000..c70d40a677 --- /dev/null +++ b/target/linux/generic/patches-3.14/071-net-phy-override-PHY-reset.patch @@ -0,0 +1,81 @@ +commit 9df81dd7583d14862d0cfb673a941b261f3b2112 +Author: Florian Fainelli +Date: Mon Feb 17 13:34:03 2014 -0800 + + net: phy: allow PHY drivers to implement their own software reset + + As pointed out by Shaohui, most 10G PHYs out there have a non-standard + compliant software reset sequence, eventually something much more + complex than just toggling the BMCR_RESET bit. Allow PHY driver to + implement their own soft_reset() callback to deal with that. If no + callback is provided, call into genphy_soft_reset() which makes sure the + existing behavior is kept intact. + + Reported-by: Shaohui Xie + Signed-off-by: Florian Fainelli + Signed-off-by: David S. Miller + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -534,12 +534,16 @@ static int phy_poll_reset(struct phy_dev + + int phy_init_hw(struct phy_device *phydev) + { +- int ret; ++ int ret = 0; + + if (!phydev->drv || !phydev->drv->config_init) + return 0; + +- ret = genphy_soft_reset(phydev); ++ if (phydev->drv->soft_reset) ++ ret = phydev->drv->soft_reset(phydev); ++ else ++ ret = genphy_soft_reset(phydev); ++ + if (ret < 0) + return ret; + +@@ -1092,6 +1096,12 @@ static int genphy_config_init(struct phy + return 0; + } + ++static int gen10g_soft_reset(struct phy_device *phydev) ++{ ++ /* Do nothing for now */ ++ return 0; ++} ++ + static int gen10g_config_init(struct phy_device *phydev) + { + /* Temporarily just say we support everything */ +@@ -1266,6 +1276,7 @@ static struct phy_driver genphy_driver[] + .phy_id = 0xffffffff, + .phy_id_mask = 0xffffffff, + .name = "Generic PHY", ++ .soft_reset = genphy_soft_reset, + .config_init = genphy_config_init, + .features = 0, + .config_aneg = genphy_config_aneg, +@@ -1277,6 +1288,7 @@ static struct phy_driver genphy_driver[] + .phy_id = 0xffffffff, + .phy_id_mask = 0xffffffff, + .name = "Generic 10G PHY", ++ .soft_reset = gen10g_soft_reset, + .config_init = gen10g_config_init, + .features = 0, + .config_aneg = gen10g_config_aneg, +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -394,6 +394,11 @@ struct phy_driver { + u32 flags; + + /* ++ * Called to issue a PHY software reset ++ */ ++ int (*soft_reset)(struct phy_device *phydev); ++ ++ /* + * Called to initialize the PHY, + * including after a reset + */ diff --git a/target/linux/generic/patches-3.14/701-phy_extension.patch b/target/linux/generic/patches-3.14/701-phy_extension.patch index 4c1841155f..eda088fe20 100644 --- a/target/linux/generic/patches-3.14/701-phy_extension.patch +++ b/target/linux/generic/patches-3.14/701-phy_extension.patch @@ -53,7 +53,7 @@ * @phydev: the phy_device struct --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -627,6 +627,7 @@ void phy_start_machine(struct phy_device +@@ -633,6 +633,7 @@ void phy_start_machine(struct phy_device void phy_stop_machine(struct phy_device *phydev); int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd); int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd); diff --git a/target/linux/generic/patches-3.14/702-phy_add_aneg_done_function.patch b/target/linux/generic/patches-3.14/702-phy_add_aneg_done_function.patch index d634647ddb..b617fc2575 100644 --- a/target/linux/generic/patches-3.14/702-phy_add_aneg_done_function.patch +++ b/target/linux/generic/patches-3.14/702-phy_add_aneg_done_function.patch @@ -1,6 +1,6 @@ --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -417,9 +417,18 @@ struct phy_driver { +@@ -422,9 +422,18 @@ struct phy_driver { */ int (*config_aneg)(struct phy_device *phydev); diff --git a/target/linux/generic/patches-3.14/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/patches-3.14/703-phy-add-detach-callback-to-struct-phy_driver.patch index f4750bd56e..fee6b8c6c0 100644 --- a/target/linux/generic/patches-3.14/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/patches-3.14/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -12,7 +12,7 @@ phy_suspend(phydev); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -441,6 +441,12 @@ struct phy_driver { +@@ -446,6 +446,12 @@ struct phy_driver { */ int (*did_interrupt)(struct phy_device *phydev); diff --git a/target/linux/generic/patches-3.14/710-phy-add-mdio_register_board_info.patch b/target/linux/generic/patches-3.14/710-phy-add-mdio_register_board_info.patch index 91ae12630a..757616fa32 100644 --- a/target/linux/generic/patches-3.14/710-phy-add-mdio_register_board_info.patch +++ b/target/linux/generic/patches-3.14/710-phy-add-mdio_register_board_info.patch @@ -45,7 +45,7 @@ phy_device_free(phydev); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -667,4 +667,22 @@ int __init mdio_bus_init(void); +@@ -673,4 +673,22 @@ int __init mdio_bus_init(void); void mdio_bus_exit(void); extern struct bus_type mdio_bus_type;