Commit 9c7ad356 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'arrange-pse-core-and-update-tps23881-driver'

Kory Maincent says:

====================
Arrange PSE core and update TPS23881 driver

This patch includes several improvements to the PSE core for better
implementation and maintainability:

- Move the conversion between current limit and power limit from the driver
  to the PSE core.
- Update power and current limit checks.
- Split the ethtool_get_status callback into multiple callbacks.
- Fix PSE PI of_node detection.
- Clean ethtool header of PSE structures.

Additionally, the TPS23881 driver has been updated to support power
limit and measurement features, aligning with the new PSE core
functionalities.

This patch series is the first part of the budget evaluation strategy
support patch series sent earlier:
https://lore.kernel.org/netdev/20250104161622.7b82dfdf@kmaincent-XPS-13-7390/T/#t



Signed-off-by: default avatarKory Maincent <kory.maincent@bootlin.com>
====================

Link: https://patch.msgid.link/20250110-b4-feature_poe_arrange-v3-0-142279aedb94@bootlin.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 2b1d9116 5385f1e1
Loading
Loading
Loading
Loading
+119 −105
Original line number Diff line number Diff line
@@ -431,31 +431,6 @@ static int pd692x0_pi_disable(struct pse_controller_dev *pcdev, int id)
	return 0;
}

static int pd692x0_pi_is_enabled(struct pse_controller_dev *pcdev, int id)
{
	struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
	struct pd692x0_msg msg, buf = {0};
	int ret;

	ret = pd692x0_fw_unavailable(priv);
	if (ret)
		return ret;

	msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS];
	msg.sub[2] = id;
	ret = pd692x0_sendrecv_msg(priv, &msg, &buf);
	if (ret < 0)
		return ret;

	if (buf.sub[1]) {
		priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED;
		return 1;
	} else {
		priv->admin_state[id] = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED;
		return 0;
	}
}

struct pd692x0_pse_ext_state_mapping {
	u32 status_code;
	enum ethtool_c33_pse_ext_state pse_ext_state;
@@ -517,21 +492,38 @@ pd692x0_pse_ext_state_map[] = {
	{ /* sentinel */ }
};

static void
pd692x0_get_ext_state(struct ethtool_c33_pse_ext_state_info *c33_ext_state_info,
		      u32 status_code)
static int
pd692x0_pi_get_ext_state(struct pse_controller_dev *pcdev, int id,
			 struct pse_ext_state_info *ext_state_info)
{
	struct ethtool_c33_pse_ext_state_info *c33_ext_state_info;
	const struct pd692x0_pse_ext_state_mapping *ext_state_map;
	struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
	struct pd692x0_msg msg, buf = {0};
	int ret;

	ret = pd692x0_fw_unavailable(priv);
	if (ret)
		return ret;

	msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS];
	msg.sub[2] = id;
	ret = pd692x0_sendrecv_msg(priv, &msg, &buf);
	if (ret < 0)
		return ret;

	c33_ext_state_info = &ext_state_info->c33_ext_state_info;
	ext_state_map = pd692x0_pse_ext_state_map;
	while (ext_state_map->status_code) {
		if (ext_state_map->status_code == status_code) {
		if (ext_state_map->status_code == buf.sub[0]) {
			c33_ext_state_info->c33_pse_ext_state = ext_state_map->pse_ext_state;
			c33_ext_state_info->__c33_pse_ext_substate = ext_state_map->pse_ext_substate;
			return;
			return  0;
		}
		ext_state_map++;
	}

	return 0;
}

struct pd692x0_class_pw {
@@ -613,35 +605,36 @@ static int pd692x0_pi_set_pw_from_table(struct device *dev,
}

static int
pd692x0_pi_get_pw_ranges(struct pse_control_status *st)
pd692x0_pi_get_pw_limit_ranges(struct pse_controller_dev *pcdev, int id,
			       struct pse_pw_limit_ranges *pw_limit_ranges)
{
	struct ethtool_c33_pse_pw_limit_range *c33_pw_limit_ranges;
	const struct pd692x0_class_pw *pw_table;
	int i;

	pw_table = pd692x0_class_pw_table;
	st->c33_pw_limit_ranges = kcalloc(PD692X0_CLASS_PW_TABLE_SIZE,
					  sizeof(struct ethtool_c33_pse_pw_limit_range),
	c33_pw_limit_ranges = kcalloc(PD692X0_CLASS_PW_TABLE_SIZE,
				      sizeof(*c33_pw_limit_ranges),
				      GFP_KERNEL);
	if (!st->c33_pw_limit_ranges)
	if (!c33_pw_limit_ranges)
		return -ENOMEM;

	for (i = 0; i < PD692X0_CLASS_PW_TABLE_SIZE; i++, pw_table++) {
		st->c33_pw_limit_ranges[i].min = pw_table->class_pw;
		st->c33_pw_limit_ranges[i].max = pw_table->class_pw + pw_table->max_added_class_pw;
		c33_pw_limit_ranges[i].min = pw_table->class_pw;
		c33_pw_limit_ranges[i].max = pw_table->class_pw +
					     pw_table->max_added_class_pw;
	}

	st->c33_pw_limit_nb_ranges = i;
	return 0;
	pw_limit_ranges->c33_pw_limit_ranges = c33_pw_limit_ranges;
	return i;
}

static int pd692x0_ethtool_get_status(struct pse_controller_dev *pcdev,
				      unsigned long id,
				      struct netlink_ext_ack *extack,
				      struct pse_control_status *status)
static int
pd692x0_pi_get_admin_state(struct pse_controller_dev *pcdev, int id,
			   struct pse_admin_state *admin_state)
{
	struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
	struct pd692x0_msg msg, buf = {0};
	u32 class;
	int ret;

	ret = pd692x0_fw_unavailable(priv);
@@ -654,39 +647,65 @@ static int pd692x0_ethtool_get_status(struct pse_controller_dev *pcdev,
	if (ret < 0)
		return ret;

	/* Compare Port Status (Communication Protocol Document par. 7.1) */
	if ((buf.sub[0] & 0xf0) == 0x80 || (buf.sub[0] & 0xf0) == 0x90)
		status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING;
	else if (buf.sub[0] == 0x1b || buf.sub[0] == 0x22)
		status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_SEARCHING;
	else if (buf.sub[0] == 0x12)
		status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_FAULT;
	else
		status->c33_pw_status = ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED;

	if (buf.sub[1])
		status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED;
		admin_state->c33_admin_state =
			ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED;
	else
		status->c33_admin_state = ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED;
		admin_state->c33_admin_state =
			ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED;

	priv->admin_state[id] = status->c33_admin_state;
	priv->admin_state[id] = admin_state->c33_admin_state;

	pd692x0_get_ext_state(&status->c33_ext_state_info, buf.sub[0]);
	status->c33_actual_pw = (buf.data[0] << 4 | buf.data[1]) * 100;
	return 0;
}

	msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_PARAM];
static int
pd692x0_pi_get_pw_status(struct pse_controller_dev *pcdev, int id,
			 struct pse_pw_status *pw_status)
{
	struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
	struct pd692x0_msg msg, buf = {0};
	int ret;

	ret = pd692x0_fw_unavailable(priv);
	if (ret)
		return ret;

	msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS];
	msg.sub[2] = id;
	memset(&buf, 0, sizeof(buf));
	ret = pd692x0_sendrecv_msg(priv, &msg, &buf);
	if (ret < 0)
		return ret;

	ret = pd692x0_pi_get_pw_from_table(buf.data[0], buf.data[1]);
	if (ret < 0)
	/* Compare Port Status (Communication Protocol Document par. 7.1) */
	if ((buf.sub[0] & 0xf0) == 0x80 || (buf.sub[0] & 0xf0) == 0x90)
		pw_status->c33_pw_status =
			ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING;
	else if (buf.sub[0] == 0x1b || buf.sub[0] == 0x22)
		pw_status->c33_pw_status =
			ETHTOOL_C33_PSE_PW_D_STATUS_SEARCHING;
	else if (buf.sub[0] == 0x12)
		pw_status->c33_pw_status =
			ETHTOOL_C33_PSE_PW_D_STATUS_FAULT;
	else
		pw_status->c33_pw_status =
			ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED;

	return 0;
}

static int
pd692x0_pi_get_pw_class(struct pse_controller_dev *pcdev, int id)
{
	struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
	struct pd692x0_msg msg, buf = {0};
	u32 class;
	int ret;

	ret = pd692x0_fw_unavailable(priv);
	if (ret)
		return ret;
	status->c33_avail_pw_limit = ret;

	memset(&buf, 0, sizeof(buf));
	msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_CLASS];
	msg.sub[2] = id;
	ret = pd692x0_sendrecv_msg(priv, &msg, &buf);
@@ -695,13 +714,29 @@ static int pd692x0_ethtool_get_status(struct pse_controller_dev *pcdev,

	class = buf.data[3] >> 4;
	if (class <= 8)
		status->c33_pw_class = class;
		return class;

	ret = pd692x0_pi_get_pw_ranges(status);
	return 0;
}

static int
pd692x0_pi_get_actual_pw(struct pse_controller_dev *pcdev, int id)
{
	struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
	struct pd692x0_msg msg, buf = {0};
	int ret;

	ret = pd692x0_fw_unavailable(priv);
	if (ret)
		return ret;

	msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_STATUS];
	msg.sub[2] = id;
	ret = pd692x0_sendrecv_msg(priv, &msg, &buf);
	if (ret < 0)
		return ret;

	return 0;
	return (buf.data[0] << 4 | buf.data[1]) * 100;
}

static struct pd692x0_msg_ver pd692x0_get_sw_version(struct pd692x0_priv *priv)
@@ -999,13 +1034,12 @@ static int pd692x0_pi_get_voltage(struct pse_controller_dev *pcdev, int id)
	return (buf.sub[0] << 8 | buf.sub[1]) * 100000;
}

static int pd692x0_pi_get_current_limit(struct pse_controller_dev *pcdev,
static int pd692x0_pi_get_pw_limit(struct pse_controller_dev *pcdev,
				   int id)
{
	struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
	struct pd692x0_msg msg, buf = {0};
	int mW, uV, uA, ret;
	s64 tmp_64;
	int ret;

	msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_PARAM];
	msg.sub[2] = id;
@@ -1013,48 +1047,24 @@ static int pd692x0_pi_get_current_limit(struct pse_controller_dev *pcdev,
	if (ret < 0)
		return ret;

	ret = pd692x0_pi_get_pw_from_table(buf.data[2], buf.data[3]);
	if (ret < 0)
		return ret;
	mW = ret;

	ret = pd692x0_pi_get_voltage(pcdev, id);
	if (ret < 0)
		return ret;
	uV = ret;

	tmp_64 = mW;
	tmp_64 *= 1000000000ull;
	/* uA = mW * 1000000000 / uV */
	uA = DIV_ROUND_CLOSEST_ULL(tmp_64, uV);
	return uA;
	return pd692x0_pi_get_pw_from_table(buf.data[2], buf.data[3]);
}

static int pd692x0_pi_set_current_limit(struct pse_controller_dev *pcdev,
					int id, int max_uA)
static int pd692x0_pi_set_pw_limit(struct pse_controller_dev *pcdev,
				   int id, int max_mW)
{
	struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
	struct device *dev = &priv->client->dev;
	struct pd692x0_msg msg, buf = {0};
	int uV, ret, mW;
	s64 tmp_64;
	int ret;

	ret = pd692x0_fw_unavailable(priv);
	if (ret)
		return ret;

	ret = pd692x0_pi_get_voltage(pcdev, id);
	if (ret < 0)
		return ret;
	uV = ret;

	msg = pd692x0_msg_template_list[PD692X0_MSG_SET_PORT_PARAM];
	msg.sub[2] = id;
	tmp_64 = uV;
	tmp_64 *= max_uA;
	/* mW = uV * uA / 1000000000 */
	mW = DIV_ROUND_CLOSEST_ULL(tmp_64, 1000000000);
	ret = pd692x0_pi_set_pw_from_table(dev, &msg, mW);
	ret = pd692x0_pi_set_pw_from_table(dev, &msg, max_mW);
	if (ret)
		return ret;

@@ -1063,13 +1073,17 @@ static int pd692x0_pi_set_current_limit(struct pse_controller_dev *pcdev,

static const struct pse_controller_ops pd692x0_ops = {
	.setup_pi_matrix = pd692x0_setup_pi_matrix,
	.ethtool_get_status = pd692x0_ethtool_get_status,
	.pi_get_admin_state = pd692x0_pi_get_admin_state,
	.pi_get_pw_status = pd692x0_pi_get_pw_status,
	.pi_get_ext_state = pd692x0_pi_get_ext_state,
	.pi_get_pw_class = pd692x0_pi_get_pw_class,
	.pi_get_actual_pw = pd692x0_pi_get_actual_pw,
	.pi_enable = pd692x0_pi_enable,
	.pi_disable = pd692x0_pi_disable,
	.pi_is_enabled = pd692x0_pi_is_enabled,
	.pi_get_voltage = pd692x0_pi_get_voltage,
	.pi_get_current_limit = pd692x0_pi_get_current_limit,
	.pi_set_current_limit = pd692x0_pi_set_current_limit,
	.pi_get_pw_limit = pd692x0_pi_get_pw_limit,
	.pi_set_pw_limit = pd692x0_pi_set_pw_limit,
	.pi_get_pw_limit_ranges = pd692x0_pi_get_pw_limit_ranges,
};

#define PD692X0_FW_LINE_MAX_SZ 0xff
+126 −57
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
//

#include <linux/device.h>
#include <linux/ethtool.h>
#include <linux/of.h>
#include <linux/pse-pd/pse.h>
#include <linux/regulator/driver.h>
@@ -210,16 +211,25 @@ static int of_load_pse_pis(struct pse_controller_dev *pcdev)
static int pse_pi_is_enabled(struct regulator_dev *rdev)
{
	struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
	struct pse_admin_state admin_state = {0};
	const struct pse_controller_ops *ops;
	int id, ret;

	ops = pcdev->ops;
	if (!ops->pi_is_enabled)
	if (!ops->pi_get_admin_state)
		return -EOPNOTSUPP;

	id = rdev_get_id(rdev);
	mutex_lock(&pcdev->lock);
	ret = ops->pi_is_enabled(pcdev, id);
	ret = ops->pi_get_admin_state(pcdev, id, &admin_state);
	if (ret)
		goto out;

	if (admin_state.podl_admin_state == ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED ||
	    admin_state.c33_admin_state == ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED)
		ret = 1;

out:
	mutex_unlock(&pcdev->lock);

	return ret;
@@ -291,33 +301,25 @@ static int pse_pi_get_voltage(struct regulator_dev *rdev)
	return ret;
}

static int _pse_ethtool_get_status(struct pse_controller_dev *pcdev,
				   int id,
				   struct netlink_ext_ack *extack,
				   struct pse_control_status *status);

static int pse_pi_get_current_limit(struct regulator_dev *rdev)
{
	struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
	const struct pse_controller_ops *ops;
	struct netlink_ext_ack extack = {};
	struct pse_control_status st = {};
	int id, uV, ret;
	int id, uV, mW, ret;
	s64 tmp_64;

	ops = pcdev->ops;
	id = rdev_get_id(rdev);
	if (!ops->pi_get_pw_limit || !ops->pi_get_voltage)
		return -EOPNOTSUPP;

	mutex_lock(&pcdev->lock);
	if (ops->pi_get_current_limit) {
		ret = ops->pi_get_current_limit(pcdev, id);
	ret = ops->pi_get_pw_limit(pcdev, id);
	if (ret < 0)
		goto out;
	}
	mW = ret;

	/* If pi_get_current_limit() callback not populated get voltage
	 * from pi_get_voltage() and power limit from ethtool_get_status()
	 *  to calculate current limit.
	 */
	ret = _pse_pi_get_voltage(rdev);
	ret = pse_pi_get_voltage(rdev);
	if (!ret) {
		dev_err(pcdev->dev, "Voltage null\n");
		ret = -ERANGE;
@@ -327,16 +329,7 @@ static int pse_pi_get_current_limit(struct regulator_dev *rdev)
		goto out;
	uV = ret;

	ret = _pse_ethtool_get_status(pcdev, id, &extack, &st);
	if (ret)
		goto out;

	if (!st.c33_avail_pw_limit) {
		ret = -ENODATA;
		goto out;
	}

	tmp_64 = st.c33_avail_pw_limit;
	tmp_64 = mW;
	tmp_64 *= 1000000000ull;
	/* uA = mW * 1000000000 / uV */
	ret = DIV_ROUND_CLOSEST_ULL(tmp_64, uV);
@@ -351,15 +344,33 @@ static int pse_pi_set_current_limit(struct regulator_dev *rdev, int min_uA,
{
	struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
	const struct pse_controller_ops *ops;
	int id, ret;
	int id, mW, ret;
	s64 tmp_64;

	ops = pcdev->ops;
	if (!ops->pi_set_current_limit)
	if (!ops->pi_set_pw_limit || !ops->pi_get_voltage)
		return -EOPNOTSUPP;

	if (max_uA > MAX_PI_CURRENT)
		return -ERANGE;

	id = rdev_get_id(rdev);
	mutex_lock(&pcdev->lock);
	ret = ops->pi_set_current_limit(pcdev, id, max_uA);
	ret = pse_pi_get_voltage(rdev);
	if (!ret) {
		dev_err(pcdev->dev, "Voltage null\n");
		ret = -ERANGE;
		goto out;
	}
	if (ret < 0)
		goto out;

	tmp_64 = ret;
	tmp_64 *= max_uA;
	/* mW = uA * uV / 1000000000 */
	mW = DIV_ROUND_CLOSEST_ULL(tmp_64, 1000000000);
	ret = ops->pi_set_pw_limit(pcdev, id, mW);
out:
	mutex_unlock(&pcdev->lock);

	return ret;
@@ -403,17 +414,16 @@ devm_pse_pi_regulator_register(struct pse_controller_dev *pcdev,

	rinit_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;

	if (pcdev->ops->pi_set_current_limit) {
	if (pcdev->ops->pi_set_pw_limit)
		rinit_data->constraints.valid_ops_mask |=
			REGULATOR_CHANGE_CURRENT;
		rinit_data->constraints.max_uA = MAX_PI_CURRENT;
	}

	rinit_data->supply_regulator = "vpwr";

	rconfig.dev = pcdev->dev;
	rconfig.driver_data = pcdev;
	rconfig.init_data = rinit_data;
	rconfig.of_node = pcdev->pi[id].np;

	rdev = devm_regulator_register(pcdev->dev, rdesc, &rconfig);
	if (IS_ERR(rdev)) {
@@ -444,6 +454,13 @@ int pse_controller_register(struct pse_controller_dev *pcdev)
	if (!pcdev->nr_lines)
		pcdev->nr_lines = 1;

	if (!pcdev->ops->pi_get_admin_state ||
	    !pcdev->ops->pi_get_pw_status) {
		dev_err(pcdev->dev,
			"Mandatory status report callbacks are missing");
		return -EINVAL;
	}

	ret = of_load_pse_pis(pcdev);
	if (ret)
		return ret;
@@ -736,23 +753,6 @@ struct pse_control *of_pse_control_get(struct device_node *node)
}
EXPORT_SYMBOL_GPL(of_pse_control_get);

static int _pse_ethtool_get_status(struct pse_controller_dev *pcdev,
				   int id,
				   struct netlink_ext_ack *extack,
				   struct pse_control_status *status)
{
	const struct pse_controller_ops *ops;

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

	return ops->ethtool_get_status(pcdev, id, extack, status);
}

/**
 * pse_ethtool_get_status - get status of PSE control
 * @psec: PSE control pointer
@@ -763,15 +763,81 @@ static int _pse_ethtool_get_status(struct pse_controller_dev *pcdev,
 */
int pse_ethtool_get_status(struct pse_control *psec,
			   struct netlink_ext_ack *extack,
			   struct pse_control_status *status)
			   struct ethtool_pse_control_status *status)
{
	int err;
	struct pse_admin_state admin_state = {0};
	struct pse_pw_status pw_status = {0};
	const struct pse_controller_ops *ops;
	struct pse_controller_dev *pcdev;
	int ret;

	mutex_lock(&psec->pcdev->lock);
	err = _pse_ethtool_get_status(psec->pcdev, psec->id, extack, status);
	mutex_unlock(&psec->pcdev->lock);
	pcdev = psec->pcdev;
	ops = pcdev->ops;
	mutex_lock(&pcdev->lock);
	ret = ops->pi_get_admin_state(pcdev, psec->id, &admin_state);
	if (ret)
		goto out;
	status->podl_admin_state = admin_state.podl_admin_state;
	status->c33_admin_state = admin_state.c33_admin_state;

	return err;
	ret = ops->pi_get_pw_status(pcdev, psec->id, &pw_status);
	if (ret)
		goto out;
	status->podl_pw_status = pw_status.podl_pw_status;
	status->c33_pw_status = pw_status.c33_pw_status;

	if (ops->pi_get_ext_state) {
		struct pse_ext_state_info ext_state_info = {0};

		ret = ops->pi_get_ext_state(pcdev, psec->id,
					    &ext_state_info);
		if (ret)
			goto out;

		memcpy(&status->c33_ext_state_info,
		       &ext_state_info.c33_ext_state_info,
		       sizeof(status->c33_ext_state_info));
	}

	if (ops->pi_get_pw_class) {
		ret = ops->pi_get_pw_class(pcdev, psec->id);
		if (ret < 0)
			goto out;

		status->c33_pw_class = ret;
	}

	if (ops->pi_get_actual_pw) {
		ret = ops->pi_get_actual_pw(pcdev, psec->id);
		if (ret < 0)
			goto out;

		status->c33_actual_pw = ret;
	}

	if (ops->pi_get_pw_limit) {
		ret = ops->pi_get_pw_limit(pcdev, psec->id);
		if (ret < 0)
			goto out;

		status->c33_avail_pw_limit = ret;
	}

	if (ops->pi_get_pw_limit_ranges) {
		struct pse_pw_limit_ranges pw_limit_ranges = {0};

		ret = ops->pi_get_pw_limit_ranges(pcdev, psec->id,
						  &pw_limit_ranges);
		if (ret < 0)
			goto out;

		status->c33_pw_limit_ranges =
			pw_limit_ranges.c33_pw_limit_ranges;
		status->c33_pw_limit_nb_ranges = ret;
	}
out:
	mutex_unlock(&psec->pcdev->lock);
	return ret;
}
EXPORT_SYMBOL_GPL(pse_ethtool_get_status);

@@ -876,6 +942,9 @@ int pse_ethtool_set_pw_limit(struct pse_control *psec,
	int uV, uA, ret;
	s64 tmp_64;

	if (pw_limit > MAX_PI_PW)
		return -ERANGE;

	ret = regulator_get_voltage(psec->ps);
	if (!ret) {
		NL_SET_ERR_MSG(extack,
+12 −11
Original line number Diff line number Diff line
@@ -52,17 +52,19 @@ pse_reg_pi_disable(struct pse_controller_dev *pcdev, int id)
}

static int
pse_reg_pi_is_enabled(struct pse_controller_dev *pcdev, int id)
pse_reg_pi_get_admin_state(struct pse_controller_dev *pcdev, int id,
			   struct pse_admin_state *admin_state)
{
	struct pse_reg_priv *priv = to_pse_reg(pcdev);

	return regulator_is_enabled(priv->ps);
	admin_state->podl_admin_state = priv->admin_state;

	return 0;
}

static int
pse_reg_ethtool_get_status(struct pse_controller_dev *pcdev, unsigned long id,
			   struct netlink_ext_ack *extack,
			   struct pse_control_status *status)
pse_reg_pi_get_pw_status(struct pse_controller_dev *pcdev, int id,
			 struct pse_pw_status *pw_status)
{
	struct pse_reg_priv *priv = to_pse_reg(pcdev);
	int ret;
@@ -72,20 +74,19 @@ pse_reg_ethtool_get_status(struct pse_controller_dev *pcdev, unsigned long id,
		return ret;

	if (!ret)
		status->podl_pw_status = ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED;
		pw_status->podl_pw_status =
			ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED;
	else
		status->podl_pw_status =
		pw_status->podl_pw_status =
			ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING;

	status->podl_admin_state = priv->admin_state;

	return 0;
}

static const struct pse_controller_ops pse_reg_ops = {
	.ethtool_get_status = pse_reg_ethtool_get_status,
	.pi_get_admin_state = pse_reg_pi_get_admin_state,
	.pi_get_pw_status = pse_reg_pi_get_pw_status,
	.pi_enable = pse_reg_pi_enable,
	.pi_is_enabled = pse_reg_pi_is_enabled,
	.pi_disable = pse_reg_pi_disable,
};

+370 −79

File changed.

Preview size limit exceeded, changes collapsed.

+0 −20
Original line number Diff line number Diff line
@@ -1326,24 +1326,4 @@ struct ethtool_forced_speed_map {

void
ethtool_forced_speed_maps_init(struct ethtool_forced_speed_map *maps, u32 size);

/* C33 PSE extended state and substate. */
struct ethtool_c33_pse_ext_state_info {
	enum ethtool_c33_pse_ext_state c33_pse_ext_state;
	union {
		enum ethtool_c33_pse_ext_substate_error_condition error_condition;
		enum ethtool_c33_pse_ext_substate_mr_pse_enable mr_pse_enable;
		enum ethtool_c33_pse_ext_substate_option_detect_ted option_detect_ted;
		enum ethtool_c33_pse_ext_substate_option_vport_lim option_vport_lim;
		enum ethtool_c33_pse_ext_substate_ovld_detected ovld_detected;
		enum ethtool_c33_pse_ext_substate_power_not_available power_not_available;
		enum ethtool_c33_pse_ext_substate_short_detected short_detected;
		u32 __c33_pse_ext_substate;
	};
};

struct ethtool_c33_pse_pw_limit_range {
	u32 min;
	u32 max;
};
#endif /* _LINUX_ETHTOOL_H */
Loading