/** * dpll_device_register - register the dpll device in the subsystem * @dpll: pointer to a dpll * @type: type of a dpll * @ops: ops for a dpll device * @priv: pointer to private information of owner * * Make dpll device available for user space. * * Context: Acquires a lock (dpll_lock) * Return: * * 0 on success * * negative - error value
*/ int dpll_device_register(struct dpll_device *dpll, enum dpll_type type, conststruct dpll_device_ops *ops, void *priv)
{ struct dpll_device_registration *reg; bool first_registration = false;
if (WARN_ON(!ops)) return -EINVAL; if (WARN_ON(!ops->mode_get)) return -EINVAL; if (WARN_ON(!ops->lock_status_get)) return -EINVAL; if (WARN_ON(type < DPLL_TYPE_PPS || type > DPLL_TYPE_MAX)) return -EINVAL;
/** * dpll_device_unregister - unregister dpll device * @dpll: registered dpll pointer * @ops: ops for a dpll device * @priv: pointer to private information of owner * * Unregister device, make it unavailable for userspace. * Note: It does not free the memory * Context: Acquires a lock (dpll_lock)
*/ void dpll_device_unregister(struct dpll_device *dpll, conststruct dpll_device_ops *ops, void *priv)
{ struct dpll_device_registration *reg;
/** * dpll_pin_get - find existing or create new dpll pin * @clock_id: clock_id of creator * @pin_idx: idx given by dev driver * @module: reference to registering module * @prop: dpll pin properties * * Get existing object of a pin (unique for given arguments) or create new * if doesn't exist yet. * * Context: Acquires a lock (dpll_lock) * Return: * * valid allocated dpll_pin struct pointer if succeeded * * ERR_PTR(X) - error
*/ struct dpll_pin *
dpll_pin_get(u64 clock_id, u32 pin_idx, struct module *module, conststruct dpll_pin_properties *prop)
{ struct dpll_pin *pos, *ret = NULL; unsignedlong i;
mutex_lock(&dpll_lock);
xa_for_each(&dpll_pin_xa, i, pos) { if (pos->clock_id == clock_id &&
pos->pin_idx == pin_idx &&
pos->module == module) {
ret = pos;
refcount_inc(&ret->refcount); break;
}
} if (!ret)
ret = dpll_pin_alloc(clock_id, pin_idx, module, prop);
mutex_unlock(&dpll_lock);
return ret;
}
EXPORT_SYMBOL_GPL(dpll_pin_get);
/** * dpll_pin_put - decrease the refcount and free memory if possible * @pin: pointer to a pin to be put * * Drop reference for a pin, if all references are gone, delete pin object. * * Context: Acquires a lock (dpll_lock)
*/ void dpll_pin_put(struct dpll_pin *pin)
{
mutex_lock(&dpll_lock); if (refcount_dec_and_test(&pin->refcount)) {
xa_erase(&dpll_pin_xa, pin->id);
xa_destroy(&pin->dpll_refs);
xa_destroy(&pin->parent_refs);
xa_destroy(&pin->ref_sync_pins);
dpll_pin_prop_free(&pin->prop);
kfree_rcu(pin, rcu);
}
mutex_unlock(&dpll_lock);
}
EXPORT_SYMBOL_GPL(dpll_pin_put);
/** * dpll_pin_register - register the dpll pin in the subsystem * @dpll: pointer to a dpll * @pin: pointer to a dpll pin * @ops: ops for a dpll pin ops * @priv: pointer to private information of owner * * Context: Acquires a lock (dpll_lock) * Return: * * 0 on success * * negative - error value
*/ int
dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, conststruct dpll_pin_ops *ops, void *priv)
{ int ret;
if (WARN_ON(!ops) ||
WARN_ON(!ops->state_on_dpll_get) ||
WARN_ON(!ops->direction_get)) return -EINVAL;
mutex_lock(&dpll_lock); if (WARN_ON(!(dpll->module == pin->module &&
dpll->clock_id == pin->clock_id)))
ret = -EINVAL; else
ret = __dpll_pin_register(dpll, pin, ops, priv, NULL);
mutex_unlock(&dpll_lock);
/** * dpll_pin_unregister - unregister dpll pin from dpll device * @dpll: registered dpll pointer * @pin: pointer to a pin * @ops: ops for a dpll pin * @priv: pointer to private information of owner * * Note: It does not free the memory * Context: Acquires a lock (dpll_lock)
*/ void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, conststruct dpll_pin_ops *ops, void *priv)
{ if (WARN_ON(xa_empty(&dpll->pin_refs))) return; if (WARN_ON(!xa_empty(&pin->parent_refs))) return;
/** * dpll_pin_on_pin_register - register a pin with a parent pin * @parent: pointer to a parent pin * @pin: pointer to a pin * @ops: ops for a dpll pin * @priv: pointer to private information of owner * * Register a pin with a parent pin, create references between them and * between newly registered pin and dplls connected with a parent pin. * * Context: Acquires a lock (dpll_lock) * Return: * * 0 on success * * negative - error value
*/ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, conststruct dpll_pin_ops *ops, void *priv)
{ struct dpll_pin_ref *ref; unsignedlong i, stop; int ret;
if (WARN_ON(parent->prop.type != DPLL_PIN_TYPE_MUX)) return -EINVAL;
if (WARN_ON(!ops) ||
WARN_ON(!ops->state_on_pin_get) ||
WARN_ON(!ops->direction_get)) return -EINVAL;
mutex_lock(&dpll_lock);
ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin); if (ret) goto unlock;
refcount_inc(&pin->refcount);
xa_for_each(&parent->dpll_refs, i, ref) {
ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent); if (ret) {
stop = i; goto dpll_unregister;
}
dpll_pin_create_ntf(pin);
}
mutex_unlock(&dpll_lock);
return ret;
dpll_unregister:
xa_for_each(&parent->dpll_refs, i, ref) if (i < stop) {
__dpll_pin_unregister(ref->dpll, pin, ops, priv,
parent);
dpll_pin_delete_ntf(pin);
}
refcount_dec(&pin->refcount);
dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
unlock:
mutex_unlock(&dpll_lock); return ret;
}
EXPORT_SYMBOL_GPL(dpll_pin_on_pin_register);
/** * dpll_pin_on_pin_unregister - unregister dpll pin from a parent pin * @parent: pointer to a parent pin * @pin: pointer to a pin * @ops: ops for a dpll pin * @priv: pointer to private information of owner * * Context: Acquires a lock (dpll_lock) * Note: It does not free the memory
*/ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, conststruct dpll_pin_ops *ops, void *priv)
{ struct dpll_pin_ref *ref; unsignedlong i;
/** * dpll_pin_ref_sync_pair_add - create a reference sync signal pin pair * @pin: pin which produces the base frequency * @ref_sync_pin: pin which produces the sync signal * * Once pins are paired, the user-space configuration of reference sync pair * is possible. * Context: Acquires a lock (dpll_lock) * Return: * * 0 on success * * negative - error value
*/ int dpll_pin_ref_sync_pair_add(struct dpll_pin *pin, struct dpll_pin *ref_sync_pin)
{ int ret;
mutex_lock(&dpll_lock);
ret = xa_insert(&pin->ref_sync_pins, ref_sync_pin->id,
ref_sync_pin, GFP_KERNEL);
__dpll_pin_change_ntf(pin);
mutex_unlock(&dpll_lock);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.