lkml.org 
[lkml]   [2023]   [Aug]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v9 net-next 11/12] net: phy: provide phylib stubs for hardware timestamping operations
    Date
    net/core/dev_ioctl.c (built-in code) will want to call phy_mii_ioctl()
    for hardware timestamping purposes. This is not directly possible,
    because phy_mii_ioctl() is a symbol provided under CONFIG_PHYLIB.

    Do something similar to what was done in DSA in commit 5a17818682cf
    ("net: dsa: replace NETDEV_PRE_CHANGE_HWTSTAMP notifier with a stub"),
    and arrange some indirect calls to phy_mii_ioctl() through a stub
    structure containing function pointers, that's provided by phylib as
    built-in even when CONFIG_PHYLIB=m, and which phy_init() populates at
    runtime (module insertion).

    Note: maybe the ownership of the ethtool_phy_ops singleton is backwards,
    and the methods exposed by that should be later merged into phylib_stubs.

    Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
    ---
    Changes in v9:
    - Add MAINTAINERS entry
    - Add missing include/linux/phylib_stubs.h
    - Add missing drivers/net/phy/stubs.c
    Changes in v8:
    - Patch is new

    MAINTAINERS | 1 +
    drivers/net/phy/Makefile | 2 ++
    drivers/net/phy/phy.c | 34 ++++++++++++++++++
    drivers/net/phy/phy_device.c | 19 ++++++++++
    drivers/net/phy/stubs.c | 10 ++++++
    include/linux/phy.h | 7 ++++
    include/linux/phylib_stubs.h | 68 ++++++++++++++++++++++++++++++++++++
    7 files changed, 141 insertions(+)
    create mode 100644 drivers/net/phy/stubs.c
    create mode 100644 include/linux/phylib_stubs.h

    diff --git a/MAINTAINERS b/MAINTAINERS
    index c4f95a9d03b9..069e176d607a 100644
    --- a/MAINTAINERS
    +++ b/MAINTAINERS
    @@ -7752,6 +7752,7 @@ F: include/linux/mii.h
    F: include/linux/of_net.h
    F: include/linux/phy.h
    F: include/linux/phy_fixed.h
    +F: include/linux/phylib_stubs.h
    F: include/linux/platform_data/mdio-bcm-unimac.h
    F: include/linux/platform_data/mdio-gpio.h
    F: include/trace/events/mdio.h
    diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
    index 35142780fc9d..c945ed9bd14b 100644
    --- a/drivers/net/phy/Makefile
    +++ b/drivers/net/phy/Makefile
    @@ -14,6 +14,8 @@ endif
    # dedicated loadable module, so we bundle them all together into libphy.ko
    ifdef CONFIG_PHYLIB
    libphy-y += $(mdio-bus-y)
    +# the stubs are built-in whenever PHYLIB is built-in or module
    +obj-y += stubs.o
    else
    obj-$(CONFIG_MDIO_DEVICE) += mdio-bus.o
    endif
    diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
    index bdf00b2b2c1d..8aec8e83038c 100644
    --- a/drivers/net/phy/phy.c
    +++ b/drivers/net/phy/phy.c
    @@ -455,6 +455,40 @@ int phy_do_ioctl_running(struct net_device *dev, struct ifreq *ifr, int cmd)
    }
    EXPORT_SYMBOL(phy_do_ioctl_running);

    +/**
    + * __phy_hwtstamp_get - Get hardware timestamping configuration from PHY
    + *
    + * @phydev: the PHY device structure
    + * @config: structure holding the timestamping configuration
    + *
    + * Query the PHY device for its current hardware timestamping configuration.
    + */
    +int __phy_hwtstamp_get(struct phy_device *phydev,
    + struct kernel_hwtstamp_config *config)
    +{
    + if (!phydev)
    + return -ENODEV;
    +
    + return phy_mii_ioctl(phydev, config->ifr, SIOCGHWTSTAMP);
    +}
    +
    +/**
    + * __phy_hwtstamp_set - Modify PHY hardware timestamping configuration
    + *
    + * @phydev: the PHY device structure
    + * @config: structure holding the timestamping configuration
    + * @extack: netlink extended ack structure, for error reporting
    + */
    +int __phy_hwtstamp_set(struct phy_device *phydev,
    + struct kernel_hwtstamp_config *config,
    + struct netlink_ext_ack *extack)
    +{
    + if (!phydev)
    + return -ENODEV;
    +
    + return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP);
    +}
    +
    /**
    * phy_queue_state_machine - Trigger the state machine to run soon
    *
    diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
    index 98b8ac28e5a1..e19c4fee8d22 100644
    --- a/drivers/net/phy/phy_device.c
    +++ b/drivers/net/phy/phy_device.c
    @@ -27,6 +27,7 @@
    #include <linux/of.h>
    #include <linux/netdevice.h>
    #include <linux/phy.h>
    +#include <linux/phylib_stubs.h>
    #include <linux/phy_led_triggers.h>
    #include <linux/pse-pd/pse.h>
    #include <linux/property.h>
    @@ -3448,12 +3449,28 @@ static const struct ethtool_phy_ops phy_ethtool_phy_ops = {
    .start_cable_test_tdr = phy_start_cable_test_tdr,
    };

    +static const struct phylib_stubs __phylib_stubs = {
    + .hwtstamp_get = __phy_hwtstamp_get,
    + .hwtstamp_set = __phy_hwtstamp_set,
    +};
    +
    +static void phylib_register_stubs(void)
    +{
    + phylib_stubs = &__phylib_stubs;
    +}
    +
    +static void phylib_unregister_stubs(void)
    +{
    + phylib_stubs = NULL;
    +}
    +
    static int __init phy_init(void)
    {
    int rc;

    rtnl_lock();
    ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
    + phylib_register_stubs();
    rtnl_unlock();

    rc = mdio_bus_init();
    @@ -3478,6 +3495,7 @@ static int __init phy_init(void)
    mdio_bus_exit();
    err_ethtool_phy_ops:
    rtnl_lock();
    + phylib_unregister_stubs();
    ethtool_set_ethtool_phy_ops(NULL);
    rtnl_unlock();

    @@ -3490,6 +3508,7 @@ static void __exit phy_exit(void)
    phy_driver_unregister(&genphy_driver);
    mdio_bus_exit();
    rtnl_lock();
    + phylib_unregister_stubs();
    ethtool_set_ethtool_phy_ops(NULL);
    rtnl_unlock();
    }
    diff --git a/drivers/net/phy/stubs.c b/drivers/net/phy/stubs.c
    new file mode 100644
    index 000000000000..cfb9f275eb18
    --- /dev/null
    +++ b/drivers/net/phy/stubs.c
    @@ -0,0 +1,10 @@
    +// SPDX-License-Identifier: GPL-2.0+
    +/*
    + * Stubs for PHY library functionality called by the core network stack.
    + * These are necessary because CONFIG_PHYLIB can be a module, and built-in
    + * code cannot directly call symbols exported by modules.
    + */
    +#include <linux/phylib_stubs.h>
    +
    +const struct phylib_stubs *phylib_stubs;
    +EXPORT_SYMBOL_GPL(phylib_stubs);
    diff --git a/include/linux/phy.h b/include/linux/phy.h
    index b254848a9c99..ba08b0e60279 100644
    --- a/include/linux/phy.h
    +++ b/include/linux/phy.h
    @@ -298,6 +298,7 @@ static inline const char *phy_modes(phy_interface_t interface)
    #define MII_BUS_ID_SIZE 61

    struct device;
    +struct kernel_hwtstamp_config;
    struct phylink;
    struct sfp_bus;
    struct sfp_upstream_ops;
    @@ -1955,6 +1956,12 @@ int phy_ethtool_set_plca_cfg(struct phy_device *phydev,
    int phy_ethtool_get_plca_status(struct phy_device *phydev,
    struct phy_plca_status *plca_st);

    +int __phy_hwtstamp_get(struct phy_device *phydev,
    + struct kernel_hwtstamp_config *config);
    +int __phy_hwtstamp_set(struct phy_device *phydev,
    + struct kernel_hwtstamp_config *config,
    + struct netlink_ext_ack *extack);
    +
    static inline int phy_package_read(struct phy_device *phydev, u32 regnum)
    {
    struct phy_package_shared *shared = phydev->shared;
    diff --git a/include/linux/phylib_stubs.h b/include/linux/phylib_stubs.h
    new file mode 100644
    index 000000000000..1279f48c8a70
    --- /dev/null
    +++ b/include/linux/phylib_stubs.h
    @@ -0,0 +1,68 @@
    +/* SPDX-License-Identifier: GPL-2.0-or-later */
    +/*
    + * Stubs for the Network PHY library
    + */
    +
    +#include <linux/rtnetlink.h>
    +
    +struct kernel_hwtstamp_config;
    +struct netlink_ext_ack;
    +struct phy_device;
    +
    +#if IS_ENABLED(CONFIG_PHYLIB)
    +
    +extern const struct phylib_stubs *phylib_stubs;
    +
    +struct phylib_stubs {
    + int (*hwtstamp_get)(struct phy_device *phydev,
    + struct kernel_hwtstamp_config *config);
    + int (*hwtstamp_set)(struct phy_device *phydev,
    + struct kernel_hwtstamp_config *config,
    + struct netlink_ext_ack *extack);
    +};
    +
    +static inline int phy_hwtstamp_get(struct phy_device *phydev,
    + struct kernel_hwtstamp_config *config)
    +{
    + /* phylib_register_stubs() and phylib_unregister_stubs()
    + * also run under rtnl_lock().
    + */
    + ASSERT_RTNL();
    +
    + if (!phylib_stubs)
    + return -EOPNOTSUPP;
    +
    + return phylib_stubs->hwtstamp_get(phydev, config);
    +}
    +
    +static inline int phy_hwtstamp_set(struct phy_device *phydev,
    + struct kernel_hwtstamp_config *config,
    + struct netlink_ext_ack *extack)
    +{
    + /* phylib_register_stubs() and phylib_unregister_stubs()
    + * also run under rtnl_lock().
    + */
    + ASSERT_RTNL();
    +
    + if (!phylib_stubs)
    + return -EOPNOTSUPP;
    +
    + return phylib_stubs->hwtstamp_set(phydev, config, extack);
    +}
    +
    +#else
    +
    +static inline int phy_hwtstamp_get(struct phy_device *phydev,
    + struct kernel_hwtstamp_config *config)
    +{
    + return -EOPNOTSUPP;
    +}
    +
    +static inline int phy_hwtstamp_set(struct phy_device *phydev,
    + struct kernel_hwtstamp_config *config,
    + struct netlink_ext_ack *extack)
    +{
    + return -EOPNOTSUPP;
    +}
    +
    +#endif
    --
    2.34.1
    \
     
     \ /
      Last update: 2023-08-01 16:31    [W:4.387 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site