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