xref: /linux/drivers/dpll/dpll_netlink.c (revision 268531be211f18c55f7ff5a1641d32c0fd0571cd)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Generic netlink for DPLL management framework
4  *
5  *  Copyright (c) 2023 Meta Platforms, Inc. and affiliates
6  *  Copyright (c) 2023 Intel and affiliates
7  *
8  */
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <net/genetlink.h>
12 #include "dpll_core.h"
13 #include "dpll_netlink.h"
14 #include "dpll_nl.h"
15 #include <uapi/linux/dpll.h>
16 
17 #define ASSERT_NOT_NULL(ptr)	(WARN_ON(!ptr))
18 
19 #define xa_for_each_marked_start(xa, index, entry, filter, start) \
20 	for (index = start, entry = xa_find(xa, &index, ULONG_MAX, filter); \
21 	     entry; entry = xa_find_after(xa, &index, ULONG_MAX, filter))
22 
23 struct dpll_dump_ctx {
24 	unsigned long idx;
25 };
26 
27 static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb)
28 {
29 	return (struct dpll_dump_ctx *)cb->ctx;
30 }
31 
32 static int
33 dpll_msg_add_dev_handle(struct sk_buff *msg, struct dpll_device *dpll)
34 {
35 	if (nla_put_u32(msg, DPLL_A_ID, dpll->id))
36 		return -EMSGSIZE;
37 
38 	return 0;
39 }
40 
41 static int
42 dpll_msg_add_dev_parent_handle(struct sk_buff *msg, u32 id)
43 {
44 	if (nla_put_u32(msg, DPLL_A_PIN_PARENT_ID, id))
45 		return -EMSGSIZE;
46 
47 	return 0;
48 }
49 
50 /**
51  * dpll_msg_pin_handle_size - get size of pin handle attribute for given pin
52  * @pin: pin pointer
53  *
54  * Return: byte size of pin handle attribute for given pin.
55  */
56 size_t dpll_msg_pin_handle_size(struct dpll_pin *pin)
57 {
58 	return pin ? nla_total_size(4) : 0; /* DPLL_A_PIN_ID */
59 }
60 EXPORT_SYMBOL_GPL(dpll_msg_pin_handle_size);
61 
62 /**
63  * dpll_msg_add_pin_handle - attach pin handle attribute to a given message
64  * @msg: pointer to sk_buff message to attach a pin handle
65  * @pin: pin pointer
66  *
67  * Return:
68  * * 0 - success
69  * * -EMSGSIZE - no space in message to attach pin handle
70  */
71 int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin)
72 {
73 	if (!pin)
74 		return 0;
75 	if (nla_put_u32(msg, DPLL_A_PIN_ID, pin->id))
76 		return -EMSGSIZE;
77 	return 0;
78 }
79 EXPORT_SYMBOL_GPL(dpll_msg_add_pin_handle);
80 
81 static int
82 dpll_msg_add_mode(struct sk_buff *msg, struct dpll_device *dpll,
83 		  struct netlink_ext_ack *extack)
84 {
85 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
86 	enum dpll_mode mode;
87 	int ret;
88 
89 	ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack);
90 	if (ret)
91 		return ret;
92 	if (nla_put_u32(msg, DPLL_A_MODE, mode))
93 		return -EMSGSIZE;
94 
95 	return 0;
96 }
97 
98 static int
99 dpll_msg_add_mode_supported(struct sk_buff *msg, struct dpll_device *dpll,
100 			    struct netlink_ext_ack *extack)
101 {
102 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
103 	enum dpll_mode mode;
104 	int ret;
105 
106 	/* No mode change is supported now, so the only supported mode is the
107 	 * one obtained by mode_get().
108 	 */
109 
110 	ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack);
111 	if (ret)
112 		return ret;
113 	if (nla_put_u32(msg, DPLL_A_MODE_SUPPORTED, mode))
114 		return -EMSGSIZE;
115 
116 	return 0;
117 }
118 
119 static int
120 dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll,
121 			 struct netlink_ext_ack *extack)
122 {
123 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
124 	enum dpll_lock_status status;
125 	int ret;
126 
127 	ret = ops->lock_status_get(dpll, dpll_priv(dpll), &status, extack);
128 	if (ret)
129 		return ret;
130 	if (nla_put_u32(msg, DPLL_A_LOCK_STATUS, status))
131 		return -EMSGSIZE;
132 
133 	return 0;
134 }
135 
136 static int
137 dpll_msg_add_temp(struct sk_buff *msg, struct dpll_device *dpll,
138 		  struct netlink_ext_ack *extack)
139 {
140 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
141 	s32 temp;
142 	int ret;
143 
144 	if (!ops->temp_get)
145 		return 0;
146 	ret = ops->temp_get(dpll, dpll_priv(dpll), &temp, extack);
147 	if (ret)
148 		return ret;
149 	if (nla_put_s32(msg, DPLL_A_TEMP, temp))
150 		return -EMSGSIZE;
151 
152 	return 0;
153 }
154 
155 static int
156 dpll_msg_add_pin_prio(struct sk_buff *msg, struct dpll_pin *pin,
157 		      struct dpll_pin_ref *ref,
158 		      struct netlink_ext_ack *extack)
159 {
160 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
161 	struct dpll_device *dpll = ref->dpll;
162 	u32 prio;
163 	int ret;
164 
165 	if (!ops->prio_get)
166 		return 0;
167 	ret = ops->prio_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
168 			    dpll_priv(dpll), &prio, extack);
169 	if (ret)
170 		return ret;
171 	if (nla_put_u32(msg, DPLL_A_PIN_PRIO, prio))
172 		return -EMSGSIZE;
173 
174 	return 0;
175 }
176 
177 static int
178 dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, struct dpll_pin *pin,
179 			       struct dpll_pin_ref *ref,
180 			       struct netlink_ext_ack *extack)
181 {
182 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
183 	struct dpll_device *dpll = ref->dpll;
184 	enum dpll_pin_state state;
185 	int ret;
186 
187 	if (!ops->state_on_dpll_get)
188 		return 0;
189 	ret = ops->state_on_dpll_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
190 				     dpll, dpll_priv(dpll), &state, extack);
191 	if (ret)
192 		return ret;
193 	if (nla_put_u32(msg, DPLL_A_PIN_STATE, state))
194 		return -EMSGSIZE;
195 
196 	return 0;
197 }
198 
199 static int
200 dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin,
201 			   struct dpll_pin_ref *ref,
202 			   struct netlink_ext_ack *extack)
203 {
204 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
205 	struct dpll_device *dpll = ref->dpll;
206 	enum dpll_pin_direction direction;
207 	int ret;
208 
209 	ret = ops->direction_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
210 				 dpll_priv(dpll), &direction, extack);
211 	if (ret)
212 		return ret;
213 	if (nla_put_u32(msg, DPLL_A_PIN_DIRECTION, direction))
214 		return -EMSGSIZE;
215 
216 	return 0;
217 }
218 
219 static int
220 dpll_msg_add_pin_phase_adjust(struct sk_buff *msg, struct dpll_pin *pin,
221 			      struct dpll_pin_ref *ref,
222 			      struct netlink_ext_ack *extack)
223 {
224 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
225 	struct dpll_device *dpll = ref->dpll;
226 	s32 phase_adjust;
227 	int ret;
228 
229 	if (!ops->phase_adjust_get)
230 		return 0;
231 	ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
232 				    dpll, dpll_priv(dpll),
233 				    &phase_adjust, extack);
234 	if (ret)
235 		return ret;
236 	if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST, phase_adjust))
237 		return -EMSGSIZE;
238 
239 	return 0;
240 }
241 
242 static int
243 dpll_msg_add_phase_offset(struct sk_buff *msg, struct dpll_pin *pin,
244 			  struct dpll_pin_ref *ref,
245 			  struct netlink_ext_ack *extack)
246 {
247 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
248 	struct dpll_device *dpll = ref->dpll;
249 	s64 phase_offset;
250 	int ret;
251 
252 	if (!ops->phase_offset_get)
253 		return 0;
254 	ret = ops->phase_offset_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
255 				    dpll, dpll_priv(dpll), &phase_offset,
256 				    extack);
257 	if (ret)
258 		return ret;
259 	if (nla_put_64bit(msg, DPLL_A_PIN_PHASE_OFFSET, sizeof(phase_offset),
260 			  &phase_offset, DPLL_A_PIN_PAD))
261 		return -EMSGSIZE;
262 
263 	return 0;
264 }
265 
266 static int
267 dpll_msg_add_pin_freq(struct sk_buff *msg, struct dpll_pin *pin,
268 		      struct dpll_pin_ref *ref, struct netlink_ext_ack *extack)
269 {
270 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
271 	struct dpll_device *dpll = ref->dpll;
272 	struct nlattr *nest;
273 	int fs, ret;
274 	u64 freq;
275 
276 	if (!ops->frequency_get)
277 		return 0;
278 	ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
279 				 dpll_priv(dpll), &freq, extack);
280 	if (ret)
281 		return ret;
282 	if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY, sizeof(freq), &freq,
283 			  DPLL_A_PIN_PAD))
284 		return -EMSGSIZE;
285 	for (fs = 0; fs < pin->prop->freq_supported_num; fs++) {
286 		nest = nla_nest_start(msg, DPLL_A_PIN_FREQUENCY_SUPPORTED);
287 		if (!nest)
288 			return -EMSGSIZE;
289 		freq = pin->prop->freq_supported[fs].min;
290 		if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MIN, sizeof(freq),
291 				  &freq, DPLL_A_PIN_PAD)) {
292 			nla_nest_cancel(msg, nest);
293 			return -EMSGSIZE;
294 		}
295 		freq = pin->prop->freq_supported[fs].max;
296 		if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MAX, sizeof(freq),
297 				  &freq, DPLL_A_PIN_PAD)) {
298 			nla_nest_cancel(msg, nest);
299 			return -EMSGSIZE;
300 		}
301 		nla_nest_end(msg, nest);
302 	}
303 
304 	return 0;
305 }
306 
307 static bool dpll_pin_is_freq_supported(struct dpll_pin *pin, u32 freq)
308 {
309 	int fs;
310 
311 	for (fs = 0; fs < pin->prop->freq_supported_num; fs++)
312 		if (freq >= pin->prop->freq_supported[fs].min &&
313 		    freq <= pin->prop->freq_supported[fs].max)
314 			return true;
315 	return false;
316 }
317 
318 static int
319 dpll_msg_add_pin_parents(struct sk_buff *msg, struct dpll_pin *pin,
320 			 struct dpll_pin_ref *dpll_ref,
321 			 struct netlink_ext_ack *extack)
322 {
323 	enum dpll_pin_state state;
324 	struct dpll_pin_ref *ref;
325 	struct dpll_pin *ppin;
326 	struct nlattr *nest;
327 	unsigned long index;
328 	int ret;
329 
330 	xa_for_each(&pin->parent_refs, index, ref) {
331 		const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
332 		void *parent_priv;
333 
334 		ppin = ref->pin;
335 		parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, ppin);
336 		ret = ops->state_on_pin_get(pin,
337 					    dpll_pin_on_pin_priv(ppin, pin),
338 					    ppin, parent_priv, &state, extack);
339 		if (ret)
340 			return ret;
341 		nest = nla_nest_start(msg, DPLL_A_PIN_PARENT_PIN);
342 		if (!nest)
343 			return -EMSGSIZE;
344 		ret = dpll_msg_add_dev_parent_handle(msg, ppin->id);
345 		if (ret)
346 			goto nest_cancel;
347 		if (nla_put_u32(msg, DPLL_A_PIN_STATE, state)) {
348 			ret = -EMSGSIZE;
349 			goto nest_cancel;
350 		}
351 		nla_nest_end(msg, nest);
352 	}
353 
354 	return 0;
355 
356 nest_cancel:
357 	nla_nest_cancel(msg, nest);
358 	return ret;
359 }
360 
361 static int
362 dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin,
363 		       struct netlink_ext_ack *extack)
364 {
365 	struct dpll_pin_ref *ref;
366 	struct nlattr *attr;
367 	unsigned long index;
368 	int ret;
369 
370 	xa_for_each(&pin->dpll_refs, index, ref) {
371 		attr = nla_nest_start(msg, DPLL_A_PIN_PARENT_DEVICE);
372 		if (!attr)
373 			return -EMSGSIZE;
374 		ret = dpll_msg_add_dev_parent_handle(msg, ref->dpll->id);
375 		if (ret)
376 			goto nest_cancel;
377 		ret = dpll_msg_add_pin_on_dpll_state(msg, pin, ref, extack);
378 		if (ret)
379 			goto nest_cancel;
380 		ret = dpll_msg_add_pin_prio(msg, pin, ref, extack);
381 		if (ret)
382 			goto nest_cancel;
383 		ret = dpll_msg_add_pin_direction(msg, pin, ref, extack);
384 		if (ret)
385 			goto nest_cancel;
386 		ret = dpll_msg_add_phase_offset(msg, pin, ref, extack);
387 		if (ret)
388 			goto nest_cancel;
389 		nla_nest_end(msg, attr);
390 	}
391 
392 	return 0;
393 
394 nest_cancel:
395 	nla_nest_end(msg, attr);
396 	return ret;
397 }
398 
399 static int
400 dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
401 		     struct netlink_ext_ack *extack)
402 {
403 	const struct dpll_pin_properties *prop = pin->prop;
404 	struct dpll_pin_ref *ref;
405 	int ret;
406 
407 	ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
408 	ASSERT_NOT_NULL(ref);
409 
410 	ret = dpll_msg_add_pin_handle(msg, pin);
411 	if (ret)
412 		return ret;
413 	if (nla_put_string(msg, DPLL_A_PIN_MODULE_NAME,
414 			   module_name(pin->module)))
415 		return -EMSGSIZE;
416 	if (nla_put_64bit(msg, DPLL_A_PIN_CLOCK_ID, sizeof(pin->clock_id),
417 			  &pin->clock_id, DPLL_A_PIN_PAD))
418 		return -EMSGSIZE;
419 	if (prop->board_label &&
420 	    nla_put_string(msg, DPLL_A_PIN_BOARD_LABEL, prop->board_label))
421 		return -EMSGSIZE;
422 	if (prop->panel_label &&
423 	    nla_put_string(msg, DPLL_A_PIN_PANEL_LABEL, prop->panel_label))
424 		return -EMSGSIZE;
425 	if (prop->package_label &&
426 	    nla_put_string(msg, DPLL_A_PIN_PACKAGE_LABEL,
427 			   prop->package_label))
428 		return -EMSGSIZE;
429 	if (nla_put_u32(msg, DPLL_A_PIN_TYPE, prop->type))
430 		return -EMSGSIZE;
431 	if (nla_put_u32(msg, DPLL_A_PIN_CAPABILITIES, prop->capabilities))
432 		return -EMSGSIZE;
433 	ret = dpll_msg_add_pin_freq(msg, pin, ref, extack);
434 	if (ret)
435 		return ret;
436 	if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MIN,
437 			prop->phase_range.min))
438 		return -EMSGSIZE;
439 	if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MAX,
440 			prop->phase_range.max))
441 		return -EMSGSIZE;
442 	ret = dpll_msg_add_pin_phase_adjust(msg, pin, ref, extack);
443 	if (ret)
444 		return ret;
445 	if (xa_empty(&pin->parent_refs))
446 		ret = dpll_msg_add_pin_dplls(msg, pin, extack);
447 	else
448 		ret = dpll_msg_add_pin_parents(msg, pin, ref, extack);
449 
450 	return ret;
451 }
452 
453 static int
454 dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
455 		    struct netlink_ext_ack *extack)
456 {
457 	int ret;
458 
459 	ret = dpll_msg_add_dev_handle(msg, dpll);
460 	if (ret)
461 		return ret;
462 	if (nla_put_string(msg, DPLL_A_MODULE_NAME, module_name(dpll->module)))
463 		return -EMSGSIZE;
464 	if (nla_put_64bit(msg, DPLL_A_CLOCK_ID, sizeof(dpll->clock_id),
465 			  &dpll->clock_id, DPLL_A_PAD))
466 		return -EMSGSIZE;
467 	ret = dpll_msg_add_temp(msg, dpll, extack);
468 	if (ret)
469 		return ret;
470 	ret = dpll_msg_add_lock_status(msg, dpll, extack);
471 	if (ret)
472 		return ret;
473 	ret = dpll_msg_add_mode(msg, dpll, extack);
474 	if (ret)
475 		return ret;
476 	ret = dpll_msg_add_mode_supported(msg, dpll, extack);
477 	if (ret)
478 		return ret;
479 	if (nla_put_u32(msg, DPLL_A_TYPE, dpll->type))
480 		return -EMSGSIZE;
481 
482 	return 0;
483 }
484 
485 static int
486 dpll_device_event_send(enum dpll_cmd event, struct dpll_device *dpll)
487 {
488 	struct sk_buff *msg;
489 	int ret = -ENOMEM;
490 	void *hdr;
491 
492 	if (WARN_ON(!xa_get_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED)))
493 		return -ENODEV;
494 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
495 	if (!msg)
496 		return -ENOMEM;
497 	hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
498 	if (!hdr)
499 		goto err_free_msg;
500 	ret = dpll_device_get_one(dpll, msg, NULL);
501 	if (ret)
502 		goto err_cancel_msg;
503 	genlmsg_end(msg, hdr);
504 	genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
505 
506 	return 0;
507 
508 err_cancel_msg:
509 	genlmsg_cancel(msg, hdr);
510 err_free_msg:
511 	nlmsg_free(msg);
512 
513 	return ret;
514 }
515 
516 int dpll_device_create_ntf(struct dpll_device *dpll)
517 {
518 	return dpll_device_event_send(DPLL_CMD_DEVICE_CREATE_NTF, dpll);
519 }
520 
521 int dpll_device_delete_ntf(struct dpll_device *dpll)
522 {
523 	return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF, dpll);
524 }
525 
526 static int
527 __dpll_device_change_ntf(struct dpll_device *dpll)
528 {
529 	return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll);
530 }
531 
532 /**
533  * dpll_device_change_ntf - notify that the dpll device has been changed
534  * @dpll: registered dpll pointer
535  *
536  * Context: acquires and holds a dpll_lock.
537  * Return: 0 if succeeds, error code otherwise.
538  */
539 int dpll_device_change_ntf(struct dpll_device *dpll)
540 {
541 	int ret;
542 
543 	mutex_lock(&dpll_lock);
544 	ret = __dpll_device_change_ntf(dpll);
545 	mutex_unlock(&dpll_lock);
546 
547 	return ret;
548 }
549 EXPORT_SYMBOL_GPL(dpll_device_change_ntf);
550 
551 static int
552 dpll_pin_event_send(enum dpll_cmd event, struct dpll_pin *pin)
553 {
554 	struct sk_buff *msg;
555 	int ret = -ENOMEM;
556 	void *hdr;
557 
558 	if (WARN_ON(!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED)))
559 		return -ENODEV;
560 
561 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
562 	if (!msg)
563 		return -ENOMEM;
564 
565 	hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
566 	if (!hdr)
567 		goto err_free_msg;
568 	ret = dpll_cmd_pin_get_one(msg, pin, NULL);
569 	if (ret)
570 		goto err_cancel_msg;
571 	genlmsg_end(msg, hdr);
572 	genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
573 
574 	return 0;
575 
576 err_cancel_msg:
577 	genlmsg_cancel(msg, hdr);
578 err_free_msg:
579 	nlmsg_free(msg);
580 
581 	return ret;
582 }
583 
584 int dpll_pin_create_ntf(struct dpll_pin *pin)
585 {
586 	return dpll_pin_event_send(DPLL_CMD_PIN_CREATE_NTF, pin);
587 }
588 
589 int dpll_pin_delete_ntf(struct dpll_pin *pin)
590 {
591 	return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin);
592 }
593 
594 static int __dpll_pin_change_ntf(struct dpll_pin *pin)
595 {
596 	return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin);
597 }
598 
599 /**
600  * dpll_pin_change_ntf - notify that the pin has been changed
601  * @pin: registered pin pointer
602  *
603  * Context: acquires and holds a dpll_lock.
604  * Return: 0 if succeeds, error code otherwise.
605  */
606 int dpll_pin_change_ntf(struct dpll_pin *pin)
607 {
608 	int ret;
609 
610 	mutex_lock(&dpll_lock);
611 	ret = __dpll_pin_change_ntf(pin);
612 	mutex_unlock(&dpll_lock);
613 
614 	return ret;
615 }
616 EXPORT_SYMBOL_GPL(dpll_pin_change_ntf);
617 
618 static int
619 dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
620 		  struct netlink_ext_ack *extack)
621 {
622 	u64 freq = nla_get_u64(a), old_freq;
623 	struct dpll_pin_ref *ref, *failed;
624 	const struct dpll_pin_ops *ops;
625 	struct dpll_device *dpll;
626 	unsigned long i;
627 	int ret;
628 
629 	if (!dpll_pin_is_freq_supported(pin, freq)) {
630 		NL_SET_ERR_MSG_ATTR(extack, a, "frequency is not supported by the device");
631 		return -EINVAL;
632 	}
633 
634 	xa_for_each(&pin->dpll_refs, i, ref) {
635 		ops = dpll_pin_ops(ref);
636 		if (!ops->frequency_set || !ops->frequency_get) {
637 			NL_SET_ERR_MSG(extack, "frequency set not supported by the device");
638 			return -EOPNOTSUPP;
639 		}
640 	}
641 	ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
642 	ops = dpll_pin_ops(ref);
643 	dpll = ref->dpll;
644 	ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
645 				 dpll_priv(dpll), &old_freq, extack);
646 	if (ret) {
647 		NL_SET_ERR_MSG(extack, "unable to get old frequency value");
648 		return ret;
649 	}
650 	if (freq == old_freq)
651 		return 0;
652 
653 	xa_for_each(&pin->dpll_refs, i, ref) {
654 		ops = dpll_pin_ops(ref);
655 		dpll = ref->dpll;
656 		ret = ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
657 					 dpll, dpll_priv(dpll), freq, extack);
658 		if (ret) {
659 			failed = ref;
660 			NL_SET_ERR_MSG_FMT(extack, "frequency set failed for dpll_id:%u",
661 					   dpll->id);
662 			goto rollback;
663 		}
664 	}
665 	__dpll_pin_change_ntf(pin);
666 
667 	return 0;
668 
669 rollback:
670 	xa_for_each(&pin->dpll_refs, i, ref) {
671 		if (ref == failed)
672 			break;
673 		ops = dpll_pin_ops(ref);
674 		dpll = ref->dpll;
675 		if (ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
676 				       dpll, dpll_priv(dpll), old_freq, extack))
677 			NL_SET_ERR_MSG(extack, "set frequency rollback failed");
678 	}
679 	return ret;
680 }
681 
682 static int
683 dpll_pin_on_pin_state_set(struct dpll_pin *pin, u32 parent_idx,
684 			  enum dpll_pin_state state,
685 			  struct netlink_ext_ack *extack)
686 {
687 	struct dpll_pin_ref *parent_ref;
688 	const struct dpll_pin_ops *ops;
689 	struct dpll_pin_ref *dpll_ref;
690 	void *pin_priv, *parent_priv;
691 	struct dpll_pin *parent;
692 	unsigned long i;
693 	int ret;
694 
695 	if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
696 	      pin->prop->capabilities)) {
697 		NL_SET_ERR_MSG(extack, "state changing is not allowed");
698 		return -EOPNOTSUPP;
699 	}
700 	parent = xa_load(&dpll_pin_xa, parent_idx);
701 	if (!parent)
702 		return -EINVAL;
703 	parent_ref = xa_load(&pin->parent_refs, parent->pin_idx);
704 	if (!parent_ref)
705 		return -EINVAL;
706 	xa_for_each(&parent->dpll_refs, i, dpll_ref) {
707 		ops = dpll_pin_ops(parent_ref);
708 		if (!ops->state_on_pin_set)
709 			return -EOPNOTSUPP;
710 		pin_priv = dpll_pin_on_pin_priv(parent, pin);
711 		parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, parent);
712 		ret = ops->state_on_pin_set(pin, pin_priv, parent, parent_priv,
713 					    state, extack);
714 		if (ret)
715 			return ret;
716 	}
717 	__dpll_pin_change_ntf(pin);
718 
719 	return 0;
720 }
721 
722 static int
723 dpll_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin,
724 		   enum dpll_pin_state state,
725 		   struct netlink_ext_ack *extack)
726 {
727 	const struct dpll_pin_ops *ops;
728 	struct dpll_pin_ref *ref;
729 	int ret;
730 
731 	if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
732 	      pin->prop->capabilities)) {
733 		NL_SET_ERR_MSG(extack, "state changing is not allowed");
734 		return -EOPNOTSUPP;
735 	}
736 	ref = xa_load(&pin->dpll_refs, dpll->id);
737 	ASSERT_NOT_NULL(ref);
738 	ops = dpll_pin_ops(ref);
739 	if (!ops->state_on_dpll_set)
740 		return -EOPNOTSUPP;
741 	ret = ops->state_on_dpll_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
742 				     dpll, dpll_priv(dpll), state, extack);
743 	if (ret)
744 		return ret;
745 	__dpll_pin_change_ntf(pin);
746 
747 	return 0;
748 }
749 
750 static int
751 dpll_pin_prio_set(struct dpll_device *dpll, struct dpll_pin *pin,
752 		  u32 prio, struct netlink_ext_ack *extack)
753 {
754 	const struct dpll_pin_ops *ops;
755 	struct dpll_pin_ref *ref;
756 	int ret;
757 
758 	if (!(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE &
759 	      pin->prop->capabilities)) {
760 		NL_SET_ERR_MSG(extack, "prio changing is not allowed");
761 		return -EOPNOTSUPP;
762 	}
763 	ref = xa_load(&pin->dpll_refs, dpll->id);
764 	ASSERT_NOT_NULL(ref);
765 	ops = dpll_pin_ops(ref);
766 	if (!ops->prio_set)
767 		return -EOPNOTSUPP;
768 	ret = ops->prio_set(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
769 			    dpll_priv(dpll), prio, extack);
770 	if (ret)
771 		return ret;
772 	__dpll_pin_change_ntf(pin);
773 
774 	return 0;
775 }
776 
777 static int
778 dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll,
779 		       enum dpll_pin_direction direction,
780 		       struct netlink_ext_ack *extack)
781 {
782 	const struct dpll_pin_ops *ops;
783 	struct dpll_pin_ref *ref;
784 	int ret;
785 
786 	if (!(DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE &
787 	      pin->prop->capabilities)) {
788 		NL_SET_ERR_MSG(extack, "direction changing is not allowed");
789 		return -EOPNOTSUPP;
790 	}
791 	ref = xa_load(&pin->dpll_refs, dpll->id);
792 	ASSERT_NOT_NULL(ref);
793 	ops = dpll_pin_ops(ref);
794 	if (!ops->direction_set)
795 		return -EOPNOTSUPP;
796 	ret = ops->direction_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
797 				 dpll, dpll_priv(dpll), direction, extack);
798 	if (ret)
799 		return ret;
800 	__dpll_pin_change_ntf(pin);
801 
802 	return 0;
803 }
804 
805 static int
806 dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr,
807 		       struct netlink_ext_ack *extack)
808 {
809 	struct dpll_pin_ref *ref, *failed;
810 	const struct dpll_pin_ops *ops;
811 	s32 phase_adj, old_phase_adj;
812 	struct dpll_device *dpll;
813 	unsigned long i;
814 	int ret;
815 
816 	phase_adj = nla_get_s32(phase_adj_attr);
817 	if (phase_adj > pin->prop->phase_range.max ||
818 	    phase_adj < pin->prop->phase_range.min) {
819 		NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr,
820 				    "phase adjust value not supported");
821 		return -EINVAL;
822 	}
823 
824 	xa_for_each(&pin->dpll_refs, i, ref) {
825 		ops = dpll_pin_ops(ref);
826 		if (!ops->phase_adjust_set || !ops->phase_adjust_get) {
827 			NL_SET_ERR_MSG(extack, "phase adjust not supported");
828 			return -EOPNOTSUPP;
829 		}
830 	}
831 	ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
832 	ops = dpll_pin_ops(ref);
833 	dpll = ref->dpll;
834 	ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
835 				    dpll, dpll_priv(dpll), &old_phase_adj,
836 				    extack);
837 	if (ret) {
838 		NL_SET_ERR_MSG(extack, "unable to get old phase adjust value");
839 		return ret;
840 	}
841 	if (phase_adj == old_phase_adj)
842 		return 0;
843 
844 	xa_for_each(&pin->dpll_refs, i, ref) {
845 		ops = dpll_pin_ops(ref);
846 		dpll = ref->dpll;
847 		ret = ops->phase_adjust_set(pin,
848 					    dpll_pin_on_dpll_priv(dpll, pin),
849 					    dpll, dpll_priv(dpll), phase_adj,
850 					    extack);
851 		if (ret) {
852 			failed = ref;
853 			NL_SET_ERR_MSG_FMT(extack,
854 					   "phase adjust set failed for dpll_id:%u",
855 					   dpll->id);
856 			goto rollback;
857 		}
858 	}
859 	__dpll_pin_change_ntf(pin);
860 
861 	return 0;
862 
863 rollback:
864 	xa_for_each(&pin->dpll_refs, i, ref) {
865 		if (ref == failed)
866 			break;
867 		ops = dpll_pin_ops(ref);
868 		dpll = ref->dpll;
869 		if (ops->phase_adjust_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
870 					  dpll, dpll_priv(dpll), old_phase_adj,
871 					  extack))
872 			NL_SET_ERR_MSG(extack, "set phase adjust rollback failed");
873 	}
874 	return ret;
875 }
876 
877 static int
878 dpll_pin_parent_device_set(struct dpll_pin *pin, struct nlattr *parent_nest,
879 			   struct netlink_ext_ack *extack)
880 {
881 	struct nlattr *tb[DPLL_A_PIN_MAX + 1];
882 	enum dpll_pin_direction direction;
883 	enum dpll_pin_state state;
884 	struct dpll_pin_ref *ref;
885 	struct dpll_device *dpll;
886 	u32 pdpll_idx, prio;
887 	int ret;
888 
889 	nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
890 			 dpll_pin_parent_device_nl_policy, extack);
891 	if (!tb[DPLL_A_PIN_PARENT_ID]) {
892 		NL_SET_ERR_MSG(extack, "device parent id expected");
893 		return -EINVAL;
894 	}
895 	pdpll_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
896 	dpll = xa_load(&dpll_device_xa, pdpll_idx);
897 	if (!dpll) {
898 		NL_SET_ERR_MSG(extack, "parent device not found");
899 		return -EINVAL;
900 	}
901 	ref = xa_load(&pin->dpll_refs, dpll->id);
902 	if (!ref) {
903 		NL_SET_ERR_MSG(extack, "pin not connected to given parent device");
904 		return -EINVAL;
905 	}
906 	if (tb[DPLL_A_PIN_STATE]) {
907 		state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
908 		ret = dpll_pin_state_set(dpll, pin, state, extack);
909 		if (ret)
910 			return ret;
911 	}
912 	if (tb[DPLL_A_PIN_PRIO]) {
913 		prio = nla_get_u32(tb[DPLL_A_PIN_PRIO]);
914 		ret = dpll_pin_prio_set(dpll, pin, prio, extack);
915 		if (ret)
916 			return ret;
917 	}
918 	if (tb[DPLL_A_PIN_DIRECTION]) {
919 		direction = nla_get_u32(tb[DPLL_A_PIN_DIRECTION]);
920 		ret = dpll_pin_direction_set(pin, dpll, direction, extack);
921 		if (ret)
922 			return ret;
923 	}
924 	return 0;
925 }
926 
927 static int
928 dpll_pin_parent_pin_set(struct dpll_pin *pin, struct nlattr *parent_nest,
929 			struct netlink_ext_ack *extack)
930 {
931 	struct nlattr *tb[DPLL_A_PIN_MAX + 1];
932 	u32 ppin_idx;
933 	int ret;
934 
935 	nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
936 			 dpll_pin_parent_pin_nl_policy, extack);
937 	if (!tb[DPLL_A_PIN_PARENT_ID]) {
938 		NL_SET_ERR_MSG(extack, "device parent id expected");
939 		return -EINVAL;
940 	}
941 	ppin_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
942 
943 	if (tb[DPLL_A_PIN_STATE]) {
944 		enum dpll_pin_state state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
945 
946 		ret = dpll_pin_on_pin_state_set(pin, ppin_idx, state, extack);
947 		if (ret)
948 			return ret;
949 	}
950 
951 	return 0;
952 }
953 
954 static int
955 dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
956 {
957 	struct nlattr *a;
958 	int rem, ret;
959 
960 	nla_for_each_attr(a, genlmsg_data(info->genlhdr),
961 			  genlmsg_len(info->genlhdr), rem) {
962 		switch (nla_type(a)) {
963 		case DPLL_A_PIN_FREQUENCY:
964 			ret = dpll_pin_freq_set(pin, a, info->extack);
965 			if (ret)
966 				return ret;
967 			break;
968 		case DPLL_A_PIN_PHASE_ADJUST:
969 			ret = dpll_pin_phase_adj_set(pin, a, info->extack);
970 			if (ret)
971 				return ret;
972 			break;
973 		case DPLL_A_PIN_PARENT_DEVICE:
974 			ret = dpll_pin_parent_device_set(pin, a, info->extack);
975 			if (ret)
976 				return ret;
977 			break;
978 		case DPLL_A_PIN_PARENT_PIN:
979 			ret = dpll_pin_parent_pin_set(pin, a, info->extack);
980 			if (ret)
981 				return ret;
982 			break;
983 		}
984 	}
985 
986 	return 0;
987 }
988 
989 static struct dpll_pin *
990 dpll_pin_find(u64 clock_id, struct nlattr *mod_name_attr,
991 	      enum dpll_pin_type type, struct nlattr *board_label,
992 	      struct nlattr *panel_label, struct nlattr *package_label,
993 	      struct netlink_ext_ack *extack)
994 {
995 	bool board_match, panel_match, package_match;
996 	struct dpll_pin *pin_match = NULL, *pin;
997 	const struct dpll_pin_properties *prop;
998 	bool cid_match, mod_match, type_match;
999 	unsigned long i;
1000 
1001 	xa_for_each_marked(&dpll_pin_xa, i, pin, DPLL_REGISTERED) {
1002 		prop = pin->prop;
1003 		cid_match = clock_id ? pin->clock_id == clock_id : true;
1004 		mod_match = mod_name_attr && module_name(pin->module) ?
1005 			!nla_strcmp(mod_name_attr,
1006 				    module_name(pin->module)) : true;
1007 		type_match = type ? prop->type == type : true;
1008 		board_match = board_label ? (prop->board_label ?
1009 			!nla_strcmp(board_label, prop->board_label) : false) :
1010 			true;
1011 		panel_match = panel_label ? (prop->panel_label ?
1012 			!nla_strcmp(panel_label, prop->panel_label) : false) :
1013 			true;
1014 		package_match = package_label ? (prop->package_label ?
1015 			!nla_strcmp(package_label, prop->package_label) :
1016 			false) : true;
1017 		if (cid_match && mod_match && type_match && board_match &&
1018 		    panel_match && package_match) {
1019 			if (pin_match) {
1020 				NL_SET_ERR_MSG(extack, "multiple matches");
1021 				return ERR_PTR(-EINVAL);
1022 			}
1023 			pin_match = pin;
1024 		}
1025 	}
1026 	if (!pin_match) {
1027 		NL_SET_ERR_MSG(extack, "not found");
1028 		return ERR_PTR(-ENODEV);
1029 	}
1030 	return pin_match;
1031 }
1032 
1033 static struct dpll_pin *dpll_pin_find_from_nlattr(struct genl_info *info)
1034 {
1035 	struct nlattr *attr, *mod_name_attr = NULL, *board_label_attr = NULL,
1036 		*panel_label_attr = NULL, *package_label_attr = NULL;
1037 	enum dpll_pin_type type = 0;
1038 	u64 clock_id = 0;
1039 	int rem = 0;
1040 
1041 	nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
1042 			  genlmsg_len(info->genlhdr), rem) {
1043 		switch (nla_type(attr)) {
1044 		case DPLL_A_PIN_CLOCK_ID:
1045 			if (clock_id)
1046 				goto duplicated_attr;
1047 			clock_id = nla_get_u64(attr);
1048 			break;
1049 		case DPLL_A_PIN_MODULE_NAME:
1050 			if (mod_name_attr)
1051 				goto duplicated_attr;
1052 			mod_name_attr = attr;
1053 			break;
1054 		case DPLL_A_PIN_TYPE:
1055 			if (type)
1056 				goto duplicated_attr;
1057 			type = nla_get_u32(attr);
1058 		break;
1059 		case DPLL_A_PIN_BOARD_LABEL:
1060 			if (board_label_attr)
1061 				goto duplicated_attr;
1062 			board_label_attr = attr;
1063 		break;
1064 		case DPLL_A_PIN_PANEL_LABEL:
1065 			if (panel_label_attr)
1066 				goto duplicated_attr;
1067 			panel_label_attr = attr;
1068 		break;
1069 		case DPLL_A_PIN_PACKAGE_LABEL:
1070 			if (package_label_attr)
1071 				goto duplicated_attr;
1072 			package_label_attr = attr;
1073 		break;
1074 		default:
1075 			break;
1076 		}
1077 	}
1078 	if (!(clock_id  || mod_name_attr || board_label_attr ||
1079 	      panel_label_attr || package_label_attr)) {
1080 		NL_SET_ERR_MSG(info->extack, "missing attributes");
1081 		return ERR_PTR(-EINVAL);
1082 	}
1083 	return dpll_pin_find(clock_id, mod_name_attr, type, board_label_attr,
1084 			     panel_label_attr, package_label_attr,
1085 			     info->extack);
1086 duplicated_attr:
1087 	NL_SET_ERR_MSG(info->extack, "duplicated attribute");
1088 	return ERR_PTR(-EINVAL);
1089 }
1090 
1091 int dpll_nl_pin_id_get_doit(struct sk_buff *skb, struct genl_info *info)
1092 {
1093 	struct dpll_pin *pin;
1094 	struct sk_buff *msg;
1095 	struct nlattr *hdr;
1096 	int ret;
1097 
1098 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1099 	if (!msg)
1100 		return -ENOMEM;
1101 	hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1102 				DPLL_CMD_PIN_ID_GET);
1103 	if (!hdr) {
1104 		nlmsg_free(msg);
1105 		return -EMSGSIZE;
1106 	}
1107 	pin = dpll_pin_find_from_nlattr(info);
1108 	if (!IS_ERR(pin)) {
1109 		ret = dpll_msg_add_pin_handle(msg, pin);
1110 		if (ret) {
1111 			nlmsg_free(msg);
1112 			return ret;
1113 		}
1114 	}
1115 	genlmsg_end(msg, hdr);
1116 
1117 	return genlmsg_reply(msg, info);
1118 }
1119 
1120 int dpll_nl_pin_get_doit(struct sk_buff *skb, struct genl_info *info)
1121 {
1122 	struct dpll_pin *pin = info->user_ptr[0];
1123 	struct sk_buff *msg;
1124 	struct nlattr *hdr;
1125 	int ret;
1126 
1127 	if (!pin)
1128 		return -ENODEV;
1129 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1130 	if (!msg)
1131 		return -ENOMEM;
1132 	hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1133 				DPLL_CMD_PIN_GET);
1134 	if (!hdr) {
1135 		nlmsg_free(msg);
1136 		return -EMSGSIZE;
1137 	}
1138 	ret = dpll_cmd_pin_get_one(msg, pin, info->extack);
1139 	if (ret) {
1140 		nlmsg_free(msg);
1141 		return ret;
1142 	}
1143 	genlmsg_end(msg, hdr);
1144 
1145 	return genlmsg_reply(msg, info);
1146 }
1147 
1148 int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
1149 {
1150 	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
1151 	struct dpll_pin *pin;
1152 	struct nlattr *hdr;
1153 	unsigned long i;
1154 	int ret = 0;
1155 
1156 	xa_for_each_marked_start(&dpll_pin_xa, i, pin, DPLL_REGISTERED,
1157 				 ctx->idx) {
1158 		hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1159 				  cb->nlh->nlmsg_seq,
1160 				  &dpll_nl_family, NLM_F_MULTI,
1161 				  DPLL_CMD_PIN_GET);
1162 		if (!hdr) {
1163 			ret = -EMSGSIZE;
1164 			break;
1165 		}
1166 		ret = dpll_cmd_pin_get_one(skb, pin, cb->extack);
1167 		if (ret) {
1168 			genlmsg_cancel(skb, hdr);
1169 			break;
1170 		}
1171 		genlmsg_end(skb, hdr);
1172 	}
1173 	if (ret == -EMSGSIZE) {
1174 		ctx->idx = i;
1175 		return skb->len;
1176 	}
1177 	return ret;
1178 }
1179 
1180 int dpll_nl_pin_set_doit(struct sk_buff *skb, struct genl_info *info)
1181 {
1182 	struct dpll_pin *pin = info->user_ptr[0];
1183 
1184 	return dpll_pin_set_from_nlattr(pin, info);
1185 }
1186 
1187 static struct dpll_device *
1188 dpll_device_find(u64 clock_id, struct nlattr *mod_name_attr,
1189 		 enum dpll_type type, struct netlink_ext_ack *extack)
1190 {
1191 	struct dpll_device *dpll_match = NULL, *dpll;
1192 	bool cid_match, mod_match, type_match;
1193 	unsigned long i;
1194 
1195 	xa_for_each_marked(&dpll_device_xa, i, dpll, DPLL_REGISTERED) {
1196 		cid_match = clock_id ? dpll->clock_id == clock_id : true;
1197 		mod_match = mod_name_attr ? (module_name(dpll->module) ?
1198 			!nla_strcmp(mod_name_attr,
1199 				    module_name(dpll->module)) : false) : true;
1200 		type_match = type ? dpll->type == type : true;
1201 		if (cid_match && mod_match && type_match) {
1202 			if (dpll_match) {
1203 				NL_SET_ERR_MSG(extack, "multiple matches");
1204 				return ERR_PTR(-EINVAL);
1205 			}
1206 			dpll_match = dpll;
1207 		}
1208 	}
1209 	if (!dpll_match) {
1210 		NL_SET_ERR_MSG(extack, "not found");
1211 		return ERR_PTR(-ENODEV);
1212 	}
1213 
1214 	return dpll_match;
1215 }
1216 
1217 static struct dpll_device *
1218 dpll_device_find_from_nlattr(struct genl_info *info)
1219 {
1220 	struct nlattr *attr, *mod_name_attr = NULL;
1221 	enum dpll_type type = 0;
1222 	u64 clock_id = 0;
1223 	int rem = 0;
1224 
1225 	nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
1226 			  genlmsg_len(info->genlhdr), rem) {
1227 		switch (nla_type(attr)) {
1228 		case DPLL_A_CLOCK_ID:
1229 			if (clock_id)
1230 				goto duplicated_attr;
1231 			clock_id = nla_get_u64(attr);
1232 			break;
1233 		case DPLL_A_MODULE_NAME:
1234 			if (mod_name_attr)
1235 				goto duplicated_attr;
1236 			mod_name_attr = attr;
1237 			break;
1238 		case DPLL_A_TYPE:
1239 			if (type)
1240 				goto duplicated_attr;
1241 			type = nla_get_u32(attr);
1242 			break;
1243 		default:
1244 			break;
1245 		}
1246 	}
1247 	if (!clock_id && !mod_name_attr && !type) {
1248 		NL_SET_ERR_MSG(info->extack, "missing attributes");
1249 		return ERR_PTR(-EINVAL);
1250 	}
1251 	return dpll_device_find(clock_id, mod_name_attr, type, info->extack);
1252 duplicated_attr:
1253 	NL_SET_ERR_MSG(info->extack, "duplicated attribute");
1254 	return ERR_PTR(-EINVAL);
1255 }
1256 
1257 int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info)
1258 {
1259 	struct dpll_device *dpll;
1260 	struct sk_buff *msg;
1261 	struct nlattr *hdr;
1262 	int ret;
1263 
1264 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1265 	if (!msg)
1266 		return -ENOMEM;
1267 	hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1268 				DPLL_CMD_DEVICE_ID_GET);
1269 	if (!hdr) {
1270 		nlmsg_free(msg);
1271 		return -EMSGSIZE;
1272 	}
1273 
1274 	dpll = dpll_device_find_from_nlattr(info);
1275 	if (!IS_ERR(dpll)) {
1276 		ret = dpll_msg_add_dev_handle(msg, dpll);
1277 		if (ret) {
1278 			nlmsg_free(msg);
1279 			return ret;
1280 		}
1281 	}
1282 	genlmsg_end(msg, hdr);
1283 
1284 	return genlmsg_reply(msg, info);
1285 }
1286 
1287 int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info)
1288 {
1289 	struct dpll_device *dpll = info->user_ptr[0];
1290 	struct sk_buff *msg;
1291 	struct nlattr *hdr;
1292 	int ret;
1293 
1294 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1295 	if (!msg)
1296 		return -ENOMEM;
1297 	hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1298 				DPLL_CMD_DEVICE_GET);
1299 	if (!hdr) {
1300 		nlmsg_free(msg);
1301 		return -EMSGSIZE;
1302 	}
1303 
1304 	ret = dpll_device_get_one(dpll, msg, info->extack);
1305 	if (ret) {
1306 		nlmsg_free(msg);
1307 		return ret;
1308 	}
1309 	genlmsg_end(msg, hdr);
1310 
1311 	return genlmsg_reply(msg, info);
1312 }
1313 
1314 int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info)
1315 {
1316 	/* placeholder for set command */
1317 	return 0;
1318 }
1319 
1320 int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
1321 {
1322 	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
1323 	struct dpll_device *dpll;
1324 	struct nlattr *hdr;
1325 	unsigned long i;
1326 	int ret = 0;
1327 
1328 	xa_for_each_marked_start(&dpll_device_xa, i, dpll, DPLL_REGISTERED,
1329 				 ctx->idx) {
1330 		hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1331 				  cb->nlh->nlmsg_seq, &dpll_nl_family,
1332 				  NLM_F_MULTI, DPLL_CMD_DEVICE_GET);
1333 		if (!hdr) {
1334 			ret = -EMSGSIZE;
1335 			break;
1336 		}
1337 		ret = dpll_device_get_one(dpll, skb, cb->extack);
1338 		if (ret) {
1339 			genlmsg_cancel(skb, hdr);
1340 			break;
1341 		}
1342 		genlmsg_end(skb, hdr);
1343 	}
1344 	if (ret == -EMSGSIZE) {
1345 		ctx->idx = i;
1346 		return skb->len;
1347 	}
1348 	return ret;
1349 }
1350 
1351 int dpll_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1352 		  struct genl_info *info)
1353 {
1354 	u32 id;
1355 
1356 	if (GENL_REQ_ATTR_CHECK(info, DPLL_A_ID))
1357 		return -EINVAL;
1358 
1359 	mutex_lock(&dpll_lock);
1360 	id = nla_get_u32(info->attrs[DPLL_A_ID]);
1361 	info->user_ptr[0] = dpll_device_get_by_id(id);
1362 	if (!info->user_ptr[0]) {
1363 		NL_SET_ERR_MSG(info->extack, "device not found");
1364 		goto unlock;
1365 	}
1366 	return 0;
1367 unlock:
1368 	mutex_unlock(&dpll_lock);
1369 	return -ENODEV;
1370 }
1371 
1372 void dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1373 		    struct genl_info *info)
1374 {
1375 	mutex_unlock(&dpll_lock);
1376 }
1377 
1378 int
1379 dpll_lock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1380 	       struct genl_info *info)
1381 {
1382 	mutex_lock(&dpll_lock);
1383 
1384 	return 0;
1385 }
1386 
1387 void
1388 dpll_unlock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1389 		 struct genl_info *info)
1390 {
1391 	mutex_unlock(&dpll_lock);
1392 }
1393 
1394 int dpll_lock_dumpit(struct netlink_callback *cb)
1395 {
1396 	mutex_lock(&dpll_lock);
1397 
1398 	return 0;
1399 }
1400 
1401 int dpll_unlock_dumpit(struct netlink_callback *cb)
1402 {
1403 	mutex_unlock(&dpll_lock);
1404 
1405 	return 0;
1406 }
1407 
1408 int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1409 		      struct genl_info *info)
1410 {
1411 	int ret;
1412 
1413 	mutex_lock(&dpll_lock);
1414 	if (GENL_REQ_ATTR_CHECK(info, DPLL_A_PIN_ID)) {
1415 		ret = -EINVAL;
1416 		goto unlock_dev;
1417 	}
1418 	info->user_ptr[0] = xa_load(&dpll_pin_xa,
1419 				    nla_get_u32(info->attrs[DPLL_A_PIN_ID]));
1420 	if (!info->user_ptr[0]) {
1421 		NL_SET_ERR_MSG(info->extack, "pin not found");
1422 		ret = -ENODEV;
1423 		goto unlock_dev;
1424 	}
1425 
1426 	return 0;
1427 
1428 unlock_dev:
1429 	mutex_unlock(&dpll_lock);
1430 	return ret;
1431 }
1432 
1433 void dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1434 			struct genl_info *info)
1435 {
1436 	mutex_unlock(&dpll_lock);
1437 }
1438