Loading drivers/reset/core.c +166 −14 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ static LIST_HEAD(reset_lookup_list); * @id: ID of the reset controller in the reset * controller device * @refcnt: Number of gets of this reset_control * @acquired: Only one reset_control may be acquired for a given rcdev and id. * @shared: Is this a shared (1), or an exclusive (0) reset_control? * @deassert_cnt: Number of times this reset line has been deasserted * @triggered_count: Number of times this reset line has been reset. Currently Loading @@ -45,6 +46,7 @@ struct reset_control { struct list_head list; unsigned int id; struct kref refcnt; bool acquired; bool shared; bool array; atomic_t deassert_count; Loading @@ -63,6 +65,17 @@ struct reset_control_array { struct reset_control *rstc[]; }; static const char *rcdev_name(struct reset_controller_dev *rcdev) { if (rcdev->dev) return dev_name(rcdev->dev); if (rcdev->of_node) return rcdev->of_node->full_name; return NULL; } /** * of_reset_simple_xlate - translate reset_spec to the reset line number * @rcdev: a pointer to the reset controller device Loading Loading @@ -232,6 +245,34 @@ static int reset_control_array_deassert(struct reset_control_array *resets) return ret; } static int reset_control_array_acquire(struct reset_control_array *resets) { unsigned int i; int err; for (i = 0; i < resets->num_rstcs; i++) { err = reset_control_acquire(resets->rstc[i]); if (err < 0) goto release; } return 0; release: while (i--) reset_control_release(resets->rstc[i]); return err; } static void reset_control_array_release(struct reset_control_array *resets) { unsigned int i; for (i = 0; i < resets->num_rstcs; i++) reset_control_release(resets->rstc[i]); } static inline bool reset_control_is_array(struct reset_control *rstc) { return rstc->array; Loading Loading @@ -272,6 +313,9 @@ int reset_control_reset(struct reset_control *rstc) if (atomic_inc_return(&rstc->triggered_count) != 1) return 0; } else { if (!rstc->acquired) return -EPERM; } ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); Loading Loading @@ -334,6 +378,12 @@ int reset_control_assert(struct reset_control *rstc) */ if (!rstc->rcdev->ops->assert) return -ENOTSUPP; if (!rstc->acquired) { WARN(1, "reset %s (ID: %u) is not acquired\n", rcdev_name(rstc->rcdev), rstc->id); return -EPERM; } } return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); Loading Loading @@ -369,6 +419,12 @@ int reset_control_deassert(struct reset_control *rstc) if (atomic_inc_return(&rstc->deassert_count) != 1) return 0; } else { if (!rstc->acquired) { WARN(1, "reset %s (ID: %u) is not acquired\n", rcdev_name(rstc->rcdev), rstc->id); return -EPERM; } } /* Loading Loading @@ -406,9 +462,87 @@ int reset_control_status(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_status); /** * reset_control_acquire() - acquires a reset control for exclusive use * @rstc: reset control * * This is used to explicitly acquire a reset control for exclusive use. Note * that exclusive resets are requested as acquired by default. In order for a * second consumer to be able to control the reset, the first consumer has to * release it first. Typically the easiest way to achieve this is to call the * reset_control_get_exclusive_released() to obtain an instance of the reset * control. Such reset controls are not acquired by default. * * Consumers implementing shared access to an exclusive reset need to follow * a specific protocol in order to work together. Before consumers can change * a reset they must acquire exclusive access using reset_control_acquire(). * After they are done operating the reset, they must release exclusive access * with a call to reset_control_release(). Consumers are not granted exclusive * access to the reset as long as another consumer hasn't released a reset. * * See also: reset_control_release() */ int reset_control_acquire(struct reset_control *rstc) { struct reset_control *rc; if (!rstc) return 0; if (WARN_ON(IS_ERR(rstc))) return -EINVAL; if (reset_control_is_array(rstc)) return reset_control_array_acquire(rstc_to_array(rstc)); mutex_lock(&reset_list_mutex); if (rstc->acquired) { mutex_unlock(&reset_list_mutex); return 0; } list_for_each_entry(rc, &rstc->rcdev->reset_control_head, list) { if (rstc != rc && rstc->id == rc->id) { if (rc->acquired) { mutex_unlock(&reset_list_mutex); return -EBUSY; } } } rstc->acquired = true; mutex_unlock(&reset_list_mutex); return 0; } EXPORT_SYMBOL_GPL(reset_control_acquire); /** * reset_control_release() - releases exclusive access to a reset control * @rstc: reset control * * Releases exclusive access right to a reset control previously obtained by a * call to reset_control_acquire(). Until a consumer calls this function, no * other consumers will be granted exclusive access. * * See also: reset_control_acquire() */ void reset_control_release(struct reset_control *rstc) { if (!rstc || WARN_ON(IS_ERR(rstc))) return; if (reset_control_is_array(rstc)) reset_control_array_release(rstc_to_array(rstc)); else rstc->acquired = false; } EXPORT_SYMBOL_GPL(reset_control_release); static struct reset_control *__reset_control_get_internal( struct reset_controller_dev *rcdev, unsigned int index, bool shared) unsigned int index, bool shared, bool acquired) { struct reset_control *rstc; Loading @@ -416,6 +550,14 @@ static struct reset_control *__reset_control_get_internal( list_for_each_entry(rstc, &rcdev->reset_control_head, list) { if (rstc->id == index) { /* * Allow creating a secondary exclusive reset_control * that is initially not acquired for an already * controlled reset line. */ if (!rstc->shared && !shared && !acquired) break; if (WARN_ON(!rstc->shared || !shared)) return ERR_PTR(-EBUSY); Loading @@ -434,6 +576,7 @@ static struct reset_control *__reset_control_get_internal( list_add(&rstc->list, &rcdev->reset_control_head); rstc->id = index; kref_init(&rstc->refcnt); rstc->acquired = acquired; rstc->shared = shared; return rstc; Loading Loading @@ -461,7 +604,7 @@ static void __reset_control_put_internal(struct reset_control *rstc) struct reset_control *__of_reset_control_get(struct device_node *node, const char *id, int index, bool shared, bool optional) bool optional, bool acquired) { struct reset_control *rstc; struct reset_controller_dev *r, *rcdev; Loading Loading @@ -514,7 +657,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, } /* reset_list_mutex also protects the rcdev's reset_control list */ rstc = __reset_control_get_internal(rcdev, rstc_id, shared); rstc = __reset_control_get_internal(rcdev, rstc_id, shared, acquired); out: mutex_unlock(&reset_list_mutex); Loading Loading @@ -544,7 +687,7 @@ __reset_controller_by_name(const char *name) static struct reset_control * __reset_control_get_from_lookup(struct device *dev, const char *con_id, bool shared, bool optional) bool shared, bool optional, bool acquired) { const struct reset_control_lookup *lookup; struct reset_controller_dev *rcdev; Loading Loading @@ -574,7 +717,7 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id, rstc = __reset_control_get_internal(rcdev, lookup->index, shared); shared, acquired); mutex_unlock(&reset_list_mutex); break; } Loading @@ -589,13 +732,18 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id, } struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional) int index, bool shared, bool optional, bool acquired) { if (WARN_ON(shared && acquired)) return ERR_PTR(-EINVAL); if (dev->of_node) return __of_reset_control_get(dev->of_node, id, index, shared, optional); optional, acquired); return __reset_control_get_from_lookup(dev, id, shared, optional); return __reset_control_get_from_lookup(dev, id, shared, optional, acquired); } EXPORT_SYMBOL_GPL(__reset_control_get); Loading Loading @@ -636,7 +784,7 @@ static void devm_reset_control_release(struct device *dev, void *res) struct reset_control *__devm_reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional) bool optional, bool acquired) { struct reset_control **ptr, *rstc; Loading @@ -645,7 +793,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev, if (!ptr) return ERR_PTR(-ENOMEM); rstc = __reset_control_get(dev, id, index, shared, optional); rstc = __reset_control_get(dev, id, index, shared, optional, acquired); if (!IS_ERR(rstc)) { *ptr = rstc; devres_add(dev, ptr); Loading @@ -672,7 +820,7 @@ int __device_reset(struct device *dev, bool optional) struct reset_control *rstc; int ret; rstc = __reset_control_get(dev, NULL, 0, 0, optional); rstc = __reset_control_get(dev, NULL, 0, 0, optional, true); if (IS_ERR(rstc)) return PTR_ERR(rstc); Loading Loading @@ -716,12 +864,15 @@ static int of_reset_control_get_count(struct device_node *node) * @np: device node for the device that requests the reset controls array * @shared: whether reset controls are shared or not * @optional: whether it is optional to get the reset controls * @acquired: only one reset control may be acquired for a given controller * and ID * * Returns pointer to allocated reset_control_array on success or * error on failure */ struct reset_control * of_reset_control_array_get(struct device_node *np, bool shared, bool optional) of_reset_control_array_get(struct device_node *np, bool shared, bool optional, bool acquired) { struct reset_control_array *resets; struct reset_control *rstc; Loading @@ -736,7 +887,8 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional) return ERR_PTR(-ENOMEM); for (i = 0; i < num; i++) { rstc = __of_reset_control_get(np, NULL, i, shared, optional); rstc = __of_reset_control_get(np, NULL, i, shared, optional, acquired); if (IS_ERR(rstc)) goto err_rst; resets->rstc[i] = rstc; Loading Loading @@ -783,7 +935,7 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional) if (!devres) return ERR_PTR(-ENOMEM); rstc = of_reset_control_array_get(dev->of_node, shared, optional); rstc = of_reset_control_array_get(dev->of_node, shared, optional, true); if (IS_ERR(rstc)) { devres_free(devres); return rstc; Loading drivers/usb/dwc3/dwc3-of-simple.c +2 −1 Original line number Diff line number Diff line Loading @@ -107,7 +107,8 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) simple->pulse_resets = true; } simple->resets = of_reset_control_array_get(np, shared_resets, true); simple->resets = of_reset_control_array_get(np, shared_resets, true, true); if (IS_ERR(simple->resets)) { ret = PTR_ERR(simple->resets); dev_err(dev, "failed to get device resets, err=%d\n", ret); Loading include/linux/reset.h +87 −26 Original line number Diff line number Diff line Loading @@ -14,23 +14,26 @@ int reset_control_reset(struct reset_control *rstc); int reset_control_assert(struct reset_control *rstc); int reset_control_deassert(struct reset_control *rstc); int reset_control_status(struct reset_control *rstc); int reset_control_acquire(struct reset_control *rstc); void reset_control_release(struct reset_control *rstc); struct reset_control *__of_reset_control_get(struct device_node *node, const char *id, int index, bool shared, bool optional); bool optional, bool acquired); struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional); bool optional, bool acquired); void reset_control_put(struct reset_control *rstc); int __device_reset(struct device *dev, bool optional); struct reset_control *__devm_reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional); bool optional, bool acquired); struct reset_control *devm_reset_control_array_get(struct device *dev, bool shared, bool optional); struct reset_control *of_reset_control_array_get(struct device_node *np, bool shared, bool optional); bool shared, bool optional, bool acquired); int reset_control_get_count(struct device *dev); Loading @@ -56,6 +59,15 @@ static inline int reset_control_status(struct reset_control *rstc) return 0; } static inline int reset_control_acquire(struct reset_control *rstc) { return 0; } static inline void reset_control_release(struct reset_control *rstc) { } static inline void reset_control_put(struct reset_control *rstc) { } Loading @@ -68,21 +80,23 @@ static inline int __device_reset(struct device *dev, bool optional) static inline struct reset_control *__of_reset_control_get( struct device_node *node, const char *id, int index, bool shared, bool optional) bool optional, bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } static inline struct reset_control *__reset_control_get( struct device *dev, const char *id, int index, bool shared, bool optional) int index, bool shared, bool optional, bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } static inline struct reset_control *__devm_reset_control_get( struct device *dev, const char *id, int index, bool shared, bool optional) int index, bool shared, bool optional, bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } Loading @@ -94,7 +108,8 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional) } static inline struct reset_control * of_reset_control_array_get(struct device_node *np, bool shared, bool optional) of_reset_control_array_get(struct device_node *np, bool shared, bool optional, bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } Loading Loading @@ -134,7 +149,28 @@ static inline int device_reset_optional(struct device *dev) static inline struct reset_control * __must_check reset_control_get_exclusive(struct device *dev, const char *id) { return __reset_control_get(dev, id, 0, false, false); return __reset_control_get(dev, id, 0, false, false, true); } /** * reset_control_get_exclusive_released - Lookup and obtain a temoprarily * exclusive reference to a reset * controller. * @dev: device to be reset by the controller * @id: reset line name * * Returns a struct reset_control or IS_ERR() condition containing errno. * reset-controls returned by this function must be acquired via * reset_control_acquire() before they can be used and should be released * via reset_control_release() afterwards. * * Use of id names is optional. */ static inline struct reset_control * __must_check reset_control_get_exclusive_released(struct device *dev, const char *id) { return __reset_control_get(dev, id, 0, false, false, false); } /** Loading Loading @@ -162,19 +198,19 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id) static inline struct reset_control *reset_control_get_shared( struct device *dev, const char *id) { return __reset_control_get(dev, id, 0, true, false); return __reset_control_get(dev, id, 0, true, false, false); } static inline struct reset_control *reset_control_get_optional_exclusive( struct device *dev, const char *id) { return __reset_control_get(dev, id, 0, false, true); return __reset_control_get(dev, id, 0, false, true, true); } static inline struct reset_control *reset_control_get_optional_shared( struct device *dev, const char *id) { return __reset_control_get(dev, id, 0, true, true); return __reset_control_get(dev, id, 0, true, true, false); } /** Loading @@ -190,7 +226,7 @@ static inline struct reset_control *reset_control_get_optional_shared( static inline struct reset_control *of_reset_control_get_exclusive( struct device_node *node, const char *id) { return __of_reset_control_get(node, id, 0, false, false); return __of_reset_control_get(node, id, 0, false, false, true); } /** Loading @@ -215,7 +251,7 @@ static inline struct reset_control *of_reset_control_get_exclusive( static inline struct reset_control *of_reset_control_get_shared( struct device_node *node, const char *id) { return __of_reset_control_get(node, id, 0, true, false); return __of_reset_control_get(node, id, 0, true, false, false); } /** Loading @@ -232,7 +268,7 @@ static inline struct reset_control *of_reset_control_get_shared( static inline struct reset_control *of_reset_control_get_exclusive_by_index( struct device_node *node, int index) { return __of_reset_control_get(node, NULL, index, false, false); return __of_reset_control_get(node, NULL, index, false, false, true); } /** Loading Loading @@ -260,7 +296,7 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index( static inline struct reset_control *of_reset_control_get_shared_by_index( struct device_node *node, int index) { return __of_reset_control_get(node, NULL, index, true, false); return __of_reset_control_get(node, NULL, index, true, false, false); } /** Loading @@ -279,7 +315,26 @@ static inline struct reset_control * __must_check devm_reset_control_get_exclusive(struct device *dev, const char *id) { return __devm_reset_control_get(dev, id, 0, false, false); return __devm_reset_control_get(dev, id, 0, false, false, true); } /** * devm_reset_control_get_exclusive_released - resource managed * reset_control_get_exclusive_released() * @dev: device to be reset by the controller * @id: reset line name * * Managed reset_control_get_exclusive_released(). For reset controllers * returned from this function, reset_control_put() is called automatically on * driver detach. * * See reset_control_get_exclusive_released() for more information. */ static inline struct reset_control * __must_check devm_reset_control_get_exclusive_released(struct device *dev, const char *id) { return __devm_reset_control_get(dev, id, 0, false, false, false); } /** Loading @@ -294,19 +349,19 @@ __must_check devm_reset_control_get_exclusive(struct device *dev, static inline struct reset_control *devm_reset_control_get_shared( struct device *dev, const char *id) { return __devm_reset_control_get(dev, id, 0, true, false); return __devm_reset_control_get(dev, id, 0, true, false, false); } static inline struct reset_control *devm_reset_control_get_optional_exclusive( struct device *dev, const char *id) { return __devm_reset_control_get(dev, id, 0, false, true); return __devm_reset_control_get(dev, id, 0, false, true, true); } static inline struct reset_control *devm_reset_control_get_optional_shared( struct device *dev, const char *id) { return __devm_reset_control_get(dev, id, 0, true, true); return __devm_reset_control_get(dev, id, 0, true, true, false); } /** Loading @@ -324,7 +379,7 @@ static inline struct reset_control *devm_reset_control_get_optional_shared( static inline struct reset_control * devm_reset_control_get_exclusive_by_index(struct device *dev, int index) { return __devm_reset_control_get(dev, NULL, index, false, false); return __devm_reset_control_get(dev, NULL, index, false, false, true); } /** Loading @@ -340,7 +395,7 @@ devm_reset_control_get_exclusive_by_index(struct device *dev, int index) static inline struct reset_control * devm_reset_control_get_shared_by_index(struct device *dev, int index) { return __devm_reset_control_get(dev, NULL, index, true, false); return __devm_reset_control_get(dev, NULL, index, true, false, false); } /* Loading Loading @@ -412,24 +467,30 @@ devm_reset_control_array_get_optional_shared(struct device *dev) static inline struct reset_control * of_reset_control_array_get_exclusive(struct device_node *node) { return of_reset_control_array_get(node, false, false); return of_reset_control_array_get(node, false, false, true); } static inline struct reset_control * of_reset_control_array_get_exclusive_released(struct device_node *node) { return of_reset_control_array_get(node, false, false, false); } static inline struct reset_control * of_reset_control_array_get_shared(struct device_node *node) { return of_reset_control_array_get(node, true, false); return of_reset_control_array_get(node, true, false, true); } static inline struct reset_control * of_reset_control_array_get_optional_exclusive(struct device_node *node) { return of_reset_control_array_get(node, false, true); return of_reset_control_array_get(node, false, true, true); } static inline struct reset_control * of_reset_control_array_get_optional_shared(struct device_node *node) { return of_reset_control_array_get(node, true, true); return of_reset_control_array_get(node, true, true, true); } #endif Loading
drivers/reset/core.c +166 −14 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ static LIST_HEAD(reset_lookup_list); * @id: ID of the reset controller in the reset * controller device * @refcnt: Number of gets of this reset_control * @acquired: Only one reset_control may be acquired for a given rcdev and id. * @shared: Is this a shared (1), or an exclusive (0) reset_control? * @deassert_cnt: Number of times this reset line has been deasserted * @triggered_count: Number of times this reset line has been reset. Currently Loading @@ -45,6 +46,7 @@ struct reset_control { struct list_head list; unsigned int id; struct kref refcnt; bool acquired; bool shared; bool array; atomic_t deassert_count; Loading @@ -63,6 +65,17 @@ struct reset_control_array { struct reset_control *rstc[]; }; static const char *rcdev_name(struct reset_controller_dev *rcdev) { if (rcdev->dev) return dev_name(rcdev->dev); if (rcdev->of_node) return rcdev->of_node->full_name; return NULL; } /** * of_reset_simple_xlate - translate reset_spec to the reset line number * @rcdev: a pointer to the reset controller device Loading Loading @@ -232,6 +245,34 @@ static int reset_control_array_deassert(struct reset_control_array *resets) return ret; } static int reset_control_array_acquire(struct reset_control_array *resets) { unsigned int i; int err; for (i = 0; i < resets->num_rstcs; i++) { err = reset_control_acquire(resets->rstc[i]); if (err < 0) goto release; } return 0; release: while (i--) reset_control_release(resets->rstc[i]); return err; } static void reset_control_array_release(struct reset_control_array *resets) { unsigned int i; for (i = 0; i < resets->num_rstcs; i++) reset_control_release(resets->rstc[i]); } static inline bool reset_control_is_array(struct reset_control *rstc) { return rstc->array; Loading Loading @@ -272,6 +313,9 @@ int reset_control_reset(struct reset_control *rstc) if (atomic_inc_return(&rstc->triggered_count) != 1) return 0; } else { if (!rstc->acquired) return -EPERM; } ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); Loading Loading @@ -334,6 +378,12 @@ int reset_control_assert(struct reset_control *rstc) */ if (!rstc->rcdev->ops->assert) return -ENOTSUPP; if (!rstc->acquired) { WARN(1, "reset %s (ID: %u) is not acquired\n", rcdev_name(rstc->rcdev), rstc->id); return -EPERM; } } return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); Loading Loading @@ -369,6 +419,12 @@ int reset_control_deassert(struct reset_control *rstc) if (atomic_inc_return(&rstc->deassert_count) != 1) return 0; } else { if (!rstc->acquired) { WARN(1, "reset %s (ID: %u) is not acquired\n", rcdev_name(rstc->rcdev), rstc->id); return -EPERM; } } /* Loading Loading @@ -406,9 +462,87 @@ int reset_control_status(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_status); /** * reset_control_acquire() - acquires a reset control for exclusive use * @rstc: reset control * * This is used to explicitly acquire a reset control for exclusive use. Note * that exclusive resets are requested as acquired by default. In order for a * second consumer to be able to control the reset, the first consumer has to * release it first. Typically the easiest way to achieve this is to call the * reset_control_get_exclusive_released() to obtain an instance of the reset * control. Such reset controls are not acquired by default. * * Consumers implementing shared access to an exclusive reset need to follow * a specific protocol in order to work together. Before consumers can change * a reset they must acquire exclusive access using reset_control_acquire(). * After they are done operating the reset, they must release exclusive access * with a call to reset_control_release(). Consumers are not granted exclusive * access to the reset as long as another consumer hasn't released a reset. * * See also: reset_control_release() */ int reset_control_acquire(struct reset_control *rstc) { struct reset_control *rc; if (!rstc) return 0; if (WARN_ON(IS_ERR(rstc))) return -EINVAL; if (reset_control_is_array(rstc)) return reset_control_array_acquire(rstc_to_array(rstc)); mutex_lock(&reset_list_mutex); if (rstc->acquired) { mutex_unlock(&reset_list_mutex); return 0; } list_for_each_entry(rc, &rstc->rcdev->reset_control_head, list) { if (rstc != rc && rstc->id == rc->id) { if (rc->acquired) { mutex_unlock(&reset_list_mutex); return -EBUSY; } } } rstc->acquired = true; mutex_unlock(&reset_list_mutex); return 0; } EXPORT_SYMBOL_GPL(reset_control_acquire); /** * reset_control_release() - releases exclusive access to a reset control * @rstc: reset control * * Releases exclusive access right to a reset control previously obtained by a * call to reset_control_acquire(). Until a consumer calls this function, no * other consumers will be granted exclusive access. * * See also: reset_control_acquire() */ void reset_control_release(struct reset_control *rstc) { if (!rstc || WARN_ON(IS_ERR(rstc))) return; if (reset_control_is_array(rstc)) reset_control_array_release(rstc_to_array(rstc)); else rstc->acquired = false; } EXPORT_SYMBOL_GPL(reset_control_release); static struct reset_control *__reset_control_get_internal( struct reset_controller_dev *rcdev, unsigned int index, bool shared) unsigned int index, bool shared, bool acquired) { struct reset_control *rstc; Loading @@ -416,6 +550,14 @@ static struct reset_control *__reset_control_get_internal( list_for_each_entry(rstc, &rcdev->reset_control_head, list) { if (rstc->id == index) { /* * Allow creating a secondary exclusive reset_control * that is initially not acquired for an already * controlled reset line. */ if (!rstc->shared && !shared && !acquired) break; if (WARN_ON(!rstc->shared || !shared)) return ERR_PTR(-EBUSY); Loading @@ -434,6 +576,7 @@ static struct reset_control *__reset_control_get_internal( list_add(&rstc->list, &rcdev->reset_control_head); rstc->id = index; kref_init(&rstc->refcnt); rstc->acquired = acquired; rstc->shared = shared; return rstc; Loading Loading @@ -461,7 +604,7 @@ static void __reset_control_put_internal(struct reset_control *rstc) struct reset_control *__of_reset_control_get(struct device_node *node, const char *id, int index, bool shared, bool optional) bool optional, bool acquired) { struct reset_control *rstc; struct reset_controller_dev *r, *rcdev; Loading Loading @@ -514,7 +657,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, } /* reset_list_mutex also protects the rcdev's reset_control list */ rstc = __reset_control_get_internal(rcdev, rstc_id, shared); rstc = __reset_control_get_internal(rcdev, rstc_id, shared, acquired); out: mutex_unlock(&reset_list_mutex); Loading Loading @@ -544,7 +687,7 @@ __reset_controller_by_name(const char *name) static struct reset_control * __reset_control_get_from_lookup(struct device *dev, const char *con_id, bool shared, bool optional) bool shared, bool optional, bool acquired) { const struct reset_control_lookup *lookup; struct reset_controller_dev *rcdev; Loading Loading @@ -574,7 +717,7 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id, rstc = __reset_control_get_internal(rcdev, lookup->index, shared); shared, acquired); mutex_unlock(&reset_list_mutex); break; } Loading @@ -589,13 +732,18 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id, } struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional) int index, bool shared, bool optional, bool acquired) { if (WARN_ON(shared && acquired)) return ERR_PTR(-EINVAL); if (dev->of_node) return __of_reset_control_get(dev->of_node, id, index, shared, optional); optional, acquired); return __reset_control_get_from_lookup(dev, id, shared, optional); return __reset_control_get_from_lookup(dev, id, shared, optional, acquired); } EXPORT_SYMBOL_GPL(__reset_control_get); Loading Loading @@ -636,7 +784,7 @@ static void devm_reset_control_release(struct device *dev, void *res) struct reset_control *__devm_reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional) bool optional, bool acquired) { struct reset_control **ptr, *rstc; Loading @@ -645,7 +793,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev, if (!ptr) return ERR_PTR(-ENOMEM); rstc = __reset_control_get(dev, id, index, shared, optional); rstc = __reset_control_get(dev, id, index, shared, optional, acquired); if (!IS_ERR(rstc)) { *ptr = rstc; devres_add(dev, ptr); Loading @@ -672,7 +820,7 @@ int __device_reset(struct device *dev, bool optional) struct reset_control *rstc; int ret; rstc = __reset_control_get(dev, NULL, 0, 0, optional); rstc = __reset_control_get(dev, NULL, 0, 0, optional, true); if (IS_ERR(rstc)) return PTR_ERR(rstc); Loading Loading @@ -716,12 +864,15 @@ static int of_reset_control_get_count(struct device_node *node) * @np: device node for the device that requests the reset controls array * @shared: whether reset controls are shared or not * @optional: whether it is optional to get the reset controls * @acquired: only one reset control may be acquired for a given controller * and ID * * Returns pointer to allocated reset_control_array on success or * error on failure */ struct reset_control * of_reset_control_array_get(struct device_node *np, bool shared, bool optional) of_reset_control_array_get(struct device_node *np, bool shared, bool optional, bool acquired) { struct reset_control_array *resets; struct reset_control *rstc; Loading @@ -736,7 +887,8 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional) return ERR_PTR(-ENOMEM); for (i = 0; i < num; i++) { rstc = __of_reset_control_get(np, NULL, i, shared, optional); rstc = __of_reset_control_get(np, NULL, i, shared, optional, acquired); if (IS_ERR(rstc)) goto err_rst; resets->rstc[i] = rstc; Loading Loading @@ -783,7 +935,7 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional) if (!devres) return ERR_PTR(-ENOMEM); rstc = of_reset_control_array_get(dev->of_node, shared, optional); rstc = of_reset_control_array_get(dev->of_node, shared, optional, true); if (IS_ERR(rstc)) { devres_free(devres); return rstc; Loading
drivers/usb/dwc3/dwc3-of-simple.c +2 −1 Original line number Diff line number Diff line Loading @@ -107,7 +107,8 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) simple->pulse_resets = true; } simple->resets = of_reset_control_array_get(np, shared_resets, true); simple->resets = of_reset_control_array_get(np, shared_resets, true, true); if (IS_ERR(simple->resets)) { ret = PTR_ERR(simple->resets); dev_err(dev, "failed to get device resets, err=%d\n", ret); Loading
include/linux/reset.h +87 −26 Original line number Diff line number Diff line Loading @@ -14,23 +14,26 @@ int reset_control_reset(struct reset_control *rstc); int reset_control_assert(struct reset_control *rstc); int reset_control_deassert(struct reset_control *rstc); int reset_control_status(struct reset_control *rstc); int reset_control_acquire(struct reset_control *rstc); void reset_control_release(struct reset_control *rstc); struct reset_control *__of_reset_control_get(struct device_node *node, const char *id, int index, bool shared, bool optional); bool optional, bool acquired); struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional); bool optional, bool acquired); void reset_control_put(struct reset_control *rstc); int __device_reset(struct device *dev, bool optional); struct reset_control *__devm_reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional); bool optional, bool acquired); struct reset_control *devm_reset_control_array_get(struct device *dev, bool shared, bool optional); struct reset_control *of_reset_control_array_get(struct device_node *np, bool shared, bool optional); bool shared, bool optional, bool acquired); int reset_control_get_count(struct device *dev); Loading @@ -56,6 +59,15 @@ static inline int reset_control_status(struct reset_control *rstc) return 0; } static inline int reset_control_acquire(struct reset_control *rstc) { return 0; } static inline void reset_control_release(struct reset_control *rstc) { } static inline void reset_control_put(struct reset_control *rstc) { } Loading @@ -68,21 +80,23 @@ static inline int __device_reset(struct device *dev, bool optional) static inline struct reset_control *__of_reset_control_get( struct device_node *node, const char *id, int index, bool shared, bool optional) bool optional, bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } static inline struct reset_control *__reset_control_get( struct device *dev, const char *id, int index, bool shared, bool optional) int index, bool shared, bool optional, bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } static inline struct reset_control *__devm_reset_control_get( struct device *dev, const char *id, int index, bool shared, bool optional) int index, bool shared, bool optional, bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } Loading @@ -94,7 +108,8 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional) } static inline struct reset_control * of_reset_control_array_get(struct device_node *np, bool shared, bool optional) of_reset_control_array_get(struct device_node *np, bool shared, bool optional, bool acquired) { return optional ? NULL : ERR_PTR(-ENOTSUPP); } Loading Loading @@ -134,7 +149,28 @@ static inline int device_reset_optional(struct device *dev) static inline struct reset_control * __must_check reset_control_get_exclusive(struct device *dev, const char *id) { return __reset_control_get(dev, id, 0, false, false); return __reset_control_get(dev, id, 0, false, false, true); } /** * reset_control_get_exclusive_released - Lookup and obtain a temoprarily * exclusive reference to a reset * controller. * @dev: device to be reset by the controller * @id: reset line name * * Returns a struct reset_control or IS_ERR() condition containing errno. * reset-controls returned by this function must be acquired via * reset_control_acquire() before they can be used and should be released * via reset_control_release() afterwards. * * Use of id names is optional. */ static inline struct reset_control * __must_check reset_control_get_exclusive_released(struct device *dev, const char *id) { return __reset_control_get(dev, id, 0, false, false, false); } /** Loading Loading @@ -162,19 +198,19 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id) static inline struct reset_control *reset_control_get_shared( struct device *dev, const char *id) { return __reset_control_get(dev, id, 0, true, false); return __reset_control_get(dev, id, 0, true, false, false); } static inline struct reset_control *reset_control_get_optional_exclusive( struct device *dev, const char *id) { return __reset_control_get(dev, id, 0, false, true); return __reset_control_get(dev, id, 0, false, true, true); } static inline struct reset_control *reset_control_get_optional_shared( struct device *dev, const char *id) { return __reset_control_get(dev, id, 0, true, true); return __reset_control_get(dev, id, 0, true, true, false); } /** Loading @@ -190,7 +226,7 @@ static inline struct reset_control *reset_control_get_optional_shared( static inline struct reset_control *of_reset_control_get_exclusive( struct device_node *node, const char *id) { return __of_reset_control_get(node, id, 0, false, false); return __of_reset_control_get(node, id, 0, false, false, true); } /** Loading @@ -215,7 +251,7 @@ static inline struct reset_control *of_reset_control_get_exclusive( static inline struct reset_control *of_reset_control_get_shared( struct device_node *node, const char *id) { return __of_reset_control_get(node, id, 0, true, false); return __of_reset_control_get(node, id, 0, true, false, false); } /** Loading @@ -232,7 +268,7 @@ static inline struct reset_control *of_reset_control_get_shared( static inline struct reset_control *of_reset_control_get_exclusive_by_index( struct device_node *node, int index) { return __of_reset_control_get(node, NULL, index, false, false); return __of_reset_control_get(node, NULL, index, false, false, true); } /** Loading Loading @@ -260,7 +296,7 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index( static inline struct reset_control *of_reset_control_get_shared_by_index( struct device_node *node, int index) { return __of_reset_control_get(node, NULL, index, true, false); return __of_reset_control_get(node, NULL, index, true, false, false); } /** Loading @@ -279,7 +315,26 @@ static inline struct reset_control * __must_check devm_reset_control_get_exclusive(struct device *dev, const char *id) { return __devm_reset_control_get(dev, id, 0, false, false); return __devm_reset_control_get(dev, id, 0, false, false, true); } /** * devm_reset_control_get_exclusive_released - resource managed * reset_control_get_exclusive_released() * @dev: device to be reset by the controller * @id: reset line name * * Managed reset_control_get_exclusive_released(). For reset controllers * returned from this function, reset_control_put() is called automatically on * driver detach. * * See reset_control_get_exclusive_released() for more information. */ static inline struct reset_control * __must_check devm_reset_control_get_exclusive_released(struct device *dev, const char *id) { return __devm_reset_control_get(dev, id, 0, false, false, false); } /** Loading @@ -294,19 +349,19 @@ __must_check devm_reset_control_get_exclusive(struct device *dev, static inline struct reset_control *devm_reset_control_get_shared( struct device *dev, const char *id) { return __devm_reset_control_get(dev, id, 0, true, false); return __devm_reset_control_get(dev, id, 0, true, false, false); } static inline struct reset_control *devm_reset_control_get_optional_exclusive( struct device *dev, const char *id) { return __devm_reset_control_get(dev, id, 0, false, true); return __devm_reset_control_get(dev, id, 0, false, true, true); } static inline struct reset_control *devm_reset_control_get_optional_shared( struct device *dev, const char *id) { return __devm_reset_control_get(dev, id, 0, true, true); return __devm_reset_control_get(dev, id, 0, true, true, false); } /** Loading @@ -324,7 +379,7 @@ static inline struct reset_control *devm_reset_control_get_optional_shared( static inline struct reset_control * devm_reset_control_get_exclusive_by_index(struct device *dev, int index) { return __devm_reset_control_get(dev, NULL, index, false, false); return __devm_reset_control_get(dev, NULL, index, false, false, true); } /** Loading @@ -340,7 +395,7 @@ devm_reset_control_get_exclusive_by_index(struct device *dev, int index) static inline struct reset_control * devm_reset_control_get_shared_by_index(struct device *dev, int index) { return __devm_reset_control_get(dev, NULL, index, true, false); return __devm_reset_control_get(dev, NULL, index, true, false, false); } /* Loading Loading @@ -412,24 +467,30 @@ devm_reset_control_array_get_optional_shared(struct device *dev) static inline struct reset_control * of_reset_control_array_get_exclusive(struct device_node *node) { return of_reset_control_array_get(node, false, false); return of_reset_control_array_get(node, false, false, true); } static inline struct reset_control * of_reset_control_array_get_exclusive_released(struct device_node *node) { return of_reset_control_array_get(node, false, false, false); } static inline struct reset_control * of_reset_control_array_get_shared(struct device_node *node) { return of_reset_control_array_get(node, true, false); return of_reset_control_array_get(node, true, false, true); } static inline struct reset_control * of_reset_control_array_get_optional_exclusive(struct device_node *node) { return of_reset_control_array_get(node, false, true); return of_reset_control_array_get(node, false, true, true); } static inline struct reset_control * of_reset_control_array_get_optional_shared(struct device_node *node) { return of_reset_control_array_get(node, true, true); return of_reset_control_array_get(node, true, true, true); } #endif