xref: /linux/drivers/dpll/dpll_netlink.c (revision 3f1c07fc21c68bd3bd2df9d2c9441f6485e934d9)
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 
dpll_dump_context(struct netlink_callback * cb)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
dpll_msg_add_dev_handle(struct sk_buff * msg,struct dpll_device * dpll)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
dpll_msg_add_dev_parent_handle(struct sk_buff * msg,u32 id)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 
dpll_pin_available(struct dpll_pin * pin)51 static bool dpll_pin_available(struct dpll_pin *pin)
52 {
53 	struct dpll_pin_ref *par_ref;
54 	unsigned long i;
55 
56 	if (!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED))
57 		return false;
58 	xa_for_each(&pin->parent_refs, i, par_ref)
59 		if (xa_get_mark(&dpll_pin_xa, par_ref->pin->id,
60 				DPLL_REGISTERED))
61 			return true;
62 	xa_for_each(&pin->dpll_refs, i, par_ref)
63 		if (xa_get_mark(&dpll_device_xa, par_ref->dpll->id,
64 				DPLL_REGISTERED))
65 			return true;
66 	return false;
67 }
68 
69 /**
70  * dpll_msg_add_pin_handle - attach pin handle attribute to a given message
71  * @msg: pointer to sk_buff message to attach a pin handle
72  * @pin: pin pointer
73  *
74  * Return:
75  * * 0 - success
76  * * -EMSGSIZE - no space in message to attach pin handle
77  */
dpll_msg_add_pin_handle(struct sk_buff * msg,struct dpll_pin * pin)78 static int dpll_msg_add_pin_handle(struct sk_buff *msg, struct dpll_pin *pin)
79 {
80 	if (!pin)
81 		return 0;
82 	if (nla_put_u32(msg, DPLL_A_PIN_ID, pin->id))
83 		return -EMSGSIZE;
84 	return 0;
85 }
86 
dpll_netdev_pin(const struct net_device * dev)87 static struct dpll_pin *dpll_netdev_pin(const struct net_device *dev)
88 {
89 	return rcu_dereference_rtnl(dev->dpll_pin);
90 }
91 
92 /**
93  * dpll_netdev_pin_handle_size - get size of pin handle attribute of a netdev
94  * @dev: netdev from which to get the pin
95  *
96  * Return: byte size of pin handle attribute, or 0 if @dev has no pin.
97  */
dpll_netdev_pin_handle_size(const struct net_device * dev)98 size_t dpll_netdev_pin_handle_size(const struct net_device *dev)
99 {
100 	return dpll_netdev_pin(dev) ? nla_total_size(4) : 0; /* DPLL_A_PIN_ID */
101 }
102 
dpll_netdev_add_pin_handle(struct sk_buff * msg,const struct net_device * dev)103 int dpll_netdev_add_pin_handle(struct sk_buff *msg,
104 			       const struct net_device *dev)
105 {
106 	return dpll_msg_add_pin_handle(msg, dpll_netdev_pin(dev));
107 }
108 
109 static int
dpll_msg_add_mode(struct sk_buff * msg,struct dpll_device * dpll,struct netlink_ext_ack * extack)110 dpll_msg_add_mode(struct sk_buff *msg, struct dpll_device *dpll,
111 		  struct netlink_ext_ack *extack)
112 {
113 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
114 	enum dpll_mode mode;
115 	int ret;
116 
117 	ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack);
118 	if (ret)
119 		return ret;
120 	if (nla_put_u32(msg, DPLL_A_MODE, mode))
121 		return -EMSGSIZE;
122 
123 	return 0;
124 }
125 
126 static int
dpll_msg_add_mode_supported(struct sk_buff * msg,struct dpll_device * dpll,struct netlink_ext_ack * extack)127 dpll_msg_add_mode_supported(struct sk_buff *msg, struct dpll_device *dpll,
128 			    struct netlink_ext_ack *extack)
129 {
130 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
131 	enum dpll_mode mode;
132 	int ret;
133 
134 	/* No mode change is supported now, so the only supported mode is the
135 	 * one obtained by mode_get().
136 	 */
137 
138 	ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack);
139 	if (ret)
140 		return ret;
141 	if (nla_put_u32(msg, DPLL_A_MODE_SUPPORTED, mode))
142 		return -EMSGSIZE;
143 
144 	return 0;
145 }
146 
147 static int
dpll_msg_add_phase_offset_monitor(struct sk_buff * msg,struct dpll_device * dpll,struct netlink_ext_ack * extack)148 dpll_msg_add_phase_offset_monitor(struct sk_buff *msg, struct dpll_device *dpll,
149 				  struct netlink_ext_ack *extack)
150 {
151 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
152 	enum dpll_feature_state state;
153 	int ret;
154 
155 	if (ops->phase_offset_monitor_set && ops->phase_offset_monitor_get) {
156 		ret = ops->phase_offset_monitor_get(dpll, dpll_priv(dpll),
157 						    &state, extack);
158 		if (ret)
159 			return ret;
160 		if (nla_put_u32(msg, DPLL_A_PHASE_OFFSET_MONITOR, state))
161 			return -EMSGSIZE;
162 	}
163 
164 	return 0;
165 }
166 
167 static int
dpll_msg_add_phase_offset_avg_factor(struct sk_buff * msg,struct dpll_device * dpll,struct netlink_ext_ack * extack)168 dpll_msg_add_phase_offset_avg_factor(struct sk_buff *msg,
169 				     struct dpll_device *dpll,
170 				     struct netlink_ext_ack *extack)
171 {
172 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
173 	u32 factor;
174 	int ret;
175 
176 	if (ops->phase_offset_avg_factor_get) {
177 		ret = ops->phase_offset_avg_factor_get(dpll, dpll_priv(dpll),
178 						       &factor, extack);
179 		if (ret)
180 			return ret;
181 		if (nla_put_u32(msg, DPLL_A_PHASE_OFFSET_AVG_FACTOR, factor))
182 			return -EMSGSIZE;
183 	}
184 
185 	return 0;
186 }
187 
188 static int
dpll_msg_add_lock_status(struct sk_buff * msg,struct dpll_device * dpll,struct netlink_ext_ack * extack)189 dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll,
190 			 struct netlink_ext_ack *extack)
191 {
192 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
193 	enum dpll_lock_status_error status_error = 0;
194 	enum dpll_lock_status status;
195 	int ret;
196 
197 	ret = ops->lock_status_get(dpll, dpll_priv(dpll), &status,
198 				   &status_error, extack);
199 	if (ret)
200 		return ret;
201 	if (nla_put_u32(msg, DPLL_A_LOCK_STATUS, status))
202 		return -EMSGSIZE;
203 	if (status_error &&
204 	    (status == DPLL_LOCK_STATUS_UNLOCKED ||
205 	     status == DPLL_LOCK_STATUS_HOLDOVER) &&
206 	    nla_put_u32(msg, DPLL_A_LOCK_STATUS_ERROR, status_error))
207 		return -EMSGSIZE;
208 
209 	return 0;
210 }
211 
212 static int
dpll_msg_add_temp(struct sk_buff * msg,struct dpll_device * dpll,struct netlink_ext_ack * extack)213 dpll_msg_add_temp(struct sk_buff *msg, struct dpll_device *dpll,
214 		  struct netlink_ext_ack *extack)
215 {
216 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
217 	s32 temp;
218 	int ret;
219 
220 	if (!ops->temp_get)
221 		return 0;
222 	ret = ops->temp_get(dpll, dpll_priv(dpll), &temp, extack);
223 	if (ret)
224 		return ret;
225 	if (nla_put_s32(msg, DPLL_A_TEMP, temp))
226 		return -EMSGSIZE;
227 
228 	return 0;
229 }
230 
231 static int
dpll_msg_add_clock_quality_level(struct sk_buff * msg,struct dpll_device * dpll,struct netlink_ext_ack * extack)232 dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll,
233 				 struct netlink_ext_ack *extack)
234 {
235 	DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1) = { 0 };
236 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
237 	enum dpll_clock_quality_level ql;
238 	int ret;
239 
240 	if (!ops->clock_quality_level_get)
241 		return 0;
242 	ret = ops->clock_quality_level_get(dpll, dpll_priv(dpll), qls, extack);
243 	if (ret)
244 		return ret;
245 	for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1)
246 		if (nla_put_u32(msg, DPLL_A_CLOCK_QUALITY_LEVEL, ql))
247 			return -EMSGSIZE;
248 
249 	return 0;
250 }
251 
252 static int
dpll_msg_add_pin_prio(struct sk_buff * msg,struct dpll_pin * pin,struct dpll_pin_ref * ref,struct netlink_ext_ack * extack)253 dpll_msg_add_pin_prio(struct sk_buff *msg, struct dpll_pin *pin,
254 		      struct dpll_pin_ref *ref,
255 		      struct netlink_ext_ack *extack)
256 {
257 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
258 	struct dpll_device *dpll = ref->dpll;
259 	u32 prio;
260 	int ret;
261 
262 	if (!ops->prio_get)
263 		return 0;
264 	ret = ops->prio_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
265 			    dpll_priv(dpll), &prio, extack);
266 	if (ret)
267 		return ret;
268 	if (nla_put_u32(msg, DPLL_A_PIN_PRIO, prio))
269 		return -EMSGSIZE;
270 
271 	return 0;
272 }
273 
274 static int
dpll_msg_add_pin_on_dpll_state(struct sk_buff * msg,struct dpll_pin * pin,struct dpll_pin_ref * ref,struct netlink_ext_ack * extack)275 dpll_msg_add_pin_on_dpll_state(struct sk_buff *msg, struct dpll_pin *pin,
276 			       struct dpll_pin_ref *ref,
277 			       struct netlink_ext_ack *extack)
278 {
279 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
280 	struct dpll_device *dpll = ref->dpll;
281 	enum dpll_pin_state state;
282 	int ret;
283 
284 	if (!ops->state_on_dpll_get)
285 		return 0;
286 	ret = ops->state_on_dpll_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
287 				     dpll, dpll_priv(dpll), &state, extack);
288 	if (ret)
289 		return ret;
290 	if (nla_put_u32(msg, DPLL_A_PIN_STATE, state))
291 		return -EMSGSIZE;
292 
293 	return 0;
294 }
295 
296 static int
dpll_msg_add_pin_direction(struct sk_buff * msg,struct dpll_pin * pin,struct dpll_pin_ref * ref,struct netlink_ext_ack * extack)297 dpll_msg_add_pin_direction(struct sk_buff *msg, struct dpll_pin *pin,
298 			   struct dpll_pin_ref *ref,
299 			   struct netlink_ext_ack *extack)
300 {
301 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
302 	struct dpll_device *dpll = ref->dpll;
303 	enum dpll_pin_direction direction;
304 	int ret;
305 
306 	ret = ops->direction_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
307 				 dpll_priv(dpll), &direction, extack);
308 	if (ret)
309 		return ret;
310 	if (nla_put_u32(msg, DPLL_A_PIN_DIRECTION, direction))
311 		return -EMSGSIZE;
312 
313 	return 0;
314 }
315 
316 static int
dpll_msg_add_pin_phase_adjust(struct sk_buff * msg,struct dpll_pin * pin,struct dpll_pin_ref * ref,struct netlink_ext_ack * extack)317 dpll_msg_add_pin_phase_adjust(struct sk_buff *msg, struct dpll_pin *pin,
318 			      struct dpll_pin_ref *ref,
319 			      struct netlink_ext_ack *extack)
320 {
321 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
322 	struct dpll_device *dpll = ref->dpll;
323 	s32 phase_adjust;
324 	int ret;
325 
326 	if (!ops->phase_adjust_get)
327 		return 0;
328 	ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
329 				    dpll, dpll_priv(dpll),
330 				    &phase_adjust, extack);
331 	if (ret)
332 		return ret;
333 	if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST, phase_adjust))
334 		return -EMSGSIZE;
335 
336 	return 0;
337 }
338 
339 static int
dpll_msg_add_phase_offset(struct sk_buff * msg,struct dpll_pin * pin,struct dpll_pin_ref * ref,struct netlink_ext_ack * extack)340 dpll_msg_add_phase_offset(struct sk_buff *msg, struct dpll_pin *pin,
341 			  struct dpll_pin_ref *ref,
342 			  struct netlink_ext_ack *extack)
343 {
344 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
345 	struct dpll_device *dpll = ref->dpll;
346 	s64 phase_offset;
347 	int ret;
348 
349 	if (!ops->phase_offset_get)
350 		return 0;
351 	ret = ops->phase_offset_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
352 				    dpll, dpll_priv(dpll), &phase_offset,
353 				    extack);
354 	if (ret)
355 		return ret;
356 	if (nla_put_64bit(msg, DPLL_A_PIN_PHASE_OFFSET, sizeof(phase_offset),
357 			  &phase_offset, DPLL_A_PIN_PAD))
358 		return -EMSGSIZE;
359 
360 	return 0;
361 }
362 
dpll_msg_add_ffo(struct sk_buff * msg,struct dpll_pin * pin,struct dpll_pin_ref * ref,struct netlink_ext_ack * extack)363 static int dpll_msg_add_ffo(struct sk_buff *msg, struct dpll_pin *pin,
364 			    struct dpll_pin_ref *ref,
365 			    struct netlink_ext_ack *extack)
366 {
367 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
368 	struct dpll_device *dpll = ref->dpll;
369 	s64 ffo;
370 	int ret;
371 
372 	if (!ops->ffo_get)
373 		return 0;
374 	ret = ops->ffo_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
375 			   dpll, dpll_priv(dpll), &ffo, extack);
376 	if (ret) {
377 		if (ret == -ENODATA)
378 			return 0;
379 		return ret;
380 	}
381 	return nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET, ffo);
382 }
383 
384 static int
dpll_msg_add_pin_freq(struct sk_buff * msg,struct dpll_pin * pin,struct dpll_pin_ref * ref,struct netlink_ext_ack * extack)385 dpll_msg_add_pin_freq(struct sk_buff *msg, struct dpll_pin *pin,
386 		      struct dpll_pin_ref *ref, struct netlink_ext_ack *extack)
387 {
388 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
389 	struct dpll_device *dpll = ref->dpll;
390 	struct nlattr *nest;
391 	int fs, ret;
392 	u64 freq;
393 
394 	if (!ops->frequency_get)
395 		return 0;
396 	ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
397 				 dpll_priv(dpll), &freq, extack);
398 	if (ret)
399 		return ret;
400 	if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY, sizeof(freq), &freq,
401 			  DPLL_A_PIN_PAD))
402 		return -EMSGSIZE;
403 	for (fs = 0; fs < pin->prop.freq_supported_num; fs++) {
404 		nest = nla_nest_start(msg, DPLL_A_PIN_FREQUENCY_SUPPORTED);
405 		if (!nest)
406 			return -EMSGSIZE;
407 		freq = pin->prop.freq_supported[fs].min;
408 		if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MIN, sizeof(freq),
409 				  &freq, DPLL_A_PIN_PAD)) {
410 			nla_nest_cancel(msg, nest);
411 			return -EMSGSIZE;
412 		}
413 		freq = pin->prop.freq_supported[fs].max;
414 		if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MAX, sizeof(freq),
415 				  &freq, DPLL_A_PIN_PAD)) {
416 			nla_nest_cancel(msg, nest);
417 			return -EMSGSIZE;
418 		}
419 		nla_nest_end(msg, nest);
420 	}
421 
422 	return 0;
423 }
424 
425 static int
dpll_msg_add_pin_esync(struct sk_buff * msg,struct dpll_pin * pin,struct dpll_pin_ref * ref,struct netlink_ext_ack * extack)426 dpll_msg_add_pin_esync(struct sk_buff *msg, struct dpll_pin *pin,
427 		       struct dpll_pin_ref *ref, struct netlink_ext_ack *extack)
428 {
429 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
430 	struct dpll_device *dpll = ref->dpll;
431 	struct dpll_pin_esync esync;
432 	struct nlattr *nest;
433 	int ret, i;
434 
435 	if (!ops->esync_get)
436 		return 0;
437 	ret = ops->esync_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
438 			     dpll_priv(dpll), &esync, extack);
439 	if (ret == -EOPNOTSUPP)
440 		return 0;
441 	else if (ret)
442 		return ret;
443 	if (nla_put_64bit(msg, DPLL_A_PIN_ESYNC_FREQUENCY, sizeof(esync.freq),
444 			  &esync.freq, DPLL_A_PIN_PAD))
445 		return -EMSGSIZE;
446 	if (nla_put_u32(msg, DPLL_A_PIN_ESYNC_PULSE, esync.pulse))
447 		return -EMSGSIZE;
448 	for (i = 0; i < esync.range_num; i++) {
449 		nest = nla_nest_start(msg,
450 				      DPLL_A_PIN_ESYNC_FREQUENCY_SUPPORTED);
451 		if (!nest)
452 			return -EMSGSIZE;
453 		if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MIN,
454 				  sizeof(esync.range[i].min),
455 				  &esync.range[i].min, DPLL_A_PIN_PAD))
456 			goto nest_cancel;
457 		if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MAX,
458 				  sizeof(esync.range[i].max),
459 				  &esync.range[i].max, DPLL_A_PIN_PAD))
460 			goto nest_cancel;
461 		nla_nest_end(msg, nest);
462 	}
463 	return 0;
464 
465 nest_cancel:
466 	nla_nest_cancel(msg, nest);
467 	return -EMSGSIZE;
468 }
469 
470 static int
dpll_msg_add_pin_ref_sync(struct sk_buff * msg,struct dpll_pin * pin,struct dpll_pin_ref * ref,struct netlink_ext_ack * extack)471 dpll_msg_add_pin_ref_sync(struct sk_buff *msg, struct dpll_pin *pin,
472 			  struct dpll_pin_ref *ref,
473 			  struct netlink_ext_ack *extack)
474 {
475 	const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
476 	struct dpll_device *dpll = ref->dpll;
477 	void *pin_priv, *ref_sync_pin_priv;
478 	struct dpll_pin *ref_sync_pin;
479 	enum dpll_pin_state state;
480 	struct nlattr *nest;
481 	unsigned long index;
482 	int ret;
483 
484 	pin_priv = dpll_pin_on_dpll_priv(dpll, pin);
485 	xa_for_each(&pin->ref_sync_pins, index, ref_sync_pin) {
486 		if (!dpll_pin_available(ref_sync_pin))
487 			continue;
488 		ref_sync_pin_priv = dpll_pin_on_dpll_priv(dpll, ref_sync_pin);
489 		if (WARN_ON(!ops->ref_sync_get))
490 			return -EOPNOTSUPP;
491 		ret = ops->ref_sync_get(pin, pin_priv, ref_sync_pin,
492 					ref_sync_pin_priv, &state, extack);
493 		if (ret)
494 			return ret;
495 		nest = nla_nest_start(msg, DPLL_A_PIN_REFERENCE_SYNC);
496 		if (!nest)
497 			return -EMSGSIZE;
498 		if (nla_put_s32(msg, DPLL_A_PIN_ID, ref_sync_pin->id))
499 			goto nest_cancel;
500 		if (nla_put_s32(msg, DPLL_A_PIN_STATE, state))
501 			goto nest_cancel;
502 		nla_nest_end(msg, nest);
503 	}
504 	return 0;
505 
506 nest_cancel:
507 	nla_nest_cancel(msg, nest);
508 	return -EMSGSIZE;
509 }
510 
dpll_pin_is_freq_supported(struct dpll_pin * pin,u32 freq)511 static bool dpll_pin_is_freq_supported(struct dpll_pin *pin, u32 freq)
512 {
513 	int fs;
514 
515 	for (fs = 0; fs < pin->prop.freq_supported_num; fs++)
516 		if (freq >= pin->prop.freq_supported[fs].min &&
517 		    freq <= pin->prop.freq_supported[fs].max)
518 			return true;
519 	return false;
520 }
521 
522 static int
dpll_msg_add_pin_parents(struct sk_buff * msg,struct dpll_pin * pin,struct dpll_pin_ref * dpll_ref,struct netlink_ext_ack * extack)523 dpll_msg_add_pin_parents(struct sk_buff *msg, struct dpll_pin *pin,
524 			 struct dpll_pin_ref *dpll_ref,
525 			 struct netlink_ext_ack *extack)
526 {
527 	enum dpll_pin_state state;
528 	struct dpll_pin_ref *ref;
529 	struct dpll_pin *ppin;
530 	struct nlattr *nest;
531 	unsigned long index;
532 	int ret;
533 
534 	xa_for_each(&pin->parent_refs, index, ref) {
535 		const struct dpll_pin_ops *ops = dpll_pin_ops(ref);
536 		void *parent_priv;
537 
538 		ppin = ref->pin;
539 		parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, ppin);
540 		ret = ops->state_on_pin_get(pin,
541 					    dpll_pin_on_pin_priv(ppin, pin),
542 					    ppin, parent_priv, &state, extack);
543 		if (ret)
544 			return ret;
545 		nest = nla_nest_start(msg, DPLL_A_PIN_PARENT_PIN);
546 		if (!nest)
547 			return -EMSGSIZE;
548 		ret = dpll_msg_add_dev_parent_handle(msg, ppin->id);
549 		if (ret)
550 			goto nest_cancel;
551 		if (nla_put_u32(msg, DPLL_A_PIN_STATE, state)) {
552 			ret = -EMSGSIZE;
553 			goto nest_cancel;
554 		}
555 		nla_nest_end(msg, nest);
556 	}
557 
558 	return 0;
559 
560 nest_cancel:
561 	nla_nest_cancel(msg, nest);
562 	return ret;
563 }
564 
565 static int
dpll_msg_add_pin_dplls(struct sk_buff * msg,struct dpll_pin * pin,struct netlink_ext_ack * extack)566 dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin,
567 		       struct netlink_ext_ack *extack)
568 {
569 	struct dpll_pin_ref *ref;
570 	struct nlattr *attr;
571 	unsigned long index;
572 	int ret;
573 
574 	xa_for_each(&pin->dpll_refs, index, ref) {
575 		attr = nla_nest_start(msg, DPLL_A_PIN_PARENT_DEVICE);
576 		if (!attr)
577 			return -EMSGSIZE;
578 		ret = dpll_msg_add_dev_parent_handle(msg, ref->dpll->id);
579 		if (ret)
580 			goto nest_cancel;
581 		ret = dpll_msg_add_pin_on_dpll_state(msg, pin, ref, extack);
582 		if (ret)
583 			goto nest_cancel;
584 		ret = dpll_msg_add_pin_prio(msg, pin, ref, extack);
585 		if (ret)
586 			goto nest_cancel;
587 		ret = dpll_msg_add_pin_direction(msg, pin, ref, extack);
588 		if (ret)
589 			goto nest_cancel;
590 		ret = dpll_msg_add_phase_offset(msg, pin, ref, extack);
591 		if (ret)
592 			goto nest_cancel;
593 		nla_nest_end(msg, attr);
594 	}
595 
596 	return 0;
597 
598 nest_cancel:
599 	nla_nest_end(msg, attr);
600 	return ret;
601 }
602 
603 static int
dpll_cmd_pin_get_one(struct sk_buff * msg,struct dpll_pin * pin,struct netlink_ext_ack * extack)604 dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
605 		     struct netlink_ext_ack *extack)
606 {
607 	const struct dpll_pin_properties *prop = &pin->prop;
608 	struct dpll_pin_ref *ref;
609 	int ret;
610 
611 	ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
612 	ASSERT_NOT_NULL(ref);
613 
614 	ret = dpll_msg_add_pin_handle(msg, pin);
615 	if (ret)
616 		return ret;
617 	if (nla_put_string(msg, DPLL_A_PIN_MODULE_NAME,
618 			   module_name(pin->module)))
619 		return -EMSGSIZE;
620 	if (nla_put_64bit(msg, DPLL_A_PIN_CLOCK_ID, sizeof(pin->clock_id),
621 			  &pin->clock_id, DPLL_A_PIN_PAD))
622 		return -EMSGSIZE;
623 	if (prop->board_label &&
624 	    nla_put_string(msg, DPLL_A_PIN_BOARD_LABEL, prop->board_label))
625 		return -EMSGSIZE;
626 	if (prop->panel_label &&
627 	    nla_put_string(msg, DPLL_A_PIN_PANEL_LABEL, prop->panel_label))
628 		return -EMSGSIZE;
629 	if (prop->package_label &&
630 	    nla_put_string(msg, DPLL_A_PIN_PACKAGE_LABEL,
631 			   prop->package_label))
632 		return -EMSGSIZE;
633 	if (nla_put_u32(msg, DPLL_A_PIN_TYPE, prop->type))
634 		return -EMSGSIZE;
635 	if (nla_put_u32(msg, DPLL_A_PIN_CAPABILITIES, prop->capabilities))
636 		return -EMSGSIZE;
637 	ret = dpll_msg_add_pin_freq(msg, pin, ref, extack);
638 	if (ret)
639 		return ret;
640 	if (prop->phase_gran &&
641 	    nla_put_u32(msg, DPLL_A_PIN_PHASE_ADJUST_GRAN,
642 			prop->phase_gran))
643 		return -EMSGSIZE;
644 	if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MIN,
645 			prop->phase_range.min))
646 		return -EMSGSIZE;
647 	if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MAX,
648 			prop->phase_range.max))
649 		return -EMSGSIZE;
650 	ret = dpll_msg_add_pin_phase_adjust(msg, pin, ref, extack);
651 	if (ret)
652 		return ret;
653 	ret = dpll_msg_add_ffo(msg, pin, ref, extack);
654 	if (ret)
655 		return ret;
656 	ret = dpll_msg_add_pin_esync(msg, pin, ref, extack);
657 	if (ret)
658 		return ret;
659 	if (!xa_empty(&pin->ref_sync_pins))
660 		ret = dpll_msg_add_pin_ref_sync(msg, pin, ref, extack);
661 	if (ret)
662 		return ret;
663 	if (xa_empty(&pin->parent_refs))
664 		ret = dpll_msg_add_pin_dplls(msg, pin, extack);
665 	else
666 		ret = dpll_msg_add_pin_parents(msg, pin, ref, extack);
667 
668 	return ret;
669 }
670 
671 static int
dpll_device_get_one(struct dpll_device * dpll,struct sk_buff * msg,struct netlink_ext_ack * extack)672 dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
673 		    struct netlink_ext_ack *extack)
674 {
675 	int ret;
676 
677 	ret = dpll_msg_add_dev_handle(msg, dpll);
678 	if (ret)
679 		return ret;
680 	if (nla_put_string(msg, DPLL_A_MODULE_NAME, module_name(dpll->module)))
681 		return -EMSGSIZE;
682 	if (nla_put_64bit(msg, DPLL_A_CLOCK_ID, sizeof(dpll->clock_id),
683 			  &dpll->clock_id, DPLL_A_PAD))
684 		return -EMSGSIZE;
685 	ret = dpll_msg_add_temp(msg, dpll, extack);
686 	if (ret)
687 		return ret;
688 	ret = dpll_msg_add_lock_status(msg, dpll, extack);
689 	if (ret)
690 		return ret;
691 	ret = dpll_msg_add_clock_quality_level(msg, dpll, extack);
692 	if (ret)
693 		return ret;
694 	ret = dpll_msg_add_mode(msg, dpll, extack);
695 	if (ret)
696 		return ret;
697 	ret = dpll_msg_add_mode_supported(msg, dpll, extack);
698 	if (ret)
699 		return ret;
700 	if (nla_put_u32(msg, DPLL_A_TYPE, dpll->type))
701 		return -EMSGSIZE;
702 	ret = dpll_msg_add_phase_offset_monitor(msg, dpll, extack);
703 	if (ret)
704 		return ret;
705 	ret = dpll_msg_add_phase_offset_avg_factor(msg, dpll, extack);
706 	if (ret)
707 		return ret;
708 
709 	return 0;
710 }
711 
712 static int
dpll_device_event_send(enum dpll_cmd event,struct dpll_device * dpll)713 dpll_device_event_send(enum dpll_cmd event, struct dpll_device *dpll)
714 {
715 	struct sk_buff *msg;
716 	int ret = -ENOMEM;
717 	void *hdr;
718 
719 	if (WARN_ON(!xa_get_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED)))
720 		return -ENODEV;
721 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
722 	if (!msg)
723 		return -ENOMEM;
724 	hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
725 	if (!hdr)
726 		goto err_free_msg;
727 	ret = dpll_device_get_one(dpll, msg, NULL);
728 	if (ret)
729 		goto err_cancel_msg;
730 	genlmsg_end(msg, hdr);
731 	genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
732 
733 	return 0;
734 
735 err_cancel_msg:
736 	genlmsg_cancel(msg, hdr);
737 err_free_msg:
738 	nlmsg_free(msg);
739 
740 	return ret;
741 }
742 
dpll_device_create_ntf(struct dpll_device * dpll)743 int dpll_device_create_ntf(struct dpll_device *dpll)
744 {
745 	return dpll_device_event_send(DPLL_CMD_DEVICE_CREATE_NTF, dpll);
746 }
747 
dpll_device_delete_ntf(struct dpll_device * dpll)748 int dpll_device_delete_ntf(struct dpll_device *dpll)
749 {
750 	return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF, dpll);
751 }
752 
753 static int
__dpll_device_change_ntf(struct dpll_device * dpll)754 __dpll_device_change_ntf(struct dpll_device *dpll)
755 {
756 	return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll);
757 }
758 
759 /**
760  * dpll_device_change_ntf - notify that the dpll device has been changed
761  * @dpll: registered dpll pointer
762  *
763  * Context: acquires and holds a dpll_lock.
764  * Return: 0 if succeeds, error code otherwise.
765  */
dpll_device_change_ntf(struct dpll_device * dpll)766 int dpll_device_change_ntf(struct dpll_device *dpll)
767 {
768 	int ret;
769 
770 	mutex_lock(&dpll_lock);
771 	ret = __dpll_device_change_ntf(dpll);
772 	mutex_unlock(&dpll_lock);
773 
774 	return ret;
775 }
776 EXPORT_SYMBOL_GPL(dpll_device_change_ntf);
777 
778 static int
dpll_pin_event_send(enum dpll_cmd event,struct dpll_pin * pin)779 dpll_pin_event_send(enum dpll_cmd event, struct dpll_pin *pin)
780 {
781 	struct sk_buff *msg;
782 	int ret = -ENOMEM;
783 	void *hdr;
784 
785 	if (!dpll_pin_available(pin))
786 		return -ENODEV;
787 
788 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
789 	if (!msg)
790 		return -ENOMEM;
791 
792 	hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
793 	if (!hdr)
794 		goto err_free_msg;
795 	ret = dpll_cmd_pin_get_one(msg, pin, NULL);
796 	if (ret)
797 		goto err_cancel_msg;
798 	genlmsg_end(msg, hdr);
799 	genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
800 
801 	return 0;
802 
803 err_cancel_msg:
804 	genlmsg_cancel(msg, hdr);
805 err_free_msg:
806 	nlmsg_free(msg);
807 
808 	return ret;
809 }
810 
dpll_pin_create_ntf(struct dpll_pin * pin)811 int dpll_pin_create_ntf(struct dpll_pin *pin)
812 {
813 	return dpll_pin_event_send(DPLL_CMD_PIN_CREATE_NTF, pin);
814 }
815 
dpll_pin_delete_ntf(struct dpll_pin * pin)816 int dpll_pin_delete_ntf(struct dpll_pin *pin)
817 {
818 	return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin);
819 }
820 
__dpll_pin_change_ntf(struct dpll_pin * pin)821 int __dpll_pin_change_ntf(struct dpll_pin *pin)
822 {
823 	return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin);
824 }
825 
826 /**
827  * dpll_pin_change_ntf - notify that the pin has been changed
828  * @pin: registered pin pointer
829  *
830  * Context: acquires and holds a dpll_lock.
831  * Return: 0 if succeeds, error code otherwise.
832  */
dpll_pin_change_ntf(struct dpll_pin * pin)833 int dpll_pin_change_ntf(struct dpll_pin *pin)
834 {
835 	int ret;
836 
837 	mutex_lock(&dpll_lock);
838 	ret = __dpll_pin_change_ntf(pin);
839 	mutex_unlock(&dpll_lock);
840 
841 	return ret;
842 }
843 EXPORT_SYMBOL_GPL(dpll_pin_change_ntf);
844 
845 static int
dpll_phase_offset_monitor_set(struct dpll_device * dpll,struct nlattr * a,struct netlink_ext_ack * extack)846 dpll_phase_offset_monitor_set(struct dpll_device *dpll, struct nlattr *a,
847 			      struct netlink_ext_ack *extack)
848 {
849 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
850 	enum dpll_feature_state state = nla_get_u32(a), old_state;
851 	int ret;
852 
853 	if (!(ops->phase_offset_monitor_set && ops->phase_offset_monitor_get)) {
854 		NL_SET_ERR_MSG_ATTR(extack, a, "dpll device not capable of phase offset monitor");
855 		return -EOPNOTSUPP;
856 	}
857 	ret = ops->phase_offset_monitor_get(dpll, dpll_priv(dpll), &old_state,
858 					    extack);
859 	if (ret) {
860 		NL_SET_ERR_MSG(extack, "unable to get current state of phase offset monitor");
861 		return ret;
862 	}
863 	if (state == old_state)
864 		return 0;
865 
866 	return ops->phase_offset_monitor_set(dpll, dpll_priv(dpll), state,
867 					     extack);
868 }
869 
870 static int
dpll_phase_offset_avg_factor_set(struct dpll_device * dpll,struct nlattr * a,struct netlink_ext_ack * extack)871 dpll_phase_offset_avg_factor_set(struct dpll_device *dpll, struct nlattr *a,
872 				 struct netlink_ext_ack *extack)
873 {
874 	const struct dpll_device_ops *ops = dpll_device_ops(dpll);
875 	u32 factor = nla_get_u32(a);
876 
877 	if (!ops->phase_offset_avg_factor_set) {
878 		NL_SET_ERR_MSG_ATTR(extack, a,
879 				    "device not capable of changing phase offset average factor");
880 		return -EOPNOTSUPP;
881 	}
882 
883 	return ops->phase_offset_avg_factor_set(dpll, dpll_priv(dpll), factor,
884 						extack);
885 }
886 
887 static int
dpll_pin_freq_set(struct dpll_pin * pin,struct nlattr * a,struct netlink_ext_ack * extack)888 dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
889 		  struct netlink_ext_ack *extack)
890 {
891 	u64 freq = nla_get_u64(a), old_freq;
892 	struct dpll_pin_ref *ref, *failed;
893 	const struct dpll_pin_ops *ops;
894 	struct dpll_device *dpll;
895 	unsigned long i;
896 	int ret;
897 
898 	if (!dpll_pin_is_freq_supported(pin, freq)) {
899 		NL_SET_ERR_MSG_ATTR(extack, a, "frequency is not supported by the device");
900 		return -EINVAL;
901 	}
902 
903 	xa_for_each(&pin->dpll_refs, i, ref) {
904 		ops = dpll_pin_ops(ref);
905 		if (!ops->frequency_set || !ops->frequency_get) {
906 			NL_SET_ERR_MSG(extack, "frequency set not supported by the device");
907 			return -EOPNOTSUPP;
908 		}
909 	}
910 	ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
911 	ops = dpll_pin_ops(ref);
912 	dpll = ref->dpll;
913 	ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
914 				 dpll_priv(dpll), &old_freq, extack);
915 	if (ret) {
916 		NL_SET_ERR_MSG(extack, "unable to get old frequency value");
917 		return ret;
918 	}
919 	if (freq == old_freq)
920 		return 0;
921 
922 	xa_for_each(&pin->dpll_refs, i, ref) {
923 		ops = dpll_pin_ops(ref);
924 		dpll = ref->dpll;
925 		ret = ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
926 					 dpll, dpll_priv(dpll), freq, extack);
927 		if (ret) {
928 			failed = ref;
929 			NL_SET_ERR_MSG_FMT(extack, "frequency set failed for dpll_id:%u",
930 					   dpll->id);
931 			goto rollback;
932 		}
933 	}
934 	__dpll_pin_change_ntf(pin);
935 
936 	return 0;
937 
938 rollback:
939 	xa_for_each(&pin->dpll_refs, i, ref) {
940 		if (ref == failed)
941 			break;
942 		ops = dpll_pin_ops(ref);
943 		dpll = ref->dpll;
944 		if (ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
945 				       dpll, dpll_priv(dpll), old_freq, extack))
946 			NL_SET_ERR_MSG(extack, "set frequency rollback failed");
947 	}
948 	return ret;
949 }
950 
951 static int
dpll_pin_esync_set(struct dpll_pin * pin,struct nlattr * a,struct netlink_ext_ack * extack)952 dpll_pin_esync_set(struct dpll_pin *pin, struct nlattr *a,
953 		   struct netlink_ext_ack *extack)
954 {
955 	struct dpll_pin_ref *ref, *failed;
956 	const struct dpll_pin_ops *ops;
957 	struct dpll_pin_esync esync;
958 	u64 freq = nla_get_u64(a);
959 	struct dpll_device *dpll;
960 	bool supported = false;
961 	unsigned long i;
962 	int ret;
963 
964 	xa_for_each(&pin->dpll_refs, i, ref) {
965 		ops = dpll_pin_ops(ref);
966 		if (!ops->esync_set || !ops->esync_get) {
967 			NL_SET_ERR_MSG(extack,
968 				       "embedded sync feature is not supported by this device");
969 			return -EOPNOTSUPP;
970 		}
971 	}
972 	ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
973 	ops = dpll_pin_ops(ref);
974 	dpll = ref->dpll;
975 	ret = ops->esync_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
976 			     dpll_priv(dpll), &esync, extack);
977 	if (ret) {
978 		NL_SET_ERR_MSG(extack, "unable to get current embedded sync frequency value");
979 		return ret;
980 	}
981 	if (freq == esync.freq)
982 		return 0;
983 	for (i = 0; i < esync.range_num; i++)
984 		if (freq <= esync.range[i].max && freq >= esync.range[i].min)
985 			supported = true;
986 	if (!supported) {
987 		NL_SET_ERR_MSG_ATTR(extack, a,
988 				    "requested embedded sync frequency value is not supported by this device");
989 		return -EINVAL;
990 	}
991 
992 	xa_for_each(&pin->dpll_refs, i, ref) {
993 		void *pin_dpll_priv;
994 
995 		ops = dpll_pin_ops(ref);
996 		dpll = ref->dpll;
997 		pin_dpll_priv = dpll_pin_on_dpll_priv(dpll, pin);
998 		ret = ops->esync_set(pin, pin_dpll_priv, dpll, dpll_priv(dpll),
999 				      freq, extack);
1000 		if (ret) {
1001 			failed = ref;
1002 			NL_SET_ERR_MSG_FMT(extack,
1003 					   "embedded sync frequency set failed for dpll_id: %u",
1004 					   dpll->id);
1005 			goto rollback;
1006 		}
1007 	}
1008 	__dpll_pin_change_ntf(pin);
1009 
1010 	return 0;
1011 
1012 rollback:
1013 	xa_for_each(&pin->dpll_refs, i, ref) {
1014 		void *pin_dpll_priv;
1015 
1016 		if (ref == failed)
1017 			break;
1018 		ops = dpll_pin_ops(ref);
1019 		dpll = ref->dpll;
1020 		pin_dpll_priv = dpll_pin_on_dpll_priv(dpll, pin);
1021 		if (ops->esync_set(pin, pin_dpll_priv, dpll, dpll_priv(dpll),
1022 				   esync.freq, extack))
1023 			NL_SET_ERR_MSG(extack, "set embedded sync frequency rollback failed");
1024 	}
1025 	return ret;
1026 }
1027 
1028 static int
dpll_pin_ref_sync_state_set(struct dpll_pin * pin,unsigned long ref_sync_pin_idx,const enum dpll_pin_state state,struct netlink_ext_ack * extack)1029 dpll_pin_ref_sync_state_set(struct dpll_pin *pin,
1030 			    unsigned long ref_sync_pin_idx,
1031 			    const enum dpll_pin_state state,
1032 			    struct netlink_ext_ack *extack)
1033 
1034 {
1035 	struct dpll_pin_ref *ref, *failed;
1036 	const struct dpll_pin_ops *ops;
1037 	enum dpll_pin_state old_state;
1038 	struct dpll_pin *ref_sync_pin;
1039 	struct dpll_device *dpll;
1040 	unsigned long i;
1041 	int ret;
1042 
1043 	ref_sync_pin = xa_find(&pin->ref_sync_pins, &ref_sync_pin_idx,
1044 			       ULONG_MAX, XA_PRESENT);
1045 	if (!ref_sync_pin) {
1046 		NL_SET_ERR_MSG(extack, "reference sync pin not found");
1047 		return -EINVAL;
1048 	}
1049 	if (!dpll_pin_available(ref_sync_pin)) {
1050 		NL_SET_ERR_MSG(extack, "reference sync pin not available");
1051 		return -EINVAL;
1052 	}
1053 	ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
1054 	ASSERT_NOT_NULL(ref);
1055 	ops = dpll_pin_ops(ref);
1056 	if (!ops->ref_sync_set || !ops->ref_sync_get) {
1057 		NL_SET_ERR_MSG(extack, "reference sync not supported by this pin");
1058 		return -EOPNOTSUPP;
1059 	}
1060 	dpll = ref->dpll;
1061 	ret = ops->ref_sync_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
1062 				ref_sync_pin,
1063 				dpll_pin_on_dpll_priv(dpll, ref_sync_pin),
1064 				&old_state, extack);
1065 	if (ret) {
1066 		NL_SET_ERR_MSG(extack, "unable to get old reference sync state");
1067 		return ret;
1068 	}
1069 	if (state == old_state)
1070 		return 0;
1071 	xa_for_each(&pin->dpll_refs, i, ref) {
1072 		ops = dpll_pin_ops(ref);
1073 		dpll = ref->dpll;
1074 		ret = ops->ref_sync_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
1075 					ref_sync_pin,
1076 					dpll_pin_on_dpll_priv(dpll,
1077 							      ref_sync_pin),
1078 					state, extack);
1079 		if (ret) {
1080 			failed = ref;
1081 			NL_SET_ERR_MSG_FMT(extack, "reference sync set failed for dpll_id:%u",
1082 					   dpll->id);
1083 			goto rollback;
1084 		}
1085 	}
1086 	__dpll_pin_change_ntf(pin);
1087 
1088 	return 0;
1089 
1090 rollback:
1091 	xa_for_each(&pin->dpll_refs, i, ref) {
1092 		if (ref == failed)
1093 			break;
1094 		ops = dpll_pin_ops(ref);
1095 		dpll = ref->dpll;
1096 		if (ops->ref_sync_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
1097 				      ref_sync_pin,
1098 				      dpll_pin_on_dpll_priv(dpll, ref_sync_pin),
1099 				      old_state, extack))
1100 			NL_SET_ERR_MSG(extack, "set reference sync rollback failed");
1101 	}
1102 	return ret;
1103 }
1104 
1105 static int
dpll_pin_ref_sync_set(struct dpll_pin * pin,struct nlattr * nest,struct netlink_ext_ack * extack)1106 dpll_pin_ref_sync_set(struct dpll_pin *pin, struct nlattr *nest,
1107 		      struct netlink_ext_ack *extack)
1108 {
1109 	struct nlattr *tb[DPLL_A_PIN_MAX + 1];
1110 	enum dpll_pin_state state;
1111 	u32 sync_pin_id;
1112 
1113 	nla_parse_nested(tb, DPLL_A_PIN_MAX, nest,
1114 			 dpll_reference_sync_nl_policy, extack);
1115 	if (!tb[DPLL_A_PIN_ID]) {
1116 		NL_SET_ERR_MSG(extack, "sync pin id expected");
1117 		return -EINVAL;
1118 	}
1119 	sync_pin_id = nla_get_u32(tb[DPLL_A_PIN_ID]);
1120 
1121 	if (!tb[DPLL_A_PIN_STATE]) {
1122 		NL_SET_ERR_MSG(extack, "sync pin state expected");
1123 		return -EINVAL;
1124 	}
1125 	state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
1126 
1127 	return dpll_pin_ref_sync_state_set(pin, sync_pin_id, state, extack);
1128 }
1129 
1130 static int
dpll_pin_on_pin_state_set(struct dpll_pin * pin,u32 parent_idx,enum dpll_pin_state state,struct netlink_ext_ack * extack)1131 dpll_pin_on_pin_state_set(struct dpll_pin *pin, u32 parent_idx,
1132 			  enum dpll_pin_state state,
1133 			  struct netlink_ext_ack *extack)
1134 {
1135 	struct dpll_pin_ref *parent_ref;
1136 	const struct dpll_pin_ops *ops;
1137 	struct dpll_pin_ref *dpll_ref;
1138 	void *pin_priv, *parent_priv;
1139 	struct dpll_pin *parent;
1140 	unsigned long i;
1141 	int ret;
1142 
1143 	if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
1144 	      pin->prop.capabilities)) {
1145 		NL_SET_ERR_MSG(extack, "state changing is not allowed");
1146 		return -EOPNOTSUPP;
1147 	}
1148 	parent = xa_load(&dpll_pin_xa, parent_idx);
1149 	if (!parent)
1150 		return -EINVAL;
1151 	parent_ref = xa_load(&pin->parent_refs, parent->pin_idx);
1152 	if (!parent_ref)
1153 		return -EINVAL;
1154 	xa_for_each(&parent->dpll_refs, i, dpll_ref) {
1155 		ops = dpll_pin_ops(parent_ref);
1156 		if (!ops->state_on_pin_set)
1157 			return -EOPNOTSUPP;
1158 		pin_priv = dpll_pin_on_pin_priv(parent, pin);
1159 		parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, parent);
1160 		ret = ops->state_on_pin_set(pin, pin_priv, parent, parent_priv,
1161 					    state, extack);
1162 		if (ret)
1163 			return ret;
1164 	}
1165 	__dpll_pin_change_ntf(pin);
1166 
1167 	return 0;
1168 }
1169 
1170 static int
dpll_pin_state_set(struct dpll_device * dpll,struct dpll_pin * pin,enum dpll_pin_state state,struct netlink_ext_ack * extack)1171 dpll_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin,
1172 		   enum dpll_pin_state state,
1173 		   struct netlink_ext_ack *extack)
1174 {
1175 	const struct dpll_pin_ops *ops;
1176 	struct dpll_pin_ref *ref;
1177 	int ret;
1178 
1179 	if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
1180 	      pin->prop.capabilities)) {
1181 		NL_SET_ERR_MSG(extack, "state changing is not allowed");
1182 		return -EOPNOTSUPP;
1183 	}
1184 	ref = xa_load(&pin->dpll_refs, dpll->id);
1185 	ASSERT_NOT_NULL(ref);
1186 	ops = dpll_pin_ops(ref);
1187 	if (!ops->state_on_dpll_set)
1188 		return -EOPNOTSUPP;
1189 	ret = ops->state_on_dpll_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
1190 				     dpll, dpll_priv(dpll), state, extack);
1191 	if (ret)
1192 		return ret;
1193 	__dpll_pin_change_ntf(pin);
1194 
1195 	return 0;
1196 }
1197 
1198 static int
dpll_pin_prio_set(struct dpll_device * dpll,struct dpll_pin * pin,u32 prio,struct netlink_ext_ack * extack)1199 dpll_pin_prio_set(struct dpll_device *dpll, struct dpll_pin *pin,
1200 		  u32 prio, struct netlink_ext_ack *extack)
1201 {
1202 	const struct dpll_pin_ops *ops;
1203 	struct dpll_pin_ref *ref;
1204 	int ret;
1205 
1206 	if (!(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE &
1207 	      pin->prop.capabilities)) {
1208 		NL_SET_ERR_MSG(extack, "prio changing is not allowed");
1209 		return -EOPNOTSUPP;
1210 	}
1211 	ref = xa_load(&pin->dpll_refs, dpll->id);
1212 	ASSERT_NOT_NULL(ref);
1213 	ops = dpll_pin_ops(ref);
1214 	if (!ops->prio_set)
1215 		return -EOPNOTSUPP;
1216 	ret = ops->prio_set(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
1217 			    dpll_priv(dpll), prio, extack);
1218 	if (ret)
1219 		return ret;
1220 	__dpll_pin_change_ntf(pin);
1221 
1222 	return 0;
1223 }
1224 
1225 static int
dpll_pin_direction_set(struct dpll_pin * pin,struct dpll_device * dpll,enum dpll_pin_direction direction,struct netlink_ext_ack * extack)1226 dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll,
1227 		       enum dpll_pin_direction direction,
1228 		       struct netlink_ext_ack *extack)
1229 {
1230 	const struct dpll_pin_ops *ops;
1231 	struct dpll_pin_ref *ref;
1232 	int ret;
1233 
1234 	if (!(DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE &
1235 	      pin->prop.capabilities)) {
1236 		NL_SET_ERR_MSG(extack, "direction changing is not allowed");
1237 		return -EOPNOTSUPP;
1238 	}
1239 	ref = xa_load(&pin->dpll_refs, dpll->id);
1240 	ASSERT_NOT_NULL(ref);
1241 	ops = dpll_pin_ops(ref);
1242 	if (!ops->direction_set)
1243 		return -EOPNOTSUPP;
1244 	ret = ops->direction_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
1245 				 dpll, dpll_priv(dpll), direction, extack);
1246 	if (ret)
1247 		return ret;
1248 	__dpll_pin_change_ntf(pin);
1249 
1250 	return 0;
1251 }
1252 
1253 static int
dpll_pin_phase_adj_set(struct dpll_pin * pin,struct nlattr * phase_adj_attr,struct netlink_ext_ack * extack)1254 dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr,
1255 		       struct netlink_ext_ack *extack)
1256 {
1257 	struct dpll_pin_ref *ref, *failed;
1258 	const struct dpll_pin_ops *ops;
1259 	s32 phase_adj, old_phase_adj;
1260 	struct dpll_device *dpll;
1261 	unsigned long i;
1262 	int ret;
1263 
1264 	phase_adj = nla_get_s32(phase_adj_attr);
1265 	if (phase_adj > pin->prop.phase_range.max ||
1266 	    phase_adj < pin->prop.phase_range.min) {
1267 		NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr,
1268 				    "phase adjust value of out range");
1269 		return -EINVAL;
1270 	}
1271 	if (pin->prop.phase_gran && phase_adj % (s32)pin->prop.phase_gran) {
1272 		NL_SET_ERR_MSG_ATTR_FMT(extack, phase_adj_attr,
1273 					"phase adjust value not multiple of %u",
1274 					pin->prop.phase_gran);
1275 		return -EINVAL;
1276 	}
1277 
1278 	xa_for_each(&pin->dpll_refs, i, ref) {
1279 		ops = dpll_pin_ops(ref);
1280 		if (!ops->phase_adjust_set || !ops->phase_adjust_get) {
1281 			NL_SET_ERR_MSG(extack, "phase adjust not supported");
1282 			return -EOPNOTSUPP;
1283 		}
1284 	}
1285 	ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
1286 	ops = dpll_pin_ops(ref);
1287 	dpll = ref->dpll;
1288 	ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
1289 				    dpll, dpll_priv(dpll), &old_phase_adj,
1290 				    extack);
1291 	if (ret) {
1292 		NL_SET_ERR_MSG(extack, "unable to get old phase adjust value");
1293 		return ret;
1294 	}
1295 	if (phase_adj == old_phase_adj)
1296 		return 0;
1297 
1298 	xa_for_each(&pin->dpll_refs, i, ref) {
1299 		ops = dpll_pin_ops(ref);
1300 		dpll = ref->dpll;
1301 		ret = ops->phase_adjust_set(pin,
1302 					    dpll_pin_on_dpll_priv(dpll, pin),
1303 					    dpll, dpll_priv(dpll), phase_adj,
1304 					    extack);
1305 		if (ret) {
1306 			failed = ref;
1307 			NL_SET_ERR_MSG_FMT(extack,
1308 					   "phase adjust set failed for dpll_id:%u",
1309 					   dpll->id);
1310 			goto rollback;
1311 		}
1312 	}
1313 	__dpll_pin_change_ntf(pin);
1314 
1315 	return 0;
1316 
1317 rollback:
1318 	xa_for_each(&pin->dpll_refs, i, ref) {
1319 		if (ref == failed)
1320 			break;
1321 		ops = dpll_pin_ops(ref);
1322 		dpll = ref->dpll;
1323 		if (ops->phase_adjust_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
1324 					  dpll, dpll_priv(dpll), old_phase_adj,
1325 					  extack))
1326 			NL_SET_ERR_MSG(extack, "set phase adjust rollback failed");
1327 	}
1328 	return ret;
1329 }
1330 
1331 static int
dpll_pin_parent_device_set(struct dpll_pin * pin,struct nlattr * parent_nest,struct netlink_ext_ack * extack)1332 dpll_pin_parent_device_set(struct dpll_pin *pin, struct nlattr *parent_nest,
1333 			   struct netlink_ext_ack *extack)
1334 {
1335 	struct nlattr *tb[DPLL_A_PIN_MAX + 1];
1336 	enum dpll_pin_direction direction;
1337 	enum dpll_pin_state state;
1338 	struct dpll_pin_ref *ref;
1339 	struct dpll_device *dpll;
1340 	u32 pdpll_idx, prio;
1341 	int ret;
1342 
1343 	nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
1344 			 dpll_pin_parent_device_nl_policy, extack);
1345 	if (!tb[DPLL_A_PIN_PARENT_ID]) {
1346 		NL_SET_ERR_MSG(extack, "device parent id expected");
1347 		return -EINVAL;
1348 	}
1349 	pdpll_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
1350 	dpll = xa_load(&dpll_device_xa, pdpll_idx);
1351 	if (!dpll) {
1352 		NL_SET_ERR_MSG(extack, "parent device not found");
1353 		return -EINVAL;
1354 	}
1355 	ref = xa_load(&pin->dpll_refs, dpll->id);
1356 	if (!ref) {
1357 		NL_SET_ERR_MSG(extack, "pin not connected to given parent device");
1358 		return -EINVAL;
1359 	}
1360 	if (tb[DPLL_A_PIN_STATE]) {
1361 		state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
1362 		ret = dpll_pin_state_set(dpll, pin, state, extack);
1363 		if (ret)
1364 			return ret;
1365 	}
1366 	if (tb[DPLL_A_PIN_PRIO]) {
1367 		prio = nla_get_u32(tb[DPLL_A_PIN_PRIO]);
1368 		ret = dpll_pin_prio_set(dpll, pin, prio, extack);
1369 		if (ret)
1370 			return ret;
1371 	}
1372 	if (tb[DPLL_A_PIN_DIRECTION]) {
1373 		direction = nla_get_u32(tb[DPLL_A_PIN_DIRECTION]);
1374 		ret = dpll_pin_direction_set(pin, dpll, direction, extack);
1375 		if (ret)
1376 			return ret;
1377 	}
1378 	return 0;
1379 }
1380 
1381 static int
dpll_pin_parent_pin_set(struct dpll_pin * pin,struct nlattr * parent_nest,struct netlink_ext_ack * extack)1382 dpll_pin_parent_pin_set(struct dpll_pin *pin, struct nlattr *parent_nest,
1383 			struct netlink_ext_ack *extack)
1384 {
1385 	struct nlattr *tb[DPLL_A_PIN_MAX + 1];
1386 	u32 ppin_idx;
1387 	int ret;
1388 
1389 	nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
1390 			 dpll_pin_parent_pin_nl_policy, extack);
1391 	if (!tb[DPLL_A_PIN_PARENT_ID]) {
1392 		NL_SET_ERR_MSG(extack, "device parent id expected");
1393 		return -EINVAL;
1394 	}
1395 	ppin_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
1396 
1397 	if (tb[DPLL_A_PIN_STATE]) {
1398 		enum dpll_pin_state state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
1399 
1400 		ret = dpll_pin_on_pin_state_set(pin, ppin_idx, state, extack);
1401 		if (ret)
1402 			return ret;
1403 	}
1404 
1405 	return 0;
1406 }
1407 
1408 static int
dpll_pin_set_from_nlattr(struct dpll_pin * pin,struct genl_info * info)1409 dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
1410 {
1411 	struct nlattr *a;
1412 	int rem, ret;
1413 
1414 	nla_for_each_attr(a, genlmsg_data(info->genlhdr),
1415 			  genlmsg_len(info->genlhdr), rem) {
1416 		switch (nla_type(a)) {
1417 		case DPLL_A_PIN_FREQUENCY:
1418 			ret = dpll_pin_freq_set(pin, a, info->extack);
1419 			if (ret)
1420 				return ret;
1421 			break;
1422 		case DPLL_A_PIN_PHASE_ADJUST:
1423 			ret = dpll_pin_phase_adj_set(pin, a, info->extack);
1424 			if (ret)
1425 				return ret;
1426 			break;
1427 		case DPLL_A_PIN_PARENT_DEVICE:
1428 			ret = dpll_pin_parent_device_set(pin, a, info->extack);
1429 			if (ret)
1430 				return ret;
1431 			break;
1432 		case DPLL_A_PIN_PARENT_PIN:
1433 			ret = dpll_pin_parent_pin_set(pin, a, info->extack);
1434 			if (ret)
1435 				return ret;
1436 			break;
1437 		case DPLL_A_PIN_ESYNC_FREQUENCY:
1438 			ret = dpll_pin_esync_set(pin, a, info->extack);
1439 			if (ret)
1440 				return ret;
1441 			break;
1442 		case DPLL_A_PIN_REFERENCE_SYNC:
1443 			ret = dpll_pin_ref_sync_set(pin, a, info->extack);
1444 			if (ret)
1445 				return ret;
1446 			break;
1447 		}
1448 	}
1449 
1450 	return 0;
1451 }
1452 
1453 static struct dpll_pin *
dpll_pin_find(u64 clock_id,struct nlattr * mod_name_attr,enum dpll_pin_type type,struct nlattr * board_label,struct nlattr * panel_label,struct nlattr * package_label,struct netlink_ext_ack * extack)1454 dpll_pin_find(u64 clock_id, struct nlattr *mod_name_attr,
1455 	      enum dpll_pin_type type, struct nlattr *board_label,
1456 	      struct nlattr *panel_label, struct nlattr *package_label,
1457 	      struct netlink_ext_ack *extack)
1458 {
1459 	bool board_match, panel_match, package_match;
1460 	struct dpll_pin *pin_match = NULL, *pin;
1461 	const struct dpll_pin_properties *prop;
1462 	bool cid_match, mod_match, type_match;
1463 	unsigned long i;
1464 
1465 	xa_for_each_marked(&dpll_pin_xa, i, pin, DPLL_REGISTERED) {
1466 		prop = &pin->prop;
1467 		cid_match = clock_id ? pin->clock_id == clock_id : true;
1468 		mod_match = mod_name_attr && module_name(pin->module) ?
1469 			!nla_strcmp(mod_name_attr,
1470 				    module_name(pin->module)) : true;
1471 		type_match = type ? prop->type == type : true;
1472 		board_match = board_label ? (prop->board_label ?
1473 			!nla_strcmp(board_label, prop->board_label) : false) :
1474 			true;
1475 		panel_match = panel_label ? (prop->panel_label ?
1476 			!nla_strcmp(panel_label, prop->panel_label) : false) :
1477 			true;
1478 		package_match = package_label ? (prop->package_label ?
1479 			!nla_strcmp(package_label, prop->package_label) :
1480 			false) : true;
1481 		if (cid_match && mod_match && type_match && board_match &&
1482 		    panel_match && package_match) {
1483 			if (pin_match) {
1484 				NL_SET_ERR_MSG(extack, "multiple matches");
1485 				return ERR_PTR(-EINVAL);
1486 			}
1487 			pin_match = pin;
1488 		}
1489 	}
1490 	if (!pin_match) {
1491 		NL_SET_ERR_MSG(extack, "not found");
1492 		return ERR_PTR(-ENODEV);
1493 	}
1494 	return pin_match;
1495 }
1496 
dpll_pin_find_from_nlattr(struct genl_info * info)1497 static struct dpll_pin *dpll_pin_find_from_nlattr(struct genl_info *info)
1498 {
1499 	struct nlattr *attr, *mod_name_attr = NULL, *board_label_attr = NULL,
1500 		*panel_label_attr = NULL, *package_label_attr = NULL;
1501 	enum dpll_pin_type type = 0;
1502 	u64 clock_id = 0;
1503 	int rem = 0;
1504 
1505 	nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
1506 			  genlmsg_len(info->genlhdr), rem) {
1507 		switch (nla_type(attr)) {
1508 		case DPLL_A_PIN_CLOCK_ID:
1509 			if (clock_id)
1510 				goto duplicated_attr;
1511 			clock_id = nla_get_u64(attr);
1512 			break;
1513 		case DPLL_A_PIN_MODULE_NAME:
1514 			if (mod_name_attr)
1515 				goto duplicated_attr;
1516 			mod_name_attr = attr;
1517 			break;
1518 		case DPLL_A_PIN_TYPE:
1519 			if (type)
1520 				goto duplicated_attr;
1521 			type = nla_get_u32(attr);
1522 		break;
1523 		case DPLL_A_PIN_BOARD_LABEL:
1524 			if (board_label_attr)
1525 				goto duplicated_attr;
1526 			board_label_attr = attr;
1527 		break;
1528 		case DPLL_A_PIN_PANEL_LABEL:
1529 			if (panel_label_attr)
1530 				goto duplicated_attr;
1531 			panel_label_attr = attr;
1532 		break;
1533 		case DPLL_A_PIN_PACKAGE_LABEL:
1534 			if (package_label_attr)
1535 				goto duplicated_attr;
1536 			package_label_attr = attr;
1537 		break;
1538 		default:
1539 			break;
1540 		}
1541 	}
1542 	if (!(clock_id  || mod_name_attr || board_label_attr ||
1543 	      panel_label_attr || package_label_attr)) {
1544 		NL_SET_ERR_MSG(info->extack, "missing attributes");
1545 		return ERR_PTR(-EINVAL);
1546 	}
1547 	return dpll_pin_find(clock_id, mod_name_attr, type, board_label_attr,
1548 			     panel_label_attr, package_label_attr,
1549 			     info->extack);
1550 duplicated_attr:
1551 	NL_SET_ERR_MSG(info->extack, "duplicated attribute");
1552 	return ERR_PTR(-EINVAL);
1553 }
1554 
dpll_nl_pin_id_get_doit(struct sk_buff * skb,struct genl_info * info)1555 int dpll_nl_pin_id_get_doit(struct sk_buff *skb, struct genl_info *info)
1556 {
1557 	struct dpll_pin *pin;
1558 	struct sk_buff *msg;
1559 	struct nlattr *hdr;
1560 	int ret;
1561 
1562 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1563 	if (!msg)
1564 		return -ENOMEM;
1565 	hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1566 				DPLL_CMD_PIN_ID_GET);
1567 	if (!hdr) {
1568 		nlmsg_free(msg);
1569 		return -EMSGSIZE;
1570 	}
1571 	pin = dpll_pin_find_from_nlattr(info);
1572 	if (IS_ERR(pin)) {
1573 		nlmsg_free(msg);
1574 		return PTR_ERR(pin);
1575 	}
1576 	if (!dpll_pin_available(pin)) {
1577 		nlmsg_free(msg);
1578 		return -ENODEV;
1579 	}
1580 	ret = dpll_msg_add_pin_handle(msg, pin);
1581 	if (ret) {
1582 		nlmsg_free(msg);
1583 		return ret;
1584 	}
1585 	genlmsg_end(msg, hdr);
1586 
1587 	return genlmsg_reply(msg, info);
1588 }
1589 
dpll_nl_pin_get_doit(struct sk_buff * skb,struct genl_info * info)1590 int dpll_nl_pin_get_doit(struct sk_buff *skb, struct genl_info *info)
1591 {
1592 	struct dpll_pin *pin = info->user_ptr[0];
1593 	struct sk_buff *msg;
1594 	struct nlattr *hdr;
1595 	int ret;
1596 
1597 	if (!pin)
1598 		return -ENODEV;
1599 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1600 	if (!msg)
1601 		return -ENOMEM;
1602 	hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1603 				DPLL_CMD_PIN_GET);
1604 	if (!hdr) {
1605 		nlmsg_free(msg);
1606 		return -EMSGSIZE;
1607 	}
1608 	ret = dpll_cmd_pin_get_one(msg, pin, info->extack);
1609 	if (ret) {
1610 		nlmsg_free(msg);
1611 		return ret;
1612 	}
1613 	genlmsg_end(msg, hdr);
1614 
1615 	return genlmsg_reply(msg, info);
1616 }
1617 
dpll_nl_pin_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)1618 int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
1619 {
1620 	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
1621 	struct dpll_pin *pin;
1622 	struct nlattr *hdr;
1623 	unsigned long i;
1624 	int ret = 0;
1625 
1626 	mutex_lock(&dpll_lock);
1627 	xa_for_each_marked_start(&dpll_pin_xa, i, pin, DPLL_REGISTERED,
1628 				 ctx->idx) {
1629 		if (!dpll_pin_available(pin))
1630 			continue;
1631 		hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1632 				  cb->nlh->nlmsg_seq,
1633 				  &dpll_nl_family, NLM_F_MULTI,
1634 				  DPLL_CMD_PIN_GET);
1635 		if (!hdr) {
1636 			ret = -EMSGSIZE;
1637 			break;
1638 		}
1639 		ret = dpll_cmd_pin_get_one(skb, pin, cb->extack);
1640 		if (ret) {
1641 			genlmsg_cancel(skb, hdr);
1642 			break;
1643 		}
1644 		genlmsg_end(skb, hdr);
1645 	}
1646 	mutex_unlock(&dpll_lock);
1647 
1648 	if (ret == -EMSGSIZE) {
1649 		ctx->idx = i;
1650 		return skb->len;
1651 	}
1652 	return ret;
1653 }
1654 
dpll_nl_pin_set_doit(struct sk_buff * skb,struct genl_info * info)1655 int dpll_nl_pin_set_doit(struct sk_buff *skb, struct genl_info *info)
1656 {
1657 	struct dpll_pin *pin = info->user_ptr[0];
1658 
1659 	return dpll_pin_set_from_nlattr(pin, info);
1660 }
1661 
1662 static struct dpll_device *
dpll_device_find(u64 clock_id,struct nlattr * mod_name_attr,enum dpll_type type,struct netlink_ext_ack * extack)1663 dpll_device_find(u64 clock_id, struct nlattr *mod_name_attr,
1664 		 enum dpll_type type, struct netlink_ext_ack *extack)
1665 {
1666 	struct dpll_device *dpll_match = NULL, *dpll;
1667 	bool cid_match, mod_match, type_match;
1668 	unsigned long i;
1669 
1670 	xa_for_each_marked(&dpll_device_xa, i, dpll, DPLL_REGISTERED) {
1671 		cid_match = clock_id ? dpll->clock_id == clock_id : true;
1672 		mod_match = mod_name_attr ? (module_name(dpll->module) ?
1673 			!nla_strcmp(mod_name_attr,
1674 				    module_name(dpll->module)) : false) : true;
1675 		type_match = type ? dpll->type == type : true;
1676 		if (cid_match && mod_match && type_match) {
1677 			if (dpll_match) {
1678 				NL_SET_ERR_MSG(extack, "multiple matches");
1679 				return ERR_PTR(-EINVAL);
1680 			}
1681 			dpll_match = dpll;
1682 		}
1683 	}
1684 	if (!dpll_match) {
1685 		NL_SET_ERR_MSG(extack, "not found");
1686 		return ERR_PTR(-ENODEV);
1687 	}
1688 
1689 	return dpll_match;
1690 }
1691 
1692 static struct dpll_device *
dpll_device_find_from_nlattr(struct genl_info * info)1693 dpll_device_find_from_nlattr(struct genl_info *info)
1694 {
1695 	struct nlattr *attr, *mod_name_attr = NULL;
1696 	enum dpll_type type = 0;
1697 	u64 clock_id = 0;
1698 	int rem = 0;
1699 
1700 	nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
1701 			  genlmsg_len(info->genlhdr), rem) {
1702 		switch (nla_type(attr)) {
1703 		case DPLL_A_CLOCK_ID:
1704 			if (clock_id)
1705 				goto duplicated_attr;
1706 			clock_id = nla_get_u64(attr);
1707 			break;
1708 		case DPLL_A_MODULE_NAME:
1709 			if (mod_name_attr)
1710 				goto duplicated_attr;
1711 			mod_name_attr = attr;
1712 			break;
1713 		case DPLL_A_TYPE:
1714 			if (type)
1715 				goto duplicated_attr;
1716 			type = nla_get_u32(attr);
1717 			break;
1718 		default:
1719 			break;
1720 		}
1721 	}
1722 	if (!clock_id && !mod_name_attr && !type) {
1723 		NL_SET_ERR_MSG(info->extack, "missing attributes");
1724 		return ERR_PTR(-EINVAL);
1725 	}
1726 	return dpll_device_find(clock_id, mod_name_attr, type, info->extack);
1727 duplicated_attr:
1728 	NL_SET_ERR_MSG(info->extack, "duplicated attribute");
1729 	return ERR_PTR(-EINVAL);
1730 }
1731 
dpll_nl_device_id_get_doit(struct sk_buff * skb,struct genl_info * info)1732 int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info)
1733 {
1734 	struct dpll_device *dpll;
1735 	struct sk_buff *msg;
1736 	struct nlattr *hdr;
1737 	int ret;
1738 
1739 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1740 	if (!msg)
1741 		return -ENOMEM;
1742 	hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1743 				DPLL_CMD_DEVICE_ID_GET);
1744 	if (!hdr) {
1745 		nlmsg_free(msg);
1746 		return -EMSGSIZE;
1747 	}
1748 
1749 	dpll = dpll_device_find_from_nlattr(info);
1750 	if (IS_ERR(dpll)) {
1751 		nlmsg_free(msg);
1752 		return PTR_ERR(dpll);
1753 	}
1754 	ret = dpll_msg_add_dev_handle(msg, dpll);
1755 	if (ret) {
1756 		nlmsg_free(msg);
1757 		return ret;
1758 	}
1759 	genlmsg_end(msg, hdr);
1760 
1761 	return genlmsg_reply(msg, info);
1762 }
1763 
dpll_nl_device_get_doit(struct sk_buff * skb,struct genl_info * info)1764 int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info)
1765 {
1766 	struct dpll_device *dpll = info->user_ptr[0];
1767 	struct sk_buff *msg;
1768 	struct nlattr *hdr;
1769 	int ret;
1770 
1771 	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1772 	if (!msg)
1773 		return -ENOMEM;
1774 	hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1775 				DPLL_CMD_DEVICE_GET);
1776 	if (!hdr) {
1777 		nlmsg_free(msg);
1778 		return -EMSGSIZE;
1779 	}
1780 
1781 	ret = dpll_device_get_one(dpll, msg, info->extack);
1782 	if (ret) {
1783 		nlmsg_free(msg);
1784 		return ret;
1785 	}
1786 	genlmsg_end(msg, hdr);
1787 
1788 	return genlmsg_reply(msg, info);
1789 }
1790 
1791 static int
dpll_set_from_nlattr(struct dpll_device * dpll,struct genl_info * info)1792 dpll_set_from_nlattr(struct dpll_device *dpll, struct genl_info *info)
1793 {
1794 	struct nlattr *a;
1795 	int rem, ret;
1796 
1797 	nla_for_each_attr(a, genlmsg_data(info->genlhdr),
1798 			  genlmsg_len(info->genlhdr), rem) {
1799 		switch (nla_type(a)) {
1800 		case DPLL_A_PHASE_OFFSET_MONITOR:
1801 			ret = dpll_phase_offset_monitor_set(dpll, a,
1802 							    info->extack);
1803 			if (ret)
1804 				return ret;
1805 			break;
1806 		case DPLL_A_PHASE_OFFSET_AVG_FACTOR:
1807 			ret = dpll_phase_offset_avg_factor_set(dpll, a,
1808 							       info->extack);
1809 			if (ret)
1810 				return ret;
1811 			break;
1812 		}
1813 	}
1814 
1815 	return 0;
1816 }
1817 
dpll_nl_device_set_doit(struct sk_buff * skb,struct genl_info * info)1818 int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info)
1819 {
1820 	struct dpll_device *dpll = info->user_ptr[0];
1821 
1822 	return dpll_set_from_nlattr(dpll, info);
1823 }
1824 
dpll_nl_device_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)1825 int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
1826 {
1827 	struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
1828 	struct dpll_device *dpll;
1829 	struct nlattr *hdr;
1830 	unsigned long i;
1831 	int ret = 0;
1832 
1833 	mutex_lock(&dpll_lock);
1834 	xa_for_each_marked_start(&dpll_device_xa, i, dpll, DPLL_REGISTERED,
1835 				 ctx->idx) {
1836 		hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1837 				  cb->nlh->nlmsg_seq, &dpll_nl_family,
1838 				  NLM_F_MULTI, DPLL_CMD_DEVICE_GET);
1839 		if (!hdr) {
1840 			ret = -EMSGSIZE;
1841 			break;
1842 		}
1843 		ret = dpll_device_get_one(dpll, skb, cb->extack);
1844 		if (ret) {
1845 			genlmsg_cancel(skb, hdr);
1846 			break;
1847 		}
1848 		genlmsg_end(skb, hdr);
1849 	}
1850 	mutex_unlock(&dpll_lock);
1851 
1852 	if (ret == -EMSGSIZE) {
1853 		ctx->idx = i;
1854 		return skb->len;
1855 	}
1856 	return ret;
1857 }
1858 
dpll_pre_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1859 int dpll_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1860 		  struct genl_info *info)
1861 {
1862 	u32 id;
1863 
1864 	if (GENL_REQ_ATTR_CHECK(info, DPLL_A_ID))
1865 		return -EINVAL;
1866 
1867 	mutex_lock(&dpll_lock);
1868 	id = nla_get_u32(info->attrs[DPLL_A_ID]);
1869 	info->user_ptr[0] = dpll_device_get_by_id(id);
1870 	if (!info->user_ptr[0]) {
1871 		NL_SET_ERR_MSG(info->extack, "device not found");
1872 		goto unlock;
1873 	}
1874 	return 0;
1875 unlock:
1876 	mutex_unlock(&dpll_lock);
1877 	return -ENODEV;
1878 }
1879 
dpll_post_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1880 void dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1881 		    struct genl_info *info)
1882 {
1883 	mutex_unlock(&dpll_lock);
1884 }
1885 
1886 int
dpll_lock_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1887 dpll_lock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1888 	       struct genl_info *info)
1889 {
1890 	mutex_lock(&dpll_lock);
1891 
1892 	return 0;
1893 }
1894 
1895 void
dpll_unlock_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1896 dpll_unlock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1897 		 struct genl_info *info)
1898 {
1899 	mutex_unlock(&dpll_lock);
1900 }
1901 
dpll_pin_pre_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1902 int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1903 		      struct genl_info *info)
1904 {
1905 	int ret;
1906 
1907 	mutex_lock(&dpll_lock);
1908 	if (GENL_REQ_ATTR_CHECK(info, DPLL_A_PIN_ID)) {
1909 		ret = -EINVAL;
1910 		goto unlock_dev;
1911 	}
1912 	info->user_ptr[0] = xa_load(&dpll_pin_xa,
1913 				    nla_get_u32(info->attrs[DPLL_A_PIN_ID]));
1914 	if (!info->user_ptr[0] ||
1915 	    !dpll_pin_available(info->user_ptr[0])) {
1916 		NL_SET_ERR_MSG(info->extack, "pin not found");
1917 		ret = -ENODEV;
1918 		goto unlock_dev;
1919 	}
1920 
1921 	return 0;
1922 
1923 unlock_dev:
1924 	mutex_unlock(&dpll_lock);
1925 	return ret;
1926 }
1927 
dpll_pin_post_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1928 void dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1929 			struct genl_info *info)
1930 {
1931 	mutex_unlock(&dpll_lock);
1932 }
1933