Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'ARM-imx6ul-14x14-evk-Fix-suspend-over-nfs-by-phy'

Leonard Crestez says:

====================
ARM: imx6ul-14x14-evk: Fix suspend over nfs by phy

Right now attempting doing suspend/resume while root is mounted over NFS
hangs on imx6ul-14x14-evk. This is happening because ksz8081 phy fixups are
lost on resume.

Fix this by using equivalent devicetree properties instead of a phy fixup
and handling those properties on resume in the micrel driver.

In theory it might now be possible to remove the phy fixup from mach-imx6ul
entirely but it is possible that this would break other imx6ul boards which
use the same phy. The solution would be to patch their dts but it's not
clear how to identify affected boards.

This code is shared with imx6ull-14x14-evk but 6ull suspend needs an
unrelated patch: https://lkml.org/lkml/2017/5/30/584

This is something of a corner case so there is no CC: stable.

Changes since v1: https://lkml.org/lkml/2017/5/30/672
* Split a kszphy_config_reset function for stuff shared between
config_init and resume. Calling config_init directly could be an option but
on some HW variants it does extra stuff like parsing devicetree options.
That would not be appropriate for resume code.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+34 -14
+6
arch/arm/boot/dts/imx6ul-14x14-evk.dts
··· 120 120 121 121 ethphy0: ethernet-phy@2 { 122 122 reg = <2>; 123 + micrel,led-mode = <1>; 124 + clocks = <&clks IMX6UL_CLK_ENET_REF>; 125 + clock-names = "rmii-ref"; 123 126 }; 124 127 125 128 ethphy1: ethernet-phy@1 { 126 129 reg = <1>; 130 + micrel,led-mode = <1>; 131 + clocks = <&clks IMX6UL_CLK_ENET2_REF>; 132 + clock-names = "rmii-ref"; 127 133 }; 128 134 }; 129 135 };
+28 -14
drivers/net/phy/micrel.c
··· 268 268 return ret; 269 269 } 270 270 271 + /* Some config bits need to be set again on resume, handle them here. */ 272 + static int kszphy_config_reset(struct phy_device *phydev) 273 + { 274 + struct kszphy_priv *priv = phydev->priv; 275 + int ret; 276 + 277 + if (priv->rmii_ref_clk_sel) { 278 + ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val); 279 + if (ret) { 280 + phydev_err(phydev, 281 + "failed to set rmii reference clock\n"); 282 + return ret; 283 + } 284 + } 285 + 286 + if (priv->led_mode >= 0) 287 + kszphy_setup_led(phydev, priv->type->led_mode_reg, priv->led_mode); 288 + 289 + return 0; 290 + } 291 + 271 292 static int kszphy_config_init(struct phy_device *phydev) 272 293 { 273 294 struct kszphy_priv *priv = phydev->priv; 274 295 const struct kszphy_type *type; 275 - int ret; 276 296 277 297 if (!priv) 278 298 return 0; ··· 305 285 if (type->has_nand_tree_disable) 306 286 kszphy_nand_tree_disable(phydev); 307 287 308 - if (priv->rmii_ref_clk_sel) { 309 - ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val); 310 - if (ret) { 311 - phydev_err(phydev, 312 - "failed to set rmii reference clock\n"); 313 - return ret; 314 - } 315 - } 316 - 317 - if (priv->led_mode >= 0) 318 - kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode); 319 - 320 - return 0; 288 + return kszphy_config_reset(phydev); 321 289 } 322 290 323 291 static int ksz8041_config_init(struct phy_device *phydev) ··· 708 700 709 701 static int kszphy_resume(struct phy_device *phydev) 710 702 { 703 + int ret; 704 + 711 705 genphy_resume(phydev); 706 + 707 + ret = kszphy_config_reset(phydev); 708 + if (ret) 709 + return ret; 712 710 713 711 /* Enable PHY Interrupts */ 714 712 if (phy_interrupt_is_valid(phydev)) {