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