Skip to content

Commit 820ee17

Browse files
ffainellidavem330
authored andcommitted
net: phy: broadcom: Add support code for reading PHY counters
Broadcom PHYs expose a number of PHY error counters: receive errors, false carrier sense, SerDes BER count, local and remote receive errors. Add support code to allow retrieving these error counters. Since the Broadcom PHY library code is used by several drivers, make it possible for them to specify the storage for the software copy of the statistics. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 5a6681e commit 820ee17

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

drivers/net/phy/bcm-phy-lib.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/mdio.h>
1818
#include <linux/module.h>
1919
#include <linux/phy.h>
20+
#include <linux/ethtool.h>
2021

2122
#define MII_BCM_CHANNEL_WIDTH 0x2000
2223
#define BCM_CL45VEN_EEE_ADV 0x3c
@@ -317,6 +318,75 @@ int bcm_phy_downshift_set(struct phy_device *phydev, u8 count)
317318
}
318319
EXPORT_SYMBOL_GPL(bcm_phy_downshift_set);
319320

321+
struct bcm_phy_hw_stat {
322+
const char *string;
323+
u8 reg;
324+
u8 shift;
325+
u8 bits;
326+
};
327+
328+
/* Counters freeze at either 0xffff or 0xff, better than nothing */
329+
static const struct bcm_phy_hw_stat bcm_phy_hw_stats[] = {
330+
{ "phy_receive_errors", MII_BRCM_CORE_BASE12, 0, 16 },
331+
{ "phy_serdes_ber_errors", MII_BRCM_CORE_BASE13, 8, 8 },
332+
{ "phy_false_carrier_sense_errors", MII_BRCM_CORE_BASE13, 0, 8 },
333+
{ "phy_local_rcvr_nok", MII_BRCM_CORE_BASE14, 8, 8 },
334+
{ "phy_remote_rcv_nok", MII_BRCM_CORE_BASE14, 0, 8 },
335+
};
336+
337+
int bcm_phy_get_sset_count(struct phy_device *phydev)
338+
{
339+
return ARRAY_SIZE(bcm_phy_hw_stats);
340+
}
341+
EXPORT_SYMBOL_GPL(bcm_phy_get_sset_count);
342+
343+
void bcm_phy_get_strings(struct phy_device *phydev, u8 *data)
344+
{
345+
unsigned int i;
346+
347+
for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
348+
memcpy(data + i * ETH_GSTRING_LEN,
349+
bcm_phy_hw_stats[i].string, ETH_GSTRING_LEN);
350+
}
351+
EXPORT_SYMBOL_GPL(bcm_phy_get_strings);
352+
353+
#ifndef UINT64_MAX
354+
#define UINT64_MAX (u64)(~((u64)0))
355+
#endif
356+
357+
/* Caller is supposed to provide appropriate storage for the library code to
358+
* access the shadow copy
359+
*/
360+
static u64 bcm_phy_get_stat(struct phy_device *phydev, u64 *shadow,
361+
unsigned int i)
362+
{
363+
struct bcm_phy_hw_stat stat = bcm_phy_hw_stats[i];
364+
int val;
365+
u64 ret;
366+
367+
val = phy_read(phydev, stat.reg);
368+
if (val < 0) {
369+
ret = UINT64_MAX;
370+
} else {
371+
val >>= stat.shift;
372+
val = val & ((1 << stat.bits) - 1);
373+
shadow[i] += val;
374+
ret = shadow[i];
375+
}
376+
377+
return ret;
378+
}
379+
380+
void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
381+
struct ethtool_stats *stats, u64 *data)
382+
{
383+
unsigned int i;
384+
385+
for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
386+
data[i] = bcm_phy_get_stat(phydev, shadow, i);
387+
}
388+
EXPORT_SYMBOL_GPL(bcm_phy_get_stats);
389+
320390
MODULE_DESCRIPTION("Broadcom PHY Library");
321391
MODULE_LICENSE("GPL v2");
322392
MODULE_AUTHOR("Broadcom Corporation");

drivers/net/phy/bcm-phy-lib.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,9 @@ int bcm_phy_downshift_get(struct phy_device *phydev, u8 *count);
4242

4343
int bcm_phy_downshift_set(struct phy_device *phydev, u8 count);
4444

45+
int bcm_phy_get_sset_count(struct phy_device *phydev);
46+
void bcm_phy_get_strings(struct phy_device *phydev, u8 *data);
47+
void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
48+
struct ethtool_stats *stats, u64 *data);
49+
4550
#endif /* _LINUX_BCM_PHY_LIB_H */

include/linux/brcmphy.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@
244244
#define LPI_FEATURE_EN_DIG1000X 0x4000
245245

246246
/* Core register definitions*/
247+
#define MII_BRCM_CORE_BASE12 0x12
248+
#define MII_BRCM_CORE_BASE13 0x13
249+
#define MII_BRCM_CORE_BASE14 0x14
247250
#define MII_BRCM_CORE_BASE1E 0x1E
248251
#define MII_BRCM_CORE_EXPB0 0xB0
249252
#define MII_BRCM_CORE_EXPB1 0xB1

0 commit comments

Comments
 (0)