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