Skip to contentSkip to conversation

Fix Nvidia BlueField-3 GPIO access

PATCH Superseded Asmaa Mnebhi 3 participants 9 messages Aug 16, 2023 – Aug 17, 2023

Subsystems (2)

v2 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

v2 cover Fix Nvidia BlueField-3 GPIO access

Fix Nvidia BlueField-3 GPIO access via libgpiod gpioset tool. gpioset tool fails to modify the GPIO value due to the following:
1) the pinctrl-mlxbf3 driver defines mlxbf3_gpio_request_enable() to enable software to take control over a gpio. Only then can the gpio-mlxbf3 driver modify the direction and value of the gpio. mlxbf3_gpio_disable_free() gives control back to hardware and is called when the "gpioset" command is invoked. This cancels out the effort to change the GPIO value and direction. So mlxbf3_gpio_disable_free() needs to be removed.
2) the gpio-mlxbf3 driver calls gpiochip_generic_request() which calls mlxbf3_gpio_request_enable(). "pin_ranges" needs not to be empty for mlxbf3_gpio_request_enable() to be invoked. So gpio-mlxbf3 needs to populate "pin_ranges".

Asmaa Mnebhi (2):
pinctrl: mlxbf3: Remove gpio_disable_free()
gpio: mlxbf3: Support add_pin_ranges()

 drivers/gpio/gpio-mlxbf3.c       | 15 +++++++++++++++
 drivers/pinctrl/pinctrl-mlxbf3.c | 14 --------------
 2 files changed, 15 insertions(+), 14 deletions(-)
Signature · 1 line
2.30.1
#1 lore raw

PATCH v2 1/2 pinctrl: mlxbf3: Remove gpio_disable_free()

Remove support for gpio_disable_free() because it is called when the libgpiod command "gpioset" is invoked. This gives the GPIO control back to hardware which cancels out the effort to set the GPIO value.

Reminder of the code flow to change a GPIO value from software:
1) All GPIOs are controlled by hardware by default
2) To change the GPIO value, enable software control via a mux.
3) Once software has control over the GPIO pin, the gpio-mlxbf3 driver will be able to change the direction and value of the GPIO.

When the user runs "gpioset gpiochip0 0=0" for example, the gpio pin value should change from 1 to 0. In this case, mlxbf3_gpio_request_enable() is called via gpiochip_generic_request(). The latter switches GPIO control from hardware to software. Then the GPIO value is changed from 1 to 0. However, gpio_disable_free() is also called which changes control back to hardware which changes the GPIO value back to 1.

Fixes d11f932808d ("pinctrl: mlxbf3: Add pinctrl driver support")

---
v1->v2:
- Clean up mlxbf3_gpio_add_pin_ranges

 drivers/pinctrl/pinctrl-mlxbf3.c | 14 --------------
 1 file changed, 14 deletions(-)
drivers/pinctrl/pinctrl-mlxbf3.c +0 -14
index d9944e6a0af9..0e852a0d5ec2 100644
@@ -223,26 +223,12 @@ static int mlxbf3_gpio_request_enable(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
-static void mlxbf3_gpio_disable_free(struct pinctrl_dev *pctldev,
-				    struct pinctrl_gpio_range *range,
-				    unsigned int offset)
-{
-	struct mlxbf3_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev);
-
-	/* disable GPIO functionality by giving control back to hardware */
-	if (offset < MLXBF3_NGPIOS_GPIO0)
-		writel(BIT(offset), priv->fw_ctrl_clr0);
-	else
-		writel(BIT(offset % MLXBF3_NGPIOS_GPIO0), priv->fw_ctrl_clr1);
-}
-
 static const struct pinmux_ops mlxbf3_pmx_ops = {
 	.get_functions_count = mlxbf3_pmx_get_funcs_count,
 	.get_function_name = mlxbf3_pmx_get_func_name,
 	.get_function_groups = mlxbf3_pmx_get_groups,
 	.set_mux = mlxbf3_pmx_set,
 	.gpio_request_enable = mlxbf3_gpio_request_enable,
-	.gpio_disable_free = mlxbf3_gpio_disable_free,
 };
 
 static struct pinctrl_desc mlxbf3_pin_desc = {
Signature · 1 line
2.30.1
#2 lore raw

PATCH v2 2/2 gpio: mlxbf3: Support add_pin_ranges()

In reply to Asmaa Mnebhi

Support add_pin_ranges() so that pinctrl_gpio_request() can be called. The GPIO value is not modified when the user runs the "gpioset" tool. This is because when gpiochip_generic_request is invoked by the gpio-mlxbf3 driver, "pin_ranges" is empty so it skips "pinctrl_gpio_request()". pinctrl_gpio_request() is essential in the code flow because it changes the mux value so that software has control over modifying the GPIO value. Adding add_pin_ranges() creates a dependency on the pinctrl-mlxbf3.c driver.

Fixes cd33f216d24 ("gpio: mlxbf3: Add gpio driver support")

---
v1->v2:
- No changes.

 drivers/gpio/gpio-mlxbf3.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
drivers/gpio/gpio-mlxbf3.c +15 -0
index e30cee108986..d00cc61ea7b8 100644
@@ -158,6 +158,19 @@ static const struct irq_chip gpio_mlxbf3_irqchip = {
 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
 };
 
+static int mlxbf3_gpio_add_pin_ranges(struct gpio_chip *chip)
+{
+	unsigned int id = 0;
+	int ret;
+
+	if (chip->ngpio % MLXBF3_GPIO_MAX_PINS_PER_BLOCK)
+		id = 1;
+
+	return gpiochip_add_pin_range(chip, "MLNXBF34:00",
+			chip->base, id * MLXBF3_GPIO_MAX_PINS_PER_BLOCK,
+			chip->ngpio);
+}
+
 static int mlxbf3_gpio_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -197,6 +210,7 @@ static int mlxbf3_gpio_probe(struct platform_device *pdev)
 	gc->request = gpiochip_generic_request;
 	gc->free = gpiochip_generic_free;
 	gc->owner = THIS_MODULE;
+	gc->add_pin_ranges = mlxbf3_gpio_add_pin_ranges;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq >= 0) {
@@ -243,6 +257,7 @@ static struct platform_driver mlxbf3_gpio_driver = {
 };
 module_platform_driver(mlxbf3_gpio_driver);
 
+MODULE_SOFTDEP("pre: pinctrl-mlxbf3");
 MODULE_DESCRIPTION("NVIDIA BlueField-3 GPIO Driver");
 MODULE_AUTHOR("Asmaa Mnebhi <[email protected]>");
 MODULE_LICENSE("Dual BSD/GPL");
Signature · 1 line
2.30.1
#3 lore raw

Re: [PATCH v2 2/2] gpio: mlxbf3: Support add_pin_ranges()

Quoted 8 lines · Asmaa Mnebhi

Support add_pin_ranges() so that pinctrl_gpio_request() can be called. The GPIO value is not modified when the user runs the "gpioset" tool. This is because when gpiochip_generic_request is invoked by the gpio-mlxbf3 driver, "pin_ranges" is empty so it skips "pinctrl_gpio_request()". pinctrl_gpio_request() is essential in the code flow because it changes the mux value so that software has control over modifying the GPIO value. Adding add_pin_ranges() creates a dependency on the pinctrl-mlxbf3.c driver.

...

Quoted 2 lines

v1->v2:
- No changes.

Is this correct?

...

drivers/gpio/gpio-mlxbf3.c static const struct irq_chip gpio_mlxbf3_irqchip = { · line 167

Quoted 7 lines
drivers/gpio/gpio-mlxbf3.c +7 -0
+static int mlxbf3_gpio_add_pin_ranges(struct gpio_chip *chip)
+{
+       unsigned int id = 0;
+       int ret;
+
+       if (chip->ngpio % MLXBF3_GPIO_MAX_PINS_PER_BLOCK)
+               id = 1;

This id calculation seems wrong to me as I said in v1 review. Why do you think the above is what you want and not just working by luck?

Quoted 4 lines
drivers/gpio/gpio-mlxbf3.c +4 -0
+       return gpiochip_add_pin_range(chip, "MLNXBF34:00",
+                       chip->base, id * MLXBF3_GPIO_MAX_PINS_PER_BLOCK,
+                       chip->ngpio);
+}
Signature · 2 lines
With Best Regards,
Andy Shevchenko
#4 lore raw

RE: [PATCH v2 2/2] gpio: mlxbf3: Support add_pin_ranges()

Quoted 4 lines
Quoted 2 lines

v1->v2:
- No changes.

Is this correct?

Ah my apologies, I added the wrong comment here. I put it in "v2 1/2".

Quoted 9 lines

drivers/gpio/gpio-mlxbf3.c static const struct irq_chip gpio_mlxbf3_irqchip = { · line 167

Quoted 6 lines
drivers/gpio/gpio-mlxbf3.c +6 -0
+static int mlxbf3_gpio_add_pin_ranges(struct gpio_chip *chip) {
+       unsigned int id = 0;
+       int ret;
+
+       if (chip->ngpio % MLXBF3_GPIO_MAX_PINS_PER_BLOCK)
+               id = 1;

This id calculation seems wrong to me as I said in v1 review. Why do you think the above is what you want and not just working by luck?

I would like to get the gpio block id which can only be 0 or 1 on BlueField-3 (only 2 gpio blocks, one with 32 gpio pins and one with 24 gpio pins). The above logic was an "easy" way for me to get the gpio block id. Then the pin_base for each gpio block is:
pin_base = id * MLXBF3_GPIO_MAX_PINS_PER_BLOCK

#5 lore raw

Re: [PATCH v2 2/2] gpio: mlxbf3: Support add_pin_ranges()

Quoted 17 lines · Asmaa Mnebhi
Quoted 5 lines
Quoted 3 lines

v1->v2:
- No changes.

Is this correct?

Ah my apologies, I added the wrong comment here. I put it in "v2 1/2".

Quoted 9 lines

drivers/gpio/gpio-mlxbf3.c static const struct irq_chip gpio_mlxbf3_irqchip = { · line 167

Quoted 6 lines
drivers/gpio/gpio-mlxbf3.c +6 -0
+static int mlxbf3_gpio_add_pin_ranges(struct gpio_chip *chip) {
+       unsigned int id = 0;
+       int ret;
+
+       if (chip->ngpio % MLXBF3_GPIO_MAX_PINS_PER_BLOCK)
+               id = 1;

This id calculation seems wrong to me as I said in v1 review. Why do you think the above is what you want and not just working by luck?

Quoted 3 lines

I would like to get the gpio block id which can only be 0 or 1 on BlueField-3 (only 2 gpio blocks, one with 32 gpio pins and one with 24 gpio pins). The above logic was an "easy" way for me to get the gpio block id. Then the pin_base for each gpio block is:
pin_base = id * MLXBF3_GPIO_MAX_PINS_PER_BLOCK

It's fragile. Use a direct case switch for that, which will be more explicit and robust (however still can fail for any new chip revision/version where it might be a different GPIO layout).

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#6 lore raw

RE: [PATCH v2 2/2] gpio: mlxbf3: Support add_pin_ranges()

Quoted 11 lines
Quoted 2 lines

I would like to get the gpio block id which can only be 0 or 1 on BlueField-3

(only 2 gpio blocks, one with 32 gpio pins and one with 24 gpio pins).

Quoted 1 line

The above logic was an "easy" way for me to get the gpio block id. Then the

pin_base for each gpio block is:

Quoted 1 line

pin_base = id * MLXBF3_GPIO_MAX_PINS_PER_BLOCK

It's fragile. Use a direct case switch for that, which will be more explicit and robust (however still can fail for any new chip revision/version where it might be a different GPIO layout).

Thanks Andy! Will do. Hopefully it is too late to change the BF3 hardware at this point so we should be good ; ) .

#7 lore raw

Re: [PATCH v2 2/2] gpio: mlxbf3: Support add_pin_ranges()

In reply to Asmaa Mnebhi
kernel test robot noticed the following build warnings:

Hi Asmaa,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linusw-pinctrl/devel]
[also build test WARNING on linusw-pinctrl/for-next brgl/gpio/for-next linus/master v6.5-rc6 next-20230816] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Asmaa-Mnebhi/pinctrl-mlxbf3-Remove-gpio_disable_free/20230816-234711
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
patch link:    https://lore.kernel.org/r/20230816154442.8417-3-asmaa%40nvidia.com
patch subject: [PATCH v2 2/2] gpio: mlxbf3: Support add_pin_ranges()
config: i386-buildonly-randconfig-r005-20230817 (https://download.01.org/0day-ci/archive/20230817/[email protected]/config)
compiler: clang version 16.0.4 (https://github.com/llvm/llvm-project.git ae42196bc493ffe877a7e3dff8be32035dea4d07)
reproduce: (https://download.01.org/0day-ci/archive/20230817/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> drivers/gpio/gpio-mlxbf3.c:164:6: warning: unused variable 'ret' [-Wunused-variable]
           int ret;
               ^

1 warning generated.

vim +/ret +164 drivers/gpio/gpio-mlxbf3.c

160
161 static int mlxbf3_gpio_add_pin_ranges(struct gpio_chip *chip)
162 {
163 unsigned int id = 0;

 > 164		int ret;

165
166 if (chip->ngpio % MLXBF3_GPIO_MAX_PINS_PER_BLOCK)
167 id = 1;
168
169 return gpiochip_add_pin_range(chip, "MLNXBF34:00",
170 chip->base, id * MLXBF3_GPIO_MAX_PINS_PER_BLOCK,
171 chip->ngpio);
172 }
173

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
#8 lore raw

Re: [PATCH v2 2/2] gpio: mlxbf3: Support add_pin_ranges()

In reply to Asmaa Mnebhi
kernel test robot noticed the following build warnings:

Hi Asmaa,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linusw-pinctrl/devel]
[also build test WARNING on linusw-pinctrl/for-next brgl/gpio/for-next linus/master v6.5-rc6 next-20230816] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Asmaa-Mnebhi/pinctrl-mlxbf3-Remove-gpio_disable_free/20230816-234711
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
patch link:    https://lore.kernel.org/r/20230816154442.8417-3-asmaa%40nvidia.com
patch subject: [PATCH v2 2/2] gpio: mlxbf3: Support add_pin_ranges()
config: i386-allyesconfig (https://download.01.org/0day-ci/archive/20230817/[email protected]/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce: (https://download.01.org/0day-ci/archive/20230817/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

drivers/gpio/gpio-mlxbf3.c: In function 'mlxbf3_gpio_add_pin_ranges':

>> drivers/gpio/gpio-mlxbf3.c:164:13: warning: unused variable 'ret' [-Wunused-variable]
     164 |         int ret;
         |             ^~~

vim +/ret +164 drivers/gpio/gpio-mlxbf3.c

160
161 static int mlxbf3_gpio_add_pin_ranges(struct gpio_chip *chip)
162 {
163 unsigned int id = 0;

 > 164		int ret;

165
166 if (chip->ngpio % MLXBF3_GPIO_MAX_PINS_PER_BLOCK)
167 id = 1;
168
169 return gpiochip_add_pin_range(chip, "MLNXBF34:00",
170 chip->base, id * MLXBF3_GPIO_MAX_PINS_PER_BLOCK,
171 chip->ngpio);
172 }
173

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki