From f2865c6300d75a9f187dd7918d248e010970fd44 Mon Sep 17 00:00:00 2001 From: Amit Sunil Dhamne Date: Mon, 10 Mar 2025 19:19:07 -0700 Subject: [PATCH 01/16] usb: typec: tcpm: fix state transition for SNK_WAIT_CAPABILITIES state in run_state_machine() A subtle error got introduced while manually fixing merge conflict in tcpm.c for commit 85c4efbe6088 ("Merge v6.12-rc6 into usb-next"). As a result of this error, the next state is unconditionally set to SNK_WAIT_CAPABILITIES_TIMEOUT while handling SNK_WAIT_CAPABILITIES state in run_state_machine(...). Fix this by setting new state of TCPM state machine to `upcoming_state` (that is set to different values based on conditions). Cc: stable@vger.kernel.org Fixes: 85c4efbe60888 ("Merge v6.12-rc6 into usb-next") Signed-off-by: Amit Sunil Dhamne Reviewed-by: Badhri Jagan Sridharan Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20250310-fix-snk-wait-timeout-v6-14-rc6-v1-1-5db14475798f@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm/tcpm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 6bf1a22c785a..62ca4a0ec55b 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -5117,16 +5117,16 @@ static void run_state_machine(struct tcpm_port *port) */ if (port->vbus_never_low) { port->vbus_never_low = false; - tcpm_set_state(port, SNK_SOFT_RESET, - port->timings.sink_wait_cap_time); + upcoming_state = SNK_SOFT_RESET; } else { if (!port->self_powered) upcoming_state = SNK_WAIT_CAPABILITIES_TIMEOUT; else upcoming_state = hard_reset_state(port); - tcpm_set_state(port, SNK_WAIT_CAPABILITIES_TIMEOUT, - port->timings.sink_wait_cap_time); } + + tcpm_set_state(port, upcoming_state, + port->timings.sink_wait_cap_time); break; case SNK_WAIT_CAPABILITIES_TIMEOUT: /* -- 2.51.0 From 0b4ffbe4888a2c71185eaf5c1a02dd3586a9bc04 Mon Sep 17 00:00:00 2001 From: Tengda Wu Date: Fri, 14 Mar 2025 06:53:35 +0000 Subject: [PATCH 02/16] tracing: Correct the refcount if the hist/hist_debug file fails to open The function event_{hist,hist_debug}_open() maintains the refcount of 'file->tr' and 'file' through tracing_open_file_tr(). However, it does not roll back these counts on subsequent failure paths, resulting in a refcount leak. A very obvious case is that if the hist/hist_debug file belongs to a specific instance, the refcount leak will prevent the deletion of that instance, as it relies on the condition 'tr->ref == 1' within __remove_instance(). Fix this by calling tracing_release_file_tr() on all failure paths in event_{hist,hist_debug}_open() to correct the refcount. Cc: stable@vger.kernel.org Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Zheng Yejian Link: https://lore.kernel.org/20250314065335.1202817-1-wutengda@huaweicloud.com Fixes: 1cc111b9cddc ("tracing: Fix uaf issue when open the hist or hist_debug file") Signed-off-by: Tengda Wu Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_events_hist.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index ad7419e24055..53dc6719181e 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -5689,12 +5689,16 @@ static int event_hist_open(struct inode *inode, struct file *file) guard(mutex)(&event_mutex); event_file = event_file_data(file); - if (!event_file) - return -ENODEV; + if (!event_file) { + ret = -ENODEV; + goto err; + } hist_file = kzalloc(sizeof(*hist_file), GFP_KERNEL); - if (!hist_file) - return -ENOMEM; + if (!hist_file) { + ret = -ENOMEM; + goto err; + } hist_file->file = file; hist_file->last_act = get_hist_hit_count(event_file); @@ -5702,9 +5706,14 @@ static int event_hist_open(struct inode *inode, struct file *file) /* Clear private_data to avoid warning in single_open() */ file->private_data = NULL; ret = single_open(file, hist_show, hist_file); - if (ret) + if (ret) { kfree(hist_file); + goto err; + } + return 0; +err: + tracing_release_file_tr(inode, file); return ret; } @@ -5979,7 +5988,10 @@ static int event_hist_debug_open(struct inode *inode, struct file *file) /* Clear private_data to avoid warning in single_open() */ file->private_data = NULL; - return single_open(file, hist_debug_show, file); + ret = single_open(file, hist_debug_show, file); + if (ret) + tracing_release_file_tr(inode, file); + return ret; } const struct file_operations event_hist_debug_fops = { -- 2.51.0 From ca3ac4bf4dc307cea5781dccccf41c1d14c2f82f Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 3 Mar 2025 18:02:32 +0000 Subject: [PATCH 03/16] xfs: Use abs_diff instead of XFS_ABSDIFF We have a central definition for this function since 2023, used by a number of different parts of the kernel. Signed-off-by: Matthew Wilcox (Oracle) Reviewed-by: Carlos Maiolino Reviewed-by: Eric Sandeen Signed-off-by: Carlos Maiolino --- fs/xfs/libxfs/xfs_alloc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 3d33e17f2e5c..7839efe050bf 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -33,8 +33,6 @@ struct kmem_cache *xfs_extfree_item_cache; struct workqueue_struct *xfs_alloc_wq; -#define XFS_ABSDIFF(a,b) (((a) <= (b)) ? ((b) - (a)) : ((a) - (b))) - #define XFSA_FIXUP_BNO_OK 1 #define XFSA_FIXUP_CNT_OK 2 @@ -410,8 +408,8 @@ xfs_alloc_compute_diff( if (newbno1 != NULLAGBLOCK && newbno2 != NULLAGBLOCK) { if (newlen1 < newlen2 || (newlen1 == newlen2 && - XFS_ABSDIFF(newbno1, wantbno) > - XFS_ABSDIFF(newbno2, wantbno))) + abs_diff(newbno1, wantbno) > + abs_diff(newbno2, wantbno))) newbno1 = newbno2; } else if (newbno2 != NULLAGBLOCK) newbno1 = newbno2; @@ -427,7 +425,7 @@ xfs_alloc_compute_diff( } else newbno1 = freeend - wantlen; *newbnop = newbno1; - return newbno1 == NULLAGBLOCK ? 0 : XFS_ABSDIFF(newbno1, wantbno); + return newbno1 == NULLAGBLOCK ? 0 : abs_diff(newbno1, wantbno); } /* -- 2.51.0 From 03fc0a2dc9f8c292fad8a1bcfb6d1f0dec1824be Mon Sep 17 00:00:00 2001 From: Ike Panhc Date: Fri, 14 Mar 2025 12:57:32 +0800 Subject: [PATCH 04/16] MAINTAINERS: Update Ike Panhc's email address MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit I am no longer at Canonical and update with my personal email address. Signed-off-by: Ike Panhc Link: https://lore.kernel.org/r/20250314045732.389973-1-ike.pan@canonical.com Signed-off-by: Ilpo Järvinen --- .mailmap | 1 + MAINTAINERS | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index ae0adc499f4a..449c5e3a5d26 100644 --- a/.mailmap +++ b/.mailmap @@ -281,6 +281,7 @@ Henrik Rydberg Herbert Xu Huacai Chen Huacai Chen +Ike Panhc J. Bruce Fields J. Bruce Fields Jacob Shin diff --git a/MAINTAINERS b/MAINTAINERS index 896a307fa065..bb4c069cc1e9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11140,7 +11140,7 @@ S: Maintained F: drivers/i2c/busses/i2c-icy.c IDEAPAD LAPTOP EXTRAS DRIVER -M: Ike Panhc +M: Ike Panhc L: platform-driver-x86@vger.kernel.org S: Maintained W: http://launchpad.net/ideapad-laptop -- 2.51.0 From 90fd9ad5b0c981693c8512d9da01f14fb6596e9d Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 14 Mar 2025 09:54:43 -0400 Subject: [PATCH 05/16] bcachefs: Change btree wb assert to runtime error We just had a report of the assert for "btree in write buffer for non-write buffer btree" popping during the 6.14 upgrade. - 150TB filesystem, after a reboot the upgrade was able to continue from where it left off, so no major damage. But with 6.14 about to come out we want to get this tracked down asap, and need more data if other users hit this. Convert the BUG_ON() to an emergency read-only, and print out btree, the key itself, and stack trace from the original write buffer update (which did not have this check before). Reported-by: Stijn Tintel Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_update.h | 8 ++++++++ fs/bcachefs/btree_write_buffer.c | 21 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_update.h b/fs/bcachefs/btree_update.h index 8f22ef9a7651..47d8690f01bf 100644 --- a/fs/bcachefs/btree_update.h +++ b/fs/bcachefs/btree_update.h @@ -126,10 +126,18 @@ bch2_trans_jset_entry_alloc(struct btree_trans *trans, unsigned u64s) int bch2_btree_insert_clone_trans(struct btree_trans *, enum btree_id, struct bkey_i *); +int bch2_btree_write_buffer_insert_err(struct btree_trans *, + enum btree_id, struct bkey_i *); + static inline int __must_check bch2_trans_update_buffered(struct btree_trans *trans, enum btree_id btree, struct bkey_i *k) { + if (unlikely(!btree_type_uses_write_buffer(btree))) { + int ret = bch2_btree_write_buffer_insert_err(trans, btree, k); + dump_stack(); + return ret; + } /* * Most updates skip the btree write buffer until journal replay is * finished because synchronization with journal replay relies on having diff --git a/fs/bcachefs/btree_write_buffer.c b/fs/bcachefs/btree_write_buffer.c index b56c4987b8c9..2c09d19dd621 100644 --- a/fs/bcachefs/btree_write_buffer.c +++ b/fs/bcachefs/btree_write_buffer.c @@ -264,6 +264,22 @@ out: BUG_ON(wb->sorted.size < wb->flushing.keys.nr); } +int bch2_btree_write_buffer_insert_err(struct btree_trans *trans, + enum btree_id btree, struct bkey_i *k) +{ + struct bch_fs *c = trans->c; + struct printbuf buf = PRINTBUF; + + prt_printf(&buf, "attempting to do write buffer update on non wb btree="); + bch2_btree_id_to_text(&buf, btree); + prt_str(&buf, "\n"); + bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k)); + + bch2_fs_inconsistent(c, "%s", buf.buf); + printbuf_exit(&buf); + return -EROFS; +} + static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans) { struct bch_fs *c = trans->c; @@ -312,7 +328,10 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans) darray_for_each(wb->sorted, i) { struct btree_write_buffered_key *k = &wb->flushing.keys.data[i->idx]; - BUG_ON(!btree_type_uses_write_buffer(k->btree)); + if (unlikely(!btree_type_uses_write_buffer(k->btree))) { + ret = bch2_btree_write_buffer_insert_err(trans, k->btree, &k->k); + goto err; + } for (struct wb_key_ref *n = i + 1; n < min(i + 4, &darray_top(wb->sorted)); n++) prefetch(&wb->flushing.keys.data[n->idx]); -- 2.51.0 From 1a2b74d0a2a46c219b25fdb0efcf9cd7f55cfe5e Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 14 Mar 2025 18:20:20 -0400 Subject: [PATCH 06/16] bcachefs: fix build on 32 bit in get_random_u64_below() bare 64 bit divides not allowed, whoops arm-linux-gnueabi-ld: drivers/char/random.o: in function `__get_random_u64_below': drivers/char/random.c:602:(.text+0xc70): undefined reference to `__aeabi_uldivmod' Signed-off-by: Kent Overstreet --- fs/bcachefs/util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c index 8e3ab4bf79a9..da2cd11b3025 100644 --- a/fs/bcachefs/util.c +++ b/fs/bcachefs/util.c @@ -663,7 +663,8 @@ u64 bch2_get_random_u64_below(u64 ceil) u64 mult = ceil * rand; if (unlikely(mult < ceil)) { - u64 bound = -ceil % ceil; + u64 bound; + div64_u64_rem(-ceil, ceil, &bound); while (unlikely(mult < bound)) { rand = get_random_u64(); mult = ceil * rand; -- 2.51.0 From 4701f33a10702d5fc577c32434eb62adde0a1ae1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 16 Mar 2025 12:55:17 -1000 Subject: [PATCH 07/16] Linux 6.14-rc7 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1d6a9ec8a2ac..50694bbbf828 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 14 SUBLEVEL = 0 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7 NAME = Baby Opossum Posse # *DOCUMENTATION* -- 2.51.0 From cd7d117a297149b61871d441fa1a8146c55c435d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Mar 2025 13:40:15 +0100 Subject: [PATCH 08/16] gpio: bcm-kona: use lock guards Reduce the code complexity by using automatic lock guards with the raw spinlock. Link: https://lore.kernel.org/r/20250310-gpiochip-set-conversion-v1-1-03798bb833eb@linaro.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-bcm-kona.c | 64 ++++++++++-------------------------- 1 file changed, 18 insertions(+), 46 deletions(-) diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 64908f1a5e7f..a7390b1f1173 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -100,7 +101,6 @@ static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio, unsigned gpio) { u32 val; - unsigned long flags; int bank_id = GPIO_BANK(gpio); int bit = GPIO_BIT(gpio); struct bcm_kona_gpio_bank *bank = &kona_gpio->banks[bank_id]; @@ -112,13 +112,11 @@ static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio, } if (--bank->gpio_unlock_count[bit] == 0) { - raw_spin_lock_irqsave(&kona_gpio->lock, flags); + guard(raw_spinlock_irqsave)(&kona_gpio->lock); val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id)); val |= BIT(bit); bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); - - raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } } @@ -126,19 +124,16 @@ static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio, unsigned gpio) { u32 val; - unsigned long flags; int bank_id = GPIO_BANK(gpio); int bit = GPIO_BIT(gpio); struct bcm_kona_gpio_bank *bank = &kona_gpio->banks[bank_id]; if (bank->gpio_unlock_count[bit] == 0) { - raw_spin_lock_irqsave(&kona_gpio->lock, flags); + guard(raw_spinlock_irqsave)(&kona_gpio->lock); val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id)); val &= ~BIT(bit); bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); - - raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } ++bank->gpio_unlock_count[bit]; @@ -161,24 +156,21 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) int bank_id = GPIO_BANK(gpio); int bit = GPIO_BIT(gpio); u32 val, reg_offset; - unsigned long flags; kona_gpio = gpiochip_get_data(chip); reg_base = kona_gpio->reg_base; - raw_spin_lock_irqsave(&kona_gpio->lock, flags); + + guard(raw_spinlock_irqsave)(&kona_gpio->lock); /* this function only applies to output pin */ if (bcm_kona_gpio_get_dir(chip, gpio) == GPIO_LINE_DIRECTION_IN) - goto out; + return; reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id); val = readl(reg_base + reg_offset); val |= BIT(bit); writel(val, reg_base + reg_offset); - -out: - raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio) @@ -188,11 +180,11 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio) int bank_id = GPIO_BANK(gpio); int bit = GPIO_BIT(gpio); u32 val, reg_offset; - unsigned long flags; kona_gpio = gpiochip_get_data(chip); reg_base = kona_gpio->reg_base; - raw_spin_lock_irqsave(&kona_gpio->lock, flags); + + guard(raw_spinlock_irqsave)(&kona_gpio->lock); if (bcm_kona_gpio_get_dir(chip, gpio) == GPIO_LINE_DIRECTION_IN) reg_offset = GPIO_IN_STATUS(bank_id); @@ -202,8 +194,6 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio) /* read the GPIO bank status */ val = readl(reg_base + reg_offset); - raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); - /* return the specified bit status */ return !!(val & BIT(bit)); } @@ -228,19 +218,17 @@ static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) struct bcm_kona_gpio *kona_gpio; void __iomem *reg_base; u32 val; - unsigned long flags; kona_gpio = gpiochip_get_data(chip); reg_base = kona_gpio->reg_base; - raw_spin_lock_irqsave(&kona_gpio->lock, flags); + + guard(raw_spinlock_irqsave)(&kona_gpio->lock); val = readl(reg_base + GPIO_CONTROL(gpio)); val &= ~GPIO_GPCTR0_IOTR_MASK; val |= GPIO_GPCTR0_IOTR_CMD_INPUT; writel(val, reg_base + GPIO_CONTROL(gpio)); - raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); - return 0; } @@ -252,11 +240,11 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip, int bank_id = GPIO_BANK(gpio); int bit = GPIO_BIT(gpio); u32 val, reg_offset; - unsigned long flags; kona_gpio = gpiochip_get_data(chip); reg_base = kona_gpio->reg_base; - raw_spin_lock_irqsave(&kona_gpio->lock, flags); + + guard(raw_spinlock_irqsave)(&kona_gpio->lock); val = readl(reg_base + GPIO_CONTROL(gpio)); val &= ~GPIO_GPCTR0_IOTR_MASK; @@ -268,8 +256,6 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip, val |= BIT(bit); writel(val, reg_base + reg_offset); - raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); - return 0; } @@ -289,7 +275,6 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio, struct bcm_kona_gpio *kona_gpio; void __iomem *reg_base; u32 val, res; - unsigned long flags; kona_gpio = gpiochip_get_data(chip); reg_base = kona_gpio->reg_base; @@ -312,7 +297,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio, } /* spin lock for read-modify-write of the GPIO register */ - raw_spin_lock_irqsave(&kona_gpio->lock, flags); + guard(raw_spinlock_irqsave)(&kona_gpio->lock); val = readl(reg_base + GPIO_CONTROL(gpio)); val &= ~GPIO_GPCTR0_DBR_MASK; @@ -327,8 +312,6 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio, writel(val, reg_base + GPIO_CONTROL(gpio)); - raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); - return 0; } @@ -367,17 +350,15 @@ static void bcm_kona_gpio_irq_ack(struct irq_data *d) int bank_id = GPIO_BANK(gpio); int bit = GPIO_BIT(gpio); u32 val; - unsigned long flags; kona_gpio = irq_data_get_irq_chip_data(d); reg_base = kona_gpio->reg_base; - raw_spin_lock_irqsave(&kona_gpio->lock, flags); + + guard(raw_spinlock_irqsave)(&kona_gpio->lock); val = readl(reg_base + GPIO_INT_STATUS(bank_id)); val |= BIT(bit); writel(val, reg_base + GPIO_INT_STATUS(bank_id)); - - raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } static void bcm_kona_gpio_irq_mask(struct irq_data *d) @@ -388,19 +369,16 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d) int bank_id = GPIO_BANK(gpio); int bit = GPIO_BIT(gpio); u32 val; - unsigned long flags; kona_gpio = irq_data_get_irq_chip_data(d); reg_base = kona_gpio->reg_base; - raw_spin_lock_irqsave(&kona_gpio->lock, flags); + guard(raw_spinlock_irqsave)(&kona_gpio->lock); val = readl(reg_base + GPIO_INT_MASK(bank_id)); val |= BIT(bit); writel(val, reg_base + GPIO_INT_MASK(bank_id)); gpiochip_disable_irq(&kona_gpio->gpio_chip, gpio); - - raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } static void bcm_kona_gpio_irq_unmask(struct irq_data *d) @@ -411,19 +389,16 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d) int bank_id = GPIO_BANK(gpio); int bit = GPIO_BIT(gpio); u32 val; - unsigned long flags; kona_gpio = irq_data_get_irq_chip_data(d); reg_base = kona_gpio->reg_base; - raw_spin_lock_irqsave(&kona_gpio->lock, flags); + guard(raw_spinlock_irqsave)(&kona_gpio->lock); val = readl(reg_base + GPIO_INT_MSKCLR(bank_id)); val |= BIT(bit); writel(val, reg_base + GPIO_INT_MSKCLR(bank_id)); gpiochip_enable_irq(&kona_gpio->gpio_chip, gpio); - - raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type) @@ -433,7 +408,6 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type) unsigned gpio = d->hwirq; u32 lvl_type; u32 val; - unsigned long flags; kona_gpio = irq_data_get_irq_chip_data(d); reg_base = kona_gpio->reg_base; @@ -459,15 +433,13 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type) return -EINVAL; } - raw_spin_lock_irqsave(&kona_gpio->lock, flags); + guard(raw_spinlock_irqsave)(&kona_gpio->lock); val = readl(reg_base + GPIO_CONTROL(gpio)); val &= ~GPIO_GPCTR0_ITR_MASK; val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT; writel(val, reg_base + GPIO_CONTROL(gpio)); - raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); - return 0; } -- 2.51.0 From d5cc72803b146c811b01f9a5b91e97337adf5784 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Mar 2025 13:40:16 +0100 Subject: [PATCH 09/16] gpio: bcm-kona: use new line value setter callbacks struct gpio_chip now has callbacks for setting line values that return an integer, allowing to indicate failures. Convert the driver to using them. Link: https://lore.kernel.org/r/20250310-gpiochip-set-conversion-v1-2-03798bb833eb@linaro.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-bcm-kona.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index a7390b1f1173..17c287dc7471 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -149,7 +149,8 @@ static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio) return val ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT; } -static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) +static int bcm_kona_gpio_set(struct gpio_chip *chip, unsigned int gpio, + int value) { struct bcm_kona_gpio *kona_gpio; void __iomem *reg_base; @@ -164,13 +165,15 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) /* this function only applies to output pin */ if (bcm_kona_gpio_get_dir(chip, gpio) == GPIO_LINE_DIRECTION_IN) - return; + return 0; reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id); val = readl(reg_base + reg_offset); val |= BIT(bit); writel(val, reg_base + reg_offset); + + return 0; } static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio) @@ -336,7 +339,7 @@ static const struct gpio_chip template_chip = { .direction_input = bcm_kona_gpio_direction_input, .get = bcm_kona_gpio_get, .direction_output = bcm_kona_gpio_direction_output, - .set = bcm_kona_gpio_set, + .set_rv = bcm_kona_gpio_set, .set_config = bcm_kona_gpio_set_config, .to_irq = bcm_kona_gpio_to_irq, .base = 0, -- 2.51.0 From 7bd2bb7901a67f6b14c913596acb471351f500a5 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Mar 2025 13:40:17 +0100 Subject: [PATCH 10/16] gpio: bd71815: use new line value setter callbacks struct gpio_chip now has callbacks for setting line values that return an integer, allowing to indicate failures. Convert the driver to using them. Reviewed-by: Matti Vaittinen Link: https://lore.kernel.org/r/20250310-gpiochip-set-conversion-v1-3-03798bb833eb@linaro.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-bd71815.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-bd71815.c b/drivers/gpio/gpio-bd71815.c index 08ff2857256f..36701500925e 100644 --- a/drivers/gpio/gpio-bd71815.c +++ b/drivers/gpio/gpio-bd71815.c @@ -37,21 +37,18 @@ static int bd71815gpo_get(struct gpio_chip *chip, unsigned int offset) return (val >> offset) & 1; } -static void bd71815gpo_set(struct gpio_chip *chip, unsigned int offset, - int value) +static int bd71815gpo_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct bd71815_gpio *bd71815 = gpiochip_get_data(chip); - int ret, bit; + int bit; bit = BIT(offset); if (value) - ret = regmap_set_bits(bd71815->regmap, BD71815_REG_GPO, bit); - else - ret = regmap_clear_bits(bd71815->regmap, BD71815_REG_GPO, bit); + return regmap_set_bits(bd71815->regmap, BD71815_REG_GPO, bit); - if (ret) - dev_warn(bd71815->dev, "failed to toggle GPO\n"); + return regmap_clear_bits(bd71815->regmap, BD71815_REG_GPO, bit); } static int bd71815_gpio_set_config(struct gpio_chip *chip, unsigned int offset, @@ -88,7 +85,7 @@ static const struct gpio_chip bd71815gpo_chip = { .owner = THIS_MODULE, .get = bd71815gpo_get, .get_direction = bd71815gpo_direction_get, - .set = bd71815gpo_set, + .set_rv = bd71815gpo_set, .set_config = bd71815_gpio_set_config, .can_sleep = true, }; -- 2.51.0 From 8a050f738d41d337fb73ef582916328dc5bd73e1 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Mar 2025 13:40:18 +0100 Subject: [PATCH 11/16] gpio: bd71828: use new line value setter callbacks struct gpio_chip now has callbacks for setting line values that return an integer, allowing to indicate failures. Convert the driver to using them. Reviewed-by: Matti Vaittinen Link: https://lore.kernel.org/r/20250310-gpiochip-set-conversion-v1-4-03798bb833eb@linaro.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-bd71828.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-bd71828.c b/drivers/gpio/gpio-bd71828.c index b2ccc320c7b5..4ba151e5cf25 100644 --- a/drivers/gpio/gpio-bd71828.c +++ b/drivers/gpio/gpio-bd71828.c @@ -16,10 +16,9 @@ struct bd71828_gpio { struct gpio_chip gpio; }; -static void bd71828_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) +static int bd71828_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { - int ret; struct bd71828_gpio *bdgpio = gpiochip_get_data(chip); u8 val = (value) ? BD71828_GPIO_OUT_HI : BD71828_GPIO_OUT_LO; @@ -28,12 +27,10 @@ static void bd71828_gpio_set(struct gpio_chip *chip, unsigned int offset, * we are dealing with - then we are done */ if (offset == HALL_GPIO_OFFSET) - return; + return 0; - ret = regmap_update_bits(bdgpio->regmap, GPIO_OUT_REG(offset), - BD71828_GPIO_OUT_MASK, val); - if (ret) - dev_err(bdgpio->dev, "Could not set gpio to %d\n", value); + return regmap_update_bits(bdgpio->regmap, GPIO_OUT_REG(offset), + BD71828_GPIO_OUT_MASK, val); } static int bd71828_gpio_get(struct gpio_chip *chip, unsigned int offset) @@ -112,7 +109,7 @@ static int bd71828_probe(struct platform_device *pdev) bdgpio->gpio.set_config = bd71828_gpio_set_config; bdgpio->gpio.can_sleep = true; bdgpio->gpio.get = bd71828_gpio_get; - bdgpio->gpio.set = bd71828_gpio_set; + bdgpio->gpio.set_rv = bd71828_gpio_set; bdgpio->gpio.base = -1; /* -- 2.51.0 From fe7667f2085ee7d66a6a34e6bf6830be7e641b52 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Mar 2025 13:40:19 +0100 Subject: [PATCH 12/16] gpio: bd9571mwv: use new line value setter callbacks struct gpio_chip now has callbacks for setting line values that return an integer, allowing to indicate failures. Convert the driver to using them. Reviewed-by: Matti Vaittinen Link: https://lore.kernel.org/r/20250310-gpiochip-set-conversion-v1-5-03798bb833eb@linaro.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-bd9571mwv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-bd9571mwv.c b/drivers/gpio/gpio-bd9571mwv.c index 9a4d55f703bb..8df1361e3e84 100644 --- a/drivers/gpio/gpio-bd9571mwv.c +++ b/drivers/gpio/gpio-bd9571mwv.c @@ -72,13 +72,13 @@ static int bd9571mwv_gpio_get(struct gpio_chip *chip, unsigned int offset) return val & BIT(offset); } -static void bd9571mwv_gpio_set(struct gpio_chip *chip, unsigned int offset, +static int bd9571mwv_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); - regmap_update_bits(gpio->regmap, BD9571MWV_GPIO_OUT, - BIT(offset), value ? BIT(offset) : 0); + return regmap_update_bits(gpio->regmap, BD9571MWV_GPIO_OUT, + BIT(offset), value ? BIT(offset) : 0); } static const struct gpio_chip template_chip = { @@ -88,7 +88,7 @@ static const struct gpio_chip template_chip = { .direction_input = bd9571mwv_gpio_direction_input, .direction_output = bd9571mwv_gpio_direction_output, .get = bd9571mwv_gpio_get, - .set = bd9571mwv_gpio_set, + .set_rv = bd9571mwv_gpio_set, .base = -1, .ngpio = 2, .can_sleep = true, -- 2.51.0 From c948feeadba290e989b049913576b3d30ba02235 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Mar 2025 13:40:20 +0100 Subject: [PATCH 13/16] gpio: bt8xx: allow to build the module with COMPILE_TEST=y Link: https://lore.kernel.org/r/20250310-gpiochip-set-conversion-v1-6-03798bb833eb@linaro.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3e9b174fee84..f2c39bbff83a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1671,7 +1671,7 @@ config GPIO_AMD8111 config GPIO_BT8XX tristate "BT8XX GPIO abuser" - depends on VIDEO_BT848=n + depends on VIDEO_BT848=n || COMPILE_TEST help The BT8xx frame grabber chip has 24 GPIO pins that can be abused as a cheap PCI GPIO card. -- 2.51.0 From b9a557d05a7dde42b1e3652751eea6c06091402e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Mar 2025 13:40:21 +0100 Subject: [PATCH 14/16] gpio: bt8xx: use lock guards Reduce the code complexity by using automatic lock guards with the spinlock. Link: https://lore.kernel.org/r/20250310-gpiochip-set-conversion-v1-7-03798bb833eb@linaro.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-bt8xx.c | 43 +++++++++++++-------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c index 7920cf256798..173da7bbfc98 100644 --- a/drivers/gpio/gpio-bt8xx.c +++ b/drivers/gpio/gpio-bt8xx.c @@ -31,6 +31,7 @@ */ +#include #include #include #include @@ -69,10 +70,9 @@ MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) { struct bt8xxgpio *bg = gpiochip_get_data(gpio); - unsigned long flags; u32 outen, data; - spin_lock_irqsave(&bg->lock, flags); + guard(spinlock_irqsave)(&bg->lock); data = bgread(BT848_GPIO_DATA); data &= ~(1 << nr); @@ -82,20 +82,17 @@ static int bt8xxgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) outen &= ~(1 << nr); bgwrite(outen, BT848_GPIO_OUT_EN); - spin_unlock_irqrestore(&bg->lock, flags); - return 0; } static int bt8xxgpio_gpio_get(struct gpio_chip *gpio, unsigned nr) { struct bt8xxgpio *bg = gpiochip_get_data(gpio); - unsigned long flags; u32 val; - spin_lock_irqsave(&bg->lock, flags); + guard(spinlock_irqsave)(&bg->lock); + val = bgread(BT848_GPIO_DATA); - spin_unlock_irqrestore(&bg->lock, flags); return !!(val & (1 << nr)); } @@ -104,10 +101,9 @@ static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, int val) { struct bt8xxgpio *bg = gpiochip_get_data(gpio); - unsigned long flags; u32 outen, data; - spin_lock_irqsave(&bg->lock, flags); + guard(spinlock_irqsave)(&bg->lock); outen = bgread(BT848_GPIO_OUT_EN); outen |= (1 << nr); @@ -120,8 +116,6 @@ static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio, data &= ~(1 << nr); bgwrite(data, BT848_GPIO_DATA); - spin_unlock_irqrestore(&bg->lock, flags); - return 0; } @@ -129,10 +123,9 @@ static void bt8xxgpio_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) { struct bt8xxgpio *bg = gpiochip_get_data(gpio); - unsigned long flags; u32 data; - spin_lock_irqsave(&bg->lock, flags); + guard(spinlock_irqsave)(&bg->lock); data = bgread(BT848_GPIO_DATA); if (val) @@ -140,8 +133,6 @@ static void bt8xxgpio_gpio_set(struct gpio_chip *gpio, else data &= ~(1 << nr); bgwrite(data, BT848_GPIO_DATA); - - spin_unlock_irqrestore(&bg->lock, flags); } static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg) @@ -236,18 +227,15 @@ static void bt8xxgpio_remove(struct pci_dev *pdev) static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state) { struct bt8xxgpio *bg = pci_get_drvdata(pdev); - unsigned long flags; - - spin_lock_irqsave(&bg->lock, flags); - bg->saved_outen = bgread(BT848_GPIO_OUT_EN); - bg->saved_data = bgread(BT848_GPIO_DATA); + scoped_guard(spinlock_irqsave, &bg->lock) { + bg->saved_outen = bgread(BT848_GPIO_OUT_EN); + bg->saved_data = bgread(BT848_GPIO_DATA); - bgwrite(0, BT848_INT_MASK); - bgwrite(~0x0, BT848_INT_STAT); - bgwrite(0x0, BT848_GPIO_OUT_EN); - - spin_unlock_irqrestore(&bg->lock, flags); + bgwrite(0, BT848_INT_MASK); + bgwrite(~0x0, BT848_INT_STAT); + bgwrite(0x0, BT848_GPIO_OUT_EN); + } pci_save_state(pdev); pci_disable_device(pdev); @@ -259,7 +247,6 @@ static int bt8xxgpio_suspend(struct pci_dev *pdev, pm_message_t state) static int bt8xxgpio_resume(struct pci_dev *pdev) { struct bt8xxgpio *bg = pci_get_drvdata(pdev); - unsigned long flags; int err; pci_set_power_state(pdev, PCI_D0); @@ -268,7 +255,7 @@ static int bt8xxgpio_resume(struct pci_dev *pdev) return err; pci_restore_state(pdev); - spin_lock_irqsave(&bg->lock, flags); + guard(spinlock_irqsave)(&bg->lock); bgwrite(0, BT848_INT_MASK); bgwrite(0, BT848_GPIO_DMA_CTL); @@ -277,8 +264,6 @@ static int bt8xxgpio_resume(struct pci_dev *pdev) bgwrite(bg->saved_data & bg->saved_outen, BT848_GPIO_DATA); - spin_unlock_irqrestore(&bg->lock, flags); - return 0; } #else -- 2.51.0 From 19c39c53752ae0b5cbf7577bcdf7c13d1c146e65 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Mar 2025 13:40:22 +0100 Subject: [PATCH 15/16] gpio: bt8xx: use new line value setter callbacks struct gpio_chip now has callbacks for setting line values that return an integer, allowing to indicate failures. Convert the driver to using them. Link: https://lore.kernel.org/r/20250310-gpiochip-set-conversion-v1-8-03798bb833eb@linaro.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-bt8xx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c index 173da7bbfc98..7c9e81fea37a 100644 --- a/drivers/gpio/gpio-bt8xx.c +++ b/drivers/gpio/gpio-bt8xx.c @@ -119,8 +119,7 @@ static int bt8xxgpio_gpio_direction_output(struct gpio_chip *gpio, return 0; } -static void bt8xxgpio_gpio_set(struct gpio_chip *gpio, - unsigned nr, int val) +static int bt8xxgpio_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val) { struct bt8xxgpio *bg = gpiochip_get_data(gpio); u32 data; @@ -133,6 +132,8 @@ static void bt8xxgpio_gpio_set(struct gpio_chip *gpio, else data &= ~(1 << nr); bgwrite(data, BT848_GPIO_DATA); + + return 0; } static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg) @@ -144,7 +145,7 @@ static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg) c->direction_input = bt8xxgpio_gpio_direction_input; c->get = bt8xxgpio_gpio_get; c->direction_output = bt8xxgpio_gpio_direction_output; - c->set = bt8xxgpio_gpio_set; + c->set_rv = bt8xxgpio_gpio_set; c->dbg_show = NULL; c->base = modparam_gpiobase; c->ngpio = BT8XXGPIO_NR_GPIOS; -- 2.51.0 From 1e69c7532a188a84b4cb535944fd7d60393a1fc8 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Mar 2025 13:40:23 +0100 Subject: [PATCH 16/16] gpio: cgbc: use new line value setter callbacks struct gpio_chip now has callbacks for setting line values that return an integer, allowing to indicate failures. Convert the driver to using them. Link: https://lore.kernel.org/r/20250310-gpiochip-set-conversion-v1-9-03798bb833eb@linaro.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-cgbc.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-cgbc.c b/drivers/gpio/gpio-cgbc.c index 9213faa11522..1495bec62456 100644 --- a/drivers/gpio/gpio-cgbc.c +++ b/drivers/gpio/gpio-cgbc.c @@ -51,8 +51,8 @@ static int cgbc_gpio_get(struct gpio_chip *chip, unsigned int offset) return (int)(val & (u8)BIT(offset)); } -static void __cgbc_gpio_set(struct gpio_chip *chip, - unsigned int offset, int value) +static int __cgbc_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct cgbc_gpio_data *gpio = gpiochip_get_data(chip); struct cgbc_device_data *cgbc = gpio->cgbc; @@ -61,23 +61,23 @@ static void __cgbc_gpio_set(struct gpio_chip *chip, ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_GET, (offset > 7) ? 1 : 0, 0, &val); if (ret) - return; + return ret; if (value) val |= BIT(offset % 8); else val &= ~(BIT(offset % 8)); - cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_SET, (offset > 7) ? 1 : 0, val, &val); + return cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_SET, (offset > 7) ? 1 : 0, val, &val); } -static void cgbc_gpio_set(struct gpio_chip *chip, - unsigned int offset, int value) +static int cgbc_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { struct cgbc_gpio_data *gpio = gpiochip_get_data(chip); - scoped_guard(mutex, &gpio->lock) - __cgbc_gpio_set(chip, offset, value); + guard(mutex)(&gpio->lock); + + return __cgbc_gpio_set(chip, offset, value); } static int cgbc_gpio_direction_set(struct gpio_chip *chip, @@ -116,10 +116,14 @@ static int cgbc_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value) { struct cgbc_gpio_data *gpio = gpiochip_get_data(chip); + int ret; guard(mutex)(&gpio->lock); - __cgbc_gpio_set(chip, offset, value); + ret = __cgbc_gpio_set(chip, offset, value); + if (ret) + return ret; + return cgbc_gpio_direction_set(chip, offset, GPIO_LINE_DIRECTION_OUT); } @@ -167,7 +171,7 @@ static int cgbc_gpio_probe(struct platform_device *pdev) chip->direction_output = cgbc_gpio_direction_output; chip->get_direction = cgbc_gpio_get_direction; chip->get = cgbc_gpio_get; - chip->set = cgbc_gpio_set; + chip->set_rv = cgbc_gpio_set; chip->ngpio = CGBC_GPIO_NGPIO; ret = devm_mutex_init(dev, &gpio->lock); -- 2.51.0