linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] pinctrl: sunxi: Increase size of regulator array
@ 2019-01-10  8:26 Chen-Yu Tsai
  2019-01-10  8:26 ` [PATCH 2/2] pinctrl: sunxi: Fix and simplify pin bank regulator handling Chen-Yu Tsai
  2019-01-10 15:26 ` [PATCH 1/2] pinctrl: sunxi: Increase size of regulator array Maxime Ripard
  0 siblings, 2 replies; 5+ messages in thread
From: Chen-Yu Tsai @ 2019-01-10  8:26 UTC (permalink / raw)
  To: Maxime Ripard, Linus Walleij
  Cc: Chen-Yu Tsai, linux-arm-kernel, linux-gpio, linux-kernel

On the A80, the pin banks go up to PN, which translates to the 14th
entry in the regulator array. The array is only 12 entries long, which
causes the sunxi_pmx_{request,free} functions to access beyond the
array on the A80 and the A31 (which has pin bank PM). While the
accessed data is still valid allocated data within the same driver
data structure, it is likely not a pointer.

Increase the size of the regulator array from 12 to 14. This is a simple
fix. While we could have the code take into account the fact that R_PIO
pin banks start from PL, or maybe even dynamically allocate the array
based on the last pin of the pin controller, the size reduction probably
isn't worth the additional code complexity.

Fixes: 9a2a566adb00 ("pinctrl: sunxi: Deal with per-bank regulators")
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
This fixes a crash due to an invalid pointer on the A80.
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index e340d2a24b44..e8161aa17dab 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -136,7 +136,7 @@ struct sunxi_pinctrl {
 	struct gpio_chip		*chip;
 	const struct sunxi_pinctrl_desc	*desc;
 	struct device			*dev;
-	struct sunxi_pinctrl_regulator	regulators[12];
+	struct sunxi_pinctrl_regulator	regulators[14];
 	struct irq_domain		*domain;
 	struct sunxi_pinctrl_function	*functions;
 	unsigned			nfunctions;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] pinctrl: sunxi: Fix and simplify pin bank regulator handling
  2019-01-10  8:26 [PATCH 1/2] pinctrl: sunxi: Increase size of regulator array Chen-Yu Tsai
@ 2019-01-10  8:26 ` Chen-Yu Tsai
  2019-01-10 15:28   ` Maxime Ripard
  2019-01-10 15:26 ` [PATCH 1/2] pinctrl: sunxi: Increase size of regulator array Maxime Ripard
  1 sibling, 1 reply; 5+ messages in thread
From: Chen-Yu Tsai @ 2019-01-10  8:26 UTC (permalink / raw)
  To: Maxime Ripard, Linus Walleij
  Cc: Chen-Yu Tsai, linux-arm-kernel, linux-gpio, linux-kernel

The new per-pin-bank regulator handling code in the sunxi pinctrl driver
has mismatched conditions for enabling and disabling the regulator: it
is enabled each time a pin is requested, but only disabled when the
pin-bank's reference count reaches zero.

Since we are doing reference counting already, there's no need to enable
the regulator each time a pin is requested. Instead we can just do it
for the first requested pin of each pin-bank. Thus we can reverse the
test and bail out early if it's not the first occurrence.

Fixes: 9a2a566adb00 ("pinctrl: sunxi: Deal with per-bank regulators")
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---

I'm getting the feeling that the current code is prone to race
conditions when pinctrl sets are actively switched during runtime, or
gpios are requested and freed from userspace.

Any ideas?

---
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 36 ++++++++++++---------------
 1 file changed, 16 insertions(+), 20 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 5d9184d18c16..9ad6e9c2adab 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -699,25 +699,21 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)
 	struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
 	unsigned short bank = offset / PINS_PER_BANK;
 	struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank];
-	struct regulator *reg;
+	struct regulator *reg = s_reg->regulator;
+	char supply[16];
 	int ret;
 
-	reg = s_reg->regulator;
-	if (!reg) {
-		char supply[16];
-
-		snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank);
-		reg = regulator_get(pctl->dev, supply);
-		if (IS_ERR(reg)) {
-			dev_err(pctl->dev, "Couldn't get bank P%c regulator\n",
-				'A' + bank);
-			return PTR_ERR(reg);
-		}
-
-		s_reg->regulator = reg;
-		refcount_set(&s_reg->refcount, 1);
-	} else {
+	if (reg) {
 		refcount_inc(&s_reg->refcount);
+		return 0;
+	}
+
+	snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank);
+	reg = regulator_get(pctl->dev, supply);
+	if (IS_ERR(reg)) {
+		dev_err(pctl->dev, "Couldn't get bank P%c regulator\n",
+			'A' + bank);
+		return PTR_ERR(reg);
 	}
 
 	ret = regulator_enable(reg);
@@ -727,13 +723,13 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)
 		goto out;
 	}
 
+	s_reg->regulator = reg;
+	refcount_set(&s_reg->refcount, 1);
+
 	return 0;
 
 out:
-	if (refcount_dec_and_test(&s_reg->refcount)) {
-		regulator_put(s_reg->regulator);
-		s_reg->regulator = NULL;
-	}
+	regulator_put(s_reg->regulator);
 
 	return ret;
 }
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] pinctrl: sunxi: Increase size of regulator array
  2019-01-10  8:26 [PATCH 1/2] pinctrl: sunxi: Increase size of regulator array Chen-Yu Tsai
  2019-01-10  8:26 ` [PATCH 2/2] pinctrl: sunxi: Fix and simplify pin bank regulator handling Chen-Yu Tsai
@ 2019-01-10 15:26 ` Maxime Ripard
  2019-01-11 13:46   ` Chen-Yu Tsai
  1 sibling, 1 reply; 5+ messages in thread
From: Maxime Ripard @ 2019-01-10 15:26 UTC (permalink / raw)
  To: Chen-Yu Tsai; +Cc: Linus Walleij, linux-arm-kernel, linux-gpio, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1282 bytes --]

Hi,

On Thu, Jan 10, 2019 at 04:26:32PM +0800, Chen-Yu Tsai wrote:
> On the A80, the pin banks go up to PN, which translates to the 14th
> entry in the regulator array. The array is only 12 entries long, which
> causes the sunxi_pmx_{request,free} functions to access beyond the
> array on the A80 and the A31 (which has pin bank PM). While the
> accessed data is still valid allocated data within the same driver
> data structure, it is likely not a pointer.
> 
> Increase the size of the regulator array from 12 to 14. This is a simple
> fix. While we could have the code take into account the fact that R_PIO
> pin banks start from PL, or maybe even dynamically allocate the array
> based on the last pin of the pin controller, the size reduction probably
> isn't worth the additional code complexity.
> 
> Fixes: 9a2a566adb00 ("pinctrl: sunxi: Deal with per-bank regulators")
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>

I definitely overlooked the R_PIO case, sorry. I guess the proper fix
would be the first alternative one you suggested, and we should take
the pin_base into account. There's no need to store twice such a large
array for this case.

Maxime

-- 
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] pinctrl: sunxi: Fix and simplify pin bank regulator handling
  2019-01-10  8:26 ` [PATCH 2/2] pinctrl: sunxi: Fix and simplify pin bank regulator handling Chen-Yu Tsai
@ 2019-01-10 15:28   ` Maxime Ripard
  0 siblings, 0 replies; 5+ messages in thread
From: Maxime Ripard @ 2019-01-10 15:28 UTC (permalink / raw)
  To: Chen-Yu Tsai; +Cc: Linus Walleij, linux-arm-kernel, linux-gpio, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1284 bytes --]

On Thu, Jan 10, 2019 at 04:26:33PM +0800, Chen-Yu Tsai wrote:
> The new per-pin-bank regulator handling code in the sunxi pinctrl driver
> has mismatched conditions for enabling and disabling the regulator: it
> is enabled each time a pin is requested, but only disabled when the
> pin-bank's reference count reaches zero.
> 
> Since we are doing reference counting already, there's no need to enable
> the regulator each time a pin is requested. Instead we can just do it
> for the first requested pin of each pin-bank. Thus we can reverse the
> test and bail out early if it's not the first occurrence.
> 
> Fixes: 9a2a566adb00 ("pinctrl: sunxi: Deal with per-bank regulators")
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>

Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>

> I'm getting the feeling that the current code is prone to race
> conditions when pinctrl sets are actively switched during runtime, or
> gpios are requested and freed from userspace.
> 
> Any ideas?

IIRC, I've looked into it when writing that patch and there's an upper
mutex that prevents request from being called multiple times at
once. Linus might prove me wrong though.

Maxime

-- 
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] pinctrl: sunxi: Increase size of regulator array
  2019-01-10 15:26 ` [PATCH 1/2] pinctrl: sunxi: Increase size of regulator array Maxime Ripard
@ 2019-01-11 13:46   ` Chen-Yu Tsai
  0 siblings, 0 replies; 5+ messages in thread
From: Chen-Yu Tsai @ 2019-01-11 13:46 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: Linus Walleij, linux-arm-kernel, linux-gpio, linux-kernel

On Thu, Jan 10, 2019 at 11:26 PM Maxime Ripard
<maxime.ripard@bootlin.com> wrote:
>
> Hi,
>
> On Thu, Jan 10, 2019 at 04:26:32PM +0800, Chen-Yu Tsai wrote:
> > On the A80, the pin banks go up to PN, which translates to the 14th
> > entry in the regulator array. The array is only 12 entries long, which
> > causes the sunxi_pmx_{request,free} functions to access beyond the
> > array on the A80 and the A31 (which has pin bank PM). While the
> > accessed data is still valid allocated data within the same driver
> > data structure, it is likely not a pointer.
> >
> > Increase the size of the regulator array from 12 to 14. This is a simple
> > fix. While we could have the code take into account the fact that R_PIO
> > pin banks start from PL, or maybe even dynamically allocate the array
> > based on the last pin of the pin controller, the size reduction probably
> > isn't worth the additional code complexity.
> >
> > Fixes: 9a2a566adb00 ("pinctrl: sunxi: Deal with per-bank regulators")
> > Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>
> I definitely overlooked the R_PIO case, sorry. I guess the proper fix
> would be the first alternative one you suggested, and we should take
> the pin_base into account. There's no need to store twice such a large
> array for this case.

OK.

I wonder if we should try to get rid of pin_base though, at least as far
as the pinctrl core is concerned. In other words, in our description we'd
still have PL0 == 352, but when the pin is registered, PL0 == 0. This is
OK since each pinctrl device has its own numbering space. And it would
match up with what we use for GPIO.

It would also be better to nail this down one way or the other if we want
to use the gpio-ranges property.

Either way this would be a separate patch.

ChenYu

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-01-11 13:46 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-10  8:26 [PATCH 1/2] pinctrl: sunxi: Increase size of regulator array Chen-Yu Tsai
2019-01-10  8:26 ` [PATCH 2/2] pinctrl: sunxi: Fix and simplify pin bank regulator handling Chen-Yu Tsai
2019-01-10 15:28   ` Maxime Ripard
2019-01-10 15:26 ` [PATCH 1/2] pinctrl: sunxi: Increase size of regulator array Maxime Ripard
2019-01-11 13:46   ` Chen-Yu Tsai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).