Skip to content

Commit 30d7b67

Browse files
kmaincentkuba-moo
authored andcommitted
net: ethtool: Add new power limit get and set features
This patch expands the status information provided by ethtool for PSE c33 with available power limit and available power limit ranges. It also adds a call to pse_ethtool_set_pw_limit() to configure the PSE control power limit. Reviewed-by: Oleksij Rempel <[email protected]> Signed-off-by: Kory Maincent <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 4a83abc commit 30d7b67

File tree

4 files changed

+141
-25
lines changed

4 files changed

+141
-25
lines changed

Documentation/networking/ethtool-netlink.rst

+46-18
Original file line numberDiff line numberDiff line change
@@ -1730,24 +1730,28 @@ Request contents:
17301730

17311731
Kernel response contents:
17321732

1733-
====================================== ====== =============================
1734-
``ETHTOOL_A_PSE_HEADER`` nested reply header
1735-
``ETHTOOL_A_PODL_PSE_ADMIN_STATE`` u32 Operational state of the PoDL
1736-
PSE functions
1737-
``ETHTOOL_A_PODL_PSE_PW_D_STATUS`` u32 power detection status of the
1738-
PoDL PSE.
1739-
``ETHTOOL_A_C33_PSE_ADMIN_STATE`` u32 Operational state of the PoE
1740-
PSE functions.
1741-
``ETHTOOL_A_C33_PSE_PW_D_STATUS`` u32 power detection status of the
1742-
PoE PSE.
1743-
``ETHTOOL_A_C33_PSE_PW_CLASS`` u32 power class of the PoE PSE.
1744-
``ETHTOOL_A_C33_PSE_ACTUAL_PW`` u32 actual power drawn on the
1745-
PoE PSE.
1746-
``ETHTOOL_A_C33_PSE_EXT_STATE`` u32 power extended state of the
1747-
PoE PSE.
1748-
``ETHTOOL_A_C33_PSE_EXT_SUBSTATE`` u32 power extended substatus of
1749-
the PoE PSE.
1750-
====================================== ====== =============================
1733+
========================================== ====== =============================
1734+
``ETHTOOL_A_PSE_HEADER`` nested reply header
1735+
``ETHTOOL_A_PODL_PSE_ADMIN_STATE`` u32 Operational state of the PoDL
1736+
PSE functions
1737+
``ETHTOOL_A_PODL_PSE_PW_D_STATUS`` u32 power detection status of the
1738+
PoDL PSE.
1739+
``ETHTOOL_A_C33_PSE_ADMIN_STATE`` u32 Operational state of the PoE
1740+
PSE functions.
1741+
``ETHTOOL_A_C33_PSE_PW_D_STATUS`` u32 power detection status of the
1742+
PoE PSE.
1743+
``ETHTOOL_A_C33_PSE_PW_CLASS`` u32 power class of the PoE PSE.
1744+
``ETHTOOL_A_C33_PSE_ACTUAL_PW`` u32 actual power drawn on the
1745+
PoE PSE.
1746+
``ETHTOOL_A_C33_PSE_EXT_STATE`` u32 power extended state of the
1747+
PoE PSE.
1748+
``ETHTOOL_A_C33_PSE_EXT_SUBSTATE`` u32 power extended substatus of
1749+
the PoE PSE.
1750+
``ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT`` u32 currently configured power
1751+
limit of the PoE PSE.
1752+
``ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES`` nested Supported power limit
1753+
configuration ranges.
1754+
========================================== ====== =============================
17511755

17521756
When set, the optional ``ETHTOOL_A_PODL_PSE_ADMIN_STATE`` attribute identifies
17531757
the operational state of the PoDL PSE functions. The operational state of the
@@ -1809,6 +1813,16 @@ Possible values are:
18091813
ethtool_c33_pse_ext_substate_power_not_available
18101814
ethtool_c33_pse_ext_substate_short_detected
18111815

1816+
When set, the optional ``ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT`` attribute
1817+
identifies the C33 PSE power limit in mW.
1818+
1819+
When set the optional ``ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES`` nested attribute
1820+
identifies the C33 PSE power limit ranges through
1821+
``ETHTOOL_A_C33_PSE_PWR_VAL_LIMIT_RANGE_MIN`` and
1822+
``ETHTOOL_A_C33_PSE_PWR_VAL_LIMIT_RANGE_MAX``.
1823+
If the controller works with fixed classes, the min and max values will be
1824+
equal.
1825+
18121826
PSE_SET
18131827
=======
18141828

@@ -1820,6 +1834,8 @@ Request contents:
18201834
``ETHTOOL_A_PSE_HEADER`` nested request header
18211835
``ETHTOOL_A_PODL_PSE_ADMIN_CONTROL`` u32 Control PoDL PSE Admin state
18221836
``ETHTOOL_A_C33_PSE_ADMIN_CONTROL`` u32 Control PSE Admin state
1837+
``ETHTOOL_A_C33_PSE_AVAIL_PWR_LIMIT`` u32 Control PoE PSE available
1838+
power limit
18231839
====================================== ====== =============================
18241840

18251841
When set, the optional ``ETHTOOL_A_PODL_PSE_ADMIN_CONTROL`` attribute is used
@@ -1830,6 +1846,18 @@ to control PoDL PSE Admin functions. This option is implementing
18301846
The same goes for ``ETHTOOL_A_C33_PSE_ADMIN_CONTROL`` implementing
18311847
``IEEE 802.3-2022`` 30.9.1.2.1 acPSEAdminControl.
18321848

1849+
When set, the optional ``ETHTOOL_A_C33_PSE_AVAIL_PWR_LIMIT`` attribute is
1850+
used to control the available power value limit for C33 PSE in milliwatts.
1851+
This attribute corresponds to the `pse_available_power` variable described in
1852+
``IEEE 802.3-2022`` 33.2.4.4 Variables and `pse_avail_pwr` in 145.2.5.4
1853+
Variables, which are described in power classes.
1854+
1855+
It was decided to use milliwatts for this interface to unify it with other
1856+
power monitoring interfaces, which also use milliwatts, and to align with
1857+
various existing products that document power consumption in watts rather than
1858+
classes. If power limit configuration based on classes is needed, the
1859+
conversion can be done in user space, for example by ethtool.
1860+
18331861
RSS_GET
18341862
=======
18351863

include/linux/ethtool.h

+5
Original file line numberDiff line numberDiff line change
@@ -1288,4 +1288,9 @@ struct ethtool_c33_pse_ext_state_info {
12881288
u32 __c33_pse_ext_substate;
12891289
};
12901290
};
1291+
1292+
struct ethtool_c33_pse_pw_limit_range {
1293+
u32 min;
1294+
u32 max;
1295+
};
12911296
#endif /* _LINUX_ETHTOOL_H */

include/uapi/linux/ethtool_netlink.h

+8
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,12 @@ enum {
930930
};
931931

932932
/* Power Sourcing Equipment */
933+
enum {
934+
ETHTOOL_A_C33_PSE_PW_LIMIT_UNSPEC,
935+
ETHTOOL_A_C33_PSE_PW_LIMIT_MIN, /* u32 */
936+
ETHTOOL_A_C33_PSE_PW_LIMIT_MAX, /* u32 */
937+
};
938+
933939
enum {
934940
ETHTOOL_A_PSE_UNSPEC,
935941
ETHTOOL_A_PSE_HEADER, /* nest - _A_HEADER_* */
@@ -943,6 +949,8 @@ enum {
943949
ETHTOOL_A_C33_PSE_ACTUAL_PW, /* u32 */
944950
ETHTOOL_A_C33_PSE_EXT_STATE, /* u32 */
945951
ETHTOOL_A_C33_PSE_EXT_SUBSTATE, /* u32 */
952+
ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT, /* u32 */
953+
ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES, /* nest - _C33_PSE_PW_LIMIT_* */
946954

947955
/* add new constants above here */
948956
__ETHTOOL_A_PSE_CNT,

net/ethtool/pse-pd.c

+82-7
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,46 @@ static int pse_reply_size(const struct ethnl_req_info *req_base,
9696
/* _C33_PSE_EXT_SUBSTATE */
9797
len += nla_total_size(sizeof(u32));
9898
}
99+
if (st->c33_avail_pw_limit > 0)
100+
/* _C33_AVAIL_PSE_PW_LIMIT */
101+
len += nla_total_size(sizeof(u32));
102+
if (st->c33_pw_limit_nb_ranges > 0)
103+
/* _C33_PSE_PW_LIMIT_RANGES */
104+
len += st->c33_pw_limit_nb_ranges *
105+
(nla_total_size(0) +
106+
nla_total_size(sizeof(u32)) * 2);
107+
99108
return len;
100109
}
101110

111+
static int pse_put_pw_limit_ranges(struct sk_buff *skb,
112+
const struct pse_control_status *st)
113+
{
114+
const struct ethtool_c33_pse_pw_limit_range *pw_limit_ranges;
115+
int i;
116+
117+
pw_limit_ranges = st->c33_pw_limit_ranges;
118+
for (i = 0; i < st->c33_pw_limit_nb_ranges; i++) {
119+
struct nlattr *nest;
120+
121+
nest = nla_nest_start(skb, ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES);
122+
if (!nest)
123+
return -EMSGSIZE;
124+
125+
if (nla_put_u32(skb, ETHTOOL_A_C33_PSE_PW_LIMIT_MIN,
126+
pw_limit_ranges->min) ||
127+
nla_put_u32(skb, ETHTOOL_A_C33_PSE_PW_LIMIT_MAX,
128+
pw_limit_ranges->max)) {
129+
nla_nest_cancel(skb, nest);
130+
return -EMSGSIZE;
131+
}
132+
nla_nest_end(skb, nest);
133+
pw_limit_ranges++;
134+
}
135+
136+
return 0;
137+
}
138+
102139
static int pse_fill_reply(struct sk_buff *skb,
103140
const struct ethnl_req_info *req_base,
104141
const struct ethnl_reply_data *reply_base)
@@ -147,9 +184,25 @@ static int pse_fill_reply(struct sk_buff *skb,
147184
return -EMSGSIZE;
148185
}
149186

187+
if (st->c33_avail_pw_limit > 0 &&
188+
nla_put_u32(skb, ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT,
189+
st->c33_avail_pw_limit))
190+
return -EMSGSIZE;
191+
192+
if (st->c33_pw_limit_nb_ranges > 0 &&
193+
pse_put_pw_limit_ranges(skb, st))
194+
return -EMSGSIZE;
195+
150196
return 0;
151197
}
152198

199+
static void pse_cleanup_data(struct ethnl_reply_data *reply_base)
200+
{
201+
const struct pse_reply_data *data = PSE_REPDATA(reply_base);
202+
203+
kfree(data->status.c33_pw_limit_ranges);
204+
}
205+
153206
/* PSE_SET */
154207

155208
const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1] = {
@@ -160,6 +213,7 @@ const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1] = {
160213
[ETHTOOL_A_C33_PSE_ADMIN_CONTROL] =
161214
NLA_POLICY_RANGE(NLA_U32, ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED,
162215
ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED),
216+
[ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT] = { .type = NLA_U32 },
163217
};
164218

165219
static int
@@ -202,19 +256,39 @@ static int
202256
ethnl_set_pse(struct ethnl_req_info *req_info, struct genl_info *info)
203257
{
204258
struct net_device *dev = req_info->dev;
205-
struct pse_control_config config = {};
206259
struct nlattr **tb = info->attrs;
207260
struct phy_device *phydev;
261+
int ret = 0;
208262

209263
phydev = dev->phydev;
264+
265+
if (tb[ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT]) {
266+
unsigned int pw_limit;
267+
268+
pw_limit = nla_get_u32(tb[ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT]);
269+
ret = pse_ethtool_set_pw_limit(phydev->psec, info->extack,
270+
pw_limit);
271+
if (ret)
272+
return ret;
273+
}
274+
210275
/* These values are already validated by the ethnl_pse_set_policy */
211-
if (pse_has_podl(phydev->psec))
212-
config.podl_admin_control = nla_get_u32(tb[ETHTOOL_A_PODL_PSE_ADMIN_CONTROL]);
213-
if (pse_has_c33(phydev->psec))
214-
config.c33_admin_control = nla_get_u32(tb[ETHTOOL_A_C33_PSE_ADMIN_CONTROL]);
276+
if (tb[ETHTOOL_A_PODL_PSE_ADMIN_CONTROL] ||
277+
tb[ETHTOOL_A_C33_PSE_ADMIN_CONTROL]) {
278+
struct pse_control_config config = {};
279+
280+
if (pse_has_podl(phydev->psec))
281+
config.podl_admin_control = nla_get_u32(tb[ETHTOOL_A_PODL_PSE_ADMIN_CONTROL]);
282+
if (pse_has_c33(phydev->psec))
283+
config.c33_admin_control = nla_get_u32(tb[ETHTOOL_A_C33_PSE_ADMIN_CONTROL]);
284+
285+
ret = pse_ethtool_set_config(phydev->psec, info->extack,
286+
&config);
287+
if (ret)
288+
return ret;
289+
}
215290

216-
/* Return errno directly - PSE has no notification */
217-
return pse_ethtool_set_config(phydev->psec, info->extack, &config);
291+
return ret;
218292
}
219293

220294
const struct ethnl_request_ops ethnl_pse_request_ops = {
@@ -227,6 +301,7 @@ const struct ethnl_request_ops ethnl_pse_request_ops = {
227301
.prepare_data = pse_prepare_data,
228302
.reply_size = pse_reply_size,
229303
.fill_reply = pse_fill_reply,
304+
.cleanup_data = pse_cleanup_data,
230305

231306
.set_validate = ethnl_set_pse_validate,
232307
.set = ethnl_set_pse,

0 commit comments

Comments
 (0)