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