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 (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MIN,
641 prop->phase_range.min))
642 return -EMSGSIZE;
643 if (nla_put_s32(msg, DPLL_A_PIN_PHASE_ADJUST_MAX,
644 prop->phase_range.max))
645 return -EMSGSIZE;
646 ret = dpll_msg_add_pin_phase_adjust(msg, pin, ref, extack);
647 if (ret)
648 return ret;
649 ret = dpll_msg_add_ffo(msg, pin, ref, extack);
650 if (ret)
651 return ret;
652 ret = dpll_msg_add_pin_esync(msg, pin, ref, extack);
653 if (ret)
654 return ret;
655 if (!xa_empty(&pin->ref_sync_pins))
656 ret = dpll_msg_add_pin_ref_sync(msg, pin, ref, extack);
657 if (ret)
658 return ret;
659 if (xa_empty(&pin->parent_refs))
660 ret = dpll_msg_add_pin_dplls(msg, pin, extack);
661 else
662 ret = dpll_msg_add_pin_parents(msg, pin, ref, extack);
663
664 return ret;
665 }
666
667 static int
dpll_device_get_one(struct dpll_device * dpll,struct sk_buff * msg,struct netlink_ext_ack * extack)668 dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
669 struct netlink_ext_ack *extack)
670 {
671 int ret;
672
673 ret = dpll_msg_add_dev_handle(msg, dpll);
674 if (ret)
675 return ret;
676 if (nla_put_string(msg, DPLL_A_MODULE_NAME, module_name(dpll->module)))
677 return -EMSGSIZE;
678 if (nla_put_64bit(msg, DPLL_A_CLOCK_ID, sizeof(dpll->clock_id),
679 &dpll->clock_id, DPLL_A_PAD))
680 return -EMSGSIZE;
681 ret = dpll_msg_add_temp(msg, dpll, extack);
682 if (ret)
683 return ret;
684 ret = dpll_msg_add_lock_status(msg, dpll, extack);
685 if (ret)
686 return ret;
687 ret = dpll_msg_add_clock_quality_level(msg, dpll, extack);
688 if (ret)
689 return ret;
690 ret = dpll_msg_add_mode(msg, dpll, extack);
691 if (ret)
692 return ret;
693 ret = dpll_msg_add_mode_supported(msg, dpll, extack);
694 if (ret)
695 return ret;
696 if (nla_put_u32(msg, DPLL_A_TYPE, dpll->type))
697 return -EMSGSIZE;
698 ret = dpll_msg_add_phase_offset_monitor(msg, dpll, extack);
699 if (ret)
700 return ret;
701 ret = dpll_msg_add_phase_offset_avg_factor(msg, dpll, extack);
702 if (ret)
703 return ret;
704
705 return 0;
706 }
707
708 static int
dpll_device_event_send(enum dpll_cmd event,struct dpll_device * dpll)709 dpll_device_event_send(enum dpll_cmd event, struct dpll_device *dpll)
710 {
711 struct sk_buff *msg;
712 int ret = -ENOMEM;
713 void *hdr;
714
715 if (WARN_ON(!xa_get_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED)))
716 return -ENODEV;
717 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
718 if (!msg)
719 return -ENOMEM;
720 hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
721 if (!hdr)
722 goto err_free_msg;
723 ret = dpll_device_get_one(dpll, msg, NULL);
724 if (ret)
725 goto err_cancel_msg;
726 genlmsg_end(msg, hdr);
727 genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
728
729 return 0;
730
731 err_cancel_msg:
732 genlmsg_cancel(msg, hdr);
733 err_free_msg:
734 nlmsg_free(msg);
735
736 return ret;
737 }
738
dpll_device_create_ntf(struct dpll_device * dpll)739 int dpll_device_create_ntf(struct dpll_device *dpll)
740 {
741 return dpll_device_event_send(DPLL_CMD_DEVICE_CREATE_NTF, dpll);
742 }
743
dpll_device_delete_ntf(struct dpll_device * dpll)744 int dpll_device_delete_ntf(struct dpll_device *dpll)
745 {
746 return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF, dpll);
747 }
748
749 static int
__dpll_device_change_ntf(struct dpll_device * dpll)750 __dpll_device_change_ntf(struct dpll_device *dpll)
751 {
752 return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll);
753 }
754
755 /**
756 * dpll_device_change_ntf - notify that the dpll device has been changed
757 * @dpll: registered dpll pointer
758 *
759 * Context: acquires and holds a dpll_lock.
760 * Return: 0 if succeeds, error code otherwise.
761 */
dpll_device_change_ntf(struct dpll_device * dpll)762 int dpll_device_change_ntf(struct dpll_device *dpll)
763 {
764 int ret;
765
766 mutex_lock(&dpll_lock);
767 ret = __dpll_device_change_ntf(dpll);
768 mutex_unlock(&dpll_lock);
769
770 return ret;
771 }
772 EXPORT_SYMBOL_GPL(dpll_device_change_ntf);
773
774 static int
dpll_pin_event_send(enum dpll_cmd event,struct dpll_pin * pin)775 dpll_pin_event_send(enum dpll_cmd event, struct dpll_pin *pin)
776 {
777 struct sk_buff *msg;
778 int ret = -ENOMEM;
779 void *hdr;
780
781 if (!dpll_pin_available(pin))
782 return -ENODEV;
783
784 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
785 if (!msg)
786 return -ENOMEM;
787
788 hdr = genlmsg_put(msg, 0, 0, &dpll_nl_family, 0, event);
789 if (!hdr)
790 goto err_free_msg;
791 ret = dpll_cmd_pin_get_one(msg, pin, NULL);
792 if (ret)
793 goto err_cancel_msg;
794 genlmsg_end(msg, hdr);
795 genlmsg_multicast(&dpll_nl_family, msg, 0, 0, GFP_KERNEL);
796
797 return 0;
798
799 err_cancel_msg:
800 genlmsg_cancel(msg, hdr);
801 err_free_msg:
802 nlmsg_free(msg);
803
804 return ret;
805 }
806
dpll_pin_create_ntf(struct dpll_pin * pin)807 int dpll_pin_create_ntf(struct dpll_pin *pin)
808 {
809 return dpll_pin_event_send(DPLL_CMD_PIN_CREATE_NTF, pin);
810 }
811
dpll_pin_delete_ntf(struct dpll_pin * pin)812 int dpll_pin_delete_ntf(struct dpll_pin *pin)
813 {
814 return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin);
815 }
816
__dpll_pin_change_ntf(struct dpll_pin * pin)817 int __dpll_pin_change_ntf(struct dpll_pin *pin)
818 {
819 return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin);
820 }
821
822 /**
823 * dpll_pin_change_ntf - notify that the pin has been changed
824 * @pin: registered pin pointer
825 *
826 * Context: acquires and holds a dpll_lock.
827 * Return: 0 if succeeds, error code otherwise.
828 */
dpll_pin_change_ntf(struct dpll_pin * pin)829 int dpll_pin_change_ntf(struct dpll_pin *pin)
830 {
831 int ret;
832
833 mutex_lock(&dpll_lock);
834 ret = __dpll_pin_change_ntf(pin);
835 mutex_unlock(&dpll_lock);
836
837 return ret;
838 }
839 EXPORT_SYMBOL_GPL(dpll_pin_change_ntf);
840
841 static int
dpll_phase_offset_monitor_set(struct dpll_device * dpll,struct nlattr * a,struct netlink_ext_ack * extack)842 dpll_phase_offset_monitor_set(struct dpll_device *dpll, struct nlattr *a,
843 struct netlink_ext_ack *extack)
844 {
845 const struct dpll_device_ops *ops = dpll_device_ops(dpll);
846 enum dpll_feature_state state = nla_get_u32(a), old_state;
847 int ret;
848
849 if (!(ops->phase_offset_monitor_set && ops->phase_offset_monitor_get)) {
850 NL_SET_ERR_MSG_ATTR(extack, a, "dpll device not capable of phase offset monitor");
851 return -EOPNOTSUPP;
852 }
853 ret = ops->phase_offset_monitor_get(dpll, dpll_priv(dpll), &old_state,
854 extack);
855 if (ret) {
856 NL_SET_ERR_MSG(extack, "unable to get current state of phase offset monitor");
857 return ret;
858 }
859 if (state == old_state)
860 return 0;
861
862 return ops->phase_offset_monitor_set(dpll, dpll_priv(dpll), state,
863 extack);
864 }
865
866 static int
dpll_phase_offset_avg_factor_set(struct dpll_device * dpll,struct nlattr * a,struct netlink_ext_ack * extack)867 dpll_phase_offset_avg_factor_set(struct dpll_device *dpll, struct nlattr *a,
868 struct netlink_ext_ack *extack)
869 {
870 const struct dpll_device_ops *ops = dpll_device_ops(dpll);
871 u32 factor = nla_get_u32(a);
872
873 if (!ops->phase_offset_avg_factor_set) {
874 NL_SET_ERR_MSG_ATTR(extack, a,
875 "device not capable of changing phase offset average factor");
876 return -EOPNOTSUPP;
877 }
878
879 return ops->phase_offset_avg_factor_set(dpll, dpll_priv(dpll), factor,
880 extack);
881 }
882
883 static int
dpll_pin_freq_set(struct dpll_pin * pin,struct nlattr * a,struct netlink_ext_ack * extack)884 dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
885 struct netlink_ext_ack *extack)
886 {
887 u64 freq = nla_get_u64(a), old_freq;
888 struct dpll_pin_ref *ref, *failed;
889 const struct dpll_pin_ops *ops;
890 struct dpll_device *dpll;
891 unsigned long i;
892 int ret;
893
894 if (!dpll_pin_is_freq_supported(pin, freq)) {
895 NL_SET_ERR_MSG_ATTR(extack, a, "frequency is not supported by the device");
896 return -EINVAL;
897 }
898
899 xa_for_each(&pin->dpll_refs, i, ref) {
900 ops = dpll_pin_ops(ref);
901 if (!ops->frequency_set || !ops->frequency_get) {
902 NL_SET_ERR_MSG(extack, "frequency set not supported by the device");
903 return -EOPNOTSUPP;
904 }
905 }
906 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
907 ops = dpll_pin_ops(ref);
908 dpll = ref->dpll;
909 ret = ops->frequency_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
910 dpll_priv(dpll), &old_freq, extack);
911 if (ret) {
912 NL_SET_ERR_MSG(extack, "unable to get old frequency value");
913 return ret;
914 }
915 if (freq == old_freq)
916 return 0;
917
918 xa_for_each(&pin->dpll_refs, i, ref) {
919 ops = dpll_pin_ops(ref);
920 dpll = ref->dpll;
921 ret = ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
922 dpll, dpll_priv(dpll), freq, extack);
923 if (ret) {
924 failed = ref;
925 NL_SET_ERR_MSG_FMT(extack, "frequency set failed for dpll_id:%u",
926 dpll->id);
927 goto rollback;
928 }
929 }
930 __dpll_pin_change_ntf(pin);
931
932 return 0;
933
934 rollback:
935 xa_for_each(&pin->dpll_refs, i, ref) {
936 if (ref == failed)
937 break;
938 ops = dpll_pin_ops(ref);
939 dpll = ref->dpll;
940 if (ops->frequency_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
941 dpll, dpll_priv(dpll), old_freq, extack))
942 NL_SET_ERR_MSG(extack, "set frequency rollback failed");
943 }
944 return ret;
945 }
946
947 static int
dpll_pin_esync_set(struct dpll_pin * pin,struct nlattr * a,struct netlink_ext_ack * extack)948 dpll_pin_esync_set(struct dpll_pin *pin, struct nlattr *a,
949 struct netlink_ext_ack *extack)
950 {
951 struct dpll_pin_ref *ref, *failed;
952 const struct dpll_pin_ops *ops;
953 struct dpll_pin_esync esync;
954 u64 freq = nla_get_u64(a);
955 struct dpll_device *dpll;
956 bool supported = false;
957 unsigned long i;
958 int ret;
959
960 xa_for_each(&pin->dpll_refs, i, ref) {
961 ops = dpll_pin_ops(ref);
962 if (!ops->esync_set || !ops->esync_get) {
963 NL_SET_ERR_MSG(extack,
964 "embedded sync feature is not supported by this device");
965 return -EOPNOTSUPP;
966 }
967 }
968 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
969 ops = dpll_pin_ops(ref);
970 dpll = ref->dpll;
971 ret = ops->esync_get(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
972 dpll_priv(dpll), &esync, extack);
973 if (ret) {
974 NL_SET_ERR_MSG(extack, "unable to get current embedded sync frequency value");
975 return ret;
976 }
977 if (freq == esync.freq)
978 return 0;
979 for (i = 0; i < esync.range_num; i++)
980 if (freq <= esync.range[i].max && freq >= esync.range[i].min)
981 supported = true;
982 if (!supported) {
983 NL_SET_ERR_MSG_ATTR(extack, a,
984 "requested embedded sync frequency value is not supported by this device");
985 return -EINVAL;
986 }
987
988 xa_for_each(&pin->dpll_refs, i, ref) {
989 void *pin_dpll_priv;
990
991 ops = dpll_pin_ops(ref);
992 dpll = ref->dpll;
993 pin_dpll_priv = dpll_pin_on_dpll_priv(dpll, pin);
994 ret = ops->esync_set(pin, pin_dpll_priv, dpll, dpll_priv(dpll),
995 freq, extack);
996 if (ret) {
997 failed = ref;
998 NL_SET_ERR_MSG_FMT(extack,
999 "embedded sync frequency set failed for dpll_id: %u",
1000 dpll->id);
1001 goto rollback;
1002 }
1003 }
1004 __dpll_pin_change_ntf(pin);
1005
1006 return 0;
1007
1008 rollback:
1009 xa_for_each(&pin->dpll_refs, i, ref) {
1010 void *pin_dpll_priv;
1011
1012 if (ref == failed)
1013 break;
1014 ops = dpll_pin_ops(ref);
1015 dpll = ref->dpll;
1016 pin_dpll_priv = dpll_pin_on_dpll_priv(dpll, pin);
1017 if (ops->esync_set(pin, pin_dpll_priv, dpll, dpll_priv(dpll),
1018 esync.freq, extack))
1019 NL_SET_ERR_MSG(extack, "set embedded sync frequency rollback failed");
1020 }
1021 return ret;
1022 }
1023
1024 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)1025 dpll_pin_ref_sync_state_set(struct dpll_pin *pin,
1026 unsigned long ref_sync_pin_idx,
1027 const enum dpll_pin_state state,
1028 struct netlink_ext_ack *extack)
1029
1030 {
1031 struct dpll_pin_ref *ref, *failed;
1032 const struct dpll_pin_ops *ops;
1033 enum dpll_pin_state old_state;
1034 struct dpll_pin *ref_sync_pin;
1035 struct dpll_device *dpll;
1036 unsigned long i;
1037 int ret;
1038
1039 ref_sync_pin = xa_find(&pin->ref_sync_pins, &ref_sync_pin_idx,
1040 ULONG_MAX, XA_PRESENT);
1041 if (!ref_sync_pin) {
1042 NL_SET_ERR_MSG(extack, "reference sync pin not found");
1043 return -EINVAL;
1044 }
1045 if (!dpll_pin_available(ref_sync_pin)) {
1046 NL_SET_ERR_MSG(extack, "reference sync pin not available");
1047 return -EINVAL;
1048 }
1049 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
1050 ASSERT_NOT_NULL(ref);
1051 ops = dpll_pin_ops(ref);
1052 if (!ops->ref_sync_set || !ops->ref_sync_get) {
1053 NL_SET_ERR_MSG(extack, "reference sync not supported by this pin");
1054 return -EOPNOTSUPP;
1055 }
1056 dpll = ref->dpll;
1057 ret = ops->ref_sync_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
1058 ref_sync_pin,
1059 dpll_pin_on_dpll_priv(dpll, ref_sync_pin),
1060 &old_state, extack);
1061 if (ret) {
1062 NL_SET_ERR_MSG(extack, "unable to get old reference sync state");
1063 return ret;
1064 }
1065 if (state == old_state)
1066 return 0;
1067 xa_for_each(&pin->dpll_refs, i, ref) {
1068 ops = dpll_pin_ops(ref);
1069 dpll = ref->dpll;
1070 ret = ops->ref_sync_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
1071 ref_sync_pin,
1072 dpll_pin_on_dpll_priv(dpll,
1073 ref_sync_pin),
1074 state, extack);
1075 if (ret) {
1076 failed = ref;
1077 NL_SET_ERR_MSG_FMT(extack, "reference sync set failed for dpll_id:%u",
1078 dpll->id);
1079 goto rollback;
1080 }
1081 }
1082 __dpll_pin_change_ntf(pin);
1083
1084 return 0;
1085
1086 rollback:
1087 xa_for_each(&pin->dpll_refs, i, ref) {
1088 if (ref == failed)
1089 break;
1090 ops = dpll_pin_ops(ref);
1091 dpll = ref->dpll;
1092 if (ops->ref_sync_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
1093 ref_sync_pin,
1094 dpll_pin_on_dpll_priv(dpll, ref_sync_pin),
1095 old_state, extack))
1096 NL_SET_ERR_MSG(extack, "set reference sync rollback failed");
1097 }
1098 return ret;
1099 }
1100
1101 static int
dpll_pin_ref_sync_set(struct dpll_pin * pin,struct nlattr * nest,struct netlink_ext_ack * extack)1102 dpll_pin_ref_sync_set(struct dpll_pin *pin, struct nlattr *nest,
1103 struct netlink_ext_ack *extack)
1104 {
1105 struct nlattr *tb[DPLL_A_PIN_MAX + 1];
1106 enum dpll_pin_state state;
1107 u32 sync_pin_id;
1108
1109 nla_parse_nested(tb, DPLL_A_PIN_MAX, nest,
1110 dpll_reference_sync_nl_policy, extack);
1111 if (!tb[DPLL_A_PIN_ID]) {
1112 NL_SET_ERR_MSG(extack, "sync pin id expected");
1113 return -EINVAL;
1114 }
1115 sync_pin_id = nla_get_u32(tb[DPLL_A_PIN_ID]);
1116
1117 if (!tb[DPLL_A_PIN_STATE]) {
1118 NL_SET_ERR_MSG(extack, "sync pin state expected");
1119 return -EINVAL;
1120 }
1121 state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
1122
1123 return dpll_pin_ref_sync_state_set(pin, sync_pin_id, state, extack);
1124 }
1125
1126 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)1127 dpll_pin_on_pin_state_set(struct dpll_pin *pin, u32 parent_idx,
1128 enum dpll_pin_state state,
1129 struct netlink_ext_ack *extack)
1130 {
1131 struct dpll_pin_ref *parent_ref;
1132 const struct dpll_pin_ops *ops;
1133 struct dpll_pin_ref *dpll_ref;
1134 void *pin_priv, *parent_priv;
1135 struct dpll_pin *parent;
1136 unsigned long i;
1137 int ret;
1138
1139 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
1140 pin->prop.capabilities)) {
1141 NL_SET_ERR_MSG(extack, "state changing is not allowed");
1142 return -EOPNOTSUPP;
1143 }
1144 parent = xa_load(&dpll_pin_xa, parent_idx);
1145 if (!parent)
1146 return -EINVAL;
1147 parent_ref = xa_load(&pin->parent_refs, parent->pin_idx);
1148 if (!parent_ref)
1149 return -EINVAL;
1150 xa_for_each(&parent->dpll_refs, i, dpll_ref) {
1151 ops = dpll_pin_ops(parent_ref);
1152 if (!ops->state_on_pin_set)
1153 return -EOPNOTSUPP;
1154 pin_priv = dpll_pin_on_pin_priv(parent, pin);
1155 parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, parent);
1156 ret = ops->state_on_pin_set(pin, pin_priv, parent, parent_priv,
1157 state, extack);
1158 if (ret)
1159 return ret;
1160 }
1161 __dpll_pin_change_ntf(pin);
1162
1163 return 0;
1164 }
1165
1166 static int
dpll_pin_state_set(struct dpll_device * dpll,struct dpll_pin * pin,enum dpll_pin_state state,struct netlink_ext_ack * extack)1167 dpll_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin,
1168 enum dpll_pin_state state,
1169 struct netlink_ext_ack *extack)
1170 {
1171 const struct dpll_pin_ops *ops;
1172 struct dpll_pin_ref *ref;
1173 int ret;
1174
1175 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
1176 pin->prop.capabilities)) {
1177 NL_SET_ERR_MSG(extack, "state changing is not allowed");
1178 return -EOPNOTSUPP;
1179 }
1180 ref = xa_load(&pin->dpll_refs, dpll->id);
1181 ASSERT_NOT_NULL(ref);
1182 ops = dpll_pin_ops(ref);
1183 if (!ops->state_on_dpll_set)
1184 return -EOPNOTSUPP;
1185 ret = ops->state_on_dpll_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
1186 dpll, dpll_priv(dpll), state, extack);
1187 if (ret)
1188 return ret;
1189 __dpll_pin_change_ntf(pin);
1190
1191 return 0;
1192 }
1193
1194 static int
dpll_pin_prio_set(struct dpll_device * dpll,struct dpll_pin * pin,u32 prio,struct netlink_ext_ack * extack)1195 dpll_pin_prio_set(struct dpll_device *dpll, struct dpll_pin *pin,
1196 u32 prio, struct netlink_ext_ack *extack)
1197 {
1198 const struct dpll_pin_ops *ops;
1199 struct dpll_pin_ref *ref;
1200 int ret;
1201
1202 if (!(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE &
1203 pin->prop.capabilities)) {
1204 NL_SET_ERR_MSG(extack, "prio changing is not allowed");
1205 return -EOPNOTSUPP;
1206 }
1207 ref = xa_load(&pin->dpll_refs, dpll->id);
1208 ASSERT_NOT_NULL(ref);
1209 ops = dpll_pin_ops(ref);
1210 if (!ops->prio_set)
1211 return -EOPNOTSUPP;
1212 ret = ops->prio_set(pin, dpll_pin_on_dpll_priv(dpll, pin), dpll,
1213 dpll_priv(dpll), prio, extack);
1214 if (ret)
1215 return ret;
1216 __dpll_pin_change_ntf(pin);
1217
1218 return 0;
1219 }
1220
1221 static int
dpll_pin_direction_set(struct dpll_pin * pin,struct dpll_device * dpll,enum dpll_pin_direction direction,struct netlink_ext_ack * extack)1222 dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll,
1223 enum dpll_pin_direction direction,
1224 struct netlink_ext_ack *extack)
1225 {
1226 const struct dpll_pin_ops *ops;
1227 struct dpll_pin_ref *ref;
1228 int ret;
1229
1230 if (!(DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE &
1231 pin->prop.capabilities)) {
1232 NL_SET_ERR_MSG(extack, "direction changing is not allowed");
1233 return -EOPNOTSUPP;
1234 }
1235 ref = xa_load(&pin->dpll_refs, dpll->id);
1236 ASSERT_NOT_NULL(ref);
1237 ops = dpll_pin_ops(ref);
1238 if (!ops->direction_set)
1239 return -EOPNOTSUPP;
1240 ret = ops->direction_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
1241 dpll, dpll_priv(dpll), direction, extack);
1242 if (ret)
1243 return ret;
1244 __dpll_pin_change_ntf(pin);
1245
1246 return 0;
1247 }
1248
1249 static int
dpll_pin_phase_adj_set(struct dpll_pin * pin,struct nlattr * phase_adj_attr,struct netlink_ext_ack * extack)1250 dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr,
1251 struct netlink_ext_ack *extack)
1252 {
1253 struct dpll_pin_ref *ref, *failed;
1254 const struct dpll_pin_ops *ops;
1255 s32 phase_adj, old_phase_adj;
1256 struct dpll_device *dpll;
1257 unsigned long i;
1258 int ret;
1259
1260 phase_adj = nla_get_s32(phase_adj_attr);
1261 if (phase_adj > pin->prop.phase_range.max ||
1262 phase_adj < pin->prop.phase_range.min) {
1263 NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr,
1264 "phase adjust value not supported");
1265 return -EINVAL;
1266 }
1267
1268 xa_for_each(&pin->dpll_refs, i, ref) {
1269 ops = dpll_pin_ops(ref);
1270 if (!ops->phase_adjust_set || !ops->phase_adjust_get) {
1271 NL_SET_ERR_MSG(extack, "phase adjust not supported");
1272 return -EOPNOTSUPP;
1273 }
1274 }
1275 ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
1276 ops = dpll_pin_ops(ref);
1277 dpll = ref->dpll;
1278 ret = ops->phase_adjust_get(pin, dpll_pin_on_dpll_priv(dpll, pin),
1279 dpll, dpll_priv(dpll), &old_phase_adj,
1280 extack);
1281 if (ret) {
1282 NL_SET_ERR_MSG(extack, "unable to get old phase adjust value");
1283 return ret;
1284 }
1285 if (phase_adj == old_phase_adj)
1286 return 0;
1287
1288 xa_for_each(&pin->dpll_refs, i, ref) {
1289 ops = dpll_pin_ops(ref);
1290 dpll = ref->dpll;
1291 ret = ops->phase_adjust_set(pin,
1292 dpll_pin_on_dpll_priv(dpll, pin),
1293 dpll, dpll_priv(dpll), phase_adj,
1294 extack);
1295 if (ret) {
1296 failed = ref;
1297 NL_SET_ERR_MSG_FMT(extack,
1298 "phase adjust set failed for dpll_id:%u",
1299 dpll->id);
1300 goto rollback;
1301 }
1302 }
1303 __dpll_pin_change_ntf(pin);
1304
1305 return 0;
1306
1307 rollback:
1308 xa_for_each(&pin->dpll_refs, i, ref) {
1309 if (ref == failed)
1310 break;
1311 ops = dpll_pin_ops(ref);
1312 dpll = ref->dpll;
1313 if (ops->phase_adjust_set(pin, dpll_pin_on_dpll_priv(dpll, pin),
1314 dpll, dpll_priv(dpll), old_phase_adj,
1315 extack))
1316 NL_SET_ERR_MSG(extack, "set phase adjust rollback failed");
1317 }
1318 return ret;
1319 }
1320
1321 static int
dpll_pin_parent_device_set(struct dpll_pin * pin,struct nlattr * parent_nest,struct netlink_ext_ack * extack)1322 dpll_pin_parent_device_set(struct dpll_pin *pin, struct nlattr *parent_nest,
1323 struct netlink_ext_ack *extack)
1324 {
1325 struct nlattr *tb[DPLL_A_PIN_MAX + 1];
1326 enum dpll_pin_direction direction;
1327 enum dpll_pin_state state;
1328 struct dpll_pin_ref *ref;
1329 struct dpll_device *dpll;
1330 u32 pdpll_idx, prio;
1331 int ret;
1332
1333 nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
1334 dpll_pin_parent_device_nl_policy, extack);
1335 if (!tb[DPLL_A_PIN_PARENT_ID]) {
1336 NL_SET_ERR_MSG(extack, "device parent id expected");
1337 return -EINVAL;
1338 }
1339 pdpll_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
1340 dpll = xa_load(&dpll_device_xa, pdpll_idx);
1341 if (!dpll) {
1342 NL_SET_ERR_MSG(extack, "parent device not found");
1343 return -EINVAL;
1344 }
1345 ref = xa_load(&pin->dpll_refs, dpll->id);
1346 if (!ref) {
1347 NL_SET_ERR_MSG(extack, "pin not connected to given parent device");
1348 return -EINVAL;
1349 }
1350 if (tb[DPLL_A_PIN_STATE]) {
1351 state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
1352 ret = dpll_pin_state_set(dpll, pin, state, extack);
1353 if (ret)
1354 return ret;
1355 }
1356 if (tb[DPLL_A_PIN_PRIO]) {
1357 prio = nla_get_u32(tb[DPLL_A_PIN_PRIO]);
1358 ret = dpll_pin_prio_set(dpll, pin, prio, extack);
1359 if (ret)
1360 return ret;
1361 }
1362 if (tb[DPLL_A_PIN_DIRECTION]) {
1363 direction = nla_get_u32(tb[DPLL_A_PIN_DIRECTION]);
1364 ret = dpll_pin_direction_set(pin, dpll, direction, extack);
1365 if (ret)
1366 return ret;
1367 }
1368 return 0;
1369 }
1370
1371 static int
dpll_pin_parent_pin_set(struct dpll_pin * pin,struct nlattr * parent_nest,struct netlink_ext_ack * extack)1372 dpll_pin_parent_pin_set(struct dpll_pin *pin, struct nlattr *parent_nest,
1373 struct netlink_ext_ack *extack)
1374 {
1375 struct nlattr *tb[DPLL_A_PIN_MAX + 1];
1376 u32 ppin_idx;
1377 int ret;
1378
1379 nla_parse_nested(tb, DPLL_A_PIN_MAX, parent_nest,
1380 dpll_pin_parent_pin_nl_policy, extack);
1381 if (!tb[DPLL_A_PIN_PARENT_ID]) {
1382 NL_SET_ERR_MSG(extack, "device parent id expected");
1383 return -EINVAL;
1384 }
1385 ppin_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
1386
1387 if (tb[DPLL_A_PIN_STATE]) {
1388 enum dpll_pin_state state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
1389
1390 ret = dpll_pin_on_pin_state_set(pin, ppin_idx, state, extack);
1391 if (ret)
1392 return ret;
1393 }
1394
1395 return 0;
1396 }
1397
1398 static int
dpll_pin_set_from_nlattr(struct dpll_pin * pin,struct genl_info * info)1399 dpll_pin_set_from_nlattr(struct dpll_pin *pin, struct genl_info *info)
1400 {
1401 struct nlattr *a;
1402 int rem, ret;
1403
1404 nla_for_each_attr(a, genlmsg_data(info->genlhdr),
1405 genlmsg_len(info->genlhdr), rem) {
1406 switch (nla_type(a)) {
1407 case DPLL_A_PIN_FREQUENCY:
1408 ret = dpll_pin_freq_set(pin, a, info->extack);
1409 if (ret)
1410 return ret;
1411 break;
1412 case DPLL_A_PIN_PHASE_ADJUST:
1413 ret = dpll_pin_phase_adj_set(pin, a, info->extack);
1414 if (ret)
1415 return ret;
1416 break;
1417 case DPLL_A_PIN_PARENT_DEVICE:
1418 ret = dpll_pin_parent_device_set(pin, a, info->extack);
1419 if (ret)
1420 return ret;
1421 break;
1422 case DPLL_A_PIN_PARENT_PIN:
1423 ret = dpll_pin_parent_pin_set(pin, a, info->extack);
1424 if (ret)
1425 return ret;
1426 break;
1427 case DPLL_A_PIN_ESYNC_FREQUENCY:
1428 ret = dpll_pin_esync_set(pin, a, info->extack);
1429 if (ret)
1430 return ret;
1431 break;
1432 case DPLL_A_PIN_REFERENCE_SYNC:
1433 ret = dpll_pin_ref_sync_set(pin, a, info->extack);
1434 if (ret)
1435 return ret;
1436 break;
1437 }
1438 }
1439
1440 return 0;
1441 }
1442
1443 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)1444 dpll_pin_find(u64 clock_id, struct nlattr *mod_name_attr,
1445 enum dpll_pin_type type, struct nlattr *board_label,
1446 struct nlattr *panel_label, struct nlattr *package_label,
1447 struct netlink_ext_ack *extack)
1448 {
1449 bool board_match, panel_match, package_match;
1450 struct dpll_pin *pin_match = NULL, *pin;
1451 const struct dpll_pin_properties *prop;
1452 bool cid_match, mod_match, type_match;
1453 unsigned long i;
1454
1455 xa_for_each_marked(&dpll_pin_xa, i, pin, DPLL_REGISTERED) {
1456 prop = &pin->prop;
1457 cid_match = clock_id ? pin->clock_id == clock_id : true;
1458 mod_match = mod_name_attr && module_name(pin->module) ?
1459 !nla_strcmp(mod_name_attr,
1460 module_name(pin->module)) : true;
1461 type_match = type ? prop->type == type : true;
1462 board_match = board_label ? (prop->board_label ?
1463 !nla_strcmp(board_label, prop->board_label) : false) :
1464 true;
1465 panel_match = panel_label ? (prop->panel_label ?
1466 !nla_strcmp(panel_label, prop->panel_label) : false) :
1467 true;
1468 package_match = package_label ? (prop->package_label ?
1469 !nla_strcmp(package_label, prop->package_label) :
1470 false) : true;
1471 if (cid_match && mod_match && type_match && board_match &&
1472 panel_match && package_match) {
1473 if (pin_match) {
1474 NL_SET_ERR_MSG(extack, "multiple matches");
1475 return ERR_PTR(-EINVAL);
1476 }
1477 pin_match = pin;
1478 }
1479 }
1480 if (!pin_match) {
1481 NL_SET_ERR_MSG(extack, "not found");
1482 return ERR_PTR(-ENODEV);
1483 }
1484 return pin_match;
1485 }
1486
dpll_pin_find_from_nlattr(struct genl_info * info)1487 static struct dpll_pin *dpll_pin_find_from_nlattr(struct genl_info *info)
1488 {
1489 struct nlattr *attr, *mod_name_attr = NULL, *board_label_attr = NULL,
1490 *panel_label_attr = NULL, *package_label_attr = NULL;
1491 enum dpll_pin_type type = 0;
1492 u64 clock_id = 0;
1493 int rem = 0;
1494
1495 nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
1496 genlmsg_len(info->genlhdr), rem) {
1497 switch (nla_type(attr)) {
1498 case DPLL_A_PIN_CLOCK_ID:
1499 if (clock_id)
1500 goto duplicated_attr;
1501 clock_id = nla_get_u64(attr);
1502 break;
1503 case DPLL_A_PIN_MODULE_NAME:
1504 if (mod_name_attr)
1505 goto duplicated_attr;
1506 mod_name_attr = attr;
1507 break;
1508 case DPLL_A_PIN_TYPE:
1509 if (type)
1510 goto duplicated_attr;
1511 type = nla_get_u32(attr);
1512 break;
1513 case DPLL_A_PIN_BOARD_LABEL:
1514 if (board_label_attr)
1515 goto duplicated_attr;
1516 board_label_attr = attr;
1517 break;
1518 case DPLL_A_PIN_PANEL_LABEL:
1519 if (panel_label_attr)
1520 goto duplicated_attr;
1521 panel_label_attr = attr;
1522 break;
1523 case DPLL_A_PIN_PACKAGE_LABEL:
1524 if (package_label_attr)
1525 goto duplicated_attr;
1526 package_label_attr = attr;
1527 break;
1528 default:
1529 break;
1530 }
1531 }
1532 if (!(clock_id || mod_name_attr || board_label_attr ||
1533 panel_label_attr || package_label_attr)) {
1534 NL_SET_ERR_MSG(info->extack, "missing attributes");
1535 return ERR_PTR(-EINVAL);
1536 }
1537 return dpll_pin_find(clock_id, mod_name_attr, type, board_label_attr,
1538 panel_label_attr, package_label_attr,
1539 info->extack);
1540 duplicated_attr:
1541 NL_SET_ERR_MSG(info->extack, "duplicated attribute");
1542 return ERR_PTR(-EINVAL);
1543 }
1544
dpll_nl_pin_id_get_doit(struct sk_buff * skb,struct genl_info * info)1545 int dpll_nl_pin_id_get_doit(struct sk_buff *skb, struct genl_info *info)
1546 {
1547 struct dpll_pin *pin;
1548 struct sk_buff *msg;
1549 struct nlattr *hdr;
1550 int ret;
1551
1552 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1553 if (!msg)
1554 return -ENOMEM;
1555 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1556 DPLL_CMD_PIN_ID_GET);
1557 if (!hdr) {
1558 nlmsg_free(msg);
1559 return -EMSGSIZE;
1560 }
1561 pin = dpll_pin_find_from_nlattr(info);
1562 if (!IS_ERR(pin)) {
1563 if (!dpll_pin_available(pin)) {
1564 nlmsg_free(msg);
1565 return -ENODEV;
1566 }
1567 ret = dpll_msg_add_pin_handle(msg, pin);
1568 if (ret) {
1569 nlmsg_free(msg);
1570 return ret;
1571 }
1572 }
1573 genlmsg_end(msg, hdr);
1574
1575 return genlmsg_reply(msg, info);
1576 }
1577
dpll_nl_pin_get_doit(struct sk_buff * skb,struct genl_info * info)1578 int dpll_nl_pin_get_doit(struct sk_buff *skb, struct genl_info *info)
1579 {
1580 struct dpll_pin *pin = info->user_ptr[0];
1581 struct sk_buff *msg;
1582 struct nlattr *hdr;
1583 int ret;
1584
1585 if (!pin)
1586 return -ENODEV;
1587 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1588 if (!msg)
1589 return -ENOMEM;
1590 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1591 DPLL_CMD_PIN_GET);
1592 if (!hdr) {
1593 nlmsg_free(msg);
1594 return -EMSGSIZE;
1595 }
1596 ret = dpll_cmd_pin_get_one(msg, pin, info->extack);
1597 if (ret) {
1598 nlmsg_free(msg);
1599 return ret;
1600 }
1601 genlmsg_end(msg, hdr);
1602
1603 return genlmsg_reply(msg, info);
1604 }
1605
dpll_nl_pin_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)1606 int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
1607 {
1608 struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
1609 struct dpll_pin *pin;
1610 struct nlattr *hdr;
1611 unsigned long i;
1612 int ret = 0;
1613
1614 mutex_lock(&dpll_lock);
1615 xa_for_each_marked_start(&dpll_pin_xa, i, pin, DPLL_REGISTERED,
1616 ctx->idx) {
1617 if (!dpll_pin_available(pin))
1618 continue;
1619 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1620 cb->nlh->nlmsg_seq,
1621 &dpll_nl_family, NLM_F_MULTI,
1622 DPLL_CMD_PIN_GET);
1623 if (!hdr) {
1624 ret = -EMSGSIZE;
1625 break;
1626 }
1627 ret = dpll_cmd_pin_get_one(skb, pin, cb->extack);
1628 if (ret) {
1629 genlmsg_cancel(skb, hdr);
1630 break;
1631 }
1632 genlmsg_end(skb, hdr);
1633 }
1634 mutex_unlock(&dpll_lock);
1635
1636 if (ret == -EMSGSIZE) {
1637 ctx->idx = i;
1638 return skb->len;
1639 }
1640 return ret;
1641 }
1642
dpll_nl_pin_set_doit(struct sk_buff * skb,struct genl_info * info)1643 int dpll_nl_pin_set_doit(struct sk_buff *skb, struct genl_info *info)
1644 {
1645 struct dpll_pin *pin = info->user_ptr[0];
1646
1647 return dpll_pin_set_from_nlattr(pin, info);
1648 }
1649
1650 static struct dpll_device *
dpll_device_find(u64 clock_id,struct nlattr * mod_name_attr,enum dpll_type type,struct netlink_ext_ack * extack)1651 dpll_device_find(u64 clock_id, struct nlattr *mod_name_attr,
1652 enum dpll_type type, struct netlink_ext_ack *extack)
1653 {
1654 struct dpll_device *dpll_match = NULL, *dpll;
1655 bool cid_match, mod_match, type_match;
1656 unsigned long i;
1657
1658 xa_for_each_marked(&dpll_device_xa, i, dpll, DPLL_REGISTERED) {
1659 cid_match = clock_id ? dpll->clock_id == clock_id : true;
1660 mod_match = mod_name_attr ? (module_name(dpll->module) ?
1661 !nla_strcmp(mod_name_attr,
1662 module_name(dpll->module)) : false) : true;
1663 type_match = type ? dpll->type == type : true;
1664 if (cid_match && mod_match && type_match) {
1665 if (dpll_match) {
1666 NL_SET_ERR_MSG(extack, "multiple matches");
1667 return ERR_PTR(-EINVAL);
1668 }
1669 dpll_match = dpll;
1670 }
1671 }
1672 if (!dpll_match) {
1673 NL_SET_ERR_MSG(extack, "not found");
1674 return ERR_PTR(-ENODEV);
1675 }
1676
1677 return dpll_match;
1678 }
1679
1680 static struct dpll_device *
dpll_device_find_from_nlattr(struct genl_info * info)1681 dpll_device_find_from_nlattr(struct genl_info *info)
1682 {
1683 struct nlattr *attr, *mod_name_attr = NULL;
1684 enum dpll_type type = 0;
1685 u64 clock_id = 0;
1686 int rem = 0;
1687
1688 nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
1689 genlmsg_len(info->genlhdr), rem) {
1690 switch (nla_type(attr)) {
1691 case DPLL_A_CLOCK_ID:
1692 if (clock_id)
1693 goto duplicated_attr;
1694 clock_id = nla_get_u64(attr);
1695 break;
1696 case DPLL_A_MODULE_NAME:
1697 if (mod_name_attr)
1698 goto duplicated_attr;
1699 mod_name_attr = attr;
1700 break;
1701 case DPLL_A_TYPE:
1702 if (type)
1703 goto duplicated_attr;
1704 type = nla_get_u32(attr);
1705 break;
1706 default:
1707 break;
1708 }
1709 }
1710 if (!clock_id && !mod_name_attr && !type) {
1711 NL_SET_ERR_MSG(info->extack, "missing attributes");
1712 return ERR_PTR(-EINVAL);
1713 }
1714 return dpll_device_find(clock_id, mod_name_attr, type, info->extack);
1715 duplicated_attr:
1716 NL_SET_ERR_MSG(info->extack, "duplicated attribute");
1717 return ERR_PTR(-EINVAL);
1718 }
1719
dpll_nl_device_id_get_doit(struct sk_buff * skb,struct genl_info * info)1720 int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info)
1721 {
1722 struct dpll_device *dpll;
1723 struct sk_buff *msg;
1724 struct nlattr *hdr;
1725 int ret;
1726
1727 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1728 if (!msg)
1729 return -ENOMEM;
1730 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1731 DPLL_CMD_DEVICE_ID_GET);
1732 if (!hdr) {
1733 nlmsg_free(msg);
1734 return -EMSGSIZE;
1735 }
1736
1737 dpll = dpll_device_find_from_nlattr(info);
1738 if (!IS_ERR(dpll)) {
1739 ret = dpll_msg_add_dev_handle(msg, dpll);
1740 if (ret) {
1741 nlmsg_free(msg);
1742 return ret;
1743 }
1744 }
1745 genlmsg_end(msg, hdr);
1746
1747 return genlmsg_reply(msg, info);
1748 }
1749
dpll_nl_device_get_doit(struct sk_buff * skb,struct genl_info * info)1750 int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info)
1751 {
1752 struct dpll_device *dpll = info->user_ptr[0];
1753 struct sk_buff *msg;
1754 struct nlattr *hdr;
1755 int ret;
1756
1757 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1758 if (!msg)
1759 return -ENOMEM;
1760 hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
1761 DPLL_CMD_DEVICE_GET);
1762 if (!hdr) {
1763 nlmsg_free(msg);
1764 return -EMSGSIZE;
1765 }
1766
1767 ret = dpll_device_get_one(dpll, msg, info->extack);
1768 if (ret) {
1769 nlmsg_free(msg);
1770 return ret;
1771 }
1772 genlmsg_end(msg, hdr);
1773
1774 return genlmsg_reply(msg, info);
1775 }
1776
1777 static int
dpll_set_from_nlattr(struct dpll_device * dpll,struct genl_info * info)1778 dpll_set_from_nlattr(struct dpll_device *dpll, struct genl_info *info)
1779 {
1780 struct nlattr *a;
1781 int rem, ret;
1782
1783 nla_for_each_attr(a, genlmsg_data(info->genlhdr),
1784 genlmsg_len(info->genlhdr), rem) {
1785 switch (nla_type(a)) {
1786 case DPLL_A_PHASE_OFFSET_MONITOR:
1787 ret = dpll_phase_offset_monitor_set(dpll, a,
1788 info->extack);
1789 if (ret)
1790 return ret;
1791 break;
1792 case DPLL_A_PHASE_OFFSET_AVG_FACTOR:
1793 ret = dpll_phase_offset_avg_factor_set(dpll, a,
1794 info->extack);
1795 if (ret)
1796 return ret;
1797 break;
1798 }
1799 }
1800
1801 return 0;
1802 }
1803
dpll_nl_device_set_doit(struct sk_buff * skb,struct genl_info * info)1804 int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info)
1805 {
1806 struct dpll_device *dpll = info->user_ptr[0];
1807
1808 return dpll_set_from_nlattr(dpll, info);
1809 }
1810
dpll_nl_device_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)1811 int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
1812 {
1813 struct dpll_dump_ctx *ctx = dpll_dump_context(cb);
1814 struct dpll_device *dpll;
1815 struct nlattr *hdr;
1816 unsigned long i;
1817 int ret = 0;
1818
1819 mutex_lock(&dpll_lock);
1820 xa_for_each_marked_start(&dpll_device_xa, i, dpll, DPLL_REGISTERED,
1821 ctx->idx) {
1822 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1823 cb->nlh->nlmsg_seq, &dpll_nl_family,
1824 NLM_F_MULTI, DPLL_CMD_DEVICE_GET);
1825 if (!hdr) {
1826 ret = -EMSGSIZE;
1827 break;
1828 }
1829 ret = dpll_device_get_one(dpll, skb, cb->extack);
1830 if (ret) {
1831 genlmsg_cancel(skb, hdr);
1832 break;
1833 }
1834 genlmsg_end(skb, hdr);
1835 }
1836 mutex_unlock(&dpll_lock);
1837
1838 if (ret == -EMSGSIZE) {
1839 ctx->idx = i;
1840 return skb->len;
1841 }
1842 return ret;
1843 }
1844
dpll_pre_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1845 int dpll_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1846 struct genl_info *info)
1847 {
1848 u32 id;
1849
1850 if (GENL_REQ_ATTR_CHECK(info, DPLL_A_ID))
1851 return -EINVAL;
1852
1853 mutex_lock(&dpll_lock);
1854 id = nla_get_u32(info->attrs[DPLL_A_ID]);
1855 info->user_ptr[0] = dpll_device_get_by_id(id);
1856 if (!info->user_ptr[0]) {
1857 NL_SET_ERR_MSG(info->extack, "device not found");
1858 goto unlock;
1859 }
1860 return 0;
1861 unlock:
1862 mutex_unlock(&dpll_lock);
1863 return -ENODEV;
1864 }
1865
dpll_post_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1866 void dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1867 struct genl_info *info)
1868 {
1869 mutex_unlock(&dpll_lock);
1870 }
1871
1872 int
dpll_lock_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1873 dpll_lock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1874 struct genl_info *info)
1875 {
1876 mutex_lock(&dpll_lock);
1877
1878 return 0;
1879 }
1880
1881 void
dpll_unlock_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1882 dpll_unlock_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1883 struct genl_info *info)
1884 {
1885 mutex_unlock(&dpll_lock);
1886 }
1887
dpll_pin_pre_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1888 int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1889 struct genl_info *info)
1890 {
1891 int ret;
1892
1893 mutex_lock(&dpll_lock);
1894 if (GENL_REQ_ATTR_CHECK(info, DPLL_A_PIN_ID)) {
1895 ret = -EINVAL;
1896 goto unlock_dev;
1897 }
1898 info->user_ptr[0] = xa_load(&dpll_pin_xa,
1899 nla_get_u32(info->attrs[DPLL_A_PIN_ID]));
1900 if (!info->user_ptr[0] ||
1901 !dpll_pin_available(info->user_ptr[0])) {
1902 NL_SET_ERR_MSG(info->extack, "pin not found");
1903 ret = -ENODEV;
1904 goto unlock_dev;
1905 }
1906
1907 return 0;
1908
1909 unlock_dev:
1910 mutex_unlock(&dpll_lock);
1911 return ret;
1912 }
1913
dpll_pin_post_doit(const struct genl_split_ops * ops,struct sk_buff * skb,struct genl_info * info)1914 void dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
1915 struct genl_info *info)
1916 {
1917 mutex_unlock(&dpll_lock);
1918 }
1919