Merge tag 'qcom-arm64-fixes-for-6.8' of https://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / drivers / dpll / dpll_core.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  dpll_core.c - DPLL subsystem kernel-space interface implementation.
4  *
5  *  Copyright (c) 2023 Meta Platforms, Inc. and affiliates
6  *  Copyright (c) 2023 Intel Corporation.
7  */
8
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11 #include <linux/device.h>
12 #include <linux/err.h>
13 #include <linux/slab.h>
14 #include <linux/string.h>
15
16 #include "dpll_core.h"
17 #include "dpll_netlink.h"
18
19 /* Mutex lock to protect DPLL subsystem devices and pins */
20 DEFINE_MUTEX(dpll_lock);
21
22 DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC);
23 DEFINE_XARRAY_FLAGS(dpll_pin_xa, XA_FLAGS_ALLOC);
24
25 static u32 dpll_device_xa_id;
26 static u32 dpll_pin_xa_id;
27
28 #define ASSERT_DPLL_REGISTERED(d)       \
29         WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
30 #define ASSERT_DPLL_NOT_REGISTERED(d)   \
31         WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
32
33 struct dpll_device_registration {
34         struct list_head list;
35         const struct dpll_device_ops *ops;
36         void *priv;
37 };
38
39 struct dpll_pin_registration {
40         struct list_head list;
41         const struct dpll_pin_ops *ops;
42         void *priv;
43 };
44
45 struct dpll_pin *netdev_dpll_pin(const struct net_device *dev)
46 {
47         return rcu_dereference_rtnl(dev->dpll_pin);
48 }
49
50 struct dpll_device *dpll_device_get_by_id(int id)
51 {
52         if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED))
53                 return xa_load(&dpll_device_xa, id);
54
55         return NULL;
56 }
57
58 static struct dpll_pin_registration *
59 dpll_pin_registration_find(struct dpll_pin_ref *ref,
60                            const struct dpll_pin_ops *ops, void *priv)
61 {
62         struct dpll_pin_registration *reg;
63
64         list_for_each_entry(reg, &ref->registration_list, list) {
65                 if (reg->ops == ops && reg->priv == priv)
66                         return reg;
67         }
68         return NULL;
69 }
70
71 static int
72 dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
73                     const struct dpll_pin_ops *ops, void *priv)
74 {
75         struct dpll_pin_registration *reg;
76         struct dpll_pin_ref *ref;
77         bool ref_exists = false;
78         unsigned long i;
79         int ret;
80
81         xa_for_each(xa_pins, i, ref) {
82                 if (ref->pin != pin)
83                         continue;
84                 reg = dpll_pin_registration_find(ref, ops, priv);
85                 if (reg) {
86                         refcount_inc(&ref->refcount);
87                         return 0;
88                 }
89                 ref_exists = true;
90                 break;
91         }
92
93         if (!ref_exists) {
94                 ref = kzalloc(sizeof(*ref), GFP_KERNEL);
95                 if (!ref)
96                         return -ENOMEM;
97                 ref->pin = pin;
98                 INIT_LIST_HEAD(&ref->registration_list);
99                 ret = xa_insert(xa_pins, pin->pin_idx, ref, GFP_KERNEL);
100                 if (ret) {
101                         kfree(ref);
102                         return ret;
103                 }
104                 refcount_set(&ref->refcount, 1);
105         }
106
107         reg = kzalloc(sizeof(*reg), GFP_KERNEL);
108         if (!reg) {
109                 if (!ref_exists) {
110                         xa_erase(xa_pins, pin->pin_idx);
111                         kfree(ref);
112                 }
113                 return -ENOMEM;
114         }
115         reg->ops = ops;
116         reg->priv = priv;
117         if (ref_exists)
118                 refcount_inc(&ref->refcount);
119         list_add_tail(&reg->list, &ref->registration_list);
120
121         return 0;
122 }
123
124 static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
125                                const struct dpll_pin_ops *ops, void *priv)
126 {
127         struct dpll_pin_registration *reg;
128         struct dpll_pin_ref *ref;
129         unsigned long i;
130
131         xa_for_each(xa_pins, i, ref) {
132                 if (ref->pin != pin)
133                         continue;
134                 reg = dpll_pin_registration_find(ref, ops, priv);
135                 if (WARN_ON(!reg))
136                         return -EINVAL;
137                 if (refcount_dec_and_test(&ref->refcount)) {
138                         list_del(&reg->list);
139                         kfree(reg);
140                         xa_erase(xa_pins, i);
141                         WARN_ON(!list_empty(&ref->registration_list));
142                         kfree(ref);
143                 }
144                 return 0;
145         }
146
147         return -EINVAL;
148 }
149
150 static int
151 dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
152                      const struct dpll_pin_ops *ops, void *priv)
153 {
154         struct dpll_pin_registration *reg;
155         struct dpll_pin_ref *ref;
156         bool ref_exists = false;
157         unsigned long i;
158         int ret;
159
160         xa_for_each(xa_dplls, i, ref) {
161                 if (ref->dpll != dpll)
162                         continue;
163                 reg = dpll_pin_registration_find(ref, ops, priv);
164                 if (reg) {
165                         refcount_inc(&ref->refcount);
166                         return 0;
167                 }
168                 ref_exists = true;
169                 break;
170         }
171
172         if (!ref_exists) {
173                 ref = kzalloc(sizeof(*ref), GFP_KERNEL);
174                 if (!ref)
175                         return -ENOMEM;
176                 ref->dpll = dpll;
177                 INIT_LIST_HEAD(&ref->registration_list);
178                 ret = xa_insert(xa_dplls, dpll->id, ref, GFP_KERNEL);
179                 if (ret) {
180                         kfree(ref);
181                         return ret;
182                 }
183                 refcount_set(&ref->refcount, 1);
184         }
185
186         reg = kzalloc(sizeof(*reg), GFP_KERNEL);
187         if (!reg) {
188                 if (!ref_exists) {
189                         xa_erase(xa_dplls, dpll->id);
190                         kfree(ref);
191                 }
192                 return -ENOMEM;
193         }
194         reg->ops = ops;
195         reg->priv = priv;
196         if (ref_exists)
197                 refcount_inc(&ref->refcount);
198         list_add_tail(&reg->list, &ref->registration_list);
199
200         return 0;
201 }
202
203 static void
204 dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll,
205                      const struct dpll_pin_ops *ops, void *priv)
206 {
207         struct dpll_pin_registration *reg;
208         struct dpll_pin_ref *ref;
209         unsigned long i;
210
211         xa_for_each(xa_dplls, i, ref) {
212                 if (ref->dpll != dpll)
213                         continue;
214                 reg = dpll_pin_registration_find(ref, ops, priv);
215                 if (WARN_ON(!reg))
216                         return;
217                 if (refcount_dec_and_test(&ref->refcount)) {
218                         list_del(&reg->list);
219                         kfree(reg);
220                         xa_erase(xa_dplls, i);
221                         WARN_ON(!list_empty(&ref->registration_list));
222                         kfree(ref);
223                 }
224                 return;
225         }
226 }
227
228 struct dpll_pin_ref *dpll_xa_ref_dpll_first(struct xarray *xa_refs)
229 {
230         struct dpll_pin_ref *ref;
231         unsigned long i = 0;
232
233         ref = xa_find(xa_refs, &i, ULONG_MAX, XA_PRESENT);
234         WARN_ON(!ref);
235         return ref;
236 }
237
238 static struct dpll_device *
239 dpll_device_alloc(const u64 clock_id, u32 device_idx, struct module *module)
240 {
241         struct dpll_device *dpll;
242         int ret;
243
244         dpll = kzalloc(sizeof(*dpll), GFP_KERNEL);
245         if (!dpll)
246                 return ERR_PTR(-ENOMEM);
247         refcount_set(&dpll->refcount, 1);
248         INIT_LIST_HEAD(&dpll->registration_list);
249         dpll->device_idx = device_idx;
250         dpll->clock_id = clock_id;
251         dpll->module = module;
252         ret = xa_alloc_cyclic(&dpll_device_xa, &dpll->id, dpll, xa_limit_32b,
253                               &dpll_device_xa_id, GFP_KERNEL);
254         if (ret < 0) {
255                 kfree(dpll);
256                 return ERR_PTR(ret);
257         }
258         xa_init_flags(&dpll->pin_refs, XA_FLAGS_ALLOC);
259
260         return dpll;
261 }
262
263 /**
264  * dpll_device_get - find existing or create new dpll device
265  * @clock_id: clock_id of creator
266  * @device_idx: idx given by device driver
267  * @module: reference to registering module
268  *
269  * Get existing object of a dpll device, unique for given arguments.
270  * Create new if doesn't exist yet.
271  *
272  * Context: Acquires a lock (dpll_lock)
273  * Return:
274  * * valid dpll_device struct pointer if succeeded
275  * * ERR_PTR(X) - error
276  */
277 struct dpll_device *
278 dpll_device_get(u64 clock_id, u32 device_idx, struct module *module)
279 {
280         struct dpll_device *dpll, *ret = NULL;
281         unsigned long index;
282
283         mutex_lock(&dpll_lock);
284         xa_for_each(&dpll_device_xa, index, dpll) {
285                 if (dpll->clock_id == clock_id &&
286                     dpll->device_idx == device_idx &&
287                     dpll->module == module) {
288                         ret = dpll;
289                         refcount_inc(&ret->refcount);
290                         break;
291                 }
292         }
293         if (!ret)
294                 ret = dpll_device_alloc(clock_id, device_idx, module);
295         mutex_unlock(&dpll_lock);
296
297         return ret;
298 }
299 EXPORT_SYMBOL_GPL(dpll_device_get);
300
301 /**
302  * dpll_device_put - decrease the refcount and free memory if possible
303  * @dpll: dpll_device struct pointer
304  *
305  * Context: Acquires a lock (dpll_lock)
306  * Drop reference for a dpll device, if all references are gone, delete
307  * dpll device object.
308  */
309 void dpll_device_put(struct dpll_device *dpll)
310 {
311         mutex_lock(&dpll_lock);
312         if (refcount_dec_and_test(&dpll->refcount)) {
313                 ASSERT_DPLL_NOT_REGISTERED(dpll);
314                 WARN_ON_ONCE(!xa_empty(&dpll->pin_refs));
315                 xa_destroy(&dpll->pin_refs);
316                 xa_erase(&dpll_device_xa, dpll->id);
317                 WARN_ON(!list_empty(&dpll->registration_list));
318                 kfree(dpll);
319         }
320         mutex_unlock(&dpll_lock);
321 }
322 EXPORT_SYMBOL_GPL(dpll_device_put);
323
324 static struct dpll_device_registration *
325 dpll_device_registration_find(struct dpll_device *dpll,
326                               const struct dpll_device_ops *ops, void *priv)
327 {
328         struct dpll_device_registration *reg;
329
330         list_for_each_entry(reg, &dpll->registration_list, list) {
331                 if (reg->ops == ops && reg->priv == priv)
332                         return reg;
333         }
334         return NULL;
335 }
336
337 /**
338  * dpll_device_register - register the dpll device in the subsystem
339  * @dpll: pointer to a dpll
340  * @type: type of a dpll
341  * @ops: ops for a dpll device
342  * @priv: pointer to private information of owner
343  *
344  * Make dpll device available for user space.
345  *
346  * Context: Acquires a lock (dpll_lock)
347  * Return:
348  * * 0 on success
349  * * negative - error value
350  */
351 int dpll_device_register(struct dpll_device *dpll, enum dpll_type type,
352                          const struct dpll_device_ops *ops, void *priv)
353 {
354         struct dpll_device_registration *reg;
355         bool first_registration = false;
356
357         if (WARN_ON(!ops))
358                 return -EINVAL;
359         if (WARN_ON(!ops->mode_get))
360                 return -EINVAL;
361         if (WARN_ON(!ops->lock_status_get))
362                 return -EINVAL;
363         if (WARN_ON(type < DPLL_TYPE_PPS || type > DPLL_TYPE_MAX))
364                 return -EINVAL;
365
366         mutex_lock(&dpll_lock);
367         reg = dpll_device_registration_find(dpll, ops, priv);
368         if (reg) {
369                 mutex_unlock(&dpll_lock);
370                 return -EEXIST;
371         }
372
373         reg = kzalloc(sizeof(*reg), GFP_KERNEL);
374         if (!reg) {
375                 mutex_unlock(&dpll_lock);
376                 return -ENOMEM;
377         }
378         reg->ops = ops;
379         reg->priv = priv;
380         dpll->type = type;
381         first_registration = list_empty(&dpll->registration_list);
382         list_add_tail(&reg->list, &dpll->registration_list);
383         if (!first_registration) {
384                 mutex_unlock(&dpll_lock);
385                 return 0;
386         }
387
388         xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
389         dpll_device_create_ntf(dpll);
390         mutex_unlock(&dpll_lock);
391
392         return 0;
393 }
394 EXPORT_SYMBOL_GPL(dpll_device_register);
395
396 /**
397  * dpll_device_unregister - unregister dpll device
398  * @dpll: registered dpll pointer
399  * @ops: ops for a dpll device
400  * @priv: pointer to private information of owner
401  *
402  * Unregister device, make it unavailable for userspace.
403  * Note: It does not free the memory
404  * Context: Acquires a lock (dpll_lock)
405  */
406 void dpll_device_unregister(struct dpll_device *dpll,
407                             const struct dpll_device_ops *ops, void *priv)
408 {
409         struct dpll_device_registration *reg;
410
411         mutex_lock(&dpll_lock);
412         ASSERT_DPLL_REGISTERED(dpll);
413         dpll_device_delete_ntf(dpll);
414         reg = dpll_device_registration_find(dpll, ops, priv);
415         if (WARN_ON(!reg)) {
416                 mutex_unlock(&dpll_lock);
417                 return;
418         }
419         list_del(&reg->list);
420         kfree(reg);
421
422         if (!list_empty(&dpll->registration_list)) {
423                 mutex_unlock(&dpll_lock);
424                 return;
425         }
426         xa_clear_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED);
427         mutex_unlock(&dpll_lock);
428 }
429 EXPORT_SYMBOL_GPL(dpll_device_unregister);
430
431 static void dpll_pin_prop_free(struct dpll_pin_properties *prop)
432 {
433         kfree(prop->package_label);
434         kfree(prop->panel_label);
435         kfree(prop->board_label);
436         kfree(prop->freq_supported);
437 }
438
439 static int dpll_pin_prop_dup(const struct dpll_pin_properties *src,
440                              struct dpll_pin_properties *dst)
441 {
442         memcpy(dst, src, sizeof(*dst));
443         if (src->freq_supported && src->freq_supported_num) {
444                 size_t freq_size = src->freq_supported_num *
445                                    sizeof(*src->freq_supported);
446                 dst->freq_supported = kmemdup(src->freq_supported,
447                                               freq_size, GFP_KERNEL);
448                 if (!src->freq_supported)
449                         return -ENOMEM;
450         }
451         if (src->board_label) {
452                 dst->board_label = kstrdup(src->board_label, GFP_KERNEL);
453                 if (!dst->board_label)
454                         goto err_board_label;
455         }
456         if (src->panel_label) {
457                 dst->panel_label = kstrdup(src->panel_label, GFP_KERNEL);
458                 if (!dst->panel_label)
459                         goto err_panel_label;
460         }
461         if (src->package_label) {
462                 dst->package_label = kstrdup(src->package_label, GFP_KERNEL);
463                 if (!dst->package_label)
464                         goto err_package_label;
465         }
466
467         return 0;
468
469 err_package_label:
470         kfree(dst->panel_label);
471 err_panel_label:
472         kfree(dst->board_label);
473 err_board_label:
474         kfree(dst->freq_supported);
475         return -ENOMEM;
476 }
477
478 static struct dpll_pin *
479 dpll_pin_alloc(u64 clock_id, u32 pin_idx, struct module *module,
480                const struct dpll_pin_properties *prop)
481 {
482         struct dpll_pin *pin;
483         int ret;
484
485         pin = kzalloc(sizeof(*pin), GFP_KERNEL);
486         if (!pin)
487                 return ERR_PTR(-ENOMEM);
488         pin->pin_idx = pin_idx;
489         pin->clock_id = clock_id;
490         pin->module = module;
491         if (WARN_ON(prop->type < DPLL_PIN_TYPE_MUX ||
492                     prop->type > DPLL_PIN_TYPE_MAX)) {
493                 ret = -EINVAL;
494                 goto err_pin_prop;
495         }
496         ret = dpll_pin_prop_dup(prop, &pin->prop);
497         if (ret)
498                 goto err_pin_prop;
499         refcount_set(&pin->refcount, 1);
500         xa_init_flags(&pin->dpll_refs, XA_FLAGS_ALLOC);
501         xa_init_flags(&pin->parent_refs, XA_FLAGS_ALLOC);
502         ret = xa_alloc_cyclic(&dpll_pin_xa, &pin->id, pin, xa_limit_32b,
503                               &dpll_pin_xa_id, GFP_KERNEL);
504         if (ret)
505                 goto err_xa_alloc;
506         return pin;
507 err_xa_alloc:
508         xa_destroy(&pin->dpll_refs);
509         xa_destroy(&pin->parent_refs);
510         dpll_pin_prop_free(&pin->prop);
511 err_pin_prop:
512         kfree(pin);
513         return ERR_PTR(ret);
514 }
515
516 /**
517  * dpll_pin_get - find existing or create new dpll pin
518  * @clock_id: clock_id of creator
519  * @pin_idx: idx given by dev driver
520  * @module: reference to registering module
521  * @prop: dpll pin properties
522  *
523  * Get existing object of a pin (unique for given arguments) or create new
524  * if doesn't exist yet.
525  *
526  * Context: Acquires a lock (dpll_lock)
527  * Return:
528  * * valid allocated dpll_pin struct pointer if succeeded
529  * * ERR_PTR(X) - error
530  */
531 struct dpll_pin *
532 dpll_pin_get(u64 clock_id, u32 pin_idx, struct module *module,
533              const struct dpll_pin_properties *prop)
534 {
535         struct dpll_pin *pos, *ret = NULL;
536         unsigned long i;
537
538         mutex_lock(&dpll_lock);
539         xa_for_each(&dpll_pin_xa, i, pos) {
540                 if (pos->clock_id == clock_id &&
541                     pos->pin_idx == pin_idx &&
542                     pos->module == module) {
543                         ret = pos;
544                         refcount_inc(&ret->refcount);
545                         break;
546                 }
547         }
548         if (!ret)
549                 ret = dpll_pin_alloc(clock_id, pin_idx, module, prop);
550         mutex_unlock(&dpll_lock);
551
552         return ret;
553 }
554 EXPORT_SYMBOL_GPL(dpll_pin_get);
555
556 /**
557  * dpll_pin_put - decrease the refcount and free memory if possible
558  * @pin: pointer to a pin to be put
559  *
560  * Drop reference for a pin, if all references are gone, delete pin object.
561  *
562  * Context: Acquires a lock (dpll_lock)
563  */
564 void dpll_pin_put(struct dpll_pin *pin)
565 {
566         mutex_lock(&dpll_lock);
567         if (refcount_dec_and_test(&pin->refcount)) {
568                 xa_destroy(&pin->dpll_refs);
569                 xa_destroy(&pin->parent_refs);
570                 xa_erase(&dpll_pin_xa, pin->id);
571                 dpll_pin_prop_free(&pin->prop);
572                 kfree_rcu(pin, rcu);
573         }
574         mutex_unlock(&dpll_lock);
575 }
576 EXPORT_SYMBOL_GPL(dpll_pin_put);
577
578 static int
579 __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
580                     const struct dpll_pin_ops *ops, void *priv)
581 {
582         int ret;
583
584         ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv);
585         if (ret)
586                 return ret;
587         ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv);
588         if (ret)
589                 goto ref_pin_del;
590         xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
591         dpll_pin_create_ntf(pin);
592
593         return ret;
594
595 ref_pin_del:
596         dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
597         return ret;
598 }
599
600 /**
601  * dpll_pin_register - register the dpll pin in the subsystem
602  * @dpll: pointer to a dpll
603  * @pin: pointer to a dpll pin
604  * @ops: ops for a dpll pin ops
605  * @priv: pointer to private information of owner
606  *
607  * Context: Acquires a lock (dpll_lock)
608  * Return:
609  * * 0 on success
610  * * negative - error value
611  */
612 int
613 dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
614                   const struct dpll_pin_ops *ops, void *priv)
615 {
616         int ret;
617
618         if (WARN_ON(!ops) ||
619             WARN_ON(!ops->state_on_dpll_get) ||
620             WARN_ON(!ops->direction_get))
621                 return -EINVAL;
622
623         mutex_lock(&dpll_lock);
624         if (WARN_ON(!(dpll->module == pin->module &&
625                       dpll->clock_id == pin->clock_id)))
626                 ret = -EINVAL;
627         else
628                 ret = __dpll_pin_register(dpll, pin, ops, priv);
629         mutex_unlock(&dpll_lock);
630
631         return ret;
632 }
633 EXPORT_SYMBOL_GPL(dpll_pin_register);
634
635 static void
636 __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
637                       const struct dpll_pin_ops *ops, void *priv)
638 {
639         dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
640         dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv);
641         if (xa_empty(&pin->dpll_refs))
642                 xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
643 }
644
645 /**
646  * dpll_pin_unregister - unregister dpll pin from dpll device
647  * @dpll: registered dpll pointer
648  * @pin: pointer to a pin
649  * @ops: ops for a dpll pin
650  * @priv: pointer to private information of owner
651  *
652  * Note: It does not free the memory
653  * Context: Acquires a lock (dpll_lock)
654  */
655 void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
656                          const struct dpll_pin_ops *ops, void *priv)
657 {
658         if (WARN_ON(xa_empty(&dpll->pin_refs)))
659                 return;
660         if (WARN_ON(!xa_empty(&pin->parent_refs)))
661                 return;
662
663         mutex_lock(&dpll_lock);
664         dpll_pin_delete_ntf(pin);
665         __dpll_pin_unregister(dpll, pin, ops, priv);
666         mutex_unlock(&dpll_lock);
667 }
668 EXPORT_SYMBOL_GPL(dpll_pin_unregister);
669
670 /**
671  * dpll_pin_on_pin_register - register a pin with a parent pin
672  * @parent: pointer to a parent pin
673  * @pin: pointer to a pin
674  * @ops: ops for a dpll pin
675  * @priv: pointer to private information of owner
676  *
677  * Register a pin with a parent pin, create references between them and
678  * between newly registered pin and dplls connected with a parent pin.
679  *
680  * Context: Acquires a lock (dpll_lock)
681  * Return:
682  * * 0 on success
683  * * negative - error value
684  */
685 int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
686                              const struct dpll_pin_ops *ops, void *priv)
687 {
688         struct dpll_pin_ref *ref;
689         unsigned long i, stop;
690         int ret;
691
692         if (WARN_ON(parent->prop.type != DPLL_PIN_TYPE_MUX))
693                 return -EINVAL;
694
695         if (WARN_ON(!ops) ||
696             WARN_ON(!ops->state_on_pin_get) ||
697             WARN_ON(!ops->direction_get))
698                 return -EINVAL;
699
700         mutex_lock(&dpll_lock);
701         ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv);
702         if (ret)
703                 goto unlock;
704         refcount_inc(&pin->refcount);
705         xa_for_each(&parent->dpll_refs, i, ref) {
706                 ret = __dpll_pin_register(ref->dpll, pin, ops, priv);
707                 if (ret) {
708                         stop = i;
709                         goto dpll_unregister;
710                 }
711                 dpll_pin_create_ntf(pin);
712         }
713         mutex_unlock(&dpll_lock);
714
715         return ret;
716
717 dpll_unregister:
718         xa_for_each(&parent->dpll_refs, i, ref)
719                 if (i < stop) {
720                         __dpll_pin_unregister(ref->dpll, pin, ops, priv);
721                         dpll_pin_delete_ntf(pin);
722                 }
723         refcount_dec(&pin->refcount);
724         dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
725 unlock:
726         mutex_unlock(&dpll_lock);
727         return ret;
728 }
729 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_register);
730
731 /**
732  * dpll_pin_on_pin_unregister - unregister dpll pin from a parent pin
733  * @parent: pointer to a parent pin
734  * @pin: pointer to a pin
735  * @ops: ops for a dpll pin
736  * @priv: pointer to private information of owner
737  *
738  * Context: Acquires a lock (dpll_lock)
739  * Note: It does not free the memory
740  */
741 void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
742                                 const struct dpll_pin_ops *ops, void *priv)
743 {
744         struct dpll_pin_ref *ref;
745         unsigned long i;
746
747         mutex_lock(&dpll_lock);
748         dpll_pin_delete_ntf(pin);
749         dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
750         refcount_dec(&pin->refcount);
751         xa_for_each(&pin->dpll_refs, i, ref)
752                 __dpll_pin_unregister(ref->dpll, pin, ops, priv);
753         mutex_unlock(&dpll_lock);
754 }
755 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister);
756
757 static struct dpll_device_registration *
758 dpll_device_registration_first(struct dpll_device *dpll)
759 {
760         struct dpll_device_registration *reg;
761
762         reg = list_first_entry_or_null((struct list_head *)&dpll->registration_list,
763                                        struct dpll_device_registration, list);
764         WARN_ON(!reg);
765         return reg;
766 }
767
768 void *dpll_priv(struct dpll_device *dpll)
769 {
770         struct dpll_device_registration *reg;
771
772         reg = dpll_device_registration_first(dpll);
773         return reg->priv;
774 }
775
776 const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll)
777 {
778         struct dpll_device_registration *reg;
779
780         reg = dpll_device_registration_first(dpll);
781         return reg->ops;
782 }
783
784 static struct dpll_pin_registration *
785 dpll_pin_registration_first(struct dpll_pin_ref *ref)
786 {
787         struct dpll_pin_registration *reg;
788
789         reg = list_first_entry_or_null(&ref->registration_list,
790                                        struct dpll_pin_registration, list);
791         WARN_ON(!reg);
792         return reg;
793 }
794
795 void *dpll_pin_on_dpll_priv(struct dpll_device *dpll,
796                             struct dpll_pin *pin)
797 {
798         struct dpll_pin_registration *reg;
799         struct dpll_pin_ref *ref;
800
801         ref = xa_load(&dpll->pin_refs, pin->pin_idx);
802         if (!ref)
803                 return NULL;
804         reg = dpll_pin_registration_first(ref);
805         return reg->priv;
806 }
807
808 void *dpll_pin_on_pin_priv(struct dpll_pin *parent,
809                            struct dpll_pin *pin)
810 {
811         struct dpll_pin_registration *reg;
812         struct dpll_pin_ref *ref;
813
814         ref = xa_load(&pin->parent_refs, parent->pin_idx);
815         if (!ref)
816                 return NULL;
817         reg = dpll_pin_registration_first(ref);
818         return reg->priv;
819 }
820
821 const struct dpll_pin_ops *dpll_pin_ops(struct dpll_pin_ref *ref)
822 {
823         struct dpll_pin_registration *reg;
824
825         reg = dpll_pin_registration_first(ref);
826         return reg->ops;
827 }
828
829 static int __init dpll_init(void)
830 {
831         int ret;
832
833         ret = genl_register_family(&dpll_nl_family);
834         if (ret)
835                 goto error;
836
837         return 0;
838
839 error:
840         mutex_destroy(&dpll_lock);
841         return ret;
842 }
843
844 static void __exit dpll_exit(void)
845 {
846         genl_unregister_family(&dpll_nl_family);
847         mutex_destroy(&dpll_lock);
848 }
849
850 subsys_initcall(dpll_init);
851 module_exit(dpll_exit);