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_error status_error
= 0;
135 enum dpll_lock_status status
;
138 ret
= ops
->lock_status_get(dpll
, dpll_priv(dpll
), &status
,
139 &status_error
, extack
);
142 if (nla_put_u32(msg
, DPLL_A_LOCK_STATUS
, status
))
145 (status
== DPLL_LOCK_STATUS_UNLOCKED
||
146 status
== DPLL_LOCK_STATUS_HOLDOVER
) &&
147 nla_put_u32(msg
, DPLL_A_LOCK_STATUS_ERROR
, status_error
))
154 dpll_msg_add_temp(struct sk_buff
*msg
, struct dpll_device
*dpll
,
155 struct netlink_ext_ack
*extack
)
157 const struct dpll_device_ops
*ops
= dpll_device_ops(dpll
);
163 ret
= ops
->temp_get(dpll
, dpll_priv(dpll
), &temp
, extack
);
166 if (nla_put_s32(msg
, DPLL_A_TEMP
, temp
))
173 dpll_msg_add_pin_prio(struct sk_buff
*msg
, struct dpll_pin
*pin
,
174 struct dpll_pin_ref
*ref
,
175 struct netlink_ext_ack
*extack
)
177 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
178 struct dpll_device
*dpll
= ref
->dpll
;
184 ret
= ops
->prio_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
185 dpll_priv(dpll
), &prio
, extack
);
188 if (nla_put_u32(msg
, DPLL_A_PIN_PRIO
, prio
))
195 dpll_msg_add_pin_on_dpll_state(struct sk_buff
*msg
, struct dpll_pin
*pin
,
196 struct dpll_pin_ref
*ref
,
197 struct netlink_ext_ack
*extack
)
199 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
200 struct dpll_device
*dpll
= ref
->dpll
;
201 enum dpll_pin_state state
;
204 if (!ops
->state_on_dpll_get
)
206 ret
= ops
->state_on_dpll_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
207 dpll
, dpll_priv(dpll
), &state
, extack
);
210 if (nla_put_u32(msg
, DPLL_A_PIN_STATE
, state
))
217 dpll_msg_add_pin_direction(struct sk_buff
*msg
, struct dpll_pin
*pin
,
218 struct dpll_pin_ref
*ref
,
219 struct netlink_ext_ack
*extack
)
221 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
222 struct dpll_device
*dpll
= ref
->dpll
;
223 enum dpll_pin_direction direction
;
226 ret
= ops
->direction_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
227 dpll_priv(dpll
), &direction
, extack
);
230 if (nla_put_u32(msg
, DPLL_A_PIN_DIRECTION
, direction
))
237 dpll_msg_add_pin_phase_adjust(struct sk_buff
*msg
, struct dpll_pin
*pin
,
238 struct dpll_pin_ref
*ref
,
239 struct netlink_ext_ack
*extack
)
241 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
242 struct dpll_device
*dpll
= ref
->dpll
;
246 if (!ops
->phase_adjust_get
)
248 ret
= ops
->phase_adjust_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
249 dpll
, dpll_priv(dpll
),
250 &phase_adjust
, extack
);
253 if (nla_put_s32(msg
, DPLL_A_PIN_PHASE_ADJUST
, phase_adjust
))
260 dpll_msg_add_phase_offset(struct sk_buff
*msg
, struct dpll_pin
*pin
,
261 struct dpll_pin_ref
*ref
,
262 struct netlink_ext_ack
*extack
)
264 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
265 struct dpll_device
*dpll
= ref
->dpll
;
269 if (!ops
->phase_offset_get
)
271 ret
= ops
->phase_offset_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
272 dpll
, dpll_priv(dpll
), &phase_offset
,
276 if (nla_put_64bit(msg
, DPLL_A_PIN_PHASE_OFFSET
, sizeof(phase_offset
),
277 &phase_offset
, DPLL_A_PIN_PAD
))
283 static int dpll_msg_add_ffo(struct sk_buff
*msg
, struct dpll_pin
*pin
,
284 struct dpll_pin_ref
*ref
,
285 struct netlink_ext_ack
*extack
)
287 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
288 struct dpll_device
*dpll
= ref
->dpll
;
294 ret
= ops
->ffo_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
295 dpll
, dpll_priv(dpll
), &ffo
, extack
);
301 return nla_put_sint(msg
, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET
, ffo
);
305 dpll_msg_add_pin_freq(struct sk_buff
*msg
, struct dpll_pin
*pin
,
306 struct dpll_pin_ref
*ref
, struct netlink_ext_ack
*extack
)
308 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
309 struct dpll_device
*dpll
= ref
->dpll
;
314 if (!ops
->frequency_get
)
316 ret
= ops
->frequency_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
317 dpll_priv(dpll
), &freq
, extack
);
320 if (nla_put_64bit(msg
, DPLL_A_PIN_FREQUENCY
, sizeof(freq
), &freq
,
323 for (fs
= 0; fs
< pin
->prop
.freq_supported_num
; fs
++) {
324 nest
= nla_nest_start(msg
, DPLL_A_PIN_FREQUENCY_SUPPORTED
);
327 freq
= pin
->prop
.freq_supported
[fs
].min
;
328 if (nla_put_64bit(msg
, DPLL_A_PIN_FREQUENCY_MIN
, sizeof(freq
),
329 &freq
, DPLL_A_PIN_PAD
)) {
330 nla_nest_cancel(msg
, nest
);
333 freq
= pin
->prop
.freq_supported
[fs
].max
;
334 if (nla_put_64bit(msg
, DPLL_A_PIN_FREQUENCY_MAX
, sizeof(freq
),
335 &freq
, DPLL_A_PIN_PAD
)) {
336 nla_nest_cancel(msg
, nest
);
339 nla_nest_end(msg
, nest
);
345 static bool dpll_pin_is_freq_supported(struct dpll_pin
*pin
, u32 freq
)
349 for (fs
= 0; fs
< pin
->prop
.freq_supported_num
; fs
++)
350 if (freq
>= pin
->prop
.freq_supported
[fs
].min
&&
351 freq
<= pin
->prop
.freq_supported
[fs
].max
)
357 dpll_msg_add_pin_parents(struct sk_buff
*msg
, struct dpll_pin
*pin
,
358 struct dpll_pin_ref
*dpll_ref
,
359 struct netlink_ext_ack
*extack
)
361 enum dpll_pin_state state
;
362 struct dpll_pin_ref
*ref
;
363 struct dpll_pin
*ppin
;
368 xa_for_each(&pin
->parent_refs
, index
, ref
) {
369 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
373 parent_priv
= dpll_pin_on_dpll_priv(dpll_ref
->dpll
, ppin
);
374 ret
= ops
->state_on_pin_get(pin
,
375 dpll_pin_on_pin_priv(ppin
, pin
),
376 ppin
, parent_priv
, &state
, extack
);
379 nest
= nla_nest_start(msg
, DPLL_A_PIN_PARENT_PIN
);
382 ret
= dpll_msg_add_dev_parent_handle(msg
, ppin
->id
);
385 if (nla_put_u32(msg
, DPLL_A_PIN_STATE
, state
)) {
389 nla_nest_end(msg
, nest
);
395 nla_nest_cancel(msg
, nest
);
400 dpll_msg_add_pin_dplls(struct sk_buff
*msg
, struct dpll_pin
*pin
,
401 struct netlink_ext_ack
*extack
)
403 struct dpll_pin_ref
*ref
;
408 xa_for_each(&pin
->dpll_refs
, index
, ref
) {
409 attr
= nla_nest_start(msg
, DPLL_A_PIN_PARENT_DEVICE
);
412 ret
= dpll_msg_add_dev_parent_handle(msg
, ref
->dpll
->id
);
415 ret
= dpll_msg_add_pin_on_dpll_state(msg
, pin
, ref
, extack
);
418 ret
= dpll_msg_add_pin_prio(msg
, pin
, ref
, extack
);
421 ret
= dpll_msg_add_pin_direction(msg
, pin
, ref
, extack
);
424 ret
= dpll_msg_add_phase_offset(msg
, pin
, ref
, extack
);
427 nla_nest_end(msg
, attr
);
433 nla_nest_end(msg
, attr
);
438 dpll_cmd_pin_get_one(struct sk_buff
*msg
, struct dpll_pin
*pin
,
439 struct netlink_ext_ack
*extack
)
441 const struct dpll_pin_properties
*prop
= &pin
->prop
;
442 struct dpll_pin_ref
*ref
;
445 ref
= dpll_xa_ref_dpll_first(&pin
->dpll_refs
);
446 ASSERT_NOT_NULL(ref
);
448 ret
= dpll_msg_add_pin_handle(msg
, pin
);
451 if (nla_put_string(msg
, DPLL_A_PIN_MODULE_NAME
,
452 module_name(pin
->module
)))
454 if (nla_put_64bit(msg
, DPLL_A_PIN_CLOCK_ID
, sizeof(pin
->clock_id
),
455 &pin
->clock_id
, DPLL_A_PIN_PAD
))
457 if (prop
->board_label
&&
458 nla_put_string(msg
, DPLL_A_PIN_BOARD_LABEL
, prop
->board_label
))
460 if (prop
->panel_label
&&
461 nla_put_string(msg
, DPLL_A_PIN_PANEL_LABEL
, prop
->panel_label
))
463 if (prop
->package_label
&&
464 nla_put_string(msg
, DPLL_A_PIN_PACKAGE_LABEL
,
465 prop
->package_label
))
467 if (nla_put_u32(msg
, DPLL_A_PIN_TYPE
, prop
->type
))
469 if (nla_put_u32(msg
, DPLL_A_PIN_CAPABILITIES
, prop
->capabilities
))
471 ret
= dpll_msg_add_pin_freq(msg
, pin
, ref
, extack
);
474 if (nla_put_s32(msg
, DPLL_A_PIN_PHASE_ADJUST_MIN
,
475 prop
->phase_range
.min
))
477 if (nla_put_s32(msg
, DPLL_A_PIN_PHASE_ADJUST_MAX
,
478 prop
->phase_range
.max
))
480 ret
= dpll_msg_add_pin_phase_adjust(msg
, pin
, ref
, extack
);
483 ret
= dpll_msg_add_ffo(msg
, pin
, ref
, extack
);
486 if (xa_empty(&pin
->parent_refs
))
487 ret
= dpll_msg_add_pin_dplls(msg
, pin
, extack
);
489 ret
= dpll_msg_add_pin_parents(msg
, pin
, ref
, extack
);
495 dpll_device_get_one(struct dpll_device
*dpll
, struct sk_buff
*msg
,
496 struct netlink_ext_ack
*extack
)
500 ret
= dpll_msg_add_dev_handle(msg
, dpll
);
503 if (nla_put_string(msg
, DPLL_A_MODULE_NAME
, module_name(dpll
->module
)))
505 if (nla_put_64bit(msg
, DPLL_A_CLOCK_ID
, sizeof(dpll
->clock_id
),
506 &dpll
->clock_id
, DPLL_A_PAD
))
508 ret
= dpll_msg_add_temp(msg
, dpll
, extack
);
511 ret
= dpll_msg_add_lock_status(msg
, dpll
, extack
);
514 ret
= dpll_msg_add_mode(msg
, dpll
, extack
);
517 ret
= dpll_msg_add_mode_supported(msg
, dpll
, extack
);
520 if (nla_put_u32(msg
, DPLL_A_TYPE
, dpll
->type
))
527 dpll_device_event_send(enum dpll_cmd event
, struct dpll_device
*dpll
)
533 if (WARN_ON(!xa_get_mark(&dpll_device_xa
, dpll
->id
, DPLL_REGISTERED
)))
535 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
538 hdr
= genlmsg_put(msg
, 0, 0, &dpll_nl_family
, 0, event
);
541 ret
= dpll_device_get_one(dpll
, msg
, NULL
);
544 genlmsg_end(msg
, hdr
);
545 genlmsg_multicast(&dpll_nl_family
, msg
, 0, 0, GFP_KERNEL
);
550 genlmsg_cancel(msg
, hdr
);
557 int dpll_device_create_ntf(struct dpll_device
*dpll
)
559 return dpll_device_event_send(DPLL_CMD_DEVICE_CREATE_NTF
, dpll
);
562 int dpll_device_delete_ntf(struct dpll_device
*dpll
)
564 return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF
, dpll
);
568 __dpll_device_change_ntf(struct dpll_device
*dpll
)
570 return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF
, dpll
);
573 static bool dpll_pin_available(struct dpll_pin
*pin
)
575 struct dpll_pin_ref
*par_ref
;
578 if (!xa_get_mark(&dpll_pin_xa
, pin
->id
, DPLL_REGISTERED
))
580 xa_for_each(&pin
->parent_refs
, i
, par_ref
)
581 if (xa_get_mark(&dpll_pin_xa
, par_ref
->pin
->id
,
584 xa_for_each(&pin
->dpll_refs
, i
, par_ref
)
585 if (xa_get_mark(&dpll_device_xa
, par_ref
->dpll
->id
,
592 * dpll_device_change_ntf - notify that the dpll device has been changed
593 * @dpll: registered dpll pointer
595 * Context: acquires and holds a dpll_lock.
596 * Return: 0 if succeeds, error code otherwise.
598 int dpll_device_change_ntf(struct dpll_device
*dpll
)
602 mutex_lock(&dpll_lock
);
603 ret
= __dpll_device_change_ntf(dpll
);
604 mutex_unlock(&dpll_lock
);
608 EXPORT_SYMBOL_GPL(dpll_device_change_ntf
);
611 dpll_pin_event_send(enum dpll_cmd event
, struct dpll_pin
*pin
)
617 if (!dpll_pin_available(pin
))
620 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
624 hdr
= genlmsg_put(msg
, 0, 0, &dpll_nl_family
, 0, event
);
627 ret
= dpll_cmd_pin_get_one(msg
, pin
, NULL
);
630 genlmsg_end(msg
, hdr
);
631 genlmsg_multicast(&dpll_nl_family
, msg
, 0, 0, GFP_KERNEL
);
636 genlmsg_cancel(msg
, hdr
);
643 int dpll_pin_create_ntf(struct dpll_pin
*pin
)
645 return dpll_pin_event_send(DPLL_CMD_PIN_CREATE_NTF
, pin
);
648 int dpll_pin_delete_ntf(struct dpll_pin
*pin
)
650 return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF
, pin
);
653 static int __dpll_pin_change_ntf(struct dpll_pin
*pin
)
655 return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF
, pin
);
659 * dpll_pin_change_ntf - notify that the pin has been changed
660 * @pin: registered pin pointer
662 * Context: acquires and holds a dpll_lock.
663 * Return: 0 if succeeds, error code otherwise.
665 int dpll_pin_change_ntf(struct dpll_pin
*pin
)
669 mutex_lock(&dpll_lock
);
670 ret
= __dpll_pin_change_ntf(pin
);
671 mutex_unlock(&dpll_lock
);
675 EXPORT_SYMBOL_GPL(dpll_pin_change_ntf
);
678 dpll_pin_freq_set(struct dpll_pin
*pin
, struct nlattr
*a
,
679 struct netlink_ext_ack
*extack
)
681 u64 freq
= nla_get_u64(a
), old_freq
;
682 struct dpll_pin_ref
*ref
, *failed
;
683 const struct dpll_pin_ops
*ops
;
684 struct dpll_device
*dpll
;
688 if (!dpll_pin_is_freq_supported(pin
, freq
)) {
689 NL_SET_ERR_MSG_ATTR(extack
, a
, "frequency is not supported by the device");
693 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
694 ops
= dpll_pin_ops(ref
);
695 if (!ops
->frequency_set
|| !ops
->frequency_get
) {
696 NL_SET_ERR_MSG(extack
, "frequency set not supported by the device");
700 ref
= dpll_xa_ref_dpll_first(&pin
->dpll_refs
);
701 ops
= dpll_pin_ops(ref
);
703 ret
= ops
->frequency_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
704 dpll_priv(dpll
), &old_freq
, extack
);
706 NL_SET_ERR_MSG(extack
, "unable to get old frequency value");
709 if (freq
== old_freq
)
712 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
713 ops
= dpll_pin_ops(ref
);
715 ret
= ops
->frequency_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
716 dpll
, dpll_priv(dpll
), freq
, extack
);
719 NL_SET_ERR_MSG_FMT(extack
, "frequency set failed for dpll_id:%u",
724 __dpll_pin_change_ntf(pin
);
729 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
732 ops
= dpll_pin_ops(ref
);
734 if (ops
->frequency_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
735 dpll
, dpll_priv(dpll
), old_freq
, extack
))
736 NL_SET_ERR_MSG(extack
, "set frequency rollback failed");
742 dpll_pin_on_pin_state_set(struct dpll_pin
*pin
, u32 parent_idx
,
743 enum dpll_pin_state state
,
744 struct netlink_ext_ack
*extack
)
746 struct dpll_pin_ref
*parent_ref
;
747 const struct dpll_pin_ops
*ops
;
748 struct dpll_pin_ref
*dpll_ref
;
749 void *pin_priv
, *parent_priv
;
750 struct dpll_pin
*parent
;
754 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE
&
755 pin
->prop
.capabilities
)) {
756 NL_SET_ERR_MSG(extack
, "state changing is not allowed");
759 parent
= xa_load(&dpll_pin_xa
, parent_idx
);
762 parent_ref
= xa_load(&pin
->parent_refs
, parent
->pin_idx
);
765 xa_for_each(&parent
->dpll_refs
, i
, dpll_ref
) {
766 ops
= dpll_pin_ops(parent_ref
);
767 if (!ops
->state_on_pin_set
)
769 pin_priv
= dpll_pin_on_pin_priv(parent
, pin
);
770 parent_priv
= dpll_pin_on_dpll_priv(dpll_ref
->dpll
, parent
);
771 ret
= ops
->state_on_pin_set(pin
, pin_priv
, parent
, parent_priv
,
776 __dpll_pin_change_ntf(pin
);
782 dpll_pin_state_set(struct dpll_device
*dpll
, struct dpll_pin
*pin
,
783 enum dpll_pin_state state
,
784 struct netlink_ext_ack
*extack
)
786 const struct dpll_pin_ops
*ops
;
787 struct dpll_pin_ref
*ref
;
790 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE
&
791 pin
->prop
.capabilities
)) {
792 NL_SET_ERR_MSG(extack
, "state changing is not allowed");
795 ref
= xa_load(&pin
->dpll_refs
, dpll
->id
);
796 ASSERT_NOT_NULL(ref
);
797 ops
= dpll_pin_ops(ref
);
798 if (!ops
->state_on_dpll_set
)
800 ret
= ops
->state_on_dpll_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
801 dpll
, dpll_priv(dpll
), state
, extack
);
804 __dpll_pin_change_ntf(pin
);
810 dpll_pin_prio_set(struct dpll_device
*dpll
, struct dpll_pin
*pin
,
811 u32 prio
, struct netlink_ext_ack
*extack
)
813 const struct dpll_pin_ops
*ops
;
814 struct dpll_pin_ref
*ref
;
817 if (!(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE
&
818 pin
->prop
.capabilities
)) {
819 NL_SET_ERR_MSG(extack
, "prio changing is not allowed");
822 ref
= xa_load(&pin
->dpll_refs
, dpll
->id
);
823 ASSERT_NOT_NULL(ref
);
824 ops
= dpll_pin_ops(ref
);
827 ret
= ops
->prio_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
828 dpll_priv(dpll
), prio
, extack
);
831 __dpll_pin_change_ntf(pin
);
837 dpll_pin_direction_set(struct dpll_pin
*pin
, struct dpll_device
*dpll
,
838 enum dpll_pin_direction direction
,
839 struct netlink_ext_ack
*extack
)
841 const struct dpll_pin_ops
*ops
;
842 struct dpll_pin_ref
*ref
;
845 if (!(DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE
&
846 pin
->prop
.capabilities
)) {
847 NL_SET_ERR_MSG(extack
, "direction changing is not allowed");
850 ref
= xa_load(&pin
->dpll_refs
, dpll
->id
);
851 ASSERT_NOT_NULL(ref
);
852 ops
= dpll_pin_ops(ref
);
853 if (!ops
->direction_set
)
855 ret
= ops
->direction_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
856 dpll
, dpll_priv(dpll
), direction
, extack
);
859 __dpll_pin_change_ntf(pin
);
865 dpll_pin_phase_adj_set(struct dpll_pin
*pin
, struct nlattr
*phase_adj_attr
,
866 struct netlink_ext_ack
*extack
)
868 struct dpll_pin_ref
*ref
, *failed
;
869 const struct dpll_pin_ops
*ops
;
870 s32 phase_adj
, old_phase_adj
;
871 struct dpll_device
*dpll
;
875 phase_adj
= nla_get_s32(phase_adj_attr
);
876 if (phase_adj
> pin
->prop
.phase_range
.max
||
877 phase_adj
< pin
->prop
.phase_range
.min
) {
878 NL_SET_ERR_MSG_ATTR(extack
, phase_adj_attr
,
879 "phase adjust value not supported");
883 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
884 ops
= dpll_pin_ops(ref
);
885 if (!ops
->phase_adjust_set
|| !ops
->phase_adjust_get
) {
886 NL_SET_ERR_MSG(extack
, "phase adjust not supported");
890 ref
= dpll_xa_ref_dpll_first(&pin
->dpll_refs
);
891 ops
= dpll_pin_ops(ref
);
893 ret
= ops
->phase_adjust_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
894 dpll
, dpll_priv(dpll
), &old_phase_adj
,
897 NL_SET_ERR_MSG(extack
, "unable to get old phase adjust value");
900 if (phase_adj
== old_phase_adj
)
903 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
904 ops
= dpll_pin_ops(ref
);
906 ret
= ops
->phase_adjust_set(pin
,
907 dpll_pin_on_dpll_priv(dpll
, pin
),
908 dpll
, dpll_priv(dpll
), phase_adj
,
912 NL_SET_ERR_MSG_FMT(extack
,
913 "phase adjust set failed for dpll_id:%u",
918 __dpll_pin_change_ntf(pin
);
923 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
926 ops
= dpll_pin_ops(ref
);
928 if (ops
->phase_adjust_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
929 dpll
, dpll_priv(dpll
), old_phase_adj
,
931 NL_SET_ERR_MSG(extack
, "set phase adjust rollback failed");
937 dpll_pin_parent_device_set(struct dpll_pin
*pin
, struct nlattr
*parent_nest
,
938 struct netlink_ext_ack
*extack
)
940 struct nlattr
*tb
[DPLL_A_PIN_MAX
+ 1];
941 enum dpll_pin_direction direction
;
942 enum dpll_pin_state state
;
943 struct dpll_pin_ref
*ref
;
944 struct dpll_device
*dpll
;
948 nla_parse_nested(tb
, DPLL_A_PIN_MAX
, parent_nest
,
949 dpll_pin_parent_device_nl_policy
, extack
);
950 if (!tb
[DPLL_A_PIN_PARENT_ID
]) {
951 NL_SET_ERR_MSG(extack
, "device parent id expected");
954 pdpll_idx
= nla_get_u32(tb
[DPLL_A_PIN_PARENT_ID
]);
955 dpll
= xa_load(&dpll_device_xa
, pdpll_idx
);
957 NL_SET_ERR_MSG(extack
, "parent device not found");
960 ref
= xa_load(&pin
->dpll_refs
, dpll
->id
);
962 NL_SET_ERR_MSG(extack
, "pin not connected to given parent device");
965 if (tb
[DPLL_A_PIN_STATE
]) {
966 state
= nla_get_u32(tb
[DPLL_A_PIN_STATE
]);
967 ret
= dpll_pin_state_set(dpll
, pin
, state
, extack
);
971 if (tb
[DPLL_A_PIN_PRIO
]) {
972 prio
= nla_get_u32(tb
[DPLL_A_PIN_PRIO
]);
973 ret
= dpll_pin_prio_set(dpll
, pin
, prio
, extack
);
977 if (tb
[DPLL_A_PIN_DIRECTION
]) {
978 direction
= nla_get_u32(tb
[DPLL_A_PIN_DIRECTION
]);
979 ret
= dpll_pin_direction_set(pin
, dpll
, direction
, extack
);
987 dpll_pin_parent_pin_set(struct dpll_pin
*pin
, struct nlattr
*parent_nest
,
988 struct netlink_ext_ack
*extack
)
990 struct nlattr
*tb
[DPLL_A_PIN_MAX
+ 1];
994 nla_parse_nested(tb
, DPLL_A_PIN_MAX
, parent_nest
,
995 dpll_pin_parent_pin_nl_policy
, extack
);
996 if (!tb
[DPLL_A_PIN_PARENT_ID
]) {
997 NL_SET_ERR_MSG(extack
, "device parent id expected");
1000 ppin_idx
= nla_get_u32(tb
[DPLL_A_PIN_PARENT_ID
]);
1002 if (tb
[DPLL_A_PIN_STATE
]) {
1003 enum dpll_pin_state state
= nla_get_u32(tb
[DPLL_A_PIN_STATE
]);
1005 ret
= dpll_pin_on_pin_state_set(pin
, ppin_idx
, state
, extack
);
1014 dpll_pin_set_from_nlattr(struct dpll_pin
*pin
, struct genl_info
*info
)
1019 nla_for_each_attr(a
, genlmsg_data(info
->genlhdr
),
1020 genlmsg_len(info
->genlhdr
), rem
) {
1021 switch (nla_type(a
)) {
1022 case DPLL_A_PIN_FREQUENCY
:
1023 ret
= dpll_pin_freq_set(pin
, a
, info
->extack
);
1027 case DPLL_A_PIN_PHASE_ADJUST
:
1028 ret
= dpll_pin_phase_adj_set(pin
, a
, info
->extack
);
1032 case DPLL_A_PIN_PARENT_DEVICE
:
1033 ret
= dpll_pin_parent_device_set(pin
, a
, info
->extack
);
1037 case DPLL_A_PIN_PARENT_PIN
:
1038 ret
= dpll_pin_parent_pin_set(pin
, a
, info
->extack
);
1048 static struct dpll_pin
*
1049 dpll_pin_find(u64 clock_id
, struct nlattr
*mod_name_attr
,
1050 enum dpll_pin_type type
, struct nlattr
*board_label
,
1051 struct nlattr
*panel_label
, struct nlattr
*package_label
,
1052 struct netlink_ext_ack
*extack
)
1054 bool board_match
, panel_match
, package_match
;
1055 struct dpll_pin
*pin_match
= NULL
, *pin
;
1056 const struct dpll_pin_properties
*prop
;
1057 bool cid_match
, mod_match
, type_match
;
1060 xa_for_each_marked(&dpll_pin_xa
, i
, pin
, DPLL_REGISTERED
) {
1062 cid_match
= clock_id
? pin
->clock_id
== clock_id
: true;
1063 mod_match
= mod_name_attr
&& module_name(pin
->module
) ?
1064 !nla_strcmp(mod_name_attr
,
1065 module_name(pin
->module
)) : true;
1066 type_match
= type
? prop
->type
== type
: true;
1067 board_match
= board_label
? (prop
->board_label
?
1068 !nla_strcmp(board_label
, prop
->board_label
) : false) :
1070 panel_match
= panel_label
? (prop
->panel_label
?
1071 !nla_strcmp(panel_label
, prop
->panel_label
) : false) :
1073 package_match
= package_label
? (prop
->package_label
?
1074 !nla_strcmp(package_label
, prop
->package_label
) :
1076 if (cid_match
&& mod_match
&& type_match
&& board_match
&&
1077 panel_match
&& package_match
) {
1079 NL_SET_ERR_MSG(extack
, "multiple matches");
1080 return ERR_PTR(-EINVAL
);
1086 NL_SET_ERR_MSG(extack
, "not found");
1087 return ERR_PTR(-ENODEV
);
1092 static struct dpll_pin
*dpll_pin_find_from_nlattr(struct genl_info
*info
)
1094 struct nlattr
*attr
, *mod_name_attr
= NULL
, *board_label_attr
= NULL
,
1095 *panel_label_attr
= NULL
, *package_label_attr
= NULL
;
1096 enum dpll_pin_type type
= 0;
1100 nla_for_each_attr(attr
, genlmsg_data(info
->genlhdr
),
1101 genlmsg_len(info
->genlhdr
), rem
) {
1102 switch (nla_type(attr
)) {
1103 case DPLL_A_PIN_CLOCK_ID
:
1105 goto duplicated_attr
;
1106 clock_id
= nla_get_u64(attr
);
1108 case DPLL_A_PIN_MODULE_NAME
:
1110 goto duplicated_attr
;
1111 mod_name_attr
= attr
;
1113 case DPLL_A_PIN_TYPE
:
1115 goto duplicated_attr
;
1116 type
= nla_get_u32(attr
);
1118 case DPLL_A_PIN_BOARD_LABEL
:
1119 if (board_label_attr
)
1120 goto duplicated_attr
;
1121 board_label_attr
= attr
;
1123 case DPLL_A_PIN_PANEL_LABEL
:
1124 if (panel_label_attr
)
1125 goto duplicated_attr
;
1126 panel_label_attr
= attr
;
1128 case DPLL_A_PIN_PACKAGE_LABEL
:
1129 if (package_label_attr
)
1130 goto duplicated_attr
;
1131 package_label_attr
= attr
;
1137 if (!(clock_id
|| mod_name_attr
|| board_label_attr
||
1138 panel_label_attr
|| package_label_attr
)) {
1139 NL_SET_ERR_MSG(info
->extack
, "missing attributes");
1140 return ERR_PTR(-EINVAL
);
1142 return dpll_pin_find(clock_id
, mod_name_attr
, type
, board_label_attr
,
1143 panel_label_attr
, package_label_attr
,
1146 NL_SET_ERR_MSG(info
->extack
, "duplicated attribute");
1147 return ERR_PTR(-EINVAL
);
1150 int dpll_nl_pin_id_get_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1152 struct dpll_pin
*pin
;
1153 struct sk_buff
*msg
;
1157 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
1160 hdr
= genlmsg_put_reply(msg
, info
, &dpll_nl_family
, 0,
1161 DPLL_CMD_PIN_ID_GET
);
1166 pin
= dpll_pin_find_from_nlattr(info
);
1168 if (!dpll_pin_available(pin
)) {
1172 ret
= dpll_msg_add_pin_handle(msg
, pin
);
1178 genlmsg_end(msg
, hdr
);
1180 return genlmsg_reply(msg
, info
);
1183 int dpll_nl_pin_get_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1185 struct dpll_pin
*pin
= info
->user_ptr
[0];
1186 struct sk_buff
*msg
;
1192 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
1195 hdr
= genlmsg_put_reply(msg
, info
, &dpll_nl_family
, 0,
1201 ret
= dpll_cmd_pin_get_one(msg
, pin
, info
->extack
);
1206 genlmsg_end(msg
, hdr
);
1208 return genlmsg_reply(msg
, info
);
1211 int dpll_nl_pin_get_dumpit(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1213 struct dpll_dump_ctx
*ctx
= dpll_dump_context(cb
);
1214 struct dpll_pin
*pin
;
1219 mutex_lock(&dpll_lock
);
1220 xa_for_each_marked_start(&dpll_pin_xa
, i
, pin
, DPLL_REGISTERED
,
1222 if (!dpll_pin_available(pin
))
1224 hdr
= genlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
,
1226 &dpll_nl_family
, NLM_F_MULTI
,
1232 ret
= dpll_cmd_pin_get_one(skb
, pin
, cb
->extack
);
1234 genlmsg_cancel(skb
, hdr
);
1237 genlmsg_end(skb
, hdr
);
1239 mutex_unlock(&dpll_lock
);
1241 if (ret
== -EMSGSIZE
) {
1248 int dpll_nl_pin_set_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1250 struct dpll_pin
*pin
= info
->user_ptr
[0];
1252 return dpll_pin_set_from_nlattr(pin
, info
);
1255 static struct dpll_device
*
1256 dpll_device_find(u64 clock_id
, struct nlattr
*mod_name_attr
,
1257 enum dpll_type type
, struct netlink_ext_ack
*extack
)
1259 struct dpll_device
*dpll_match
= NULL
, *dpll
;
1260 bool cid_match
, mod_match
, type_match
;
1263 xa_for_each_marked(&dpll_device_xa
, i
, dpll
, DPLL_REGISTERED
) {
1264 cid_match
= clock_id
? dpll
->clock_id
== clock_id
: true;
1265 mod_match
= mod_name_attr
? (module_name(dpll
->module
) ?
1266 !nla_strcmp(mod_name_attr
,
1267 module_name(dpll
->module
)) : false) : true;
1268 type_match
= type
? dpll
->type
== type
: true;
1269 if (cid_match
&& mod_match
&& type_match
) {
1271 NL_SET_ERR_MSG(extack
, "multiple matches");
1272 return ERR_PTR(-EINVAL
);
1278 NL_SET_ERR_MSG(extack
, "not found");
1279 return ERR_PTR(-ENODEV
);
1285 static struct dpll_device
*
1286 dpll_device_find_from_nlattr(struct genl_info
*info
)
1288 struct nlattr
*attr
, *mod_name_attr
= NULL
;
1289 enum dpll_type type
= 0;
1293 nla_for_each_attr(attr
, genlmsg_data(info
->genlhdr
),
1294 genlmsg_len(info
->genlhdr
), rem
) {
1295 switch (nla_type(attr
)) {
1296 case DPLL_A_CLOCK_ID
:
1298 goto duplicated_attr
;
1299 clock_id
= nla_get_u64(attr
);
1301 case DPLL_A_MODULE_NAME
:
1303 goto duplicated_attr
;
1304 mod_name_attr
= attr
;
1308 goto duplicated_attr
;
1309 type
= nla_get_u32(attr
);
1315 if (!clock_id
&& !mod_name_attr
&& !type
) {
1316 NL_SET_ERR_MSG(info
->extack
, "missing attributes");
1317 return ERR_PTR(-EINVAL
);
1319 return dpll_device_find(clock_id
, mod_name_attr
, type
, info
->extack
);
1321 NL_SET_ERR_MSG(info
->extack
, "duplicated attribute");
1322 return ERR_PTR(-EINVAL
);
1325 int dpll_nl_device_id_get_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1327 struct dpll_device
*dpll
;
1328 struct sk_buff
*msg
;
1332 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
1335 hdr
= genlmsg_put_reply(msg
, info
, &dpll_nl_family
, 0,
1336 DPLL_CMD_DEVICE_ID_GET
);
1342 dpll
= dpll_device_find_from_nlattr(info
);
1343 if (!IS_ERR(dpll
)) {
1344 ret
= dpll_msg_add_dev_handle(msg
, dpll
);
1350 genlmsg_end(msg
, hdr
);
1352 return genlmsg_reply(msg
, info
);
1355 int dpll_nl_device_get_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1357 struct dpll_device
*dpll
= info
->user_ptr
[0];
1358 struct sk_buff
*msg
;
1362 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
1365 hdr
= genlmsg_put_reply(msg
, info
, &dpll_nl_family
, 0,
1366 DPLL_CMD_DEVICE_GET
);
1372 ret
= dpll_device_get_one(dpll
, msg
, info
->extack
);
1377 genlmsg_end(msg
, hdr
);
1379 return genlmsg_reply(msg
, info
);
1382 int dpll_nl_device_set_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1384 /* placeholder for set command */
1388 int dpll_nl_device_get_dumpit(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1390 struct dpll_dump_ctx
*ctx
= dpll_dump_context(cb
);
1391 struct dpll_device
*dpll
;
1396 mutex_lock(&dpll_lock
);
1397 xa_for_each_marked_start(&dpll_device_xa
, i
, dpll
, DPLL_REGISTERED
,
1399 hdr
= genlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
,
1400 cb
->nlh
->nlmsg_seq
, &dpll_nl_family
,
1401 NLM_F_MULTI
, DPLL_CMD_DEVICE_GET
);
1406 ret
= dpll_device_get_one(dpll
, skb
, cb
->extack
);
1408 genlmsg_cancel(skb
, hdr
);
1411 genlmsg_end(skb
, hdr
);
1413 mutex_unlock(&dpll_lock
);
1415 if (ret
== -EMSGSIZE
) {
1422 int dpll_pre_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1423 struct genl_info
*info
)
1427 if (GENL_REQ_ATTR_CHECK(info
, DPLL_A_ID
))
1430 mutex_lock(&dpll_lock
);
1431 id
= nla_get_u32(info
->attrs
[DPLL_A_ID
]);
1432 info
->user_ptr
[0] = dpll_device_get_by_id(id
);
1433 if (!info
->user_ptr
[0]) {
1434 NL_SET_ERR_MSG(info
->extack
, "device not found");
1439 mutex_unlock(&dpll_lock
);
1443 void dpll_post_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1444 struct genl_info
*info
)
1446 mutex_unlock(&dpll_lock
);
1450 dpll_lock_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1451 struct genl_info
*info
)
1453 mutex_lock(&dpll_lock
);
1459 dpll_unlock_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1460 struct genl_info
*info
)
1462 mutex_unlock(&dpll_lock
);
1465 int dpll_pin_pre_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1466 struct genl_info
*info
)
1470 mutex_lock(&dpll_lock
);
1471 if (GENL_REQ_ATTR_CHECK(info
, DPLL_A_PIN_ID
)) {
1475 info
->user_ptr
[0] = xa_load(&dpll_pin_xa
,
1476 nla_get_u32(info
->attrs
[DPLL_A_PIN_ID
]));
1477 if (!info
->user_ptr
[0] ||
1478 !dpll_pin_available(info
->user_ptr
[0])) {
1479 NL_SET_ERR_MSG(info
->extack
, "pin not found");
1487 mutex_unlock(&dpll_lock
);
1491 void dpll_pin_post_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1492 struct genl_info
*info
)
1494 mutex_unlock(&dpll_lock
);