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