Merge branch 'dpll-expose-lock-status-error-value-to-user'

Jiri Pirko says:

====================
dpll: expose lock status error value to user

From: Jiri Pirko <jiri@nvidia.com>

Allow to expose lock status errort value over new DPLL generic netlink
attribute. Extend the lock_status_get() op by new argument to get the
value from the driver. Implement this new argument fill-up
in mlx5 driver.
====================

Link: https://lore.kernel.org/r/20240130120831.261085-1-jiri@resnulli.us
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Paolo Abeni 2024-02-01 15:39:46 +01:00
commit cacfd6bfc3
8 changed files with 121 additions and 9 deletions

View file

@ -51,6 +51,40 @@ definitions:
if dpll lock-state was not DPLL_LOCK_STATUS_LOCKED_HO_ACQ, the
dpll's lock-state shall remain DPLL_LOCK_STATUS_UNLOCKED)
render-max: true
-
type: enum
name: lock-status-error
doc: |
if previous status change was done due to a failure, this provides
information of dpll device lock status error.
Valid values for DPLL_A_LOCK_STATUS_ERROR attribute
entries:
-
name: none
doc: |
dpll device lock status was changed without any error
value: 1
-
name: undefined
doc: |
dpll device lock status was changed due to undefined error.
Driver fills this value up in case it is not able
to obtain suitable exact error type.
-
name: media-down
doc: |
dpll device lock status was changed because of associated
media got down.
This may happen for example if dpll device was previously
locked on an input pin of type PIN_TYPE_SYNCE_ETH_PORT.
-
name: fractional-frequency-offset-too-high
doc: |
the FFO (Fractional Frequency Offset) between the RX and TX
symbol rate on the media got too high.
This may happen for example if dpll device was previously
locked on an input pin of type PIN_TYPE_SYNCE_ETH_PORT.
render-max: true
-
type: const
name: temp-divider
@ -214,6 +248,10 @@ attribute-sets:
name: type
type: u32
enum: type
-
name: lock-status-error
type: u32
enum: lock-status-error
-
name: pin
enum-name: dpll_a_pin
@ -379,6 +417,7 @@ operations:
- mode
- mode-supported
- lock-status
- lock-status-error
- temp
- clock-id
- type

View file

@ -121,14 +121,21 @@ dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll,
struct netlink_ext_ack *extack)
{
const struct dpll_device_ops *ops = dpll_device_ops(dpll);
enum dpll_lock_status_error status_error = 0;
enum dpll_lock_status status;
int ret;
ret = ops->lock_status_get(dpll, dpll_priv(dpll), &status, extack);
ret = ops->lock_status_get(dpll, dpll_priv(dpll), &status,
&status_error, extack);
if (ret)
return ret;
if (nla_put_u32(msg, DPLL_A_LOCK_STATUS, status))
return -EMSGSIZE;
if (status_error &&
(status == DPLL_LOCK_STATUS_UNLOCKED ||
status == DPLL_LOCK_STATUS_HOLDOVER) &&
nla_put_u32(msg, DPLL_A_LOCK_STATUS_ERROR, status_error))
return -EMSGSIZE;
return 0;
}

View file

@ -488,6 +488,7 @@ ice_dpll_hw_input_prio_set(struct ice_pf *pf, struct ice_dpll *dpll,
* @dpll: registered dpll pointer
* @dpll_priv: private data pointer passed on dpll registration
* @status: on success holds dpll's lock status
* @status_error: status error value
* @extack: error reporting
*
* Dpll subsystem callback, provides dpll's lock status.
@ -500,6 +501,7 @@ ice_dpll_hw_input_prio_set(struct ice_pf *pf, struct ice_dpll *dpll,
static int
ice_dpll_lock_status_get(const struct dpll_device *dpll, void *dpll_priv,
enum dpll_lock_status *status,
enum dpll_lock_status_error *status_error,
struct netlink_ext_ack *extack)
{
struct ice_dpll *d = dpll_priv;

View file

@ -41,6 +41,7 @@ struct mlx5_dpll_synce_status {
enum mlx5_msees_oper_status oper_status;
bool ho_acq;
bool oper_freq_measure;
enum mlx5_msees_failure_reason failure_reason;
s32 frequency_diff;
};
@ -60,6 +61,7 @@ mlx5_dpll_synce_status_get(struct mlx5_core_dev *mdev,
synce_status->oper_status = MLX5_GET(msees_reg, out, oper_status);
synce_status->ho_acq = MLX5_GET(msees_reg, out, ho_acq);
synce_status->oper_freq_measure = MLX5_GET(msees_reg, out, oper_freq_measure);
synce_status->failure_reason = MLX5_GET(msees_reg, out, failure_reason);
synce_status->frequency_diff = MLX5_GET(msees_reg, out, frequency_diff);
return 0;
}
@ -99,6 +101,26 @@ mlx5_dpll_lock_status_get(struct mlx5_dpll_synce_status *synce_status)
}
}
static enum dpll_lock_status_error
mlx5_dpll_lock_status_error_get(struct mlx5_dpll_synce_status *synce_status)
{
switch (synce_status->oper_status) {
case MLX5_MSEES_OPER_STATUS_FAIL_HOLDOVER:
fallthrough;
case MLX5_MSEES_OPER_STATUS_FAIL_FREE_RUNNING:
switch (synce_status->failure_reason) {
case MLX5_MSEES_FAILURE_REASON_PORT_DOWN:
return DPLL_LOCK_STATUS_ERROR_MEDIA_DOWN;
case MLX5_MSEES_FAILURE_REASON_TOO_HIGH_FREQUENCY_DIFF:
return DPLL_LOCK_STATUS_ERROR_FRACTIONAL_FREQUENCY_OFFSET_TOO_HIGH;
default:
return DPLL_LOCK_STATUS_ERROR_UNDEFINED;
}
default:
return DPLL_LOCK_STATUS_ERROR_NONE;
}
}
static enum dpll_pin_state
mlx5_dpll_pin_state_get(struct mlx5_dpll_synce_status *synce_status)
{
@ -118,10 +140,11 @@ mlx5_dpll_pin_ffo_get(struct mlx5_dpll_synce_status *synce_status,
return 0;
}
static int mlx5_dpll_device_lock_status_get(const struct dpll_device *dpll,
void *priv,
enum dpll_lock_status *status,
struct netlink_ext_ack *extack)
static int
mlx5_dpll_device_lock_status_get(const struct dpll_device *dpll, void *priv,
enum dpll_lock_status *status,
enum dpll_lock_status_error *status_error,
struct netlink_ext_ack *extack)
{
struct mlx5_dpll_synce_status synce_status;
struct mlx5_dpll *mdpll = priv;
@ -131,6 +154,7 @@ static int mlx5_dpll_device_lock_status_get(const struct dpll_device *dpll,
if (err)
return err;
*status = mlx5_dpll_lock_status_get(&synce_status);
*status_error = mlx5_dpll_lock_status_error_get(&synce_status);
return 0;
}

View file

@ -4209,10 +4209,11 @@ ptp_ocp_detach(struct ptp_ocp *bp)
device_unregister(&bp->dev);
}
static int ptp_ocp_dpll_lock_status_get(const struct dpll_device *dpll,
void *priv,
enum dpll_lock_status *status,
struct netlink_ext_ack *extack)
static int
ptp_ocp_dpll_lock_status_get(const struct dpll_device *dpll, void *priv,
enum dpll_lock_status *status,
enum dpll_lock_status_error *status_error,
struct netlink_ext_ack *extack)
{
struct ptp_ocp *bp = priv;

View file

@ -19,6 +19,7 @@ struct dpll_device_ops {
enum dpll_mode *mode, struct netlink_ext_ack *extack);
int (*lock_status_get)(const struct dpll_device *dpll, void *dpll_priv,
enum dpll_lock_status *status,
enum dpll_lock_status_error *status_error,
struct netlink_ext_ack *extack);
int (*temp_get)(const struct dpll_device *dpll, void *dpll_priv,
s32 *temp, struct netlink_ext_ack *extack);

View file

@ -12705,6 +12705,14 @@ enum mlx5_msees_oper_status {
MLX5_MSEES_OPER_STATUS_FAIL_FREE_RUNNING = 0x5,
};
enum mlx5_msees_failure_reason {
MLX5_MSEES_FAILURE_REASON_UNDEFINED_ERROR = 0x0,
MLX5_MSEES_FAILURE_REASON_PORT_DOWN = 0x1,
MLX5_MSEES_FAILURE_REASON_TOO_HIGH_FREQUENCY_DIFF = 0x2,
MLX5_MSEES_FAILURE_REASON_NET_SYNCHRONIZER_DEVICE_ERROR = 0x3,
MLX5_MSEES_FAILURE_REASON_LACK_OF_RESOURCES = 0x4,
};
struct mlx5_ifc_msees_reg_bits {
u8 reserved_at_0[0x8];
u8 local_port[0x8];

View file

@ -50,6 +50,35 @@ enum dpll_lock_status {
DPLL_LOCK_STATUS_MAX = (__DPLL_LOCK_STATUS_MAX - 1)
};
/**
* enum dpll_lock_status_error - if previous status change was done due to a
* failure, this provides information of dpll device lock status error. Valid
* values for DPLL_A_LOCK_STATUS_ERROR attribute
* @DPLL_LOCK_STATUS_ERROR_NONE: dpll device lock status was changed without
* any error
* @DPLL_LOCK_STATUS_ERROR_UNDEFINED: dpll device lock status was changed due
* to undefined error. Driver fills this value up in case it is not able to
* obtain suitable exact error type.
* @DPLL_LOCK_STATUS_ERROR_MEDIA_DOWN: dpll device lock status was changed
* because of associated media got down. This may happen for example if dpll
* device was previously locked on an input pin of type
* PIN_TYPE_SYNCE_ETH_PORT.
* @DPLL_LOCK_STATUS_ERROR_FRACTIONAL_FREQUENCY_OFFSET_TOO_HIGH: the FFO
* (Fractional Frequency Offset) between the RX and TX symbol rate on the
* media got too high. This may happen for example if dpll device was
* previously locked on an input pin of type PIN_TYPE_SYNCE_ETH_PORT.
*/
enum dpll_lock_status_error {
DPLL_LOCK_STATUS_ERROR_NONE = 1,
DPLL_LOCK_STATUS_ERROR_UNDEFINED,
DPLL_LOCK_STATUS_ERROR_MEDIA_DOWN,
DPLL_LOCK_STATUS_ERROR_FRACTIONAL_FREQUENCY_OFFSET_TOO_HIGH,
/* private: */
__DPLL_LOCK_STATUS_ERROR_MAX,
DPLL_LOCK_STATUS_ERROR_MAX = (__DPLL_LOCK_STATUS_ERROR_MAX - 1)
};
#define DPLL_TEMP_DIVIDER 1000
/**
@ -150,6 +179,7 @@ enum dpll_a {
DPLL_A_LOCK_STATUS,
DPLL_A_TEMP,
DPLL_A_TYPE,
DPLL_A_LOCK_STATUS_ERROR,
__DPLL_A_MAX,
DPLL_A_MAX = (__DPLL_A_MAX - 1)