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