Hi all,
This patch series untangles the ethtool netlink dependency with PHYLIB
which exists because the cable test feature calls directly into PHY
library functions. The approach taken here is to introduce
ethtool_phy_ops function pointers which can be dynamically registered
when PHYLIB loads.
Florian Fainelli (3):
net: ethtool: Introduce ethtool_phy_ops
net: phy: Register ethtool PHY operations
net: ethtool: Remove PHYLIB direct dependency
drivers/net/phy/phy_device.c | 7 +++++++
include/linux/ethtool.h | 25 +++++++++++++++++++++++++
net/Kconfig | 1 -
net/ethtool/cabletest.c | 18 ++++++++++++++++--
net/ethtool/common.c | 11 +++++++++++
net/ethtool/common.h | 2 ++
6 files changed, 61 insertions(+), 3 deletions(-)
--
2.25.1
In order to decouple ethtool from its PHY library dependency, define an
ethtool_phy_ops singleton which can be overriden by the PHY library when
it loads with an appropriate set of function pointers.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
include/linux/ethtool.h | 25 +++++++++++++++++++++++++
net/ethtool/common.c | 11 +++++++++++
net/ethtool/common.h | 2 ++
3 files changed, 38 insertions(+)
Utilize ethtool_set_ethtool_phy_ops to register a suitable set of PHY
ethtool operations in a dynamic fashion such that ethtool will no longer
directy reference PHY library symbols.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/phy_device.c | 7 +++++++
1 file changed, 7 insertions(+)
Now that we have introduced ethtool_phy_ops and the PHY library
dynamically registers its operations with that function pointer, we can
remove the direct PHYLIB dependency in favor of using dynamic
operations.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/Kconfig | 1 -
net/ethtool/cabletest.c | 18 ++++++++++++++++--
2 files changed, 16 insertions(+), 3 deletions(-)
From: Andrew Lunn <andrew@lunn.ch> Date: 2020-07-06 13:46:51
On Sun, Jul 05, 2020 at 09:27:55PM -0700, Florian Fainelli wrote:
Hi all,
This patch series untangles the ethtool netlink dependency with PHYLIB
which exists because the cable test feature calls directly into PHY
library functions. The approach taken here is to introduce
ethtool_phy_ops function pointers which can be dynamically registered
when PHYLIB loads.
Hi Florian
This looks good. I would suggest leaving it a day or two for 0-day to
randconfig it for a while.
Andrew
From: Jakub Kicinski <kuba@kernel.org> Date: 2020-07-06 18:40:07
On Sun, 5 Jul 2020 21:27:58 -0700 Florian Fainelli wrote:
+ ops = ethtool_phy_ops;
+ if (!ops || !ops->start_cable_test) {
nit: don't think member-by-member checking is necessary. We don't
expect there to be any alternative versions of the ops, right?
+ ret = -EOPNOTSUPP;
+ goto out_rtnl;
+ }
+
ret = ethnl_ops_begin(dev);
if (ret < 0)
goto out_rtnl;
- ret = phy_start_cable_test(dev->phydev, info->extack);
+ ret = ops->start_cable_test(dev->phydev, info->extack);
nit: my personal preference would be to hide checking the ops and
calling the member in a static inline helper.
Note that we should be able to remove this from phy.h now:
#if IS_ENABLED(CONFIG_PHYLIB)
int phy_start_cable_test(struct phy_device *phydev,
struct netlink_ext_ack *extack);
int phy_start_cable_test_tdr(struct phy_device *phydev,
struct netlink_ext_ack *extack,
const struct phy_tdr_config *config);
#else
static inline
int phy_start_cable_test(struct phy_device *phydev,
struct netlink_ext_ack *extack)
{
NL_SET_ERR_MSG(extack, "Kernel not compiled with PHYLIB support");
return -EOPNOTSUPP;
}
static inline
int phy_start_cable_test_tdr(struct phy_device *phydev,
struct netlink_ext_ack *extack,
const struct phy_tdr_config *config)
{
NL_SET_ERR_MSG(extack, "Kernel not compiled with PHYLIB support");
return -EOPNOTSUPP;
}
#endif
We could even risk a direct call:
#if IS_REACHABLE(CONFIG_PHYLIB)
static inline int do_x()
{
return __do_x();
}
#else
static inline int do_x()
{
if (!ops)
return -EOPNOTSUPP;
return ops->do_x();
}
#endif
But that's perhaps doing too much...
On Sun, 5 Jul 2020 21:27:58 -0700 Florian Fainelli wrote:
quoted
+ ops = ethtool_phy_ops;
+ if (!ops || !ops->start_cable_test) {
nit: don't think member-by-member checking is necessary. We don't
expect there to be any alternative versions of the ops, right?
There could be, a network device driver not using PHYLIB could register
its own operations and only implement a subset of these operations.
quoted
+ ret = -EOPNOTSUPP;
+ goto out_rtnl;
+ }
+
ret = ethnl_ops_begin(dev);
if (ret < 0)
goto out_rtnl;
- ret = phy_start_cable_test(dev->phydev, info->extack);
+ ret = ops->start_cable_test(dev->phydev, info->extack);
nit: my personal preference would be to hide checking the ops and
calling the member in a static inline helper.
Note that we should be able to remove this from phy.h now:
I would prefer to keep thsose around in case a network device driver
cannot punt entirely onto PHYLIB and instead needs to wrap those calls
around.
#if IS_ENABLED(CONFIG_PHYLIB)
int phy_start_cable_test(struct phy_device *phydev,
struct netlink_ext_ack *extack);
int phy_start_cable_test_tdr(struct phy_device *phydev,
struct netlink_ext_ack *extack,
const struct phy_tdr_config *config);
#else
static inline
int phy_start_cable_test(struct phy_device *phydev,
struct netlink_ext_ack *extack)
{
NL_SET_ERR_MSG(extack, "Kernel not compiled with PHYLIB support");
return -EOPNOTSUPP;
}
static inline
int phy_start_cable_test_tdr(struct phy_device *phydev,
struct netlink_ext_ack *extack,
const struct phy_tdr_config *config)
{
NL_SET_ERR_MSG(extack, "Kernel not compiled with PHYLIB support");
return -EOPNOTSUPP;
}
#endif
We could even risk a direct call:
#if IS_REACHABLE(CONFIG_PHYLIB)
static inline int do_x()
{
return __do_x();
}
#else
static inline int do_x()
{
if (!ops)
return -EOPNOTSUPP;
return ops->do_x();
}
#endif
But that's perhaps doing too much...
Fine either way with me, let us see what Michal and Andrew think about that.
--
Florian
From: Jakub Kicinski <kuba@kernel.org> Date: 2020-07-06 18:54:31
On Mon, 6 Jul 2020 11:45:38 -0700 Florian Fainelli wrote:
On 7/6/2020 11:40 AM, Jakub Kicinski wrote:
quoted
On Sun, 5 Jul 2020 21:27:58 -0700 Florian Fainelli wrote:
quoted
+ ops = ethtool_phy_ops;
+ if (!ops || !ops->start_cable_test) {
nit: don't think member-by-member checking is necessary. We don't
expect there to be any alternative versions of the ops, right?
There could be, a network device driver not using PHYLIB could register
its own operations and only implement a subset of these operations.
I'd strongly prefer drivers did not insert themselves into
subsys-to-subsys glue :S
quoted
We could even risk a direct call:
#if IS_REACHABLE(CONFIG_PHYLIB)
static inline int do_x()
{
return __do_x();
}
#else
static inline int do_x()
{
if (!ops)
return -EOPNOTSUPP;
return ops->do_x();
}
#endif
But that's perhaps doing too much...
Fine either way with me, let us see what Michal and Andrew think about that.
From: Andrew Lunn <andrew@lunn.ch> Date: 2020-07-06 19:56:12
On Mon, Jul 06, 2020 at 11:40:00AM -0700, Jakub Kicinski wrote:
On Sun, 5 Jul 2020 21:27:58 -0700 Florian Fainelli wrote:
quoted
+ ops = ethtool_phy_ops;
+ if (!ops || !ops->start_cable_test) {
nit: don't think member-by-member checking is necessary. We don't
expect there to be any alternative versions of the ops, right?
I would not like to see anything else registering an ops. So i think
taking an Opps would be a good indication somebody is doing something
wrong and needs fixing.
We could even risk a direct call:
#if IS_REACHABLE(CONFIG_PHYLIB)
static inline int do_x()
{
return __do_x();
}
#else
static inline int do_x()
{
if (!ops)
return -EOPNOTSUPP;
return ops->do_x();
}
#endif
But that's perhaps doing too much...
I would say it is too far. Two ways of doing the same thing requires
twice as much testing. And these are not hot paths where we want to
eliminate as many instructions and trampolines as possible.
Andrew
From: Michal Kubecek <hidden> Date: 2020-07-07 12:52:57
On Mon, Jul 06, 2020 at 09:56:03PM +0200, Andrew Lunn wrote:
On Mon, Jul 06, 2020 at 11:40:00AM -0700, Jakub Kicinski wrote:
quoted
On Sun, 5 Jul 2020 21:27:58 -0700 Florian Fainelli wrote:
quoted
+ ops = ethtool_phy_ops;
+ if (!ops || !ops->start_cable_test) {
nit: don't think member-by-member checking is necessary. We don't
expect there to be any alternative versions of the ops, right?
I would not like to see anything else registering an ops. So i think
taking an Opps would be a good indication somebody is doing something
wrong and needs fixing.
quoted
We could even risk a direct call:
#if IS_REACHABLE(CONFIG_PHYLIB)
static inline int do_x()
{
return __do_x();
}
#else
static inline int do_x()
{
if (!ops)
return -EOPNOTSUPP;
return ops->do_x();
}
#endif
But that's perhaps doing too much...
I would say it is too far. Two ways of doing the same thing requires
twice as much testing. And these are not hot paths where we want to
eliminate as many instructions and trampolines as possible.
This patch series untangles the ethtool netlink dependency with PHYLIB
which exists because the cable test feature calls directly into PHY
library functions. The approach taken here is to introduce
ethtool_phy_ops function pointers which can be dynamically registered
when PHYLIB loads.
Series applied, thanks for doing this work Florian.