From: Ramiro Oliveira Ramiro.Oliveira@synopsys.com
commit bb475230b8e59a547ab66ac3b02572df21a580e9 upstream.
The *_get_optional_* functions weren't really optional so this patch makes them really optional.
These *_get_optional_* functions will now return NULL instead of an error if no matching reset phandle is found in the DT, and all the reset_control_* functions now accept NULL rstc pointers.
Signed-off-by: Ramiro Oliveira Ramiro.Oliveira@synopsys.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de --- Please apply to v4.9.y stable tree. --- drivers/reset/core.c | 48 +++++++++++++++++++++++++++++++++---------- include/linux/reset.h | 45 +++++++++++++++++++++++----------------- 2 files changed, 63 insertions(+), 30 deletions(-)
diff --git a/drivers/reset/core.c b/drivers/reset/core.c index b8ae1dbd4c17..75821417b799 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -135,11 +135,16 @@ EXPORT_SYMBOL_GPL(devm_reset_controller_register); * @rstc: reset controller * * Calling this on a shared reset controller is an error. + * + * If rstc is NULL it is an optional reset and the function will just + * return 0. */ int reset_control_reset(struct reset_control *rstc) { - if (WARN_ON(IS_ERR_OR_NULL(rstc)) || - WARN_ON(rstc->shared)) + if (!rstc) + return 0; + + if (WARN_ON(IS_ERR(rstc))) return -EINVAL;
if (rstc->rcdev->ops->reset) @@ -159,10 +164,16 @@ EXPORT_SYMBOL_GPL(reset_control_reset); * * For shared reset controls a driver cannot expect the hw's registers and * internal state to be reset, but must be prepared for this to happen. + * + * If rstc is NULL it is an optional reset and the function will just + * return 0. */ int reset_control_assert(struct reset_control *rstc) { - if (WARN_ON(IS_ERR_OR_NULL(rstc))) + if (!rstc) + return 0; + + if (WARN_ON(IS_ERR(rstc))) return -EINVAL;
if (!rstc->rcdev->ops->assert) @@ -185,10 +196,16 @@ EXPORT_SYMBOL_GPL(reset_control_assert); * @rstc: reset controller * * After calling this function, the reset is guaranteed to be deasserted. + * + * If rstc is NULL it is an optional reset and the function will just + * return 0. */ int reset_control_deassert(struct reset_control *rstc) { - if (WARN_ON(IS_ERR_OR_NULL(rstc))) + if (!rstc) + return 0; + + if (WARN_ON(IS_ERR(rstc))) return -EINVAL;
if (!rstc->rcdev->ops->deassert) @@ -206,12 +223,15 @@ EXPORT_SYMBOL_GPL(reset_control_deassert); /** * reset_control_status - returns a negative errno if not supported, a * positive value if the reset line is asserted, or zero if the reset - * line is not asserted. + * line is not asserted or if the desc is NULL (optional reset). * @rstc: reset controller */ int reset_control_status(struct reset_control *rstc) { - if (WARN_ON(IS_ERR_OR_NULL(rstc))) + if (!rstc) + return 0; + + if (WARN_ON(IS_ERR(rstc))) return -EINVAL;
if (rstc->rcdev->ops->status) @@ -268,7 +288,8 @@ static void __reset_control_put(struct reset_control *rstc) }
struct reset_control *__of_reset_control_get(struct device_node *node, - const char *id, int index, int shared) + const char *id, int index, bool shared, + bool optional) { struct reset_control *rstc; struct reset_controller_dev *r, *rcdev; @@ -282,14 +303,18 @@ struct reset_control *__of_reset_control_get(struct device_node *node, if (id) { index = of_property_match_string(node, "reset-names", id); + if (index == -EILSEQ) + return ERR_PTR(index); if (index < 0) - return ERR_PTR(-ENOENT); + return optional ? NULL : ERR_PTR(-ENOENT); }
ret = of_parse_phandle_with_args(node, "resets", "#reset-cells", index, &args); - if (ret) + if (ret == -EINVAL) return ERR_PTR(ret); + if (ret) + return optional ? NULL : ERR_PTR(ret);
mutex_lock(&reset_list_mutex); rcdev = NULL; @@ -348,7 +373,8 @@ 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, int shared) + const char *id, int index, bool shared, + bool optional) { struct reset_control **ptr, *rstc;
@@ -358,7 +384,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev, return ERR_PTR(-ENOMEM);
rstc = __of_reset_control_get(dev ? dev->of_node : NULL, - id, index, shared); + id, index, shared, optional); if (!IS_ERR(rstc)) { *ptr = rstc; devres_add(dev, ptr); diff --git a/include/linux/reset.h b/include/linux/reset.h index 5daff15722d3..86b4ed75359e 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -13,10 +13,12 @@ int reset_control_deassert(struct reset_control *rstc); int reset_control_status(struct reset_control *rstc);
struct reset_control *__of_reset_control_get(struct device_node *node, - const char *id, int index, int shared); + const char *id, int index, bool shared, + bool optional); void reset_control_put(struct reset_control *rstc); struct reset_control *__devm_reset_control_get(struct device *dev, - const char *id, int index, int shared); + const char *id, int index, bool shared, + bool optional);
int __must_check device_reset(struct device *dev);
@@ -69,14 +71,15 @@ static inline int device_reset_optional(struct device *dev)
static inline struct reset_control *__of_reset_control_get( struct device_node *node, - const char *id, int index, int shared) + const char *id, int index, bool shared, + bool optional) { return ERR_PTR(-ENOTSUPP); }
static inline struct reset_control *__devm_reset_control_get( - struct device *dev, - const char *id, int index, int shared) + struct device *dev, const char *id, + int index, bool shared, bool optional) { return ERR_PTR(-ENOTSUPP); } @@ -104,7 +107,8 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id) #ifndef CONFIG_RESET_CONTROLLER WARN_ON(1); #endif - return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0); + return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, false, + false); }
/** @@ -132,19 +136,22 @@ __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 __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 1); + return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, true, + false); }
static inline struct reset_control *reset_control_get_optional_exclusive( struct device *dev, const char *id) { - return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0); + return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, false, + true); }
static inline struct reset_control *reset_control_get_optional_shared( struct device *dev, const char *id) { - return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 1); + return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, true, + true); }
/** @@ -160,7 +167,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, 0); + return __of_reset_control_get(node, id, 0, false, false); }
/** @@ -185,7 +192,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, 1); + return __of_reset_control_get(node, id, 0, true, false); }
/** @@ -202,7 +209,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, 0); + return __of_reset_control_get(node, NULL, index, false, false); }
/** @@ -230,7 +237,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, 1); + return __of_reset_control_get(node, NULL, index, true, false); }
/** @@ -252,7 +259,7 @@ __must_check devm_reset_control_get_exclusive(struct device *dev, #ifndef CONFIG_RESET_CONTROLLER WARN_ON(1); #endif - return __devm_reset_control_get(dev, id, 0, 0); + return __devm_reset_control_get(dev, id, 0, false, false); }
/** @@ -267,19 +274,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, 1); + return __devm_reset_control_get(dev, id, 0, true, 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, 0); + return __devm_reset_control_get(dev, id, 0, false, 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, 1); + return __devm_reset_control_get(dev, id, 0, true, true); }
/** @@ -297,7 +304,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, 0); + return __devm_reset_control_get(dev, NULL, index, false, false); }
/** @@ -313,7 +320,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, 1); + return __devm_reset_control_get(dev, NULL, index, true, false); }
/*
On Mon, Dec 03, 2018 at 11:30:29AM -0600, Dinh Nguyen wrote:
From: Ramiro Oliveira Ramiro.Oliveira@synopsys.com
commit bb475230b8e59a547ab66ac3b02572df21a580e9 upstream.
The *_get_optional_* functions weren't really optional so this patch makes them really optional.
These *_get_optional_* functions will now return NULL instead of an error if no matching reset phandle is found in the DT, and all the reset_control_* functions now accept NULL rstc pointers.
Signed-off-by: Ramiro Oliveira Ramiro.Oliveira@synopsys.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de
Please apply to v4.9.y stable tree.
The original commit had a few upstream fixes:
bb6c7768385b reset: remove remaining WARN_ON() in <linux/reset.h> 1554bbd4ad40 reset: make device_reset_optional() really optional 62e24c5775ec reset: add exported __reset_control_get, return NULL if optional 0ca10b60ceeb reset: fix optional reset_control_get stubs to return NULL 4891486fb2c8 reset: core: fix reset_control_put
We'll need to backport them to 4.9 as well if you backport this commit.
-- Thanks, Sasha
On 12/3/18 11:44 AM, Sasha Levin wrote:
On Mon, Dec 03, 2018 at 11:30:29AM -0600, Dinh Nguyen wrote:
From: Ramiro Oliveira Ramiro.Oliveira@synopsys.com
commit bb475230b8e59a547ab66ac3b02572df21a580e9 upstream.
The *_get_optional_* functions weren't really optional so this patch makes them really optional.
These *_get_optional_* functions will now return NULL instead of an error if no matching reset phandle is found in the DT, and all the reset_control_* functions now accept NULL rstc pointers.
Signed-off-by: Ramiro Oliveira Ramiro.Oliveira@synopsys.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de
Please apply to v4.9.y stable tree.
The original commit had a few upstream fixes:
bb6c7768385b reset: remove remaining WARN_ON() in <linux/reset.h> 1554bbd4ad40 reset: make device_reset_optional() really optional 62e24c5775ec reset: add exported __reset_control_get, return NULL if optional 0ca10b60ceeb reset: fix optional reset_control_get stubs to return NULL 4891486fb2c8 reset: core: fix reset_control_put
We'll need to backport them to 4.9 as well if you backport this commit.
Hmm..I was able to fix an ethernet driver load issue by just backporting this patch. Should I investigate backport of the other patches as well?
Dinh
On Mon, Dec 03, 2018 at 12:31:59PM -0600, Dinh Nguyen wrote:
On 12/3/18 11:44 AM, Sasha Levin wrote:
On Mon, Dec 03, 2018 at 11:30:29AM -0600, Dinh Nguyen wrote:
From: Ramiro Oliveira Ramiro.Oliveira@synopsys.com
commit bb475230b8e59a547ab66ac3b02572df21a580e9 upstream.
The *_get_optional_* functions weren't really optional so this patch makes them really optional.
These *_get_optional_* functions will now return NULL instead of an error if no matching reset phandle is found in the DT, and all the reset_control_* functions now accept NULL rstc pointers.
Signed-off-by: Ramiro Oliveira Ramiro.Oliveira@synopsys.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de
Please apply to v4.9.y stable tree.
The original commit had a few upstream fixes:
bb6c7768385b reset: remove remaining WARN_ON() in <linux/reset.h> 1554bbd4ad40 reset: make device_reset_optional() really optional 62e24c5775ec reset: add exported __reset_control_get, return NULL if optional 0ca10b60ceeb reset: fix optional reset_control_get stubs to return NULL 4891486fb2c8 reset: core: fix reset_control_put
We'll need to backport them to 4.9 as well if you backport this commit.
Hmm..I was able to fix an ethernet driver load issue by just backporting this patch. Should I investigate backport of the other patches as well?
That patch will probably work on it's own, but if there are fixes for it then they should be backported as well.
-- Thanks, Sasha
On Mon, Dec 03, 2018 at 11:30:29AM -0600, Dinh Nguyen wrote:
From: Ramiro Oliveira Ramiro.Oliveira@synopsys.com
commit bb475230b8e59a547ab66ac3b02572df21a580e9 upstream.
The *_get_optional_* functions weren't really optional so this patch makes them really optional.
These *_get_optional_* functions will now return NULL instead of an error if no matching reset phandle is found in the DT, and all the reset_control_* functions now accept NULL rstc pointers.
Signed-off-by: Ramiro Oliveira Ramiro.Oliveira@synopsys.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de
Please apply to v4.9.y stable tree.
drivers/reset/core.c | 48 +++++++++++++++++++++++++++++++++---------- include/linux/reset.h | 45 +++++++++++++++++++++++----------------- 2 files changed, 63 insertions(+), 30 deletions(-)
What problem is this solving? Why is this suddenly needed now?
thanks,
greg k-h
On 12/3/18 11:45 AM, Greg KH wrote:
On Mon, Dec 03, 2018 at 11:30:29AM -0600, Dinh Nguyen wrote:
From: Ramiro Oliveira Ramiro.Oliveira@synopsys.com
commit bb475230b8e59a547ab66ac3b02572df21a580e9 upstream.
The *_get_optional_* functions weren't really optional so this patch makes them really optional.
These *_get_optional_* functions will now return NULL instead of an error if no matching reset phandle is found in the DT, and all the reset_control_* functions now accept NULL rstc pointers.
Signed-off-by: Ramiro Oliveira Ramiro.Oliveira@synopsys.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de
Please apply to v4.9.y stable tree.
drivers/reset/core.c | 48 +++++++++++++++++++++++++++++++++---------- include/linux/reset.h | 45 +++++++++++++++++++++++----------------- 2 files changed, 63 insertions(+), 30 deletions(-)
What problem is this solving? Why is this suddenly needed now?
The v4.9-stable branch has this patch for stmmac ethernet driver:
"6f37f7b62baa net: stmmac: socfpga: add additional ocp reset line for Stratix10"
This patch calls devm_reset_control_get_optional(). This call ultimately fails without optional reset patch, causing the ethernet driver to fail to load.
Dinh
linux-stable-mirror@lists.linaro.org