diff options
Diffstat (limited to 'drivers/dpll/dpll_netlink.c')
-rw-r--r-- | drivers/dpll/dpll_netlink.c | 66 |
1 files changed, 59 insertions, 7 deletions
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index 0a852011653c..74c1f0ca95f2 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -165,6 +165,27 @@ dpll_msg_add_phase_offset_monitor(struct sk_buff *msg, struct dpll_device *dpll, } static int +dpll_msg_add_phase_offset_avg_factor(struct sk_buff *msg, + struct dpll_device *dpll, + struct netlink_ext_ack *extack) +{ + const struct dpll_device_ops *ops = dpll_device_ops(dpll); + u32 factor; + int ret; + + if (ops->phase_offset_avg_factor_get) { + ret = ops->phase_offset_avg_factor_get(dpll, dpll_priv(dpll), + &factor, extack); + if (ret) + return ret; + if (nla_put_u32(msg, DPLL_A_PHASE_OFFSET_AVG_FACTOR, factor)) + return -EMSGSIZE; + } + + return 0; +} + +static int dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll, struct netlink_ext_ack *extack) { @@ -677,6 +698,9 @@ dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg, ret = dpll_msg_add_phase_offset_monitor(msg, dpll, extack); if (ret) return ret; + ret = dpll_msg_add_phase_offset_avg_factor(msg, dpll, extack); + if (ret) + return ret; return 0; } @@ -840,6 +864,23 @@ dpll_phase_offset_monitor_set(struct dpll_device *dpll, struct nlattr *a, } static int +dpll_phase_offset_avg_factor_set(struct dpll_device *dpll, struct nlattr *a, + struct netlink_ext_ack *extack) +{ + const struct dpll_device_ops *ops = dpll_device_ops(dpll); + u32 factor = nla_get_u32(a); + + if (!ops->phase_offset_avg_factor_set) { + NL_SET_ERR_MSG_ATTR(extack, a, + "device not capable of changing phase offset average factor"); + return -EOPNOTSUPP; + } + + return ops->phase_offset_avg_factor_set(dpll, dpll_priv(dpll), factor, + extack); +} + +static int dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a, struct netlink_ext_ack *extack) { @@ -1736,14 +1777,25 @@ int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info) static int dpll_set_from_nlattr(struct dpll_device *dpll, struct genl_info *info) { - int ret; - - if (info->attrs[DPLL_A_PHASE_OFFSET_MONITOR]) { - struct nlattr *a = info->attrs[DPLL_A_PHASE_OFFSET_MONITOR]; + struct nlattr *a; + int rem, ret; - ret = dpll_phase_offset_monitor_set(dpll, a, info->extack); - if (ret) - return ret; + nla_for_each_attr(a, genlmsg_data(info->genlhdr), + genlmsg_len(info->genlhdr), rem) { + switch (nla_type(a)) { + case DPLL_A_PHASE_OFFSET_MONITOR: + ret = dpll_phase_offset_monitor_set(dpll, a, + info->extack); + if (ret) + return ret; + break; + case DPLL_A_PHASE_OFFSET_AVG_FACTOR: + ret = dpll_phase_offset_avg_factor_set(dpll, a, + info->extack); + if (ret) + return ret; + break; + } } return 0; |