Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'dpll-expose-clock-quality-level'

Jiri Pirko says:

====================
dpll: expose clock quality level

Some device driver might know the quality of the clock it is running.
In order to expose the information to the user, introduce new netlink
attribute and dpll device op. Implement the op in mlx5 driver.

Example:
$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/dpll.yaml --dump device-get
[{'clock-id': 13316852727532664826,
'clock-quality-level': ['itu-opt1-eeec'], <<<<<<<<<<<<<<<<<
'id': 0,
'lock-status': 'unlocked',
'lock-status-error': 'none',
'mode': 'manual',
'mode-supported': ['manual'],
'module-name': 'mlx5_dpll',
'type': 'eec'}]
====================

Link: https://patch.msgid.link/20241030081157.966604-1-jiri@resnulli.us
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+174
+41
Documentation/netlink/specs/dpll.yaml
··· 86 86 locked on an input pin of type PIN_TYPE_SYNCE_ETH_PORT. 87 87 render-max: true 88 88 - 89 + type: enum 90 + name: clock-quality-level 91 + doc: | 92 + level of quality of a clock device. This mainly applies when 93 + the dpll lock-status is DPLL_LOCK_STATUS_HOLDOVER. 94 + The current list is defined according to the table 11-7 contained 95 + in ITU-T G.8264/Y.1364 document. One may extend this list freely 96 + by other ITU-T defined clock qualities, or different ones defined 97 + by another standardization body (for those, please use 98 + different prefix). 99 + entries: 100 + - 101 + name: itu-opt1-prc 102 + value: 1 103 + - 104 + name: itu-opt1-ssu-a 105 + - 106 + name: itu-opt1-ssu-b 107 + - 108 + name: itu-opt1-eec1 109 + - 110 + name: itu-opt1-prtc 111 + - 112 + name: itu-opt1-eprtc 113 + - 114 + name: itu-opt1-eeec 115 + - 116 + name: itu-opt1-eprc 117 + render-max: true 118 + - 89 119 type: const 90 120 name: temp-divider 91 121 value: 1000 ··· 282 252 name: lock-status-error 283 253 type: u32 284 254 enum: lock-status-error 255 + - 256 + name: clock-quality-level 257 + type: u32 258 + enum: clock-quality-level 259 + multi-attr: true 260 + doc: | 261 + Level of quality of a clock device. This mainly applies when 262 + the dpll lock-status is DPLL_LOCK_STATUS_HOLDOVER. This could 263 + be put to message multiple times to indicate possible parallel 264 + quality levels (e.g. one specified by ITU option 1 and another 265 + one specified by option 2). 285 266 - 286 267 name: pin 287 268 enum-name: dpll_a_pin
+24
drivers/dpll/dpll_netlink.c
··· 170 170 } 171 171 172 172 static int 173 + dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll, 174 + struct netlink_ext_ack *extack) 175 + { 176 + const struct dpll_device_ops *ops = dpll_device_ops(dpll); 177 + DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) = { 0 }; 178 + enum dpll_clock_quality_level ql; 179 + int ret; 180 + 181 + if (!ops->clock_quality_level_get) 182 + return 0; 183 + ret = ops->clock_quality_level_get(dpll, dpll_priv(dpll), qls, extack); 184 + if (ret) 185 + return ret; 186 + for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) 187 + if (nla_put_u32(msg, DPLL_A_CLOCK_QUALITY_LEVEL, ql)) 188 + return -EMSGSIZE; 189 + 190 + return 0; 191 + } 192 + 193 + static int 173 194 dpll_msg_add_pin_prio(struct sk_buff *msg, struct dpll_pin *pin, 174 195 struct dpll_pin_ref *ref, 175 196 struct netlink_ext_ack *extack) ··· 578 557 if (ret) 579 558 return ret; 580 559 ret = dpll_msg_add_lock_status(msg, dpll, extack); 560 + if (ret) 561 + return ret; 562 + ret = dpll_msg_add_clock_quality_level(msg, dpll, extack); 581 563 if (ret) 582 564 return ret; 583 565 ret = dpll_msg_add_mode(msg, dpll, extack);
+81
drivers/net/ethernet/mellanox/mlx5/core/dpll.c
··· 166 166 return 0; 167 167 } 168 168 169 + enum { 170 + MLX5_DPLL_SSM_CODE_PRC = 0b0010, 171 + MLX5_DPLL_SSM_CODE_SSU_A = 0b0100, 172 + MLX5_DPLL_SSM_CODE_SSU_B = 0b1000, 173 + MLX5_DPLL_SSM_CODE_EEC1 = 0b1011, 174 + MLX5_DPLL_SSM_CODE_PRTC = 0b0010, 175 + MLX5_DPLL_SSM_CODE_EPRTC = 0b0010, 176 + MLX5_DPLL_SSM_CODE_EEEC = 0b1011, 177 + MLX5_DPLL_SSM_CODE_EPRC = 0b0010, 178 + }; 179 + 180 + enum { 181 + MLX5_DPLL_ENHANCED_SSM_CODE_PRC = 0xff, 182 + MLX5_DPLL_ENHANCED_SSM_CODE_SSU_A = 0xff, 183 + MLX5_DPLL_ENHANCED_SSM_CODE_SSU_B = 0xff, 184 + MLX5_DPLL_ENHANCED_SSM_CODE_EEC1 = 0xff, 185 + MLX5_DPLL_ENHANCED_SSM_CODE_PRTC = 0x20, 186 + MLX5_DPLL_ENHANCED_SSM_CODE_EPRTC = 0x21, 187 + MLX5_DPLL_ENHANCED_SSM_CODE_EEEC = 0x22, 188 + MLX5_DPLL_ENHANCED_SSM_CODE_EPRC = 0x23, 189 + }; 190 + 191 + #define __MLX5_DPLL_SSM_COMBINED_CODE(ssm_code, enhanced_ssm_code) \ 192 + ((ssm_code) | ((enhanced_ssm_code) << 8)) 193 + 194 + #define MLX5_DPLL_SSM_COMBINED_CODE(type) \ 195 + __MLX5_DPLL_SSM_COMBINED_CODE(MLX5_DPLL_SSM_CODE_##type, \ 196 + MLX5_DPLL_ENHANCED_SSM_CODE_##type) 197 + 198 + static int mlx5_dpll_clock_quality_level_get(const struct dpll_device *dpll, 199 + void *priv, unsigned long *qls, 200 + struct netlink_ext_ack *extack) 201 + { 202 + u8 network_option, ssm_code, enhanced_ssm_code; 203 + u32 out[MLX5_ST_SZ_DW(msecq_reg)] = {}; 204 + u32 in[MLX5_ST_SZ_DW(msecq_reg)] = {}; 205 + struct mlx5_dpll *mdpll = priv; 206 + int err; 207 + 208 + err = mlx5_core_access_reg(mdpll->mdev, in, sizeof(in), 209 + out, sizeof(out), MLX5_REG_MSECQ, 0, 0); 210 + if (err) 211 + return err; 212 + network_option = MLX5_GET(msecq_reg, out, network_option); 213 + if (network_option != 1) 214 + goto errout; 215 + ssm_code = MLX5_GET(msecq_reg, out, local_ssm_code); 216 + enhanced_ssm_code = MLX5_GET(msecq_reg, out, local_enhanced_ssm_code); 217 + 218 + switch (__MLX5_DPLL_SSM_COMBINED_CODE(ssm_code, enhanced_ssm_code)) { 219 + case MLX5_DPLL_SSM_COMBINED_CODE(PRC): 220 + __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRC, qls); 221 + return 0; 222 + case MLX5_DPLL_SSM_COMBINED_CODE(SSU_A): 223 + __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_A, qls); 224 + return 0; 225 + case MLX5_DPLL_SSM_COMBINED_CODE(SSU_B): 226 + __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_B, qls); 227 + return 0; 228 + case MLX5_DPLL_SSM_COMBINED_CODE(EEC1): 229 + __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEC1, qls); 230 + return 0; 231 + case MLX5_DPLL_SSM_COMBINED_CODE(PRTC): 232 + __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRTC, qls); 233 + return 0; 234 + case MLX5_DPLL_SSM_COMBINED_CODE(EPRTC): 235 + __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRTC, qls); 236 + return 0; 237 + case MLX5_DPLL_SSM_COMBINED_CODE(EEEC): 238 + __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEEC, qls); 239 + return 0; 240 + case MLX5_DPLL_SSM_COMBINED_CODE(EPRC): 241 + __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRC, qls); 242 + return 0; 243 + } 244 + errout: 245 + NL_SET_ERR_MSG_MOD(extack, "Invalid clock quality level obtained from firmware\n"); 246 + return -EINVAL; 247 + } 248 + 169 249 static const struct dpll_device_ops mlx5_dpll_device_ops = { 170 250 .lock_status_get = mlx5_dpll_device_lock_status_get, 171 251 .mode_get = mlx5_dpll_device_mode_get, 252 + .clock_quality_level_get = mlx5_dpll_clock_quality_level_get, 172 253 }; 173 254 174 255 static int mlx5_dpll_pin_direction_get(const struct dpll_pin *pin,
+4
include/linux/dpll.h
··· 26 26 struct netlink_ext_ack *extack); 27 27 int (*temp_get)(const struct dpll_device *dpll, void *dpll_priv, 28 28 s32 *temp, struct netlink_ext_ack *extack); 29 + int (*clock_quality_level_get)(const struct dpll_device *dpll, 30 + void *dpll_priv, 31 + unsigned long *qls, 32 + struct netlink_ext_ack *extack); 29 33 }; 30 34 31 35 struct dpll_pin_ops {
+24
include/uapi/linux/dpll.h
··· 79 79 DPLL_LOCK_STATUS_ERROR_MAX = (__DPLL_LOCK_STATUS_ERROR_MAX - 1) 80 80 }; 81 81 82 + /** 83 + * enum dpll_clock_quality_level - level of quality of a clock device. This 84 + * mainly applies when the dpll lock-status is DPLL_LOCK_STATUS_HOLDOVER. The 85 + * current list is defined according to the table 11-7 contained in ITU-T 86 + * G.8264/Y.1364 document. One may extend this list freely by other ITU-T 87 + * defined clock qualities, or different ones defined by another 88 + * standardization body (for those, please use different prefix). 89 + */ 90 + enum dpll_clock_quality_level { 91 + DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRC = 1, 92 + DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_A, 93 + DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_B, 94 + DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEC1, 95 + DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRTC, 96 + DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRTC, 97 + DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEEC, 98 + DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRC, 99 + 100 + /* private: */ 101 + __DPLL_CLOCK_QUALITY_LEVEL_MAX, 102 + DPLL_CLOCK_QUALITY_LEVEL_MAX = (__DPLL_CLOCK_QUALITY_LEVEL_MAX - 1) 103 + }; 104 + 82 105 #define DPLL_TEMP_DIVIDER 1000 83 106 84 107 /** ··· 203 180 DPLL_A_TEMP, 204 181 DPLL_A_TYPE, 205 182 DPLL_A_LOCK_STATUS_ERROR, 183 + DPLL_A_CLOCK_QUALITY_LEVEL, 206 184 207 185 __DPLL_A_MAX, 208 186 DPLL_A_MAX = (__DPLL_A_MAX - 1)