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. ====================
Unified · Split
| @@ -51,6 +51,40 @@ definitions: · 50 unmodified lines | ||
| 51 | 51 | if dpll lock-state was not DPLL_LOCK_STATUS_LOCKED_HO_ACQ, the |
| 52 | 52 | dpll's lock-state shall remain DPLL_LOCK_STATUS_UNLOCKED) |
| 53 | 53 | render-max: true |
| 54 | + - | |
| 55 | + type: enum | |
| 56 | + name: lock-status-error | |
| 57 | + doc: | | |
| 58 | + if previous status change was done due to a failure, this provides | |
| 59 | + information of dpll device lock status error. | |
| 60 | + Valid values for DPLL_A_LOCK_STATUS_ERROR attribute | |
| 61 | + entries: | |
| 62 | + - | |
| 63 | + name: none | |
| 64 | + doc: | | |
| 65 | + dpll device lock status was changed without any error | |
| 66 | + value: 1 | |
| 67 | + - | |
| 68 | + name: undefined | |
| 69 | + doc: | | |
| 70 | + dpll device lock status was changed due to undefined error. | |
| 71 | + Driver fills this value up in case it is not able | |
| 72 | + to obtain suitable exact error type. | |
| 73 | + - | |
| 74 | + name: media-down | |
| 75 | + doc: | | |
| 76 | + dpll device lock status was changed because of associated | |
| 77 | + media got down. | |
| 78 | + This may happen for example if dpll device was previously | |
| 79 | + locked on an input pin of type PIN_TYPE_SYNCE_ETH_PORT. | |
| 80 | + - | |
| 81 | + name: fractional-frequency-offset-too-high | |
| 82 | + doc: | | |
| 83 | + the FFO (Fractional Frequency Offset) between the RX and TX | |
| 84 | + symbol rate on the media got too high. | |
| 85 | + This may happen for example if dpll device was previously | |
| 86 | + locked on an input pin of type PIN_TYPE_SYNCE_ETH_PORT. | |
| 87 | + render-max: true | |
| 54 | 88 | - |
| 55 | 89 | type: const |
| 56 | 90 | name: temp-divider |
| @@ -214,6 +248,10 @@ attribute-sets: · 157 unmodified lines | ||
| 214 | 248 | name: type |
| 215 | 249 | type: u32 |
| 216 | 250 | enum: type |
| 251 | + - | |
| 252 | + name: lock-status-error | |
| 253 | + type: u32 | |
| 254 | + enum: lock-status-error | |
| 217 | 255 | - |
| 218 | 256 | name: pin |
| 219 | 257 | enum-name: dpll_a_pin |
| @@ -379,6 +417,7 @@ operations: · 159 unmodified lines | ||
| 379 | 417 | - mode |
| 380 | 418 | - mode-supported |
| 381 | 419 | - lock-status |
| 420 | + - lock-status-error | |
| 382 | 421 | - temp |
| 383 | 422 | - clock-id |
| 384 | 423 | - type |
| @@ -121,14 +121,21 @@ dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll, · 120 unmodified lines | ||
| 121 | 121 | struct netlink_ext_ack *extack) |
| 122 | 122 | { |
| 123 | 123 | const struct dpll_device_ops *ops = dpll_device_ops(dpll); |
| 124 | + enum dpll_lock_status_error status_error = 0; | |
| 124 | 125 | enum dpll_lock_status status; |
| 125 | 126 | int ret; |
| 126 | 127 | |
| 127 | − ret = ops->lock_status_get(dpll, dpll_priv(dpll), &status, extack); | |
| 128 | + ret = ops->lock_status_get(dpll, dpll_priv(dpll), &status, | |
| 129 | + &status_error, extack); | |
| 128 | 130 | if (ret) |
| 129 | 131 | return ret; |
| 130 | 132 | if (nla_put_u32(msg, DPLL_A_LOCK_STATUS, status)) |
| 131 | 133 | return -EMSGSIZE; |
| 134 | + if (status_error && | |
| 135 | + (status == DPLL_LOCK_STATUS_UNLOCKED || | |
| 136 | + status == DPLL_LOCK_STATUS_HOLDOVER) && | |
| 137 | + nla_put_u32(msg, DPLL_A_LOCK_STATUS_ERROR, status_error)) | |
| 138 | + return -EMSGSIZE; | |
| 132 | 139 | |
| 133 | 140 | return 0; |
| 134 | 141 | } |
| @@ -488,6 +488,7 @@ ice_dpll_hw_input_prio_set(struct ice_pf *pf, struct ice_dpll *dpll, · 487 unmodified lines | ||
| 488 | 488 | * @dpll: registered dpll pointer |
| 489 | 489 | * @dpll_priv: private data pointer passed on dpll registration |
| 490 | 490 | * @status: on success holds dpll's lock status |
| 491 | + * @status_error: status error value | |
| 491 | 492 | * @extack: error reporting |
| 492 | 493 | * |
| 493 | 494 | * 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, · 6 unmodified lines | ||
| 500 | 501 | static int |
| 501 | 502 | ice_dpll_lock_status_get(const struct dpll_device *dpll, void *dpll_priv, |
| 502 | 503 | enum dpll_lock_status *status, |
| 504 | + enum dpll_lock_status_error *status_error, | |
| 503 | 505 | struct netlink_ext_ack *extack) |
| 504 | 506 | { |
| 505 | 507 | struct ice_dpll *d = dpll_priv; |
| @@ -41,6 +41,7 @@ struct mlx5_dpll_synce_status { · 40 unmodified lines | ||
| 41 | 41 | enum mlx5_msees_oper_status oper_status; |
| 42 | 42 | bool ho_acq; |
| 43 | 43 | bool oper_freq_measure; |
| 44 | + enum mlx5_msees_failure_reason failure_reason; | |
| 44 | 45 | s32 frequency_diff; |
| 45 | 46 | }; |
| 46 | 47 | |
| @@ -60,6 +61,7 @@ mlx5_dpll_synce_status_get(struct mlx5_core_dev *mdev, · 13 unmodified lines | ||
| 60 | 61 | synce_status->oper_status = MLX5_GET(msees_reg, out, oper_status); |
| 61 | 62 | synce_status->ho_acq = MLX5_GET(msees_reg, out, ho_acq); |
| 62 | 63 | synce_status->oper_freq_measure = MLX5_GET(msees_reg, out, oper_freq_measure); |
| 64 | + synce_status->failure_reason = MLX5_GET(msees_reg, out, failure_reason); | |
| 63 | 65 | synce_status->frequency_diff = MLX5_GET(msees_reg, out, frequency_diff); |
| 64 | 66 | return 0; |
| 65 | 67 | } |
| @@ -99,6 +101,26 @@ mlx5_dpll_lock_status_get(struct mlx5_dpll_synce_status *synce_status) · 33 unmodified lines | ||
| 99 | 101 | } |
| 100 | 102 | } |
| 101 | 103 | |
| 104 | +static enum dpll_lock_status_error | |
| 105 | +mlx5_dpll_lock_status_error_get(struct mlx5_dpll_synce_status *synce_status) | |
| 106 | +{ | |
| 107 | + switch (synce_status->oper_status) { | |
| 108 | + case MLX5_MSEES_OPER_STATUS_FAIL_HOLDOVER: | |
| 109 | + fallthrough; | |
| 110 | + case MLX5_MSEES_OPER_STATUS_FAIL_FREE_RUNNING: | |
| 111 | + switch (synce_status->failure_reason) { | |
| 112 | + case MLX5_MSEES_FAILURE_REASON_PORT_DOWN: | |
| 113 | + return DPLL_LOCK_STATUS_ERROR_MEDIA_DOWN; | |
| 114 | + case MLX5_MSEES_FAILURE_REASON_TOO_HIGH_FREQUENCY_DIFF: | |
| 115 | + return DPLL_LOCK_STATUS_ERROR_FRACTIONAL_FREQUENCY_OFFSET_TOO_HIGH; | |
| 116 | + default: | |
| 117 | + return DPLL_LOCK_STATUS_ERROR_UNDEFINED; | |
| 118 | + } | |
| 119 | + default: | |
| 120 | + return DPLL_LOCK_STATUS_ERROR_NONE; | |
| 121 | + } | |
| 122 | +} | |
| 123 | + | |
| 102 | 124 | static enum dpll_pin_state |
| 103 | 125 | mlx5_dpll_pin_state_get(struct mlx5_dpll_synce_status *synce_status) |
| 104 | 126 | { |
| @@ -118,10 +140,11 @@ mlx5_dpll_pin_ffo_get(struct mlx5_dpll_synce_status *synce_status, · 13 unmodified lines | ||
| 118 | 140 | return 0; |
| 119 | 141 | } |
| 120 | 142 | |
| 121 | −static int mlx5_dpll_device_lock_status_get(const struct dpll_device *dpll, | |
| 122 | − void *priv, | |
| 123 | − enum dpll_lock_status *status, | |
| 124 | − struct netlink_ext_ack *extack) | |
| 143 | +static int | |
| 144 | +mlx5_dpll_device_lock_status_get(const struct dpll_device *dpll, void *priv, | |
| 145 | + enum dpll_lock_status *status, | |
| 146 | + enum dpll_lock_status_error *status_error, | |
| 147 | + struct netlink_ext_ack *extack) | |
| 125 | 148 | { |
| 126 | 149 | struct mlx5_dpll_synce_status synce_status; |
| 127 | 150 | struct mlx5_dpll *mdpll = priv; |
| @@ -131,6 +154,7 @@ static int mlx5_dpll_device_lock_status_get(const struct dpll_device *dpll, · 3 unmodified lines | ||
| 131 | 154 | if (err) |
| 132 | 155 | return err; |
| 133 | 156 | *status = mlx5_dpll_lock_status_get(&synce_status); |
| 157 | + *status_error = mlx5_dpll_lock_status_error_get(&synce_status); | |
| 134 | 158 | return 0; |
| 135 | 159 | } |
| 136 | 160 | |
| @@ -4209,10 +4209,11 @@ ptp_ocp_detach(struct ptp_ocp *bp) · 4208 unmodified lines | ||
| 4209 | 4209 | device_unregister(&bp->dev); |
| 4210 | 4210 | } |
| 4211 | 4211 | |
| 4212 | −static int ptp_ocp_dpll_lock_status_get(const struct dpll_device *dpll, | |
| 4213 | − void *priv, | |
| 4214 | − enum dpll_lock_status *status, | |
| 4215 | − struct netlink_ext_ack *extack) | |
| 4212 | +static int | |
| 4213 | +ptp_ocp_dpll_lock_status_get(const struct dpll_device *dpll, void *priv, | |
| 4214 | + enum dpll_lock_status *status, | |
| 4215 | + enum dpll_lock_status_error *status_error, | |
| 4216 | + struct netlink_ext_ack *extack) | |
| 4216 | 4217 | { |
| 4217 | 4218 | struct ptp_ocp *bp = priv; |
| 4218 | 4219 | |
| @@ -19,6 +19,7 @@ struct dpll_device_ops { · 18 unmodified lines | ||
| 19 | 19 | enum dpll_mode *mode, struct netlink_ext_ack *extack); |
| 20 | 20 | int (*lock_status_get)(const struct dpll_device *dpll, void *dpll_priv, |
| 21 | 21 | enum dpll_lock_status *status, |
| 22 | + enum dpll_lock_status_error *status_error, | |
| 22 | 23 | struct netlink_ext_ack *extack); |
| 23 | 24 | int (*temp_get)(const struct dpll_device *dpll, void *dpll_priv, |
| 24 | 25 | s32 *temp, struct netlink_ext_ack *extack); |
| @@ -12705,6 +12705,14 @@ enum mlx5_msees_oper_status { · 12704 unmodified lines | ||
| 12705 | 12705 | MLX5_MSEES_OPER_STATUS_FAIL_FREE_RUNNING = 0x5, |
| 12706 | 12706 | }; |
| 12707 | 12707 | |
| 12708 | +enum mlx5_msees_failure_reason { | |
| 12709 | + MLX5_MSEES_FAILURE_REASON_UNDEFINED_ERROR = 0x0, | |
| 12710 | + MLX5_MSEES_FAILURE_REASON_PORT_DOWN = 0x1, | |
| 12711 | + MLX5_MSEES_FAILURE_REASON_TOO_HIGH_FREQUENCY_DIFF = 0x2, | |
| 12712 | + MLX5_MSEES_FAILURE_REASON_NET_SYNCHRONIZER_DEVICE_ERROR = 0x3, | |
| 12713 | + MLX5_MSEES_FAILURE_REASON_LACK_OF_RESOURCES = 0x4, | |
| 12714 | +}; | |
| 12715 | + | |
| 12708 | 12716 | struct mlx5_ifc_msees_reg_bits { |
| 12709 | 12717 | u8 reserved_at_0[0x8]; |
| 12710 | 12718 | u8 local_port[0x8]; |
| @@ -50,6 +50,35 @@ enum dpll_lock_status { · 49 unmodified lines | ||
| 50 | 50 | DPLL_LOCK_STATUS_MAX = (__DPLL_LOCK_STATUS_MAX - 1) |
| 51 | 51 | }; |
| 52 | 52 | |
| 53 | +/** | |
| 54 | + * enum dpll_lock_status_error - if previous status change was done due to a | |
| 55 | + * failure, this provides information of dpll device lock status error. Valid | |
| 56 | + * values for DPLL_A_LOCK_STATUS_ERROR attribute | |
| 57 | + * @DPLL_LOCK_STATUS_ERROR_NONE: dpll device lock status was changed without | |
| 58 | + * any error | |
| 59 | + * @DPLL_LOCK_STATUS_ERROR_UNDEFINED: dpll device lock status was changed due | |
| 60 | + * to undefined error. Driver fills this value up in case it is not able to | |
| 61 | + * obtain suitable exact error type. | |
| 62 | + * @DPLL_LOCK_STATUS_ERROR_MEDIA_DOWN: dpll device lock status was changed | |
| 63 | + * because of associated media got down. This may happen for example if dpll | |
| 64 | + * device was previously locked on an input pin of type | |
| 65 | + * PIN_TYPE_SYNCE_ETH_PORT. | |
| 66 | + * @DPLL_LOCK_STATUS_ERROR_FRACTIONAL_FREQUENCY_OFFSET_TOO_HIGH: the FFO | |
| 67 | + * (Fractional Frequency Offset) between the RX and TX symbol rate on the | |
| 68 | + * media got too high. This may happen for example if dpll device was | |
| 69 | + * previously locked on an input pin of type PIN_TYPE_SYNCE_ETH_PORT. | |
| 70 | + */ | |
| 71 | +enum dpll_lock_status_error { | |
| 72 | + DPLL_LOCK_STATUS_ERROR_NONE = 1, | |
| 73 | + DPLL_LOCK_STATUS_ERROR_UNDEFINED, | |
| 74 | + DPLL_LOCK_STATUS_ERROR_MEDIA_DOWN, | |
| 75 | + DPLL_LOCK_STATUS_ERROR_FRACTIONAL_FREQUENCY_OFFSET_TOO_HIGH, | |
| 76 | + | |
| 77 | + /* private: */ | |
| 78 | + __DPLL_LOCK_STATUS_ERROR_MAX, | |
| 79 | + DPLL_LOCK_STATUS_ERROR_MAX = (__DPLL_LOCK_STATUS_ERROR_MAX - 1) | |
| 80 | +}; | |
| 81 | + | |
| 53 | 82 | #define DPLL_TEMP_DIVIDER 1000 |
| 54 | 83 | |
| 55 | 84 | /** |
| @@ -150,6 +179,7 @@ enum dpll_a { · 94 unmodified lines | ||
| 150 | 179 | DPLL_A_LOCK_STATUS, |
| 151 | 180 | DPLL_A_TEMP, |
| 152 | 181 | DPLL_A_TYPE, |
| 182 | + DPLL_A_LOCK_STATUS_ERROR, | |
| 153 | 183 | |
| 154 | 184 | __DPLL_A_MAX, |
| 155 | 185 | DPLL_A_MAX = (__DPLL_A_MAX - 1) |