Message ID | 20220408184844.22829-1-andriy.shevchenko@linux.intel.com (mailing list archive) |
---|---|
State | Mainlined, archived |
Headers | show |
Series | [v6,1/5] device property: Allow error pointer to be passed to fwnode APIs | expand |
On Fri, Apr 08, 2022 at 09:48:40PM +0300, Andy Shevchenko wrote: > Some of the fwnode APIs might return an error pointer instead of NULL > or valid fwnode handle. The result of such API call may be considered > optional and hence the test for it is usually done in a form of > > fwnode = fwnode_find_reference(...); > if (IS_ERR(fwnode)) > ...error handling... > > Nevertheless the resulting fwnode may have bumped the reference count > and hence caller of the above API is obliged to call fwnode_handle_put(). > Since fwnode may be not valid either as NULL or error pointer the check > has to be performed there. This approach uglifies the code and adds > a point of making a mistake, i.e. forgetting about error point case. > > To prevent this, allow an error pointer to be passed to the fwnode APIs. Rafael and Greg, if this okay for you, can the first three patches be applied, so we will have at least the fix in and consider constification a further work?
On Mon, Apr 11, 2022 at 04:50:11PM +0300, Andy Shevchenko wrote: > On Fri, Apr 08, 2022 at 09:48:40PM +0300, Andy Shevchenko wrote: > > Some of the fwnode APIs might return an error pointer instead of NULL > > or valid fwnode handle. The result of such API call may be considered > > optional and hence the test for it is usually done in a form of > > > > fwnode = fwnode_find_reference(...); > > if (IS_ERR(fwnode)) > > ...error handling... > > > > Nevertheless the resulting fwnode may have bumped the reference count > > and hence caller of the above API is obliged to call fwnode_handle_put(). > > Since fwnode may be not valid either as NULL or error pointer the check > > has to be performed there. This approach uglifies the code and adds > > a point of making a mistake, i.e. forgetting about error point case. > > > > To prevent this, allow an error pointer to be passed to the fwnode APIs. > > Rafael and Greg, if this okay for you, can the first three patches be > applied, so we will have at least the fix in and consider constification > a further work? Give us a chance, you sent this on friday and are asking about it first thing Monday morning? Please go and review other patches sent on the list to help us catch up. greg k-h
On Mon, Apr 11, 2022 at 04:28:06PM +0200, Greg Kroah-Hartman wrote: > On Mon, Apr 11, 2022 at 04:50:11PM +0300, Andy Shevchenko wrote: > > On Fri, Apr 08, 2022 at 09:48:40PM +0300, Andy Shevchenko wrote: > > > Some of the fwnode APIs might return an error pointer instead of NULL > > > or valid fwnode handle. The result of such API call may be considered > > > optional and hence the test for it is usually done in a form of > > > > > > fwnode = fwnode_find_reference(...); > > > if (IS_ERR(fwnode)) > > > ...error handling... > > > > > > Nevertheless the resulting fwnode may have bumped the reference count > > > and hence caller of the above API is obliged to call fwnode_handle_put(). > > > Since fwnode may be not valid either as NULL or error pointer the check > > > has to be performed there. This approach uglifies the code and adds > > > a point of making a mistake, i.e. forgetting about error point case. > > > > > > To prevent this, allow an error pointer to be passed to the fwnode APIs. > > > > Rafael and Greg, if this okay for you, can the first three patches be > > applied, so we will have at least the fix in and consider constification > > a further work? > > Give us a chance, you sent this on friday and are asking about it first > thing Monday morning? > > Please go and review other patches sent on the list to help us catch up. OK! Reviewed (actually commented on) a few patches so far.
On Mon, Apr 11, 2022 at 5:49 PM Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > > On Mon, Apr 11, 2022 at 04:28:06PM +0200, Greg Kroah-Hartman wrote: > > On Mon, Apr 11, 2022 at 04:50:11PM +0300, Andy Shevchenko wrote: > > > On Fri, Apr 08, 2022 at 09:48:40PM +0300, Andy Shevchenko wrote: > > > > Some of the fwnode APIs might return an error pointer instead of NULL > > > > or valid fwnode handle. The result of such API call may be considered > > > > optional and hence the test for it is usually done in a form of > > > > > > > > fwnode = fwnode_find_reference(...); > > > > if (IS_ERR(fwnode)) > > > > ...error handling... > > > > > > > > Nevertheless the resulting fwnode may have bumped the reference count > > > > and hence caller of the above API is obliged to call fwnode_handle_put(). > > > > Since fwnode may be not valid either as NULL or error pointer the check > > > > has to be performed there. This approach uglifies the code and adds > > > > a point of making a mistake, i.e. forgetting about error point case. > > > > > > > > To prevent this, allow an error pointer to be passed to the fwnode APIs. > > > > > > Rafael and Greg, if this okay for you, can the first three patches be > > > applied, so we will have at least the fix in and consider constification > > > a further work? > > > > Give us a chance, you sent this on friday and are asking about it first > > thing Monday morning? > > > > Please go and review other patches sent on the list to help us catch up. > > OK! Reviewed (actually commented on) a few patches so far. I've just queued up the first three patches in the series for 5.19. Thanks!
On Wed, Apr 13, 2022 at 08:06:27PM +0200, Rafael J. Wysocki wrote: > On Mon, Apr 11, 2022 at 5:49 PM Andy Shevchenko > <andriy.shevchenko@linux.intel.com> wrote: > > On Mon, Apr 11, 2022 at 04:28:06PM +0200, Greg Kroah-Hartman wrote: > > > On Mon, Apr 11, 2022 at 04:50:11PM +0300, Andy Shevchenko wrote: > > > > On Fri, Apr 08, 2022 at 09:48:40PM +0300, Andy Shevchenko wrote: ... > > > > Rafael and Greg, if this okay for you, can the first three patches be > > > > applied, so we will have at least the fix in and consider constification > > > > a further work? > > > > > > Give us a chance, you sent this on friday and are asking about it first > > > thing Monday morning? > > > > > > Please go and review other patches sent on the list to help us catch up. > > > > OK! Reviewed (actually commented on) a few patches so far. > > I've just queued up the first three patches in the series for 5.19. Thank you!
diff --git a/drivers/base/property.c b/drivers/base/property.c index 3560c4419d11..6ecc1398b0ba 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -47,12 +47,14 @@ bool fwnode_property_present(const struct fwnode_handle *fwnode, { bool ret; + if (IS_ERR_OR_NULL(fwnode)) + return false; + ret = fwnode_call_bool_op(fwnode, property_present, propname); - if (ret == false && !IS_ERR_OR_NULL(fwnode) && - !IS_ERR_OR_NULL(fwnode->secondary)) - ret = fwnode_call_bool_op(fwnode->secondary, property_present, - propname); - return ret; + if (ret) + return ret; + + return fwnode_call_bool_op(fwnode->secondary, property_present, propname); } EXPORT_SYMBOL_GPL(fwnode_property_present); @@ -232,15 +234,16 @@ static int fwnode_property_read_int_array(const struct fwnode_handle *fwnode, { int ret; + if (IS_ERR_OR_NULL(fwnode)) + return -EINVAL; + ret = fwnode_call_int_op(fwnode, property_read_int_array, propname, elem_size, val, nval); - if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) && - !IS_ERR_OR_NULL(fwnode->secondary)) - ret = fwnode_call_int_op( - fwnode->secondary, property_read_int_array, propname, - elem_size, val, nval); + if (ret != -EINVAL) + return ret; - return ret; + return fwnode_call_int_op(fwnode->secondary, property_read_int_array, propname, + elem_size, val, nval); } /** @@ -371,14 +374,16 @@ int fwnode_property_read_string_array(const struct fwnode_handle *fwnode, { int ret; + if (IS_ERR_OR_NULL(fwnode)) + return -EINVAL; + ret = fwnode_call_int_op(fwnode, property_read_string_array, propname, val, nval); - if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) && - !IS_ERR_OR_NULL(fwnode->secondary)) - ret = fwnode_call_int_op(fwnode->secondary, - property_read_string_array, propname, - val, nval); - return ret; + if (ret != -EINVAL) + return ret; + + return fwnode_call_int_op(fwnode->secondary, property_read_string_array, propname, + val, nval); } EXPORT_SYMBOL_GPL(fwnode_property_read_string_array); @@ -480,15 +485,19 @@ int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode, { int ret; + if (IS_ERR_OR_NULL(fwnode)) + return -ENOENT; + ret = fwnode_call_int_op(fwnode, get_reference_args, prop, nargs_prop, nargs, index, args); + if (ret == 0) + return ret; - if (ret < 0 && !IS_ERR_OR_NULL(fwnode) && - !IS_ERR_OR_NULL(fwnode->secondary)) - ret = fwnode_call_int_op(fwnode->secondary, get_reference_args, - prop, nargs_prop, nargs, index, args); + if (IS_ERR_OR_NULL(fwnode->secondary)) + return ret; - return ret; + return fwnode_call_int_op(fwnode->secondary, get_reference_args, prop, nargs_prop, + nargs, index, args); } EXPORT_SYMBOL_GPL(fwnode_property_get_reference_args); @@ -635,12 +644,13 @@ EXPORT_SYMBOL_GPL(fwnode_count_parents); struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwnode, unsigned int depth) { - unsigned int i; - fwnode_handle_get(fwnode); - for (i = 0; i < depth && fwnode; i++) + do { + if (depth-- == 0) + break; fwnode = fwnode_get_next_parent(fwnode); + } while (fwnode); return fwnode; } @@ -659,17 +669,17 @@ EXPORT_SYMBOL_GPL(fwnode_get_nth_parent); bool fwnode_is_ancestor_of(struct fwnode_handle *test_ancestor, struct fwnode_handle *test_child) { - if (!test_ancestor) + if (IS_ERR_OR_NULL(test_ancestor)) return false; fwnode_handle_get(test_child); - while (test_child) { + do { if (test_child == test_ancestor) { fwnode_handle_put(test_child); return true; } test_child = fwnode_get_next_parent(test_child); - } + } while (test_child); return false; } @@ -698,7 +708,7 @@ fwnode_get_next_available_child_node(const struct fwnode_handle *fwnode, { struct fwnode_handle *next_child = child; - if (!fwnode) + if (IS_ERR_OR_NULL(fwnode)) return NULL; do { @@ -722,16 +732,16 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev, const struct fwnode_handle *fwnode = dev_fwnode(dev); struct fwnode_handle *next; + if (IS_ERR_OR_NULL(fwnode)) + return NULL; + /* Try to find a child in primary fwnode */ next = fwnode_get_next_child_node(fwnode, child); if (next) return next; /* When no more children in primary, continue with secondary */ - if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary)) - next = fwnode_get_next_child_node(fwnode->secondary, child); - - return next; + return fwnode_get_next_child_node(fwnode->secondary, child); } EXPORT_SYMBOL_GPL(device_get_next_child_node); @@ -798,6 +808,9 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put); */ bool fwnode_device_is_available(const struct fwnode_handle *fwnode) { + if (IS_ERR_OR_NULL(fwnode)) + return false; + if (!fwnode_has_op(fwnode, device_is_available)) return true; @@ -958,14 +971,14 @@ fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode, parent = fwnode_graph_get_port_parent(prev); else parent = fwnode; + if (IS_ERR_OR_NULL(parent)) + return NULL; ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev); + if (ep) + return ep; - if (IS_ERR_OR_NULL(ep) && - !IS_ERR_OR_NULL(parent) && !IS_ERR_OR_NULL(parent->secondary)) - ep = fwnode_graph_get_next_endpoint(parent->secondary, NULL); - - return ep; + return fwnode_graph_get_next_endpoint(parent->secondary, NULL); } EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint); diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 6ab69871b06d..9a81c4410b9f 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h @@ -153,12 +153,12 @@ struct fwnode_operations { int (*add_links)(struct fwnode_handle *fwnode); }; -#define fwnode_has_op(fwnode, op) \ - ((fwnode) && (fwnode)->ops && (fwnode)->ops->op) +#define fwnode_has_op(fwnode, op) \ + (!IS_ERR_OR_NULL(fwnode) && (fwnode)->ops && (fwnode)->ops->op) + #define fwnode_call_int_op(fwnode, op, ...) \ - (fwnode ? (fwnode_has_op(fwnode, op) ? \ - (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : -ENXIO) : \ - -EINVAL) + (fwnode_has_op(fwnode, op) ? \ + (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : (IS_ERR_OR_NULL(fwnode) ? -EINVAL : -ENXIO)) #define fwnode_call_bool_op(fwnode, op, ...) \ (fwnode_has_op(fwnode, op) ? \