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