Recreate RHEL 5.14.0-687.10.1 from CS9/upstream backports

Drop the 687.5.3/687.5.4 security-ahead patches superseded by the RHEL
687.6.1..687.10.1 backports (1100-1104), and add those backports (1100-1196)
sourced from centos-stream-9 and upstream stable. Keep the AlmaLinux-ahead
smb cifs.spnego fix (retained as 1197). Bump to 5.14.0-687.10.1.
This commit is contained in:
Andrew Lukoshko 2026-06-06 22:24:45 +00:00
parent 53ec6c7fe3
commit 5c58271075
104 changed files with 8788 additions and 1318 deletions

View File

@ -0,0 +1,167 @@
From 07bcb984353e8e436251bdc10804e952fec12943 Mon Sep 17 00:00:00 2001
From: Kamal Heib <kheib@redhat.com>
Date: Mon, 13 Apr 2026 13:56:58 -0400
Subject: [PATCH] rtnetlink: Allocate vfinfo size for VF GUIDs when supported
JIRA: https://issues.redhat.com/browse/RHEL-167866
CVE: CVE-2025-22075
commit 23f00807619d15063d676218f36c5dfeda1eb420
Author: Mark Zhang <markzhang@nvidia.com>
Date: Tue Mar 25 11:02:26 2025 +0200
rtnetlink: Allocate vfinfo size for VF GUIDs when supported
Commit 30aad41721e0 ("net/core: Add support for getting VF GUIDs")
added support for getting VF port and node GUIDs in netlink ifinfo
messages, but their size was not taken into consideration in the
function that allocates the netlink message, causing the following
warning when a netlink message is filled with many VF port and node
GUIDs:
# echo 64 > /sys/bus/pci/devices/0000\:08\:00.0/sriov_numvfs
# ip link show dev ib0
RTNETLINK answers: Message too long
Cannot send link get request: Message too long
Kernel warning:
------------[ cut here ]------------
WARNING: CPU: 2 PID: 1930 at net/core/rtnetlink.c:4151 rtnl_getlink+0x586/0x5a0
Modules linked in: xt_conntrack xt_MASQUERADE nfnetlink xt_addrtype iptable_nat nf_nat br_netfilter overlay mlx5_ib macsec mlx5_core tls rpcrdma rdma_ucm ib_uverbs ib_iser libiscsi scsi_transport_iscsi ib_umad rdma_cm iw_cm ib_ipoib fuse ib_cm ib_core
CPU: 2 UID: 0 PID: 1930 Comm: ip Not tainted 6.14.0-rc2+ #1
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
RIP: 0010:rtnl_getlink+0x586/0x5a0
Code: cb 82 e8 3d af 0a 00 4d 85 ff 0f 84 08 ff ff ff 4c 89 ff 41 be ea ff ff ff e8 66 63 5b ff 49 c7 07 80 4f cb 82 e9 36 fc ff ff <0f> 0b e9 16 fe ff ff e8 de a0 56 00 66 66 2e 0f 1f 84 00 00 00 00
RSP: 0018:ffff888113557348 EFLAGS: 00010246
RAX: 00000000ffffffa6 RBX: ffff88817e87aa34 RCX: dffffc0000000000
RDX: 0000000000000003 RSI: 0000000000000000 RDI: ffff88817e87afb8
RBP: 0000000000000009 R08: ffffffff821f44aa R09: 0000000000000000
R10: ffff8881260f79a8 R11: ffff88817e87af00 R12: ffff88817e87aa00
R13: ffffffff8563d300 R14: 00000000ffffffa6 R15: 00000000ffffffff
FS: 00007f63a5dbf280(0000) GS:ffff88881ee00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f63a5ba4493 CR3: 00000001700fe002 CR4: 0000000000772eb0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
PKRU: 55555554
Call Trace:
<TASK>
? __warn+0xa5/0x230
? rtnl_getlink+0x586/0x5a0
? report_bug+0x22d/0x240
? handle_bug+0x53/0xa0
? exc_invalid_op+0x14/0x50
? asm_exc_invalid_op+0x16/0x20
? skb_trim+0x6a/0x80
? rtnl_getlink+0x586/0x5a0
? __pfx_rtnl_getlink+0x10/0x10
? rtnetlink_rcv_msg+0x1e5/0x860
? __pfx___mutex_lock+0x10/0x10
? rcu_is_watching+0x34/0x60
? __pfx_lock_acquire+0x10/0x10
? stack_trace_save+0x90/0xd0
? filter_irq_stacks+0x1d/0x70
? kasan_save_stack+0x30/0x40
? kasan_save_stack+0x20/0x40
? kasan_save_track+0x10/0x30
rtnetlink_rcv_msg+0x21c/0x860
? entry_SYSCALL_64_after_hwframe+0x76/0x7e
? __pfx_rtnetlink_rcv_msg+0x10/0x10
? arch_stack_walk+0x9e/0xf0
? rcu_is_watching+0x34/0x60
? lock_acquire+0xd5/0x410
? rcu_is_watching+0x34/0x60
netlink_rcv_skb+0xe0/0x210
? __pfx_rtnetlink_rcv_msg+0x10/0x10
? __pfx_netlink_rcv_skb+0x10/0x10
? rcu_is_watching+0x34/0x60
? __pfx___netlink_lookup+0x10/0x10
? lock_release+0x62/0x200
? netlink_deliver_tap+0xfd/0x290
? rcu_is_watching+0x34/0x60
? lock_release+0x62/0x200
? netlink_deliver_tap+0x95/0x290
netlink_unicast+0x31f/0x480
? __pfx_netlink_unicast+0x10/0x10
? rcu_is_watching+0x34/0x60
? lock_acquire+0xd5/0x410
netlink_sendmsg+0x369/0x660
? lock_release+0x62/0x200
? __pfx_netlink_sendmsg+0x10/0x10
? import_ubuf+0xb9/0xf0
? __import_iovec+0x254/0x2b0
? lock_release+0x62/0x200
? __pfx_netlink_sendmsg+0x10/0x10
____sys_sendmsg+0x559/0x5a0
? __pfx_____sys_sendmsg+0x10/0x10
? __pfx_copy_msghdr_from_user+0x10/0x10
? rcu_is_watching+0x34/0x60
? do_read_fault+0x213/0x4a0
? rcu_is_watching+0x34/0x60
___sys_sendmsg+0xe4/0x150
? __pfx____sys_sendmsg+0x10/0x10
? do_fault+0x2cc/0x6f0
? handle_pte_fault+0x2e3/0x3d0
? __pfx_handle_pte_fault+0x10/0x10
? preempt_count_sub+0x14/0xc0
? __down_read_trylock+0x150/0x270
? __handle_mm_fault+0x404/0x8e0
? __pfx___handle_mm_fault+0x10/0x10
? lock_release+0x62/0x200
? __rcu_read_unlock+0x65/0x90
? rcu_is_watching+0x34/0x60
__sys_sendmsg+0xd5/0x150
? __pfx___sys_sendmsg+0x10/0x10
? __up_read+0x192/0x480
? lock_release+0x62/0x200
? __rcu_read_unlock+0x65/0x90
? rcu_is_watching+0x34/0x60
do_syscall_64+0x6d/0x140
entry_SYSCALL_64_after_hwframe+0x76/0x7e
RIP: 0033:0x7f63a5b13367
Code: 0e 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b9 0f 1f 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 89 54 24 1c 48 89 74 24 10
RSP: 002b:00007fff8c726bc8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 0000000067b687c2 RCX: 00007f63a5b13367
RDX: 0000000000000000 RSI: 00007fff8c726c30 RDI: 0000000000000004
RBP: 00007fff8c726cb8 R08: 0000000000000000 R09: 0000000000000034
R10: 00007fff8c726c7c R11: 0000000000000246 R12: 0000000000000001
R13: 0000000000000000 R14: 00007fff8c726cd0 R15: 00007fff8c726cd0
</TASK>
irq event stamp: 0
hardirqs last enabled at (0): [<0000000000000000>] 0x0
hardirqs last disabled at (0): [<ffffffff813f9e58>] copy_process+0xd08/0x2830
softirqs last enabled at (0): [<ffffffff813f9e58>] copy_process+0xd08/0x2830
softirqs last disabled at (0): [<0000000000000000>] 0x0
---[ end trace 0000000000000000 ]---
Thus, when calculating ifinfo message size, take VF GUIDs sizes into
account when supported.
Fixes: 30aad41721e0 ("net/core: Add support for getting VF GUIDs")
Signed-off-by: Mark Zhang <markzhang@nvidia.com>
Reviewed-by: Maher Sanalla <msanalla@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Link: https://patch.msgid.link/20250325090226.749730-1-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Kamal Heib <kheib@redhat.com>
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index e58604891437..cf61b887c5fc 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1005,6 +1005,9 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev,
/* IFLA_VF_STATS_TX_DROPPED */
nla_total_size_64bit(sizeof(__u64)));
}
+ if (dev->netdev_ops->ndo_get_vf_guid)
+ size += num_vfs * 2 *
+ nla_total_size(sizeof(struct ifla_vf_guid));
return size;
} else
return 0;
--
2.50.1 (Apple Git-155)

View File

@ -1,75 +0,0 @@
From: Andrew Lukoshko <alukoshko@almalinux.org>
Subject: [PATCH AlmaLinux 9] xfrm: esp: avoid in-place decrypt on shared skb frags
Backport of upstream commit f4c50a4034e6 ("xfrm: esp: avoid in-place
decrypt on shared skb frags") for AlmaLinux 9 (5.14 kernel).
Verified to apply with `patch -p1 -F0` (no offset, no fuzz, no rejects)
against kernel-5.14.0-611.54.1.el9_7.
ESP-in-UDP packets built from caller-owned pages (e.g. pipe pages
attached via udp_sendpage(2) -> ip_append_page() -> skb_append_pagefrags())
look like ordinary uncloned nonlinear skbs. ESP input then takes the
no-COW fast path and decrypts in place over data that is not owned
privately by the skb.
Tree adaptation:
* Upstream patches __ip_append_data() / __ip6_append_data(), the
MSG_SPLICE_PAGES branch added by 7da0dde68486 / 6d8192bd69bb.
That feature has not been wired into UDP send paths on this tree
(no caller of skb_splice_from_iter in net/ipv{4,6}/).
* The age-equivalent producer is ip_append_page() (udp_sendpage).
Mark frags there with SKBFL_SHARED_FRAG so skb_has_shared_frag()
fires for these skbs.
* UDPv6 has no .sendpage op in this tree, so the esp6 hunk is
defense-in-depth in case a later backport adds one.
* The esp4/esp6 receiver-side hunks are taken verbatim from
upstream.
Fixes: cac2661c53f3 ("esp4: Avoid skb_cow_data whenever possible")
Fixes: 03e2a30f6a27 ("esp6: Avoid skb_cow_data whenever possible")
(cherry picked from commit f4c50a4034e62ab75f1d5cdd191dd5f9c77fdff4)
Signed-off-by: Andrew Lukoshko <alukoshko@almalinux.org>
---
net/ipv4/esp4.c | 3 ++-
net/ipv4/ip_output.c | 2 ++
net/ipv6/esp6.c | 3 ++-
3 files changed, 6 insertions(+), 2 deletions(-)
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -920,7 +920,8 @@
nfrags = 1;
goto skip_cow;
- } else if (!skb_has_frag_list(skb)) {
+ } else if (!skb_has_frag_list(skb) &&
+ !skb_has_shared_frag(skb)) {
nfrags = skb_shinfo(skb)->nr_frags;
nfrags++;
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1467,6 +1467,8 @@
err = -EMSGSIZE;
goto error;
}
+ if (!(flags & MSG_NO_SHARED_FRAGS))
+ skb_shinfo(skb)->flags |= SKBFL_SHARED_FRAG;
if (skb->ip_summed == CHECKSUM_NONE) {
__wsum csum;
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -960,7 +960,8 @@
nfrags = 1;
goto skip_cow;
- } else if (!skb_has_frag_list(skb)) {
+ } else if (!skb_has_frag_list(skb) &&
+ !skb_has_shared_frag(skb)) {
nfrags = skb_shinfo(skb)->nr_frags;
nfrags++;
--
2.43.0

View File

@ -0,0 +1,97 @@
From be8f678b4eaf729472075519c05dc8a70ae4b072 Mon Sep 17 00:00:00 2001
From: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
Date: Fri, 10 Apr 2026 08:59:49 +0000
Subject: [PATCH] net/sched: Make cake_enqueue return NET_XMIT_CN when past
buffer_limit
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
JIRA: https://redhat.atlassian.net/browse/RHEL-166730
CVE: CVE-2025-39766
commit 15de71d06a400f7fdc15bf377a2552b0ec437cf5
Author: William Liu <will@willsroot.io>
Date: Tue Aug 19 03:36:28 2025 +0000
net/sched: Make cake_enqueue return NET_XMIT_CN when past buffer_limit
The following setup can trigger a WARNING in htb_activate due to
the condition: !cl->leaf.q->q.qlen
tc qdisc del dev lo root
tc qdisc add dev lo root handle 1: htb default 1
tc class add dev lo parent 1: classid 1:1 \
htb rate 64bit
tc qdisc add dev lo parent 1:1 handle f: \
cake memlimit 1b
ping -I lo -f -c1 -s64 -W0.001 127.0.0.1
This is because the low memlimit leads to a low buffer_limit, which
causes packet dropping. However, cake_enqueue still returns
NET_XMIT_SUCCESS, causing htb_enqueue to call htb_activate with an
empty child qdisc. We should return NET_XMIT_CN when packets are
dropped from the same tin and flow.
I do not believe return value of NET_XMIT_CN is necessary for packet
drops in the case of ack filtering, as that is meant to optimize
performance, not to signal congestion.
Fixes: 046f6fd5daef ("sched: Add Common Applications Kept Enhanced (cake) qdisc")
Signed-off-by: William Liu <will@willsroot.io>
Reviewed-by: Savino Dicanosa <savy@syst3mfailure.io>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/20250819033601.579821-1-will@willsroot.io
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index 48dd8c88903f..aa9f31e4415a 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -1747,7 +1747,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
ktime_t now = ktime_get();
struct cake_tin_data *b;
struct cake_flow *flow;
- u32 idx;
+ u32 idx, tin;
/* choose flow to insert into */
idx = cake_classify(sch, &b, skb, q->flow_mode, &ret);
@@ -1757,6 +1757,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
__qdisc_drop(skb, to_free);
return ret;
}
+ tin = (u32)(b - q->tins);
idx--;
flow = &b->flows[idx];
@@ -1924,13 +1925,22 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
q->buffer_max_used = q->buffer_used;
if (q->buffer_used > q->buffer_limit) {
+ bool same_flow = false;
u32 dropped = 0;
+ u32 drop_id;
while (q->buffer_used > q->buffer_limit) {
dropped++;
- cake_drop(sch, to_free);
+ drop_id = cake_drop(sch, to_free);
+
+ if ((drop_id >> 16) == tin &&
+ (drop_id & 0xFFFF) == idx)
+ same_flow = true;
}
b->drop_overlimit += dropped;
+
+ if (same_flow)
+ return NET_XMIT_CN;
}
return NET_XMIT_SUCCESS;
}
--
2.50.1 (Apple Git-155)

View File

@ -1,68 +0,0 @@
From: Andrew Lukoshko <alukoshko@almalinux.org>
Subject: [PATCH AlmaLinux 9] rxrpc: linearize incoming DATA packet when it has paged frags
AlmaLinux-specific backport of the intent of the upstream rxrpc fix
posted at https://lore.kernel.org/all/afKV2zGR6rrelPC7@v4bel/
(sibling to upstream commit f4c50a4034e6 in the ESP/xfrm subsystem).
The upstream patch can not be cherry-picked against this 5.14 tree:
its target lines were introduced by upstream commit d0d5c0cd1e71
("rxrpc: Use skb_unshare() rather than skb_cow_data()") which is not
present here. The age-equivalent code path on AlmaLinux 9 is the
centralized skb_unshare() in net/rxrpc/io_thread.c that is run for
every DATA packet with a non-zero securityIndex before in-place
decryption.
skb_unshare() only handles cloned skbs. An skb that is non-cloned but
carries paged fragments (skb->data_len != 0) — e.g. pages attached via
udp_sendpage() / splice() / MSG_SPLICE_PAGES on a UDP socket carrying
rxrpc traffic — slips through and is decrypted in place over data the
skb does not own privately. With kernel-modules-partner installed
(rxrpc.ko enabled), this is exploitable.
Replace the unconditional skb_unshare() with skb_copy() whenever the
skb is cloned OR carries paged fragments. skb_copy() always returns a
freshly allocated linear skb, so subsequent in-place decryption only
touches kernel-owned memory. The original skb is consumed explicitly
(skb_unshare did this internally via consume_skb()).
Verified to apply with `patch -p1 -F0` (no offset, no fuzz, no
rejects) against kernel-5.14.0-611.54.1.el9_7.
Fixes: cac2661c53f3 ("rxrpc: Use skb_cow_data() in rxrpc_recvmsg_data()")
Signed-off-by: Andrew Lukoshko <alukoshko@almalinux.org>
---
net/rxrpc/io_thread.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
--- a/net/rxrpc/io_thread.c
+++ b/net/rxrpc/io_thread.c
@@ -225,16 +225,18 @@
* decryption.
*/
if (sp->hdr.securityIndex != 0) {
- skb = skb_unshare(skb, GFP_ATOMIC);
- if (!skb) {
- rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare_nomem);
- *_skb = NULL;
- return just_discard;
- }
+ if (skb_cloned(skb) || skb->data_len) {
+ struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
+
+ if (!nskb) {
+ rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare_nomem);
+ return just_discard;
+ }
- if (skb != *_skb) {
rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare);
- *_skb = skb;
+ consume_skb(*_skb);
+ *_skb = nskb;
+ skb = nskb;
rxrpc_new_skb(skb, rxrpc_skb_new_unshared);
sp = rxrpc_skb(skb);
}
--
2.43.0

View File

@ -0,0 +1,162 @@
From d7f88307eaa11490b3ad24647bdf96922504fd5e Mon Sep 17 00:00:00 2001
From: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
Date: Fri, 10 Apr 2026 08:59:50 +0000
Subject: [PATCH] net/sched: sch_cake: Fix incorrect qlen reduction in
cake_drop
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
JIRA: https://redhat.atlassian.net/browse/RHEL-166730
CVE: CVE-2025-39766
commit 9fefc78f7f02d71810776fdeb119a05a946a27cc
Author: Xiang Mei <xmei5@asu.edu>
Date: Thu Nov 27 17:14:14 2025 -0700
net/sched: sch_cake: Fix incorrect qlen reduction in cake_drop
In cake_drop(), qdisc_tree_reduce_backlog() is used to update the qlen
and backlog of the qdisc hierarchy. Its caller, cake_enqueue(), assumes
that the parent qdisc will enqueue the current packet. However, this
assumption breaks when cake_enqueue() returns NET_XMIT_CN: the parent
qdisc stops enqueuing current packet, leaving the tree qlen/backlog
accounting inconsistent. This mismatch can lead to a NULL dereference
(e.g., when the parent Qdisc is qfq_qdisc).
This patch computes the qlen/backlog delta in a more robust way by
observing the difference before and after the series of cake_drop()
calls, and then compensates the qdisc tree accounting if cake_enqueue()
returns NET_XMIT_CN.
To ensure correct compensation when ACK thinning is enabled, a new
variable is introduced to keep qlen unchanged.
Fixes: 15de71d06a40 ("net/sched: Make cake_enqueue return NET_XMIT_CN when past buffer_limit")
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Reviewed-by: Toke Høiland-Jørgensen <toke@toke.dk>
Link: https://patch.msgid.link/20251128001415.377823-1-xmei5@asu.edu
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index aa9f31e4415a..ef51a9e0f621 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -1594,7 +1594,6 @@ static unsigned int cake_drop(struct Qdisc *sch, struct sk_buff **to_free)
qdisc_drop_reason(skb, sch, to_free, SKB_DROP_REASON_QDISC_OVERLIMIT);
sch->q.qlen--;
- qdisc_tree_reduce_backlog(sch, 1, len);
cake_heapify(q, 0);
@@ -1740,14 +1739,14 @@ static void cake_reconfigure(struct Qdisc *sch);
static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
+ u32 idx, tin, prev_qlen, prev_backlog, drop_id;
struct cake_sched_data *q = qdisc_priv(sch);
- int len = qdisc_pkt_len(skb);
- int ret;
+ int len = qdisc_pkt_len(skb), ret;
struct sk_buff *ack = NULL;
ktime_t now = ktime_get();
struct cake_tin_data *b;
struct cake_flow *flow;
- u32 idx, tin;
+ bool same_flow = false;
/* choose flow to insert into */
idx = cake_classify(sch, &b, skb, q->flow_mode, &ret);
@@ -1820,6 +1819,8 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
consume_skb(skb);
} else {
/* not splitting */
+ int ack_pkt_len = 0;
+
cobalt_set_enqueue_time(skb, now);
get_cobalt_cb(skb)->adjusted_len = cake_overhead(q, skb);
flow_queue_add(flow, skb);
@@ -1830,13 +1831,13 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (ack) {
b->ack_drops++;
sch->qstats.drops++;
- b->bytes += qdisc_pkt_len(ack);
- len -= qdisc_pkt_len(ack);
+ ack_pkt_len = qdisc_pkt_len(ack);
+ b->bytes += ack_pkt_len;
q->buffer_used += skb->truesize - ack->truesize;
if (q->rate_flags & CAKE_FLAG_INGRESS)
cake_advance_shaper(q, b, ack, now, true);
- qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(ack));
+ qdisc_tree_reduce_backlog(sch, 1, ack_pkt_len);
consume_skb(ack);
} else {
sch->q.qlen++;
@@ -1845,11 +1846,11 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
/* stats */
b->packets++;
- b->bytes += len;
- b->backlogs[idx] += len;
- b->tin_backlog += len;
- sch->qstats.backlog += len;
- q->avg_window_bytes += len;
+ b->bytes += len - ack_pkt_len;
+ b->backlogs[idx] += len - ack_pkt_len;
+ b->tin_backlog += len - ack_pkt_len;
+ sch->qstats.backlog += len - ack_pkt_len;
+ q->avg_window_bytes += len - ack_pkt_len;
}
if (q->overflow_timeout)
@@ -1924,24 +1925,29 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (q->buffer_used > q->buffer_max_used)
q->buffer_max_used = q->buffer_used;
- if (q->buffer_used > q->buffer_limit) {
- bool same_flow = false;
- u32 dropped = 0;
- u32 drop_id;
+ if (q->buffer_used <= q->buffer_limit)
+ return NET_XMIT_SUCCESS;
- while (q->buffer_used > q->buffer_limit) {
- dropped++;
- drop_id = cake_drop(sch, to_free);
+ prev_qlen = sch->q.qlen;
+ prev_backlog = sch->qstats.backlog;
- if ((drop_id >> 16) == tin &&
- (drop_id & 0xFFFF) == idx)
- same_flow = true;
- }
- b->drop_overlimit += dropped;
+ while (q->buffer_used > q->buffer_limit) {
+ drop_id = cake_drop(sch, to_free);
+ if ((drop_id >> 16) == tin &&
+ (drop_id & 0xFFFF) == idx)
+ same_flow = true;
+ }
+
+ prev_qlen -= sch->q.qlen;
+ prev_backlog -= sch->qstats.backlog;
+ b->drop_overlimit += prev_qlen;
- if (same_flow)
- return NET_XMIT_CN;
+ if (same_flow) {
+ qdisc_tree_reduce_backlog(sch, prev_qlen - 1,
+ prev_backlog - len);
+ return NET_XMIT_CN;
}
+ qdisc_tree_reduce_backlog(sch, prev_qlen, prev_backlog);
return NET_XMIT_SUCCESS;
}
--
2.50.1 (Apple Git-155)

View File

@ -1,145 +0,0 @@
From: Andrew Lukoshko <alukoshko@almalinux.org>
Subject: [PATCH AlmaLinux 9] net: skbuff: propagate shared-frag marker through frag-transfer helpers
Backport of upstream v5 patch posted at
https://lore.kernel.org/all/ageeJfJHwgzmKXbh@v4bel/
(sibling to upstream commit f4c50a4034e6 "xfrm: esp: avoid in-place
decrypt on shared skb frags").
Three frag-transfer helpers in net/core/skbuff.c
(__pskb_copy_fclone(), skb_try_coalesce(), skb_shift()), the GRO
accumulator path in net/core/gro.c (skb_gro_receive()) and the UDP
GRO list helper in net/ipv4/udp_offload.c (skb_gro_receive_list(),
kept as a static helper on AlmaLinux 9) fail to propagate the
SKBFL_SHARED_FRAG bit in skb_shinfo()->flags when moving frag
descriptors from source to destination. In addition, skb_segment()
folds only head_skb's flag into nskb on the per-iteration flag
merge, and the inner switch that rebinds frag_skb to list_skb on
head_skb-frags exhaustion does not fold the new frag_skb's flag
into nskb. As a result, the destination skb keeps a reference to
the same externally-owned or page-cache-backed pages while reporting
skb_has_shared_frag() as false.
The mismatch is harmful in any in-place writer that uses
skb_has_shared_frag() to decide whether shared pages must be detoured
through skb_cow_data(). ESP input is one such writer (esp4.c,
esp6.c). Combined with an nft 'dup to <local>' rule, an
nf_dup_ipv4() / xt_TEE caller, or ESP-over-UDP with UDP GRO, this
lets an unprivileged user write into the page cache of a root-owned
read-only file via authencesn-ESN stray writes (CVE-2026-46300,
"Fragnesia").
Set SKBFL_SHARED_FRAG on the destination whenever frag descriptors
were actually moved from the source. skb_copy() and skb_copy_expand()
share skb_copy_header() too but linearize all paged data into freshly
allocated head storage and emerge with nr_frags == 0, so
skb_has_shared_frag() returns false on its own; they need no change.
tcp_clone_payload() does not exist in 5.14; no equivalent hunk
applies.
The same omission exists in skb_gro_receive() and
skb_gro_receive_list(). The former moves the incoming skb's frag
descriptors into the accumulator's last sub-skb via two paths plus a
"merge:" fallback that chains the whole skb onto frag_list; the
latter chains the incoming skb whole onto p's frag_list. Downstream
skb_segment() reads only skb_shinfo(p)->flags, and skb_segment_list()
reuses each sub-skb's shinfo as the nskb -- both p and lp must carry
the marker.
Tree adaptation:
* Upstream v5 places skb_gro_receive_list() in net/core/gro.c.
AlmaLinux 9 still keeps it as a static helper in
net/ipv4/udp_offload.c (it has not been promoted to a global
GRO helper in this tree). Apply the propagation hunk there
instead.
* Upstream tcp_clone_payload() was added in v6.5 (commit
808599b88c93); 5.14 has no such helper, so the corresponding v5
hunk is omitted.
Fixes: cef401de7be8 ("net: fix possible wrong checksum generation")
Fixes: f4c50a4034e6 ("xfrm: esp: avoid in-place decrypt on shared skb frags")
Reported-by: Sultan Alsawaf <sultan@kerneltoast.com>
Reported-by: William Bowling <vakzz@zellic.io>
Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Signed-off-by: Andrew Lukoshko <alukoshko@almalinux.org>
---
net/core/gro.c | 2 ++
net/core/skbuff.c | 12 ++++++++++++
net/ipv4/udp_offload.c | 2 ++
3 files changed, 16 insertions(+)
--- a/net/core/skbuff.c 2026-05-28 12:54:14.127155793 +0200
+++ b/net/core/skbuff.c 2026-05-28 12:57:03.811526691 +0200
@@ -2027,6 +2027,7 @@
skb_frag_ref(skb, i);
}
skb_shinfo(n)->nr_frags = i;
+ skb_shinfo(n)->flags |= skb_shinfo(skb)->flags & SKBFL_SHARED_FRAG;
}
if (skb_has_frag_list(skb)) {
@@ -4029,6 +4030,8 @@
tgt->ip_summed = CHECKSUM_PARTIAL;
skb->ip_summed = CHECKSUM_PARTIAL;
+ skb_shinfo(tgt)->flags |= skb_shinfo(skb)->flags & SKBFL_SHARED_FRAG;
+
/* Yak, is it really working this way? Some helper please? */
skb->len -= shiftlen;
skb->data_len -= shiftlen;
@@ -4604,7 +4607,8 @@
skb_copy_from_linear_data_offset(head_skb, offset,
skb_put(nskb, hsize), hsize);
- skb_shinfo(nskb)->flags |= skb_shinfo(head_skb)->flags &
+ skb_shinfo(nskb)->flags |= (skb_shinfo(head_skb)->flags |
+ skb_shinfo(frag_skb)->flags) &
SKBFL_SHARED_FRAG;
if (skb_zerocopy_clone(nskb, frag_skb, GFP_ATOMIC))
@@ -4621,6 +4625,10 @@
nfrags = skb_shinfo(list_skb)->nr_frags;
frag = skb_shinfo(list_skb)->frags;
frag_skb = list_skb;
+
+ skb_shinfo(nskb)->flags |= skb_shinfo(frag_skb)->flags &
+ SKBFL_SHARED_FRAG;
+
if (!skb_headlen(list_skb)) {
BUG_ON(!nfrags);
} else {
@@ -5741,6 +5749,8 @@
from_shinfo->frags,
from_shinfo->nr_frags * sizeof(skb_frag_t));
to_shinfo->nr_frags += from_shinfo->nr_frags;
+ if (from_shinfo->nr_frags)
+ to_shinfo->flags |= from_shinfo->flags & SKBFL_SHARED_FRAG;
if (!skb_cloned(from))
from_shinfo->nr_frags = 0;
--- a/net/core/gro.c 2026-05-28 12:54:14.126244251 +0200
+++ b/net/core/gro.c 2026-05-28 12:57:12.210673266 +0200
@@ -222,10 +222,12 @@
p->data_len += len;
p->truesize += delta_truesize;
p->len += len;
+ skb_shinfo(p)->flags |= skbinfo->flags & SKBFL_SHARED_FRAG;
if (lp != p) {
lp->data_len += len;
lp->truesize += delta_truesize;
lp->len += len;
+ skb_shinfo(lp)->flags |= skbinfo->flags & SKBFL_SHARED_FRAG;
}
NAPI_GRO_CB(skb)->same_flow = 1;
return 0;
--- a/net/ipv4/udp_offload.c 2026-05-28 12:54:14.556608350 +0200
+++ b/net/ipv4/udp_offload.c 2026-05-28 12:57:19.503137455 +0200
@@ -487,6 +487,8 @@
p->truesize += skb->truesize;
p->len += skb->len;
+ skb_shinfo(p)->flags |= skb_shinfo(skb)->flags & SKBFL_SHARED_FRAG;
+
NAPI_GRO_CB(skb)->same_flow = 1;
return 0;

View File

@ -0,0 +1,135 @@
From d770e24a36c555404676344d2b3a55f0aeecbde0 Mon Sep 17 00:00:00 2001
From: Petr Oros <poros@redhat.com>
Date: Thu, 5 Mar 2026 14:22:14 +0100
Subject: [PATCH] ice: fix page leak for zero-size Rx descriptors
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
JIRA: https://issues.redhat.com/browse/RHEL-152865
Upstream Status: RHEL-only
Intel E800 hardware can generate zero-size descriptors within
multi-buffer (jumbo) frames. These descriptors carry no packet data
but still occupy a slot in the Rx ring and have a page assigned to
them.
ice_add_xdp_frag() correctly skips zero-size descriptors (returns 0
when size == 0), so the page is never added to the xdp_buff/SKB.
However, ice_get_rx_buf() unconditionally decrements pagecnt_bias for
every descriptor, including zero-size ones. This creates a permanent
pagecnt_bias deficit for the affected page: the driver has "promised"
(via pagecnt_bias--) that someone will eventually call put_page() to
balance it, but since the page is not part of any SKB, nobody ever
does.
The deficit accumulates and manifests as follows:
1. Zero-size descriptor: pagecnt_bias-- in ice_get_rx_buf(), but
the page is not added to any SKB by ice_add_xdp_frag().
2. The page is recycled back to the ring via ice_reuse_rx_page()
with pagecnt_bias one lower than it should be.
3. On the next normal use of this page, pagecnt_bias-- again.
Now page_count - pagecnt_bias = 2 > 1, so ice_can_reuse_rx_page()
returns false.
4. The page goes to __page_frag_cache_drain(page, pagecnt_bias),
but pagecnt_bias is too low by 1, leaving page_count = 2.
5. The SKB eventually frees its reference (put_page), bringing
page_count to 1 - a phantom reference with no owner.
6. The page is permanently leaked. ice_alloc_rx_bufs() must
allocate a fresh page to replace it.
The previous attempt to fix the associated panic (commit ef68094cb09e
"ice: Fix kernel panic due to page refcount underflow") added
pagecnt_bias-- for zero-size descriptors in ice_get_rx_buf(). This
fixed the panic in the CONSUMED (XDP_DROP/error) path but introduced
the page leak in the PASS path described above.
The root cause is that ice_put_rx_mbuf() used a positional counter
('i') to decide which buffers need pagecnt_bias restoration. This
counter counted all ring positions including zero-size descriptors,
but xdp_frags only counted real fragments, causing misalignment:
zero-size descriptors "stole" pagecnt_bias++ slots from real
fragments that needed them.
Fix this by adding an 'has_data' flag to ice_rx_buf that records whether
ice_get_rx_buf() was called with actual data (size > 0). Replace
the broken positional counter in ice_put_rx_mbuf() with a direct
check on this flag:
- has_data && !CONSUMED: call ice_rx_buf_adjust_pg_offset() — the page
is in an SKB or XDP TX buffer that will eventually call put_page()
to balance the pagecnt_bias decrement.
- !has_data || CONSUMED: call pagecnt_bias++ — either the page carries
no data (zero-size descriptor, nobody will put_page()) or the
frame was dropped (no external reference holds any page).
The 'has_data' field fits within existing struct padding so ice_rx_buf
size does not change.
Signed-off-by: Petr Oros <poros@redhat.com>
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
index 499269f03c9d..2712ad743d38 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
@@ -1081,6 +1081,7 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size,
if (!size) {
rx_buf->pagecnt_bias--;
+ rx_buf->has_data = false;
return rx_buf;
}
/* we are reusing so sync this buffer for CPU use */
@@ -1090,6 +1091,7 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size,
/* We have pulled a buffer for use, so decrement pagecnt_bias */
rx_buf->pagecnt_bias--;
+ rx_buf->has_data = true;
return rx_buf;
}
@@ -1302,25 +1304,15 @@ static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
u32 idx = rx_ring->first_desc;
u32 cnt = rx_ring->count;
struct ice_rx_buf *buf;
- u32 xdp_frags = 0;
- int i = 0;
-
- if (unlikely(xdp_buff_has_frags(xdp)))
- xdp_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags;
while (idx != ntc) {
buf = &rx_ring->rx_buf[idx];
if (++idx == cnt)
idx = 0;
- /* An XDP program could release fragments from the end of the
- * buffer. For these, we need to keep the pagecnt_bias as-is.
- * To do this, only adjust pagecnt_bias for fragments up to
- * the total remaining after the XDP program has run.
- */
- if (verdict != ICE_XDP_CONSUMED)
+ if (verdict != ICE_XDP_CONSUMED && buf->has_data)
ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz);
- else if (i++ <= xdp_frags)
+ else
buf->pagecnt_bias++;
ice_put_rx_buf(rx_ring, buf);
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h
index 841a07bfba54..70f40a5ec33f 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.h
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.h
@@ -203,6 +203,7 @@ struct ice_rx_buf {
unsigned int page_offset;
unsigned int pgcnt;
unsigned int pagecnt_bias;
+ bool has_data;
};
struct ice_q_stats {
--
2.50.1 (Apple Git-155)

View File

@ -1,55 +0,0 @@
From: Andrew Lukoshko <alukoshko@almalinux.org>
Subject: [PATCH AlmaLinux 9] ptrace: require CAP_SYS_PTRACE when task has no mm
kABI-safe AlmaLinux backport of upstream commit 31e62c2ebbfd
("ptrace: slightly saner 'get_dumpable()' logic") posted at
https://github.com/torvalds/linux/commit/31e62c2ebbfdc3fe3dbdf5e02c92a9dc67087a3a
The upstream fix adds a 'user_dumpable:1' bit to task_struct and
caches the last dumpability in exit_mm() so __ptrace_may_access()
can require CAP_SYS_PTRACE when the target has no mm (e.g. kernel
threads or already-exited user tasks). That layout change to
task_struct breaks kABI on RHEL/AlmaLinux 9 (the symtype
signature of struct task_struct is referenced by stablelist exports
such as set_cpus_allowed_ptr() and wake_up_process()), so we cannot
import the field/exit_mm hunks as-is.
Take the minimal kABI-safe slice instead: when task->mm == NULL,
require CAP_SYS_PTRACE in init_user_ns unconditionally. This closes
the Qualys Security Advisory hole -- mm-less targets no longer pass
the dumpability check by default -- without touching task_struct or
exit.c. The only behavioural delta versus upstream is that a user
task that has already cleared its mm in exit_mm() (a dying/zombie
task) now also requires CAP_SYS_PTRACE to attach, instead of being
remembered as previously dumpable. Such targets are rarely ptraced
in practice.
Verified to apply with `patch -p1 -F0` (no offset, no fuzz, no rejects)
against kernel-5.14.0-611.54.1.el9_7.
Reported-by: Qualys Security Advisory <qsa@qualys.com>
Signed-off-by: Andrew Lukoshko <alukoshko@almalinux.org>
---
kernel/ptrace.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -349,8 +349,11 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
smp_rmb();
mm = task->mm;
- if (mm &&
- ((get_dumpable(mm) != SUID_DUMP_USER) &&
- !ptrace_has_cap(mm->user_ns, mode)))
- return -EPERM;
+ if (mm) {
+ if ((get_dumpable(mm) != SUID_DUMP_USER) &&
+ !ptrace_has_cap(mm->user_ns, mode))
+ return -EPERM;
+ } else if (!ptrace_has_cap(&init_user_ns, mode)) {
+ return -EPERM;
+ }
return security_ptrace_access_check(task, mode);
--
2.43.0

View File

@ -1,962 +0,0 @@
From: AlmaLinux Backport <packager@almalinux.org>
Subject: [PATCH] CVE-2026-31431 ("Copy Fail"): crypto AEAD/algif fixes from linux-5.15.y
Combined backport addressing CVE-2026-31431 ("Copy Fail"), reported by
Taeyang Lee <0wn@theori.io>. EL9 kernel is based on 5.14.0; the closest
stable branch is linux-5.15.y. Pulls one prerequisite (committed
2026-02-06 to 5.15.y) plus nine 2026-04-30 stable fixes:
fee86edf5803 crypto: authencesn - reject too-short AAD (assoclen<8) to match ESP/ESN spec
36435a56cd6b crypto: scatterwalk - Backport memcpy_sglist()
17774d99bb43 crypto: algif_aead - use memcpy_sglist() instead of null skcipher
19d43105a97b crypto: algif_aead - Revert to operating out-of-place
a920cabdb0b7 crypto: algif_aead - snapshot IV for async AEAD requests
e416c41a96c8 crypto: authenc - use memcpy_sglist() instead of null skcipher
d589abd8b019 crypto: authencesn - Do not place hiseq at end of dst for out-of-place decryption
723bb1b4a6dd crypto: authencesn - Fix src offset when decrypting in-place
2b781d1d4f93 crypto: af_alg - Fix page reassignment overflow in af_alg_pull_tsgl
fd427dd84f22 crypto: algif_aead - Fix minimum RX size check for decryption
fee86edf5803 is the prerequisite for d589abd8b019 to apply.
Signed-off-by: Andrew Lukoshko <alukoshko@almalinux.org>
---
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -525,15 +525,13 @@
/**
* af_alg_count_tsgl - Count number of TX SG entries
*
- * The counting starts from the beginning of the SGL to @bytes. If
- * an @offset is provided, the counting of the SG entries starts at the @offset.
+ * The counting starts from the beginning of the SGL to @bytes.
*
* @sk: socket of connection to user space
* @bytes: Count the number of SG entries holding given number of bytes.
- * @offset: Start the counting of SG entries from the given offset.
* Return: Number of TX SG entries found given the constraints
*/
-unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset)
+unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes)
{
const struct alg_sock *ask = alg_sk(sk);
const struct af_alg_ctx *ctx = ask->private;
@@ -548,25 +546,11 @@
const struct scatterlist *sg = sgl->sg;
for (i = 0; i < sgl->cur; i++) {
- size_t bytes_count;
-
- /* Skip offset */
- if (offset >= sg[i].length) {
- offset -= sg[i].length;
- bytes -= sg[i].length;
- continue;
- }
-
- bytes_count = sg[i].length - offset;
-
- offset = 0;
sgl_count++;
-
- /* If we have seen requested number of bytes, stop */
- if (bytes_count >= bytes)
+ if (sg[i].length >= bytes)
return sgl_count;
- bytes -= bytes_count;
+ bytes -= sg[i].length;
}
}
@@ -578,19 +562,14 @@
* af_alg_pull_tsgl - Release the specified buffers from TX SGL
*
* If @dst is non-null, reassign the pages to @dst. The caller must release
- * the pages. If @dst_offset is given only reassign the pages to @dst starting
- * at the @dst_offset (byte). The caller must ensure that @dst is large
- * enough (e.g. by using af_alg_count_tsgl with the same offset).
+ * the pages.
*
* @sk: socket of connection to user space
* @used: Number of bytes to pull from TX SGL
* @dst: If non-NULL, buffer is reassigned to dst SGL instead of releasing. The
* caller must release the buffers in dst.
- * @dst_offset: Reassign the TX SGL from given offset. All buffers before
- * reaching the offset is released.
*/
-void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
- size_t dst_offset)
+void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst)
{
struct alg_sock *ask = alg_sk(sk);
struct af_alg_ctx *ctx = ask->private;
@@ -614,19 +593,11 @@
* Assumption: caller created af_alg_count_tsgl(len)
* SG entries in dst.
*/
- if (dst) {
- if (dst_offset >= plen) {
- /* discard page before offset */
- dst_offset -= plen;
- } else {
- /* reassign page to dst after offset */
- get_page(page);
- sg_set_page(dst + j, page,
- plen - dst_offset,
- sg[i].offset + dst_offset);
- dst_offset = 0;
- j++;
- }
+ if (dst && plen) {
+ /* reassign page to dst */
+ get_page(page);
+ sg_set_page(dst + j, page, plen, sg[i].offset);
+ j++;
}
sg[i].length -= plen;
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -26,8 +26,6 @@
#include <crypto/internal/aead.h>
#include <crypto/scatterwalk.h>
#include <crypto/if_alg.h>
-#include <crypto/skcipher.h>
-#include <crypto/null.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/kernel.h>
@@ -36,19 +34,13 @@
#include <linux/net.h>
#include <net/sock.h>
-struct aead_tfm {
- struct crypto_aead *aead;
- struct crypto_sync_skcipher *null_tfm;
-};
-
static inline bool aead_sufficient_data(struct sock *sk)
{
struct alg_sock *ask = alg_sk(sk);
struct sock *psk = ask->parent;
struct alg_sock *pask = alg_sk(psk);
struct af_alg_ctx *ctx = ask->private;
- struct aead_tfm *aeadc = pask->private;
- struct crypto_aead *tfm = aeadc->aead;
+ struct crypto_aead *tfm = pask->private;
unsigned int as = crypto_aead_authsize(tfm);
/*
@@ -64,27 +56,12 @@
struct alg_sock *ask = alg_sk(sk);
struct sock *psk = ask->parent;
struct alg_sock *pask = alg_sk(psk);
- struct aead_tfm *aeadc = pask->private;
- struct crypto_aead *tfm = aeadc->aead;
+ struct crypto_aead *tfm = pask->private;
unsigned int ivsize = crypto_aead_ivsize(tfm);
return af_alg_sendmsg(sock, msg, size, ivsize);
}
-static int crypto_aead_copy_sgl(struct crypto_sync_skcipher *null_tfm,
- struct scatterlist *src,
- struct scatterlist *dst, unsigned int len)
-{
- SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, null_tfm);
-
- skcipher_request_set_sync_tfm(skreq, null_tfm);
- skcipher_request_set_callback(skreq, CRYPTO_TFM_REQ_MAY_SLEEP,
- NULL, NULL);
- skcipher_request_set_crypt(skreq, src, dst, len, NULL);
-
- return crypto_skcipher_encrypt(skreq);
-}
-
static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
size_t ignored, int flags)
{
@@ -93,13 +70,12 @@
struct sock *psk = ask->parent;
struct alg_sock *pask = alg_sk(psk);
struct af_alg_ctx *ctx = ask->private;
- struct aead_tfm *aeadc = pask->private;
- struct crypto_aead *tfm = aeadc->aead;
- struct crypto_sync_skcipher *null_tfm = aeadc->null_tfm;
- unsigned int i, as = crypto_aead_authsize(tfm);
+ struct crypto_aead *tfm = pask->private;
+ unsigned int as = crypto_aead_authsize(tfm);
+ unsigned int ivsize = crypto_aead_ivsize(tfm);
struct af_alg_async_req *areq;
- struct af_alg_tsgl *tsgl, *tmp;
struct scatterlist *rsgl_src, *tsgl_src = NULL;
+ void *iv;
int err = 0;
size_t used = 0; /* [in] TX bufs to be en/decrypted */
size_t outlen = 0; /* [out] RX bufs produced by kernel */
@@ -151,10 +127,14 @@
/* Allocate cipher request for current operation. */
areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) +
- crypto_aead_reqsize(tfm));
+ crypto_aead_reqsize(tfm) + ivsize);
if (IS_ERR(areq))
return PTR_ERR(areq);
+ iv = (u8 *)aead_request_ctx(&areq->cra_u.aead_req) +
+ crypto_aead_reqsize(tfm);
+ memcpy(iv, ctx->iv, ivsize);
+
/* convert iovecs of output buffers into RX SGL */
err = af_alg_get_rsgl(sk, msg, flags, areq, outlen, &usedpages);
if (err)
@@ -170,7 +150,7 @@
if (usedpages < outlen) {
size_t less = outlen - usedpages;
- if (used < less) {
+ if (used < less + (ctx->enc ? 0 : as)) {
err = -EINVAL;
goto free;
}
@@ -178,23 +158,24 @@
outlen -= less;
}
+ /*
+ * Create a per request TX SGL for this request which tracks the
+ * SG entries from the global TX SGL.
+ */
processed = used + ctx->aead_assoclen;
- list_for_each_entry_safe(tsgl, tmp, &ctx->tsgl_list, list) {
- for (i = 0; i < tsgl->cur; i++) {
- struct scatterlist *process_sg = tsgl->sg + i;
-
- if (!(process_sg->length) || !sg_page(process_sg))
- continue;
- tsgl_src = process_sg;
- break;
- }
- if (tsgl_src)
- break;
- }
- if (processed && !tsgl_src) {
- err = -EFAULT;
+ areq->tsgl_entries = af_alg_count_tsgl(sk, processed);
+ if (!areq->tsgl_entries)
+ areq->tsgl_entries = 1;
+ areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
+ areq->tsgl_entries),
+ GFP_KERNEL);
+ if (!areq->tsgl) {
+ err = -ENOMEM;
goto free;
}
+ sg_init_table(areq->tsgl, areq->tsgl_entries);
+ af_alg_pull_tsgl(sk, processed, areq->tsgl);
+ tsgl_src = areq->tsgl;
/*
* Copy of AAD from source to destination
@@ -203,82 +184,16 @@
* when user space uses an in-place cipher operation, the kernel
* will copy the data as it does not see whether such in-place operation
* is initiated.
- *
- * To ensure efficiency, the following implementation ensure that the
- * ciphers are invoked to perform a crypto operation in-place. This
- * is achieved by memory management specified as follows.
*/
/* Use the RX SGL as source (and destination) for crypto op. */
rsgl_src = areq->first_rsgl.sgl.sg;
- if (ctx->enc) {
- /*
- * Encryption operation - The in-place cipher operation is
- * achieved by the following operation:
- *
- * TX SGL: AAD || PT
- * | |
- * | copy |
- * v v
- * RX SGL: AAD || PT || Tag
- */
- err = crypto_aead_copy_sgl(null_tfm, tsgl_src,
- areq->first_rsgl.sgl.sg, processed);
- if (err)
- goto free;
- af_alg_pull_tsgl(sk, processed, NULL, 0);
- } else {
- /*
- * Decryption operation - To achieve an in-place cipher
- * operation, the following SGL structure is used:
- *
- * TX SGL: AAD || CT || Tag
- * | | ^
- * | copy | | Create SGL link.
- * v v |
- * RX SGL: AAD || CT ----+
- */
-
- /* Copy AAD || CT to RX SGL buffer for in-place operation. */
- err = crypto_aead_copy_sgl(null_tfm, tsgl_src,
- areq->first_rsgl.sgl.sg, outlen);
- if (err)
- goto free;
-
- /* Create TX SGL for tag and chain it to RX SGL. */
- areq->tsgl_entries = af_alg_count_tsgl(sk, processed,
- processed - as);
- if (!areq->tsgl_entries)
- areq->tsgl_entries = 1;
- areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
- areq->tsgl_entries),
- GFP_KERNEL);
- if (!areq->tsgl) {
- err = -ENOMEM;
- goto free;
- }
- sg_init_table(areq->tsgl, areq->tsgl_entries);
-
- /* Release TX SGL, except for tag data and reassign tag data. */
- af_alg_pull_tsgl(sk, processed, areq->tsgl, processed - as);
-
- /* chain the areq TX SGL holding the tag with RX SGL */
- if (usedpages) {
- /* RX SGL present */
- struct af_alg_sgl *sgl_prev = &areq->last_rsgl->sgl;
-
- sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1);
- sg_chain(sgl_prev->sg, sgl_prev->npages + 1,
- areq->tsgl);
- } else
- /* no RX SGL present (e.g. authentication only) */
- rsgl_src = areq->tsgl;
- }
+ memcpy_sglist(rsgl_src, tsgl_src, ctx->aead_assoclen);
/* Initialize the crypto operation */
- aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src,
- areq->first_rsgl.sgl.sg, used, ctx->iv);
+ aead_request_set_crypt(&areq->cra_u.aead_req, tsgl_src,
+ areq->first_rsgl.sgl.sg, used, iv);
aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen);
aead_request_set_tfm(&areq->cra_u.aead_req, tfm);
@@ -378,7 +293,7 @@
int err = 0;
struct sock *psk;
struct alg_sock *pask;
- struct aead_tfm *tfm;
+ struct crypto_aead *tfm;
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
@@ -392,7 +307,7 @@
err = -ENOKEY;
lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
- if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY)
+ if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
goto unlock;
atomic_dec(&pask->nokey_refcnt);
@@ -466,54 +381,22 @@
static void *aead_bind(const char *name, u32 type, u32 mask)
{
- struct aead_tfm *tfm;
- struct crypto_aead *aead;
- struct crypto_sync_skcipher *null_tfm;
-
- tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
- if (!tfm)
- return ERR_PTR(-ENOMEM);
-
- aead = crypto_alloc_aead(name, type, mask);
- if (IS_ERR(aead)) {
- kfree(tfm);
- return ERR_CAST(aead);
- }
-
- null_tfm = crypto_get_default_null_skcipher();
- if (IS_ERR(null_tfm)) {
- crypto_free_aead(aead);
- kfree(tfm);
- return ERR_CAST(null_tfm);
- }
-
- tfm->aead = aead;
- tfm->null_tfm = null_tfm;
-
- return tfm;
+ return crypto_alloc_aead(name, type, mask);
}
static void aead_release(void *private)
{
- struct aead_tfm *tfm = private;
-
- crypto_free_aead(tfm->aead);
- crypto_put_default_null_skcipher();
- kfree(tfm);
+ crypto_free_aead(private);
}
static int aead_setauthsize(void *private, unsigned int authsize)
{
- struct aead_tfm *tfm = private;
-
- return crypto_aead_setauthsize(tfm->aead, authsize);
+ return crypto_aead_setauthsize(private, authsize);
}
static int aead_setkey(void *private, const u8 *key, unsigned int keylen)
{
- struct aead_tfm *tfm = private;
-
- return crypto_aead_setkey(tfm->aead, key, keylen);
+ return crypto_aead_setkey(private, key, keylen);
}
static void aead_sock_destruct(struct sock *sk)
@@ -522,11 +405,10 @@
struct af_alg_ctx *ctx = ask->private;
struct sock *psk = ask->parent;
struct alg_sock *pask = alg_sk(psk);
- struct aead_tfm *aeadc = pask->private;
- struct crypto_aead *tfm = aeadc->aead;
+ struct crypto_aead *tfm = pask->private;
unsigned int ivlen = crypto_aead_ivsize(tfm);
- af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
+ af_alg_pull_tsgl(sk, ctx->used, NULL);
sock_kzfree_s(sk, ctx->iv, ivlen);
sock_kfree_s(sk, ctx, ctx->len);
af_alg_release_parent(sk);
@@ -536,10 +418,9 @@
{
struct af_alg_ctx *ctx;
struct alg_sock *ask = alg_sk(sk);
- struct aead_tfm *tfm = private;
- struct crypto_aead *aead = tfm->aead;
+ struct crypto_aead *tfm = private;
unsigned int len = sizeof(*ctx);
- unsigned int ivlen = crypto_aead_ivsize(aead);
+ unsigned int ivlen = crypto_aead_ivsize(tfm);
ctx = sock_kmalloc(sk, len, GFP_KERNEL);
if (!ctx)
@@ -566,9 +447,9 @@
static int aead_accept_parent(void *private, struct sock *sk)
{
- struct aead_tfm *tfm = private;
+ struct crypto_aead *tfm = private;
- if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY)
+ if (crypto_aead_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY;
return aead_accept_parent_nokey(private, sk);
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -89,7 +89,7 @@
* Create a per request TX SGL for this request which tracks the
* SG entries from the global TX SGL.
*/
- areq->tsgl_entries = af_alg_count_tsgl(sk, len, 0);
+ areq->tsgl_entries = af_alg_count_tsgl(sk, len);
if (!areq->tsgl_entries)
areq->tsgl_entries = 1;
areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
@@ -100,7 +100,7 @@
goto free;
}
sg_init_table(areq->tsgl, areq->tsgl_entries);
- af_alg_pull_tsgl(sk, len, areq->tsgl, 0);
+ af_alg_pull_tsgl(sk, len, areq->tsgl);
/* Initialize the crypto operation */
skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm);
@@ -313,7 +313,7 @@
struct alg_sock *pask = alg_sk(psk);
struct crypto_skcipher *tfm = pask->private;
- af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
+ af_alg_pull_tsgl(sk, ctx->used, NULL);
sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
sock_kfree_s(sk, ctx, ctx->len);
af_alg_release_parent(sk);
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -9,7 +9,6 @@
#include <crypto/internal/hash.h>
#include <crypto/internal/skcipher.h>
#include <crypto/authenc.h>
-#include <crypto/null.h>
#include <crypto/scatterwalk.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -28,7 +27,6 @@
struct crypto_authenc_ctx {
struct crypto_ahash *auth;
struct crypto_skcipher *enc;
- struct crypto_sync_skcipher *null;
};
struct authenc_request_ctx {
@@ -174,21 +172,6 @@
authenc_request_complete(areq, err);
}
-static int crypto_authenc_copy_assoc(struct aead_request *req)
-{
- struct crypto_aead *authenc = crypto_aead_reqtfm(req);
- struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
- SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, ctx->null);
-
- skcipher_request_set_sync_tfm(skreq, ctx->null);
- skcipher_request_set_callback(skreq, aead_request_flags(req),
- NULL, NULL);
- skcipher_request_set_crypt(skreq, req->src, req->dst, req->assoclen,
- NULL);
-
- return crypto_skcipher_encrypt(skreq);
-}
-
static int crypto_authenc_encrypt(struct aead_request *req)
{
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
@@ -207,10 +190,7 @@
dst = src;
if (req->src != req->dst) {
- err = crypto_authenc_copy_assoc(req);
- if (err)
- return err;
-
+ memcpy_sglist(req->dst, req->src, req->assoclen);
dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, req->assoclen);
}
@@ -311,7 +291,6 @@
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(tfm);
struct crypto_ahash *auth;
struct crypto_skcipher *enc;
- struct crypto_sync_skcipher *null;
int err;
auth = crypto_spawn_ahash(&ictx->auth);
@@ -323,14 +302,8 @@
if (IS_ERR(enc))
goto err_free_ahash;
- null = crypto_get_default_null_skcipher();
- err = PTR_ERR(null);
- if (IS_ERR(null))
- goto err_free_skcipher;
-
ctx->auth = auth;
ctx->enc = enc;
- ctx->null = null;
crypto_aead_set_reqsize(
tfm,
@@ -344,8 +317,6 @@
return 0;
-err_free_skcipher:
- crypto_free_skcipher(enc);
err_free_ahash:
crypto_free_ahash(auth);
return err;
@@ -357,7 +328,6 @@
crypto_free_ahash(ctx->auth);
crypto_free_skcipher(ctx->enc);
- crypto_put_default_null_skcipher();
}
static void crypto_authenc_free(struct aead_instance *inst)
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -12,7 +12,6 @@
#include <crypto/internal/hash.h>
#include <crypto/internal/skcipher.h>
#include <crypto/authenc.h>
-#include <crypto/null.h>
#include <crypto/scatterwalk.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -31,7 +30,6 @@
unsigned int reqoff;
struct crypto_ahash *auth;
struct crypto_skcipher *enc;
- struct crypto_sync_skcipher *null;
};
struct authenc_esn_request_ctx {
@@ -164,20 +162,6 @@
authenc_esn_request_complete(areq, err);
}
-static int crypto_authenc_esn_copy(struct aead_request *req, unsigned int len)
-{
- struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
- struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
- SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, ctx->null);
-
- skcipher_request_set_sync_tfm(skreq, ctx->null);
- skcipher_request_set_callback(skreq, aead_request_flags(req),
- NULL, NULL);
- skcipher_request_set_crypt(skreq, req->src, req->dst, len, NULL);
-
- return crypto_skcipher_encrypt(skreq);
-}
-
static int crypto_authenc_esn_encrypt(struct aead_request *req)
{
struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
@@ -191,15 +175,15 @@
struct scatterlist *src, *dst;
int err;
+ if (assoclen < 8)
+ return -EINVAL;
+
sg_init_table(areq_ctx->src, 2);
src = scatterwalk_ffwd(areq_ctx->src, req->src, assoclen);
dst = src;
if (req->src != req->dst) {
- err = crypto_authenc_esn_copy(req, assoclen);
- if (err)
- return err;
-
+ memcpy_sglist(req->dst, req->src, assoclen);
sg_init_table(areq_ctx->dst, 2);
dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, assoclen);
}
@@ -230,6 +214,7 @@
crypto_ahash_alignmask(auth) + 1);
unsigned int cryptlen = req->cryptlen - authsize;
unsigned int assoclen = req->assoclen;
+ struct scatterlist *src = req->src;
struct scatterlist *dst = req->dst;
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
u32 tmp[2];
@@ -237,23 +222,29 @@
if (!authsize)
goto decrypt;
- /* Move high-order bits of sequence number back. */
- scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
- scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
- scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
+ if (src == dst) {
+ /* Move high-order bits of sequence number back. */
+ scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
+ scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
+ scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
+ } else
+ memcpy_sglist(dst, src, assoclen);
if (crypto_memneq(ihash, ohash, authsize))
return -EBADMSG;
decrypt:
- sg_init_table(areq_ctx->dst, 2);
dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen);
+ if (req->src == req->dst)
+ src = dst;
+ else
+ src = scatterwalk_ffwd(areq_ctx->src, src, assoclen);
skcipher_request_set_tfm(skreq, ctx->enc);
skcipher_request_set_callback(skreq, flags,
req->base.complete, req->base.data);
- skcipher_request_set_crypt(skreq, dst, dst, cryptlen, req->iv);
+ skcipher_request_set_crypt(skreq, src, dst, cryptlen, req->iv);
return crypto_skcipher_decrypt(skreq);
}
@@ -280,31 +271,36 @@
unsigned int assoclen = req->assoclen;
unsigned int cryptlen = req->cryptlen;
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
+ struct scatterlist *src = req->src;
struct scatterlist *dst = req->dst;
u32 tmp[2];
int err;
- cryptlen -= authsize;
+ if (assoclen < 8)
+ return -EINVAL;
- if (req->src != dst) {
- err = crypto_authenc_esn_copy(req, assoclen + cryptlen);
- if (err)
- return err;
- }
+ if (!authsize)
+ goto tail;
+ cryptlen -= authsize;
scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen,
authsize, 0);
- if (!authsize)
- goto tail;
-
/* Move high-order bits of sequence number to the end. */
- scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);
- scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
- scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
-
- sg_init_table(areq_ctx->dst, 2);
- dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
+ scatterwalk_map_and_copy(tmp, src, 0, 8, 0);
+ if (src == dst) {
+ scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
+ scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
+ dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
+ } else {
+ scatterwalk_map_and_copy(tmp, dst, 0, 4, 1);
+ scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen - 4, 4, 1);
+
+ src = scatterwalk_ffwd(areq_ctx->src, src, 8);
+ dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
+ memcpy_sglist(dst, src, assoclen + cryptlen - 8);
+ dst = req->dst;
+ }
ahash_request_set_tfm(ahreq, auth);
ahash_request_set_crypt(ahreq, dst, ohash, assoclen + cryptlen);
@@ -326,7 +322,6 @@
struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(tfm);
struct crypto_ahash *auth;
struct crypto_skcipher *enc;
- struct crypto_sync_skcipher *null;
int err;
auth = crypto_spawn_ahash(&ictx->auth);
@@ -338,14 +333,8 @@
if (IS_ERR(enc))
goto err_free_ahash;
- null = crypto_get_default_null_skcipher();
- err = PTR_ERR(null);
- if (IS_ERR(null))
- goto err_free_skcipher;
-
ctx->auth = auth;
ctx->enc = enc;
- ctx->null = null;
ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth),
crypto_ahash_alignmask(auth) + 1);
@@ -362,8 +351,6 @@
return 0;
-err_free_skcipher:
- crypto_free_skcipher(enc);
err_free_ahash:
crypto_free_ahash(auth);
return err;
@@ -375,7 +362,6 @@
crypto_free_ahash(ctx->auth);
crypto_free_skcipher(ctx->enc);
- crypto_put_default_null_skcipher();
}
static void crypto_authenc_esn_free(struct aead_instance *inst)
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -69,6 +69,100 @@
}
EXPORT_SYMBOL_GPL(scatterwalk_map_and_copy);
+/**
+ * memcpy_sglist() - Copy data from one scatterlist to another
+ * @dst: The destination scatterlist. Can be NULL if @nbytes == 0.
+ * @src: The source scatterlist. Can be NULL if @nbytes == 0.
+ * @nbytes: Number of bytes to copy
+ *
+ * The scatterlists can describe exactly the same memory, in which case this
+ * function is a no-op. No other overlaps are supported.
+ *
+ * Context: Any context
+ */
+void memcpy_sglist(struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ unsigned int src_offset, dst_offset;
+
+ if (unlikely(nbytes == 0)) /* in case src and/or dst is NULL */
+ return;
+
+ src_offset = src->offset;
+ dst_offset = dst->offset;
+ for (;;) {
+ /* Compute the length to copy this step. */
+ unsigned int len = min3(src->offset + src->length - src_offset,
+ dst->offset + dst->length - dst_offset,
+ nbytes);
+ struct page *src_page = sg_page(src);
+ struct page *dst_page = sg_page(dst);
+ const void *src_virt;
+ void *dst_virt;
+
+ if (IS_ENABLED(CONFIG_HIGHMEM)) {
+ /* HIGHMEM: we may have to actually map the pages. */
+ const unsigned int src_oip = offset_in_page(src_offset);
+ const unsigned int dst_oip = offset_in_page(dst_offset);
+ const unsigned int limit = PAGE_SIZE;
+
+ /* Further limit len to not cross a page boundary. */
+ len = min3(len, limit - src_oip, limit - dst_oip);
+
+ /* Compute the source and destination pages. */
+ src_page += src_offset / PAGE_SIZE;
+ dst_page += dst_offset / PAGE_SIZE;
+
+ if (src_page != dst_page) {
+ /* Copy between different pages. */
+ memcpy_page(dst_page, dst_oip,
+ src_page, src_oip, len);
+ flush_dcache_page(dst_page);
+ } else if (src_oip != dst_oip) {
+ /* Copy between different parts of same page. */
+ dst_virt = kmap_local_page(dst_page);
+ memcpy(dst_virt + dst_oip, dst_virt + src_oip,
+ len);
+ kunmap_local(dst_virt);
+ flush_dcache_page(dst_page);
+ } /* Else, it's the same memory. No action needed. */
+ } else {
+ /*
+ * !HIGHMEM: no mapping needed. Just work in the linear
+ * buffer of each sg entry. Note that we can cross page
+ * boundaries, as they are not significant in this case.
+ */
+ src_virt = page_address(src_page) + src_offset;
+ dst_virt = page_address(dst_page) + dst_offset;
+ if (src_virt != dst_virt) {
+ memcpy(dst_virt, src_virt, len);
+ if (ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE)
+ __scatterwalk_flush_dcache_pages(
+ dst_page, dst_offset, len);
+ } /* Else, it's the same memory. No action needed. */
+ }
+ nbytes -= len;
+ if (nbytes == 0) /* No more to copy? */
+ break;
+
+ /*
+ * There's more to copy. Advance the offsets by the length
+ * copied this step, and advance the sg entries as needed.
+ */
+ src_offset += len;
+ if (src_offset >= src->offset + src->length) {
+ src = sg_next(src);
+ src_offset = src->offset;
+ }
+ dst_offset += len;
+ if (dst_offset >= dst->offset + dst->length) {
+ dst = sg_next(dst);
+ dst_offset = dst->offset;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(memcpy_sglist);
+
struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2],
struct scatterlist *src,
unsigned int len)
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -221,7 +221,6 @@
select CRYPTO_SKCIPHER
select CRYPTO_MANAGER
select CRYPTO_HASH
- select CRYPTO_NULL
help
Authenc: Combined mode wrapper for IPsec.
This is required for IPSec.
@@ -2120,7 +2119,6 @@
depends on NET
select CRYPTO_AEAD
select CRYPTO_SKCIPHER
- select CRYPTO_NULL
select CRYPTO_USER_API
help
This option enables the user-spaces interface for AEAD
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -226,9 +226,8 @@
return PAGE_SIZE <= af_alg_rcvbuf(sk);
}
-unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset);
-void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
- size_t dst_offset);
+unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes);
+void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst);
void af_alg_wmem_wakeup(struct sock *sk);
int af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min);
int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
--- a/include/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -89,6 +89,35 @@
scatterwalk_start(walk, sg_next(walk->sg));
}
+/*
+ * Flush the dcache of any pages that overlap the region
+ * [offset, offset + nbytes) relative to base_page.
+ *
+ * This should be called only when ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE, to ensure
+ * that all relevant code (including the call to sg_page() in the caller, if
+ * applicable) gets fully optimized out when !ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE.
+ */
+static inline void __scatterwalk_flush_dcache_pages(struct page *base_page,
+ unsigned int offset,
+ unsigned int nbytes)
+{
+ unsigned int num_pages;
+ unsigned int i;
+
+ base_page += offset / PAGE_SIZE;
+ offset %= PAGE_SIZE;
+
+ /*
+ * This is an overflow-safe version of
+ * num_pages = DIV_ROUND_UP(offset + nbytes, PAGE_SIZE).
+ */
+ num_pages = nbytes / PAGE_SIZE;
+ num_pages += DIV_ROUND_UP(offset + (nbytes % PAGE_SIZE), PAGE_SIZE);
+
+ for (i = 0; i < num_pages; i++)
+ flush_dcache_page(base_page + i);
+}
+
static inline void scatterwalk_done(struct scatter_walk *walk, int out,
int more)
{
@@ -101,6 +130,9 @@
size_t nbytes, int out);
void *scatterwalk_map(struct scatter_walk *walk);
+void memcpy_sglist(struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes);
+
void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
unsigned int start, unsigned int nbytes, int out);

View File

@ -0,0 +1,49 @@
From 21f7e8315ba37d429d01c98365e7e33d7611eb1e Mon Sep 17 00:00:00 2001
From: Medha Mummigatti <mmummiga@redhat.com>
Date: Thu, 12 Mar 2026 13:47:24 +0530
Subject: [PATCH] net: hv_netvsc: reject RSS hash key programming without RX
indirection table
JIRA: https://issues.redhat.com/browse/RHEL-150569
commit d23564955811da493f34412d7de60fa268c8cb50
Author Aditya Garg <gargaditya@linux.microsoft.com>
net: hv_netvsc: reject RSS hash key programming without RX indirection table
RSS configuration requires a valid RX indirection table. When the device
reports a single receive queue, rndis_filter_device_add() does not
allocate an indirection table, accepting RSS hash key updates in this
state leads to a hang.
Fix this by gating netvsc_set_rxfh() on ndc->rx_table_sz and return
-EOPNOTSUPP when the table is absent. This aligns set_rxfh with the device
capabilities and prevents incorrect behavior.
Fixes: 962f3fee83a4 ("netvsc: add ethtool ops to get/set RSS key")
Signed-off-by: Aditya Garg <gargaditya@linux.microsoft.com>
Reviewed-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Link: https://patch.msgid.link/1768212093-1594-1-git-send-email-gargaditya@linux.microsoft.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
(cherry picked from commit d23564955811da493f34412d7de60fa268c8cb50)
Signed-off-by: Medha Mummigatti <mmummiga@redhat.com>
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 229e29498ecf..6cfef8b22cae 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1756,6 +1756,9 @@ static int netvsc_set_rxfh(struct net_device *dev,
rxfh->hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
+ if (!ndc->rx_table_sz)
+ return -EOPNOTSUPP;
+
rndis_dev = ndev->extension;
if (rxfh->indir) {
for (i = 0; i < ndc->rx_table_sz; i++)
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,62 @@
From 4f4e442a275bfa406ab9766548cb30001deb4515 Mon Sep 17 00:00:00 2001
From: Sreekanth Reddy <sreeredd@redhat.com>
Date: Tue, 12 Aug 2025 16:35:13 -0700
Subject: [PATCH] RDMA/bnxt_re: Support extended stats for Thor2 VF
JIRA: https://issues.redhat.com/browse/RHEL-108696
JIRA: https://issues.redhat.com/browse/RHEL-96539
commit 260ce16e579d375ba8f1ac945308343522f98d50
Author: Ajit Khaparde <ajit.khaparde@broadcom.com>
Date: Fri May 23 13:29:52 2025 +0530
RDMA/bnxt_re: Support extended stats for Thor2 VF
The driver currently checks if the user is querying VF RoCE statistics.
It will not send the query_roce_stats_ext HWRM command if it is for a
VF. But Thor2 VF can support extended statistics.
Allow query of extended stats for Thor2 VFs.
Signed-off-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
Link: https://patch.msgid.link/20250523075952.1267827-1-kalesh-anakkur.purayil@broadcom.com
Reviewed-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sreekanth Reddy <sreeredd@redhat.com>
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
index 457eecb99f96..be34c605d516 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
@@ -1113,7 +1113,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_FORCE_COMPLETION;
if (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE)
qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_VARIABLE_SIZED_WQE_ENABLED;
- if (_is_ext_stats_supported(res->dattr->dev_cap_flags) && !res->is_vf)
+ if (bnxt_ext_stats_supported(res->cctx, res->dattr->dev_cap_flags, res->is_vf))
qp_flags |= CMDQ_CREATE_QP_QP_FLAGS_EXT_STATS_ENABLED;
req.qp_flags = cpu_to_le32(qp_flags);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
index f231e886ad9d..9efd32a3dc55 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
@@ -846,7 +846,12 @@ int bnxt_qplib_qext_stat(struct bnxt_qplib_rcfw *rcfw, u32 fid,
req.resp_size = sbuf.size / BNXT_QPLIB_CMDQE_UNITS;
req.resp_addr = cpu_to_le64(sbuf.dma_addr);
- req.function_id = cpu_to_le32(fid);
+ if (bnxt_qplib_is_chip_gen_p7(rcfw->res->cctx) && rcfw->res->is_vf)
+ req.function_id =
+ cpu_to_le32(CMDQ_QUERY_ROCE_STATS_EXT_VF_VALID |
+ (fid << CMDQ_QUERY_ROCE_STATS_EXT_VF_NUM_SFT));
+ else
+ req.function_id = cpu_to_le32(fid);
req.flags = cpu_to_le16(CMDQ_QUERY_ROCE_STATS_EXT_FLAGS_FUNCTION_ID);
bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, &sbuf, sizeof(req),
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,42 @@
From fd15899f1b6ab1026242424f9b3f9ba817c9656f Mon Sep 17 00:00:00 2001
From: Sreekanth Reddy <sreeredd@redhat.com>
Date: Tue, 12 Aug 2025 16:35:35 -0700
Subject: [PATCH] RDMA/bnxt_re: Fix size of uverbs_copy_to() in
BNXT_RE_METHOD_GET_TOGGLE_MEM
JIRA: https://issues.redhat.com/browse/RHEL-108696
JIRA: https://issues.redhat.com/browse/RHEL-96539
commit 09d231ab569ca97478445ccc1ad44ab026de39b1
Author: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Date: Fri Jul 4 10:08:55 2025 +0530
RDMA/bnxt_re: Fix size of uverbs_copy_to() in BNXT_RE_METHOD_GET_TOGGLE_MEM
Since both "length" and "offset" are of type u32, there is
no functional issue here.
Reviewed-by: Saravanan Vajravel <saravanan.vajravel@broadcom.com>
Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Link: https://patch.msgid.link/20250704043857.19158-2-kalesh-anakkur.purayil@broadcom.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sreekanth Reddy <sreeredd@redhat.com>
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 063801384b2b..3a627acb82ce 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -4738,7 +4738,7 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_TOGGLE_MEM)(struct uverbs_attr_bund
return err;
err = uverbs_copy_to(attrs, BNXT_RE_TOGGLE_MEM_MMAP_OFFSET,
- &offset, sizeof(length));
+ &offset, sizeof(offset));
if (err)
return err;
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,128 @@
From bae4a2298624cecd837e2deff15b915e6804f940 Mon Sep 17 00:00:00 2001
From: Sreekanth Reddy <sreeredd@redhat.com>
Date: Tue, 12 Aug 2025 16:35:48 -0700
Subject: [PATCH] RDMA/bnxt_re: Support 2G message size
JIRA: https://issues.redhat.com/browse/RHEL-108696
JIRA: https://issues.redhat.com/browse/RHEL-96539
commit 0aed817380d620987b2d5c573fdd2f01c30976a4
Author: Selvin Xavier <selvin.xavier@broadcom.com>
Date: Fri Jul 4 10:08:56 2025 +0530
RDMA/bnxt_re: Support 2G message size
bnxt_qplib_put_sges is calculating the length in
a signed int. So handling the 2G message size
is not working since it is considered as negative.
Use a unsigned number to calculate the total message
length. As per the spec, IB message size shall be
between zero and 2^31 bytes (inclusive). So adding
a check for 2G message size.
Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
Link: https://patch.msgid.link/20250704043857.19158-3-kalesh-anakkur.purayil@broadcom.com
Reviewed-by: Saravanan Vajravel <saravanan.vajravel@broadcom.com>
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sreekanth Reddy <sreeredd@redhat.com>
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
index be34c605d516..dfe3177123e5 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
@@ -1750,9 +1750,9 @@ static void bnxt_qplib_fill_psn_search(struct bnxt_qplib_qp *qp,
}
}
-static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp,
- struct bnxt_qplib_swqe *wqe,
- u16 *idx)
+static unsigned int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp,
+ struct bnxt_qplib_swqe *wqe,
+ u32 *idx)
{
struct bnxt_qplib_hwq *hwq;
int len, t_len, offt;
@@ -1769,7 +1769,7 @@ static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp,
il_src = (void *)wqe->sg_list[indx].addr;
t_len += len;
if (t_len > qp->max_inline_data)
- return -ENOMEM;
+ return BNXT_RE_INVAL_MSG_SIZE;
while (len) {
if (pull_dst) {
pull_dst = false;
@@ -1795,9 +1795,9 @@ static int bnxt_qplib_put_inline(struct bnxt_qplib_qp *qp,
return t_len;
}
-static u32 bnxt_qplib_put_sges(struct bnxt_qplib_hwq *hwq,
- struct bnxt_qplib_sge *ssge,
- u16 nsge, u16 *idx)
+static unsigned int bnxt_qplib_put_sges(struct bnxt_qplib_hwq *hwq,
+ struct bnxt_qplib_sge *ssge,
+ u32 nsge, u32 *idx)
{
struct sq_sge *dsge;
int indx, len = 0;
@@ -1878,14 +1878,12 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
struct bnxt_qplib_hwq *hwq;
struct bnxt_qplib_swq *swq;
bool sch_handler = false;
+ u32 wqe_idx, slots, idx;
u16 wqe_sz, qdf = 0;
bool msn_update;
void *base_hdr;
void *ext_hdr;
__le32 temp32;
- u32 wqe_idx;
- u32 slots;
- u16 idx;
hwq = &sq->hwq;
if (qp->state != CMDQ_MODIFY_QP_NEW_STATE_RTS &&
@@ -1937,8 +1935,10 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
else
data_len = bnxt_qplib_put_sges(hwq, wqe->sg_list, wqe->num_sge,
&idx);
- if (data_len < 0)
- goto queue_err;
+ if (data_len > BNXT_RE_MAX_MSG_SIZE) {
+ rc = -EINVAL;
+ goto done;
+ }
/* Make sure we update MSN table only for wired wqes */
msn_update = true;
/* Specifics */
@@ -2139,8 +2139,8 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp,
struct bnxt_qplib_hwq *hwq;
struct bnxt_qplib_swq *swq;
bool sch_handler = false;
- u16 wqe_sz, idx;
- u32 wqe_idx;
+ u32 wqe_idx, idx;
+ u16 wqe_sz;
int rc = 0;
hwq = &rq->hwq;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
index 0d9487c889ff..ab125f1d949e 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
@@ -346,6 +346,9 @@ struct bnxt_qplib_qp {
u8 tos_dscp;
};
+#define BNXT_RE_MAX_MSG_SIZE 0x80000000
+#define BNXT_RE_INVAL_MSG_SIZE 0xFFFFFFFF
+
#define BNXT_QPLIB_MAX_CQE_ENTRY_SIZE sizeof(struct cq_base)
#define CQE_CNT_PER_PG (PAGE_SIZE / BNXT_QPLIB_MAX_CQE_ENTRY_SIZE)
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,54 @@
From ab6f51d337f71bac3f2fa37ef2508295fcf5323f Mon Sep 17 00:00:00 2001
From: Sreekanth Reddy <sreeredd@redhat.com>
Date: Tue, 12 Aug 2025 16:36:00 -0700
Subject: [PATCH] RDMA/bnxt_re: Use macro instead of hard coded value
JIRA: https://issues.redhat.com/browse/RHEL-108696
JIRA: https://issues.redhat.com/browse/RHEL-96539
commit 7788278ff267f831bab39a377beaa7e08d79c2a9
Author: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Date: Fri Jul 4 10:08:57 2025 +0530
RDMA/bnxt_re: Use macro instead of hard coded value
1. Defined a macro for the hard coded value.
2. "access" field in the request structure is of type "u8".
Updated the mask accordingly.
Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Shravya KN <shravya.k-n@broadcom.com>
Link: https://patch.msgid.link/20250704043857.19158-4-kalesh-anakkur.purayil@broadcom.com
Reviewed-by: Hongguang Gao <hongguang.gao@broadcom.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sreekanth Reddy <sreeredd@redhat.com>
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
index 9efd32a3dc55..68981399598d 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
@@ -674,7 +674,7 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
req.log2_pbl_pg_size = cpu_to_le16(((ilog2(PAGE_SIZE) <<
CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_SFT) &
CMDQ_REGISTER_MR_LOG2_PBL_PG_SIZE_MASK));
- req.access = (mr->access_flags & 0xFFFF);
+ req.access = (mr->access_flags & BNXT_QPLIB_MR_ACCESS_MASK);
req.va = cpu_to_le64(mr->va);
req.key = cpu_to_le32(mr->lkey);
if (_is_alloc_mr_unified(res->dattr->dev_cap_flags))
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.h b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
index e626b05038a1..09faf4a1e849 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
@@ -111,6 +111,7 @@ struct bnxt_qplib_mrw {
struct bnxt_qplib_pd *pd;
int type;
u32 access_flags;
+#define BNXT_QPLIB_MR_ACCESS_MASK 0xFF
#define BNXT_QPLIB_FR_PMR 0x80000000
u32 lkey;
u32 rkey;
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,311 @@
From 8f82b5a5bc35f1760cc957cd20aa8d1b804f0076 Mon Sep 17 00:00:00 2001
From: Sreekanth Reddy <sreeredd@redhat.com>
Date: Tue, 19 Aug 2025 14:28:40 -0700
Subject: [PATCH] RDMA/bnxt_re: Congestion control settings using debugfs hook
JIRA: https://issues.redhat.com/browse/RHEL-108696
JIRA: https://issues.redhat.com/browse/RHEL-96539
commit 656dff55da19eb889f2b1df5a5f2aa1d28f024fd
Author: Selvin Xavier <selvin.xavier@broadcom.com>
Date: Sun Jan 19 07:45:35 2025 -0800
RDMA/bnxt_re: Congestion control settings using debugfs hook
Implements routines to set and get different settings of
the congestion control. This will enable the users to modify
the settings according to their network.
Currently supporting only GEN 0 version of the parameters.
Reading these files queries the firmware and report the values
currently programmed. Writing to the files sends commands that
update the congestion control settings
Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
Link: https://patch.msgid.link/1737301535-6599-1-git-send-email-selvin.xavier@broadcom.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sreekanth Reddy <sreeredd@redhat.com>
diff --git a/drivers/infiniband/hw/bnxt_re/bnxt_re.h b/drivers/infiniband/hw/bnxt_re/bnxt_re.h
index b758705e2062..6df5a2738c95 100644
--- a/drivers/infiniband/hw/bnxt_re/bnxt_re.h
+++ b/drivers/infiniband/hw/bnxt_re/bnxt_re.h
@@ -225,6 +225,8 @@ struct bnxt_re_dev {
unsigned long event_bitmap;
struct bnxt_qplib_cc_param cc_param;
struct workqueue_struct *dcb_wq;
+ struct dentry *cc_config;
+ struct bnxt_re_dbg_cc_config_params *cc_config_params;
};
#define to_bnxt_re_dev(ptr, member) \
diff --git a/drivers/infiniband/hw/bnxt_re/debugfs.c b/drivers/infiniband/hw/bnxt_re/debugfs.c
index 7c47039044ef..f4dd2fb51867 100644
--- a/drivers/infiniband/hw/bnxt_re/debugfs.c
+++ b/drivers/infiniband/hw/bnxt_re/debugfs.c
@@ -22,6 +22,23 @@
static struct dentry *bnxt_re_debugfs_root;
+static const char * const bnxt_re_cc_gen0_name[] = {
+ "enable_cc",
+ "run_avg_weight_g",
+ "num_phase_per_state",
+ "init_cr",
+ "init_tr",
+ "tos_ecn",
+ "tos_dscp",
+ "alt_vlan_pcp",
+ "alt_vlan_dscp",
+ "rtt",
+ "cc_mode",
+ "tcp_cp",
+ "tx_queue",
+ "inactivity_cp",
+};
+
static inline const char *bnxt_re_qp_state_str(u8 state)
{
switch (state) {
@@ -110,19 +127,212 @@ void bnxt_re_debug_rem_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
debugfs_remove(qp->dentry);
}
+static int map_cc_config_offset_gen0_ext0(u32 offset, struct bnxt_qplib_cc_param *ccparam, u32 *val)
+{
+ u64 map_offset;
+
+ map_offset = BIT(offset);
+
+ switch (map_offset) {
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC:
+ *val = ccparam->enable;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_G:
+ *val = ccparam->g;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_NUMPHASEPERSTATE:
+ *val = ccparam->nph_per_state;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_CR:
+ *val = ccparam->init_cr;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_TR:
+ *val = ccparam->init_tr;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN:
+ *val = ccparam->tos_ecn;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP:
+ *val = ccparam->tos_dscp;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP:
+ *val = ccparam->alt_vlan_pcp;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP:
+ *val = ccparam->alt_tos_dscp;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_RTT:
+ *val = ccparam->rtt;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE:
+ *val = ccparam->cc_mode;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TCP_CP:
+ *val = ccparam->tcp_cp;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static ssize_t bnxt_re_cc_config_get(struct file *filp, char __user *buffer,
+ size_t usr_buf_len, loff_t *ppos)
+{
+ struct bnxt_re_cc_param *dbg_cc_param = filp->private_data;
+ struct bnxt_re_dev *rdev = dbg_cc_param->rdev;
+ struct bnxt_qplib_cc_param ccparam = {};
+ u32 offset = dbg_cc_param->offset;
+ char buf[16];
+ u32 val;
+ int rc;
+
+ rc = bnxt_qplib_query_cc_param(&rdev->qplib_res, &ccparam);
+ if (rc)
+ return rc;
+
+ rc = map_cc_config_offset_gen0_ext0(offset, &ccparam, &val);
+ if (rc)
+ return rc;
+
+ rc = snprintf(buf, sizeof(buf), "%d\n", val);
+ if (rc < 0)
+ return rc;
+
+ return simple_read_from_buffer(buffer, usr_buf_len, ppos, (u8 *)(buf), rc);
+}
+
+static void bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offset, u32 val)
+{
+ u32 modify_mask;
+
+ modify_mask = BIT(offset);
+
+ switch (modify_mask) {
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC:
+ ccparam->enable = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_G:
+ ccparam->g = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_NUMPHASEPERSTATE:
+ ccparam->nph_per_state = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_CR:
+ ccparam->init_cr = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_TR:
+ ccparam->init_tr = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN:
+ ccparam->tos_ecn = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP:
+ ccparam->tos_dscp = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP:
+ ccparam->alt_vlan_pcp = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP:
+ ccparam->alt_tos_dscp = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_RTT:
+ ccparam->rtt = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE:
+ ccparam->cc_mode = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TCP_CP:
+ ccparam->tcp_cp = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TX_QUEUE:
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TIME_PER_PHASE:
+ ccparam->time_pph = val;
+ break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_PKTS_PER_PHASE:
+ ccparam->pkts_pph = val;
+ break;
+ }
+
+ ccparam->mask = modify_mask;
+}
+
+static int bnxt_re_configure_cc(struct bnxt_re_dev *rdev, u32 gen_ext, u32 offset, u32 val)
+{
+ struct bnxt_qplib_cc_param ccparam = { };
+
+ /* Supporting only Gen 0 now */
+ if (gen_ext != CC_CONFIG_GEN0_EXT0)
+ bnxt_re_fill_gen0_ext0(&ccparam, offset, val);
+ else
+ return -EINVAL;
+
+ bnxt_qplib_modify_cc(&rdev->qplib_res, &ccparam);
+ return 0;
+}
+
+static ssize_t bnxt_re_cc_config_set(struct file *filp, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct bnxt_re_cc_param *dbg_cc_param = filp->private_data;
+ struct bnxt_re_dev *rdev = dbg_cc_param->rdev;
+ u32 offset = dbg_cc_param->offset;
+ u8 cc_gen = dbg_cc_param->cc_gen;
+ char buf[16];
+ u32 val;
+ int rc;
+
+ if (copy_from_user(buf, buffer, count))
+ return -EFAULT;
+
+ buf[count] = '\0';
+ if (kstrtou32(buf, 0, &val))
+ return -EINVAL;
+
+ rc = bnxt_re_configure_cc(rdev, cc_gen, offset, val);
+ return rc ? rc : count;
+}
+
+static const struct file_operations bnxt_re_cc_config_ops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = bnxt_re_cc_config_get,
+ .write = bnxt_re_cc_config_set,
+};
+
void bnxt_re_debugfs_add_pdev(struct bnxt_re_dev *rdev)
{
struct pci_dev *pdev = rdev->en_dev->pdev;
+ struct bnxt_re_dbg_cc_config_params *cc_params;
+ int i;
rdev->dbg_root = debugfs_create_dir(dev_name(&pdev->dev), bnxt_re_debugfs_root);
rdev->qp_debugfs = debugfs_create_dir("QPs", rdev->dbg_root);
+ rdev->cc_config = debugfs_create_dir("cc_config", rdev->dbg_root);
+
+ rdev->cc_config_params = kzalloc(sizeof(*cc_params), GFP_KERNEL);
+
+ for (i = 0; i < BNXT_RE_CC_PARAM_GEN0; i++) {
+ struct bnxt_re_cc_param *tmp_params = &rdev->cc_config_params->gen0_parms[i];
+
+ tmp_params->rdev = rdev;
+ tmp_params->offset = i;
+ tmp_params->cc_gen = CC_CONFIG_GEN0_EXT0;
+ tmp_params->dentry = debugfs_create_file(bnxt_re_cc_gen0_name[i], 0400,
+ rdev->cc_config, tmp_params,
+ &bnxt_re_cc_config_ops);
+ }
}
void bnxt_re_debugfs_rem_pdev(struct bnxt_re_dev *rdev)
{
debugfs_remove_recursive(rdev->qp_debugfs);
-
+ debugfs_remove_recursive(rdev->cc_config);
+ kfree(rdev->cc_config_params);
debugfs_remove_recursive(rdev->dbg_root);
rdev->dbg_root = NULL;
}
diff --git a/drivers/infiniband/hw/bnxt_re/debugfs.h b/drivers/infiniband/hw/bnxt_re/debugfs.h
index cd3be0a9ec7e..8f101df4e838 100644
--- a/drivers/infiniband/hw/bnxt_re/debugfs.h
+++ b/drivers/infiniband/hw/bnxt_re/debugfs.h
@@ -18,4 +18,19 @@ void bnxt_re_debugfs_rem_pdev(struct bnxt_re_dev *rdev);
void bnxt_re_register_debugfs(void);
void bnxt_re_unregister_debugfs(void);
+#define CC_CONFIG_GEN_EXT(x, y) (((x) << 16) | (y))
+#define CC_CONFIG_GEN0_EXT0 CC_CONFIG_GEN_EXT(0, 0)
+
+#define BNXT_RE_CC_PARAM_GEN0 14
+
+struct bnxt_re_cc_param {
+ struct bnxt_re_dev *rdev;
+ struct dentry *dentry;
+ u32 offset;
+ u8 cc_gen;
+};
+
+struct bnxt_re_dbg_cc_config_params {
+ struct bnxt_re_cc_param gen0_parms[BNXT_RE_CC_PARAM_GEN0];
+};
#endif
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,43 @@
From 62a794efee2f8717d599696c8e1933b675c727e9 Mon Sep 17 00:00:00 2001
From: Sreekanth Reddy <sreeredd@redhat.com>
Date: Tue, 19 Aug 2025 14:30:09 -0700
Subject: [PATCH] RDMA/bnxt_re: Fix buffer overflow in debugfs code
JIRA: https://issues.redhat.com/browse/RHEL-108696
JIRA: https://issues.redhat.com/browse/RHEL-96539
commit dbc641ecf1cbd41a649e7ac6ea7175562ef599b2
Author: Dan Carpenter <dan.carpenter@linaro.org>
Date: Fri Feb 7 12:16:19 2025 +0300
RDMA/bnxt_re: Fix buffer overflow in debugfs code
Add some bounds checking to prevent memory corruption in
bnxt_re_cc_config_set(). This is debugfs code so the bug can only be
triggered by root.
Fixes: 656dff55da19 ("RDMA/bnxt_re: Congestion control settings using debugfs hook")
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
Link: https://patch.msgid.link/a6b081ab-55fe-4d0c-8f69-c5e5a59e9141@stanley.mountain
Acked-by: Selvin Xavier <selvin.xavier@broadcom.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sreekanth Reddy <sreeredd@redhat.com>
diff --git a/drivers/infiniband/hw/bnxt_re/debugfs.c b/drivers/infiniband/hw/bnxt_re/debugfs.c
index f4dd2fb51867..d7354e7753fe 100644
--- a/drivers/infiniband/hw/bnxt_re/debugfs.c
+++ b/drivers/infiniband/hw/bnxt_re/debugfs.c
@@ -285,6 +285,9 @@ static ssize_t bnxt_re_cc_config_set(struct file *filp, const char __user *buffe
u32 val;
int rc;
+ if (count >= sizeof(buf))
+ return -EINVAL;
+
if (copy_from_user(buf, buffer, count))
return -EFAULT;
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,43 @@
From 01d9de21a2cdbcaf02378da7cb143a2c5b84547a Mon Sep 17 00:00:00 2001
From: Sreekanth Reddy <sreeredd@redhat.com>
Date: Tue, 19 Aug 2025 14:31:21 -0700
Subject: [PATCH] RDMA/bnxt_re: Fix the condition check while programming
congestion control
JIRA: https://issues.redhat.com/browse/RHEL-108696
JIRA: https://issues.redhat.com/browse/RHEL-96539
commit f26e648a978ae7958e0958095768363c851a736d
Author: Selvin Xavier <selvin.xavier@broadcom.com>
Date: Sat Feb 8 05:48:26 2025 -0800
RDMA/bnxt_re: Fix the condition check while programming congestion control
Program the Congestion control values when the CC gen matches.
Fix the condition check for the same.
Fixes: 656dff55da19 ("RDMA/bnxt_re: Congestion control settings using debugfs hook")
Reported-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Reported-by: Chengchang Tang <tangchengchang@huawei.com>
Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
Link: https://patch.msgid.link/1739022506-8937-1-git-send-email-selvin.xavier@broadcom.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sreekanth Reddy <sreeredd@redhat.com>
diff --git a/drivers/infiniband/hw/bnxt_re/debugfs.c b/drivers/infiniband/hw/bnxt_re/debugfs.c
index d7354e7753fe..af91d16c3c77 100644
--- a/drivers/infiniband/hw/bnxt_re/debugfs.c
+++ b/drivers/infiniband/hw/bnxt_re/debugfs.c
@@ -265,7 +265,7 @@ static int bnxt_re_configure_cc(struct bnxt_re_dev *rdev, u32 gen_ext, u32 offse
struct bnxt_qplib_cc_param ccparam = { };
/* Supporting only Gen 0 now */
- if (gen_ext != CC_CONFIG_GEN0_EXT0)
+ if (gen_ext == CC_CONFIG_GEN0_EXT0)
bnxt_re_fill_gen0_ext0(&ccparam, offset, val);
else
return -EINVAL;
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,57 @@
From 1938524b38203de2db0bbd8ffffbc96bf23a5e9b Mon Sep 17 00:00:00 2001
From: Sreekanth Reddy <sreeredd@redhat.com>
Date: Tue, 19 Aug 2025 14:32:40 -0700
Subject: [PATCH] RDMA/bnxt_re: Fix incorrect display of inactivity_cp in
debugfs output
JIRA: https://issues.redhat.com/browse/RHEL-108696
JIRA: https://issues.redhat.com/browse/RHEL-96539
commit 58d7a965bb2b014d467445d38cdb07099b1f0f77
Author: Gautam R A <gautam-r.a@broadcom.com>
Date: Tue May 20 09:29:07 2025 +0530
RDMA/bnxt_re: Fix incorrect display of inactivity_cp in debugfs output
The inactivity_cp parameter in debugfs was not being read or
written correctly, resulting in "Invalid argument" errors.
Fixed this by ensuring proper mapping of inactivity_cp in
both the map_cc_config_offset_gen0_ext0 and
bnxt_re_fill_gen0_ext0() functions.
Fixes: 656dff55da19 ("RDMA/bnxt_re: Congestion control settings using debugfs hook")
Signed-off-by: Gautam R A <gautam-r.a@broadcom.com>
Link: https://patch.msgid.link/20250520035910.1061918-2-kalesh-anakkur.purayil@broadcom.com
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sreekanth Reddy <sreeredd@redhat.com>
diff --git a/drivers/infiniband/hw/bnxt_re/debugfs.c b/drivers/infiniband/hw/bnxt_re/debugfs.c
index af91d16c3c77..a3aad6c3dbec 100644
--- a/drivers/infiniband/hw/bnxt_re/debugfs.c
+++ b/drivers/infiniband/hw/bnxt_re/debugfs.c
@@ -170,6 +170,9 @@ static int map_cc_config_offset_gen0_ext0(u32 offset, struct bnxt_qplib_cc_param
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TCP_CP:
*val = ccparam->tcp_cp;
break;
+ case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
+ *val = ccparam->inact_th;
+ break;
default:
return -EINVAL;
}
@@ -247,7 +250,9 @@ static void bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offs
ccparam->tcp_cp = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TX_QUEUE:
+ break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
+ ccparam->inact_th = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TIME_PER_PHASE:
ccparam->time_pph = val;
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,80 @@
From bc635dde20a74550cf70a2e7f5b25ce3f07db3ed Mon Sep 17 00:00:00 2001
From: Sreekanth Reddy <sreeredd@redhat.com>
Date: Tue, 19 Aug 2025 14:32:52 -0700
Subject: [PATCH] RDMA/bnxt_re: Fix missing error handling for tx_queue
JIRA: https://issues.redhat.com/browse/RHEL-108696
JIRA: https://issues.redhat.com/browse/RHEL-96539
commit e3d57a00d4d1f36689e9eab80b60d5024361efec
Author: Gautam R A <gautam-r.a@broadcom.com>
Date: Tue May 20 09:29:08 2025 +0530
RDMA/bnxt_re: Fix missing error handling for tx_queue
bnxt_re_fill_gen0_ext0() did not return an error when
attempting to modify CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TX_QUEUE,
leading to silent failures.
Fixed this by returning -EOPNOTSUPP for tx_queue modifications and
ensuring proper error propagation in bnxt_re_configure_cc().
Fixes: 656dff55da19 ("RDMA/bnxt_re: Congestion control settings using debugfs hook")
Signed-off-by: Gautam R A <gautam-r.a@broadcom.com>
Link: https://patch.msgid.link/20250520035910.1061918-3-kalesh-anakkur.purayil@broadcom.com
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sreekanth Reddy <sreeredd@redhat.com>
diff --git a/drivers/infiniband/hw/bnxt_re/debugfs.c b/drivers/infiniband/hw/bnxt_re/debugfs.c
index a3aad6c3dbec..9f6392155d91 100644
--- a/drivers/infiniband/hw/bnxt_re/debugfs.c
+++ b/drivers/infiniband/hw/bnxt_re/debugfs.c
@@ -206,7 +206,7 @@ static ssize_t bnxt_re_cc_config_get(struct file *filp, char __user *buffer,
return simple_read_from_buffer(buffer, usr_buf_len, ppos, (u8 *)(buf), rc);
}
-static void bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offset, u32 val)
+static int bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offset, u32 val)
{
u32 modify_mask;
@@ -250,7 +250,7 @@ static void bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offs
ccparam->tcp_cp = val;
break;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TX_QUEUE:
- break;
+ return -EOPNOTSUPP;
case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
ccparam->inact_th = val;
break;
@@ -263,18 +263,21 @@ static void bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offs
}
ccparam->mask = modify_mask;
+ return 0;
}
static int bnxt_re_configure_cc(struct bnxt_re_dev *rdev, u32 gen_ext, u32 offset, u32 val)
{
struct bnxt_qplib_cc_param ccparam = { };
+ int rc;
- /* Supporting only Gen 0 now */
- if (gen_ext == CC_CONFIG_GEN0_EXT0)
- bnxt_re_fill_gen0_ext0(&ccparam, offset, val);
- else
+ if (gen_ext != CC_CONFIG_GEN0_EXT0)
return -EINVAL;
+ rc = bnxt_re_fill_gen0_ext0(&ccparam, offset, val);
+ if (rc)
+ return rc;
+
bnxt_qplib_modify_cc(&rdev->qplib_res, &ccparam);
return 0;
}
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,43 @@
From a646adda44acd8b4eca1b95ed00609a27bbd390c Mon Sep 17 00:00:00 2001
From: Sreekanth Reddy <sreeredd@redhat.com>
Date: Tue, 19 Aug 2025 14:32:59 -0700
Subject: [PATCH] RDMA/bnxt_re: Fix return code of bnxt_re_configure_cc
JIRA: https://issues.redhat.com/browse/RHEL-108696
JIRA: https://issues.redhat.com/browse/RHEL-96539
commit 990b5c07f677a0b633b41130a70771337c18343e
Author: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Date: Tue May 20 09:29:09 2025 +0530
RDMA/bnxt_re: Fix return code of bnxt_re_configure_cc
Driver currently supports modifying GEN0_EXT0 CC parameters
through debugfs hook.
Fixed to return -EOPNOTSUPP instead of -EINVAL in bnxt_re_configure_cc()
when the user tries to modify any other CC parameters.
Fixes: 656dff55da19 ("RDMA/bnxt_re: Congestion control settings using debugfs hook")
Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Link: https://patch.msgid.link/20250520035910.1061918-4-kalesh-anakkur.purayil@broadcom.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sreekanth Reddy <sreeredd@redhat.com>
diff --git a/drivers/infiniband/hw/bnxt_re/debugfs.c b/drivers/infiniband/hw/bnxt_re/debugfs.c
index 9f6392155d91..e632f1661b92 100644
--- a/drivers/infiniband/hw/bnxt_re/debugfs.c
+++ b/drivers/infiniband/hw/bnxt_re/debugfs.c
@@ -272,7 +272,7 @@ static int bnxt_re_configure_cc(struct bnxt_re_dev *rdev, u32 gen_ext, u32 offse
int rc;
if (gen_ext != CC_CONFIG_GEN0_EXT0)
- return -EINVAL;
+ return -EOPNOTSUPP;
rc = bnxt_re_fill_gen0_ext0(&ccparam, offset, val);
if (rc)
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,94 @@
From 489b805b61b98f02178efdbe33f9d3f11f039fd0 Mon Sep 17 00:00:00 2001
From: Sreekanth Reddy <sreeredd@redhat.com>
Date: Tue, 19 Aug 2025 14:33:06 -0700
Subject: [PATCH] RDMA/bnxt_re: convert timeouts to secs_to_jiffies()
JIRA: https://issues.redhat.com/browse/RHEL-108696
JIRA: https://issues.redhat.com/browse/RHEL-96539
commit f873136416293b786e7611d36226c9f5a8f6d20b
Author: Easwar Hariharan <eahariha@linux.microsoft.com>
Date: Tue Feb 25 20:17:30 2025 +0000
RDMA/bnxt_re: convert timeouts to secs_to_jiffies()
Commit b35108a51cf7 ("jiffies: Define secs_to_jiffies()") introduced
secs_to_jiffies(). As the value here is a multiple of 1000, use
secs_to_jiffies() instead of msecs_to_jiffies() to avoid the
multiplication
This is converted using scripts/coccinelle/misc/secs_to_jiffies.cocci with
the following Coccinelle rules:
@depends on patch@
expression E;
@@
-msecs_to_jiffies
+secs_to_jiffies
(E
- * \( 1000 \| MSEC_PER_SEC \)
)
Link: https://lkml.kernel.org/r/20250225-converge-secs-to-jiffies-part-two-v3-16-a43967e36c88@linux.microsoft.com
Signed-off-by: Easwar Hariharan <eahariha@linux.microsoft.com>
Cc: Carlos Maiolino <cem@kernel.org>
Cc: Carlos Maiolino <cmaiolino@redhat.com>
Cc: Chris Mason <clm@fb.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Damien Le Maol <dlemoal@kernel.org>
Cc: "Darrick J. Wong" <djwong@kernel.org>
Cc: David Sterba <dsterba@suse.com>
Cc: Dick Kennedy <dick.kennedy@broadcom.com>
Cc: Dongsheng Yang <dongsheng.yang@easystack.cn>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: Frank Li <frank.li@nxp.com>
Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Cc: Ilpo Jarvinen <ilpo.jarvinen@linux.intel.com>
Cc: Ilya Dryomov <idryomov@gmail.com>
Cc: James Bottomley <james.bottomley@HansenPartnership.com>
Cc: James Smart <james.smart@broadcom.com>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Josef Bacik <josef@toxicpanda.com>
Cc: Julia Lawall <julia.lawall@inria.fr>
Cc: Kalesh Anakkur Purayil <kalesh-anakkur.purayil@broadcom.com>
Cc: Keith Busch <kbusch@kernel.org>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
Cc: Mark Brown <broonie@kernel.org>
Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
Cc: Nicolas Palix <nicolas.palix@imag.fr>
Cc: Niklas Cassel <cassel@kernel.org>
Cc: Oded Gabbay <ogabbay@kernel.org>
Cc: Sagi Grimberg <sagi@grimberg.me>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Sebastian Reichel <sre@kernel.org>
Cc: Selvin Thyparampil Xavier <selvin.xavier@broadcom.com>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Shyam-sundar S-k <Shyam-sundar.S-k@amd.com>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Takashi Iwai <tiwai@suse.de>
Cc: Xiubo Li <xiubli@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Sreekanth Reddy <sreeredd@redhat.com>
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
index d23074383428..804bc773b4ef 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
@@ -160,7 +160,7 @@ static int __wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
wait_event_timeout(cmdq->waitq,
!crsqe->is_in_used ||
test_bit(ERR_DEVICE_DETACHED, &cmdq->flags),
- msecs_to_jiffies(rcfw->max_timeout * 1000));
+ secs_to_jiffies(rcfw->max_timeout));
if (!crsqe->is_in_used)
return 0;
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,60 @@
From cbcb3cfcdc436d6f91a3d95ecfa9c831abe14aed Mon Sep 17 00:00:00 2001
From: Mohammad Heib <mheib@redhat.com>
Date: Tue, 17 Mar 2026 19:08:06 +0200
Subject: [PATCH] ionic: fix persistent MAC address override on PF
The use of IONIC_CMD_LIF_SETATTR in the MAC address update path causes
the ionic firmware to update the LIF's identity in its persistent state.
Since the firmware state is maintained across host warm boots and driver
reloads, any MAC change on the Physical Function (PF) becomes "sticky.
This is problematic because it causes ethtool -P to report the
user-configured MAC as the permanent factory address, which breaks
system management tools that rely on a stable hardware identity.
While Virtual Functions (VFs) need this hardware-level programming to
properly handle MAC assignments in guest environments, the PF should
maintain standard transient behavior. This patch gates the
ionic_program_mac call using is_virtfn so that PF MAC changes remain
local to the netdev filters and do not overwrite the firmware's
permanent identity block.
Fixes: 19058be7c48c ("ionic: VF initial random MAC address if no assigned mac")
Signed-off-by: Mohammad Heib <mheib@redhat.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Brett Creeley <brett.creeley@amd.com>
Link: https://patch.msgid.link/20260317170806.35390-1-mheib@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 8d040e611d5a..637e635bbf03 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -1719,13 +1719,18 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa)
if (ether_addr_equal(netdev->dev_addr, mac))
return 0;
- err = ionic_program_mac(lif, mac);
- if (err < 0)
- return err;
+ /* Only program macs for virtual functions to avoid losing the permanent
+ * Mac across warm reset/reboot.
+ */
+ if (lif->ionic->pdev->is_virtfn) {
+ err = ionic_program_mac(lif, mac);
+ if (err < 0)
+ return err;
- if (err > 0)
- netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n",
- __func__);
+ if (err > 0)
+ netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n",
+ __func__);
+ }
err = eth_prepare_mac_addr_change(netdev, addr);
if (err)
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,74 @@
From def2d2719295c70f747e7bd1cb56fc51992c6977 Mon Sep 17 00:00:00 2001
From: Paulo Alcantara <paalcant@redhat.com>
Date: Mon, 23 Mar 2026 19:10:59 -0300
Subject: [PATCH] smb: client: fix krb5 mount with username option
JIRA: https://issues.redhat.com/browse/RHEL-156455
commit 12b4c5d98cd7ca46d5035a57bcd995df614c14e1
Author: Paulo Alcantara <pc@manguebit.org>
Date: Fri Mar 13 00:03:38 2026 -0300
smb: client: fix krb5 mount with username option
Customer reported that some of their krb5 mounts were failing against
a single server as the client was trying to mount the shares with
wrong credentials. It turned out the client was reusing SMB session
from first mount to try mounting the other shares, even though a
different username= option had been specified to the other mounts.
By using username mount option along with sec=krb5 to search for
principals from keytab is supported by cifs.upcall(8) since
cifs-utils-4.8. So fix this by matching username mount option in
match_session() even with Kerberos.
For example, the second mount below should fail with -ENOKEY as there
is no 'foobar' principal in keytab (/etc/krb5.keytab). The client
ends up reusing SMB session from first mount to perform the second
one, which is wrong.
```
$ ktutil
ktutil: add_entry -password -p testuser -k 1 -e aes256-cts
Password for testuser@ZELDA.TEST:
ktutil: write_kt /etc/krb5.keytab
ktutil: quit
$ klist -ke
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- ----------------------------------------------------------------
1 testuser@ZELDA.TEST (aes256-cts-hmac-sha1-96)
$ mount.cifs //w22-root2/scratch /mnt/1 -o sec=krb5,username=testuser
$ mount.cifs //w22-root2/scratch /mnt/2 -o sec=krb5,username=foobar
$ mount -t cifs | grep -Po 'username=\K\w+'
testuser
testuser
```
Reported-by: Oscar Santos <ossantos@redhat.com>
Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
Cc: David Howells <dhowells@redhat.com>
Cc: linux-cifs@vger.kernel.org
Cc: stable@vger.kernel.org
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Paulo Alcantara <paalcant@redhat.com>
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index 3e06f59ba8ad..0c2dea25572d 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -1954,6 +1954,10 @@ static int match_session(struct cifs_ses *ses,
case Kerberos:
if (!uid_eq(ctx->cred_uid, ses->cred_uid))
return 0;
+ if (strncmp(ses->user_name ?: "",
+ ctx->username ?: "",
+ CIFS_MAX_USERNAME_LEN))
+ return 0;
break;
case NTLMv2:
case RawNTLMSSP:
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,54 @@
From b05914e695853c3784f3fd1b588cabc025cf4337 Mon Sep 17 00:00:00 2001
From: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
Date: Thu, 26 Mar 2026 20:21:27 +0000
Subject: [PATCH] scsi: qla2xxx: Fix improper freeing of purex item
JIRA: https://redhat.atlassian.net/browse/RHEL-161149
CVE: CVE-2025-68741
commit 78b1a242fe612a755f2158fd206ee6bb577d18ca
Author: Zilin Guan <zilin@seu.edu.cn>
Date: Thu Nov 13 15:12:46 2025 +0000
scsi: qla2xxx: Fix improper freeing of purex item
In qla2xxx_process_purls_iocb(), an item is allocated via
qla27xx_copy_multiple_pkt(), which internally calls
qla24xx_alloc_purex_item().
The qla24xx_alloc_purex_item() function may return a pre-allocated item
from a per-adapter pool for small allocations, instead of dynamically
allocating memory with kzalloc().
An error handling path in qla2xxx_process_purls_iocb() incorrectly uses
kfree() to release the item. If the item was from the pre-allocated
pool, calling kfree() on it is a bug that can lead to memory corruption.
Fix this by using the correct deallocation function,
qla24xx_free_purex_item(), which properly handles both dynamically
allocated and pre-allocated items.
Fixes: 875386b98857 ("scsi: qla2xxx: Add Unsolicited LS Request and Response Support for NVMe")
Signed-off-by: Zilin Guan <zilin@seu.edu.cn>
Reviewed-by: Himanshu Madhani <hmadhani2024@gmail.com>
Link: https://patch.msgid.link/20251113151246.762510-1-zilin@seu.edu.cn
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index 8ee2e337c9e1..6ecf3da765aa 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -1292,7 +1292,7 @@ void qla2xxx_process_purls_iocb(void **pkt, struct rsp_que **rsp)
a.reason = FCNVME_RJT_RC_LOGIC;
a.explanation = FCNVME_RJT_EXP_NONE;
xmt_reject = true;
- kfree(item);
+ qla24xx_free_purex_item(item);
goto out;
}
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,90 @@
From 5133b61aaf437e5f25b1b396b14242a6bb0508e2 Mon Sep 17 00:00:00 2001
From: Jeff Layton <jlayton@kernel.org>
Date: Tue, 24 Feb 2026 11:33:35 -0500
Subject: [PATCH] nfsd: fix heap overflow in NFSv4.0 LOCK replay cache
The NFSv4.0 replay cache uses a fixed 112-byte inline buffer
(rp_ibuf[NFSD4_REPLAY_ISIZE]) to store encoded operation responses.
This size was calculated based on OPEN responses and does not account
for LOCK denied responses, which include the conflicting lock owner as
a variable-length field up to 1024 bytes (NFS4_OPAQUE_LIMIT).
When a LOCK operation is denied due to a conflict with an existing lock
that has a large owner, nfsd4_encode_operation() copies the full encoded
response into the undersized replay buffer via read_bytes_from_xdr_buf()
with no bounds check. This results in a slab-out-of-bounds write of up
to 944 bytes past the end of the buffer, corrupting adjacent heap memory.
This can be triggered remotely by an unauthenticated attacker with two
cooperating NFSv4.0 clients: one sets a lock with a large owner string,
then the other requests a conflicting lock to provoke the denial.
We could fix this by increasing NFSD4_REPLAY_ISIZE to allow for a full
opaque, but that would increase the size of every stateowner, when most
lockowners are not that large.
Instead, fix this by checking the encoded response length against
NFSD4_REPLAY_ISIZE before copying into the replay buffer. If the
response is too large, set rp_buflen to 0 to skip caching the replay
payload. The status is still cached, and the client already received the
correct response on the original request.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@kernel.org
Reported-by: Nicholas Carlini <npc@anthropic.com>
Tested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 5172dbd0cb05..fa16b34fae50 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -6281,9 +6281,14 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
int len = xdr->buf->len - (op_status_offset + XDR_UNIT);
so->so_replay.rp_status = op->status;
- so->so_replay.rp_buflen = len;
- read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT,
+ if (len <= NFSD4_REPLAY_ISIZE) {
+ so->so_replay.rp_buflen = len;
+ read_bytes_from_xdr_buf(xdr->buf,
+ op_status_offset + XDR_UNIT,
so->so_replay.rp_buf, len);
+ } else {
+ so->so_replay.rp_buflen = 0;
+ }
}
status:
op->status = nfsd4_map_status(op->status,
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 6fcbf1e427d4..c0ca115c3b74 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -541,11 +541,18 @@ struct nfs4_client_reclaim {
struct xdr_netobj cr_princhash;
};
-/* A reasonable value for REPLAY_ISIZE was estimated as follows:
- * The OPEN response, typically the largest, requires
- * 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) + 8(verifier) +
- * 4(deleg. type) + 8(deleg. stateid) + 4(deleg. recall flag) +
- * 20(deleg. space limit) + ~32(deleg. ace) = 112 bytes
+/*
+ * REPLAY_ISIZE is sized for an OPEN response with delegation:
+ * 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) +
+ * 8(verifier) + 4(deleg. type) + 8(deleg. stateid) +
+ * 4(deleg. recall flag) + 20(deleg. space limit) +
+ * ~32(deleg. ace) = 112 bytes
+ *
+ * Some responses can exceed this. A LOCK denial includes the conflicting
+ * lock owner, which can be up to 1024 bytes (NFS4_OPAQUE_LIMIT). Responses
+ * larger than REPLAY_ISIZE are not cached in rp_ibuf; only rp_status is
+ * saved. Enlarging this constant increases the size of every
+ * nfs4_stateowner.
*/
#define NFSD4_REPLAY_ISIZE 112
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,39 @@
From 13e00fdc9236bd4d0bff4109d2983171fbcb74c4 Mon Sep 17 00:00:00 2001
From: Eric Dumazet <edumazet@google.com>
Date: Wed, 28 Jan 2026 14:15:38 +0000
Subject: [PATCH] net: add skb_header_pointer_careful() helper
This variant of skb_header_pointer() should be used in contexts
where @offset argument is user-controlled and could be negative.
Negative offsets are supported, as long as the zone starts
between skb->head and skb->data.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260128141539.3404400-2-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 3f4decc..574edae 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -4043,6 +4043,18 @@ skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer)
skb_headlen(skb), buffer);
}
+/* Variant of skb_header_pointer() where @offset is user-controlled
+ * and potentially negative.
+ */
+static inline void * __must_check
+skb_header_pointer_careful(const struct sk_buff *skb, int offset,
+ int len, void *buffer)
+{
+ if (unlikely(offset < 0 && -offset > skb_headroom(skb)))
+ return NULL;
+ return skb_header_pointer(skb, offset, len, buffer);
+}
+
/**
* skb_needs_linearize - check if we need to linearize a given skb
* depending on the given device features.

View File

@ -0,0 +1,62 @@
From cabd1a976375780dabab888784e356f574bbaed8 Mon Sep 17 00:00:00 2001
From: Eric Dumazet <edumazet@google.com>
Date: Wed, 28 Jan 2026 14:15:39 +0000
Subject: [PATCH] net/sched: cls_u32: use skb_header_pointer_careful()
skb_header_pointer() does not fully validate negative @offset values.
Use skb_header_pointer_careful() instead.
GangMin Kim provided a report and a repro fooling u32_classify():
BUG: KASAN: slab-out-of-bounds in u32_classify+0x1180/0x11b0
net/sched/cls_u32.c:221
Fixes: fbc2e7d9cf49 ("cls_u32: use skb_header_pointer() to dereference data safely")
Reported-by: GangMin Kim <km.kim1503@gmail.com>
Closes: https://lore.kernel.org/netdev/CANn89iJkyUZ=mAzLzC4GdcAgLuPnUoivdLaOs6B9rq5_erj76w@mail.gmail.com/T/
Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260128141539.3404400-3-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 2a1c00048fd6..58e849c0acf4 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -161,10 +161,8 @@ TC_INDIRECT_SCOPE int u32_classify(struct sk_buff *skb,
int toff = off + key->off + (off2 & key->offmask);
__be32 *data, hdata;
- if (skb_headroom(skb) + toff > INT_MAX)
- goto out;
-
- data = skb_header_pointer(skb, toff, 4, &hdata);
+ data = skb_header_pointer_careful(skb, toff, 4,
+ &hdata);
if (!data)
goto out;
if ((*data ^ key->val) & key->mask) {
@@ -214,8 +212,9 @@ TC_INDIRECT_SCOPE int u32_classify(struct sk_buff *skb,
if (ht->divisor) {
__be32 *data, hdata;
- data = skb_header_pointer(skb, off + n->sel.hoff, 4,
- &hdata);
+ data = skb_header_pointer_careful(skb,
+ off + n->sel.hoff,
+ 4, &hdata);
if (!data)
goto out;
sel = ht->divisor & u32_hash_fold(*data, &n->sel,
@@ -229,7 +228,7 @@ TC_INDIRECT_SCOPE int u32_classify(struct sk_buff *skb,
if (n->sel.flags & TC_U32_VAROFFSET) {
__be16 *data, hdata;
- data = skb_header_pointer(skb,
+ data = skb_header_pointer_careful(skb,
off + n->sel.offoff,
2, &hdata);
if (!data)
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,89 @@
From 11cb63b0d1a0685e0831ae3c77223e002ef18189 Mon Sep 17 00:00:00 2001
From: Victor Nogueira <victor@mojatatu.com>
Date: Wed, 25 Feb 2026 10:43:48 -0300
Subject: [PATCH] net/sched: Only allow act_ct to bind to clsact/ingress qdiscs
and shared blocks
As Paolo said earlier [1]:
"Since the blamed commit below, classify can return TC_ACT_CONSUMED while
the current skb being held by the defragmentation engine. As reported by
GangMin Kim, if such packet is that may cause a UaF when the defrag engine
later on tries to tuch again such packet."
act_ct was never meant to be used in the egress path, however some users
are attaching it to egress today [2]. Attempting to reach a middle
ground, we noticed that, while most qdiscs are not handling
TC_ACT_CONSUMED, clsact/ingress qdiscs are. With that in mind, we
address the issue by only allowing act_ct to bind to clsact/ingress
qdiscs and shared blocks. That way it's still possible to attach act_ct to
egress (albeit only with clsact).
[1] https://lore.kernel.org/netdev/674b8cbfc385c6f37fb29a1de08d8fe5c2b0fbee.1771321118.git.pabeni@redhat.com/
[2] https://lore.kernel.org/netdev/cc6bfb4a-4a2b-42d8-b9ce-7ef6644fb22b@ovn.org/
Reported-by: GangMin Kim <km.kim1503@gmail.com>
Fixes: 3f14b377d01d ("net/sched: act_ct: fix skb leak and crash on ooo frags")
CC: stable@vger.kernel.org
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/20260225134349.1287037-1-victor@mojatatu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/include/net/act_api.h b/include/net/act_api.h
index e1e8f0f7dacb..d11b79107930 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -70,6 +70,7 @@ struct tc_action {
#define TCA_ACT_FLAGS_REPLACE (1U << (TCA_ACT_FLAGS_USER_BITS + 2))
#define TCA_ACT_FLAGS_NO_RTNL (1U << (TCA_ACT_FLAGS_USER_BITS + 3))
#define TCA_ACT_FLAGS_AT_INGRESS (1U << (TCA_ACT_FLAGS_USER_BITS + 4))
+#define TCA_ACT_FLAGS_AT_INGRESS_OR_CLSACT (1U << (TCA_ACT_FLAGS_USER_BITS + 5))
/* Update lastuse only if needed, to avoid dirtying a cache line.
* We use a temp variable to avoid fetching jiffies twice.
diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
index bd51522c7953..7d5e50c921a0 100644
--- a/net/sched/act_ct.c
+++ b/net/sched/act_ct.c
@@ -1360,6 +1360,12 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
return -EINVAL;
}
+ if (bind && !(flags & TCA_ACT_FLAGS_AT_INGRESS_OR_CLSACT)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Attaching ct to a non ingress/clsact qdisc is unsupported");
+ return -EOPNOTSUPP;
+ }
+
err = nla_parse_nested(tb, TCA_CT_MAX, nla, ct_policy, extack);
if (err < 0)
return err;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 343309e9009b..4829c27446e3 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -2228,6 +2228,11 @@ static bool is_qdisc_ingress(__u32 classid)
return (TC_H_MIN(classid) == TC_H_MIN(TC_H_MIN_INGRESS));
}
+static bool is_ingress_or_clsact(struct tcf_block *block, struct Qdisc *q)
+{
+ return tcf_block_shared(block) || (q && !!(q->flags & TCQ_F_INGRESS));
+}
+
static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
struct netlink_ext_ack *extack)
{
@@ -2420,6 +2425,8 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
flags |= TCA_ACT_FLAGS_NO_RTNL;
if (is_qdisc_ingress(parent))
flags |= TCA_ACT_FLAGS_AT_INGRESS;
+ if (is_ingress_or_clsact(block, q))
+ flags |= TCA_ACT_FLAGS_AT_INGRESS_OR_CLSACT;
err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
flags, extack);
if (err == 0) {
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,51 @@
From 65b8cbd50f25d2dab7050a51dd9cbd4122c29113 Mon Sep 17 00:00:00 2001
From: Jan Stancek <jstancek@redhat.com>
Date: Mon, 9 Mar 2026 08:52:45 +0100
Subject: [PATCH] x86/boot: Handle relative CONFIG_EFI_SBAT_FILE file paths
JIRA: https://issues.redhat.com/browse/RHEL-150459
Upstream Status: linux.git
Conflicts: minor context difference, rhel9 strips quotes from config value
commit 3d1973a0c76a78a4728cff13648a188ed486cf44
Author: Jan Stancek <jstancek@redhat.com>
Date: Wed Feb 25 20:30:23 2026 +0100
x86/boot: Handle relative CONFIG_EFI_SBAT_FILE file paths
CONFIG_EFI_SBAT_FILE can be a relative path. When compiling using a different
output directory (O=) the build currently fails because it can't find the
filename set in CONFIG_EFI_SBAT_FILE:
arch/x86/boot/compressed/sbat.S: Assembler messages:
arch/x86/boot/compressed/sbat.S:6: Error: file not found: kernel.sbat
Add $(srctree) as include dir for sbat.o.
[ bp: Massage commit message. ]
Fixes: 61b57d35396a ("x86/efi: Implement support for embedding SBAT data for x86")
Signed-off-by: Jan Stancek <jstancek@redhat.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Cc: <stable@kernel.org>
Link: https://patch.msgid.link/f4eda155b0cef91d4d316b4e92f5771cb0aa7187.1772047658.git.jstancek@redhat.com
Signed-off-by: Jan Stancek <jstancek@redhat.com>
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index b294f0a7ac32..77e3bd5d39af 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -122,6 +122,7 @@ vmlinux-objs-$(CONFIG_EFI_SBAT) += $(obj)/sbat.o
ifdef CONFIG_EFI_SBAT
# Strip quotes
$(obj)/sbat.o: $(strip $(subst ",,$(CONFIG_EFI_SBAT_FILE)))
+AFLAGS_sbat.o += -I $(srctree)
endif
$(obj)/vmlinux: $(vmlinux-objs-y) FORCE
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,81 @@
From c88e70dc8bfca9a2be74a100387b1b66de973128 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@intel.com>
Date: Wed, 15 Oct 2025 19:19:28 +0300
Subject: [PATCH] drm/i915/dsc: Add helper to enable the DSC configuration for
a CRTC
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add a helper to enable the DSC compression configuration for a CRTC.
Follow-up changes will introduce tracking for the same DSC state on the
whole link, which will need to be set whenever DSC is enabled for the
CRTC. Also, according to the above, when querying the DSC state on the
link, both the CRTC's and the link's DSC state must be considered.
Setting the DSC configuration for a CRTC and querying the DSC
configuration for the link (added by follow-up changes) is better done
via helper functions based on the above, prepare for that here.
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Jouni Högander <jouni.hogander@intel.com>
Link: https://lore.kernel.org/r/20251015161934.262108-2-imre.deak@intel.com
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index 37faa8f19f6e..297368ff42a5 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -1655,7 +1655,7 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
if (ret)
return ret;
- crtc_state->dsc.compression_enable = true;
+ intel_dsc_enable_on_crtc(crtc_state);
return 0;
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 7059d55687cf..fc1949e0c4de 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2475,7 +2475,8 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
return ret;
}
- pipe_config->dsc.compression_enable = true;
+ intel_dsc_enable_on_crtc(pipe_config);
+
drm_dbg_kms(display->drm, "DP DSC computed with Input Bpp = %d "
"Compressed Bpp = " FXP_Q4_FMT " Slice Count = %d\n",
pipe_config->pipe_bpp,
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index bca747e24a7f..803f3b395c79 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -372,6 +372,11 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
return 0;
}
+void intel_dsc_enable_on_crtc(struct intel_crtc_state *crtc_state)
+{
+ crtc_state->dsc.compression_enable = true;
+}
+
enum intel_display_power_domain
intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
{
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h
index 2139391ff881..8c7c7fb652c3 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.h
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.h
@@ -20,6 +20,7 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state)
void intel_dsc_enable(const struct intel_crtc_state *crtc_state);
void intel_dsc_disable(const struct intel_crtc_state *crtc_state);
int intel_dsc_compute_params(struct intel_crtc_state *pipe_config);
+void intel_dsc_enable_on_crtc(struct intel_crtc_state *crtc_state);
void intel_dsc_get_config(struct intel_crtc_state *crtc_state);
enum intel_display_power_domain
intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder);
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,90 @@
From 69df31263bcabc527a5b526fb8972cb080a179b3 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@intel.com>
Date: Wed, 15 Oct 2025 19:19:29 +0300
Subject: [PATCH] drm/i915/dp: Ensure the FEC state stays disabled for UHBR
links
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Atm, in the DP SST case the FEC state is computed before
intel_crtc_state::port_clock is initialized, hence intel_dp_is_uhbr()
will always return false and the FEC state will be always computed
assuming a non-UHBR link.
This happens to work, since the FEC state is recomputed later in
intel_dp_mtp_tu_compute_config(), where port_clock will be set already,
so intel_crtc_state::fec_enable will be reset as expected for UHBR. This
also depends on link rates being tried in an increasing order (i.e. from
non-UHBR -> UHBR link rates) in dsc_compute_link_config(), thus
intel_crtc_state::fec_enable being set for the non-UHBR rates and
getting reset for the first UHBR rate as expected.
A follow-up change will reuse intel_dp_fec_compute_config() for the DP
MST state computation, prepare for that here, making sure that the
function determines the correct intel_crtc_state::fec_enable=false state
for UHBR link rates based on the above.
The DP SST and MST state computation should be further unified to avoid
computing/setting the intel_crtc_state::fec_enable state multiple times,
but that's left for a follow-up change. For now add only code comments
about this.
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Jouni Högander <jouni.hogander@intel.com>
Link: https://lore.kernel.org/r/20251015161934.262108-3-imre.deak@intel.com
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index fc1949e0c4de..7c568c23134f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2368,6 +2368,9 @@ static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
static void intel_dp_fec_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state)
{
+ if (intel_dp_is_uhbr(crtc_state))
+ return;
+
if (crtc_state->fec_enable)
return;
@@ -2379,9 +2382,6 @@ static void intel_dp_fec_compute_config(struct intel_dp *intel_dp,
if (intel_dp_is_edp(intel_dp))
return;
- if (intel_dp_is_uhbr(crtc_state))
- return;
-
crtc_state->fec_enable = true;
}
@@ -2400,6 +2400,10 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
bool is_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST);
int ret;
+ /*
+ * FIXME: set the FEC enabled state once pipe_config->port_clock is
+ * already known, so the UHBR/non-UHBR mode can be determined.
+ */
intel_dp_fec_compute_config(intel_dp, pipe_config);
if (!intel_dp_dsc_supports_format(connector, pipe_config->output_format))
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index f2266b265304..27e952a67c34 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -293,6 +293,11 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
mst_stream_update_slots(crtc_state, mst_state);
}
+ /*
+ * NOTE: The following must reset crtc_state->fec_enable for UHBR/DSC
+ * after it was set by intel_dp_dsc_compute_config() ->
+ * intel_dp_fec_compute_config().
+ */
if (dsc) {
if (!intel_dp_supports_fec(intel_dp, connector, crtc_state))
return -EINVAL;
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,106 @@
From cb6c8f1f6f46ac2cbfb42ce8eb8b18257aeaa91a Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@intel.com>
Date: Wed, 15 Oct 2025 19:19:30 +0300
Subject: [PATCH] drm/i915/dp: Export helper to determine if FEC on non-UHBR
links is required
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Export the helper function to determine if FEC is required on a non-UHBR
(8b10b) SST or MST link. A follow up change will take this into use for
MST as well.
While at it determine the output type from the CRTC state, which allows
dropping the intel_dp argument. Also make the function return the
required FEC state, instead of setting this in the CRTC state, which
allows only querying this requirement, without changing the state.
Also rename the function to intel_dp_needs_8b10b_fec(), to clarify that
the function determines if FEC is required on an 8b10b link (on 128b132b
links FEC is always enabled by the HW implicitly, so the function will
return false for that case).
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Jouni Högander <jouni.hogander@intel.com>
Link: https://lore.kernel.org/r/20251015161934.262108-4-imre.deak@intel.com
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 7c568c23134f..844118735998 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2365,24 +2365,29 @@ static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
return 0;
}
-static void intel_dp_fec_compute_config(struct intel_dp *intel_dp,
- struct intel_crtc_state *crtc_state)
+/*
+ * Return whether FEC must be enabled for 8b10b SST or MST links. On 128b132b
+ * links FEC is always enabled implicitly by the HW, so this function returns
+ * false for that case.
+ */
+bool intel_dp_needs_8b10b_fec(const struct intel_crtc_state *crtc_state,
+ bool dsc_enabled_on_crtc)
{
if (intel_dp_is_uhbr(crtc_state))
- return;
+ return false;
if (crtc_state->fec_enable)
- return;
+ return true;
/*
* Though eDP v1.5 supports FEC with DSC, unlike DP, it is optional.
* Since, FEC is a bandwidth overhead, continue to not enable it for
* eDP. Until, there is a good reason to do so.
*/
- if (intel_dp_is_edp(intel_dp))
- return;
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
+ return false;
- crtc_state->fec_enable = true;
+ return dsc_enabled_on_crtc;
}
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
@@ -2404,7 +2409,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
* FIXME: set the FEC enabled state once pipe_config->port_clock is
* already known, so the UHBR/non-UHBR mode can be determined.
*/
- intel_dp_fec_compute_config(intel_dp, pipe_config);
+ pipe_config->fec_enable = intel_dp_needs_8b10b_fec(pipe_config, true);
if (!intel_dp_dsc_supports_format(connector, pipe_config->output_format))
return -EINVAL;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 281ced3a3b39..0537be20fe7b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -73,6 +73,8 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder);
int intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state);
+bool intel_dp_needs_8b10b_fec(const struct intel_crtc_state *crtc_state,
+ bool dsc_enabled_on_crtc);
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 27e952a67c34..d0590b5ffffd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -296,7 +296,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
/*
* NOTE: The following must reset crtc_state->fec_enable for UHBR/DSC
* after it was set by intel_dp_dsc_compute_config() ->
- * intel_dp_fec_compute_config().
+ * intel_dp_needs_8b10b_fec().
*/
if (dsc) {
if (!intel_dp_supports_fec(intel_dp, connector, crtc_state))
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,40 @@
From b762ae48293e2cc2145cdc91eb596d057f1aff11 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@intel.com>
Date: Wed, 15 Oct 2025 19:19:31 +0300
Subject: [PATCH] drm/i915/dp_mst: Reuse the DP-SST helper function to compute
FEC config
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reuse the DP-SST helper to compute the state for the FEC enabled state
for DP-MST as well.
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Jouni Högander <jouni.hogander@intel.com>
Link: https://lore.kernel.org/r/20251015161934.262108-5-imre.deak@intel.com
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index d0590b5ffffd..0cbb4c3a8e22 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -298,12 +298,10 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
* after it was set by intel_dp_dsc_compute_config() ->
* intel_dp_needs_8b10b_fec().
*/
- if (dsc) {
- if (!intel_dp_supports_fec(intel_dp, connector, crtc_state))
- return -EINVAL;
-
- crtc_state->fec_enable = !intel_dp_is_uhbr(crtc_state);
- }
+ crtc_state->fec_enable = intel_dp_needs_8b10b_fec(crtc_state, dsc);
+ if (crtc_state->fec_enable &&
+ !intel_dp_supports_fec(intel_dp, connector, crtc_state))
+ return -EINVAL;
max_dpt_bpp_x16 = fxp_q4_from_int(intel_dp_mst_max_dpt_bpp(crtc_state, dsc));
if (max_dpt_bpp_x16 && max_bpp_x16 > max_dpt_bpp_x16) {
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,100 @@
From 7c027070e98d7b515e4d3a94b54d288c61cb5918 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@intel.com>
Date: Wed, 15 Oct 2025 19:19:32 +0300
Subject: [PATCH] drm/i915/dp_mst: Track DSC enabled status on the MST link
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Track whether DSC is enabled on any CRTC on a link. On DP-SST (and DSI)
this will always match the CRTC's DSC state, those links having only a
single stream (aka CRTC). For instance, on DP-MST if DSC is enabled for
CRTC#0, but disabled for CRTC#1, the DSC/FEC state for these CRTCs will
be as follows:
CRTC#0:
- compression_enable = true
- compression_enabled_on_link = true
- fec_enable = true for 8b10b, false for 128b132b
CRTC#1:
- compression_enable = false
- compression_enabled_on_link = true
- fec_enable = true for 8b10b, false for 128b132b
This patch only sets compression_enabled_on_link for CRTC#0 above and
enables FEC on CRTC#0 if DSC was enabled on any other CRTC on the 8b10b
MST link. A follow-up change will make sure that the state of all the
CRTCs (CRTC#1 above) on an MST link is recomputed if DSC gets enabled on
any CRTC, setting compression_enabled_on_link and fec_enable for these.
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Jouni Högander <jouni.hogander@intel.com>
Link: https://lore.kernel.org/r/20251015161934.262108-6-imre.deak@intel.com
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 203dd38a9ec4..20747fa4d3da 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1279,6 +1279,8 @@ struct intel_crtc_state {
/* Display Stream compression state */
struct {
+ /* Only used for state computation, not read out from the HW. */
+ bool compression_enabled_on_link;
bool compression_enable;
int num_streams;
/* Compressed Bpp in U6.4 format (first 4 bits for fractional part) */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 844118735998..95884af242b3 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2387,7 +2387,7 @@ bool intel_dp_needs_8b10b_fec(const struct intel_crtc_state *crtc_state,
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
return false;
- return dsc_enabled_on_crtc;
+ return dsc_enabled_on_crtc || intel_dsc_enabled_on_link(crtc_state);
}
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 803f3b395c79..dbf2cf1b896d 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -374,9 +374,20 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
void intel_dsc_enable_on_crtc(struct intel_crtc_state *crtc_state)
{
+ crtc_state->dsc.compression_enabled_on_link = true;
crtc_state->dsc.compression_enable = true;
}
+bool intel_dsc_enabled_on_link(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+
+ drm_WARN_ON(display->drm, crtc_state->dsc.compression_enable &&
+ !crtc_state->dsc.compression_enabled_on_link);
+
+ return crtc_state->dsc.compression_enabled_on_link;
+}
+
enum intel_display_power_domain
intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
{
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h
index 8c7c7fb652c3..99f64ac54b27 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.h
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.h
@@ -21,6 +21,7 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state);
void intel_dsc_disable(const struct intel_crtc_state *crtc_state);
int intel_dsc_compute_params(struct intel_crtc_state *pipe_config);
void intel_dsc_enable_on_crtc(struct intel_crtc_state *crtc_state);
+bool intel_dsc_enabled_on_link(const struct intel_crtc_state *crtc_state);
void intel_dsc_get_config(struct intel_crtc_state *crtc_state);
enum intel_display_power_domain
intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder);
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,171 @@
From 470b84af457e34cbfa4d2c17dab78746736ab898 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@intel.com>
Date: Wed, 15 Oct 2025 19:19:33 +0300
Subject: [PATCH] drm/i915/dp_mst: Recompute all MST link CRTCs if DSC gets
enabled on the link
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The state of all the CRTCs on an MST link must be recomputed, if DSC
gets enabled on any of the CRTCs on the link. For instance an MST
docking station's Panel Replay capability may depend on whether DSC is
enabled on any of the dock's streams (aka CRTCs). To assist the Panel
Replay state computation for a CRTC based on the above, track in the
CRTC state if DSC is enabled on any CRTC on an MST link.
The intel_link_bw_limits::force_fec_pipes mask is used for a reason
similar to the above: enable FEC on all CRTCs of a non-UHBR (8b10b) MST
link if DSC is enabled on any of the link's CRTCs. The FEC enabled state
for a CRTC doesn't indicate if DSC is enabled on a UHBR MST link (FEC is
always enabled by the HW for UHBR, hence it's not tracked by the
intel_crtc_state::fec_enable flag for such links, where this flag is
always false).
Based on the above, to be able to determine the DSC state on both
non-UHBR and UHBR MST links, track the more generic DSC-enabled-on-link
state (instead of the FEC-enabled-on-link state) for each CRTC in
intel_link_bw_limits.
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Jouni Högander <jouni.hogander@intel.com>
Link: https://lore.kernel.org/r/20251015161934.262108-7-imre.deak@intel.com
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index bbb6ff929d64..a8b4619de347 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -4603,7 +4603,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
if (ret)
return ret;
- crtc_state->fec_enable = limits->force_fec_pipes & BIT(crtc->pipe);
+ crtc_state->dsc.compression_enabled_on_link = limits->link_dsc_pipes & BIT(crtc->pipe);
crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
if (crtc_state->pipe_bpp > fxp_q4_to_int(crtc_state->max_link_bpp_x16)) {
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 0cbb4c3a8e22..a845b2612a3f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -814,14 +814,14 @@ static u8 get_pipes_downstream_of_mst_port(struct intel_atomic_state *state,
return mask;
}
-static int intel_dp_mst_check_fec_change(struct intel_atomic_state *state,
+static int intel_dp_mst_check_dsc_change(struct intel_atomic_state *state,
struct drm_dp_mst_topology_mgr *mst_mgr,
struct intel_link_bw_limits *limits)
{
struct intel_display *display = to_intel_display(state);
struct intel_crtc *crtc;
u8 mst_pipe_mask;
- u8 fec_pipe_mask = 0;
+ u8 dsc_pipe_mask = 0;
int ret;
mst_pipe_mask = get_pipes_downstream_of_mst_port(state, mst_mgr, NULL);
@@ -834,16 +834,16 @@ static int intel_dp_mst_check_fec_change(struct intel_atomic_state *state,
if (drm_WARN_ON(display->drm, !crtc_state))
return -EINVAL;
- if (crtc_state->fec_enable)
- fec_pipe_mask |= BIT(crtc->pipe);
+ if (intel_dsc_enabled_on_link(crtc_state))
+ dsc_pipe_mask |= BIT(crtc->pipe);
}
- if (!fec_pipe_mask || mst_pipe_mask == fec_pipe_mask)
+ if (!dsc_pipe_mask || mst_pipe_mask == dsc_pipe_mask)
return 0;
- limits->force_fec_pipes |= mst_pipe_mask;
+ limits->link_dsc_pipes |= mst_pipe_mask;
- ret = intel_modeset_pipes_in_mask_early(state, "MST FEC",
+ ret = intel_modeset_pipes_in_mask_early(state, "MST DSC",
mst_pipe_mask);
return ret ? : -EAGAIN;
@@ -897,7 +897,7 @@ int intel_dp_mst_atomic_check_link(struct intel_atomic_state *state,
int i;
for_each_new_mst_mgr_in_state(&state->base, mgr, mst_state, i) {
- ret = intel_dp_mst_check_fec_change(state, mgr, limits);
+ ret = intel_dp_mst_check_dsc_change(state, mgr, limits);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
index f52dee0ea412..d2862de894fa 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -20,6 +20,7 @@
#include "intel_dp_tunnel.h"
#include "intel_fdi.h"
#include "intel_link_bw.h"
+#include "intel_vdsc.h"
static int get_forced_link_bpp_x16(struct intel_atomic_state *state,
const struct intel_crtc *crtc)
@@ -55,7 +56,7 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state,
struct intel_display *display = to_intel_display(state);
enum pipe pipe;
- limits->force_fec_pipes = 0;
+ limits->link_dsc_pipes = 0;
limits->bpp_limit_reached_pipes = 0;
for_each_pipe(display, pipe) {
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
@@ -65,8 +66,8 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state,
if (state->base.duplicated && crtc_state) {
limits->max_bpp_x16[pipe] = crtc_state->max_link_bpp_x16;
- if (crtc_state->fec_enable)
- limits->force_fec_pipes |= BIT(pipe);
+ if (intel_dsc_enabled_on_link(crtc_state))
+ limits->link_dsc_pipes |= BIT(pipe);
} else {
limits->max_bpp_x16[pipe] = INT_MAX;
}
@@ -265,10 +266,10 @@ assert_link_limit_change_valid(struct intel_display *display,
bool bpps_changed = false;
enum pipe pipe;
- /* FEC can't be forced off after it was forced on. */
+ /* DSC can't be disabled after it was enabled. */
if (drm_WARN_ON(display->drm,
- (old_limits->force_fec_pipes & new_limits->force_fec_pipes) !=
- old_limits->force_fec_pipes))
+ (old_limits->link_dsc_pipes & new_limits->link_dsc_pipes) !=
+ old_limits->link_dsc_pipes))
return false;
for_each_pipe(display, pipe) {
@@ -286,8 +287,8 @@ assert_link_limit_change_valid(struct intel_display *display,
/* At least one limit must change. */
if (drm_WARN_ON(display->drm,
!bpps_changed &&
- new_limits->force_fec_pipes ==
- old_limits->force_fec_pipes))
+ new_limits->link_dsc_pipes ==
+ old_limits->link_dsc_pipes))
return false;
return true;
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
index 95ab7c50c61d..cb18e171037c 100644
--- a/drivers/gpu/drm/i915/display/intel_link_bw.h
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
@@ -15,7 +15,7 @@ struct intel_connector;
struct intel_crtc_state;
struct intel_link_bw_limits {
- u8 force_fec_pipes;
+ u8 link_dsc_pipes;
u8 bpp_limit_reached_pipes;
/* in 1/16 bpp units */
int max_bpp_x16[I915_MAX_PIPES];
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,248 @@
From c390bf07961b3a39f3417d75850a4e721b87e595 Mon Sep 17 00:00:00 2001
From: Imre Deak <imre.deak@intel.com>
Date: Wed, 15 Oct 2025 19:19:34 +0300
Subject: [PATCH] drm/i915/dp: Fix panel replay when DSC is enabled
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Prevent enabling panel replay if the sink doesn't support this due to
DSC being enabled.
Panel replay has two modes, updating full frames or only selected
regions of the frame. If the sink doesn't support Panel Replay in full
frame update mode with DSC prevent Panel Replay completely if DSC is
enabled. If the sink doesn't support Panel Replay only in the selective
update mode while DSC is enabled, it will still support Panel Replay in
the full frame update mode, so only prevent selective updates in this
case.
v2:
- Use Panel Replay instead of PR in debug prints. (Jouni)
- Rebase on change tracking the link DSC state in the crtc state.
Cc: Jouni Högander <jouni.hogander@intel.com>
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14869
Reviewed-by: Jouni Högander <jouni.hogander@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://lore.kernel.org/r/20251015161934.262108-8-imre.deak@intel.com
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 20747fa4d3da..1e0cd81c9474 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -955,6 +955,12 @@ struct intel_csc_matrix {
u16 postoff[3];
};
+enum intel_panel_replay_dsc_support {
+ INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED,
+ INTEL_DP_PANEL_REPLAY_DSC_FULL_FRAME_ONLY,
+ INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE,
+};
+
struct intel_crtc_state {
/*
* uapi (drm) state. This is the software state shown to userspace.
@@ -1133,6 +1139,8 @@ struct intel_crtc_state {
bool has_panel_replay;
bool wm_level_disabled;
bool pkg_c_latency_used;
+ /* Only used for state verification. */
+ enum intel_panel_replay_dsc_support panel_replay_dsc_support;
u32 dc3co_exitline;
u16 su_y_granularity;
u8 active_non_psr_pipes;
@@ -1706,6 +1714,7 @@ struct intel_psr {
bool source_panel_replay_support;
bool sink_panel_replay_support;
bool sink_panel_replay_su_support;
+ enum intel_panel_replay_dsc_support sink_panel_replay_dsc_support;
bool panel_replay_enabled;
u32 dc3co_exitline;
u32 dc3co_exit_delay;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 95884af242b3..215ad690ab07 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6053,6 +6053,8 @@ intel_dp_detect(struct drm_connector *_connector,
memset(connector->dp.dsc_dpcd, 0, sizeof(connector->dp.dsc_dpcd));
intel_dp->psr.sink_panel_replay_support = false;
intel_dp->psr.sink_panel_replay_su_support = false;
+ intel_dp->psr.sink_panel_replay_dsc_support =
+ INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED;
intel_dp_mst_disconnect(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 703e5f6af04c..3e99a65ec988 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -29,6 +29,7 @@
#include <drm/drm_vblank.h>
#include "i915_reg.h"
+#include "i915_utils.h"
#include "intel_alpm.h"
#include "intel_atomic.h"
#include "intel_crtc.h"
@@ -50,6 +51,7 @@
#include "intel_snps_phy.h"
#include "intel_step.h"
#include "intel_vblank.h"
+#include "intel_vdsc.h"
#include "intel_vrr.h"
#include "skl_universal_plane.h"
@@ -580,6 +582,44 @@ static void intel_dp_get_su_granularity(struct intel_dp *intel_dp)
intel_dp->psr.su_y_granularity = y;
}
+static enum intel_panel_replay_dsc_support
+compute_pr_dsc_support(struct intel_dp *intel_dp)
+{
+ u8 pr_dsc_mode;
+ u8 val;
+
+ val = intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)];
+ pr_dsc_mode = REG_FIELD_GET8(DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_MASK, val);
+
+ switch (pr_dsc_mode) {
+ case DP_DSC_DECODE_CAPABILITY_IN_PR_FULL_FRAME_ONLY:
+ return INTEL_DP_PANEL_REPLAY_DSC_FULL_FRAME_ONLY;
+ case DP_DSC_DECODE_CAPABILITY_IN_PR_SUPPORTED:
+ return INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE;
+ default:
+ MISSING_CASE(pr_dsc_mode);
+ fallthrough;
+ case DP_DSC_DECODE_CAPABILITY_IN_PR_NOT_SUPPORTED:
+ case DP_DSC_DECODE_CAPABILITY_IN_PR_RESERVED:
+ return INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED;
+ }
+}
+
+static const char *panel_replay_dsc_support_str(enum intel_panel_replay_dsc_support dsc_support)
+{
+ switch (dsc_support) {
+ case INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED:
+ return "not supported";
+ case INTEL_DP_PANEL_REPLAY_DSC_FULL_FRAME_ONLY:
+ return "full frame only";
+ case INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE:
+ return "selective update";
+ default:
+ MISSING_CASE(dsc_support);
+ return "n/a";
+ };
+}
+
static void _panel_replay_init_dpcd(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
@@ -615,10 +655,13 @@ static void _panel_replay_init_dpcd(struct intel_dp *intel_dp)
DP_PANEL_REPLAY_SU_SUPPORT)
intel_dp->psr.sink_panel_replay_su_support = true;
+ intel_dp->psr.sink_panel_replay_dsc_support = compute_pr_dsc_support(intel_dp);
+
drm_dbg_kms(display->drm,
- "Panel replay %sis supported by panel\n",
+ "Panel replay %sis supported by panel (in DSC mode: %s)\n",
intel_dp->psr.sink_panel_replay_su_support ?
- "selective_update " : "");
+ "selective_update " : "",
+ panel_replay_dsc_support_str(intel_dp->psr.sink_panel_replay_dsc_support));
}
static void _psr_init_dpcd(struct intel_dp *intel_dp)
@@ -1606,9 +1649,21 @@ static bool intel_sel_update_config_valid(struct intel_dp *intel_dp,
goto unsupported;
}
- if (crtc_state->has_panel_replay && (DISPLAY_VER(display) < 14 ||
- !intel_dp->psr.sink_panel_replay_su_support))
- goto unsupported;
+ if (crtc_state->has_panel_replay) {
+ if (DISPLAY_VER(display) < 14)
+ goto unsupported;
+
+ if (!intel_dp->psr.sink_panel_replay_su_support)
+ goto unsupported;
+
+ if (intel_dsc_enabled_on_link(crtc_state) &&
+ intel_dp->psr.sink_panel_replay_dsc_support !=
+ INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE) {
+ drm_dbg_kms(display->drm,
+ "Selective update with Panel Replay not enabled because it's not supported with DSC\n");
+ goto unsupported;
+ }
+ }
if (crtc_state->crc_enabled) {
drm_dbg_kms(display->drm,
@@ -1685,6 +1740,14 @@ _panel_replay_compute_config(struct intel_dp *intel_dp,
return false;
}
+ if (intel_dsc_enabled_on_link(crtc_state) &&
+ intel_dp->psr.sink_panel_replay_dsc_support ==
+ INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED) {
+ drm_dbg_kms(display->drm,
+ "Panel Replay not enabled because it's not supported with DSC\n");
+ return false;
+ }
+
if (!intel_dp_is_edp(intel_dp))
return true;
@@ -1790,6 +1853,8 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
return;
}
+ /* Only used for state verification. */
+ crtc_state->panel_replay_dsc_support = intel_dp->psr.sink_panel_replay_dsc_support;
crtc_state->has_panel_replay = _panel_replay_compute_config(intel_dp,
crtc_state,
conn_state);
@@ -2991,6 +3056,20 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state,
}
}
+static void
+verify_panel_replay_dsc_state(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+
+ if (!crtc_state->has_panel_replay)
+ return;
+
+ drm_WARN_ON(display->drm,
+ intel_dsc_enabled_on_link(crtc_state) &&
+ crtc_state->panel_replay_dsc_support ==
+ INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED);
+}
+
void intel_psr_post_plane_update(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -3002,6 +3081,8 @@ void intel_psr_post_plane_update(struct intel_atomic_state *state,
if (!crtc_state->has_psr)
return;
+ verify_panel_replay_dsc_state(crtc_state);
+
for_each_intel_encoder_mask_with_psr(state->base.dev, encoder,
crtc_state->uapi.encoder_mask) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@@ -4031,6 +4112,8 @@ static void intel_psr_sink_capability(struct intel_dp *intel_dp,
seq_printf(m, ", Panel Replay = %s", str_yes_no(psr->sink_panel_replay_support));
seq_printf(m, ", Panel Replay Selective Update = %s",
str_yes_no(psr->sink_panel_replay_su_support));
+ seq_printf(m, ", Panel Replay DSC support = %s",
+ panel_replay_dsc_support_str(psr->sink_panel_replay_dsc_support));
if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] &
DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT)
seq_printf(m, " (Early Transport)");
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,19 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Update lpfc version to 14.4.0.12"
# Revert of f586e5f3f3751e4115a539e81d8dce066fb27f2d
scsi: lpfc: Update lpfc version to 14.4.0.12
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index f3dada5bf7c1..31c3c5abdca6 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "14.4.0.12"
+#define LPFC_DRIVER_VERSION "14.4.0.11"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */

View File

@ -0,0 +1,332 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Add capability to register Platform Name ID to fabric"
# Revert of 329b0632fcf901b929ca7658a8a3a4af2682011e
scsi: lpfc: Add capability to register Platform Name ID to fabric
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index ef83b8e0e9f8..42bf2fda825f 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -634,7 +634,6 @@ struct lpfc_vport {
#define FC_CT_RSPN_ID 0x8 /* RSPN_ID accepted by switch */
#define FC_CT_RFT_ID 0x10 /* RFT_ID accepted by switch */
#define FC_CT_RPRT_DEFER 0x20 /* Defer issuing FDMI RPRT */
-#define FC_CT_RSPNI_PNI 0x40 /* RSPNI_PNI accepted by switch */
struct list_head fc_nodes;
spinlock_t fc_nodes_list_lock; /* spinlock for fc_nodes list */
@@ -1079,8 +1078,6 @@ struct lpfc_hba {
uint32_t nport_event_cnt; /* timestamp for nlplist entry */
- unsigned long pni; /* 64-bit Platform Name Identifier */
-
uint8_t wwnn[8];
uint8_t wwpn[8];
uint32_t RandomData[7];
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 1c7fa13c8728..94f612d1fef0 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -1742,28 +1742,6 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return;
}
-static void
-lpfc_cmpl_ct_cmd_rspni_pni(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
- struct lpfc_iocbq *rspiocb)
-{
- struct lpfc_vport *vport;
- struct lpfc_dmabuf *outp;
- struct lpfc_sli_ct_request *ctrsp;
- u32 ulp_status;
-
- vport = cmdiocb->vport;
- ulp_status = get_job_ulpstatus(phba, rspiocb);
-
- if (ulp_status == IOSTAT_SUCCESS) {
- outp = cmdiocb->rsp_dmabuf;
- ctrsp = (struct lpfc_sli_ct_request *)outp->virt;
- if (be16_to_cpu(ctrsp->CommandResponse.bits.CmdRsp) ==
- SLI_CT_RESPONSE_FS_ACC)
- vport->ct_flags |= FC_CT_RSPNI_PNI;
- }
- lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
-}
-
static void
lpfc_cmpl_ct_cmd_da_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -1978,8 +1956,6 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
bpl->tus.f.bdeSize = RSPN_REQUEST_SZ;
else if (cmdcode == SLI_CTNS_RSNN_NN)
bpl->tus.f.bdeSize = RSNN_REQUEST_SZ;
- else if (cmdcode == SLI_CTNS_RSPNI_PNI)
- bpl->tus.f.bdeSize = RSPNI_REQUEST_SZ;
else if (cmdcode == SLI_CTNS_DA_ID)
bpl->tus.f.bdeSize = DA_ID_REQUEST_SZ;
else if (cmdcode == SLI_CTNS_RFF_ID)
@@ -2101,18 +2077,6 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
CtReq->un.rsnn.symbname, size);
cmpl = lpfc_cmpl_ct_cmd_rsnn_nn;
break;
- case SLI_CTNS_RSPNI_PNI:
- vport->ct_flags &= ~FC_CT_RSPNI_PNI;
- CtReq->CommandResponse.bits.CmdRsp =
- cpu_to_be16(SLI_CTNS_RSPNI_PNI);
- CtReq->un.rspni.pni = cpu_to_be64(phba->pni);
- scnprintf(CtReq->un.rspni.symbname,
- sizeof(CtReq->un.rspni.symbname), "OS Host Name::%s",
- phba->os_host_name);
- CtReq->un.rspni.len = strnlen(CtReq->un.rspni.symbname,
- sizeof(CtReq->un.rspni.symbname));
- cmpl = lpfc_cmpl_ct_cmd_rspni_pni;
- break;
case SLI_CTNS_DA_ID:
/* Implement DA_ID Nameserver request */
CtReq->CommandResponse.bits.CmdRsp =
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index fbf2fd97f093..c07d6805dbdb 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -650,6 +650,8 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_class_sup |= FC_COS_CLASS2;
if (sp->cls3.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS3;
+ if (sp->cls4.classValid)
+ ndlp->nlp_class_sup |= FC_COS_CLASS4;
ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
sp->cmn.bbRcvSizeLsb;
@@ -1354,14 +1356,6 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
/* Can't do SLI4 class2 without support sequence coalescing */
sp->cls2.classValid = 0;
sp->cls2.seqDelivery = 0;
-
- /* Fill out Auxiliary Parameter Data */
- if (phba->pni) {
- sp->aux.flags =
- AUX_PARM_DATA_VALID | AUX_PARM_PNI_VALID;
- sp->aux.pni = cpu_to_be64(phba->pni);
- sp->aux.npiv_cnt = cpu_to_be16(phba->max_vpi - 1);
- }
} else {
/* Historical, setting sequential-delivery bit for SLI3 */
sp->cls2.seqDelivery = (sp->cls2.classValid) ? 1 : 0;
@@ -5662,6 +5656,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
sp->cls1.classValid = 0;
sp->cls2.classValid = 0;
sp->cls3.classValid = 0;
+ sp->cls4.classValid = 0;
/* Copy our worldwide names */
memcpy(&sp->portName, &vport->fc_sparam.portName,
@@ -11520,13 +11515,6 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
sp->cls2.seqDelivery = 1;
sp->cls3.seqDelivery = 1;
- /* Fill out Auxiliary Parameter Data */
- if (phba->pni) {
- sp->aux.flags =
- AUX_PARM_DATA_VALID | AUX_PARM_PNI_VALID;
- sp->aux.pni = cpu_to_be64(phba->pni);
- }
-
pcmd += sizeof(uint32_t); /* CSP Word 2 */
pcmd += sizeof(uint32_t); /* CSP Word 3 */
pcmd += sizeof(uint32_t); /* CSP Word 4 */
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 5d2210790c0a..5a8ccdc956df 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -4373,8 +4373,6 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
lpfc_ns_cmd(vport, SLI_CTNS_RNN_ID, 0, 0);
lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0);
lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0);
- if (phba->pni)
- lpfc_ns_cmd(vport, SLI_CTNS_RSPNI_PNI, 0, 0);
lpfc_ns_cmd(vport, SLI_CTNS_RFT_ID, 0, 0);
if ((vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index b2e353590ebb..3bc0efa7453e 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -168,11 +168,6 @@ struct lpfc_sli_ct_request {
uint8_t len;
uint8_t symbname[255];
} rspn;
- struct rspni { /* For RSPNI_PNI requests */
- __be64 pni;
- u8 len;
- u8 symbname[255];
- } rspni;
struct gff {
uint32_t PortId;
} gff;
@@ -218,8 +213,6 @@ struct lpfc_sli_ct_request {
sizeof(struct da_id))
#define RSPN_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
sizeof(struct rspn))
-#define RSPNI_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
- sizeof(struct rspni))
/*
* FsType Definitions
@@ -316,7 +309,6 @@ struct lpfc_sli_ct_request {
#define SLI_CTNS_RIP_NN 0x0235
#define SLI_CTNS_RIPA_NN 0x0236
#define SLI_CTNS_RSNN_NN 0x0239
-#define SLI_CTNS_RSPNI_PNI 0x0240
#define SLI_CTNS_DA_ID 0x0300
/*
@@ -520,21 +512,6 @@ struct class_parms {
uint8_t word3Reserved2; /* Fc Word 3, bit 0: 7 */
};
-enum aux_parm_flags {
- AUX_PARM_PNI_VALID = 0x20, /* FC Word 0, bit 29 */
- AUX_PARM_DATA_VALID = 0x40, /* FC Word 0, bit 30 */
-};
-
-struct aux_parm {
- u8 flags; /* FC Word 0, bit 31:24 */
- u8 ext_feat[3]; /* FC Word 0, bit 23:0 */
-
- __be64 pni; /* FC Word 1 and 2, platform name identifier */
-
- __be16 rsvd; /* FC Word 3, bit 31:16 */
- __be16 npiv_cnt; /* FC Word 3, bit 15:0 */
-} __packed;
-
struct serv_parm { /* Structure is in Big Endian format */
struct csp cmn;
struct lpfc_name portName;
@@ -542,7 +519,7 @@ struct serv_parm { /* Structure is in Big Endian format */
struct class_parms cls1;
struct class_parms cls2;
struct class_parms cls3;
- struct aux_parm aux;
+ struct class_parms cls4;
union {
uint8_t vendorVersion[16];
struct {
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 9e785bbf6785..e16370da3e45 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -432,6 +432,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_class_sup |= FC_COS_CLASS2;
if (sp->cls3.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS3;
+ if (sp->cls4.classValid)
+ ndlp->nlp_class_sup |= FC_COS_CLASS4;
ndlp->nlp_maxframe =
((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
/* if already logged in, do implicit logout */
@@ -1415,6 +1417,8 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
ndlp->nlp_class_sup |= FC_COS_CLASS2;
if (sp->cls3.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS3;
+ if (sp->cls4.classValid)
+ ndlp->nlp_class_sup |= FC_COS_CLASS4;
ndlp->nlp_maxframe =
((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 2e3f77538266..66730c3e4cb9 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -27,8 +27,6 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/lockdep.h>
-#include <linux/dmi.h>
-#include <linux/of.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -8451,70 +8449,6 @@ lpfc_set_host_tm(struct lpfc_hba *phba)
return rc;
}
-/**
- * lpfc_get_platform_uuid - Attempts to extract a platform uuid
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine attempts to first read SMBIOS DMI data for the System
- * Information structure offset 08h called System UUID. Else, no platform
- * UUID will be advertised.
- **/
-static void
-lpfc_get_platform_uuid(struct lpfc_hba *phba)
-{
- int rc;
- const char *uuid;
- char pni[17] = {0}; /* 16 characters + '\0' */
- bool is_ff = true, is_00 = true;
- u8 i;
-
- /* First attempt SMBIOS DMI */
- uuid = dmi_get_system_info(DMI_PRODUCT_UUID);
- if (uuid) {
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "2088 SMBIOS UUID %s\n",
- uuid);
- } else {
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "2099 Could not extract UUID\n");
- }
-
- if (uuid && uuid_is_valid(uuid)) {
- /* Generate PNI from UUID format.
- *
- * 1.) Extract lower 64 bits from UUID format.
- * 2.) Set 3h for NAA Locally Assigned Name Identifier format.
- *
- * e.g. xxxxxxxx-xxxx-xxxx-yyyy-yyyyyyyyyyyy
- *
- * extract the yyyy-yyyyyyyyyyyy portion
- * final PNI 3yyyyyyyyyyyyyyy
- */
- scnprintf(pni, sizeof(pni), "3%c%c%c%s",
- uuid[20], uuid[21], uuid[22], &uuid[24]);
-
- /* Sanitize the converted PNI */
- for (i = 1; i < 16 && (is_ff || is_00); i++) {
- if (pni[i] != '0')
- is_00 = false;
- if (pni[i] != 'f' && pni[i] != 'F')
- is_ff = false;
- }
-
- /* Convert from char* to unsigned long */
- rc = kstrtoul(pni, 16, &phba->pni);
- if (!rc && !is_ff && !is_00) {
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "2100 PNI 0x%016lx\n", phba->pni);
- } else {
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "2101 PNI %s generation status %d\n",
- pni, rc);
- phba->pni = 0;
- }
- }
-}
-
/**
* lpfc_sli4_hba_setup - SLI4 device initialization PCI function
* @phba: Pointer to HBA context object.
@@ -8598,10 +8532,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
clear_bit(HBA_FCOE_MODE, &phba->hba_flag);
}
- /* Obtain platform UUID, only for SLI4 FC adapters */
- if (!test_bit(HBA_FCOE_MODE, &phba->hba_flag))
- lpfc_get_platform_uuid(phba);
-
if (bf_get(lpfc_mbx_rd_rev_cee_ver, &mqe->un.read_rev) ==
LPFC_DCBX_CEE_MODE)
set_bit(HBA_FIP_SUPPORT, &phba->hba_flag);

View File

@ -0,0 +1,30 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Allow support for BB credit recovery in point-to-point topology"
# Revert of a07aace5da5f860c8db0ec271438e9b46e3db858
scsi: lpfc: Allow support for BB credit recovery in point-to-point topology
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index c07d6805dbdb..0ebd6a0b0b76 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -2279,8 +2279,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
sp->cmn.valid_vendor_ver_level = 0;
memset(sp->un.vendorVersion, 0, sizeof(sp->un.vendorVersion));
- if (!test_bit(FC_PT2PT, &vport->fc_flag))
- sp->cmn.bbRcvSizeMsb &= 0xF;
+ sp->cmn.bbRcvSizeMsb &= 0xF;
/* Check if the destination port supports VMID */
ndlp->vmid_support = 0;
@@ -5670,8 +5669,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
sp->cmn.valid_vendor_ver_level = 0;
memset(sp->un.vendorVersion, 0,
sizeof(sp->un.vendorVersion));
- if (!test_bit(FC_PT2PT, &vport->fc_flag))
- sp->cmn.bbRcvSizeMsb &= 0xF;
+ sp->cmn.bbRcvSizeMsb &= 0xF;
/* If our firmware supports this feature, convey that
* info to the target using the vendor specific field.

View File

@ -0,0 +1,234 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Modify kref handling for Fabric Controller ndlps"
# Revert of f827c0e0303fbe9099192ebe9363b1170bc9d736
scsi: lpfc: Modify kref handling for Fabric Controller ndlps
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 0f9ddb7d2e7b..74b1a4116aee 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3390,21 +3390,11 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_cmpl_els_edc(phba, cmdiocb, rspiocb);
return;
}
-
if (ulp_status) {
/* ELS discovery cmd completes with error */
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS | LOG_CGN_MGMT,
"4203 ELS cmd x%x error: x%x x%X\n", cmd,
ulp_status, ulp_word4);
-
- /* In the case where the ELS cmd completes with an error and
- * the node does not have RPI registered, the node is
- * outstanding and should put its initial reference.
- */
- if ((cmd == ELS_CMD_SCR || cmd == ELS_CMD_RDF) &&
- !(ndlp->fc4_xpt_flags & SCSI_XPT_REGD) &&
- !test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
- lpfc_nlp_put(ndlp);
goto out;
}
@@ -3473,7 +3463,6 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
uint8_t *pcmd;
uint16_t cmdsize;
struct lpfc_nodelist *ndlp;
- bool node_created = false;
cmdsize = (sizeof(uint32_t) + sizeof(SCR));
@@ -3483,21 +3472,21 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
if (!ndlp)
return 1;
lpfc_enqueue_node(vport, ndlp);
- node_created = true;
}
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
ndlp->nlp_DID, ELS_CMD_SCR);
if (!elsiocb)
- goto out_node_created;
+ return 1;
if (phba->sli_rev == LPFC_SLI_REV4) {
rc = lpfc_reg_fab_ctrl_node(vport, ndlp);
if (rc) {
+ lpfc_els_free_iocb(phba, elsiocb);
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
"0937 %s: Failed to reg fc node, rc %d\n",
__func__, rc);
- goto out_free_iocb;
+ return 1;
}
}
pcmd = (uint8_t *)elsiocb->cmd_dmabuf->virt;
@@ -3516,27 +3505,23 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
phba->fc_stat.elsXmitSCR++;
elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
elsiocb->ndlp = lpfc_nlp_get(ndlp);
- if (!elsiocb->ndlp)
- goto out_free_iocb;
+ if (!elsiocb->ndlp) {
+ lpfc_els_free_iocb(phba, elsiocb);
+ return 1;
+ }
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
"Issue SCR: did:x%x refcnt %d",
ndlp->nlp_DID, kref_read(&ndlp->kref), 0);
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
- if (rc == IOCB_ERROR)
- goto out_iocb_error;
+ if (rc == IOCB_ERROR) {
+ lpfc_els_free_iocb(phba, elsiocb);
+ lpfc_nlp_put(ndlp);
+ return 1;
+ }
return 0;
-
-out_iocb_error:
- lpfc_nlp_put(ndlp);
-out_free_iocb:
- lpfc_els_free_iocb(phba, elsiocb);
-out_node_created:
- if (node_created)
- lpfc_nlp_put(ndlp);
- return 1;
}
/**
@@ -3749,12 +3734,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
*
* Return code
* 0 - Successfully issued rdf command
- * < 0 - Failed to issue rdf command
- * -EACCES - RDF not required for NPIV_PORT
- * -ENODEV - No fabric controller device available
- * -ENOMEM - No available memory
- * -EIO - The mailbox failed to complete successfully.
- *
+ * 1 - Failed to issue rdf command
**/
int
lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
@@ -3765,30 +3745,25 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
struct lpfc_nodelist *ndlp;
uint16_t cmdsize;
int rc;
- bool node_created = false;
- int err;
cmdsize = sizeof(*prdf);
- /* RDF ELS is not required on an NPIV VN_Port. */
- if (vport->port_type == LPFC_NPIV_PORT)
- return -EACCES;
-
ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID);
if (!ndlp) {
ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID);
if (!ndlp)
return -ENODEV;
lpfc_enqueue_node(vport, ndlp);
- node_created = true;
}
+ /* RDF ELS is not required on an NPIV VN_Port. */
+ if (vport->port_type == LPFC_NPIV_PORT)
+ return -EACCES;
+
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
ndlp->nlp_DID, ELS_CMD_RDF);
- if (!elsiocb) {
- err = -ENOMEM;
- goto out_node_created;
- }
+ if (!elsiocb)
+ return -ENOMEM;
/* Configure the payload for the supported FPIN events. */
prdf = (struct lpfc_els_rdf_req *)elsiocb->cmd_dmabuf->virt;
@@ -3814,8 +3789,8 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
elsiocb->ndlp = lpfc_nlp_get(ndlp);
if (!elsiocb->ndlp) {
- err = -EIO;
- goto out_free_iocb;
+ lpfc_els_free_iocb(phba, elsiocb);
+ return -EIO;
}
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
@@ -3824,19 +3799,11 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
if (rc == IOCB_ERROR) {
- err = -EIO;
- goto out_iocb_error;
+ lpfc_els_free_iocb(phba, elsiocb);
+ lpfc_nlp_put(ndlp);
+ return -EIO;
}
return 0;
-
-out_iocb_error:
- lpfc_nlp_put(ndlp);
-out_free_iocb:
- lpfc_els_free_iocb(phba, elsiocb);
-out_node_created:
- if (node_created)
- lpfc_nlp_put(ndlp);
- return err;
}
/**
@@ -3857,23 +3824,19 @@ static int
lpfc_els_rcv_rdf(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
{
- int rc;
-
- rc = lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL);
/* Send LS_ACC */
- if (rc) {
+ if (lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
- "1623 Failed to RDF_ACC from x%x for x%x Data: %d\n",
- ndlp->nlp_DID, vport->fc_myDID, rc);
+ "1623 Failed to RDF_ACC from x%x for x%x\n",
+ ndlp->nlp_DID, vport->fc_myDID);
return -EIO;
}
- rc = lpfc_issue_els_rdf(vport, 0);
/* Issue new RDF for reregistering */
- if (rc) {
+ if (lpfc_issue_els_rdf(vport, 0)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
- "2623 Failed to re register RDF for x%x Data: %d\n",
- vport->fc_myDID, rc);
+ "2623 Failed to re register RDF for x%x\n",
+ vport->fc_myDID);
return -EIO;
}
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index f3bd42652549..e32a2dfa516a 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -3057,6 +3057,12 @@ lpfc_cleanup(struct lpfc_vport *vport)
lpfc_vmid_vport_cleanup(vport);
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+ if (ndlp->nlp_DID == Fabric_Cntl_DID &&
+ ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
+ lpfc_nlp_put(ndlp);
+ continue;
+ }
+
/* Fabric Ports not in UNMAPPED state are cleaned up in the
* DEVICE_RM event.
*/

View File

@ -0,0 +1,169 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Fix leaked ndlp krefs when in point-to-point topology"
# Revert of 355b54c3c42b0525403b8b17058d27d418a24106
scsi: lpfc: Fix leaked ndlp krefs when in point-to-point topology
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 42bf2fda825f..4d095a3bcb0e 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -312,6 +312,7 @@ struct lpfc_defer_flogi_acc {
u16 rx_id;
u16 ox_id;
struct lpfc_nodelist *ndlp;
+
};
#define LPFC_VMID_TIMER 300 /* timer interval in seconds */
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 51cb8571c049..3d47dc7458d1 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -208,7 +208,6 @@ enum lpfc_nlp_flag {
NPR list */
NLP_RM_DFLT_RPI = 26, /* need to remove leftover dflt RPI */
NLP_NODEV_REMOVE = 27, /* Defer removal till discovery ends */
- NLP_FLOGI_DFR_ACC = 28, /* FLOGI LS_ACC was Deferred */
NLP_SC_REQ = 29, /* Target requires authentication */
NLP_FIRSTBURST = 30, /* Target supports FirstBurst */
NLP_RPI_REGISTERED = 31 /* nlp_rpi is valid */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 74b1a4116aee..5beef9df9884 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1413,12 +1413,11 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
phba->defer_flogi_acc.ox_id;
}
- /* The LS_ACC completion needs to drop the initial reference.
- * This is a special case for Pt2Pt because both FLOGIs need
- * to complete and lpfc defers the LS_ACC when the remote
- * FLOGI arrives before the driver's FLOGI.
- */
- set_bit(NLP_FLOGI_DFR_ACC, &ndlp->nlp_flag);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "3354 Xmit deferred FLOGI ACC: rx_id: x%x,"
+ " ox_id: x%x, hba_flag x%lx\n",
+ phba->defer_flogi_acc.rx_id,
+ phba->defer_flogi_acc.ox_id, phba->hba_flag);
/* Send deferred FLOGI ACC */
lpfc_els_rsp_acc(vport, ELS_CMD_FLOGI, &defer_flogi_acc,
@@ -1434,14 +1433,6 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
phba->defer_flogi_acc.ndlp = NULL;
}
- lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
- "3354 Xmit deferred FLOGI ACC: rx_id: x%x,"
- " ox_id: x%x, ndlp x%px hba_flag x%lx\n",
- phba->defer_flogi_acc.rx_id,
- phba->defer_flogi_acc.ox_id,
- phba->defer_flogi_acc.ndlp,
- phba->hba_flag);
-
vport->fc_myDID = did;
}
@@ -5310,12 +5301,11 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
IOCB_t *irsp;
LPFC_MBOXQ_t *mbox = NULL;
u32 ulp_status, ulp_word4, tmo, did, iotag;
- u32 cmd;
if (!vport) {
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
"3177 null vport in ELS rsp\n");
- goto release;
+ goto out;
}
if (cmdiocb->context_un.mbox)
mbox = cmdiocb->context_un.mbox;
@@ -5425,7 +5415,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
* these conditions because it doesn't need the login.
*/
if (phba->sli_rev == LPFC_SLI_REV4 &&
- vport->port_type == LPFC_NPIV_PORT &&
+ vport && vport->port_type == LPFC_NPIV_PORT &&
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE &&
ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE &&
@@ -5441,27 +5431,6 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
}
- /* The driver's unsolicited deferred FLOGI ACC in Pt2Pt needs to
- * release the initial reference because the put after the free_iocb
- * call removes only the reference from the defer logic. This FLOGI
- * is never registered with the SCSI transport.
- */
- if (test_bit(FC_PT2PT, &vport->fc_flag) &&
- test_and_clear_bit(NLP_FLOGI_DFR_ACC, &ndlp->nlp_flag)) {
- lpfc_printf_vlog(vport, KERN_INFO,
- LOG_ELS | LOG_NODE | LOG_DISCOVERY,
- "3357 Pt2Pt Defer FLOGI ACC ndlp x%px, "
- "nflags x%lx, fc_flag x%lx\n",
- ndlp, ndlp->nlp_flag,
- vport->fc_flag);
- cmd = *((u32 *)cmdiocb->cmd_dmabuf->virt);
- if (cmd == ELS_CMD_ACC) {
- if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
- lpfc_nlp_put(ndlp);
- }
- }
-
-release:
/* Release the originating I/O reference. */
lpfc_els_free_iocb(phba, cmdiocb);
lpfc_nlp_put(ndlp);
@@ -8430,6 +8399,13 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
&wqe->xmit_els_rsp.wqe_com);
vport->fc_myDID = did;
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "3344 Deferring FLOGI ACC: rx_id: x%x,"
+ " ox_id: x%x, hba_flag x%lx\n",
+ phba->defer_flogi_acc.rx_id,
+ phba->defer_flogi_acc.ox_id, phba->hba_flag);
+
phba->defer_flogi_acc.flag = true;
/* This nlp_get is paired with nlp_puts that reset the
@@ -8438,14 +8414,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
* processed or cancelled.
*/
phba->defer_flogi_acc.ndlp = lpfc_nlp_get(ndlp);
-
- lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
- "3344 Deferring FLOGI ACC: rx_id: x%x,"
- " ox_id: x%x, ndlp x%px, hba_flag x%lx\n",
- phba->defer_flogi_acc.rx_id,
- phba->defer_flogi_acc.ox_id,
- phba->defer_flogi_acc.ndlp,
- phba->hba_flag);
return 0;
}
@@ -10391,8 +10359,11 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
* Do not process any unsolicited ELS commands
* if the ndlp is in DEV_LOSS
*/
- if (test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag))
+ if (test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag)) {
+ if (newnode)
+ lpfc_nlp_put(ndlp);
goto dropit;
+ }
elsiocb->ndlp = lpfc_nlp_get(ndlp);
if (!elsiocb->ndlp)

View File

@ -0,0 +1,54 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Ensure unregistration of rpis for received PLOGIs"
# Revert of 35234917d9a2719b77db215e5b8dce2e2687bce9
scsi: lpfc: Ensure unregistration of rpis for received PLOGIs
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 5beef9df9884..377add7048d7 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3263,7 +3263,7 @@ lpfc_reg_fab_ctrl_node(struct lpfc_vport *vport, struct lpfc_nodelist *fc_ndlp)
return -ENOMEM;
}
rc = lpfc_reg_rpi(phba, vport->vpi, fc_ndlp->nlp_DID,
- (u8 *)&ns_ndlp->fc_sparam, mbox, fc_ndlp->nlp_rpi);
+ (u8 *)&vport->fc_sparam, mbox, fc_ndlp->nlp_rpi);
if (rc) {
rc = -EACCES;
goto out;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index e16370da3e45..99aefc54ac35 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -452,7 +452,18 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
*/
if (!(ndlp->nlp_type & NLP_FABRIC) &&
!(phba->nvmet_support)) {
- break;
+ /* Clear ndlp info, since follow up PRLI may have
+ * updated ndlp information
+ */
+ ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
+ ndlp->nlp_type &= ~(NLP_NVME_TARGET | NLP_NVME_INITIATOR);
+ ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
+ ndlp->nlp_nvme_info &= ~NLP_NVME_NSLER;
+ clear_bit(NLP_FIRSTBURST, &ndlp->nlp_flag);
+
+ lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb,
+ ndlp, NULL);
+ return 1;
}
if (nlp_portwwn != 0 &&
nlp_portwwn != wwn_to_u64(sp->portName.u.wwn))
@@ -474,9 +485,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
break;
}
- /* Clear ndlp info, since follow up processes may have
- * updated ndlp information
- */
+
ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
ndlp->nlp_type &= ~(NLP_NVME_TARGET | NLP_NVME_INITIATOR);
ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;

View File

@ -0,0 +1,25 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Remove redundant NULL ptr assignment in lpfc_els_free_iocb()"
# Revert of 9ed3e03334ac8ffb8a7371dc760940ef8de5d0ea
scsi: lpfc: Remove redundant NULL ptr assignment in lpfc_els_free_iocb()
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 377add7048d7..9bc2f4975566 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -5158,12 +5158,14 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
} else {
buf_ptr1 = elsiocb->cmd_dmabuf;
lpfc_els_free_data(phba, buf_ptr1);
+ elsiocb->cmd_dmabuf = NULL;
}
}
if (elsiocb->bpl_dmabuf) {
buf_ptr = elsiocb->bpl_dmabuf;
lpfc_els_free_bpl(phba, buf_ptr);
+ elsiocb->bpl_dmabuf = NULL;
}
lpfc_sli_release_iocbq(phba, elsiocb);
return 0;

View File

@ -0,0 +1,107 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Revise discovery related function headers and comments"
# Revert of 75d230ed196c1375f5a200039c8ee4495240c57c
scsi: lpfc: Revise discovery related function headers and comments
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 9bc2f4975566..7f6ddf50c315 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3024,7 +3024,6 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
ndlp->nlp_DID, ulp_status,
ulp_word4);
- /* Call NLP_EVT_DEVICE_RM if link is down or LOGO is aborted */
if (lpfc_error_lost_link(vport, ulp_status, ulp_word4))
skip_recovery = 1;
}
@@ -3307,8 +3306,7 @@ lpfc_reg_fab_ctrl_node(struct lpfc_vport *vport, struct lpfc_nodelist *fc_ndlp)
*
* This routine is a generic completion callback function for Discovery ELS cmd.
* Currently used by the ELS command issuing routines for the ELS State Change
- * Request (SCR), lpfc_issue_els_scr(), Exchange Diagnostic Capabilities (EDC),
- * lpfc_issue_els_edc() and the ELS RDF, lpfc_issue_els_rdf().
+ * Request (SCR), lpfc_issue_els_scr() and the ELS RDF, lpfc_issue_els_rdf().
* These commands will be retried once only for ELS timeout errors.
**/
static void
@@ -3707,7 +3705,10 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
lpfc_nlp_put(ndlp);
return 1;
}
-
+ /* This will cause the callback-function lpfc_cmpl_els_cmd to
+ * trigger the release of the node.
+ */
+ /* Don't release reference count as RDF is likely outstanding */
return 0;
}
@@ -4298,7 +4299,7 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
if (rc == IOCB_ERROR) {
/* The additional lpfc_nlp_put will cause the following
- * lpfc_els_free_iocb routine to trigger the release of
+ * lpfc_els_free_iocb routine to trigger the rlease of
* the node.
*/
lpfc_els_free_iocb(phba, elsiocb);
@@ -5125,7 +5126,7 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
{
struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
- /* The I/O iocb is complete. Clear the node and first dmabuf */
+ /* The I/O iocb is complete. Clear the node and first dmbuf */
elsiocb->ndlp = NULL;
/* cmd_dmabuf = cmd, cmd_dmabuf->next = rsp, bpl_dmabuf = bpl */
@@ -8733,7 +8734,7 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
- * This routine processes Read Timeout Value (RTV) IOCB received as an
+ * This routine processes Read Timout Value (RTV) IOCB received as an
* ELS unsolicited event. It first checks the remote port state. If the
* remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE
* state, it invokes the lpfc_els_rsl_reject() routine to send the reject
@@ -10847,7 +10848,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
/*
* The different unsolicited event handlers would tell us
- * if they are done with "mp" by setting cmd_dmabuf/bpl_dmabuf to NULL.
+ * if they are done with "mp" by setting cmd_dmabuf to NULL.
*/
if (elsiocb->cmd_dmabuf) {
lpfc_in_buf_free(phba, elsiocb->cmd_dmabuf);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 66730c3e4cb9..e658f2a914d9 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -19867,15 +19867,13 @@ lpfc_sli4_remove_rpis(struct lpfc_hba *phba)
}
/**
- * lpfc_sli4_resume_rpi - Resume traffic relative to an RPI
+ * lpfc_sli4_resume_rpi - Remove the rpi bitmask region
* @ndlp: pointer to lpfc nodelist data structure.
* @cmpl: completion call-back.
* @iocbq: data to load as mbox ctx_u information
*
- * Return codes
- * 0 - successful
- * -ENOMEM - No available memory
- * -EIO - The mailbox failed to complete successfully.
+ * This routine is invoked to remove the memory region that
+ * provided rpi via a bitmask.
**/
int
lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp,
@@ -19905,6 +19903,7 @@ lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp,
return -EIO;
}
+ /* Post all rpi memory regions to the port. */
lpfc_resume_rpi(mboxq, ndlp);
if (cmpl) {
mboxq->mbox_cmpl = cmpl;

View File

@ -0,0 +1,47 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Update various NPIV diagnostic log messaging"
# Revert of 958b3db3862eeef3b1e92c877d70f57ce019740a
scsi: lpfc: Update various NPIV diagnostic log messaging
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 7f6ddf50c315..0630d109e767 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -2367,7 +2367,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
mode = KERN_INFO;
/* Warn PRLI status */
- lpfc_vlog_msg(vport, mode, LOG_ELS,
+ lpfc_printf_vlog(vport, mode, LOG_ELS,
"2754 PRLI DID:%06X Status:x%x/x%x, "
"data: x%x x%x x%lx\n",
ndlp->nlp_DID, ulp_status,
@@ -3597,8 +3597,8 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry)
}
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
- "Issue RSCN: did:x%x refcnt %d",
- ndlp->nlp_DID, kref_read(&ndlp->kref), 0);
+ "Issue RSCN: did:x%x",
+ ndlp->nlp_DID, 0, 0);
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
if (rc == IOCB_ERROR) {
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index e32a2dfa516a..2f3629ef64e6 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -9077,9 +9077,9 @@ lpfc_setup_fdmi_mask(struct lpfc_vport *vport)
vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR;
}
- lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
- "6077 Setup FDMI mask: hba x%x port x%x\n",
- vport->fdmi_hba_mask, vport->fdmi_port_mask);
+ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
+ "6077 Setup FDMI mask: hba x%x port x%x\n",
+ vport->fdmi_hba_mask, vport->fdmi_port_mask);
}
/**

View File

@ -0,0 +1,58 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Copyright updates for 14.4.0.11 patches"
# Revert of 6da7906c531c73840fecb724d4da97334ab46ca6
scsi: lpfc: Copyright updates for 14.4.0.11 patches
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 4d095a3bcb0e..5e08f7a39702 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
index a1464f8ac331..566dd84e0677 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.h
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2007-2011 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 3bc0efa7453e..b287d39ad033 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 99aefc54ac35..1e331b76dff4 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *

View File

@ -0,0 +1,19 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Update lpfc version to 14.4.0.11"
# Revert of 1a4e6ee8d31372eff037fed3dfc762ecbe964e98
scsi: lpfc: Update lpfc version to 14.4.0.11
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 31c3c5abdca6..9ee3a3a4ec4d 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "14.4.0.11"
+#define LPFC_DRIVER_VERSION "14.4.0.10"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */

View File

@ -0,0 +1,92 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Convert debugfs directory counts from atomic to unsigned int"
# Revert of a20734de11ba1c0ef97622bf51ee502b626dca0a
scsi: lpfc: Convert debugfs directory counts from atomic to unsigned int
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 5e08f7a39702..291f0cc38f14 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -1333,7 +1333,7 @@ struct lpfc_hba {
unsigned long last_ramp_down_time;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
struct dentry *hba_debugfs_root;
- unsigned int debugfs_vport_count;
+ atomic_t debugfs_vport_count;
struct lpfc_debugfs_nvmeio_trc *nvmeio_trc;
atomic_t nvmeio_trc_cnt;
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index a4378c66427c..bfc0b9c40c5b 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -5752,7 +5752,7 @@ static const struct file_operations lpfc_debugfs_op_slow_ring_trc = {
};
static struct dentry *lpfc_debugfs_root = NULL;
-static unsigned int lpfc_debugfs_hba_count;
+static atomic_t lpfc_debugfs_hba_count;
/*
* File operations for the iDiag debugfs
@@ -6074,7 +6074,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
/* Setup lpfc root directory */
if (!lpfc_debugfs_root) {
lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
- lpfc_debugfs_hba_count = 0;
+ atomic_set(&lpfc_debugfs_hba_count, 0);
if (IS_ERR(lpfc_debugfs_root)) {
lpfc_vlog_msg(vport, KERN_WARNING, LOG_INIT,
"0527 Cannot create debugfs lpfc\n");
@@ -6090,13 +6090,13 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
pport_setup = true;
phba->hba_debugfs_root =
debugfs_create_dir(name, lpfc_debugfs_root);
- phba->debugfs_vport_count = 0;
+ atomic_set(&phba->debugfs_vport_count, 0);
if (IS_ERR(phba->hba_debugfs_root)) {
lpfc_vlog_msg(vport, KERN_WARNING, LOG_INIT,
"0528 Cannot create debugfs %s\n", name);
return;
}
- lpfc_debugfs_hba_count++;
+ atomic_inc(&lpfc_debugfs_hba_count);
/* Multi-XRI pools */
debugfs_create_file("multixripools", 0644,
@@ -6268,7 +6268,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
"0529 Cannot create debugfs %s\n", name);
return;
}
- phba->debugfs_vport_count++;
+ atomic_inc(&phba->debugfs_vport_count);
}
if (lpfc_debugfs_max_disc_trc) {
@@ -6402,10 +6402,10 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
if (vport->vport_debugfs_root) {
debugfs_remove(vport->vport_debugfs_root); /* vportX */
vport->vport_debugfs_root = NULL;
- phba->debugfs_vport_count--;
+ atomic_dec(&phba->debugfs_vport_count);
}
- if (!phba->debugfs_vport_count) {
+ if (atomic_read(&phba->debugfs_vport_count) == 0) {
kfree(phba->slow_ring_trc);
phba->slow_ring_trc = NULL;
@@ -6415,10 +6415,10 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
if (phba->hba_debugfs_root) {
debugfs_remove(phba->hba_debugfs_root); /* fnX */
phba->hba_debugfs_root = NULL;
- lpfc_debugfs_hba_count--;
+ atomic_dec(&lpfc_debugfs_hba_count);
}
- if (!lpfc_debugfs_hba_count) {
+ if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
debugfs_remove(lpfc_debugfs_root); /* lpfc */
lpfc_debugfs_root = NULL;
}

View File

@ -0,0 +1,683 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Clean up extraneous phba dentries"
# Revert of 080408a120c922181dec5d5a59ee6e94b010bbc5
scsi: lpfc: Clean up extraneous phba dentries
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 291f0cc38f14..0a43be24cee8 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -742,6 +742,12 @@ struct lpfc_vport {
struct lpfc_vmid_priority_info vmid_priority;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ struct dentry *debug_disc_trc;
+ struct dentry *debug_nodelist;
+ struct dentry *debug_nvmestat;
+ struct dentry *debug_scsistat;
+ struct dentry *debug_ioktime;
+ struct dentry *debug_hdwqstat;
struct dentry *vport_debugfs_root;
struct lpfc_debugfs_trc *disc_trc;
atomic_t disc_trc_cnt;
@@ -1334,8 +1340,29 @@ struct lpfc_hba {
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
struct dentry *hba_debugfs_root;
atomic_t debugfs_vport_count;
-
+ struct dentry *debug_multixri_pools;
+ struct dentry *debug_hbqinfo;
+ struct dentry *debug_dumpHostSlim;
+ struct dentry *debug_dumpHBASlim;
+ struct dentry *debug_InjErrLBA; /* LBA to inject errors at */
+ struct dentry *debug_InjErrNPortID; /* NPortID to inject errors at */
+ struct dentry *debug_InjErrWWPN; /* WWPN to inject errors at */
+ struct dentry *debug_writeGuard; /* inject write guard_tag errors */
+ struct dentry *debug_writeApp; /* inject write app_tag errors */
+ struct dentry *debug_writeRef; /* inject write ref_tag errors */
+ struct dentry *debug_readGuard; /* inject read guard_tag errors */
+ struct dentry *debug_readApp; /* inject read app_tag errors */
+ struct dentry *debug_readRef; /* inject read ref_tag errors */
+
+ struct dentry *debug_nvmeio_trc;
struct lpfc_debugfs_nvmeio_trc *nvmeio_trc;
+ struct dentry *debug_hdwqinfo;
+#ifdef LPFC_HDWQ_LOCK_STAT
+ struct dentry *debug_lockstat;
+#endif
+ struct dentry *debug_cgn_buffer;
+ struct dentry *debug_rx_monitor;
+ struct dentry *debug_ras_log;
atomic_t nvmeio_trc_cnt;
uint32_t nvmeio_trc_size;
uint32_t nvmeio_trc_output_idx;
@@ -1352,10 +1379,19 @@ struct lpfc_hba {
sector_t lpfc_injerr_lba;
#define LPFC_INJERR_LBA_OFF (sector_t)(-1)
+ struct dentry *debug_slow_ring_trc;
struct lpfc_debugfs_trc *slow_ring_trc;
atomic_t slow_ring_trc_cnt;
/* iDiag debugfs sub-directory */
struct dentry *idiag_root;
+ struct dentry *idiag_pci_cfg;
+ struct dentry *idiag_bar_acc;
+ struct dentry *idiag_que_info;
+ struct dentry *idiag_que_acc;
+ struct dentry *idiag_drb_acc;
+ struct dentry *idiag_ctl_acc;
+ struct dentry *idiag_mbx_acc;
+ struct dentry *idiag_ext_acc;
uint8_t lpfc_idiag_last_eq;
#endif
uint16_t nvmeio_trc_on;
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index bfc0b9c40c5b..892e2177663a 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -6075,11 +6075,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
if (!lpfc_debugfs_root) {
lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
atomic_set(&lpfc_debugfs_hba_count, 0);
- if (IS_ERR(lpfc_debugfs_root)) {
- lpfc_vlog_msg(vport, KERN_WARNING, LOG_INIT,
- "0527 Cannot create debugfs lpfc\n");
- return;
- }
}
if (!lpfc_debugfs_start_time)
lpfc_debugfs_start_time = jiffies;
@@ -6090,96 +6085,150 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
pport_setup = true;
phba->hba_debugfs_root =
debugfs_create_dir(name, lpfc_debugfs_root);
- atomic_set(&phba->debugfs_vport_count, 0);
- if (IS_ERR(phba->hba_debugfs_root)) {
- lpfc_vlog_msg(vport, KERN_WARNING, LOG_INIT,
- "0528 Cannot create debugfs %s\n", name);
- return;
- }
atomic_inc(&lpfc_debugfs_hba_count);
+ atomic_set(&phba->debugfs_vport_count, 0);
/* Multi-XRI pools */
- debugfs_create_file("multixripools", 0644,
- phba->hba_debugfs_root, phba,
- &lpfc_debugfs_op_multixripools);
+ snprintf(name, sizeof(name), "multixripools");
+ phba->debug_multixri_pools =
+ debugfs_create_file(name, S_IFREG | 0644,
+ phba->hba_debugfs_root,
+ phba,
+ &lpfc_debugfs_op_multixripools);
+ if (IS_ERR(phba->debug_multixri_pools)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0527 Cannot create debugfs multixripools\n");
+ goto debug_failed;
+ }
/* Congestion Info Buffer */
- debugfs_create_file("cgn_buffer", 0644, phba->hba_debugfs_root,
- phba, &lpfc_cgn_buffer_op);
+ scnprintf(name, sizeof(name), "cgn_buffer");
+ phba->debug_cgn_buffer =
+ debugfs_create_file(name, S_IFREG | 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_cgn_buffer_op);
+ if (IS_ERR(phba->debug_cgn_buffer)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "6527 Cannot create debugfs "
+ "cgn_buffer\n");
+ goto debug_failed;
+ }
/* RX Monitor */
- debugfs_create_file("rx_monitor", 0644, phba->hba_debugfs_root,
- phba, &lpfc_rx_monitor_op);
+ scnprintf(name, sizeof(name), "rx_monitor");
+ phba->debug_rx_monitor =
+ debugfs_create_file(name, S_IFREG | 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_rx_monitor_op);
+ if (IS_ERR(phba->debug_rx_monitor)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "6528 Cannot create debugfs "
+ "rx_monitor\n");
+ goto debug_failed;
+ }
/* RAS log */
- debugfs_create_file("ras_log", 0644, phba->hba_debugfs_root,
- phba, &lpfc_debugfs_ras_log);
+ snprintf(name, sizeof(name), "ras_log");
+ phba->debug_ras_log =
+ debugfs_create_file(name, 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_ras_log);
+ if (IS_ERR(phba->debug_ras_log)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "6148 Cannot create debugfs"
+ " ras_log\n");
+ goto debug_failed;
+ }
/* Setup hbqinfo */
- debugfs_create_file("hbqinfo", 0644, phba->hba_debugfs_root,
- phba, &lpfc_debugfs_op_hbqinfo);
+ snprintf(name, sizeof(name), "hbqinfo");
+ phba->debug_hbqinfo =
+ debugfs_create_file(name, S_IFREG | 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_hbqinfo);
#ifdef LPFC_HDWQ_LOCK_STAT
/* Setup lockstat */
- debugfs_create_file("lockstat", 0644, phba->hba_debugfs_root,
- phba, &lpfc_debugfs_op_lockstat);
+ snprintf(name, sizeof(name), "lockstat");
+ phba->debug_lockstat =
+ debugfs_create_file(name, S_IFREG | 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_lockstat);
+ if (IS_ERR(phba->debug_lockstat)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "4610 Can't create debugfs lockstat\n");
+ goto debug_failed;
+ }
#endif
+
+ /* Setup dumpHBASlim */
if (phba->sli_rev < LPFC_SLI_REV4) {
- /* Setup dumpHBASlim */
- debugfs_create_file("dumpHBASlim", 0644,
- phba->hba_debugfs_root, phba,
- &lpfc_debugfs_op_dumpHBASlim);
- }
+ snprintf(name, sizeof(name), "dumpHBASlim");
+ phba->debug_dumpHBASlim =
+ debugfs_create_file(name,
+ S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dumpHBASlim);
+ } else
+ phba->debug_dumpHBASlim = NULL;
+ /* Setup dumpHostSlim */
if (phba->sli_rev < LPFC_SLI_REV4) {
- /* Setup dumpHostSlim */
- debugfs_create_file("dumpHostSlim", 0644,
- phba->hba_debugfs_root, phba,
- &lpfc_debugfs_op_dumpHostSlim);
- }
+ snprintf(name, sizeof(name), "dumpHostSlim");
+ phba->debug_dumpHostSlim =
+ debugfs_create_file(name,
+ S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_dumpHostSlim);
+ } else
+ phba->debug_dumpHostSlim = NULL;
/* Setup DIF Error Injections */
- debugfs_create_file_aux_num("InjErrLBA", 0644,
- phba->hba_debugfs_root, phba,
- InjErrLBA,
- &lpfc_debugfs_op_dif_err);
+ phba->debug_InjErrLBA =
+ debugfs_create_file_aux_num("InjErrLBA", 0644,
+ phba->hba_debugfs_root,
+ phba, InjErrLBA, &lpfc_debugfs_op_dif_err);
phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
- debugfs_create_file_aux_num("InjErrNPortID", 0644,
- phba->hba_debugfs_root, phba,
- InjErrNPortID,
- &lpfc_debugfs_op_dif_err);
-
- debugfs_create_file_aux_num("InjErrWWPN", 0644,
- phba->hba_debugfs_root, phba,
- InjErrWWPN,
- &lpfc_debugfs_op_dif_err);
-
- debugfs_create_file_aux_num("writeGuardInjErr", 0644,
- phba->hba_debugfs_root, phba,
- writeGuard,
- &lpfc_debugfs_op_dif_err);
-
- debugfs_create_file_aux_num("writeAppInjErr", 0644,
- phba->hba_debugfs_root, phba,
- writeApp, &lpfc_debugfs_op_dif_err);
-
- debugfs_create_file_aux_num("writeRefInjErr", 0644,
- phba->hba_debugfs_root, phba,
- writeRef, &lpfc_debugfs_op_dif_err);
-
- debugfs_create_file_aux_num("readGuardInjErr", 0644,
- phba->hba_debugfs_root, phba,
- readGuard,
- &lpfc_debugfs_op_dif_err);
-
- debugfs_create_file_aux_num("readAppInjErr", 0644,
- phba->hba_debugfs_root, phba,
- readApp, &lpfc_debugfs_op_dif_err);
-
- debugfs_create_file_aux_num("readRefInjErr", 0644,
- phba->hba_debugfs_root, phba,
- readRef, &lpfc_debugfs_op_dif_err);
+ phba->debug_InjErrNPortID =
+ debugfs_create_file_aux_num("InjErrNPortID", 0644,
+ phba->hba_debugfs_root,
+ phba, InjErrNPortID, &lpfc_debugfs_op_dif_err);
+
+ phba->debug_InjErrWWPN =
+ debugfs_create_file_aux_num("InjErrWWPN", 0644,
+ phba->hba_debugfs_root,
+ phba, InjErrWWPN, &lpfc_debugfs_op_dif_err);
+
+ phba->debug_writeGuard =
+ debugfs_create_file_aux_num("writeGuardInjErr", 0644,
+ phba->hba_debugfs_root,
+ phba, writeGuard, &lpfc_debugfs_op_dif_err);
+
+ phba->debug_writeApp =
+ debugfs_create_file_aux_num("writeAppInjErr", 0644,
+ phba->hba_debugfs_root,
+ phba, writeApp, &lpfc_debugfs_op_dif_err);
+
+ phba->debug_writeRef =
+ debugfs_create_file_aux_num("writeRefInjErr", 0644,
+ phba->hba_debugfs_root,
+ phba, writeRef, &lpfc_debugfs_op_dif_err);
+
+ phba->debug_readGuard =
+ debugfs_create_file_aux_num("readGuardInjErr", 0644,
+ phba->hba_debugfs_root,
+ phba, readGuard, &lpfc_debugfs_op_dif_err);
+
+ phba->debug_readApp =
+ debugfs_create_file_aux_num("readAppInjErr", 0644,
+ phba->hba_debugfs_root,
+ phba, readApp, &lpfc_debugfs_op_dif_err);
+
+ phba->debug_readRef =
+ debugfs_create_file_aux_num("readRefInjErr", 0644,
+ phba->hba_debugfs_root,
+ phba, readRef, &lpfc_debugfs_op_dif_err);
/* Setup slow ring trace */
if (lpfc_debugfs_max_slow_ring_trc) {
@@ -6199,9 +6248,11 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
}
}
- debugfs_create_file("slow_ring_trace", 0644,
- phba->hba_debugfs_root, phba,
- &lpfc_debugfs_op_slow_ring_trc);
+ snprintf(name, sizeof(name), "slow_ring_trace");
+ phba->debug_slow_ring_trc =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_slow_ring_trc);
if (!phba->slow_ring_trc) {
phba->slow_ring_trc = kcalloc(
lpfc_debugfs_max_slow_ring_trc,
@@ -6211,13 +6262,16 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"0416 Cannot create debugfs "
"slow_ring buffer\n");
- goto out;
+ goto debug_failed;
}
atomic_set(&phba->slow_ring_trc_cnt, 0);
}
- debugfs_create_file("nvmeio_trc", 0644, phba->hba_debugfs_root,
- phba, &lpfc_debugfs_op_nvmeio_trc);
+ snprintf(name, sizeof(name), "nvmeio_trc");
+ phba->debug_nvmeio_trc =
+ debugfs_create_file(name, 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_nvmeio_trc);
atomic_set(&phba->nvmeio_trc_cnt, 0);
if (lpfc_debugfs_max_nvmeio_trc) {
@@ -6263,11 +6317,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
if (!vport->vport_debugfs_root) {
vport->vport_debugfs_root =
debugfs_create_dir(name, phba->hba_debugfs_root);
- if (IS_ERR(vport->vport_debugfs_root)) {
- lpfc_vlog_msg(vport, KERN_WARNING, LOG_INIT,
- "0529 Cannot create debugfs %s\n", name);
- return;
- }
atomic_inc(&phba->debugfs_vport_count);
}
@@ -6295,27 +6344,54 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"0418 Cannot create debugfs disc trace "
"buffer\n");
- goto out;
+ goto debug_failed;
}
atomic_set(&vport->disc_trc_cnt, 0);
- debugfs_create_file("discovery_trace", 0644, vport->vport_debugfs_root,
- vport, &lpfc_debugfs_op_disc_trc);
-
- debugfs_create_file("nodelist", 0644, vport->vport_debugfs_root, vport,
- &lpfc_debugfs_op_nodelist);
-
- debugfs_create_file("nvmestat", 0644, vport->vport_debugfs_root, vport,
- &lpfc_debugfs_op_nvmestat);
-
- debugfs_create_file("scsistat", 0644, vport->vport_debugfs_root, vport,
- &lpfc_debugfs_op_scsistat);
+ snprintf(name, sizeof(name), "discovery_trace");
+ vport->debug_disc_trc =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ vport->vport_debugfs_root,
+ vport, &lpfc_debugfs_op_disc_trc);
+ snprintf(name, sizeof(name), "nodelist");
+ vport->debug_nodelist =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ vport->vport_debugfs_root,
+ vport, &lpfc_debugfs_op_nodelist);
+
+ snprintf(name, sizeof(name), "nvmestat");
+ vport->debug_nvmestat =
+ debugfs_create_file(name, 0644,
+ vport->vport_debugfs_root,
+ vport, &lpfc_debugfs_op_nvmestat);
+
+ snprintf(name, sizeof(name), "scsistat");
+ vport->debug_scsistat =
+ debugfs_create_file(name, 0644,
+ vport->vport_debugfs_root,
+ vport, &lpfc_debugfs_op_scsistat);
+ if (IS_ERR(vport->debug_scsistat)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "4611 Cannot create debugfs scsistat\n");
+ goto debug_failed;
+ }
- debugfs_create_file("ioktime", 0644, vport->vport_debugfs_root, vport,
- &lpfc_debugfs_op_ioktime);
+ snprintf(name, sizeof(name), "ioktime");
+ vport->debug_ioktime =
+ debugfs_create_file(name, 0644,
+ vport->vport_debugfs_root,
+ vport, &lpfc_debugfs_op_ioktime);
+ if (IS_ERR(vport->debug_ioktime)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0815 Cannot create debugfs ioktime\n");
+ goto debug_failed;
+ }
- debugfs_create_file("hdwqstat", 0644, vport->vport_debugfs_root, vport,
- &lpfc_debugfs_op_hdwqstat);
+ snprintf(name, sizeof(name), "hdwqstat");
+ vport->debug_hdwqstat =
+ debugfs_create_file(name, 0644,
+ vport->vport_debugfs_root,
+ vport, &lpfc_debugfs_op_hdwqstat);
/*
* The following section is for additional directories/files for the
@@ -6323,58 +6399,93 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
*/
if (!pport_setup)
- return;
+ goto debug_failed;
/*
* iDiag debugfs root entry points for SLI4 device only
*/
if (phba->sli_rev < LPFC_SLI_REV4)
- return;
+ goto debug_failed;
+ snprintf(name, sizeof(name), "iDiag");
if (!phba->idiag_root) {
phba->idiag_root =
- debugfs_create_dir("iDiag", phba->hba_debugfs_root);
+ debugfs_create_dir(name, phba->hba_debugfs_root);
/* Initialize iDiag data structure */
memset(&idiag, 0, sizeof(idiag));
}
/* iDiag read PCI config space */
- debugfs_create_file("pciCfg", 0644, phba->idiag_root, phba,
- &lpfc_idiag_op_pciCfg);
- idiag.offset.last_rd = 0;
+ snprintf(name, sizeof(name), "pciCfg");
+ if (!phba->idiag_pci_cfg) {
+ phba->idiag_pci_cfg =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->idiag_root, phba, &lpfc_idiag_op_pciCfg);
+ idiag.offset.last_rd = 0;
+ }
/* iDiag PCI BAR access */
- debugfs_create_file("barAcc", 0644, phba->idiag_root, phba,
- &lpfc_idiag_op_barAcc);
- idiag.offset.last_rd = 0;
+ snprintf(name, sizeof(name), "barAcc");
+ if (!phba->idiag_bar_acc) {
+ phba->idiag_bar_acc =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->idiag_root, phba, &lpfc_idiag_op_barAcc);
+ idiag.offset.last_rd = 0;
+ }
/* iDiag get PCI function queue information */
- debugfs_create_file("queInfo", 0444, phba->idiag_root, phba,
- &lpfc_idiag_op_queInfo);
+ snprintf(name, sizeof(name), "queInfo");
+ if (!phba->idiag_que_info) {
+ phba->idiag_que_info =
+ debugfs_create_file(name, S_IFREG|S_IRUGO,
+ phba->idiag_root, phba, &lpfc_idiag_op_queInfo);
+ }
/* iDiag access PCI function queue */
- debugfs_create_file("queAcc", 0644, phba->idiag_root, phba,
- &lpfc_idiag_op_queAcc);
+ snprintf(name, sizeof(name), "queAcc");
+ if (!phba->idiag_que_acc) {
+ phba->idiag_que_acc =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->idiag_root, phba, &lpfc_idiag_op_queAcc);
+ }
/* iDiag access PCI function doorbell registers */
- debugfs_create_file("drbAcc", 0644, phba->idiag_root, phba,
- &lpfc_idiag_op_drbAcc);
+ snprintf(name, sizeof(name), "drbAcc");
+ if (!phba->idiag_drb_acc) {
+ phba->idiag_drb_acc =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->idiag_root, phba, &lpfc_idiag_op_drbAcc);
+ }
/* iDiag access PCI function control registers */
- debugfs_create_file("ctlAcc", 0644, phba->idiag_root, phba,
- &lpfc_idiag_op_ctlAcc);
+ snprintf(name, sizeof(name), "ctlAcc");
+ if (!phba->idiag_ctl_acc) {
+ phba->idiag_ctl_acc =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->idiag_root, phba, &lpfc_idiag_op_ctlAcc);
+ }
/* iDiag access mbox commands */
- debugfs_create_file("mbxAcc", 0644, phba->idiag_root, phba,
- &lpfc_idiag_op_mbxAcc);
+ snprintf(name, sizeof(name), "mbxAcc");
+ if (!phba->idiag_mbx_acc) {
+ phba->idiag_mbx_acc =
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+ phba->idiag_root, phba, &lpfc_idiag_op_mbxAcc);
+ }
/* iDiag extents access commands */
if (phba->sli4_hba.extents_in_use) {
- debugfs_create_file("extAcc", 0644, phba->idiag_root, phba,
- &lpfc_idiag_op_extAcc);
+ snprintf(name, sizeof(name), "extAcc");
+ if (!phba->idiag_ext_acc) {
+ phba->idiag_ext_acc =
+ debugfs_create_file(name,
+ S_IFREG|S_IRUGO|S_IWUSR,
+ phba->idiag_root, phba,
+ &lpfc_idiag_op_extAcc);
+ }
}
-out:
- /* alloc'ed items are kfree'd in lpfc_debugfs_terminate */
+
+debug_failed:
return;
#endif
}
@@ -6399,6 +6510,24 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
kfree(vport->disc_trc);
vport->disc_trc = NULL;
+ debugfs_remove(vport->debug_disc_trc); /* discovery_trace */
+ vport->debug_disc_trc = NULL;
+
+ debugfs_remove(vport->debug_nodelist); /* nodelist */
+ vport->debug_nodelist = NULL;
+
+ debugfs_remove(vport->debug_nvmestat); /* nvmestat */
+ vport->debug_nvmestat = NULL;
+
+ debugfs_remove(vport->debug_scsistat); /* scsistat */
+ vport->debug_scsistat = NULL;
+
+ debugfs_remove(vport->debug_ioktime); /* ioktime */
+ vport->debug_ioktime = NULL;
+
+ debugfs_remove(vport->debug_hdwqstat); /* hdwqstat */
+ vport->debug_hdwqstat = NULL;
+
if (vport->vport_debugfs_root) {
debugfs_remove(vport->vport_debugfs_root); /* vportX */
vport->vport_debugfs_root = NULL;
@@ -6406,12 +6535,113 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
}
if (atomic_read(&phba->debugfs_vport_count) == 0) {
+
+ debugfs_remove(phba->debug_multixri_pools); /* multixripools*/
+ phba->debug_multixri_pools = NULL;
+
+ debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
+ phba->debug_hbqinfo = NULL;
+
+ debugfs_remove(phba->debug_cgn_buffer);
+ phba->debug_cgn_buffer = NULL;
+
+ debugfs_remove(phba->debug_rx_monitor);
+ phba->debug_rx_monitor = NULL;
+
+ debugfs_remove(phba->debug_ras_log);
+ phba->debug_ras_log = NULL;
+
+#ifdef LPFC_HDWQ_LOCK_STAT
+ debugfs_remove(phba->debug_lockstat); /* lockstat */
+ phba->debug_lockstat = NULL;
+#endif
+ debugfs_remove(phba->debug_dumpHBASlim); /* HBASlim */
+ phba->debug_dumpHBASlim = NULL;
+
+ debugfs_remove(phba->debug_dumpHostSlim); /* HostSlim */
+ phba->debug_dumpHostSlim = NULL;
+
+ debugfs_remove(phba->debug_InjErrLBA); /* InjErrLBA */
+ phba->debug_InjErrLBA = NULL;
+
+ debugfs_remove(phba->debug_InjErrNPortID);
+ phba->debug_InjErrNPortID = NULL;
+
+ debugfs_remove(phba->debug_InjErrWWPN); /* InjErrWWPN */
+ phba->debug_InjErrWWPN = NULL;
+
+ debugfs_remove(phba->debug_writeGuard); /* writeGuard */
+ phba->debug_writeGuard = NULL;
+
+ debugfs_remove(phba->debug_writeApp); /* writeApp */
+ phba->debug_writeApp = NULL;
+
+ debugfs_remove(phba->debug_writeRef); /* writeRef */
+ phba->debug_writeRef = NULL;
+
+ debugfs_remove(phba->debug_readGuard); /* readGuard */
+ phba->debug_readGuard = NULL;
+
+ debugfs_remove(phba->debug_readApp); /* readApp */
+ phba->debug_readApp = NULL;
+
+ debugfs_remove(phba->debug_readRef); /* readRef */
+ phba->debug_readRef = NULL;
+
kfree(phba->slow_ring_trc);
phba->slow_ring_trc = NULL;
+ /* slow_ring_trace */
+ debugfs_remove(phba->debug_slow_ring_trc);
+ phba->debug_slow_ring_trc = NULL;
+
+ debugfs_remove(phba->debug_nvmeio_trc);
+ phba->debug_nvmeio_trc = NULL;
+
kfree(phba->nvmeio_trc);
phba->nvmeio_trc = NULL;
+ /*
+ * iDiag release
+ */
+ if (phba->sli_rev == LPFC_SLI_REV4) {
+ /* iDiag extAcc */
+ debugfs_remove(phba->idiag_ext_acc);
+ phba->idiag_ext_acc = NULL;
+
+ /* iDiag mbxAcc */
+ debugfs_remove(phba->idiag_mbx_acc);
+ phba->idiag_mbx_acc = NULL;
+
+ /* iDiag ctlAcc */
+ debugfs_remove(phba->idiag_ctl_acc);
+ phba->idiag_ctl_acc = NULL;
+
+ /* iDiag drbAcc */
+ debugfs_remove(phba->idiag_drb_acc);
+ phba->idiag_drb_acc = NULL;
+
+ /* iDiag queAcc */
+ debugfs_remove(phba->idiag_que_acc);
+ phba->idiag_que_acc = NULL;
+
+ /* iDiag queInfo */
+ debugfs_remove(phba->idiag_que_info);
+ phba->idiag_que_info = NULL;
+
+ /* iDiag barAcc */
+ debugfs_remove(phba->idiag_bar_acc);
+ phba->idiag_bar_acc = NULL;
+
+ /* iDiag pciCfg */
+ debugfs_remove(phba->idiag_pci_cfg);
+ phba->idiag_pci_cfg = NULL;
+
+ /* Finally remove the iDiag debugfs root */
+ debugfs_remove(phba->idiag_root);
+ phba->idiag_root = NULL;
+ }
+
if (phba->hba_debugfs_root) {
debugfs_remove(phba->hba_debugfs_root); /* fnX */
phba->hba_debugfs_root = NULL;

View File

@ -0,0 +1,198 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Use switch case statements in DIF debugfs handlers"
# Revert of ab563ef364bb83aeddbbfaa4f23f317cb3145f2e
scsi: lpfc: Use switch case statements in DIF debugfs handlers
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 892e2177663a..cd5180151321 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -2373,117 +2373,93 @@ lpfc_debugfs_dumpHostSlim_open(struct inode *inode, struct file *file)
static ssize_t
lpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
- size_t nbytes, loff_t *ppos)
+ size_t nbytes, loff_t *ppos)
{
struct lpfc_hba *phba = file->private_data;
int kind = debugfs_get_aux_num(file);
- char cbuf[32] = {0};
+ char cbuf[32];
+ uint64_t tmp = 0;
int cnt = 0;
- switch (kind) {
- case writeGuard:
- cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
- phba->lpfc_injerr_wgrd_cnt);
- break;
- case writeApp:
- cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
- phba->lpfc_injerr_wapp_cnt);
- break;
- case writeRef:
- cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
- phba->lpfc_injerr_wref_cnt);
- break;
- case readGuard:
- cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
- phba->lpfc_injerr_rgrd_cnt);
- break;
- case readApp:
- cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
- phba->lpfc_injerr_rapp_cnt);
- break;
- case readRef:
- cnt = scnprintf(cbuf, sizeof(cbuf), "%u\n",
- phba->lpfc_injerr_rref_cnt);
- break;
- case InjErrNPortID:
- cnt = scnprintf(cbuf, sizeof(cbuf), "0x%06x\n",
+ if (kind == writeGuard)
+ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wgrd_cnt);
+ else if (kind == writeApp)
+ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wapp_cnt);
+ else if (kind == writeRef)
+ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wref_cnt);
+ else if (kind == readGuard)
+ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rgrd_cnt);
+ else if (kind == readApp)
+ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rapp_cnt);
+ else if (kind == readRef)
+ cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rref_cnt);
+ else if (kind == InjErrNPortID)
+ cnt = scnprintf(cbuf, 32, "0x%06x\n",
phba->lpfc_injerr_nportid);
- break;
- case InjErrWWPN:
- cnt = scnprintf(cbuf, sizeof(cbuf), "0x%016llx\n",
- be64_to_cpu(phba->lpfc_injerr_wwpn.u.wwn_be));
- break;
- case InjErrLBA:
- if (phba->lpfc_injerr_lba == LPFC_INJERR_LBA_OFF)
- cnt = scnprintf(cbuf, sizeof(cbuf), "off\n");
+ else if (kind == InjErrWWPN) {
+ memcpy(&tmp, &phba->lpfc_injerr_wwpn, sizeof(struct lpfc_name));
+ tmp = cpu_to_be64(tmp);
+ cnt = scnprintf(cbuf, 32, "0x%016llx\n", tmp);
+ } else if (kind == InjErrLBA) {
+ if (phba->lpfc_injerr_lba == (sector_t)(-1))
+ cnt = scnprintf(cbuf, 32, "off\n");
else
- cnt = scnprintf(cbuf, sizeof(cbuf), "0x%llx\n",
- (uint64_t)phba->lpfc_injerr_lba);
- break;
- default:
- lpfc_log_msg(phba, KERN_WARNING, LOG_INIT,
- "0547 Unknown debugfs error injection entry\n");
- break;
- }
+ cnt = scnprintf(cbuf, 32, "0x%llx\n",
+ (uint64_t) phba->lpfc_injerr_lba);
+ } else
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0547 Unknown debugfs error injection entry\n");
return simple_read_from_buffer(buf, nbytes, ppos, &cbuf, cnt);
}
static ssize_t
lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
- size_t nbytes, loff_t *ppos)
+ size_t nbytes, loff_t *ppos)
{
struct lpfc_hba *phba = file->private_data;
int kind = debugfs_get_aux_num(file);
- char dstbuf[33] = {0};
- unsigned long long tmp;
- unsigned long size;
+ char dstbuf[33];
+ uint64_t tmp = 0;
+ int size;
- size = (nbytes < (sizeof(dstbuf) - 1)) ? nbytes : (sizeof(dstbuf) - 1);
+ memset(dstbuf, 0, 33);
+ size = (nbytes < 32) ? nbytes : 32;
if (copy_from_user(dstbuf, buf, size))
return -EFAULT;
- if (kstrtoull(dstbuf, 0, &tmp)) {
- if (kind != InjErrLBA || !strstr(dstbuf, "off"))
- return -EINVAL;
+ if (kind == InjErrLBA) {
+ if ((dstbuf[0] == 'o') && (dstbuf[1] == 'f') &&
+ (dstbuf[2] == 'f'))
+ tmp = (uint64_t)(-1);
}
- switch (kind) {
- case writeGuard:
+ if ((tmp == 0) && (kstrtoull(dstbuf, 0, &tmp)))
+ return -EINVAL;
+
+ if (kind == writeGuard)
phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp;
- break;
- case writeApp:
+ else if (kind == writeApp)
phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp;
- break;
- case writeRef:
+ else if (kind == writeRef)
phba->lpfc_injerr_wref_cnt = (uint32_t)tmp;
- break;
- case readGuard:
+ else if (kind == readGuard)
phba->lpfc_injerr_rgrd_cnt = (uint32_t)tmp;
- break;
- case readApp:
+ else if (kind == readApp)
phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp;
- break;
- case readRef:
+ else if (kind == readRef)
phba->lpfc_injerr_rref_cnt = (uint32_t)tmp;
- break;
- case InjErrLBA:
- if (strstr(dstbuf, "off"))
- phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
- else
- phba->lpfc_injerr_lba = (sector_t)tmp;
- break;
- case InjErrNPortID:
+ else if (kind == InjErrLBA)
+ phba->lpfc_injerr_lba = (sector_t)tmp;
+ else if (kind == InjErrNPortID)
phba->lpfc_injerr_nportid = (uint32_t)(tmp & Mask_DID);
- break;
- case InjErrWWPN:
- phba->lpfc_injerr_wwpn.u.wwn_be = cpu_to_be64(tmp);
- break;
- default:
- lpfc_log_msg(phba, KERN_WARNING, LOG_INIT,
- "0548 Unknown debugfs error injection entry\n");
- break;
- }
+ else if (kind == InjErrWWPN) {
+ tmp = cpu_to_be64(tmp);
+ memcpy(&phba->lpfc_injerr_wwpn, &tmp, sizeof(struct lpfc_name));
+ } else
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0548 Unknown debugfs error injection entry\n");
+
return nbytes;
}
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index b287d39ad033..32298285ea5e 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -366,7 +366,6 @@ struct lpfc_name {
} s;
uint8_t wwn[8];
uint64_t name __packed __aligned(4);
- __be64 wwn_be __packed __aligned(4);
} u;
};

View File

@ -0,0 +1,18 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Fix memory leak when nvmeio_trc debugfs entry is used"
# Revert of 7188eff1a4a6e2f9144684df495ee5bcce503c8d
scsi: lpfc: Fix memory leak when nvmeio_trc debugfs entry is used
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index cd5180151321..82ab7660572f 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -6280,6 +6280,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
}
phba->nvmeio_trc_on = 1;
phba->nvmeio_trc_output_idx = 0;
+ phba->nvmeio_trc = NULL;
} else {
nvmeio_off:
phba->nvmeio_trc_size = 0;

View File

@ -0,0 +1,20 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Define size of debugfs entry for xri rebalancing"
# Revert of 5eec6dfb351f6412694cfb294f1a0d153a9b8142
scsi: lpfc: Define size of debugfs entry for xri rebalancing
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
index 566dd84e0677..f319f3af0400 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.h
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -44,9 +44,6 @@
/* hbqinfo output buffer size */
#define LPFC_HBQINFO_SIZE 8192
-/* hdwqinfo output buffer size */
-#define LPFC_HDWQINFO_SIZE 8192
-
/* nvmestat output buffer size */
#define LPFC_NVMESTAT_SIZE 8192
#define LPFC_IOKTIME_SIZE 8192

View File

@ -0,0 +1,78 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Ensure PLOGI_ACC is sent prior to PRLI in Point to Point topology"
# Revert of 123878d674dbeccfa9efa5b489d2a538dd740f7c
scsi: lpfc: Ensure PLOGI_ACC is sent prior to PRLI in Point to Point topology
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 0630d109e767..3cc9d9829551 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -5338,12 +5338,12 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
ulp_status, ulp_word4, did);
/* ELS response tag <ulpIoTag> completes */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
- "0110 ELS response tag x%x completes fc_flag x%lx"
+ "0110 ELS response tag x%x completes "
"Data: x%x x%x x%x x%x x%lx x%x x%x x%x %p %p\n",
- iotag, vport->fc_flag, ulp_status, ulp_word4, tmo,
+ iotag, ulp_status, ulp_word4, tmo,
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
ndlp->nlp_rpi, kref_read(&ndlp->kref), mbox, ndlp);
- if (mbox && !test_bit(FC_PT2PT, &vport->fc_flag)) {
+ if (mbox) {
if (ulp_status == 0 &&
test_bit(NLP_ACC_REGLOGIN, &ndlp->nlp_flag)) {
if (!lpfc_unreg_rpi(vport, ndlp) &&
@@ -5402,10 +5402,6 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
out_free_mbox:
lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
- } else if (mbox && test_bit(FC_PT2PT, &vport->fc_flag) &&
- test_bit(NLP_ACC_REGLOGIN, &ndlp->nlp_flag)) {
- lpfc_mbx_cmpl_reg_login(phba, mbox);
- clear_bit(NLP_ACC_REGLOGIN, &ndlp->nlp_flag);
}
out:
if (ndlp && shost) {
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 1e331b76dff4..5aa21c683ac6 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -326,14 +326,8 @@ lpfc_defer_plogi_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *login_mbox)
/* Now that REG_RPI completed successfully,
* we can now proceed with sending the PLOGI ACC.
*/
- if (test_bit(FC_PT2PT, &ndlp->vport->fc_flag)) {
- rc = lpfc_els_rsp_acc(login_mbox->vport, ELS_CMD_PLOGI,
- save_iocb, ndlp, login_mbox);
- } else {
- rc = lpfc_els_rsp_acc(login_mbox->vport, ELS_CMD_PLOGI,
- save_iocb, ndlp, NULL);
- }
-
+ rc = lpfc_els_rsp_acc(login_mbox->vport, ELS_CMD_PLOGI,
+ save_iocb, ndlp, NULL);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"4576 PLOGI ACC fails pt2pt discovery: "
@@ -341,16 +335,9 @@ lpfc_defer_plogi_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *login_mbox)
}
}
- /* If this is a fabric topology, complete the reg_rpi and prli now.
- * For Pt2Pt, the reg_rpi and PRLI are deferred until after the LS_ACC
- * completes. This ensures, in Pt2Pt, that the PLOGI LS_ACC is sent
- * before the PRLI.
- */
- if (!test_bit(FC_PT2PT, &ndlp->vport->fc_flag)) {
- /* Now process the REG_RPI cmpl */
- lpfc_mbx_cmpl_reg_login(phba, login_mbox);
- clear_bit(NLP_ACC_REGLOGIN, &ndlp->nlp_flag);
- }
+ /* Now process the REG_RPI cmpl */
+ lpfc_mbx_cmpl_reg_login(phba, login_mbox);
+ clear_bit(NLP_ACC_REGLOGIN, &ndlp->nlp_flag);
kfree(save_iocb);
}

View File

@ -0,0 +1,45 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Check return status of lpfc_reset_flush_io_context during TGT_RESET"
# Revert of 42cd66663ae18668544eaee105d82bea2a5921f4
scsi: lpfc: Check return status of lpfc_reset_flush_io_context during TGT_RESET
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 1638fc3fc916..0f145022aaaa 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -5943,7 +5943,7 @@ lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct fc_rport *rport)
/**
* lpfc_reset_flush_io_context -
* @vport: The virtual port (scsi_host) for the flush context
- * @tgt_id: If aborting by Target context - specifies the target id
+ * @tgt_id: If aborting by Target contect - specifies the target id
* @lun_id: If aborting by Lun context - specifies the lun id
* @context: specifies the context level to flush at.
*
@@ -6117,14 +6117,8 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
spin_unlock_irqrestore(&pnode->lock, flags);
}
- status = lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
- LPFC_CTX_TGT);
- if (status != SUCCESS) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
- "0726 Target Reset flush status x%x\n",
- status);
- return status;
- }
+ lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
+ LPFC_CTX_TGT);
return FAST_IO_FAIL;
}
@@ -6217,7 +6211,7 @@ lpfc_host_reset_handler(struct scsi_cmnd *cmnd)
int rc, ret = SUCCESS;
lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
- "3172 SCSI layer issued Host Reset\n");
+ "3172 SCSI layer issued Host Reset Data:\n");
lpfc_offline_prep(phba, LPFC_MBX_WAIT);
lpfc_offline(phba);

View File

@ -0,0 +1,22 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Decrement ndlp kref after FDISC retries exhausted"
# Revert of 34a2ffe35bb05d7eeb7353737c22efaead84158c
scsi: lpfc: Decrement ndlp kref after FDISC retries exhausted
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 3cc9d9829551..729bee3c657e 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -11264,11 +11264,6 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
"0126 FDISC cmpl status: x%x/x%x)\n",
ulp_status, ulp_word4);
-
- /* drop initial reference */
- if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
- lpfc_nlp_put(ndlp);
-
goto fdisc_failed;
}

View File

@ -0,0 +1,41 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Remove ndlp kref decrement clause for F_Port_Ctrl in lpfc_cleanup"
# Revert of 0cfe4ba53cd1fe0efede8ebdc450d75daf07a3f2
scsi: lpfc: Remove ndlp kref decrement clause for F_Port_Ctrl in lpfc_cleanup
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 729bee3c657e..853cf7649451 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -12012,11 +12012,7 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba,
sglq_entry->state = SGL_FREED;
spin_unlock_irqrestore(&phba->sli4_hba.sgl_list_lock,
iflag);
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_SLI |
- LOG_DISCOVERY | LOG_NODE,
- "0732 ELS XRI ABORT on Node: ndlp=x%px "
- "xri=x%x\n",
- ndlp, xri);
+
if (ndlp) {
lpfc_set_rrq_active(phba, ndlp,
sglq_entry->sli4_lxritag,
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 2f3629ef64e6..c681bd0ecbbc 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -3057,6 +3057,13 @@ lpfc_cleanup(struct lpfc_vport *vport)
lpfc_vmid_vport_cleanup(vport);
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+ if (vport->port_type != LPFC_PHYSICAL_PORT &&
+ ndlp->nlp_DID == Fabric_DID) {
+ /* Just free up ndlp with Fabric_DID for vports */
+ lpfc_nlp_put(ndlp);
+ continue;
+ }
+
if (ndlp->nlp_DID == Fabric_Cntl_DID &&
ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
lpfc_nlp_put(ndlp);

View File

@ -0,0 +1,27 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Clean up allocated queues when queue setup mbox commands fail"
# Revert of dd7b6c550a31baa747b697cf9746e05c6d36464e
scsi: lpfc: Clean up allocated queues when queue setup mbox commands fail
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index e658f2a914d9..c6bfd8e97f59 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -8823,7 +8823,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
if (unlikely(rc)) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0381 Error %d during queue setup.\n", rc);
- goto out_destroy_queue;
+ goto out_stop_timers;
}
/* Initialize the driver internal SLI layer lists. */
lpfc_sli4_setup(phba);
@@ -9106,6 +9106,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
lpfc_free_iocb_list(phba);
out_destroy_queue:
lpfc_sli4_queue_destroy(phba);
+out_stop_timers:
lpfc_stop_hba_timers(phba);
out_free_mbox:
mempool_free(mboxq, phba->mbox_mem_pool);

View File

@ -0,0 +1,34 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Abort outstanding ELS WQEs regardless of if rmmod is in progress"
# Revert of 70672fd3d84f298f276d2e2604b1d385e8b553fc
scsi: lpfc: Abort outstanding ELS WQEs regardless of if rmmod is in progress
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index c6bfd8e97f59..393937c727f6 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -12446,11 +12446,19 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/*
- * Always abort the outstanding WQE and set the IA bit correctly
- * for the context. This is necessary for correctly removing
- * outstanding ndlp reference counts when the CQE completes with
- * the XB bit set.
+ * If we're unloading, don't abort iocb on the ELS ring, but change
+ * the callback so that nothing happens when it finishes.
*/
+ if (test_bit(FC_UNLOADING, &vport->load_flag) &&
+ pring->ringno == LPFC_ELS_RING) {
+ if (cmdiocb->cmd_flag & LPFC_IO_FABRIC)
+ cmdiocb->fabric_cmd_cmpl = lpfc_ignore_els_cmpl;
+ else
+ cmdiocb->cmd_cmpl = lpfc_ignore_els_cmpl;
+ return retval;
+ }
+
+ /* issue ABTS for this IOCB based on iotag */
abtsiocbp = __lpfc_sli_get_iocbq(phba);
if (abtsiocbp == NULL)
return IOCB_NORESOURCE;

View File

@ -0,0 +1,61 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Remove unused member variables in struct lpfc_hba and lpfc_vport"
# Revert of 12503dd7ac27930b8889b15014474829c56c11f2
scsi: lpfc: Remove unused member variables in struct lpfc_hba and lpfc_vport
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 0a43be24cee8..bf8ec461c0ee 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -662,12 +662,15 @@ struct lpfc_vport {
uint32_t num_disc_nodes; /* in addition to hba_state */
uint32_t gidft_inp; /* cnt of outstanding GID_FTs */
+ uint32_t fc_nlp_cnt; /* outstanding NODELIST requests */
uint32_t fc_rscn_id_cnt; /* count of RSCNs payloads in list */
uint32_t fc_rscn_flush; /* flag use of fc_rscn_id_list */
struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN];
struct lpfc_name fc_nodename; /* fc nodename */
struct lpfc_name fc_portname; /* fc portname */
+ struct lpfc_work_evt disc_timeout_evt;
+
struct timer_list fc_disctmo; /* Discovery rescue timer */
uint8_t fc_ns_retry; /* retries for fabric nameserver */
uint32_t fc_prli_sent; /* cntr for outstanding PRLIs */
@@ -765,6 +768,7 @@ struct lpfc_vport {
/* There is a single nvme instance per vport. */
struct nvme_fc_local_port *localport;
uint8_t nvmei_support; /* driver supports NVME Initiator */
+ uint32_t last_fcp_wqidx;
uint32_t rcv_flogi_cnt; /* How many unsol FLOGIs ACK'd. */
};
@@ -1057,6 +1061,8 @@ struct lpfc_hba {
struct lpfc_dmabuf hbqslimp;
+ uint16_t pci_cfg_value;
+
uint8_t fc_linkspeed; /* Link speed after last READ_LA */
uint32_t fc_eventTag; /* event tag for link attention */
@@ -1083,6 +1089,7 @@ struct lpfc_hba {
struct lpfc_stats fc_stat;
+ struct lpfc_nodelist fc_fcpnodev; /* nodelist entry for no device */
uint32_t nport_event_cnt; /* timestamp for nlplist entry */
uint8_t wwnn[8];
@@ -1223,6 +1230,9 @@ struct lpfc_hba {
uint32_t hbq_count; /* Count of configured HBQs */
struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies */
+ atomic_t fcp_qidx; /* next FCP WQ (RR Policy) */
+ atomic_t nvme_qidx; /* next NVME WQ (RR Policy) */
+
phys_addr_t pci_bar0_map; /* Physical address for PCI BAR0 */
phys_addr_t pci_bar1_map; /* Physical address for PCI BAR1 */
phys_addr_t pci_bar2_map; /* Physical address for PCI BAR2 */

View File

@ -0,0 +1,19 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Use int type to store negative error codes"
# Revert of dfe48c6bb068813490395974ec06f38342da2d6f
scsi: lpfc: Use int type to store negative error codes
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 393937c727f6..7d459a88ec5a 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -21382,7 +21382,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp,
struct lpfc_sglq *sglq;
struct lpfc_sli_ring *pring;
unsigned long iflags;
- int ret = 0;
+ uint32_t ret = 0;
/* NVME_LS and NVME_LS ABTS requests. */
if (pwqe->cmd_flag & LPFC_IO_NVME_LS) {

View File

@ -0,0 +1,41 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: use min() to improve code"
# Revert of 548552ed278e8ebd0e27ae1461b7fe891f268825
scsi: lpfc: use min() to improve code
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index c681bd0ecbbc..b78edd11d9d4 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -8298,7 +8298,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
phba->cfg_total_seg_cnt, phba->cfg_scsi_seg_cnt,
phba->cfg_nvme_seg_cnt);
- i = min(phba->cfg_sg_dma_buf_size, SLI4_PAGE_SIZE);
+ if (phba->cfg_sg_dma_buf_size < SLI4_PAGE_SIZE)
+ i = phba->cfg_sg_dma_buf_size;
+ else
+ i = SLI4_PAGE_SIZE;
phba->lpfc_sg_dma_buf_pool =
dma_pool_create("lpfc_sg_dma_buf_pool",
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 47818cf5b2f3..d539ee15a806 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -1234,8 +1234,12 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
if ((phba->cfg_nvme_enable_fb) &&
test_bit(NLP_FIRSTBURST, &pnode->nlp_flag)) {
req_len = lpfc_ncmd->nvmeCmd->payload_length;
- wqe->fcp_iwrite.initial_xfer_len = min(req_len,
- pnode->nvme_fb_size);
+ if (req_len < pnode->nvme_fb_size)
+ wqe->fcp_iwrite.initial_xfer_len =
+ req_len;
+ else
+ wqe->fcp_iwrite.initial_xfer_len =
+ pnode->nvme_fb_size;
} else {
wqe->fcp_iwrite.initial_xfer_len = 0;
}

View File

@ -0,0 +1,19 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Fix wrong function reference in a comment"
# Revert of 2936f5bdfbcc6669ca78472d83afe96613281b41
scsi: lpfc: Fix wrong function reference in a comment
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 8653839ee728..3d70cc517573 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -666,7 +666,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
* Take early refcount for outstanding I/O requests we schedule during
* delete processing for unreg_vpi. Always keep this before
* scsi_remove_host() as we can no longer obtain a reference through
- * scsi_host_get() after scsi_remove_host as shost is set to SHOST_DEL.
+ * scsi_host_get() after scsi_host_remove as shost is set to SHOST_DEL.
*/
if (!scsi_host_get(shost))
return VPORT_INVAL;

View File

@ -0,0 +1,206 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "lpfc: don't use file->f_path.dentry for comparisons"
# Revert of 6190ea44e36d9cc8416eef6efdd1561ee22696c2
lpfc: don't use file->f_path.dentry for comparisons
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 82ab7660572f..52ad5449fa26 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -2375,32 +2375,32 @@ static ssize_t
lpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos)
{
+ struct dentry *dent = file->f_path.dentry;
struct lpfc_hba *phba = file->private_data;
- int kind = debugfs_get_aux_num(file);
char cbuf[32];
uint64_t tmp = 0;
int cnt = 0;
- if (kind == writeGuard)
+ if (dent == phba->debug_writeGuard)
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wgrd_cnt);
- else if (kind == writeApp)
+ else if (dent == phba->debug_writeApp)
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wapp_cnt);
- else if (kind == writeRef)
+ else if (dent == phba->debug_writeRef)
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wref_cnt);
- else if (kind == readGuard)
+ else if (dent == phba->debug_readGuard)
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rgrd_cnt);
- else if (kind == readApp)
+ else if (dent == phba->debug_readApp)
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rapp_cnt);
- else if (kind == readRef)
+ else if (dent == phba->debug_readRef)
cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rref_cnt);
- else if (kind == InjErrNPortID)
+ else if (dent == phba->debug_InjErrNPortID)
cnt = scnprintf(cbuf, 32, "0x%06x\n",
phba->lpfc_injerr_nportid);
- else if (kind == InjErrWWPN) {
+ else if (dent == phba->debug_InjErrWWPN) {
memcpy(&tmp, &phba->lpfc_injerr_wwpn, sizeof(struct lpfc_name));
tmp = cpu_to_be64(tmp);
cnt = scnprintf(cbuf, 32, "0x%016llx\n", tmp);
- } else if (kind == InjErrLBA) {
+ } else if (dent == phba->debug_InjErrLBA) {
if (phba->lpfc_injerr_lba == (sector_t)(-1))
cnt = scnprintf(cbuf, 32, "off\n");
else
@@ -2417,8 +2417,8 @@ static ssize_t
lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
size_t nbytes, loff_t *ppos)
{
+ struct dentry *dent = file->f_path.dentry;
struct lpfc_hba *phba = file->private_data;
- int kind = debugfs_get_aux_num(file);
char dstbuf[33];
uint64_t tmp = 0;
int size;
@@ -2428,7 +2428,7 @@ lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
if (copy_from_user(dstbuf, buf, size))
return -EFAULT;
- if (kind == InjErrLBA) {
+ if (dent == phba->debug_InjErrLBA) {
if ((dstbuf[0] == 'o') && (dstbuf[1] == 'f') &&
(dstbuf[2] == 'f'))
tmp = (uint64_t)(-1);
@@ -2437,23 +2437,23 @@ lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
if ((tmp == 0) && (kstrtoull(dstbuf, 0, &tmp)))
return -EINVAL;
- if (kind == writeGuard)
+ if (dent == phba->debug_writeGuard)
phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp;
- else if (kind == writeApp)
+ else if (dent == phba->debug_writeApp)
phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp;
- else if (kind == writeRef)
+ else if (dent == phba->debug_writeRef)
phba->lpfc_injerr_wref_cnt = (uint32_t)tmp;
- else if (kind == readGuard)
+ else if (dent == phba->debug_readGuard)
phba->lpfc_injerr_rgrd_cnt = (uint32_t)tmp;
- else if (kind == readApp)
+ else if (dent == phba->debug_readApp)
phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp;
- else if (kind == readRef)
+ else if (dent == phba->debug_readRef)
phba->lpfc_injerr_rref_cnt = (uint32_t)tmp;
- else if (kind == InjErrLBA)
+ else if (dent == phba->debug_InjErrLBA)
phba->lpfc_injerr_lba = (sector_t)tmp;
- else if (kind == InjErrNPortID)
+ else if (dent == phba->debug_InjErrNPortID)
phba->lpfc_injerr_nportid = (uint32_t)(tmp & Mask_DID);
- else if (kind == InjErrWWPN) {
+ else if (dent == phba->debug_InjErrWWPN) {
tmp = cpu_to_be64(tmp);
memcpy(&phba->lpfc_injerr_wwpn, &tmp, sizeof(struct lpfc_name));
} else
@@ -6160,51 +6160,60 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
phba->debug_dumpHostSlim = NULL;
/* Setup DIF Error Injections */
+ snprintf(name, sizeof(name), "InjErrLBA");
phba->debug_InjErrLBA =
- debugfs_create_file_aux_num("InjErrLBA", 0644,
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
phba->hba_debugfs_root,
- phba, InjErrLBA, &lpfc_debugfs_op_dif_err);
+ phba, &lpfc_debugfs_op_dif_err);
phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF;
+ snprintf(name, sizeof(name), "InjErrNPortID");
phba->debug_InjErrNPortID =
- debugfs_create_file_aux_num("InjErrNPortID", 0644,
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
phba->hba_debugfs_root,
- phba, InjErrNPortID, &lpfc_debugfs_op_dif_err);
+ phba, &lpfc_debugfs_op_dif_err);
+ snprintf(name, sizeof(name), "InjErrWWPN");
phba->debug_InjErrWWPN =
- debugfs_create_file_aux_num("InjErrWWPN", 0644,
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
phba->hba_debugfs_root,
- phba, InjErrWWPN, &lpfc_debugfs_op_dif_err);
+ phba, &lpfc_debugfs_op_dif_err);
+ snprintf(name, sizeof(name), "writeGuardInjErr");
phba->debug_writeGuard =
- debugfs_create_file_aux_num("writeGuardInjErr", 0644,
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
phba->hba_debugfs_root,
- phba, writeGuard, &lpfc_debugfs_op_dif_err);
+ phba, &lpfc_debugfs_op_dif_err);
+ snprintf(name, sizeof(name), "writeAppInjErr");
phba->debug_writeApp =
- debugfs_create_file_aux_num("writeAppInjErr", 0644,
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
phba->hba_debugfs_root,
- phba, writeApp, &lpfc_debugfs_op_dif_err);
+ phba, &lpfc_debugfs_op_dif_err);
+ snprintf(name, sizeof(name), "writeRefInjErr");
phba->debug_writeRef =
- debugfs_create_file_aux_num("writeRefInjErr", 0644,
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
phba->hba_debugfs_root,
- phba, writeRef, &lpfc_debugfs_op_dif_err);
+ phba, &lpfc_debugfs_op_dif_err);
+ snprintf(name, sizeof(name), "readGuardInjErr");
phba->debug_readGuard =
- debugfs_create_file_aux_num("readGuardInjErr", 0644,
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
phba->hba_debugfs_root,
- phba, readGuard, &lpfc_debugfs_op_dif_err);
+ phba, &lpfc_debugfs_op_dif_err);
+ snprintf(name, sizeof(name), "readAppInjErr");
phba->debug_readApp =
- debugfs_create_file_aux_num("readAppInjErr", 0644,
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
phba->hba_debugfs_root,
- phba, readApp, &lpfc_debugfs_op_dif_err);
+ phba, &lpfc_debugfs_op_dif_err);
+ snprintf(name, sizeof(name), "readRefInjErr");
phba->debug_readRef =
- debugfs_create_file_aux_num("readRefInjErr", 0644,
+ debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
phba->hba_debugfs_root,
- phba, readRef, &lpfc_debugfs_op_dif_err);
+ phba, &lpfc_debugfs_op_dif_err);
/* Setup slow ring trace */
if (lpfc_debugfs_max_slow_ring_trc) {
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
index f319f3af0400..8d2e8d05bbc0 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.h
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -322,17 +322,6 @@ enum {
* discovery */
#endif /* H_LPFC_DEBUG_FS */
-enum {
- writeGuard = 1,
- writeApp,
- writeRef,
- readGuard,
- readApp,
- readRef,
- InjErrLBA,
- InjErrNPortID,
- InjErrWWPN,
-};
/*
* Driver debug utility routines outside of debugfs. The debug utility

View File

@ -0,0 +1,19 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Update lpfc version to 14.4.0.10"
# Revert of 962ac7d119e10f5ce809aea5c67e2e20415fe24e
scsi: lpfc: Update lpfc version to 14.4.0.10
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 9ee3a3a4ec4d..749688aa8a82 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "14.4.0.10"
+#define LPFC_DRIVER_VERSION "14.4.0.9"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */

View File

@ -0,0 +1,71 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Copyright updates for 14.4.0.10 patches"
# Revert of 6826b3ee8d47e7dea2f29e327e33a1a40433eaaf
scsi: lpfc: Copyright updates for 14.4.0.10 patches
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 94f612d1fef0..aa6c2b0f9907 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 52ad5449fa26..1b6cdadc7426 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2007-2015 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index bc709786e6af..dd9f170fbdc8 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2009-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 0f145022aaaa..0786952cd7d5 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index fd6dab157887..e42b44fcc7f6 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2009-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *

View File

@ -0,0 +1,141 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Modify end-of-life adapters' model descriptions"
# Revert of 19ab9fa7f11f1675a15dda0cd6606d71f7599cfd
scsi: lpfc: Modify end-of-life adapters' model descriptions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index b78edd11d9d4..8007c961bbd7 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2627,33 +2627,27 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
"Obsolete, Unsupported Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_BMID:
- m = (typeof(m)){"LP1150", "PCI-X2",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LP1150", "PCI-X2", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_BSMB:
m = (typeof(m)){"LP111", "PCI-X2",
"Obsolete, Unsupported Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_ZEPHYR:
- m = (typeof(m)){"LPe11000", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LPe11000", "PCIe", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_ZEPHYR_SCSP:
- m = (typeof(m)){"LPe11000", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LPe11000", "PCIe", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_ZEPHYR_DCSP:
- m = (typeof(m)){"LP2105", "PCIe",
- "Obsolete, Unsupported FCoE Adapter"};
+ m = (typeof(m)){"LP2105", "PCIe", "FCoE Adapter"};
GE = 1;
break;
case PCI_DEVICE_ID_ZMID:
- m = (typeof(m)){"LPe1150", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LPe1150", "PCIe", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_ZSMB:
- m = (typeof(m)){"LPe111", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LPe111", "PCIe", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_LP101:
m = (typeof(m)){"LP101", "PCI-X",
@@ -2672,28 +2666,22 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
"Obsolete, Unsupported Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_SAT:
- m = (typeof(m)){"LPe12000", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LPe12000", "PCIe", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_SAT_MID:
- m = (typeof(m)){"LPe1250", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LPe1250", "PCIe", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_SAT_SMB:
- m = (typeof(m)){"LPe121", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LPe121", "PCIe", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_SAT_DCSP:
- m = (typeof(m)){"LPe12002-SP", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LPe12002-SP", "PCIe", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_SAT_SCSP:
- m = (typeof(m)){"LPe12000-SP", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LPe12000-SP", "PCIe", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_SAT_S:
- m = (typeof(m)){"LPe12000-S", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LPe12000-S", "PCIe", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_PROTEUS_VF:
m = (typeof(m)){"LPev12000", "PCIe IOV",
@@ -2709,25 +2697,22 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
break;
case PCI_DEVICE_ID_TIGERSHARK:
oneConnect = 1;
- m = (typeof(m)){"OCe10100", "PCIe",
- "Obsolete, Unsupported FCoE Adapter"};
+ m = (typeof(m)){"OCe10100", "PCIe", "FCoE"};
break;
case PCI_DEVICE_ID_TOMCAT:
oneConnect = 1;
- m = (typeof(m)){"OCe11100", "PCIe",
- "Obsolete, Unsupported FCoE Adapter"};
+ m = (typeof(m)){"OCe11100", "PCIe", "FCoE"};
break;
case PCI_DEVICE_ID_FALCON:
m = (typeof(m)){"LPSe12002-ML1-E", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ "EmulexSecure Fibre"};
break;
case PCI_DEVICE_ID_BALIUS:
m = (typeof(m)){"LPVe12002", "PCIe Shared I/O",
"Obsolete, Unsupported Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_LANCER_FC:
- m = (typeof(m)){"LPe16000", "PCIe",
- "Obsolete, Unsupported Fibre Channel Adapter"};
+ m = (typeof(m)){"LPe16000", "PCIe", "Fibre Channel Adapter"};
break;
case PCI_DEVICE_ID_LANCER_FC_VF:
m = (typeof(m)){"LPe16000", "PCIe",
@@ -2735,13 +2720,12 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
break;
case PCI_DEVICE_ID_LANCER_FCOE:
oneConnect = 1;
- m = (typeof(m)){"OCe15100", "PCIe",
- "Obsolete, Unsupported FCoE Adapter"};
+ m = (typeof(m)){"OCe15100", "PCIe", "FCoE"};
break;
case PCI_DEVICE_ID_LANCER_FCOE_VF:
oneConnect = 1;
m = (typeof(m)){"OCe15100", "PCIe",
- "Obsolete, Unsupported FCoE Adapter"};
+ "Obsolete, Unsupported FCoE"};
break;
case PCI_DEVICE_ID_LANCER_G6_FC:
m = (typeof(m)){"LPe32000", "PCIe", "Fibre Channel Adapter"};
@@ -2755,8 +2739,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
case PCI_DEVICE_ID_SKYHAWK:
case PCI_DEVICE_ID_SKYHAWK_VF:
oneConnect = 1;
- m = (typeof(m)){"OCe14000", "PCIe",
- "Obsolete, Unsupported FCoE Adapter"};
+ m = (typeof(m)){"OCe14000", "PCIe", "FCoE"};
break;
default:
m = (typeof(m)){"Unknown", "", ""};

View File

@ -0,0 +1,105 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Revise CQ_CREATE_SET mailbox bitfield definitions"
# Revert of 47f0e888d0df9c51919a5258f9019c6a619bb8ad
scsi: lpfc: Revise CQ_CREATE_SET mailbox bitfield definitions
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index dd9f170fbdc8..2dedb273b091 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -1328,9 +1328,6 @@ struct cq_context {
#define LPFC_CQ_CNT_512 0x1
#define LPFC_CQ_CNT_1024 0x2
#define LPFC_CQ_CNT_WORD7 0x3
-#define lpfc_cq_context_cqe_sz_SHIFT 25
-#define lpfc_cq_context_cqe_sz_MASK 0x00000003
-#define lpfc_cq_context_cqe_sz_WORD word0
#define lpfc_cq_context_autovalid_SHIFT 15
#define lpfc_cq_context_autovalid_MASK 0x00000001
#define lpfc_cq_context_autovalid_WORD word0
@@ -1386,9 +1383,9 @@ struct lpfc_mbx_cq_create_set {
#define lpfc_mbx_cq_create_set_valid_SHIFT 29
#define lpfc_mbx_cq_create_set_valid_MASK 0x00000001
#define lpfc_mbx_cq_create_set_valid_WORD word1
-#define lpfc_mbx_cq_create_set_cqecnt_SHIFT 27
-#define lpfc_mbx_cq_create_set_cqecnt_MASK 0x00000003
-#define lpfc_mbx_cq_create_set_cqecnt_WORD word1
+#define lpfc_mbx_cq_create_set_cqe_cnt_SHIFT 27
+#define lpfc_mbx_cq_create_set_cqe_cnt_MASK 0x00000003
+#define lpfc_mbx_cq_create_set_cqe_cnt_WORD word1
#define lpfc_mbx_cq_create_set_cqe_size_SHIFT 25
#define lpfc_mbx_cq_create_set_cqe_size_MASK 0x00000003
#define lpfc_mbx_cq_create_set_cqe_size_WORD word1
@@ -1401,16 +1398,13 @@ struct lpfc_mbx_cq_create_set {
#define lpfc_mbx_cq_create_set_clswm_SHIFT 12
#define lpfc_mbx_cq_create_set_clswm_MASK 0x00000003
#define lpfc_mbx_cq_create_set_clswm_WORD word1
-#define lpfc_mbx_cq_create_set_cqe_cnt_hi_SHIFT 0
-#define lpfc_mbx_cq_create_set_cqe_cnt_hi_MASK 0x0000001F
-#define lpfc_mbx_cq_create_set_cqe_cnt_hi_WORD word1
uint32_t word2;
#define lpfc_mbx_cq_create_set_arm_SHIFT 31
#define lpfc_mbx_cq_create_set_arm_MASK 0x00000001
#define lpfc_mbx_cq_create_set_arm_WORD word2
-#define lpfc_mbx_cq_create_set_cqe_cnt_lo_SHIFT 16
-#define lpfc_mbx_cq_create_set_cqe_cnt_lo_MASK 0x00007FFF
-#define lpfc_mbx_cq_create_set_cqe_cnt_lo_WORD word2
+#define lpfc_mbx_cq_create_set_cq_cnt_SHIFT 16
+#define lpfc_mbx_cq_create_set_cq_cnt_MASK 0x00007FFF
+#define lpfc_mbx_cq_create_set_cq_cnt_WORD word2
#define lpfc_mbx_cq_create_set_num_cq_SHIFT 0
#define lpfc_mbx_cq_create_set_num_cq_MASK 0x0000FFFF
#define lpfc_mbx_cq_create_set_num_cq_WORD word2
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 7d459a88ec5a..73f8a0e3a4c0 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -16486,10 +16486,10 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
case 4096:
if (phba->sli4_hba.pc_sli4_params.cqv ==
LPFC_Q_CREATE_VERSION_2) {
- bf_set(lpfc_mbx_cq_create_set_cqe_cnt_lo,
+ bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
&cq_set->u.request,
- cq->entry_count);
- bf_set(lpfc_mbx_cq_create_set_cqecnt,
+ cq->entry_count);
+ bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
&cq_set->u.request,
LPFC_CQ_CNT_WORD7);
break;
@@ -16505,15 +16505,15 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
}
fallthrough; /* otherwise default to smallest */
case 256:
- bf_set(lpfc_mbx_cq_create_set_cqecnt,
+ bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
&cq_set->u.request, LPFC_CQ_CNT_256);
break;
case 512:
- bf_set(lpfc_mbx_cq_create_set_cqecnt,
+ bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
&cq_set->u.request, LPFC_CQ_CNT_512);
break;
case 1024:
- bf_set(lpfc_mbx_cq_create_set_cqecnt,
+ bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
&cq_set->u.request, LPFC_CQ_CNT_1024);
break;
}
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index e42b44fcc7f6..9be3da91c923 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -575,10 +575,8 @@ struct lpfc_pc_sli4_params {
#define LPFC_CQ_4K_PAGE_SZ 0x1
#define LPFC_CQ_16K_PAGE_SZ 0x4
-#define LPFC_CQ_32K_PAGE_SZ 0x8
#define LPFC_WQ_4K_PAGE_SZ 0x1
#define LPFC_WQ_16K_PAGE_SZ 0x4
-#define LPFC_WQ_32K_PAGE_SZ 0x8
struct lpfc_iov {
uint32_t pf_number;

View File

@ -0,0 +1,40 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Move clearing of HBA_SETUP flag to before lpfc_sli4_queue_unset"
# Revert of 0506fd6f9cce6d603c88619704e0281fbea553cc
scsi: lpfc: Move clearing of HBA_SETUP flag to before lpfc_sli4_queue_unset
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 0786952cd7d5..9fa5de43f500 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -536,8 +536,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
psb = container_of(iocbq, struct lpfc_io_buf, cur_iocbq);
psb->flags &= ~LPFC_SBUF_XBUSY;
spin_unlock_irqrestore(&phba->hbalock, iflag);
- if (test_bit(HBA_SETUP, &phba->hba_flag) &&
- !list_empty(&pring->txq))
+ if (!list_empty(&pring->txq))
lpfc_worker_wake_up(phba);
return;
}
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 73f8a0e3a4c0..bcc7ce426fbe 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5170,6 +5170,7 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba)
phba->link_events = 0;
phba->pport->fc_myDID = 0;
phba->pport->fc_prevDID = 0;
+ clear_bit(HBA_SETUP, &phba->hba_flag);
spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~(LPFC_PROCESS_LA);
@@ -5286,7 +5287,6 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
"0296 Restart HBA Data: x%x x%x\n",
phba->pport->port_state, psli->sli_flag);
- clear_bit(HBA_SETUP, &phba->hba_flag);
lpfc_sli4_queue_unset(phba);
rc = lpfc_sli4_brdreset(phba);

View File

@ -0,0 +1,20 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Ensure HBA_SETUP flag is used only for SLI4 in dev_loss_tmo_callbk"
# Revert of 86faf91ba7bc2858562ae56d12d90779b9e5ca53
scsi: lpfc: Ensure HBA_SETUP flag is used only for SLI4 in dev_loss_tmo_callbk
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index d4760fa67076..bcd943722f06 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -183,8 +183,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
/* Don't schedule a worker thread event if the vport is going down. */
if (test_bit(FC_UNLOADING, &vport->load_flag) ||
- (phba->sli_rev == LPFC_SLI_REV4 &&
- !test_bit(HBA_SETUP, &phba->hba_flag))) {
+ !test_bit(HBA_SETUP, &phba->hba_flag)) {
spin_lock_irqsave(&ndlp->lock, iflags);
ndlp->rport = NULL;

View File

@ -0,0 +1,48 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Relocate clearing initial phba flags from link up to link down hdlr"
# Revert of 0bba7f35a566c624c3a3c74285b61b59f2cf68bb
scsi: lpfc: Relocate clearing initial phba flags from link up to link down hdlr
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 853cf7649451..cdac8600ae9c 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -8376,9 +8376,9 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
clear_bit(FC_PUBLIC_LOOP, &vport->fc_flag);
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"3311 Rcv Flogi PS x%x new PS x%x "
- "fc_flag x%lx new fc_flag x%lx, hba_flag x%lx\n",
+ "fc_flag x%lx new fc_flag x%lx\n",
port_state, vport->port_state,
- fc_flag, vport->fc_flag, phba->hba_flag);
+ fc_flag, vport->fc_flag);
/*
* We temporarily set fc_myDID to make it look like we are
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index bcd943722f06..c5502272f00e 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1266,10 +1266,6 @@ lpfc_linkdown(struct lpfc_hba *phba)
}
phba->defer_flogi_acc.flag = false;
- /* reinitialize initial HBA flag */
- clear_bit(HBA_FLOGI_ISSUED, &phba->hba_flag);
- clear_bit(HBA_RHBA_CMPL, &phba->hba_flag);
-
/* Clear external loopback plug detected flag */
phba->link_flag &= ~LS_EXTERNAL_LOOPBACK;
@@ -1440,6 +1436,10 @@ lpfc_linkup(struct lpfc_hba *phba)
phba->pport->rcv_flogi_cnt = 0;
spin_unlock_irq(shost->host_lock);
+ /* reinitialize initial HBA flag */
+ clear_bit(HBA_FLOGI_ISSUED, &phba->hba_flag);
+ clear_bit(HBA_RHBA_CMPL, &phba->hba_flag);
+
return 0;
}

View File

@ -0,0 +1,53 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Simplify error handling for failed lpfc_get_sli4_parameters cmd"
# Revert of 58213a54e9c389dbde59a6b2714a77c7aed21eff
scsi: lpfc: Simplify error handling for failed lpfc_get_sli4_parameters cmd
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 8007c961bbd7..488a4bd363e3 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -7916,6 +7916,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
int longs;
int extra;
uint64_t wwn;
+ u32 if_type;
+ u32 if_fam;
phba->sli4_hba.num_present_cpu = lpfc_present_cpu;
phba->sli4_hba.num_possible_cpu = cpumask_last(cpu_possible_mask) + 1;
@@ -8176,11 +8178,28 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
*/
rc = lpfc_get_sli4_parameters(phba, mboxq);
if (rc) {
- lpfc_log_msg(phba, KERN_WARNING, LOG_INIT,
- "2999 Could not get SLI4 parameters\n");
- rc = -EIO;
- mempool_free(mboxq, phba->mbox_mem_pool);
- goto out_free_bsmbx;
+ if_type = bf_get(lpfc_sli_intf_if_type,
+ &phba->sli4_hba.sli_intf);
+ if_fam = bf_get(lpfc_sli_intf_sli_family,
+ &phba->sli4_hba.sli_intf);
+ if (phba->sli4_hba.extents_in_use &&
+ phba->sli4_hba.rpi_hdrs_in_use) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2999 Unsupported SLI4 Parameters "
+ "Extents and RPI headers enabled.\n");
+ if (if_type == LPFC_SLI_INTF_IF_TYPE_0 &&
+ if_fam == LPFC_SLI_INTF_FAMILY_BE2) {
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ rc = -EIO;
+ goto out_free_bsmbx;
+ }
+ }
+ if (!(if_type == LPFC_SLI_INTF_IF_TYPE_0 &&
+ if_fam == LPFC_SLI_INTF_FAMILY_BE2)) {
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ rc = -EIO;
+ goto out_free_bsmbx;
+ }
}
/*

View File

@ -0,0 +1,42 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Early return out of FDMI cmpl for locally rejected statuses"
# Revert of 9c000843bf3d8afda0e42d382062558a239dc7f9
scsi: lpfc: Early return out of FDMI cmpl for locally rejected statuses
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index aa6c2b0f9907..2e1d762b75a9 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -2229,6 +2229,21 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* Look for a retryable error */
if (ulp_status == IOSTAT_LOCAL_REJECT) {
switch ((ulp_word4 & IOERR_PARAM_MASK)) {
+ case IOERR_SLI_ABORTED:
+ case IOERR_SLI_DOWN:
+ /* Driver aborted this IO. No retry as error
+ * is likely Offline->Online or some adapter
+ * error. Recovery will try again, but if port
+ * is not active there's no point to continue
+ * issuing follow up FDMI commands.
+ */
+ if (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE)) {
+ free_ndlp = cmdiocb->ndlp;
+ lpfc_ct_free_iocb(phba, cmdiocb);
+ lpfc_nlp_put(free_ndlp);
+ return;
+ }
+ break;
case IOERR_ABORT_IN_PROGRESS:
case IOERR_SEQUENCE_TIMEOUT:
case IOERR_ILLEGAL_FRAME:
@@ -2254,9 +2269,6 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_ct_free_iocb(phba, cmdiocb);
lpfc_nlp_put(free_ndlp);
- if (ulp_status != IOSTAT_SUCCESS)
- return;
-
ndlp = lpfc_findnode_did(vport, FDMI_DID);
if (!ndlp)
return;

View File

@ -0,0 +1,24 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Skip RSCN processing when FC_UNLOADING flag is set"
# Revert of c21abd3cdb713b806a0a8ecbc1c161f1fa9be73b
scsi: lpfc: Skip RSCN processing when FC_UNLOADING flag is set
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index cdac8600ae9c..0205c54bce63 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -7860,13 +7860,6 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport)
/* Move all affected nodes by pending RSCNs to NPR state. */
list_for_each_entry_safe(ndlp, n, &vport->fc_nodes, nlp_listp) {
- if (test_bit(FC_UNLOADING, &vport->load_flag)) {
- lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
- "1000 %s Unloading set\n",
- __func__);
- return 0;
- }
-
if ((ndlp->nlp_state == NLP_STE_UNUSED_NODE) ||
!lpfc_rscn_payload_check(vport, ndlp->nlp_DID))
continue;

View File

@ -0,0 +1,21 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Check for hdwq null ptr when cleaning up lpfc_vport structure"
# Revert of 22e5c00fb500e6d78967da8a034de9e950a4db49
scsi: lpfc: Check for hdwq null ptr when cleaning up lpfc_vport structure
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 9fa5de43f500..6309eb286a33 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -390,10 +390,6 @@ lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport)
if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP))
return;
- /* may be called before queues established if hba_setup fails */
- if (!phba->sli4_hba.hdwq)
- return;
-
spin_lock_irqsave(&phba->hbalock, iflag);
for (idx = 0; idx < phba->cfg_hdw_queue; idx++) {
qp = &phba->sli4_hba.hdwq[idx];

View File

@ -0,0 +1,56 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Update debugfs trace ring initialization messages"
# Revert of 580bc25e722ca698094ef3e4aa1ac7152ed0e071
scsi: lpfc: Update debugfs trace ring initialization messages
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 1b6cdadc7426..e5a31bc0f6c9 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -6227,9 +6227,8 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
i++;
}
lpfc_debugfs_max_slow_ring_trc = (1 << i);
- pr_info("lpfc_debugfs_max_slow_ring_trc "
- "changed to %d\n",
- lpfc_debugfs_max_slow_ring_trc);
+ pr_err("lpfc_debugfs_max_disc_trc changed to "
+ "%d\n", lpfc_debugfs_max_disc_trc);
}
}
@@ -6261,7 +6260,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
atomic_set(&phba->nvmeio_trc_cnt, 0);
if (lpfc_debugfs_max_nvmeio_trc) {
num = lpfc_debugfs_max_nvmeio_trc - 1;
- if (num & lpfc_debugfs_max_nvmeio_trc) {
+ if (num & lpfc_debugfs_max_disc_trc) {
/* Change to be a power of 2 */
num = lpfc_debugfs_max_nvmeio_trc;
i = 0;
@@ -6270,9 +6269,10 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
i++;
}
lpfc_debugfs_max_nvmeio_trc = (1 << i);
- pr_info("lpfc_debugfs_max_nvmeio_trc changed "
- "to %d\n",
- lpfc_debugfs_max_nvmeio_trc);
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0575 lpfc_debugfs_max_nvmeio_trc "
+ "changed to %d\n",
+ lpfc_debugfs_max_nvmeio_trc);
}
phba->nvmeio_trc_size = lpfc_debugfs_max_nvmeio_trc;
@@ -6317,8 +6317,8 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
i++;
}
lpfc_debugfs_max_disc_trc = (1 << i);
- pr_info("lpfc_debugfs_max_disc_trc changed to %d\n",
- lpfc_debugfs_max_disc_trc);
+ pr_err("lpfc_debugfs_max_disc_trc changed to %d\n",
+ lpfc_debugfs_max_disc_trc);
}
}

View File

@ -0,0 +1,32 @@
From: AlmaLinux backport
Subject: [PATCH] Revert "scsi: lpfc: Revise logging format for failed CT MIB requests"
# Revert of dfd30218a269fc6f6df48cb0781977d53223f955
scsi: lpfc: Revise logging format for failed CT MIB requests
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 2e1d762b75a9..0c9260dc2706 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -264,9 +264,9 @@ lpfc_ct_reject_event(struct lpfc_nodelist *ndlp,
ct_free_mp:
kfree(mp);
ct_exit:
- lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
- "6440 Unsol CT: Rsp err %d Data: x%lx\n",
- rc, vport->fc_flag);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "6440 Unsol CT: Rsp err %d Data: x%lx\n",
+ rc, vport->fc_flag);
}
/**
@@ -313,7 +313,7 @@ lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq)
mi_cmd = be16_to_cpu(ct_req->CommandResponse.bits.CmdRsp);
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
- "6442 MI Cmd: x%x Not Supported\n", mi_cmd);
+ "6442 MI Cmd : x%x Not Supported\n", mi_cmd);
lpfc_ct_reject_event(ndlp, ct_req,
bf_get(wqe_ctxt_tag,
&ctiocbq->wqe.xmit_els_rsp.wqe_com),

View File

@ -0,0 +1,33 @@
From: AlmaLinux (RHEL-only, no upstream/CS9 source) <noreply@almalinux.org>
Subject: [PATCH] scsi: lpfc: avoid crashing in lpfc_nlp_get() if lpfc_nodelist was freed
JIRA: RHEL-167742
NOTE: RHEL-specific fix; no CS9 or upstream commit exists. Reconstructed change.
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 14ebc9c..a7064fd 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -6597,11 +6597,6 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp)
unsigned long flags;
if (ndlp) {
- lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
- "node get: did:x%x flg:x%lx refcnt:x%x",
- ndlp->nlp_DID, ndlp->nlp_flag,
- kref_read(&ndlp->kref));
-
/* The check of ndlp usage to prevent incrementing the
* ndlp reference count that is in the process of being
* released.
@@ -6609,9 +6604,8 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp)
spin_lock_irqsave(&ndlp->lock, flags);
if (!kref_get_unless_zero(&ndlp->kref)) {
spin_unlock_irqrestore(&ndlp->lock, flags);
- lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE,
- "0276 %s: ndlp:x%px refcnt:%d\n",
- __func__, (void *)ndlp, kref_read(&ndlp->kref));
+ pr_info("0276 %s: NDLP has zero reference count. "
+ "Exiting\n", __func__);
return NULL;
}
spin_unlock_irqrestore(&ndlp->lock, flags);

View File

@ -0,0 +1,218 @@
From 8c738512714e8c0aa18f8a10c072d5b01c83db39 Mon Sep 17 00:00:00 2001
From: Ilya Dryomov <idryomov@gmail.com>
Date: Tue, 2 Dec 2025 10:32:31 +0100
Subject: [PATCH] libceph: make decode_pool() more resilient against corrupted
osdmaps
If the osdmap is (maliciously) corrupted such that the encoded length
of ceph_pg_pool envelope is less than what is expected for a particular
encoding version, out-of-bounds reads may ensue because the only bounds
check that is there is based on that length value.
This patch adds explicit bounds checks for each field that is decoded
or skipped.
Cc: stable@vger.kernel.org
Reported-by: ziming zhang <ezrakiez@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
Tested-by: ziming zhang <ezrakiez@gmail.com>
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
index 329eeea2f922..34b3ab59602f 100644
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -806,51 +806,49 @@ static int decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi)
ceph_decode_need(p, end, len, bad);
pool_end = *p + len;
+ ceph_decode_need(p, end, 4 + 4 + 4, bad);
pi->type = ceph_decode_8(p);
pi->size = ceph_decode_8(p);
pi->crush_ruleset = ceph_decode_8(p);
pi->object_hash = ceph_decode_8(p);
-
pi->pg_num = ceph_decode_32(p);
pi->pgp_num = ceph_decode_32(p);
- *p += 4 + 4; /* skip lpg* */
- *p += 4; /* skip last_change */
- *p += 8 + 4; /* skip snap_seq, snap_epoch */
+ /* lpg*, last_change, snap_seq, snap_epoch */
+ ceph_decode_skip_n(p, end, 8 + 4 + 8 + 4, bad);
/* skip snaps */
- num = ceph_decode_32(p);
+ ceph_decode_32_safe(p, end, num, bad);
while (num--) {
- *p += 8; /* snapid key */
- *p += 1 + 1; /* versions */
- len = ceph_decode_32(p);
- *p += len;
+ /* snapid key, pool snap (with versions) */
+ ceph_decode_skip_n(p, end, 8 + 2, bad);
+ ceph_decode_skip_string(p, end, bad);
}
- /* skip removed_snaps */
- num = ceph_decode_32(p);
- *p += num * (8 + 8);
+ /* removed_snaps */
+ ceph_decode_skip_map(p, end, 64, 64, bad);
+ ceph_decode_need(p, end, 8 + 8 + 4, bad);
*p += 8; /* skip auid */
pi->flags = ceph_decode_64(p);
*p += 4; /* skip crash_replay_interval */
if (ev >= 7)
- pi->min_size = ceph_decode_8(p);
+ ceph_decode_8_safe(p, end, pi->min_size, bad);
else
pi->min_size = pi->size - pi->size / 2;
if (ev >= 8)
- *p += 8 + 8; /* skip quota_max_* */
+ /* quota_max_* */
+ ceph_decode_skip_n(p, end, 8 + 8, bad);
if (ev >= 9) {
- /* skip tiers */
- num = ceph_decode_32(p);
- *p += num * 8;
+ /* tiers */
+ ceph_decode_skip_set(p, end, 64, bad);
+ ceph_decode_need(p, end, 8 + 1 + 8 + 8, bad);
*p += 8; /* skip tier_of */
*p += 1; /* skip cache_mode */
-
pi->read_tier = ceph_decode_64(p);
pi->write_tier = ceph_decode_64(p);
} else {
@@ -858,86 +856,76 @@ static int decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi)
pi->write_tier = -1;
}
- if (ev >= 10) {
- /* skip properties */
- num = ceph_decode_32(p);
- while (num--) {
- len = ceph_decode_32(p);
- *p += len; /* key */
- len = ceph_decode_32(p);
- *p += len; /* val */
- }
- }
+ if (ev >= 10)
+ /* properties */
+ ceph_decode_skip_map(p, end, string, string, bad);
if (ev >= 11) {
- /* skip hit_set_params */
- *p += 1 + 1; /* versions */
- len = ceph_decode_32(p);
- *p += len;
+ /* hit_set_params (with versions) */
+ ceph_decode_skip_n(p, end, 2, bad);
+ ceph_decode_skip_string(p, end, bad);
- *p += 4; /* skip hit_set_period */
- *p += 4; /* skip hit_set_count */
+ /* hit_set_period, hit_set_count */
+ ceph_decode_skip_n(p, end, 4 + 4, bad);
}
if (ev >= 12)
- *p += 4; /* skip stripe_width */
+ /* stripe_width */
+ ceph_decode_skip_32(p, end, bad);
- if (ev >= 13) {
- *p += 8; /* skip target_max_bytes */
- *p += 8; /* skip target_max_objects */
- *p += 4; /* skip cache_target_dirty_ratio_micro */
- *p += 4; /* skip cache_target_full_ratio_micro */
- *p += 4; /* skip cache_min_flush_age */
- *p += 4; /* skip cache_min_evict_age */
- }
+ if (ev >= 13)
+ /* target_max_*, cache_target_*, cache_min_* */
+ ceph_decode_skip_n(p, end, 16 + 8 + 8, bad);
- if (ev >= 14) {
- /* skip erasure_code_profile */
- len = ceph_decode_32(p);
- *p += len;
- }
+ if (ev >= 14)
+ /* erasure_code_profile */
+ ceph_decode_skip_string(p, end, bad);
/*
* last_force_op_resend_preluminous, will be overridden if the
* map was encoded with RESEND_ON_SPLIT
*/
if (ev >= 15)
- pi->last_force_request_resend = ceph_decode_32(p);
+ ceph_decode_32_safe(p, end, pi->last_force_request_resend, bad);
else
pi->last_force_request_resend = 0;
if (ev >= 16)
- *p += 4; /* skip min_read_recency_for_promote */
+ /* min_read_recency_for_promote */
+ ceph_decode_skip_32(p, end, bad);
if (ev >= 17)
- *p += 8; /* skip expected_num_objects */
+ /* expected_num_objects */
+ ceph_decode_skip_64(p, end, bad);
if (ev >= 19)
- *p += 4; /* skip cache_target_dirty_high_ratio_micro */
+ /* cache_target_dirty_high_ratio_micro */
+ ceph_decode_skip_32(p, end, bad);
if (ev >= 20)
- *p += 4; /* skip min_write_recency_for_promote */
+ /* min_write_recency_for_promote */
+ ceph_decode_skip_32(p, end, bad);
if (ev >= 21)
- *p += 1; /* skip use_gmt_hitset */
+ /* use_gmt_hitset */
+ ceph_decode_skip_8(p, end, bad);
if (ev >= 22)
- *p += 1; /* skip fast_read */
+ /* fast_read */
+ ceph_decode_skip_8(p, end, bad);
- if (ev >= 23) {
- *p += 4; /* skip hit_set_grade_decay_rate */
- *p += 4; /* skip hit_set_search_last_n */
- }
+ if (ev >= 23)
+ /* hit_set_grade_decay_rate, hit_set_search_last_n */
+ ceph_decode_skip_n(p, end, 4 + 4, bad);
if (ev >= 24) {
- /* skip opts */
- *p += 1 + 1; /* versions */
- len = ceph_decode_32(p);
- *p += len;
+ /* opts (with versions) */
+ ceph_decode_skip_n(p, end, 2, bad);
+ ceph_decode_skip_string(p, end, bad);
}
if (ev >= 25)
- pi->last_force_request_resend = ceph_decode_32(p);
+ ceph_decode_32_safe(p, end, pi->last_force_request_resend, bad);
/* ignore the rest */
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,33 @@
From 818156caffbf55cb4d368f9c3cac64e458fb49c9 Mon Sep 17 00:00:00 2001
From: ziming zhang <ezrakiez@gmail.com>
Date: Thu, 11 Dec 2025 16:52:58 +0800
Subject: [PATCH] libceph: prevent potential out-of-bounds reads in
handle_auth_done()
Perform an explicit bounds check on payload_len to avoid a possible
out-of-bounds access in the callout.
[ idryomov: changelog ]
Cc: stable@vger.kernel.org
Signed-off-by: ziming zhang <ezrakiez@gmail.com>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c
index 833e57849c1d..c9d50c0dcd33 100644
--- a/net/ceph/messenger_v2.c
+++ b/net/ceph/messenger_v2.c
@@ -2376,7 +2376,9 @@ static int process_auth_done(struct ceph_connection *con, void *p, void *end)
ceph_decode_64_safe(&p, end, global_id, bad);
ceph_decode_32_safe(&p, end, con->v2.con_mode, bad);
+
ceph_decode_32_safe(&p, end, payload_len, bad);
+ ceph_decode_need(&p, end, payload_len, bad);
dout("%s con %p global_id %llu con_mode %d payload_len %d\n",
__func__, con, global_id, con->v2.con_mode, payload_len);
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,36 @@
From e00c3f71b5cf75681dbd74ee3f982a99cb690c2b Mon Sep 17 00:00:00 2001
From: Ilya Dryomov <idryomov@gmail.com>
Date: Mon, 15 Dec 2025 11:53:31 +0100
Subject: [PATCH] libceph: replace overzealous BUG_ON in
osdmap_apply_incremental()
If the osdmap is (maliciously) corrupted such that the incremental
osdmap epoch is different from what is expected, there is no need to
BUG. Instead, just declare the incremental osdmap to be invalid.
Cc: stable@vger.kernel.org
Reported-by: ziming zhang <ezrakiez@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
index 34b3ab59602f..3377a22e3f6c 100644
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -1979,11 +1979,13 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, bool msgr2,
sizeof(u64) + sizeof(u32), e_inval);
ceph_decode_copy(p, &fsid, sizeof(fsid));
epoch = ceph_decode_32(p);
- BUG_ON(epoch != map->epoch+1);
ceph_decode_copy(p, &modified, sizeof(modified));
new_pool_max = ceph_decode_64(p);
new_flags = ceph_decode_32(p);
+ if (epoch != map->epoch + 1)
+ goto e_inval;
+
/* full map? */
ceph_decode_32_safe(p, end, len, e_inval);
if (len > 0) {
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,48 @@
From 11194b416ef95012c2cfe5f546d71af07b639e93 Mon Sep 17 00:00:00 2001
From: Sam Edwards <cfsworks@gmail.com>
Date: Tue, 30 Dec 2025 20:05:06 -0800
Subject: [PATCH] libceph: reset sparse-read state in osd_fault()
When a fault occurs, the connection is abandoned, reestablished, and any
pending operations are retried. The OSD client tracks the progress of a
sparse-read reply using a separate state machine, largely independent of
the messenger's state.
If a connection is lost mid-payload or the sparse-read state machine
returns an error, the sparse-read state is not reset. The OSD client
will then interpret the beginning of a new reply as the continuation of
the old one. If this makes the sparse-read machinery enter a failure
state, it may never recover, producing loops like:
libceph: [0] got 0 extents
libceph: data len 142248331 != extent len 0
libceph: osd0 (1)...:6801 socket error on read
libceph: data len 142248331 != extent len 0
libceph: osd0 (1)...:6801 socket error on read
Therefore, reset the sparse-read state in osd_fault(), ensuring retries
start from a clean state.
Cc: stable@vger.kernel.org
Fixes: f628d7999727 ("libceph: add sparse read support to OSD client")
Signed-off-by: Sam Edwards <CFSworks@gmail.com>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 3667319b949d..1a7be2f615dc 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -4281,6 +4281,9 @@ static void osd_fault(struct ceph_connection *con)
goto out_unlock;
}
+ osd->o_sparse_op_idx = -1;
+ ceph_init_sparse_read(&osd->o_sparse_read);
+
if (!reopen_osd(osd))
kick_osd_requests(osd);
maybe_request_map(osdc);
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,54 @@
From 123d241dcfc31871e2610504c50583dce8ac832f Mon Sep 17 00:00:00 2001
From: Jan Stancek <jstancek@redhat.com>
Date: Tue, 23 Sep 2025 17:32:16 +0200
Subject: [PATCH] powerpc/tools: drop `-o pipefail` in gcc check scripts
JIRA: https://redhat.atlassian.net/browse/RHEL-165107
Upstream Status: linux.git
Conflicts:
- RHEL commit 12e313df71b6 ("powerpc/tools: drop `-o pipefail` in gcc check scripts")
applied one of the hunks of upstream commit, because at the time RHEL9
was missing gcc-check-fpatchable-function-entry.sh.
This has changed when RHEL commit
c3aeb790328d ("powerpc/ftrace: Add support for -fpatchable-function-entry")
introduced it.
This applies missing hunk from f1164534ad62f0cc247d99650b07bd59ad2a49fd to
arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh
commit f1164534ad62f0cc247d99650b07bd59ad2a49fd
Author: Jan Stancek <jstancek@redhat.com>
Date: Tue Sep 23 17:32:16 2025 +0200
powerpc/tools: drop `-o pipefail` in gcc check scripts
Fixes: 0f71dcfb4aef ("powerpc/ftrace: Add support for -fpatchable-function-entry")
Fixes: b71c9ffb1405 ("powerpc: Add arch/powerpc/tools directory")
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Acked-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Jan Stancek <jstancek@redhat.com>
Fixes: 8c50b72a3b4f ("powerpc/ftrace: Add Kconfig & Make glue for mprofile-kernel")
Fixes: abba759796f9 ("powerpc/kbuild: move -mprofile-kernel check to Kconfig")
Tested-by: Justin M. Forbes <jforbes@fedoraproject.org>
Reviewed-by: Naveen N Rao (AMD) <naveen@kernel.org>
Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/cc6cdd116c3ad9d990df21f13c6d8e8a83815bbd.1758641374.git.jstancek@redhat.com
Signed-off-by: Jan Stancek <jstancek@redhat.com>
diff --git a/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh b/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh
index 06706903503b..baed467a016b 100755
--- a/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh
+++ b/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh
@@ -2,7 +2,6 @@
# SPDX-License-Identifier: GPL-2.0
set -e
-set -o pipefail
# To debug, uncomment the following line
# set -x
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,79 @@
From aad885e774966e97b675dfe928da164214a71605 Mon Sep 17 00:00:00 2001
From: Sean Christopherson <seanjc@google.com>
Date: Thu, 5 Mar 2026 17:28:04 -0800
Subject: [PATCH] KVM: x86/mmu: Drop/zap existing present SPTE even when
creating an MMIO SPTE
When installing an emulated MMIO SPTE, do so *after* dropping/zapping the
existing SPTE (if it's shadow-present). While commit a54aa15c6bda3 was
right about it being impossible to convert a shadow-present SPTE to an
MMIO SPTE due to a _guest_ write, it failed to account for writes to guest
memory that are outside the scope of KVM.
E.g. if host userspace modifies a shadowed gPTE to switch from a memslot
to emulted MMIO and then the guest hits a relevant page fault, KVM will
install the MMIO SPTE without first zapping the shadow-present SPTE.
------------[ cut here ]------------
is_shadow_present_pte(*sptep)
WARNING: arch/x86/kvm/mmu/mmu.c:484 at mark_mmio_spte+0xb2/0xc0 [kvm], CPU#0: vmx_ept_stale_r/4292
Modules linked in: kvm_intel kvm irqbypass
CPU: 0 UID: 1000 PID: 4292 Comm: vmx_ept_stale_r Not tainted 7.0.0-rc2-eafebd2d2ab0-sink-vm #319 PREEMPT
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
RIP: 0010:mark_mmio_spte+0xb2/0xc0 [kvm]
Call Trace:
<TASK>
mmu_set_spte+0x237/0x440 [kvm]
ept_page_fault+0x535/0x7f0 [kvm]
kvm_mmu_do_page_fault+0xee/0x1f0 [kvm]
kvm_mmu_page_fault+0x8d/0x620 [kvm]
vmx_handle_exit+0x18c/0x5a0 [kvm_intel]
kvm_arch_vcpu_ioctl_run+0xc55/0x1c20 [kvm]
kvm_vcpu_ioctl+0x2d5/0x980 [kvm]
__x64_sys_ioctl+0x8a/0xd0
do_syscall_64+0xb5/0x730
entry_SYSCALL_64_after_hwframe+0x4b/0x53
RIP: 0033:0x47fa3f
</TASK>
---[ end trace 0000000000000000 ]---
Reported-by: Alexander Bulekov <bkov@amazon.com>
Debugged-by: Alexander Bulekov <bkov@amazon.com>
Suggested-by: Fred Griffoul <fgriffo@amazon.co.uk>
Fixes: a54aa15c6bda3 ("KVM: x86/mmu: Handle MMIO SPTEs directly in mmu_set_spte()")
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <seanjc@google.com>
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index c542b26..8895c98 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -2892,12 +2892,6 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, struct kvm_memory_slot *slot,
bool prefetch = !fault || fault->prefetch;
bool write_fault = fault && fault->write;
- if (unlikely(is_noslot_pfn(pfn))) {
- vcpu->stat.pf_mmio_spte_created++;
- mark_mmio_spte(vcpu, sptep, gfn, pte_access);
- return RET_PF_EMULATE;
- }
-
if (is_shadow_present_pte(*sptep)) {
if (prefetch)
return RET_PF_SPURIOUS;
@@ -2920,6 +2914,14 @@ static int mmu_set_spte(struct kvm_vcpu *vcpu, struct kvm_memory_slot *slot,
was_rmapped = 1;
}
+ if (unlikely(is_noslot_pfn(pfn))) {
+ vcpu->stat.pf_mmio_spte_created++;
+ mark_mmio_spte(vcpu, sptep, gfn, pte_access);
+ if (flush)
+ kvm_flush_remote_tlbs_gfn(vcpu->kvm, gfn, level);
+ return RET_PF_EMULATE;
+ }
+
wrprot = make_spte(vcpu, sp, slot, pte_access, gfn, pfn, *sptep, prefetch,
true, host_writable, &spte);

View File

@ -0,0 +1,52 @@
From 00de3c031466400b8db061ae3149de8c64999974 Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert.xu@redhat.com>
Date: Thu, 30 Apr 2026 12:54:18 +0800
Subject: [PATCH] crypto: af-alg - fix NULL pointer dereference in scatterwalk
JIRA: https://redhat.atlassian.net/browse/RHEL-172207
Upstream Status: 62397b493e14107ae82d8b80938f293d95425bcb
commit 62397b493e14107ae82d8b80938f293d95425bcb
Author: Norbert Szetei <norbert@doyensec.com>
Date: Wed Mar 25 18:26:13 2026 +0100
crypto: af-alg - fix NULL pointer dereference in scatterwalk
The AF_ALG interface fails to unmark the end of a Scatter/Gather List (SGL)
when chaining a new af_alg_tsgl structure. If a sendmsg() fills an SGL
exactly to MAX_SGL_ENTS, the last entry is marked as the end. A subsequent
sendmsg() allocates a new SGL and chains it, but fails to clear the end
marker on the previous SGL's last data entry.
This causes the crypto scatterwalk to hit a premature end, returning NULL
on sg_next() and leading to a kernel panic during dereference.
Fix this by explicitly unmarking the end of the previous SGL when
performing sg_chain() in af_alg_alloc_tsgl().
Fixes: 8ff590903d5f ("crypto: algif_skcipher - User-space interface for skcipher operations")
Signed-off-by: Norbert Szetei <norbert@doyensec.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Herbert Xu <herbert.xu@redhat.com>
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 67e66729281b..25d9d907dd9f 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -513,8 +513,10 @@ static int af_alg_alloc_tsgl(struct sock *sk)
sg_init_table(sgl->sg, MAX_SGL_ENTS + 1);
sgl->cur = 0;
- if (sg)
+ if (sg) {
+ sg_unmark_end(sg + MAX_SGL_ENTS - 1);
sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg);
+ }
list_add_tail(&sgl->list, &ctx->tsgl_list);
}
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,325 @@
From ada3d4ca449018dd63cee4a4b806d7cb78e76e4c Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert.xu@redhat.com>
Date: Thu, 30 Apr 2026 20:52:06 +0800
Subject: [PATCH] crypto: algif_aead - Revert to operating out-of-place
JIRA: https://redhat.atlassian.net/browse/RHEL-172207
CVE: CVE-2026-31431
Upstream Status: a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5
commit a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date: Thu Mar 26 15:30:20 2026 +0900
crypto: algif_aead - Revert to operating out-of-place
This mostly reverts commit 72548b093ee3 except for the copying of
the associated data.
There is no benefit in operating in-place in algif_aead since the
source and destination come from different mappings. Get rid of
all the complexity added for in-place operation and just copy the
AD directly.
Fixes: 72548b093ee3 ("crypto: algif_aead - copy AAD from src to dst")
Reported-by: Taeyang Lee <0wn@theori.io>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Herbert Xu <herbert.xu@redhat.com>
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 25d9d907dd9f..45a058ca890a 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -527,15 +527,13 @@ static int af_alg_alloc_tsgl(struct sock *sk)
/**
* af_alg_count_tsgl - Count number of TX SG entries
*
- * The counting starts from the beginning of the SGL to @bytes. If
- * an @offset is provided, the counting of the SG entries starts at the @offset.
+ * The counting starts from the beginning of the SGL to @bytes.
*
* @sk: socket of connection to user space
* @bytes: Count the number of SG entries holding given number of bytes.
- * @offset: Start the counting of SG entries from the given offset.
* Return: Number of TX SG entries found given the constraints
*/
-unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset)
+unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes)
{
const struct alg_sock *ask = alg_sk(sk);
const struct af_alg_ctx *ctx = ask->private;
@@ -550,25 +548,11 @@ unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset)
const struct scatterlist *sg = sgl->sg;
for (i = 0; i < sgl->cur; i++) {
- size_t bytes_count;
-
- /* Skip offset */
- if (offset >= sg[i].length) {
- offset -= sg[i].length;
- bytes -= sg[i].length;
- continue;
- }
-
- bytes_count = sg[i].length - offset;
-
- offset = 0;
sgl_count++;
-
- /* If we have seen requested number of bytes, stop */
- if (bytes_count >= bytes)
+ if (sg[i].length >= bytes)
return sgl_count;
- bytes -= bytes_count;
+ bytes -= sg[i].length;
}
}
@@ -580,19 +564,14 @@ EXPORT_SYMBOL_GPL(af_alg_count_tsgl);
* af_alg_pull_tsgl - Release the specified buffers from TX SGL
*
* If @dst is non-null, reassign the pages to @dst. The caller must release
- * the pages. If @dst_offset is given only reassign the pages to @dst starting
- * at the @dst_offset (byte). The caller must ensure that @dst is large
- * enough (e.g. by using af_alg_count_tsgl with the same offset).
+ * the pages.
*
* @sk: socket of connection to user space
* @used: Number of bytes to pull from TX SGL
* @dst: If non-NULL, buffer is reassigned to dst SGL instead of releasing. The
* caller must release the buffers in dst.
- * @dst_offset: Reassign the TX SGL from given offset. All buffers before
- * reaching the offset is released.
*/
-void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
- size_t dst_offset)
+void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst)
{
struct alg_sock *ask = alg_sk(sk);
struct af_alg_ctx *ctx = ask->private;
@@ -617,18 +596,10 @@ void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
* SG entries in dst.
*/
if (dst) {
- if (dst_offset >= plen) {
- /* discard page before offset */
- dst_offset -= plen;
- } else {
- /* reassign page to dst after offset */
- get_page(page);
- sg_set_page(dst + j, page,
- plen - dst_offset,
- sg[i].offset + dst_offset);
- dst_offset = 0;
- j++;
- }
+ /* reassign page to dst after offset */
+ get_page(page);
+ sg_set_page(dst + j, page, plen, sg[i].offset);
+ j++;
}
sg[i].length -= plen;
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index 42493b4d8ce4..4a6a0bb1ae3c 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -96,9 +96,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
struct aead_tfm *aeadc = pask->private;
struct crypto_aead *tfm = aeadc->aead;
struct crypto_sync_skcipher *null_tfm = aeadc->null_tfm;
- unsigned int i, as = crypto_aead_authsize(tfm);
+ unsigned int as = crypto_aead_authsize(tfm);
struct af_alg_async_req *areq;
- struct af_alg_tsgl *tsgl, *tmp;
struct scatterlist *rsgl_src, *tsgl_src = NULL;
int err = 0;
size_t used = 0; /* [in] TX bufs to be en/decrypted */
@@ -178,23 +177,24 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
outlen -= less;
}
+ /*
+ * Create a per request TX SGL for this request which tracks the
+ * SG entries from the global TX SGL.
+ */
processed = used + ctx->aead_assoclen;
- list_for_each_entry_safe(tsgl, tmp, &ctx->tsgl_list, list) {
- for (i = 0; i < tsgl->cur; i++) {
- struct scatterlist *process_sg = tsgl->sg + i;
-
- if (!(process_sg->length) || !sg_page(process_sg))
- continue;
- tsgl_src = process_sg;
- break;
- }
- if (tsgl_src)
- break;
- }
- if (processed && !tsgl_src) {
- err = -EFAULT;
+ areq->tsgl_entries = af_alg_count_tsgl(sk, processed);
+ if (!areq->tsgl_entries)
+ areq->tsgl_entries = 1;
+ areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
+ areq->tsgl_entries),
+ GFP_KERNEL);
+ if (!areq->tsgl) {
+ err = -ENOMEM;
goto free;
}
+ sg_init_table(areq->tsgl, areq->tsgl_entries);
+ af_alg_pull_tsgl(sk, processed, areq->tsgl);
+ tsgl_src = areq->tsgl;
/*
* Copy of AAD from source to destination
@@ -203,81 +203,18 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
* when user space uses an in-place cipher operation, the kernel
* will copy the data as it does not see whether such in-place operation
* is initiated.
- *
- * To ensure efficiency, the following implementation ensure that the
- * ciphers are invoked to perform a crypto operation in-place. This
- * is achieved by memory management specified as follows.
*/
/* Use the RX SGL as source (and destination) for crypto op. */
rsgl_src = areq->first_rsgl.sgl.sg;
- if (ctx->enc) {
- /*
- * Encryption operation - The in-place cipher operation is
- * achieved by the following operation:
- *
- * TX SGL: AAD || PT
- * | |
- * | copy |
- * v v
- * RX SGL: AAD || PT || Tag
- */
- err = crypto_aead_copy_sgl(null_tfm, tsgl_src,
- areq->first_rsgl.sgl.sg, processed);
- if (err)
- goto free;
- af_alg_pull_tsgl(sk, processed, NULL, 0);
- } else {
- /*
- * Decryption operation - To achieve an in-place cipher
- * operation, the following SGL structure is used:
- *
- * TX SGL: AAD || CT || Tag
- * | | ^
- * | copy | | Create SGL link.
- * v v |
- * RX SGL: AAD || CT ----+
- */
-
- /* Copy AAD || CT to RX SGL buffer for in-place operation. */
- err = crypto_aead_copy_sgl(null_tfm, tsgl_src,
- areq->first_rsgl.sgl.sg, outlen);
- if (err)
- goto free;
-
- /* Create TX SGL for tag and chain it to RX SGL. */
- areq->tsgl_entries = af_alg_count_tsgl(sk, processed,
- processed - as);
- if (!areq->tsgl_entries)
- areq->tsgl_entries = 1;
- areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
- areq->tsgl_entries),
- GFP_KERNEL);
- if (!areq->tsgl) {
- err = -ENOMEM;
- goto free;
- }
- sg_init_table(areq->tsgl, areq->tsgl_entries);
-
- /* Release TX SGL, except for tag data and reassign tag data. */
- af_alg_pull_tsgl(sk, processed, areq->tsgl, processed - as);
-
- /* chain the areq TX SGL holding the tag with RX SGL */
- if (usedpages) {
- /* RX SGL present */
- struct af_alg_sgl *sgl_prev = &areq->last_rsgl->sgl;
-
- sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1);
- sg_chain(sgl_prev->sg, sgl_prev->npages + 1,
- areq->tsgl);
- } else
- /* no RX SGL present (e.g. authentication only) */
- rsgl_src = areq->tsgl;
- }
+ err = crypto_aead_copy_sgl(null_tfm, tsgl_src, rsgl_src,
+ ctx->aead_assoclen);
+ if (err)
+ goto free;
/* Initialize the crypto operation */
- aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src,
+ aead_request_set_crypt(&areq->cra_u.aead_req, tsgl_src,
areq->first_rsgl.sgl.sg, used, ctx->iv);
aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen);
aead_request_set_tfm(&areq->cra_u.aead_req, tfm);
@@ -526,7 +463,7 @@ static void aead_sock_destruct(struct sock *sk)
struct crypto_aead *tfm = aeadc->aead;
unsigned int ivlen = crypto_aead_ivsize(tfm);
- af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
+ af_alg_pull_tsgl(sk, ctx->used, NULL);
sock_kzfree_s(sk, ctx->iv, ivlen);
sock_kfree_s(sk, ctx, ctx->len);
af_alg_release_parent(sk);
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index ee8890ee8f33..8b314260929f 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -89,7 +89,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
* Create a per request TX SGL for this request which tracks the
* SG entries from the global TX SGL.
*/
- areq->tsgl_entries = af_alg_count_tsgl(sk, len, 0);
+ areq->tsgl_entries = af_alg_count_tsgl(sk, len);
if (!areq->tsgl_entries)
areq->tsgl_entries = 1;
areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
@@ -100,7 +100,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
goto free;
}
sg_init_table(areq->tsgl, areq->tsgl_entries);
- af_alg_pull_tsgl(sk, len, areq->tsgl, 0);
+ af_alg_pull_tsgl(sk, len, areq->tsgl);
/* Initialize the crypto operation */
skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm);
@@ -313,7 +313,7 @@ static void skcipher_sock_destruct(struct sock *sk)
struct alg_sock *pask = alg_sk(psk);
struct crypto_skcipher *tfm = pask->private;
- af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
+ af_alg_pull_tsgl(sk, ctx->used, NULL);
sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
sock_kfree_s(sk, ctx, ctx->len);
af_alg_release_parent(sk);
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 249e6bbf5cb2..f18a4ca6f07c 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -226,9 +226,8 @@ static inline bool af_alg_readable(struct sock *sk)
return PAGE_SIZE <= af_alg_rcvbuf(sk);
}
-unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset);
-void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
- size_t dst_offset);
+unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes);
+void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst);
void af_alg_wmem_wakeup(struct sock *sk);
int af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min);
int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,77 @@
From 40240fa36eae2ed097d9191cfa568fcc702472b6 Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert.xu@redhat.com>
Date: Fri, 1 May 2026 21:54:01 +0800
Subject: [PATCH] crypto: af_alg - limit RX SG extraction by receive buffer
budget
JIRA: https://redhat.atlassian.net/browse/RHEL-172207
CVE: CVE-2026-31677
Upstream Status: 8eceab19eba9dcbfd2a0daec72e1bf48aa100170
commit 8eceab19eba9dcbfd2a0daec72e1bf48aa100170
Author: Douya Le <ldy3087146292@gmail.com>
Date: Thu Apr 2 23:34:55 2026 +0800
crypto: af_alg - limit RX SG extraction by receive buffer budget
Make af_alg_get_rsgl() limit each RX scatterlist extraction to the
remaining receive buffer budget.
af_alg_get_rsgl() currently uses af_alg_readable() only as a gate
before extracting data into the RX scatterlist. Limit each extraction
to the remaining af_alg_rcvbuf(sk) budget so that receive-side
accounting matches the amount of data attached to the request.
If skcipher cannot obtain enough RX space for at least one chunk while
more data remains to be processed, reject the recvmsg call instead of
rounding the request length down to zero.
Fixes: e870456d8e7c8d57c059ea479b5aadbb55ff4c3a ("crypto: algif_skcipher - overhaul memory management")
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Co-developed-by: Yuan Tan <yuantan098@gmail.com>
Signed-off-by: Yuan Tan <yuantan098@gmail.com>
Suggested-by: Xin Liu <bird@lzu.edu.cn>
Signed-off-by: Douya Le <ldy3087146292@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Herbert Xu <herbert.xu@redhat.com>
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 45a058ca890a..450869efc079 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -1135,6 +1135,8 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
seglen = min_t(size_t, (maxsize - len),
msg_data_left(msg));
+ /* Never pin more pages than the remaining RX accounting budget. */
+ seglen = min_t(size_t, seglen, af_alg_rcvbuf(sk));
if (list_empty(&areq->rsgl_list)) {
rsgl = &areq->first_rsgl;
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 8b314260929f..edbdc19cdb31 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -82,8 +82,14 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
* If more buffers are to be expected to be processed, process only
* full block size buffers.
*/
- if (ctx->more || len < ctx->used)
+ if (ctx->more || len < ctx->used) {
+ if (len < bs) {
+ err = -EINVAL;
+ goto free;
+ }
+
len -= len % bs;
+ }
/*
* Create a per request TX SGL for this request which tracks the
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,49 @@
From 9e1c6ad59b9a5d325cda7cf7860d1442a1121c34 Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert.xu@redhat.com>
Date: Thu, 30 Apr 2026 20:10:09 +0800
Subject: [PATCH] crypto: af_alg - Fix page reassignment overflow in
af_alg_pull_tsgl
JIRA: https://redhat.atlassian.net/browse/RHEL-172207
Upstream Status: 31d00156e50ecad37f2cb6cbf04aaa9a260505ef
commit 31d00156e50ecad37f2cb6cbf04aaa9a260505ef
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date: Sat Apr 4 08:29:58 2026 +0800
crypto: af_alg - Fix page reassignment overflow in af_alg_pull_tsgl
When page reassignment was added to af_alg_pull_tsgl the original
loop wasn't updated so it may try to reassign one more page than
necessary.
Add the check to the reassignment so that this does not happen.
Also update the comment which still refers to the obsolete offset
argument.
Reported-by: syzbot+d23888375c2737c17ba5@syzkaller.appspotmail.com
Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Herbert Xu <herbert.xu@redhat.com>
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 450869efc079..567e9f234ba3 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -595,8 +595,8 @@ void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst)
* Assumption: caller created af_alg_count_tsgl(len)
* SG entries in dst.
*/
- if (dst) {
- /* reassign page to dst after offset */
+ if (dst && plen) {
+ /* reassign page to dst */
get_page(page);
sg_set_page(dst + j, page, plen, sg[i].offset);
j++;
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,58 @@
From 3d6c89a117ab9fce6fa8240ad5b45bcd48f6d751 Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert.xu@redhat.com>
Date: Fri, 1 May 2026 21:54:32 +0800
Subject: [PATCH] crypto: authencesn - reject too-short AAD (assoclen<8) to
match ESP/ESN spec
JIRA: https://redhat.atlassian.net/browse/RHEL-172207
CVE: CVE-2026-23060
Upstream Status: 2397e9264676be7794f8f7f1e9763d90bd3c7335
commit 2397e9264676be7794f8f7f1e9763d90bd3c7335
Author: Taeyang Lee <0wn@theori.io>
Date: Fri Jan 16 16:03:58 2026 +0900
crypto: authencesn - reject too-short AAD (assoclen<8) to match ESP/ESN spec
authencesn assumes an ESP/ESN-formatted AAD. When assoclen is shorter than
the minimum expected length, crypto_authenc_esn_decrypt() can advance past
the end of the destination scatterlist and trigger a NULL pointer dereference
in scatterwalk_map_and_copy(), leading to a kernel panic (DoS).
Add a minimum AAD length check to fail fast on invalid inputs.
Fixes: 104880a6b470 ("crypto: authencesn - Convert to new AEAD interface")
Reported-By: Taeyang Lee <0wn@theori.io>
Signed-off-by: Taeyang Lee <0wn@theori.io>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Herbert Xu <herbert.xu@redhat.com>
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
index b60e61b1904c..6487b35851d5 100644
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -191,6 +191,9 @@ static int crypto_authenc_esn_encrypt(struct aead_request *req)
struct scatterlist *src, *dst;
int err;
+ if (assoclen < 8)
+ return -EINVAL;
+
sg_init_table(areq_ctx->src, 2);
src = scatterwalk_ffwd(areq_ctx->src, req->src, assoclen);
dst = src;
@@ -284,6 +287,9 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req)
u32 tmp[2];
int err;
+ if (assoclen < 8)
+ return -EINVAL;
+
cryptlen -= authsize;
if (req->src != dst) {
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,172 @@
From 4a2446436fe796a1b8cef89e30f54c2c295943fe Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert.xu@redhat.com>
Date: Thu, 30 Apr 2026 20:16:25 +0800
Subject: [PATCH] crypto: authencesn - Do not place hiseq at end of dst for
out-of-place decryption
JIRA: https://redhat.atlassian.net/browse/RHEL-172207
CVE: CVE-2026-31431
Upstream Status: e02494114ebf7c8b42777c6cd6982f113bfdbec7
commit e02494114ebf7c8b42777c6cd6982f113bfdbec7
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date: Fri Mar 27 15:04:17 2026 +0900
crypto: authencesn - Do not place hiseq at end of dst for out-of-place decryption
When decrypting data that is not in-place (src != dst), there is
no need to save the high-order sequence bits in dst as it could
simply be re-copied from the source.
However, the data to be hashed need to be rearranged accordingly.
Reported-by: Taeyang Lee <0wn@theori.io>
Fixes: 104880a6b470 ("crypto: authencesn - Convert to new AEAD interface")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Thanks,
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Herbert Xu <herbert.xu@redhat.com>
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
index 6487b35851d5..8664dad45792 100644
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -164,7 +164,10 @@ static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req,
authenc_esn_request_complete(areq, err);
}
-static int crypto_authenc_esn_copy(struct aead_request *req, unsigned int len)
+static int crypto_authenc_esn_copy_sg(struct aead_request *req,
+ struct scatterlist *src,
+ struct scatterlist *dst,
+ unsigned int len)
{
struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
@@ -173,11 +176,16 @@ static int crypto_authenc_esn_copy(struct aead_request *req, unsigned int len)
skcipher_request_set_sync_tfm(skreq, ctx->null);
skcipher_request_set_callback(skreq, aead_request_flags(req),
NULL, NULL);
- skcipher_request_set_crypt(skreq, req->src, req->dst, len, NULL);
+ skcipher_request_set_crypt(skreq, src, dst, len, NULL);
return crypto_skcipher_encrypt(skreq);
}
+static int crypto_authenc_esn_copy(struct aead_request *req, unsigned int len)
+{
+ return crypto_authenc_esn_copy_sg(req, req->src, req->dst, len);
+}
+
static int crypto_authenc_esn_encrypt(struct aead_request *req)
{
struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
@@ -233,30 +241,39 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
crypto_ahash_alignmask(auth) + 1);
unsigned int cryptlen = req->cryptlen - authsize;
unsigned int assoclen = req->assoclen;
+ struct scatterlist *src = req->src;
struct scatterlist *dst = req->dst;
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
u32 tmp[2];
+ int err;
if (!authsize)
goto decrypt;
- /* Move high-order bits of sequence number back. */
- scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
- scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
- scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
+ if (src == dst) {
+ /* Move high-order bits of sequence number back. */
+ scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
+ scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
+ scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
+ } else {
+ err = crypto_authenc_esn_copy(req, assoclen);
+ if (err)
+ return err;
+ }
if (crypto_memneq(ihash, ohash, authsize))
return -EBADMSG;
decrypt:
- sg_init_table(areq_ctx->dst, 2);
+ if (src != dst)
+ src = scatterwalk_ffwd(areq_ctx->src, src, assoclen);
dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen);
skcipher_request_set_tfm(skreq, ctx->enc);
skcipher_request_set_callback(skreq, flags,
req->base.complete, req->base.data);
- skcipher_request_set_crypt(skreq, dst, dst, cryptlen, req->iv);
+ skcipher_request_set_crypt(skreq, src, dst, cryptlen, req->iv);
return crypto_skcipher_decrypt(skreq);
}
@@ -283,6 +300,7 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req)
unsigned int assoclen = req->assoclen;
unsigned int cryptlen = req->cryptlen;
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
+ struct scatterlist *src = req->src;
struct scatterlist *dst = req->dst;
u32 tmp[2];
int err;
@@ -290,27 +308,31 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req)
if (assoclen < 8)
return -EINVAL;
- cryptlen -= authsize;
-
- if (req->src != dst) {
- err = crypto_authenc_esn_copy(req, assoclen + cryptlen);
- if (err)
- return err;
- }
+ if (!authsize)
+ goto tail;
+ cryptlen -= authsize;
scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen,
authsize, 0);
- if (!authsize)
- goto tail;
-
/* Move high-order bits of sequence number to the end. */
- scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);
- scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
- scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
-
- sg_init_table(areq_ctx->dst, 2);
- dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
+ scatterwalk_map_and_copy(tmp, src, 0, 8, 0);
+ if (src == dst) {
+ scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
+ scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
+ dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
+ } else {
+ scatterwalk_map_and_copy(tmp, dst, 0, 4, 1);
+ scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen - 4, 4, 1);
+
+ src = scatterwalk_ffwd(areq_ctx->src, src, 8);
+ dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
+ err = crypto_authenc_esn_copy_sg(req, src, dst,
+ assoclen + cryptlen - 8);
+ if (err)
+ return err;
+ dst = req->dst;
+ }
ahash_request_set_tfm(ahreq, auth);
ahash_request_set_crypt(ahreq, dst, ohash, assoclen + cryptlen);
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,45 @@
From 37dc4d521edd3990b54849381ea8a82ee5f8bdc5 Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert.xu@redhat.com>
Date: Thu, 30 Apr 2026 19:56:24 +0800
Subject: [PATCH] crypto: authencesn - Fix src offset when decrypting in-place
JIRA: https://redhat.atlassian.net/browse/RHEL-172207
Upstream Status: 1f48ad3b19a9dfc947868edda0bb8e48e5b5a8fa
commit 1f48ad3b19a9dfc947868edda0bb8e48e5b5a8fa
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed Apr 15 07:39:06 2026 +0800
crypto: authencesn - Fix src offset when decrypting in-place
The src SG list offset wasn't set properly when decrypting in-place,
fix it.
Reported-by: Wolfgang Walter <linux@stwm.de>
Fixes: e02494114ebf ("crypto: authencesn - Do not place hiseq at end of dst for out-of-place decryption")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Herbert Xu <herbert.xu@redhat.com>
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
index 8664dad45792..9a586b0b7716 100644
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -266,9 +266,11 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
decrypt:
- if (src != dst)
- src = scatterwalk_ffwd(areq_ctx->src, src, assoclen);
dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen);
+ if (req->src == req->dst)
+ src = dst;
+ else
+ src = scatterwalk_ffwd(areq_ctx->src, src, assoclen);
skcipher_request_set_tfm(skreq, ctx->enc);
skcipher_request_set_callback(skreq, flags,
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,70 @@
From 18fe1da8a470fbfaf19071dac3e9f43a61bd2ec9 Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert.xu@redhat.com>
Date: Thu, 30 Apr 2026 20:02:19 +0800
Subject: [PATCH] crypto: authencesn - reject short ahash digests during
instance creation
JIRA: https://redhat.atlassian.net/browse/RHEL-172207
Upstream Status: cryptodev
commit 5db6ef9847717329f12c5ea8aba7e9f588a980c0
Author: Yucheng Lu <kanolyc@gmail.com>
Date: Wed Apr 22 21:45:04 2026 +0800
crypto: authencesn - reject short ahash digests during instance creation
authencesn requires either a zero authsize or an authsize of at least
4 bytes because the ESN encrypt/decrypt paths always move 4 bytes of
high-order sequence number data at the end of the authenticated data.
While crypto_authenc_esn_setauthsize() already rejects explicit
non-zero authsizes in the range 1..3, crypto_authenc_esn_create()
still copied auth->digestsize into inst->alg.maxauthsize without
validating it. The AEAD core then initialized the tfm's default
authsize from that value.
As a result, selecting an ahash with digest size 1..3, such as
cbcmac(cipher_null), exposed authencesn instances whose default
authsize was invalid even though setauthsize() would have rejected the
same value. AF_ALG could then trigger the ESN tail handling with a
too-short tag and hit an out-of-bounds access.
Reject authencesn instances whose ahash digest size is in the invalid
non-zero range 1..3 so that no tfm can inherit an unsupported default
authsize.
Fixes: f15f05b0a5de ("crypto: ccm - switch to separate cbcmac driver")
Cc: stable@kernel.org
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Co-developed-by: Yuan Tan <yuantan098@gmail.com>
Signed-off-by: Yuan Tan <yuantan098@gmail.com>
Suggested-by: Xin Liu <bird@lzu.edu.cn>
Tested-by: Yuhang Zheng <z1652074432@gmail.com>
Reviewed-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Yucheng Lu <kanolyc@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Herbert Xu <herbert.xu@redhat.com>
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
index 9a586b0b7716..b0f40fe03b56 100644
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -444,6 +444,11 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl,
auth = crypto_spawn_ahash_alg(&ctx->auth);
auth_base = &auth->base;
+ if (auth->digestsize > 0 && auth->digestsize < 4) {
+ err = -EINVAL;
+ goto err_free_inst;
+ }
+
err = crypto_grab_skcipher(&ctx->enc, aead_crypto_instance(inst),
crypto_attr_alg_name(tb[2]), 0, mask);
if (err)
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,42 @@
From 834916d950469022e266fb8667df2c17af47df94 Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert.xu@redhat.com>
Date: Fri, 1 May 2026 21:56:44 +0800
Subject: [PATCH] crypto: algif_aead - Fix minimum RX size check for decryption
JIRA: https://redhat.atlassian.net/browse/RHEL-172207
Upstream Status: 3d14bd48e3a77091cbce637a12c2ae31b4a1687c
commit 3d14bd48e3a77091cbce637a12c2ae31b4a1687c
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date: Sun Apr 12 13:32:21 2026 +0800
crypto: algif_aead - Fix minimum RX size check for decryption
The check for the minimum receive buffer size did not take the
tag size into account during decryption. Fix this by adding the
required extra length.
Reported-by: syzbot+aa11561819dc42ebbc7c@syzkaller.appspotmail.com
Reported-by: Daniel Pouzzner <douzzer@mega.nu>
Fixes: d887c52d6ae4 ("crypto: algif_aead - overhaul memory management")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Herbert Xu <herbert.xu@redhat.com>
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index 4a6a0bb1ae3c..029f1bd72fd7 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -169,7 +169,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
if (usedpages < outlen) {
size_t less = outlen - usedpages;
- if (used < less) {
+ if (used < less + (ctx->enc ? 0 : as)) {
err = -EINVAL;
goto free;
}
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,82 @@
From 39335f1f582fbe7006ab1d9c83f0957324ad0367 Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert.xu@redhat.com>
Date: Thu, 30 Apr 2026 20:03:29 +0800
Subject: [PATCH] crypto: algif_aead - snapshot IV for async AEAD requests
JIRA: https://redhat.atlassian.net/browse/RHEL-172207
Upstream Status: 5aa58c3a572b3e3b6c786953339f7978b845cc52
commit 5aa58c3a572b3e3b6c786953339f7978b845cc52
Author: Douya Le <ldy3087146292@gmail.com>
Date: Sun Apr 19 16:52:59 2026 +0800
crypto: algif_aead - snapshot IV for async AEAD requests
AF_ALG AEAD AIO requests currently use the socket-wide IV buffer during
request processing. For async requests, later socket activity can
update that shared state before the original request has fully
completed, which can lead to inconsistent IV handling.
Snapshot the IV into per-request storage when preparing the AEAD
request, so in-flight operations no longer depend on mutable socket
state.
Fixes: d887c52d6ae4 ("crypto: algif_aead - overhaul memory management")
Cc: stable@kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Co-developed-by: Luxing Yin <tr0jan@lzu.edu.cn>
Signed-off-by: Luxing Yin <tr0jan@lzu.edu.cn>
Tested-by: Yucheng Lu <kanolyc@gmail.com>
Signed-off-by: Douya Le <ldy3087146292@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Herbert Xu <herbert.xu@redhat.com>
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index 029f1bd72fd7..9b589ab1af20 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -97,8 +97,10 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
struct crypto_aead *tfm = aeadc->aead;
struct crypto_sync_skcipher *null_tfm = aeadc->null_tfm;
unsigned int as = crypto_aead_authsize(tfm);
+ unsigned int ivsize = crypto_aead_ivsize(tfm);
struct af_alg_async_req *areq;
struct scatterlist *rsgl_src, *tsgl_src = NULL;
+ void *iv;
int err = 0;
size_t used = 0; /* [in] TX bufs to be en/decrypted */
size_t outlen = 0; /* [out] RX bufs produced by kernel */
@@ -150,10 +152,14 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
/* Allocate cipher request for current operation. */
areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) +
- crypto_aead_reqsize(tfm));
+ crypto_aead_reqsize(tfm) + ivsize);
if (IS_ERR(areq))
return PTR_ERR(areq);
+ iv = (u8 *)aead_request_ctx(&areq->cra_u.aead_req) +
+ crypto_aead_reqsize(tfm);
+ memcpy(iv, ctx->iv, ivsize);
+
/* convert iovecs of output buffers into RX SGL */
err = af_alg_get_rsgl(sk, msg, flags, areq, outlen, &usedpages);
if (err)
@@ -215,7 +221,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
/* Initialize the crypto operation */
aead_request_set_crypt(&areq->cra_u.aead_req, tsgl_src,
- areq->first_rsgl.sgl.sg, used, ctx->iv);
+ areq->first_rsgl.sgl.sg, used, iv);
aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen);
aead_request_set_tfm(&areq->cra_u.aead_req, tfm);
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,99 @@
From 52a21cfbdbc63d33544aafaa89e3ac9571268065 Mon Sep 17 00:00:00 2001
From: Sabrina Dubroca <sdubroca@redhat.com>
Date: Fri, 8 May 2026 00:56:43 +0200
Subject: [PATCH] xfrm: esp: avoid in-place decrypt on shared skb frags
JIRA: https://redhat.atlassian.net/browse/RHEL-174565
CVE: CVE-2026-43284
Conflicts: rhel9 doesn't use MSG_SPLICE_PAGES in
sendmsg/ip_append_data
patch udp_sendpage/ip_append_page instead
nothing to do for ipv6, no .sendpage for UDP there
commit f4c50a4034e62ab75f1d5cdd191dd5f9c77fdff4
Author: Kuan-Ting Chen <h3xrabbit@gmail.com>
Date: Mon May 4 23:27:12 2026 +0800
xfrm: esp: avoid in-place decrypt on shared skb frags
MSG_SPLICE_PAGES can attach pages from a pipe directly to an skb. TCP
marks such skbs with SKBFL_SHARED_FRAG after skb_splice_from_iter(),
so later paths that may modify packet data can first make a private
copy. The IPv4/IPv6 datagram append paths did not set this flag when
splicing pages into UDP skbs.
That leaves an ESP-in-UDP packet made from shared pipe pages looking
like an ordinary uncloned nonlinear skb. ESP input then takes the no-COW
fast path for uncloned skbs without a frag_list and decrypts in place
over data that is not owned privately by the skb.
Mark IPv4/IPv6 datagram splice frags with SKBFL_SHARED_FRAG, matching
TCP. Also make ESP input fall back to skb_cow_data() when the flag is
present, so ESP does not decrypt externally backed frags in place.
Private nonlinear skb frags still use the existing fast path.
This intentionally does not change ESP output. In esp_output_head(),
the path that appends the ESP trailer to existing skb tailroom without
calling skb_cow_data() is not reachable for nonlinear skbs:
skb_tailroom() returns zero when skb->data_len is nonzero, while ESP
tailen is positive. Thus ESP output will either use the separate
destination-frag path or fall back to skb_cow_data().
Fixes: cac2661c53f3 ("esp4: Avoid skb_cow_data whenever possible")
Fixes: 03e2a30f6a27 ("esp6: Avoid skb_cow_data whenever possible")
Fixes: 7da0dde68486 ("ip, udp: Support MSG_SPLICE_PAGES")
Fixes: 6d8192bd69bb ("ip6, udp6: Support MSG_SPLICE_PAGES")
Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Reported-by: Kuan-Ting Chen <h3xrabbit@gmail.com>
Tested-by: Hyunwoo Kim <imv4bel@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Kuan-Ting Chen <h3xrabbit@gmail.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Sabrina Dubroca <sdubroca@redhat.com>
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 4d07a51fa9a0..8ff8489bbf37 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -881,7 +881,8 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
nfrags = 1;
goto skip_cow;
- } else if (!skb_has_frag_list(skb)) {
+ } else if (!skb_has_frag_list(skb) &&
+ !skb_has_shared_frag(skb)) {
nfrags = skb_shinfo(skb)->nr_frags;
nfrags++;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index ec48d434acca..9c000e0ceb39 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1480,6 +1480,9 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
goto error;
}
+ if (!(flags & MSG_NO_SHARED_FRAGS))
+ skb_shinfo(skb)->flags |= SKBFL_SHARED_FRAG;
+
if (skb->ip_summed == CHECKSUM_NONE) {
__wsum csum;
csum = csum_page(page, offset, len);
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 07565986cf82..7e17e9e1a33b 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -921,7 +921,8 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
nfrags = 1;
goto skip_cow;
- } else if (!skb_has_frag_list(skb)) {
+ } else if (!skb_has_frag_list(skb) &&
+ !skb_has_shared_frag(skb)) {
nfrags = skb_shinfo(skb)->nr_frags;
nfrags++;
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,65 @@
From a535a9217ca3f2fccedaafb2fddb4c48f27d36dc Mon Sep 17 00:00:00 2001
From: Samuel Page <sam@bynar.io>
Date: Wed, 8 Apr 2026 15:30:13 +0100
Subject: [PATCH] can: raw: fix ro->uniq use-after-free in raw_rcv()
raw_release() unregisters raw CAN receive filters via can_rx_unregister(),
but receiver deletion is deferred with call_rcu(). This leaves a window
where raw_rcv() may still be running in an RCU read-side critical section
after raw_release() frees ro->uniq, leading to a use-after-free of the
percpu uniq storage.
Move free_percpu(ro->uniq) out of raw_release() and into a raw-specific
socket destructor. can_rx_unregister() takes an extra reference to the
socket and only drops it from the RCU callback, so freeing uniq from
sk_destruct ensures the percpu area is not released until the relevant
callbacks have drained.
Fixes: 514ac99c64b2 ("can: fix multiple delivery of a single CAN frame for overlapping CAN filters")
Cc: stable@vger.kernel.org # v4.1+
Assisted-by: Bynario AI
Signed-off-by: Samuel Page <sam@bynar.io>
Link: https://patch.msgid.link/26ec626d-cae7-4418-9782-7198864d070c@bynar.io
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
[mkl: applied manually]
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
diff --git a/net/can/raw.c b/net/can/raw.c
index eee244ffc31e..58a96e933deb 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -361,6 +361,14 @@ static int raw_notifier(struct notifier_block *nb, unsigned long msg,
return NOTIFY_DONE;
}
+static void raw_sock_destruct(struct sock *sk)
+{
+ struct raw_sock *ro = raw_sk(sk);
+
+ free_percpu(ro->uniq);
+ can_sock_destruct(sk);
+}
+
static int raw_init(struct sock *sk)
{
struct raw_sock *ro = raw_sk(sk);
@@ -387,6 +395,8 @@ static int raw_init(struct sock *sk)
if (unlikely(!ro->uniq))
return -ENOMEM;
+ sk->sk_destruct = raw_sock_destruct;
+
/* set notifier */
spin_lock(&raw_notifier_lock);
list_add_tail(&ro->notifier, &raw_notifier_list);
@@ -436,7 +446,6 @@ static int raw_release(struct socket *sock)
ro->bound = 0;
ro->dev = NULL;
ro->count = 0;
- free_percpu(ro->uniq);
sock_orphan(sk);
sock->sk = NULL;
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,95 @@
From 98551d7729dace772c045e8696df06ba532d4088 Mon Sep 17 00:00:00 2001
From: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
Date: Tue, 28 Apr 2026 11:39:45 +0000
Subject: [PATCH] usbip: validate number_of_packets in usbip_pack_ret_submit()
JIRA: https://redhat.atlassian.net/browse/RHEL-171433
CVE: CVE-2026-31607
commit 2ab833a16a825373aad2ba7d54b572b277e95b71
Author: Nathan Rebello <nathan.c.rebello@gmail.com>
Date: Thu Apr 2 04:52:59 2026 -0400
usbip: validate number_of_packets in usbip_pack_ret_submit()
When a USB/IP client receives a RET_SUBMIT response,
usbip_pack_ret_submit() unconditionally overwrites
urb->number_of_packets from the network PDU. This value is
subsequently used as the loop bound in usbip_recv_iso() and
usbip_pad_iso() to iterate over urb->iso_frame_desc[], a flexible
array whose size was fixed at URB allocation time based on the
*original* number_of_packets from the CMD_SUBMIT.
A malicious USB/IP server can set number_of_packets in the response
to a value larger than what was originally submitted, causing a heap
out-of-bounds write when usbip_recv_iso() writes to
urb->iso_frame_desc[i] beyond the allocated region.
KASAN confirmed this with kernel 7.0.0-rc5:
BUG: KASAN: slab-out-of-bounds in usbip_recv_iso+0x46a/0x640
Write of size 4 at addr ffff888106351d40 by task vhci_rx/69
The buggy address is located 0 bytes to the right of
allocated 320-byte region [ffff888106351c00, ffff888106351d40)
The server side (stub_rx.c) and gadget side (vudc_rx.c) already
validate number_of_packets in the CMD_SUBMIT path since commits
c6688ef9f297 ("usbip: fix stub_rx: harden CMD_SUBMIT path to handle
malicious input") and b78d830f0049 ("usbip: fix vudc_rx: harden
CMD_SUBMIT path to handle malicious input"). The server side validates
against USBIP_MAX_ISO_PACKETS because no URB exists yet at that point.
On the client side we have the original URB, so we can use the tighter
bound: the response must not exceed the original number_of_packets.
This mirrors the existing validation of actual_length against
transfer_buffer_length in usbip_recv_xbuff(), which checks the
response value against the original allocation size.
Kelvin Mbogo's series ("usb: usbip: fix integer overflow in
usbip_recv_iso()", v2) hardens the receive-side functions themselves;
this patch complements that work by catching the bad value at its
source -- in usbip_pack_ret_submit() before the overwrite -- and
using the tighter per-URB allocation bound rather than the global
USBIP_MAX_ISO_PACKETS limit.
Fix this by checking rpdu->number_of_packets against
urb->number_of_packets in usbip_pack_ret_submit() before the
overwrite. On violation, clamp to zero so that usbip_recv_iso() and
usbip_pad_iso() safely return early.
Fixes: 1325f85fa49f ("staging: usbip: bugfix add number of packets for isochronous frames")
Cc: stable <stable@kernel.org>
Acked-by: Shuah Khan <skhan@linuxfoundation.org>
Signed-off-by: Nathan Rebello <nathan.c.rebello@gmail.com>
Link: https://patch.msgid.link/20260402085259.234-1-nathan.c.rebello@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com>
diff --git a/drivers/usb/usbip/usbip_common.c b/drivers/usb/usbip/usbip_common.c
index a2b2da1255dd..ba9e7c616e12 100644
--- a/drivers/usb/usbip/usbip_common.c
+++ b/drivers/usb/usbip/usbip_common.c
@@ -470,6 +470,18 @@ static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb,
urb->status = rpdu->status;
urb->actual_length = rpdu->actual_length;
urb->start_frame = rpdu->start_frame;
+ /*
+ * The number_of_packets field determines the length of
+ * iso_frame_desc[], which is a flexible array allocated
+ * at URB creation time. A response must never claim more
+ * packets than originally submitted; doing so would cause
+ * an out-of-bounds write in usbip_recv_iso() and
+ * usbip_pad_iso(). Clamp to zero on violation so both
+ * functions safely return early.
+ */
+ if (rpdu->number_of_packets < 0 ||
+ rpdu->number_of_packets > urb->number_of_packets)
+ rpdu->number_of_packets = 0;
urb->number_of_packets = rpdu->number_of_packets;
urb->error_count = rpdu->error_count;
}
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,54 @@
From 31e26e3f09482329fb7f0fcf3893ed2dbb4e231a Mon Sep 17 00:00:00 2001
From: Kamal Heib <kheib@redhat.com>
Date: Tue, 28 Apr 2026 13:24:19 -0400
Subject: [PATCH] RDMA/umem: Fix double dma_buf_unpin in failure path
JIRA: https://redhat.atlassian.net/browse/RHEL-163491
commit 104016eb671e19709721c1b0048dd912dc2e96be
Author: Jacob Moroni <jmoroni@google.com>
Date: Tue Feb 24 23:41:53 2026 +0000
RDMA/umem: Fix double dma_buf_unpin in failure path
In ib_umem_dmabuf_get_pinned_with_dma_device(), the call to
ib_umem_dmabuf_map_pages() can fail. If this occurs, the dmabuf
is immediately unpinned but the umem_dmabuf->pinned flag is still
set. Then, when ib_umem_release() is called, it calls
ib_umem_dmabuf_revoke() which will call dma_buf_unpin() again.
Fix this by removing the immediate unpin upon failure and just let
the ib_umem_release/revoke path handle it. This also ensures the
proper unmap-unpin unwind ordering if the dmabuf_map_pages call
happened to fail due to dma_resv_wait_timeout (and therefore has
a non-NULL umem_dmabuf->sgt).
Fixes: 1e4df4a21c5a ("RDMA/umem: Allow pinned dmabuf umem usage")
Signed-off-by: Jacob Moroni <jmoroni@google.com>
Link: https://patch.msgid.link/20260224234153.1207849-1-jmoroni@google.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Kamal Heib <kheib@redhat.com>
diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c
index 2023a735de20..8d6430278000 100644
--- a/drivers/infiniband/core/umem_dmabuf.c
+++ b/drivers/infiniband/core/umem_dmabuf.c
@@ -220,13 +220,11 @@ ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device,
err = ib_umem_dmabuf_map_pages(umem_dmabuf);
if (err)
- goto err_unpin;
+ goto err_release;
dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv);
return umem_dmabuf;
-err_unpin:
- dma_buf_unpin(umem_dmabuf->attach);
err_release:
dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv);
ib_umem_release(&umem_dmabuf->umem);
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,57 @@
From 43ed28eec61843c0cc821683028c70c9419a7b40 Mon Sep 17 00:00:00 2001
From: Nigel Croxon <ncroxon@redhat.com>
Date: Mon, 16 Feb 2026 13:50:16 -0500
Subject: [PATCH] md/bitmap: fix GPF in write_page caused by resize race
JIRA: https://issues.redhat.com/browse/RHEL-129338
commit 46ef85f854dfa9d5226b3c1c46493d79556c9589
Author: Jack Wang <jinpu.wang@ionos.com>
Date: Tue Jan 20 11:24:56 2026 +0100
md/bitmap: fix GPF in write_page caused by resize race
A General Protection Fault occurs in write_page() during array resize:
RIP: 0010:write_page+0x22b/0x3c0 [md_mod]
This is a use-after-free race between bitmap_daemon_work() and
__bitmap_resize(). The daemon iterates over `bitmap->storage.filemap`
without locking, while the resize path frees that storage via
md_bitmap_file_unmap(). `quiesce()` does not stop the md thread,
allowing concurrent access to freed pages.
Fix by holding `mddev->bitmap_info.mutex` during the bitmap update.
Link: https://lore.kernel.org/linux-raid/20260120102456.25169-1-jinpu.wang@ionos.com
Closes: https://lore.kernel.org/linux-raid/CAMGffE=Mbfp=7xD_hYxXk1PAaCZNSEAVeQGKGy7YF9f2S4=NEA@mail.gmail.com/T/#u
Cc: stable@vger.kernel.org
Fixes: d60b479d177a ("md/bitmap: add bitmap_resize function to allow bitmap resizing.")
Signed-off-by: Jack Wang <jinpu.wang@ionos.com>
Signed-off-by: Yu Kuai <yukuai@fnnas.com>
Signed-off-by: Nigel Croxon <ncroxon@redhat.com>
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index 6280bae60526..3b86909a411e 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -2453,6 +2453,7 @@ static int __bitmap_resize(struct bitmap *bitmap, sector_t blocks,
memcpy(page_address(store.sb_page),
page_address(bitmap->storage.sb_page),
sizeof(bitmap_super_t));
+ mutex_lock(&bitmap->mddev->bitmap_info.mutex);
spin_lock_irq(&bitmap->counts.lock);
md_bitmap_file_unmap(&bitmap->storage);
bitmap->storage = store;
@@ -2560,7 +2561,7 @@ static int __bitmap_resize(struct bitmap *bitmap, sector_t blocks,
set_page_attr(bitmap, i, BITMAP_PAGE_DIRTY);
}
spin_unlock_irq(&bitmap->counts.lock);
-
+ mutex_unlock(&bitmap->mddev->bitmap_info.mutex);
if (!init) {
__bitmap_unplug(bitmap);
bitmap->mddev->pers->quiesce(bitmap->mddev, 0);
--
2.50.1 (Apple Git-155)

View File

@ -0,0 +1,122 @@
From bb79c39164a6539d01cfa3151a81da5be998840f Mon Sep 17 00:00:00 2001
From: Ricardo Robaina <rrobaina@redhat.com>
Date: Fri, 15 May 2026 10:20:50 -0300
Subject: [PATCH] ptrace: slightly saner 'get_dumpable()' logic
JIRA: https://issues.redhat.com/browse/RHEL-176447
CVE: CVE-2026-46333
Conflicts:
- Minor context conflict due to missing upstream commit
90383cc07895 ("exec: Distinguish in_execve from in_exec")
commit 31e62c2ebbfdc3fe3dbdf5e02c92a9dc67087a3a
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date: Wed May 13 11:37:18 2026 -0700
ptrace: slightly saner 'get_dumpable()' logic
The 'dumpability' of a task is fundamentally about the memory image of
the task - the concept comes from whether it can core dump or not - and
makes no sense when you don't have an associated mm.
And almost all users do in fact use it only for the case where the task
has a mm pointer.
But we have one odd special case: ptrace_may_access() uses 'dumpable' to
check various other things entirely independently of the MM (typically
explicitly using flags like PTRACE_MODE_READ_FSCREDS). Including for
threads that no longer have a VM (and maybe never did, like most kernel
threads).
It's not what this flag was designed for, but it is what it is.
The ptrace code does check that the uid/gid matches, so you do have to
be uid-0 to see kernel thread details, but this means that the
traditional "drop capabilities" model doesn't make any difference for
this all.
Make it all make a *bit* more sense by saying that if you don't have a
MM pointer, we'll use a cached "last dumpability" flag if the thread
ever had a MM (it will be zero for kernel threads since it is never
set), and require a proper CAP_SYS_PTRACE capability to override.
Reported-by: Qualys Security Advisory <qsa@qualys.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Kees Cook <kees@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ricardo Robaina <rrobaina@redhat.com>
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 066ab5f..0ecc266 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -936,6 +936,9 @@ struct task_struct {
unsigned sched_migrated:1;
unsigned sched_task_hot:1;
+ /* Save user-dumpable when mm goes away */
+ RH_KABI_FILL_HOLE(unsigned user_dumpable:1)
+
/* Force alignment to the next boundary: */
unsigned :0;
diff --git a/kernel/exit.c b/kernel/exit.c
index 8782a6b..aa08b46 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -534,6 +534,7 @@ static void exit_mm(void)
*/
smp_mb__after_spinlock();
local_irq_disable();
+ current->user_dumpable = (get_dumpable(mm) == SUID_DUMP_USER);
current->mm = NULL;
membarrier_update_current_mm(NULL);
enter_lazy_tlb(mm, current);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index a0fd4bd..495fde1 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -282,11 +282,24 @@ static bool ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
return ns_capable(ns, CAP_SYS_PTRACE);
}
+static bool task_still_dumpable(struct task_struct *task, unsigned int mode)
+{
+ struct mm_struct *mm = task->mm;
+ if (mm) {
+ if (get_dumpable(mm) == SUID_DUMP_USER)
+ return true;
+ return ptrace_has_cap(mm->user_ns, mode);
+ }
+
+ if (task->user_dumpable)
+ return true;
+ return ptrace_has_cap(&init_user_ns, mode);
+}
+
/* Returns 0 on success, -errno on denial. */
static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
{
const struct cred *cred = current_cred(), *tcred;
- struct mm_struct *mm;
kuid_t caller_uid;
kgid_t caller_gid;
@@ -347,11 +360,8 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
* Pairs with a write barrier in commit_creds().
*/
smp_rmb();
- mm = task->mm;
- if (mm &&
- ((get_dumpable(mm) != SUID_DUMP_USER) &&
- !ptrace_has_cap(mm->user_ns, mode)))
- return -EPERM;
+ if (!task_still_dumpable(task, mode))
+ return -EPERM;
return security_ptrace_access_check(task, mode);
}

View File

@ -0,0 +1,45 @@
From f84eca5817390257cef78013d0112481c503b4a3 Mon Sep 17 00:00:00 2001
From: William Bowling <vakzz@zellic.io>
Date: Wed, 13 May 2026 04:16:35 +0000
Subject: [PATCH] net: skbuff: preserve shared-frag marker during coalescing
skb_try_coalesce() can attach paged frags from @from to @to. If @from
has SKBFL_SHARED_FRAG set, the resulting @to skb can contain the same
externally-owned or page-cache-backed frags, but the shared-frag marker
is currently lost.
That breaks the invariant relied on by later in-place writers. In
particular, ESP input checks skb_has_shared_frag() before deciding
whether an uncloned nonlinear skb can skip skb_cow_data(). If TCP
receive coalescing has moved shared frags into an unmarked skb, ESP can
see skb_has_shared_frag() as false and decrypt in place over page-cache
backed frags.
Propagate SKBFL_SHARED_FRAG when skb_try_coalesce() transfers paged
frags. The tailroom copy path does not need the marker because it copies
bytes into @to's linear data rather than transferring frag descriptors.
Fixes: cef401de7be8 ("net: fix possible wrong checksum generation")
Fixes: f4c50a4034e6 ("xfrm: esp: avoid in-place decrypt on shared skb frags")
Signed-off-by: William Bowling <vakzz@zellic.io>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Tested-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Link: https://patch.msgid.link/20260513041635.1289541-1-vakzz@zellic.io
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 7dad68e3b518..9c4e8d331d6d 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -6200,6 +6200,8 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
from_shinfo->frags,
from_shinfo->nr_frags * sizeof(skb_frag_t));
to_shinfo->nr_frags += from_shinfo->nr_frags;
+ if (from_shinfo->nr_frags)
+ to_shinfo->flags |= from_shinfo->flags & SKBFL_SHARED_FRAG;
if (!skb_cloned(from))
from_shinfo->nr_frags = 0;
--
2.50.1 (Apple Git-155)

Some files were not shown because too many files have changed in this diff Show More