Skip to content

Commit 687678f

Browse files
committed
Merge branch 'add-shared-phy-counter-support-for-qca807x-and-qca808x'
Luo Jie says: ==================== Add shared PHY counter support for QCA807x and QCA808x The implementation of the PHY counter is identical for both QCA808x and QCA807x series devices. This includes counters for both good and bad CRC frames in the RX and TX directions, which are active when CRC checking is enabled. This patch series introduces PHY counter functions into a shared library, enabling counter support for the QCA808x and QCA807x families through this common infrastructure. Additionally, enable CRC checking and configure automatic clearing of counters after reading within config_init() to ensure accurate counter recording. v2: https://lore.kernel.org/[email protected] v1: https://lore.kernel.org/[email protected] ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents a93f38e + d98f43b commit 687678f

File tree

4 files changed

+146
-0
lines changed

4 files changed

+146
-0
lines changed

drivers/net/phy/qcom/qca807x.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ struct qca807x_priv {
124124
bool dac_full_amplitude;
125125
bool dac_full_bias_current;
126126
bool dac_disable_bias_current_tweak;
127+
struct qcom_phy_hw_stats hw_stats;
127128
};
128129

129130
static int qca807x_cable_test_start(struct phy_device *phydev)
@@ -768,6 +769,10 @@ static int qca807x_config_init(struct phy_device *phydev)
768769
return ret;
769770
}
770771

772+
ret = qcom_phy_counter_config(phydev);
773+
if (ret)
774+
return ret;
775+
771776
control_dac = phy_read_mmd(phydev, MDIO_MMD_AN,
772777
QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH);
773778
control_dac &= ~QCA807X_CONTROL_DAC_MASK;
@@ -782,6 +787,22 @@ static int qca807x_config_init(struct phy_device *phydev)
782787
control_dac);
783788
}
784789

790+
static int qca807x_update_stats(struct phy_device *phydev)
791+
{
792+
struct qca807x_priv *priv = phydev->priv;
793+
794+
return qcom_phy_update_stats(phydev, &priv->hw_stats);
795+
}
796+
797+
static void qca807x_get_phy_stats(struct phy_device *phydev,
798+
struct ethtool_eth_phy_stats *eth_stats,
799+
struct ethtool_phy_stats *stats)
800+
{
801+
struct qca807x_priv *priv = phydev->priv;
802+
803+
qcom_phy_get_stats(stats, priv->hw_stats);
804+
}
805+
785806
static struct phy_driver qca807x_drivers[] = {
786807
{
787808
PHY_ID_MATCH_EXACT(PHY_ID_QCA8072),
@@ -800,6 +821,8 @@ static struct phy_driver qca807x_drivers[] = {
800821
.suspend = genphy_suspend,
801822
.cable_test_start = qca807x_cable_test_start,
802823
.cable_test_get_status = qca808x_cable_test_get_status,
824+
.update_stats = qca807x_update_stats,
825+
.get_phy_stats = qca807x_get_phy_stats,
803826
},
804827
{
805828
PHY_ID_MATCH_EXACT(PHY_ID_QCA8075),
@@ -823,6 +846,8 @@ static struct phy_driver qca807x_drivers[] = {
823846
.led_hw_is_supported = qca807x_led_hw_is_supported,
824847
.led_hw_control_set = qca807x_led_hw_control_set,
825848
.led_hw_control_get = qca807x_led_hw_control_get,
849+
.update_stats = qca807x_update_stats,
850+
.get_phy_stats = qca807x_get_phy_stats,
826851
},
827852
};
828853
module_phy_driver(qca807x_drivers);

drivers/net/phy/qcom/qca808x.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ MODULE_LICENSE("GPL");
9393

9494
struct qca808x_priv {
9595
int led_polarity_mode;
96+
struct qcom_phy_hw_stats hw_stats;
9697
};
9798

9899
static int qca808x_phy_fast_retrain_config(struct phy_device *phydev)
@@ -243,6 +244,10 @@ static int qca808x_config_init(struct phy_device *phydev)
243244

244245
qca808x_fill_possible_interfaces(phydev);
245246

247+
ret = qcom_phy_counter_config(phydev);
248+
if (ret)
249+
return ret;
250+
246251
/* Configure adc threshold as 100mv for the link 10M */
247252
return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD,
248253
QCA808X_ADC_THRESHOLD_MASK,
@@ -622,6 +627,22 @@ static int qca808x_led_polarity_set(struct phy_device *phydev, int index,
622627
active_low ? 0 : QCA808X_LED_ACTIVE_HIGH);
623628
}
624629

630+
static int qca808x_update_stats(struct phy_device *phydev)
631+
{
632+
struct qca808x_priv *priv = phydev->priv;
633+
634+
return qcom_phy_update_stats(phydev, &priv->hw_stats);
635+
}
636+
637+
static void qca808x_get_phy_stats(struct phy_device *phydev,
638+
struct ethtool_eth_phy_stats *eth_stats,
639+
struct ethtool_phy_stats *stats)
640+
{
641+
struct qca808x_priv *priv = phydev->priv;
642+
643+
qcom_phy_get_stats(stats, priv->hw_stats);
644+
}
645+
625646
static struct phy_driver qca808x_driver[] = {
626647
{
627648
/* Qualcomm QCA8081 */
@@ -651,6 +672,8 @@ static struct phy_driver qca808x_driver[] = {
651672
.led_hw_control_set = qca808x_led_hw_control_set,
652673
.led_hw_control_get = qca808x_led_hw_control_get,
653674
.led_polarity_set = qca808x_led_polarity_set,
675+
.update_stats = qca808x_update_stats,
676+
.get_phy_stats = qca808x_get_phy_stats,
654677
}, };
655678

656679
module_phy_driver(qca808x_driver);

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

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,3 +699,78 @@ int qca808x_led_reg_blink_set(struct phy_device *phydev, u16 reg,
699699
return 0;
700700
}
701701
EXPORT_SYMBOL_GPL(qca808x_led_reg_blink_set);
702+
703+
/* Enable CRC checking for both received and transmitted frames to ensure
704+
* accurate counter recording. The hardware supports a 32-bit counter,
705+
* configure the counter to clear after it is read to facilitate the
706+
* implementation of a 64-bit software counter
707+
*/
708+
int qcom_phy_counter_config(struct phy_device *phydev)
709+
{
710+
return phy_set_bits_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_CNT_CTRL,
711+
QCA808X_MMD7_CNT_CTRL_CRC_CHECK_EN |
712+
QCA808X_MMD7_CNT_CTRL_READ_CLEAR_EN);
713+
}
714+
EXPORT_SYMBOL_GPL(qcom_phy_counter_config);
715+
716+
int qcom_phy_update_stats(struct phy_device *phydev,
717+
struct qcom_phy_hw_stats *hw_stats)
718+
{
719+
int ret;
720+
u32 cnt;
721+
722+
/* PHY 32-bit counter for RX packets. */
723+
ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_CNT_RX_PKT_15_0);
724+
if (ret < 0)
725+
return ret;
726+
727+
cnt = ret;
728+
729+
ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_CNT_RX_PKT_31_16);
730+
if (ret < 0)
731+
return ret;
732+
733+
cnt |= ret << 16;
734+
hw_stats->rx_pkts += cnt;
735+
736+
/* PHY 16-bit counter for RX CRC error packets. */
737+
ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_CNT_RX_ERR_PKT);
738+
if (ret < 0)
739+
return ret;
740+
741+
hw_stats->rx_err_pkts += ret;
742+
743+
/* PHY 32-bit counter for TX packets. */
744+
ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_CNT_TX_PKT_15_0);
745+
if (ret < 0)
746+
return ret;
747+
748+
cnt = ret;
749+
750+
ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_CNT_TX_PKT_31_16);
751+
if (ret < 0)
752+
return ret;
753+
754+
cnt |= ret << 16;
755+
hw_stats->tx_pkts += cnt;
756+
757+
/* PHY 16-bit counter for TX CRC error packets. */
758+
ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_CNT_TX_ERR_PKT);
759+
if (ret < 0)
760+
return ret;
761+
762+
hw_stats->tx_err_pkts += ret;
763+
764+
return 0;
765+
}
766+
EXPORT_SYMBOL_GPL(qcom_phy_update_stats);
767+
768+
void qcom_phy_get_stats(struct ethtool_phy_stats *stats,
769+
struct qcom_phy_hw_stats hw_stats)
770+
{
771+
stats->tx_packets = hw_stats.tx_pkts;
772+
stats->tx_errors = hw_stats.tx_err_pkts;
773+
stats->rx_packets = hw_stats.rx_pkts;
774+
stats->rx_errors = hw_stats.rx_err_pkts;
775+
}
776+
EXPORT_SYMBOL_GPL(qcom_phy_get_stats);

drivers/net/phy/qcom/qcom.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,17 @@
195195
#define AT803X_MIN_DOWNSHIFT 2
196196
#define AT803X_MAX_DOWNSHIFT 9
197197

198+
#define QCA808X_MMD7_CNT_CTRL 0x8029
199+
#define QCA808X_MMD7_CNT_CTRL_READ_CLEAR_EN BIT(1)
200+
#define QCA808X_MMD7_CNT_CTRL_CRC_CHECK_EN BIT(0)
201+
202+
#define QCA808X_MMD7_CNT_RX_PKT_31_16 0x802a
203+
#define QCA808X_MMD7_CNT_RX_PKT_15_0 0x802b
204+
#define QCA808X_MMD7_CNT_RX_ERR_PKT 0x802c
205+
#define QCA808X_MMD7_CNT_TX_PKT_31_16 0x802d
206+
#define QCA808X_MMD7_CNT_TX_PKT_15_0 0x802e
207+
#define QCA808X_MMD7_CNT_TX_ERR_PKT 0x802f
208+
198209
enum stat_access_type {
199210
PHY,
200211
MMD
@@ -212,6 +223,13 @@ struct at803x_ss_mask {
212223
u8 speed_shift;
213224
};
214225

226+
struct qcom_phy_hw_stats {
227+
u64 rx_pkts;
228+
u64 rx_err_pkts;
229+
u64 tx_pkts;
230+
u64 tx_err_pkts;
231+
};
232+
215233
int at803x_debug_reg_read(struct phy_device *phydev, u16 reg);
216234
int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
217235
u16 clear, u16 set);
@@ -246,3 +264,8 @@ int qca808x_led_reg_brightness_set(struct phy_device *phydev,
246264
int qca808x_led_reg_blink_set(struct phy_device *phydev, u16 reg,
247265
unsigned long *delay_on,
248266
unsigned long *delay_off);
267+
int qcom_phy_counter_config(struct phy_device *phydev);
268+
int qcom_phy_update_stats(struct phy_device *phydev,
269+
struct qcom_phy_hw_stats *hw_stats);
270+
void qcom_phy_get_stats(struct ethtool_phy_stats *stats,
271+
struct qcom_phy_hw_stats hw_stats);

0 commit comments

Comments
 (0)