Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/dpll/dpll_netlink.c
29267 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_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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
*/
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
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
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
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
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
*/
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
1920