Lines Matching +full:ref +full:-

1 // SPDX-License-Identifier: GPL-2.0
3 * dpll_core.c - DPLL subsystem kernel-space interface implementation.
29 WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
31 WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
33 WARN_ON_ONCE(!xa_get_mark(&dpll_pin_xa, (p)->id, DPLL_REGISTERED))
57 dpll_pin_registration_find(struct dpll_pin_ref *ref, in dpll_pin_registration_find() argument
63 list_for_each_entry(reg, &ref->registration_list, list) { in dpll_pin_registration_find()
64 if (reg->ops == ops && reg->priv == priv && in dpll_pin_registration_find()
65 reg->cookie == cookie) in dpll_pin_registration_find()
77 struct dpll_pin_ref *ref; in dpll_xa_ref_pin_add() local
82 xa_for_each(xa_pins, i, ref) { in dpll_xa_ref_pin_add()
83 if (ref->pin != pin) in dpll_xa_ref_pin_add()
85 reg = dpll_pin_registration_find(ref, ops, priv, cookie); in dpll_xa_ref_pin_add()
87 refcount_inc(&ref->refcount); in dpll_xa_ref_pin_add()
95 ref = kzalloc(sizeof(*ref), GFP_KERNEL); in dpll_xa_ref_pin_add()
96 if (!ref) in dpll_xa_ref_pin_add()
97 return -ENOMEM; in dpll_xa_ref_pin_add()
98 ref->pin = pin; in dpll_xa_ref_pin_add()
99 INIT_LIST_HEAD(&ref->registration_list); in dpll_xa_ref_pin_add()
100 ret = xa_insert(xa_pins, pin->pin_idx, ref, GFP_KERNEL); in dpll_xa_ref_pin_add()
102 kfree(ref); in dpll_xa_ref_pin_add()
105 refcount_set(&ref->refcount, 1); in dpll_xa_ref_pin_add()
111 xa_erase(xa_pins, pin->pin_idx); in dpll_xa_ref_pin_add()
112 kfree(ref); in dpll_xa_ref_pin_add()
114 return -ENOMEM; in dpll_xa_ref_pin_add()
116 reg->ops = ops; in dpll_xa_ref_pin_add()
117 reg->priv = priv; in dpll_xa_ref_pin_add()
118 reg->cookie = cookie; in dpll_xa_ref_pin_add()
120 refcount_inc(&ref->refcount); in dpll_xa_ref_pin_add()
121 list_add_tail(&reg->list, &ref->registration_list); in dpll_xa_ref_pin_add()
131 struct dpll_pin_ref *ref; in dpll_xa_ref_pin_del() local
134 xa_for_each(xa_pins, i, ref) { in dpll_xa_ref_pin_del()
135 if (ref->pin != pin) in dpll_xa_ref_pin_del()
137 reg = dpll_pin_registration_find(ref, ops, priv, cookie); in dpll_xa_ref_pin_del()
139 return -EINVAL; in dpll_xa_ref_pin_del()
140 list_del(&reg->list); in dpll_xa_ref_pin_del()
142 if (refcount_dec_and_test(&ref->refcount)) { in dpll_xa_ref_pin_del()
144 WARN_ON(!list_empty(&ref->registration_list)); in dpll_xa_ref_pin_del()
145 kfree(ref); in dpll_xa_ref_pin_del()
150 return -EINVAL; in dpll_xa_ref_pin_del()
158 struct dpll_pin_ref *ref; in dpll_xa_ref_dpll_add() local
163 xa_for_each(xa_dplls, i, ref) { in dpll_xa_ref_dpll_add()
164 if (ref->dpll != dpll) in dpll_xa_ref_dpll_add()
166 reg = dpll_pin_registration_find(ref, ops, priv, cookie); in dpll_xa_ref_dpll_add()
168 refcount_inc(&ref->refcount); in dpll_xa_ref_dpll_add()
176 ref = kzalloc(sizeof(*ref), GFP_KERNEL); in dpll_xa_ref_dpll_add()
177 if (!ref) in dpll_xa_ref_dpll_add()
178 return -ENOMEM; in dpll_xa_ref_dpll_add()
179 ref->dpll = dpll; in dpll_xa_ref_dpll_add()
180 INIT_LIST_HEAD(&ref->registration_list); in dpll_xa_ref_dpll_add()
181 ret = xa_insert(xa_dplls, dpll->id, ref, GFP_KERNEL); in dpll_xa_ref_dpll_add()
183 kfree(ref); in dpll_xa_ref_dpll_add()
186 refcount_set(&ref->refcount, 1); in dpll_xa_ref_dpll_add()
192 xa_erase(xa_dplls, dpll->id); in dpll_xa_ref_dpll_add()
193 kfree(ref); in dpll_xa_ref_dpll_add()
195 return -ENOMEM; in dpll_xa_ref_dpll_add()
197 reg->ops = ops; in dpll_xa_ref_dpll_add()
198 reg->priv = priv; in dpll_xa_ref_dpll_add()
199 reg->cookie = cookie; in dpll_xa_ref_dpll_add()
201 refcount_inc(&ref->refcount); in dpll_xa_ref_dpll_add()
202 list_add_tail(&reg->list, &ref->registration_list); in dpll_xa_ref_dpll_add()
212 struct dpll_pin_ref *ref; in dpll_xa_ref_dpll_del() local
215 xa_for_each(xa_dplls, i, ref) { in dpll_xa_ref_dpll_del()
216 if (ref->dpll != dpll) in dpll_xa_ref_dpll_del()
218 reg = dpll_pin_registration_find(ref, ops, priv, cookie); in dpll_xa_ref_dpll_del()
221 list_del(&reg->list); in dpll_xa_ref_dpll_del()
223 if (refcount_dec_and_test(&ref->refcount)) { in dpll_xa_ref_dpll_del()
225 WARN_ON(!list_empty(&ref->registration_list)); in dpll_xa_ref_dpll_del()
226 kfree(ref); in dpll_xa_ref_dpll_del()
234 struct dpll_pin_ref *ref; in dpll_xa_ref_dpll_first() local
237 ref = xa_find(xa_refs, &i, ULONG_MAX, XA_PRESENT); in dpll_xa_ref_dpll_first()
238 WARN_ON(!ref); in dpll_xa_ref_dpll_first()
239 return ref; in dpll_xa_ref_dpll_first()
250 return ERR_PTR(-ENOMEM); in dpll_device_alloc()
251 refcount_set(&dpll->refcount, 1); in dpll_device_alloc()
252 INIT_LIST_HEAD(&dpll->registration_list); in dpll_device_alloc()
253 dpll->device_idx = device_idx; in dpll_device_alloc()
254 dpll->clock_id = clock_id; in dpll_device_alloc()
255 dpll->module = module; in dpll_device_alloc()
256 ret = xa_alloc_cyclic(&dpll_device_xa, &dpll->id, dpll, xa_limit_32b, in dpll_device_alloc()
262 xa_init_flags(&dpll->pin_refs, XA_FLAGS_ALLOC); in dpll_device_alloc()
268 * dpll_device_get - find existing or create new dpll device
279 * * ERR_PTR(X) - error
289 if (dpll->clock_id == clock_id && in dpll_device_get()
290 dpll->device_idx == device_idx && in dpll_device_get()
291 dpll->module == module) { in dpll_device_get()
293 refcount_inc(&ret->refcount); in dpll_device_get()
306 * dpll_device_put - decrease the refcount and free memory if possible
316 if (refcount_dec_and_test(&dpll->refcount)) { in dpll_device_put()
318 WARN_ON_ONCE(!xa_empty(&dpll->pin_refs)); in dpll_device_put()
319 xa_destroy(&dpll->pin_refs); in dpll_device_put()
320 xa_erase(&dpll_device_xa, dpll->id); in dpll_device_put()
321 WARN_ON(!list_empty(&dpll->registration_list)); in dpll_device_put()
334 list_for_each_entry(reg, &dpll->registration_list, list) { in dpll_device_registration_find()
335 if (reg->ops == ops && reg->priv == priv) in dpll_device_registration_find()
342 * dpll_device_register - register the dpll device in the subsystem
353 * * negative - error value
362 return -EINVAL; in dpll_device_register()
363 if (WARN_ON(!ops->mode_get)) in dpll_device_register()
364 return -EINVAL; in dpll_device_register()
365 if (WARN_ON(!ops->lock_status_get)) in dpll_device_register()
366 return -EINVAL; in dpll_device_register()
368 return -EINVAL; in dpll_device_register()
374 return -EEXIST; in dpll_device_register()
380 return -ENOMEM; in dpll_device_register()
382 reg->ops = ops; in dpll_device_register()
383 reg->priv = priv; in dpll_device_register()
384 dpll->type = type; in dpll_device_register()
385 first_registration = list_empty(&dpll->registration_list); in dpll_device_register()
386 list_add_tail(&reg->list, &dpll->registration_list); in dpll_device_register()
392 xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED); in dpll_device_register()
401 * dpll_device_unregister - unregister dpll device
423 list_del(&reg->list); in dpll_device_unregister()
426 if (!list_empty(&dpll->registration_list)) { in dpll_device_unregister()
430 xa_clear_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED); in dpll_device_unregister()
437 kfree(prop->package_label); in dpll_pin_prop_free()
438 kfree(prop->panel_label); in dpll_pin_prop_free()
439 kfree(prop->board_label); in dpll_pin_prop_free()
440 kfree(prop->freq_supported); in dpll_pin_prop_free()
447 if (src->freq_supported && src->freq_supported_num) { in dpll_pin_prop_dup()
448 size_t freq_size = src->freq_supported_num * in dpll_pin_prop_dup()
449 sizeof(*src->freq_supported); in dpll_pin_prop_dup()
450 dst->freq_supported = kmemdup(src->freq_supported, in dpll_pin_prop_dup()
452 if (!dst->freq_supported) in dpll_pin_prop_dup()
453 return -ENOMEM; in dpll_pin_prop_dup()
455 if (src->board_label) { in dpll_pin_prop_dup()
456 dst->board_label = kstrdup(src->board_label, GFP_KERNEL); in dpll_pin_prop_dup()
457 if (!dst->board_label) in dpll_pin_prop_dup()
460 if (src->panel_label) { in dpll_pin_prop_dup()
461 dst->panel_label = kstrdup(src->panel_label, GFP_KERNEL); in dpll_pin_prop_dup()
462 if (!dst->panel_label) in dpll_pin_prop_dup()
465 if (src->package_label) { in dpll_pin_prop_dup()
466 dst->package_label = kstrdup(src->package_label, GFP_KERNEL); in dpll_pin_prop_dup()
467 if (!dst->package_label) in dpll_pin_prop_dup()
474 kfree(dst->panel_label); in dpll_pin_prop_dup()
476 kfree(dst->board_label); in dpll_pin_prop_dup()
478 kfree(dst->freq_supported); in dpll_pin_prop_dup()
479 return -ENOMEM; in dpll_pin_prop_dup()
491 return ERR_PTR(-ENOMEM); in dpll_pin_alloc()
492 pin->pin_idx = pin_idx; in dpll_pin_alloc()
493 pin->clock_id = clock_id; in dpll_pin_alloc()
494 pin->module = module; in dpll_pin_alloc()
495 if (WARN_ON(prop->type < DPLL_PIN_TYPE_MUX || in dpll_pin_alloc()
496 prop->type > DPLL_PIN_TYPE_MAX)) { in dpll_pin_alloc()
497 ret = -EINVAL; in dpll_pin_alloc()
500 ret = dpll_pin_prop_dup(prop, &pin->prop); in dpll_pin_alloc()
503 refcount_set(&pin->refcount, 1); in dpll_pin_alloc()
504 xa_init_flags(&pin->dpll_refs, XA_FLAGS_ALLOC); in dpll_pin_alloc()
505 xa_init_flags(&pin->parent_refs, XA_FLAGS_ALLOC); in dpll_pin_alloc()
506 ret = xa_alloc_cyclic(&dpll_pin_xa, &pin->id, pin, xa_limit_32b, in dpll_pin_alloc()
512 xa_destroy(&pin->dpll_refs); in dpll_pin_alloc()
513 xa_destroy(&pin->parent_refs); in dpll_pin_alloc()
514 dpll_pin_prop_free(&pin->prop); in dpll_pin_alloc()
523 rcu_assign_pointer(dev->dpll_pin, dpll_pin); in dpll_netdev_pin_assign()
541 * dpll_pin_get - find existing or create new dpll pin
553 * * ERR_PTR(X) - error
564 if (pos->clock_id == clock_id && in dpll_pin_get()
565 pos->pin_idx == pin_idx && in dpll_pin_get()
566 pos->module == module) { in dpll_pin_get()
568 refcount_inc(&ret->refcount); in dpll_pin_get()
581 * dpll_pin_put - decrease the refcount and free memory if possible
591 if (refcount_dec_and_test(&pin->refcount)) { in dpll_pin_put()
592 xa_erase(&dpll_pin_xa, pin->id); in dpll_pin_put()
593 xa_destroy(&pin->dpll_refs); in dpll_pin_put()
594 xa_destroy(&pin->parent_refs); in dpll_pin_put()
595 dpll_pin_prop_free(&pin->prop); in dpll_pin_put()
608 ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv, cookie); in __dpll_pin_register()
611 ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv, cookie); in __dpll_pin_register()
614 xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); in __dpll_pin_register()
620 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); in __dpll_pin_register()
625 * dpll_pin_register - register the dpll pin in the subsystem
634 * * negative - error value
643 WARN_ON(!ops->state_on_dpll_get) || in dpll_pin_register()
644 WARN_ON(!ops->direction_get)) in dpll_pin_register()
645 return -EINVAL; in dpll_pin_register()
648 if (WARN_ON(!(dpll->module == pin->module && in dpll_pin_register()
649 dpll->clock_id == pin->clock_id))) in dpll_pin_register()
650 ret = -EINVAL; in dpll_pin_register()
664 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); in __dpll_pin_unregister()
665 dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie); in __dpll_pin_unregister()
666 if (xa_empty(&pin->dpll_refs)) in __dpll_pin_unregister()
667 xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); in __dpll_pin_unregister()
671 * dpll_pin_unregister - unregister dpll pin from dpll device
683 if (WARN_ON(xa_empty(&dpll->pin_refs))) in dpll_pin_unregister()
685 if (WARN_ON(!xa_empty(&pin->parent_refs))) in dpll_pin_unregister()
696 * dpll_pin_on_pin_register - register a pin with a parent pin
708 * * negative - error value
713 struct dpll_pin_ref *ref; in dpll_pin_on_pin_register() local
717 if (WARN_ON(parent->prop.type != DPLL_PIN_TYPE_MUX)) in dpll_pin_on_pin_register()
718 return -EINVAL; in dpll_pin_on_pin_register()
721 WARN_ON(!ops->state_on_pin_get) || in dpll_pin_on_pin_register()
722 WARN_ON(!ops->direction_get)) in dpll_pin_on_pin_register()
723 return -EINVAL; in dpll_pin_on_pin_register()
726 ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin); in dpll_pin_on_pin_register()
729 refcount_inc(&pin->refcount); in dpll_pin_on_pin_register()
730 xa_for_each(&parent->dpll_refs, i, ref) { in dpll_pin_on_pin_register()
731 ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent); in dpll_pin_on_pin_register()
743 xa_for_each(&parent->dpll_refs, i, ref) in dpll_pin_on_pin_register()
745 __dpll_pin_unregister(ref->dpll, pin, ops, priv, in dpll_pin_on_pin_register()
749 refcount_dec(&pin->refcount); in dpll_pin_on_pin_register()
750 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); in dpll_pin_on_pin_register()
758 * dpll_pin_on_pin_unregister - unregister dpll pin from a parent pin
770 struct dpll_pin_ref *ref; in dpll_pin_on_pin_unregister() local
775 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); in dpll_pin_on_pin_unregister()
776 refcount_dec(&pin->refcount); in dpll_pin_on_pin_unregister()
777 xa_for_each(&pin->dpll_refs, i, ref) in dpll_pin_on_pin_unregister()
778 __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent); in dpll_pin_on_pin_unregister()
788 reg = list_first_entry_or_null((struct list_head *)&dpll->registration_list, in dpll_device_registration_first()
799 return reg->priv; in dpll_priv()
807 return reg->ops; in dpll_device_ops()
811 dpll_pin_registration_first(struct dpll_pin_ref *ref) in dpll_pin_registration_first() argument
815 reg = list_first_entry_or_null(&ref->registration_list, in dpll_pin_registration_first()
825 struct dpll_pin_ref *ref; in dpll_pin_on_dpll_priv() local
827 ref = xa_load(&dpll->pin_refs, pin->pin_idx); in dpll_pin_on_dpll_priv()
828 if (!ref) in dpll_pin_on_dpll_priv()
830 reg = dpll_pin_registration_first(ref); in dpll_pin_on_dpll_priv()
831 return reg->priv; in dpll_pin_on_dpll_priv()
838 struct dpll_pin_ref *ref; in dpll_pin_on_pin_priv() local
840 ref = xa_load(&pin->parent_refs, parent->pin_idx); in dpll_pin_on_pin_priv()
841 if (!ref) in dpll_pin_on_pin_priv()
843 reg = dpll_pin_registration_first(ref); in dpll_pin_on_pin_priv()
844 return reg->priv; in dpll_pin_on_pin_priv()
847 const struct dpll_pin_ops *dpll_pin_ops(struct dpll_pin_ref *ref) in dpll_pin_ops() argument
851 reg = dpll_pin_registration_first(ref); in dpll_pin_ops()
852 return reg->ops; in dpll_pin_ops()