diff mbox

[ethtool,2/2] Ethtool: Implements PHY Loopback

Message ID 1480339512-5882-3-git-send-email-allan.nielsen@microsemi.com
State Changes Requested, archived
Delegated to: John Linville
Headers show

Commit Message

Allan W. Nielsen Nov. 28, 2016, 1:25 p.m. UTC
From: Raju Lakkaraju <Raju.Lakkaraju@microsemi.com>

Add loopback in ethtool tunables to access PHY drivers.

Ethtool Help: ethtool -h for PHY tunables
    ethtool --set-phy-tunable DEVNAME      Set PHY tunable
                [ loopback off|near|far|extn ]
    ethtool --get-phy-tunable DEVNAME      Get PHY tunable
                [ loopback ]

Ethtool ex:
  ethtool --set-phy-tunable eth0 loopback near
  ethtool --set-phy-tunable eth0 loopback far
  ethtool --set-phy-tunable eth0 loopback extn
  ethtool --set-phy-tunable eth0 loopback off

  ethtool --get-phy-tunable eth0 loopback

Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microsemi.com>
Signed-off-by: Allan W. Nielsen <allan.nielsen@microsemi.com>
---
 ethtool.8.in |  49 +++++++++++++++++++++
 ethtool.c    | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 188 insertions(+)

Comments

Florian Fainelli Nov. 28, 2016, 5:56 p.m. UTC | #1
On 11/28/2016 05:25 AM, Allan W. Nielsen wrote:
> From: Raju Lakkaraju <Raju.Lakkaraju@microsemi.com>
> 
> Add loopback in ethtool tunables to access PHY drivers.
> 
> Ethtool Help: ethtool -h for PHY tunables
>     ethtool --set-phy-tunable DEVNAME      Set PHY tunable
>                 [ loopback off|near|far|extn ]
>     ethtool --get-phy-tunable DEVNAME      Get PHY tunable
>                 [ loopback ]
> 
> Ethtool ex:
>   ethtool --set-phy-tunable eth0 loopback near
>   ethtool --set-phy-tunable eth0 loopback far
>   ethtool --set-phy-tunable eth0 loopback extn
>   ethtool --set-phy-tunable eth0 loopback off
> 
>   ethtool --get-phy-tunable eth0 loopback
> 
> Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microsemi.com>
> Signed-off-by: Allan W. Nielsen <allan.nielsen@microsemi.com>
> ---

> +Near-End Loopback:
> +Transmitted data (TXD) is looped back in the PCS block onto the receive data
> +signal (RXD). When Near-End loopback enable, no data is transmitted over
> +the network. no data receive from the network.

This is also known as the local loopback test mode, right?

> +
> +Far-End Loopback:
> +This loopback is a special test mode to allow testing the PHY from link
> +partner side. In this mode data that is received from the link partner pass
> +through the PHY's receiver, looped back on the MII and transmitted back to
> +the link partner.

And this is the remote loopback mode.


> +
> +External Loopback:
> +An RJ45 loopback cable can be used to route the transmit signals an the
> +output of the trnsformer back to the receiver inputs and this loopback will
> +work at either 10 or 100 or 1000 Mbps speed.
> +RJ45 Loopback cable created by conncting pin 1 to pin 3 and connecting pin
> +2 to pin 6.

OK, this name makes sense to me, but for the two other names, we need to
use a terminology that is clearer to the reader and/or people familiar
and targeted at using this feature (e.g: in a lab or during manufacturing).
Allan W. Nielsen Nov. 28, 2016, 7:34 p.m. UTC | #2
On 28/11/16 09:56, Florian Fainelli wrote:
> On 11/28/2016 05:25 AM, Allan W. Nielsen wrote:
> > From: Raju Lakkaraju <Raju.Lakkaraju@microsemi.com>
> >
> > Add loopback in ethtool tunables to access PHY drivers.
> >
> > Ethtool Help: ethtool -h for PHY tunables
> >     ethtool --set-phy-tunable DEVNAME      Set PHY tunable
> >                 [ loopback off|near|far|extn ]
> >     ethtool --get-phy-tunable DEVNAME      Get PHY tunable
> >                 [ loopback ]
> >
> > Ethtool ex:
> >   ethtool --set-phy-tunable eth0 loopback near
> >   ethtool --set-phy-tunable eth0 loopback far
> >   ethtool --set-phy-tunable eth0 loopback extn
> >   ethtool --set-phy-tunable eth0 loopback off
> >
> >   ethtool --get-phy-tunable eth0 loopback
> >
> > Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microsemi.com>
> > Signed-off-by: Allan W. Nielsen <allan.nielsen@microsemi.com>
> > ---
> 
> > +Near-End Loopback:
> > +Transmitted data (TXD) is looped back in the PCS block onto the receive data
> > +signal (RXD). When Near-End loopback enable, no data is transmitted over
> > +the network. no data receive from the network.
> 
> This is also known as the local loopback test mode, right?
Yes - Traffic transmitted/generated by the host list loopback to the
host instead of transmitting it on the wire.

> > +
> > +Far-End Loopback:
> > +This loopback is a special test mode to allow testing the PHY from link
> > +partner side. In this mode data that is received from the link partner pass
> > +through the PHY's receiver, looped back on the MII and transmitted back to
> > +the link partner.
> 
> And this is the remote loopback mode.
Yes - Traffic receiwed on the "wire" is transmitted back on the wire.

> > +
> > +External Loopback:
> > +An RJ45 loopback cable can be used to route the transmit signals an the
> > +output of the trnsformer back to the receiver inputs and this loopback will
> > +work at either 10 or 100 or 1000 Mbps speed.
> > +RJ45 Loopback cable created by conncting pin 1 to pin 3 and connecting pin
> > +2 to pin 6.
> 
> OK, this name makes sense to me, but for the two other names, we need to
> use a terminology that is clearer to the reader and/or people familiar
> and targeted at using this feature (e.g: in a lab or during manufacturing).
Sure, we can find better names and/or improve the documentation. But
before jumping to that, then it is properly a good idea to agree on
the overall concept.

We will get back to the naming when we agree on the other parts.

/Allan
diff mbox

Patch

diff --git a/ethtool.8.in b/ethtool.8.in
index 9631847..83e6b97 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -340,6 +340,15 @@  ethtool \- query or control network driver and hardware settings
 .B2 tx-lpi on off
 .BN tx-timer
 .BN advertise
+.HP
+.B ethtool \-\-set\-phy\-tunable
+.I devname
+.B4 loopback off near far extn
+.HP
+.B ethtool \-\-get\-phy\-tunable
+.I devname
+.RB [ loopback ]
+.HP
 .
 .\" Adjust lines (i.e. full justification) and hyphenate.
 .ad
@@ -947,6 +956,46 @@  Values are as for
 Sets the amount of time the device should stay in idle mode prior to asserting
 its Tx LPI (in microseconds). This has meaning only when Tx LPI is enabled.
 .RE
+.TP
+.B \-\-set\-phy\-tunable
+Sets the PHY tunable parameters.
+.RS 4
+.TP
+.A4 loopback off near far extn
+Specifies whether the type of loopback should be enabled
+.RE
+.TP
+.B \-\-get\-phy\-tunable
+Gets the PHY tunable parameters.
+.RS 4
+.TP
+.B loopback
+PHY supports 3 types of the Loopbacks. i.e near, far and external.
+
+Near-End Loopback:
+Transmitted data (TXD) is looped back in the PCS block onto the receive data
+signal (RXD). When Near-End loopback enable, no data is transmitted over
+the network. no data receive from the network.
+
+Far-End Loopback:
+This loopback is a special test mode to allow testing the PHY from link
+partner side. In this mode data that is received from the link partner pass
+through the PHY's receiver, looped back on the MII and transmitted back to
+the link partner.
+
+External Loopback:
+An RJ45 loopback cable can be used to route the transmit signals an the
+output of the trnsformer back to the receiver inputs and this loopback will
+work at either 10 or 100 or 1000 Mbps speed.
+RJ45 Loopback cable created by conncting pin 1 to pin 3 and connecting pin
+2 to pin 6.
+
+Gets the PHY Loopback status.
+.TS
+.PD
+.RE
+.TE
+.RE
 .SH BUGS
 Not supported (in part or whole) on all network drivers.
 .SH AUTHOR
diff --git a/ethtool.c b/ethtool.c
index 62f86ef..a4e6c0d 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -4522,6 +4522,141 @@  static int do_seee(struct cmd_context *ctx)
 	return 0;
 }
 
+static int do_get_phy_tunable(struct cmd_context *ctx)
+{
+	int argc = ctx->argc;
+	char **argp = ctx->argp;
+	int err = 0, i;
+	u8 lpbk_changed = 0;
+	struct ethtool_tunable tunable;
+
+	if (argc < 1)
+		exit_bad_args();
+	for (i = 0; i < argc; i++) {
+		if (!strcmp(argp[i], "loopback")) {
+			lpbk_changed = 1;
+			i += 1;
+			if (i < argc)
+				exit_bad_args();
+		} else  {
+			exit_bad_args();
+		}
+	}
+
+	if (lpbk_changed) {
+		u8 type;
+
+		tunable.cmd = ETHTOOL_PHY_GTUNABLE;
+		tunable.id = ETHTOOL_PHY_LOOPBACK;
+		tunable.type_id = ETHTOOL_TUNABLE_U8;
+		tunable.len = 1;
+		tunable.data[0] = &type;
+		err = send_ioctl(ctx, &tunable);
+		if (err < 0) {
+			perror("Cannot Get PHY Loopback status");
+			return 87;
+		}
+		type = *((u8 *)&tunable.data[0]);
+		switch (type) {
+		case ETHTOOL_PHY_LOOPBACK_NEAR:
+			fprintf(stdout, "Near-end Loopback enabled\n");
+			break;
+		case ETHTOOL_PHY_LOOPBACK_FAR:
+			fprintf(stdout, "Far-end Loopback enabled\n");
+			break;
+		case ETHTOOL_PHY_LOOPBACK_EXTN:
+			fprintf(stdout, "External Loopback enabled\n");
+			break;
+		case ETHTOOL_PHY_LOOPBACK_DISABLE:
+			fprintf(stdout, "All PHY Loopbacks disabled\n");
+			break;
+		default:
+			fprintf(stdout, "Invalid Loopback type\n");
+			break;
+		}
+	}
+
+	return err;
+}
+
+static int parse_named_flag(struct cmd_context *ctx, const char *name,
+			    const struct flag_info *flags, size_t size,
+			    u8 *type)
+{
+	size_t idx;
+	int found = 0;
+
+	if (ctx->argc < 2)
+		return 0;
+
+	if (strcmp(*ctx->argp, name))
+		return 0;
+	ctx->argc -= 1;
+	ctx->argp += 1;
+
+	for (idx = 0; idx < size; idx++) {
+		if (!strcmp(flags[idx].name, *ctx->argp)) {
+			*type = flags[idx].value;
+			ctx->argc -= 1;
+			ctx->argp += 1;
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found)
+		exit_bad_args();
+
+	return 1;
+}
+
+static const struct flag_info lpbk_flags[] = {
+	{ "off", ETHTOOL_PHY_LOOPBACK_DISABLE },
+	{ "near", ETHTOOL_PHY_LOOPBACK_NEAR },
+	{ "far",  ETHTOOL_PHY_LOOPBACK_FAR },
+	{ "extn",  ETHTOOL_PHY_LOOPBACK_EXTN },
+};
+
+static int do_set_phy_tunable(struct cmd_context *ctx)
+{
+	int err = 0;
+	u8 lpbk_changed = 0, lpbk_type = ETHTOOL_PHY_LOOPBACK_DISABLE;
+	struct ethtool_tunable tunable;
+
+	if (ctx->argc == 0)
+		exit_bad_args();
+
+	/* Parse arguments */
+	while (ctx->argc) {
+		if (parse_named_flag(ctx, "loopback", lpbk_flags,
+					    ARRAY_SIZE(lpbk_flags),
+					    &lpbk_type)) {
+			lpbk_changed = 1;
+		} else {
+			exit_bad_args();
+		}
+	}
+
+	/* Do it */
+	if (lpbk_changed) {
+		u8 type;
+
+		tunable.cmd = ETHTOOL_PHY_STUNABLE;
+		tunable.id = ETHTOOL_PHY_LOOPBACK;
+		tunable.type_id = ETHTOOL_TUNABLE_U8;
+		tunable.len = sizeof(type);
+		tunable.data[0] = &type;
+		*((u8 *)&tunable.data[0]) = lpbk_type;
+		err = send_ioctl(ctx, &tunable);
+		if (err < 0) {
+			perror("Cannot Set PHY Loopback");
+			err = 87;
+		}
+	}
+
+	return err;
+}
+
 #ifndef TEST_ETHTOOL
 int send_ioctl(struct cmd_context *ctx, void *cmd)
 {
@@ -4683,6 +4818,10 @@  static const struct option {
 	  "		[ advertise %x ]\n"
 	  "		[ tx-lpi on|off ]\n"
 	  "		[ tx-timer %d ]\n"},
+	{ "--set-phy-tunable", 1, do_set_phy_tunable, "Set PHY tunable",
+	  "		[ loopback off|near|far|extn ]\n"},
+	{ "--get-phy-tunable", 1, do_get_phy_tunable, "Get PHY tunable",
+	  "		[ loopback ]\n"},
 	{ "-h|--help", 0, show_usage, "Show this help" },
 	{ "--version", 0, do_version, "Show version number" },
 	{}