Messages in this thread Patch in this message | | | From | Horatiu Vultur <> | Subject | [RFC PATCH net-next 1/2] net: phy: Add phy latency adjustment support in phy framework. | Date | Tue, 19 Apr 2022 10:37:03 +0200 |
| |
Add adjustment support for latency for the phy using sysfs. This is used to adjust the latency of the phy based on link mode and direction.
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com> --- .../ABI/testing/sysfs-class-net-phydev | 10 ++++ drivers/net/phy/phy_device.c | 58 +++++++++++++++++++ include/linux/phy.h | 9 +++ 3 files changed, 77 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-class-net-phydev b/Documentation/ABI/testing/sysfs-class-net-phydev index ac722dd5e694..a99bbfeddb6f 100644 --- a/Documentation/ABI/testing/sysfs-class-net-phydev +++ b/Documentation/ABI/testing/sysfs-class-net-phydev @@ -63,3 +63,13 @@ Description: only used internally by the kernel and their placement are not meant to be stable across kernel versions. This is intended for facilitating the debugging of PHY drivers. + +What: /sys/class/mdio_bus/<bus>/<device>/adjust_latency +Date: April 2022 +KernelVersion: 5.19 +Contact: netdev@vger.kernel.org +Description: + This file adjusts the latency in the PHY. To set value, + write three integers into the file: interface mode, RX latency, + TX latency. When the file is read, it returns the supported + interface modes and the latency values. diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8406ac739def..80bf04ca0e02 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -529,6 +529,48 @@ static ssize_t phy_dev_flags_show(struct device *dev, } static DEVICE_ATTR_RO(phy_dev_flags); +static ssize_t adjust_latency_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct phy_device *phydev = to_phy_device(dev); + ssize_t count = 0; + int err, i; + s32 rx, tx; + + for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; ++i) { + err = phydev->drv->get_adj_latency(phydev, i, &rx, &tx); + if (err == -EINVAL) + continue; + + count += sprintf(&buf[count], "%d rx: %d, tx: %d\n", i, rx, tx); + } + + return count; +} + +static ssize_t adjust_latency_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct phy_device *phydev = to_phy_device(dev); + enum ethtool_link_mode_bit_indices link_mode; + int cnt, err = -EINVAL; + s32 rx, tx; + + cnt = sscanf(buf, "%u %d %d", &link_mode, &rx, &tx); + if (cnt != 3) + goto out; + + err = phydev->drv->set_adj_latency(phydev, link_mode, rx, tx); + if (err) + goto out; + + return count; +out: + return err; +} +static DEVICE_ATTR_RW(adjust_latency); + static struct attribute *phy_dev_attrs[] = { &dev_attr_phy_id.attr, &dev_attr_phy_interface.attr, @@ -3009,6 +3051,16 @@ static int phy_probe(struct device *dev) phydev->drv = phydrv; + if (phydev->drv && + phydev->drv->set_adj_latency && + phydev->drv->get_adj_latency) { + err = sysfs_create_file(&phydev->mdio.dev.kobj, + &dev_attr_adjust_latency.attr); + if (err) + phydev_err(phydev, "error creating 'adjust_latency' sysfs entry\n"); + err = 0; + } + /* Disable the interrupt if the PHY doesn't support it * but the interrupt is still a valid one */ @@ -3112,6 +3164,12 @@ static int phy_remove(struct device *dev) if (phydev->drv && phydev->drv->remove) phydev->drv->remove(phydev); + if (phydev->drv && + phydev->drv->set_adj_latency && + phydev->drv->get_adj_latency) + sysfs_remove_file(&phydev->mdio.dev.kobj, + &dev_attr_adjust_latency.attr); + /* Assert the reset signal */ phy_device_reset(phydev, 1); diff --git a/include/linux/phy.h b/include/linux/phy.h index 36ca2b5c2253..584e467ff4d1 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -932,6 +932,15 @@ struct phy_driver { int (*get_sqi)(struct phy_device *dev); /** @get_sqi_max: Get the maximum signal quality indication */ int (*get_sqi_max)(struct phy_device *dev); + /** @set_adj_latency: Set the latency values of the PHY */ + int (*set_adj_latency)(struct phy_device *dev, + enum ethtool_link_mode_bit_indices link_mode, + s32 rx, s32 tx); + /** @get_latency: Get the latency values of the PHY */ + int (*get_adj_latency)(struct phy_device *dev, + enum ethtool_link_mode_bit_indices link_mode, + s32 *rx, s32 *tx); + }; #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ struct phy_driver, mdiodrv) -- 2.33.0
| |