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.

dpll: add frequency monitoring callback ops

Add new callback operations for a dpll device:
- freq_monitor_get(..) - to obtain current state of frequency monitor
feature from dpll device,
- freq_monitor_set(..) - to allow feature configuration.

Add new callback operation for a dpll pin:
- measured_freq_get(..) - to obtain the measured frequency in mHz.

Obtain the feature state value using the get callback and provide it to
the user if the device driver implements callbacks. The measured_freq_get
pin callback is only invoked when the frequency monitor is enabled.
The freq_monitor_get device callback is required when measured_freq_get
is provided by the driver.

Execute the set callback upon user requests.

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Link: https://patch.msgid.link/20260402184057.1890514-3-ivecera@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Ivan Vecera and committed by
Jakub Kicinski
15ed91aa 3fdea79c

+104 -1
+4 -1
drivers/dpll/dpll_core.c
··· 876 876 877 877 if (WARN_ON(!ops) || 878 878 WARN_ON(!ops->state_on_dpll_get) || 879 - WARN_ON(!ops->direction_get)) 879 + WARN_ON(!ops->direction_get) || 880 + WARN_ON(ops->measured_freq_get && 881 + (!dpll_device_ops(dpll)->freq_monitor_get || 882 + !dpll_device_ops(dpll)->freq_monitor_set))) 880 883 return -EINVAL; 881 884 882 885 mutex_lock(&dpll_lock);
+90
drivers/dpll/dpll_netlink.c
··· 176 176 } 177 177 178 178 static int 179 + dpll_msg_add_freq_monitor(struct sk_buff *msg, struct dpll_device *dpll, 180 + struct netlink_ext_ack *extack) 181 + { 182 + const struct dpll_device_ops *ops = dpll_device_ops(dpll); 183 + enum dpll_feature_state state; 184 + int ret; 185 + 186 + if (ops->freq_monitor_set && ops->freq_monitor_get) { 187 + ret = ops->freq_monitor_get(dpll, dpll_priv(dpll), 188 + &state, extack); 189 + if (ret) 190 + return ret; 191 + if (nla_put_u32(msg, DPLL_A_FREQUENCY_MONITOR, state)) 192 + return -EMSGSIZE; 193 + } 194 + 195 + return 0; 196 + } 197 + 198 + static int 179 199 dpll_msg_add_phase_offset_avg_factor(struct sk_buff *msg, 180 200 struct dpll_device *dpll, 181 201 struct netlink_ext_ack *extack) ··· 418 398 return -EMSGSIZE; 419 399 return nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT, 420 400 ffo); 401 + } 402 + 403 + static int dpll_msg_add_measured_freq(struct sk_buff *msg, struct dpll_pin *pin, 404 + struct dpll_pin_ref *ref, 405 + struct netlink_ext_ack *extack) 406 + { 407 + const struct dpll_device_ops *dev_ops = dpll_device_ops(ref->dpll); 408 + const struct dpll_pin_ops *ops = dpll_pin_ops(ref); 409 + struct dpll_device *dpll = ref->dpll; 410 + enum dpll_feature_state state; 411 + u64 measured_freq; 412 + int ret; 413 + 414 + if (!ops->measured_freq_get) 415 + return 0; 416 + ret = dev_ops->freq_monitor_get(dpll, dpll_priv(dpll), 417 + &state, extack); 418 + if (ret) 419 + return ret; 420 + if (state == DPLL_FEATURE_STATE_DISABLE) 421 + return 0; 422 + ret = ops->measured_freq_get(pin, dpll_pin_on_dpll_priv(dpll, pin), 423 + dpll, dpll_priv(dpll), &measured_freq, 424 + extack); 425 + if (ret) 426 + return ret; 427 + if (nla_put_64bit(msg, DPLL_A_PIN_MEASURED_FREQUENCY, 428 + sizeof(measured_freq), &measured_freq, 429 + DPLL_A_PIN_PAD)) 430 + return -EMSGSIZE; 431 + 432 + return 0; 421 433 } 422 434 423 435 static int ··· 724 672 ret = dpll_msg_add_ffo(msg, pin, ref, extack); 725 673 if (ret) 726 674 return ret; 675 + ret = dpll_msg_add_measured_freq(msg, pin, ref, extack); 676 + if (ret) 677 + return ret; 727 678 ret = dpll_msg_add_pin_esync(msg, pin, ref, extack); 728 679 if (ret) 729 680 return ret; ··· 777 722 if (ret) 778 723 return ret; 779 724 ret = dpll_msg_add_phase_offset_avg_factor(msg, dpll, extack); 725 + if (ret) 726 + return ret; 727 + ret = dpll_msg_add_freq_monitor(msg, dpll, extack); 780 728 if (ret) 781 729 return ret; 782 730 ··· 1004 946 1005 947 return ops->phase_offset_avg_factor_set(dpll, dpll_priv(dpll), factor, 1006 948 extack); 949 + } 950 + 951 + static int 952 + dpll_freq_monitor_set(struct dpll_device *dpll, struct nlattr *a, 953 + struct netlink_ext_ack *extack) 954 + { 955 + const struct dpll_device_ops *ops = dpll_device_ops(dpll); 956 + enum dpll_feature_state state = nla_get_u32(a), old_state; 957 + int ret; 958 + 959 + if (!(ops->freq_monitor_set && ops->freq_monitor_get)) { 960 + NL_SET_ERR_MSG_ATTR(extack, a, 961 + "dpll device not capable of frequency monitor"); 962 + return -EOPNOTSUPP; 963 + } 964 + ret = ops->freq_monitor_get(dpll, dpll_priv(dpll), &old_state, 965 + extack); 966 + if (ret) { 967 + NL_SET_ERR_MSG(extack, 968 + "unable to get current state of frequency monitor"); 969 + return ret; 970 + } 971 + if (state == old_state) 972 + return 0; 973 + 974 + return ops->freq_monitor_set(dpll, dpll_priv(dpll), state, extack); 1007 975 } 1008 976 1009 977 static int ··· 1959 1875 case DPLL_A_PHASE_OFFSET_AVG_FACTOR: 1960 1876 ret = dpll_phase_offset_avg_factor_set(dpll, a, 1961 1877 info->extack); 1878 + if (ret) 1879 + return ret; 1880 + break; 1881 + case DPLL_A_FREQUENCY_MONITOR: 1882 + ret = dpll_freq_monitor_set(dpll, a, 1883 + info->extack); 1962 1884 if (ret) 1963 1885 return ret; 1964 1886 break;
+10
include/linux/dpll.h
··· 52 52 int (*phase_offset_avg_factor_get)(const struct dpll_device *dpll, 53 53 void *dpll_priv, u32 *factor, 54 54 struct netlink_ext_ack *extack); 55 + int (*freq_monitor_set)(const struct dpll_device *dpll, void *dpll_priv, 56 + enum dpll_feature_state state, 57 + struct netlink_ext_ack *extack); 58 + int (*freq_monitor_get)(const struct dpll_device *dpll, void *dpll_priv, 59 + enum dpll_feature_state *state, 60 + struct netlink_ext_ack *extack); 55 61 }; 56 62 57 63 struct dpll_pin_ops { ··· 116 110 int (*ffo_get)(const struct dpll_pin *pin, void *pin_priv, 117 111 const struct dpll_device *dpll, void *dpll_priv, 118 112 s64 *ffo, struct netlink_ext_ack *extack); 113 + int (*measured_freq_get)(const struct dpll_pin *pin, void *pin_priv, 114 + const struct dpll_device *dpll, 115 + void *dpll_priv, u64 *measured_freq, 116 + struct netlink_ext_ack *extack); 119 117 int (*esync_set)(const struct dpll_pin *pin, void *pin_priv, 120 118 const struct dpll_device *dpll, void *dpll_priv, 121 119 u64 freq, struct netlink_ext_ack *extack);