FAILED: patch "[PATCH] gpio: ml-ioh: use raw_spinlock_t for the register lock" failed to apply to 6.1-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 600411ea1f2443fdf5b1af9b6480f616d7aff9d0
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026082011-harddisk-capitol-82ef@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 600411ea1f2443fdf5b1af9b6480f616d7aff9d0 Mon Sep 17 00:00:00 2001
From: Junjie Cao <[email protected]>
Date: Fri, 31 Jul 2026 11:27:47 +0800
Subject: [PATCH] gpio: ml-ioh: use raw_spinlock_t for the register lock
ioh_irq_type() is registered as the irq_chip .irq_set_type callback and takes chip->spinlock with spin_lock_irqsave(). This callback is reached from __setup_irq() -> __irq_set_trigger() -> chip->irq_set_type() while the caller holds desc->lock, a raw_spinlock_t, with hardirqs disabled. That context is not sleepable, but on PREEMPT_RT a regular spinlock_t is an rtmutex-backed sleeping lock, so acquiring it there is invalid. ioh_irq_enable() and ioh_irq_disable() take the same lock from the .irq_enable/.irq_disable callbacks, which are likewise invoked with desc->lock held.
Convert the register lock to raw_spinlock_t. The same lock also serializes the GPIO direction/value callbacks and the suspend/resume register save/restore, and those critical sections only perform short sequences of MMIO register accesses (ioread32()/iowrite32()); the .irq_set_type callback additionally emits a dev_warn() on an unsupported type. None of these are sleepable operations, so keeping this register lock non-sleeping is appropriate for the irqchip callbacks and does not change the GPIO-side locking contract.
This is the same fix as commit a02b8950d619 ("gpio: pch: use raw_spinlock_t for the register lock"); this driver shares the same structure as gpio-pch.
drivers/gpio/gpio-ml-ioh.c +18 -18
@@ -84,7 +84,7 @@ struct ioh_gpio {u32 gpio_use_sel;int ch;int irq_base; -spinlock_t spinlock; +raw_spinlock_t spinlock; };static const int num_ports[] = {6 ,12 ,16 ,16 ,15 ,16 ,16 ,12 };
@@ -95,7 +95,7 @@ static int ioh_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val)struct ioh_gpio *chip =gpiochip_get_data (gpio);unsigned long flags; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags); reg_val =ioread32 (&chip->reg->regs[chip->ch].po);if (val) reg_val |=BIT (nr);
@@ -103,7 +103,7 @@ static int ioh_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val) reg_val &= ~BIT (nr);iowrite32 (reg_val, &chip->reg->regs[chip->ch].po); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags);return 0 ; }
@@ -123,7 +123,7 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,u32 reg_val;unsigned long flags; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags); pm =ioread32 (&chip->reg->regs[chip->ch].pm); pm &=BIT (num_ports[chip->ch]) -1 ; pm |=BIT (nr);
@@ -136,7 +136,7 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, reg_val &= ~BIT (nr);iowrite32 (reg_val, &chip->reg->regs[chip->ch].po); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags);return 0 ; }
@@ -147,12 +147,12 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)u32 pm;unsigned long flags; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags); pm =ioread32 (&chip->reg->regs[chip->ch].pm); pm &=BIT (num_ports[chip->ch]) -1 ; pm &= ~BIT (nr);iowrite32 (pm, &chip->reg->regs[chip->ch].pm); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags);return 0 ; }
@@ -256,7 +256,7 @@ static int ioh_irq_type(struct irq_data *d, unsigned int type)dev_dbg (chip->dev,"%s:irq=%d type=%d ch=%d pos=%d type=%d\n" , __func__, irq, type, ch, im_pos, type); -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags);switch (type) {case IRQ_TYPE_EDGE_RISING :
@@ -296,7 +296,7 @@ static int ioh_irq_type(struct irq_data *d, unsigned int type) ien =ioread32 (&chip->reg->regs[chip->ch].ien);iowrite32 (ien |BIT (ch), &chip->reg->regs[chip->ch].ien); end: -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags);return 0 ; }
@@ -326,11 +326,11 @@ static void ioh_irq_disable(struct irq_data *d)unsigned long flags;u32 ien; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags); ien =ioread32 (&chip->reg->regs[chip->ch].ien); ien &= ~BIT (d->irq - chip->irq_base);iowrite32 (ien, &chip->reg->regs[chip->ch].ien); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags); }static void ioh_irq_enable (struct irq_data *d)
@@ -340,11 +340,11 @@ static void ioh_irq_enable(struct irq_data *d)unsigned long flags;u32 ien; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags); ien =ioread32 (&chip->reg->regs[chip->ch].ien); ien |=BIT (d->irq - chip->irq_base);iowrite32 (ien, &chip->reg->regs[chip->ch].ien); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags); }static irqreturn_t ioh_gpio_handler (int irq,void *dev_id)
@@ -440,7 +440,7 @@ static int ioh_gpio_probe(struct pci_dev *pdev, chip->base = base; chip->reg = chip->base; chip->ch = i; -spin_lock_init (&chip->spinlock); +raw_spin_lock_init (&chip->spinlock);ioh_gpio_setup (chip, num_ports[i]); ret =devm_gpiochip_add_data (dev, &chip->gpio, chip);if (ret) {
@@ -484,9 +484,9 @@ static int ioh_gpio_suspend(struct device *dev)struct ioh_gpio *chip =dev_get_drvdata (dev);unsigned long flags; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags);ioh_gpio_save_reg_conf (chip); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags);return 0 ; }
@@ -496,11 +496,11 @@ static int ioh_gpio_resume(struct device *dev)struct ioh_gpio *chip =dev_get_drvdata (dev);unsigned long flags; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags);iowrite32 (0x01 , &chip->reg->srst);iowrite32 (0x00 , &chip->reg->srst);ioh_gpio_restore_reg_conf (chip); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags);return 0 ; }
PATCH 1/1 gpio: ml-ioh: use raw_spinlock_t for the register lock
ioh_irq_type() is registered as the irq_chip .irq_set_type callback and takes chip->spinlock with spin_lock_irqsave(). This callback is reached from __setup_irq() -> __irq_set_trigger() -> chip->irq_set_type() while the caller holds desc->lock, a raw_spinlock_t, with hardirqs disabled. That context is not sleepable, but on PREEMPT_RT a regular spinlock_t is an rtmutex-backed sleeping lock, so acquiring it there is invalid. ioh_irq_enable() and ioh_irq_disable() take the same lock from the .irq_enable/.irq_disable callbacks, which are likewise invoked with desc->lock held.
Convert the register lock to raw_spinlock_t. The same lock also serializes the GPIO direction/value callbacks and the suspend/resume register save/restore, and those critical sections only perform short sequences of MMIO register accesses (ioread32()/iowrite32()); the .irq_set_type callback additionally emits a dev_warn() on an unsupported type. None of these are sleepable operations, so keeping this register lock non-sleeping is appropriate for the irqchip callbacks and does not change the GPIO-side locking contract.
This is the same fix as commit a02b8950d619 ("gpio: pch: use raw_spinlock_t for the register lock"); this driver shares the same structure as gpio-pch.
--- drivers/gpio/gpio-ml-ioh.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-)
drivers/gpio/gpio-ml-ioh.c +18 -18
@@ -84,7 +84,7 @@ struct ioh_gpio {u32 gpio_use_sel;int ch;int irq_base; -spinlock_t spinlock; +raw_spinlock_t spinlock; };static const int num_ports[] = {6 ,12 ,16 ,16 ,15 ,16 ,16 ,12 };
@@ -95,7 +95,7 @@ static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)struct ioh_gpio *chip =gpiochip_get_data (gpio);unsigned long flags; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags); reg_val =ioread32 (&chip->reg->regs[chip->ch].po);if (val) reg_val |=BIT (nr);
@@ -103,7 +103,7 @@ static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) reg_val &= ~BIT (nr);iowrite32 (reg_val, &chip->reg->regs[chip->ch].po); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags); }static int ioh_gpio_get (struct gpio_chip *gpio,unsigned nr)
@@ -121,7 +121,7 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,u32 reg_val;unsigned long flags; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags); pm =ioread32 (&chip->reg->regs[chip->ch].pm); pm &=BIT (num_ports[chip->ch]) -1 ; pm |=BIT (nr);
@@ -134,7 +134,7 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, reg_val &= ~BIT (nr);iowrite32 (reg_val, &chip->reg->regs[chip->ch].po); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags);return 0 ; }
@@ -145,12 +145,12 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)u32 pm;unsigned long flags; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags); pm =ioread32 (&chip->reg->regs[chip->ch].pm); pm &=BIT (num_ports[chip->ch]) -1 ; pm &= ~BIT (nr);iowrite32 (pm, &chip->reg->regs[chip->ch].pm); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags);return 0 ; }
@@ -254,7 +254,7 @@ static int ioh_irq_type(struct irq_data *d, unsigned int type)dev_dbg (chip->dev,"%s:irq=%d type=%d ch=%d pos=%d type=%d\n" , __func__, irq, type, ch, im_pos, type); -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags);switch (type) {case IRQ_TYPE_EDGE_RISING :
@@ -294,7 +294,7 @@ static int ioh_irq_type(struct irq_data *d, unsigned int type) ien =ioread32 (&chip->reg->regs[chip->ch].ien);iowrite32 (ien |BIT (ch), &chip->reg->regs[chip->ch].ien); end: -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags);return 0 ; }
@@ -324,11 +324,11 @@ static void ioh_irq_disable(struct irq_data *d)unsigned long flags;u32 ien; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags); ien =ioread32 (&chip->reg->regs[chip->ch].ien); ien &= ~BIT (d->irq - chip->irq_base);iowrite32 (ien, &chip->reg->regs[chip->ch].ien); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags); }static void ioh_irq_enable (struct irq_data *d)
@@ -338,11 +338,11 @@ static void ioh_irq_enable(struct irq_data *d)unsigned long flags;u32 ien; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags); ien =ioread32 (&chip->reg->regs[chip->ch].ien); ien |=BIT (d->irq - chip->irq_base);iowrite32 (ien, &chip->reg->regs[chip->ch].ien); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags); }static irqreturn_t ioh_gpio_handler (int irq,void *dev_id)
@@ -438,7 +438,7 @@ static int ioh_gpio_probe(struct pci_dev *pdev, chip->base = base; chip->reg = chip->base; chip->ch = i; -spin_lock_init (&chip->spinlock); +raw_spin_lock_init (&chip->spinlock);ioh_gpio_setup (chip, num_ports[i]); ret =devm_gpiochip_add_data (dev, &chip->gpio, chip);if (ret) {
@@ -482,9 +482,9 @@ static int __maybe_unused ioh_gpio_suspend(struct device *dev)struct ioh_gpio *chip =dev_get_drvdata (dev);unsigned long flags; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags);ioh_gpio_save_reg_conf (chip); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags);return 0 ; }
@@ -494,11 +494,11 @@ static int __maybe_unused ioh_gpio_resume(struct device *dev)struct ioh_gpio *chip =dev_get_drvdata (dev);unsigned long flags; -spin_lock_irqsave (&chip->spinlock, flags); +raw_spin_lock_irqsave (&chip->spinlock, flags);iowrite32 (0x01 , &chip->reg->srst);iowrite32 (0x00 , &chip->reg->srst);ioh_gpio_restore_reg_conf (chip); -spin_unlock_irqrestore (&chip->spinlock, flags); +raw_spin_unlock_irqrestore (&chip->spinlock, flags);return 0 ; }
Signature · 1 line
2.43.0