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