From: Sasha Levin Date: Sun, 18 May 2025 10:30:32 +0000 (-0400) Subject: Fixes for 5.4 X-Git-Tag: v5.15.184~56 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e4ca91cb86c9da48ee34f32c61976fb8e234ee3;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/alsa-sh-snd_aica-should-depend-on-sh_dma_api.patch b/queue-5.4/alsa-sh-snd_aica-should-depend-on-sh_dma_api.patch new file mode 100644 index 0000000000..768de4b807 --- /dev/null +++ b/queue-5.4/alsa-sh-snd_aica-should-depend-on-sh_dma_api.patch @@ -0,0 +1,46 @@ +From 0f9242b08ecf66d505597300e879774795c4f441 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 May 2025 09:31:04 +0200 +Subject: ALSA: sh: SND_AICA should depend on SH_DMA_API + +From: Geert Uytterhoeven + +[ Upstream commit 66e48ef6ef506c89ec1b3851c6f9f5f80b5835ff ] + +If CONFIG_SH_DMA_API=n: + + WARNING: unmet direct dependencies detected for G2_DMA + Depends on [n]: SH_DREAMCAST [=y] && SH_DMA_API [=n] + Selected by [y]: + - SND_AICA [=y] && SOUND [=y] && SND [=y] && SND_SUPERH [=y] && SH_DREAMCAST [=y] + +SND_AICA selects G2_DMA. As the latter depends on SH_DMA_API, the +former should depend on SH_DMA_API, too. + +Fixes: f477a538c14d07f8 ("sh: dma: fix kconfig dependency for G2_DMA") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202505131320.PzgTtl9H-lkp@intel.com/ +Signed-off-by: Geert Uytterhoeven +Link: https://patch.msgid.link/b90625f8a9078d0d304bafe862cbe3a3fab40082.1747121335.git.geert+renesas@glider.be +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/sh/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/sh/Kconfig b/sound/sh/Kconfig +index b75fbb3236a7b..f5fa09d740b4c 100644 +--- a/sound/sh/Kconfig ++++ b/sound/sh/Kconfig +@@ -14,7 +14,7 @@ if SND_SUPERH + + config SND_AICA + tristate "Dreamcast Yamaha AICA sound" +- depends on SH_DREAMCAST ++ depends on SH_DREAMCAST && SH_DMA_API + select SND_PCM + select G2_DMA + help +-- +2.39.5 + diff --git a/queue-5.4/iio-adc-ad7768-1-fix-insufficient-alignment-of-times.patch b/queue-5.4/iio-adc-ad7768-1-fix-insufficient-alignment-of-times.patch new file mode 100644 index 0000000000..ab49d327dd --- /dev/null +++ b/queue-5.4/iio-adc-ad7768-1-fix-insufficient-alignment-of-times.patch @@ -0,0 +1,44 @@ +From 0ed4a5c266093f42710f33991d79877f455a6f03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 13 Apr 2025 11:34:25 +0100 +Subject: iio: adc: ad7768-1: Fix insufficient alignment of timestamp. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jonathan Cameron + +[ Upstream commit ffbc26bc91c1f1eb3dcf5d8776e74cbae21ee13a ] + +On architectures where an s64 is not 64-bit aligned, this may result +insufficient alignment of the timestamp and the structure being too small. +Use aligned_s64 to force the alignment. + +Fixes: a1caeebab07e ("iio: adc: ad7768-1: Fix too small buffer passed to iio_push_to_buffers_with_timestamp()") # aligned_s64 newer +Reported-by: David Lechner +Reviewed-by: Nuno Sá +Reviewed-by: David Lechner +Link: https://patch.msgid.link/20250413103443.2420727-3-jic23@kernel.org +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7768-1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c +index c1adb95f2a464..fd9aea1453201 100644 +--- a/drivers/iio/adc/ad7768-1.c ++++ b/drivers/iio/adc/ad7768-1.c +@@ -168,7 +168,7 @@ struct ad7768_state { + union { + struct { + __be32 chan; +- s64 timestamp; ++ aligned_s64 timestamp; + } scan; + __be32 d32; + u8 d8[2]; +-- +2.39.5 + diff --git a/queue-5.4/iio-chemical-sps30-use-aligned_s64-for-timestamp.patch b/queue-5.4/iio-chemical-sps30-use-aligned_s64-for-timestamp.patch new file mode 100644 index 0000000000..9470407c6e --- /dev/null +++ b/queue-5.4/iio-chemical-sps30-use-aligned_s64-for-timestamp.patch @@ -0,0 +1,43 @@ +From 136ffa9ffa6232d733356e9c4608de4b4f2c3844 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 11:52:37 -0500 +Subject: iio: chemical: sps30: use aligned_s64 for timestamp +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David Lechner + +[ Upstream commit bb49d940344bcb8e2b19e69d7ac86f567887ea9a ] + +Follow the pattern of other drivers and use aligned_s64 for the +timestamp. This will ensure that the timestamp is correctly aligned on +all architectures. + +Fixes: a5bf6fdd19c3 ("iio:chemical:sps30: Fix timestamp alignment") +Signed-off-by: David Lechner +Reviewed-by: Nuno Sá +Link: https://patch.msgid.link/20250417-iio-more-timestamp-alignment-v1-5-eafac1e22318@baylibre.com +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/chemical/sps30.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c +index c0845d892faad..0e466106becb4 100644 +--- a/drivers/iio/chemical/sps30.c ++++ b/drivers/iio/chemical/sps30.c +@@ -232,7 +232,7 @@ static irqreturn_t sps30_trigger_handler(int irq, void *p) + int ret; + struct { + s32 data[4]; /* PM1, PM2P5, PM4, PM10 */ +- s64 ts; ++ aligned_s64 ts; + } scan; + + mutex_lock(&state->lock); +-- +2.39.5 + diff --git a/queue-5.4/net-dsa-sja1105-discard-incoming-frames-in-br_state_.patch b/queue-5.4/net-dsa-sja1105-discard-incoming-frames-in-br_state_.patch new file mode 100644 index 0000000000..ac3817617f --- /dev/null +++ b/queue-5.4/net-dsa-sja1105-discard-incoming-frames-in-br_state_.patch @@ -0,0 +1,92 @@ +From 386ab7ac3886f796009ef09da76014df6ee4b179 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 May 2025 14:38:16 +0300 +Subject: net: dsa: sja1105: discard incoming frames in BR_STATE_LISTENING + +From: Vladimir Oltean + +[ Upstream commit 498625a8ab2c8e1c9ab5105744310e8d6952cc01 ] + +It has been reported that when under a bridge with stp_state=1, the logs +get spammed with this message: + +[ 251.734607] fsl_dpaa2_eth dpni.5 eth0: Couldn't decode source port + +Further debugging shows the following info associated with packets: +source_port=-1, switch_id=-1, vid=-1, vbid=1 + +In other words, they are data plane packets which are supposed to be +decoded by dsa_tag_8021q_find_port_by_vbid(), but the latter (correctly) +refuses to do so, because no switch port is currently in +BR_STATE_LEARNING or BR_STATE_FORWARDING - so the packet is effectively +unexpected. + +The error goes away after the port progresses to BR_STATE_LEARNING in 15 +seconds (the default forward_time of the bridge), because then, +dsa_tag_8021q_find_port_by_vbid() can correctly associate the data plane +packets with a plausible bridge port in a plausible STP state. + +Re-reading IEEE 802.1D-1990, I see the following: + +"4.4.2 Learning: (...) The Forwarding Process shall discard received +frames." + +IEEE 802.1D-2004 further clarifies: + +"DISABLED, BLOCKING, LISTENING, and BROKEN all correspond to the +DISCARDING port state. While those dot1dStpPortStates serve to +distinguish reasons for discarding frames, the operation of the +Forwarding and Learning processes is the same for all of them. (...) +LISTENING represents a port that the spanning tree algorithm has +selected to be part of the active topology (computing a Root Port or +Designated Port role) but is temporarily discarding frames to guard +against loops or incorrect learning." + +Well, this is not what the driver does - instead it sets +mac[port].ingress = true. + +To get rid of the log spam, prevent unexpected data plane packets to +be received by software by discarding them on ingress in the LISTENING +state. + +In terms of blame attribution: the prints only date back to commit +d7f9787a763f ("net: dsa: tag_8021q: add support for imprecise RX based +on the VBID"). However, the settings would permit a LISTENING port to +forward to a FORWARDING port, and the standard suggests that's not OK. + +Fixes: 640f763f98c2 ("net: dsa: sja1105: Add support for Spanning Tree Protocol") +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20250509113816.2221992-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_main.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index eab861352bf23..007eb05ed659f 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -1390,6 +1390,7 @@ static void sja1105_bridge_stp_state_set(struct dsa_switch *ds, int port, + switch (state) { + case BR_STATE_DISABLED: + case BR_STATE_BLOCKING: ++ case BR_STATE_LISTENING: + /* From UM10944 description of DRPDTAG (why put this there?): + * "Management traffic flows to the port regardless of the state + * of the INGRESS flag". So BPDUs are still be allowed to pass. +@@ -1399,11 +1400,6 @@ static void sja1105_bridge_stp_state_set(struct dsa_switch *ds, int port, + mac[port].egress = false; + mac[port].dyn_learn = false; + break; +- case BR_STATE_LISTENING: +- mac[port].ingress = true; +- mac[port].egress = false; +- mac[port].dyn_learn = false; +- break; + case BR_STATE_LEARNING: + mac[port].ingress = true; + mac[port].egress = false; +-- +2.39.5 + diff --git a/queue-5.4/nfs-handle-failure-of-nfs_get_lock_context-in-unlock.patch b/queue-5.4/nfs-handle-failure-of-nfs_get_lock_context-in-unlock.patch new file mode 100644 index 0000000000..841889c1af --- /dev/null +++ b/queue-5.4/nfs-handle-failure-of-nfs_get_lock_context-in-unlock.patch @@ -0,0 +1,97 @@ +From bff46f3446358d126f30a5be496428102b12edac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Apr 2025 15:25:08 +0800 +Subject: nfs: handle failure of nfs_get_lock_context in unlock path + +From: Li Lingfeng + +[ Upstream commit c457dc1ec770a22636b473ce5d35614adfe97636 ] + +When memory is insufficient, the allocation of nfs_lock_context in +nfs_get_lock_context() fails and returns -ENOMEM. If we mistakenly treat +an nfs4_unlockdata structure (whose l_ctx member has been set to -ENOMEM) +as valid and proceed to execute rpc_run_task(), this will trigger a NULL +pointer dereference in nfs4_locku_prepare. For example: + +BUG: kernel NULL pointer dereference, address: 000000000000000c +PGD 0 P4D 0 +Oops: Oops: 0000 [#1] SMP PTI +CPU: 15 UID: 0 PID: 12 Comm: kworker/u64:0 Not tainted 6.15.0-rc2-dirty #60 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-2.fc40 +Workqueue: rpciod rpc_async_schedule +RIP: 0010:nfs4_locku_prepare+0x35/0xc2 +Code: 89 f2 48 89 fd 48 c7 c7 68 69 ef b5 53 48 8b 8e 90 00 00 00 48 89 f3 +RSP: 0018:ffffbbafc006bdb8 EFLAGS: 00010246 +RAX: 000000000000004b RBX: ffff9b964fc1fa00 RCX: 0000000000000000 +RDX: 0000000000000000 RSI: fffffffffffffff4 RDI: ffff9ba53fddbf40 +RBP: ffff9ba539934000 R08: 0000000000000000 R09: ffffbbafc006bc38 +R10: ffffffffb6b689c8 R11: 0000000000000003 R12: ffff9ba539934030 +R13: 0000000000000001 R14: 0000000004248060 R15: ffffffffb56d1c30 +FS: 0000000000000000(0000) GS:ffff9ba5881f0000(0000) knlGS:00000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000000000000000c CR3: 000000093f244000 CR4: 00000000000006f0 +Call Trace: + + __rpc_execute+0xbc/0x480 + rpc_async_schedule+0x2f/0x40 + process_one_work+0x232/0x5d0 + worker_thread+0x1da/0x3d0 + ? __pfx_worker_thread+0x10/0x10 + kthread+0x10d/0x240 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x34/0x50 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + +Modules linked in: +CR2: 000000000000000c +---[ end trace 0000000000000000 ]--- + +Free the allocated nfs4_unlockdata when nfs_get_lock_context() fails and +return NULL to terminate subsequent rpc_run_task, preventing NULL pointer +dereference. + +Fixes: f30cb757f680 ("NFS: Always wait for I/O completion before unlock") +Signed-off-by: Li Lingfeng +Reviewed-by: Jeff Layton +Link: https://lore.kernel.org/r/20250417072508.3850532-1-lilingfeng3@huawei.com +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4proc.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 632cea3fb91da..3477da3c2190e 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -6573,10 +6573,18 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, + struct nfs4_unlockdata *p; + struct nfs4_state *state = lsp->ls_state; + struct inode *inode = state->inode; ++ struct nfs_lock_context *l_ctx; + + p = kzalloc(sizeof(*p), GFP_NOFS); + if (p == NULL) + return NULL; ++ l_ctx = nfs_get_lock_context(ctx); ++ if (!IS_ERR(l_ctx)) { ++ p->l_ctx = l_ctx; ++ } else { ++ kfree(p); ++ return NULL; ++ } + p->arg.fh = NFS_FH(inode); + p->arg.fl = &p->fl; + p->arg.seqid = seqid; +@@ -6584,7 +6592,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, + p->lsp = lsp; + /* Ensure we don't close file until we're done freeing locks! */ + p->ctx = get_nfs_open_context(ctx); +- p->l_ctx = nfs_get_lock_context(ctx); + locks_init_lock(&p->fl); + locks_copy_lock(&p->fl, fl); + p->server = NFS_SERVER(inode); +-- +2.39.5 + diff --git a/queue-5.4/nfsv4-pnfs-pnfs_set_layout_stateid-should-update-the.patch b/queue-5.4/nfsv4-pnfs-pnfs_set_layout_stateid-should-update-the.patch new file mode 100644 index 0000000000..b1143cbc3e --- /dev/null +++ b/queue-5.4/nfsv4-pnfs-pnfs_set_layout_stateid-should-update-the.patch @@ -0,0 +1,111 @@ +From fbe767e4e91e409e6c2be2ce01901b76b2ce5e0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2020 13:07:26 -0500 +Subject: NFSv4/pnfs: pnfs_set_layout_stateid() should update the layout cred + +From: Trond Myklebust + +[ Upstream commit 59b5639490f51aa604d18064dcf0c2d72eb1decf ] + +If the cred assigned to the layout that we're updating differs from +the one used to retrieve the new layout segment, then we need to +update the layout plh_lc_cred field. + +Signed-off-by: Trond Myklebust +Stable-dep-of: 6d6d7f91cc8c ("NFSv4/pnfs: Reset the layout state after a layoutreturn") +Signed-off-by: Sasha Levin +--- + fs/nfs/callback_proc.c | 2 +- + fs/nfs/pnfs.c | 20 ++++++++++++++++---- + fs/nfs/pnfs.h | 1 + + 3 files changed, 18 insertions(+), 5 deletions(-) + +diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c +index 31922657e836e..1397e0816ba09 100644 +--- a/fs/nfs/callback_proc.c ++++ b/fs/nfs/callback_proc.c +@@ -284,7 +284,7 @@ static u32 initiate_file_draining(struct nfs_client *clp, + goto unlock; + } + +- pnfs_set_layout_stateid(lo, &args->cbl_stateid, true); ++ pnfs_set_layout_stateid(lo, &args->cbl_stateid, NULL, true); + switch (pnfs_mark_matching_lsegs_return(lo, &free_me_list, + &args->cbl_range, + be32_to_cpu(args->cbl_stateid.seqid))) { +diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c +index 90961dae4dc3b..a6362c07cff63 100644 +--- a/fs/nfs/pnfs.c ++++ b/fs/nfs/pnfs.c +@@ -943,10 +943,21 @@ pnfs_destroy_all_layouts(struct nfs_client *clp) + pnfs_destroy_layouts_byclid(clp, false); + } + ++static void ++pnfs_set_layout_cred(struct pnfs_layout_hdr *lo, const struct cred *cred) ++{ ++ const struct cred *old; ++ ++ if (cred && cred_fscmp(lo->plh_lc_cred, cred) != 0) { ++ old = xchg(&lo->plh_lc_cred, get_cred(cred)); ++ put_cred(old); ++ } ++} ++ + /* update lo->plh_stateid with new if is more recent */ + void + pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new, +- bool update_barrier) ++ const struct cred *cred, bool update_barrier) + { + u32 oldseq, newseq, new_barrier = 0; + +@@ -954,6 +965,7 @@ pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new, + newseq = be32_to_cpu(new->seqid); + + if (!pnfs_layout_is_valid(lo)) { ++ pnfs_set_layout_cred(lo, cred); + nfs4_stateid_copy(&lo->plh_stateid, new); + lo->plh_barrier = newseq; + pnfs_clear_layoutreturn_info(lo); +@@ -1149,7 +1161,7 @@ void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo, + + pnfs_mark_matching_lsegs_invalid(lo, &freeme, range, seq); + pnfs_free_returned_lsegs(lo, &freeme, range, seq); +- pnfs_set_layout_stateid(lo, stateid, true); ++ pnfs_set_layout_stateid(lo, stateid, NULL, true); + } else + pnfs_mark_layout_stateid_invalid(lo, &freeme); + out_unlock: +@@ -2382,14 +2394,14 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) + + if (!pnfs_layout_is_valid(lo)) { + /* We have a completely new layout */ +- pnfs_set_layout_stateid(lo, &res->stateid, true); ++ pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, true); + } else if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) { + /* existing state ID, make sure the sequence number matches. */ + if (pnfs_layout_stateid_blocked(lo, &res->stateid)) { + dprintk("%s forget reply due to sequence\n", __func__); + goto out_forget; + } +- pnfs_set_layout_stateid(lo, &res->stateid, false); ++ pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, false); + } else { + /* + * We got an entirely new state ID. Mark all segments for the +diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h +index 68339680bb7d1..b0f91a4592cb5 100644 +--- a/fs/nfs/pnfs.h ++++ b/fs/nfs/pnfs.h +@@ -270,6 +270,7 @@ bool nfs4_layout_refresh_old_stateid(nfs4_stateid *dst, + void pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo); + void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, + const nfs4_stateid *new, ++ const struct cred *cred, + bool update_barrier); + int pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, + struct list_head *tmp_list, +-- +2.39.5 + diff --git a/queue-5.4/nfsv4-pnfs-reset-the-layout-state-after-a-layoutretu.patch b/queue-5.4/nfsv4-pnfs-reset-the-layout-state-after-a-layoutretu.patch new file mode 100644 index 0000000000..354919a3ca --- /dev/null +++ b/queue-5.4/nfsv4-pnfs-reset-the-layout-state-after-a-layoutretu.patch @@ -0,0 +1,50 @@ +From 162452f8f30ab3825cd2ec6f477a1dde3a5db9bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 May 2025 10:50:13 -0400 +Subject: NFSv4/pnfs: Reset the layout state after a layoutreturn + +From: Trond Myklebust + +[ Upstream commit 6d6d7f91cc8c111d40416ac9240a3bb9396c5235 ] + +If there are still layout segments in the layout plh_return_lsegs list +after a layout return, we should be resetting the state to ensure they +eventually get returned as well. + +Fixes: 68f744797edd ("pNFS: Do not free layout segments that are marked for return") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/pnfs.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c +index a6362c07cff63..d91576a587e4e 100644 +--- a/fs/nfs/pnfs.c ++++ b/fs/nfs/pnfs.c +@@ -710,6 +710,14 @@ pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, + return remaining; + } + ++static void pnfs_reset_return_info(struct pnfs_layout_hdr *lo) ++{ ++ struct pnfs_layout_segment *lseg; ++ ++ list_for_each_entry(lseg, &lo->plh_return_segs, pls_list) ++ pnfs_set_plh_return_info(lo, lseg->pls_range.iomode, 0); ++} ++ + static void + pnfs_free_returned_lsegs(struct pnfs_layout_hdr *lo, + struct list_head *free_me, +@@ -1162,6 +1170,7 @@ void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo, + pnfs_mark_matching_lsegs_invalid(lo, &freeme, range, seq); + pnfs_free_returned_lsegs(lo, &freeme, range, seq); + pnfs_set_layout_stateid(lo, stateid, NULL, true); ++ pnfs_reset_return_info(lo); + } else + pnfs_mark_layout_stateid_invalid(lo, &freeme); + out_unlock: +-- +2.39.5 + diff --git a/queue-5.4/platform-x86-asus-wmi-fix-wlan_ctrl_by_user-detectio.patch b/queue-5.4/platform-x86-asus-wmi-fix-wlan_ctrl_by_user-detectio.patch new file mode 100644 index 0000000000..87556ff655 --- /dev/null +++ b/queue-5.4/platform-x86-asus-wmi-fix-wlan_ctrl_by_user-detectio.patch @@ -0,0 +1,76 @@ +From f4af9011d15c4f36dd16614859b204eae66fe90e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 May 2025 15:17:02 +0200 +Subject: platform/x86: asus-wmi: Fix wlan_ctrl_by_user detection +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hans de Goede + +[ Upstream commit bfcfe6d335a967f8ea0c1980960e6f0205b5de6e ] + +The wlan_ctrl_by_user detection was introduced by commit a50bd128f28c +("asus-wmi: record wlan status while controlled by userapp"). + +Quoting from that commit's commit message: + +""" +When you call WMIMethod(DSTS, 0x00010011) to get WLAN status, it may return + +(1) 0x00050001 (On) +(2) 0x00050000 (Off) +(3) 0x00030001 (On) +(4) 0x00030000 (Off) +(5) 0x00000002 (Unknown) + +(1), (2) means that the model has hardware GPIO for WLAN, you can call +WMIMethod(DEVS, 0x00010011, 1 or 0) to turn WLAN on/off. +(3), (4) means that the model doesn’t have hardware GPIO, you need to use +API or driver library to turn WLAN on/off, and call +WMIMethod(DEVS, 0x00010012, 1 or 0) to set WLAN LED status. +After you set WLAN LED status, you can see the WLAN status is changed with +WMIMethod(DSTS, 0x00010011). Because the status is recorded lastly +(ex: Windows), you can use it for synchronization. +(5) means that the model doesn’t have WLAN device. + +WLAN is the ONLY special case with upper rule. +""" + +The wlan_ctrl_by_user flag should be set on 0x0003000? ((3), (4) above) +return values, but the flag mistakenly also gets set on laptops with +0x0005000? ((1), (2)) return values. This is causing rfkill problems on +laptops where 0x0005000? is returned. + +Fix the check to only set the wlan_ctrl_by_user flag for 0x0003000? +return values. + +Fixes: a50bd128f28c ("asus-wmi: record wlan status while controlled by userapp") +Link: https://bugzilla.kernel.org/show_bug.cgi?id=219786 +Signed-off-by: Hans de Goede +Reviewed-by: Armin Wolf +Link: https://lore.kernel.org/r/20250501131702.103360-2-hdegoede@redhat.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-wmi.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index 761cab698c750..9e8be6c52e3d3 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -2458,7 +2458,8 @@ static int asus_wmi_add(struct platform_device *pdev) + goto fail_leds; + + asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result); +- if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) ++ if ((result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) == ++ (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) + asus->driver->wlan_ctrl_by_user = 1; + + if (!(asus->driver->wlan_ctrl_by_user && ashs_present())) { +-- +2.39.5 + diff --git a/queue-5.4/qlcnic-fix-memory-leak-in-qlcnic_sriov_channel_cfg_c.patch b/queue-5.4/qlcnic-fix-memory-leak-in-qlcnic_sriov_channel_cfg_c.patch new file mode 100644 index 0000000000..4f69f72f2b --- /dev/null +++ b/queue-5.4/qlcnic-fix-memory-leak-in-qlcnic_sriov_channel_cfg_c.patch @@ -0,0 +1,45 @@ +From e74cb0cb067b381897c1729cb7722ed361a83996 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 May 2025 10:18:27 +0530 +Subject: qlcnic: fix memory leak in qlcnic_sriov_channel_cfg_cmd() + +From: Abdun Nihaal + +[ Upstream commit 9d8a99c5a7c7f4f7eca2c168a4ec254409670035 ] + +In one of the error paths in qlcnic_sriov_channel_cfg_cmd(), the memory +allocated in qlcnic_sriov_alloc_bc_mbx_args() for mailbox arguments is +not freed. Fix that by jumping to the error path that frees them, by +calling qlcnic_free_mbx_args(). This was found using static analysis. + +Fixes: f197a7aa6288 ("qlcnic: VF-PF communication channel implementation") +Signed-off-by: Abdun Nihaal +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250512044829.36400-1-abdun.nihaal@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +index 5d8b9e10ddf84..d6fcef1651a7e 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +@@ -1486,8 +1486,11 @@ static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_o + } + + cmd_op = (cmd.rsp.arg[0] & 0xff); +- if (cmd.rsp.arg[0] >> 25 == 2) +- return 2; ++ if (cmd.rsp.arg[0] >> 25 == 2) { ++ ret = 2; ++ goto out; ++ } ++ + if (cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) + set_bit(QLC_BC_VF_STATE, &vf->state); + else +-- +2.39.5 + diff --git a/queue-5.4/rdma-rxe-fix-slab-use-after-free-read-in-rxe_queue_c.patch b/queue-5.4/rdma-rxe-fix-slab-use-after-free-read-in-rxe_queue_c.patch new file mode 100644 index 0000000000..e810aa40fb --- /dev/null +++ b/queue-5.4/rdma-rxe-fix-slab-use-after-free-read-in-rxe_queue_c.patch @@ -0,0 +1,69 @@ +From 38e852239fef17b19ae64dcaa190ca70582e938c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 12 Apr 2025 09:57:14 +0200 +Subject: RDMA/rxe: Fix slab-use-after-free Read in rxe_queue_cleanup bug + +From: Zhu Yanjun + +[ Upstream commit f81b33582f9339d2dc17c69b92040d3650bb4bae ] + +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x7d/0xa0 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 [inline] + print_report+0xcf/0x610 mm/kasan/report.c:489 + kasan_report+0xb5/0xe0 mm/kasan/report.c:602 + rxe_queue_cleanup+0xd0/0xe0 drivers/infiniband/sw/rxe/rxe_queue.c:195 + rxe_cq_cleanup+0x3f/0x50 drivers/infiniband/sw/rxe/rxe_cq.c:132 + __rxe_cleanup+0x168/0x300 drivers/infiniband/sw/rxe/rxe_pool.c:232 + rxe_create_cq+0x22e/0x3a0 drivers/infiniband/sw/rxe/rxe_verbs.c:1109 + create_cq+0x658/0xb90 drivers/infiniband/core/uverbs_cmd.c:1052 + ib_uverbs_create_cq+0xc7/0x120 drivers/infiniband/core/uverbs_cmd.c:1095 + ib_uverbs_write+0x969/0xc90 drivers/infiniband/core/uverbs_main.c:679 + vfs_write fs/read_write.c:677 [inline] + vfs_write+0x26a/0xcc0 fs/read_write.c:659 + ksys_write+0x1b8/0x200 fs/read_write.c:731 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xaa/0x1b0 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +In the function rxe_create_cq, when rxe_cq_from_init fails, the function +rxe_cleanup will be called to handle the allocated resources. In fact, +some memory resources have already been freed in the function +rxe_cq_from_init. Thus, this problem will occur. + +The solution is to let rxe_cleanup do all the work. + +Fixes: 8700e3e7c485 ("Soft RoCE driver") +Link: https://paste.ubuntu.com/p/tJgC42wDf6/ +Tested-by: liuyi +Signed-off-by: Zhu Yanjun +Link: https://patch.msgid.link/20250412075714.3257358-1-yanjun.zhu@linux.dev +Reviewed-by: Daisuke Matsuda +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/rxe/rxe_cq.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/infiniband/sw/rxe/rxe_cq.c b/drivers/infiniband/sw/rxe/rxe_cq.c +index ad30901311268..81f66ba6bf359 100644 +--- a/drivers/infiniband/sw/rxe/rxe_cq.c ++++ b/drivers/infiniband/sw/rxe/rxe_cq.c +@@ -96,11 +96,8 @@ int rxe_cq_from_init(struct rxe_dev *rxe, struct rxe_cq *cq, int cqe, + + err = do_mmap_info(rxe, uresp ? &uresp->mi : NULL, udata, + cq->queue->buf, cq->queue->buf_size, &cq->queue->ip); +- if (err) { +- vfree(cq->queue->buf); +- kfree(cq->queue); ++ if (err) + return err; +- } + + if (uresp) + cq->is_user = 1; +-- +2.39.5 + diff --git a/queue-5.4/series b/queue-5.4/series index 99e6fb721f..e501a98372 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -59,3 +59,18 @@ iio-adc-dln2-use-aligned_s64-for-timestamp.patch mips-fix-max_reg_offset.patch nvme-unblock-ctrl-state-transition-for-firmware-upda.patch do_umount-add-missing-barrier-before-refcount-checks.patch +platform-x86-asus-wmi-fix-wlan_ctrl_by_user-detectio.patch +staging-axis-fifo-replace-spinlock-with-mutex.patch +staging-axis-fifo-remove-hardware-resets-for-user-er.patch +staging-axis-fifo-avoid-parsing-ignored-device-tree-.patch +staging-axis-fifo-correct-handling-of-tx_fifo_depth-.patch +iio-adc-ad7768-1-fix-insufficient-alignment-of-times.patch +iio-chemical-sps30-use-aligned_s64-for-timestamp.patch +rdma-rxe-fix-slab-use-after-free-read-in-rxe_queue_c.patch +nfs-handle-failure-of-nfs_get_lock_context-in-unlock.patch +spi-loopback-test-do-not-split-1024-byte-hexdumps.patch +net-dsa-sja1105-discard-incoming-frames-in-br_state_.patch +alsa-sh-snd_aica-should-depend-on-sh_dma_api.patch +qlcnic-fix-memory-leak-in-qlcnic_sriov_channel_cfg_c.patch +nfsv4-pnfs-pnfs_set_layout_stateid-should-update-the.patch +nfsv4-pnfs-reset-the-layout-state-after-a-layoutretu.patch diff --git a/queue-5.4/spi-loopback-test-do-not-split-1024-byte-hexdumps.patch b/queue-5.4/spi-loopback-test-do-not-split-1024-byte-hexdumps.patch new file mode 100644 index 0000000000..394bfdea41 --- /dev/null +++ b/queue-5.4/spi-loopback-test-do-not-split-1024-byte-hexdumps.patch @@ -0,0 +1,43 @@ +From cfd870ccd4aeb0131e7f9395aa5eb15a5e37efe9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 May 2025 13:10:35 +0200 +Subject: spi: loopback-test: Do not split 1024-byte hexdumps + +From: Geert Uytterhoeven + +[ Upstream commit a73fa3690a1f3014d6677e368dce4e70767a6ba2 ] + +spi_test_print_hex_dump() prints buffers holding less than 1024 bytes in +full. Larger buffers are truncated: only the first 512 and the last 512 +bytes are printed, separated by a truncation message. The latter is +confusing in case the buffer holds exactly 1024 bytes, as all data is +printed anyway. + +Fix this by printing buffers holding up to and including 1024 bytes in +full. + +Fixes: 84e0c4e5e2c4ef42 ("spi: add loopback test driver to allow for spi_master regression tests") +Signed-off-by: Geert Uytterhoeven +Link: https://patch.msgid.link/37ee1bc90c6554c9347040adabf04188c8f704aa.1746184171.git.geert+renesas@glider.be +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-loopback-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c +index 69a9df2cbbcf2..0f571ff132377 100644 +--- a/drivers/spi/spi-loopback-test.c ++++ b/drivers/spi/spi-loopback-test.c +@@ -377,7 +377,7 @@ MODULE_LICENSE("GPL"); + static void spi_test_print_hex_dump(char *pre, const void *ptr, size_t len) + { + /* limit the hex_dump */ +- if (len < 1024) { ++ if (len <= 1024) { + print_hex_dump(KERN_INFO, pre, + DUMP_PREFIX_OFFSET, 16, 1, + ptr, len, 0); +-- +2.39.5 + diff --git a/queue-5.4/staging-axis-fifo-avoid-parsing-ignored-device-tree-.patch b/queue-5.4/staging-axis-fifo-avoid-parsing-ignored-device-tree-.patch new file mode 100644 index 0000000000..ba9a0c667c --- /dev/null +++ b/queue-5.4/staging-axis-fifo-avoid-parsing-ignored-device-tree-.patch @@ -0,0 +1,344 @@ +From d52c382add71f0fe0becd2ac551edcba72b3913b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Nov 2019 21:42:50 +0000 +Subject: staging: axis-fifo: avoid parsing ignored device tree properties + +From: Quentin Deslandes + +[ Upstream commit ed6daf2b2832d9b07582a6ff884039afa9063206 ] + +Some properties were parsed from the device tree and then ignored by the +driver. Some would return an error if absent from the device tree, then +return an error if they were found because they are unsupported by the +driver. + +Avoid parsing unused properties and clearly explain in the documentation +the ignored / unsupported properties. + +Signed-off-by: Quentin Deslandes +Link: https://lore.kernel.org/r/20191101214232.16960-2-quentin.deslandes@itdev.co.uk +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 2ca34b508774 ("staging: axis-fifo: Correct handling of tx_fifo_depth for size validation") +Signed-off-by: Sasha Levin +--- + drivers/staging/axis-fifo/axis-fifo.c | 247 ++++++------------------ + drivers/staging/axis-fifo/axis-fifo.txt | 18 +- + 2 files changed, 74 insertions(+), 191 deletions(-) + +diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c +index 42528d4593b83..08f9990ab499a 100644 +--- a/drivers/staging/axis-fifo/axis-fifo.c ++++ b/drivers/staging/axis-fifo/axis-fifo.c +@@ -738,6 +738,68 @@ static int get_dts_property(struct axis_fifo *fifo, + return 0; + } + ++static int axis_fifo_parse_dt(struct axis_fifo *fifo) ++{ ++ int ret; ++ unsigned int value; ++ ++ ret = get_dts_property(fifo, "xlnx,axi-str-rxd-tdata-width", &value); ++ if (ret) { ++ dev_err(fifo->dt_device, "missing xlnx,axi-str-rxd-tdata-width property\n"); ++ goto end; ++ } else if (value != 32) { ++ dev_err(fifo->dt_device, "xlnx,axi-str-rxd-tdata-width only supports 32 bits\n"); ++ ret = -EIO; ++ goto end; ++ } ++ ++ ret = get_dts_property(fifo, "xlnx,axi-str-txd-tdata-width", &value); ++ if (ret) { ++ dev_err(fifo->dt_device, "missing xlnx,axi-str-txd-tdata-width property\n"); ++ goto end; ++ } else if (value != 32) { ++ dev_err(fifo->dt_device, "xlnx,axi-str-txd-tdata-width only supports 32 bits\n"); ++ ret = -EIO; ++ goto end; ++ } ++ ++ ret = get_dts_property(fifo, "xlnx,rx-fifo-depth", ++ &fifo->rx_fifo_depth); ++ if (ret) { ++ dev_err(fifo->dt_device, "missing xlnx,rx-fifo-depth property\n"); ++ ret = -EIO; ++ goto end; ++ } ++ ++ ret = get_dts_property(fifo, "xlnx,tx-fifo-depth", ++ &fifo->tx_fifo_depth); ++ if (ret) { ++ dev_err(fifo->dt_device, "missing xlnx,tx-fifo-depth property\n"); ++ ret = -EIO; ++ goto end; ++ } ++ ++ /* IP sets TDFV to fifo depth - 4 so we will do the same */ ++ fifo->tx_fifo_depth -= 4; ++ ++ ret = get_dts_property(fifo, "xlnx,use-rx-data", &fifo->has_rx_fifo); ++ if (ret) { ++ dev_err(fifo->dt_device, "missing xlnx,use-rx-data property\n"); ++ ret = -EIO; ++ goto end; ++ } ++ ++ ret = get_dts_property(fifo, "xlnx,use-tx-data", &fifo->has_tx_fifo); ++ if (ret) { ++ dev_err(fifo->dt_device, "missing xlnx,use-tx-data property\n"); ++ ret = -EIO; ++ goto end; ++ } ++ ++end: ++ return ret; ++} ++ + static int axis_fifo_probe(struct platform_device *pdev) + { + struct resource *r_irq; /* interrupt resources */ +@@ -749,34 +811,6 @@ static int axis_fifo_probe(struct platform_device *pdev) + + int rc = 0; /* error return value */ + +- /* IP properties from device tree */ +- unsigned int rxd_tdata_width; +- unsigned int txc_tdata_width; +- unsigned int txd_tdata_width; +- unsigned int tdest_width; +- unsigned int tid_width; +- unsigned int tuser_width; +- unsigned int data_interface_type; +- unsigned int has_tdest; +- unsigned int has_tid; +- unsigned int has_tkeep; +- unsigned int has_tstrb; +- unsigned int has_tuser; +- unsigned int rx_fifo_depth; +- unsigned int rx_programmable_empty_threshold; +- unsigned int rx_programmable_full_threshold; +- unsigned int axi_id_width; +- unsigned int axi4_data_width; +- unsigned int select_xpm; +- unsigned int tx_fifo_depth; +- unsigned int tx_programmable_empty_threshold; +- unsigned int tx_programmable_full_threshold; +- unsigned int use_rx_cut_through; +- unsigned int use_rx_data; +- unsigned int use_tx_control; +- unsigned int use_tx_cut_through; +- unsigned int use_tx_data; +- + /* ---------------------------- + * init wrapper device + * ---------------------------- +@@ -843,164 +877,9 @@ static int axis_fifo_probe(struct platform_device *pdev) + * ---------------------------- + */ + +- /* retrieve device tree properties */ +- rc = get_dts_property(fifo, "xlnx,axi-str-rxd-tdata-width", +- &rxd_tdata_width); ++ rc = axis_fifo_parse_dt(fifo); + if (rc) + goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,axi-str-txc-tdata-width", +- &txc_tdata_width); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,axi-str-txd-tdata-width", +- &txd_tdata_width); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,axis-tdest-width", &tdest_width); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,axis-tid-width", &tid_width); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,axis-tuser-width", &tuser_width); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,data-interface-type", +- &data_interface_type); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,has-axis-tdest", &has_tdest); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,has-axis-tid", &has_tid); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,has-axis-tkeep", &has_tkeep); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,has-axis-tstrb", &has_tstrb); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,has-axis-tuser", &has_tuser); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,rx-fifo-depth", &rx_fifo_depth); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,rx-fifo-pe-threshold", +- &rx_programmable_empty_threshold); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,rx-fifo-pf-threshold", +- &rx_programmable_full_threshold); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,s-axi-id-width", &axi_id_width); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,s-axi4-data-width", &axi4_data_width); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,select-xpm", &select_xpm); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,tx-fifo-depth", &tx_fifo_depth); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,tx-fifo-pe-threshold", +- &tx_programmable_empty_threshold); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,tx-fifo-pf-threshold", +- &tx_programmable_full_threshold); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,use-rx-cut-through", +- &use_rx_cut_through); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,use-rx-data", &use_rx_data); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,use-tx-ctrl", &use_tx_control); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,use-tx-cut-through", +- &use_tx_cut_through); +- if (rc) +- goto err_unmap; +- rc = get_dts_property(fifo, "xlnx,use-tx-data", &use_tx_data); +- if (rc) +- goto err_unmap; +- +- /* check validity of device tree properties */ +- if (rxd_tdata_width != 32) { +- dev_err(fifo->dt_device, +- "rxd_tdata_width width [%u] unsupported\n", +- rxd_tdata_width); +- rc = -EIO; +- goto err_unmap; +- } +- if (txd_tdata_width != 32) { +- dev_err(fifo->dt_device, +- "txd_tdata_width width [%u] unsupported\n", +- txd_tdata_width); +- rc = -EIO; +- goto err_unmap; +- } +- if (has_tdest) { +- dev_err(fifo->dt_device, "tdest not supported\n"); +- rc = -EIO; +- goto err_unmap; +- } +- if (has_tid) { +- dev_err(fifo->dt_device, "tid not supported\n"); +- rc = -EIO; +- goto err_unmap; +- } +- if (has_tkeep) { +- dev_err(fifo->dt_device, "tkeep not supported\n"); +- rc = -EIO; +- goto err_unmap; +- } +- if (has_tstrb) { +- dev_err(fifo->dt_device, "tstrb not supported\n"); +- rc = -EIO; +- goto err_unmap; +- } +- if (has_tuser) { +- dev_err(fifo->dt_device, "tuser not supported\n"); +- rc = -EIO; +- goto err_unmap; +- } +- if (use_rx_cut_through) { +- dev_err(fifo->dt_device, "rx cut-through not supported\n"); +- rc = -EIO; +- goto err_unmap; +- } +- if (use_tx_cut_through) { +- dev_err(fifo->dt_device, "tx cut-through not supported\n"); +- rc = -EIO; +- goto err_unmap; +- } +- if (use_tx_control) { +- dev_err(fifo->dt_device, "tx control not supported\n"); +- rc = -EIO; +- goto err_unmap; +- } +- +- /* TODO +- * these exist in the device tree but it's unclear what they do +- * - select-xpm +- * - data-interface-type +- */ +- +- /* set device wrapper properties based on IP config */ +- fifo->rx_fifo_depth = rx_fifo_depth; +- /* IP sets TDFV to fifo depth - 4 so we will do the same */ +- fifo->tx_fifo_depth = tx_fifo_depth - 4; +- fifo->has_rx_fifo = use_rx_data; +- fifo->has_tx_fifo = use_tx_data; + + reset_ip_core(fifo); + +diff --git a/drivers/staging/axis-fifo/axis-fifo.txt b/drivers/staging/axis-fifo/axis-fifo.txt +index 85d88c010e724..5828e1b8e8223 100644 +--- a/drivers/staging/axis-fifo/axis-fifo.txt ++++ b/drivers/staging/axis-fifo/axis-fifo.txt +@@ -25,10 +25,10 @@ Required properties: + - xlnx,axi-str-txc-tdata-width: Should be <0x20> + - xlnx,axi-str-txd-protocol: Should be "XIL_AXI_STREAM_ETH_DATA" + - xlnx,axi-str-txd-tdata-width: Should be <0x20> +-- xlnx,axis-tdest-width: AXI-Stream TDEST width +-- xlnx,axis-tid-width: AXI-Stream TID width +-- xlnx,axis-tuser-width: AXI-Stream TUSER width +-- xlnx,data-interface-type: Should be <0x0> ++- xlnx,axis-tdest-width: AXI-Stream TDEST width (ignored by the driver) ++- xlnx,axis-tid-width: AXI-Stream TID width (ignored by the driver) ++- xlnx,axis-tuser-width: AXI-Stream TUSER width (ignored by the driver) ++- xlnx,data-interface-type: Should be <0x0> (ignored by the driver) + - xlnx,has-axis-tdest: Should be <0x0> (this feature isn't supported) + - xlnx,has-axis-tid: Should be <0x0> (this feature isn't supported) + - xlnx,has-axis-tkeep: Should be <0x0> (this feature isn't supported) +@@ -36,13 +36,17 @@ Required properties: + - xlnx,has-axis-tuser: Should be <0x0> (this feature isn't supported) + - xlnx,rx-fifo-depth: Depth of RX FIFO in words + - xlnx,rx-fifo-pe-threshold: RX programmable empty interrupt threshold ++ (ignored by the driver) + - xlnx,rx-fifo-pf-threshold: RX programmable full interrupt threshold +-- xlnx,s-axi-id-width: Should be <0x4> +-- xlnx,s-axi4-data-width: Should be <0x20> +-- xlnx,select-xpm: Should be <0x0> ++ (ignored by the driver) ++- xlnx,s-axi-id-width: Should be <0x4> (ignored by the driver) ++- xlnx,s-axi4-data-width: Should be <0x20> (ignored by the driver) ++- xlnx,select-xpm: Should be <0x0> (ignored by the driver) + - xlnx,tx-fifo-depth: Depth of TX FIFO in words + - xlnx,tx-fifo-pe-threshold: TX programmable empty interrupt threshold ++ (ignored by the driver) + - xlnx,tx-fifo-pf-threshold: TX programmable full interrupt threshold ++ (ignored by the driver) + - xlnx,use-rx-cut-through: Should be <0x0> (this feature isn't supported) + - xlnx,use-rx-data: <0x1> if RX FIFO is enabled, <0x0> otherwise + - xlnx,use-tx-ctrl: Should be <0x0> (this feature isn't supported) +-- +2.39.5 + diff --git a/queue-5.4/staging-axis-fifo-correct-handling-of-tx_fifo_depth-.patch b/queue-5.4/staging-axis-fifo-correct-handling-of-tx_fifo_depth-.patch new file mode 100644 index 0000000000..a018af61d4 --- /dev/null +++ b/queue-5.4/staging-axis-fifo-correct-handling-of-tx_fifo_depth-.patch @@ -0,0 +1,45 @@ +From 7a36666f1f82bfd2ed2bf0fb9316e7e2e79cc173 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Apr 2025 21:29:37 -0400 +Subject: staging: axis-fifo: Correct handling of tx_fifo_depth for size + validation + +From: Gabriel Shahrouzi + +[ Upstream commit 2ca34b508774aaa590fc3698a54204706ecca4ba ] + +Remove erroneous subtraction of 4 from the total FIFO depth read from +device tree. The stored depth is for checking against total capacity, +not initial vacancy. This prevented writes near the FIFO's full size. + +The check performed just before data transfer, which uses live reads of +the TDFV register to determine current vacancy, correctly handles the +initial Depth - 4 hardware state and subsequent FIFO fullness. + +Fixes: 4a965c5f89de ("staging: add driver for Xilinx AXI-Stream FIFO v4.1 IP core") +Cc: stable@vger.kernel.org +Signed-off-by: Gabriel Shahrouzi +Link: https://lore.kernel.org/r/20250419012937.674924-1-gshahrouzi@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/axis-fifo/axis-fifo.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c +index 08f9990ab499a..4dd2c8e9b7878 100644 +--- a/drivers/staging/axis-fifo/axis-fifo.c ++++ b/drivers/staging/axis-fifo/axis-fifo.c +@@ -779,9 +779,6 @@ static int axis_fifo_parse_dt(struct axis_fifo *fifo) + goto end; + } + +- /* IP sets TDFV to fifo depth - 4 so we will do the same */ +- fifo->tx_fifo_depth -= 4; +- + ret = get_dts_property(fifo, "xlnx,use-rx-data", &fifo->has_rx_fifo); + if (ret) { + dev_err(fifo->dt_device, "missing xlnx,use-rx-data property\n"); +-- +2.39.5 + diff --git a/queue-5.4/staging-axis-fifo-remove-hardware-resets-for-user-er.patch b/queue-5.4/staging-axis-fifo-remove-hardware-resets-for-user-er.patch new file mode 100644 index 0000000000..42f82367e8 --- /dev/null +++ b/queue-5.4/staging-axis-fifo-remove-hardware-resets-for-user-er.patch @@ -0,0 +1,79 @@ +From 57f1ce28b04d2446bc62d89619be023c4449f312 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Apr 2025 20:43:06 -0400 +Subject: staging: axis-fifo: Remove hardware resets for user errors + +From: Gabriel Shahrouzi + +[ Upstream commit c6e8d85fafa7193613db37da29c0e8d6e2515b13 ] + +The axis-fifo driver performs a full hardware reset (via +reset_ip_core()) in several error paths within the read and write +functions. This reset flushes both TX and RX FIFOs and resets the +AXI-Stream links. + +Allow the user to handle the error without causing hardware disruption +or data loss in other FIFO paths. + +Fixes: 4a965c5f89de ("staging: add driver for Xilinx AXI-Stream FIFO v4.1 IP core") +Cc: stable@vger.kernel.org +Signed-off-by: Gabriel Shahrouzi +Link: https://lore.kernel.org/r/20250419004306.669605-1-gshahrouzi@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/axis-fifo/axis-fifo.c | 11 +++-------- + 1 file changed, 3 insertions(+), 8 deletions(-) + +diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c +index c1dd01c5c9ea6..42528d4593b83 100644 +--- a/drivers/staging/axis-fifo/axis-fifo.c ++++ b/drivers/staging/axis-fifo/axis-fifo.c +@@ -401,16 +401,14 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, + + bytes_available = ioread32(fifo->base_addr + XLLF_RLR_OFFSET); + if (!bytes_available) { +- dev_err(fifo->dt_device, "received a packet of length 0 - fifo core will be reset\n"); +- reset_ip_core(fifo); ++ dev_err(fifo->dt_device, "received a packet of length 0\n"); + ret = -EIO; + goto end_unlock; + } + + if (bytes_available > len) { +- dev_err(fifo->dt_device, "user read buffer too small (available bytes=%zu user buffer bytes=%zu) - fifo core will be reset\n", ++ dev_err(fifo->dt_device, "user read buffer too small (available bytes=%zu user buffer bytes=%zu)\n", + bytes_available, len); +- reset_ip_core(fifo); + ret = -EINVAL; + goto end_unlock; + } +@@ -419,8 +417,7 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, + /* this probably can't happen unless IP + * registers were previously mishandled + */ +- dev_err(fifo->dt_device, "received a packet that isn't word-aligned - fifo core will be reset\n"); +- reset_ip_core(fifo); ++ dev_err(fifo->dt_device, "received a packet that isn't word-aligned\n"); + ret = -EIO; + goto end_unlock; + } +@@ -441,7 +438,6 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, + + if (copy_to_user(buf + copied * sizeof(u32), tmp_buf, + copy * sizeof(u32))) { +- reset_ip_core(fifo); + ret = -EFAULT; + goto end_unlock; + } +@@ -551,7 +547,6 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf, + + if (copy_from_user(tmp_buf, buf + copied * sizeof(u32), + copy * sizeof(u32))) { +- reset_ip_core(fifo); + ret = -EFAULT; + goto end_unlock; + } +-- +2.39.5 + diff --git a/queue-5.4/staging-axis-fifo-replace-spinlock-with-mutex.patch b/queue-5.4/staging-axis-fifo-replace-spinlock-with-mutex.patch new file mode 100644 index 0000000000..9e8ad6594f --- /dev/null +++ b/queue-5.4/staging-axis-fifo-replace-spinlock-with-mutex.patch @@ -0,0 +1,314 @@ +From c65bf2163673387bf03785f4fa2439c981eab5c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jan 2020 10:40:24 +0000 +Subject: staging: axis-fifo: replace spinlock with mutex + +From: Quentin Deslandes + +[ Upstream commit 0443b3f4436321e1098fdf74432c8867016339da ] + +Following the device's documentation guidance, reading a packet from the +device or writing a packet to it must be atomic. Previously, only +reading device's vacancy (before writing on it) or occupancy (before +reading from it) was locked. Hence, effectively reading the packet or +writing the packet wasn't locked at all. However, reading a packet (and +writing one, to a lesser extent) requires to read 3 different registers +in a specific order, without missing one or else we should reset the +device. + +This patch fixes the device's locking mechanism on the FIFO character +device. As the device was using copy_from_user() and copy_to_user(), we +need to replace spinlocks with mutexes. + +Signed-off-by: Quentin Deslandes +Link: https://lore.kernel.org/r/20200121103958.12941-1-quentin.deslandes@itdev.co.uk +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: c6e8d85fafa7 ("staging: axis-fifo: Remove hardware resets for user errors") +Signed-off-by: Sasha Levin +--- + drivers/staging/axis-fifo/axis-fifo.c | 160 ++++++++++++++++---------- + 1 file changed, 101 insertions(+), 59 deletions(-) + +diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c +index 805437fa249a9..c1dd01c5c9ea6 100644 +--- a/drivers/staging/axis-fifo/axis-fifo.c ++++ b/drivers/staging/axis-fifo/axis-fifo.c +@@ -16,7 +16,7 @@ + + #include + #include +-#include ++#include + #include + #include + #include +@@ -134,9 +134,9 @@ struct axis_fifo { + int has_tx_fifo; /* whether the IP has the tx fifo enabled */ + + wait_queue_head_t read_queue; /* wait queue for asynchronos read */ +- spinlock_t read_queue_lock; /* lock for reading waitqueue */ ++ struct mutex read_lock; /* lock for reading */ + wait_queue_head_t write_queue; /* wait queue for asynchronos write */ +- spinlock_t write_queue_lock; /* lock for writing waitqueue */ ++ struct mutex write_lock; /* lock for writing */ + unsigned int write_flags; /* write file flags */ + unsigned int read_flags; /* read file flags */ + +@@ -337,7 +337,21 @@ static void reset_ip_core(struct axis_fifo *fifo) + iowrite32(XLLF_INT_ALL_MASK, fifo->base_addr + XLLF_ISR_OFFSET); + } + +-/* reads a single packet from the fifo as dictated by the tlast signal */ ++/** ++ * axis_fifo_write() - Read a packet from AXIS-FIFO character device. ++ * @f Open file. ++ * @buf User space buffer to read to. ++ * @len User space buffer length. ++ * @off Buffer offset. ++ * ++ * As defined by the device's documentation, we need to check the device's ++ * occupancy before reading the length register and then the data. All these ++ * operations must be executed atomically, in order and one after the other ++ * without missing any. ++ * ++ * Returns the number of bytes read from the device or negative error code ++ * on failure. ++ */ + static ssize_t axis_fifo_read(struct file *f, char __user *buf, + size_t len, loff_t *off) + { +@@ -351,36 +365,37 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, + u32 tmp_buf[READ_BUF_SIZE]; + + if (fifo->read_flags & O_NONBLOCK) { +- /* opened in non-blocking mode +- * return if there are no packets available ++ /* ++ * Device opened in non-blocking mode. Try to lock it and then ++ * check if any packet is available. + */ +- if (!ioread32(fifo->base_addr + XLLF_RDFO_OFFSET)) ++ if (!mutex_trylock(&fifo->read_lock)) + return -EAGAIN; ++ ++ if (!ioread32(fifo->base_addr + XLLF_RDFO_OFFSET)) { ++ ret = -EAGAIN; ++ goto end_unlock; ++ } + } else { + /* opened in blocking mode + * wait for a packet available interrupt (or timeout) + * if nothing is currently available + */ +- spin_lock_irq(&fifo->read_queue_lock); +- ret = wait_event_interruptible_lock_irq_timeout +- (fifo->read_queue, +- ioread32(fifo->base_addr + XLLF_RDFO_OFFSET), +- fifo->read_queue_lock, +- (read_timeout >= 0) ? msecs_to_jiffies(read_timeout) : ++ mutex_lock(&fifo->read_lock); ++ ret = wait_event_interruptible_timeout(fifo->read_queue, ++ ioread32(fifo->base_addr + XLLF_RDFO_OFFSET), ++ (read_timeout >= 0) ? msecs_to_jiffies(read_timeout) : + MAX_SCHEDULE_TIMEOUT); +- spin_unlock_irq(&fifo->read_queue_lock); + +- if (ret == 0) { +- /* timeout occurred */ +- dev_dbg(fifo->dt_device, "read timeout"); +- return -EAGAIN; +- } else if (ret == -ERESTARTSYS) { +- /* signal received */ +- return -ERESTARTSYS; +- } else if (ret < 0) { +- dev_err(fifo->dt_device, "wait_event_interruptible_timeout() error in read (ret=%i)\n", +- ret); +- return ret; ++ if (ret <= 0) { ++ if (ret == 0) { ++ ret = -EAGAIN; ++ } else if (ret != -ERESTARTSYS) { ++ dev_err(fifo->dt_device, "wait_event_interruptible_timeout() error in read (ret=%i)\n", ++ ret); ++ } ++ ++ goto end_unlock; + } + } + +@@ -388,14 +403,16 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, + if (!bytes_available) { + dev_err(fifo->dt_device, "received a packet of length 0 - fifo core will be reset\n"); + reset_ip_core(fifo); +- return -EIO; ++ ret = -EIO; ++ goto end_unlock; + } + + if (bytes_available > len) { + dev_err(fifo->dt_device, "user read buffer too small (available bytes=%zu user buffer bytes=%zu) - fifo core will be reset\n", + bytes_available, len); + reset_ip_core(fifo); +- return -EINVAL; ++ ret = -EINVAL; ++ goto end_unlock; + } + + if (bytes_available % sizeof(u32)) { +@@ -404,7 +421,8 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, + */ + dev_err(fifo->dt_device, "received a packet that isn't word-aligned - fifo core will be reset\n"); + reset_ip_core(fifo); +- return -EIO; ++ ret = -EIO; ++ goto end_unlock; + } + + words_available = bytes_available / sizeof(u32); +@@ -424,16 +442,37 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, + if (copy_to_user(buf + copied * sizeof(u32), tmp_buf, + copy * sizeof(u32))) { + reset_ip_core(fifo); +- return -EFAULT; ++ ret = -EFAULT; ++ goto end_unlock; + } + + copied += copy; + words_available -= copy; + } + +- return bytes_available; ++ ret = bytes_available; ++ ++end_unlock: ++ mutex_unlock(&fifo->read_lock); ++ ++ return ret; + } + ++/** ++ * axis_fifo_write() - Write buffer to AXIS-FIFO character device. ++ * @f Open file. ++ * @buf User space buffer to write to the device. ++ * @len User space buffer length. ++ * @off Buffer offset. ++ * ++ * As defined by the device's documentation, we need to write to the device's ++ * data buffer then to the device's packet length register atomically. Also, ++ * we need to lock before checking if the device has available space to avoid ++ * any concurrency issue. ++ * ++ * Returns the number of bytes written to the device or negative error code ++ * on failure. ++ */ + static ssize_t axis_fifo_write(struct file *f, const char __user *buf, + size_t len, loff_t *off) + { +@@ -466,12 +505,17 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf, + } + + if (fifo->write_flags & O_NONBLOCK) { +- /* opened in non-blocking mode +- * return if there is not enough room available in the fifo ++ /* ++ * Device opened in non-blocking mode. Try to lock it and then ++ * check if there is any room to write the given buffer. + */ ++ if (!mutex_trylock(&fifo->write_lock)) ++ return -EAGAIN; ++ + if (words_to_write > ioread32(fifo->base_addr + + XLLF_TDFV_OFFSET)) { +- return -EAGAIN; ++ ret = -EAGAIN; ++ goto end_unlock; + } + } else { + /* opened in blocking mode */ +@@ -479,30 +523,22 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf, + /* wait for an interrupt (or timeout) if there isn't + * currently enough room in the fifo + */ +- spin_lock_irq(&fifo->write_queue_lock); +- ret = wait_event_interruptible_lock_irq_timeout +- (fifo->write_queue, +- ioread32(fifo->base_addr + XLLF_TDFV_OFFSET) ++ mutex_lock(&fifo->write_lock); ++ ret = wait_event_interruptible_timeout(fifo->write_queue, ++ ioread32(fifo->base_addr + XLLF_TDFV_OFFSET) + >= words_to_write, +- fifo->write_queue_lock, +- (write_timeout >= 0) ? +- msecs_to_jiffies(write_timeout) : ++ (write_timeout >= 0) ? msecs_to_jiffies(write_timeout) : + MAX_SCHEDULE_TIMEOUT); +- spin_unlock_irq(&fifo->write_queue_lock); + +- if (ret == 0) { +- /* timeout occurred */ +- dev_dbg(fifo->dt_device, "write timeout\n"); +- return -EAGAIN; +- } else if (ret == -ERESTARTSYS) { +- /* signal received */ +- return -ERESTARTSYS; +- } else if (ret < 0) { +- /* unknown error */ +- dev_err(fifo->dt_device, +- "wait_event_interruptible_timeout() error in write (ret=%i)\n", +- ret); +- return ret; ++ if (ret <= 0) { ++ if (ret == 0) { ++ ret = -EAGAIN; ++ } else if (ret != -ERESTARTSYS) { ++ dev_err(fifo->dt_device, "wait_event_interruptible_timeout() error in write (ret=%i)\n", ++ ret); ++ } ++ ++ goto end_unlock; + } + } + +@@ -516,7 +552,8 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf, + if (copy_from_user(tmp_buf, buf + copied * sizeof(u32), + copy * sizeof(u32))) { + reset_ip_core(fifo); +- return -EFAULT; ++ ret = -EFAULT; ++ goto end_unlock; + } + + for (i = 0; i < copy; i++) +@@ -527,10 +564,15 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf, + words_to_write -= copy; + } + ++ ret = copied * sizeof(u32); ++ + /* write packet size to fifo */ +- iowrite32(copied * sizeof(u32), fifo->base_addr + XLLF_TLR_OFFSET); ++ iowrite32(ret, fifo->base_addr + XLLF_TLR_OFFSET); ++ ++end_unlock: ++ mutex_unlock(&fifo->write_lock); + +- return (ssize_t)copied * sizeof(u32); ++ return ret; + } + + static irqreturn_t axis_fifo_irq(int irq, void *dw) +@@ -756,8 +798,8 @@ static int axis_fifo_probe(struct platform_device *pdev) + init_waitqueue_head(&fifo->read_queue); + init_waitqueue_head(&fifo->write_queue); + +- spin_lock_init(&fifo->read_queue_lock); +- spin_lock_init(&fifo->write_queue_lock); ++ mutex_init(&fifo->read_lock); ++ mutex_init(&fifo->write_lock); + + /* ---------------------------- + * init device memory space +-- +2.39.5 +