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 <linux/netdevice.h>
12 #include <net/genetlink.h>
13 #include "dpll_core.h"
14 #include "dpll_netlink.h"
16 #include <uapi/linux/dpll.h>
18 #define ASSERT_NOT_NULL(ptr) (WARN_ON(!ptr))
20 #define xa_for_each_marked_start(xa, index, entry, filter, start) \
21 for (index = start, entry = xa_find(xa, &index, ULONG_MAX, filter); \
22 entry; entry = xa_find_after(xa, &index, ULONG_MAX, filter))
24 struct dpll_dump_ctx {
28 static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
30 return (struct dpll_dump_ctx *)cb->ctx;
34 dpll_msg_add_dev_handle(struct sk_buff *msg, struct dpll_device *dpll)
36 if (nla_put_u32(msg, DPLL_A_ID, dpll->id))
43 dpll_msg_add_dev_parent_handle(struct sk_buff *msg, u32 id)
45 if (nla_put_u32(msg, DPLL_A_PIN_PARENT_ID, id))
52 * dpll_msg_add_pin_handle - attach pin handle attribute to a given message
53 * @msg: pointer to sk_buff message to attach a pin handle
58 * * -EMSGSIZE - no space in message to attach pin handle
60 static int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin)
64 if (nla_put_u32(msg, DPLL_A_PIN_ID, pin->id))
69 static struct dpll_pin *dpll_netdev_pin(const struct net_device *dev)
71 return rcu_dereference_rtnl(dev->dpll_pin);
75 * dpll_netdev_pin_handle_size - get size of pin handle attribute of a netdev
76 * @dev: netdev from which to get the pin
78 * Return: byte size of pin handle attribute, or 0 if @dev has no pin.
80 size_t dpll_netdev_pin_handle_size(const struct net_device *dev)
82 return dpll_netdev_pin(dev) ? nla_total_size(4) : 0; /* DPLL_A_PIN_ID */
85 int dpll_netdev_add_pin_handle(struct sk_buff *msg,
86 const struct net_device *dev)
88 return dpll_msg_add_pin_handle(msg, dpll_netdev_pin(dev));
92 dpll_msg_add_mode(struct sk_buff *msg, struct dpll_device *dpll,
93 struct netlink_ext_ack *extack)
95 const struct dpll_device_ops *ops = dpll_device_ops(dpll);
99 ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack);
102 if (nla_put_u32(msg, DPLL_A_MODE, mode))
109 dpll_msg_add_mode_supported(struct sk_buff *msg, struct dpll_device *dpll,
110 struct netlink_ext_ack *extack)
112 const struct dpll_device_ops *ops = dpll_device_ops(dpll);
116 /* No mode change is supported now, so the only supported mode is the
117 * one obtained by mode_get().
120 ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack);
123 if (nla_put_u32(msg, DPLL_A_MODE_SUPPORTED, mode))
130 dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll,
131 struct netlink_ext_ack *extack)
133 const struct dpll_device_ops *ops = dpll_device_ops(dpll);
134 enum dpll_lock_status status;
137 ret = ops->lock_status_get(dpll, dpll_priv(dpll), &status, extack);
140 if (nla_put_u32(msg, DPLL_A_LOCK_STATUS, status))
147 dpll_msg_add_temp(struct sk_buff *msg, struct dpll_device *dpll,
148 struct netlink_ext_ack *extack)
150 const struct dpll_device_ops *ops = dpll_device_ops(dpll);
156 ret = ops->temp_get(dpll, dpll_priv(dpll), &temp, extack);
159 if (nla_put_s32(msg, DPLL_A_TEMP, temp))
166 dpll_msg_add_pin_prio(struct sk_buff *msg, struct dpll_pin *pin,
167 struct dpll_pin_ref *ref,
168 struct netlink_ext_ack *extack)
170 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
171 struct dpll_device *dpll = ref->dpll;
177 ret = ops->prio_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
178 dpll_priv(dpll), &prio, extack);
181 if (nla_put_u32(msg, DPLL_A_PIN_PRIO, prio))
188 dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, struct dpll_pin *pin,
189 struct dpll_pin_ref *ref,
190 struct netlink_ext_ack *extack)
192 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
193 struct dpll_device *dpll = ref->dpll;
194 enum dpll_pin_state state;
197 if (!ops->state_on_dpll_get)
199 ret = ops->state_on_dpll_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
200 dpll, dpll_priv(dpll), &state, extack);
203 if (nla_put_u32(msg, DPLL_A_PIN_STATE, state))
210 dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin,
211 struct dpll_pin_ref *ref,
212 struct netlink_ext_ack *extack)
214 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
215 struct dpll_device *dpll = ref->dpll;
216 enum dpll_pin_direction direction;
219 ret = ops->direction_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
220 dpll_priv(dpll), &direction, extack);
223 if (nla_put_u32(msg, DPLL_A_PIN_DIRECTION, direction))
230 dpll_msg_add_pin_phase_adjust(struct sk_buff *msg, struct dpll_pin *pin,
231 struct dpll_pin_ref *ref,
232 struct netlink_ext_ack *extack)
234 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
235 struct dpll_device *dpll = ref->dpll;
239 if (!ops->phase_adjust_get)
241 ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
242 dpll, dpll_priv(dpll),
243 &phase_adjust, extack);
246 if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST, phase_adjust))
253 dpll_msg_add_phase_offset(struct sk_buff *msg, struct dpll_pin *pin,
254 struct dpll_pin_ref *ref,
255 struct netlink_ext_ack *extack)
257 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
258 struct dpll_device *dpll = ref->dpll;
262 if (!ops->phase_offset_get)
264 ret = ops->phase_offset_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
265 dpll, dpll_priv(dpll), &phase_offset,
269 if (nla_put_64bit(msg, DPLL_A_PIN_PHASE_OFFSET, sizeof(phase_offset),
270 &phase_offset, DPLL_A_PIN_PAD))
276 static int dpll_msg_add_ffo(struct sk_buff *msg, struct dpll_pin *pin,
277 struct dpll_pin_ref *ref,
278 struct netlink_ext_ack *extack)
280 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
281 struct dpll_device *dpll = ref->dpll;
287 ret = ops->ffo_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
288 dpll, dpll_priv(dpll), &ffo, extack);
294 return nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET, ffo);
298 dpll_msg_add_pin_freq(struct sk_buff *msg, struct dpll_pin *pin,
299 struct dpll_pin_ref *ref, struct netlink_ext_ack *extack)
301 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
302 struct dpll_device *dpll = ref->dpll;
307 if (!ops->frequency_get)
309 ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
310 dpll_priv(dpll), &freq, extack);
313 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY, sizeof(freq), &freq,
316 for (fs = 0; fs < pin->prop.freq_supported_num; fs++) {
317 nest = nla_nest_start(msg, DPLL_A_PIN_FREQUENCY_SUPPORTED);
320 freq = pin->prop.freq_supported[fs].min;
321 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MIN, sizeof(freq),
322 &freq, DPLL_A_PIN_PAD)) {
323 nla_nest_cancel(msg, nest);
326 freq = pin->prop.freq_supported[fs].max;
327 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MAX, sizeof(freq),
328 &freq, DPLL_A_PIN_PAD)) {
329 nla_nest_cancel(msg, nest);
332 nla_nest_end(msg, nest);
338 static bool dpll_pin_is_freq_supported(struct dpll_pin *pin, u32 freq)
342 for (fs = 0; fs < pin->prop.freq_supported_num; fs++)
343 if (freq >= pin->prop.freq_supported[fs].min &&
344 freq <= pin->prop.freq_supported[fs].max)
350 dpll_msg_add_pin_parents(struct sk_buff *msg, struct dpll_pin *pin,
351 struct dpll_pin_ref *dpll_ref,
352 struct netlink_ext_ack *extack)
354 enum dpll_pin_state state;
355 struct dpll_pin_ref *ref;
356 struct dpll_pin *ppin;
361 xa_for_each(&pin->parent_refs, index, ref) {
362 const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
366 parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, ppin);
367 ret = ops->state_on_pin_get(pin,
368 dpll_pin_on_pin_priv(ppin, pin),
369 ppin, parent_priv, &state, extack);
372 nest = nla_nest_start(msg, DPLL_A_PIN_PARENT_PIN);
375 ret = dpll_msg_add_dev_parent_handle(msg, ppin->id);
378 if (nla_put_u32(msg, DPLL_A_PIN_STATE, state)) {
382 nla_nest_end(msg, nest);
388 nla_nest_cancel(msg, nest);
393 dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin,
394 struct netlink_ext_ack *extack)
396 struct dpll_pin_ref *ref;
401 xa_for_each(&pin->dpll_refs, index, ref) {
402 attr = nla_nest_start(msg, DPLL_A_PIN_PARENT_DEVICE);
405 ret = dpll_msg_add_dev_parent_handle(msg, ref->dpll->id);
408 ret = dpll_msg_add_pin_on_dpll_state(msg, pin, ref, extack);
411 ret = dpll_msg_add_pin_prio(msg, pin, ref, extack);
414 ret = dpll_msg_add_pin_direction(msg, pin, ref, extack);
417 ret = dpll_msg_add_phase_offset(msg, pin, ref, extack);
420 nla_nest_end(msg, attr);
426 nla_nest_end(msg, attr);
431 dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
432 struct netlink_ext_ack *extack)
434 const struct dpll_pin_properties *prop = &pin->prop;
435 struct dpll_pin_ref *ref;
438 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
439 ASSERT_NOT_NULL(ref);
441 ret = dpll_msg_add_pin_handle(msg, pin);
444 if (nla_put_string(msg, DPLL_A_PIN_MODULE_NAME,
445 module_name(pin->module)))
447 if (nla_put_64bit(msg, DPLL_A_PIN_CLOCK_ID, sizeof(pin->clock_id),
448 &pin->clock_id, DPLL_A_PIN_PAD))
450 if (prop->board_label &&
451 nla_put_string(msg, DPLL_A_PIN_BOARD_LABEL, prop->board_label))
453 if (prop->panel_label &&
454 nla_put_string(msg, DPLL_A_PIN_PANEL_LABEL, prop->panel_label))
456 if (prop->package_label &&
457 nla_put_string(msg, DPLL_A_PIN_PACKAGE_LABEL,
458 prop->package_label))
460 if (nla_put_u32(msg, DPLL_A_PIN_TYPE, prop->type))
462 if (nla_put_u32(msg, DPLL_A_PIN_CAPABILITIES, prop->capabilities))
464 ret = dpll_msg_add_pin_freq(msg, pin, ref, extack);
467 if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MIN,
468 prop->phase_range.min))
470 if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MAX,
471 prop->phase_range.max))
473 ret = dpll_msg_add_pin_phase_adjust(msg, pin, ref, extack);
476 ret = dpll_msg_add_ffo(msg, pin, ref, extack);
479 if (xa_empty(&pin->parent_refs))
480 ret = dpll_msg_add_pin_dplls(msg, pin, extack);
482 ret = dpll_msg_add_pin_parents(msg, pin, ref, extack);
488 dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
489 struct netlink_ext_ack *extack)
493 ret = dpll_msg_add_dev_handle(msg, dpll);
496 if (nla_put_string(msg, DPLL_A_MODULE_NAME, module_name(dpll->module)))
498 if (nla_put_64bit(msg, DPLL_A_CLOCK_ID, sizeof(dpll->clock_id),
499 &dpll->clock_id, DPLL_A_PAD))
501 ret = dpll_msg_add_temp(msg, dpll, extack);
504 ret = dpll_msg_add_lock_status(msg, dpll, extack);
507 ret = dpll_msg_add_mode(msg, dpll, extack);
510 ret = dpll_msg_add_mode_supported(msg, dpll, extack);
513 if (nla_put_u32(msg, DPLL_A_TYPE, dpll->type))
520 dpll_device_event_send(enum dpll_cmd event, struct dpll_device *dpll)
526 if (WARN_ON(!xa_get_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED)))
528 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
531 hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
534 ret = dpll_device_get_one(dpll, msg, NULL);
537 genlmsg_end(msg, hdr);
538 genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
543 genlmsg_cancel(msg, hdr);
550 int dpll_device_create_ntf(struct dpll_device *dpll)
552 return dpll_device_event_send(DPLL_CMD_DEVICE_CREATE_NTF, dpll);
555 int dpll_device_delete_ntf(struct dpll_device *dpll)
557 return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF, dpll);
561 __dpll_device_change_ntf(struct dpll_device *dpll)
563 return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll);
566 static bool dpll_pin_available(struct dpll_pin *pin)
568 struct dpll_pin_ref *par_ref;
571 if (!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED))
573 xa_for_each(&pin->parent_refs, i, par_ref)
574 if (xa_get_mark(&dpll_pin_xa, par_ref->pin->id,
577 xa_for_each(&pin->dpll_refs, i, par_ref)
578 if (xa_get_mark(&dpll_device_xa, par_ref->dpll->id,
585 * dpll_device_change_ntf - notify that the dpll device has been changed
586 * @dpll: registered dpll pointer
588 * Context: acquires and holds a dpll_lock.
589 * Return: 0 if succeeds, error code otherwise.
591 int dpll_device_change_ntf(struct dpll_device *dpll)
595 mutex_lock(&dpll_lock);
596 ret = __dpll_device_change_ntf(dpll);
597 mutex_unlock(&dpll_lock);
601 EXPORT_SYMBOL_GPL(dpll_device_change_ntf);
604 dpll_pin_event_send(enum dpll_cmd event, struct dpll_pin *pin)
610 if (!dpll_pin_available(pin))
613 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
617 hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
620 ret = dpll_cmd_pin_get_one(msg, pin, NULL);
623 genlmsg_end(msg, hdr);
624 genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
629 genlmsg_cancel(msg, hdr);
636 int dpll_pin_create_ntf(struct dpll_pin *pin)
638 return dpll_pin_event_send(DPLL_CMD_PIN_CREATE_NTF, pin);
641 int dpll_pin_delete_ntf(struct dpll_pin *pin)
643 return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin);
646 static int __dpll_pin_change_ntf(struct dpll_pin *pin)
648 return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin);
652 * dpll_pin_change_ntf - notify that the pin has been changed
653 * @pin: registered pin pointer
655 * Context: acquires and holds a dpll_lock.
656 * Return: 0 if succeeds, error code otherwise.
658 int dpll_pin_change_ntf(struct dpll_pin *pin)
662 mutex_lock(&dpll_lock);
663 ret = __dpll_pin_change_ntf(pin);
664 mutex_unlock(&dpll_lock);
668 EXPORT_SYMBOL_GPL(dpll_pin_change_ntf);
671 dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
672 struct netlink_ext_ack *extack)
674 u64 freq = nla_get_u64(a), old_freq;
675 struct dpll_pin_ref *ref, *failed;
676 const struct dpll_pin_ops *ops;
677 struct dpll_device *dpll;
681 if (!dpll_pin_is_freq_supported(pin, freq)) {
682 NL_SET_ERR_MSG_ATTR(extack, a, "frequency is not supported by the device");
686 xa_for_each(&pin->dpll_refs, i, ref) {
687 ops = dpll_pin_ops(ref);
688 if (!ops->frequency_set || !ops->frequency_get) {
689 NL_SET_ERR_MSG(extack, "frequency set not supported by the device");
693 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
694 ops = dpll_pin_ops(ref);
696 ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
697 dpll_priv(dpll), &old_freq, extack);
699 NL_SET_ERR_MSG(extack, "unable to get old frequency value");
702 if (freq == old_freq)
705 xa_for_each(&pin->dpll_refs, i, ref) {
706 ops = dpll_pin_ops(ref);
708 ret = ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
709 dpll, dpll_priv(dpll), freq, extack);
712 NL_SET_ERR_MSG_FMT(extack, "frequency set failed for dpll_id:%u",
717 __dpll_pin_change_ntf(pin);
722 xa_for_each(&pin->dpll_refs, i, ref) {
725 ops = dpll_pin_ops(ref);
727 if (ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
728 dpll, dpll_priv(dpll), old_freq, extack))
729 NL_SET_ERR_MSG(extack, "set frequency rollback failed");
735 dpll_pin_on_pin_state_set(struct dpll_pin *pin, u32 parent_idx,
736 enum dpll_pin_state state,
737 struct netlink_ext_ack *extack)
739 struct dpll_pin_ref *parent_ref;
740 const struct dpll_pin_ops *ops;
741 struct dpll_pin_ref *dpll_ref;
742 void *pin_priv, *parent_priv;
743 struct dpll_pin *parent;
747 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
748 pin->prop.capabilities)) {
749 NL_SET_ERR_MSG(extack, "state changing is not allowed");
752 parent = xa_load(&dpll_pin_xa, parent_idx);
755 parent_ref = xa_load(&pin->parent_refs, parent->pin_idx);
758 xa_for_each(&parent->dpll_refs, i, dpll_ref) {
759 ops = dpll_pin_ops(parent_ref);
760 if (!ops->state_on_pin_set)
762 pin_priv = dpll_pin_on_pin_priv(parent, pin);
763 parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, parent);
764 ret = ops->state_on_pin_set(pin, pin_priv, parent, parent_priv,
769 __dpll_pin_change_ntf(pin);
775 dpll_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin,
776 enum dpll_pin_state state,
777 struct netlink_ext_ack *extack)
779 const struct dpll_pin_ops *ops;
780 struct dpll_pin_ref *ref;
783 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
784 pin->prop.capabilities)) {
785 NL_SET_ERR_MSG(extack, "state changing is not allowed");
788 ref = xa_load(&pin->dpll_refs, dpll->id);
789 ASSERT_NOT_NULL(ref);
790 ops = dpll_pin_ops(ref);
791 if (!ops->state_on_dpll_set)
793 ret = ops->state_on_dpll_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
794 dpll, dpll_priv(dpll), state, extack);
797 __dpll_pin_change_ntf(pin);
803 dpll_pin_prio_set(struct dpll_device *dpll, struct dpll_pin *pin,
804 u32 prio, struct netlink_ext_ack *extack)
806 const struct dpll_pin_ops *ops;
807 struct dpll_pin_ref *ref;
810 if (!(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE &
811 pin->prop.capabilities)) {
812 NL_SET_ERR_MSG(extack, "prio changing is not allowed");
815 ref = xa_load(&pin->dpll_refs, dpll->id);
816 ASSERT_NOT_NULL(ref);
817 ops = dpll_pin_ops(ref);
820 ret = ops->prio_set(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
821 dpll_priv(dpll), prio, extack);
824 __dpll_pin_change_ntf(pin);
830 dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll,
831 enum dpll_pin_direction direction,
832 struct netlink_ext_ack *extack)
834 const struct dpll_pin_ops *ops;
835 struct dpll_pin_ref *ref;
838 if (!(DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE &
839 pin->prop.capabilities)) {
840 NL_SET_ERR_MSG(extack, "direction changing is not allowed");
843 ref = xa_load(&pin->dpll_refs, dpll->id);
844 ASSERT_NOT_NULL(ref);
845 ops = dpll_pin_ops(ref);
846 if (!ops->direction_set)
848 ret = ops->direction_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
849 dpll, dpll_priv(dpll), direction, extack);
852 __dpll_pin_change_ntf(pin);
858 dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr,
859 struct netlink_ext_ack *extack)
861 struct dpll_pin_ref *ref, *failed;
862 const struct dpll_pin_ops *ops;
863 s32 phase_adj, old_phase_adj;
864 struct dpll_device *dpll;
868 phase_adj = nla_get_s32(phase_adj_attr);
869 if (phase_adj > pin->prop.phase_range.max ||
870 phase_adj < pin->prop.phase_range.min) {
871 NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr,
872 "phase adjust value not supported");
876 xa_for_each(&pin->dpll_refs, i, ref) {
877 ops = dpll_pin_ops(ref);
878 if (!ops->phase_adjust_set || !ops->phase_adjust_get) {
879 NL_SET_ERR_MSG(extack, "phase adjust not supported");
883 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
884 ops = dpll_pin_ops(ref);
886 ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
887 dpll, dpll_priv(dpll), &old_phase_adj,
890 NL_SET_ERR_MSG(extack, "unable to get old phase adjust value");
893 if (phase_adj == old_phase_adj)
896 xa_for_each(&pin->dpll_refs, i, ref) {
897 ops = dpll_pin_ops(ref);
899 ret = ops->phase_adjust_set(pin,
900 dpll_pin_on_dpll_priv(dpll, pin),
901 dpll, dpll_priv(dpll), phase_adj,
905 NL_SET_ERR_MSG_FMT(extack,
906 "phase adjust set failed for dpll_id:%u",
911 __dpll_pin_change_ntf(pin);
916 xa_for_each(&pin->dpll_refs, i, ref) {
919 ops = dpll_pin_ops(ref);
921 if (ops->phase_adjust_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
922 dpll, dpll_priv(dpll), old_phase_adj,
924 NL_SET_ERR_MSG(extack, "set phase adjust rollback failed");
930 dpll_pin_parent_device_set(struct dpll_pin *pin, struct nlattr *parent_nest,
931 struct netlink_ext_ack *extack)
933 struct nlattr *tb[DPLL_A_PIN_MAX + 1];
934 enum dpll_pin_direction direction;
935 enum dpll_pin_state state;
936 struct dpll_pin_ref *ref;
937 struct dpll_device *dpll;
941 nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
942 dpll_pin_parent_device_nl_policy, extack);
943 if (!tb[DPLL_A_PIN_PARENT_ID]) {
944 NL_SET_ERR_MSG(extack, "device parent id expected");
947 pdpll_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
948 dpll = xa_load(&dpll_device_xa, pdpll_idx);
950 NL_SET_ERR_MSG(extack, "parent device not found");
953 ref = xa_load(&pin->dpll_refs, dpll->id);
955 NL_SET_ERR_MSG(extack, "pin not connected to given parent device");
958 if (tb[DPLL_A_PIN_STATE]) {
959 state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
960 ret = dpll_pin_state_set(dpll, pin, state, extack);
964 if (tb[DPLL_A_PIN_PRIO]) {
965 prio = nla_get_u32(tb[DPLL_A_PIN_PRIO]);
966 ret = dpll_pin_prio_set(dpll, pin, prio, extack);
970 if (tb[DPLL_A_PIN_DIRECTION]) {
971 direction = nla_get_u32(tb[DPLL_A_PIN_DIRECTION]);
972 ret = dpll_pin_direction_set(pin, dpll, direction, extack);
980 dpll_pin_parent_pin_set(struct dpll_pin *pin, struct nlattr *parent_nest,
981 struct netlink_ext_ack *extack)
983 struct nlattr *tb[DPLL_A_PIN_MAX + 1];
987 nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
988 dpll_pin_parent_pin_nl_policy, extack);
989 if (!tb[DPLL_A_PIN_PARENT_ID]) {
990 NL_SET_ERR_MSG(extack, "device parent id expected");
993 ppin_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
995 if (tb[DPLL_A_PIN_STATE]) {
996 enum dpll_pin_state state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
998 ret = dpll_pin_on_pin_state_set(pin, ppin_idx, state, extack);
1007 dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
1012 nla_for_each_attr(a, genlmsg_data(info->genlhdr),
1013 genlmsg_len(info->genlhdr), rem) {
1014 switch (nla_type(a)) {
1015 case DPLL_A_PIN_FREQUENCY:
1016 ret = dpll_pin_freq_set(pin, a, info->extack);
1020 case DPLL_A_PIN_PHASE_ADJUST:
1021 ret = dpll_pin_phase_adj_set(pin, a, info->extack);
1025 case DPLL_A_PIN_PARENT_DEVICE:
1026 ret = dpll_pin_parent_device_set(pin, a, info->extack);
1030 case DPLL_A_PIN_PARENT_PIN:
1031 ret = dpll_pin_parent_pin_set(pin, a, info->extack);
1041 static struct dpll_pin *
1042 dpll_pin_find(u64 clock_id, struct nlattr *mod_name_attr,
1043 enum dpll_pin_type type, struct nlattr *board_label,
1044 struct nlattr *panel_label, struct nlattr *package_label,
1045 struct netlink_ext_ack *extack)
1047 bool board_match, panel_match, package_match;
1048 struct dpll_pin *pin_match = NULL, *pin;
1049 const struct dpll_pin_properties *prop;
1050 bool cid_match, mod_match, type_match;
1053 xa_for_each_marked(&dpll_pin_xa, i, pin, DPLL_REGISTERED) {
1055 cid_match = clock_id ? pin->clock_id == clock_id : true;
1056 mod_match = mod_name_attr && module_name(pin->module) ?
1057 !nla_strcmp(mod_name_attr,
1058 module_name(pin->module)) : true;
1059 type_match = type ? prop->type == type : true;
1060 board_match = board_label ? (prop->board_label ?
1061 !nla_strcmp(board_label, prop->board_label) : false) :
1063 panel_match = panel_label ? (prop->panel_label ?
1064 !nla_strcmp(panel_label, prop->panel_label) : false) :
1066 package_match = package_label ? (prop->package_label ?
1067 !nla_strcmp(package_label, prop->package_label) :
1069 if (cid_match && mod_match && type_match && board_match &&
1070 panel_match && package_match) {
1072 NL_SET_ERR_MSG(extack, "multiple matches");
1073 return ERR_PTR(-EINVAL);
1079 NL_SET_ERR_MSG(extack, "not found");
1080 return ERR_PTR(-ENODEV);
1085 static struct dpll_pin *dpll_pin_find_from_nlattr(struct genl_info *info)
1087 struct nlattr *attr, *mod_name_attr = NULL, *board_label_attr = NULL,
1088 *panel_label_attr = NULL, *package_label_attr = NULL;
1089 enum dpll_pin_type type = 0;
1093 nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
1094 genlmsg_len(info->genlhdr), rem) {
1095 switch (nla_type(attr)) {
1096 case DPLL_A_PIN_CLOCK_ID:
1098 goto duplicated_attr;
1099 clock_id = nla_get_u64(attr);
1101 case DPLL_A_PIN_MODULE_NAME:
1103 goto duplicated_attr;
1104 mod_name_attr = attr;
1106 case DPLL_A_PIN_TYPE:
1108 goto duplicated_attr;
1109 type = nla_get_u32(attr);
1111 case DPLL_A_PIN_BOARD_LABEL:
1112 if (board_label_attr)
1113 goto duplicated_attr;
1114 board_label_attr = attr;
1116 case DPLL_A_PIN_PANEL_LABEL:
1117 if (panel_label_attr)
1118 goto duplicated_attr;
1119 panel_label_attr = attr;
1121 case DPLL_A_PIN_PACKAGE_LABEL:
1122 if (package_label_attr)
1123 goto duplicated_attr;
1124 package_label_attr = attr;
1130 if (!(clock_id || mod_name_attr || board_label_attr ||
1131 panel_label_attr || package_label_attr)) {
1132 NL_SET_ERR_MSG(info->extack, "missing attributes");
1133 return ERR_PTR(-EINVAL);
1135 return dpll_pin_find(clock_id, mod_name_attr, type, board_label_attr,
1136 panel_label_attr, package_label_attr,
1139 NL_SET_ERR_MSG(info->extack, "duplicated attribute");
1140 return ERR_PTR(-EINVAL);
1143 int dpll_nl_pin_id_get_doit(struct sk_buff *skb, struct genl_info *info)
1145 struct dpll_pin *pin;
1146 struct sk_buff *msg;
1150 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1153 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1154 DPLL_CMD_PIN_ID_GET);
1159 pin = dpll_pin_find_from_nlattr(info);
1161 if (!dpll_pin_available(pin)) {
1165 ret = dpll_msg_add_pin_handle(msg, pin);
1171 genlmsg_end(msg, hdr);
1173 return genlmsg_reply(msg, info);
1176 int dpll_nl_pin_get_doit(struct sk_buff *skb, struct genl_info *info)
1178 struct dpll_pin *pin = info->user_ptr[0];
1179 struct sk_buff *msg;
1185 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1188 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1194 ret = dpll_cmd_pin_get_one(msg, pin, info->extack);
1199 genlmsg_end(msg, hdr);
1201 return genlmsg_reply(msg, info);
1204 int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
1206 struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
1207 struct dpll_pin *pin;
1212 mutex_lock(&dpll_lock);
1213 xa_for_each_marked_start(&dpll_pin_xa, i, pin, DPLL_REGISTERED,
1215 if (!dpll_pin_available(pin))
1217 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1219 &dpll_nl_family, NLM_F_MULTI,
1225 ret = dpll_cmd_pin_get_one(skb, pin, cb->extack);
1227 genlmsg_cancel(skb, hdr);
1230 genlmsg_end(skb, hdr);
1232 mutex_unlock(&dpll_lock);
1234 if (ret == -EMSGSIZE) {
1241 int dpll_nl_pin_set_doit(struct sk_buff *skb, struct genl_info *info)
1243 struct dpll_pin *pin = info->user_ptr[0];
1245 return dpll_pin_set_from_nlattr(pin, info);
1248 static struct dpll_device *
1249 dpll_device_find(u64 clock_id, struct nlattr *mod_name_attr,
1250 enum dpll_type type, struct netlink_ext_ack *extack)
1252 struct dpll_device *dpll_match = NULL, *dpll;
1253 bool cid_match, mod_match, type_match;
1256 xa_for_each_marked(&dpll_device_xa, i, dpll, DPLL_REGISTERED) {
1257 cid_match = clock_id ? dpll->clock_id == clock_id : true;
1258 mod_match = mod_name_attr ? (module_name(dpll->module) ?
1259 !nla_strcmp(mod_name_attr,
1260 module_name(dpll->module)) : false) : true;
1261 type_match = type ? dpll->type == type : true;
1262 if (cid_match && mod_match && type_match) {
1264 NL_SET_ERR_MSG(extack, "multiple matches");
1265 return ERR_PTR(-EINVAL);
1271 NL_SET_ERR_MSG(extack, "not found");
1272 return ERR_PTR(-ENODEV);
1278 static struct dpll_device *
1279 dpll_device_find_from_nlattr(struct genl_info *info)
1281 struct nlattr *attr, *mod_name_attr = NULL;
1282 enum dpll_type type = 0;
1286 nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
1287 genlmsg_len(info->genlhdr), rem) {
1288 switch (nla_type(attr)) {
1289 case DPLL_A_CLOCK_ID:
1291 goto duplicated_attr;
1292 clock_id = nla_get_u64(attr);
1294 case DPLL_A_MODULE_NAME:
1296 goto duplicated_attr;
1297 mod_name_attr = attr;
1301 goto duplicated_attr;
1302 type = nla_get_u32(attr);
1308 if (!clock_id && !mod_name_attr && !type) {
1309 NL_SET_ERR_MSG(info->extack, "missing attributes");
1310 return ERR_PTR(-EINVAL);
1312 return dpll_device_find(clock_id, mod_name_attr, type, info->extack);
1314 NL_SET_ERR_MSG(info->extack, "duplicated attribute");
1315 return ERR_PTR(-EINVAL);
1318 int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info)
1320 struct dpll_device *dpll;
1321 struct sk_buff *msg;
1325 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1328 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1329 DPLL_CMD_DEVICE_ID_GET);
1335 dpll = dpll_device_find_from_nlattr(info);
1336 if (!IS_ERR(dpll)) {
1337 ret = dpll_msg_add_dev_handle(msg, dpll);
1343 genlmsg_end(msg, hdr);
1345 return genlmsg_reply(msg, info);
1348 int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info)
1350 struct dpll_device *dpll = info->user_ptr[0];
1351 struct sk_buff *msg;
1355 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1358 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1359 DPLL_CMD_DEVICE_GET);
1365 ret = dpll_device_get_one(dpll, msg, info->extack);
1370 genlmsg_end(msg, hdr);
1372 return genlmsg_reply(msg, info);
1375 int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info)
1377 /* placeholder for set command */
1381 int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
1383 struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
1384 struct dpll_device *dpll;
1389 mutex_lock(&dpll_lock);
1390 xa_for_each_marked_start(&dpll_device_xa, i, dpll, DPLL_REGISTERED,
1392 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1393 cb->nlh->nlmsg_seq, &dpll_nl_family,
1394 NLM_F_MULTI, DPLL_CMD_DEVICE_GET);
1399 ret = dpll_device_get_one(dpll, skb, cb->extack);
1401 genlmsg_cancel(skb, hdr);
1404 genlmsg_end(skb, hdr);
1406 mutex_unlock(&dpll_lock);
1408 if (ret == -EMSGSIZE) {
1415 int dpll_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1416 struct genl_info *info)
1420 if (GENL_REQ_ATTR_CHECK(info, DPLL_A_ID))
1423 mutex_lock(&dpll_lock);
1424 id = nla_get_u32(info->attrs[DPLL_A_ID]);
1425 info->user_ptr[0] = dpll_device_get_by_id(id);
1426 if (!info->user_ptr[0]) {
1427 NL_SET_ERR_MSG(info->extack, "device not found");
1432 mutex_unlock(&dpll_lock);
1436 void dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1437 struct genl_info *info)
1439 mutex_unlock(&dpll_lock);
1443 dpll_lock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1444 struct genl_info *info)
1446 mutex_lock(&dpll_lock);
1452 dpll_unlock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1453 struct genl_info *info)
1455 mutex_unlock(&dpll_lock);
1458 int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1459 struct genl_info *info)
1463 mutex_lock(&dpll_lock);
1464 if (GENL_REQ_ATTR_CHECK(info, DPLL_A_PIN_ID)) {
1468 info->user_ptr[0] = xa_load(&dpll_pin_xa,
1469 nla_get_u32(info->attrs[DPLL_A_PIN_ID]));
1470 if (!info->user_ptr[0] ||
1471 !dpll_pin_available(info->user_ptr[0])) {
1472 NL_SET_ERR_MSG(info->extack, "pin not found");
1480 mutex_unlock(&dpll_lock);
1484 void dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1485 struct genl_info *info)
1487 mutex_unlock(&dpll_lock);