The patch below does not apply to the 6.18-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 <stable(a)vger.kernel.org>.
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.18.y
git checkout FETCH_HEAD
git cherry-pick -x 1e876e5a0875e71e34148c9feb2eedd3bf6b2b43
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable(a)vger.kernel.org>' --in-reply-to '2026011202-scheming-operating-3cbb@gregkh' --subject-prefix 'PATCH 6.18.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 1e876e5a0875e71e34148c9feb2eedd3bf6b2b43 Mon Sep 17 00:00:00 2001
From: Abdun Nihaal <nihaal(a)cse.iitm.ac.in>
Date: Fri, 26 Dec 2025 11:34:10 +0530
Subject: [PATCH] gpio: mpsse: fix reference leak in gpio_mpsse_probe() error
paths
The reference obtained by calling usb_get_dev() is not released in the
gpio_mpsse_probe() error paths. Fix that by using device managed helper
functions. Also remove the usb_put_dev() call in the disconnect function
since now it will be released automatically.
Cc: stable(a)vger.kernel.org
Fixes: c46a74ff05c0 ("gpio: add support for FTDI's MPSSE as GPIO")
Signed-off-by: Abdun Nihaal <nihaal(a)cse.iitm.ac.in>
Link: https://lore.kernel.org/r/20251226060414.20785-1-nihaal@cse.iitm.ac.in
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski(a)oss.qualcomm.com>
diff --git a/drivers/gpio/gpio-mpsse.c b/drivers/gpio/gpio-mpsse.c
index ace652ba4df1..12191aeb6566 100644
--- a/drivers/gpio/gpio-mpsse.c
+++ b/drivers/gpio/gpio-mpsse.c
@@ -548,6 +548,13 @@ static void gpio_mpsse_ida_remove(void *data)
ida_free(&gpio_mpsse_ida, priv->id);
}
+static void gpio_mpsse_usb_put_dev(void *data)
+{
+ struct mpsse_priv *priv = data;
+
+ usb_put_dev(priv->udev);
+}
+
static int mpsse_init_valid_mask(struct gpio_chip *chip,
unsigned long *valid_mask,
unsigned int ngpios)
@@ -592,6 +599,10 @@ static int gpio_mpsse_probe(struct usb_interface *interface,
INIT_LIST_HEAD(&priv->workers);
priv->udev = usb_get_dev(interface_to_usbdev(interface));
+ err = devm_add_action_or_reset(dev, gpio_mpsse_usb_put_dev, priv);
+ if (err)
+ return err;
+
priv->intf = interface;
priv->intf_id = interface->cur_altsetting->desc.bInterfaceNumber;
@@ -713,7 +724,6 @@ static void gpio_mpsse_disconnect(struct usb_interface *intf)
priv->intf = NULL;
usb_set_intfdata(intf, NULL);
- usb_put_dev(priv->udev);
}
static struct usb_driver gpio_mpsse_driver = {
On Mon, Jan 12, 2026 at 12:23:45PM -0500, Sasha Levin wrote:
> This is a note to let you know that I've just added the patch titled
>
> bcache: fix improper use of bi_end_io
>
> to the 6.6-stable tree which can be found at:
> http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=sum…
>
> The filename of the patch is:
> bcache-fix-improper-use-of-bi_end_io.patch
> and it can be found in the queue-6.6 subdirectory.
>
> If you, or anyone else, feels it should not be added to the stable tree,
> please let <stable(a)vger.kernel.org> know about it.
Has this code been tested?
bio_endio() is not equivalent to calling bi_end_io; if the code is
swapping out bi_end_io to pass it down the stack, then you have two
completions on the same bio - you cannot call bio_endio() twice on the
same bio.
>
>
>
> commit 81e7e43a810e8f40e163928d441de02d2816b073
> Author: Shida Zhang <zhangshida(a)kylinos.cn>
> Date: Tue Dec 9 17:01:56 2025 +0800
>
> bcache: fix improper use of bi_end_io
>
> [ Upstream commit 53280e398471f0bddbb17b798a63d41264651325 ]
>
> Don't call bio->bi_end_io() directly. Use the bio_endio() helper
> function instead, which handles completion more safely and uniformly.
>
> Suggested-by: Christoph Hellwig <hch(a)infradead.org>
> Reviewed-by: Christoph Hellwig <hch(a)lst.de>
> Signed-off-by: Shida Zhang <zhangshida(a)kylinos.cn>
> Signed-off-by: Jens Axboe <axboe(a)kernel.dk>
> Signed-off-by: Sasha Levin <sashal(a)kernel.org>
>
> diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
> index a9b1f3896249b..b4059d2daa326 100644
> --- a/drivers/md/bcache/request.c
> +++ b/drivers/md/bcache/request.c
> @@ -1090,7 +1090,7 @@ static void detached_dev_end_io(struct bio *bio)
> }
>
> kfree(ddip);
> - bio->bi_end_io(bio);
> + bio_endio(bio);
> }
>
> static void detached_dev_do_request(struct bcache_device *d, struct bio *bio,
> @@ -1107,7 +1107,7 @@ static void detached_dev_do_request(struct bcache_device *d, struct bio *bio,
> ddip = kzalloc(sizeof(struct detached_dev_io_private), GFP_NOIO);
> if (!ddip) {
> bio->bi_status = BLK_STS_RESOURCE;
> - bio->bi_end_io(bio);
> + bio_endio(bio);
> return;
> }
>
> @@ -1122,7 +1122,7 @@ static void detached_dev_do_request(struct bcache_device *d, struct bio *bio,
>
> if ((bio_op(bio) == REQ_OP_DISCARD) &&
> !bdev_max_discard_sectors(dc->bdev))
> - bio->bi_end_io(bio);
> + detached_dev_end_io(bio);
> else
> submit_bio_noacct(bio);
> }
The 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 <stable(a)vger.kernel.org>.
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 830988b6cf197e6dcffdfe2008c5738e6c6c3c0f
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable(a)vger.kernel.org>' --in-reply-to '2026011239-rockband-chewable-857b@gregkh' --subject-prefix 'PATCH 6.1.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 830988b6cf197e6dcffdfe2008c5738e6c6c3c0f Mon Sep 17 00:00:00 2001
From: Haoxiang Li <lihaoxiang(a)isrc.iscas.ac.cn>
Date: Sat, 20 Dec 2025 00:28:45 +0800
Subject: [PATCH] ALSA: ac97: fix a double free in
snd_ac97_controller_register()
If ac97_add_adapter() fails, put_device() is the correct way to drop
the device reference. kfree() is not required.
Add kfree() if idr_alloc() fails and in ac97_adapter_release() to do
the cleanup.
Found by code review.
Fixes: 74426fbff66e ("ALSA: ac97: add an ac97 bus")
Cc: stable(a)vger.kernel.org
Signed-off-by: Haoxiang Li <lihaoxiang(a)isrc.iscas.ac.cn>
Link: https://patch.msgid.link/20251219162845.657525-1-lihaoxiang@isrc.iscas.ac.cn
Signed-off-by: Takashi Iwai <tiwai(a)suse.de>
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
index f4254703d29f..bb9b795e0226 100644
--- a/sound/ac97/bus.c
+++ b/sound/ac97/bus.c
@@ -298,6 +298,7 @@ static void ac97_adapter_release(struct device *dev)
idr_remove(&ac97_adapter_idr, ac97_ctrl->nr);
dev_dbg(&ac97_ctrl->adap, "adapter unregistered by %s\n",
dev_name(ac97_ctrl->parent));
+ kfree(ac97_ctrl);
}
static const struct device_type ac97_adapter_type = {
@@ -319,7 +320,9 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl)
ret = device_register(&ac97_ctrl->adap);
if (ret)
put_device(&ac97_ctrl->adap);
- }
+ } else
+ kfree(ac97_ctrl);
+
if (!ret) {
list_add(&ac97_ctrl->controllers, &ac97_controllers);
dev_dbg(&ac97_ctrl->adap, "adapter registered by %s\n",
@@ -361,14 +364,11 @@ struct ac97_controller *snd_ac97_controller_register(
ret = ac97_add_adapter(ac97_ctrl);
if (ret)
- goto err;
+ return ERR_PTR(ret);
ac97_bus_reset(ac97_ctrl);
ac97_bus_scan(ac97_ctrl);
return ac97_ctrl;
-err:
- kfree(ac97_ctrl);
- return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(snd_ac97_controller_register);
The patch below does not apply to the 5.15-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 <stable(a)vger.kernel.org>.
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-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 23f9485510c338476b9735d516c1d4aacb810d46
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable(a)vger.kernel.org>' --in-reply-to '2026011244-unbaked-pajamas-9c74@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 23f9485510c338476b9735d516c1d4aacb810d46 Mon Sep 17 00:00:00 2001
From: Alexander Sverdlin <alexander.sverdlin(a)gmail.com>
Date: Tue, 18 Nov 2025 09:35:48 +0100
Subject: [PATCH] counter: interrupt-cnt: Drop IRQF_NO_THREAD flag
An IRQ handler can either be IRQF_NO_THREAD or acquire spinlock_t, as
CONFIG_PROVE_RAW_LOCK_NESTING warns:
=============================
[ BUG: Invalid wait context ]
6.18.0-rc1+git... #1
-----------------------------
some-user-space-process/1251 is trying to lock:
(&counter->events_list_lock){....}-{3:3}, at: counter_push_event [counter]
other info that might help us debug this:
context-{2:2}
no locks held by some-user-space-process/....
stack backtrace:
CPU: 0 UID: 0 PID: 1251 Comm: some-user-space-process 6.18.0-rc1+git... #1 PREEMPT
Call trace:
show_stack (C)
dump_stack_lvl
dump_stack
__lock_acquire
lock_acquire
_raw_spin_lock_irqsave
counter_push_event [counter]
interrupt_cnt_isr [interrupt_cnt]
__handle_irq_event_percpu
handle_irq_event
handle_simple_irq
handle_irq_desc
generic_handle_domain_irq
gpio_irq_handler
handle_irq_desc
generic_handle_domain_irq
gic_handle_irq
call_on_irq_stack
do_interrupt_handler
el0_interrupt
__el0_irq_handler_common
el0t_64_irq_handler
el0t_64_irq
... and Sebastian correctly points out. Remove IRQF_NO_THREAD as an
alternative to switching to raw_spinlock_t, because the latter would limit
all potential nested locks to raw_spinlock_t only.
Cc: Sebastian Andrzej Siewior <bigeasy(a)linutronix.de>
Cc: stable(a)vger.kernel.org
Link: https://lore.kernel.org/all/20251117151314.xwLAZrWY@linutronix.de/
Fixes: a55ebd47f21f ("counter: add IRQ or GPIO based counter")
Signed-off-by: Alexander Sverdlin <alexander.sverdlin(a)siemens.com>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy(a)linutronix.de>
Reviewed-by: Oleksij Rempel <o.rempel(a)pengutronix.de>
Link: https://lore.kernel.org/r/20251118083603.778626-1-alexander.sverdlin@siemen…
Signed-off-by: William Breathitt Gray <wbg(a)kernel.org>
diff --git a/drivers/counter/interrupt-cnt.c b/drivers/counter/interrupt-cnt.c
index 6c0c1d2d7027..e6100b5fb082 100644
--- a/drivers/counter/interrupt-cnt.c
+++ b/drivers/counter/interrupt-cnt.c
@@ -229,8 +229,7 @@ static int interrupt_cnt_probe(struct platform_device *pdev)
irq_set_status_flags(priv->irq, IRQ_NOAUTOEN);
ret = devm_request_irq(dev, priv->irq, interrupt_cnt_isr,
- IRQF_TRIGGER_RISING | IRQF_NO_THREAD,
- dev_name(dev), counter);
+ IRQF_TRIGGER_RISING, dev_name(dev), counter);
if (ret)
return ret;
The patch below does not apply to the 6.6-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 <stable(a)vger.kernel.org>.
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.6.y
git checkout FETCH_HEAD
git cherry-pick -x 830988b6cf197e6dcffdfe2008c5738e6c6c3c0f
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable(a)vger.kernel.org>' --in-reply-to '2026011239-sustained-underpass-b703@gregkh' --subject-prefix 'PATCH 6.6.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 830988b6cf197e6dcffdfe2008c5738e6c6c3c0f Mon Sep 17 00:00:00 2001
From: Haoxiang Li <lihaoxiang(a)isrc.iscas.ac.cn>
Date: Sat, 20 Dec 2025 00:28:45 +0800
Subject: [PATCH] ALSA: ac97: fix a double free in
snd_ac97_controller_register()
If ac97_add_adapter() fails, put_device() is the correct way to drop
the device reference. kfree() is not required.
Add kfree() if idr_alloc() fails and in ac97_adapter_release() to do
the cleanup.
Found by code review.
Fixes: 74426fbff66e ("ALSA: ac97: add an ac97 bus")
Cc: stable(a)vger.kernel.org
Signed-off-by: Haoxiang Li <lihaoxiang(a)isrc.iscas.ac.cn>
Link: https://patch.msgid.link/20251219162845.657525-1-lihaoxiang@isrc.iscas.ac.cn
Signed-off-by: Takashi Iwai <tiwai(a)suse.de>
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
index f4254703d29f..bb9b795e0226 100644
--- a/sound/ac97/bus.c
+++ b/sound/ac97/bus.c
@@ -298,6 +298,7 @@ static void ac97_adapter_release(struct device *dev)
idr_remove(&ac97_adapter_idr, ac97_ctrl->nr);
dev_dbg(&ac97_ctrl->adap, "adapter unregistered by %s\n",
dev_name(ac97_ctrl->parent));
+ kfree(ac97_ctrl);
}
static const struct device_type ac97_adapter_type = {
@@ -319,7 +320,9 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl)
ret = device_register(&ac97_ctrl->adap);
if (ret)
put_device(&ac97_ctrl->adap);
- }
+ } else
+ kfree(ac97_ctrl);
+
if (!ret) {
list_add(&ac97_ctrl->controllers, &ac97_controllers);
dev_dbg(&ac97_ctrl->adap, "adapter registered by %s\n",
@@ -361,14 +364,11 @@ struct ac97_controller *snd_ac97_controller_register(
ret = ac97_add_adapter(ac97_ctrl);
if (ret)
- goto err;
+ return ERR_PTR(ret);
ac97_bus_reset(ac97_ctrl);
ac97_bus_scan(ac97_ctrl);
return ac97_ctrl;
-err:
- kfree(ac97_ctrl);
- return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(snd_ac97_controller_register);
The patch below does not apply to the 6.12-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 <stable(a)vger.kernel.org>.
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.12.y
git checkout FETCH_HEAD
git cherry-pick -x 830988b6cf197e6dcffdfe2008c5738e6c6c3c0f
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable(a)vger.kernel.org>' --in-reply-to '2026011238-subduing-rural-1bbc@gregkh' --subject-prefix 'PATCH 6.12.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 830988b6cf197e6dcffdfe2008c5738e6c6c3c0f Mon Sep 17 00:00:00 2001
From: Haoxiang Li <lihaoxiang(a)isrc.iscas.ac.cn>
Date: Sat, 20 Dec 2025 00:28:45 +0800
Subject: [PATCH] ALSA: ac97: fix a double free in
snd_ac97_controller_register()
If ac97_add_adapter() fails, put_device() is the correct way to drop
the device reference. kfree() is not required.
Add kfree() if idr_alloc() fails and in ac97_adapter_release() to do
the cleanup.
Found by code review.
Fixes: 74426fbff66e ("ALSA: ac97: add an ac97 bus")
Cc: stable(a)vger.kernel.org
Signed-off-by: Haoxiang Li <lihaoxiang(a)isrc.iscas.ac.cn>
Link: https://patch.msgid.link/20251219162845.657525-1-lihaoxiang@isrc.iscas.ac.cn
Signed-off-by: Takashi Iwai <tiwai(a)suse.de>
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
index f4254703d29f..bb9b795e0226 100644
--- a/sound/ac97/bus.c
+++ b/sound/ac97/bus.c
@@ -298,6 +298,7 @@ static void ac97_adapter_release(struct device *dev)
idr_remove(&ac97_adapter_idr, ac97_ctrl->nr);
dev_dbg(&ac97_ctrl->adap, "adapter unregistered by %s\n",
dev_name(ac97_ctrl->parent));
+ kfree(ac97_ctrl);
}
static const struct device_type ac97_adapter_type = {
@@ -319,7 +320,9 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl)
ret = device_register(&ac97_ctrl->adap);
if (ret)
put_device(&ac97_ctrl->adap);
- }
+ } else
+ kfree(ac97_ctrl);
+
if (!ret) {
list_add(&ac97_ctrl->controllers, &ac97_controllers);
dev_dbg(&ac97_ctrl->adap, "adapter registered by %s\n",
@@ -361,14 +364,11 @@ struct ac97_controller *snd_ac97_controller_register(
ret = ac97_add_adapter(ac97_ctrl);
if (ret)
- goto err;
+ return ERR_PTR(ret);
ac97_bus_reset(ac97_ctrl);
ac97_bus_scan(ac97_ctrl);
return ac97_ctrl;
-err:
- kfree(ac97_ctrl);
- return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(snd_ac97_controller_register);
Commit 53326135d0e0 ("i2c: riic: Add suspend/resume support") added
suspend support for the Renesas I2C driver and following this change
on RZ/G3E the following WARNING is seen on entering suspend ...
[ 134.275704] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[ 134.285536] ------------[ cut here ]------------
[ 134.290298] i2c i2c-2: Transfer while suspended
[ 134.295174] WARNING: drivers/i2c/i2c-core.h:56 at __i2c_smbus_xfer+0x1e4/0x214, CPU#0: systemd-sleep/388
[ 134.365507] Tainted: [W]=WARN
[ 134.368485] Hardware name: Renesas SMARC EVK version 2 based on r9a09g047e57 (DT)
[ 134.375961] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 134.382935] pc : __i2c_smbus_xfer+0x1e4/0x214
[ 134.387329] lr : __i2c_smbus_xfer+0x1e4/0x214
[ 134.391717] sp : ffff800083f23860
[ 134.395040] x29: ffff800083f23860 x28: 0000000000000000 x27: ffff800082ed5d60
[ 134.402226] x26: 0000001f4395fd74 x25: 0000000000000007 x24: 0000000000000001
[ 134.409408] x23: 0000000000000000 x22: 000000000000006f x21: ffff800083f23936
[ 134.416589] x20: ffff0000c090e140 x19: ffff0000c090e0d0 x18: 0000000000000006
[ 134.423771] x17: 6f63657320313030 x16: 2e30206465737061 x15: ffff800083f23280
[ 134.430953] x14: 0000000000000000 x13: ffff800082b16ce8 x12: 0000000000000f09
[ 134.438134] x11: 0000000000000503 x10: ffff800082b6ece8 x9 : ffff800082b16ce8
[ 134.445315] x8 : 00000000ffffefff x7 : ffff800082b6ece8 x6 : 80000000fffff000
[ 134.452495] x5 : 0000000000000504 x4 : 0000000000000000 x3 : 0000000000000000
[ 134.459672] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0000c9ee9e80
[ 134.466851] Call trace:
[ 134.469311] __i2c_smbus_xfer+0x1e4/0x214 (P)
[ 134.473715] i2c_smbus_xfer+0xbc/0x120
[ 134.477507] i2c_smbus_read_byte_data+0x4c/0x84
[ 134.482077] isl1208_i2c_read_time+0x44/0x178 [rtc_isl1208]
[ 134.487703] isl1208_rtc_read_time+0x14/0x20 [rtc_isl1208]
[ 134.493226] __rtc_read_time+0x44/0x88
[ 134.497012] rtc_read_time+0x3c/0x68
[ 134.500622] rtc_suspend+0x9c/0x170
The warning is triggered because I2C transfers can still be attempted
while the controller is already suspended, due to inappropriate ordering
of the system sleep callbacks.
If the controller is autosuspended, there is no way to wake it up once
runtime PM disabled (in suspend_late()). During system resume, the I2C
controller will be available only after runtime PM is re-enabled
(in resume_early()). However, this may be too late for some devices.
Wake up the controller in the suspend() callback while runtime PM is
still enabled. The I2C controller will remain available until the
suspend_noirq() callback (pm_runtime_force_suspend()) is called. During
resume, the I2C controller can be restored by the resume_noirq() callback
(pm_runtime_force_resume()). Finally, the resume() callback re-enables
autosuspend. As a result, the I2C controller can remain available until
the system enters suspend_noirq() and from resume_noirq().
Cc: stable(a)vger.kernel.org
Fixes: 53326135d0e0 ("i2c: riic: Add suspend/resume support")
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr(a)bp.renesas.com>
---
v1->v2:
- Taking as reference commit:
4262df2a69c3 ("i2c: imx-lpi2c: make controller available until the system
enters suspend_noirq() and from resume_noirq().") reworked the patch with
a similar approach. Updated commit body accordingly.
drivers/i2c/busses/i2c-riic.c | 46 +++++++++++++++++++++++++++++------
1 file changed, 39 insertions(+), 7 deletions(-)
diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
index 3e8f126cb7f7..9e3595b3623e 100644
--- a/drivers/i2c/busses/i2c-riic.c
+++ b/drivers/i2c/busses/i2c-riic.c
@@ -670,12 +670,39 @@ static const struct riic_of_data riic_rz_t2h_info = {
static int riic_i2c_suspend(struct device *dev)
{
- struct riic_dev *riic = dev_get_drvdata(dev);
- int ret;
+ /*
+ * Some I2C devices may need the I2C controller to remain active
+ * during resume_noirq() or suspend_noirq(). If the controller is
+ * autosuspended, there is no way to wake it up once runtime PM is
+ * disabled (in suspend_late()).
+ *
+ * During system resume, the I2C controller will be available only
+ * after runtime PM is re-enabled (in resume_early()). However, this
+ * may be too late for some devices.
+ *
+ * Wake up the controller in the suspend() callback while runtime PM
+ * is still enabled. The I2C controller will remain available until
+ * the suspend_noirq() callback (pm_runtime_force_suspend()) is
+ * called. During resume, the I2C controller can be restored by the
+ * resume_noirq() callback (pm_runtime_force_resume()).
+ *
+ * Finally, the resume() callback re-enables autosuspend, ensuring
+ * the I2C controller remains available until the system enters
+ * suspend_noirq() and from resume_noirq().
+ */
+ return pm_runtime_resume_and_get(dev);
+}
- ret = pm_runtime_resume_and_get(dev);
- if (ret)
- return ret;
+static int riic_i2c_resume(struct device *dev)
+{
+ pm_runtime_put_autosuspend(dev);
+
+ return 0;
+}
+
+static int riic_i2c_suspend_noirq(struct device *dev)
+{
+ struct riic_dev *riic = dev_get_drvdata(dev);
i2c_mark_adapter_suspended(&riic->adapter);
@@ -683,12 +710,12 @@ static int riic_i2c_suspend(struct device *dev)
riic_clear_set_bit(riic, ICCR1_ICE, 0, RIIC_ICCR1);
pm_runtime_mark_last_busy(dev);
- pm_runtime_put_sync(dev);
+ pm_runtime_force_suspend(dev);
return reset_control_assert(riic->rstc);
}
-static int riic_i2c_resume(struct device *dev)
+static int riic_i2c_resume_noirq(struct device *dev)
{
struct riic_dev *riic = dev_get_drvdata(dev);
int ret;
@@ -697,6 +724,10 @@ static int riic_i2c_resume(struct device *dev)
if (ret)
return ret;
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
ret = riic_init_hw(riic);
if (ret) {
/*
@@ -714,6 +745,7 @@ static int riic_i2c_resume(struct device *dev)
}
static const struct dev_pm_ops riic_i2c_pm_ops = {
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(riic_i2c_suspend_noirq, riic_i2c_resume_noirq)
SYSTEM_SLEEP_PM_OPS(riic_i2c_suspend, riic_i2c_resume)
};
--
2.43.0