Commit cacfd6bf authored by Paolo Abeni's avatar Paolo Abeni

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.usSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 644c6431 2c54a4d7
......@@ -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
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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];
......
......@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment