diff mbox

[v2,4/9] pinctrl: sunxi: Deal with configless pins

Message ID d707c657502b87a7f8e70c7b44492bc95939f9f6.1476200742.git-series.maxime.ripard@free-electrons.com
State New
Headers show

Commit Message

Maxime Ripard Oct. 11, 2016, 3:46 p.m. UTC
Even though the our binding had the assumption that the allwinner,pull and
allwinner,drive properties were optional, the code never took that into
account.

Fix that.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 53 ++++++++++++++++++++--------
 1 file changed, 39 insertions(+), 14 deletions(-)

Comments

Chen-Yu Tsai Oct. 18, 2016, 7:47 a.m. UTC | #1
On Tue, Oct 11, 2016 at 11:46 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Even though the our binding had the assumption that the allwinner,pull and
> allwinner,drive properties were optional, the code never took that into
> account.
>
> Fix that.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c | 53 ++++++++++++++++++++--------
>  1 file changed, 39 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index 6f6f1e0011e2..2ee8d48ed5d3 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -218,20 +218,29 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node,
>  {
>         unsigned long *pinconfig;
>         unsigned int configlen = 0, idx = 0;
> +       int ret;
>
>         if (sunxi_pctrl_has_drive_prop(node))
>                 configlen++;
>         if (sunxi_pctrl_has_bias_prop(node))
>                 configlen++;
>
> +       /*
> +        * If we don't have any configuration, bail out
> +        */
> +       if (!configlen)
> +               return NULL;
> +
>         pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL);
>         if (!pinconfig)
> -               return NULL;
> +               return ERR_PTR(-ENOMEM);
>
>         if (sunxi_pctrl_has_drive_prop(node)) {
>                 int drive = sunxi_pctrl_parse_drive_prop(node);
> -               if (drive < 0)
> +               if (drive < 0) {
> +                       ret = drive;
>                         goto err_free;
> +               }
>
>                 pinconfig[idx++] = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH,
>                                                           drive);
> @@ -239,8 +248,10 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node,
>
>         if (sunxi_pctrl_has_bias_prop(node)) {
>                 int pull = sunxi_pctrl_parse_bias_prop(node);
> -               if (pull < 0)
> +               if (pull < 0) {
> +                       ret = pull;
>                         goto err_free;
> +               }
>
>                 pinconfig[idx++] = pinconf_to_config_packed(pull, 0);
>         }
> @@ -251,7 +262,7 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node,
>
>  err_free:
>         kfree(pinconfig);
> -       return NULL;
> +       return ERR_PTR(ret);
>  }
>
>  static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
> @@ -285,7 +296,10 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
>
>         /*
>          * We have two maps for each pin: one for the function, one
> -        * for the configuration (bias, strength, etc)
> +        * for the configuration (bias, strength, etc).
> +        *
> +        * We might be slightly overshooting, since we might not have
> +        * any configuration.
>          */
>         nmaps = npins * 2;
>         *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
> @@ -293,8 +307,8 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
>                 return -ENOMEM;
>
>         pinconfig = sunxi_pctrl_build_pin_config(node, &configlen);
> -       if (!pinconfig) {
> -               ret = -EINVAL;
> +       if (IS_ERR(pinconfig)) {
> +               ret = PTR_ERR(pinconfig);
>                 goto err_free_map;
>         }
>
> @@ -321,15 +335,24 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
>
>                 i++;
>
> -               (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
> -               (*map)[i].data.configs.group_or_pin = group;
> -               (*map)[i].data.configs.configs = pinconfig;
> -               (*map)[i].data.configs.num_configs = configlen;
> -
> -               i++;
> +               if (pinconfig) {
> +                       (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
> +                       (*map)[i].data.configs.group_or_pin = group;
> +                       (*map)[i].data.configs.configs = pinconfig;
> +                       (*map)[i].data.configs.num_configs = configlen;
> +                       i++;
> +               }
>         }
>
> -       *num_maps = nmaps;
> +       *num_maps = i;
> +
> +       /*
> +        * We know have the number of maps we need, we can resize our
> +        * map array
> +        */
> +       *map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL);
> +       if (!map)
> +               return -ENOMEM;
>
>         return 0;
>
> @@ -342,6 +365,8 @@ static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
>                                     struct pinctrl_map *map,
>                                     unsigned num_maps)
>  {
> +       unsigned long *pinconfig;

This looks out of place and context?

Otherwise,

Acked-by: Chen-Yu Tsai <wens@csie.org>

> +
>         /* All the maps have the same pin config, free only the first one */
>         kfree(map[0].data.configs.configs);
>         kfree(map);
> --
> git-series 0.8.10
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Maxime Ripard Oct. 19, 2016, 12:16 p.m. UTC | #2
On Tue, Oct 18, 2016 at 03:47:03PM +0800, Chen-Yu Tsai wrote:
> > @@ -342,6 +365,8 @@ static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
> >                                     struct pinctrl_map *map,
> >                                     unsigned num_maps)
> >  {
> > +       unsigned long *pinconfig;
> 
> This looks out of place and context?

Yeah, sorry, it's just a leftover from the previous version. This has
been removed.

Thanks!
Maxime
Linus Walleij Oct. 20, 2016, 12:52 p.m. UTC | #3
On Wed, Oct 19, 2016 at 2:16 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> On Tue, Oct 18, 2016 at 03:47:03PM +0800, Chen-Yu Tsai wrote:
>> > @@ -342,6 +365,8 @@ static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
>> >                                     struct pinctrl_map *map,
>> >                                     unsigned num_maps)
>> >  {
>> > +       unsigned long *pinconfig;
>>
>> This looks out of place and context?
>
> Yeah, sorry, it's just a leftover from the previous version. This has
> been removed.

Do you mean you will send a v3 of this series?

OK stopping to apply then.

But I have already applied patches 1, 2 and 3 so just resend the rest :)

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Maxime Ripard Oct. 20, 2016, 1:46 p.m. UTC | #4
Hi Linus,

On Thu, Oct 20, 2016 at 02:52:54PM +0200, Linus Walleij wrote:
> On Wed, Oct 19, 2016 at 2:16 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > On Tue, Oct 18, 2016 at 03:47:03PM +0800, Chen-Yu Tsai wrote:
> >> > @@ -342,6 +365,8 @@ static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
> >> >                                     struct pinctrl_map *map,
> >> >                                     unsigned num_maps)
> >> >  {
> >> > +       unsigned long *pinconfig;
> >>
> >> This looks out of place and context?
> >
> > Yeah, sorry, it's just a leftover from the previous version. This has
> > been removed.
> 
> Do you mean you will send a v3 of this series?

Yes, I was waiting for your input to do that, but I guess you're ok
with it :)

> OK stopping to apply then.
>
> But I have already applied patches 1, 2 and 3 so just resend the rest :)

Ack, I'll send it in a moment.

Thanks!
Maxime
diff mbox

Patch

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 6f6f1e0011e2..2ee8d48ed5d3 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -218,20 +218,29 @@  static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node,
 {
 	unsigned long *pinconfig;
 	unsigned int configlen = 0, idx = 0;
+	int ret;
 
 	if (sunxi_pctrl_has_drive_prop(node))
 		configlen++;
 	if (sunxi_pctrl_has_bias_prop(node))
 		configlen++;
 
+	/*
+	 * If we don't have any configuration, bail out
+	 */
+	if (!configlen)
+		return NULL;
+
 	pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL);
 	if (!pinconfig)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	if (sunxi_pctrl_has_drive_prop(node)) {
 		int drive = sunxi_pctrl_parse_drive_prop(node);
-		if (drive < 0)
+		if (drive < 0) {
+			ret = drive;
 			goto err_free;
+		}
 
 		pinconfig[idx++] = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH,
 							  drive);
@@ -239,8 +248,10 @@  static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node,
 
 	if (sunxi_pctrl_has_bias_prop(node)) {
 		int pull = sunxi_pctrl_parse_bias_prop(node);
-		if (pull < 0)
+		if (pull < 0) {
+			ret = pull;
 			goto err_free;
+		}
 
 		pinconfig[idx++] = pinconf_to_config_packed(pull, 0);
 	}
@@ -251,7 +262,7 @@  static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node,
 
 err_free:
 	kfree(pinconfig);
-	return NULL;
+	return ERR_PTR(ret);
 }
 
 static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
@@ -285,7 +296,10 @@  static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 
 	/*
 	 * We have two maps for each pin: one for the function, one
-	 * for the configuration (bias, strength, etc)
+	 * for the configuration (bias, strength, etc).
+	 *
+	 * We might be slightly overshooting, since we might not have
+	 * any configuration.
 	 */
 	nmaps = npins * 2;
 	*map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
@@ -293,8 +307,8 @@  static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 		return -ENOMEM;
 
 	pinconfig = sunxi_pctrl_build_pin_config(node, &configlen);
-	if (!pinconfig) {
-		ret = -EINVAL;
+	if (IS_ERR(pinconfig)) {
+		ret = PTR_ERR(pinconfig);
 		goto err_free_map;
 	}
 
@@ -321,15 +335,24 @@  static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 
 		i++;
 
-		(*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
-		(*map)[i].data.configs.group_or_pin = group;
-		(*map)[i].data.configs.configs = pinconfig;
-		(*map)[i].data.configs.num_configs = configlen;
-
-		i++;
+		if (pinconfig) {
+			(*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+			(*map)[i].data.configs.group_or_pin = group;
+			(*map)[i].data.configs.configs = pinconfig;
+			(*map)[i].data.configs.num_configs = configlen;
+			i++;
+		}
 	}
 
-	*num_maps = nmaps;
+	*num_maps = i;
+
+	/*
+	 * We know have the number of maps we need, we can resize our
+	 * map array
+	 */
+	*map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL);
+	if (!map)
+		return -ENOMEM;
 
 	return 0;
 
@@ -342,6 +365,8 @@  static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
 				    struct pinctrl_map *map,
 				    unsigned num_maps)
 {
+	unsigned long *pinconfig;
+
 	/* All the maps have the same pin config, free only the first one */
 	kfree(map[0].data.configs.configs);
 	kfree(map);