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