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