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_clock_quality_level(struct sk_buff
*msg
, struct dpll_device
*dpll
,
174 struct netlink_ext_ack
*extack
)
176 const struct dpll_device_ops
*ops
= dpll_device_ops(dpll
);
177 DECLARE_BITMAP(qls
, DPLL_CLOCK_QUALITY_LEVEL_MAX
) = { 0 };
178 enum dpll_clock_quality_level ql
;
181 if (!ops
->clock_quality_level_get
)
183 ret
= ops
->clock_quality_level_get(dpll
, dpll_priv(dpll
), qls
, extack
);
186 for_each_set_bit(ql
, qls
, DPLL_CLOCK_QUALITY_LEVEL_MAX
)
187 if (nla_put_u32(msg
, DPLL_A_CLOCK_QUALITY_LEVEL
, ql
))
194 dpll_msg_add_pin_prio(struct sk_buff
*msg
, struct dpll_pin
*pin
,
195 struct dpll_pin_ref
*ref
,
196 struct netlink_ext_ack
*extack
)
198 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
199 struct dpll_device
*dpll
= ref
->dpll
;
205 ret
= ops
->prio_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
206 dpll_priv(dpll
), &prio
, extack
);
209 if (nla_put_u32(msg
, DPLL_A_PIN_PRIO
, prio
))
216 dpll_msg_add_pin_on_dpll_state(struct sk_buff
*msg
, struct dpll_pin
*pin
,
217 struct dpll_pin_ref
*ref
,
218 struct netlink_ext_ack
*extack
)
220 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
221 struct dpll_device
*dpll
= ref
->dpll
;
222 enum dpll_pin_state state
;
225 if (!ops
->state_on_dpll_get
)
227 ret
= ops
->state_on_dpll_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
228 dpll
, dpll_priv(dpll
), &state
, extack
);
231 if (nla_put_u32(msg
, DPLL_A_PIN_STATE
, state
))
238 dpll_msg_add_pin_direction(struct sk_buff
*msg
, struct dpll_pin
*pin
,
239 struct dpll_pin_ref
*ref
,
240 struct netlink_ext_ack
*extack
)
242 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
243 struct dpll_device
*dpll
= ref
->dpll
;
244 enum dpll_pin_direction direction
;
247 ret
= ops
->direction_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
248 dpll_priv(dpll
), &direction
, extack
);
251 if (nla_put_u32(msg
, DPLL_A_PIN_DIRECTION
, direction
))
258 dpll_msg_add_pin_phase_adjust(struct sk_buff
*msg
, struct dpll_pin
*pin
,
259 struct dpll_pin_ref
*ref
,
260 struct netlink_ext_ack
*extack
)
262 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
263 struct dpll_device
*dpll
= ref
->dpll
;
267 if (!ops
->phase_adjust_get
)
269 ret
= ops
->phase_adjust_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
270 dpll
, dpll_priv(dpll
),
271 &phase_adjust
, extack
);
274 if (nla_put_s32(msg
, DPLL_A_PIN_PHASE_ADJUST
, phase_adjust
))
281 dpll_msg_add_phase_offset(struct sk_buff
*msg
, struct dpll_pin
*pin
,
282 struct dpll_pin_ref
*ref
,
283 struct netlink_ext_ack
*extack
)
285 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
286 struct dpll_device
*dpll
= ref
->dpll
;
290 if (!ops
->phase_offset_get
)
292 ret
= ops
->phase_offset_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
293 dpll
, dpll_priv(dpll
), &phase_offset
,
297 if (nla_put_64bit(msg
, DPLL_A_PIN_PHASE_OFFSET
, sizeof(phase_offset
),
298 &phase_offset
, DPLL_A_PIN_PAD
))
304 static int dpll_msg_add_ffo(struct sk_buff
*msg
, struct dpll_pin
*pin
,
305 struct dpll_pin_ref
*ref
,
306 struct netlink_ext_ack
*extack
)
308 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
309 struct dpll_device
*dpll
= ref
->dpll
;
315 ret
= ops
->ffo_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
316 dpll
, dpll_priv(dpll
), &ffo
, extack
);
322 return nla_put_sint(msg
, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET
, ffo
);
326 dpll_msg_add_pin_freq(struct sk_buff
*msg
, struct dpll_pin
*pin
,
327 struct dpll_pin_ref
*ref
, struct netlink_ext_ack
*extack
)
329 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
330 struct dpll_device
*dpll
= ref
->dpll
;
335 if (!ops
->frequency_get
)
337 ret
= ops
->frequency_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
338 dpll_priv(dpll
), &freq
, extack
);
341 if (nla_put_64bit(msg
, DPLL_A_PIN_FREQUENCY
, sizeof(freq
), &freq
,
344 for (fs
= 0; fs
< pin
->prop
.freq_supported_num
; fs
++) {
345 nest
= nla_nest_start(msg
, DPLL_A_PIN_FREQUENCY_SUPPORTED
);
348 freq
= pin
->prop
.freq_supported
[fs
].min
;
349 if (nla_put_64bit(msg
, DPLL_A_PIN_FREQUENCY_MIN
, sizeof(freq
),
350 &freq
, DPLL_A_PIN_PAD
)) {
351 nla_nest_cancel(msg
, nest
);
354 freq
= pin
->prop
.freq_supported
[fs
].max
;
355 if (nla_put_64bit(msg
, DPLL_A_PIN_FREQUENCY_MAX
, sizeof(freq
),
356 &freq
, DPLL_A_PIN_PAD
)) {
357 nla_nest_cancel(msg
, nest
);
360 nla_nest_end(msg
, nest
);
367 dpll_msg_add_pin_esync(struct sk_buff
*msg
, struct dpll_pin
*pin
,
368 struct dpll_pin_ref
*ref
, struct netlink_ext_ack
*extack
)
370 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
371 struct dpll_device
*dpll
= ref
->dpll
;
372 struct dpll_pin_esync esync
;
378 ret
= ops
->esync_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
379 dpll_priv(dpll
), &esync
, extack
);
380 if (ret
== -EOPNOTSUPP
)
384 if (nla_put_64bit(msg
, DPLL_A_PIN_ESYNC_FREQUENCY
, sizeof(esync
.freq
),
385 &esync
.freq
, DPLL_A_PIN_PAD
))
387 if (nla_put_u32(msg
, DPLL_A_PIN_ESYNC_PULSE
, esync
.pulse
))
389 for (i
= 0; i
< esync
.range_num
; i
++) {
390 nest
= nla_nest_start(msg
,
391 DPLL_A_PIN_ESYNC_FREQUENCY_SUPPORTED
);
394 if (nla_put_64bit(msg
, DPLL_A_PIN_FREQUENCY_MIN
,
395 sizeof(esync
.range
[i
].min
),
396 &esync
.range
[i
].min
, DPLL_A_PIN_PAD
))
398 if (nla_put_64bit(msg
, DPLL_A_PIN_FREQUENCY_MAX
,
399 sizeof(esync
.range
[i
].max
),
400 &esync
.range
[i
].max
, DPLL_A_PIN_PAD
))
402 nla_nest_end(msg
, nest
);
407 nla_nest_cancel(msg
, nest
);
411 static bool dpll_pin_is_freq_supported(struct dpll_pin
*pin
, u32 freq
)
415 for (fs
= 0; fs
< pin
->prop
.freq_supported_num
; fs
++)
416 if (freq
>= pin
->prop
.freq_supported
[fs
].min
&&
417 freq
<= pin
->prop
.freq_supported
[fs
].max
)
423 dpll_msg_add_pin_parents(struct sk_buff
*msg
, struct dpll_pin
*pin
,
424 struct dpll_pin_ref
*dpll_ref
,
425 struct netlink_ext_ack
*extack
)
427 enum dpll_pin_state state
;
428 struct dpll_pin_ref
*ref
;
429 struct dpll_pin
*ppin
;
434 xa_for_each(&pin
->parent_refs
, index
, ref
) {
435 const struct dpll_pin_ops
*ops
= dpll_pin_ops(ref
);
439 parent_priv
= dpll_pin_on_dpll_priv(dpll_ref
->dpll
, ppin
);
440 ret
= ops
->state_on_pin_get(pin
,
441 dpll_pin_on_pin_priv(ppin
, pin
),
442 ppin
, parent_priv
, &state
, extack
);
445 nest
= nla_nest_start(msg
, DPLL_A_PIN_PARENT_PIN
);
448 ret
= dpll_msg_add_dev_parent_handle(msg
, ppin
->id
);
451 if (nla_put_u32(msg
, DPLL_A_PIN_STATE
, state
)) {
455 nla_nest_end(msg
, nest
);
461 nla_nest_cancel(msg
, nest
);
466 dpll_msg_add_pin_dplls(struct sk_buff
*msg
, struct dpll_pin
*pin
,
467 struct netlink_ext_ack
*extack
)
469 struct dpll_pin_ref
*ref
;
474 xa_for_each(&pin
->dpll_refs
, index
, ref
) {
475 attr
= nla_nest_start(msg
, DPLL_A_PIN_PARENT_DEVICE
);
478 ret
= dpll_msg_add_dev_parent_handle(msg
, ref
->dpll
->id
);
481 ret
= dpll_msg_add_pin_on_dpll_state(msg
, pin
, ref
, extack
);
484 ret
= dpll_msg_add_pin_prio(msg
, pin
, ref
, extack
);
487 ret
= dpll_msg_add_pin_direction(msg
, pin
, ref
, extack
);
490 ret
= dpll_msg_add_phase_offset(msg
, pin
, ref
, extack
);
493 nla_nest_end(msg
, attr
);
499 nla_nest_end(msg
, attr
);
504 dpll_cmd_pin_get_one(struct sk_buff
*msg
, struct dpll_pin
*pin
,
505 struct netlink_ext_ack
*extack
)
507 const struct dpll_pin_properties
*prop
= &pin
->prop
;
508 struct dpll_pin_ref
*ref
;
511 ref
= dpll_xa_ref_dpll_first(&pin
->dpll_refs
);
512 ASSERT_NOT_NULL(ref
);
514 ret
= dpll_msg_add_pin_handle(msg
, pin
);
517 if (nla_put_string(msg
, DPLL_A_PIN_MODULE_NAME
,
518 module_name(pin
->module
)))
520 if (nla_put_64bit(msg
, DPLL_A_PIN_CLOCK_ID
, sizeof(pin
->clock_id
),
521 &pin
->clock_id
, DPLL_A_PIN_PAD
))
523 if (prop
->board_label
&&
524 nla_put_string(msg
, DPLL_A_PIN_BOARD_LABEL
, prop
->board_label
))
526 if (prop
->panel_label
&&
527 nla_put_string(msg
, DPLL_A_PIN_PANEL_LABEL
, prop
->panel_label
))
529 if (prop
->package_label
&&
530 nla_put_string(msg
, DPLL_A_PIN_PACKAGE_LABEL
,
531 prop
->package_label
))
533 if (nla_put_u32(msg
, DPLL_A_PIN_TYPE
, prop
->type
))
535 if (nla_put_u32(msg
, DPLL_A_PIN_CAPABILITIES
, prop
->capabilities
))
537 ret
= dpll_msg_add_pin_freq(msg
, pin
, ref
, extack
);
540 if (nla_put_s32(msg
, DPLL_A_PIN_PHASE_ADJUST_MIN
,
541 prop
->phase_range
.min
))
543 if (nla_put_s32(msg
, DPLL_A_PIN_PHASE_ADJUST_MAX
,
544 prop
->phase_range
.max
))
546 ret
= dpll_msg_add_pin_phase_adjust(msg
, pin
, ref
, extack
);
549 ret
= dpll_msg_add_ffo(msg
, pin
, ref
, extack
);
552 ret
= dpll_msg_add_pin_esync(msg
, pin
, ref
, extack
);
555 if (xa_empty(&pin
->parent_refs
))
556 ret
= dpll_msg_add_pin_dplls(msg
, pin
, extack
);
558 ret
= dpll_msg_add_pin_parents(msg
, pin
, ref
, extack
);
564 dpll_device_get_one(struct dpll_device
*dpll
, struct sk_buff
*msg
,
565 struct netlink_ext_ack
*extack
)
569 ret
= dpll_msg_add_dev_handle(msg
, dpll
);
572 if (nla_put_string(msg
, DPLL_A_MODULE_NAME
, module_name(dpll
->module
)))
574 if (nla_put_64bit(msg
, DPLL_A_CLOCK_ID
, sizeof(dpll
->clock_id
),
575 &dpll
->clock_id
, DPLL_A_PAD
))
577 ret
= dpll_msg_add_temp(msg
, dpll
, extack
);
580 ret
= dpll_msg_add_lock_status(msg
, dpll
, extack
);
583 ret
= dpll_msg_add_clock_quality_level(msg
, dpll
, extack
);
586 ret
= dpll_msg_add_mode(msg
, dpll
, extack
);
589 ret
= dpll_msg_add_mode_supported(msg
, dpll
, extack
);
592 if (nla_put_u32(msg
, DPLL_A_TYPE
, dpll
->type
))
599 dpll_device_event_send(enum dpll_cmd event
, struct dpll_device
*dpll
)
605 if (WARN_ON(!xa_get_mark(&dpll_device_xa
, dpll
->id
, DPLL_REGISTERED
)))
607 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
610 hdr
= genlmsg_put(msg
, 0, 0, &dpll_nl_family
, 0, event
);
613 ret
= dpll_device_get_one(dpll
, msg
, NULL
);
616 genlmsg_end(msg
, hdr
);
617 genlmsg_multicast(&dpll_nl_family
, msg
, 0, 0, GFP_KERNEL
);
622 genlmsg_cancel(msg
, hdr
);
629 int dpll_device_create_ntf(struct dpll_device
*dpll
)
631 return dpll_device_event_send(DPLL_CMD_DEVICE_CREATE_NTF
, dpll
);
634 int dpll_device_delete_ntf(struct dpll_device
*dpll
)
636 return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF
, dpll
);
640 __dpll_device_change_ntf(struct dpll_device
*dpll
)
642 return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF
, dpll
);
645 static bool dpll_pin_available(struct dpll_pin
*pin
)
647 struct dpll_pin_ref
*par_ref
;
650 if (!xa_get_mark(&dpll_pin_xa
, pin
->id
, DPLL_REGISTERED
))
652 xa_for_each(&pin
->parent_refs
, i
, par_ref
)
653 if (xa_get_mark(&dpll_pin_xa
, par_ref
->pin
->id
,
656 xa_for_each(&pin
->dpll_refs
, i
, par_ref
)
657 if (xa_get_mark(&dpll_device_xa
, par_ref
->dpll
->id
,
664 * dpll_device_change_ntf - notify that the dpll device has been changed
665 * @dpll: registered dpll pointer
667 * Context: acquires and holds a dpll_lock.
668 * Return: 0 if succeeds, error code otherwise.
670 int dpll_device_change_ntf(struct dpll_device
*dpll
)
674 mutex_lock(&dpll_lock
);
675 ret
= __dpll_device_change_ntf(dpll
);
676 mutex_unlock(&dpll_lock
);
680 EXPORT_SYMBOL_GPL(dpll_device_change_ntf
);
683 dpll_pin_event_send(enum dpll_cmd event
, struct dpll_pin
*pin
)
689 if (!dpll_pin_available(pin
))
692 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
696 hdr
= genlmsg_put(msg
, 0, 0, &dpll_nl_family
, 0, event
);
699 ret
= dpll_cmd_pin_get_one(msg
, pin
, NULL
);
702 genlmsg_end(msg
, hdr
);
703 genlmsg_multicast(&dpll_nl_family
, msg
, 0, 0, GFP_KERNEL
);
708 genlmsg_cancel(msg
, hdr
);
715 int dpll_pin_create_ntf(struct dpll_pin
*pin
)
717 return dpll_pin_event_send(DPLL_CMD_PIN_CREATE_NTF
, pin
);
720 int dpll_pin_delete_ntf(struct dpll_pin
*pin
)
722 return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF
, pin
);
725 static int __dpll_pin_change_ntf(struct dpll_pin
*pin
)
727 return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF
, pin
);
731 * dpll_pin_change_ntf - notify that the pin has been changed
732 * @pin: registered pin pointer
734 * Context: acquires and holds a dpll_lock.
735 * Return: 0 if succeeds, error code otherwise.
737 int dpll_pin_change_ntf(struct dpll_pin
*pin
)
741 mutex_lock(&dpll_lock
);
742 ret
= __dpll_pin_change_ntf(pin
);
743 mutex_unlock(&dpll_lock
);
747 EXPORT_SYMBOL_GPL(dpll_pin_change_ntf
);
750 dpll_pin_freq_set(struct dpll_pin
*pin
, struct nlattr
*a
,
751 struct netlink_ext_ack
*extack
)
753 u64 freq
= nla_get_u64(a
), old_freq
;
754 struct dpll_pin_ref
*ref
, *failed
;
755 const struct dpll_pin_ops
*ops
;
756 struct dpll_device
*dpll
;
760 if (!dpll_pin_is_freq_supported(pin
, freq
)) {
761 NL_SET_ERR_MSG_ATTR(extack
, a
, "frequency is not supported by the device");
765 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
766 ops
= dpll_pin_ops(ref
);
767 if (!ops
->frequency_set
|| !ops
->frequency_get
) {
768 NL_SET_ERR_MSG(extack
, "frequency set not supported by the device");
772 ref
= dpll_xa_ref_dpll_first(&pin
->dpll_refs
);
773 ops
= dpll_pin_ops(ref
);
775 ret
= ops
->frequency_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
776 dpll_priv(dpll
), &old_freq
, extack
);
778 NL_SET_ERR_MSG(extack
, "unable to get old frequency value");
781 if (freq
== old_freq
)
784 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
785 ops
= dpll_pin_ops(ref
);
787 ret
= ops
->frequency_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
788 dpll
, dpll_priv(dpll
), freq
, extack
);
791 NL_SET_ERR_MSG_FMT(extack
, "frequency set failed for dpll_id:%u",
796 __dpll_pin_change_ntf(pin
);
801 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
804 ops
= dpll_pin_ops(ref
);
806 if (ops
->frequency_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
807 dpll
, dpll_priv(dpll
), old_freq
, extack
))
808 NL_SET_ERR_MSG(extack
, "set frequency rollback failed");
814 dpll_pin_esync_set(struct dpll_pin
*pin
, struct nlattr
*a
,
815 struct netlink_ext_ack
*extack
)
817 struct dpll_pin_ref
*ref
, *failed
;
818 const struct dpll_pin_ops
*ops
;
819 struct dpll_pin_esync esync
;
820 u64 freq
= nla_get_u64(a
);
821 struct dpll_device
*dpll
;
822 bool supported
= false;
826 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
827 ops
= dpll_pin_ops(ref
);
828 if (!ops
->esync_set
|| !ops
->esync_get
) {
829 NL_SET_ERR_MSG(extack
,
830 "embedded sync feature is not supported by this device");
834 ref
= dpll_xa_ref_dpll_first(&pin
->dpll_refs
);
835 ops
= dpll_pin_ops(ref
);
837 ret
= ops
->esync_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
838 dpll_priv(dpll
), &esync
, extack
);
840 NL_SET_ERR_MSG(extack
, "unable to get current embedded sync frequency value");
843 if (freq
== esync
.freq
)
845 for (i
= 0; i
< esync
.range_num
; i
++)
846 if (freq
<= esync
.range
[i
].max
&& freq
>= esync
.range
[i
].min
)
849 NL_SET_ERR_MSG_ATTR(extack
, a
,
850 "requested embedded sync frequency value is not supported by this device");
854 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
857 ops
= dpll_pin_ops(ref
);
859 pin_dpll_priv
= dpll_pin_on_dpll_priv(dpll
, pin
);
860 ret
= ops
->esync_set(pin
, pin_dpll_priv
, dpll
, dpll_priv(dpll
),
864 NL_SET_ERR_MSG_FMT(extack
,
865 "embedded sync frequency set failed for dpll_id: %u",
870 __dpll_pin_change_ntf(pin
);
875 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
880 ops
= dpll_pin_ops(ref
);
882 pin_dpll_priv
= dpll_pin_on_dpll_priv(dpll
, pin
);
883 if (ops
->esync_set(pin
, pin_dpll_priv
, dpll
, dpll_priv(dpll
),
885 NL_SET_ERR_MSG(extack
, "set embedded sync frequency rollback failed");
891 dpll_pin_on_pin_state_set(struct dpll_pin
*pin
, u32 parent_idx
,
892 enum dpll_pin_state state
,
893 struct netlink_ext_ack
*extack
)
895 struct dpll_pin_ref
*parent_ref
;
896 const struct dpll_pin_ops
*ops
;
897 struct dpll_pin_ref
*dpll_ref
;
898 void *pin_priv
, *parent_priv
;
899 struct dpll_pin
*parent
;
903 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE
&
904 pin
->prop
.capabilities
)) {
905 NL_SET_ERR_MSG(extack
, "state changing is not allowed");
908 parent
= xa_load(&dpll_pin_xa
, parent_idx
);
911 parent_ref
= xa_load(&pin
->parent_refs
, parent
->pin_idx
);
914 xa_for_each(&parent
->dpll_refs
, i
, dpll_ref
) {
915 ops
= dpll_pin_ops(parent_ref
);
916 if (!ops
->state_on_pin_set
)
918 pin_priv
= dpll_pin_on_pin_priv(parent
, pin
);
919 parent_priv
= dpll_pin_on_dpll_priv(dpll_ref
->dpll
, parent
);
920 ret
= ops
->state_on_pin_set(pin
, pin_priv
, parent
, parent_priv
,
925 __dpll_pin_change_ntf(pin
);
931 dpll_pin_state_set(struct dpll_device
*dpll
, struct dpll_pin
*pin
,
932 enum dpll_pin_state state
,
933 struct netlink_ext_ack
*extack
)
935 const struct dpll_pin_ops
*ops
;
936 struct dpll_pin_ref
*ref
;
939 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE
&
940 pin
->prop
.capabilities
)) {
941 NL_SET_ERR_MSG(extack
, "state changing is not allowed");
944 ref
= xa_load(&pin
->dpll_refs
, dpll
->id
);
945 ASSERT_NOT_NULL(ref
);
946 ops
= dpll_pin_ops(ref
);
947 if (!ops
->state_on_dpll_set
)
949 ret
= ops
->state_on_dpll_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
950 dpll
, dpll_priv(dpll
), state
, extack
);
953 __dpll_pin_change_ntf(pin
);
959 dpll_pin_prio_set(struct dpll_device
*dpll
, struct dpll_pin
*pin
,
960 u32 prio
, struct netlink_ext_ack
*extack
)
962 const struct dpll_pin_ops
*ops
;
963 struct dpll_pin_ref
*ref
;
966 if (!(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE
&
967 pin
->prop
.capabilities
)) {
968 NL_SET_ERR_MSG(extack
, "prio changing is not allowed");
971 ref
= xa_load(&pin
->dpll_refs
, dpll
->id
);
972 ASSERT_NOT_NULL(ref
);
973 ops
= dpll_pin_ops(ref
);
976 ret
= ops
->prio_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
), dpll
,
977 dpll_priv(dpll
), prio
, extack
);
980 __dpll_pin_change_ntf(pin
);
986 dpll_pin_direction_set(struct dpll_pin
*pin
, struct dpll_device
*dpll
,
987 enum dpll_pin_direction direction
,
988 struct netlink_ext_ack
*extack
)
990 const struct dpll_pin_ops
*ops
;
991 struct dpll_pin_ref
*ref
;
994 if (!(DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE
&
995 pin
->prop
.capabilities
)) {
996 NL_SET_ERR_MSG(extack
, "direction changing is not allowed");
999 ref
= xa_load(&pin
->dpll_refs
, dpll
->id
);
1000 ASSERT_NOT_NULL(ref
);
1001 ops
= dpll_pin_ops(ref
);
1002 if (!ops
->direction_set
)
1004 ret
= ops
->direction_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
1005 dpll
, dpll_priv(dpll
), direction
, extack
);
1008 __dpll_pin_change_ntf(pin
);
1014 dpll_pin_phase_adj_set(struct dpll_pin
*pin
, struct nlattr
*phase_adj_attr
,
1015 struct netlink_ext_ack
*extack
)
1017 struct dpll_pin_ref
*ref
, *failed
;
1018 const struct dpll_pin_ops
*ops
;
1019 s32 phase_adj
, old_phase_adj
;
1020 struct dpll_device
*dpll
;
1024 phase_adj
= nla_get_s32(phase_adj_attr
);
1025 if (phase_adj
> pin
->prop
.phase_range
.max
||
1026 phase_adj
< pin
->prop
.phase_range
.min
) {
1027 NL_SET_ERR_MSG_ATTR(extack
, phase_adj_attr
,
1028 "phase adjust value not supported");
1032 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
1033 ops
= dpll_pin_ops(ref
);
1034 if (!ops
->phase_adjust_set
|| !ops
->phase_adjust_get
) {
1035 NL_SET_ERR_MSG(extack
, "phase adjust not supported");
1039 ref
= dpll_xa_ref_dpll_first(&pin
->dpll_refs
);
1040 ops
= dpll_pin_ops(ref
);
1042 ret
= ops
->phase_adjust_get(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
1043 dpll
, dpll_priv(dpll
), &old_phase_adj
,
1046 NL_SET_ERR_MSG(extack
, "unable to get old phase adjust value");
1049 if (phase_adj
== old_phase_adj
)
1052 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
1053 ops
= dpll_pin_ops(ref
);
1055 ret
= ops
->phase_adjust_set(pin
,
1056 dpll_pin_on_dpll_priv(dpll
, pin
),
1057 dpll
, dpll_priv(dpll
), phase_adj
,
1061 NL_SET_ERR_MSG_FMT(extack
,
1062 "phase adjust set failed for dpll_id:%u",
1067 __dpll_pin_change_ntf(pin
);
1072 xa_for_each(&pin
->dpll_refs
, i
, ref
) {
1075 ops
= dpll_pin_ops(ref
);
1077 if (ops
->phase_adjust_set(pin
, dpll_pin_on_dpll_priv(dpll
, pin
),
1078 dpll
, dpll_priv(dpll
), old_phase_adj
,
1080 NL_SET_ERR_MSG(extack
, "set phase adjust rollback failed");
1086 dpll_pin_parent_device_set(struct dpll_pin
*pin
, struct nlattr
*parent_nest
,
1087 struct netlink_ext_ack
*extack
)
1089 struct nlattr
*tb
[DPLL_A_PIN_MAX
+ 1];
1090 enum dpll_pin_direction direction
;
1091 enum dpll_pin_state state
;
1092 struct dpll_pin_ref
*ref
;
1093 struct dpll_device
*dpll
;
1094 u32 pdpll_idx
, prio
;
1097 nla_parse_nested(tb
, DPLL_A_PIN_MAX
, parent_nest
,
1098 dpll_pin_parent_device_nl_policy
, extack
);
1099 if (!tb
[DPLL_A_PIN_PARENT_ID
]) {
1100 NL_SET_ERR_MSG(extack
, "device parent id expected");
1103 pdpll_idx
= nla_get_u32(tb
[DPLL_A_PIN_PARENT_ID
]);
1104 dpll
= xa_load(&dpll_device_xa
, pdpll_idx
);
1106 NL_SET_ERR_MSG(extack
, "parent device not found");
1109 ref
= xa_load(&pin
->dpll_refs
, dpll
->id
);
1111 NL_SET_ERR_MSG(extack
, "pin not connected to given parent device");
1114 if (tb
[DPLL_A_PIN_STATE
]) {
1115 state
= nla_get_u32(tb
[DPLL_A_PIN_STATE
]);
1116 ret
= dpll_pin_state_set(dpll
, pin
, state
, extack
);
1120 if (tb
[DPLL_A_PIN_PRIO
]) {
1121 prio
= nla_get_u32(tb
[DPLL_A_PIN_PRIO
]);
1122 ret
= dpll_pin_prio_set(dpll
, pin
, prio
, extack
);
1126 if (tb
[DPLL_A_PIN_DIRECTION
]) {
1127 direction
= nla_get_u32(tb
[DPLL_A_PIN_DIRECTION
]);
1128 ret
= dpll_pin_direction_set(pin
, dpll
, direction
, extack
);
1136 dpll_pin_parent_pin_set(struct dpll_pin
*pin
, struct nlattr
*parent_nest
,
1137 struct netlink_ext_ack
*extack
)
1139 struct nlattr
*tb
[DPLL_A_PIN_MAX
+ 1];
1143 nla_parse_nested(tb
, DPLL_A_PIN_MAX
, parent_nest
,
1144 dpll_pin_parent_pin_nl_policy
, extack
);
1145 if (!tb
[DPLL_A_PIN_PARENT_ID
]) {
1146 NL_SET_ERR_MSG(extack
, "device parent id expected");
1149 ppin_idx
= nla_get_u32(tb
[DPLL_A_PIN_PARENT_ID
]);
1151 if (tb
[DPLL_A_PIN_STATE
]) {
1152 enum dpll_pin_state state
= nla_get_u32(tb
[DPLL_A_PIN_STATE
]);
1154 ret
= dpll_pin_on_pin_state_set(pin
, ppin_idx
, state
, extack
);
1163 dpll_pin_set_from_nlattr(struct dpll_pin
*pin
, struct genl_info
*info
)
1168 nla_for_each_attr(a
, genlmsg_data(info
->genlhdr
),
1169 genlmsg_len(info
->genlhdr
), rem
) {
1170 switch (nla_type(a
)) {
1171 case DPLL_A_PIN_FREQUENCY
:
1172 ret
= dpll_pin_freq_set(pin
, a
, info
->extack
);
1176 case DPLL_A_PIN_PHASE_ADJUST
:
1177 ret
= dpll_pin_phase_adj_set(pin
, a
, info
->extack
);
1181 case DPLL_A_PIN_PARENT_DEVICE
:
1182 ret
= dpll_pin_parent_device_set(pin
, a
, info
->extack
);
1186 case DPLL_A_PIN_PARENT_PIN
:
1187 ret
= dpll_pin_parent_pin_set(pin
, a
, info
->extack
);
1191 case DPLL_A_PIN_ESYNC_FREQUENCY
:
1192 ret
= dpll_pin_esync_set(pin
, a
, info
->extack
);
1202 static struct dpll_pin
*
1203 dpll_pin_find(u64 clock_id
, struct nlattr
*mod_name_attr
,
1204 enum dpll_pin_type type
, struct nlattr
*board_label
,
1205 struct nlattr
*panel_label
, struct nlattr
*package_label
,
1206 struct netlink_ext_ack
*extack
)
1208 bool board_match
, panel_match
, package_match
;
1209 struct dpll_pin
*pin_match
= NULL
, *pin
;
1210 const struct dpll_pin_properties
*prop
;
1211 bool cid_match
, mod_match
, type_match
;
1214 xa_for_each_marked(&dpll_pin_xa
, i
, pin
, DPLL_REGISTERED
) {
1216 cid_match
= clock_id
? pin
->clock_id
== clock_id
: true;
1217 mod_match
= mod_name_attr
&& module_name(pin
->module
) ?
1218 !nla_strcmp(mod_name_attr
,
1219 module_name(pin
->module
)) : true;
1220 type_match
= type
? prop
->type
== type
: true;
1221 board_match
= board_label
? (prop
->board_label
?
1222 !nla_strcmp(board_label
, prop
->board_label
) : false) :
1224 panel_match
= panel_label
? (prop
->panel_label
?
1225 !nla_strcmp(panel_label
, prop
->panel_label
) : false) :
1227 package_match
= package_label
? (prop
->package_label
?
1228 !nla_strcmp(package_label
, prop
->package_label
) :
1230 if (cid_match
&& mod_match
&& type_match
&& board_match
&&
1231 panel_match
&& package_match
) {
1233 NL_SET_ERR_MSG(extack
, "multiple matches");
1234 return ERR_PTR(-EINVAL
);
1240 NL_SET_ERR_MSG(extack
, "not found");
1241 return ERR_PTR(-ENODEV
);
1246 static struct dpll_pin
*dpll_pin_find_from_nlattr(struct genl_info
*info
)
1248 struct nlattr
*attr
, *mod_name_attr
= NULL
, *board_label_attr
= NULL
,
1249 *panel_label_attr
= NULL
, *package_label_attr
= NULL
;
1250 enum dpll_pin_type type
= 0;
1254 nla_for_each_attr(attr
, genlmsg_data(info
->genlhdr
),
1255 genlmsg_len(info
->genlhdr
), rem
) {
1256 switch (nla_type(attr
)) {
1257 case DPLL_A_PIN_CLOCK_ID
:
1259 goto duplicated_attr
;
1260 clock_id
= nla_get_u64(attr
);
1262 case DPLL_A_PIN_MODULE_NAME
:
1264 goto duplicated_attr
;
1265 mod_name_attr
= attr
;
1267 case DPLL_A_PIN_TYPE
:
1269 goto duplicated_attr
;
1270 type
= nla_get_u32(attr
);
1272 case DPLL_A_PIN_BOARD_LABEL
:
1273 if (board_label_attr
)
1274 goto duplicated_attr
;
1275 board_label_attr
= attr
;
1277 case DPLL_A_PIN_PANEL_LABEL
:
1278 if (panel_label_attr
)
1279 goto duplicated_attr
;
1280 panel_label_attr
= attr
;
1282 case DPLL_A_PIN_PACKAGE_LABEL
:
1283 if (package_label_attr
)
1284 goto duplicated_attr
;
1285 package_label_attr
= attr
;
1291 if (!(clock_id
|| mod_name_attr
|| board_label_attr
||
1292 panel_label_attr
|| package_label_attr
)) {
1293 NL_SET_ERR_MSG(info
->extack
, "missing attributes");
1294 return ERR_PTR(-EINVAL
);
1296 return dpll_pin_find(clock_id
, mod_name_attr
, type
, board_label_attr
,
1297 panel_label_attr
, package_label_attr
,
1300 NL_SET_ERR_MSG(info
->extack
, "duplicated attribute");
1301 return ERR_PTR(-EINVAL
);
1304 int dpll_nl_pin_id_get_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1306 struct dpll_pin
*pin
;
1307 struct sk_buff
*msg
;
1311 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
1314 hdr
= genlmsg_put_reply(msg
, info
, &dpll_nl_family
, 0,
1315 DPLL_CMD_PIN_ID_GET
);
1320 pin
= dpll_pin_find_from_nlattr(info
);
1322 if (!dpll_pin_available(pin
)) {
1326 ret
= dpll_msg_add_pin_handle(msg
, pin
);
1332 genlmsg_end(msg
, hdr
);
1334 return genlmsg_reply(msg
, info
);
1337 int dpll_nl_pin_get_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1339 struct dpll_pin
*pin
= info
->user_ptr
[0];
1340 struct sk_buff
*msg
;
1346 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
1349 hdr
= genlmsg_put_reply(msg
, info
, &dpll_nl_family
, 0,
1355 ret
= dpll_cmd_pin_get_one(msg
, pin
, info
->extack
);
1360 genlmsg_end(msg
, hdr
);
1362 return genlmsg_reply(msg
, info
);
1365 int dpll_nl_pin_get_dumpit(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1367 struct dpll_dump_ctx
*ctx
= dpll_dump_context(cb
);
1368 struct dpll_pin
*pin
;
1373 mutex_lock(&dpll_lock
);
1374 xa_for_each_marked_start(&dpll_pin_xa
, i
, pin
, DPLL_REGISTERED
,
1376 if (!dpll_pin_available(pin
))
1378 hdr
= genlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
,
1380 &dpll_nl_family
, NLM_F_MULTI
,
1386 ret
= dpll_cmd_pin_get_one(skb
, pin
, cb
->extack
);
1388 genlmsg_cancel(skb
, hdr
);
1391 genlmsg_end(skb
, hdr
);
1393 mutex_unlock(&dpll_lock
);
1395 if (ret
== -EMSGSIZE
) {
1402 int dpll_nl_pin_set_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1404 struct dpll_pin
*pin
= info
->user_ptr
[0];
1406 return dpll_pin_set_from_nlattr(pin
, info
);
1409 static struct dpll_device
*
1410 dpll_device_find(u64 clock_id
, struct nlattr
*mod_name_attr
,
1411 enum dpll_type type
, struct netlink_ext_ack
*extack
)
1413 struct dpll_device
*dpll_match
= NULL
, *dpll
;
1414 bool cid_match
, mod_match
, type_match
;
1417 xa_for_each_marked(&dpll_device_xa
, i
, dpll
, DPLL_REGISTERED
) {
1418 cid_match
= clock_id
? dpll
->clock_id
== clock_id
: true;
1419 mod_match
= mod_name_attr
? (module_name(dpll
->module
) ?
1420 !nla_strcmp(mod_name_attr
,
1421 module_name(dpll
->module
)) : false) : true;
1422 type_match
= type
? dpll
->type
== type
: true;
1423 if (cid_match
&& mod_match
&& type_match
) {
1425 NL_SET_ERR_MSG(extack
, "multiple matches");
1426 return ERR_PTR(-EINVAL
);
1432 NL_SET_ERR_MSG(extack
, "not found");
1433 return ERR_PTR(-ENODEV
);
1439 static struct dpll_device
*
1440 dpll_device_find_from_nlattr(struct genl_info
*info
)
1442 struct nlattr
*attr
, *mod_name_attr
= NULL
;
1443 enum dpll_type type
= 0;
1447 nla_for_each_attr(attr
, genlmsg_data(info
->genlhdr
),
1448 genlmsg_len(info
->genlhdr
), rem
) {
1449 switch (nla_type(attr
)) {
1450 case DPLL_A_CLOCK_ID
:
1452 goto duplicated_attr
;
1453 clock_id
= nla_get_u64(attr
);
1455 case DPLL_A_MODULE_NAME
:
1457 goto duplicated_attr
;
1458 mod_name_attr
= attr
;
1462 goto duplicated_attr
;
1463 type
= nla_get_u32(attr
);
1469 if (!clock_id
&& !mod_name_attr
&& !type
) {
1470 NL_SET_ERR_MSG(info
->extack
, "missing attributes");
1471 return ERR_PTR(-EINVAL
);
1473 return dpll_device_find(clock_id
, mod_name_attr
, type
, info
->extack
);
1475 NL_SET_ERR_MSG(info
->extack
, "duplicated attribute");
1476 return ERR_PTR(-EINVAL
);
1479 int dpll_nl_device_id_get_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1481 struct dpll_device
*dpll
;
1482 struct sk_buff
*msg
;
1486 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
1489 hdr
= genlmsg_put_reply(msg
, info
, &dpll_nl_family
, 0,
1490 DPLL_CMD_DEVICE_ID_GET
);
1496 dpll
= dpll_device_find_from_nlattr(info
);
1497 if (!IS_ERR(dpll
)) {
1498 ret
= dpll_msg_add_dev_handle(msg
, dpll
);
1504 genlmsg_end(msg
, hdr
);
1506 return genlmsg_reply(msg
, info
);
1509 int dpll_nl_device_get_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1511 struct dpll_device
*dpll
= info
->user_ptr
[0];
1512 struct sk_buff
*msg
;
1516 msg
= genlmsg_new(NLMSG_GOODSIZE
, GFP_KERNEL
);
1519 hdr
= genlmsg_put_reply(msg
, info
, &dpll_nl_family
, 0,
1520 DPLL_CMD_DEVICE_GET
);
1526 ret
= dpll_device_get_one(dpll
, msg
, info
->extack
);
1531 genlmsg_end(msg
, hdr
);
1533 return genlmsg_reply(msg
, info
);
1536 int dpll_nl_device_set_doit(struct sk_buff
*skb
, struct genl_info
*info
)
1538 /* placeholder for set command */
1542 int dpll_nl_device_get_dumpit(struct sk_buff
*skb
, struct netlink_callback
*cb
)
1544 struct dpll_dump_ctx
*ctx
= dpll_dump_context(cb
);
1545 struct dpll_device
*dpll
;
1550 mutex_lock(&dpll_lock
);
1551 xa_for_each_marked_start(&dpll_device_xa
, i
, dpll
, DPLL_REGISTERED
,
1553 hdr
= genlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
,
1554 cb
->nlh
->nlmsg_seq
, &dpll_nl_family
,
1555 NLM_F_MULTI
, DPLL_CMD_DEVICE_GET
);
1560 ret
= dpll_device_get_one(dpll
, skb
, cb
->extack
);
1562 genlmsg_cancel(skb
, hdr
);
1565 genlmsg_end(skb
, hdr
);
1567 mutex_unlock(&dpll_lock
);
1569 if (ret
== -EMSGSIZE
) {
1576 int dpll_pre_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1577 struct genl_info
*info
)
1581 if (GENL_REQ_ATTR_CHECK(info
, DPLL_A_ID
))
1584 mutex_lock(&dpll_lock
);
1585 id
= nla_get_u32(info
->attrs
[DPLL_A_ID
]);
1586 info
->user_ptr
[0] = dpll_device_get_by_id(id
);
1587 if (!info
->user_ptr
[0]) {
1588 NL_SET_ERR_MSG(info
->extack
, "device not found");
1593 mutex_unlock(&dpll_lock
);
1597 void dpll_post_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1598 struct genl_info
*info
)
1600 mutex_unlock(&dpll_lock
);
1604 dpll_lock_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1605 struct genl_info
*info
)
1607 mutex_lock(&dpll_lock
);
1613 dpll_unlock_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1614 struct genl_info
*info
)
1616 mutex_unlock(&dpll_lock
);
1619 int dpll_pin_pre_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1620 struct genl_info
*info
)
1624 mutex_lock(&dpll_lock
);
1625 if (GENL_REQ_ATTR_CHECK(info
, DPLL_A_PIN_ID
)) {
1629 info
->user_ptr
[0] = xa_load(&dpll_pin_xa
,
1630 nla_get_u32(info
->attrs
[DPLL_A_PIN_ID
]));
1631 if (!info
->user_ptr
[0] ||
1632 !dpll_pin_available(info
->user_ptr
[0])) {
1633 NL_SET_ERR_MSG(info
->extack
, "pin not found");
1641 mutex_unlock(&dpll_lock
);
1645 void dpll_pin_post_doit(const struct genl_split_ops
*ops
, struct sk_buff
*skb
,
1646 struct genl_info
*info
)
1648 mutex_unlock(&dpll_lock
);