Skip to content

Commit

Permalink
Merge branch 'arrange-pse-core-and-update-tps23881-driver'
Browse files Browse the repository at this point in the history
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: Kory Maincent <kory.maincent@bootlin.com>
====================

Link: https://patch.msgid.link/20250110-b4-feature_poe_arrange-v3-0-142279aedb94@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Paolo Abeni committed Jan 14, 2025
2 parents 2b1d911 + 5385f1e commit 9c7ad35
Show file tree
Hide file tree
Showing 7 changed files with 733 additions and 308 deletions.
224 changes: 119 additions & 105 deletions drivers/net/pse-pd/pd692x0.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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),
GFP_KERNEL);
if (!st->c33_pw_limit_ranges)
c33_pw_limit_ranges = kcalloc(PD692X0_CLASS_PW_TABLE_SIZE,
sizeof(*c33_pw_limit_ranges),
GFP_KERNEL);
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);
Expand All @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -999,62 +1034,37 @@ 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,
int id)
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;
ret = pd692x0_sendrecv_msg(priv, &msg, &buf);
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;

Expand All @@ -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
Expand Down
Loading

0 comments on commit 9c7ad35

Please sign in to comment.