net: pse-pd: Add support for budget evaluation strategies

This patch introduces the ability to configure the PSE PI budget evaluation
strategies. Budget evaluation strategies is utilized by PSE controllers to
determine which ports to turn off first in scenarios such as power budget
exceedance.

The pis_prio_max value is used to define the maximum priority level
supported by the controller. Both the current priority and the maximum
priority are exposed to the user through the pse_ethtool_get_status call.

This patch add support for two mode of budget evaluation strategies.
1. Static Method:

   This method involves distributing power based on PD classification.
   It’s straightforward and stable, the PSE core keeping track of the
   budget and subtracting the power requested by each PD’s class.

   Advantages: Every PD gets its promised power at any time, which
   guarantees reliability.

   Disadvantages: PD classification steps are large, meaning devices
   request much more power than they actually need. As a result, the power
   supply may only operate at, say, 50% capacity, which is inefficient and
   wastes money.

   Priority max value is matching the number of PSE PIs within the PSE.

2. Dynamic Method:

   To address the inefficiencies of the static method, vendors like
   Microchip have introduced dynamic power budgeting, as seen in the
   PD692x0 firmware. This method monitors the current consumption per port
   and subtracts it from the available power budget. When the budget is
   exceeded, lower-priority ports are shut down.

   Advantages: This method optimizes resource utilization, saving costs.

   Disadvantages: Low-priority devices may experience instability.

   Priority max value is set by the PSE controller driver.

For now, budget evaluation methods are not configurable and cannot be
mixed. They are hardcoded in the PSE driver itself, as no current PSE
controller supports both methods.

Signed-off-by: Kory Maincent (Dent Project) <kory.maincent@bootlin.com>
Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
Link: https://patch.msgid.link/20250617-feature_poe_port_prio-v14-7-78a1a645e2ee@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Kory Maincent (Dent Project)
2025-06-18 19:00:17 -07:00
committed by Jakub Kicinski
parent c394e757de
commit ffef61d6d2
4 changed files with 816 additions and 41 deletions
+28 -2
View File
@@ -122,13 +122,39 @@ definitions:
name: pse-event
doc: PSE event list for the PSE controller
type: flags
name-prefix: ethtool-
entries:
-
name: over-current
name: pse-event-over-current
doc: PSE output current is too high
-
name: over-temp
name: pse-event-over-temp
doc: PSE in over temperature state
-
name: c33-pse-event-detection
doc: |
detection process occur on the PSE. IEEE 802.3-2022 33.2.5 and
145.2.6 PSE detection of PDs. IEEE 802.3-202 30.9.1.1.5
aPSEPowerDetectionStatus
-
name: c33-pse-event-classification
doc: |
classification process occur on the PSE. IEEE 802.3-2022 33.2.6
and 145.2.8 classification of PDs mutual identification.
IEEE 802.3-2022 30.9.1.1.8 aPSEPowerClassification.
-
name: c33-pse-event-disconnection
doc: |
PD has been disconnected on the PSE. IEEE 802.3-2022 33.3.8
and 145.3.9 PD Maintain Power Signature. IEEE 802.3-2022
33.5.1.2.9 MPS Absent. IEEE 802.3-2022 30.9.1.1.20
aPSEMPSAbsentCounter.
-
name: pse-event-over-budget
doc: PSE turned off due to over budget situation
-
name: pse-event-sw-pw-control-error
doc: PSE faced an error managing the power control from software
attribute-sets:
-
File diff suppressed because it is too large Load Diff
+76
View File
@@ -6,6 +6,8 @@
#define _LINUX_PSE_CONTROLLER_H
#include <linux/list.h>
#include <linux/netlink.h>
#include <linux/kfifo.h>
#include <uapi/linux/ethtool.h>
#include <uapi/linux/ethtool_netlink_generated.h>
#include <linux/regulator/driver.h>
@@ -134,6 +136,9 @@ struct pse_pw_limit_ranges {
* is in charge of the memory allocation
* @c33_pw_limit_nb_ranges: number of supported power limit configuration
* ranges
* @prio_max: max priority allowed for the c33_prio variable value.
* @prio: priority of the PSE. Managed by PSE core in case of static budget
* evaluation strategy.
*/
struct ethtool_pse_control_status {
u32 pw_d_id;
@@ -147,6 +152,8 @@ struct ethtool_pse_control_status {
u32 c33_avail_pw_limit;
struct ethtool_c33_pse_pw_limit_range *c33_pw_limit_ranges;
u32 c33_pw_limit_nb_ranges;
u32 prio_max;
u32 prio;
};
/**
@@ -170,6 +177,11 @@ struct ethtool_pse_control_status {
* range. The driver is in charge of the memory
* allocation and should return the number of
* ranges.
* @pi_get_prio: Get the PSE PI priority.
* @pi_set_prio: Configure the PSE PI priority.
* @pi_get_pw_req: Get the power requested by a PD before enabling the PSE PI.
* This is only relevant when an interrupt is registered using
* devm_pse_irq_helper helper.
*/
struct pse_controller_ops {
int (*setup_pi_matrix)(struct pse_controller_dev *pcdev);
@@ -190,6 +202,10 @@ struct pse_controller_ops {
int id, int max_mW);
int (*pi_get_pw_limit_ranges)(struct pse_controller_dev *pcdev, int id,
struct pse_pw_limit_ranges *pw_limit_ranges);
int (*pi_get_prio)(struct pse_controller_dev *pcdev, int id);
int (*pi_set_prio)(struct pse_controller_dev *pcdev, int id,
unsigned int prio);
int (*pi_get_pw_req)(struct pse_controller_dev *pcdev, int id);
};
struct module;
@@ -225,6 +241,13 @@ struct pse_pi_pairset {
* @rdev: regulator represented by the PSE PI
* @admin_state_enabled: PI enabled state
* @pw_d: Power domain of the PSE PI
* @prio: Priority of the PSE PI. Used in static budget evaluation strategy
* @isr_pd_detected: PSE PI detection status managed by the interruption
* handler. This variable is relevant when the power enabled
* management is managed in software like the static
* budget evaluation strategy.
* @pw_allocated_mW: Power allocated to a PSE PI to manage power budget in
* static budget evaluation strategy.
*/
struct pse_pi {
struct pse_pi_pairset pairset[2];
@@ -232,6 +255,20 @@ struct pse_pi {
struct regulator_dev *rdev;
bool admin_state_enabled;
struct pse_power_domain *pw_d;
int prio;
bool isr_pd_detected;
int pw_allocated_mW;
};
/**
* struct pse_ntf - PSE notification element
*
* @id: ID of the PSE control
* @notifs: PSE notifications to be reported
*/
struct pse_ntf {
int id;
unsigned long notifs;
};
/**
@@ -249,6 +286,12 @@ struct pse_pi {
* @pi: table of PSE PIs described in this controller device
* @no_of_pse_pi: flag set if the pse_pis devicetree node is not used
* @irq: PSE interrupt
* @pis_prio_max: Maximum value allowed for the PSE PIs priority
* @supp_budget_eval_strategies: budget evaluation strategies supported
* by the PSE
* @ntf_work: workqueue for PSE notification management
* @ntf_fifo: PSE notifications FIFO
* @ntf_fifo_lock: protect @ntf_fifo writer
*/
struct pse_controller_dev {
const struct pse_controller_ops *ops;
@@ -263,6 +306,29 @@ struct pse_controller_dev {
struct pse_pi *pi;
bool no_of_pse_pi;
int irq;
unsigned int pis_prio_max;
u32 supp_budget_eval_strategies;
struct work_struct ntf_work;
DECLARE_KFIFO_PTR(ntf_fifo, struct pse_ntf);
spinlock_t ntf_fifo_lock; /* Protect @ntf_fifo writer */
};
/**
* enum pse_budget_eval_strategies - PSE budget evaluation strategies.
* @PSE_BUDGET_EVAL_STRAT_DISABLED: Budget evaluation strategy disabled.
* @PSE_BUDGET_EVAL_STRAT_STATIC: PSE static budget evaluation strategy.
* Budget evaluation strategy based on the power requested during PD
* classification. This strategy is managed by the PSE core.
* @PSE_BUDGET_EVAL_STRAT_DYNAMIC: PSE dynamic budget evaluation
* strategy. Budget evaluation strategy based on the current consumption
* per ports compared to the total power budget. This mode is managed by
* the PSE controller.
*/
enum pse_budget_eval_strategies {
PSE_BUDGET_EVAL_STRAT_DISABLED = 1 << 0,
PSE_BUDGET_EVAL_STRAT_STATIC = 1 << 1,
PSE_BUDGET_EVAL_STRAT_DYNAMIC = 1 << 2,
};
#if IS_ENABLED(CONFIG_PSE_CONTROLLER)
@@ -287,6 +353,9 @@ int pse_ethtool_set_config(struct pse_control *psec,
int pse_ethtool_set_pw_limit(struct pse_control *psec,
struct netlink_ext_ack *extack,
const unsigned int pw_limit);
int pse_ethtool_set_prio(struct pse_control *psec,
struct netlink_ext_ack *extack,
unsigned int prio);
bool pse_has_podl(struct pse_control *psec);
bool pse_has_c33(struct pse_control *psec);
@@ -324,6 +393,13 @@ static inline int pse_ethtool_set_pw_limit(struct pse_control *psec,
return -EOPNOTSUPP;
}
static inline int pse_ethtool_set_prio(struct pse_control *psec,
struct netlink_ext_ack *extack,
unsigned int prio)
{
return -EOPNOTSUPP;
}
static inline bool pse_has_podl(struct pse_control *psec)
{
return false;
@@ -53,10 +53,28 @@ enum hwtstamp_source {
* enum ethtool_pse_event - PSE event list for the PSE controller
* @ETHTOOL_PSE_EVENT_OVER_CURRENT: PSE output current is too high
* @ETHTOOL_PSE_EVENT_OVER_TEMP: PSE in over temperature state
* @ETHTOOL_C33_PSE_EVENT_DETECTION: detection process occur on the PSE. IEEE
* 802.3-2022 33.2.5 and 145.2.6 PSE detection of PDs. IEEE 802.3-202
* 30.9.1.1.5 aPSEPowerDetectionStatus
* @ETHTOOL_C33_PSE_EVENT_CLASSIFICATION: classification process occur on the
* PSE. IEEE 802.3-2022 33.2.6 and 145.2.8 classification of PDs mutual
* identification. IEEE 802.3-2022 30.9.1.1.8 aPSEPowerClassification.
* @ETHTOOL_C33_PSE_EVENT_DISCONNECTION: PD has been disconnected on the PSE.
* IEEE 802.3-2022 33.3.8 and 145.3.9 PD Maintain Power Signature. IEEE
* 802.3-2022 33.5.1.2.9 MPS Absent. IEEE 802.3-2022 30.9.1.1.20
* aPSEMPSAbsentCounter.
* @ETHTOOL_PSE_EVENT_OVER_BUDGET: PSE turned off due to over budget situation
* @ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR: PSE faced an error managing the
* power control from software
*/
enum ethtool_pse_event {
ETHTOOL_PSE_EVENT_OVER_CURRENT = 1,
ETHTOOL_PSE_EVENT_OVER_TEMP = 2,
ETHTOOL_C33_PSE_EVENT_DETECTION = 4,
ETHTOOL_C33_PSE_EVENT_CLASSIFICATION = 8,
ETHTOOL_C33_PSE_EVENT_DISCONNECTION = 16,
ETHTOOL_PSE_EVENT_OVER_BUDGET = 32,
ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR = 64,
};
enum {