Commit 18ff0bcd authored by Oleksij Rempel's avatar Oleksij Rempel Committed by Jakub Kicinski
Browse files

ethtool: add interface to interact with Ethernet Power Equipment



Add interface to support Power Sourcing Equipment. At current step it
provides generic way to address all variants of PSE devices as defined
in IEEE 802.3-2018 but support only objects specified for IEEE 802.3-2018 104.4
PoDL Power Sourcing Equipment (PSE).

Currently supported and mandatory objects are:
IEEE 802.3-2018 30.15.1.1.3 aPoDLPSEPowerDetectionStatus
IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState
IEEE 802.3-2018 30.15.1.2.1 acPoDLPSEAdminControl

This is minimal interface needed to control PSE on each separate
ethernet port but it provides not all mandatory objects specified in
IEEE 802.3-2018.

Since "PoDL PSE" and "PSE" have similar names, but some different values
I decide to not merge them and keep separate naming schema. This should
allow as to be as close to IEEE 802.3 spec as possible and avoid name
conflicts in the future.

This implementation is connected to PHYs instead of MACs because PSE
auto classification can potentially interfere with PHY auto negotiation.
So, may be some extra PHY related initialization will be needed.

With WIP version of ethtools interaction with PSE capable link looks
as following:

$ ip l
...
5: t1l1@eth0: <BROADCAST,MULTICAST> ..
...

$ ethtool --show-pse t1l1
PSE attributs for t1l1:
PoDL PSE Admin State: disabled
PoDL PSE Power Detection Status: disabled

$ ethtool --set-pse t1l1 podl-pse-admin-control enable
$ ethtool --show-pse t1l1
PSE attributs for t1l1:
PoDL PSE Admin State: enabled
PoDL PSE Power Detection Status: delivering power

Signed-off-by: default avatarkernel test robot <lkp@intel.com>
Signed-off-by: default avatarOleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: default avatarBagas Sanjaya <bagasdotme@gmail.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 5e82147d
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -220,6 +220,8 @@ Userspace to kernel:
  ``ETHTOOL_MSG_PHC_VCLOCKS_GET``       get PHC virtual clocks info
  ``ETHTOOL_MSG_MODULE_SET``            set transceiver module parameters
  ``ETHTOOL_MSG_MODULE_GET``            get transceiver module parameters
  ``ETHTOOL_MSG_PSE_SET``               set PSE parameters
  ``ETHTOOL_MSG_PSE_GET``               get PSE parameters
  ===================================== =================================

Kernel to userspace:
@@ -260,6 +262,7 @@ Kernel to userspace:
  ``ETHTOOL_MSG_STATS_GET_REPLY``          standard statistics
  ``ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY``    PHC virtual clocks info
  ``ETHTOOL_MSG_MODULE_GET_REPLY``         transceiver module parameters
  ``ETHTOOL_MSG_PSE_GET_REPLY``            PSE parameters
  ======================================== =================================

``GET`` requests are sent by userspace applications to retrieve device
@@ -1627,6 +1630,62 @@ For SFF-8636 modules, low power mode is forced by the host according to table
For CMIS modules, low power mode is forced by the host according to table 6-12
in revision 5.0 of the specification.

PSE_GET
=======

Gets PSE attributes.

Request contents:

  =====================================  ======  ==========================
  ``ETHTOOL_A_PSE_HEADER``               nested  request header
  =====================================  ======  ==========================

Kernel response contents:

  ======================================  ======  =============================
  ``ETHTOOL_A_PSE_HEADER``                nested  reply header
  ``ETHTOOL_A_PODL_PSE_ADMIN_STATE``         u32  Operational state of the PoDL
                                                  PSE functions
  ``ETHTOOL_A_PODL_PSE_PW_D_STATUS``         u32  power detection status of the
                                                  PoDL PSE.
  ======================================  ======  =============================

When set, the optional ``ETHTOOL_A_PODL_PSE_ADMIN_STATE`` attribute identifies
the operational state of the PoDL PSE functions.  The operational state of the
PSE function can be changed using the ``ETHTOOL_A_PODL_PSE_ADMIN_CONTROL``
action. This option is corresponding to ``IEEE 802.3-2018`` 30.15.1.1.2
aPoDLPSEAdminState. Possible values are:

.. kernel-doc:: include/uapi/linux/ethtool.h
    :identifiers: ethtool_podl_pse_admin_state

When set, the optional ``ETHTOOL_A_PODL_PSE_PW_D_STATUS`` attribute identifies
the power detection status of the PoDL PSE.  The status depend on internal PSE
state machine and automatic PD classification support. This option is
corresponding to ``IEEE 802.3-2018`` 30.15.1.1.3 aPoDLPSEPowerDetectionStatus.
Possible values are:

.. kernel-doc:: include/uapi/linux/ethtool.h
    :identifiers: ethtool_podl_pse_pw_d_status

PSE_SET
=======

Sets PSE parameters.

Request contents:

  ======================================  ======  =============================
  ``ETHTOOL_A_PSE_HEADER``                nested  request header
  ``ETHTOOL_A_PODL_PSE_ADMIN_CONTROL``       u32  Control PoDL PSE Admin state
  ======================================  ======  =============================

When set, the optional ``ETHTOOL_A_PODL_PSE_ADMIN_CONTROL`` attribute is used
to control PoDL PSE Admin functions. This option is implementing
``IEEE 802.3-2018`` 30.15.1.2.1 acPoDLPSEAdminControl. See
``ETHTOOL_A_PODL_PSE_ADMIN_STATE`` for supported values.

Request translation
===================

+58 −0
Original line number Diff line number Diff line
@@ -254,3 +254,61 @@ of_pse_control_get(struct device_node *node)
	return psec;
}
EXPORT_SYMBOL_GPL(of_pse_control_get);

/**
 * pse_ethtool_get_status - get status of PSE control
 * @psec: PSE control pointer
 * @extack: extack for reporting useful error messages
 * @status: struct to store PSE status
 */
int pse_ethtool_get_status(struct pse_control *psec,
			   struct netlink_ext_ack *extack,
			   struct pse_control_status *status)
{
	const struct pse_controller_ops *ops;
	int err;

	ops = psec->pcdev->ops;

	if (!ops->ethtool_get_status) {
		NL_SET_ERR_MSG(extack,
			       "PSE driver does not support status report");
		return -EOPNOTSUPP;
	}

	mutex_lock(&psec->pcdev->lock);
	err = ops->ethtool_get_status(psec->pcdev, psec->id, extack, status);
	mutex_unlock(&psec->pcdev->lock);

	return err;
}
EXPORT_SYMBOL_GPL(pse_ethtool_get_status);

/**
 * pse_ethtool_set_config - set PSE control configuration
 * @psec: PSE control pointer
 * @extack: extack for reporting useful error messages
 * @config: Configuration of the test to run
 */
int pse_ethtool_set_config(struct pse_control *psec,
			   struct netlink_ext_ack *extack,
			   const struct pse_control_config *config)
{
	const struct pse_controller_ops *ops;
	int err;

	ops = psec->pcdev->ops;

	if (!ops->ethtool_set_config) {
		NL_SET_ERR_MSG(extack,
			       "PSE driver does not configuration");
		return -EOPNOTSUPP;
	}

	mutex_lock(&psec->pcdev->lock);
	err = ops->ethtool_set_config(psec->pcdev, psec->id, extack, config);
	mutex_unlock(&psec->pcdev->lock);

	return err;
}
EXPORT_SYMBOL_GPL(pse_ethtool_set_config);
+62 −0
Original line number Diff line number Diff line
@@ -9,6 +9,47 @@
#include <linux/list.h>
#include <uapi/linux/ethtool.h>

struct phy_device;
struct pse_controller_dev;

/**
 * struct pse_control_config - PSE control/channel configuration.
 *
 * @admin_cotrol: set PoDL PSE admin control as described in
 *	IEEE 802.3-2018 30.15.1.2.1 acPoDLPSEAdminControl
 */
struct pse_control_config {
	enum ethtool_podl_pse_admin_state admin_cotrol;
};

/**
 * struct pse_control_status - PSE control/channel status.
 *
 * @podl_admin_state: operational state of the PoDL PSE
 *	functions. IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState
 * @podl_pw_status: power detection status of the PoDL PSE.
 *	IEEE 802.3-2018 30.15.1.1.3 aPoDLPSEPowerDetectionStatus:
 */
struct pse_control_status {
	enum ethtool_podl_pse_admin_state podl_admin_state;
	enum ethtool_podl_pse_pw_d_status podl_pw_status;
};

/**
 * struct pse_controller_ops - PSE controller driver callbacks
 *
 * @ethtool_get_status: get PSE control status for ethtool interface
 * @ethtool_set_config: set PSE control configuration over ethtool interface
 */
struct pse_controller_ops {
	int (*ethtool_get_status)(struct pse_controller_dev *pcdev,
		unsigned long id, struct netlink_ext_ack *extack,
		struct pse_control_status *status);
	int (*ethtool_set_config)(struct pse_controller_dev *pcdev,
		unsigned long id, struct netlink_ext_ack *extack,
		const struct pse_control_config *config);
};

struct module;
struct device_node;
struct of_phandle_args;
@@ -51,6 +92,13 @@ int devm_pse_controller_register(struct device *dev,
struct pse_control *of_pse_control_get(struct device_node *node);
void pse_control_put(struct pse_control *psec);

int pse_ethtool_get_status(struct pse_control *psec,
			   struct netlink_ext_ack *extack,
			   struct pse_control_status *status);
int pse_ethtool_set_config(struct pse_control *psec,
			   struct netlink_ext_ack *extack,
			   const struct pse_control_config *config);

#else

static inline struct pse_control *of_pse_control_get(struct device_node *node)
@@ -62,6 +110,20 @@ static inline void pse_control_put(struct pse_control *psec)
{
}

int pse_ethtool_get_status(struct pse_control *psec,
			   struct netlink_ext_ack *extack,
			   struct pse_control_status *status)
{
	return -ENOTSUPP;
}

int pse_ethtool_set_config(struct pse_control *psec,
			   struct netlink_ext_ack *extack,
			   const struct pse_control_config *config)
{
	return -ENOTSUPP;
}

#endif

#endif
+45 −0
Original line number Diff line number Diff line
@@ -736,6 +736,51 @@ enum ethtool_module_power_mode {
	ETHTOOL_MODULE_POWER_MODE_HIGH,
};

/**
 * enum ethtool_podl_pse_admin_state - operational state of the PoDL PSE
 *	functions. IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState
 * @ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN: state of PoDL PSE functions are
 * 	unknown
 * @ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED: PoDL PSE functions are disabled
 * @ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED: PoDL PSE functions are enabled
 */
enum ethtool_podl_pse_admin_state {
	ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN = 1,
	ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED,
	ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED,
};

/**
 * enum ethtool_podl_pse_pw_d_status - power detection status of the PoDL PSE.
 *	IEEE 802.3-2018 30.15.1.1.3 aPoDLPSEPowerDetectionStatus:
 * @ETHTOOL_PODL_PSE_PW_D_STATUS_UNKNOWN: PoDL PSE
 * @ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED: "The enumeration “disabled” is
 *	asserted true when the PoDL PSE state diagram variable mr_pse_enable is
 *	false"
 * @ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING: "The enumeration “searching” is
 *	asserted true when either of the PSE state diagram variables
 *	pi_detecting or pi_classifying is true."
 * @ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING: "The enumeration “deliveringPower”
 *	is asserted true when the PoDL PSE state diagram variable pi_powered is
 *	true."
 * @ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP: "The enumeration “sleep” is asserted
 *	true when the PoDL PSE state diagram variable pi_sleeping is true."
 * @ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE: "The enumeration “idle” is asserted true
 *	when the logical combination of the PoDL PSE state diagram variables
 *	pi_prebiased*!pi_sleeping is true."
 * @ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR: "The enumeration “error” is asserted
 *	true when the PoDL PSE state diagram variable overload_held is true."
 */
enum ethtool_podl_pse_pw_d_status {
	ETHTOOL_PODL_PSE_PW_D_STATUS_UNKNOWN = 1,
	ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED,
	ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING,
	ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING,
	ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP,
	ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE,
	ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR,
};

/**
 * struct ethtool_gstrings - string set for data tagging
 * @cmd: Command number = %ETHTOOL_GSTRINGS
+16 −0
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ enum {
	ETHTOOL_MSG_PHC_VCLOCKS_GET,
	ETHTOOL_MSG_MODULE_GET,
	ETHTOOL_MSG_MODULE_SET,
	ETHTOOL_MSG_PSE_GET,
	ETHTOOL_MSG_PSE_SET,

	/* add new constants above here */
	__ETHTOOL_MSG_USER_CNT,
@@ -94,6 +96,7 @@ enum {
	ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY,
	ETHTOOL_MSG_MODULE_GET_REPLY,
	ETHTOOL_MSG_MODULE_NTF,
	ETHTOOL_MSG_PSE_GET_REPLY,

	/* add new constants above here */
	__ETHTOOL_MSG_KERNEL_CNT,
@@ -863,6 +866,19 @@ enum {
	ETHTOOL_A_MODULE_MAX = (__ETHTOOL_A_MODULE_CNT - 1)
};

/* Power Sourcing Equipment */
enum {
	ETHTOOL_A_PSE_UNSPEC,
	ETHTOOL_A_PSE_HEADER,			/* nest - _A_HEADER_* */
	ETHTOOL_A_PODL_PSE_ADMIN_STATE,		/* u32 */
	ETHTOOL_A_PODL_PSE_ADMIN_CONTROL,	/* u32 */
	ETHTOOL_A_PODL_PSE_PW_D_STATUS,		/* u32 */

	/* add new constants above here */
	__ETHTOOL_A_PSE_CNT,
	ETHTOOL_A_PSE_MAX = (__ETHTOOL_A_PSE_CNT - 1)
};

/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
#define ETHTOOL_GENL_VERSION 1
Loading