![]() |
index : kernel/git/stable/stable-queue.git | |
| Linux kernel stable patch queue | Stable Group |
| aboutsummaryrefslogtreecommitdiffstats |
diff options
| author | Sasha Levin <sashal@kernel.org> | 2026-07-03 22:04:51 -0400 |
|---|---|---|
| committer | Sasha Levin <sashal@kernel.org> | 2026-07-03 22:04:51 -0400 |
| commit | 67fbfcf4e1f3c59ee15bf7d242ae838be2a5780b (patch) | |
| tree | ca6ba28e6b21b23c01818378570c06d4b90b2b8a | |
| parent | 800a8114d6462a0b34e0e65641d2b97564cea269 (diff) | |
| download | stable-queue-master.tar.gz | |
Signed-off-by: Sasha Levin <sashal@kernel.org>
51 files changed, 4162 insertions, 0 deletions
diff --git a/staging-5.10/clk-imx-add-check-for-kcalloc.patch b/staging-5.10/clk-imx-add-check-for-kcalloc.patch new file mode 100644 index 0000000000..32a16b2b1d --- /dev/null +++ b/staging-5.10/clk-imx-add-check-for-kcalloc.patch @@ -0,0 +1,40 @@ +From ad2208a35a011c1eaa43f80a1e70e9ea0dc5799a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 3 Jul 2026 15:13:38 +0300 +Subject: clk: imx: Add check for kcalloc + +From: Jiasheng Jiang <jiasheng@iscas.ac.cn> + +commit ed713e2bc093239ccd380c2ce8ae9e4162f5c037 upstream. + +As the potential failure of the kcalloc(), +it should be better to check it in order to +avoid the dereference of the NULL pointer. + +Fixes: 379c9a24cc23 ("clk: imx: Fix reparenting of UARTs not associated with stdout") +Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn> +Reviewed-by: Abel Vesa <abel.vesa@nxp.com> +Link: https://lore.kernel.org/r/20220310080257.1988412-1-jiasheng@iscas.ac.cn +Signed-off-by: Abel Vesa <abel.vesa@nxp.com> +Signed-off-by: Alexandra Diupina <adiupina@astralinux.ru> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/imx/clk.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c +index d4cf0c7045ab27..be0493e5b494e6 100644 +--- a/drivers/clk/imx/clk.c ++++ b/drivers/clk/imx/clk.c +@@ -173,6 +173,8 @@ void imx_register_uart_clocks(unsigned int clk_count) + int i; + + imx_uart_clocks = kcalloc(clk_count, sizeof(struct clk *), GFP_KERNEL); ++ if (!imx_uart_clocks) ++ return; + + if (!of_stdout) + return; +-- +2.53.0 + diff --git a/staging-5.10/nfsd-release-layout-stid-on-setlease-failure.patch b/staging-5.10/nfsd-release-layout-stid-on-setlease-failure.patch new file mode 100644 index 0000000000..9055cb8057 --- /dev/null +++ b/staging-5.10/nfsd-release-layout-stid-on-setlease-failure.patch @@ -0,0 +1,75 @@ +From 122574ca65b1fdbcf6cc08385e970fb6e6114496 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 23:39:54 -0400 +Subject: nfsd: release layout stid on setlease failure + +From: Chris Mason <clm@meta.com> + +commit 30d55c8aabb261bc3f427d6b9aae7ef6206063f9 upstream. + +nfs4_alloc_stid() publishes the new stid into cl->cl_stateids via +idr_alloc_cyclic() under cl_lock before returning to +nfsd4_alloc_layout_stateid(). When nfsd4_layout_setlease() then +fails, the error path frees the layout stateid directly with +kmem_cache_free() without ever calling idr_remove(), leaving the +IDR slot pointing at freed slab memory. Any subsequent IDR walker +(states_show, client teardown) dereferences the dangling pointer. + +The correct teardown for an IDR-published stid is nfs4_put_stid(), +which removes the IDR slot under cl_lock, dispatches sc_free +(nfsd4_free_layout_stateid) to release ls->ls_file via +nfsd4_close_layout(), and drops the nfs4_file reference in its +tail. + +A second issue blocks that switch: nfsd4_free_layout_stateid() +unconditionally inspects ls->ls_fence_work via +delayed_work_pending() under ls_lock, but +INIT_DELAYED_WORK(&ls->ls_fence_work, ...) currently runs only +after the setlease call. On the setlease-failure path the +destructor would touch an uninitialized delayed_work. + + nfsd4_alloc_layout_stateid() + nfs4_alloc_stid() /* idr_alloc_cyclic under cl_lock */ + nfsd4_layout_setlease() /* fails */ + nfs4_put_stid() + nfsd4_free_layout_stateid() + delayed_work_pending(&ls->ls_fence_work) /* needs INIT */ + nfsd4_close_layout() /* nfsd_file_put(ls->ls_file) */ + put_nfs4_file() + +Fix by hoisting the ls_fenced / ls_fence_delay / INIT_DELAYED_WORK +initialization above the nfsd4_layout_setlease() call, and replace +the manual nfsd_file_put + put_nfs4_file + kmem_cache_free cleanup +with a single nfs4_put_stid(stp). + +Fixes: c5c707f96fc9 ("nfsd: implement pNFS layout recalls") +Cc: stable@vger.kernel.org +Assisted-by: kres (claude-opus-4-7) +Signed-off-by: Chris Mason <clm@meta.com> +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +[ cel: no ls_fence_work in 5.10.y; dropped INIT_DELAYED_WORK hunk ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4layouts.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c +index d0fbbd34db689c..bcf16dd07d4883 100644 +--- a/fs/nfsd/nfs4layouts.c ++++ b/fs/nfsd/nfs4layouts.c +@@ -241,9 +241,7 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate, + BUG_ON(!ls->ls_file); + + if (nfsd4_layout_setlease(ls)) { +- nfsd_file_put(ls->ls_file); +- put_nfs4_file(fp); +- kmem_cache_free(nfs4_layout_stateid_cache, ls); ++ nfs4_put_stid(stp); + return NULL; + } + +-- +2.53.0 + diff --git a/staging-5.10/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch b/staging-5.10/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch new file mode 100644 index 0000000000..3afe63adb4 --- /dev/null +++ b/staging-5.10/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch @@ -0,0 +1,73 @@ +From e2150551b46f9c37bef29685380d8e35a6dba1e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 23:40:48 -0400 +Subject: nfsd: reset write verifier on deferred writeback errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jeff Layton <jlayton@kernel.org> + +commit 2090b05803faab8a9fa62fbff871007862cac1b7 upstream. + +nfsd_vfs_write() and nfsd_commit() both call filemap_check_wb_err() to +detect deferred writeback errors, but neither rotates the server's write +verifier (nn->writeverf) when this check fails. Every other +durable-storage-failure path in these functions calls +commit_reset_write_verifier() before returning an error. + +The missing rotation means clients holding UNSTABLE write data under the +current verifier will COMMIT, receive the unchanged verifier back, and +conclude their data is durable â silently dropping data that failed +writeback. This violates the UNSTABLE+COMMIT durability contract +(RFC 1813 §3.3.7, RFC 8881 §18.32). + +Add commit_reset_write_verifier() calls at both filemap_check_wb_err() +error sites, matching the pattern used by adjacent error paths in the +same functions. The helper already filters -EAGAIN and -ESTALE +internally, so the calls are unconditionally safe. + +Reported-by: Chris Mason <clm@meta.com> +Fixes: 555dbf1a9aac ("nfsd: Replace use of rwsem with errseq_t") +Cc: stable@vger.kernel.org +Assisted-by: kres:claude-opus-4-6 +Signed-off-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +[ cel: open-code the reset; commit_reset_write_verifier() is v6.7 ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/vfs.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c +index 19468142486671..c8eebd03784a21 100644 +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -1149,8 +1149,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, + nfsd_stats_io_write_add(nn, exp, *cnt); + fsnotify_modify(file); + host_err = filemap_check_wb_err(file->f_mapping, since); +- if (host_err < 0) ++ if (host_err < 0) { ++ nfsd_reset_write_verifier(nn); ++ trace_nfsd_writeverf_reset(nn, rqstp, host_err); + goto out_nfserr; ++ } + + if (stable && use_wgather) { + host_err = wait_for_concurrent_writes(file); +@@ -1286,6 +1289,10 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, + nfsd_copy_write_verifier(verf, nn); + err2 = filemap_check_wb_err(nf->nf_file->f_mapping, + since); ++ if (err2 < 0) { ++ nfsd_reset_write_verifier(nn); ++ trace_nfsd_writeverf_reset(nn, rqstp, err2); ++ } + err = nfserrno(err2); + break; + case -EINVAL: +-- +2.53.0 + diff --git a/staging-5.10/series b/staging-5.10/series index 3e69bb8311..c6c484d9c3 100644 --- a/staging-5.10/series +++ b/staging-5.10/series @@ -1 +1,5 @@ nvmet-tcp-fix-race-between-icreq-handling-and-queue-.patch +nfsd-release-layout-stid-on-setlease-failure.patch +nfsd-reset-write-verifier-on-deferred-writeback-erro.patch +userfaultfd-gate-must_wait-writability-check-on-pte_.patch +clk-imx-add-check-for-kcalloc.patch diff --git a/staging-5.10/userfaultfd-gate-must_wait-writability-check-on-pte_.patch b/staging-5.10/userfaultfd-gate-must_wait-writability-check-on-pte_.patch new file mode 100644 index 0000000000..dd287d3924 --- /dev/null +++ b/staging-5.10/userfaultfd-gate-must_wait-writability-check-on-pte_.patch @@ -0,0 +1,88 @@ +From 0238b29475513ccd662ba52895b839e4ecff68d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:48:59 +0100 +Subject: userfaultfd: gate must_wait writability check on pte_present() + +From: Kiryl Shutsemau <kas@kernel.org> + +[ Upstream commit 8e80af52db652fbc41320eee45a4f73bc029faf2 ] + +userfaultfd_must_wait() and userfaultfd_huge_must_wait() read the PTE +without taking the page table lock and then apply pte_write() / +huge_pte_write() to it. Those accessors decode bits from the present +encoding only; on a swap or migration entry they read the offset bits that +happen to share the same position and return an undefined result. + +The intent of the check is "is this fault still WP-blocked?". A +non-marker swap entry means the page is in transit -- the userfault +context the original fault delivered against is no longer the same, and +the swap-in or migration completion path will re-deliver a fresh fault if +userspace still needs to handle it. Worst case under the current code the +garbage write bit says "wait", and the thread stays asleep until a +UFFDIO_WAKE that may never arrive. + +Gate the writability check on pte_present() so the lockless re-check only +inspects present-PTE bits when the entry is actually present. The +non-present, non-marker case returns "don't wait" and lets the fault path +retry. + +Link: https://lore.kernel.org/20260529172331.356655-6-kas@kernel.org +Fixes: 369cd2121be4 ("userfaultfd: hugetlbfs: userfaultfd_huge_must_wait for hugepmd ranges") +Fixes: 63b2d4174c4a ("userfaultfd: wp: add the writeprotect API to userfaultfd ioctl") +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Reported-by: Sashiko AI review <sashiko-bot@kernel.org> +Reviewed-by: Lorenzo Stoakes <ljs@kernel.org> +Cc: David Hildenbrand <david@kernel.org> +Cc: Michal Hocko <mhocko@suse.com> +Cc: Mike Rapoport <rppt@kernel.org> +Cc: Peter Xu <peterx@redhat.com> +Cc: Suren Baghdasaryan <surenb@google.com> +Cc: Vlastimil Babka <vbabka@kernel.org> +Cc: Balbir Singh <balbirs@nvidia.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> + +[ kas: apply to fs/userfaultfd.c and fold the pte_present()/ + huge_pte_present() gate into the existing writability checks; this tree + predates the marker/return-style refactor of these functions ] +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/userfaultfd.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c +index 0d6c00e9b49316..6773227fbe889e 100644 +--- a/fs/userfaultfd.c ++++ b/fs/userfaultfd.c +@@ -251,7 +251,12 @@ static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx, + */ + if (huge_pte_none(pte)) + ret = true; +- if (!huge_pte_write(pte) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): huge_pte_write() on a ++ * non-present migration entry decodes random offset bits. The ++ * migration completion path re-delivers the fault if still needed. ++ */ ++ if (pte_present(pte) && !huge_pte_write(pte) && (reason & VM_UFFD_WP)) + ret = true; + out: + return ret; +@@ -332,7 +337,12 @@ static inline bool userfaultfd_must_wait(struct userfaultfd_ctx *ctx, + */ + if (pte_none(*pte)) + ret = true; +- if (!pte_write(*pte) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): pte_write() on a ++ * non-present swap/migration entry decodes random offset bits. The ++ * page-in path re-delivers the fault if it still needs userspace. ++ */ ++ if (pte_present(*pte) && !pte_write(*pte) && (reason & VM_UFFD_WP)) + ret = true; + pte_unmap(pte); + +-- +2.53.0 + diff --git a/staging-5.15/clk-imx-add-check-for-kcalloc.patch b/staging-5.15/clk-imx-add-check-for-kcalloc.patch new file mode 100644 index 0000000000..26095abee2 --- /dev/null +++ b/staging-5.15/clk-imx-add-check-for-kcalloc.patch @@ -0,0 +1,40 @@ +From d222ad955ddcccfb80986e8d247cfa7bc20e3553 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 3 Jul 2026 15:13:38 +0300 +Subject: clk: imx: Add check for kcalloc + +From: Jiasheng Jiang <jiasheng@iscas.ac.cn> + +commit ed713e2bc093239ccd380c2ce8ae9e4162f5c037 upstream. + +As the potential failure of the kcalloc(), +it should be better to check it in order to +avoid the dereference of the NULL pointer. + +Fixes: 379c9a24cc23 ("clk: imx: Fix reparenting of UARTs not associated with stdout") +Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn> +Reviewed-by: Abel Vesa <abel.vesa@nxp.com> +Link: https://lore.kernel.org/r/20220310080257.1988412-1-jiasheng@iscas.ac.cn +Signed-off-by: Abel Vesa <abel.vesa@nxp.com> +Signed-off-by: Alexandra Diupina <adiupina@astralinux.ru> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/clk/imx/clk.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c +index d4cf0c7045ab27..be0493e5b494e6 100644 +--- a/drivers/clk/imx/clk.c ++++ b/drivers/clk/imx/clk.c +@@ -173,6 +173,8 @@ void imx_register_uart_clocks(unsigned int clk_count) + int i; + + imx_uart_clocks = kcalloc(clk_count, sizeof(struct clk *), GFP_KERNEL); ++ if (!imx_uart_clocks) ++ return; + + if (!of_stdout) + return; +-- +2.53.0 + diff --git a/staging-5.15/nfc-llcp-protect-nfc_llcp_sock_unlink-calls.patch b/staging-5.15/nfc-llcp-protect-nfc_llcp_sock_unlink-calls.patch new file mode 100644 index 0000000000..ed00f6407e --- /dev/null +++ b/staging-5.15/nfc-llcp-protect-nfc_llcp_sock_unlink-calls.patch @@ -0,0 +1,56 @@ +From 75f355d4d6cc11f927ba7294db5d5a21f7c68b70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 2 Mar 2022 20:25:22 +0100 +Subject: nfc: llcp: protect nfc_llcp_sock_unlink() calls + +From: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + +[ Upstream commit a06b8044169f6d5c3eb34772c13d2c0c1b205352 ] + +nfc_llcp_sock_link() is called in all paths (bind/connect) as a last +action, still protected with lock_sock(). When cleaning up in +llcp_sock_release(), call nfc_llcp_sock_unlink() in a mirrored way: +earlier and still under the lock_sock(). + +Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/nfc/llcp_sock.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c +index 54af85d939c6b9..57dea580c02912 100644 +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -626,6 +626,13 @@ static int llcp_sock_release(struct socket *sock) + } + } + ++ if (sock->type == SOCK_RAW) ++ nfc_llcp_sock_unlink(&local->raw_sockets, sk); ++ else if (sk->sk_state == LLCP_CONNECTING) ++ nfc_llcp_sock_unlink(&local->connecting_sockets, sk); ++ else ++ nfc_llcp_sock_unlink(&local->sockets, sk); ++ + if (llcp_sock->reserved_ssap < LLCP_SAP_MAX) + nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); + +@@ -638,13 +645,6 @@ static int llcp_sock_release(struct socket *sock) + if (sk->sk_state == LLCP_DISCONNECTING) + return err; + +- if (sock->type == SOCK_RAW) +- nfc_llcp_sock_unlink(&local->raw_sockets, sk); +- else if (sk->sk_state == LLCP_CONNECTING) +- nfc_llcp_sock_unlink(&local->connecting_sockets, sk); +- else +- nfc_llcp_sock_unlink(&local->sockets, sk); +- + out: + sock_orphan(sk); + sock_put(sk); +-- +2.53.0 + diff --git a/staging-5.15/nfsd-release-layout-stid-on-setlease-failure.patch b/staging-5.15/nfsd-release-layout-stid-on-setlease-failure.patch new file mode 100644 index 0000000000..6f22cf26b1 --- /dev/null +++ b/staging-5.15/nfsd-release-layout-stid-on-setlease-failure.patch @@ -0,0 +1,75 @@ +From 01729f0bdb4c64bb22ea8a36287859b05258fa57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 23:38:15 -0400 +Subject: nfsd: release layout stid on setlease failure + +From: Chris Mason <clm@meta.com> + +commit 30d55c8aabb261bc3f427d6b9aae7ef6206063f9 upstream. + +nfs4_alloc_stid() publishes the new stid into cl->cl_stateids via +idr_alloc_cyclic() under cl_lock before returning to +nfsd4_alloc_layout_stateid(). When nfsd4_layout_setlease() then +fails, the error path frees the layout stateid directly with +kmem_cache_free() without ever calling idr_remove(), leaving the +IDR slot pointing at freed slab memory. Any subsequent IDR walker +(states_show, client teardown) dereferences the dangling pointer. + +The correct teardown for an IDR-published stid is nfs4_put_stid(), +which removes the IDR slot under cl_lock, dispatches sc_free +(nfsd4_free_layout_stateid) to release ls->ls_file via +nfsd4_close_layout(), and drops the nfs4_file reference in its +tail. + +A second issue blocks that switch: nfsd4_free_layout_stateid() +unconditionally inspects ls->ls_fence_work via +delayed_work_pending() under ls_lock, but +INIT_DELAYED_WORK(&ls->ls_fence_work, ...) currently runs only +after the setlease call. On the setlease-failure path the +destructor would touch an uninitialized delayed_work. + + nfsd4_alloc_layout_stateid() + nfs4_alloc_stid() /* idr_alloc_cyclic under cl_lock */ + nfsd4_layout_setlease() /* fails */ + nfs4_put_stid() + nfsd4_free_layout_stateid() + delayed_work_pending(&ls->ls_fence_work) /* needs INIT */ + nfsd4_close_layout() /* nfsd_file_put(ls->ls_file) */ + put_nfs4_file() + +Fix by hoisting the ls_fenced / ls_fence_delay / INIT_DELAYED_WORK +initialization above the nfsd4_layout_setlease() call, and replace +the manual nfsd_file_put + put_nfs4_file + kmem_cache_free cleanup +with a single nfs4_put_stid(stp). + +Fixes: c5c707f96fc9 ("nfsd: implement pNFS layout recalls") +Cc: stable@vger.kernel.org +Assisted-by: kres (claude-opus-4-7) +Signed-off-by: Chris Mason <clm@meta.com> +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +[ cel: no ls_fence_work in 5.15.y; dropped INIT_DELAYED_WORK hunk ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4layouts.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c +index d0fbbd34db689c..bcf16dd07d4883 100644 +--- a/fs/nfsd/nfs4layouts.c ++++ b/fs/nfsd/nfs4layouts.c +@@ -241,9 +241,7 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate, + BUG_ON(!ls->ls_file); + + if (nfsd4_layout_setlease(ls)) { +- nfsd_file_put(ls->ls_file); +- put_nfs4_file(fp); +- kmem_cache_free(nfs4_layout_stateid_cache, ls); ++ nfs4_put_stid(stp); + return NULL; + } + +-- +2.53.0 + diff --git a/staging-5.15/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch b/staging-5.15/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch new file mode 100644 index 0000000000..634ab69667 --- /dev/null +++ b/staging-5.15/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch @@ -0,0 +1,73 @@ +From f299c908152878a01db1687ae9b7f6974f1d779b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 23:37:05 -0400 +Subject: nfsd: reset write verifier on deferred writeback errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jeff Layton <jlayton@kernel.org> + +commit 2090b05803faab8a9fa62fbff871007862cac1b7 upstream. + +nfsd_vfs_write() and nfsd_commit() both call filemap_check_wb_err() to +detect deferred writeback errors, but neither rotates the server's write +verifier (nn->writeverf) when this check fails. Every other +durable-storage-failure path in these functions calls +commit_reset_write_verifier() before returning an error. + +The missing rotation means clients holding UNSTABLE write data under the +current verifier will COMMIT, receive the unchanged verifier back, and +conclude their data is durable â silently dropping data that failed +writeback. This violates the UNSTABLE+COMMIT durability contract +(RFC 1813 §3.3.7, RFC 8881 §18.32). + +Add commit_reset_write_verifier() calls at both filemap_check_wb_err() +error sites, matching the pattern used by adjacent error paths in the +same functions. The helper already filters -EAGAIN and -ESTALE +internally, so the calls are unconditionally safe. + +Reported-by: Chris Mason <clm@meta.com> +Fixes: 555dbf1a9aac ("nfsd: Replace use of rwsem with errseq_t") +Cc: stable@vger.kernel.org +Assisted-by: kres:claude-opus-4-6 +Signed-off-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +[ cel: open-code the reset; commit_reset_write_verifier() is v6.7 ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/vfs.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c +index e1737984e0ca11..7b0bc4507ad047 100644 +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -1133,8 +1133,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, + nfsd_stats_io_write_add(nn, exp, *cnt); + fsnotify_modify(file); + host_err = filemap_check_wb_err(file->f_mapping, since); +- if (host_err < 0) ++ if (host_err < 0) { ++ nfsd_reset_write_verifier(nn); ++ trace_nfsd_writeverf_reset(nn, rqstp, host_err); + goto out_nfserr; ++ } + + if (stable && use_wgather) { + host_err = wait_for_concurrent_writes(file); +@@ -1270,6 +1273,10 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, + nfsd_copy_write_verifier(verf, nn); + err2 = filemap_check_wb_err(nf->nf_file->f_mapping, + since); ++ if (err2 < 0) { ++ nfsd_reset_write_verifier(nn); ++ trace_nfsd_writeverf_reset(nn, rqstp, err2); ++ } + err = nfserrno(err2); + break; + case -EINVAL: +-- +2.53.0 + diff --git a/staging-5.15/series b/staging-5.15/series index 3e69bb8311..78a5123e8a 100644 --- a/staging-5.15/series +++ b/staging-5.15/series @@ -1 +1,6 @@ nvmet-tcp-fix-race-between-icreq-handling-and-queue-.patch +nfc-llcp-protect-nfc_llcp_sock_unlink-calls.patch +nfsd-release-layout-stid-on-setlease-failure.patch +nfsd-reset-write-verifier-on-deferred-writeback-erro.patch +userfaultfd-gate-must_wait-writability-check-on-pte_.patch +clk-imx-add-check-for-kcalloc.patch diff --git a/staging-5.15/userfaultfd-gate-must_wait-writability-check-on-pte_.patch b/staging-5.15/userfaultfd-gate-must_wait-writability-check-on-pte_.patch new file mode 100644 index 0000000000..62b93ec772 --- /dev/null +++ b/staging-5.15/userfaultfd-gate-must_wait-writability-check-on-pte_.patch @@ -0,0 +1,88 @@ +From 6818363111ac85da61e796958bab5d953ad04d96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:49:00 +0100 +Subject: userfaultfd: gate must_wait writability check on pte_present() + +From: Kiryl Shutsemau <kas@kernel.org> + +[ Upstream commit 8e80af52db652fbc41320eee45a4f73bc029faf2 ] + +userfaultfd_must_wait() and userfaultfd_huge_must_wait() read the PTE +without taking the page table lock and then apply pte_write() / +huge_pte_write() to it. Those accessors decode bits from the present +encoding only; on a swap or migration entry they read the offset bits that +happen to share the same position and return an undefined result. + +The intent of the check is "is this fault still WP-blocked?". A +non-marker swap entry means the page is in transit -- the userfault +context the original fault delivered against is no longer the same, and +the swap-in or migration completion path will re-deliver a fresh fault if +userspace still needs to handle it. Worst case under the current code the +garbage write bit says "wait", and the thread stays asleep until a +UFFDIO_WAKE that may never arrive. + +Gate the writability check on pte_present() so the lockless re-check only +inspects present-PTE bits when the entry is actually present. The +non-present, non-marker case returns "don't wait" and lets the fault path +retry. + +Link: https://lore.kernel.org/20260529172331.356655-6-kas@kernel.org +Fixes: 369cd2121be4 ("userfaultfd: hugetlbfs: userfaultfd_huge_must_wait for hugepmd ranges") +Fixes: 63b2d4174c4a ("userfaultfd: wp: add the writeprotect API to userfaultfd ioctl") +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Reported-by: Sashiko AI review <sashiko-bot@kernel.org> +Reviewed-by: Lorenzo Stoakes <ljs@kernel.org> +Cc: David Hildenbrand <david@kernel.org> +Cc: Michal Hocko <mhocko@suse.com> +Cc: Mike Rapoport <rppt@kernel.org> +Cc: Peter Xu <peterx@redhat.com> +Cc: Suren Baghdasaryan <surenb@google.com> +Cc: Vlastimil Babka <vbabka@kernel.org> +Cc: Balbir Singh <balbirs@nvidia.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> + +[ kas: apply to fs/userfaultfd.c and fold the pte_present()/ + huge_pte_present() gate into the existing writability checks; this tree + predates the marker/return-style refactor of these functions ] +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/userfaultfd.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c +index 868405f3cfa0c4..271ce399f6b6fd 100644 +--- a/fs/userfaultfd.c ++++ b/fs/userfaultfd.c +@@ -249,7 +249,12 @@ static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx, + */ + if (huge_pte_none(pte)) + ret = true; +- if (!huge_pte_write(pte) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): huge_pte_write() on a ++ * non-present migration entry decodes random offset bits. The ++ * migration completion path re-delivers the fault if still needed. ++ */ ++ if (pte_present(pte) && !huge_pte_write(pte) && (reason & VM_UFFD_WP)) + ret = true; + out: + return ret; +@@ -330,7 +335,12 @@ static inline bool userfaultfd_must_wait(struct userfaultfd_ctx *ctx, + */ + if (pte_none(*pte)) + ret = true; +- if (!pte_write(*pte) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): pte_write() on a ++ * non-present swap/migration entry decodes random offset bits. The ++ * page-in path re-delivers the fault if it still needs userspace. ++ */ ++ if (pte_present(*pte) && !pte_write(*pte) && (reason & VM_UFFD_WP)) + ret = true; + pte_unmap(pte); + +-- +2.53.0 + diff --git a/staging-6.1/loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch b/staging-6.1/loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch new file mode 100644 index 0000000000..9ed4e4e8b3 --- /dev/null +++ b/staging-6.1/loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch @@ -0,0 +1,64 @@ +From 95196fa5ddb921ba5e98e461cb508beb95e1e305 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 3 Jul 2026 11:24:00 +0800 +Subject: LoongArch: Report dying CPU to RCU in stop_this_cpu() + +From: Huacai Chen <chenhuacai@loongson.cn> + +commit f2539c56c74691e7a88af6372ba2b48c06ed2fe4 upstream. + +This is a port of MIPS commit 9f3f3bdc6d9dac1 ("MIPS: smp: report dying +CPU to RCU in stop_this_cpu()"). smp_send_stop() parks all secondary +CPUs in stop_this_cpu(). And the function marks the CPU offline for the +scheduler via set_cpu_online(false) but never informs RCU, so RCU keeps +expecting a quiescent state from CPUs that are now spinning forever with +interrupts disabled. + +As long as nothing waits for an RCU grace period after smp_send_stop() +this is harmless, which is why it went unnoticed. However, since commit +91840be8f710370 ("irq_work: Fix use-after-free in irq_work_single() on +PREEMPT_RT"), irq_work_sync() calls synchronize_rcu() on architectures +without an irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() +returns false. Any irq_work_sync() issued in the reboot/shutdown/halt +path after smp_send_stop() then blocks on a grace period that can never +complete, hanging the reboot: + + WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on + ... + rcu: INFO: rcu_sched detected stalls on CPUs/tasks: + rcu: Offline CPU 1 blocking current GP. + rcu: Offline CPU 2 blocking current GP. + rcu: Offline CPU 3 blocking current GP. + +This issue needs some hacks to reproduce, and it was not noticed on +LoongArch because arch_irq_work_has_interrupt() usually returns true. + +Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring +the generic CPU-hotplug offline path, so RCU stops waiting on the parked +CPUs and grace periods can still complete. LoongArch shuts down all CPUs +here without going through the CPU-hotplug mechanism, so this report is +not otherwise issued. + +Cc: <stable@vger.kernel.org> +Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/loongarch/kernel/smp.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c +index 18a2b37f4aea37..356918d5aa28f1 100644 +--- a/arch/loongarch/kernel/smp.c ++++ b/arch/loongarch/kernel/smp.c +@@ -517,6 +517,7 @@ static void stop_this_cpu(void *dummy) + set_cpu_online(smp_processor_id(), false); + calculate_cpu_foreign_map(); + local_irq_disable(); ++ rcu_report_dead(smp_processor_id()); + while (true); + } + +-- +2.53.0 + diff --git a/staging-6.1/nfsd-release-layout-stid-on-setlease-failure.patch b/staging-6.1/nfsd-release-layout-stid-on-setlease-failure.patch new file mode 100644 index 0000000000..84b090bf8c --- /dev/null +++ b/staging-6.1/nfsd-release-layout-stid-on-setlease-failure.patch @@ -0,0 +1,75 @@ +From c621b5be1c3140f4f9eddc00beb50fb10b1ff6f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 23:32:42 -0400 +Subject: nfsd: release layout stid on setlease failure + +From: Chris Mason <clm@meta.com> + +commit 30d55c8aabb261bc3f427d6b9aae7ef6206063f9 upstream. + +nfs4_alloc_stid() publishes the new stid into cl->cl_stateids via +idr_alloc_cyclic() under cl_lock before returning to +nfsd4_alloc_layout_stateid(). When nfsd4_layout_setlease() then +fails, the error path frees the layout stateid directly with +kmem_cache_free() without ever calling idr_remove(), leaving the +IDR slot pointing at freed slab memory. Any subsequent IDR walker +(states_show, client teardown) dereferences the dangling pointer. + +The correct teardown for an IDR-published stid is nfs4_put_stid(), +which removes the IDR slot under cl_lock, dispatches sc_free +(nfsd4_free_layout_stateid) to release ls->ls_file via +nfsd4_close_layout(), and drops the nfs4_file reference in its +tail. + +A second issue blocks that switch: nfsd4_free_layout_stateid() +unconditionally inspects ls->ls_fence_work via +delayed_work_pending() under ls_lock, but +INIT_DELAYED_WORK(&ls->ls_fence_work, ...) currently runs only +after the setlease call. On the setlease-failure path the +destructor would touch an uninitialized delayed_work. + + nfsd4_alloc_layout_stateid() + nfs4_alloc_stid() /* idr_alloc_cyclic under cl_lock */ + nfsd4_layout_setlease() /* fails */ + nfs4_put_stid() + nfsd4_free_layout_stateid() + delayed_work_pending(&ls->ls_fence_work) /* needs INIT */ + nfsd4_close_layout() /* nfsd_file_put(ls->ls_file) */ + put_nfs4_file() + +Fix by hoisting the ls_fenced / ls_fence_delay / INIT_DELAYED_WORK +initialization above the nfsd4_layout_setlease() call, and replace +the manual nfsd_file_put + put_nfs4_file + kmem_cache_free cleanup +with a single nfs4_put_stid(stp). + +Fixes: c5c707f96fc9 ("nfsd: implement pNFS layout recalls") +Cc: stable@vger.kernel.org +Assisted-by: kres (claude-opus-4-7) +Signed-off-by: Chris Mason <clm@meta.com> +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +[ cel: no ls_fence_work in 6.1.y; dropped INIT_DELAYED_WORK hunk ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4layouts.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c +index 308214378fd352..84bb200e24adea 100644 +--- a/fs/nfsd/nfs4layouts.c ++++ b/fs/nfsd/nfs4layouts.c +@@ -242,9 +242,7 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate, + BUG_ON(!ls->ls_file); + + if (nfsd4_layout_setlease(ls)) { +- nfsd_file_put(ls->ls_file); +- put_nfs4_file(fp); +- kmem_cache_free(nfs4_layout_stateid_cache, ls); ++ nfs4_put_stid(stp); + return NULL; + } + +-- +2.53.0 + diff --git a/staging-6.1/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch b/staging-6.1/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch new file mode 100644 index 0000000000..068ef4f873 --- /dev/null +++ b/staging-6.1/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch @@ -0,0 +1,73 @@ +From e389b2a9d556c5a60f483c1ffc2fa09e9f43e9ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 23:32:43 -0400 +Subject: nfsd: reset write verifier on deferred writeback errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jeff Layton <jlayton@kernel.org> + +commit 2090b05803faab8a9fa62fbff871007862cac1b7 upstream. + +nfsd_vfs_write() and nfsd_commit() both call filemap_check_wb_err() to +detect deferred writeback errors, but neither rotates the server's write +verifier (nn->writeverf) when this check fails. Every other +durable-storage-failure path in these functions calls +commit_reset_write_verifier() before returning an error. + +The missing rotation means clients holding UNSTABLE write data under the +current verifier will COMMIT, receive the unchanged verifier back, and +conclude their data is durable â silently dropping data that failed +writeback. This violates the UNSTABLE+COMMIT durability contract +(RFC 1813 §3.3.7, RFC 8881 §18.32). + +Add commit_reset_write_verifier() calls at both filemap_check_wb_err() +error sites, matching the pattern used by adjacent error paths in the +same functions. The helper already filters -EAGAIN and -ESTALE +internally, so the calls are unconditionally safe. + +Reported-by: Chris Mason <clm@meta.com> +Fixes: 555dbf1a9aac ("nfsd: Replace use of rwsem with errseq_t") +Cc: stable@vger.kernel.org +Assisted-by: kres:claude-opus-4-6 +Signed-off-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +[ cel: open-code the reset; commit_reset_write_verifier() is v6.7 ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/vfs.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c +index 87a596fc6654dd..c40b2a706691c5 100644 +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -1134,8 +1134,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, + nfsd_stats_io_write_add(nn, exp, *cnt); + fsnotify_modify(file); + host_err = filemap_check_wb_err(file->f_mapping, since); +- if (host_err < 0) ++ if (host_err < 0) { ++ nfsd_reset_write_verifier(nn); ++ trace_nfsd_writeverf_reset(nn, rqstp, host_err); + goto out_nfserr; ++ } + + if (stable && use_wgather) { + host_err = wait_for_concurrent_writes(file); +@@ -1271,6 +1274,10 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, + nfsd_copy_write_verifier(verf, nn); + err2 = filemap_check_wb_err(nf->nf_file->f_mapping, + since); ++ if (err2 < 0) { ++ nfsd_reset_write_verifier(nn); ++ trace_nfsd_writeverf_reset(nn, rqstp, err2); ++ } + err = nfserrno(err2); + break; + case -EINVAL: +-- +2.53.0 + diff --git a/staging-6.1/series b/staging-6.1/series index 403a0254b1..cc168ce6a7 100644 --- a/staging-6.1/series +++ b/staging-6.1/series @@ -1,2 +1,6 @@ nvmet-tcp-fix-race-between-icreq-handling-and-queue-.patch bpf-arm64-reject-out-of-range-b.cond-targets.patch +nfsd-release-layout-stid-on-setlease-failure.patch +nfsd-reset-write-verifier-on-deferred-writeback-erro.patch +loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch +userfaultfd-gate-must_wait-writability-check-on-pte_.patch diff --git a/staging-6.1/userfaultfd-gate-must_wait-writability-check-on-pte_.patch b/staging-6.1/userfaultfd-gate-must_wait-writability-check-on-pte_.patch new file mode 100644 index 0000000000..c70b928b13 --- /dev/null +++ b/staging-6.1/userfaultfd-gate-must_wait-writability-check-on-pte_.patch @@ -0,0 +1,88 @@ +From f72740d8aa7b34d3c54f08ffe217fe59ca94e55f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:49:02 +0100 +Subject: userfaultfd: gate must_wait writability check on pte_present() + +From: Kiryl Shutsemau <kas@kernel.org> + +[ Upstream commit 8e80af52db652fbc41320eee45a4f73bc029faf2 ] + +userfaultfd_must_wait() and userfaultfd_huge_must_wait() read the PTE +without taking the page table lock and then apply pte_write() / +huge_pte_write() to it. Those accessors decode bits from the present +encoding only; on a swap or migration entry they read the offset bits that +happen to share the same position and return an undefined result. + +The intent of the check is "is this fault still WP-blocked?". A +non-marker swap entry means the page is in transit -- the userfault +context the original fault delivered against is no longer the same, and +the swap-in or migration completion path will re-deliver a fresh fault if +userspace still needs to handle it. Worst case under the current code the +garbage write bit says "wait", and the thread stays asleep until a +UFFDIO_WAKE that may never arrive. + +Gate the writability check on pte_present() so the lockless re-check only +inspects present-PTE bits when the entry is actually present. The +non-present, non-marker case returns "don't wait" and lets the fault path +retry. + +Link: https://lore.kernel.org/20260529172331.356655-6-kas@kernel.org +Fixes: 369cd2121be4 ("userfaultfd: hugetlbfs: userfaultfd_huge_must_wait for hugepmd ranges") +Fixes: 63b2d4174c4a ("userfaultfd: wp: add the writeprotect API to userfaultfd ioctl") +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Reported-by: Sashiko AI review <sashiko-bot@kernel.org> +Reviewed-by: Lorenzo Stoakes <ljs@kernel.org> +Cc: David Hildenbrand <david@kernel.org> +Cc: Michal Hocko <mhocko@suse.com> +Cc: Mike Rapoport <rppt@kernel.org> +Cc: Peter Xu <peterx@redhat.com> +Cc: Suren Baghdasaryan <surenb@google.com> +Cc: Vlastimil Babka <vbabka@kernel.org> +Cc: Balbir Singh <balbirs@nvidia.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> + +[ kas: apply to fs/userfaultfd.c and fold the pte_present()/ + huge_pte_present() gate into the existing writability checks; this tree + predates the marker/return-style refactor of these functions ] +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/userfaultfd.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c +index 7f8b397597b0d1..6ebee2b3a5a83e 100644 +--- a/fs/userfaultfd.c ++++ b/fs/userfaultfd.c +@@ -273,7 +273,12 @@ static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx, + */ + if (huge_pte_none_mostly(pte)) + ret = true; +- if (!huge_pte_write(pte) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): huge_pte_write() on a ++ * non-present migration entry decodes random offset bits. The ++ * migration completion path re-delivers the fault if still needed. ++ */ ++ if (pte_present(pte) && !huge_pte_write(pte) && (reason & VM_UFFD_WP)) + ret = true; + out: + return ret; +@@ -355,7 +360,12 @@ static inline bool userfaultfd_must_wait(struct userfaultfd_ctx *ctx, + */ + if (pte_none_mostly(*pte)) + ret = true; +- if (!pte_write(*pte) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): pte_write() on a ++ * non-present swap/migration entry decodes random offset bits. The ++ * page-in path re-delivers the fault if it still needs userspace. ++ */ ++ if (pte_present(*pte) && !pte_write(*pte) && (reason & VM_UFFD_WP)) + ret = true; + pte_unmap(pte); + +-- +2.53.0 + diff --git a/staging-6.12/kernel-fork-clear-pf_block_ts-in-copy_process.patch b/staging-6.12/kernel-fork-clear-pf_block_ts-in-copy_process.patch new file mode 100644 index 0000000000..807720c115 --- /dev/null +++ b/staging-6.12/kernel-fork-clear-pf_block_ts-in-copy_process.patch @@ -0,0 +1,44 @@ +From 753a6b0ee88ec528751193273d6f92bc00431cf6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 16 Jun 2026 07:15:17 -0700 +Subject: kernel/fork: clear PF_BLOCK_TS in copy_process() + +From: Usama Arif <usama.arif@linux.dev> + +[ Upstream commit fd38b75c4b43295b10d69772a46d1c74dbd6fc81 ] + +PF_BLOCK_TS is only set in blk_time_get_ns() when current->plug is +non-NULL, and blk_finish_plug() clears it via __blk_flush_plug() +before NULLing the plug pointer. copy_process() breaks the +invariant by inheriting PF_BLOCK_TS from the parent while resetting +the child's plug to NULL. + +Clear PF_BLOCK_TS alongside that assignment so callers can rely on +"PF_BLOCK_TS set implies current->plug != NULL" and dereference +current->plug unguarded. + +Fixes: 06b23f92af87 ("block: update cached timestamp post schedule/preemption") +Cc: stable@vger.kernel.org +Signed-off-by: Usama Arif <usama.arif@linux.dev> +Link: https://patch.msgid.link/20260616141604.328820-2-usama.arif@linux.dev +Signed-off-by: Jens Axboe <axboe@kernel.dk> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/fork.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/fork.c b/kernel/fork.c +index c4955cffcb6f4e..c81b45509e8ab1 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -2450,6 +2450,7 @@ __latent_entropy struct task_struct *copy_process( + + #ifdef CONFIG_BLOCK + p->plug = NULL; ++ p->flags &= ~PF_BLOCK_TS; + #endif + futex_init_task(p); + +-- +2.53.0 + diff --git a/staging-6.12/nfsd-fix-file-change-detection-in-cb_getattr.patch b/staging-6.12/nfsd-fix-file-change-detection-in-cb_getattr.patch new file mode 100644 index 0000000000..ec4d838f4a --- /dev/null +++ b/staging-6.12/nfsd-fix-file-change-detection-in-cb_getattr.patch @@ -0,0 +1,84 @@ +From 08a5b7cba8363c749ec96f7d3b4ed3b39635385d Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:27:48 -0400 +Subject: nfsd: fix file change detection in CB_GETATTR + +From: Scott Mayhew <smayhew@redhat.com> + +commit 304d81a2fbf2b454def4debcb38ea173911b72cd upstream. + +RFC 8881, section 10.4.3 doesn't say anything about caching the file +size in the delegation record, nor does it say anything about comparing +a cached file size with the size reported by the client in the +CB_GETATTR reply for the purpose of determining if the client holds +modified data for the file. + +What section 10.4.3 of RFC 8881 does say is that the server should +compare the *current* file size with the size reported by the client +holding the delegation in the CB_GETATTR reply, and if they differ to +treat it as a modification regardless of the change attribute retrieved +via the CB_GETATTR. + +Doing otherwise would cause the server to believe the client holding the +delegation has a modified version of the file, even if the client +flushed the modifications to the server prior to the CB_GETATTR. This +would have the added side effect of subsequent CB_GETATTRs causing +updates to the mtime, ctime, and change attribute even if the client +holding the delegation makes no further updates to the file. + +Modify nfsd4_deleg_getattr_conflict() to obtain the current file size +via i_size_read(). Retain the ncf_cur_fsize field, since it's a +convenient way to return the file size back to nfsd4_encode_fattr4(), +but don't use it for the purpose of detecting file changes. Remove the +unnecessary initialization of ncf_cur_fsize in nfs4_open_delegation(). + +Also, if we recall the delegation (because the client didn't respond to +the CB_GETATTR), then skip the logic that checks the nfs4_cb_fattr +fields. + +Fixes: c5967721e106 ("NFSD: handle GETATTR conflict with write delegation") +Cc: stable@vger.kernel.org +Signed-off-by: Scott Mayhew <smayhew@redhat.com> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +[ cel: no deleg_ts in 6.12.y; dropped the now-dead ncf_cur_fsize init ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4state.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 1ce66acc9b6ba0..e18d70adcdb903 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -6086,7 +6086,6 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp, + goto out_no_deleg; + } + open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE; +- dp->dl_cb_fattr.ncf_cur_fsize = stat.size; + dp->dl_cb_fattr.ncf_initial_cinfo = nfsd4_change_attribute(&stat); + trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid); + } else { +@@ -9040,11 +9039,15 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry, + if (status != nfserr_jukebox || + !nfsd_wait_for_delegreturn(rqstp, inode)) + goto out_status; ++ status = nfs_ok; ++ goto out_status; ++ } ++ if (!ncf->ncf_file_modified) { ++ if (ncf->ncf_initial_cinfo != ncf->ncf_cb_change) ++ ncf->ncf_file_modified = true; ++ else if (i_size_read(inode) != ncf->ncf_cb_fsize) ++ ncf->ncf_file_modified = true; + } +- if (!ncf->ncf_file_modified && +- (ncf->ncf_initial_cinfo != ncf->ncf_cb_change || +- ncf->ncf_cur_fsize != ncf->ncf_cb_fsize)) +- ncf->ncf_file_modified = true; + if (ncf->ncf_file_modified) { + int err; + +-- +2.53.0 + diff --git a/staging-6.12/nfsd-release-layout-stid-on-setlease-failure.patch b/staging-6.12/nfsd-release-layout-stid-on-setlease-failure.patch new file mode 100644 index 0000000000..5b98b26953 --- /dev/null +++ b/staging-6.12/nfsd-release-layout-stid-on-setlease-failure.patch @@ -0,0 +1,57 @@ +From 6479dc14c89ee830e35d6f8157b5ac5fc2583c19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:27:49 -0400 +Subject: nfsd: release layout stid on setlease failure + +From: Chris Mason <clm@meta.com> + +commit 30d55c8aabb261bc3f427d6b9aae7ef6206063f9 upstream. + +nfs4_alloc_stid() publishes the new stid into cl->cl_stateids via +idr_alloc_cyclic() under cl_lock before returning to +nfsd4_alloc_layout_stateid(). When nfsd4_layout_setlease() then +fails, the error path frees the layout stateid directly with +kmem_cache_free() without ever calling idr_remove(), leaving the +IDR slot pointing at freed slab memory. Any subsequent IDR walker +(states_show, client teardown) dereferences the dangling pointer. + +The correct teardown for an IDR-published stid is nfs4_put_stid(), +which removes the IDR slot under cl_lock, dispatches sc_free +(nfsd4_free_layout_stateid) to release ls->ls_file via +nfsd4_close_layout(), and drops the nfs4_file reference in its +tail. + +Replace the manual nfsd_file_put + put_nfs4_file + kmem_cache_free +cleanup with a single nfs4_put_stid(stp). + +Fixes: c5c707f96fc9 ("nfsd: implement pNFS layout recalls") +Cc: stable@vger.kernel.org +Signed-off-by: Chris Mason <clm@meta.com> +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Chuck Lever <cel@kernel.org> +[ cel: no ls_fence_work in 6.12.y; dropped INIT_DELAYED_WORK hunk ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4layouts.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c +index fc5e82eddaa1af..c08bc2d0d37796 100644 +--- a/fs/nfsd/nfs4layouts.c ++++ b/fs/nfsd/nfs4layouts.c +@@ -256,9 +256,7 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate, + BUG_ON(!ls->ls_file); + + if (nfsd4_layout_setlease(ls)) { +- nfsd_file_put(ls->ls_file); +- put_nfs4_file(fp); +- kmem_cache_free(nfs4_layout_stateid_cache, ls); ++ nfs4_put_stid(stp); + return NULL; + } + +-- +2.53.0 + diff --git a/staging-6.12/perf-fix-dangling-cgroup-pointer-in-cpuctx-backport.patch b/staging-6.12/perf-fix-dangling-cgroup-pointer-in-cpuctx-backport.patch new file mode 100644 index 0000000000..2c3d458ecf --- /dev/null +++ b/staging-6.12/perf-fix-dangling-cgroup-pointer-in-cpuctx-backport.patch @@ -0,0 +1,41 @@ +From cbc9ac710af188b0ccafec80f422c7385da4ead7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 3 Jul 2026 00:48:25 +0800 +Subject: perf: Fix dangling cgroup pointer in cpuctx backport + +From: Wentao Guan <guanwentao@uniontech.com> + +recently backport of ("perf: Fix dangling cgroup pointer in cpuctx") +use a middle version, so aligned with the upstream commit: +commit 3b7a34aebbdf ("perf: Fix dangling cgroup pointer in cpuctx") + +This is a fix for stable v6.12.94 backport commit, so no upstream commit. + +Link: https://lore.kernel.org/all/2026070200-uneaten-smock-4130@gregkh/ +Fixes: 46f5623f9b0e ("perf: Fix dangling cgroup pointer in cpuctx") +Signed-off-by: Wentao Guan <guanwentao@uniontech.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/events/core.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 9099c0cc933be2..8fa3ee209a5be6 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -2440,10 +2440,9 @@ __perf_remove_from_context(struct perf_event *event, + */ + if (flags & DETACH_EXIT) + state = PERF_EVENT_STATE_EXIT; +- if (flags & DETACH_DEAD) { +- event->pending_disable = 1; ++ if (flags & DETACH_DEAD) + state = PERF_EVENT_STATE_DEAD; +- } ++ + event_sched_out(event, ctx); + + if (event->state > PERF_EVENT_STATE_OFF) +-- +2.53.0 + diff --git a/staging-6.12/series b/staging-6.12/series index 5702e744cc..88309abee0 100644 --- a/staging-6.12/series +++ b/staging-6.12/series @@ -1 +1,6 @@ bpf-arm64-reject-out-of-range-b.cond-targets.patch +nfsd-fix-file-change-detection-in-cb_getattr.patch +nfsd-release-layout-stid-on-setlease-failure.patch +kernel-fork-clear-pf_block_ts-in-copy_process.patch +userfaultfd-gate-must_wait-writability-check-on-pte_.patch +perf-fix-dangling-cgroup-pointer-in-cpuctx-backport.patch diff --git a/staging-6.12/userfaultfd-gate-must_wait-writability-check-on-pte_.patch b/staging-6.12/userfaultfd-gate-must_wait-writability-check-on-pte_.patch new file mode 100644 index 0000000000..515b26e91e --- /dev/null +++ b/staging-6.12/userfaultfd-gate-must_wait-writability-check-on-pte_.patch @@ -0,0 +1,88 @@ +From 53e60536810e916ce20d10ac84ccf4c679884fa0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:49:05 +0100 +Subject: userfaultfd: gate must_wait writability check on pte_present() + +From: Kiryl Shutsemau <kas@kernel.org> + +[ Upstream commit 8e80af52db652fbc41320eee45a4f73bc029faf2 ] + +userfaultfd_must_wait() and userfaultfd_huge_must_wait() read the PTE +without taking the page table lock and then apply pte_write() / +huge_pte_write() to it. Those accessors decode bits from the present +encoding only; on a swap or migration entry they read the offset bits that +happen to share the same position and return an undefined result. + +The intent of the check is "is this fault still WP-blocked?". A +non-marker swap entry means the page is in transit -- the userfault +context the original fault delivered against is no longer the same, and +the swap-in or migration completion path will re-deliver a fresh fault if +userspace still needs to handle it. Worst case under the current code the +garbage write bit says "wait", and the thread stays asleep until a +UFFDIO_WAKE that may never arrive. + +Gate the writability check on pte_present() so the lockless re-check only +inspects present-PTE bits when the entry is actually present. The +non-present, non-marker case returns "don't wait" and lets the fault path +retry. + +Link: https://lore.kernel.org/20260529172331.356655-6-kas@kernel.org +Fixes: 369cd2121be4 ("userfaultfd: hugetlbfs: userfaultfd_huge_must_wait for hugepmd ranges") +Fixes: 63b2d4174c4a ("userfaultfd: wp: add the writeprotect API to userfaultfd ioctl") +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Reported-by: Sashiko AI review <sashiko-bot@kernel.org> +Reviewed-by: Lorenzo Stoakes <ljs@kernel.org> +Cc: David Hildenbrand <david@kernel.org> +Cc: Michal Hocko <mhocko@suse.com> +Cc: Mike Rapoport <rppt@kernel.org> +Cc: Peter Xu <peterx@redhat.com> +Cc: Suren Baghdasaryan <surenb@google.com> +Cc: Vlastimil Babka <vbabka@kernel.org> +Cc: Balbir Singh <balbirs@nvidia.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> + +[ kas: apply to fs/userfaultfd.c and fold the pte_present()/ + huge_pte_present() gate into the existing writability checks; this tree + predates the marker/return-style refactor of these functions ] +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/userfaultfd.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c +index 29c9941e5ea79f..cbd9d610c54bf0 100644 +--- a/fs/userfaultfd.c ++++ b/fs/userfaultfd.c +@@ -251,7 +251,12 @@ static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx, + */ + if (huge_pte_none_mostly(pte)) + ret = true; +- if (!huge_pte_write(pte) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): huge_pte_write() on a ++ * non-present migration entry decodes random offset bits. The ++ * migration completion path re-delivers the fault if still needed. ++ */ ++ if (pte_present(pte) && !huge_pte_write(pte) && (reason & VM_UFFD_WP)) + ret = true; + out: + return ret; +@@ -326,7 +331,12 @@ static inline bool userfaultfd_must_wait(struct userfaultfd_ctx *ctx, + ptent = ptep_get(pte); + if (pte_none_mostly(ptent)) + ret = true; +- if (!pte_write(ptent) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): pte_write() on a ++ * non-present swap/migration entry decodes random offset bits. The ++ * page-in path re-delivers the fault if it still needs userspace. ++ */ ++ if (pte_present(ptent) && !pte_write(ptent) && (reason & VM_UFFD_WP)) + ret = true; + pte_unmap(pte); + +-- +2.53.0 + diff --git a/staging-6.18/kernel-fork-clear-pf_block_ts-in-copy_process.patch b/staging-6.18/kernel-fork-clear-pf_block_ts-in-copy_process.patch new file mode 100644 index 0000000000..2988bd6601 --- /dev/null +++ b/staging-6.18/kernel-fork-clear-pf_block_ts-in-copy_process.patch @@ -0,0 +1,44 @@ +From 77ca1ddf431d2da2c0a0f90448a6a286cfb3f90e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 16 Jun 2026 07:15:17 -0700 +Subject: kernel/fork: clear PF_BLOCK_TS in copy_process() + +From: Usama Arif <usama.arif@linux.dev> + +[ Upstream commit fd38b75c4b43295b10d69772a46d1c74dbd6fc81 ] + +PF_BLOCK_TS is only set in blk_time_get_ns() when current->plug is +non-NULL, and blk_finish_plug() clears it via __blk_flush_plug() +before NULLing the plug pointer. copy_process() breaks the +invariant by inheriting PF_BLOCK_TS from the parent while resetting +the child's plug to NULL. + +Clear PF_BLOCK_TS alongside that assignment so callers can rely on +"PF_BLOCK_TS set implies current->plug != NULL" and dereference +current->plug unguarded. + +Fixes: 06b23f92af87 ("block: update cached timestamp post schedule/preemption") +Cc: stable@vger.kernel.org +Signed-off-by: Usama Arif <usama.arif@linux.dev> +Link: https://patch.msgid.link/20260616141604.328820-2-usama.arif@linux.dev +Signed-off-by: Jens Axboe <axboe@kernel.dk> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/fork.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/fork.c b/kernel/fork.c +index 1215d3f52c6d21..8b1238d692916c 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -2230,6 +2230,7 @@ __latent_entropy struct task_struct *copy_process( + + #ifdef CONFIG_BLOCK + p->plug = NULL; ++ p->flags &= ~PF_BLOCK_TS; + #endif + futex_init_task(p); + +-- +2.53.0 + diff --git a/staging-6.18/nfsd-release-layout-stid-on-setlease-failure.patch b/staging-6.18/nfsd-release-layout-stid-on-setlease-failure.patch new file mode 100644 index 0000000000..f6edcf73ce --- /dev/null +++ b/staging-6.18/nfsd-release-layout-stid-on-setlease-failure.patch @@ -0,0 +1,75 @@ +From cfeac762936a8a9061631f99271029941fe760b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:24:09 -0400 +Subject: nfsd: release layout stid on setlease failure + +From: Chris Mason <clm@meta.com> + +commit 30d55c8aabb261bc3f427d6b9aae7ef6206063f9 upstream. + +nfs4_alloc_stid() publishes the new stid into cl->cl_stateids via +idr_alloc_cyclic() under cl_lock before returning to +nfsd4_alloc_layout_stateid(). When nfsd4_layout_setlease() then +fails, the error path frees the layout stateid directly with +kmem_cache_free() without ever calling idr_remove(), leaving the +IDR slot pointing at freed slab memory. Any subsequent IDR walker +(states_show, client teardown) dereferences the dangling pointer. + +The correct teardown for an IDR-published stid is nfs4_put_stid(), +which removes the IDR slot under cl_lock, dispatches sc_free +(nfsd4_free_layout_stateid) to release ls->ls_file via +nfsd4_close_layout(), and drops the nfs4_file reference in its +tail. + +A second issue blocks that switch: nfsd4_free_layout_stateid() +unconditionally inspects ls->ls_fence_work via +delayed_work_pending() under ls_lock, but +INIT_DELAYED_WORK(&ls->ls_fence_work, ...) currently runs only +after the setlease call. On the setlease-failure path the +destructor would touch an uninitialized delayed_work. + + nfsd4_alloc_layout_stateid() + nfs4_alloc_stid() /* idr_alloc_cyclic under cl_lock */ + nfsd4_layout_setlease() /* fails */ + nfs4_put_stid() + nfsd4_free_layout_stateid() + delayed_work_pending(&ls->ls_fence_work) /* needs INIT */ + nfsd4_close_layout() /* nfsd_file_put(ls->ls_file) */ + put_nfs4_file() + +Fix by hoisting the ls_fenced / ls_fence_delay / INIT_DELAYED_WORK +initialization above the nfsd4_layout_setlease() call, and replace +the manual nfsd_file_put + put_nfs4_file + kmem_cache_free cleanup +with a single nfs4_put_stid(stp). + +Fixes: c5c707f96fc9 ("nfsd: implement pNFS layout recalls") +Cc: stable@vger.kernel.org +Assisted-by: kres (claude-opus-4-7) +Signed-off-by: Chris Mason <clm@meta.com> +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +[ cel: drop fence_work init hoist absent from 6.18.y ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4layouts.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c +index 683bd1130afe29..62762e43f810b3 100644 +--- a/fs/nfsd/nfs4layouts.c ++++ b/fs/nfsd/nfs4layouts.c +@@ -256,9 +256,7 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate, + BUG_ON(!ls->ls_file); + + if (nfsd4_layout_setlease(ls)) { +- nfsd_file_put(ls->ls_file); +- put_nfs4_file(fp); +- kmem_cache_free(nfs4_layout_stateid_cache, ls); ++ nfs4_put_stid(stp); + return NULL; + } + +-- +2.53.0 + diff --git a/staging-6.18/nfsd-update-mtime-ctime-on-clone-in-presense-of-dele.patch b/staging-6.18/nfsd-update-mtime-ctime-on-clone-in-presense-of-dele.patch new file mode 100644 index 0000000000..3be862a7b4 --- /dev/null +++ b/staging-6.18/nfsd-update-mtime-ctime-on-clone-in-presense-of-dele.patch @@ -0,0 +1,123 @@ +From 8f5c131aec0d4bd9d28f822e8bddd3f73662d252 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:24:07 -0400 +Subject: nfsd: update mtime/ctime on CLONE in presense of delegated attributes + +From: Olga Kornievskaia <okorniev@redhat.com> + +commit 2863bac7f49c4acd80a048ce52506a2b9c8db015 upstream. + +When delegated attributes are given on open, the file is opened with +NOCMTIME and modifying operations do not update mtime/ctime as to not get +out-of-sync with the client's delegated view. However, for CLONE operation, +the server should update its view of mtime/ctime and reflect that in any +GETATTR queries. + +Fixes: e5e9b24ab8fa ("nfsd: freeze c/mtime updates with outstanding WRITE_ATTRS delegation") +Cc: stable@vger.kernel.org +Signed-off-by: Olga Kornievskaia <okorniev@redhat.com> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +[ cel: 9be4b7e74eb7 and 3daab3112f03 are missing from linux-6.18.y ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4proc.c | 3 +++ + fs/nfsd/nfs4state.c | 44 +++++++++++++++++++++++++++++--------------- + fs/nfsd/state.h | 1 + + 3 files changed, 33 insertions(+), 15 deletions(-) + +diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c +index 9d876f9d98be20..5bfe49502a06f4 100644 +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -1350,6 +1350,9 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + dst, clone->cl_dst_pos, clone->cl_count, + EX_ISSYNC(cstate->current_fh.fh_export)); + ++ if (!status && (READ_ONCE(dst->nf_file->f_mode) & FMODE_NOCMTIME) != 0) ++ nfsd_update_cmtime_attr(dst->nf_file, 0); ++ + nfsd_file_put(dst); + nfsd_file_put(src); + out: +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index b02fe9926b093c..a063a4a83ec22d 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -1226,10 +1226,6 @@ static void put_deleg_file(struct nfs4_file *fp) + + static void nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct file *f) + { +- struct iattr ia = { .ia_valid = ATTR_ATIME | ATTR_CTIME | ATTR_MTIME | ATTR_DELEG }; +- struct inode *inode = file_inode(f); +- int ret; +- + /* don't do anything if FMODE_NOCMTIME isn't set */ + if ((READ_ONCE(f->f_mode) & FMODE_NOCMTIME) == 0) + return; +@@ -1247,17 +1243,7 @@ static void nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct f + return; + + /* Stamp everything to "now" */ +- inode_lock(inode); +- ret = notify_change(&nop_mnt_idmap, f->f_path.dentry, &ia, NULL); +- inode_unlock(inode); +- if (ret) { +- struct inode *inode = file_inode(f); +- +- pr_notice_ratelimited("Unable to update timestamps on inode %02x:%02x:%lu: %d\n", +- MAJOR(inode->i_sb->s_dev), +- MINOR(inode->i_sb->s_dev), +- inode->i_ino, ret); +- } ++ nfsd_update_cmtime_attr(f, ATTR_ATIME); + } + + static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp) +@@ -9434,3 +9420,31 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct dentry *dentry, + nfs4_put_stid(&dp->dl_stid); + return status; + } ++ ++/** ++ * nfsd_update_cmtime_attr - update file's delegated ctime/mtime, ++ * and optionally other attributes (ie ATTR_ATIME). ++ * @f: pointer to an opened file ++ * @flags: any additional flags that should be updated ++ * ++ * Given upon opening a file delegated attributes were issues, update ++ * @f attributes to current times. ++ */ ++void nfsd_update_cmtime_attr(struct file *f, unsigned int flags) ++{ ++ int ret; ++ struct inode *inode = file_inode(f); ++ struct iattr attr = { ++ .ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_DELEG | flags, ++ }; ++ ++ inode_lock(inode); ++ ret = notify_change(&nop_mnt_idmap, f->f_path.dentry, &attr, NULL); ++ inode_unlock(inode); ++ if (ret) ++ pr_notice_ratelimited("nfsd: Unable to update timestamps on " ++ "inode %02x:%02x:%lu: %d\n", ++ MAJOR(inode->i_sb->s_dev), ++ MINOR(inode->i_sb->s_dev), ++ inode->i_ino, ret); ++} +diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h +index aaf513ed910459..2eed2c5b3cd0c2 100644 +--- a/fs/nfsd/state.h ++++ b/fs/nfsd/state.h +@@ -831,6 +831,7 @@ extern void nfsd4_shutdown_callback(struct nfs4_client *); + extern void nfsd4_shutdown_copy(struct nfs4_client *clp); + void nfsd4_async_copy_reaper(struct nfsd_net *nn); + bool nfsd4_has_active_async_copies(struct nfs4_client *clp); ++void nfsd_update_cmtime_attr(struct file *f, unsigned int flags); + extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj name, + struct xdr_netobj princhash, struct nfsd_net *nn); + extern bool nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn); +-- +2.53.0 + diff --git a/staging-6.18/nfsd-update-mtime-ctime-on-copy-in-presence-of-deleg.patch b/staging-6.18/nfsd-update-mtime-ctime-on-copy-in-presence-of-deleg.patch new file mode 100644 index 0000000000..dd27d538bd --- /dev/null +++ b/staging-6.18/nfsd-update-mtime-ctime-on-copy-in-presence-of-deleg.patch @@ -0,0 +1,78 @@ +From 5baa12ecda3d86229dcc96934f06da46ce01632c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:24:08 -0400 +Subject: nfsd: update mtime/ctime on COPY in presence of delegated attributes + +From: Olga Kornievskaia <okorniev@redhat.com> + +commit 4183cf383b6faec17a0882b84cd2d901dba62b16 upstream. + +When delegated attributes are given on open, the file is opened with +NOCMTIME and modifying operations do not update mtime/ctime as to not get +out-of-sync with the client's delegated view. However, for COPY operation, +the server should update its view of mtime/ctime and reflect that in any +GETATTR queries. + +Fixes: e5e9b24ab8fa ("nfsd: freeze c/mtime updates with outstanding WRITE_ATTRS delegation") +Cc: stable@vger.kernel.org +Signed-off-by: Olga Kornievskaia <okorniev@redhat.com> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4proc.c | 11 ++++++++++- + fs/nfsd/xdr4.h | 1 + + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c +index 5bfe49502a06f4..98086d217aa220 100644 +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -1956,8 +1956,10 @@ static int nfsd4_do_async_copy(void *data) + + set_bit(NFSD4_COPY_F_COMPLETED, ©->cp_flags); + trace_nfsd_copy_async_done(copy); +- nfsd4_send_cb_offload(copy); + atomic_dec(©->cp_nn->pending_async_copies); ++ if (copy->cp_res.wr_bytes_written > 0 && copy->attr_update) ++ nfsd_update_cmtime_attr(copy->nf_dst->nf_file, 0); ++ nfsd4_send_cb_offload(copy); + return 0; + } + +@@ -2017,6 +2019,9 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + memcpy(&result->cb_stateid, ©->cp_stateid.cs_stid, + sizeof(result->cb_stateid)); + dup_copy_fields(copy, async_copy); ++ if ((READ_ONCE(copy->nf_dst->nf_file->f_mode) & ++ FMODE_NOCMTIME) != 0) ++ async_copy->attr_update = true; + memcpy(async_copy->cp_cb_offload.co_referring_sessionid.data, + cstate->session->se_sessionid.data, + NFS4_MAX_SESSIONID_LEN); +@@ -2035,6 +2040,10 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + } else { + status = nfsd4_do_copy(copy, copy->nf_src->nf_file, + copy->nf_dst->nf_file, true); ++ if ((READ_ONCE(copy->nf_dst->nf_file->f_mode) & ++ FMODE_NOCMTIME) != 0 && ++ copy->cp_res.wr_bytes_written > 0) ++ nfsd_update_cmtime_attr(copy->nf_dst->nf_file, 0); + } + out: + trace_nfsd_copy_done(copy, status); +diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h +index 1ce8e12ae3354c..d0ef5e7f10778f 100644 +--- a/fs/nfsd/xdr4.h ++++ b/fs/nfsd/xdr4.h +@@ -745,6 +745,7 @@ struct nfsd4_copy { + + struct nfsd_file *nf_src; + struct nfsd_file *nf_dst; ++ bool attr_update; + + copy_stateid_t cp_stateid; + +-- +2.53.0 + diff --git a/staging-6.18/rust-str-clean-unused-import-for-rust-1.98.patch b/staging-6.18/rust-str-clean-unused-import-for-rust-1.98.patch new file mode 100644 index 0000000000..fe2d5e7828 --- /dev/null +++ b/staging-6.18/rust-str-clean-unused-import-for-rust-1.98.patch @@ -0,0 +1,53 @@ +From b6bf453231a442e2704299420b50d548709d8f15 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 9 Jun 2026 12:41:52 +0200 +Subject: rust: str: clean unused import for Rust >= 1.98 + +From: Miguel Ojeda <ojeda@kernel.org> + +[ Upstream commit 3fff4271809b57182c4011811e96556bdd4cb2f9 ] + +Starting with Rust 1.98.0 (expected 2026-08-20), the compiler has changed +how the resolution algorithm works [1] in upstream commit c4d84db5f184 +("Resolver: Batched import resolution."), and it now spots: + + error: unused import: `flags::*` + --> rust/kernel/str.rs:7:9 + | + 7 | flags::*, + | ^^^^^^^^ + | + = note: `-D unused-imports` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(unused_imports)]` + +It happens to not be needed because the `prelude::*` already provides +the flags. + +Thus clean it up. + +Cc: stable@vger.kernel.org # Needed in 6.18.y and later (prelude added to `str`). +Link: https://github.com/rust-lang/rust/pull/145108 [1] +Reviewed-by: Gary Guo <gary@garyguo.net> +Reviewed-by: Alice Ryhl <aliceryhl@google.com> +Link: https://patch.msgid.link/20260609104152.261145-2-ojeda@kernel.org +Signed-off-by: Miguel Ojeda <ojeda@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + rust/kernel/str.rs | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs +index 3a276bc32962d9..22cefbc9852360 100644 +--- a/rust/kernel/str.rs ++++ b/rust/kernel/str.rs +@@ -4,7 +4,6 @@ + + use crate::{ + alloc::{ +- flags::*, + AllocError, + KVec, // + }, +-- +2.53.0 + diff --git a/staging-6.18/rust-str-use-the-kernel-vertical-imports-style.patch b/staging-6.18/rust-str-use-the-kernel-vertical-imports-style.patch new file mode 100644 index 0000000000..2d0891c4c2 --- /dev/null +++ b/staging-6.18/rust-str-use-the-kernel-vertical-imports-style.patch @@ -0,0 +1,65 @@ +From a0fff564c0eccea685be81101d7c2a50cb71ff9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 9 Jun 2026 12:41:51 +0200 +Subject: rust: str: use the "kernel vertical" imports style + +From: Miguel Ojeda <ojeda@kernel.org> + +[ Upstream commit 724a93a9f6033800b02a3530dbcb464638448e7f ] + +Convert the imports to use the "kernel vertical" imports style [1]. + +No functional changes intended. + +Link: https://docs.kernel.org/rust/coding-guidelines.html#imports [1] +Reviewed-by: Gary Guo <gary@garyguo.net> +Link: https://patch.msgid.link/20260609104152.261145-1-ojeda@kernel.org +Signed-off-by: Miguel Ojeda <ojeda@kernel.org> +Stable-dep-of: 3fff4271809b ("rust: str: clean unused import for Rust >= 1.98") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + rust/kernel/str.rs | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs +index 8992fedabaf0f7..3a276bc32962d9 100644 +--- a/rust/kernel/str.rs ++++ b/rust/kernel/str.rs +@@ -3,14 +3,29 @@ + //! String representations. + + use crate::{ +- alloc::{flags::*, AllocError, KVec}, +- error::{to_result, Result}, +- fmt::{self, Write}, +- prelude::*, ++ alloc::{ ++ flags::*, ++ AllocError, ++ KVec, // ++ }, ++ error::{ ++ to_result, ++ Result, // ++ }, ++ fmt::{ ++ self, ++ Write, // ++ }, ++ prelude::*, // + }; + use core::{ + marker::PhantomData, +- ops::{self, Deref, DerefMut, Index}, ++ ops::{ ++ self, ++ Deref, ++ DerefMut, ++ Index, // ++ }, // + }; + + /// Byte string without UTF-8 validity guarantee. +-- +2.53.0 + diff --git a/staging-6.18/series b/staging-6.18/series index 5702e744cc..4170be490c 100644 --- a/staging-6.18/series +++ b/staging-6.18/series @@ -1 +1,8 @@ bpf-arm64-reject-out-of-range-b.cond-targets.patch +nfsd-update-mtime-ctime-on-clone-in-presense-of-dele.patch +nfsd-update-mtime-ctime-on-copy-in-presence-of-deleg.patch +nfsd-release-layout-stid-on-setlease-failure.patch +kernel-fork-clear-pf_block_ts-in-copy_process.patch +rust-str-use-the-kernel-vertical-imports-style.patch +rust-str-clean-unused-import-for-rust-1.98.patch +userfaultfd-gate-must_wait-writability-check-on-pte_.patch diff --git a/staging-6.18/userfaultfd-gate-must_wait-writability-check-on-pte_.patch b/staging-6.18/userfaultfd-gate-must_wait-writability-check-on-pte_.patch new file mode 100644 index 0000000000..d50b339d65 --- /dev/null +++ b/staging-6.18/userfaultfd-gate-must_wait-writability-check-on-pte_.patch @@ -0,0 +1,88 @@ +From 8e8e4086e0a1117a188b3f83a2b84aa2112de741 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:49:07 +0100 +Subject: userfaultfd: gate must_wait writability check on pte_present() + +From: Kiryl Shutsemau <kas@kernel.org> + +[ Upstream commit 8e80af52db652fbc41320eee45a4f73bc029faf2 ] + +userfaultfd_must_wait() and userfaultfd_huge_must_wait() read the PTE +without taking the page table lock and then apply pte_write() / +huge_pte_write() to it. Those accessors decode bits from the present +encoding only; on a swap or migration entry they read the offset bits that +happen to share the same position and return an undefined result. + +The intent of the check is "is this fault still WP-blocked?". A +non-marker swap entry means the page is in transit -- the userfault +context the original fault delivered against is no longer the same, and +the swap-in or migration completion path will re-deliver a fresh fault if +userspace still needs to handle it. Worst case under the current code the +garbage write bit says "wait", and the thread stays asleep until a +UFFDIO_WAKE that may never arrive. + +Gate the writability check on pte_present() so the lockless re-check only +inspects present-PTE bits when the entry is actually present. The +non-present, non-marker case returns "don't wait" and lets the fault path +retry. + +Link: https://lore.kernel.org/20260529172331.356655-6-kas@kernel.org +Fixes: 369cd2121be4 ("userfaultfd: hugetlbfs: userfaultfd_huge_must_wait for hugepmd ranges") +Fixes: 63b2d4174c4a ("userfaultfd: wp: add the writeprotect API to userfaultfd ioctl") +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Reported-by: Sashiko AI review <sashiko-bot@kernel.org> +Reviewed-by: Lorenzo Stoakes <ljs@kernel.org> +Cc: David Hildenbrand <david@kernel.org> +Cc: Michal Hocko <mhocko@suse.com> +Cc: Mike Rapoport <rppt@kernel.org> +Cc: Peter Xu <peterx@redhat.com> +Cc: Suren Baghdasaryan <surenb@google.com> +Cc: Vlastimil Babka <vbabka@kernel.org> +Cc: Balbir Singh <balbirs@nvidia.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> + +[ kas: apply to fs/userfaultfd.c and fold the pte_present()/ + huge_pte_present() gate into the existing writability checks; this tree + predates the marker/return-style refactor of these functions ] +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/userfaultfd.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c +index a67afdbbf77af1..7e40eb9131bd70 100644 +--- a/fs/userfaultfd.c ++++ b/fs/userfaultfd.c +@@ -251,7 +251,12 @@ static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx, + */ + if (huge_pte_none_mostly(pte)) + ret = true; +- if (!huge_pte_write(pte) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): huge_pte_write() on a ++ * non-present migration entry decodes random offset bits. The ++ * migration completion path re-delivers the fault if still needed. ++ */ ++ if (pte_present(pte) && !huge_pte_write(pte) && (reason & VM_UFFD_WP)) + ret = true; + out: + return ret; +@@ -326,7 +331,12 @@ static inline bool userfaultfd_must_wait(struct userfaultfd_ctx *ctx, + ptent = ptep_get(pte); + if (pte_none_mostly(ptent)) + ret = true; +- if (!pte_write(ptent) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): pte_write() on a ++ * non-present swap/migration entry decodes random offset bits. The ++ * page-in path re-delivers the fault if it still needs userspace. ++ */ ++ if (pte_present(ptent) && !pte_write(ptent) && (reason & VM_UFFD_WP)) + ret = true; + pte_unmap(pte); + +-- +2.53.0 + diff --git a/staging-6.6/bluetooth-btmtk-apply-the-common-btmtk_fw_get_filena.patch b/staging-6.6/bluetooth-btmtk-apply-the-common-btmtk_fw_get_filena.patch new file mode 100644 index 0000000000..4737f87361 --- /dev/null +++ b/staging-6.6/bluetooth-btmtk-apply-the-common-btmtk_fw_get_filena.patch @@ -0,0 +1,59 @@ +From cd09de42640fbefa66acb845eaf68bc2af47162c Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 15 May 2024 16:15:18 -0700 +Subject: Bluetooth: btmtk: apply the common btmtk_fw_get_filename + +From: Sean Wang <sean.wang@mediatek.com> + +[ Upstream commit 7f935b21bee4d8a9f26b57ae6c3682161b247809 ] + +Apply the common btmtk_fw_get_filename to avoid the similar coding in each +driver. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> +Stable-dep-of: 5c5e8c52e3ca ("Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/bluetooth/btmtksdio.c | 3 +++ + drivers/bluetooth/btusb.c | 10 ++-------- + 2 files changed, 5 insertions(+), 8 deletions(-) + +diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c +index e249aa7587833b..2be38c8e353efb 100644 +--- a/drivers/bluetooth/btmtksdio.c ++++ b/drivers/bluetooth/btmtksdio.c +@@ -1111,6 +1111,9 @@ static int btmtksdio_setup(struct hci_dev *hdev) + return err; + } + ++ btmtk_fw_get_filename(fwname, sizeof(fwname), dev_id, ++ fw_version, 0); ++ + snprintf(fwname, sizeof(fwname), + "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", + dev_id & 0xffff, (fw_version & 0xff) + 1); +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 9b2857a8e7ac1f..048929e336cf64 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2940,14 +2940,8 @@ static int btusb_mtk_setup(struct hci_dev *hdev) + case 0x7922: + case 0x7961: + case 0x7925: +- if (dev_id == 0x7925) +- snprintf(fw_bin_name, sizeof(fw_bin_name), +- "mediatek/mt%04x/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", +- dev_id & 0xffff, dev_id & 0xffff, (fw_version & 0xff) + 1); +- else +- snprintf(fw_bin_name, sizeof(fw_bin_name), +- "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", +- dev_id & 0xffff, (fw_version & 0xff) + 1); ++ btmtk_fw_get_filename(fw_bin_name, sizeof(fw_bin_name), dev_id, ++ fw_version, 0); + + err = btmtk_setup_firmware_79xx(hdev, fw_bin_name, + btmtk_usb_hci_wmt_sync); +-- +2.53.0 + diff --git a/staging-6.6/bluetooth-btmtk-fix-btmtk.c-undefined-reference-buil.patch b/staging-6.6/bluetooth-btmtk-fix-btmtk.c-undefined-reference-buil.patch new file mode 100644 index 0000000000..7457e615ff --- /dev/null +++ b/staging-6.6/bluetooth-btmtk-fix-btmtk.c-undefined-reference-buil.patch @@ -0,0 +1,74 @@ +From 42fbc2763ae4bf267900aa1fa7c048837ec2ce4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 19 Jul 2024 11:30:19 +0800 +Subject: Bluetooth: btmtk: Fix btmtk.c undefined reference build error + +From: Chris Lu <chris.lu@mediatek.com> + +[ Upstream commit f0c83a23fcbb424fdff5b38fbcdda3c04003a210 ] + +MediaTek moved some usb interface related function to btmtk.c which +may cause build failed if BT USB Kconfig wasn't enabled. +Fix undefined reference by adding config check. + +btmtk.c:(.text+0x89c): undefined reference to `usb_alloc_urb' +btmtk.c:(.text+0x8e3): undefined reference to `usb_free_urb' +btmtk.c:(.text+0x956): undefined reference to `usb_free_urb' +btmtk.c:(.text+0xa0e): undefined reference to `usb_anchor_urb' +btmtk.c:(.text+0xb43): undefined reference to `usb_autopm_get_interface' +btmtk.c:(.text+0xb7e): undefined reference to `usb_autopm_put_interface' +btmtk.c:(.text+0xf70): undefined reference to `usb_disable_autosuspend' +btmtk.c:(.text+0x133a): undefined reference to `usb_control_msg' + +Fixes: d019930b0049 ("Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c") +Reported-by: kernel test robot <lkp@intel.com> +Closes: https://lore.kernel.org/oe-kbuild-all/202407091928.AH0aGZnx-lkp@intel.com/ +Signed-off-by: Chris Lu <chris.lu@mediatek.com> +Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/bluetooth/btmtk.c | 2 ++ + drivers/bluetooth/btmtk.h | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c +index bd28a2d52af169..ab68c2cbd79e5e 100644 +--- a/drivers/bluetooth/btmtk.c ++++ b/drivers/bluetooth/btmtk.c +@@ -438,6 +438,7 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb) + } + EXPORT_SYMBOL_GPL(btmtk_process_coredump); + ++#if IS_ENABLED(CONFIG_BT_HCIBTUSB_MTK) + static void btmtk_usb_wmt_recv(struct urb *urb) + { + struct hci_dev *hdev = urb->context; +@@ -1162,6 +1163,7 @@ int btmtk_usb_shutdown(struct hci_dev *hdev) + return 0; + } + EXPORT_SYMBOL_GPL(btmtk_usb_shutdown); ++#endif + + MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); + MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>"); +diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h +index fe41528ae509bf..0acf8bd57c56e5 100644 +--- a/drivers/bluetooth/btmtk.h ++++ b/drivers/bluetooth/btmtk.h +@@ -189,11 +189,13 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb); + void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver, + u32 fw_flavor); + ++#if IS_ENABLED(CONFIG_BT_HCIBTUSB_MTK) + int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id); + + int btmtk_usb_setup(struct hci_dev *hdev); + + int btmtk_usb_shutdown(struct hci_dev *hdev); ++#endif + #else + + static inline int btmtk_set_bdaddr(struct hci_dev *hdev, +-- +2.53.0 + diff --git a/staging-6.6/bluetooth-btmtk-fix-failed-to-send-func-ctrl-for-med.patch b/staging-6.6/bluetooth-btmtk-fix-failed-to-send-func-ctrl-for-med.patch new file mode 100644 index 0000000000..13fd8db729 --- /dev/null +++ b/staging-6.6/bluetooth-btmtk-fix-failed-to-send-func-ctrl-for-med.patch @@ -0,0 +1,83 @@ +From 7e5aab02d869df92ae054b61665579c65707b250 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 8 Jan 2025 17:50:28 +0800 +Subject: Bluetooth: btmtk: Fix failed to send func ctrl for MediaTek devices. + +From: Chris Lu <chris.lu@mediatek.com> + +[ Upstream commit 67dba2c28fe0af7e25ea1aeade677162ed05310a ] + +Use usb_autopm_get_interface() and usb_autopm_put_interface() +in btmtk_usb_shutdown(), it could send func ctrl after enabling +autosuspend. + +Bluetooth: btmtk_usb_hci_wmt_sync() hci0: Execution of wmt command + timed out +Bluetooth: btmtk_usb_shutdown() hci0: Failed to send wmt func ctrl + (-110) + +Fixes: 5c5e8c52e3ca ("Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c") +Signed-off-by: Chris Lu <chris.lu@mediatek.com> +Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/bluetooth/btmtk.c | 7 +++++++ + net/bluetooth/rfcomm/tty.c | 4 ++-- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c +index 8fd923de47c1f3..29d4a04ea0d46a 100644 +--- a/drivers/bluetooth/btmtk.c ++++ b/drivers/bluetooth/btmtk.c +@@ -1140,10 +1140,15 @@ EXPORT_SYMBOL_GPL(btmtk_usb_setup); + + int btmtk_usb_shutdown(struct hci_dev *hdev) + { ++ struct btmtk_data *data = hci_get_priv(hdev); + struct btmtk_hci_wmt_params wmt_params; + u8 param = 0; + int err; + ++ err = usb_autopm_get_interface(data->intf); ++ if (err < 0) ++ return err; ++ + /* Disable the device */ + wmt_params.op = BTMTK_WMT_FUNC_CTRL; + wmt_params.flag = 0; +@@ -1154,9 +1159,11 @@ int btmtk_usb_shutdown(struct hci_dev *hdev) + err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); ++ usb_autopm_put_interface(data->intf); + return err; + } + ++ usb_autopm_put_interface(data->intf); + return 0; + } + EXPORT_SYMBOL_GPL(btmtk_usb_shutdown); +diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c +index 912e37cb8310c6..389d7b47ad6132 100644 +--- a/net/bluetooth/rfcomm/tty.c ++++ b/net/bluetooth/rfcomm/tty.c +@@ -201,14 +201,14 @@ static ssize_t address_show(struct device *tty_dev, + struct device_attribute *attr, char *buf) + { + struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); +- return sprintf(buf, "%pMR\n", &dev->dst); ++ return sysfs_emit(buf, "%pMR\n", &dev->dst); + } + + static ssize_t channel_show(struct device *tty_dev, + struct device_attribute *attr, char *buf) + { + struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); +- return sprintf(buf, "%d\n", dev->channel); ++ return sysfs_emit(buf, "%d\n", dev->channel); + } + + static DEVICE_ATTR_RO(address); +-- +2.53.0 + diff --git a/staging-6.6/bluetooth-btmtk-fix-wait_on_bit_timeout-interruption.patch b/staging-6.6/bluetooth-btmtk-fix-wait_on_bit_timeout-interruption.patch new file mode 100644 index 0000000000..c8fd449b80 --- /dev/null +++ b/staging-6.6/bluetooth-btmtk-fix-wait_on_bit_timeout-interruption.patch @@ -0,0 +1,46 @@ +From 56bc657c16594a632cfb6c958c084ff1a34888e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 24 Jul 2025 16:51:17 +0800 +Subject: Bluetooth: btmtk: Fix wait_on_bit_timeout interruption during + shutdown + +From: Jiande Lu <jiande.lu@mediatek.com> + +[ Upstream commit 099799fa9b76c5c02b49e07005a85117a25b01ea ] + +During the shutdown process, an interrupt occurs that +prematurely terminates the wait for the expected event. +This change replaces TASK_INTERRUPTIBLE with +TASK_UNINTERRUPTIBLE in the wait_on_bit_timeout call to ensure +the shutdown process completes as intended without being +interrupted by signals. + +Fixes: d019930b0049 ("Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c") +Signed-off-by: Jiande Lu <jiande.lu@mediatek.com> +Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/bluetooth/btmtk.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c +index 29d4a04ea0d46a..bd28a2d52af169 100644 +--- a/drivers/bluetooth/btmtk.c ++++ b/drivers/bluetooth/btmtk.c +@@ -640,12 +640,7 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev, + * WMT command. + */ + err = wait_on_bit_timeout(&data->flags, BTMTK_TX_WAIT_VND_EVT, +- TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT); +- if (err == -EINTR) { +- bt_dev_err(hdev, "Execution of wmt command interrupted"); +- clear_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags); +- goto err_free_wc; +- } ++ TASK_UNINTERRUPTIBLE, HCI_INIT_TIMEOUT); + + if (err) { + bt_dev_err(hdev, "Execution of wmt command timed out"); +-- +2.53.0 + diff --git a/staging-6.6/bluetooth-btmtk-move-btusb_mtk_-setup-shutdown-to-bt.patch b/staging-6.6/bluetooth-btmtk-move-btusb_mtk_-setup-shutdown-to-bt.patch new file mode 100644 index 0000000000..01dab2d2b2 --- /dev/null +++ b/staging-6.6/bluetooth-btmtk-move-btusb_mtk_-setup-shutdown-to-bt.patch @@ -0,0 +1,1046 @@ +From aaf2333ff22b4422b4762e3098abcfd1697e7102 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 4 Jul 2024 14:01:14 +0800 +Subject: Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c + +From: Chris Lu <chris.lu@mediatek.com> + +[ Upstream commit 5c5e8c52e3cafaa6f71efd44a42a674271e5b3ad ] + +Move btusb_mtk_[setup, shutdown] and related function from +btusb.c to btmtk.c which holds vendor specific stuff and +would make btusb.c clean. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Chris Lu <chris.lu@mediatek.com> +Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/bluetooth/btmtk.c | 454 +++++++++++++++++++++++++++++++++++++- + drivers/bluetooth/btmtk.h | 23 +- + drivers/bluetooth/btusb.c | 446 ++----------------------------------- + 3 files changed, 484 insertions(+), 439 deletions(-) + +diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c +index 582915f9a8d700..8fd923de47c1f3 100644 +--- a/drivers/bluetooth/btmtk.c ++++ b/drivers/bluetooth/btmtk.c +@@ -5,6 +5,8 @@ + #include <linux/module.h> + #include <linux/firmware.h> + #include <linux/usb.h> ++#include <linux/iopoll.h> ++#include <asm/unaligned.h> + + #include <net/bluetooth/bluetooth.h> + #include <net/bluetooth/hci_core.h> +@@ -573,8 +575,8 @@ static int btmtk_usb_submit_wmt_recv_urb(struct hci_dev *hdev) + return err; + } + +-int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev, +- struct btmtk_hci_wmt_params *wmt_params) ++static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev, ++ struct btmtk_hci_wmt_params *wmt_params) + { + struct btmtk_data *data = hci_get_priv(hdev); + struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc; +@@ -711,7 +713,453 @@ int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev, + kfree(wc); + return err; + } +-EXPORT_SYMBOL_GPL(btmtk_usb_hci_wmt_sync); ++ ++static int btmtk_usb_func_query(struct hci_dev *hdev) ++{ ++ struct btmtk_hci_wmt_params wmt_params; ++ int status, err; ++ u8 param = 0; ++ ++ /* Query whether the function is enabled */ ++ wmt_params.op = BTMTK_WMT_FUNC_CTRL; ++ wmt_params.flag = 4; ++ wmt_params.dlen = sizeof(param); ++ wmt_params.data = ¶m; ++ wmt_params.status = &status; ++ ++ err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to query function status (%d)", err); ++ return err; ++ } ++ ++ return status; ++} ++ ++static int btmtk_usb_uhw_reg_write(struct hci_dev *hdev, u32 reg, u32 val) ++{ ++ struct btmtk_data *data = hci_get_priv(hdev); ++ int pipe, err; ++ void *buf; ++ ++ buf = kzalloc(4, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ put_unaligned_le32(val, buf); ++ ++ pipe = usb_sndctrlpipe(data->udev, 0); ++ err = usb_control_msg(data->udev, pipe, 0x02, ++ 0x5E, ++ reg >> 16, reg & 0xffff, ++ buf, 4, USB_CTRL_SET_TIMEOUT); ++ if (err < 0) ++ bt_dev_err(hdev, "Failed to write uhw reg(%d)", err); ++ ++ kfree(buf); ++ ++ return err; ++} ++ ++static int btmtk_usb_uhw_reg_read(struct hci_dev *hdev, u32 reg, u32 *val) ++{ ++ struct btmtk_data *data = hci_get_priv(hdev); ++ int pipe, err; ++ void *buf; ++ ++ buf = kzalloc(4, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ pipe = usb_rcvctrlpipe(data->udev, 0); ++ err = usb_control_msg(data->udev, pipe, 0x01, ++ 0xDE, ++ reg >> 16, reg & 0xffff, ++ buf, 4, USB_CTRL_GET_TIMEOUT); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to read uhw reg(%d)", err); ++ goto err_free_buf; ++ } ++ ++ *val = get_unaligned_le32(buf); ++ bt_dev_dbg(hdev, "reg=%x, value=0x%08x", reg, *val); ++ ++err_free_buf: ++ kfree(buf); ++ ++ return err; ++} ++ ++static int btmtk_usb_reg_read(struct hci_dev *hdev, u32 reg, u32 *val) ++{ ++ struct btmtk_data *data = hci_get_priv(hdev); ++ int pipe, err, size = sizeof(u32); ++ void *buf; ++ ++ buf = kzalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ pipe = usb_rcvctrlpipe(data->udev, 0); ++ err = usb_control_msg(data->udev, pipe, 0x63, ++ USB_TYPE_VENDOR | USB_DIR_IN, ++ reg >> 16, reg & 0xffff, ++ buf, size, USB_CTRL_GET_TIMEOUT); ++ if (err < 0) ++ goto err_free_buf; ++ ++ *val = get_unaligned_le32(buf); ++ ++err_free_buf: ++ kfree(buf); ++ ++ return err; ++} ++ ++static int btmtk_usb_id_get(struct hci_dev *hdev, u32 reg, u32 *id) ++{ ++ return btmtk_usb_reg_read(hdev, reg, id); ++} ++ ++static u32 btmtk_usb_reset_done(struct hci_dev *hdev) ++{ ++ u32 val = 0; ++ ++ btmtk_usb_uhw_reg_read(hdev, MTK_BT_MISC, &val); ++ ++ return val & MTK_BT_RST_DONE; ++} ++ ++int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id) ++{ ++ u32 val; ++ int err; ++ ++ if (dev_id == 0x7922) { ++ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val); ++ if (err < 0) ++ return err; ++ val |= 0x00002020; ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, val); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_EP_RST_OPT, 0x00010001); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val); ++ if (err < 0) ++ return err; ++ val |= BIT(0); ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, val); ++ if (err < 0) ++ return err; ++ msleep(100); ++ } else if (dev_id == 0x7925) { ++ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val); ++ if (err < 0) ++ return err; ++ val |= (1 << 5); ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val); ++ if (err < 0) ++ return err; ++ val &= 0xFFFF00FF; ++ val |= (1 << 13); ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_EP_RST_OPT, 0x00010001); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val); ++ if (err < 0) ++ return err; ++ val |= (1 << 0); ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT, 0x000000FF); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT, &val); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT1, 0x000000FF); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT1, &val); ++ if (err < 0) ++ return err; ++ msleep(100); ++ } else { ++ /* It's Device EndPoint Reset Option Register */ ++ bt_dev_dbg(hdev, "Initiating reset mechanism via uhw"); ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_WDT_STATUS, &val); ++ if (err < 0) ++ return err; ++ /* Reset the bluetooth chip via USB interface. */ ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, 1); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT, 0x000000FF); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT, &val); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT1, 0x000000FF); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT1, &val); ++ if (err < 0) ++ return err; ++ /* MT7921 need to delay 20ms between toggle reset bit */ ++ msleep(20); ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, 0); ++ if (err < 0) ++ return err; ++ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val); ++ if (err < 0) ++ return err; ++ } ++ ++ err = readx_poll_timeout(btmtk_usb_reset_done, hdev, val, ++ val & MTK_BT_RST_DONE, 20000, 1000000); ++ if (err < 0) ++ bt_dev_err(hdev, "Reset timeout"); ++ ++ if (dev_id == 0x7922) { ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT, 0x000000FF); ++ if (err < 0) ++ return err; ++ } ++ ++ err = btmtk_usb_id_get(hdev, 0x70010200, &val); ++ if (err < 0 || !val) ++ bt_dev_err(hdev, "Can't get device id, subsys reset fail."); ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(btmtk_usb_subsys_reset); ++ ++int btmtk_usb_setup(struct hci_dev *hdev) ++{ ++ struct btmtk_data *btmtk_data = hci_get_priv(hdev); ++ struct btmtk_hci_wmt_params wmt_params; ++ ktime_t calltime, delta, rettime; ++ struct btmtk_tci_sleep tci_sleep; ++ unsigned long long duration; ++ struct sk_buff *skb; ++ const char *fwname; ++ int err, status; ++ u32 dev_id = 0; ++ char fw_bin_name[64]; ++ u32 fw_version = 0, fw_flavor = 0; ++ u8 param; ++ ++ calltime = ktime_get(); ++ ++ err = btmtk_usb_id_get(hdev, 0x80000008, &dev_id); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to get device id (%d)", err); ++ return err; ++ } ++ ++ if (!dev_id || dev_id != 0x7663) { ++ err = btmtk_usb_id_get(hdev, 0x70010200, &dev_id); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to get device id (%d)", err); ++ return err; ++ } ++ err = btmtk_usb_id_get(hdev, 0x80021004, &fw_version); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to get fw version (%d)", err); ++ return err; ++ } ++ err = btmtk_usb_id_get(hdev, 0x70010020, &fw_flavor); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to get fw flavor (%d)", err); ++ return err; ++ } ++ fw_flavor = (fw_flavor & 0x00000080) >> 7; ++ } ++ ++ btmtk_data->dev_id = dev_id; ++ ++ err = btmtk_register_coredump(hdev, btmtk_data->drv_name, fw_version); ++ if (err < 0) ++ bt_dev_err(hdev, "Failed to register coredump (%d)", err); ++ ++ switch (dev_id) { ++ case 0x7663: ++ fwname = FIRMWARE_MT7663; ++ break; ++ case 0x7668: ++ fwname = FIRMWARE_MT7668; ++ break; ++ case 0x7922: ++ case 0x7961: ++ case 0x7925: ++ /* Reset the device to ensure it's in the initial state before ++ * downloading the firmware to ensure. ++ */ ++ ++ if (!test_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags)) ++ btmtk_usb_subsys_reset(hdev, dev_id); ++ ++ btmtk_fw_get_filename(fw_bin_name, sizeof(fw_bin_name), dev_id, ++ fw_version, fw_flavor); ++ ++ err = btmtk_setup_firmware_79xx(hdev, fw_bin_name, ++ btmtk_usb_hci_wmt_sync); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to set up firmware (%d)", err); ++ clear_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags); ++ return err; ++ } ++ ++ set_bit(BTMTK_FIRMWARE_LOADED, &btmtk_data->flags); ++ ++ /* It's Device EndPoint Reset Option Register */ ++ err = btmtk_usb_uhw_reg_write(hdev, MTK_EP_RST_OPT, ++ MTK_EP_RST_IN_OUT_OPT); ++ if (err < 0) ++ return err; ++ ++ /* Enable Bluetooth protocol */ ++ param = 1; ++ wmt_params.op = BTMTK_WMT_FUNC_CTRL; ++ wmt_params.flag = 0; ++ wmt_params.dlen = sizeof(param); ++ wmt_params.data = ¶m; ++ wmt_params.status = NULL; ++ ++ err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); ++ return err; ++ } ++ ++ hci_set_msft_opcode(hdev, 0xFD30); ++ hci_set_aosp_capable(hdev); ++ ++ goto done; ++ default: ++ bt_dev_err(hdev, "Unsupported hardware variant (%08x)", ++ dev_id); ++ return -ENODEV; ++ } ++ ++ /* Query whether the firmware is already download */ ++ wmt_params.op = BTMTK_WMT_SEMAPHORE; ++ wmt_params.flag = 1; ++ wmt_params.dlen = 0; ++ wmt_params.data = NULL; ++ wmt_params.status = &status; ++ ++ err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to query firmware status (%d)", err); ++ return err; ++ } ++ ++ if (status == BTMTK_WMT_PATCH_DONE) { ++ bt_dev_info(hdev, "firmware already downloaded"); ++ goto ignore_setup_fw; ++ } ++ ++ /* Setup a firmware which the device definitely requires */ ++ err = btmtk_setup_firmware(hdev, fwname, ++ btmtk_usb_hci_wmt_sync); ++ if (err < 0) ++ return err; ++ ++ignore_setup_fw: ++ err = readx_poll_timeout(btmtk_usb_func_query, hdev, status, ++ status < 0 || status != BTMTK_WMT_ON_PROGRESS, ++ 2000, 5000000); ++ /* -ETIMEDOUT happens */ ++ if (err < 0) ++ return err; ++ ++ /* The other errors happen in btmtk_usb_func_query */ ++ if (status < 0) ++ return status; ++ ++ if (status == BTMTK_WMT_ON_DONE) { ++ bt_dev_info(hdev, "function already on"); ++ goto ignore_func_on; ++ } ++ ++ /* Enable Bluetooth protocol */ ++ param = 1; ++ wmt_params.op = BTMTK_WMT_FUNC_CTRL; ++ wmt_params.flag = 0; ++ wmt_params.dlen = sizeof(param); ++ wmt_params.data = ¶m; ++ wmt_params.status = NULL; ++ ++ err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); ++ return err; ++ } ++ ++ignore_func_on: ++ /* Apply the low power environment setup */ ++ tci_sleep.mode = 0x5; ++ tci_sleep.duration = cpu_to_le16(0x640); ++ tci_sleep.host_duration = cpu_to_le16(0x640); ++ tci_sleep.host_wakeup_pin = 0; ++ tci_sleep.time_compensation = 0; ++ ++ skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep, ++ HCI_INIT_TIMEOUT); ++ if (IS_ERR(skb)) { ++ err = PTR_ERR(skb); ++ bt_dev_err(hdev, "Failed to apply low power setting (%d)", err); ++ return err; ++ } ++ kfree_skb(skb); ++ ++done: ++ rettime = ktime_get(); ++ delta = ktime_sub(rettime, calltime); ++ duration = (unsigned long long)ktime_to_ns(delta) >> 10; ++ ++ bt_dev_info(hdev, "Device setup in %llu usecs", duration); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(btmtk_usb_setup); ++ ++int btmtk_usb_shutdown(struct hci_dev *hdev) ++{ ++ struct btmtk_hci_wmt_params wmt_params; ++ u8 param = 0; ++ int err; ++ ++ /* Disable the device */ ++ wmt_params.op = BTMTK_WMT_FUNC_CTRL; ++ wmt_params.flag = 0; ++ wmt_params.dlen = sizeof(param); ++ wmt_params.data = ¶m; ++ wmt_params.status = NULL; ++ ++ err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); ++ return err; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(btmtk_usb_shutdown); + + MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); + MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>"); +diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h +index 3055b9728ae250..fe41528ae509bf 100644 +--- a/drivers/bluetooth/btmtk.h ++++ b/drivers/bluetooth/btmtk.h +@@ -140,6 +140,8 @@ struct btmtk_hci_wmt_params { + + enum { + BTMTK_TX_WAIT_VND_EVT, ++ BTMTK_FIRMWARE_LOADED, ++ BTMTK_HW_RESET_ACTIVE, + }; + + typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *); +@@ -152,6 +154,7 @@ struct btmtk_coredump_info { + }; + + struct btmtk_data { ++ const char *drv_name; + unsigned long flags; + u32 dev_id; + btmtk_reset_sync_func_t reset_sync; +@@ -186,8 +189,11 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb); + void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver, + u32 fw_flavor); + +-int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev, +- struct btmtk_hci_wmt_params *wmt_params); ++int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id); ++ ++int btmtk_usb_setup(struct hci_dev *hdev); ++ ++int btmtk_usb_shutdown(struct hci_dev *hdev); + #else + + static inline int btmtk_set_bdaddr(struct hci_dev *hdev, +@@ -228,8 +234,17 @@ static void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, + { + } + +-static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev, +- struct btmtk_hci_wmt_params *wmt_params) ++static int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int btmtk_usb_setup(struct hci_dev *hdev) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int btmtk_usb_shutdown(struct hci_dev *hdev) + { + return -EOPNOTSUPP; + } +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index a7aa4c1dacb295..86c2aac507d673 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2686,241 +2686,6 @@ static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb) + return hci_recv_frame(hdev, skb); + } + +-static int btusb_mtk_func_query(struct hci_dev *hdev) +-{ +- struct btmtk_hci_wmt_params wmt_params; +- int status, err; +- u8 param = 0; +- +- /* Query whether the function is enabled */ +- wmt_params.op = BTMTK_WMT_FUNC_CTRL; +- wmt_params.flag = 4; +- wmt_params.dlen = sizeof(param); +- wmt_params.data = ¶m; +- wmt_params.status = &status; +- +- err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params); +- if (err < 0) { +- bt_dev_err(hdev, "Failed to query function status (%d)", err); +- return err; +- } +- +- return status; +-} +- +-static int btusb_mtk_uhw_reg_write(struct btusb_data *data, u32 reg, u32 val) +-{ +- struct hci_dev *hdev = data->hdev; +- int pipe, err; +- void *buf; +- +- buf = kzalloc(4, GFP_KERNEL); +- if (!buf) +- return -ENOMEM; +- +- put_unaligned_le32(val, buf); +- +- pipe = usb_sndctrlpipe(data->udev, 0); +- err = usb_control_msg(data->udev, pipe, 0x02, +- 0x5E, +- reg >> 16, reg & 0xffff, +- buf, 4, USB_CTRL_SET_TIMEOUT); +- if (err < 0) +- bt_dev_err(hdev, "Failed to write uhw reg(%d)", err); +- +- kfree(buf); +- +- return err; +-} +- +-static int btusb_mtk_uhw_reg_read(struct btusb_data *data, u32 reg, u32 *val) +-{ +- struct hci_dev *hdev = data->hdev; +- int pipe, err; +- void *buf; +- +- buf = kzalloc(4, GFP_KERNEL); +- if (!buf) +- return -ENOMEM; +- +- pipe = usb_rcvctrlpipe(data->udev, 0); +- err = usb_control_msg(data->udev, pipe, 0x01, +- 0xDE, +- reg >> 16, reg & 0xffff, +- buf, 4, USB_CTRL_SET_TIMEOUT); +- if (err < 0) { +- bt_dev_err(hdev, "Failed to read uhw reg(%d)", err); +- goto err_free_buf; +- } +- +- *val = get_unaligned_le32(buf); +- bt_dev_dbg(hdev, "reg=%x, value=0x%08x", reg, *val); +- +-err_free_buf: +- kfree(buf); +- +- return err; +-} +- +-static int btusb_mtk_reg_read(struct btusb_data *data, u32 reg, u32 *val) +-{ +- int pipe, err, size = sizeof(u32); +- void *buf; +- +- buf = kzalloc(size, GFP_KERNEL); +- if (!buf) +- return -ENOMEM; +- +- pipe = usb_rcvctrlpipe(data->udev, 0); +- err = usb_control_msg(data->udev, pipe, 0x63, +- USB_TYPE_VENDOR | USB_DIR_IN, +- reg >> 16, reg & 0xffff, +- buf, size, USB_CTRL_SET_TIMEOUT); +- if (err < 0) +- goto err_free_buf; +- +- *val = get_unaligned_le32(buf); +- +-err_free_buf: +- kfree(buf); +- +- return err; +-} +- +-static int btusb_mtk_id_get(struct btusb_data *data, u32 reg, u32 *id) +-{ +- return btusb_mtk_reg_read(data, reg, id); +-} +- +-static u32 btusb_mtk_reset_done(struct hci_dev *hdev) +-{ +- struct btusb_data *data = hci_get_drvdata(hdev); +- u32 val = 0; +- +- btusb_mtk_uhw_reg_read(data, MTK_BT_MISC, &val); +- +- return val & MTK_BT_RST_DONE; +-} +- +-static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id) +-{ +- struct btusb_data *data = hci_get_drvdata(hdev); +- u32 val; +- int err; +- +- if (dev_id == 0x7922) { +- err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); +- if (err < 0) +- return err; +- val |= 0x00002020; +- err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); +- if (err < 0) +- return err; +- val |= BIT(0); +- err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val); +- if (err < 0) +- return err; +- msleep(100); +- } else if (dev_id == 0x7925) { +- err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); +- if (err < 0) +- return err; +- val |= (1 << 5); +- err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); +- if (err < 0) +- return err; +- val &= 0xFFFF00FF; +- if (err < 0) +- return err; +- val |= (1 << 13); +- err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); +- if (err < 0) +- return err; +- val |= (1 << 0); +- err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val); +- if (err < 0) +- return err; +- msleep(100); +- } else { +- /* It's Device EndPoint Reset Option Register */ +- bt_dev_dbg(hdev, "Initiating reset mechanism via uhw"); +- err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val); +- if (err < 0) +- return err; +- /* Reset the bluetooth chip via USB interface. */ +- err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val); +- if (err < 0) +- return err; +- /* MT7921 need to delay 20ms between toggle reset bit */ +- msleep(20); +- err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0); +- if (err < 0) +- return err; +- err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); +- if (err < 0) +- return err; +- } +- +- err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val, +- val & MTK_BT_RST_DONE, 20000, 1000000); +- if (err < 0) +- bt_dev_err(hdev, "Reset timeout"); +- +- if (dev_id == 0x7922) { +- err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); +- if (err < 0) +- return err; +- } +- +- err = btusb_mtk_id_get(data, 0x70010200, &val); +- if (err < 0 || !val) +- bt_dev_err(hdev, "Can't get device id, subsys reset fail."); +- +- return err; +-} +- + static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data) + { + struct btusb_data *data = hci_get_drvdata(hdev); +@@ -2928,7 +2693,7 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data) + int err; + + /* It's MediaTek specific bluetooth reset mechanism via USB */ +- if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) { ++ if (test_and_set_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags)) { + bt_dev_err(hdev, "last reset failed? Not resetting again"); + return -EBUSY; + } +@@ -2940,10 +2705,10 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data) + btusb_stop_traffic(data); + usb_kill_anchored_urbs(&data->tx_anchor); + +- err = btusb_mtk_subsys_reset(hdev, btmtk_data->dev_id); ++ err = btmtk_usb_subsys_reset(hdev, btmtk_data->dev_id); + + usb_queue_reset_device(data->intf); +- clear_bit(BTUSB_HW_RESET_ACTIVE, &data->flags); ++ clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags); + + return err; + } +@@ -2951,206 +2716,23 @@ static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data) + static int btusb_mtk_setup(struct hci_dev *hdev) + { + struct btusb_data *data = hci_get_drvdata(hdev); +- struct btmtk_hci_wmt_params wmt_params; +- ktime_t calltime, delta, rettime; +- struct btmtk_tci_sleep tci_sleep; +- unsigned long long duration; +- struct sk_buff *skb; +- const char *fwname; +- int err, status; +- u32 dev_id = 0; +- char fw_bin_name[64]; +- u32 fw_version = 0; +- u8 param; +- struct btmtk_data *mediatek; +- +- calltime = ktime_get(); +- +- err = btusb_mtk_id_get(data, 0x80000008, &dev_id); +- if (err < 0) { +- bt_dev_err(hdev, "Failed to get device id (%d)", err); +- return err; +- } +- +- if (!dev_id || dev_id != 0x7663) { +- err = btusb_mtk_id_get(data, 0x70010200, &dev_id); +- if (err < 0) { +- bt_dev_err(hdev, "Failed to get device id (%d)", err); +- return err; +- } +- err = btusb_mtk_id_get(data, 0x80021004, &fw_version); +- if (err < 0) { +- bt_dev_err(hdev, "Failed to get fw version (%d)", err); +- return err; +- } +- } +- +- mediatek = hci_get_priv(hdev); +- mediatek->dev_id = dev_id; +- mediatek->reset_sync = btusb_mtk_reset; +- +- err = btmtk_register_coredump(hdev, btusb_driver.name, fw_version); +- if (err < 0) +- bt_dev_err(hdev, "Failed to register coredump (%d)", err); +- +- switch (dev_id) { +- case 0x7663: +- fwname = FIRMWARE_MT7663; +- break; +- case 0x7668: +- fwname = FIRMWARE_MT7668; +- break; +- case 0x7922: +- case 0x7961: +- case 0x7925: +- /* Reset the device to ensure it's in the initial state before +- * downloading the firmware to ensure. +- */ +- +- if (!test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) +- btusb_mtk_subsys_reset(hdev, dev_id); +- +- btmtk_fw_get_filename(fw_bin_name, sizeof(fw_bin_name), dev_id, +- fw_version, 0); +- +- err = btmtk_setup_firmware_79xx(hdev, fw_bin_name, +- btmtk_usb_hci_wmt_sync); +- if (err < 0) { +- bt_dev_err(hdev, "Failed to set up firmware (%d)", err); +- clear_bit(BTUSB_FIRMWARE_LOADED, &data->flags); +- return err; +- } +- +- set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); +- +- /* It's Device EndPoint Reset Option Register */ +- btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); +- +- /* Enable Bluetooth protocol */ +- param = 1; +- wmt_params.op = BTMTK_WMT_FUNC_CTRL; +- wmt_params.flag = 0; +- wmt_params.dlen = sizeof(param); +- wmt_params.data = ¶m; +- wmt_params.status = NULL; +- +- err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params); +- if (err < 0) { +- bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); +- return err; +- } +- +- hci_set_msft_opcode(hdev, 0xFD30); +- hci_set_aosp_capable(hdev); +- goto done; +- default: +- bt_dev_err(hdev, "Unsupported hardware variant (%08x)", +- dev_id); +- return -ENODEV; +- } +- +- /* Query whether the firmware is already download */ +- wmt_params.op = BTMTK_WMT_SEMAPHORE; +- wmt_params.flag = 1; +- wmt_params.dlen = 0; +- wmt_params.data = NULL; +- wmt_params.status = &status; +- +- err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params); +- if (err < 0) { +- bt_dev_err(hdev, "Failed to query firmware status (%d)", err); +- return err; +- } +- +- if (status == BTMTK_WMT_PATCH_DONE) { +- bt_dev_info(hdev, "firmware already downloaded"); +- goto ignore_setup_fw; +- } +- +- /* Setup a firmware which the device definitely requires */ +- err = btmtk_setup_firmware(hdev, fwname, +- btmtk_usb_hci_wmt_sync); +- if (err < 0) +- return err; +- +-ignore_setup_fw: +- err = readx_poll_timeout(btusb_mtk_func_query, hdev, status, +- status < 0 || status != BTMTK_WMT_ON_PROGRESS, +- 2000, 5000000); +- /* -ETIMEDOUT happens */ +- if (err < 0) +- return err; +- +- /* The other errors happen in btusb_mtk_func_query */ +- if (status < 0) +- return status; +- +- if (status == BTMTK_WMT_ON_DONE) { +- bt_dev_info(hdev, "function already on"); +- goto ignore_func_on; +- } +- +- /* Enable Bluetooth protocol */ +- param = 1; +- wmt_params.op = BTMTK_WMT_FUNC_CTRL; +- wmt_params.flag = 0; +- wmt_params.dlen = sizeof(param); +- wmt_params.data = ¶m; +- wmt_params.status = NULL; +- +- err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params); +- if (err < 0) { +- bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); +- return err; +- } +- +-ignore_func_on: +- /* Apply the low power environment setup */ +- tci_sleep.mode = 0x5; +- tci_sleep.duration = cpu_to_le16(0x640); +- tci_sleep.host_duration = cpu_to_le16(0x640); +- tci_sleep.host_wakeup_pin = 0; +- tci_sleep.time_compensation = 0; +- +- skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep, +- HCI_INIT_TIMEOUT); +- if (IS_ERR(skb)) { +- err = PTR_ERR(skb); +- bt_dev_err(hdev, "Failed to apply low power setting (%d)", err); +- return err; +- } +- kfree_skb(skb); +- +-done: +- rettime = ktime_get(); +- delta = ktime_sub(rettime, calltime); +- duration = (unsigned long long)ktime_to_ns(delta) >> 10; ++ struct btmtk_data *btmtk_data = hci_get_priv(hdev); + +- bt_dev_info(hdev, "Device setup in %llu usecs", duration); ++ /* MediaTek WMT vendor cmd requiring below USB resources to ++ * complete the handshake. ++ */ ++ btmtk_data->drv_name = btusb_driver.name; ++ btmtk_data->intf = data->intf; ++ btmtk_data->udev = data->udev; ++ btmtk_data->ctrl_anchor = &data->ctrl_anchor; ++ btmtk_data->reset_sync = btusb_mtk_reset; + +- return 0; ++ return btmtk_usb_setup(hdev); + } + + static int btusb_mtk_shutdown(struct hci_dev *hdev) + { +- struct btmtk_hci_wmt_params wmt_params; +- u8 param = 0; +- int err; +- +- /* Disable the device */ +- wmt_params.op = BTMTK_WMT_FUNC_CTRL; +- wmt_params.flag = 0; +- wmt_params.dlen = sizeof(param); +- wmt_params.data = ¶m; +- wmt_params.status = NULL; +- +- err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params); +- if (err < 0) { +- bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); +- return err; +- } +- +- return 0; ++ return btmtk_usb_shutdown(hdev); + } + + static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb) +-- +2.53.0 + diff --git a/staging-6.6/bluetooth-btusb-mediatek-add-mt7922-subsystem-reset.patch b/staging-6.6/bluetooth-btusb-mediatek-add-mt7922-subsystem-reset.patch new file mode 100644 index 0000000000..fab63dc09c --- /dev/null +++ b/staging-6.6/bluetooth-btusb-mediatek-add-mt7922-subsystem-reset.patch @@ -0,0 +1,58 @@ +From 982f08ceb2462f927e8d41e7ec225b0788da2197 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 15 May 2024 16:15:21 -0700 +Subject: Bluetooth: btusb: mediatek: add MT7922 subsystem reset + +From: Hao Qin <hao.qin@mediatek.com> + +[ Upstream commit 064aee501012eaeeeb40a2acb991598e0a89fac9 ] + +Add the support of MT7922 bluetooth subsystem reset that was called the +auto revert to self-recover from the fatal error in the controller like +the host encounters HCI cmd timeout or the controller crashes. + +Co-developed-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Hao Qin <hao.qin@mediatek.com> +Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> +Stable-dep-of: 5c5e8c52e3ca ("Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/bluetooth/btusb.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index c6b62437be2d5a..536b013ff7aedc 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2811,7 +2811,16 @@ static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id) + u32 val; + int err; + +- if (dev_id == 0x7925) { ++ if (dev_id == 0x7922) { ++ btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); ++ val |= 0x00002020; ++ btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val); ++ btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001); ++ btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); ++ val |= BIT(0); ++ btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val); ++ msleep(100); ++ } else if (dev_id == 0x7925) { + btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); + val |= (1 << 5); + btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); +@@ -2851,6 +2860,9 @@ static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id) + if (err < 0) + bt_dev_err(hdev, "Reset timeout"); + ++ if (dev_id == 0x7922) ++ btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); ++ + btusb_mtk_id_get(data, 0x70010200, &val); + if (!val) + bt_dev_err(hdev, "Can't get device id, subsys reset fail."); +-- +2.53.0 + diff --git a/staging-6.6/bluetooth-btusb-mediatek-remove-the-unnecessary-goto.patch b/staging-6.6/bluetooth-btusb-mediatek-remove-the-unnecessary-goto.patch new file mode 100644 index 0000000000..96470e23ac --- /dev/null +++ b/staging-6.6/bluetooth-btusb-mediatek-remove-the-unnecessary-goto.patch @@ -0,0 +1,42 @@ +From f1b28e823a220da7cedadd038c345550d208bc31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 4 Jul 2024 14:01:09 +0800 +Subject: Bluetooth: btusb: mediatek: remove the unnecessary goto tag + +From: Chris Lu <chris.lu@mediatek.com> + +[ Upstream commit be71dfb9ad2042bba713975ef50c3a5b0429f1d2 ] + +Remove the unnecessary goto tag whether there is an error or not, we have +to free the buffer at the end of the function. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Chris Lu <chris.lu@mediatek.com> +Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> +Stable-dep-of: 5c5e8c52e3ca ("Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/bluetooth/btusb.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 536b013ff7aedc..926ca7ecaf0cc2 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2725,12 +2725,9 @@ static int btusb_mtk_uhw_reg_write(struct btusb_data *data, u32 reg, u32 val) + 0x5E, + reg >> 16, reg & 0xffff, + buf, 4, USB_CTRL_SET_TIMEOUT); +- if (err < 0) { ++ if (err < 0) + bt_dev_err(hdev, "Failed to write uhw reg(%d)", err); +- goto err_free_buf; +- } + +-err_free_buf: + kfree(buf); + + return err; +-- +2.53.0 + diff --git a/staging-6.6/bluetooth-btusb-mediatek-reset-the-controller-before.patch b/staging-6.6/bluetooth-btusb-mediatek-reset-the-controller-before.patch new file mode 100644 index 0000000000..0e00dd5e69 --- /dev/null +++ b/staging-6.6/bluetooth-btusb-mediatek-reset-the-controller-before.patch @@ -0,0 +1,61 @@ +From fcba7a18c7e71c97132a18b6c1c00b92478b9f2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Wed, 15 May 2024 16:15:20 -0700 +Subject: Bluetooth: btusb: mediatek: reset the controller before downloading + the fw + +From: Hao Qin <hao.qin@mediatek.com> + +[ Upstream commit ccfc8948d7e4d93cab341a99774b24586717d89a ] + +Reset the controller before downloading the firmware to improve its +reliability. This includes situations like cold or warm reboots, ensuring +the controller is in its initial state before starting the firmware +download. + +Co-developed-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Co-developed-by: Chris Lu <chris.lu@mediatek.com> +Signed-off-by: Chris Lu <chris.lu@mediatek.com> +Signed-off-by: Hao Qin <hao.qin@mediatek.com> +Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> +Stable-dep-of: 5c5e8c52e3ca ("Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/bluetooth/btusb.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 048929e336cf64..c6b62437be2d5a 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2940,6 +2940,13 @@ static int btusb_mtk_setup(struct hci_dev *hdev) + case 0x7922: + case 0x7961: + case 0x7925: ++ /* Reset the device to ensure it's in the initial state before ++ * downloading the firmware to ensure. ++ */ ++ ++ if (!test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) ++ btusb_mtk_subsys_reset(hdev, dev_id); ++ + btmtk_fw_get_filename(fw_bin_name, sizeof(fw_bin_name), dev_id, + fw_version, 0); + +@@ -2947,9 +2954,12 @@ static int btusb_mtk_setup(struct hci_dev *hdev) + btmtk_usb_hci_wmt_sync); + if (err < 0) { + bt_dev_err(hdev, "Failed to set up firmware (%d)", err); ++ clear_bit(BTUSB_FIRMWARE_LOADED, &data->flags); + return err; + } + ++ set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); ++ + /* It's Device EndPoint Reset Option Register */ + btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); + +-- +2.53.0 + diff --git a/staging-6.6/bluetooth-btusb-mediatek-return-error-for-failed-reg.patch b/staging-6.6/bluetooth-btusb-mediatek-return-error-for-failed-reg.patch new file mode 100644 index 0000000000..6f9ce55223 --- /dev/null +++ b/staging-6.6/bluetooth-btusb-mediatek-return-error-for-failed-reg.patch @@ -0,0 +1,174 @@ +From fb216845a1f75902455659c299e00c15cf027783 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 4 Jul 2024 14:01:10 +0800 +Subject: Bluetooth: btusb: mediatek: return error for failed reg access + +From: Chris Lu <chris.lu@mediatek.com> + +[ Upstream commit 3dcb122b30643444352ff4b9aa16367dd24d7571 ] + +Update the code to immediately return an error code if accessing a +related register fails. This ensures that our desired logic for +subsequent register operations is maintained and allows us to promptly +catch any unexpected errors. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Chris Lu <chris.lu@mediatek.com> +Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> +Stable-dep-of: 5c5e8c52e3ca ("Bluetooth: btmtk: move btusb_mtk_[setup, shutdown] to btmtk.c") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + drivers/bluetooth/btusb.c | 114 ++++++++++++++++++++++++++++---------- + 1 file changed, 84 insertions(+), 30 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 926ca7ecaf0cc2..a7aa4c1dacb295 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2809,47 +2809,98 @@ static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id) + int err; + + if (dev_id == 0x7922) { +- btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); ++ err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); ++ if (err < 0) ++ return err; + val |= 0x00002020; +- btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val); +- btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001); +- btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); ++ err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); ++ if (err < 0) ++ return err; + val |= BIT(0); +- btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val); ++ err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, val); ++ if (err < 0) ++ return err; + msleep(100); + } else if (dev_id == 0x7925) { +- btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); ++ err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); ++ if (err < 0) ++ return err; + val |= (1 << 5); +- btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); +- btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); ++ err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); ++ if (err < 0) ++ return err; + val &= 0xFFFF00FF; ++ if (err < 0) ++ return err; + val |= (1 << 13); +- btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); +- btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001); +- btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); ++ err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, 0x00010001); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_read(data, MTK_BT_RESET_REG_CONNV3, &val); ++ if (err < 0) ++ return err; + val |= (1 << 0); +- btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); +- btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); +- btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val); +- btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF); +- btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val); ++ err = btusb_mtk_uhw_reg_write(data, MTK_BT_RESET_REG_CONNV3, val); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val); ++ if (err < 0) ++ return err; + msleep(100); + } else { + /* It's Device EndPoint Reset Option Register */ + bt_dev_dbg(hdev, "Initiating reset mechanism via uhw"); +- btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); +- btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val); +- ++ err = btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_read(data, MTK_BT_WDT_STATUS, &val); ++ if (err < 0) ++ return err; + /* Reset the bluetooth chip via USB interface. */ +- btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1); +- btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); +- btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val); +- btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF); +- btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val); ++ err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 1); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT, &val); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT1, 0x000000FF); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_read(data, MTK_UDMA_INT_STA_BT1, &val); ++ if (err < 0) ++ return err; + /* MT7921 need to delay 20ms between toggle reset bit */ + msleep(20); +- btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0); +- btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); ++ err = btusb_mtk_uhw_reg_write(data, MTK_BT_SUBSYS_RST, 0); ++ if (err < 0) ++ return err; ++ err = btusb_mtk_uhw_reg_read(data, MTK_BT_SUBSYS_RST, &val); ++ if (err < 0) ++ return err; + } + + err = readx_poll_timeout(btusb_mtk_reset_done, hdev, val, +@@ -2857,11 +2908,14 @@ static int btusb_mtk_subsys_reset(struct hci_dev *hdev, u32 dev_id) + if (err < 0) + bt_dev_err(hdev, "Reset timeout"); + +- if (dev_id == 0x7922) +- btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); ++ if (dev_id == 0x7922) { ++ err = btusb_mtk_uhw_reg_write(data, MTK_UDMA_INT_STA_BT, 0x000000FF); ++ if (err < 0) ++ return err; ++ } + +- btusb_mtk_id_get(data, 0x70010200, &val); +- if (!val) ++ err = btusb_mtk_id_get(data, 0x70010200, &val); ++ if (err < 0 || !val) + bt_dev_err(hdev, "Can't get device id, subsys reset fail."); + + return err; +-- +2.53.0 + diff --git a/staging-6.6/ext4-get-rid-of-ppath-in-get_ext_path.patch b/staging-6.6/ext4-get-rid-of-ppath-in-get_ext_path.patch new file mode 100644 index 0000000000..6c6fddfad2 --- /dev/null +++ b/staging-6.6/ext4-get-rid-of-ppath-in-get_ext_path.patch @@ -0,0 +1,130 @@ +From 84a8c19bd0ce8045a4f7f5527a324cfb8a694904 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 22 Aug 2024 10:35:32 +0800 +Subject: ext4: get rid of ppath in get_ext_path() + +From: Baokun Li <libaokun1@huawei.com> + +[ Upstream commit 6b854d552711aa33f59eda334e6d94a00d8825bb ] + +The use of path and ppath is now very confusing, so to make the code more +readable, pass path between functions uniformly, and get rid of ppath. + +After getting rid of ppath in get_ext_path(), its caller may pass an error +pointer to ext4_free_ext_path(), so it needs to teach ext4_free_ext_path() +and ext4_ext_drop_refs() to skip the error pointer. No functional changes. + +Signed-off-by: Baokun Li <libaokun1@huawei.com> +Reviewed-by: Jan Kara <jack@suse.cz> +Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com> +Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com> +Link: https://patch.msgid.link/20240822023545.1994557-13-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/ext4/extents.c | 5 +++-- + fs/ext4/move_extent.c | 34 +++++++++++++++++----------------- + 2 files changed, 20 insertions(+), 19 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index a94798e23c1afb..9c2d23958146bf 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -114,7 +114,7 @@ static void ext4_ext_drop_refs(struct ext4_ext_path *path) + { + int depth, i; + +- if (!path) ++ if (IS_ERR_OR_NULL(path)) + return; + depth = path->p_depth; + for (i = 0; i <= depth; i++, path++) { +@@ -125,6 +125,8 @@ static void ext4_ext_drop_refs(struct ext4_ext_path *path) + + void ext4_free_ext_path(struct ext4_ext_path *path) + { ++ if (IS_ERR_OR_NULL(path)) ++ return; + ext4_ext_drop_refs(path); + kfree(path); + } +@@ -4242,7 +4244,6 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, + path = ext4_find_extent(inode, map->m_lblk, NULL, 0); + if (IS_ERR(path)) { + err = PTR_ERR(path); +- path = NULL; + goto out; + } + +diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c +index d5636a2a718a8d..96a84de321690d 100644 +--- a/fs/ext4/move_extent.c ++++ b/fs/ext4/move_extent.c +@@ -17,27 +17,23 @@ + * get_ext_path() - Find an extent path for designated logical block number. + * @inode: inode to be searched + * @lblock: logical block number to find an extent path +- * @ppath: pointer to an extent path pointer (for output) ++ * @path: pointer to an extent path + * +- * ext4_find_extent wrapper. Return 0 on success, or a negative error value +- * on failure. ++ * ext4_find_extent wrapper. Return an extent path pointer on success, ++ * or an error pointer on failure. + */ +-static inline int ++static inline struct ext4_ext_path * + get_ext_path(struct inode *inode, ext4_lblk_t lblock, +- struct ext4_ext_path **ppath) ++ struct ext4_ext_path *path) + { +- struct ext4_ext_path *path = *ppath; +- +- *ppath = NULL; + path = ext4_find_extent(inode, lblock, path, EXT4_EX_NOCACHE); + if (IS_ERR(path)) +- return PTR_ERR(path); ++ return path; + if (path[ext_depth(inode)].p_ext == NULL) { + ext4_free_ext_path(path); +- return -ENODATA; ++ return ERR_PTR(-ENODATA); + } +- *ppath = path; +- return 0; ++ return path; + } + + /** +@@ -95,9 +91,11 @@ mext_check_coverage(struct inode *inode, ext4_lblk_t from, ext4_lblk_t count, + int ret = 0; + ext4_lblk_t last = from + count; + while (from < last) { +- *err = get_ext_path(inode, from, &path); +- if (*err) +- goto out; ++ path = get_ext_path(inode, from, path); ++ if (IS_ERR(path)) { ++ *err = PTR_ERR(path); ++ return ret; ++ } + ext = path[ext_depth(inode)].p_ext; + if (unwritten != ext4_ext_is_unwritten(ext)) + goto out; +@@ -634,9 +632,11 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk, + int offset_in_page; + int unwritten, cur_len; + +- ret = get_ext_path(orig_inode, o_start, &path); +- if (ret) ++ path = get_ext_path(orig_inode, o_start, path); ++ if (IS_ERR(path)) { ++ ret = PTR_ERR(path); + goto out; ++ } + ex = path[path->p_depth].p_ext; + cur_blk = le32_to_cpu(ex->ee_block); + cur_len = ext4_ext_get_actual_len(ex); +-- +2.53.0 + diff --git a/staging-6.6/loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch b/staging-6.6/loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch new file mode 100644 index 0000000000..df1c884676 --- /dev/null +++ b/staging-6.6/loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch @@ -0,0 +1,64 @@ +From 9550f2749ed79cd29d7c7f68dcaff035e835d4eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 3 Jul 2026 11:24:00 +0800 +Subject: LoongArch: Report dying CPU to RCU in stop_this_cpu() + +From: Huacai Chen <chenhuacai@loongson.cn> + +commit f2539c56c74691e7a88af6372ba2b48c06ed2fe4 upstream. + +This is a port of MIPS commit 9f3f3bdc6d9dac1 ("MIPS: smp: report dying +CPU to RCU in stop_this_cpu()"). smp_send_stop() parks all secondary +CPUs in stop_this_cpu(). And the function marks the CPU offline for the +scheduler via set_cpu_online(false) but never informs RCU, so RCU keeps +expecting a quiescent state from CPUs that are now spinning forever with +interrupts disabled. + +As long as nothing waits for an RCU grace period after smp_send_stop() +this is harmless, which is why it went unnoticed. However, since commit +91840be8f710370 ("irq_work: Fix use-after-free in irq_work_single() on +PREEMPT_RT"), irq_work_sync() calls synchronize_rcu() on architectures +without an irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() +returns false. Any irq_work_sync() issued in the reboot/shutdown/halt +path after smp_send_stop() then blocks on a grace period that can never +complete, hanging the reboot: + + WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on + ... + rcu: INFO: rcu_sched detected stalls on CPUs/tasks: + rcu: Offline CPU 1 blocking current GP. + rcu: Offline CPU 2 blocking current GP. + rcu: Offline CPU 3 blocking current GP. + +This issue needs some hacks to reproduce, and it was not noticed on +LoongArch because arch_irq_work_has_interrupt() usually returns true. + +Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring +the generic CPU-hotplug offline path, so RCU stops waiting on the parked +CPUs and grace periods can still complete. LoongArch shuts down all CPUs +here without going through the CPU-hotplug mechanism, so this report is +not otherwise issued. + +Cc: <stable@vger.kernel.org> +Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + arch/loongarch/kernel/smp.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c +index ed67629454374f..d3fafa5cdf6bc8 100644 +--- a/arch/loongarch/kernel/smp.c ++++ b/arch/loongarch/kernel/smp.c +@@ -613,6 +613,7 @@ static void stop_this_cpu(void *dummy) + set_cpu_online(smp_processor_id(), false); + calculate_cpu_foreign_map(); + local_irq_disable(); ++ rcu_report_dead(smp_processor_id()); + while (true); + } + +-- +2.53.0 + diff --git a/staging-6.6/nfsd-release-layout-stid-on-setlease-failure.patch b/staging-6.6/nfsd-release-layout-stid-on-setlease-failure.patch new file mode 100644 index 0000000000..dc34e5192a --- /dev/null +++ b/staging-6.6/nfsd-release-layout-stid-on-setlease-failure.patch @@ -0,0 +1,75 @@ +From 758e60ccf99ed8315bf3ead7bcc511956af65e19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 17:41:34 -0400 +Subject: nfsd: release layout stid on setlease failure + +From: Chris Mason <clm@meta.com> + +commit 30d55c8aabb261bc3f427d6b9aae7ef6206063f9 upstream. + +nfs4_alloc_stid() publishes the new stid into cl->cl_stateids via +idr_alloc_cyclic() under cl_lock before returning to +nfsd4_alloc_layout_stateid(). When nfsd4_layout_setlease() then +fails, the error path frees the layout stateid directly with +kmem_cache_free() without ever calling idr_remove(), leaving the +IDR slot pointing at freed slab memory. Any subsequent IDR walker +(states_show, client teardown) dereferences the dangling pointer. + +The correct teardown for an IDR-published stid is nfs4_put_stid(), +which removes the IDR slot under cl_lock, dispatches sc_free +(nfsd4_free_layout_stateid) to release ls->ls_file via +nfsd4_close_layout(), and drops the nfs4_file reference in its +tail. + +A second issue blocks that switch: nfsd4_free_layout_stateid() +unconditionally inspects ls->ls_fence_work via +delayed_work_pending() under ls_lock, but +INIT_DELAYED_WORK(&ls->ls_fence_work, ...) currently runs only +after the setlease call. On the setlease-failure path the +destructor would touch an uninitialized delayed_work. + + nfsd4_alloc_layout_stateid() + nfs4_alloc_stid() /* idr_alloc_cyclic under cl_lock */ + nfsd4_layout_setlease() /* fails */ + nfs4_put_stid() + nfsd4_free_layout_stateid() + delayed_work_pending(&ls->ls_fence_work) /* needs INIT */ + nfsd4_close_layout() /* nfsd_file_put(ls->ls_file) */ + put_nfs4_file() + +Fix by hoisting the ls_fenced / ls_fence_delay / INIT_DELAYED_WORK +initialization above the nfsd4_layout_setlease() call, and replace +the manual nfsd_file_put + put_nfs4_file + kmem_cache_free cleanup +with a single nfs4_put_stid(stp). + +Fixes: c5c707f96fc9 ("nfsd: implement pNFS layout recalls") +Cc: stable@vger.kernel.org +Assisted-by: kres (claude-opus-4-7) +Signed-off-by: Chris Mason <clm@meta.com> +Reviewed-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +[ cel: no ls_fence_work in 6.6.y; dropped INIT_DELAYED_WORK hunk ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/nfs4layouts.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c +index 308214378fd352..84bb200e24adea 100644 +--- a/fs/nfsd/nfs4layouts.c ++++ b/fs/nfsd/nfs4layouts.c +@@ -242,9 +242,7 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate, + BUG_ON(!ls->ls_file); + + if (nfsd4_layout_setlease(ls)) { +- nfsd_file_put(ls->ls_file); +- put_nfs4_file(fp); +- kmem_cache_free(nfs4_layout_stateid_cache, ls); ++ nfs4_put_stid(stp); + return NULL; + } + +-- +2.53.0 + diff --git a/staging-6.6/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch b/staging-6.6/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch new file mode 100644 index 0000000000..363946d287 --- /dev/null +++ b/staging-6.6/nfsd-reset-write-verifier-on-deferred-writeback-erro.patch @@ -0,0 +1,75 @@ +From 37cec347e1b38e8e4dae313e3a0e98812790469a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 17:41:35 -0400 +Subject: nfsd: reset write verifier on deferred writeback errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jeff Layton <jlayton@kernel.org> + +commit 2090b05803faab8a9fa62fbff871007862cac1b7 upstream. + +nfsd_vfs_write() and nfsd_commit() both call filemap_check_wb_err() to +detect deferred writeback errors, but neither rotates the server's write +verifier (nn->writeverf) when this check fails. Every other +durable-storage-failure path in these functions calls +commit_reset_write_verifier() before returning an error. + +The missing rotation means clients holding UNSTABLE write data under the +current verifier will COMMIT, receive the unchanged verifier back, and +conclude their data is durable â silently dropping data that failed +writeback. This violates the UNSTABLE+COMMIT durability contract +(RFC 1813 §3.3.7, RFC 8881 §18.32). + +Add commit_reset_write_verifier() calls at both filemap_check_wb_err() +error sites, matching the pattern used by adjacent error paths in the +same functions. The helper already filters -EAGAIN and -ESTALE +internally, so the calls are unconditionally safe. + +Reported-by: Chris Mason <clm@meta.com> +Fixes: 555dbf1a9aac ("nfsd: Replace use of rwsem with errseq_t") +Cc: stable@vger.kernel.org +Assisted-by: kres:claude-opus-4-6 +Signed-off-by: Jeff Layton <jlayton@kernel.org> +Signed-off-by: Chuck Lever <chuck.lever@oracle.com> +[ cel: 6.6.y predates the commit_reset_write_verifier() helper (v6.7); + open-coded nfsd_reset_write_verifier() and the reset tracepoint at + both sites, matching the other reset paths in these functions ] +Signed-off-by: Chuck Lever <cel@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/nfsd/vfs.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c +index ae1f43eb515a81..6658c92340f20b 100644 +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -1185,8 +1185,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, + nfsd_stats_io_write_add(nn, exp, *cnt); + fsnotify_modify(file); + host_err = filemap_check_wb_err(file->f_mapping, since); +- if (host_err < 0) ++ if (host_err < 0) { ++ nfsd_reset_write_verifier(nn); ++ trace_nfsd_writeverf_reset(nn, rqstp, host_err); + goto out_nfserr; ++ } + + if (stable && use_wgather) { + host_err = wait_for_concurrent_writes(file); +@@ -1330,6 +1333,10 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, + nfsd_copy_write_verifier(verf, nn); + err2 = filemap_check_wb_err(nf->nf_file->f_mapping, + since); ++ if (err2 < 0) { ++ nfsd_reset_write_verifier(nn); ++ trace_nfsd_writeverf_reset(nn, rqstp, err2); ++ } + err = nfserrno(err2); + break; + case -EINVAL: +-- +2.53.0 + diff --git a/staging-6.6/perf-fix-dangling-cgroup-pointer-in-cpuctx-backport.patch b/staging-6.6/perf-fix-dangling-cgroup-pointer-in-cpuctx-backport.patch new file mode 100644 index 0000000000..cc7e2c2e8d --- /dev/null +++ b/staging-6.6/perf-fix-dangling-cgroup-pointer-in-cpuctx-backport.patch @@ -0,0 +1,41 @@ +From 24c5bb00ce525cdc1b995f82bcfadc551a7d9f58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Fri, 3 Jul 2026 00:45:54 +0800 +Subject: perf: Fix dangling cgroup pointer in cpuctx backport + +From: Wentao Guan <guanwentao@uniontech.com> + +recently backport of ("perf: Fix dangling cgroup pointer in cpuctx") +use a middle version, so aligned with the upstream commit: +commit 3b7a34aebbdf ("perf: Fix dangling cgroup pointer in cpuctx") + +This is a fix for stable v6.6.143 backport commit, so no upstream commit. + +Link: https://lore.kernel.org/all/2026070200-uneaten-smock-4130@gregkh/ +Fixes: ae1ada0af162 ("perf: Fix dangling cgroup pointer in cpuctx") +Signed-off-by: Wentao Guan <guanwentao@uniontech.com> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/events/core.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index a4187dea6402a7..73a86db06cc9b1 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -2384,10 +2384,9 @@ __perf_remove_from_context(struct perf_event *event, + */ + if (flags & DETACH_EXIT) + state = PERF_EVENT_STATE_EXIT; +- if (flags & DETACH_DEAD) { +- event->pending_disable = 1; ++ if (flags & DETACH_DEAD) + state = PERF_EVENT_STATE_DEAD; +- } ++ + event_sched_out(event, ctx); + + if (event->state > PERF_EVENT_STATE_OFF) +-- +2.53.0 + diff --git a/staging-6.6/series b/staging-6.6/series index 5702e744cc..613b91e273 100644 --- a/staging-6.6/series +++ b/staging-6.6/series @@ -1 +1,16 @@ bpf-arm64-reject-out-of-range-b.cond-targets.patch +nfsd-release-layout-stid-on-setlease-failure.patch +nfsd-reset-write-verifier-on-deferred-writeback-erro.patch +ext4-get-rid-of-ppath-in-get_ext_path.patch +loongarch-report-dying-cpu-to-rcu-in-stop_this_cpu.patch +bluetooth-btmtk-apply-the-common-btmtk_fw_get_filena.patch +bluetooth-btusb-mediatek-reset-the-controller-before.patch +bluetooth-btusb-mediatek-add-mt7922-subsystem-reset.patch +bluetooth-btusb-mediatek-remove-the-unnecessary-goto.patch +bluetooth-btusb-mediatek-return-error-for-failed-reg.patch +bluetooth-btmtk-move-btusb_mtk_-setup-shutdown-to-bt.patch +bluetooth-btmtk-fix-failed-to-send-func-ctrl-for-med.patch +bluetooth-btmtk-fix-wait_on_bit_timeout-interruption.patch +userfaultfd-gate-must_wait-writability-check-on-pte_.patch +perf-fix-dangling-cgroup-pointer-in-cpuctx-backport.patch +bluetooth-btmtk-fix-btmtk.c-undefined-reference-buil.patch diff --git a/staging-6.6/userfaultfd-gate-must_wait-writability-check-on-pte_.patch b/staging-6.6/userfaultfd-gate-must_wait-writability-check-on-pte_.patch new file mode 100644 index 0000000000..a42aba3f7f --- /dev/null +++ b/staging-6.6/userfaultfd-gate-must_wait-writability-check-on-pte_.patch @@ -0,0 +1,88 @@ +From 439676060e94503bfd25997db4fb954eda74311f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:49:04 +0100 +Subject: userfaultfd: gate must_wait writability check on pte_present() + +From: Kiryl Shutsemau <kas@kernel.org> + +[ Upstream commit 8e80af52db652fbc41320eee45a4f73bc029faf2 ] + +userfaultfd_must_wait() and userfaultfd_huge_must_wait() read the PTE +without taking the page table lock and then apply pte_write() / +huge_pte_write() to it. Those accessors decode bits from the present +encoding only; on a swap or migration entry they read the offset bits that +happen to share the same position and return an undefined result. + +The intent of the check is "is this fault still WP-blocked?". A +non-marker swap entry means the page is in transit -- the userfault +context the original fault delivered against is no longer the same, and +the swap-in or migration completion path will re-deliver a fresh fault if +userspace still needs to handle it. Worst case under the current code the +garbage write bit says "wait", and the thread stays asleep until a +UFFDIO_WAKE that may never arrive. + +Gate the writability check on pte_present() so the lockless re-check only +inspects present-PTE bits when the entry is actually present. The +non-present, non-marker case returns "don't wait" and lets the fault path +retry. + +Link: https://lore.kernel.org/20260529172331.356655-6-kas@kernel.org +Fixes: 369cd2121be4 ("userfaultfd: hugetlbfs: userfaultfd_huge_must_wait for hugepmd ranges") +Fixes: 63b2d4174c4a ("userfaultfd: wp: add the writeprotect API to userfaultfd ioctl") +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Reported-by: Sashiko AI review <sashiko-bot@kernel.org> +Reviewed-by: Lorenzo Stoakes <ljs@kernel.org> +Cc: David Hildenbrand <david@kernel.org> +Cc: Michal Hocko <mhocko@suse.com> +Cc: Mike Rapoport <rppt@kernel.org> +Cc: Peter Xu <peterx@redhat.com> +Cc: Suren Baghdasaryan <surenb@google.com> +Cc: Vlastimil Babka <vbabka@kernel.org> +Cc: Balbir Singh <balbirs@nvidia.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> + +[ kas: apply to fs/userfaultfd.c and fold the pte_present()/ + huge_pte_present() gate into the existing writability checks; this tree + predates the marker/return-style refactor of these functions ] +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/userfaultfd.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c +index 74c468cc432e7f..49f07426259818 100644 +--- a/fs/userfaultfd.c ++++ b/fs/userfaultfd.c +@@ -300,7 +300,12 @@ static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx, + */ + if (huge_pte_none_mostly(pte)) + ret = true; +- if (!huge_pte_write(pte) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): huge_pte_write() on a ++ * non-present migration entry decodes random offset bits. The ++ * migration completion path re-delivers the fault if still needed. ++ */ ++ if (pte_present(pte) && !huge_pte_write(pte) && (reason & VM_UFFD_WP)) + ret = true; + out: + return ret; +@@ -375,7 +380,12 @@ static inline bool userfaultfd_must_wait(struct userfaultfd_ctx *ctx, + ptent = ptep_get(pte); + if (pte_none_mostly(ptent)) + ret = true; +- if (!pte_write(ptent) && (reason & VM_UFFD_WP)) ++ /* ++ * Gate the writability check on pte_present(): pte_write() on a ++ * non-present swap/migration entry decodes random offset bits. The ++ * page-in path re-delivers the fault if it still needs userspace. ++ */ ++ if (pte_present(ptent) && !pte_write(ptent) && (reason & VM_UFFD_WP)) + ret = true; + pte_unmap(pte); + +-- +2.53.0 + diff --git a/staging-7.1/kernel-fork-clear-pf_block_ts-in-copy_process.patch b/staging-7.1/kernel-fork-clear-pf_block_ts-in-copy_process.patch new file mode 100644 index 0000000000..447657f67b --- /dev/null +++ b/staging-7.1/kernel-fork-clear-pf_block_ts-in-copy_process.patch @@ -0,0 +1,44 @@ +From ea519a7176053ec52a11367b7d72cbf92a7a79d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 16 Jun 2026 07:15:17 -0700 +Subject: kernel/fork: clear PF_BLOCK_TS in copy_process() + +From: Usama Arif <usama.arif@linux.dev> + +[ Upstream commit fd38b75c4b43295b10d69772a46d1c74dbd6fc81 ] + +PF_BLOCK_TS is only set in blk_time_get_ns() when current->plug is +non-NULL, and blk_finish_plug() clears it via __blk_flush_plug() +before NULLing the plug pointer. copy_process() breaks the +invariant by inheriting PF_BLOCK_TS from the parent while resetting +the child's plug to NULL. + +Clear PF_BLOCK_TS alongside that assignment so callers can rely on +"PF_BLOCK_TS set implies current->plug != NULL" and dereference +current->plug unguarded. + +Fixes: 06b23f92af87 ("block: update cached timestamp post schedule/preemption") +Cc: stable@vger.kernel.org +Signed-off-by: Usama Arif <usama.arif@linux.dev> +Link: https://patch.msgid.link/20260616141604.328820-2-usama.arif@linux.dev +Signed-off-by: Jens Axboe <axboe@kernel.dk> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/fork.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/fork.c b/kernel/fork.c +index 8ac38beae360b4..145bcc4c8e125e 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -2314,6 +2314,7 @@ __latent_entropy struct task_struct *copy_process( + + #ifdef CONFIG_BLOCK + p->plug = NULL; ++ p->flags &= ~PF_BLOCK_TS; + #endif + futex_init_task(p); + +-- +2.53.0 + diff --git a/staging-7.1/rust-str-clean-unused-import-for-rust-1.98.patch b/staging-7.1/rust-str-clean-unused-import-for-rust-1.98.patch new file mode 100644 index 0000000000..b9b4ce2873 --- /dev/null +++ b/staging-7.1/rust-str-clean-unused-import-for-rust-1.98.patch @@ -0,0 +1,53 @@ +From 6a73384b2aa8b63997ea8be8b26439d785601b70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 9 Jun 2026 12:41:52 +0200 +Subject: rust: str: clean unused import for Rust >= 1.98 + +From: Miguel Ojeda <ojeda@kernel.org> + +[ Upstream commit 3fff4271809b57182c4011811e96556bdd4cb2f9 ] + +Starting with Rust 1.98.0 (expected 2026-08-20), the compiler has changed +how the resolution algorithm works [1] in upstream commit c4d84db5f184 +("Resolver: Batched import resolution."), and it now spots: + + error: unused import: `flags::*` + --> rust/kernel/str.rs:7:9 + | + 7 | flags::*, + | ^^^^^^^^ + | + = note: `-D unused-imports` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(unused_imports)]` + +It happens to not be needed because the `prelude::*` already provides +the flags. + +Thus clean it up. + +Cc: stable@vger.kernel.org # Needed in 6.18.y and later (prelude added to `str`). +Link: https://github.com/rust-lang/rust/pull/145108 [1] +Reviewed-by: Gary Guo <gary@garyguo.net> +Reviewed-by: Alice Ryhl <aliceryhl@google.com> +Link: https://patch.msgid.link/20260609104152.261145-2-ojeda@kernel.org +Signed-off-by: Miguel Ojeda <ojeda@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + rust/kernel/str.rs | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs +index a7fccd4c4f3b18..4517c1bc547afb 100644 +--- a/rust/kernel/str.rs ++++ b/rust/kernel/str.rs +@@ -4,7 +4,6 @@ + + use crate::{ + alloc::{ +- flags::*, + AllocError, + KVec, // + }, +-- +2.53.0 + diff --git a/staging-7.1/rust-str-use-the-kernel-vertical-imports-style.patch b/staging-7.1/rust-str-use-the-kernel-vertical-imports-style.patch new file mode 100644 index 0000000000..dbef458f74 --- /dev/null +++ b/staging-7.1/rust-str-use-the-kernel-vertical-imports-style.patch @@ -0,0 +1,64 @@ +From 815c2486403f4adaede654c21a3a69ba390cb45a Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Tue, 9 Jun 2026 12:41:51 +0200 +Subject: rust: str: use the "kernel vertical" imports style + +From: Miguel Ojeda <ojeda@kernel.org> + +[ Upstream commit 724a93a9f6033800b02a3530dbcb464638448e7f ] + +Convert the imports to use the "kernel vertical" imports style [1]. + +No functional changes intended. + +Link: https://docs.kernel.org/rust/coding-guidelines.html#imports [1] +Reviewed-by: Gary Guo <gary@garyguo.net> +Link: https://patch.msgid.link/20260609104152.261145-1-ojeda@kernel.org +Signed-off-by: Miguel Ojeda <ojeda@kernel.org> +Stable-dep-of: 3fff4271809b ("rust: str: clean unused import for Rust >= 1.98") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + rust/kernel/str.rs | 24 +++++++++++++++++++----- + 1 file changed, 19 insertions(+), 5 deletions(-) + +diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs +index 8311d91549e15e..a7fccd4c4f3b18 100644 +--- a/rust/kernel/str.rs ++++ b/rust/kernel/str.rs +@@ -3,14 +3,28 @@ + //! String representations. + + use crate::{ +- alloc::{flags::*, AllocError, KVec}, +- error::{to_result, Result}, +- fmt::{self, Write}, +- prelude::*, ++ alloc::{ ++ flags::*, ++ AllocError, ++ KVec, // ++ }, ++ error::{ ++ to_result, ++ Result, // ++ }, ++ fmt::{ ++ self, ++ Write, // ++ }, ++ prelude::*, // + }; + use core::{ + marker::PhantomData, +- ops::{Deref, DerefMut, Index}, ++ ops::{ ++ Deref, ++ DerefMut, ++ Index, // ++ }, // + }; + + pub use crate::prelude::CStr; +-- +2.53.0 + diff --git a/staging-7.1/series b/staging-7.1/series new file mode 100644 index 0000000000..47563e403d --- /dev/null +++ b/staging-7.1/series @@ -0,0 +1,4 @@ +kernel-fork-clear-pf_block_ts-in-copy_process.patch +rust-str-use-the-kernel-vertical-imports-style.patch +rust-str-clean-unused-import-for-rust-1.98.patch +userfaultfd-gate-must_wait-writability-check-on-pte_.patch diff --git a/staging-7.1/userfaultfd-gate-must_wait-writability-check-on-pte_.patch b/staging-7.1/userfaultfd-gate-must_wait-writability-check-on-pte_.patch new file mode 100644 index 0000000000..0830562270 --- /dev/null +++ b/staging-7.1/userfaultfd-gate-must_wait-writability-check-on-pte_.patch @@ -0,0 +1,93 @@ +From f4d83edd6af9af54985fb054ad39798d13d7d63e Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Thu, 2 Jul 2026 16:49:08 +0100 +Subject: userfaultfd: gate must_wait writability check on pte_present() + +From: Kiryl Shutsemau <kas@kernel.org> + +[ Upstream commit 8e80af52db652fbc41320eee45a4f73bc029faf2 ] + +userfaultfd_must_wait() and userfaultfd_huge_must_wait() read the PTE +without taking the page table lock and then apply pte_write() / +huge_pte_write() to it. Those accessors decode bits from the present +encoding only; on a swap or migration entry they read the offset bits that +happen to share the same position and return an undefined result. + +The intent of the check is "is this fault still WP-blocked?". A +non-marker swap entry means the page is in transit -- the userfault +context the original fault delivered against is no longer the same, and +the swap-in or migration completion path will re-deliver a fresh fault if +userspace still needs to handle it. Worst case under the current code the +garbage write bit says "wait", and the thread stays asleep until a +UFFDIO_WAKE that may never arrive. + +Gate the writability check on pte_present() so the lockless re-check only +inspects present-PTE bits when the entry is actually present. The +non-present, non-marker case returns "don't wait" and lets the fault path +retry. + +Link: https://lore.kernel.org/20260529172331.356655-6-kas@kernel.org +Fixes: 369cd2121be4 ("userfaultfd: hugetlbfs: userfaultfd_huge_must_wait for hugepmd ranges") +Fixes: 63b2d4174c4a ("userfaultfd: wp: add the writeprotect API to userfaultfd ioctl") +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Reported-by: Sashiko AI review <sashiko-bot@kernel.org> +Reviewed-by: Lorenzo Stoakes <ljs@kernel.org> +Cc: David Hildenbrand <david@kernel.org> +Cc: Michal Hocko <mhocko@suse.com> +Cc: Mike Rapoport <rppt@kernel.org> +Cc: Peter Xu <peterx@redhat.com> +Cc: Suren Baghdasaryan <surenb@google.com> +Cc: Vlastimil Babka <vbabka@kernel.org> +Cc: Balbir Singh <balbirs@nvidia.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> + +[ kas: apply to fs/userfaultfd.c; these checks moved to mm/userfaultfd.c + only after 7.1, the change is otherwise identical to upstream ] +Signed-off-by: Kiryl Shutsemau <kas@kernel.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + fs/userfaultfd.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c +index 390e4b7d9cb9fa..dba1172436b745 100644 +--- a/fs/userfaultfd.c ++++ b/fs/userfaultfd.c +@@ -253,6 +253,15 @@ static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx, + /* UFFD PTE markers require userspace to resolve the fault. */ + if (pte_is_uffd_marker(pte)) + return true; ++ /* ++ * Concurrent migration may have replaced the present PTE with a ++ * non-marker swap entry between fault delivery and this lockless ++ * re-check. huge_pte_write() on a swap entry decodes random offset ++ * bits, so gate it on pte_present(). The migration completion path ++ * will re-deliver the fault if it still needs userspace. ++ */ ++ if (!pte_present(pte)) ++ return false; + /* + * If VMA has UFFD WP faults enabled and WP fault, wait for userspace to + * resolve the fault. +@@ -339,6 +348,17 @@ static inline bool userfaultfd_must_wait(struct userfaultfd_ctx *ctx, + /* UFFD PTE markers require userspace to resolve the fault. */ + if (pte_is_uffd_marker(ptent)) + goto out; ++ /* ++ * Concurrent swap-out / migration may have replaced the present PTE ++ * with a non-marker swap entry between fault delivery and this ++ * lockless re-check. pte_write() on a swap entry decodes random ++ * offset bits, so gate it on pte_present(). The page-in path will ++ * re-deliver the fault if it still needs userspace. ++ */ ++ if (!pte_present(ptent)) { ++ ret = false; ++ goto out; ++ } + /* + * If VMA has UFFD WP faults enabled and WP fault, wait for userspace to + * resolve the fault. +-- +2.53.0 + |
generated by cgit 1.3-korg (git 2.53.0) at 2026-07-04 07:11:26 +0000

