Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/dpll/dpll_netlink.c
26278 views
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
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
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
43
dpll_msg_add_dev_parent_handle(struct sk_buff *msg, u32 id)
44
{
45
if (nla_put_u32(msg, DPLL_A_PIN_PARENT_ID, id))
46
return -EMSGSIZE;
47
48
return 0;
49
}
50
51
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
*/
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
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
*/
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
*/
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
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
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
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
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
*/
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
1868