Skip to content

Commit 60495b6

Browse files
vladimirolteankuba-moo
authored andcommitted
net: phy: provide phylib stubs for hardware timestamping operations
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 5a17818 ("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> Link: https://lore.kernel.org/r/20230801142824.1772134-12-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 70ef7d8 commit 60495b6

File tree

7 files changed

+141
-0
lines changed

7 files changed

+141
-0
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7752,6 +7752,7 @@ F: include/linux/mii.h
77527752
F: include/linux/of_net.h
77537753
F: include/linux/phy.h
77547754
F: include/linux/phy_fixed.h
7755+
F: include/linux/phylib_stubs.h
77557756
F: include/linux/platform_data/mdio-bcm-unimac.h
77567757
F: include/linux/platform_data/mdio-gpio.h
77577758
F: include/trace/events/mdio.h

drivers/net/phy/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ endif
1414
# dedicated loadable module, so we bundle them all together into libphy.ko
1515
ifdef CONFIG_PHYLIB
1616
libphy-y += $(mdio-bus-y)
17+
# the stubs are built-in whenever PHYLIB is built-in or module
18+
obj-y += stubs.o
1719
else
1820
obj-$(CONFIG_MDIO_DEVICE) += mdio-bus.o
1921
endif

drivers/net/phy/phy.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,40 @@ int phy_do_ioctl_running(struct net_device *dev, struct ifreq *ifr, int cmd)
455455
}
456456
EXPORT_SYMBOL(phy_do_ioctl_running);
457457

458+
/**
459+
* __phy_hwtstamp_get - Get hardware timestamping configuration from PHY
460+
*
461+
* @phydev: the PHY device structure
462+
* @config: structure holding the timestamping configuration
463+
*
464+
* Query the PHY device for its current hardware timestamping configuration.
465+
*/
466+
int __phy_hwtstamp_get(struct phy_device *phydev,
467+
struct kernel_hwtstamp_config *config)
468+
{
469+
if (!phydev)
470+
return -ENODEV;
471+
472+
return phy_mii_ioctl(phydev, config->ifr, SIOCGHWTSTAMP);
473+
}
474+
475+
/**
476+
* __phy_hwtstamp_set - Modify PHY hardware timestamping configuration
477+
*
478+
* @phydev: the PHY device structure
479+
* @config: structure holding the timestamping configuration
480+
* @extack: netlink extended ack structure, for error reporting
481+
*/
482+
int __phy_hwtstamp_set(struct phy_device *phydev,
483+
struct kernel_hwtstamp_config *config,
484+
struct netlink_ext_ack *extack)
485+
{
486+
if (!phydev)
487+
return -ENODEV;
488+
489+
return phy_mii_ioctl(phydev, config->ifr, SIOCSHWTSTAMP);
490+
}
491+
458492
/**
459493
* phy_queue_state_machine - Trigger the state machine to run soon
460494
*

drivers/net/phy/phy_device.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/of.h>
2828
#include <linux/netdevice.h>
2929
#include <linux/phy.h>
30+
#include <linux/phylib_stubs.h>
3031
#include <linux/phy_led_triggers.h>
3132
#include <linux/pse-pd/pse.h>
3233
#include <linux/property.h>
@@ -3448,12 +3449,28 @@ static const struct ethtool_phy_ops phy_ethtool_phy_ops = {
34483449
.start_cable_test_tdr = phy_start_cable_test_tdr,
34493450
};
34503451

3452+
static const struct phylib_stubs __phylib_stubs = {
3453+
.hwtstamp_get = __phy_hwtstamp_get,
3454+
.hwtstamp_set = __phy_hwtstamp_set,
3455+
};
3456+
3457+
static void phylib_register_stubs(void)
3458+
{
3459+
phylib_stubs = &__phylib_stubs;
3460+
}
3461+
3462+
static void phylib_unregister_stubs(void)
3463+
{
3464+
phylib_stubs = NULL;
3465+
}
3466+
34513467
static int __init phy_init(void)
34523468
{
34533469
int rc;
34543470

34553471
rtnl_lock();
34563472
ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
3473+
phylib_register_stubs();
34573474
rtnl_unlock();
34583475

34593476
rc = mdio_bus_init();
@@ -3478,6 +3495,7 @@ static int __init phy_init(void)
34783495
mdio_bus_exit();
34793496
err_ethtool_phy_ops:
34803497
rtnl_lock();
3498+
phylib_unregister_stubs();
34813499
ethtool_set_ethtool_phy_ops(NULL);
34823500
rtnl_unlock();
34833501

@@ -3490,6 +3508,7 @@ static void __exit phy_exit(void)
34903508
phy_driver_unregister(&genphy_driver);
34913509
mdio_bus_exit();
34923510
rtnl_lock();
3511+
phylib_unregister_stubs();
34933512
ethtool_set_ethtool_phy_ops(NULL);
34943513
rtnl_unlock();
34953514
}

drivers/net/phy/stubs.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Stubs for PHY library functionality called by the core network stack.
4+
* These are necessary because CONFIG_PHYLIB can be a module, and built-in
5+
* code cannot directly call symbols exported by modules.
6+
*/
7+
#include <linux/phylib_stubs.h>
8+
9+
const struct phylib_stubs *phylib_stubs;
10+
EXPORT_SYMBOL_GPL(phylib_stubs);

include/linux/phy.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ static inline const char *phy_modes(phy_interface_t interface)
298298
#define MII_BUS_ID_SIZE 61
299299

300300
struct device;
301+
struct kernel_hwtstamp_config;
301302
struct phylink;
302303
struct sfp_bus;
303304
struct sfp_upstream_ops;
@@ -1955,6 +1956,12 @@ int phy_ethtool_set_plca_cfg(struct phy_device *phydev,
19551956
int phy_ethtool_get_plca_status(struct phy_device *phydev,
19561957
struct phy_plca_status *plca_st);
19571958

1959+
int __phy_hwtstamp_get(struct phy_device *phydev,
1960+
struct kernel_hwtstamp_config *config);
1961+
int __phy_hwtstamp_set(struct phy_device *phydev,
1962+
struct kernel_hwtstamp_config *config,
1963+
struct netlink_ext_ack *extack);
1964+
19581965
static inline int phy_package_read(struct phy_device *phydev, u32 regnum)
19591966
{
19601967
struct phy_package_shared *shared = phydev->shared;

include/linux/phylib_stubs.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* Stubs for the Network PHY library
4+
*/
5+
6+
#include <linux/rtnetlink.h>
7+
8+
struct kernel_hwtstamp_config;
9+
struct netlink_ext_ack;
10+
struct phy_device;
11+
12+
#if IS_ENABLED(CONFIG_PHYLIB)
13+
14+
extern const struct phylib_stubs *phylib_stubs;
15+
16+
struct phylib_stubs {
17+
int (*hwtstamp_get)(struct phy_device *phydev,
18+
struct kernel_hwtstamp_config *config);
19+
int (*hwtstamp_set)(struct phy_device *phydev,
20+
struct kernel_hwtstamp_config *config,
21+
struct netlink_ext_ack *extack);
22+
};
23+
24+
static inline int phy_hwtstamp_get(struct phy_device *phydev,
25+
struct kernel_hwtstamp_config *config)
26+
{
27+
/* phylib_register_stubs() and phylib_unregister_stubs()
28+
* also run under rtnl_lock().
29+
*/
30+
ASSERT_RTNL();
31+
32+
if (!phylib_stubs)
33+
return -EOPNOTSUPP;
34+
35+
return phylib_stubs->hwtstamp_get(phydev, config);
36+
}
37+
38+
static inline int phy_hwtstamp_set(struct phy_device *phydev,
39+
struct kernel_hwtstamp_config *config,
40+
struct netlink_ext_ack *extack)
41+
{
42+
/* phylib_register_stubs() and phylib_unregister_stubs()
43+
* also run under rtnl_lock().
44+
*/
45+
ASSERT_RTNL();
46+
47+
if (!phylib_stubs)
48+
return -EOPNOTSUPP;
49+
50+
return phylib_stubs->hwtstamp_set(phydev, config, extack);
51+
}
52+
53+
#else
54+
55+
static inline int phy_hwtstamp_get(struct phy_device *phydev,
56+
struct kernel_hwtstamp_config *config)
57+
{
58+
return -EOPNOTSUPP;
59+
}
60+
61+
static inline int phy_hwtstamp_set(struct phy_device *phydev,
62+
struct kernel_hwtstamp_config *config,
63+
struct netlink_ext_ack *extack)
64+
{
65+
return -EOPNOTSUPP;
66+
}
67+
68+
#endif

0 commit comments

Comments
 (0)