diff mbox series

[02/11] Input: iqs7222 - report malformed properties

Message ID 20220908131548.48120-3-jeff@labundy.com
State New
Headers show
Series Additional fixes for Azoteq IQS7222A/B/C | expand

Commit Message

Jeff LaBundy Sept. 8, 2022, 1:15 p.m. UTC
Nonzero return values of several calls to fwnode_property_read_u32()
are silenty ignored, leaving no way to know that the properties were
not applied in the event of an error.

To solve this problem, follow the design pattern used throughout the
rest of the driver by first checking if the property is present, and
then evaluating the return value of fwnode_property_read_u32().

Fixes: e505edaedcb9 ("Input: add support for Azoteq IQS7222A/B/C")
Signed-off-by: Jeff LaBundy <jeff@labundy.com>
---
 drivers/input/misc/iqs7222.c | 65 ++++++++++++++++++++++++++++++------
 1 file changed, 55 insertions(+), 10 deletions(-)

Comments

Dmitry Torokhov Sept. 8, 2022, 9:21 p.m. UTC | #1
On Thu, Sep 08, 2022 at 08:15:39AM -0500, Jeff LaBundy wrote:
> Nonzero return values of several calls to fwnode_property_read_u32()
> are silenty ignored, leaving no way to know that the properties were
> not applied in the event of an error.
> 
> To solve this problem, follow the design pattern used throughout the
> rest of the driver by first checking if the property is present, and
> then evaluating the return value of fwnode_property_read_u32().
> 
> Fixes: e505edaedcb9 ("Input: add support for Azoteq IQS7222A/B/C")
> Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> ---
>  drivers/input/misc/iqs7222.c | 65 ++++++++++++++++++++++++++++++------
>  1 file changed, 55 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
> index 04c1050d845c..fdade24caa8a 100644
> --- a/drivers/input/misc/iqs7222.c
> +++ b/drivers/input/misc/iqs7222.c
> @@ -1819,8 +1819,17 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
>  		chan_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_FOLLOW;
>  		chan_setup[4] = val * 42 + 1048;
>  
> -		if (!fwnode_property_read_u32(chan_node, "azoteq,ref-weight",
> -					      &val)) {
> +		if (fwnode_property_present(chan_node, "azoteq,ref-weight")) {
> +			error = fwnode_property_read_u32(chan_node,
> +							 "azoteq,ref-weight",
> +							 &val);

fwnode_property_read_u32() returns EINVAL if property is missing, so
maybe have:

		error = fwnode_property_read_u32(chan_node,
						 "azoteq,ref-weight", &val);
		if (!error) {
			...
		} else {
			if (error != -EINVAL) {
				dev_err(&client->dev,
					"Failed to read %s reference weight: %d\n",
					fwnode_get_name(chan_node), error);
				goto put_chan_node;
			}
		}

to avoid double calls into property handling code?
Jeff LaBundy Sept. 9, 2022, 2:08 a.m. UTC | #2
Hi Dmitry,

On Thu, Sep 08, 2022 at 02:21:13PM -0700, Dmitry Torokhov wrote:
> On Thu, Sep 08, 2022 at 08:15:39AM -0500, Jeff LaBundy wrote:
> > Nonzero return values of several calls to fwnode_property_read_u32()
> > are silenty ignored, leaving no way to know that the properties were
> > not applied in the event of an error.
> > 
> > To solve this problem, follow the design pattern used throughout the
> > rest of the driver by first checking if the property is present, and
> > then evaluating the return value of fwnode_property_read_u32().
> > 
> > Fixes: e505edaedcb9 ("Input: add support for Azoteq IQS7222A/B/C")
> > Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> > ---
> >  drivers/input/misc/iqs7222.c | 65 ++++++++++++++++++++++++++++++------
> >  1 file changed, 55 insertions(+), 10 deletions(-)
> > 
> > diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
> > index 04c1050d845c..fdade24caa8a 100644
> > --- a/drivers/input/misc/iqs7222.c
> > +++ b/drivers/input/misc/iqs7222.c
> > @@ -1819,8 +1819,17 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
> >  		chan_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_FOLLOW;
> >  		chan_setup[4] = val * 42 + 1048;
> >  
> > -		if (!fwnode_property_read_u32(chan_node, "azoteq,ref-weight",
> > -					      &val)) {
> > +		if (fwnode_property_present(chan_node, "azoteq,ref-weight")) {
> > +			error = fwnode_property_read_u32(chan_node,
> > +							 "azoteq,ref-weight",
> > +							 &val);
> 
> fwnode_property_read_u32() returns EINVAL if property is missing, so
> maybe have:
> 
> 		error = fwnode_property_read_u32(chan_node,
> 						 "azoteq,ref-weight", &val);
> 		if (!error) {
> 			...
> 		} else {
> 			if (error != -EINVAL) {
> 				dev_err(&client->dev,
> 					"Failed to read %s reference weight: %d\n",
> 					fwnode_get_name(chan_node), error);
> 				goto put_chan_node;
> 			}
> 		}
> 
> to avoid double calls into property handling code?

That's a better idea; I can fold this into the helper functions proposed
for the previous patch too.

> 
> -- 
> Dmitry

Kind regards,
Jeff LaBundy
Dmitry Torokhov Sept. 9, 2022, 4:42 a.m. UTC | #3
On Thu, Sep 08, 2022 at 09:08:09PM -0500, Jeff LaBundy wrote:
> Hi Dmitry,
> 
> On Thu, Sep 08, 2022 at 02:21:13PM -0700, Dmitry Torokhov wrote:
> > On Thu, Sep 08, 2022 at 08:15:39AM -0500, Jeff LaBundy wrote:
> > > Nonzero return values of several calls to fwnode_property_read_u32()
> > > are silenty ignored, leaving no way to know that the properties were
> > > not applied in the event of an error.
> > > 
> > > To solve this problem, follow the design pattern used throughout the
> > > rest of the driver by first checking if the property is present, and
> > > then evaluating the return value of fwnode_property_read_u32().
> > > 
> > > Fixes: e505edaedcb9 ("Input: add support for Azoteq IQS7222A/B/C")
> > > Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> > > ---
> > >  drivers/input/misc/iqs7222.c | 65 ++++++++++++++++++++++++++++++------
> > >  1 file changed, 55 insertions(+), 10 deletions(-)
> > > 
> > > diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
> > > index 04c1050d845c..fdade24caa8a 100644
> > > --- a/drivers/input/misc/iqs7222.c
> > > +++ b/drivers/input/misc/iqs7222.c
> > > @@ -1819,8 +1819,17 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
> > >  		chan_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_FOLLOW;
> > >  		chan_setup[4] = val * 42 + 1048;
> > >  
> > > -		if (!fwnode_property_read_u32(chan_node, "azoteq,ref-weight",
> > > -					      &val)) {
> > > +		if (fwnode_property_present(chan_node, "azoteq,ref-weight")) {
> > > +			error = fwnode_property_read_u32(chan_node,
> > > +							 "azoteq,ref-weight",
> > > +							 &val);
> > 
> > fwnode_property_read_u32() returns EINVAL if property is missing, so
> > maybe have:
> > 
> > 		error = fwnode_property_read_u32(chan_node,
> > 						 "azoteq,ref-weight", &val);
> > 		if (!error) {
> > 			...
> > 		} else {
> > 			if (error != -EINVAL) {
> > 				dev_err(&client->dev,
> > 					"Failed to read %s reference weight: %d\n",
> > 					fwnode_get_name(chan_node), error);
> > 				goto put_chan_node;
> > 			}
> > 		}
> > 
> > to avoid double calls into property handling code?
> 
> That's a better idea; I can fold this into the helper functions proposed
> for the previous patch too.

We might be talking about different helpers. I had in mind:

static int __iqs7222_parse_cycle(...)
{
...
}

static int iqs7222_parse_cycle(...)
{
...
	int retval = 0;

	error = iqs7222_parse_props(iqs7222, &cycle_node, cycle_index,
				    IQS7222_REG_GRP_CYCLE,
				    IQS7222_REG_KEY_NONE);
	if (error)
		return error;

	if (cycle_node) {
		retval = __iqs7222_parse_cycle(...);
		fwnode_put(cycle_node);
	}


	return retval;
}

so that we drop the node from one place.

Thanks.
Jeff LaBundy Sept. 10, 2022, 12:04 a.m. UTC | #4
Hi Dmitry,

On Thu, Sep 08, 2022 at 09:42:47PM -0700, Dmitry Torokhov wrote:
> On Thu, Sep 08, 2022 at 09:08:09PM -0500, Jeff LaBundy wrote:
> > Hi Dmitry,
> > 
> > On Thu, Sep 08, 2022 at 02:21:13PM -0700, Dmitry Torokhov wrote:
> > > On Thu, Sep 08, 2022 at 08:15:39AM -0500, Jeff LaBundy wrote:
> > > > Nonzero return values of several calls to fwnode_property_read_u32()
> > > > are silenty ignored, leaving no way to know that the properties were
> > > > not applied in the event of an error.
> > > > 
> > > > To solve this problem, follow the design pattern used throughout the
> > > > rest of the driver by first checking if the property is present, and
> > > > then evaluating the return value of fwnode_property_read_u32().
> > > > 
> > > > Fixes: e505edaedcb9 ("Input: add support for Azoteq IQS7222A/B/C")
> > > > Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> > > > ---
> > > >  drivers/input/misc/iqs7222.c | 65 ++++++++++++++++++++++++++++++------
> > > >  1 file changed, 55 insertions(+), 10 deletions(-)
> > > > 
> > > > diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
> > > > index 04c1050d845c..fdade24caa8a 100644
> > > > --- a/drivers/input/misc/iqs7222.c
> > > > +++ b/drivers/input/misc/iqs7222.c
> > > > @@ -1819,8 +1819,17 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
> > > >  		chan_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_FOLLOW;
> > > >  		chan_setup[4] = val * 42 + 1048;
> > > >  
> > > > -		if (!fwnode_property_read_u32(chan_node, "azoteq,ref-weight",
> > > > -					      &val)) {
> > > > +		if (fwnode_property_present(chan_node, "azoteq,ref-weight")) {
> > > > +			error = fwnode_property_read_u32(chan_node,
> > > > +							 "azoteq,ref-weight",
> > > > +							 &val);
> > > 
> > > fwnode_property_read_u32() returns EINVAL if property is missing, so
> > > maybe have:
> > > 
> > > 		error = fwnode_property_read_u32(chan_node,
> > > 						 "azoteq,ref-weight", &val);
> > > 		if (!error) {
> > > 			...
> > > 		} else {
> > > 			if (error != -EINVAL) {
> > > 				dev_err(&client->dev,
> > > 					"Failed to read %s reference weight: %d\n",
> > > 					fwnode_get_name(chan_node), error);
> > > 				goto put_chan_node;
> > > 			}
> > > 		}
> > > 
> > > to avoid double calls into property handling code?
> > 
> > That's a better idea; I can fold this into the helper functions proposed
> > for the previous patch too.
> 
> We might be talking about different helpers. I had in mind:
> 
> static int __iqs7222_parse_cycle(...)
> {
> ...
> }
> 
> static int iqs7222_parse_cycle(...)
> {
> ...
> 	int retval = 0;
> 
> 	error = iqs7222_parse_props(iqs7222, &cycle_node, cycle_index,
> 				    IQS7222_REG_GRP_CYCLE,
> 				    IQS7222_REG_KEY_NONE);
> 	if (error)
> 		return error;
> 
> 	if (cycle_node) {
> 		retval = __iqs7222_parse_cycle(...);
> 		fwnode_put(cycle_node);
> 	}
> 
> 
> 	return retval;
> }
> 
> so that we drop the node from one place.

Right, originally I had imagined a wrapper around fwnode_property_read_u32()
that calls fwnode_handle_put() in the error path. However, your proposal is
even better.

Thanks for the fruitful discussion; I'll clean all of this up for v2.

> 
> Thanks.
> 
> -- 
> Dmitry

Kind regards,
Jeff LaBundy
diff mbox series

Patch

diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
index 04c1050d845c..fdade24caa8a 100644
--- a/drivers/input/misc/iqs7222.c
+++ b/drivers/input/misc/iqs7222.c
@@ -1819,8 +1819,17 @@  static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
 		chan_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_FOLLOW;
 		chan_setup[4] = val * 42 + 1048;
 
-		if (!fwnode_property_read_u32(chan_node, "azoteq,ref-weight",
-					      &val)) {
+		if (fwnode_property_present(chan_node, "azoteq,ref-weight")) {
+			error = fwnode_property_read_u32(chan_node,
+							 "azoteq,ref-weight",
+							 &val);
+			if (error) {
+				dev_err(&client->dev,
+					"Failed to read %s reference weight: %d\n",
+					fwnode_get_name(chan_node), error);
+				goto put_chan_node;
+			}
+
 			if (val > U16_MAX) {
 				dev_err(&client->dev,
 					"Invalid %s reference weight: %u\n",
@@ -1921,9 +1930,8 @@  static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
 			goto put_chan_node;
 		}
 
-		if (!fwnode_property_read_u32(event_node,
-					      "azoteq,timeout-press-ms",
-					      &val)) {
+		if (fwnode_property_present(event_node,
+					    "azoteq,timeout-press-ms")) {
 			/*
 			 * The IQS7222B employs a global pair of press timeout
 			 * registers as opposed to channel-specific registers.
@@ -1933,6 +1941,17 @@  static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
 				     &iqs7222->btn_setup[chan_index][2] :
 				     &sys_setup[9];
 
+			error = fwnode_property_read_u32(event_node,
+							 "azoteq,timeout-press-ms",
+							 &val);
+			if (error) {
+				dev_err(&client->dev,
+					"Failed to read %s press timeout: %d\n",
+					fwnode_get_name(chan_node), error);
+				fwnode_handle_put(event_node);
+				goto put_chan_node;
+			}
+
 			if (val > U8_MAX * 500) {
 				dev_err(&client->dev,
 					"Invalid %s press timeout: %u\n",
@@ -2098,7 +2117,15 @@  static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
 	if (fwnode_property_present(sldr_node, "azoteq,use-prox"))
 		sldr_setup[4 + reg_offset] -= 2;
 
-	if (!fwnode_property_read_u32(sldr_node, "azoteq,slider-size", &val)) {
+	if (fwnode_property_present(sldr_node, "azoteq,slider-size")) {
+		error = fwnode_property_read_u32(sldr_node,
+						 "azoteq,slider-size", &val);
+		if (error) {
+			dev_err(&client->dev, "Failed to read %s size: %d\n",
+				fwnode_get_name(sldr_node), error);
+			goto put_sldr_node;
+		}
+
 		if (!val || val > dev_desc->sldr_res) {
 			dev_err(&client->dev, "Invalid %s size: %u\n",
 				fwnode_get_name(sldr_node), val);
@@ -2115,7 +2142,16 @@  static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
 		}
 	}
 
-	if (!fwnode_property_read_u32(sldr_node, "azoteq,top-speed", &val)) {
+	if (fwnode_property_present(sldr_node, "azoteq,top-speed")) {
+		error = fwnode_property_read_u32(sldr_node,
+						 "azoteq,top-speed", &val);
+		if (error) {
+			dev_err(&client->dev,
+				"Failed to read %s top speed: %d\n",
+				fwnode_get_name(sldr_node), error);
+			goto put_sldr_node;
+		}
+
 		if (val > (reg_offset ? U16_MAX : U8_MAX * 4)) {
 			dev_err(&client->dev, "Invalid %s top speed: %u\n",
 				fwnode_get_name(sldr_node), val);
@@ -2131,10 +2167,19 @@  static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
 		}
 	}
 
-	if (!fwnode_property_read_u32(sldr_node, "linux,axis", &val)) {
-		u16 sldr_max = sldr_setup[3] - 1;
+	if (fwnode_property_present(sldr_node, "linux,axis")) {
+		u16 sldr_max;
+
+		error = fwnode_property_read_u32(sldr_node, "linux,axis", &val);
+		if (error) {
+			dev_err(&client->dev, "Failed to read %s axis: %d\n",
+				fwnode_get_name(sldr_node), error);
+			goto put_sldr_node;
+		}
 
-		if (!reg_offset) {
+		if (reg_offset) {
+			sldr_max = sldr_setup[3] - 1;
+		} else {
 			sldr_max = sldr_setup[2];
 
 			sldr_max &= IQS7222_SLDR_SETUP_2_RES_MASK;