gpio fixes for v6.19-rc8

- don't call into pinctrl when setting direction in gpio-rockchip as it's
   not needed and may trigger locking context errors
 - change spinlock to raw_spinlock in gpio-sprd
 - fix a use-after-free bug in gpio-virtuser
 - don't register a driver from another driver's probe() in gpio-omap
 - fix int width problems in GPIO ACPI code
 - fix interrupt-to-pin mapping in gpio-brcmstb
 - mask interrupts in irq shutdown in gpio-pca953x
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEkeUTLeW1Rh17omX8BZ0uy/82hMMFAml8lz4ACgkQBZ0uy/82
 hMN1KQ/+Imlv9lyge+IFUqX5lH1frlrNNKRIHKY9Mo5c1T0/HyqSHR/kD7TQbC8P
 RP/N4lSx1bt0Myfo6KyCqfQPH/UwgM1Opt2debU+TxtW8Bep+FPS/WzdU6yKCENA
 r71VW7rzDb3LcZ8irDzir6gYq3hTogaQ9POVHThMJAtZ/o/IlBjDe4YGW3cU2Brc
 XVu5vyjeCQjg+Qs4/1/fATSlSK0eWqUZd/sitFhZynIdoDX6tWTkQnmDrJ4N10zc
 XF78DXa+x5jI3qPoSJnOH0q8BMcU0TORVEpMx8zI1uhp88mMQjEvD97Zc0SHLytQ
 p9xgke845n7IFCywHAOc/TmuRHLHi98QsY6PW1rbm2HsO8X3GRyuCgpMWLSzNNeb
 rldlVFPFJpzFzzhxoWPh6mTItlFUSVO6M7JYzJxMMuYeM/2WOXeTN1S11AeqJqiF
 bfKETHOLH/0EK5bokIo6BEaHmUgCm7LQ5dzLyDt1s3AsCEXWJFiM+nqkpXz6FkbB
 up+GFnADfQMPQ/5EYJgv5Pz7qpXuzoxVy8ra06k70USpdgr/EILtRLbjlZZqtP8w
 qHqmqH0fcXue8uHH2Pe2tgIatOEuYlGOJ20bTfT2q1g8zCIYl46eyimoLy/wRZhS
 GRBB0mDGqIECEy5L3LHaMMiLeoaxVqTCMdMuDE0hvjP0LaWeNqo=
 =KCJE
 -----END PGP SIGNATURE-----

Merge tag 'gpio-fixes-for-v6.19-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio fixes from Bartosz Golaszewski:
 "Over the last week I received quite an unexpected (for rc7) number of
  fixes but they are all pretty small and mostly limited to drivers:

   - don't call into pinctrl when setting direction in gpio-rockchip as
     it's not needed and may trigger locking context errors

   - change spinlock to raw_spinlock in gpio-sprd

   - fix a use-after-free bug in gpio-virtuser

   - don't register a driver from another driver's probe() in gpio-omap

   - fix int width problems in GPIO ACPI code

   - fix interrupt-to-pin mapping in gpio-brcmstb

   - mask interrupts in irq shutdown in gpio-pca953x"

* tag 'gpio-fixes-for-v6.19-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
  gpiolib: acpi: Fix potential out-of-boundary left shift
  gpio: brcmstb: correct hwirq to bank map
  gpio: omap: do not register driver in probe()
  gpio: pca953x: mask interrupts in irq shutdown
  gpio: virtuser: fix UAF in configfs release path
  gpiolib: acpi: use BIT_ULL() for u64 mask in address space handler
  gpio: sprd: Change sprd_gpio lock to raw_spin_lock
  gpio: rockchip: Stop calling pinctrl for set_direction
This commit is contained in:
Linus Torvalds 2026-01-30 11:58:27 -08:00
commit d941a3f656
8 changed files with 52 additions and 34 deletions

View File

@ -301,12 +301,10 @@ static struct brcmstb_gpio_bank *brcmstb_gpio_hwirq_to_bank(
struct brcmstb_gpio_priv *priv, irq_hw_number_t hwirq)
{
struct brcmstb_gpio_bank *bank;
int i = 0;
/* banks are in descending order */
list_for_each_entry_reverse(bank, &priv->bank_list, node) {
i += bank->chip.gc.ngpio;
if (hwirq < i)
list_for_each_entry(bank, &priv->bank_list, node) {
if (hwirq >= bank->chip.gc.offset &&
hwirq < (bank->chip.gc.offset + bank->chip.gc.ngpio))
return bank;
}
return NULL;

View File

@ -799,10 +799,13 @@ static struct platform_device omap_mpuio_device = {
static inline void omap_mpuio_init(struct gpio_bank *bank)
{
platform_set_drvdata(&omap_mpuio_device, bank);
static bool registered;
if (platform_driver_register(&omap_mpuio_driver) == 0)
(void) platform_device_register(&omap_mpuio_device);
platform_set_drvdata(&omap_mpuio_device, bank);
if (!registered) {
(void)platform_device_register(&omap_mpuio_device);
registered = true;
}
}
/*---------------------------------------------------------------------*/
@ -1575,13 +1578,24 @@ static struct platform_driver omap_gpio_driver = {
*/
static int __init omap_gpio_drv_reg(void)
{
return platform_driver_register(&omap_gpio_driver);
int ret;
ret = platform_driver_register(&omap_mpuio_driver);
if (ret)
return ret;
ret = platform_driver_register(&omap_gpio_driver);
if (ret)
platform_driver_unregister(&omap_mpuio_driver);
return ret;
}
postcore_initcall(omap_gpio_drv_reg);
static void __exit omap_gpio_exit(void)
{
platform_driver_unregister(&omap_gpio_driver);
platform_driver_unregister(&omap_mpuio_driver);
}
module_exit(omap_gpio_exit);

View File

@ -914,6 +914,8 @@ static void pca953x_irq_shutdown(struct irq_data *d)
clear_bit(hwirq, chip->irq_trig_fall);
clear_bit(hwirq, chip->irq_trig_level_low);
clear_bit(hwirq, chip->irq_trig_level_high);
pca953x_irq_mask(d);
}
static void pca953x_irq_print_chip(struct irq_data *data, struct seq_file *p)

View File

@ -18,7 +18,6 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@ -164,12 +163,6 @@ static int rockchip_gpio_set_direction(struct gpio_chip *chip,
unsigned long flags;
u32 data = input ? 0 : 1;
if (input)
pinctrl_gpio_direction_input(chip, offset);
else
pinctrl_gpio_direction_output(chip, offset);
raw_spin_lock_irqsave(&bank->slock, flags);
rockchip_gpio_writel_bit(bank, offset, data, bank->gpio_regs->port_ddr);
raw_spin_unlock_irqrestore(&bank->slock, flags);
@ -593,7 +586,6 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
gc->ngpio = bank->nr_pins;
gc->label = bank->name;
gc->parent = bank->dev;
gc->can_sleep = true;
ret = gpiochip_add_data(gc, bank);
if (ret) {

View File

@ -35,7 +35,7 @@
struct sprd_gpio {
struct gpio_chip chip;
void __iomem *base;
spinlock_t lock;
raw_spinlock_t lock;
int irq;
};
@ -54,7 +54,7 @@ static void sprd_gpio_update(struct gpio_chip *chip, unsigned int offset,
unsigned long flags;
u32 tmp;
spin_lock_irqsave(&sprd_gpio->lock, flags);
raw_spin_lock_irqsave(&sprd_gpio->lock, flags);
tmp = readl_relaxed(base + reg);
if (val)
@ -63,7 +63,7 @@ static void sprd_gpio_update(struct gpio_chip *chip, unsigned int offset,
tmp &= ~BIT(SPRD_GPIO_BIT(offset));
writel_relaxed(tmp, base + reg);
spin_unlock_irqrestore(&sprd_gpio->lock, flags);
raw_spin_unlock_irqrestore(&sprd_gpio->lock, flags);
}
static int sprd_gpio_read(struct gpio_chip *chip, unsigned int offset, u16 reg)
@ -236,7 +236,7 @@ static int sprd_gpio_probe(struct platform_device *pdev)
if (IS_ERR(sprd_gpio->base))
return PTR_ERR(sprd_gpio->base);
spin_lock_init(&sprd_gpio->lock);
raw_spin_lock_init(&sprd_gpio->lock);
sprd_gpio->chip.label = dev_name(&pdev->dev);
sprd_gpio->chip.ngpio = SPRD_GPIO_NR;

View File

@ -1682,10 +1682,10 @@ static void gpio_virtuser_device_config_group_release(struct config_item *item)
{
struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item);
guard(mutex)(&dev->lock);
if (gpio_virtuser_device_is_live(dev))
gpio_virtuser_device_deactivate(dev);
scoped_guard(mutex, &dev->lock) {
if (gpio_virtuser_device_is_live(dev))
gpio_virtuser_device_deactivate(dev);
}
mutex_destroy(&dev->lock);
ida_free(&gpio_virtuser_ida, dev->id);

View File

@ -1104,6 +1104,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
unsigned int pin = agpio->pin_table[i];
struct acpi_gpio_connection *conn;
struct gpio_desc *desc;
u16 word, shift;
bool found;
mutex_lock(&achip->conn_lock);
@ -1158,10 +1159,22 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
mutex_unlock(&achip->conn_lock);
if (function == ACPI_WRITE)
gpiod_set_raw_value_cansleep(desc, !!(*value & BIT(i)));
else
*value |= (u64)gpiod_get_raw_value_cansleep(desc) << i;
/*
* For the cases when OperationRegion() consists of more than
* 64 bits calculate the word and bit shift to use that one to
* access the value.
*/
word = i / 64;
shift = i % 64;
if (function == ACPI_WRITE) {
gpiod_set_raw_value_cansleep(desc, value[word] & BIT_ULL(shift));
} else {
if (gpiod_get_raw_value_cansleep(desc))
value[word] |= BIT_ULL(shift);
else
value[word] &= ~BIT_ULL(shift);
}
}
out:

View File

@ -3545,10 +3545,9 @@ static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
return 0;
}
static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset,
bool input)
static int rockchip_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int offset)
{
struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
struct rockchip_pin_bank *bank;
@ -3562,7 +3561,7 @@ static const struct pinmux_ops rockchip_pmx_ops = {
.get_function_name = rockchip_pmx_get_func_name,
.get_function_groups = rockchip_pmx_get_groups,
.set_mux = rockchip_pmx_set,
.gpio_set_direction = rockchip_pmx_gpio_set_direction,
.gpio_request_enable = rockchip_pmx_gpio_request_enable,
};
/*