* [PATCH 7/7] drm/nova: use vertical import style
From: Guru Das Srinagesh @ 2026-06-29 3:38 UTC (permalink / raw)
To: Miguel Ojeda, rust-for-linux, linux-kernel
Cc: Danilo Krummrich, Abdiel Janulgue, Daniel Almeida, Robin Murphy,
Andreas Hindborg, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Drew Fustini, Guo Ren, Fu Wei,
Michal Wilczynski, Uwe Kleine-König, Rafael J. Wysocki,
Viresh Kumar, Jens Axboe, FUJITA Tomonori, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, David Airlie, Simona Vetter,
driver-core, linux-riscv, linux-pwm, linux-pm, linux-block,
netdev, nova-gpu, dri-devel, Guru Das Srinagesh
In-Reply-To: <20260628-b4-rust-vertical-imports-v1-0-98bc71d4810b@gurudas.dev>
Convert `use` imports to vertical layout for better readability and
maintainability.
Signed-off-by: Guru Das Srinagesh <linux@gurudas.dev>
---
drivers/gpu/drm/nova/file.rs | 5 ++++-
drivers/gpu/drm/nova/gem.rs | 6 +++++-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/nova/file.rs b/drivers/gpu/drm/nova/file.rs
index a3b7bd36792c..9a1404a7a687 100644
--- a/drivers/gpu/drm/nova/file.rs
+++ b/drivers/gpu/drm/nova/file.rs
@@ -4,7 +4,10 @@
use crate::gem::NovaObject;
use kernel::{
alloc::flags::*,
- drm::{self, gem::BaseObject},
+ drm::{
+ self,
+ gem::BaseObject, //
+ },
pci,
prelude::*,
uapi,
diff --git a/drivers/gpu/drm/nova/gem.rs b/drivers/gpu/drm/nova/gem.rs
index 9d8ff7de2c0f..f6bc7fdee732 100644
--- a/drivers/gpu/drm/nova/gem.rs
+++ b/drivers/gpu/drm/nova/gem.rs
@@ -2,7 +2,11 @@
use kernel::{
drm,
- drm::{gem, gem::BaseObject, DeviceContext},
+ drm::{
+ gem,
+ gem::BaseObject,
+ DeviceContext, //
+ },
page,
prelude::*,
sync::aref::ARef,
--
2.54.0
^ permalink raw reply related
* [PATCH 4/7] block: rnull: use vertical import style
From: Guru Das Srinagesh @ 2026-06-29 3:38 UTC (permalink / raw)
To: Miguel Ojeda, rust-for-linux, linux-kernel
Cc: Danilo Krummrich, Abdiel Janulgue, Daniel Almeida, Robin Murphy,
Andreas Hindborg, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Drew Fustini, Guo Ren, Fu Wei,
Michal Wilczynski, Uwe Kleine-König, Rafael J. Wysocki,
Viresh Kumar, Jens Axboe, FUJITA Tomonori, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, David Airlie, Simona Vetter,
driver-core, linux-riscv, linux-pwm, linux-pm, linux-block,
netdev, nova-gpu, dri-devel, Guru Das Srinagesh
In-Reply-To: <20260628-b4-rust-vertical-imports-v1-0-98bc71d4810b@gurudas.dev>
Convert `use` imports to vertical layout for better readability and
maintainability.
Signed-off-by: Guru Das Srinagesh <linux@gurudas.dev>
---
drivers/block/rnull/configfs.rs | 20 ++++++++++++++++----
drivers/block/rnull/rnull.rs | 13 ++++++++++---
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs
index 7c2eb5c0b722..07ce21a44081 100644
--- a/drivers/block/rnull/configfs.rs
+++ b/drivers/block/rnull/configfs.rs
@@ -2,14 +2,26 @@
use super::{NullBlkDevice, THIS_MODULE};
use kernel::{
- block::mq::gen_disk::{GenDisk, GenDiskBuilder},
- configfs::{self, AttributeOperations},
+ block::mq::gen_disk::{
+ GenDisk,
+ GenDiskBuilder, //
+ },
+ configfs::{
+ self,
+ AttributeOperations, //
+ },
configfs_attrs,
- fmt::{self, Write as _},
+ fmt::{
+ self,
+ Write as _, //
+ },
new_mutex,
page::PAGE_SIZE,
prelude::*,
- str::{kstrtobool_bytes, CString},
+ str::{
+ kstrtobool_bytes,
+ CString, //
+ },
sync::Mutex,
};
diff --git a/drivers/block/rnull/rnull.rs b/drivers/block/rnull/rnull.rs
index 0ca8715febe8..d58d2c4c5f63 100644
--- a/drivers/block/rnull/rnull.rs
+++ b/drivers/block/rnull/rnull.rs
@@ -10,12 +10,19 @@
self,
mq::{
self,
- gen_disk::{self, GenDisk},
- Operations, TagSet,
+ gen_disk::{
+ self,
+ GenDisk, //
+ },
+ Operations,
+ TagSet, //
},
},
prelude::*,
- sync::{aref::ARef, Arc},
+ sync::{
+ aref::ARef,
+ Arc, //
+ },
};
module! {
--
2.54.0
^ permalink raw reply related
* [PATCH 3/7] cpufreq: rcpufreq_dt: use vertical import style
From: Guru Das Srinagesh @ 2026-06-29 3:38 UTC (permalink / raw)
To: Miguel Ojeda, rust-for-linux, linux-kernel
Cc: Danilo Krummrich, Abdiel Janulgue, Daniel Almeida, Robin Murphy,
Andreas Hindborg, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Drew Fustini, Guo Ren, Fu Wei,
Michal Wilczynski, Uwe Kleine-König, Rafael J. Wysocki,
Viresh Kumar, Jens Axboe, FUJITA Tomonori, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, David Airlie, Simona Vetter,
driver-core, linux-riscv, linux-pwm, linux-pm, linux-block,
netdev, nova-gpu, dri-devel, Guru Das Srinagesh
In-Reply-To: <20260628-b4-rust-vertical-imports-v1-0-98bc71d4810b@gurudas.dev>
Convert `use` imports to vertical layout for better readability and
maintainability.
Signed-off-by: Guru Das Srinagesh <linux@gurudas.dev>
---
drivers/cpufreq/rcpufreq_dt.rs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs
index 10106fa13095..6f83cf8955a6 100644
--- a/drivers/cpufreq/rcpufreq_dt.rs
+++ b/drivers/cpufreq/rcpufreq_dt.rs
@@ -6,7 +6,10 @@
clk::Clk,
cpu, cpufreq,
cpumask::CpumaskVar,
- device::{Core, Device},
+ device::{
+ Core,
+ Device, //
+ },
error::code::*,
macros::vtable,
module_platform_driver, of, opp, platform,
--
2.54.0
^ permalink raw reply related
* [PATCH 2/7] pwm: th1520: use vertical import style
From: Guru Das Srinagesh @ 2026-06-29 3:38 UTC (permalink / raw)
To: Miguel Ojeda, rust-for-linux, linux-kernel
Cc: Danilo Krummrich, Abdiel Janulgue, Daniel Almeida, Robin Murphy,
Andreas Hindborg, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Drew Fustini, Guo Ren, Fu Wei,
Michal Wilczynski, Uwe Kleine-König, Rafael J. Wysocki,
Viresh Kumar, Jens Axboe, FUJITA Tomonori, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, David Airlie, Simona Vetter,
driver-core, linux-riscv, linux-pwm, linux-pm, linux-block,
netdev, nova-gpu, dri-devel, Guru Das Srinagesh
In-Reply-To: <20260628-b4-rust-vertical-imports-v1-0-98bc71d4810b@gurudas.dev>
Convert `use` imports to vertical layout for better readability and
maintainability.
Signed-off-by: Guru Das Srinagesh <linux@gurudas.dev>
---
drivers/pwm/pwm_th1520.rs | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs
index 3e3fa51ccef9..3e4524a1910b 100644
--- a/drivers/pwm/pwm_th1520.rs
+++ b/drivers/pwm/pwm_th1520.rs
@@ -23,7 +23,11 @@
use core::ops::Deref;
use kernel::{
clk::Clk,
- device::{Bound, Core, Device},
+ device::{
+ Bound,
+ Core,
+ Device, //
+ },
devres,
io::{
mem::IoMem,
--
2.54.0
^ permalink raw reply related
* [PATCH 0/7] rust: Use kernel style vertical imports in various drivers
From: Guru Das Srinagesh @ 2026-06-29 3:38 UTC (permalink / raw)
To: Miguel Ojeda, rust-for-linux, linux-kernel
Cc: Danilo Krummrich, Abdiel Janulgue, Daniel Almeida, Robin Murphy,
Andreas Hindborg, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Alice Ryhl, Trevor Gross, Tamir Duberstein,
Alexandre Courbot, Onur Özkan, Drew Fustini, Guo Ren, Fu Wei,
Michal Wilczynski, Uwe Kleine-König, Rafael J. Wysocki,
Viresh Kumar, Jens Axboe, FUJITA Tomonori, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, David Airlie, Simona Vetter,
driver-core, linux-riscv, linux-pwm, linux-pm, linux-block,
netdev, nova-gpu, dri-devel, Guru Das Srinagesh
Came across a recent commit bc58905eb07 ("samples: rust_misc_device: use
vertical import style") and found a few more locations that could
benefit from this cleanup. No functional changes.
Signed-off-by: Guru Das Srinagesh <linux@gurudas.dev>
---
Guru Das Srinagesh (7):
samples: rust_dma: use vertical import style
pwm: th1520: use vertical import style
cpufreq: rcpufreq_dt: use vertical import style
block: rnull: use vertical import style
net: phy: ax88796b: use vertical import style
net: phy: qt2025: use vertical import style
drm/nova: use vertical import style
drivers/block/rnull/configfs.rs | 20 ++++++++++++++++----
drivers/block/rnull/rnull.rs | 13 ++++++++++---
drivers/cpufreq/rcpufreq_dt.rs | 5 ++++-
drivers/gpu/drm/nova/file.rs | 5 ++++-
drivers/gpu/drm/nova/gem.rs | 6 +++++-
drivers/net/phy/ax88796b_rust.rs | 7 ++++++-
drivers/net/phy/qt2025.rs | 10 ++++++++--
drivers/pwm/pwm_th1520.rs | 6 +++++-
samples/rust/rust_dma.rs | 5 ++++-
9 files changed, 62 insertions(+), 15 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260628-b4-rust-vertical-imports-b46ee6c2479f
Best regards,
--
Guru Das Srinagesh <linux@gurudas.dev>
^ permalink raw reply
* Re: [PATCH v7] rust: aref: make `AlwaysRefCounted::inc_ref` an associated function
From: Viresh Kumar @ 2026-06-29 4:39 UTC (permalink / raw)
To: Trevor Chan
Cc: gregkh, rafael, dakr, ojeda, a.hindborg, paul, aliceryhl, airlied,
simona, viro, brauner, igor.korotin, vireshk, nm, sboyd,
m.wilczynski, boqun, gary, axboe, daniel.almeida, shankari.ak0208,
lyude, j, lossin, acourbot, markus.probst, driver-core,
rust-for-linux, linux-kernel, linux-block, linux-security-module,
dri-devel, linux-fsdevel, linux-mm, linux-pm, linux-pci,
linux-pwm, david.m.ertman, iweiny, leon, bjorn3_gh, tmgross,
tamird, work, sergeh, matthew.brost, thomas.hellstrom, jack, ljs,
liam, bhelgaas, kwilczynski, ptikhomirov
In-Reply-To: <20260628100731.64885-1-trev@trevrosa.dev>
On 28-06-26, 18:07, Trevor Chan wrote:
> diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs
> index 62e44676125d..84802f22b652 100644
> --- a/rust/kernel/opp.rs
> +++ b/rust/kernel/opp.rs
> @@ -1043,9 +1043,9 @@ unsafe impl Sync for OPP {}
> /// SAFETY: The type invariants guarantee that [`OPP`] is always refcounted.
> unsafe impl AlwaysRefCounted for OPP {
> #[inline]
> - fn inc_ref(&self) {
> + fn inc_ref(obj: &Self) {
> // SAFETY: The existence of a shared reference means that the refcount is nonzero.
> - unsafe { bindings::dev_pm_opp_get(self.0.get()) };
> + unsafe { bindings::dev_pm_opp_get(obj.0.get()) };
> }
>
> #[inline]
For OPP:
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* Re: [PATCH] nbd: don't warn when reclassifying a busy socket lock
From: Hillf Danton @ 2026-06-29 5:28 UTC (permalink / raw)
To: Eric Dumazet
Cc: Deepanshu Kartikey, linux-block, nbd, linux-kernel,
syzbot+6b85d1e39a5b8ed9a954
In-Reply-To: <CANn89iLPWCo_u-8jCsDM6jjZYfESvtUt9n3xD7yuAyNNntSw6w@mail.gmail.com>
On Mon, 22 Jun 2026 17:21:53 -0700 Eric Dumazet wrote:
>On Mon, Jun 22, 2026 at 5:07 PM Hillf Danton <hdanton@sina.com> wrote:
>> On Mon, 22 Jun 2026 01:18:10 -0700 Eric Dumazet wrote:
>> >On Sun, Jun 21, 2026 at 6:43 PM Hillf Danton <hdanton@sina.com> wrote:
>> >> On Mon, 22 Jun 2026 05:22:55 +0530 Deepanshu Kartikey wrote:
>> >> > nbd_reclassify_socket() warns via WARN_ON_ONCE() if the socket lock is
>> >> > held at the point of reclassification. That assertion was copied from
>> >> > nvme-tcp, where the socket is created internally by the kernel
>> >> > (sock_create_kern()) and is never visible to user space, so the lock
>> >> > is guaranteed to be free.
>> >> >
>> >> > NBD is different: the socket is looked up from a user-supplied fd in
>> >> > nbd_get_socket(), and user space retains that fd. A concurrent syscall
>> >> > on the same socket (or softirq processing taking bh_lock_sock() on a
>> >> > connected TCP socket) can legitimately hold the lock at the instant
>> >> > NBD reclassifies it. sock_allow_reclassification() then returns false
>> >> > and the WARN_ON_ONCE() fires, which turns into a crash under
>> >> > panic_on_warn. This is reachable by simply racing NBD_CMD_CONNECT
>> >> > against socket activity on the same fd, as reported by syzbot.
>> >> >
>> >> Given the syzbot report, if you are right (I suspect) then Eric delivered
>> >> another half-baked croissant, and feel free to cut it off instead to make
>> >> room for correct fix.
>> >
>> > Nobody (including you) caught this.difference between nbd and other
>> > sock_allow_reclassification() callers.
>> >
>> Nope, actually it raises the question -- does the deadlock still remain
>> after your fix without the lock key you added applied?
>
>LOCKDEP might have a false positive, but it will be much much harder to trigger.
>
>I had about 50 syzbot duplicates (that I did not release) before d532cddb6c60
> ("nbd: Reclassify sockets to avoid lockdep circular dependency").
>
>>
>> > What was the "correct fix" you envisioned exactly?
>> >
>> Frankly I had no evidence against your fix a couple days back, but now I
>> see your lock key approach fails to take off. And the correct fix is to
>> erase the incorrect locking order ffa1e7ada456 tries to catch, more
>> difficult than you thought so far.
>
>Which incorrect locking order are you referring to? This is a LOCKDEP
>false positive.
>
For archive purpose, syzbot report [1] where udp was not invovled defies
what is fixed in d532cddb6c60 ("nbd: Reclassify sockets to avoid lockdep
circular dependency") -- "Since the UDP socket and the NBD TCP/TLS socket
are different, this is a false positive."
[1] Subject: [syzbot] [net?] possible deadlock in inet_shutdown (3)
https://lore.kernel.org/lkml/69c37e6a.a70a0220.234938.0045.GAE@google.com/
^ permalink raw reply
* Re: [PATCH v2 2/4] blk-cgroup: fix race between policy activation and blkg destruction
From: Nilay Shroff @ 2026-06-29 5:33 UTC (permalink / raw)
To: yukuai, Tejun Heo, Josef Bacik, Jens Axboe
Cc: Zheng Qixing, Christoph Hellwig, Tang Yizhou, Ming Lei, cgroups,
linux-block, linux-kernel
In-Reply-To: <5f5a4729-0c90-4f6f-b97e-cab9d0289dc2@fygo.io>
On 6/27/26 9:43 AM, yu kuai wrote:
> Hi,
>
> 在 2026/6/26 14:12, Nilay Shroff 写道:
>> On 6/26/26 7:22 AM, yu kuai wrote:
>>> Hi,
>>>
>>> 在 2026/6/26 9:50, yu kuai 写道:
>>>> Hi,
>>>>
>>>> 在 2026/6/25 23:08, Nilay Shroff 写道:
>>>>> On 6/24/26 12:16 PM, Yu Kuai wrote:
>>>>>> diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
>>>>>> index 7baccfb690fe..f7e788a7fe95 100644
>>>>>> --- a/block/blk-cgroup.c
>>>>>> +++ b/block/blk-cgroup.c
>>>>>> @@ -1563,10 +1563,12 @@ int blkcg_activate_policy(struct gendisk
>>>>>> *disk, const struct blkcg_policy *pol)
>>>>>> if (WARN_ON_ONCE(!pol->pd_alloc_fn || !pol->pd_free_fn))
>>>>>> return -EINVAL;
>>>>>> if (queue_is_mq(q))
>>>>>> memflags = blk_mq_freeze_queue(q);
>>>>>> +
>>>>>> + mutex_lock(&q->blkcg_mutex);
>>>>>> retry:
>>>>>> spin_lock_irq(&q->queue_lock);
>>>>>> /* blkg_list is pushed at the head, reverse walk to
>>>>>> initialize parents first */
>>>>>> list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) {
>>>>>> @@ -1625,10 +1627,11 @@ int blkcg_activate_policy(struct gendisk
>>>>>> *disk, const struct blkcg_policy *pol)
>>>>>> __set_bit(pol->plid, q->blkcg_pols);
>>>>>> ret = 0;
>>>>>> spin_unlock_irq(&q->queue_lock);
>>>>>> out:
>>>>>> + mutex_unlock(&q->blkcg_mutex);
>>>>>> if (queue_is_mq(q))
>>>>>> blk_mq_unfreeze_queue(q, memflags);
>>>>>> if (pinned_blkg)
>>>>>> blkg_put(pinned_blkg);
>>>>>> if (pd_prealloc)
>>>>> If the policy allocation fails, we jump to the lable enomem: and
>>>>> teardown pds.
>>>>> But I see this path still only acquires ->queue_lock. Don't we also
>>>>> need
>>>>> to protect it with ->blkcg_mutex?
>>>> Yes, I agree we should protect it as well.
>>>
>>> Just take a closer look at the code, the enomem is already protected by
>>> blkcg_mutex :)
>>>
>>
>> Oh yes, but the ->blkcg_mutex is never released if we jump to enomem.
>> So that may potentially cause deadlock. We need to release ->blkcg_mutex
>> once blkcg_policy_teardown_pds() returns. Or may be refactor code (or add
>> comment) so that it's easy to realize or spot the ->blkcg_mutex is
>> acquired
>> and then released around blkcg_policy_teardown_pds().
>
> the enomem will goto out at last, and blkcg_mutex do released. The code is
> a bit hacky.
>
>>
>>>>
>>>>> Moreover I still see race between blkg insertion in blkg_create()
>>>>> which
>>>>> still doesn't use ->blkcg_mutex and so list traversal in
>>>>> bfq_end_wr_async()
>>>>> may still race with blkg_create(), isn't it? I remember you once told
>>>>> this will be handled in another series but I couldn't find that yet.
>>>> This is the set:
>>>>
>>>> [PATCH 0/8] blk-cgroup: remove queue_lock nesting from blkcg paths - Yu
>>>> Kuai <https://lore.kernel.org/all/cover.1780621988.git.yukuai@fygo.io/>
>>>>
>>>> Noted that set just make sure queue_lock is not nested under other
>>>> atomic
>>>> context, and that set do not acquire blkcg_mutex for blkg_create()
>>>> yet. Howerver,
>>>> with that set it'll be easy to convert all queue_lock to blkcg_mtuex
>>>> for blkg
>>>> protection, and together with lots of blk-cgroup code cleanups.
>>>>
>>
>> Okay, so are you planning to send a follow-up patchset that replaces
>> ->queue_lock
>> with ->blkcg_mutex for protecting the blkg_list? If so, I'd still
>> prefer acquiring
>> ->blkcg_mutex around blkg_create() in this patchset. That would
>> address the race
>> between blkg_create() and the blkg_list traversal in
>> bfq_end_wr_async(), while the
>> subsequent series can focus on cleaning up and removing the remaining
>> ->queue_lock
>> usage for blkg protection.
>
> Yes, there is a follow-up patchset. When this set was posted, blkg_create is still
> called with queue_lock held, so I can't do that. However, not that the other set
> is already applied, I can hold blkcg_mutex for blkg_create() now.
>
If you already have a follow-up patchset that replaces ->queue_lock with
->blkcg_mutex for protecting blkg_list, then I think it might make sense
to send that out first (if you haven't already) and hold off this series for
now. That way, the blkg_create() race can be addressed first, and this
series can build on top of those changes.
BTW, if that follow-up series is merged first, I suspect the first two patches in
this series may no longer be necessary, leaving only patches 3/4 and 4/4.
Thanks,
--Nilay
^ permalink raw reply
* [PATCH] nbd: fix circular lock dependency in nbd_reconnect_socket
From: Yun Zhou @ 2026-06-29 6:03 UTC (permalink / raw)
To: josef, axboe; +Cc: linux-block, nbd, linux-kernel, yun.zhou
Move sk_set_memalloc() out of the tx_lock critical section in
nbd_reconnect_socket() to break a circular lock dependency.
sk_set_memalloc() internally calls static_branch_inc() which acquires
cpu_hotplug_lock. When called under tx_lock, this creates the dependency:
tx_lock -> cpu_hotplug_lock
The lockdep splat shows the following circular chain:
cmd->lock -> tx_lock
from nbd_queue_rq() in the block I/O dispatch path.
tx_lock -> cpu_hotplug_lock
from nbd_reconnect_socket() calling sk_set_memalloc() under tx_lock.
cpu_hotplug_lock -> fs_reclaim -> q_usage_counter(io)
from create_worker() during CPU hotplug needing memory allocation,
which depends on block I/O completion to reclaim memory.
q_usage_counter(io) -> elevator_lock
from nbd_start_device() -> blk_mq_update_nr_hw_queues() ->
elevator_change() which freezes the queue then acquires elevator_lock.
elevator_lock -> set->srcu -> cmd->lock
from elevator_switch() -> blk_mq_quiesce_queue() waiting for srcu,
which waits for the I/O dispatch path holding cmd->lock.
Fix this by moving sk_set_memalloc() and sk_sndtimeo setup before the
tx_lock acquisition. This is safe because the new socket has not yet
been assigned to nsock->sock and is invisible to other code paths. In
the failure path (no dead connection found), sk_clear_memalloc() is
called to undo the setup before releasing the socket.
Fixes: b7aa3d39385d ("nbd: add a reconfigure netlink command")
Reported-by: syzbot+3dbc6142c85cc77eaf04@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=3dbc6142c85cc77eaf04
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
---
drivers/block/nbd.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 497f3bbe5795..c5d3ae8f5fc5 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -1392,6 +1392,14 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
return -ENOMEM;
}
+ /* Setup new socket properties before taking tx_lock to avoid
+ * circular dependency: tx_lock -> cpu_hotplug_lock (via
+ * sk_set_memalloc -> static_branch_inc).
+ */
+ sk_set_memalloc(sock->sk);
+ if (nbd->tag_set.timeout)
+ sock->sk->sk_sndtimeo = nbd->tag_set.timeout;
+
for (i = 0; i < config->num_connections; i++) {
struct nbd_sock *nsock = config->socks[i];
@@ -1403,9 +1411,6 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
mutex_unlock(&nsock->tx_lock);
continue;
}
- sk_set_memalloc(sock->sk);
- if (nbd->tag_set.timeout)
- sock->sk->sk_sndtimeo = nbd->tag_set.timeout;
atomic_inc(&config->recv_threads);
refcount_inc(&nbd->config_refs);
old = nsock->sock;
@@ -1433,6 +1438,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
wake_up(&config->conn_wait);
return 0;
}
+ sk_clear_memalloc(sock->sk);
sockfd_put(sock);
kfree(args);
return -ENOSPC;
--
2.43.0
^ permalink raw reply related
* [PATCH v2] block: partitions: Use seq_buf_putc() at 24 places
From: Markus Elfring @ 2026-06-29 7:16 UTC (permalink / raw)
To: linux-block, linux-efi, linux-ntfs-dev, linux-s390,
Andy Shevchenko, Christophe Jaillet, Davidlohr Bueso,
Jan Höppner, Jens Axboe, Josh Law, Kees Cook, Md Haris Iqbal,
Richard Russon, Stefan Haberland, Thorsten Blum, vulab
Cc: LKML, kernel-janitors, Steven Rostedt, Woradorn Laodhanadhaworn
In-Reply-To: <aj061omzs5WN5ar6@ashevche-desk.local>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Mon, 29 Jun 2026 08:10:24 +0200
Single line breaks should occasionally be put into a sequence buffer.
Thus use the seq_buf_putc() function in these implementations.
The source code was transformed by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
v2:
* Andy Shevchenko requested to preserve two blank lines.
* The source code transformation was extended to all affected places
for this software area.
block/partitions/acorn.c | 8 ++++----
block/partitions/amiga.c | 2 +-
block/partitions/atari.c | 2 +-
block/partitions/cmdline.c | 2 +-
block/partitions/efi.c | 2 +-
block/partitions/ibm.c | 10 +++++-----
block/partitions/karma.c | 2 +-
block/partitions/ldm.c | 2 +-
block/partitions/mac.c | 2 +-
block/partitions/msdos.c | 4 ++--
block/partitions/of.c | 2 +-
block/partitions/osf.c | 2 +-
block/partitions/sgi.c | 2 +-
block/partitions/sun.c | 2 +-
block/partitions/sysv68.c | 2 +-
block/partitions/ultrix.c | 2 +-
16 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/block/partitions/acorn.c b/block/partitions/acorn.c
index 067d6a27a3bd..c48250517448 100644
--- a/block/partitions/acorn.c
+++ b/block/partitions/acorn.c
@@ -290,7 +290,7 @@ int adfspart_check_ADFS(struct parsed_partitions *state)
break;
}
}
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
return 1;
}
#endif
@@ -397,7 +397,7 @@ int adfspart_check_ICS(struct parsed_partitions *state)
}
put_dev_sector(sect);
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
return 1;
}
#endif
@@ -468,7 +468,7 @@ int adfspart_check_POWERTEC(struct parsed_partitions *state)
}
put_dev_sector(sect);
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
return 1;
}
#endif
@@ -539,7 +539,7 @@ int adfspart_check_EESOX(struct parsed_partitions *state)
size = get_capacity(state->disk);
put_partition(state, slot++, start, size - start);
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
}
return i ? 1 : 0;
diff --git a/block/partitions/amiga.c b/block/partitions/amiga.c
index 8325046a14eb..a272f64450ec 100644
--- a/block/partitions/amiga.c
+++ b/block/partitions/amiga.c
@@ -194,7 +194,7 @@ int amiga_partition(struct parsed_partitions *state)
}
res = 1;
}
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
rdb_done:
return res;
diff --git a/block/partitions/atari.c b/block/partitions/atari.c
index 2438d1448f38..58863c1a2723 100644
--- a/block/partitions/atari.c
+++ b/block/partitions/atari.c
@@ -150,7 +150,7 @@ int atari_partition(struct parsed_partitions *state)
#endif
put_dev_sector(sect);
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
return 1;
}
diff --git a/block/partitions/cmdline.c b/block/partitions/cmdline.c
index 4fd52ed154b4..50075eccaade 100644
--- a/block/partitions/cmdline.c
+++ b/block/partitions/cmdline.c
@@ -377,7 +377,7 @@ int cmdline_partition(struct parsed_partitions *state)
cmdline_parts_set(parts, disk_size, state);
cmdline_parts_verifier(1, state);
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
return 1;
}
diff --git a/block/partitions/efi.c b/block/partitions/efi.c
index 9865d59093fa..650b91efc832 100644
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -751,6 +751,6 @@ int efi_partition(struct parsed_partitions *state)
}
kfree(ptes);
kfree(gpt);
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
return 1;
}
diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c
index 54047e722a9d..a57de3b192fc 100644
--- a/block/partitions/ibm.c
+++ b/block/partitions/ibm.c
@@ -217,7 +217,7 @@ static int find_vol1_partitions(struct parsed_partitions *state,
blk++;
data = read_part_sector(state, blk * secperblk, §);
}
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
if (!data)
return -1;
@@ -254,7 +254,7 @@ static int find_lnx1_partitions(struct parsed_partitions *state,
size = nr_sectors;
if (size != geo_size) {
if (!info) {
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
return 1;
}
if (!strcmp(info->type, "ECKD"))
@@ -266,7 +266,7 @@ static int find_lnx1_partitions(struct parsed_partitions *state,
/* first and only partition starts in the first block after the label */
offset = labelsect + secperblk;
put_partition(state, 1, offset, size - offset);
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
return 1;
}
@@ -307,7 +307,7 @@ static int find_cms1_partitions(struct parsed_partitions *state,
}
put_partition(state, 1, offset, size-offset);
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
return 1;
}
@@ -388,7 +388,7 @@ int ibm_partition(struct parsed_partitions *state)
size = nr_sectors;
offset = (info->label_block + 1) * (blocksize >> 9);
put_partition(state, 1, offset, size-offset);
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
}
} else
res = 0;
diff --git a/block/partitions/karma.c b/block/partitions/karma.c
index a4e3c5050177..b0ab84169538 100644
--- a/block/partitions/karma.c
+++ b/block/partitions/karma.c
@@ -53,7 +53,7 @@ int karma_partition(struct parsed_partitions *state)
}
slot++;
}
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
put_dev_sector(sect);
return 1;
}
diff --git a/block/partitions/ldm.c b/block/partitions/ldm.c
index c0bdcae58a3e..d1bbc9fb09f9 100644
--- a/block/partitions/ldm.c
+++ b/block/partitions/ldm.c
@@ -597,7 +597,7 @@ static bool ldm_create_data_partitions (struct parsed_partitions *pp,
part_num++;
}
- seq_buf_puts(&pp->pp_buf, "\n");
+ seq_buf_putc(&pp->pp_buf, '\n');
return true;
}
diff --git a/block/partitions/mac.c b/block/partitions/mac.c
index df03ca428e15..bb570b5a6eaa 100644
--- a/block/partitions/mac.c
+++ b/block/partitions/mac.c
@@ -152,6 +152,6 @@ int mac_partition(struct parsed_partitions *state)
#endif
put_dev_sector(sect);
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
return 1;
}
diff --git a/block/partitions/msdos.c b/block/partitions/msdos.c
index 200ea53ea6a2..4a96541f5351 100644
--- a/block/partitions/msdos.c
+++ b/block/partitions/msdos.c
@@ -608,7 +608,7 @@ int msdos_partition(struct parsed_partitions *state)
fb = (struct fat_boot_sector *) data;
if (slot == 1 && fb->reserved && fb->fats
&& fat_valid_media(fb->media)) {
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
put_dev_sector(sect);
return 1;
} else {
@@ -672,7 +672,7 @@ int msdos_partition(struct parsed_partitions *state)
seq_buf_puts(&state->pp_buf, "[EZD]");
}
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
/* second pass - output for each on a separate line */
p = (struct msdos_partition *) (0x1be + data);
diff --git a/block/partitions/of.c b/block/partitions/of.c
index 53664ea06b65..7803e6f4ecdd 100644
--- a/block/partitions/of.c
+++ b/block/partitions/of.c
@@ -104,7 +104,7 @@ int of_partition(struct parsed_partitions *state)
slot++;
}
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
of_node_put(partitions_np);
return 1;
diff --git a/block/partitions/osf.c b/block/partitions/osf.c
index 2a692584dba9..6f83d4759a5d 100644
--- a/block/partitions/osf.c
+++ b/block/partitions/osf.c
@@ -81,7 +81,7 @@ int osf_partition(struct parsed_partitions *state)
le32_to_cpu(partition->p_size));
slot++;
}
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
put_dev_sector(sect);
return 1;
}
diff --git a/block/partitions/sgi.c b/block/partitions/sgi.c
index 2383ca63cd66..f743e3583417 100644
--- a/block/partitions/sgi.c
+++ b/block/partitions/sgi.c
@@ -79,7 +79,7 @@ int sgi_partition(struct parsed_partitions *state)
}
slot++;
}
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
put_dev_sector(sect);
return 1;
}
diff --git a/block/partitions/sun.c b/block/partitions/sun.c
index 92c645fcd2e0..c71bad78f34a 100644
--- a/block/partitions/sun.c
+++ b/block/partitions/sun.c
@@ -121,7 +121,7 @@ int sun_partition(struct parsed_partitions *state)
}
slot++;
}
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
put_dev_sector(sect);
return 1;
}
diff --git a/block/partitions/sysv68.c b/block/partitions/sysv68.c
index 470e0f9de7be..31d348ac2dfb 100644
--- a/block/partitions/sysv68.c
+++ b/block/partitions/sysv68.c
@@ -86,7 +86,7 @@ int sysv68_partition(struct parsed_partitions *state)
}
slot++;
}
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
put_dev_sector(sect);
return 1;
}
diff --git a/block/partitions/ultrix.c b/block/partitions/ultrix.c
index b4b9ddc57a5d..8ac42fda25d1 100644
--- a/block/partitions/ultrix.c
+++ b/block/partitions/ultrix.c
@@ -39,7 +39,7 @@ int ultrix_partition(struct parsed_partitions *state)
label->pt_part[i].pi_blkoff,
label->pt_part[i].pi_nblocks);
put_dev_sector(sect);
- seq_buf_puts(&state->pp_buf, "\n");
+ seq_buf_putc(&state->pp_buf, '\n');
return 1;
} else {
put_dev_sector(sect);
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v2] block: partitions: Use seq_buf_putc() at 24 places
From: Andy Shevchenko @ 2026-06-29 7:35 UTC (permalink / raw)
To: Markus Elfring
Cc: linux-block, linux-efi, linux-ntfs-dev, linux-s390,
Christophe Jaillet, Davidlohr Bueso, Jan Höppner, Jens Axboe,
Josh Law, Kees Cook, Md Haris Iqbal, Richard Russon,
Stefan Haberland, Thorsten Blum, vulab, LKML, kernel-janitors,
Steven Rostedt, Woradorn Laodhanadhaworn
In-Reply-To: <7360cab3-7a2f-4903-85f1-0f03387b0d88@web.de>
On Mon, Jun 29, 2026 at 09:16:09AM +0200, Markus Elfring wrote:
> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Mon, 29 Jun 2026 08:10:24 +0200
>
> Single line breaks should occasionally be put into a sequence buffer.
> Thus use the seq_buf_putc() function in these implementations.
>
> The source code was transformed by using the Coccinelle software.
>
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
> ---
>
> v2:
> * Andy Shevchenko requested to preserve two blank lines.
This comment in the context of the given commit message may be odd.
The blank lines mentioned were in the code that previous coccinelle
script removed, id est the code
...blank line...
seq_buf_puts()
...blank line...
the script transformed to a single line
seq_buf_putc()
So my request is to keep the original blank line(s) as is.
> * The source code transformation was extended to all affected places
> for this software area.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH v6 0/9] Support for block device NVMEM providers
From: Loic Poulain @ 2026-06-29 8:55 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, Christian Marangi
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-msm, linux-block,
linux-wireless, ath10k, linux-bluetooth, netdev, daniel,
Loic Poulain, stable, Bartosz Golaszewski, Krzysztof Kozlowski,
Konrad Dybcio
On embedded devices, it is common for factory provisioning to store
device-specific information, such as Ethernet or WiFi MAC addresses,
in a dedicated area of an eMMC partition. This avoids the need for
and additional EEPROM/OTP and leverages the persistence of eMMC.
One example is the Arduino UNO-Q, where the WiFi MAC address and the
Bluetooth Device address are stored in the eMMC Boot1 partition.
Until now, accessing this information required a custom bootloader
to read the data and inject it into the Device Tree before handing
control over to the kernel. This approach is fragile and leads to
device-specific workarounds.
Rather than adding a new NVMEM provider specifically to the eMMC
subsystem, the new support operates at the block layer, allowing any
block device to behave like other non-volatile memories such as EEPROM
or OTP.
This series builds on earlier work by Daniel Golle that enables block
devices to act as NVMEM providers:
https://lore.kernel.org/all/6061aa4201030b9bb2f8d03ef32a564fdb786ed1.1709667858.git.daniel@makrotopia.org/
It also introduces an NVMEM layout description for the Arduino UNO-Q,
allowing device-specific data stored in the eMMC Boot1 partition to
be accessed in a standard way.
WiFi and Ethernet already support retrieving MAC addresses from NVMEM.
Bluetooth requires similar support, which is also addressed.
Note that this is currently limited to MMC-backed block devices, as
only the MMC core associates a firmware node with the block device
(add_disk_fwnode). This can be easily extended in the future to
support additional block drivers.
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
Changes in v6:
- blk_nvmem_add() returns int, error properly propagated (Bartosz)
- Redundant if (bdev->bd_nvmem) guard removed in blk_nvmem_del() (Bartosz)
- Size guard changed from UINT_MAX → INT_MAX to avoid signed overflow in config.size (sashiko)
- BLK_OPEN_RESTRICT_WRITES removed from blk_nvmem_reg_read() (sashiko)
- Link to v5: https://lore.kernel.org/r/20260612-block-as-nvmem-v5-0-95e0b30fff90@oss.qualcomm.com
Changes in v5:
- Fixed ath10k binding issue + extended commit message (Krzysztof)
- Moved blk-nvmem handling to block core instead of a class_interface
This allows correct/robust integration with block device life cycle (Bartosz).
- block: partitions: of: Skip child nodes without reg property (sashiko)
- Link to v4: https://lore.kernel.org/r/20260609-block-as-nvmem-v4-0-45712e6b22c6@oss.qualcomm.com
Changes in v4:
- Fix squash issue (dts commit incorrectly squashed) (Konrad)
- Use devres for nvmem resources (Bartosz)
- use __free() destructor helper when possible (Bartosz)
- Fix value return checking for bdev_file_open_by_dev
- Link to v3: https://lore.kernel.org/r/20260608-block-as-nvmem-v3-0-82681f50aa35@oss.qualcomm.com
Changes in v3:
- Fixed missing 'fixed-partitions' compatible in partition (Rob)
- Fixed clashing nvmem cells, document calibration along mac (Sashiko)
- Remove workaround to handle dangling nvmem references after
unregistering, this is a generic nvmem framework issue handled
in Bartosz's series:
https://lore.kernel.org/all/20260429-nvmem-unbind-v3-0-2a694f95395b@oss.qualcomm.com/
- Validate mac (is_valid_ether_addr) before copying to output buffer
- Link to v2: https://lore.kernel.org/r/20260507-block-as-nvmem-v2-0-bf17edd5134e@oss.qualcomm.com
Changes in v2:
- Fix example nvmem-layout cells to use compatible = "mac-base"
- Squash WiFi MAC and Bluetooth BD address consumer patches into the nvmem layout patch
- Fix possible use-after-free in blk-nvmem: bnv (nvmem priv) linked to nvmem lifetime
- Simplify nvmem-cell-names from items: - const: to plain const:
- Factor out common NVMEM EUI-48 retrieval logic
- Reorder changes
- Link to v1: https://lore.kernel.org/r/20260428-block-as-nvmem-v1-0-6ad23e75190a@oss.qualcomm.com
---
Daniel Golle (1):
block: implement NVMEM provider
Loic Poulain (8):
block: partitions: of: Skip child nodes without reg property
dt-bindings: mmc: Document support for nvmem-layout
dt-bindings: net: wireless: qcom,ath10k: Document NVMEM cells
dt-bindings: bluetooth: qcom: Add NVMEM BD address cell
net: of_net: Add of_get_nvmem_eui48() helper for EUI-48 lookup
Bluetooth: hci_sync: Add NVMEM-backed BD address retrieval
Bluetooth: qca: Set NVMEM BD address quirks when address is invalid
arm64: dts: qcom: arduino-imola: Describe NVMEM layout for WiFi/BT addresses
.../devicetree/bindings/mmc/mmc-card.yaml | 29 ++++++
.../net/bluetooth/qcom,bluetooth-common.yaml | 9 ++
.../bindings/net/wireless/qcom,ath10k.yaml | 16 +++
arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts | 39 ++++++++
block/Kconfig | 9 ++
block/Makefile | 1 +
block/blk-nvmem.c | 111 +++++++++++++++++++++
block/blk.h | 8 ++
block/genhd.c | 4 +
block/partitions/of.c | 20 ++--
drivers/bluetooth/btqca.c | 5 +-
include/linux/blk_types.h | 3 +
include/linux/blkdev.h | 1 +
include/linux/of_net.h | 7 ++
include/net/bluetooth/hci.h | 18 ++++
net/bluetooth/hci_sync.c | 39 +++++++-
net/core/of_net.c | 49 ++++++---
17 files changed, 347 insertions(+), 21 deletions(-)
---
base-commit: 47c4835fc0fed583d01d90387b67633950eba2b2
change-id: 20260428-block-as-nvmem-4b308e8bda9a
Best regards,
--
Loic Poulain <loic.poulain@oss.qualcomm.com>
^ permalink raw reply
* [PATCH v6 1/9] block: partitions: of: Skip child nodes without reg property
From: Loic Poulain @ 2026-06-29 8:55 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, Christian Marangi
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-msm, linux-block,
linux-wireless, ath10k, linux-bluetooth, netdev, daniel,
Loic Poulain, stable, Bartosz Golaszewski
In-Reply-To: <20260629-block-as-nvmem-v6-0-f02513dcd46d@oss.qualcomm.com>
Child nodes of a fixed-partitions node are not necessarily partition
entries, for example an nvmem-layout node has no reg property. The
current code passes a NULL reg pointer and uninitialized len to the
length check, which can result in a kernel panic or silent failure to
register any partitions.
Fix validate_of_partition() to return a skip indicator when no reg
property is present. Guard add_of_partition() with a reg property
check for the same reason.
Fixes: 2e3a191e89f9 ("block: add support for partition table defined in OF")
Cc: stable@vger.kernel.org
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
block/partitions/of.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/block/partitions/of.c b/block/partitions/of.c
index c22b6066109819c71568f73e8db8833d196b1cf6..534e02a9d85f62611d880af9b302d9fd49aa4d46 100644
--- a/block/partitions/of.c
+++ b/block/partitions/of.c
@@ -15,6 +15,10 @@ static int validate_of_partition(struct device_node *np, int slot)
int a_cells = of_n_addr_cells(np);
int s_cells = of_n_size_cells(np);
+ /* Skip nodes without a reg property (e.g. nvmem-layout) */
+ if (!reg)
+ return 1;
+
/* Make sure reg len match the expected addr and size cells */
if (len / sizeof(*reg) != a_cells + s_cells)
return -EINVAL;
@@ -80,14 +84,15 @@ int of_partition(struct parsed_partitions *state)
slot = 1;
/* Validate parition offset and size */
for_each_child_of_node(partitions_np, np) {
- if (validate_of_partition(np, slot)) {
+ int err = validate_of_partition(np, slot);
+
+ if (err < 0) {
of_node_put(np);
of_node_put(partitions_np);
-
return -1;
}
-
- slot++;
+ if (!err)
+ slot++;
}
slot = 1;
@@ -97,9 +102,10 @@ int of_partition(struct parsed_partitions *state)
break;
}
- add_of_partition(state, slot, np);
-
- slot++;
+ if (of_property_present(np, "reg")) {
+ add_of_partition(state, slot, np);
+ slot++;
+ }
}
seq_buf_puts(&state->pp_buf, "\n");
--
2.34.1
^ permalink raw reply related
* [PATCH v6 2/9] dt-bindings: mmc: Document support for nvmem-layout
From: Loic Poulain @ 2026-06-29 8:55 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, Christian Marangi
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-msm, linux-block,
linux-wireless, ath10k, linux-bluetooth, netdev, daniel,
Loic Poulain, Bartosz Golaszewski
In-Reply-To: <20260629-block-as-nvmem-v6-0-f02513dcd46d@oss.qualcomm.com>
Add support for an nvmem-layout subnode under an eMMC hardware
partition. This allows the partition to be exposed as an NVMEM
provider and its internal layout to be described. For example,
an eMMC boot partition can be used to store device-specific
information such as a WiFi MAC address.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
.../devicetree/bindings/mmc/mmc-card.yaml | 29 ++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/Documentation/devicetree/bindings/mmc/mmc-card.yaml b/Documentation/devicetree/bindings/mmc/mmc-card.yaml
index a61d6c96df759102f9c1fbfd548b026a77921cae..ca907ad73095925b234b119948f94ae81e698c86 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-card.yaml
+++ b/Documentation/devicetree/bindings/mmc/mmc-card.yaml
@@ -40,6 +40,9 @@ patternProperties:
contains:
const: fixed-partitions
+ nvmem-layout:
+ $ref: /schemas/nvmem/layouts/nvmem-layout.yaml
+
required:
- compatible
- reg
@@ -86,6 +89,32 @@ examples:
read-only;
};
};
+
+ partitions-boot2 {
+ compatible = "fixed-partitions";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ nvmem-layout {
+ compatible = "fixed-layout";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mac-addr@4400 {
+ compatible = "mac-base";
+ reg = <0x4400 0x6>;
+ #nvmem-cell-cells = <1>;
+ };
+
+ bd-addr@5400 {
+ compatible = "mac-base";
+ reg = <0x5400 0x6>;
+ #nvmem-cell-cells = <1>;
+ };
+ };
+ };
};
};
--
2.34.1
^ permalink raw reply related
* [PATCH v6 3/9] dt-bindings: net: wireless: qcom,ath10k: Document NVMEM cells
From: Loic Poulain @ 2026-06-29 8:55 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, Christian Marangi
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-msm, linux-block,
linux-wireless, ath10k, linux-bluetooth, netdev, daniel,
Loic Poulain, Bartosz Golaszewski, Krzysztof Kozlowski
In-Reply-To: <20260629-block-as-nvmem-v6-0-f02513dcd46d@oss.qualcomm.com>
Document the NVMEM cells supported by the ath10k driver, the
mac-address, pre-calibration data, and calibration data.
Since such data may also originate from chipset OTP or be supplied
via other device tree structures. All of these cells are optional
and can be provided independently, in any combination.
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
.../devicetree/bindings/net/wireless/qcom,ath10k.yaml | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
index c21d66c7cd558ab792524be9afec8b79272d1c87..878c5d833a9cb073520c256c1b72d0f1489e7f4a 100644
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
@@ -92,6 +92,22 @@ properties:
ieee80211-freq-limit: true
+ nvmem-cells:
+ minItems: 1
+ maxItems: 3
+ description:
+ References to nvmem cells for MAC address and/or calibration data.
+ Supported cell names are mac-address, calibration, and pre-calibration.
+
+ nvmem-cell-names:
+ minItems: 1
+ maxItems: 3
+ items:
+ enum:
+ - mac-address
+ - calibration
+ - pre-calibration
+
qcom,calibration-data:
$ref: /schemas/types.yaml#/definitions/uint8-array
description:
--
2.34.1
^ permalink raw reply related
* [PATCH v6 4/9] dt-bindings: bluetooth: qcom: Add NVMEM BD address cell
From: Loic Poulain @ 2026-06-29 8:55 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, Christian Marangi
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-msm, linux-block,
linux-wireless, ath10k, linux-bluetooth, netdev, daniel,
Loic Poulain, Bartosz Golaszewski
In-Reply-To: <20260629-block-as-nvmem-v6-0-f02513dcd46d@oss.qualcomm.com>
Add support for an NVMEM cell provider for "local-bd-address",
allowing the Bluetooth stack to retrieve controller's BD address
from non-volatile storage such as an EEPROM or an eMMC partition.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
.../devicetree/bindings/net/bluetooth/qcom,bluetooth-common.yaml | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/bluetooth/qcom,bluetooth-common.yaml b/Documentation/devicetree/bindings/net/bluetooth/qcom,bluetooth-common.yaml
index c8e9c55c1afb4c8e05ba2dae41ce2db4194b4a0f..7cb28f30c9af032082f23311f2fc89a32f266f17 100644
--- a/Documentation/devicetree/bindings/net/bluetooth/qcom,bluetooth-common.yaml
+++ b/Documentation/devicetree/bindings/net/bluetooth/qcom,bluetooth-common.yaml
@@ -22,4 +22,13 @@ properties:
description:
boot firmware is incorrectly passing the address in big-endian order
+ nvmem-cells:
+ maxItems: 1
+ description:
+ Nvmem data cell that contains a 6 byte BD address with the most
+ significant byte first (big-endian).
+
+ nvmem-cell-names:
+ const: local-bd-address
+
additionalProperties: true
--
2.34.1
^ permalink raw reply related
* [PATCH v6 5/9] block: implement NVMEM provider
From: Loic Poulain @ 2026-06-29 8:55 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, Christian Marangi
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-msm, linux-block,
linux-wireless, ath10k, linux-bluetooth, netdev, daniel,
Loic Poulain
In-Reply-To: <20260629-block-as-nvmem-v6-0-f02513dcd46d@oss.qualcomm.com>
From: Daniel Golle <daniel@makrotopia.org>
On embedded devices using an eMMC it is common that one or more partitions
on the eMMC are used to store MAC addresses and Wi-Fi calibration EEPROM
data. Allow referencing the partition in device tree for the kernel and
Wi-Fi drivers accessing it via the NVMEM layer.
For now, NVMEM is only registered for the whole disk block device, as the
OF node is currently only associated to it.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Co-developed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
block/Kconfig | 9 ++++
block/Makefile | 1 +
block/blk-nvmem.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++
block/blk.h | 8 ++++
block/genhd.c | 4 ++
include/linux/blk_types.h | 3 ++
include/linux/blkdev.h | 1 +
7 files changed, 137 insertions(+)
diff --git a/block/Kconfig b/block/Kconfig
index 15027963472d7b40e27b9097a5993c457b5b3054..0b33747e16dc33473683706f75c92bdf8b648f7c 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -209,6 +209,15 @@ config BLK_INLINE_ENCRYPTION_FALLBACK
by falling back to the kernel crypto API when inline
encryption hardware is not present.
+config BLK_NVMEM
+ bool "Block device NVMEM provider"
+ depends on OF
+ depends on NVMEM
+ help
+ Allow block devices (or partitions) to act as NVMEM providers,
+ typically used with eMMC to store MAC addresses or Wi-Fi
+ calibration data on embedded devices.
+
source "block/partitions/Kconfig"
config BLK_PM
diff --git a/block/Makefile b/block/Makefile
index 7dce2e44276c4274c11a0a61121c83d9c43d6e0c..d7ac389e71902bc091a8800ea266190a43b3e63d 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -36,3 +36,4 @@ obj-$(CONFIG_BLK_INLINE_ENCRYPTION) += blk-crypto.o blk-crypto-profile.o \
blk-crypto-sysfs.o
obj-$(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) += blk-crypto-fallback.o
obj-$(CONFIG_BLOCK_HOLDER_DEPRECATED) += holder.o
+obj-$(CONFIG_BLK_NVMEM) += blk-nvmem.o
diff --git a/block/blk-nvmem.c b/block/blk-nvmem.c
new file mode 100644
index 0000000000000000000000000000000000000000..4b35a74255059320ef0cbd3c0003f1510bae5733
--- /dev/null
+++ b/block/blk-nvmem.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * block device NVMEM provider
+ *
+ * Copyright (c) 2024 Daniel Golle <daniel@makrotopia.org>
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * Useful on devices using a partition on an eMMC for MAC addresses or
+ * Wi-Fi calibration EEPROM data.
+ */
+
+#include <linux/file.h>
+#include <linux/nvmem-provider.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/pagemap.h>
+#include <linux/property.h>
+
+#include "blk.h"
+
+static int blk_nvmem_reg_read(void *priv, unsigned int from, void *val, size_t bytes)
+{
+ dev_t devt = (dev_t)(uintptr_t)priv;
+ size_t bytes_left = bytes;
+ loff_t pos = from;
+ int ret = 0;
+
+ struct file *bdev_file __free(fput) =
+ bdev_file_open_by_dev(devt, BLK_OPEN_READ, NULL, NULL);
+ if (IS_ERR(bdev_file))
+ return PTR_ERR(bdev_file);
+
+ while (bytes_left) {
+ pgoff_t f_index = pos >> PAGE_SHIFT;
+ struct folio *folio;
+ size_t folio_off;
+ size_t to_read;
+
+ folio = read_mapping_folio(bdev_file->f_mapping, f_index, NULL);
+ if (IS_ERR(folio)) {
+ ret = PTR_ERR(folio);
+ break;
+ }
+
+ folio_off = offset_in_folio(folio, pos);
+ to_read = min(bytes_left, folio_size(folio) - folio_off);
+ memcpy_from_folio(val, folio, folio_off, to_read);
+ pos += to_read;
+ bytes_left -= to_read;
+ val += to_read;
+ folio_put(folio);
+ }
+
+ return ret;
+}
+
+int blk_nvmem_add(struct block_device *bdev)
+{
+ struct device *dev = &bdev->bd_device;
+ struct nvmem_config config = {};
+
+ /* skip devices which do not have a device tree node */
+ if (!dev_of_node(dev))
+ return 0;
+
+ /* skip devices without an nvmem layout defined */
+ struct device_node *child __free(device_node) =
+ of_get_child_by_name(dev_of_node(dev), "nvmem-layout");
+ if (!child)
+ return 0;
+
+ /*
+ * skip block device too large to be represented as NVMEM devices,
+ * nvmem_config.size is a signed int
+ */
+ if (bdev_nr_bytes(bdev) > INT_MAX) {
+ dev_warn(dev, "block device too large to be an NVMEM provider\n");
+ return 0;
+ }
+
+ config.id = NVMEM_DEVID_NONE;
+ config.dev = dev;
+ config.name = dev_name(dev);
+ config.owner = THIS_MODULE;
+ config.priv = (void *)(uintptr_t)dev->devt;
+ config.reg_read = blk_nvmem_reg_read;
+ config.size = bdev_nr_bytes(bdev);
+ config.word_size = 1;
+ config.stride = 1;
+ config.read_only = true;
+ config.root_only = true;
+ config.ignore_wp = true;
+ config.of_node = to_of_node(dev->fwnode);
+
+ bdev->bd_nvmem = nvmem_register(&config);
+ if (IS_ERR(bdev->bd_nvmem)) {
+ int ret = PTR_ERR(bdev->bd_nvmem);
+
+ bdev->bd_nvmem = NULL;
+ dev_err_probe(dev, ret, "Failed to register NVMEM device\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+void blk_nvmem_del(struct block_device *bdev)
+{
+ nvmem_unregister(bdev->bd_nvmem);
+ bdev->bd_nvmem = NULL;
+}
diff --git a/block/blk.h b/block/blk.h
index ec4674cdf2ead4fd259ff5fc42401f591e684ee9..ed0c10168ba7be10855509637f824a9cea2b9ccb 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -757,4 +757,12 @@ static inline void blk_debugfs_unlock(struct request_queue *q,
memalloc_noio_restore(memflags);
}
+#ifdef CONFIG_BLK_NVMEM
+int blk_nvmem_add(struct block_device *bdev);
+void blk_nvmem_del(struct block_device *bdev);
+#else
+static inline int blk_nvmem_add(struct block_device *bdev) { return 0; }
+static inline void blk_nvmem_del(struct block_device *bdev) {}
+#endif
+
#endif /* BLK_INTERNAL_H */
diff --git a/block/genhd.c b/block/genhd.c
index 7d6854fd28e95ae9134309679a7c6a937f5b7db8..1b2382de6fb30c1e5f60f45c04dc03ed3bf5d5f2 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -421,6 +421,8 @@ static void add_disk_final(struct gendisk *disk)
*/
dev_set_uevent_suppress(ddev, 0);
disk_uevent(disk, KOBJ_ADD);
+
+ blk_nvmem_add(disk->part0);
}
blk_apply_bdi_limits(disk->bdi, &disk->queue->limits);
@@ -704,6 +706,8 @@ static void __del_gendisk(struct gendisk *disk)
disk_del_events(disk);
+ blk_nvmem_del(disk->part0);
+
/*
* Prevent new openers by unlinked the bdev inode.
*/
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 8808ee76e73c09e0ceaac41ba59e86fb0c4efc64..ace6f59b860d0813665b2f62a1c03a1f4be94059 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -73,6 +73,9 @@ struct block_device {
int bd_writers;
#ifdef CONFIG_SECURITY
void *bd_security;
+#endif
+#ifdef CONFIG_BLK_NVMEM
+ struct nvmem_device *bd_nvmem;
#endif
/*
* keep this out-of-line as it's both big and not needed in the fast
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 890128cdea1ce66863c5baa36f3b336ec4550807..f15d2b5bf9e4fd2368b8a70416a978e22c0d4333 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -30,6 +30,7 @@
struct module;
struct request_queue;
+struct nvmem_device;
struct elevator_queue;
struct blk_trace;
struct request;
--
2.34.1
^ permalink raw reply related
* [PATCH v6 6/9] net: of_net: Add of_get_nvmem_eui48() helper for EUI-48 lookup
From: Loic Poulain @ 2026-06-29 8:55 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, Christian Marangi
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-msm, linux-block,
linux-wireless, ath10k, linux-bluetooth, netdev, daniel,
Loic Poulain, Bartosz Golaszewski
In-Reply-To: <20260629-block-as-nvmem-v6-0-f02513dcd46d@oss.qualcomm.com>
Factor out the common NVMEM EUI-48 retrieval logic from
of_get_mac_address_nvmem() into a new of_get_nvmem_eui48() helper that
accepts the NVMEM cell name as a parameter. This allows other subsystems
(e.g. Bluetooth) to reuse the same lookup-validate-copy pattern with a
different cell name, without duplicating code.
of_get_mac_address_nvmem() is updated to call of_get_nvmem_eui48() with
"mac-address", preserving its existing behavior.
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
include/linux/of_net.h | 7 +++++++
net/core/of_net.c | 49 +++++++++++++++++++++++++++++++++++++------------
2 files changed, 44 insertions(+), 12 deletions(-)
diff --git a/include/linux/of_net.h b/include/linux/of_net.h
index d88715a0b3a52f87af23d47791bea3baf5be5200..7854ba555d9a55f3d020a37fe00a27ae52e0e5dc 100644
--- a/include/linux/of_net.h
+++ b/include/linux/of_net.h
@@ -15,6 +15,7 @@ struct net_device;
extern int of_get_phy_mode(struct device_node *np, phy_interface_t *interface);
extern int of_get_mac_address(struct device_node *np, u8 *mac);
extern int of_get_mac_address_nvmem(struct device_node *np, u8 *mac);
+int of_get_nvmem_eui48(struct device_node *np, const char *cell_name, u8 *addr);
int of_get_ethdev_address(struct device_node *np, struct net_device *dev);
extern struct net_device *of_find_net_device_by_node(struct device_node *np);
#else
@@ -34,6 +35,12 @@ static inline int of_get_mac_address_nvmem(struct device_node *np, u8 *mac)
return -ENODEV;
}
+static inline int of_get_nvmem_eui48(struct device_node *np,
+ const char *cell_name, u8 *addr)
+{
+ return -ENODEV;
+}
+
static inline int of_get_ethdev_address(struct device_node *np, struct net_device *dev)
{
return -ENODEV;
diff --git a/net/core/of_net.c b/net/core/of_net.c
index 93ea425b9248a23f4f95a336e9cdbf0053248e32..11c1acca151266ac9287457b4050a54b08e2b5f5 100644
--- a/net/core/of_net.c
+++ b/net/core/of_net.c
@@ -61,9 +61,7 @@ static int of_get_mac_addr(struct device_node *np, const char *name, u8 *addr)
int of_get_mac_address_nvmem(struct device_node *np, u8 *addr)
{
struct platform_device *pdev = of_find_device_by_node(np);
- struct nvmem_cell *cell;
- const void *mac;
- size_t len;
+ u8 mac[ETH_ALEN] __aligned(sizeof(u16));
int ret;
/* Try lookup by device first, there might be a nvmem_cell_lookup
@@ -75,27 +73,54 @@ int of_get_mac_address_nvmem(struct device_node *np, u8 *addr)
return ret;
}
- cell = of_nvmem_cell_get(np, "mac-address");
+ ret = of_get_nvmem_eui48(np, "mac-address", mac);
+ if (ret)
+ return ret;
+
+ if (!is_valid_ether_addr(mac))
+ return -EINVAL;
+
+ ether_addr_copy(addr, mac);
+ return 0;
+}
+EXPORT_SYMBOL(of_get_mac_address_nvmem);
+
+/**
+ * of_get_nvmem_eui48 - Read a 6-byte EUI-48 address from a named NVMEM cell.
+ * @np: Device node to look up the NVMEM cell from.
+ * @cell_name: Name of the NVMEM cell (e.g. "mac-address", "local-bd-address").
+ * @addr: Output buffer for the 6-byte address.
+ *
+ * Reads the named NVMEM cell and validates that it contains a non-zero 6-byte
+ * address. Returns 0 on success, negative errno on failure.
+ */
+int of_get_nvmem_eui48(struct device_node *np, const char *cell_name, u8 *addr)
+{
+ struct nvmem_cell *cell;
+ const void *eui48;
+ size_t len;
+
+ cell = of_nvmem_cell_get(np, cell_name);
if (IS_ERR(cell))
return PTR_ERR(cell);
- mac = nvmem_cell_read(cell, &len);
+ eui48 = nvmem_cell_read(cell, &len);
nvmem_cell_put(cell);
- if (IS_ERR(mac))
- return PTR_ERR(mac);
+ if (IS_ERR(eui48))
+ return PTR_ERR(eui48);
- if (len != ETH_ALEN || !is_valid_ether_addr(mac)) {
- kfree(mac);
+ if (len != ETH_ALEN || !memchr_inv(eui48, 0, ETH_ALEN)) {
+ kfree(eui48);
return -EINVAL;
}
- memcpy(addr, mac, ETH_ALEN);
- kfree(mac);
+ memcpy(addr, eui48, ETH_ALEN);
+ kfree(eui48);
return 0;
}
-EXPORT_SYMBOL(of_get_mac_address_nvmem);
+EXPORT_SYMBOL_GPL(of_get_nvmem_eui48);
/**
* of_get_mac_address()
--
2.34.1
^ permalink raw reply related
* [PATCH v6 7/9] Bluetooth: hci_sync: Add NVMEM-backed BD address retrieval
From: Loic Poulain @ 2026-06-29 8:55 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, Christian Marangi
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-msm, linux-block,
linux-wireless, ath10k, linux-bluetooth, netdev, daniel,
Loic Poulain, Bartosz Golaszewski
In-Reply-To: <20260629-block-as-nvmem-v6-0-f02513dcd46d@oss.qualcomm.com>
Some devices store the Bluetooth BD address in non-volatile
memory, which can be accessed through the NVMEM framework.
Similar to Ethernet or WiFi MAC addresses, add support for
reading the BD address from a 'local-bd-address' NVMEM cell.
As with the device-tree provided BD address, add a quirk to
indicate whether a device or platform should attempt to read
the address from NVMEM when no valid in-chip address is present.
Also add a quirk to indicate if the address is stored in
big-endian byte order.
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
include/net/bluetooth/hci.h | 18 ++++++++++++++++++
net/bluetooth/hci_sync.c | 39 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 572b1c620c5d653a1fe10b26c1b0ba33e8f4968f..7686466d1109253b0d75edeb5f6a99fb98ce4cc6 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -164,6 +164,24 @@ enum {
*/
HCI_QUIRK_BDADDR_PROPERTY_BROKEN,
+ /* When this quirk is set, the public Bluetooth address
+ * initially reported by HCI Read BD Address command
+ * is considered invalid. The public BD Address can be
+ * retrieved via a 'local-bd-address' NVMEM cell.
+ *
+ * This quirk can be set before hci_register_dev is called or
+ * during the hdev->setup vendor callback.
+ */
+ HCI_QUIRK_USE_BDADDR_NVMEM,
+
+ /* When this quirk is set, the Bluetooth Device Address provided by
+ * the 'local-bd-address' NVMEM is stored in big-endian order.
+ *
+ * This quirk can be set before hci_register_dev is called or
+ * during the hdev->setup vendor callback.
+ */
+ HCI_QUIRK_BDADDR_NVMEM_BE,
+
/* When this quirk is set, the duplicate filtering during
* scanning is based on Bluetooth devices addresses. To allow
* RSSI based updates, restart scanning if needed.
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index fd3aacdea512a37c22b9a2be90c89ddca4b4d99f..589ccdfa26c1281d6eb979370523fff0d7920302 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -7,6 +7,7 @@
*/
#include <linux/property.h>
+#include <linux/of_net.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -3588,6 +3589,37 @@ int hci_powered_update_sync(struct hci_dev *hdev)
return 0;
}
+/**
+ * hci_dev_get_bd_addr_from_nvmem - Get the Bluetooth Device Address
+ * (BD_ADDR) for a HCI device from
+ * an NVMEM cell.
+ * @hdev: The HCI device
+ *
+ * Search for 'local-bd-address' NVMEM cell in the device firmware node.
+ *
+ * All-zero BD addresses are rejected (unprovisioned).
+ */
+static int hci_dev_get_bd_addr_from_nvmem(struct hci_dev *hdev)
+{
+ struct device_node *np = dev_of_node(hdev->dev.parent);
+ u8 ba[sizeof(bdaddr_t)];
+ int err;
+
+ if (!np)
+ return -ENODEV;
+
+ err = of_get_nvmem_eui48(np, "local-bd-address", ba);
+ if (err)
+ return err;
+
+ if (hci_test_quirk(hdev, HCI_QUIRK_BDADDR_NVMEM_BE))
+ baswap(&hdev->public_addr, (bdaddr_t *)ba);
+ else
+ bacpy(&hdev->public_addr, (bdaddr_t *)ba);
+
+ return 0;
+}
+
/**
* hci_dev_get_bd_addr_from_property - Get the Bluetooth Device Address
* (BD_ADDR) for a HCI device from
@@ -5042,12 +5074,17 @@ static int hci_dev_setup_sync(struct hci_dev *hdev)
* its setup callback.
*/
invalid_bdaddr = hci_test_quirk(hdev, HCI_QUIRK_INVALID_BDADDR) ||
- hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY);
+ hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY) ||
+ hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_NVMEM);
if (!ret) {
if (hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY) &&
!bacmp(&hdev->public_addr, BDADDR_ANY))
hci_dev_get_bd_addr_from_property(hdev);
+ if (hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_NVMEM) &&
+ !bacmp(&hdev->public_addr, BDADDR_ANY))
+ hci_dev_get_bd_addr_from_nvmem(hdev);
+
if (invalid_bdaddr && bacmp(&hdev->public_addr, BDADDR_ANY) &&
hdev->set_bdaddr) {
ret = hdev->set_bdaddr(hdev, &hdev->public_addr);
--
2.34.1
^ permalink raw reply related
* [PATCH v6 8/9] Bluetooth: qca: Set NVMEM BD address quirks when address is invalid
From: Loic Poulain @ 2026-06-29 8:55 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, Christian Marangi
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-msm, linux-block,
linux-wireless, ath10k, linux-bluetooth, netdev, daniel,
Loic Poulain, Bartosz Golaszewski
In-Reply-To: <20260629-block-as-nvmem-v6-0-f02513dcd46d@oss.qualcomm.com>
When the controller BD address is invalid (zero or default),
set the NVMEM quirks to allow retrieving the address from a
'local-bd-address' NVMEM cell. The BD address is often stored
alongside the WiFi MAC address in big-endian format, so also
set the big-endian quirk.
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
drivers/bluetooth/btqca.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index dda76365726f0bfe0e80e05fe04859fa4f0592e1..df33eacfd29fa680f393f90215150743e6001d5b 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -721,8 +721,11 @@ static int qca_check_bdaddr(struct hci_dev *hdev, const struct qca_fw_config *co
}
bda = (struct hci_rp_read_bd_addr *)skb->data;
- if (!bacmp(&bda->bdaddr, &config->bdaddr))
+ if (!bacmp(&bda->bdaddr, &config->bdaddr)) {
hci_set_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY);
+ hci_set_quirk(hdev, HCI_QUIRK_USE_BDADDR_NVMEM);
+ hci_set_quirk(hdev, HCI_QUIRK_BDADDR_NVMEM_BE);
+ }
kfree_skb(skb);
--
2.34.1
^ permalink raw reply related
* [PATCH v6 9/9] arm64: dts: qcom: arduino-imola: Describe NVMEM layout for WiFi/BT addresses
From: Loic Poulain @ 2026-06-29 8:55 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Jens Axboe, Johannes Berg,
Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, Christian Marangi
Cc: linux-mmc, devicetree, linux-kernel, linux-arm-msm, linux-block,
linux-wireless, ath10k, linux-bluetooth, netdev, daniel,
Loic Poulain, Konrad Dybcio, Bartosz Golaszewski
In-Reply-To: <20260629-block-as-nvmem-v6-0-f02513dcd46d@oss.qualcomm.com>
On Arduino Uno-Q, the eMMC boot1 partition is factory provisioned
with device-specific information such as the WiFi MAC address
and the Bluetooth BD address. This partition can serve as an
alternative to additional non-volatile memory, such as a
dedicated EEPROM.
The eMMC boot partitions are typically good candidates, as they
are relatively small, read-only by default (and can be enforced
as hardware read-only), and are not affected by board reflashing
procedures, which generally target the eMMC user or GP partitions.
Describe the corresponding nvmem-layout for the WiFi and Bluetooth
addresses, and point the WiFi and Bluetooth nodes to the appropriate
NVMEM cells to retrieve them.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts | 39 ++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts
index bf088fa9807f040f0c8f405f9111b01790b09377..128c7a7e76b5b089044745f5d6407d6391055fc2 100644
--- a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts
+++ b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts
@@ -409,7 +409,40 @@ &sdhc_1 {
no-sdio;
no-sd;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
status = "okay";
+
+ card@0 {
+ compatible = "mmc-card";
+ reg = <0>;
+
+ partitions-boot1 {
+ compatible = "fixed-partitions";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ wifi_mac_addr: mac-addr@4400 {
+ compatible = "mac-base";
+ reg = <0x4400 0x6>;
+ #nvmem-cell-cells = <1>;
+ };
+
+ bd_addr: bd-addr@5400 {
+ compatible = "mac-base";
+ reg = <0x5400 0x6>;
+ #nvmem-cell-cells = <1>;
+ };
+ };
+ };
+ };
};
&spi5 {
@@ -512,6 +545,9 @@ bluetooth {
vddch0-supply = <&pm4125_l22>;
enable-gpios = <&tlmm 87 GPIO_ACTIVE_HIGH>;
max-speed = <3000000>;
+
+ nvmem-cells = <&bd_addr 0>;
+ nvmem-cell-names = "local-bd-address";
};
};
@@ -557,6 +593,9 @@ &wifi {
qcom,ath10k-calibration-variant = "ArduinoImola";
firmware-name = "qcm2290";
+ nvmem-cells = <&wifi_mac_addr 0>;
+ nvmem-cell-names = "mac-address";
+
status = "okay";
};
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v2 2/4] blk-cgroup: fix race between policy activation and blkg destruction
From: yu kuai @ 2026-06-29 9:03 UTC (permalink / raw)
To: Nilay Shroff, yukuai, Tejun Heo, Josef Bacik, Jens Axboe
Cc: Zheng Qixing, Christoph Hellwig, Tang Yizhou, Ming Lei, cgroups,
linux-block, linux-kernel
In-Reply-To: <c44fcd50-6341-4617-b6cb-cad3c65a7a75@linux.ibm.com>
Hi,
在 2026/6/29 13:33, Nilay Shroff 写道:
> On 6/27/26 9:43 AM, yu kuai wrote:
>> Hi,
>>
>> 在 2026/6/26 14:12, Nilay Shroff 写道:
>>> On 6/26/26 7:22 AM, yu kuai wrote:
>>>> Hi,
>>>>
>>>> 在 2026/6/26 9:50, yu kuai 写道:
>>>>> Hi,
>>>>>
>>>>> 在 2026/6/25 23:08, Nilay Shroff 写道:
>>>>>> On 6/24/26 12:16 PM, Yu Kuai wrote:
>>>>>>> diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
>>>>>>> index 7baccfb690fe..f7e788a7fe95 100644
>>>>>>> --- a/block/blk-cgroup.c
>>>>>>> +++ b/block/blk-cgroup.c
>>>>>>> @@ -1563,10 +1563,12 @@ int blkcg_activate_policy(struct gendisk
>>>>>>> *disk, const struct blkcg_policy *pol)
>>>>>>> if (WARN_ON_ONCE(!pol->pd_alloc_fn || !pol->pd_free_fn))
>>>>>>> return -EINVAL;
>>>>>>> if (queue_is_mq(q))
>>>>>>> memflags = blk_mq_freeze_queue(q);
>>>>>>> +
>>>>>>> + mutex_lock(&q->blkcg_mutex);
>>>>>>> retry:
>>>>>>> spin_lock_irq(&q->queue_lock);
>>>>>>> /* blkg_list is pushed at the head, reverse walk to
>>>>>>> initialize parents first */
>>>>>>> list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) {
>>>>>>> @@ -1625,10 +1627,11 @@ int blkcg_activate_policy(struct gendisk
>>>>>>> *disk, const struct blkcg_policy *pol)
>>>>>>> __set_bit(pol->plid, q->blkcg_pols);
>>>>>>> ret = 0;
>>>>>>> spin_unlock_irq(&q->queue_lock);
>>>>>>> out:
>>>>>>> + mutex_unlock(&q->blkcg_mutex);
>>>>>>> if (queue_is_mq(q))
>>>>>>> blk_mq_unfreeze_queue(q, memflags);
>>>>>>> if (pinned_blkg)
>>>>>>> blkg_put(pinned_blkg);
>>>>>>> if (pd_prealloc)
>>>>>> If the policy allocation fails, we jump to the lable enomem: and
>>>>>> teardown pds.
>>>>>> But I see this path still only acquires ->queue_lock. Don't we also
>>>>>> need
>>>>>> to protect it with ->blkcg_mutex?
>>>>> Yes, I agree we should protect it as well.
>>>>
>>>> Just take a closer look at the code, the enomem is already
>>>> protected by
>>>> blkcg_mutex :)
>>>>
>>>
>>> Oh yes, but the ->blkcg_mutex is never released if we jump to enomem.
>>> So that may potentially cause deadlock. We need to release
>>> ->blkcg_mutex
>>> once blkcg_policy_teardown_pds() returns. Or may be refactor code
>>> (or add
>>> comment) so that it's easy to realize or spot the ->blkcg_mutex is
>>> acquired
>>> and then released around blkcg_policy_teardown_pds().
>>
>> the enomem will goto out at last, and blkcg_mutex do released. The
>> code is
>> a bit hacky.
>>
>>>
>>>>>
>>>>>> Moreover I still see race between blkg insertion in blkg_create()
>>>>>> which
>>>>>> still doesn't use ->blkcg_mutex and so list traversal in
>>>>>> bfq_end_wr_async()
>>>>>> may still race with blkg_create(), isn't it? I remember you once
>>>>>> told
>>>>>> this will be handled in another series but I couldn't find that yet.
>>>>> This is the set:
>>>>>
>>>>> [PATCH 0/8] blk-cgroup: remove queue_lock nesting from blkcg paths
>>>>> - Yu
>>>>> Kuai
>>>>> <https://lore.kernel.org/all/cover.1780621988.git.yukuai@fygo.io/>
>>>>>
>>>>> Noted that set just make sure queue_lock is not nested under other
>>>>> atomic
>>>>> context, and that set do not acquire blkcg_mutex for blkg_create()
>>>>> yet. Howerver,
>>>>> with that set it'll be easy to convert all queue_lock to blkcg_mtuex
>>>>> for blkg
>>>>> protection, and together with lots of blk-cgroup code cleanups.
>>>>>
>>>
>>> Okay, so are you planning to send a follow-up patchset that replaces
>>> ->queue_lock
>>> with ->blkcg_mutex for protecting the blkg_list? If so, I'd still
>>> prefer acquiring
>>> ->blkcg_mutex around blkg_create() in this patchset. That would
>>> address the race
>>> between blkg_create() and the blkg_list traversal in
>>> bfq_end_wr_async(), while the
>>> subsequent series can focus on cleaning up and removing the remaining
>>> ->queue_lock
>>> usage for blkg protection.
>>
>> Yes, there is a follow-up patchset. When this set was posted,
>> blkg_create is still
>> called with queue_lock held, so I can't do that. However, not that
>> the other set
>> is already applied, I can hold blkcg_mutex for blkg_create() now.
>>
>
> If you already have a follow-up patchset that replaces ->queue_lock with
> ->blkcg_mutex for protecting blkg_list, then I think it might make sense
> to send that out first (if you haven't already) and hold off this
> series for
> now. That way, the blkg_create() race can be addressed first, and this
> series can build on top of those changes.
Yes, I already have a follow-up patchset that is build after this set.
I agree send that first will make sense, I'll rebase and send soon.
>
> BTW, if that follow-up series is merged first, I suspect the first two
> patches in
> this series may no longer be necessary, leaving only patches 3/4 and 4/4.
Yes, the first two patches will be folded into the patch to replace
queue_lock with blkcg_mutex.
>
> Thanks,
> --Nilay
>
>
>
--
Thanks,
Kuai
^ permalink raw reply
* RE: [PATCH v6 7/9] Bluetooth: hci_sync: Add NVMEM-backed BD address retrieval
From: Kwapulinski, Piotr @ 2026-06-29 9:23 UTC (permalink / raw)
To: Loic Poulain, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio, Jens Axboe,
Johannes Berg, Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Srinivas Kandagatla, Andrew Lunn, Heiner Kallweit,
Russell King, Saravana Kannan, Christian Marangi
Cc: linux-mmc@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
linux-block@vger.kernel.org, linux-wireless@vger.kernel.org,
ath10k@lists.infradead.org, linux-bluetooth@vger.kernel.org,
netdev@vger.kernel.org, daniel@makrotopia.org,
Bartosz Golaszewski
In-Reply-To: <20260629-block-as-nvmem-v6-7-f02513dcd46d@oss.qualcomm.com>
>-----Original Message-----
>From: Loic Poulain <loic.poulain@oss.qualcomm.com>
>Sent: Monday, June 29, 2026 10:55 AM
>To: Ulf Hansson <ulfh@kernel.org>; Rob Herring <robh@kernel.org>; Krzysztof Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Bjorn Andersson <andersson@kernel.org>; Konrad Dybcio <konradybcio@kernel.org>; Jens Axboe <axboe@kernel.dk>; Johannes Berg <johannes@sipsolutions.net>; Jeff Johnson <jjohnson@kernel.org>; Bartosz Golaszewski <brgl@kernel.org>; Marcel Holtmann <marcel@holtmann.org>; Luiz Augusto von Dentz <luiz.dentz@gmail.com>; Balakrishna Godavarthi <quic_bgodavar@quicinc.com>; Rocky Liao <quic_rjliao@quicinc.com>; David S. Miller <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo Abeni <pabeni@redhat.com>; Simon Horman <horms@kernel.org>; Srinivas Kandagatla <srini@kernel.org>; Andrew Lunn <andrew@lunn.ch>; Heiner Kallweit <hkallweit1@gmail.com>; Russell King <linux@armlinux.org.uk>; Saravana Kannan <saravanak@kernel.org>; Christian Marangi <ansuelsmth@gmail.com>
>Cc: linux-mmc@vger.kernel.org; devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; linux-arm-msm@vger.kernel.org; linux-block@vger.kernel.org; linux-wireless@vger.kernel.org; ath10k@lists.infradead.org; linux-bluetooth@vger.kernel.org; netdev@vger.kernel.org; daniel@makrotopia.org; Loic Poulain <loic.poulain@oss.qualcomm.com>; Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
>Subject: [PATCH v6 7/9] Bluetooth: hci_sync: Add NVMEM-backed BD address retrieval
>
>Some devices store the Bluetooth BD address in non-volatile memory, which can be accessed through the NVMEM framework.
>Similar to Ethernet or WiFi MAC addresses, add support for reading the BD address from a 'local-bd-address' NVMEM cell.
>
>As with the device-tree provided BD address, add a quirk to indicate whether a device or platform should attempt to read the address from NVMEM when no valid in-chip address is present.
>Also add a quirk to indicate if the address is stored in big-endian byte order.
>
>Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
>Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
>---
> include/net/bluetooth/hci.h | 18 ++++++++++++++++++
> net/bluetooth/hci_sync.c | 39 ++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 56 insertions(+), 1 deletion(-)
>
>diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 572b1c620c5d653a1fe10b26c1b0ba33e8f4968f..7686466d1109253b0d75edeb5f6a99fb98ce4cc6 100644
>--- a/include/net/bluetooth/hci.h
>+++ b/include/net/bluetooth/hci.h
>@@ -164,6 +164,24 @@ enum {
> */
> HCI_QUIRK_BDADDR_PROPERTY_BROKEN,
>
>+ /* When this quirk is set, the public Bluetooth address
>+ * initially reported by HCI Read BD Address command
>+ * is considered invalid. The public BD Address can be
>+ * retrieved via a 'local-bd-address' NVMEM cell.
>+ *
>+ * This quirk can be set before hci_register_dev is called or
>+ * during the hdev->setup vendor callback.
>+ */
>+ HCI_QUIRK_USE_BDADDR_NVMEM,
>+
>+ /* When this quirk is set, the Bluetooth Device Address provided by
>+ * the 'local-bd-address' NVMEM is stored in big-endian order.
>+ *
>+ * This quirk can be set before hci_register_dev is called or
>+ * during the hdev->setup vendor callback.
>+ */
>+ HCI_QUIRK_BDADDR_NVMEM_BE,
>+
> /* When this quirk is set, the duplicate filtering during
> * scanning is based on Bluetooth devices addresses. To allow
> * RSSI based updates, restart scanning if needed.
>diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index fd3aacdea512a37c22b9a2be90c89ddca4b4d99f..589ccdfa26c1281d6eb979370523fff0d7920302 100644
>--- a/net/bluetooth/hci_sync.c
>+++ b/net/bluetooth/hci_sync.c
>@@ -7,6 +7,7 @@
> */
>
> #include <linux/property.h>
>+#include <linux/of_net.h>
>
> #include <net/bluetooth/bluetooth.h>
> #include <net/bluetooth/hci_core.h>
>@@ -3588,6 +3589,37 @@ int hci_powered_update_sync(struct hci_dev *hdev)
> return 0;
> }
>
>+/**
>+ * hci_dev_get_bd_addr_from_nvmem - Get the Bluetooth Device Address
>+ * (BD_ADDR) for a HCI device from
>+ * an NVMEM cell.
>+ * @hdev: The HCI device
>+ *
>+ * Search for 'local-bd-address' NVMEM cell in the device firmware node.
>+ *
>+ * All-zero BD addresses are rejected (unprovisioned).
Please add return value description and
Reviewed-by: Piotr Kwapulinski <piotr.kwapulinski@intel.com>
Thank you.
Piotr
>+ */
>+static int hci_dev_get_bd_addr_from_nvmem(struct hci_dev *hdev) {
>+ struct device_node *np = dev_of_node(hdev->dev.parent);
>+ u8 ba[sizeof(bdaddr_t)];
>+ int err;
>+
>+ if (!np)
>+ return -ENODEV;
>+
>+ err = of_get_nvmem_eui48(np, "local-bd-address", ba);
>+ if (err)
>+ return err;
>+
>+ if (hci_test_quirk(hdev, HCI_QUIRK_BDADDR_NVMEM_BE))
>+ baswap(&hdev->public_addr, (bdaddr_t *)ba);
>+ else
>+ bacpy(&hdev->public_addr, (bdaddr_t *)ba);
>+
>+ return 0;
>+}
>+
> /**
> * hci_dev_get_bd_addr_from_property - Get the Bluetooth Device Address
> * (BD_ADDR) for a HCI device from
>@@ -5042,12 +5074,17 @@ static int hci_dev_setup_sync(struct hci_dev *hdev)
> * its setup callback.
> */
> invalid_bdaddr = hci_test_quirk(hdev, HCI_QUIRK_INVALID_BDADDR) ||
>- hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY);
>+ hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY) ||
>+ hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_NVMEM);
> if (!ret) {
> if (hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY) &&
> !bacmp(&hdev->public_addr, BDADDR_ANY))
> hci_dev_get_bd_addr_from_property(hdev);
>
>+ if (hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_NVMEM) &&
>+ !bacmp(&hdev->public_addr, BDADDR_ANY))
>+ hci_dev_get_bd_addr_from_nvmem(hdev);
>+
> if (invalid_bdaddr && bacmp(&hdev->public_addr, BDADDR_ANY) &&
> hdev->set_bdaddr) {
> ret = hdev->set_bdaddr(hdev, &hdev->public_addr);
>
>--
>2.34.1
>
^ permalink raw reply
* Re: [PATCH] blk-flush: fix possibe deadlock when process nvme_timeout()
From: yebin @ 2026-06-29 12:00 UTC (permalink / raw)
To: axboe, linux-block, yebin10; +Cc: kbusch, hch, sagi, linux-nvme
In-Reply-To: <20260608113923.3893518-1-yebin@huaweicloud.com>
Friendly ping ...
This issue occurs once every week in our product's live network environment.
The root cause is certainly triggered by firmware issues. The kernel still
needs to reinforce this scenario to prevent system hangs caused by dead loops.
In `blk_mq_tagset_wait_completed_request()`, the reference count is continuously
acquired and released, and there is still a chance for the request to be in the
MQ_RQ_IDLE state. Therefore, the race condition pointed out by sashiko exists,
but in this scenario, it can still be handled correctly in the end.
[1] https://sashiko.dev/#/patchset/20260608113923.3893518-1-yebin%40huaweicloud.com
On 2026/6/8 19:39, Ye Bin wrote:
> From: Ye Bin <yebin10@huawei.com>
>
> There's when process nvme_timeout():
> [ 206.734601][ T8184] nvme nvme0: I/O tag 512 (1200) opcode 0x0 (I/O Cmd) QID 3 timeout, aborting req_op:FLUSH(2) size:0
> [ 206.736112][ C0] nvme nvme0: Abort status: 0x0
> [ 208.094637][ T8184] nvme nvme0: I/O tag 512 (1200) opcode 0x0 (I/O Cmd) QID 3 timeout, reset controller
>
> [root@localhost ~]# cat /proc/8184/stack
> [<0>] msleep+0x37/0x50
> [<0>] blk_mq_tagset_wait_completed_request+0x6f/0xe0
> [<0>] nvme_cancel_tagset+0x79/0xa0
> [<0>] nvme_dev_disable+0x55c/0x7e0
> [<0>] nvme_timeout+0x25b/0x1530
> [<0>] blk_mq_handle_expired+0x210/0x2c0
> [<0>] bt_iter+0x2bb/0x360
> [<0>] blk_mq_queue_tag_busy_iter+0x9f8/0x1f30
> [<0>] blk_mq_timeout_work+0x5dc/0x7d0
> [<0>] process_one_work+0xa08/0x1d00
> [<0>] worker_thread+0x698/0xeb0
> [<0>] kthread+0x408/0x540
> [<0>] ret_from_fork+0xa4d/0xdd0
> [<0>] ret_from_fork_asm+0x1a/0x30
>
> Above issue may happen as follows:
> nvme_timeout // tag 512 request's flush request the first timeout
> iod->aborted = 1;
> abort_req = nvme_alloc_request(dev->ctrl.admin_q, &cmd,
> BLK_MQ_REQ_NOWAIT, NVME_QID_ANY); // Abort tag 512 flush request
> blk_execute_rq_nowait(abort_req->q, NULL, abort_req, 0, abort_endio);
> // Abort request completion, will no wait
> ....
> ****'abort_req' not complete***
> ....
> nvme_timeout // tag 512 request's flush request the second timeout
> if (!nvmeq->qid || (iod->flags & IOD_ABORTED))
> nvme_req(req)->flags |= NVME_REQ_CANCELLED;
> goto disable;
> ...
> **** tag 512 request's flush request end ****
> nvme_try_complete_req
> blk_mq_complete_request_remote(req);
> WRITE_ONCE(rq->state, MQ_RQ_COMPLETE);
> ...
> nvme_end_req(req);
> blk_mq_end_request(req, status);
> __blk_mq_end_request(rq, error);
> if (rq->end_io)
> rq->end_io(rq, error);
> flush_end_io(rq, error);
> // The timeout process holds the reference count.
> // so request keep MQ_RQ_COMPLETE state
> if (!refcount_dec_and_test(&flush_rq->ref))
> fq->rq_status = error;
> return;
> **** tag 512 flush request is MQ_RQ_COMPLETE state ****
> disable:
> nvme_dev_disable(dev, false);
> nvme_cancel_tagset(&dev->ctrl);
> blk_mq_tagset_busy_iter(&dev->tagset, nvme_cancel_request,
> &dev->ctrl);
> nvme_cancel_request
> if (blk_mq_request_completed(req))
> return true;
> blk_mq_tagset_wait_completed_request(&dev->tagset);
> while (true)
> blk_mq_tagset_busy_iter(tagset,
> blk_mq_tagset_count_completed_rqs, &count);
> blk_mq_tagset_count_completed_rqs();
> // request is MQ_RQ_COMPLETE state
> if (blk_mq_request_completed(rq)) // return true
> (*count)++;
> if (!count) // So the value of 'count' is never 0, loop endless
> break;
> msleep(5);
> The preceding problem occurs because the timeout processing flow holds
> the reference count of the request, and the flush request is always in
> the MQ_RQ_COMPLETE state due to the special nature of the flush request.
> As a result, a dead loop occurs in the nvme_dev_disable() process.
> To solve the preceding problem, if only the timeout processing flow holds
> the reference count when the flush request times out, the request status
> must be changed to MQ_RQ_IDLE in advance. In this way, it is safe to call
> blk_mq_tagset_wait_completed_request () during the timeout processing.
>
> Fixes: e1569a16180a ("nvme: do not restart the request timeout if we're resetting the controller")
> Signed-off-by: Ye Bin <yebin10@huawei.com>
> ---
> block/blk-flush.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/block/blk-flush.c b/block/blk-flush.c
> index 403a46c86411..d12839b1fcb5 100644
> --- a/block/blk-flush.c
> +++ b/block/blk-flush.c
> @@ -213,6 +213,18 @@ static enum rq_end_io_ret flush_end_io(struct request *flush_rq,
>
> if (!req_ref_put_and_test(flush_rq)) {
> fq->rq_status = error;
> +
> + /*
> + * The timeout processing flow holds the reference count
> + * of flush_rq. If the last reference count is held by the
> + * timeout processing flow, the status of flush_rq must be
> + * changed to MQ_RQ_IDLE in advance. Otherwise, a deadlock
> + * occurs when blk_mq_tagset_wait_completed_request() is
> + * called in the timeout processing flow.
> + */
> + if (req_ref_read(flush_rq) == 1 &&
> + flush_rq->rq_flags & RQF_TIMED_OUT)
> + WRITE_ONCE(flush_rq->state, MQ_RQ_IDLE);
> spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
> return RQ_END_IO_NONE;
> }
>
^ permalink raw reply
* Re: [PATCH blktests] block/044: basic block error injection sanity test
From: Christoph Hellwig @ 2026-06-29 12:32 UTC (permalink / raw)
To: Shin'ichiro Kawasaki; +Cc: Christoph Hellwig, linux-block
In-Reply-To: <aj9KzVlDI29qvLWe@shinmob>
On Sat, Jun 27, 2026 at 01:06:29PM +0900, Shin'ichiro Kawasaki wrote:
> On Jun 26, 2026 / 06:56, Christoph Hellwig wrote:
> > On Fri, Jun 26, 2026 at 01:31:06PM +0900, Shin'ichiro Kawasaki wrote:
> > > > > Nit: Majority of the blktests test cases have GPL-3.0+. If you do not mind,
> > > > > I suggest GPL-3.0+.
> > > >
> > > > Well a mix of licenses is obviously bad, although I hate the GPL 3 with
> > > > passion.
> > >
> > > I see, I respoect author's choice.
> >
> > Well, if the common bits are GPLv3+ we can't actually legally combine
> > them with test that have a pure GPLv2 license. So I need at least
> > GPL-2.0+.
>
> I see... I read back GPLv2 and v3. My understanding is that:
>
> - GPL v3 adds additional restrictions on top of v2, such as section 6
> "Installation information" or section 3 "Legal Rights from Antci-
> Circumvention Law".
> - The v3 additions conflict with the GPL v2 section6, that says:
> "You may not impose any further restrictions on the recepients'
> excercise of the rights granted here in."
Yeah.
> Thanks. I will list up original authors and contributors of the test cases,
> and then bring up license fix up discussion.
Thanks. And I'll resend this test case with your fixups.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox