Skip to content

Commit 74dcb4c

Browse files
hkallweitdavem330
authored andcommitted
net: phy: aquantia: add SGMII statistics
The AQR107 family has SGMII statistics counters. Let's expose them to ethtool. To interpret the counters correctly one has to be aware that rx on SGMII side is tx on ethernet side. The counters are populated by the chip in 100Mbps/1Gbps mode only. v2: - add constant AQR107_SGMII_STAT_SZ - add struct aqr107_priv to be prepared for more private data fields - let aqr107_get_stat() return U64_MAX in case of an error Signed-off-by: Heiner Kallweit <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5869b8f commit 74dcb4c

File tree

1 file changed

+112
-2
lines changed

1 file changed

+112
-2
lines changed

drivers/net/phy/aquantia_main.c

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@
6969
#define MDIO_AN_RX_VEND_STAT3 0xe832
7070
#define MDIO_AN_RX_VEND_STAT3_AFR BIT(0)
7171

72+
/* MDIO_MMD_C22EXT */
73+
#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292
74+
#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294
75+
#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297
76+
#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313
77+
#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315
78+
#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317
79+
#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318
80+
#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319
81+
#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a
82+
#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b
83+
7284
/* Vendor specific 1, MDIO_MMD_VEND1 */
7385
#define VEND1_GLOBAL_FW_ID 0x0020
7486
#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8)
@@ -108,6 +120,88 @@
108120
#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1)
109121
#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0)
110122

123+
struct aqr107_hw_stat {
124+
const char *name;
125+
int reg;
126+
int size;
127+
};
128+
129+
#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s }
130+
static const struct aqr107_hw_stat aqr107_hw_stats[] = {
131+
SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26),
132+
SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26),
133+
SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8),
134+
SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26),
135+
SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26),
136+
SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8),
137+
SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8),
138+
SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8),
139+
SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16),
140+
SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22),
141+
};
142+
#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats)
143+
144+
struct aqr107_priv {
145+
u64 sgmii_stats[AQR107_SGMII_STAT_SZ];
146+
};
147+
148+
static int aqr107_get_sset_count(struct phy_device *phydev)
149+
{
150+
return AQR107_SGMII_STAT_SZ;
151+
}
152+
153+
static void aqr107_get_strings(struct phy_device *phydev, u8 *data)
154+
{
155+
int i;
156+
157+
for (i = 0; i < AQR107_SGMII_STAT_SZ; i++)
158+
strscpy(data + i * ETH_GSTRING_LEN, aqr107_hw_stats[i].name,
159+
ETH_GSTRING_LEN);
160+
}
161+
162+
static u64 aqr107_get_stat(struct phy_device *phydev, int index)
163+
{
164+
const struct aqr107_hw_stat *stat = aqr107_hw_stats + index;
165+
int len_l = min(stat->size, 16);
166+
int len_h = stat->size - len_l;
167+
u64 ret;
168+
int val;
169+
170+
val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg);
171+
if (val < 0)
172+
return U64_MAX;
173+
174+
ret = val & GENMASK(len_l - 1, 0);
175+
if (len_h) {
176+
val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg + 1);
177+
if (val < 0)
178+
return U64_MAX;
179+
180+
ret += (val & GENMASK(len_h - 1, 0)) << 16;
181+
}
182+
183+
return ret;
184+
}
185+
186+
static void aqr107_get_stats(struct phy_device *phydev,
187+
struct ethtool_stats *stats, u64 *data)
188+
{
189+
struct aqr107_priv *priv = phydev->priv;
190+
u64 val;
191+
int i;
192+
193+
for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) {
194+
val = aqr107_get_stat(phydev, i);
195+
if (val == U64_MAX)
196+
phydev_err(phydev, "Reading HW Statistics failed for %s\n",
197+
aqr107_hw_stats[i].name);
198+
else
199+
priv->sgmii_stats[i] += val;
200+
201+
data[i] = priv->sgmii_stats[i];
202+
}
203+
}
204+
111205
static int aqr_config_aneg(struct phy_device *phydev)
112206
{
113207
bool changed = false;
@@ -490,6 +584,16 @@ static int aqr107_resume(struct phy_device *phydev)
490584
MDIO_CTRL1_LPOWER);
491585
}
492586

587+
static int aqr107_probe(struct phy_device *phydev)
588+
{
589+
phydev->priv = devm_kzalloc(&phydev->mdio.dev,
590+
sizeof(struct aqr107_priv), GFP_KERNEL);
591+
if (!phydev->priv)
592+
return -ENOMEM;
593+
594+
return aqr_hwmon_probe(phydev);
595+
}
596+
493597
static struct phy_driver aqr_driver[] = {
494598
{
495599
PHY_ID_MATCH_MODEL(PHY_ID_AQ1202),
@@ -536,7 +640,7 @@ static struct phy_driver aqr_driver[] = {
536640
.name = "Aquantia AQR107",
537641
.aneg_done = genphy_c45_aneg_done,
538642
.get_features = genphy_c45_pma_read_abilities,
539-
.probe = aqr_hwmon_probe,
643+
.probe = aqr107_probe,
540644
.config_init = aqr107_config_init,
541645
.config_aneg = aqr_config_aneg,
542646
.config_intr = aqr_config_intr,
@@ -546,14 +650,17 @@ static struct phy_driver aqr_driver[] = {
546650
.set_tunable = aqr107_set_tunable,
547651
.suspend = aqr107_suspend,
548652
.resume = aqr107_resume,
653+
.get_sset_count = aqr107_get_sset_count,
654+
.get_strings = aqr107_get_strings,
655+
.get_stats = aqr107_get_stats,
549656
.link_change_notify = aqr107_link_change_notify,
550657
},
551658
{
552659
PHY_ID_MATCH_MODEL(PHY_ID_AQCS109),
553660
.name = "Aquantia AQCS109",
554661
.aneg_done = genphy_c45_aneg_done,
555662
.get_features = genphy_c45_pma_read_abilities,
556-
.probe = aqr_hwmon_probe,
663+
.probe = aqr107_probe,
557664
.config_init = aqcs109_config_init,
558665
.config_aneg = aqr_config_aneg,
559666
.config_intr = aqr_config_intr,
@@ -563,6 +670,9 @@ static struct phy_driver aqr_driver[] = {
563670
.set_tunable = aqr107_set_tunable,
564671
.suspend = aqr107_suspend,
565672
.resume = aqr107_resume,
673+
.get_sset_count = aqr107_get_sset_count,
674+
.get_strings = aqr107_get_strings,
675+
.get_stats = aqr107_get_stats,
566676
.link_change_notify = aqr107_link_change_notify,
567677
},
568678
{

0 commit comments

Comments
 (0)