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