lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1560329827-6345-3-git-send-email-Raju.Lakkaraju@microchip.com>
Date:   Wed, 12 Jun 2019 14:27:07 +0530
From:   Raju Lakkaraju <Raju.Lakkaraju@...rochip.com>
To:     netdev@...r.kernel.org
Cc:     UNGLinuxDriver@...rochip.com, f.fainelli@...il.com, andrew@...n.ch,
        Raju Lakkaraju <Raju.Lakkaraju@...rochip.com>
Subject: [RFC, net-next v0 2/2] net: phy: mscc: Add PHY driver for Cable Diagnostics command

From: Raju Lakkaraju <Raju.Lakkaraju@...rochip.com>

Add the Cable diagnostics command to VSC85xx PHYs.

Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@...rochip.com>
---
 drivers/net/phy/mscc.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 128 insertions(+)

diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index 28676af..98e3925 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -153,9 +153,29 @@ enum rgmii_rx_clock_delay {
 #define MSCC_PHY_EXT_PHY_CNTL_4		  23
 #define PHY_CNTL_4_ADDR_POS		  11
 
+#define MSCC_PHY_VERIPHY_CNTL_1           24
+#define VERIPHY_TRIGGER_CNTL_MASK	  0x8000
+#define VERIPHY_VALID_MASK		  0x4000
+#define VERIPHY_PAIR_A_DISTANCE_MASK	  0x2F00
+#define VERIPHY_PAIR_A_DISTANCE_POS	  8
+#define VERIPHY_PAIR_B_DISTANCE_MASK	  0x002F
+#define VERIPHY_PAIR_B_DISTANCE_POS	  0
+
 #define MSCC_PHY_VERIPHY_CNTL_2		  25
+#define VERIPHY_PAIR_C_DISTANCE_MASK	  0x2F00
+#define VERIPHY_PAIR_C_DISTANCE_POS	  8
+#define VERIPHY_PAIR_D_DISTANCE_MASK	  0x002F
+#define VERIPHY_PAIR_D_DISTANCE_POS	  0
 
 #define MSCC_PHY_VERIPHY_CNTL_3		  26
+#define VERIPHY_PAIR_A_STATUS_MASK	  0xF000
+#define VERIPHY_PAIR_A_STATUS_POS	  12
+#define VERIPHY_PAIR_B_STATUS_MASK	  0x0F00
+#define VERIPHY_PAIR_B_STATUS_POS	  8
+#define VERIPHY_PAIR_C_STATUS_MASK	  0x00F0
+#define VERIPHY_PAIR_C_STATUS_POS	  4
+#define VERIPHY_PAIR_D_STATUS_MASK	  0x000F
+#define VERIPHY_PAIR_D_STATUS_POS	  0
 
 /* Extended Page 2 Registers */
 #define MSCC_PHY_CU_PMD_TX_CNTL		  16
@@ -442,6 +462,107 @@ static int vsc85xx_phy_write_page(struct phy_device *phydev, int page)
 	return __phy_write(phydev, MSCC_EXT_PAGE_ACCESS, page);
 }
 
+static int vsc85xx_cabdiag_request(struct phy_device *phydev,
+				   struct phy_cabdiag_req *cfg)
+{
+	u16 reg_val;
+	u8 timeout_cnt = 0;
+	int rc;
+
+	if (cfg->pairs_bitmask < CABDIAG_PAIR_A_MASK   ||
+	    (cfg->pairs_bitmask > (CABDIAG_PAIR_A_MASK |
+				   CABDIAG_PAIR_B_MASK |
+				   CABDIAG_PAIR_C_MASK |
+				   CABDIAG_PAIR_D_MASK))) {
+		cfg->op_status = CD_REQ_INVALID_PAIR_MASK;
+		return 0;
+	}
+	if (cfg->timeout_cnt == 0) {
+		cfg->op_status = CD_REQ_INVALID_TIMEOUT;
+		return 0;
+	}
+
+	mutex_lock(&phydev->lock);
+	rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED);
+	if (rc < 0)
+		goto out_unlock;
+
+	reg_val = __phy_read(phydev, MSCC_PHY_VERIPHY_CNTL_1);
+	if (reg_val & VERIPHY_TRIGGER_CNTL_MASK) {
+		cfg->op_status = CD_REQ_REJECTED_BUSY;
+		goto out_unlock;
+	}
+	/* Start Cable Diagnostics operation */
+	reg_val |= VERIPHY_TRIGGER_CNTL_MASK;
+	__phy_write(phydev, MSCC_PHY_VERIPHY_CNTL_1, reg_val);
+
+	/* Wait till VeriPHY has completed */
+	do {
+		msleep(30);
+		reg_val = __phy_read(phydev, MSCC_PHY_VERIPHY_CNTL_1);
+	} while ((reg_val & VERIPHY_TRIGGER_CNTL_MASK) &&
+		 (timeout_cnt++ < cfg->timeout_cnt));
+
+	if (timeout_cnt >= cfg->timeout_cnt) {
+		cfg->op_status = CD_STATUS_FAILED_TIMEOUT;
+		goto out_unlock;
+	}
+	cfg->timeout_cnt = timeout_cnt;
+
+	if (reg_val & VERIPHY_VALID_MASK) {
+		/* VeriPHY results are valid */
+		if (cfg->pairs_bitmask & CABDIAG_PAIR_A_MASK) {
+			reg_val = __phy_read(phydev, MSCC_PHY_VERIPHY_CNTL_1);
+			cfg->pairs[CABDIAG_PAIR_A].length =
+			(reg_val & VERIPHY_PAIR_A_DISTANCE_MASK) >>
+			VERIPHY_PAIR_A_DISTANCE_POS;
+			reg_val = __phy_read(phydev, MSCC_PHY_VERIPHY_CNTL_3);
+			cfg->pairs[CABDIAG_PAIR_A].status =
+			(reg_val & VERIPHY_PAIR_A_STATUS_MASK) >>
+			VERIPHY_PAIR_A_STATUS_POS;
+		}
+		if (cfg->pairs_bitmask & CABDIAG_PAIR_B_MASK) {
+			reg_val = __phy_read(phydev, MSCC_PHY_VERIPHY_CNTL_1);
+			cfg->pairs[CABDIAG_PAIR_B].length =
+			(reg_val & VERIPHY_PAIR_B_DISTANCE_MASK) >>
+			VERIPHY_PAIR_B_DISTANCE_POS;
+			reg_val = __phy_read(phydev, MSCC_PHY_VERIPHY_CNTL_3);
+			cfg->pairs[CABDIAG_PAIR_B].status =
+			(reg_val & VERIPHY_PAIR_B_STATUS_MASK) >>
+			VERIPHY_PAIR_B_STATUS_POS;
+		}
+		if (cfg->pairs_bitmask & CABDIAG_PAIR_C_MASK) {
+			reg_val = __phy_read(phydev, MSCC_PHY_VERIPHY_CNTL_2);
+			cfg->pairs[CABDIAG_PAIR_C].length =
+			(reg_val & VERIPHY_PAIR_C_DISTANCE_MASK) >>
+			VERIPHY_PAIR_C_DISTANCE_POS;
+			reg_val = __phy_read(phydev, MSCC_PHY_VERIPHY_CNTL_3);
+			cfg->pairs[CABDIAG_PAIR_C].status =
+			(reg_val & VERIPHY_PAIR_C_STATUS_MASK) >>
+			VERIPHY_PAIR_C_STATUS_POS;
+		}
+		if (cfg->pairs_bitmask & CABDIAG_PAIR_D_MASK) {
+			reg_val = __phy_read(phydev, MSCC_PHY_VERIPHY_CNTL_2);
+			cfg->pairs[CABDIAG_PAIR_D].length =
+			(reg_val & VERIPHY_PAIR_D_DISTANCE_MASK) >>
+			VERIPHY_PAIR_D_DISTANCE_POS;
+			reg_val = __phy_read(phydev, MSCC_PHY_VERIPHY_CNTL_3);
+			cfg->pairs[CABDIAG_PAIR_D].status =
+			(reg_val & VERIPHY_PAIR_D_STATUS_MASK) >>
+			VERIPHY_PAIR_D_STATUS_POS;
+		}
+		cfg->op_status = CD_STATUS_SUCCESS;
+	} else {
+		cfg->op_status = CD_STATUS_FAILED_INVALID;
+	}
+
+out_unlock:
+	phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
+	mutex_unlock(&phydev->lock);
+
+	return rc;
+}
+
 static int vsc85xx_get_sset_count(struct phy_device *phydev)
 {
 	struct vsc8531_private *priv = phydev->priv;
@@ -2343,6 +2464,7 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_sset_count = &vsc85xx_get_sset_count,
 	.get_strings    = &vsc85xx_get_strings,
 	.get_stats      = &vsc85xx_get_stats,
+	.request_cable_diag = &vsc85xx_cabdiag_request,
 },
 {
 	.phy_id		= PHY_ID_VSC8530,
@@ -2368,6 +2490,7 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_sset_count = &vsc85xx_get_sset_count,
 	.get_strings    = &vsc85xx_get_strings,
 	.get_stats      = &vsc85xx_get_stats,
+	.request_cable_diag = &vsc85xx_cabdiag_request,
 },
 {
 	.phy_id		= PHY_ID_VSC8531,
@@ -2393,6 +2516,7 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_sset_count = &vsc85xx_get_sset_count,
 	.get_strings    = &vsc85xx_get_strings,
 	.get_stats      = &vsc85xx_get_stats,
+	.request_cable_diag = &vsc85xx_cabdiag_request,
 },
 {
 	.phy_id		= PHY_ID_VSC8540,
@@ -2418,6 +2542,7 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_sset_count = &vsc85xx_get_sset_count,
 	.get_strings    = &vsc85xx_get_strings,
 	.get_stats      = &vsc85xx_get_stats,
+	.request_cable_diag = &vsc85xx_cabdiag_request,
 },
 {
 	.phy_id		= PHY_ID_VSC8541,
@@ -2443,6 +2568,7 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_sset_count = &vsc85xx_get_sset_count,
 	.get_strings    = &vsc85xx_get_strings,
 	.get_stats      = &vsc85xx_get_stats,
+	.request_cable_diag = &vsc85xx_cabdiag_request,
 },
 {
 	.phy_id		= PHY_ID_VSC8574,
@@ -2469,6 +2595,7 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_sset_count = &vsc85xx_get_sset_count,
 	.get_strings    = &vsc85xx_get_strings,
 	.get_stats      = &vsc85xx_get_stats,
+	.request_cable_diag = &vsc85xx_cabdiag_request,
 },
 {
 	.phy_id		= PHY_ID_VSC8584,
@@ -2493,6 +2620,7 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_sset_count = &vsc85xx_get_sset_count,
 	.get_strings    = &vsc85xx_get_strings,
 	.get_stats      = &vsc85xx_get_stats,
+	.request_cable_diag = &vsc85xx_cabdiag_request,
 }
 
 };
-- 
2.7.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ