linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC Patch net-next 0/3] add ethtool SQI support for LAN87xx T1 Phy
@ 2022-03-21 15:53 Arun Ramadoss
  2022-03-21 15:53 ` [RFC Patch net-next 1/3] net: phy: lan87xx: added lan87xx_update_link routine Arun Ramadoss
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Arun Ramadoss @ 2022-03-21 15:53 UTC (permalink / raw)
  To: linux-kernel, netdev
  Cc: Paolo Abeni, Jakub Kicinski, David S. Miller, Russell King,
	Heiner Kallweit, Andrew Lunn, UNGLinuxDriver

This patch series add the Signal Quality Index measurement for the LAN87xx and
LAN937x T1 phy.

Arun Ramadoss (3):
  net: phy: lan87xx: added lan87xx_update_link routine
  net: phy: lan937x: added PHY_POLL_CABLE_TEST flag
  net: phy: lan87xx: added ethtool SQI support

 drivers/net/phy/microchip_t1.c | 146 ++++++++++++++++++++++++++++++++-
 1 file changed, 145 insertions(+), 1 deletion(-)


base-commit: 092d992b76ed9d06389af0bc5efd5279d7b1ed9f
-- 
2.33.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [RFC Patch net-next 1/3] net: phy: lan87xx: added lan87xx_update_link routine
  2022-03-21 15:53 [RFC Patch net-next 0/3] add ethtool SQI support for LAN87xx T1 Phy Arun Ramadoss
@ 2022-03-21 15:53 ` Arun Ramadoss
  2022-03-21 15:53 ` [RFC Patch net-next 2/3] net: phy: lan937x: added PHY_POLL_CABLE_TEST flag Arun Ramadoss
  2022-03-21 15:53 ` [RFC Patch net-next 3/3] net: phy: lan87xx: added ethtool SQI support Arun Ramadoss
  2 siblings, 0 replies; 7+ messages in thread
From: Arun Ramadoss @ 2022-03-21 15:53 UTC (permalink / raw)
  To: linux-kernel, netdev
  Cc: Paolo Abeni, Jakub Kicinski, David S. Miller, Russell King,
	Heiner Kallweit, Andrew Lunn, UNGLinuxDriver

The LAN87xx phydev->link has been updated via lan87xx_read_status
routine. To get only the recent phydev->link status instead of various
other status, refactored the code to have separate lan87xx_update_link
routine.

Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com>
---
 drivers/net/phy/microchip_t1.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/microchip_t1.c b/drivers/net/phy/microchip_t1.c
index 389df3f4293c..bb4514254adc 100644
--- a/drivers/net/phy/microchip_t1.c
+++ b/drivers/net/phy/microchip_t1.c
@@ -674,7 +674,7 @@ static int lan87xx_cable_test_get_status(struct phy_device *phydev,
 	return 0;
 }
 
-static int lan87xx_read_status(struct phy_device *phydev)
+static int lan87xx_update_link(struct phy_device *phydev)
 {
 	int rc = 0;
 
@@ -687,6 +687,17 @@ static int lan87xx_read_status(struct phy_device *phydev)
 	else
 		phydev->link = 0;
 
+	return rc;
+}
+
+static int lan87xx_read_status(struct phy_device *phydev)
+{
+	int rc = 0;
+
+	rc = lan87xx_update_link(phydev);
+	if (rc < 0)
+		return rc;
+
 	phydev->speed = SPEED_UNKNOWN;
 	phydev->duplex = DUPLEX_UNKNOWN;
 	phydev->pause = 0;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC Patch net-next 2/3] net: phy: lan937x: added PHY_POLL_CABLE_TEST flag
  2022-03-21 15:53 [RFC Patch net-next 0/3] add ethtool SQI support for LAN87xx T1 Phy Arun Ramadoss
  2022-03-21 15:53 ` [RFC Patch net-next 1/3] net: phy: lan87xx: added lan87xx_update_link routine Arun Ramadoss
@ 2022-03-21 15:53 ` Arun Ramadoss
  2022-03-21 15:53 ` [RFC Patch net-next 3/3] net: phy: lan87xx: added ethtool SQI support Arun Ramadoss
  2 siblings, 0 replies; 7+ messages in thread
From: Arun Ramadoss @ 2022-03-21 15:53 UTC (permalink / raw)
  To: linux-kernel, netdev
  Cc: Paolo Abeni, Jakub Kicinski, David S. Miller, Russell King,
	Heiner Kallweit, Andrew Lunn, UNGLinuxDriver

Added the phy_poll_cable_test flag for the lan937x phy driver.
Tested using command -  ethtool --cable-test <dev>

Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com>
---
 drivers/net/phy/microchip_t1.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/phy/microchip_t1.c b/drivers/net/phy/microchip_t1.c
index bb4514254adc..2742d71a469f 100644
--- a/drivers/net/phy/microchip_t1.c
+++ b/drivers/net/phy/microchip_t1.c
@@ -759,6 +759,7 @@ static struct phy_driver microchip_t1_phy_driver[] = {
 	{
 		PHY_ID_MATCH_MODEL(PHY_ID_LAN937X),
 		.name		= "Microchip LAN937x T1",
+		.flags          = PHY_POLL_CABLE_TEST,
 		.features	= PHY_BASIC_T1_FEATURES,
 		.config_init	= lan87xx_config_init,
 		.suspend	= genphy_suspend,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC Patch net-next 3/3] net: phy: lan87xx: added ethtool SQI support
  2022-03-21 15:53 [RFC Patch net-next 0/3] add ethtool SQI support for LAN87xx T1 Phy Arun Ramadoss
  2022-03-21 15:53 ` [RFC Patch net-next 1/3] net: phy: lan87xx: added lan87xx_update_link routine Arun Ramadoss
  2022-03-21 15:53 ` [RFC Patch net-next 2/3] net: phy: lan937x: added PHY_POLL_CABLE_TEST flag Arun Ramadoss
@ 2022-03-21 15:53 ` Arun Ramadoss
  2022-03-21 18:36   ` Andrew Lunn
  2 siblings, 1 reply; 7+ messages in thread
From: Arun Ramadoss @ 2022-03-21 15:53 UTC (permalink / raw)
  To: linux-kernel, netdev
  Cc: Paolo Abeni, Jakub Kicinski, David S. Miller, Russell King,
	Heiner Kallweit, Andrew Lunn, UNGLinuxDriver

This patch add the support for measuring Signal Quality Index for
LAN87xx and LAN937x T1 Phy. To get better accuracy of the SQI,
readings are measured and its average is calculated. If the link is
down, then routine return immediately.

Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com>
---
 drivers/net/phy/microchip_t1.c | 132 +++++++++++++++++++++++++++++++++
 1 file changed, 132 insertions(+)

diff --git a/drivers/net/phy/microchip_t1.c b/drivers/net/phy/microchip_t1.c
index 2742d71a469f..ebbf1e8067f6 100644
--- a/drivers/net/phy/microchip_t1.c
+++ b/drivers/net/phy/microchip_t1.c
@@ -9,6 +9,7 @@
 #include <linux/ethtool.h>
 #include <linux/ethtool_netlink.h>
 #include <linux/bitfield.h>
+#include <linux/sort.h>
 
 #define PHY_ID_LAN87XX				0x0007c150
 #define PHY_ID_LAN937X				0x0007c180
@@ -68,7 +69,14 @@
 #define T1_POST_LCK_MUFACT_CFG_REG	0x1C
 #define T1_TX_RX_FIFO_CFG_REG		0x02
 #define T1_TX_LPF_FIR_CFG_REG		0x55
+#define T1_COEF_CLK_PWR_DN_CFG		0x04
+#define T1_COEF_RW_CTL_CFG		0x0D
 #define T1_SQI_CONFIG_REG		0x2E
+#define T1_SQI_CONFIG2_REG		0x4A
+#define T1_DCQ_MSE_REG			0xC1
+#define T1_MSE_VLD_MSK			BIT(9)
+#define T1_DCQ_SQI_REG			0xC3
+#define T1_DCQ_SQI_MSK			GENMASK(3, 1)
 #define T1_MDIO_CONTROL2_REG		0x10
 #define T1_INTERRUPT_SOURCE_REG		0x18
 #define T1_INTERRUPT2_SOURCE_REG	0x08
@@ -82,6 +90,12 @@
 #define T1_MODE_STAT_REG		0x11
 #define T1_LINK_UP_MSK			BIT(0)
 
+/* SQI defines */
+#define LAN87XX_MAX_SQI			0x07
+#define LAN87XX_SQI_ENTRY		200
+#define SQI_AVG_MIN			40
+#define SQI_AVG_MAX			160
+
 #define DRIVER_AUTHOR	"Nisar Sayed <nisar.sayed@microchip.com>"
 #define DRIVER_DESC	"Microchip LAN87XX/LAN937x T1 PHY driver"
 
@@ -740,6 +754,120 @@ static int lan87xx_config_aneg(struct phy_device *phydev)
 	return rc;
 }
 
+static int lan87xx_sqi_cmp(const void *a, const void *b)
+{
+	return *(u16 *)a - *(u16 *)b;
+}
+
+static int lan87xx_get_sqi(struct phy_device *phydev)
+{
+	u16 sqi_value[LAN87XX_SQI_ENTRY];
+	u32 sqi_avg = 0;
+	int rc;
+	u8 i;
+
+	rc = lan87xx_update_link(phydev);
+	if (rc < 0)
+		return rc;
+
+	if (phydev->link == 0)
+		return sqi_avg;
+
+	rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
+			 PHYACC_ATTR_BANK_DSP, T1_COEF_CLK_PWR_DN_CFG, 0x16d6);
+	if (rc < 0)
+		return rc;
+
+	/* Enable SQI measurement */
+	rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
+			 PHYACC_ATTR_BANK_DSP, T1_SQI_CONFIG_REG, 0x9572);
+	if (rc < 0)
+		return rc;
+
+	/* Enable SQI Method 5 */
+	rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
+			 PHYACC_ATTR_BANK_DSP, T1_SQI_CONFIG2_REG, 0x0001);
+	if (rc < 0)
+		return rc;
+
+	/* Below effectively throws away first reading
+	 * required delay before reading DSP.
+	 */
+	rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
+			 PHYACC_ATTR_BANK_DSP, T1_COEF_RW_CTL_CFG, 0x0301);
+	if (rc < 0)
+		return rc;
+
+	usleep_range(40, 50);
+
+	for (i = 0; i < LAN87XX_SQI_ENTRY; i++) {
+		rc = lan87xx_update_link(phydev);
+		if (rc < 0)
+			return rc;
+
+		if (phydev->link == 0)
+			return sqi_avg;
+
+		rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
+				 PHYACC_ATTR_BANK_DSP,
+				 T1_COEF_RW_CTL_CFG, 0x0301);
+		if (rc < 0)
+			return rc;
+
+		rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
+				 PHYACC_ATTR_BANK_DSP, T1_DCQ_SQI_REG, 0x0);
+		if (rc < 0)
+			return rc;
+
+		sqi_value[i] = FIELD_GET(T1_DCQ_SQI_MSK, rc);
+
+		rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
+				 PHYACC_ATTR_BANK_DSP, T1_DCQ_MSE_REG, 0x0);
+		if (rc < 0)
+			return rc;
+
+		/* Check valid value. 0 - valid, 1 - Invalid
+		 * if invalid, re-read the value after 250ms
+		 */
+		if (FIELD_GET(T1_MSE_VLD_MSK, rc) == 1) {
+			rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
+					 PHYACC_ATTR_BANK_DSP,
+					 T1_COEF_RW_CTL_CFG, 0x0301);
+			if (rc < 0)
+				return rc;
+
+			msleep(250);
+
+			rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
+					 PHYACC_ATTR_BANK_DSP,
+					 T1_DCQ_SQI_REG, 0x0);
+			if (rc < 0)
+				return rc;
+
+			sqi_value[i] = FIELD_GET(T1_DCQ_SQI_MSK, rc);
+		}
+	}
+
+	/* Sorting SQI values */
+	sort(sqi_value, LAN87XX_SQI_ENTRY, sizeof(u16), lan87xx_sqi_cmp, NULL);
+
+	/* Discarding outliers */
+	for (i = 0; i < LAN87XX_SQI_ENTRY; i++) {
+		if (i >= SQI_AVG_MIN && i <= SQI_AVG_MAX)
+			sqi_avg += sqi_value[i];
+	}
+
+	/* Calculating SQI number */
+	sqi_avg = DIV_ROUND_UP(sqi_avg, (SQI_AVG_MAX - SQI_AVG_MIN + 1));
+
+	return sqi_avg;
+}
+
+static int lan87xx_get_sqi_max(struct phy_device *phydev)
+{
+	return LAN87XX_MAX_SQI;
+}
+
 static struct phy_driver microchip_t1_phy_driver[] = {
 	{
 		PHY_ID_MATCH_MODEL(PHY_ID_LAN87XX),
@@ -753,6 +881,8 @@ static struct phy_driver microchip_t1_phy_driver[] = {
 		.resume         = genphy_resume,
 		.config_aneg    = lan87xx_config_aneg,
 		.read_status	= lan87xx_read_status,
+		.get_sqi	= lan87xx_get_sqi,
+		.get_sqi_max	= lan87xx_get_sqi_max,
 		.cable_test_start = lan87xx_cable_test_start,
 		.cable_test_get_status = lan87xx_cable_test_get_status,
 	},
@@ -766,6 +896,8 @@ static struct phy_driver microchip_t1_phy_driver[] = {
 		.resume		= genphy_resume,
 		.config_aneg    = lan87xx_config_aneg,
 		.read_status	= lan87xx_read_status,
+		.get_sqi	= lan87xx_get_sqi,
+		.get_sqi_max	= lan87xx_get_sqi_max,
 		.cable_test_start = lan87xx_cable_test_start,
 		.cable_test_get_status = lan87xx_cable_test_get_status,
 	}
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC Patch net-next 3/3] net: phy: lan87xx: added ethtool SQI support
  2022-03-21 15:53 ` [RFC Patch net-next 3/3] net: phy: lan87xx: added ethtool SQI support Arun Ramadoss
@ 2022-03-21 18:36   ` Andrew Lunn
  2022-03-24 15:48     ` Arun.Ramadoss
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Lunn @ 2022-03-21 18:36 UTC (permalink / raw)
  To: Arun Ramadoss
  Cc: linux-kernel, netdev, Paolo Abeni, Jakub Kicinski,
	David S. Miller, Russell King, Heiner Kallweit, UNGLinuxDriver

> +#define T1_DCQ_SQI_MSK			GENMASK(3, 1)

> +static int lan87xx_get_sqi(struct phy_device *phydev)
> +{
> +	u16 sqi_value[LAN87XX_SQI_ENTRY];

> +	for (i = 0; i < LAN87XX_SQI_ENTRY; i++) {
> +
> +		sqi_value[i] = FIELD_GET(T1_DCQ_SQI_MSK, rc);

> +
> +	/* Sorting SQI values */
> +	sort(sqi_value, LAN87XX_SQI_ENTRY, sizeof(u16), lan87xx_sqi_cmp, NULL);

Sort is quite heavyweight. Your SQI values are in the range 0-7 right?
So rather than have an array of LAN87XX_SQI_ENTRY entries, why not
create a histogram? You then just need to keep 8 uints. There is no
need to perform a sort to discard the outliers, simply remove from the
outer histogram buckets. And then you can calculate the average.

That should be faster and use less memory.

     Andrew

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC Patch net-next 3/3] net: phy: lan87xx: added ethtool SQI support
  2022-03-21 18:36   ` Andrew Lunn
@ 2022-03-24 15:48     ` Arun.Ramadoss
  2022-03-24 16:06       ` Andrew Lunn
  0 siblings, 1 reply; 7+ messages in thread
From: Arun.Ramadoss @ 2022-03-24 15:48 UTC (permalink / raw)
  To: andrew
  Cc: linux-kernel, UNGLinuxDriver, linux, kuba, pabeni, netdev, davem,
	hkallweit1

Hi Andrew,

Thanks for the review.

On Mon, 2022-03-21 at 19:36 +0100, Andrew Lunn wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you
> know the content is safe
> 
> > +#define T1_DCQ_SQI_MSK                       GENMASK(3, 1)
> > +static int lan87xx_get_sqi(struct phy_device *phydev)
> > +{
> > +     u16 sqi_value[LAN87XX_SQI_ENTRY];
> > +     for (i = 0; i < LAN87XX_SQI_ENTRY; i++) {
> > +
> > +             sqi_value[i] = FIELD_GET(T1_DCQ_SQI_MSK, rc);
> > +
> > +     /* Sorting SQI values */
> > +     sort(sqi_value, LAN87XX_SQI_ENTRY, sizeof(u16),
> > lan87xx_sqi_cmp, NULL);
> 
> Sort is quite heavyweight. Your SQI values are in the range 0-7
> right?
> So rather than have an array of LAN87XX_SQI_ENTRY entries, why not
> create a histogram? You then just need to keep 8 uints. There is no
> need to perform a sort to discard the outliers, simply remove from
> the
> outer histogram buckets. And then you can calculate the average.
> 
> That should be faster and use less memory.
> 
>      Andrew

I could get the algorithm for replacing array of LAN87XX_SQI_ENTRY(200)
to array of 8 (sqi values 0 to 7) and increment the array[sqi_value]
for every reading. And calculate the Average = ( 1 * array[1] + 2 *
array[2] ... + 7 * array[7])/LAN87XX_SQI_ENTRY. By this way we get the
average for 200 entries.
But I couldn't get the algorithm on how to discard the outliers from
the buckets. our main aim is to average from array[40] to arrary[160]
value. Can you bit elaborate on how to remove the outer histogram
buckets.

Arun


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC Patch net-next 3/3] net: phy: lan87xx: added ethtool SQI support
  2022-03-24 15:48     ` Arun.Ramadoss
@ 2022-03-24 16:06       ` Andrew Lunn
  0 siblings, 0 replies; 7+ messages in thread
From: Andrew Lunn @ 2022-03-24 16:06 UTC (permalink / raw)
  To: Arun.Ramadoss
  Cc: linux-kernel, UNGLinuxDriver, linux, kuba, pabeni, netdev, davem,
	hkallweit1

On Thu, Mar 24, 2022 at 03:48:57PM +0000, Arun.Ramadoss@microchip.com wrote:
> Hi Andrew,
> 
> Thanks for the review.
> 
> On Mon, 2022-03-21 at 19:36 +0100, Andrew Lunn wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you
> > know the content is safe
> > 
> > > +#define T1_DCQ_SQI_MSK                       GENMASK(3, 1)
> > > +static int lan87xx_get_sqi(struct phy_device *phydev)
> > > +{
> > > +     u16 sqi_value[LAN87XX_SQI_ENTRY];
> > > +     for (i = 0; i < LAN87XX_SQI_ENTRY; i++) {
> > > +
> > > +             sqi_value[i] = FIELD_GET(T1_DCQ_SQI_MSK, rc);
> > > +
> > > +     /* Sorting SQI values */
> > > +     sort(sqi_value, LAN87XX_SQI_ENTRY, sizeof(u16),
> > > lan87xx_sqi_cmp, NULL);
> > 
> > Sort is quite heavyweight. Your SQI values are in the range 0-7
> > right?
> > So rather than have an array of LAN87XX_SQI_ENTRY entries, why not
> > create a histogram? You then just need to keep 8 uints. There is no
> > need to perform a sort to discard the outliers, simply remove from
> > the
> > outer histogram buckets. And then you can calculate the average.
> > 
> > That should be faster and use less memory.
> > 
> >      Andrew
> 
> I could get the algorithm for replacing array of LAN87XX_SQI_ENTRY(200)
> to array of 8 (sqi values 0 to 7) and increment the array[sqi_value]
> for every reading. And calculate the Average = ( 1 * array[1] + 2 *
> array[2] ... + 7 * array[7])/LAN87XX_SQI_ENTRY. By this way we get the
> average for 200 entries.
> But I couldn't get the algorithm on how to discard the outliers from
> the buckets. our main aim is to average from array[40] to arrary[160]
> value. Can you bit elaborate on how to remove the outer histogram
> buckets.

So your raw results look something like

array[0] = 10
array[1] = 10
array[2] = 25
array[3] = 100
array[4] = 50
array[5] = 1
array[6] = 4
array[7] = 0

To discard the lower outliers, take 40 away from the array[0],
array[1], array[2], etc. To discard the upper outliers, take 40 away
from array[7], array[6], array[5], etc. So you should end up with:

array[0] = 0
array[1] = 0
array[2] = 5
array[3] = 100
array[4] = 15
array[5] = 0
array[6] = 0
array[7] = 0

and then calculate the average: (2*5 + 3*100 + 4*15) / 120 = 3.

    Andrew

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-03-24 16:06 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-21 15:53 [RFC Patch net-next 0/3] add ethtool SQI support for LAN87xx T1 Phy Arun Ramadoss
2022-03-21 15:53 ` [RFC Patch net-next 1/3] net: phy: lan87xx: added lan87xx_update_link routine Arun Ramadoss
2022-03-21 15:53 ` [RFC Patch net-next 2/3] net: phy: lan937x: added PHY_POLL_CABLE_TEST flag Arun Ramadoss
2022-03-21 15:53 ` [RFC Patch net-next 3/3] net: phy: lan87xx: added ethtool SQI support Arun Ramadoss
2022-03-21 18:36   ` Andrew Lunn
2022-03-24 15:48     ` Arun.Ramadoss
2022-03-24 16:06       ` Andrew Lunn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).