1 // SPDX-License-Identifier: GPL-2.0
3 * Generic netlink for DPLL management framework
5 * Copyright (c) 2023 Meta Platforms, Inc. and affiliates
6 * Copyright (c) 2023 Intel and affiliates
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <net/genetlink.h>
12 #include "dpll_core.h"
13 #include "dpll_netlink.h"
15 #include <uapi/linux/dpll.h>
17 #define ASSERT_NOT_NULL(ptr) (WARN_ON(!ptr))
19 #define xa_for_each_marked_start(xa, index, entry, filter, start) \
20 for (index = start, entry = xa_find(xa, &index, ULONG_MAX, filter); \
21 entry; entry = xa_find_after(xa, &index, ULONG_MAX, filter))
23 struct dpll_dump_ctx {
27 static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
29 return (struct dpll_dump_ctx *)cb->ctx;
33 dpll_msg_add_dev_handle(struct sk_buff *msg, struct dpll_device *dpll)
35 if (nla_put_u32(msg, DPLL_A_ID, dpll->id))
42 dpll_msg_add_dev_parent_handle(struct sk_buff *msg, u32 id)
44 if (nla_put_u32(msg, DPLL_A_PIN_PARENT_ID, id))
51 * dpll_msg_pin_handle_size - get size of pin handle attribute for given pin
54 * Return: byte size of pin handle attribute for given pin.
56 size_t dpll_msg_pin_handle_size(struct dpll_pin *pin)
58 return pin ? nla_total_size(4) : 0; /* DPLL_A_PIN_ID */
60 EXPORT_SYMBOL_GPL(dpll_msg_pin_handle_size);
63 * dpll_msg_add_pin_handle - attach pin handle attribute to a given message
64 * @msg: pointer to sk_buff message to attach a pin handle
69 * * -EMSGSIZE - no space in message to attach pin handle
71 int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin)
75 if (nla_put_u32(msg, DPLL_A_PIN_ID, pin->id))
79 EXPORT_SYMBOL_GPL(dpll_msg_add_pin_handle);
82 dpll_msg_add_mode(struct sk_buff *msg, struct dpll_device *dpll,
83 struct netlink_ext_ack *extack)
85 const struct dpll_device_ops *ops = dpll_device_ops(dpll);
89 ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack);
92 if (nla_put_u32(msg, DPLL_A_MODE, mode))
99 dpll_msg_add_mode_supported(struct sk_buff *msg, struct dpll_device *dpll,
100 struct netlink_ext_ack *extack)
102 const struct dpll_device_ops *ops = dpll_device_ops(dpll);
106 /* No mode change is supported now, so the only supported mode is the
107 * one obtained by mode_get().
110 ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack);
113 if (nla_put_u32(msg, DPLL_A_MODE_SUPPORTED, mode))
120 dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll,
121 struct netlink_ext_ack *extack)
123 const struct dpll_device_ops *ops = dpll_device_ops(dpll);
124 enum dpll_lock_status status;
127 ret = ops->lock_status_get(dpll, dpll_priv(dpll), &status, extack);
130 if (nla_put_u32(msg, DPLL_A_LOCK_STATUS, status))
137 dpll_msg_add_temp(struct sk_buff *msg, struct dpll_device *dpll,
138 struct netlink_ext_ack *extack)
140 const struct dpll_device_ops *ops = dpll_device_ops(dpll);
146 ret = ops->temp_get(dpll, dpll_priv(dpll), &temp, extack);
149 if (nla_put_s32(msg, DPLL_A_TEMP, temp))
156 dpll_msg_add_pin_prio(struct sk_buff *msg, struct dpll_pin *pin,
157 struct dpll_pin_ref *ref,
158 struct netlink_ext_ack *extack)
160 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
161 struct dpll_device *dpll = ref->dpll;
167 ret = ops->prio_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
168 dpll_priv(dpll), &prio, extack);
171 if (nla_put_u32(msg, DPLL_A_PIN_PRIO, prio))
178 dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, struct dpll_pin *pin,
179 struct dpll_pin_ref *ref,
180 struct netlink_ext_ack *extack)
182 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
183 struct dpll_device *dpll = ref->dpll;
184 enum dpll_pin_state state;
187 if (!ops->state_on_dpll_get)
189 ret = ops->state_on_dpll_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
190 dpll, dpll_priv(dpll), &state, extack);
193 if (nla_put_u32(msg, DPLL_A_PIN_STATE, state))
200 dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin,
201 struct dpll_pin_ref *ref,
202 struct netlink_ext_ack *extack)
204 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
205 struct dpll_device *dpll = ref->dpll;
206 enum dpll_pin_direction direction;
209 ret = ops->direction_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
210 dpll_priv(dpll), &direction, extack);
213 if (nla_put_u32(msg, DPLL_A_PIN_DIRECTION, direction))
220 dpll_msg_add_pin_phase_adjust(struct sk_buff *msg, struct dpll_pin *pin,
221 struct dpll_pin_ref *ref,
222 struct netlink_ext_ack *extack)
224 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
225 struct dpll_device *dpll = ref->dpll;
229 if (!ops->phase_adjust_get)
231 ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
232 dpll, dpll_priv(dpll),
233 &phase_adjust, extack);
236 if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST, phase_adjust))
243 dpll_msg_add_phase_offset(struct sk_buff *msg, struct dpll_pin *pin,
244 struct dpll_pin_ref *ref,
245 struct netlink_ext_ack *extack)
247 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
248 struct dpll_device *dpll = ref->dpll;
252 if (!ops->phase_offset_get)
254 ret = ops->phase_offset_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
255 dpll, dpll_priv(dpll), &phase_offset,
259 if (nla_put_64bit(msg, DPLL_A_PIN_PHASE_OFFSET, sizeof(phase_offset),
260 &phase_offset, DPLL_A_PIN_PAD))
266 static int dpll_msg_add_ffo(struct sk_buff *msg, struct dpll_pin *pin,
267 struct dpll_pin_ref *ref,
268 struct netlink_ext_ack *extack)
270 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
271 struct dpll_device *dpll = ref->dpll;
277 ret = ops->ffo_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
278 dpll, dpll_priv(dpll), &ffo, extack);
284 return nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET, ffo);
288 dpll_msg_add_pin_freq(struct sk_buff *msg, struct dpll_pin *pin,
289 struct dpll_pin_ref *ref, struct netlink_ext_ack *extack)
291 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
292 struct dpll_device *dpll = ref->dpll;
297 if (!ops->frequency_get)
299 ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
300 dpll_priv(dpll), &freq, extack);
303 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY, sizeof(freq), &freq,
306 for (fs = 0; fs < pin->prop.freq_supported_num; fs++) {
307 nest = nla_nest_start(msg, DPLL_A_PIN_FREQUENCY_SUPPORTED);
310 freq = pin->prop.freq_supported[fs].min;
311 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MIN, sizeof(freq),
312 &freq, DPLL_A_PIN_PAD)) {
313 nla_nest_cancel(msg, nest);
316 freq = pin->prop.freq_supported[fs].max;
317 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MAX, sizeof(freq),
318 &freq, DPLL_A_PIN_PAD)) {
319 nla_nest_cancel(msg, nest);
322 nla_nest_end(msg, nest);
328 static bool dpll_pin_is_freq_supported(struct dpll_pin *pin, u32 freq)
332 for (fs = 0; fs < pin->prop.freq_supported_num; fs++)
333 if (freq >= pin->prop.freq_supported[fs].min &&
334 freq <= pin->prop.freq_supported[fs].max)
340 dpll_msg_add_pin_parents(struct sk_buff *msg, struct dpll_pin *pin,
341 struct dpll_pin_ref *dpll_ref,
342 struct netlink_ext_ack *extack)
344 enum dpll_pin_state state;
345 struct dpll_pin_ref *ref;
346 struct dpll_pin *ppin;
351 xa_for_each(&pin->parent_refs, index, ref) {
352 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
356 parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, ppin);
357 ret = ops->state_on_pin_get(pin,
358 dpll_pin_on_pin_priv(ppin, pin),
359 ppin, parent_priv, &state, extack);
362 nest = nla_nest_start(msg, DPLL_A_PIN_PARENT_PIN);
365 ret = dpll_msg_add_dev_parent_handle(msg, ppin->id);
368 if (nla_put_u32(msg, DPLL_A_PIN_STATE, state)) {
372 nla_nest_end(msg, nest);
378 nla_nest_cancel(msg, nest);
383 dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin,
384 struct netlink_ext_ack *extack)
386 struct dpll_pin_ref *ref;
391 xa_for_each(&pin->dpll_refs, index, ref) {
392 attr = nla_nest_start(msg, DPLL_A_PIN_PARENT_DEVICE);
395 ret = dpll_msg_add_dev_parent_handle(msg, ref->dpll->id);
398 ret = dpll_msg_add_pin_on_dpll_state(msg, pin, ref, extack);
401 ret = dpll_msg_add_pin_prio(msg, pin, ref, extack);
404 ret = dpll_msg_add_pin_direction(msg, pin, ref, extack);
407 ret = dpll_msg_add_phase_offset(msg, pin, ref, extack);
410 nla_nest_end(msg, attr);
416 nla_nest_end(msg, attr);
421 dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
422 struct netlink_ext_ack *extack)
424 const struct dpll_pin_properties *prop = &pin->prop;
425 struct dpll_pin_ref *ref;
428 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
429 ASSERT_NOT_NULL(ref);
431 ret = dpll_msg_add_pin_handle(msg, pin);
434 if (nla_put_string(msg, DPLL_A_PIN_MODULE_NAME,
435 module_name(pin->module)))
437 if (nla_put_64bit(msg, DPLL_A_PIN_CLOCK_ID, sizeof(pin->clock_id),
438 &pin->clock_id, DPLL_A_PIN_PAD))
440 if (prop->board_label &&
441 nla_put_string(msg, DPLL_A_PIN_BOARD_LABEL, prop->board_label))
443 if (prop->panel_label &&
444 nla_put_string(msg, DPLL_A_PIN_PANEL_LABEL, prop->panel_label))
446 if (prop->package_label &&
447 nla_put_string(msg, DPLL_A_PIN_PACKAGE_LABEL,
448 prop->package_label))
450 if (nla_put_u32(msg, DPLL_A_PIN_TYPE, prop->type))
452 if (nla_put_u32(msg, DPLL_A_PIN_CAPABILITIES, prop->capabilities))
454 ret = dpll_msg_add_pin_freq(msg, pin, ref, extack);
457 if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MIN,
458 prop->phase_range.min))
460 if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MAX,
461 prop->phase_range.max))
463 ret = dpll_msg_add_pin_phase_adjust(msg, pin, ref, extack);
466 ret = dpll_msg_add_ffo(msg, pin, ref, extack);
469 if (xa_empty(&pin->parent_refs))
470 ret = dpll_msg_add_pin_dplls(msg, pin, extack);
472 ret = dpll_msg_add_pin_parents(msg, pin, ref, extack);
478 dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
479 struct netlink_ext_ack *extack)
483 ret = dpll_msg_add_dev_handle(msg, dpll);
486 if (nla_put_string(msg, DPLL_A_MODULE_NAME, module_name(dpll->module)))
488 if (nla_put_64bit(msg, DPLL_A_CLOCK_ID, sizeof(dpll->clock_id),
489 &dpll->clock_id, DPLL_A_PAD))
491 ret = dpll_msg_add_temp(msg, dpll, extack);
494 ret = dpll_msg_add_lock_status(msg, dpll, extack);
497 ret = dpll_msg_add_mode(msg, dpll, extack);
500 ret = dpll_msg_add_mode_supported(msg, dpll, extack);
503 if (nla_put_u32(msg, DPLL_A_TYPE, dpll->type))
510 dpll_device_event_send(enum dpll_cmd event, struct dpll_device *dpll)
516 if (WARN_ON(!xa_get_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED)))
518 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
521 hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
524 ret = dpll_device_get_one(dpll, msg, NULL);
527 genlmsg_end(msg, hdr);
528 genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
533 genlmsg_cancel(msg, hdr);
540 int dpll_device_create_ntf(struct dpll_device *dpll)
542 return dpll_device_event_send(DPLL_CMD_DEVICE_CREATE_NTF, dpll);
545 int dpll_device_delete_ntf(struct dpll_device *dpll)
547 return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF, dpll);
551 __dpll_device_change_ntf(struct dpll_device *dpll)
553 return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll);
556 static bool dpll_pin_available(struct dpll_pin *pin)
558 struct dpll_pin_ref *par_ref;
561 if (!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED))
563 xa_for_each(&pin->parent_refs, i, par_ref)
564 if (xa_get_mark(&dpll_pin_xa, par_ref->pin->id,
567 xa_for_each(&pin->dpll_refs, i, par_ref)
568 if (xa_get_mark(&dpll_device_xa, par_ref->dpll->id,
575 * dpll_device_change_ntf - notify that the dpll device has been changed
576 * @dpll: registered dpll pointer
578 * Context: acquires and holds a dpll_lock.
579 * Return: 0 if succeeds, error code otherwise.
581 int dpll_device_change_ntf(struct dpll_device *dpll)
585 mutex_lock(&dpll_lock);
586 ret = __dpll_device_change_ntf(dpll);
587 mutex_unlock(&dpll_lock);
591 EXPORT_SYMBOL_GPL(dpll_device_change_ntf);
594 dpll_pin_event_send(enum dpll_cmd event, struct dpll_pin *pin)
600 if (!dpll_pin_available(pin))
603 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
607 hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
610 ret = dpll_cmd_pin_get_one(msg, pin, NULL);
613 genlmsg_end(msg, hdr);
614 genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
619 genlmsg_cancel(msg, hdr);
626 int dpll_pin_create_ntf(struct dpll_pin *pin)
628 return dpll_pin_event_send(DPLL_CMD_PIN_CREATE_NTF, pin);
631 int dpll_pin_delete_ntf(struct dpll_pin *pin)
633 return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin);
636 static int __dpll_pin_change_ntf(struct dpll_pin *pin)
638 return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin);
642 * dpll_pin_change_ntf - notify that the pin has been changed
643 * @pin: registered pin pointer
645 * Context: acquires and holds a dpll_lock.
646 * Return: 0 if succeeds, error code otherwise.
648 int dpll_pin_change_ntf(struct dpll_pin *pin)
652 mutex_lock(&dpll_lock);
653 ret = __dpll_pin_change_ntf(pin);
654 mutex_unlock(&dpll_lock);
658 EXPORT_SYMBOL_GPL(dpll_pin_change_ntf);
661 dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
662 struct netlink_ext_ack *extack)
664 u64 freq = nla_get_u64(a), old_freq;
665 struct dpll_pin_ref *ref, *failed;
666 const struct dpll_pin_ops *ops;
667 struct dpll_device *dpll;
671 if (!dpll_pin_is_freq_supported(pin, freq)) {
672 NL_SET_ERR_MSG_ATTR(extack, a, "frequency is not supported by the device");
676 xa_for_each(&pin->dpll_refs, i, ref) {
677 ops = dpll_pin_ops(ref);
678 if (!ops->frequency_set || !ops->frequency_get) {
679 NL_SET_ERR_MSG(extack, "frequency set not supported by the device");
683 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
684 ops = dpll_pin_ops(ref);
686 ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
687 dpll_priv(dpll), &old_freq, extack);
689 NL_SET_ERR_MSG(extack, "unable to get old frequency value");
692 if (freq == old_freq)
695 xa_for_each(&pin->dpll_refs, i, ref) {
696 ops = dpll_pin_ops(ref);
698 ret = ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
699 dpll, dpll_priv(dpll), freq, extack);
702 NL_SET_ERR_MSG_FMT(extack, "frequency set failed for dpll_id:%u",
707 __dpll_pin_change_ntf(pin);
712 xa_for_each(&pin->dpll_refs, i, ref) {
715 ops = dpll_pin_ops(ref);
717 if (ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
718 dpll, dpll_priv(dpll), old_freq, extack))
719 NL_SET_ERR_MSG(extack, "set frequency rollback failed");
725 dpll_pin_on_pin_state_set(struct dpll_pin *pin, u32 parent_idx,
726 enum dpll_pin_state state,
727 struct netlink_ext_ack *extack)
729 struct dpll_pin_ref *parent_ref;
730 const struct dpll_pin_ops *ops;
731 struct dpll_pin_ref *dpll_ref;
732 void *pin_priv, *parent_priv;
733 struct dpll_pin *parent;
737 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
738 pin->prop.capabilities)) {
739 NL_SET_ERR_MSG(extack, "state changing is not allowed");
742 parent = xa_load(&dpll_pin_xa, parent_idx);
745 parent_ref = xa_load(&pin->parent_refs, parent->pin_idx);
748 xa_for_each(&parent->dpll_refs, i, dpll_ref) {
749 ops = dpll_pin_ops(parent_ref);
750 if (!ops->state_on_pin_set)
752 pin_priv = dpll_pin_on_pin_priv(parent, pin);
753 parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, parent);
754 ret = ops->state_on_pin_set(pin, pin_priv, parent, parent_priv,
759 __dpll_pin_change_ntf(pin);
765 dpll_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin,
766 enum dpll_pin_state state,
767 struct netlink_ext_ack *extack)
769 const struct dpll_pin_ops *ops;
770 struct dpll_pin_ref *ref;
773 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
774 pin->prop.capabilities)) {
775 NL_SET_ERR_MSG(extack, "state changing is not allowed");
778 ref = xa_load(&pin->dpll_refs, dpll->id);
779 ASSERT_NOT_NULL(ref);
780 ops = dpll_pin_ops(ref);
781 if (!ops->state_on_dpll_set)
783 ret = ops->state_on_dpll_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
784 dpll, dpll_priv(dpll), state, extack);
787 __dpll_pin_change_ntf(pin);
793 dpll_pin_prio_set(struct dpll_device *dpll, struct dpll_pin *pin,
794 u32 prio, struct netlink_ext_ack *extack)
796 const struct dpll_pin_ops *ops;
797 struct dpll_pin_ref *ref;
800 if (!(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE &
801 pin->prop.capabilities)) {
802 NL_SET_ERR_MSG(extack, "prio changing is not allowed");
805 ref = xa_load(&pin->dpll_refs, dpll->id);
806 ASSERT_NOT_NULL(ref);
807 ops = dpll_pin_ops(ref);
810 ret = ops->prio_set(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
811 dpll_priv(dpll), prio, extack);
814 __dpll_pin_change_ntf(pin);
820 dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll,
821 enum dpll_pin_direction direction,
822 struct netlink_ext_ack *extack)
824 const struct dpll_pin_ops *ops;
825 struct dpll_pin_ref *ref;
828 if (!(DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE &
829 pin->prop.capabilities)) {
830 NL_SET_ERR_MSG(extack, "direction changing is not allowed");
833 ref = xa_load(&pin->dpll_refs, dpll->id);
834 ASSERT_NOT_NULL(ref);
835 ops = dpll_pin_ops(ref);
836 if (!ops->direction_set)
838 ret = ops->direction_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
839 dpll, dpll_priv(dpll), direction, extack);
842 __dpll_pin_change_ntf(pin);
848 dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr,
849 struct netlink_ext_ack *extack)
851 struct dpll_pin_ref *ref, *failed;
852 const struct dpll_pin_ops *ops;
853 s32 phase_adj, old_phase_adj;
854 struct dpll_device *dpll;
858 phase_adj = nla_get_s32(phase_adj_attr);
859 if (phase_adj > pin->prop.phase_range.max ||
860 phase_adj < pin->prop.phase_range.min) {
861 NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr,
862 "phase adjust value not supported");
866 xa_for_each(&pin->dpll_refs, i, ref) {
867 ops = dpll_pin_ops(ref);
868 if (!ops->phase_adjust_set || !ops->phase_adjust_get) {
869 NL_SET_ERR_MSG(extack, "phase adjust not supported");
873 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
874 ops = dpll_pin_ops(ref);
876 ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
877 dpll, dpll_priv(dpll), &old_phase_adj,
880 NL_SET_ERR_MSG(extack, "unable to get old phase adjust value");
883 if (phase_adj == old_phase_adj)
886 xa_for_each(&pin->dpll_refs, i, ref) {
887 ops = dpll_pin_ops(ref);
889 ret = ops->phase_adjust_set(pin,
890 dpll_pin_on_dpll_priv(dpll, pin),
891 dpll, dpll_priv(dpll), phase_adj,
895 NL_SET_ERR_MSG_FMT(extack,
896 "phase adjust set failed for dpll_id:%u",
901 __dpll_pin_change_ntf(pin);
906 xa_for_each(&pin->dpll_refs, i, ref) {
909 ops = dpll_pin_ops(ref);
911 if (ops->phase_adjust_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
912 dpll, dpll_priv(dpll), old_phase_adj,
914 NL_SET_ERR_MSG(extack, "set phase adjust rollback failed");
920 dpll_pin_parent_device_set(struct dpll_pin *pin, struct nlattr *parent_nest,
921 struct netlink_ext_ack *extack)
923 struct nlattr *tb[DPLL_A_PIN_MAX + 1];
924 enum dpll_pin_direction direction;
925 enum dpll_pin_state state;
926 struct dpll_pin_ref *ref;
927 struct dpll_device *dpll;
931 nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
932 dpll_pin_parent_device_nl_policy, extack);
933 if (!tb[DPLL_A_PIN_PARENT_ID]) {
934 NL_SET_ERR_MSG(extack, "device parent id expected");
937 pdpll_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
938 dpll = xa_load(&dpll_device_xa, pdpll_idx);
940 NL_SET_ERR_MSG(extack, "parent device not found");
943 ref = xa_load(&pin->dpll_refs, dpll->id);
945 NL_SET_ERR_MSG(extack, "pin not connected to given parent device");
948 if (tb[DPLL_A_PIN_STATE]) {
949 state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
950 ret = dpll_pin_state_set(dpll, pin, state, extack);
954 if (tb[DPLL_A_PIN_PRIO]) {
955 prio = nla_get_u32(tb[DPLL_A_PIN_PRIO]);
956 ret = dpll_pin_prio_set(dpll, pin, prio, extack);
960 if (tb[DPLL_A_PIN_DIRECTION]) {
961 direction = nla_get_u32(tb[DPLL_A_PIN_DIRECTION]);
962 ret = dpll_pin_direction_set(pin, dpll, direction, extack);
970 dpll_pin_parent_pin_set(struct dpll_pin *pin, struct nlattr *parent_nest,
971 struct netlink_ext_ack *extack)
973 struct nlattr *tb[DPLL_A_PIN_MAX + 1];
977 nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
978 dpll_pin_parent_pin_nl_policy, extack);
979 if (!tb[DPLL_A_PIN_PARENT_ID]) {
980 NL_SET_ERR_MSG(extack, "device parent id expected");
983 ppin_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
985 if (tb[DPLL_A_PIN_STATE]) {
986 enum dpll_pin_state state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
988 ret = dpll_pin_on_pin_state_set(pin, ppin_idx, state, extack);
997 dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
1002 nla_for_each_attr(a, genlmsg_data(info->genlhdr),
1003 genlmsg_len(info->genlhdr), rem) {
1004 switch (nla_type(a)) {
1005 case DPLL_A_PIN_FREQUENCY:
1006 ret = dpll_pin_freq_set(pin, a, info->extack);
1010 case DPLL_A_PIN_PHASE_ADJUST:
1011 ret = dpll_pin_phase_adj_set(pin, a, info->extack);
1015 case DPLL_A_PIN_PARENT_DEVICE:
1016 ret = dpll_pin_parent_device_set(pin, a, info->extack);
1020 case DPLL_A_PIN_PARENT_PIN:
1021 ret = dpll_pin_parent_pin_set(pin, a, info->extack);
1031 static struct dpll_pin *
1032 dpll_pin_find(u64 clock_id, struct nlattr *mod_name_attr,
1033 enum dpll_pin_type type, struct nlattr *board_label,
1034 struct nlattr *panel_label, struct nlattr *package_label,
1035 struct netlink_ext_ack *extack)
1037 bool board_match, panel_match, package_match;
1038 struct dpll_pin *pin_match = NULL, *pin;
1039 const struct dpll_pin_properties *prop;
1040 bool cid_match, mod_match, type_match;
1043 xa_for_each_marked(&dpll_pin_xa, i, pin, DPLL_REGISTERED) {
1045 cid_match = clock_id ? pin->clock_id == clock_id : true;
1046 mod_match = mod_name_attr && module_name(pin->module) ?
1047 !nla_strcmp(mod_name_attr,
1048 module_name(pin->module)) : true;
1049 type_match = type ? prop->type == type : true;
1050 board_match = board_label ? (prop->board_label ?
1051 !nla_strcmp(board_label, prop->board_label) : false) :
1053 panel_match = panel_label ? (prop->panel_label ?
1054 !nla_strcmp(panel_label, prop->panel_label) : false) :
1056 package_match = package_label ? (prop->package_label ?
1057 !nla_strcmp(package_label, prop->package_label) :
1059 if (cid_match && mod_match && type_match && board_match &&
1060 panel_match && package_match) {
1062 NL_SET_ERR_MSG(extack, "multiple matches");
1063 return ERR_PTR(-EINVAL);
1069 NL_SET_ERR_MSG(extack, "not found");
1070 return ERR_PTR(-ENODEV);
1075 static struct dpll_pin *dpll_pin_find_from_nlattr(struct genl_info *info)
1077 struct nlattr *attr, *mod_name_attr = NULL, *board_label_attr = NULL,
1078 *panel_label_attr = NULL, *package_label_attr = NULL;
1079 enum dpll_pin_type type = 0;
1083 nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
1084 genlmsg_len(info->genlhdr), rem) {
1085 switch (nla_type(attr)) {
1086 case DPLL_A_PIN_CLOCK_ID:
1088 goto duplicated_attr;
1089 clock_id = nla_get_u64(attr);
1091 case DPLL_A_PIN_MODULE_NAME:
1093 goto duplicated_attr;
1094 mod_name_attr = attr;
1096 case DPLL_A_PIN_TYPE:
1098 goto duplicated_attr;
1099 type = nla_get_u32(attr);
1101 case DPLL_A_PIN_BOARD_LABEL:
1102 if (board_label_attr)
1103 goto duplicated_attr;
1104 board_label_attr = attr;
1106 case DPLL_A_PIN_PANEL_LABEL:
1107 if (panel_label_attr)
1108 goto duplicated_attr;
1109 panel_label_attr = attr;
1111 case DPLL_A_PIN_PACKAGE_LABEL:
1112 if (package_label_attr)
1113 goto duplicated_attr;
1114 package_label_attr = attr;
1120 if (!(clock_id || mod_name_attr || board_label_attr ||
1121 panel_label_attr || package_label_attr)) {
1122 NL_SET_ERR_MSG(info->extack, "missing attributes");
1123 return ERR_PTR(-EINVAL);
1125 return dpll_pin_find(clock_id, mod_name_attr, type, board_label_attr,
1126 panel_label_attr, package_label_attr,
1129 NL_SET_ERR_MSG(info->extack, "duplicated attribute");
1130 return ERR_PTR(-EINVAL);
1133 int dpll_nl_pin_id_get_doit(struct sk_buff *skb, struct genl_info *info)
1135 struct dpll_pin *pin;
1136 struct sk_buff *msg;
1140 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1143 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1144 DPLL_CMD_PIN_ID_GET);
1149 pin = dpll_pin_find_from_nlattr(info);
1151 if (!dpll_pin_available(pin)) {
1155 ret = dpll_msg_add_pin_handle(msg, pin);
1161 genlmsg_end(msg, hdr);
1163 return genlmsg_reply(msg, info);
1166 int dpll_nl_pin_get_doit(struct sk_buff *skb, struct genl_info *info)
1168 struct dpll_pin *pin = info->user_ptr[0];
1169 struct sk_buff *msg;
1175 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1178 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1184 ret = dpll_cmd_pin_get_one(msg, pin, info->extack);
1189 genlmsg_end(msg, hdr);
1191 return genlmsg_reply(msg, info);
1194 int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
1196 struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
1197 struct dpll_pin *pin;
1202 xa_for_each_marked_start(&dpll_pin_xa, i, pin, DPLL_REGISTERED,
1204 if (!dpll_pin_available(pin))
1206 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1208 &dpll_nl_family, NLM_F_MULTI,
1214 ret = dpll_cmd_pin_get_one(skb, pin, cb->extack);
1216 genlmsg_cancel(skb, hdr);
1219 genlmsg_end(skb, hdr);
1221 if (ret == -EMSGSIZE) {
1228 int dpll_nl_pin_set_doit(struct sk_buff *skb, struct genl_info *info)
1230 struct dpll_pin *pin = info->user_ptr[0];
1232 return dpll_pin_set_from_nlattr(pin, info);
1235 static struct dpll_device *
1236 dpll_device_find(u64 clock_id, struct nlattr *mod_name_attr,
1237 enum dpll_type type, struct netlink_ext_ack *extack)
1239 struct dpll_device *dpll_match = NULL, *dpll;
1240 bool cid_match, mod_match, type_match;
1243 xa_for_each_marked(&dpll_device_xa, i, dpll, DPLL_REGISTERED) {
1244 cid_match = clock_id ? dpll->clock_id == clock_id : true;
1245 mod_match = mod_name_attr ? (module_name(dpll->module) ?
1246 !nla_strcmp(mod_name_attr,
1247 module_name(dpll->module)) : false) : true;
1248 type_match = type ? dpll->type == type : true;
1249 if (cid_match && mod_match && type_match) {
1251 NL_SET_ERR_MSG(extack, "multiple matches");
1252 return ERR_PTR(-EINVAL);
1258 NL_SET_ERR_MSG(extack, "not found");
1259 return ERR_PTR(-ENODEV);
1265 static struct dpll_device *
1266 dpll_device_find_from_nlattr(struct genl_info *info)
1268 struct nlattr *attr, *mod_name_attr = NULL;
1269 enum dpll_type type = 0;
1273 nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
1274 genlmsg_len(info->genlhdr), rem) {
1275 switch (nla_type(attr)) {
1276 case DPLL_A_CLOCK_ID:
1278 goto duplicated_attr;
1279 clock_id = nla_get_u64(attr);
1281 case DPLL_A_MODULE_NAME:
1283 goto duplicated_attr;
1284 mod_name_attr = attr;
1288 goto duplicated_attr;
1289 type = nla_get_u32(attr);
1295 if (!clock_id && !mod_name_attr && !type) {
1296 NL_SET_ERR_MSG(info->extack, "missing attributes");
1297 return ERR_PTR(-EINVAL);
1299 return dpll_device_find(clock_id, mod_name_attr, type, info->extack);
1301 NL_SET_ERR_MSG(info->extack, "duplicated attribute");
1302 return ERR_PTR(-EINVAL);
1305 int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info)
1307 struct dpll_device *dpll;
1308 struct sk_buff *msg;
1312 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1315 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1316 DPLL_CMD_DEVICE_ID_GET);
1322 dpll = dpll_device_find_from_nlattr(info);
1323 if (!IS_ERR(dpll)) {
1324 ret = dpll_msg_add_dev_handle(msg, dpll);
1330 genlmsg_end(msg, hdr);
1332 return genlmsg_reply(msg, info);
1335 int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info)
1337 struct dpll_device *dpll = info->user_ptr[0];
1338 struct sk_buff *msg;
1342 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1345 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1346 DPLL_CMD_DEVICE_GET);
1352 ret = dpll_device_get_one(dpll, msg, info->extack);
1357 genlmsg_end(msg, hdr);
1359 return genlmsg_reply(msg, info);
1362 int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info)
1364 /* placeholder for set command */
1368 int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
1370 struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
1371 struct dpll_device *dpll;
1376 xa_for_each_marked_start(&dpll_device_xa, i, dpll, DPLL_REGISTERED,
1378 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1379 cb->nlh->nlmsg_seq, &dpll_nl_family,
1380 NLM_F_MULTI, DPLL_CMD_DEVICE_GET);
1385 ret = dpll_device_get_one(dpll, skb, cb->extack);
1387 genlmsg_cancel(skb, hdr);
1390 genlmsg_end(skb, hdr);
1392 if (ret == -EMSGSIZE) {
1399 int dpll_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1400 struct genl_info *info)
1404 if (GENL_REQ_ATTR_CHECK(info, DPLL_A_ID))
1407 mutex_lock(&dpll_lock);
1408 id = nla_get_u32(info->attrs[DPLL_A_ID]);
1409 info->user_ptr[0] = dpll_device_get_by_id(id);
1410 if (!info->user_ptr[0]) {
1411 NL_SET_ERR_MSG(info->extack, "device not found");
1416 mutex_unlock(&dpll_lock);
1420 void dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1421 struct genl_info *info)
1423 mutex_unlock(&dpll_lock);
1427 dpll_lock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1428 struct genl_info *info)
1430 mutex_lock(&dpll_lock);
1436 dpll_unlock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1437 struct genl_info *info)
1439 mutex_unlock(&dpll_lock);
1442 int dpll_lock_dumpit(struct netlink_callback *cb)
1444 mutex_lock(&dpll_lock);
1449 int dpll_unlock_dumpit(struct netlink_callback *cb)
1451 mutex_unlock(&dpll_lock);
1456 int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1457 struct genl_info *info)
1461 mutex_lock(&dpll_lock);
1462 if (GENL_REQ_ATTR_CHECK(info, DPLL_A_PIN_ID)) {
1466 info->user_ptr[0] = xa_load(&dpll_pin_xa,
1467 nla_get_u32(info->attrs[DPLL_A_PIN_ID]));
1468 if (!info->user_ptr[0] ||
1469 !dpll_pin_available(info->user_ptr[0])) {
1470 NL_SET_ERR_MSG(info->extack, "pin not found");
1478 mutex_unlock(&dpll_lock);
1482 void dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1483 struct genl_info *info)
1485 mutex_unlock(&dpll_lock);