Skip to content

Commit

Permalink
Merge branch 'net-phy-improve-PM-handling-of-PHY-MDIO'
Browse files Browse the repository at this point in the history
Heiner Kallweit says:

====================
net: phy: improve PM handling of PHY/MDIO

Current implementation of MDIO bus PM ops doesn't actually implement
bus-specific PM ops but just calls PM ops defined on a device level
what doesn't seem to be fully in line with the core PM model.

When looking e.g. at __device_suspend() the PM core looks for PM ops
of a device in a specific order:
1. device PM domain
2. device type
3. device class
4. device bus

I think it has good reason that there's no PM ops on device level.
The situation can be improved by modeling PHY's as device type of
a MDIO device. If for some other type of MDIO device PM ops are
needed, it could be modeled as struct device_type as well.
====================

Tested-by: Andrew Lunn <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Jun 5, 2018
2 parents 7d840a6 + 9107c05 commit 7a72309
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 95 deletions.
48 changes: 0 additions & 48 deletions drivers/net/phy/mdio_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,58 +717,10 @@ static int mdio_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0;
}

#ifdef CONFIG_PM
static int mdio_bus_suspend(struct device *dev)
{
struct mdio_device *mdio = to_mdio_device(dev);

if (mdio->pm_ops && mdio->pm_ops->suspend)
return mdio->pm_ops->suspend(dev);

return 0;
}

static int mdio_bus_resume(struct device *dev)
{
struct mdio_device *mdio = to_mdio_device(dev);

if (mdio->pm_ops && mdio->pm_ops->resume)
return mdio->pm_ops->resume(dev);

return 0;
}

static int mdio_bus_restore(struct device *dev)
{
struct mdio_device *mdio = to_mdio_device(dev);

if (mdio->pm_ops && mdio->pm_ops->restore)
return mdio->pm_ops->restore(dev);

return 0;
}

static const struct dev_pm_ops mdio_bus_pm_ops = {
.suspend = mdio_bus_suspend,
.resume = mdio_bus_resume,
.freeze = mdio_bus_suspend,
.thaw = mdio_bus_resume,
.restore = mdio_bus_restore,
};

#define MDIO_BUS_PM_OPS (&mdio_bus_pm_ops)

#else

#define MDIO_BUS_PM_OPS NULL

#endif /* CONFIG_PM */

struct bus_type mdio_bus_type = {
.name = "mdio_bus",
.match = mdio_bus_match,
.uevent = mdio_uevent,
.pm = MDIO_BUS_PM_OPS,
};
EXPORT_SYMBOL(mdio_bus_type);

Expand Down
96 changes: 50 additions & 46 deletions drivers/net/phy/phy_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,55 @@ static int phy_bus_match(struct device *dev, struct device_driver *drv)
}
}

static ssize_t
phy_id_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct phy_device *phydev = to_phy_device(dev);

return sprintf(buf, "0x%.8lx\n", (unsigned long)phydev->phy_id);
}
static DEVICE_ATTR_RO(phy_id);

static ssize_t
phy_interface_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct phy_device *phydev = to_phy_device(dev);
const char *mode = NULL;

if (phy_is_internal(phydev))
mode = "internal";
else
mode = phy_modes(phydev->interface);

return sprintf(buf, "%s\n", mode);
}
static DEVICE_ATTR_RO(phy_interface);

static ssize_t
phy_has_fixups_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct phy_device *phydev = to_phy_device(dev);

return sprintf(buf, "%d\n", phydev->has_fixups);
}
static DEVICE_ATTR_RO(phy_has_fixups);

static struct attribute *phy_dev_attrs[] = {
&dev_attr_phy_id.attr,
&dev_attr_phy_interface.attr,
&dev_attr_phy_has_fixups.attr,
NULL,
};
ATTRIBUTE_GROUPS(phy_dev);

static const struct device_type mdio_bus_phy_type = {
.name = "PHY",
.groups = phy_dev_groups,
.release = phy_device_release,
.pm = MDIO_BUS_PHY_PM_OPS,
};

struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
bool is_c45,
struct phy_c45_device_ids *c45_ids)
Expand All @@ -359,11 +408,10 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
return ERR_PTR(-ENOMEM);

mdiodev = &dev->mdio;
mdiodev->dev.release = phy_device_release;
mdiodev->dev.parent = &bus->dev;
mdiodev->dev.bus = &mdio_bus_type;
mdiodev->dev.type = &mdio_bus_phy_type;
mdiodev->bus = bus;
mdiodev->pm_ops = MDIO_BUS_PHY_PM_OPS;
mdiodev->bus_match = phy_bus_match;
mdiodev->addr = addr;
mdiodev->flags = MDIO_DEVICE_FLAG_PHY;
Expand Down Expand Up @@ -587,48 +635,6 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
}
EXPORT_SYMBOL(get_phy_device);

static ssize_t
phy_id_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct phy_device *phydev = to_phy_device(dev);

return sprintf(buf, "0x%.8lx\n", (unsigned long)phydev->phy_id);
}
static DEVICE_ATTR_RO(phy_id);

static ssize_t
phy_interface_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct phy_device *phydev = to_phy_device(dev);
const char *mode = NULL;

if (phy_is_internal(phydev))
mode = "internal";
else
mode = phy_modes(phydev->interface);

return sprintf(buf, "%s\n", mode);
}
static DEVICE_ATTR_RO(phy_interface);

static ssize_t
phy_has_fixups_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct phy_device *phydev = to_phy_device(dev);

return sprintf(buf, "%d\n", phydev->has_fixups);
}
static DEVICE_ATTR_RO(phy_has_fixups);

static struct attribute *phy_dev_attrs[] = {
&dev_attr_phy_id.attr,
&dev_attr_phy_interface.attr,
&dev_attr_phy_has_fixups.attr,
NULL,
};
ATTRIBUTE_GROUPS(phy_dev);

/**
* phy_device_register - Register the phy device on the MDIO bus
* @phydev: phy_device structure to be added to the MDIO bus
Expand All @@ -651,8 +657,6 @@ int phy_device_register(struct phy_device *phydev)
goto out;
}

phydev->mdio.dev.groups = phy_dev_groups;

err = device_add(&phydev->mdio.dev);
if (err) {
pr_err("PHY %d failed to add\n", phydev->mdio.addr);
Expand Down
1 change: 0 additions & 1 deletion include/linux/mdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ enum mdio_mutex_lock_class {
struct mdio_device {
struct device dev;

const struct dev_pm_ops *pm_ops;
struct mii_bus *bus;
char modalias[MDIO_NAME_SIZE];

Expand Down

0 comments on commit 7a72309

Please sign in to comment.