Merge branch 'net-pse-pd-add-new-pse-c33-features'
Kory Maincent says: ==================== net: pse-pd: Add new PSE c33 features This patch series adds new c33 features to the PSE API. - Expand the PSE PI informations status with power, class and failure reason - Add the possibility to get and set the PSE PIs power limit v5: https://lore.kernel.org/r/20240628-feature_poe_power_cap-v5-0-5e1375d3817a@bootlin.com v4: https://lore.kernel.org/r/20240625-feature_poe_power_cap-v4-0-b0813aad57d5@bootlin.com v3: https://lore.kernel.org/r/20240614-feature_poe_power_cap-v3-0-a26784e78311@bootlin.com v2: https://lore.kernel.org/r/20240607-feature_poe_power_cap-v2-0-c03c2deb83ab@bootlin.com v1: https://lore.kernel.org/r/20240529-feature_poe_power_cap-v1-0-0c4b1d5953b8@bootlin.com ==================== Link: https://patch.msgid.link/20240704-feature_poe_power_cap-v6-0-320003204264@bootlin.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -24,6 +24,21 @@ definitions:
|
||||
name: module-fw-flash-status
|
||||
type: enum
|
||||
entries: [ started, in_progress, completed, error ]
|
||||
-
|
||||
name: c33-pse-ext-state
|
||||
enum-name:
|
||||
type: enum
|
||||
name-prefix: ethtool-c33-pse-ext-state-
|
||||
entries:
|
||||
- none
|
||||
- error-condition
|
||||
- mr-mps-valid
|
||||
- mr-pse-enable
|
||||
- option-detect-ted
|
||||
- option-vport-lim
|
||||
- ovld-detected
|
||||
- power-not-available
|
||||
- short-detected
|
||||
|
||||
attribute-sets:
|
||||
-
|
||||
@@ -924,6 +939,15 @@ attribute-sets:
|
||||
-
|
||||
name: power-mode
|
||||
type: u8
|
||||
-
|
||||
name: c33-pse-pw-limit
|
||||
attributes:
|
||||
-
|
||||
name: min
|
||||
type: u32
|
||||
-
|
||||
name: max
|
||||
type: u32
|
||||
-
|
||||
name: pse
|
||||
attributes:
|
||||
@@ -955,6 +979,33 @@ attribute-sets:
|
||||
name: c33-pse-pw-d-status
|
||||
type: u32
|
||||
name-prefix: ethtool-a-
|
||||
-
|
||||
name: c33-pse-pw-class
|
||||
type: u32
|
||||
name-prefix: ethtool-a-
|
||||
-
|
||||
name: c33-pse-actual-pw
|
||||
type: u32
|
||||
name-prefix: ethtool-a-
|
||||
-
|
||||
name: c33-pse-ext-state
|
||||
type: u32
|
||||
name-prefix: ethtool-a-
|
||||
enum: c33-pse-ext-state
|
||||
-
|
||||
name: c33-pse-ext-substate
|
||||
type: u32
|
||||
name-prefix: ethtool-a-
|
||||
-
|
||||
name: c33-pse-avail-pw-limit
|
||||
type: u32
|
||||
name-prefix: ethtool-a-
|
||||
-
|
||||
name: c33-pse-pw-limit-ranges
|
||||
name-prefix: ethtool-a-
|
||||
type: nest
|
||||
multi-attr: true
|
||||
nested-attributes: c33-pse-pw-limit
|
||||
-
|
||||
name: rss
|
||||
attributes:
|
||||
@@ -1672,6 +1723,12 @@ operations:
|
||||
- c33-pse-admin-state
|
||||
- c33-pse-admin-control
|
||||
- c33-pse-pw-d-status
|
||||
- c33-pse-pw-class
|
||||
- c33-pse-actual-pw
|
||||
- c33-pse-ext-state
|
||||
- c33-pse-ext-substate
|
||||
- c33-pse-avail-pw-limit
|
||||
- c33-pse-pw-limit-ranges
|
||||
dump: *pse-get-op
|
||||
-
|
||||
name: pse-set
|
||||
@@ -1685,6 +1742,7 @@ operations:
|
||||
- header
|
||||
- podl-pse-admin-control
|
||||
- c33-pse-admin-control
|
||||
- c33-pse-avail-pw-limit
|
||||
-
|
||||
name: rss-get
|
||||
doc: Get RSS params.
|
||||
|
||||
@@ -1730,17 +1730,28 @@ Request contents:
|
||||
|
||||
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.
|
||||
``ETHTOOL_A_C33_PSE_ADMIN_STATE`` u32 Operational state of the PoE
|
||||
PSE functions.
|
||||
``ETHTOOL_A_C33_PSE_PW_D_STATUS`` u32 power detection status of the
|
||||
PoE PSE.
|
||||
====================================== ====== =============================
|
||||
========================================== ====== =============================
|
||||
``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.
|
||||
``ETHTOOL_A_C33_PSE_ADMIN_STATE`` u32 Operational state of the PoE
|
||||
PSE functions.
|
||||
``ETHTOOL_A_C33_PSE_PW_D_STATUS`` u32 power detection status of the
|
||||
PoE PSE.
|
||||
``ETHTOOL_A_C33_PSE_PW_CLASS`` u32 power class of the PoE PSE.
|
||||
``ETHTOOL_A_C33_PSE_ACTUAL_PW`` u32 actual power drawn on the
|
||||
PoE PSE.
|
||||
``ETHTOOL_A_C33_PSE_EXT_STATE`` u32 power extended state of the
|
||||
PoE PSE.
|
||||
``ETHTOOL_A_C33_PSE_EXT_SUBSTATE`` u32 power extended substatus of
|
||||
the PoE PSE.
|
||||
``ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT`` u32 currently configured power
|
||||
limit of the PoE PSE.
|
||||
``ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES`` nested Supported power limit
|
||||
configuration ranges.
|
||||
========================================== ====== =============================
|
||||
|
||||
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
|
||||
@@ -1772,6 +1783,46 @@ The same goes for ``ETHTOOL_A_C33_PSE_ADMIN_PW_D_STATUS`` implementing
|
||||
.. kernel-doc:: include/uapi/linux/ethtool.h
|
||||
:identifiers: ethtool_c33_pse_pw_d_status
|
||||
|
||||
When set, the optional ``ETHTOOL_A_C33_PSE_PW_CLASS`` attribute identifies
|
||||
the power class of the C33 PSE. It depends on the class negotiated between
|
||||
the PSE and the PD. This option is corresponding to ``IEEE 802.3-2022``
|
||||
30.9.1.1.8 aPSEPowerClassification.
|
||||
|
||||
When set, the optional ``ETHTOOL_A_C33_PSE_ACTUAL_PW`` attribute identifies
|
||||
This option is corresponding to ``IEEE 802.3-2022`` 30.9.1.1.23 aPSEActualPower.
|
||||
Actual power is reported in mW.
|
||||
|
||||
When set, the optional ``ETHTOOL_A_C33_PSE_EXT_STATE`` attribute identifies
|
||||
the extended error state of the C33 PSE. Possible values are:
|
||||
|
||||
.. kernel-doc:: include/uapi/linux/ethtool.h
|
||||
:identifiers: ethtool_c33_pse_ext_state
|
||||
|
||||
When set, the optional ``ETHTOOL_A_C33_PSE_EXT_SUBSTATE`` attribute identifies
|
||||
the extended error state of the C33 PSE. Possible values are:
|
||||
Possible values are:
|
||||
|
||||
.. kernel-doc:: include/uapi/linux/ethtool.h
|
||||
:identifiers: ethtool_c33_pse_ext_substate_class_num_events
|
||||
ethtool_c33_pse_ext_substate_error_condition
|
||||
ethtool_c33_pse_ext_substate_mr_pse_enable
|
||||
ethtool_c33_pse_ext_substate_option_detect_ted
|
||||
ethtool_c33_pse_ext_substate_option_vport_lim
|
||||
ethtool_c33_pse_ext_substate_ovld_detected
|
||||
ethtool_c33_pse_ext_substate_pd_dll_power_type
|
||||
ethtool_c33_pse_ext_substate_power_not_available
|
||||
ethtool_c33_pse_ext_substate_short_detected
|
||||
|
||||
When set, the optional ``ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT`` attribute
|
||||
identifies the C33 PSE power limit in mW.
|
||||
|
||||
When set the optional ``ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES`` nested attribute
|
||||
identifies the C33 PSE power limit ranges through
|
||||
``ETHTOOL_A_C33_PSE_PWR_VAL_LIMIT_RANGE_MIN`` and
|
||||
``ETHTOOL_A_C33_PSE_PWR_VAL_LIMIT_RANGE_MAX``.
|
||||
If the controller works with fixed classes, the min and max values will be
|
||||
equal.
|
||||
|
||||
PSE_SET
|
||||
=======
|
||||
|
||||
@@ -1783,6 +1834,8 @@ Request contents:
|
||||
``ETHTOOL_A_PSE_HEADER`` nested request header
|
||||
``ETHTOOL_A_PODL_PSE_ADMIN_CONTROL`` u32 Control PoDL PSE Admin state
|
||||
``ETHTOOL_A_C33_PSE_ADMIN_CONTROL`` u32 Control PSE Admin state
|
||||
``ETHTOOL_A_C33_PSE_AVAIL_PWR_LIMIT`` u32 Control PoE PSE available
|
||||
power limit
|
||||
====================================== ====== =============================
|
||||
|
||||
When set, the optional ``ETHTOOL_A_PODL_PSE_ADMIN_CONTROL`` attribute is used
|
||||
@@ -1793,6 +1846,18 @@ to control PoDL PSE Admin functions. This option is implementing
|
||||
The same goes for ``ETHTOOL_A_C33_PSE_ADMIN_CONTROL`` implementing
|
||||
``IEEE 802.3-2022`` 30.9.1.2.1 acPSEAdminControl.
|
||||
|
||||
When set, the optional ``ETHTOOL_A_C33_PSE_AVAIL_PWR_LIMIT`` attribute is
|
||||
used to control the available power value limit for C33 PSE in milliwatts.
|
||||
This attribute corresponds to the `pse_available_power` variable described in
|
||||
``IEEE 802.3-2022`` 33.2.4.4 Variables and `pse_avail_pwr` in 145.2.5.4
|
||||
Variables, which are described in power classes.
|
||||
|
||||
It was decided to use milliwatts for this interface to unify it with other
|
||||
power monitoring interfaces, which also use milliwatts, and to align with
|
||||
various existing products that document power consumption in watts rather than
|
||||
classes. If power limit configuration based on classes is needed, the
|
||||
conversion can be done in user space, for example by ethtool.
|
||||
|
||||
RSS_GET
|
||||
=======
|
||||
|
||||
|
||||
@@ -73,6 +73,9 @@ enum {
|
||||
PD692X0_MSG_SET_PORT_PARAM,
|
||||
PD692X0_MSG_GET_PORT_STATUS,
|
||||
PD692X0_MSG_DOWNLOAD_CMD,
|
||||
PD692X0_MSG_GET_PORT_CLASS,
|
||||
PD692X0_MSG_GET_PORT_MEAS,
|
||||
PD692X0_MSG_GET_PORT_PARAM,
|
||||
|
||||
/* add new message above here */
|
||||
PD692X0_MSG_CNT
|
||||
@@ -134,7 +137,7 @@ static const struct pd692x0_msg pd692x0_msg_template_list[PD692X0_MSG_CNT] = {
|
||||
[PD692X0_MSG_SET_PORT_PARAM] = {
|
||||
.key = PD692X0_KEY_CMD,
|
||||
.sub = {0x05, 0xc0},
|
||||
.data = { 0, 0xff, 0xff, 0xff,
|
||||
.data = { 0xf, 0xff, 0xff, 0xff,
|
||||
0x4e, 0x4e, 0x4e, 0x4e},
|
||||
},
|
||||
[PD692X0_MSG_GET_PORT_STATUS] = {
|
||||
@@ -149,6 +152,24 @@ static const struct pd692x0_msg pd692x0_msg_template_list[PD692X0_MSG_CNT] = {
|
||||
.data = {0x16, 0x16, 0x99, 0x4e,
|
||||
0x4e, 0x4e, 0x4e, 0x4e},
|
||||
},
|
||||
[PD692X0_MSG_GET_PORT_CLASS] = {
|
||||
.key = PD692X0_KEY_REQ,
|
||||
.sub = {0x05, 0xc4},
|
||||
.data = {0x4e, 0x4e, 0x4e, 0x4e,
|
||||
0x4e, 0x4e, 0x4e, 0x4e},
|
||||
},
|
||||
[PD692X0_MSG_GET_PORT_MEAS] = {
|
||||
.key = PD692X0_KEY_REQ,
|
||||
.sub = {0x05, 0xc5},
|
||||
.data = {0x4e, 0x4e, 0x4e, 0x4e,
|
||||
0x4e, 0x4e, 0x4e, 0x4e},
|
||||
},
|
||||
[PD692X0_MSG_GET_PORT_PARAM] = {
|
||||
.key = PD692X0_KEY_REQ,
|
||||
.sub = {0x05, 0xc0},
|
||||
.data = {0x4e, 0x4e, 0x4e, 0x4e,
|
||||
0x4e, 0x4e, 0x4e, 0x4e},
|
||||
},
|
||||
};
|
||||
|
||||
static u8 pd692x0_build_msg(struct pd692x0_msg *msg, u8 echo)
|
||||
@@ -435,6 +456,184 @@ static int pd692x0_pi_is_enabled(struct pse_controller_dev *pcdev, int id)
|
||||
}
|
||||
}
|
||||
|
||||
struct pd692x0_pse_ext_state_mapping {
|
||||
u32 status_code;
|
||||
enum ethtool_c33_pse_ext_state pse_ext_state;
|
||||
u32 pse_ext_substate;
|
||||
};
|
||||
|
||||
static const struct pd692x0_pse_ext_state_mapping
|
||||
pd692x0_pse_ext_state_map[] = {
|
||||
{0x06, ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_HIGH_VOLTAGE},
|
||||
{0x07, ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_LOW_VOLTAGE},
|
||||
{0x08, ETHTOOL_C33_PSE_EXT_STATE_MR_PSE_ENABLE,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_PSE_ENABLE_DISABLE_PIN_ACTIVE},
|
||||
{0x0C, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_NON_EXISTING_PORT},
|
||||
{0x11, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNDEFINED_PORT},
|
||||
{0x12, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_INTERNAL_HW_FAULT},
|
||||
{0x1B, ETHTOOL_C33_PSE_EXT_STATE_OPTION_DETECT_TED,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_DET_IN_PROCESS},
|
||||
{0x1C, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},
|
||||
{0x1E, ETHTOOL_C33_PSE_EXT_STATE_MR_MPS_VALID,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_DETECTED_UNDERLOAD},
|
||||
{0x1F, ETHTOOL_C33_PSE_EXT_STATE_OVLD_DETECTED,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OVLD_DETECTED_OVERLOAD},
|
||||
{0x20, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_BUDGET_EXCEEDED},
|
||||
{0x21, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_INTERNAL_HW_FAULT},
|
||||
{0x22, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_CONFIG_CHANGE},
|
||||
{0x24, ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_VOLTAGE_INJECTION},
|
||||
{0x25, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},
|
||||
{0x34, ETHTOOL_C33_PSE_EXT_STATE_SHORT_DETECTED,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_SHORT_DETECTED_SHORT_CONDITION},
|
||||
{0x35, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_DETECTED_OVER_TEMP},
|
||||
{0x36, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_DETECTED_OVER_TEMP},
|
||||
{0x37, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},
|
||||
{0x3C, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PORT_PW_LIMIT_EXCEEDS_CONTROLLER_BUDGET},
|
||||
{0x3D, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PD_REQUEST_EXCEEDS_PORT_LIMIT},
|
||||
{0x41, ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_HW_PW_LIMIT},
|
||||
{0x43, ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS},
|
||||
{0xA7, ETHTOOL_C33_PSE_EXT_STATE_OPTION_DETECT_TED,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_CONNECTION_CHECK_ERROR},
|
||||
{0xA8, ETHTOOL_C33_PSE_EXT_STATE_MR_MPS_VALID,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_CONNECTION_OPEN},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static void
|
||||
pd692x0_get_ext_state(struct ethtool_c33_pse_ext_state_info *c33_ext_state_info,
|
||||
u32 status_code)
|
||||
{
|
||||
const struct pd692x0_pse_ext_state_mapping *ext_state_map;
|
||||
|
||||
ext_state_map = pd692x0_pse_ext_state_map;
|
||||
while (ext_state_map->status_code) {
|
||||
if (ext_state_map->status_code == status_code) {
|
||||
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;
|
||||
}
|
||||
ext_state_map++;
|
||||
}
|
||||
}
|
||||
|
||||
struct pd692x0_class_pw {
|
||||
int class;
|
||||
int class_cfg_value;
|
||||
int class_pw;
|
||||
int max_added_class_pw;
|
||||
};
|
||||
|
||||
#define PD692X0_CLASS_PW_TABLE_SIZE 4
|
||||
/* 4/2 pairs class configuration power table in compliance mode.
|
||||
* Need to be arranged in ascending order of power support.
|
||||
*/
|
||||
static const struct pd692x0_class_pw
|
||||
pd692x0_class_pw_table[PD692X0_CLASS_PW_TABLE_SIZE] = {
|
||||
{.class = 3, .class_cfg_value = 0x3, .class_pw = 15000, .max_added_class_pw = 3100},
|
||||
{.class = 4, .class_cfg_value = 0x2, .class_pw = 30000, .max_added_class_pw = 8000},
|
||||
{.class = 6, .class_cfg_value = 0x1, .class_pw = 60000, .max_added_class_pw = 5000},
|
||||
{.class = 8, .class_cfg_value = 0x0, .class_pw = 90000, .max_added_class_pw = 7500},
|
||||
};
|
||||
|
||||
static int pd692x0_pi_get_pw_from_table(int op_mode, int added_pw)
|
||||
{
|
||||
const struct pd692x0_class_pw *pw_table;
|
||||
int i;
|
||||
|
||||
pw_table = pd692x0_class_pw_table;
|
||||
for (i = 0; i < PD692X0_CLASS_PW_TABLE_SIZE; i++, pw_table++) {
|
||||
if (pw_table->class_cfg_value == op_mode)
|
||||
return pw_table->class_pw + added_pw * 100;
|
||||
}
|
||||
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
static int pd692x0_pi_set_pw_from_table(struct device *dev,
|
||||
struct pd692x0_msg *msg, int pw)
|
||||
{
|
||||
const struct pd692x0_class_pw *pw_table;
|
||||
int i;
|
||||
|
||||
pw_table = pd692x0_class_pw_table;
|
||||
if (pw < pw_table->class_pw) {
|
||||
dev_err(dev,
|
||||
"Power limit %dmW not supported. Ranges minimal available: [%d-%d]\n",
|
||||
pw,
|
||||
pw_table->class_pw,
|
||||
pw_table->class_pw + pw_table->max_added_class_pw);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
for (i = 0; i < PD692X0_CLASS_PW_TABLE_SIZE; i++, pw_table++) {
|
||||
if (pw > (pw_table->class_pw + pw_table->max_added_class_pw))
|
||||
continue;
|
||||
|
||||
if (pw < pw_table->class_pw) {
|
||||
dev_err(dev,
|
||||
"Power limit %dmW not supported. Ranges availables: [%d-%d] or [%d-%d]\n",
|
||||
pw,
|
||||
(pw_table - 1)->class_pw,
|
||||
(pw_table - 1)->class_pw + (pw_table - 1)->max_added_class_pw,
|
||||
pw_table->class_pw,
|
||||
pw_table->class_pw + pw_table->max_added_class_pw);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
msg->data[2] = pw_table->class_cfg_value;
|
||||
msg->data[3] = (pw - pw_table->class_pw) / 100;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pw_table--;
|
||||
dev_warn(dev,
|
||||
"Power limit %dmW not supported. Set to highest power limit %dmW\n",
|
||||
pw, pw_table->class_pw + pw_table->max_added_class_pw);
|
||||
msg->data[2] = pw_table->class_cfg_value;
|
||||
msg->data[3] = pw_table->max_added_class_pw / 100;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pd692x0_pi_get_pw_ranges(struct pse_control_status *st)
|
||||
{
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
st->c33_pw_limit_nb_ranges = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pd692x0_ethtool_get_status(struct pse_controller_dev *pcdev,
|
||||
unsigned long id,
|
||||
struct netlink_ext_ack *extack,
|
||||
@@ -442,6 +641,7 @@ static int pd692x0_ethtool_get_status(struct pse_controller_dev *pcdev,
|
||||
{
|
||||
struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
|
||||
struct pd692x0_msg msg, buf = {0};
|
||||
u32 class;
|
||||
int ret;
|
||||
|
||||
ret = pd692x0_fw_unavailable(priv);
|
||||
@@ -471,6 +671,36 @@ static int pd692x0_ethtool_get_status(struct pse_controller_dev *pcdev,
|
||||
|
||||
priv->admin_state[id] = status->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;
|
||||
|
||||
msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_PARAM];
|
||||
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)
|
||||
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);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
class = buf.data[3] >> 4;
|
||||
if (class <= 8)
|
||||
status->c33_pw_class = class;
|
||||
|
||||
ret = pd692x0_pi_get_pw_ranges(status);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -749,12 +979,97 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pd692x0_pi_get_voltage(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_MEAS];
|
||||
msg.sub[2] = id;
|
||||
ret = pd692x0_sendrecv_msg(priv, &msg, &buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Convert 0.1V unit to uV */
|
||||
return (buf.sub[0] << 8 | buf.sub[1]) * 100000;
|
||||
}
|
||||
|
||||
static int pd692x0_pi_get_current_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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int pd692x0_pi_set_current_limit(struct pse_controller_dev *pcdev,
|
||||
int id, int max_uA)
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return pd692x0_sendrecv_msg(priv, &msg, &buf);
|
||||
}
|
||||
|
||||
static const struct pse_controller_ops pd692x0_ops = {
|
||||
.setup_pi_matrix = pd692x0_setup_pi_matrix,
|
||||
.ethtool_get_status = pd692x0_ethtool_get_status,
|
||||
.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,
|
||||
};
|
||||
|
||||
#define PD692X0_FW_LINE_MAX_SZ 0xff
|
||||
|
||||
+161
-11
@@ -265,10 +265,113 @@ static int pse_pi_disable(struct regulator_dev *rdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _pse_pi_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
|
||||
const struct pse_controller_ops *ops;
|
||||
int id;
|
||||
|
||||
ops = pcdev->ops;
|
||||
if (!ops->pi_get_voltage)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
id = rdev_get_id(rdev);
|
||||
return ops->pi_get_voltage(pcdev, id);
|
||||
}
|
||||
|
||||
static int pse_pi_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&pcdev->lock);
|
||||
ret = _pse_pi_get_voltage(rdev);
|
||||
mutex_unlock(&pcdev->lock);
|
||||
|
||||
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;
|
||||
s64 tmp_64;
|
||||
|
||||
ops = pcdev->ops;
|
||||
id = rdev_get_id(rdev);
|
||||
mutex_lock(&pcdev->lock);
|
||||
if (ops->pi_get_current_limit) {
|
||||
ret = ops->pi_get_current_limit(pcdev, id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (!ret) {
|
||||
dev_err(pcdev->dev, "Voltage null\n");
|
||||
ret = -ERANGE;
|
||||
goto out;
|
||||
}
|
||||
if (ret < 0)
|
||||
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 *= 1000000000ull;
|
||||
/* uA = mW * 1000000000 / uV */
|
||||
ret = DIV_ROUND_CLOSEST_ULL(tmp_64, uV);
|
||||
|
||||
out:
|
||||
mutex_unlock(&pcdev->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pse_pi_set_current_limit(struct regulator_dev *rdev, int min_uA,
|
||||
int max_uA)
|
||||
{
|
||||
struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
|
||||
const struct pse_controller_ops *ops;
|
||||
int id, ret;
|
||||
|
||||
ops = pcdev->ops;
|
||||
if (!ops->pi_set_current_limit)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
id = rdev_get_id(rdev);
|
||||
mutex_lock(&pcdev->lock);
|
||||
ret = ops->pi_set_current_limit(pcdev, id, max_uA);
|
||||
mutex_unlock(&pcdev->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct regulator_ops pse_pi_ops = {
|
||||
.is_enabled = pse_pi_is_enabled,
|
||||
.enable = pse_pi_enable,
|
||||
.disable = pse_pi_disable,
|
||||
.get_voltage = pse_pi_get_voltage,
|
||||
.get_current_limit = pse_pi_get_current_limit,
|
||||
.set_current_limit = pse_pi_set_current_limit,
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -298,7 +401,9 @@ devm_pse_pi_regulator_register(struct pse_controller_dev *pcdev,
|
||||
rdesc->ops = &pse_pi_ops;
|
||||
rdesc->owner = pcdev->owner;
|
||||
|
||||
rinit_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
|
||||
rinit_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS |
|
||||
REGULATOR_CHANGE_CURRENT;
|
||||
rinit_data->constraints.max_uA = MAX_PI_CURRENT;
|
||||
rinit_data->supply_regulator = "vpwr";
|
||||
|
||||
rconfig.dev = pcdev->dev;
|
||||
@@ -626,6 +731,23 @@ out:
|
||||
}
|
||||
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
|
||||
@@ -638,19 +760,10 @@ 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);
|
||||
err = _pse_ethtool_get_status(psec->pcdev, psec->id, extack, status);
|
||||
mutex_unlock(&psec->pcdev->lock);
|
||||
|
||||
return err;
|
||||
@@ -732,6 +845,43 @@ int pse_ethtool_set_config(struct pse_control *psec,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pse_ethtool_set_config);
|
||||
|
||||
/**
|
||||
* pse_ethtool_set_pw_limit - set PSE control power limit
|
||||
* @psec: PSE control pointer
|
||||
* @extack: extack for reporting useful error messages
|
||||
* @pw_limit: power limit value in mW
|
||||
*
|
||||
* Return: 0 on success and failure value on error
|
||||
*/
|
||||
int pse_ethtool_set_pw_limit(struct pse_control *psec,
|
||||
struct netlink_ext_ack *extack,
|
||||
const unsigned int pw_limit)
|
||||
{
|
||||
int uV, uA, ret;
|
||||
s64 tmp_64;
|
||||
|
||||
ret = regulator_get_voltage(psec->ps);
|
||||
if (!ret) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"Can't calculate the current, PSE voltage read is 0");
|
||||
return -ERANGE;
|
||||
}
|
||||
if (ret < 0) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"Error reading PSE voltage");
|
||||
return ret;
|
||||
}
|
||||
uV = ret;
|
||||
|
||||
tmp_64 = pw_limit;
|
||||
tmp_64 *= 1000000000ull;
|
||||
/* uA = mW * 1000000000 / uV */
|
||||
uA = DIV_ROUND_CLOSEST_ULL(tmp_64, uV);
|
||||
|
||||
return regulator_set_current_limit(psec->ps, 0, uA);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pse_ethtool_set_pw_limit);
|
||||
|
||||
bool pse_has_podl(struct pse_control *psec)
|
||||
{
|
||||
return psec->pcdev->types & ETHTOOL_PSE_PODL;
|
||||
|
||||
@@ -1273,4 +1273,24 @@ 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 */
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#include <linux/list.h>
|
||||
#include <uapi/linux/ethtool.h>
|
||||
|
||||
/* Maximum current in uA according to IEEE 802.3-2022 Table 145-1 */
|
||||
#define MAX_PI_CURRENT 1920000
|
||||
|
||||
struct phy_device;
|
||||
struct pse_controller_dev;
|
||||
|
||||
@@ -36,12 +39,29 @@ struct pse_control_config {
|
||||
* functions. IEEE 802.3-2022 30.9.1.1.2 aPSEAdminState
|
||||
* @c33_pw_status: power detection status of the PSE.
|
||||
* IEEE 802.3-2022 30.9.1.1.5 aPSEPowerDetectionStatus:
|
||||
* @c33_pw_class: detected class of a powered PD
|
||||
* IEEE 802.3-2022 30.9.1.1.8 aPSEPowerClassification
|
||||
* @c33_actual_pw: power currently delivered by the PSE in mW
|
||||
* IEEE 802.3-2022 30.9.1.1.23 aPSEActualPower
|
||||
* @c33_ext_state_info: extended state information of the PSE
|
||||
* @c33_avail_pw_limit: available power limit of the PSE in mW
|
||||
* IEEE 802.3-2022 145.2.5.4 pse_avail_pwr
|
||||
* @c33_pw_limit_ranges: supported power limit configuration range. The driver
|
||||
* is in charge of the memory allocation.
|
||||
* @c33_pw_limit_nb_ranges: number of supported power limit configuration
|
||||
* ranges
|
||||
*/
|
||||
struct pse_control_status {
|
||||
enum ethtool_podl_pse_admin_state podl_admin_state;
|
||||
enum ethtool_podl_pse_pw_d_status podl_pw_status;
|
||||
enum ethtool_c33_pse_admin_state c33_admin_state;
|
||||
enum ethtool_c33_pse_pw_d_status c33_pw_status;
|
||||
u32 c33_pw_class;
|
||||
u32 c33_actual_pw;
|
||||
struct ethtool_c33_pse_ext_state_info c33_ext_state_info;
|
||||
u32 c33_avail_pw_limit;
|
||||
struct ethtool_c33_pse_pw_limit_range *c33_pw_limit_ranges;
|
||||
u32 c33_pw_limit_nb_ranges;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -53,6 +73,14 @@ struct pse_control_status {
|
||||
* May also return negative errno.
|
||||
* @pi_enable: Configure the PSE PI as enabled.
|
||||
* @pi_disable: Configure the PSE PI as disabled.
|
||||
* @pi_get_voltage: Return voltage similarly to get_voltage regulator
|
||||
* callback.
|
||||
* @pi_get_current_limit: Get the configured current limit similarly to
|
||||
* get_current_limit regulator callback.
|
||||
* @pi_set_current_limit: Configure the current limit similarly to
|
||||
* set_current_limit regulator callback.
|
||||
* Should not return an error in case of MAX_PI_CURRENT
|
||||
* current value set.
|
||||
*/
|
||||
struct pse_controller_ops {
|
||||
int (*ethtool_get_status)(struct pse_controller_dev *pcdev,
|
||||
@@ -62,6 +90,11 @@ struct pse_controller_ops {
|
||||
int (*pi_is_enabled)(struct pse_controller_dev *pcdev, int id);
|
||||
int (*pi_enable)(struct pse_controller_dev *pcdev, int id);
|
||||
int (*pi_disable)(struct pse_controller_dev *pcdev, int id);
|
||||
int (*pi_get_voltage)(struct pse_controller_dev *pcdev, int id);
|
||||
int (*pi_get_current_limit)(struct pse_controller_dev *pcdev,
|
||||
int id);
|
||||
int (*pi_set_current_limit)(struct pse_controller_dev *pcdev,
|
||||
int id, int max_uA);
|
||||
};
|
||||
|
||||
struct module;
|
||||
@@ -148,6 +181,11 @@ int pse_ethtool_get_status(struct pse_control *psec,
|
||||
int pse_ethtool_set_config(struct pse_control *psec,
|
||||
struct netlink_ext_ack *extack,
|
||||
const struct pse_control_config *config);
|
||||
int pse_ethtool_set_pw_limit(struct pse_control *psec,
|
||||
struct netlink_ext_ack *extack,
|
||||
const unsigned int pw_limit);
|
||||
int pse_ethtool_get_pw_limit(struct pse_control *psec,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
bool pse_has_podl(struct pse_control *psec);
|
||||
bool pse_has_c33(struct pse_control *psec);
|
||||
@@ -177,6 +215,19 @@ static inline int pse_ethtool_set_config(struct pse_control *psec,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int pse_ethtool_set_pw_limit(struct pse_control *psec,
|
||||
struct netlink_ext_ack *extack,
|
||||
const unsigned int pw_limit)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int pse_ethtool_get_pw_limit(struct pse_control *psec,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline bool pse_has_podl(struct pse_control *psec)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -752,6 +752,197 @@ enum ethtool_module_power_mode {
|
||||
ETHTOOL_MODULE_POWER_MODE_HIGH,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ethtool_c33_pse_ext_state - groups of PSE extended states
|
||||
* functions. IEEE 802.3-2022 33.2.4.4 Variables
|
||||
*
|
||||
* @ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION: Group of error_condition states
|
||||
* @ETHTOOL_C33_PSE_EXT_STATE_MR_MPS_VALID: Group of mr_mps_valid states
|
||||
* @ETHTOOL_C33_PSE_EXT_STATE_MR_PSE_ENABLE: Group of mr_pse_enable states
|
||||
* @ETHTOOL_C33_PSE_EXT_STATE_OPTION_DETECT_TED: Group of option_detect_ted
|
||||
* states
|
||||
* @ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM: Group of option_vport_lim states
|
||||
* @ETHTOOL_C33_PSE_EXT_STATE_OVLD_DETECTED: Group of ovld_detected states
|
||||
* @ETHTOOL_C33_PSE_EXT_STATE_PD_DLL_POWER_TYPE: Group of pd_dll_power_type
|
||||
* states
|
||||
* @ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE: Group of power_not_available
|
||||
* states
|
||||
* @ETHTOOL_C33_PSE_EXT_STATE_SHORT_DETECTED: Group of short_detected states
|
||||
*/
|
||||
enum ethtool_c33_pse_ext_state {
|
||||
ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION = 1,
|
||||
ETHTOOL_C33_PSE_EXT_STATE_MR_MPS_VALID,
|
||||
ETHTOOL_C33_PSE_EXT_STATE_MR_PSE_ENABLE,
|
||||
ETHTOOL_C33_PSE_EXT_STATE_OPTION_DETECT_TED,
|
||||
ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM,
|
||||
ETHTOOL_C33_PSE_EXT_STATE_OVLD_DETECTED,
|
||||
ETHTOOL_C33_PSE_EXT_STATE_PD_DLL_POWER_TYPE,
|
||||
ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,
|
||||
ETHTOOL_C33_PSE_EXT_STATE_SHORT_DETECTED,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ethtool_c33_pse_ext_substate_mr_mps_valid - mr_mps_valid states
|
||||
* functions. IEEE 802.3-2022 33.2.4.4 Variables
|
||||
*
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_DETECTED_UNDERLOAD: Underload
|
||||
* state
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_CONNECTION_OPEN: Port is not
|
||||
* connected
|
||||
*
|
||||
* The PSE monitors either the DC or AC Maintain Power Signature
|
||||
* (MPS, see 33.2.9.1). This variable indicates the presence or absence of
|
||||
* a valid MPS.
|
||||
*/
|
||||
enum ethtool_c33_pse_ext_substate_mr_mps_valid {
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_DETECTED_UNDERLOAD = 1,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_CONNECTION_OPEN,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ethtool_c33_pse_ext_substate_error_condition - error_condition states
|
||||
* functions. IEEE 802.3-2022 33.2.4.4 Variables
|
||||
*
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_NON_EXISTING_PORT: Non-existing
|
||||
* port number
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNDEFINED_PORT: Undefined port
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_INTERNAL_HW_FAULT: Internal
|
||||
* hardware fault
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_COMM_ERROR_AFTER_FORCE_ON:
|
||||
* Communication error after force on
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS: Unknown
|
||||
* port status
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_HOST_CRASH_TURN_OFF: Host
|
||||
* crash turn off
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_HOST_CRASH_FORCE_SHUTDOWN:
|
||||
* Host crash force shutdown
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_CONFIG_CHANGE: Configuration
|
||||
* change
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_DETECTED_OVER_TEMP: Over
|
||||
* temperature detected
|
||||
*
|
||||
* error_condition is a variable indicating the status of
|
||||
* implementation-specific fault conditions or optionally other system faults
|
||||
* that prevent the PSE from meeting the specifications in Table 33–11 and that
|
||||
* require the PSE not to source power. These error conditions are different
|
||||
* from those monitored by the state diagrams in Figure 33–10.
|
||||
*/
|
||||
enum ethtool_c33_pse_ext_substate_error_condition {
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_NON_EXISTING_PORT = 1,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNDEFINED_PORT,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_INTERNAL_HW_FAULT,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_COMM_ERROR_AFTER_FORCE_ON,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_HOST_CRASH_TURN_OFF,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_HOST_CRASH_FORCE_SHUTDOWN,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_CONFIG_CHANGE,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_DETECTED_OVER_TEMP,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ethtool_c33_pse_ext_substate_mr_pse_enable - mr_pse_enable states
|
||||
* functions. IEEE 802.3-2022 33.2.4.4 Variables
|
||||
*
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_PSE_ENABLE_DISABLE_PIN_ACTIVE: Disable
|
||||
* pin active
|
||||
*
|
||||
* mr_pse_enable is control variable that selects PSE operation and test
|
||||
* functions.
|
||||
*/
|
||||
enum ethtool_c33_pse_ext_substate_mr_pse_enable {
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_PSE_ENABLE_DISABLE_PIN_ACTIVE = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ethtool_c33_pse_ext_substate_option_detect_ted - option_detect_ted
|
||||
* states functions. IEEE 802.3-2022 33.2.4.4 Variables
|
||||
*
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_DET_IN_PROCESS: Detection
|
||||
* in process
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_CONNECTION_CHECK_ERROR:
|
||||
* Connection check error
|
||||
*
|
||||
* option_detect_ted is a variable indicating if detection can be performed
|
||||
* by the PSE during the ted_timer interval.
|
||||
*/
|
||||
enum ethtool_c33_pse_ext_substate_option_detect_ted {
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_DET_IN_PROCESS = 1,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_CONNECTION_CHECK_ERROR,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ethtool_c33_pse_ext_substate_option_vport_lim - option_vport_lim states
|
||||
* functions. IEEE 802.3-2022 33.2.4.4 Variables
|
||||
*
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_HIGH_VOLTAGE: Main supply
|
||||
* voltage is high
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_LOW_VOLTAGE: Main supply
|
||||
* voltage is low
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_VOLTAGE_INJECTION: Voltage
|
||||
* injection into the port
|
||||
*
|
||||
* option_vport_lim is an optional variable indicates if VPSE is out of the
|
||||
* operating range during normal operating state.
|
||||
*/
|
||||
enum ethtool_c33_pse_ext_substate_option_vport_lim {
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_HIGH_VOLTAGE = 1,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_LOW_VOLTAGE,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_VOLTAGE_INJECTION,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ethtool_c33_pse_ext_substate_ovld_detected - ovld_detected states
|
||||
* functions. IEEE 802.3-2022 33.2.4.4 Variables
|
||||
*
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_OVLD_DETECTED_OVERLOAD: Overload state
|
||||
*
|
||||
* ovld_detected is a variable indicating if the PSE output current has been
|
||||
* in an overload condition (see 33.2.7.6) for at least TCUT of a one-second
|
||||
* sliding time.
|
||||
*/
|
||||
enum ethtool_c33_pse_ext_substate_ovld_detected {
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_OVLD_DETECTED_OVERLOAD = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ethtool_c33_pse_ext_substate_power_not_available - power_not_available
|
||||
* states functions. IEEE 802.3-2022 33.2.4.4 Variables
|
||||
*
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_BUDGET_EXCEEDED: Power
|
||||
* budget exceeded for the controller
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PORT_PW_LIMIT_EXCEEDS_CONTROLLER_BUDGET:
|
||||
* Configured port power limit exceeded controller power budget
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PD_REQUEST_EXCEEDS_PORT_LIMIT:
|
||||
* Power request from PD exceeds port limit
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_HW_PW_LIMIT: Power
|
||||
* denied due to Hardware power limit
|
||||
*
|
||||
* power_not_available is a variable that is asserted in an
|
||||
* implementation-dependent manner when the PSE is no longer capable of
|
||||
* sourcing sufficient power to support the attached PD. Sufficient power
|
||||
* is defined by classification; see 33.2.6.
|
||||
*/
|
||||
enum ethtool_c33_pse_ext_substate_power_not_available {
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_BUDGET_EXCEEDED = 1,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PORT_PW_LIMIT_EXCEEDS_CONTROLLER_BUDGET,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PD_REQUEST_EXCEEDS_PORT_LIMIT,
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_HW_PW_LIMIT,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ethtool_c33_pse_ext_substate_short_detected - short_detected states
|
||||
* functions. IEEE 802.3-2022 33.2.4.4 Variables
|
||||
*
|
||||
* @ETHTOOL_C33_PSE_EXT_SUBSTATE_SHORT_DETECTED_SHORT_CONDITION: Short
|
||||
* condition was detected
|
||||
*
|
||||
* short_detected is a variable indicating if the PSE output current has been
|
||||
* in a short circuit condition for TLIM within a sliding window (see 33.2.7.7).
|
||||
*/
|
||||
enum ethtool_c33_pse_ext_substate_short_detected {
|
||||
ETHTOOL_C33_PSE_EXT_SUBSTATE_SHORT_DETECTED_SHORT_CONDITION = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ethtool_pse_types - Types of PSE controller.
|
||||
* @ETHTOOL_PSE_UNKNOWN: Type of PSE controller is unknown
|
||||
|
||||
@@ -930,6 +930,12 @@ enum {
|
||||
};
|
||||
|
||||
/* Power Sourcing Equipment */
|
||||
enum {
|
||||
ETHTOOL_A_C33_PSE_PW_LIMIT_UNSPEC,
|
||||
ETHTOOL_A_C33_PSE_PW_LIMIT_MIN, /* u32 */
|
||||
ETHTOOL_A_C33_PSE_PW_LIMIT_MAX, /* u32 */
|
||||
};
|
||||
|
||||
enum {
|
||||
ETHTOOL_A_PSE_UNSPEC,
|
||||
ETHTOOL_A_PSE_HEADER, /* nest - _A_HEADER_* */
|
||||
@@ -939,6 +945,12 @@ enum {
|
||||
ETHTOOL_A_C33_PSE_ADMIN_STATE, /* u32 */
|
||||
ETHTOOL_A_C33_PSE_ADMIN_CONTROL, /* u32 */
|
||||
ETHTOOL_A_C33_PSE_PW_D_STATUS, /* u32 */
|
||||
ETHTOOL_A_C33_PSE_PW_CLASS, /* u32 */
|
||||
ETHTOOL_A_C33_PSE_ACTUAL_PW, /* u32 */
|
||||
ETHTOOL_A_C33_PSE_EXT_STATE, /* u32 */
|
||||
ETHTOOL_A_C33_PSE_EXT_SUBSTATE, /* u32 */
|
||||
ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT, /* u32 */
|
||||
ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES, /* nest - _C33_PSE_PW_LIMIT_* */
|
||||
|
||||
/* add new constants above here */
|
||||
__ETHTOOL_A_PSE_CNT,
|
||||
|
||||
+113
-8
@@ -86,10 +86,56 @@ static int pse_reply_size(const struct ethnl_req_info *req_base,
|
||||
len += nla_total_size(sizeof(u32)); /* _C33_PSE_ADMIN_STATE */
|
||||
if (st->c33_pw_status > 0)
|
||||
len += nla_total_size(sizeof(u32)); /* _C33_PSE_PW_D_STATUS */
|
||||
if (st->c33_pw_class > 0)
|
||||
len += nla_total_size(sizeof(u32)); /* _C33_PSE_PW_CLASS */
|
||||
if (st->c33_actual_pw > 0)
|
||||
len += nla_total_size(sizeof(u32)); /* _C33_PSE_ACTUAL_PW */
|
||||
if (st->c33_ext_state_info.c33_pse_ext_state > 0) {
|
||||
len += nla_total_size(sizeof(u32)); /* _C33_PSE_EXT_STATE */
|
||||
if (st->c33_ext_state_info.__c33_pse_ext_substate > 0)
|
||||
/* _C33_PSE_EXT_SUBSTATE */
|
||||
len += nla_total_size(sizeof(u32));
|
||||
}
|
||||
if (st->c33_avail_pw_limit > 0)
|
||||
/* _C33_AVAIL_PSE_PW_LIMIT */
|
||||
len += nla_total_size(sizeof(u32));
|
||||
if (st->c33_pw_limit_nb_ranges > 0)
|
||||
/* _C33_PSE_PW_LIMIT_RANGES */
|
||||
len += st->c33_pw_limit_nb_ranges *
|
||||
(nla_total_size(0) +
|
||||
nla_total_size(sizeof(u32)) * 2);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int pse_put_pw_limit_ranges(struct sk_buff *skb,
|
||||
const struct pse_control_status *st)
|
||||
{
|
||||
const struct ethtool_c33_pse_pw_limit_range *pw_limit_ranges;
|
||||
int i;
|
||||
|
||||
pw_limit_ranges = st->c33_pw_limit_ranges;
|
||||
for (i = 0; i < st->c33_pw_limit_nb_ranges; i++) {
|
||||
struct nlattr *nest;
|
||||
|
||||
nest = nla_nest_start(skb, ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES);
|
||||
if (!nest)
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (nla_put_u32(skb, ETHTOOL_A_C33_PSE_PW_LIMIT_MIN,
|
||||
pw_limit_ranges->min) ||
|
||||
nla_put_u32(skb, ETHTOOL_A_C33_PSE_PW_LIMIT_MAX,
|
||||
pw_limit_ranges->max)) {
|
||||
nla_nest_cancel(skb, nest);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
nla_nest_end(skb, nest);
|
||||
pw_limit_ranges++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pse_fill_reply(struct sk_buff *skb,
|
||||
const struct ethnl_req_info *req_base,
|
||||
const struct ethnl_reply_data *reply_base)
|
||||
@@ -117,9 +163,46 @@ static int pse_fill_reply(struct sk_buff *skb,
|
||||
st->c33_pw_status))
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (st->c33_pw_class > 0 &&
|
||||
nla_put_u32(skb, ETHTOOL_A_C33_PSE_PW_CLASS,
|
||||
st->c33_pw_class))
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (st->c33_actual_pw > 0 &&
|
||||
nla_put_u32(skb, ETHTOOL_A_C33_PSE_ACTUAL_PW,
|
||||
st->c33_actual_pw))
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (st->c33_ext_state_info.c33_pse_ext_state > 0) {
|
||||
if (nla_put_u32(skb, ETHTOOL_A_C33_PSE_EXT_STATE,
|
||||
st->c33_ext_state_info.c33_pse_ext_state))
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (st->c33_ext_state_info.__c33_pse_ext_substate > 0 &&
|
||||
nla_put_u32(skb, ETHTOOL_A_C33_PSE_EXT_SUBSTATE,
|
||||
st->c33_ext_state_info.__c33_pse_ext_substate))
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (st->c33_avail_pw_limit > 0 &&
|
||||
nla_put_u32(skb, ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT,
|
||||
st->c33_avail_pw_limit))
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (st->c33_pw_limit_nb_ranges > 0 &&
|
||||
pse_put_pw_limit_ranges(skb, st))
|
||||
return -EMSGSIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pse_cleanup_data(struct ethnl_reply_data *reply_base)
|
||||
{
|
||||
const struct pse_reply_data *data = PSE_REPDATA(reply_base);
|
||||
|
||||
kfree(data->status.c33_pw_limit_ranges);
|
||||
}
|
||||
|
||||
/* PSE_SET */
|
||||
|
||||
const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1] = {
|
||||
@@ -130,6 +213,7 @@ const struct nla_policy ethnl_pse_set_policy[ETHTOOL_A_PSE_MAX + 1] = {
|
||||
[ETHTOOL_A_C33_PSE_ADMIN_CONTROL] =
|
||||
NLA_POLICY_RANGE(NLA_U32, ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED,
|
||||
ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED),
|
||||
[ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -172,19 +256,39 @@ static int
|
||||
ethnl_set_pse(struct ethnl_req_info *req_info, struct genl_info *info)
|
||||
{
|
||||
struct net_device *dev = req_info->dev;
|
||||
struct pse_control_config config = {};
|
||||
struct nlattr **tb = info->attrs;
|
||||
struct phy_device *phydev;
|
||||
int ret = 0;
|
||||
|
||||
phydev = dev->phydev;
|
||||
/* These values are already validated by the ethnl_pse_set_policy */
|
||||
if (pse_has_podl(phydev->psec))
|
||||
config.podl_admin_control = nla_get_u32(tb[ETHTOOL_A_PODL_PSE_ADMIN_CONTROL]);
|
||||
if (pse_has_c33(phydev->psec))
|
||||
config.c33_admin_control = nla_get_u32(tb[ETHTOOL_A_C33_PSE_ADMIN_CONTROL]);
|
||||
|
||||
/* Return errno directly - PSE has no notification */
|
||||
return pse_ethtool_set_config(phydev->psec, info->extack, &config);
|
||||
if (tb[ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT]) {
|
||||
unsigned int pw_limit;
|
||||
|
||||
pw_limit = nla_get_u32(tb[ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT]);
|
||||
ret = pse_ethtool_set_pw_limit(phydev->psec, info->extack,
|
||||
pw_limit);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* These values are already validated by the ethnl_pse_set_policy */
|
||||
if (tb[ETHTOOL_A_PODL_PSE_ADMIN_CONTROL] ||
|
||||
tb[ETHTOOL_A_C33_PSE_ADMIN_CONTROL]) {
|
||||
struct pse_control_config config = {};
|
||||
|
||||
if (pse_has_podl(phydev->psec))
|
||||
config.podl_admin_control = nla_get_u32(tb[ETHTOOL_A_PODL_PSE_ADMIN_CONTROL]);
|
||||
if (pse_has_c33(phydev->psec))
|
||||
config.c33_admin_control = nla_get_u32(tb[ETHTOOL_A_C33_PSE_ADMIN_CONTROL]);
|
||||
|
||||
ret = pse_ethtool_set_config(phydev->psec, info->extack,
|
||||
&config);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct ethnl_request_ops ethnl_pse_request_ops = {
|
||||
@@ -197,6 +301,7 @@ const struct ethnl_request_ops ethnl_pse_request_ops = {
|
||||
.prepare_data = pse_prepare_data,
|
||||
.reply_size = pse_reply_size,
|
||||
.fill_reply = pse_fill_reply,
|
||||
.cleanup_data = pse_cleanup_data,
|
||||
|
||||
.set_validate = ethnl_set_pse_validate,
|
||||
.set = ethnl_set_pse,
|
||||
|
||||
Reference in New Issue
Block a user