Commit f7b9820d authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'sh_eth-fix-reboot-crash'

Geert Uytterhoeven says:

====================
sh_eth: Fix reboot crash

This patch fixes a regression v5.11-rc1, where rebooting while a sh_eth
device is not opened will cause a crash.

Changes compared to v1:
  - Export mdiobb_{read,write}(),
  - Call mdiobb_{read,write}() now they are exported,
  - Use mii_bus.parent to avoid bb_info.dev copy,
  - Drop RFC state.

Alternatively, mdio-bitbang could provide Runtime PM-aware wrappers
itself, and use them either manually (through a new parameter to
alloc_mdio_bitbang(), or a new alloc_mdio_bitbang_*() function), or
automatically (e.g. if pm_runtime_enabled() returns true).  Note that
the latter requires a "struct device *" parameter to operate on.
Currently there are only two drivers that call alloc_mdio_bitbang() and
use Runtime PM: the Renesas sh_eth and ravb drivers.  This series fixes
the former, while the latter is not affected (it keeps the device
powered all the time between driver probe and driver unbind, and
changing that seems to be non-trivial).
====================

Link: https://lore.kernel.org/r/20210118150656.796584-1-geert+renesas@glider.beSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 7e238de8 02cae02a
...@@ -3034,6 +3034,28 @@ static int sh_mdio_release(struct sh_eth_private *mdp) ...@@ -3034,6 +3034,28 @@ static int sh_mdio_release(struct sh_eth_private *mdp)
return 0; return 0;
} }
static int sh_mdiobb_read(struct mii_bus *bus, int phy, int reg)
{
int res;
pm_runtime_get_sync(bus->parent);
res = mdiobb_read(bus, phy, reg);
pm_runtime_put(bus->parent);
return res;
}
static int sh_mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
{
int res;
pm_runtime_get_sync(bus->parent);
res = mdiobb_write(bus, phy, reg, val);
pm_runtime_put(bus->parent);
return res;
}
/* MDIO bus init function */ /* MDIO bus init function */
static int sh_mdio_init(struct sh_eth_private *mdp, static int sh_mdio_init(struct sh_eth_private *mdp,
struct sh_eth_plat_data *pd) struct sh_eth_plat_data *pd)
...@@ -3058,6 +3080,10 @@ static int sh_mdio_init(struct sh_eth_private *mdp, ...@@ -3058,6 +3080,10 @@ static int sh_mdio_init(struct sh_eth_private *mdp,
if (!mdp->mii_bus) if (!mdp->mii_bus)
return -ENOMEM; return -ENOMEM;
/* Wrap accessors with Runtime PM-aware ops */
mdp->mii_bus->read = sh_mdiobb_read;
mdp->mii_bus->write = sh_mdiobb_write;
/* Hook up MII support for ethtool */ /* Hook up MII support for ethtool */
mdp->mii_bus->name = "sh_mii"; mdp->mii_bus->name = "sh_mii";
mdp->mii_bus->parent = dev; mdp->mii_bus->parent = dev;
......
...@@ -149,7 +149,7 @@ static int mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, u32 addr) ...@@ -149,7 +149,7 @@ static int mdiobb_cmd_addr(struct mdiobb_ctrl *ctrl, int phy, u32 addr)
return dev_addr; return dev_addr;
} }
static int mdiobb_read(struct mii_bus *bus, int phy, int reg) int mdiobb_read(struct mii_bus *bus, int phy, int reg)
{ {
struct mdiobb_ctrl *ctrl = bus->priv; struct mdiobb_ctrl *ctrl = bus->priv;
int ret, i; int ret, i;
...@@ -180,8 +180,9 @@ static int mdiobb_read(struct mii_bus *bus, int phy, int reg) ...@@ -180,8 +180,9 @@ static int mdiobb_read(struct mii_bus *bus, int phy, int reg)
mdiobb_get_bit(ctrl); mdiobb_get_bit(ctrl);
return ret; return ret;
} }
EXPORT_SYMBOL(mdiobb_read);
static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
{ {
struct mdiobb_ctrl *ctrl = bus->priv; struct mdiobb_ctrl *ctrl = bus->priv;
...@@ -201,6 +202,7 @@ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) ...@@ -201,6 +202,7 @@ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
mdiobb_get_bit(ctrl); mdiobb_get_bit(ctrl);
return 0; return 0;
} }
EXPORT_SYMBOL(mdiobb_write);
struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl) struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)
{ {
......
...@@ -35,6 +35,9 @@ struct mdiobb_ctrl { ...@@ -35,6 +35,9 @@ struct mdiobb_ctrl {
const struct mdiobb_ops *ops; const struct mdiobb_ops *ops;
}; };
int mdiobb_read(struct mii_bus *bus, int phy, int reg);
int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val);
/* The returned bus is not yet registered with the phy layer. */ /* The returned bus is not yet registered with the phy layer. */
struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl); struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment