diff mbox series

[RFC,net-next,1/2] net: ethtool: plumb PHY stats to PHY drivers

Message ID 20240829174342.3255168-2-kuba@kernel.org (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series net: ethtool: add phy(dev) specific stats over netlink | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 16 this patch: 16
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers success CCed 9 of 9 maintainers
netdev/build_clang success Errors and warnings before: 29 this patch: 29
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 401 this patch: 401
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 89 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc fail Errors and warnings before: 30 this patch: 31
netdev/source_inline success Was 0 now: 0

Commit Message

Jakub Kicinski Aug. 29, 2024, 5:43 p.m. UTC
Feed the existing IEEE PHY counter struct (which currently
only has one entry) and link stats into the PHY driver.
The MAC driver can override the value if it somehow has a better
idea of PHY stats. Since the stats are "undefined" at input
the drivers can't += the values, so we should be safe from
double-counting.

Vladimir, I don't understand MM but doesn't MM share the PHY?
Ocelot seems to aggregate which I did not expect.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: Vladimir Oltean <olteanv@gmail.com>
CC: andrew@lunn.ch
CC: hkallweit1@gmail.com
CC: linux@armlinux.org.uk
CC: woojung.huh@microchip.com
CC: o.rempel@pengutronix.de
---
 include/linux/phy.h     | 10 ++++++++++
 net/ethtool/linkstate.c | 25 ++++++++++++++++++++++---
 net/ethtool/stats.c     | 19 +++++++++++++++++++
 3 files changed, 51 insertions(+), 3 deletions(-)

Comments

Oleksij Rempel Aug. 29, 2024, 6:10 p.m. UTC | #1
On Thu, Aug 29, 2024 at 10:43:41AM -0700, Jakub Kicinski wrote:
> Feed the existing IEEE PHY counter struct (which currently
> only has one entry) and link stats into the PHY driver.
> The MAC driver can override the value if it somehow has a better
> idea of PHY stats. Since the stats are "undefined" at input
> the drivers can't += the values, so we should be safe from
> double-counting.
> 
> Vladimir, I don't understand MM but doesn't MM share the PHY?
> Ocelot seems to aggregate which I did not expect.
> 
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>

Huh.. it is completely different compared to what I was thinking.
If I see it correctly, it will help to replace missing HW stats for some
MACs like ASIX. But it will fail to help diagnose MAC-PHY connections
issues like, wrong RGMII configurations or other kind of damages on the
PCB. Right?

Regards,
Oleksij
Jakub Kicinski Aug. 29, 2024, 7:13 p.m. UTC | #2
On Thu, 29 Aug 2024 20:10:00 +0200 Oleksij Rempel wrote:
> On Thu, Aug 29, 2024 at 10:43:41AM -0700, Jakub Kicinski wrote:
> > Feed the existing IEEE PHY counter struct (which currently
> > only has one entry) and link stats into the PHY driver.
> > The MAC driver can override the value if it somehow has a better
> > idea of PHY stats. Since the stats are "undefined" at input
> > the drivers can't += the values, so we should be safe from
> > double-counting.
> > 
> > Vladimir, I don't understand MM but doesn't MM share the PHY?
> > Ocelot seems to aggregate which I did not expect.
> > 
> > Signed-off-by: Jakub Kicinski <kuba@kernel.org>  
> 
> Huh.. it is completely different compared to what I was thinking.
> If I see it correctly, it will help to replace missing HW stats for some
> MACs like ASIX. But it will fail to help diagnose MAC-PHY connections
> issues like, wrong RGMII configurations or other kind of damages on the
> PCB. Right?

This is just a pre-req for the next patch, to let phy drivers report
the (very few) stats we have already defined for integrated NIC drivers.
What statistics we choose to add later is up to us, this is just
groundwork.

BTW the series is primarily to allow you to report the packet / error
and OA stats in a structured way, it's not related directly by the
discussion on T1L troubleshooting.
Maxime Chevallier Aug. 30, 2024, 8:16 a.m. UTC | #3
Hello Jakub,

On Thu, 29 Aug 2024 10:43:41 -0700
Jakub Kicinski <kuba@kernel.org> wrote:

> Feed the existing IEEE PHY counter struct (which currently
> only has one entry) and link stats into the PHY driver.
> The MAC driver can override the value if it somehow has a better
> idea of PHY stats. Since the stats are "undefined" at input
> the drivers can't += the values, so we should be safe from
> double-counting.
> 
> Vladimir, I don't understand MM but doesn't MM share the PHY?
> Ocelot seems to aggregate which I did not expect.
> 
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>

[...]

> +static void
> +ethtool_get_phydev_stats(struct net_device *dev,
> +			 struct linkstate_reply_data *data)
> +{
> +	struct phy_device *phydev = dev->phydev;

This would be a very nice spot to use the new
ethnl_req_get_phydev(), if there are multiple PHYs on that device.
Being able to access the stats individually can help
troubleshoot HW issues.

[...]

> +static void
> +ethtool_get_phydev_stats(struct net_device *dev, struct stats_reply_data *data)
> +{
> +	struct phy_device *phydev = dev->phydev;

Here as well, but that's trickier, as the MAC can override the PHY
stats, but it doesn't know which PHY were getting the stats from.

Maybe we could make so that when we pass a phy_index in the netlink
command, we don't allow the mac to override the phy stats ? Or better,
don't allow the mac to override these stats and report the MAC-reported
PHY stats alongside the PHY-reported stats ?

> +
> +	if (!phydev || !phydev->drv || !phydev->drv->get_phy_stats)
> +		return;
> +
> +	mutex_lock(&phydev->lock);
> +	phydev->drv->get_phy_stats(phydev, &data->phy_stats);
> +	mutex_unlock(&phydev->lock);
> +}
> +
>  static int stats_prepare_data(const struct ethnl_req_info *req_base,
>  			      struct ethnl_reply_data *reply_base,
>  			      const struct genl_info *info)
> @@ -145,6 +160,10 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
>  	data->ctrl_stats.src = src;
>  	data->rmon_stats.src = src;
>  
> +	if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) &&
> +	    src == ETHTOOL_MAC_STATS_SRC_AGGREGATE)
> +		ethtool_get_phydev_stats(dev, data);

I might be missing something, but I think
ETHTOOL_MAC_STATS_SRC_AGGREGATE is a MM-specific flag and I don't really
see how this applies to getting the PHY stats. I don't know much about
MM though so I could be missing the point.

I'm all in for getting the PHY stats from netlink though :)

Thanks,

Maxime
Jakub Kicinski Aug. 30, 2024, 6:30 p.m. UTC | #4
On Fri, 30 Aug 2024 10:16:30 +0200 Maxime Chevallier wrote:
> > +static void
> > +ethtool_get_phydev_stats(struct net_device *dev,
> > +			 struct linkstate_reply_data *data)
> > +{
> > +	struct phy_device *phydev = dev->phydev;  
> 
> This would be a very nice spot to use the new
> ethnl_req_get_phydev(), if there are multiple PHYs on that device.
> Being able to access the stats individually can help
> troubleshoot HW issues.
> 
> > +static void
> > +ethtool_get_phydev_stats(struct net_device *dev, struct stats_reply_data *data)
> > +{
> > +	struct phy_device *phydev = dev->phydev;  
> 
> Here as well, but that's trickier, as the MAC can override the PHY
> stats, but it doesn't know which PHY were getting the stats from.
> 
> Maybe we could make so that when we pass a phy_index in the netlink
> command, we don't allow the mac to override the phy stats ? Or better,
> don't allow the mac to override these stats and report the MAC-reported
> PHY stats alongside the PHY-reported stats ?

Maybe we can flip the order of querying regardless of the PHY that's
targeted? Always query the MAC first and then the PHY, so that the
PHY can override. Presumably the PHY can always provide more detailed
stats than the MAC (IOW if it does provide stats they will be more
accurate).

> > +	if (!phydev || !phydev->drv || !phydev->drv->get_phy_stats)
> > +		return;
> > +
> > +	mutex_lock(&phydev->lock);
> > +	phydev->drv->get_phy_stats(phydev, &data->phy_stats);
> > +	mutex_unlock(&phydev->lock);
> > +}
> > +
> >  static int stats_prepare_data(const struct ethnl_req_info *req_base,
> >  			      struct ethnl_reply_data *reply_base,
> >  			      const struct genl_info *info)
> > @@ -145,6 +160,10 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
> >  	data->ctrl_stats.src = src;
> >  	data->rmon_stats.src = src;
> >  
> > +	if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) &&
> > +	    src == ETHTOOL_MAC_STATS_SRC_AGGREGATE)
> > +		ethtool_get_phydev_stats(dev, data);  
> 
> I might be missing something, but I think
> ETHTOOL_MAC_STATS_SRC_AGGREGATE is a MM-specific flag and I don't really
> see how this applies to getting the PHY stats. I don't know much about
> MM though so I could be missing the point.

We need expert insights from Vladimir on that part :)

> I'm all in for getting the PHY stats from netlink though :)

Great! FWIW I'm not sure what the status of these patches is.
I don't know much about PHYs.
I wrote them to help Oleksij out with the "netlink parts".
I'm not sure how much I convinced Andrew about the applicability.
And I don't know if this is enough for Oleksij to take it forward.
So in the unlikely even that you have spare cycles and a PHY you can
test with, do not hesitate to take these, rework, reset the author 
and repost... :)
Vladimir Oltean Sept. 2, 2024, 3:08 p.m. UTC | #5
On Thu, Aug 29, 2024 at 10:43:41AM -0700, Jakub Kicinski wrote:
> Vladimir, I don't understand MM

MAC Merge / Frame Preemption in a nutshell:

- Frame is express if, after the preamble, it has a "normal" SFD of 0xD5

- Frame is preemptible if, after the preamble, it has an SFD of 0x07,
  0x19, 0xE6, 0x4C, 0x7F, 0xB3, 0x61, 0x52, 0x9E or 0x2A

express MAC handles express frames
preemptible MAC handles preemptible frames

ETHTOOL_MAC_STATS_SRC_EMAC counts express frames
ETHTOOL_MAC_STATS_SRC_PMAC counts preemptible frames
ETHTOOL_MAC_STATS_SRC_AGGREGATE counts both - also works when you don't know

Now you know as much as I do.

> but doesn't MM share the PHY?

It does, yes. There is a single set of MII lines, and distinction
between the express and preemptible MAC is done as described above.

I wouldn't expect the PHY to be aware of MAC Merge / Frame Preemption,
and thus, this component would normally not pay attention to the SFD of
the frames it's counting. The entire feature actually depends on the PHY
being unaware of the SFD, because they don't make PHYs "for" frame preemption.

Although, imaginably, just like we have PHYs which emit PAUSE frames,
and that technically means they have a MAC embedded inside, it would not
be impossible to twist standards such that the PHY handles FPE/MM.
This is only in the realm of theory, AFAIU, and I'm not suggesting we
should model the UAPI based on pure theory.

> Ocelot seems to aggregate which I did not expect.

Ocelot aggregates stats when the request is to aggregate them
(explicit ETHTOOL_MAC_STATS_SRC_AGGREGATE, and also default, for
comparability/ compatibility with unaware drivers). Otherwise it
reports them individually.

Also, the stats it reports into phy_stats->SymbolErrorDuringCarrier are
MAC stats. They count the number of frames received by the MAC with
RX_ER being asserted on the MII interface. So these could be counted by
either the MAC, or the PHY. The MAC is MM-aware, the PHY is probably not.

Though if I follow the thread, I'm not sure if this is exactly useful to
Oleksij, who would like to report an entirely different set of counters.

I never got the impression that the ETHTOOL_STATS_ETH_PHY structured
netlink counters were for NICs with embedded non-phylib PHYs. If they
are - sorry. I thought it was about those MAC counters which are
collected at the interface with the PHY.
Maxime Chevallier Sept. 4, 2024, 7:20 a.m. UTC | #6
Hi Jakub,

On Fri, 30 Aug 2024 11:30:47 -0700
Jakub Kicinski <kuba@kernel.org> wrote:

> On Fri, 30 Aug 2024 10:16:30 +0200 Maxime Chevallier wrote:
> > > +static void
> > > +ethtool_get_phydev_stats(struct net_device *dev,
> > > +			 struct linkstate_reply_data *data)
> > > +{
> > > +	struct phy_device *phydev = dev->phydev;    
> > 
> > This would be a very nice spot to use the new
> > ethnl_req_get_phydev(), if there are multiple PHYs on that device.
> > Being able to access the stats individually can help
> > troubleshoot HW issues.
> >   
> > > +static void
> > > +ethtool_get_phydev_stats(struct net_device *dev, struct stats_reply_data *data)
> > > +{
> > > +	struct phy_device *phydev = dev->phydev;    
> > 
> > Here as well, but that's trickier, as the MAC can override the PHY
> > stats, but it doesn't know which PHY were getting the stats from.
> > 
> > Maybe we could make so that when we pass a phy_index in the netlink
> > command, we don't allow the mac to override the phy stats ? Or better,
> > don't allow the mac to override these stats and report the MAC-reported
> > PHY stats alongside the PHY-reported stats ?  
> 
> Maybe we can flip the order of querying regardless of the PHY that's
> targeted? Always query the MAC first and then the PHY, so that the
> PHY can override. Presumably the PHY can always provide more detailed
> stats than the MAC (IOW if it does provide stats they will be more
> accurate).

I think that could work indeed, good point.

[...]

> > I'm all in for getting the PHY stats from netlink though :)  
> 
> Great! FWIW I'm not sure what the status of these patches is.
> I don't know much about PHYs.
> I wrote them to help Oleksij out with the "netlink parts".
> I'm not sure how much I convinced Andrew about the applicability.
> And I don't know if this is enough for Oleksij to take it forward.
> So in the unlikely even that you have spare cycles and a PHY you can
> test with, do not hesitate to take these, rework, reset the author 
> and repost... :)

I do have some hardware I can test this on, and I'm starting to get
familiar with netlink :) I can give it a try, however I can't guarantee
as of right now that I'll be able to send anything before net-next
closes. I'll ping here if I start moving forward with this :)

Thanks,

Maxime
Oleksij Rempel Sept. 4, 2024, 8:05 a.m. UTC | #7
Hi all,

On Wed, Sep 04, 2024 at 09:20:24AM +0200, Maxime Chevallier wrote:
> Hi Jakub,
> 
> On Fri, 30 Aug 2024 11:30:47 -0700
> Jakub Kicinski <kuba@kernel.org> wrote:
> 
> > On Fri, 30 Aug 2024 10:16:30 +0200 Maxime Chevallier wrote:
> > > > +static void
> > > > +ethtool_get_phydev_stats(struct net_device *dev,
> > > > +			 struct linkstate_reply_data *data)
> > > > +{
> > > > +	struct phy_device *phydev = dev->phydev;    
> > > 
> > > This would be a very nice spot to use the new
> > > ethnl_req_get_phydev(), if there are multiple PHYs on that device.
> > > Being able to access the stats individually can help
> > > troubleshoot HW issues.
> > >   
> > > > +static void
> > > > +ethtool_get_phydev_stats(struct net_device *dev, struct stats_reply_data *data)
> > > > +{
> > > > +	struct phy_device *phydev = dev->phydev;    
> > > 
> > > Here as well, but that's trickier, as the MAC can override the PHY
> > > stats, but it doesn't know which PHY were getting the stats from.
> > > 
> > > Maybe we could make so that when we pass a phy_index in the netlink
> > > command, we don't allow the mac to override the phy stats ? Or better,
> > > don't allow the mac to override these stats and report the MAC-reported
> > > PHY stats alongside the PHY-reported stats ?  
> > 
> > Maybe we can flip the order of querying regardless of the PHY that's
> > targeted? Always query the MAC first and then the PHY, so that the
> > PHY can override. Presumably the PHY can always provide more detailed
> > stats than the MAC (IOW if it does provide stats they will be more
> > accurate).
> 
> I think that could work indeed, good point.
> 
> [...]
> 
> > > I'm all in for getting the PHY stats from netlink though :)  
> > 
> > Great! FWIW I'm not sure what the status of these patches is.
> > I don't know much about PHYs.
> > I wrote them to help Oleksij out with the "netlink parts".
> > I'm not sure how much I convinced Andrew about the applicability.
> > And I don't know if this is enough for Oleksij to take it forward.
> > So in the unlikely even that you have spare cycles and a PHY you can
> > test with, do not hesitate to take these, rework, reset the author 
> > and repost... :)
> 
> I do have some hardware I can test this on, and I'm starting to get
> familiar with netlink :) I can give it a try, however I can't guarantee
> as of right now that I'll be able to send anything before net-next
> closes. I'll ping here if I start moving forward with this :)

I reserved some time for this work. I hope it will be this year.

In case some one else will start working on it, please let me know :)

Regard,
Oleksij
Maxime Chevallier Sept. 4, 2024, 8:09 a.m. UTC | #8
On Wed, 4 Sep 2024 10:05:10 +0200
Oleksij Rempel <o.rempel@pengutronix.de> wrote:

> Hi all,
> 
> On Wed, Sep 04, 2024 at 09:20:24AM +0200, Maxime Chevallier wrote:
> > Hi Jakub,
> > 
> > On Fri, 30 Aug 2024 11:30:47 -0700
> > Jakub Kicinski <kuba@kernel.org> wrote:
> >   
> > > On Fri, 30 Aug 2024 10:16:30 +0200 Maxime Chevallier wrote:  
> > > > > +static void
> > > > > +ethtool_get_phydev_stats(struct net_device *dev,
> > > > > +			 struct linkstate_reply_data *data)
> > > > > +{
> > > > > +	struct phy_device *phydev = dev->phydev;      
> > > > 
> > > > This would be a very nice spot to use the new
> > > > ethnl_req_get_phydev(), if there are multiple PHYs on that device.
> > > > Being able to access the stats individually can help
> > > > troubleshoot HW issues.
> > > >     
> > > > > +static void
> > > > > +ethtool_get_phydev_stats(struct net_device *dev, struct stats_reply_data *data)
> > > > > +{
> > > > > +	struct phy_device *phydev = dev->phydev;      
> > > > 
> > > > Here as well, but that's trickier, as the MAC can override the PHY
> > > > stats, but it doesn't know which PHY were getting the stats from.
> > > > 
> > > > Maybe we could make so that when we pass a phy_index in the netlink
> > > > command, we don't allow the mac to override the phy stats ? Or better,
> > > > don't allow the mac to override these stats and report the MAC-reported
> > > > PHY stats alongside the PHY-reported stats ?    
> > > 
> > > Maybe we can flip the order of querying regardless of the PHY that's
> > > targeted? Always query the MAC first and then the PHY, so that the
> > > PHY can override. Presumably the PHY can always provide more detailed
> > > stats than the MAC (IOW if it does provide stats they will be more
> > > accurate).  
> > 
> > I think that could work indeed, good point.
> > 
> > [...]
> >   
> > > > I'm all in for getting the PHY stats from netlink though :)    
> > > 
> > > Great! FWIW I'm not sure what the status of these patches is.
> > > I don't know much about PHYs.
> > > I wrote them to help Oleksij out with the "netlink parts".
> > > I'm not sure how much I convinced Andrew about the applicability.
> > > And I don't know if this is enough for Oleksij to take it forward.
> > > So in the unlikely even that you have spare cycles and a PHY you can
> > > test with, do not hesitate to take these, rework, reset the author 
> > > and repost... :)  
> > 
> > I do have some hardware I can test this on, and I'm starting to get
> > familiar with netlink :) I can give it a try, however I can't guarantee
> > as of right now that I'll be able to send anything before net-next
> > closes. I'll ping here if I start moving forward with this :)  
> 
> I reserved some time for this work. I hope it will be this year.
> 
> In case some one else will start working on it, please let me know :)

Ah perfect then :) Let me know if you ever need some extra testing, I
can run this on the hardware I have on hand if that can help.

Best regards,

Maxime
diff mbox series

Patch

diff --git a/include/linux/phy.h b/include/linux/phy.h
index 4a9a11749c55..53942fd7760f 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1090,6 +1090,16 @@  struct phy_driver {
 	int (*cable_test_get_status)(struct phy_device *dev, bool *finished);
 
 	/* Get statistics from the PHY using ethtool */
+	/**
+	 * @get_phy_stats: Get well known statistics.
+	 * @get_link_stats: Get well known link statistics.
+	 * The input structure is not zero-initialized and the implementation
+	 * must only set statistics which are actually collected by the device.
+	 */
+	void (*get_phy_stats)(struct phy_device *dev,
+			      struct ethtool_eth_phy_stats *eth_stats);
+	void (*get_link_stats)(struct phy_device *dev,
+			       struct ethtool_link_ext_stats *link_stats);
 	/** @get_sset_count: Number of statistic counters */
 	int (*get_sset_count)(struct phy_device *dev);
 	/** @get_strings: Names of the statistic counters */
diff --git a/net/ethtool/linkstate.c b/net/ethtool/linkstate.c
index 34d76e87847d..8d3a38cc3d48 100644
--- a/net/ethtool/linkstate.c
+++ b/net/ethtool/linkstate.c
@@ -94,6 +94,27 @@  static int linkstate_get_link_ext_state(struct net_device *dev,
 	return 0;
 }
 
+static void
+ethtool_get_phydev_stats(struct net_device *dev,
+			 struct linkstate_reply_data *data)
+{
+	struct phy_device *phydev = dev->phydev;
+
+	if (!phydev)
+		return;
+
+	if (dev->phydev)
+		data->link_stats.link_down_events =
+			READ_ONCE(dev->phydev->link_down_events);
+
+	if (!phydev->drv || !phydev->drv->get_link_stats)
+		return;
+
+	mutex_lock(&phydev->lock);
+	phydev->drv->get_link_stats(phydev, &data->link_stats);
+	mutex_unlock(&phydev->lock);
+}
+
 static int linkstate_prepare_data(const struct ethnl_req_info *req_base,
 				  struct ethnl_reply_data *reply_base,
 				  const struct genl_info *info)
@@ -127,9 +148,7 @@  static int linkstate_prepare_data(const struct ethnl_req_info *req_base,
 			   sizeof(data->link_stats) / 8);
 
 	if (req_base->flags & ETHTOOL_FLAG_STATS) {
-		if (dev->phydev)
-			data->link_stats.link_down_events =
-				READ_ONCE(dev->phydev->link_down_events);
+		ethtool_get_phydev_stats(dev, data);
 
 		if (dev->ethtool_ops->get_link_ext_stats)
 			dev->ethtool_ops->get_link_ext_stats(dev,
diff --git a/net/ethtool/stats.c b/net/ethtool/stats.c
index 912f0c4fff2f..cf802b1cda6f 100644
--- a/net/ethtool/stats.c
+++ b/net/ethtool/stats.c
@@ -1,5 +1,7 @@ 
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/phy.h>
+
 #include "netlink.h"
 #include "common.h"
 #include "bitset.h"
@@ -112,6 +114,19 @@  static int stats_parse_request(struct ethnl_req_info *req_base,
 	return 0;
 }
 
+static void
+ethtool_get_phydev_stats(struct net_device *dev, struct stats_reply_data *data)
+{
+	struct phy_device *phydev = dev->phydev;
+
+	if (!phydev || !phydev->drv || !phydev->drv->get_phy_stats)
+		return;
+
+	mutex_lock(&phydev->lock);
+	phydev->drv->get_phy_stats(phydev, &data->phy_stats);
+	mutex_unlock(&phydev->lock);
+}
+
 static int stats_prepare_data(const struct ethnl_req_info *req_base,
 			      struct ethnl_reply_data *reply_base,
 			      const struct genl_info *info)
@@ -145,6 +160,10 @@  static int stats_prepare_data(const struct ethnl_req_info *req_base,
 	data->ctrl_stats.src = src;
 	data->rmon_stats.src = src;
 
+	if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) &&
+	    src == ETHTOOL_MAC_STATS_SRC_AGGREGATE)
+		ethtool_get_phydev_stats(dev, data);
+
 	if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) &&
 	    dev->ethtool_ops->get_eth_phy_stats)
 		dev->ethtool_ops->get_eth_phy_stats(dev, &data->phy_stats);