From d9fd5d80d831d219c7a0c9fe296c85af8995f172 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sat, 1 Mar 2025 09:19:52 -0500 Subject: [PATCH] Fixes for 6.6 Signed-off-by: Sasha Levin --- ...er_list-to-unuse-a-displaced-server-.patch | 59 +++ ...ible-to-find-the-volumes-that-are-us.patch | 417 +++++++++++++++ ...-add-quirks-for-asus-rog-2023-models.patch | 85 ++++ ...-fix-wrong-mic-setup-for-asus-vivobo.patch | 45 ++ ...void-dropping-midi-events-at-closing.patch | 47 ++ ...-es8328-fix-route-from-dac-to-output.patch | 110 ++++ ...ap-fix-l2cap_ecred_conn_rsp-response.patch | 99 ++++ ...re-cs_dsp-remove-async-regmap-writes.patch | 115 +++++ ...30-device-ids-mac-type-and-registers.patch | 476 ++++++++++++++++++ ...-hw-vf-mailbox-message-limit-support.patch | 289 +++++++++++ ...-fix-deinitializing-vf-in-error-path.patch | 114 +++++ ...static-inline-dst_dev_overhead-to-ds.patch | 49 ++ ...-convert-icmp_route_lookup-to-dscp_t.patch | 81 +++ ...pv4-convert-ip_route_input-to-dscp_t.patch | 156 ++++++ ...pass-full-ds-field-to-ip_route_input.patch | 44 ++ ...-upper-dscp-bits-in-icmp_route_looku.patch | 51 ++ ...twork-headers-are-in-skb-linear-part.patch | 113 +++++ ...pvlan_process_v4_outbound-to-future-.patch | 50 ++ ...per-dscp-bits-in-ipvlan_process_v4_o.patch | 47 ++ ...r-ipvs_property-flag-in-skb_scrub_pa.patch | 51 ++ ...-macb-synchronize-stats-calculations.patch | 115 +++++ ...agment-checksum-value-in-napi_reuse_.patch | 77 +++ ...et-ipv4-add-tracepoint-for-icmp_send.patch | 153 ++++++ ...fix-dst-ref-loop-on-input-in-rpl-lwt.patch | 60 +++ ...ix-dst-ref-loop-on-input-in-seg6-lwt.patch | 60 +++ ...pl_iptunnel-mitigate-2-realloc-issue.patch | 154 ++++++ ...g6_iptunnel-mitigate-2-realloc-issue.patch | 254 ++++++++++ ...id-sending-ip-packets-without-an-eth.patch | 94 ++++ ...5-irq-fix-null-string-in-debug-print.patch | 42 ++ ...xed-non-ip-flow-with-vlan-tag-flow-d.patch | 40 ++ ...mum-for-net_hotdata.netdev_budget_us.patch | 58 +++ ...iep-reject-perout-generation-request.patch | 60 +++ ...remove-spinlock-based-synchronizatio.patch | 114 +++++ ...-missing-decoding-of-terminal-magic-.patch | 51 ++ queue-6.6/series | 35 ++ ...ts_recent-changes-until-req-is-owned.patch | 92 ++++ 36 files changed, 3957 insertions(+) create mode 100644 queue-6.6/afs-fix-the-server_list-to-unuse-a-displaced-server-.patch create mode 100644 queue-6.6/afs-make-it-possible-to-find-the-volumes-that-are-us.patch create mode 100644 queue-6.6/alsa-hda-realtek-add-quirks-for-asus-rog-2023-models.patch create mode 100644 queue-6.6/alsa-hda-realtek-fix-wrong-mic-setup-for-asus-vivobo.patch create mode 100644 queue-6.6/alsa-usb-audio-avoid-dropping-midi-events-at-closing.patch create mode 100644 queue-6.6/asoc-es8328-fix-route-from-dac-to-output.patch create mode 100644 queue-6.6/bluetooth-l2cap-fix-l2cap_ecred_conn_rsp-response.patch create mode 100644 queue-6.6/firmware-cs_dsp-remove-async-regmap-writes.patch create mode 100644 queue-6.6/ice-add-e830-device-ids-mac-type-and-registers.patch create mode 100644 queue-6.6/ice-add-e830-hw-vf-mailbox-message-limit-support.patch create mode 100644 queue-6.6/ice-fix-deinitializing-vf-in-error-path.patch create mode 100644 queue-6.6/include-net-add-static-inline-dst_dev_overhead-to-ds.patch create mode 100644 queue-6.6/ipv4-convert-icmp_route_lookup-to-dscp_t.patch create mode 100644 queue-6.6/ipv4-convert-ip_route_input-to-dscp_t.patch create mode 100644 queue-6.6/ipv4-icmp-pass-full-ds-field-to-ip_route_input.patch create mode 100644 queue-6.6/ipv4-icmp-unmask-upper-dscp-bits-in-icmp_route_looku.patch create mode 100644 queue-6.6/ipvlan-ensure-network-headers-are-in-skb-linear-part.patch create mode 100644 queue-6.6/ipvlan-prepare-ipvlan_process_v4_outbound-to-future-.patch create mode 100644 queue-6.6/ipvlan-unmask-upper-dscp-bits-in-ipvlan_process_v4_o.patch create mode 100644 queue-6.6/ipvs-always-clear-ipvs_property-flag-in-skb_scrub_pa.patch create mode 100644 queue-6.6/net-cadence-macb-synchronize-stats-calculations.patch create mode 100644 queue-6.6/net-clear-old-fragment-checksum-value-in-napi_reuse_.patch create mode 100644 queue-6.6/net-ipv4-add-tracepoint-for-icmp_send.patch create mode 100644 queue-6.6/net-ipv6-fix-dst-ref-loop-on-input-in-rpl-lwt.patch create mode 100644 queue-6.6/net-ipv6-fix-dst-ref-loop-on-input-in-seg6-lwt.patch create mode 100644 queue-6.6/net-ipv6-rpl_iptunnel-mitigate-2-realloc-issue.patch create mode 100644 queue-6.6/net-ipv6-seg6_iptunnel-mitigate-2-realloc-issue.patch create mode 100644 queue-6.6/net-loopback-avoid-sending-ip-packets-without-an-eth.patch create mode 100644 queue-6.6/net-mlx5-irq-fix-null-string-in-debug-print.patch create mode 100644 queue-6.6/net-mvpp2-cls-fixed-non-ip-flow-with-vlan-tag-flow-d.patch create mode 100644 queue-6.6/net-set-the-minimum-for-net_hotdata.netdev_budget_us.patch create mode 100644 queue-6.6/net-ti-icss-iep-reject-perout-generation-request.patch create mode 100644 queue-6.6/net-ti-icss-iep-remove-spinlock-based-synchronizatio.patch create mode 100644 queue-6.6/rxrpc-rxperf-fix-missing-decoding-of-terminal-magic-.patch create mode 100644 queue-6.6/tcp-defer-ts_recent-changes-until-req-is-owned.patch diff --git a/queue-6.6/afs-fix-the-server_list-to-unuse-a-displaced-server-.patch b/queue-6.6/afs-fix-the-server_list-to-unuse-a-displaced-server-.patch new file mode 100644 index 0000000000..226abf8b6f --- /dev/null +++ b/queue-6.6/afs-fix-the-server_list-to-unuse-a-displaced-server-.patch @@ -0,0 +1,59 @@ +From 2f6124ec0bc845a8eee569dd3c9791e98ef713e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 19:22:47 +0000 +Subject: afs: Fix the server_list to unuse a displaced server rather than + putting it + +From: David Howells + +[ Upstream commit add117e48df4788a86a21bd0515833c0a6db1ad1 ] + +When allocating and building an afs_server_list struct object from a VLDB +record, we look up each server address to get the server record for it - +but a server may have more than one entry in the record and we discard the +duplicate pointers. Currently, however, when we discard, we only put a +server record, not unuse it - but the lookup got as an active-user count. + +The active-user count on an afs_server_list object determines its lifetime +whereas the refcount keeps the memory backing it around. Failing to reduce +the active-user counter prevents the record from being cleaned up and can +lead to multiple copied being seen - and pointing to deleted afs_cell +objects and other such things. + +Fix this by switching the incorrect 'put' to an 'unuse' instead. + +Without this, occasionally, a dead server record can be seen in +/proc/net/afs/servers and list corruption may be observed: + + list_del corruption. prev->next should be ffff888102423e40, but was 0000000000000000. (prev=ffff88810140cd38) + +Fixes: 977e5f8ed0ab ("afs: Split the usage count on struct afs_server") +Signed-off-by: David Howells +cc: Marc Dionne +cc: Simon Horman +cc: linux-afs@lists.infradead.org +Link: https://patch.msgid.link/20250218192250.296870-5-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + fs/afs/server_list.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/afs/server_list.c b/fs/afs/server_list.c +index 4d6369477f54e..89c75d934f79e 100644 +--- a/fs/afs/server_list.c ++++ b/fs/afs/server_list.c +@@ -67,8 +67,8 @@ struct afs_server_list *afs_alloc_server_list(struct afs_volume *volume, + break; + if (j < slist->nr_servers) { + if (slist->servers[j].server == server) { +- afs_put_server(volume->cell->net, server, +- afs_server_trace_put_slist_isort); ++ afs_unuse_server(volume->cell->net, server, ++ afs_server_trace_put_slist_isort); + continue; + } + +-- +2.39.5 + diff --git a/queue-6.6/afs-make-it-possible-to-find-the-volumes-that-are-us.patch b/queue-6.6/afs-make-it-possible-to-find-the-volumes-that-are-us.patch new file mode 100644 index 0000000000..d96b636739 --- /dev/null +++ b/queue-6.6/afs-make-it-possible-to-find-the-volumes-that-are-us.patch @@ -0,0 +1,417 @@ +From 2af2962ff6e69060eedc9237acb349589611d3c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Nov 2023 16:08:43 +0000 +Subject: afs: Make it possible to find the volumes that are using a server + +From: David Howells + +[ Upstream commit ca0e79a46097d54e4af46c67c852479d97af35bb ] + +Make it possible to find the afs_volume structs that are using an +afs_server struct to aid in breaking volume callbacks. + +The way this is done is that each afs_volume already has an array of +afs_server_entry records that point to the servers where that volume might +be found. An afs_volume backpointer and a list node is added to each entry +and each entry is then added to an RCU-traversable list on the afs_server +to which it points. + +Signed-off-by: David Howells +cc: Marc Dionne +cc: linux-afs@lists.infradead.org +Stable-dep-of: add117e48df4 ("afs: Fix the server_list to unuse a displaced server rather than putting it") +Signed-off-by: Sasha Levin +--- + fs/afs/cell.c | 1 + + fs/afs/internal.h | 23 +++++---- + fs/afs/server.c | 1 + + fs/afs/server_list.c | 112 +++++++++++++++++++++++++++++++++++++++---- + fs/afs/vl_alias.c | 2 +- + fs/afs/volume.c | 36 ++++++++------ + 6 files changed, 143 insertions(+), 32 deletions(-) + +diff --git a/fs/afs/cell.c b/fs/afs/cell.c +index 926cb1188eba6..7c0dce8eecadd 100644 +--- a/fs/afs/cell.c ++++ b/fs/afs/cell.c +@@ -161,6 +161,7 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net, + refcount_set(&cell->ref, 1); + atomic_set(&cell->active, 0); + INIT_WORK(&cell->manager, afs_manage_cell_work); ++ spin_lock_init(&cell->vs_lock); + cell->volumes = RB_ROOT; + INIT_HLIST_HEAD(&cell->proc_volumes); + seqlock_init(&cell->volume_lock); +diff --git a/fs/afs/internal.h b/fs/afs/internal.h +index 2f135d19545b1..0973cd0a39695 100644 +--- a/fs/afs/internal.h ++++ b/fs/afs/internal.h +@@ -379,6 +379,7 @@ struct afs_cell { + unsigned int debug_id; + + /* The volumes belonging to this cell */ ++ spinlock_t vs_lock; /* Lock for server->volumes */ + struct rb_root volumes; /* Tree of volumes on this server */ + struct hlist_head proc_volumes; /* procfs volume list */ + seqlock_t volume_lock; /* For volumes */ +@@ -502,6 +503,7 @@ struct afs_server { + struct hlist_node addr4_link; /* Link in net->fs_addresses4 */ + struct hlist_node addr6_link; /* Link in net->fs_addresses6 */ + struct hlist_node proc_link; /* Link in net->fs_proc */ ++ struct list_head volumes; /* RCU list of afs_server_entry objects */ + struct work_struct initcb_work; /* Work for CB.InitCallBackState* */ + struct afs_server *gc_next; /* Next server in manager's list */ + time64_t unuse_time; /* Time at which last unused */ +@@ -550,12 +552,14 @@ struct afs_server { + */ + struct afs_server_entry { + struct afs_server *server; ++ struct afs_volume *volume; ++ struct list_head slink; /* Link in server->volumes */ + }; + + struct afs_server_list { + struct rcu_head rcu; +- afs_volid_t vids[AFS_MAXTYPES]; /* Volume IDs */ + refcount_t usage; ++ bool attached; /* T if attached to servers */ + unsigned char nr_servers; + unsigned char preferred; /* Preferred server */ + unsigned short vnovol_mask; /* Servers to be skipped due to VNOVOL */ +@@ -568,10 +572,9 @@ struct afs_server_list { + * Live AFS volume management. + */ + struct afs_volume { +- union { +- struct rcu_head rcu; +- afs_volid_t vid; /* volume ID */ +- }; ++ struct rcu_head rcu; ++ afs_volid_t vid; /* The volume ID of this volume */ ++ afs_volid_t vids[AFS_MAXTYPES]; /* All associated volume IDs */ + refcount_t ref; + time64_t update_at; /* Time at which to next update */ + struct afs_cell *cell; /* Cell to which belongs (pins ref) */ +@@ -1453,10 +1456,14 @@ static inline struct afs_server_list *afs_get_serverlist(struct afs_server_list + } + + extern void afs_put_serverlist(struct afs_net *, struct afs_server_list *); +-extern struct afs_server_list *afs_alloc_server_list(struct afs_cell *, struct key *, +- struct afs_vldb_entry *, +- u8); ++struct afs_server_list *afs_alloc_server_list(struct afs_volume *volume, ++ struct key *key, ++ struct afs_vldb_entry *vldb); + extern bool afs_annotate_server_list(struct afs_server_list *, struct afs_server_list *); ++void afs_attach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *slist); ++void afs_reattach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *slist, ++ struct afs_server_list *old); ++void afs_detach_volume_from_servers(struct afs_volume *volume, struct afs_server_list *slist); + + /* + * super.c +diff --git a/fs/afs/server.c b/fs/afs/server.c +index 0bd2f5ba6900c..87381c2ffe374 100644 +--- a/fs/afs/server.c ++++ b/fs/afs/server.c +@@ -236,6 +236,7 @@ static struct afs_server *afs_alloc_server(struct afs_cell *cell, + server->addr_version = alist->version; + server->uuid = *uuid; + rwlock_init(&server->fs_lock); ++ INIT_LIST_HEAD(&server->volumes); + INIT_WORK(&server->initcb_work, afs_server_init_callback_work); + init_waitqueue_head(&server->probe_wq); + INIT_LIST_HEAD(&server->probe_link); +diff --git a/fs/afs/server_list.c b/fs/afs/server_list.c +index b59896b1de0af..4d6369477f54e 100644 +--- a/fs/afs/server_list.c ++++ b/fs/afs/server_list.c +@@ -24,13 +24,13 @@ void afs_put_serverlist(struct afs_net *net, struct afs_server_list *slist) + /* + * Build a server list from a VLDB record. + */ +-struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell, ++struct afs_server_list *afs_alloc_server_list(struct afs_volume *volume, + struct key *key, +- struct afs_vldb_entry *vldb, +- u8 type_mask) ++ struct afs_vldb_entry *vldb) + { + struct afs_server_list *slist; + struct afs_server *server; ++ unsigned int type_mask = 1 << volume->type; + int ret = -ENOMEM, nr_servers = 0, i, j; + + for (i = 0; i < vldb->nr_servers; i++) +@@ -44,15 +44,12 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell, + refcount_set(&slist->usage, 1); + rwlock_init(&slist->lock); + +- for (i = 0; i < AFS_MAXTYPES; i++) +- slist->vids[i] = vldb->vid[i]; +- + /* Make sure a records exists for each server in the list. */ + for (i = 0; i < vldb->nr_servers; i++) { + if (!(vldb->fs_mask[i] & type_mask)) + continue; + +- server = afs_lookup_server(cell, key, &vldb->fs_server[i], ++ server = afs_lookup_server(volume->cell, key, &vldb->fs_server[i], + vldb->addr_version[i]); + if (IS_ERR(server)) { + ret = PTR_ERR(server); +@@ -70,7 +67,7 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell, + break; + if (j < slist->nr_servers) { + if (slist->servers[j].server == server) { +- afs_put_server(cell->net, server, ++ afs_put_server(volume->cell->net, server, + afs_server_trace_put_slist_isort); + continue; + } +@@ -81,6 +78,7 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell, + } + + slist->servers[j].server = server; ++ slist->servers[j].volume = volume; + slist->nr_servers++; + } + +@@ -92,7 +90,7 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell, + return slist; + + error_2: +- afs_put_serverlist(cell->net, slist); ++ afs_put_serverlist(volume->cell->net, slist); + error: + return ERR_PTR(ret); + } +@@ -127,3 +125,99 @@ bool afs_annotate_server_list(struct afs_server_list *new, + + return true; + } ++ ++/* ++ * Attach a volume to the servers it is going to use. ++ */ ++void afs_attach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *slist) ++{ ++ struct afs_server_entry *se, *pe; ++ struct afs_server *server; ++ struct list_head *p; ++ unsigned int i; ++ ++ spin_lock(&volume->cell->vs_lock); ++ ++ for (i = 0; i < slist->nr_servers; i++) { ++ se = &slist->servers[i]; ++ server = se->server; ++ ++ list_for_each(p, &server->volumes) { ++ pe = list_entry(p, struct afs_server_entry, slink); ++ if (volume->vid <= pe->volume->vid) ++ break; ++ } ++ list_add_tail_rcu(&se->slink, p); ++ } ++ ++ slist->attached = true; ++ spin_unlock(&volume->cell->vs_lock); ++} ++ ++/* ++ * Reattach a volume to the servers it is going to use when server list is ++ * replaced. We try to switch the attachment points to avoid rewalking the ++ * lists. ++ */ ++void afs_reattach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *new, ++ struct afs_server_list *old) ++{ ++ unsigned int n = 0, o = 0; ++ ++ spin_lock(&volume->cell->vs_lock); ++ ++ while (n < new->nr_servers || o < old->nr_servers) { ++ struct afs_server_entry *pn = n < new->nr_servers ? &new->servers[n] : NULL; ++ struct afs_server_entry *po = o < old->nr_servers ? &old->servers[o] : NULL; ++ struct afs_server_entry *s; ++ struct list_head *p; ++ int diff; ++ ++ if (pn && po && pn->server == po->server) { ++ list_replace_rcu(&po->slink, &pn->slink); ++ n++; ++ o++; ++ continue; ++ } ++ ++ if (pn && po) ++ diff = memcmp(&pn->server->uuid, &po->server->uuid, ++ sizeof(pn->server->uuid)); ++ else ++ diff = pn ? -1 : 1; ++ ++ if (diff < 0) { ++ list_for_each(p, &pn->server->volumes) { ++ s = list_entry(p, struct afs_server_entry, slink); ++ if (volume->vid <= s->volume->vid) ++ break; ++ } ++ list_add_tail_rcu(&pn->slink, p); ++ n++; ++ } else { ++ list_del_rcu(&po->slink); ++ o++; ++ } ++ } ++ ++ spin_unlock(&volume->cell->vs_lock); ++} ++ ++/* ++ * Detach a volume from the servers it has been using. ++ */ ++void afs_detach_volume_from_servers(struct afs_volume *volume, struct afs_server_list *slist) ++{ ++ unsigned int i; ++ ++ if (!slist->attached) ++ return; ++ ++ spin_lock(&volume->cell->vs_lock); ++ ++ for (i = 0; i < slist->nr_servers; i++) ++ list_del_rcu(&slist->servers[i].slink); ++ ++ slist->attached = false; ++ spin_unlock(&volume->cell->vs_lock); ++} +diff --git a/fs/afs/vl_alias.c b/fs/afs/vl_alias.c +index 83cf1bfbe343a..b2cc10df95308 100644 +--- a/fs/afs/vl_alias.c ++++ b/fs/afs/vl_alias.c +@@ -126,7 +126,7 @@ static int afs_compare_volume_slists(const struct afs_volume *vol_a, + lb = rcu_dereference(vol_b->servers); + + for (i = 0; i < AFS_MAXTYPES; i++) +- if (la->vids[i] != lb->vids[i]) ++ if (vol_a->vids[i] != vol_b->vids[i]) + return 0; + + while (a < la->nr_servers && b < lb->nr_servers) { +diff --git a/fs/afs/volume.c b/fs/afs/volume.c +index c028598a903c9..0f64b97581272 100644 +--- a/fs/afs/volume.c ++++ b/fs/afs/volume.c +@@ -72,11 +72,11 @@ static void afs_remove_volume_from_cell(struct afs_volume *volume) + */ + static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params, + struct afs_vldb_entry *vldb, +- unsigned long type_mask) ++ struct afs_server_list **_slist) + { + struct afs_server_list *slist; + struct afs_volume *volume; +- int ret = -ENOMEM; ++ int ret = -ENOMEM, i; + + volume = kzalloc(sizeof(struct afs_volume), GFP_KERNEL); + if (!volume) +@@ -95,13 +95,16 @@ static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params, + rwlock_init(&volume->cb_v_break_lock); + memcpy(volume->name, vldb->name, vldb->name_len + 1); + +- slist = afs_alloc_server_list(params->cell, params->key, vldb, type_mask); ++ for (i = 0; i < AFS_MAXTYPES; i++) ++ volume->vids[i] = vldb->vid[i]; ++ ++ slist = afs_alloc_server_list(volume, params->key, vldb); + if (IS_ERR(slist)) { + ret = PTR_ERR(slist); + goto error_1; + } + +- refcount_set(&slist->usage, 1); ++ *_slist = slist; + rcu_assign_pointer(volume->servers, slist); + trace_afs_volume(volume->vid, 1, afs_volume_trace_alloc); + return volume; +@@ -117,17 +120,19 @@ static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params, + * Look up or allocate a volume record. + */ + static struct afs_volume *afs_lookup_volume(struct afs_fs_context *params, +- struct afs_vldb_entry *vldb, +- unsigned long type_mask) ++ struct afs_vldb_entry *vldb) + { ++ struct afs_server_list *slist; + struct afs_volume *candidate, *volume; + +- candidate = afs_alloc_volume(params, vldb, type_mask); ++ candidate = afs_alloc_volume(params, vldb, &slist); + if (IS_ERR(candidate)) + return candidate; + + volume = afs_insert_volume_into_cell(params->cell, candidate); +- if (volume != candidate) ++ if (volume == candidate) ++ afs_attach_volume_to_servers(volume, slist); ++ else + afs_put_volume(params->net, candidate, afs_volume_trace_put_cell_dup); + return volume; + } +@@ -208,8 +213,7 @@ struct afs_volume *afs_create_volume(struct afs_fs_context *params) + goto error; + } + +- type_mask = 1UL << params->type; +- volume = afs_lookup_volume(params, vldb, type_mask); ++ volume = afs_lookup_volume(params, vldb); + + error: + kfree(vldb); +@@ -221,14 +225,17 @@ struct afs_volume *afs_create_volume(struct afs_fs_context *params) + */ + static void afs_destroy_volume(struct afs_net *net, struct afs_volume *volume) + { ++ struct afs_server_list *slist = rcu_access_pointer(volume->servers); ++ + _enter("%p", volume); + + #ifdef CONFIG_AFS_FSCACHE + ASSERTCMP(volume->cache, ==, NULL); + #endif + ++ afs_detach_volume_from_servers(volume, slist); + afs_remove_volume_from_cell(volume); +- afs_put_serverlist(net, rcu_access_pointer(volume->servers)); ++ afs_put_serverlist(net, slist); + afs_put_cell(volume->cell, afs_cell_trace_put_vol); + trace_afs_volume(volume->vid, refcount_read(&volume->ref), + afs_volume_trace_free); +@@ -362,8 +369,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key) + } + + /* See if the volume's server list got updated. */ +- new = afs_alloc_server_list(volume->cell, key, +- vldb, (1 << volume->type)); ++ new = afs_alloc_server_list(volume, key, vldb); + if (IS_ERR(new)) { + ret = PTR_ERR(new); + goto error_vldb; +@@ -384,9 +390,11 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key) + + volume->update_at = ktime_get_real_seconds() + afs_volume_record_life; + write_unlock(&volume->servers_lock); +- ret = 0; + ++ if (discard == old) ++ afs_reattach_volume_to_servers(volume, new, old); + afs_put_serverlist(volume->cell->net, discard); ++ ret = 0; + error_vldb: + kfree(vldb); + error: +-- +2.39.5 + diff --git a/queue-6.6/alsa-hda-realtek-add-quirks-for-asus-rog-2023-models.patch b/queue-6.6/alsa-hda-realtek-add-quirks-for-asus-rog-2023-models.patch new file mode 100644 index 0000000000..af6595f77d --- /dev/null +++ b/queue-6.6/alsa-hda-realtek-add-quirks-for-asus-rog-2023-models.patch @@ -0,0 +1,85 @@ +From 807e707f6e5746d5de17dc033d4ce144ab2d05a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Dec 2023 15:12:17 +0000 +Subject: ALSA: hda/realtek: Add quirks for ASUS ROG 2023 models + +From: Stefan Binding + +[ Upstream commit a40ce9f4bdbebfbf55fdd83a5284fbaaf222f0b9 ] + +These models use 2xCS35L41amps with HDA using SPI and I2C. +All models use Internal Boost. +Some models also use Realtek Speakers in conjunction with +CS35L41. +All models require DSD support to be added inside +cs35l41_hda_property.c + +Signed-off-by: Stefan Binding +Link: https://lore.kernel.org/r/20231218151221.388745-4-sbinding@opensource.cirrus.com +Signed-off-by: Takashi Iwai +Stable-dep-of: 9e7c6779e353 ("ALSA: hda/realtek: Fix wrong mic setup for ASUS VivoBook 15") +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 30 ++++++++++++++++++------------ + 1 file changed, 18 insertions(+), 12 deletions(-) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 75162e5f712b4..3310871ed9cc3 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10084,23 +10084,26 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x1313, "Asus K42JZ", ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK), +- SND_PCI_QUIRK(0x1043, 0x1433, "ASUS GX650P", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC), +- SND_PCI_QUIRK(0x1043, 0x1463, "Asus GA402X", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC), +- SND_PCI_QUIRK(0x1043, 0x1473, "ASUS GU604V", ALC285_FIXUP_ASUS_HEADSET_MIC), +- SND_PCI_QUIRK(0x1043, 0x1483, "ASUS GU603V", ALC285_FIXUP_ASUS_HEADSET_MIC), +- SND_PCI_QUIRK(0x1043, 0x1493, "ASUS GV601V", ALC285_FIXUP_ASUS_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1433, "ASUS GX650PY/PZ/PV/PU/PYV/PZV/PIV/PVV", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1463, "Asus GA402X/GA402N", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1473, "ASUS GU604VI/VC/VE/VG/VJ/VQ/VU/VV/VY/VZ", ALC285_FIXUP_ASUS_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1483, "ASUS GU603VQ/VU/VV/VJ/VI", ALC285_FIXUP_ASUS_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1493, "ASUS GV601VV/VU/VJ/VQ/VI", ALC285_FIXUP_ASUS_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G614JY/JZ/JG", ALC245_FIXUP_CS35L41_SPI_2), ++ SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS G513PI/PU/PV", ALC287_FIXUP_CS35L41_I2C_2), ++ SND_PCI_QUIRK(0x1043, 0x1503, "ASUS G733PY/PZ/PZV/PYV", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), +- SND_PCI_QUIRK(0x1043, 0x1533, "ASUS GV302XA", ALC287_FIXUP_CS35L41_I2C_2), +- SND_PCI_QUIRK(0x1043, 0x1573, "ASUS GZ301V", ALC285_FIXUP_ASUS_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1533, "ASUS GV302XA/XJ/XQ/XU/XV/XI", ALC287_FIXUP_CS35L41_I2C_2), ++ SND_PCI_QUIRK(0x1043, 0x1573, "ASUS GZ301VV/VQ/VU/VJ/VA/VC/VE/VVC/VQC/VUC/VJC/VEC/VCC", ALC285_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK), +- SND_PCI_QUIRK(0x1043, 0x1663, "ASUS GU603ZV", ALC285_FIXUP_ASUS_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1663, "ASUS GU603ZI/ZJ/ZQ/ZU/ZV", ALC285_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2), + SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS), + SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK), +- SND_PCI_QUIRK(0x1043, 0x17f3, "ROG Ally RC71L_RC71L", ALC294_FIXUP_ASUS_ALLY), ++ SND_PCI_QUIRK(0x1043, 0x17f3, "ROG Ally NR2301L/X", ALC294_FIXUP_ASUS_ALLY), + SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS), + SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC294_FIXUP_CS35L41_I2C_2), +@@ -10125,10 +10128,13 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2), + SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS), +- SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JI", ALC285_FIXUP_ASUS_HEADSET_MIC), +- SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS), ++ SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS), + SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC), +- SND_PCI_QUIRK(0x1043, 0x1d1f, "ASUS ROG Strix G17 2023 (G713PV)", ALC287_FIXUP_CS35L41_I2C_2), ++ SND_PCI_QUIRK(0x1043, 0x1ccf, "ASUS G814JU/JV/JI", ALC245_FIXUP_CS35L41_SPI_2), ++ SND_PCI_QUIRK(0x1043, 0x1cdf, "ASUS G814JY/JZ/JG", ALC245_FIXUP_CS35L41_SPI_2), ++ SND_PCI_QUIRK(0x1043, 0x1cef, "ASUS G834JY/JZ/JI/JG", ALC285_FIXUP_ASUS_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1d1f, "ASUS G713PI/PU/PV/PVN", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), + SND_PCI_QUIRK(0x1043, 0x1da2, "ASUS UP6502ZA/ZD", ALC245_FIXUP_CS35L41_SPI_2), +-- +2.39.5 + diff --git a/queue-6.6/alsa-hda-realtek-fix-wrong-mic-setup-for-asus-vivobo.patch b/queue-6.6/alsa-hda-realtek-fix-wrong-mic-setup-for-asus-vivobo.patch new file mode 100644 index 0000000000..48e650fa7b --- /dev/null +++ b/queue-6.6/alsa-hda-realtek-fix-wrong-mic-setup-for-asus-vivobo.patch @@ -0,0 +1,45 @@ +From 0eb8c0e646a7a793d915e66ad3a3b4f760fadb18 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 16:45:32 +0100 +Subject: ALSA: hda/realtek: Fix wrong mic setup for ASUS VivoBook 15 + +From: Takashi Iwai + +[ Upstream commit 9e7c6779e3530bbdd465214afcd13f19c33e51a2 ] + +ASUS VivoBook 15 with SSID 1043:1460 took an incorrect quirk via the +pin pattern matching for ASUS (ALC256_FIXUP_ASUS_MIC), resulting in +the two built-in mic pins (0x13 and 0x1b). This had worked without +problems casually in the past because the right pin (0x1b) was picked +up as the primary device. But since we fixed the pin enumeration for +other bugs, the bogus one (0x13) is picked up as the primary device, +hence the bug surfaced now. + +For addressing the regression, this patch explicitly specifies the +quirk entry with ALC256_FIXUP_ASUS_MIC_NO_PRESENCE, which sets up only +the headset mic pin. + +Fixes: 3b4309546b48 ("ALSA: hda: Fix headset detection failure due to unstable sort") +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219807 +Link: https://patch.msgid.link/20250225154540.13543-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 3310871ed9cc3..cb1f559303631 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10085,6 +10085,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK), + SND_PCI_QUIRK(0x1043, 0x1433, "ASUS GX650PY/PZ/PV/PU/PYV/PZV/PIV/PVV", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1043, 0x1460, "Asus VivoBook 15", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x1463, "Asus GA402X/GA402N", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x1473, "ASUS GU604VI/VC/VE/VG/VJ/VQ/VU/VV/VY/VZ", ALC285_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x1483, "ASUS GU603VQ/VU/VV/VJ/VI", ALC285_FIXUP_ASUS_HEADSET_MIC), +-- +2.39.5 + diff --git a/queue-6.6/alsa-usb-audio-avoid-dropping-midi-events-at-closing.patch b/queue-6.6/alsa-usb-audio-avoid-dropping-midi-events-at-closing.patch new file mode 100644 index 0000000000..5d72a10ace --- /dev/null +++ b/queue-6.6/alsa-usb-audio-avoid-dropping-midi-events-at-closing.patch @@ -0,0 +1,47 @@ +From 41a306cb8f3a99d45a7134f76624001f0853b839 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 12:40:24 +0100 +Subject: ALSA: usb-audio: Avoid dropping MIDI events at closing multiple ports + +From: Takashi Iwai + +[ Upstream commit a3bdd8f5c2217e1cb35db02c2eed36ea20fb50f5 ] + +We fixed the UAF issue in USB MIDI code by canceling the pending work +at closing each MIDI output device in the commit below. However, this +assumed that it's the only one that is tied with the endpoint, and it +resulted in unexpected data truncations when multiple devices are +assigned to a single endpoint and opened simultaneously. + +For addressing the unexpected MIDI message drops, simply replace +cancel_work_sync() with flush_work(). The drain callback should have +been already invoked before the close callback, hence the port->active +flag must be already cleared. So this just assures that the pending +work is finished before freeing the resources. + +Fixes: 0125de38122f ("ALSA: usb-audio: Cancel pending work at closing a MIDI substream") +Reported-and-tested-by: John Keeping +Closes: https://lore.kernel.org/20250217111647.3368132-1-jkeeping@inmusicbrands.com +Link: https://patch.msgid.link/20250218114024.23125-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/midi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/usb/midi.c b/sound/usb/midi.c +index 6b0993258e039..6d861046b582b 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -1145,7 +1145,7 @@ static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) + { + struct usbmidi_out_port *port = substream->runtime->private_data; + +- cancel_work_sync(&port->ep->work); ++ flush_work(&port->ep->work); + return substream_open(substream, 0, 0); + } + +-- +2.39.5 + diff --git a/queue-6.6/asoc-es8328-fix-route-from-dac-to-output.patch b/queue-6.6/asoc-es8328-fix-route-from-dac-to-output.patch new file mode 100644 index 0000000000..1a2239d87d --- /dev/null +++ b/queue-6.6/asoc-es8328-fix-route-from-dac-to-output.patch @@ -0,0 +1,110 @@ +From 7d9bcc04a265005a671afd1d6099faa2f6d7155c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Feb 2025 20:39:57 +0100 +Subject: ASoC: es8328: fix route from DAC to output + +From: Nicolas Frattaroli + +[ Upstream commit 5b0c02f9b8acf2a791e531bbc09acae2d51f4f9b ] + +The ES8328 codec driver, which is also used for the ES8388 chip that +appears to have an identical register map, claims that the output can +either take the route from DAC->Mixer->Output or through DAC->Output +directly. To the best of what I could find, this is not true, and +creates problems. + +Without DACCONTROL17 bit index 7 set for the left channel, as well as +DACCONTROL20 bit index 7 set for the right channel, I cannot get any +analog audio out on Left Out 2 and Right Out 2 respectively, despite the +DAPM routes claiming that this should be possible. Furthermore, the same +is the case for Left Out 1 and Right Out 1, showing that those two don't +have a direct route from DAC to output bypassing the mixer either. + +Those control bits toggle whether the DACs are fed (stale bread?) into +their respective mixers. If one "unmutes" the mixer controls in +alsamixer, then sure, the audio output works, but if it doesn't work +without the mixer being fed the DAC input then evidently it's not a +direct output from the DAC. + +ES8328/ES8388 are seemingly not alone in this. ES8323, which uses a +separate driver for what appears to be a very similar register map, +simply flips those two bits on in its probe function, and then pretends +there is no power management whatsoever for the individual controls. +Fair enough. + +My theory as to why nobody has noticed this up to this point is that +everyone just assumes it's their fault when they had to unmute an +additional control in ALSA. + +Fix this in the es8328 driver by removing the erroneous direct route, +then get rid of the playback switch controls and have those bits tied to +the mixer's widget instead, which until now had no register to play +with. + +Fixes: 567e4f98922c ("ASoC: add es8328 codec driver") +Signed-off-by: Nicolas Frattaroli +Link: https://patch.msgid.link/20250222-es8328-route-bludgeoning-v1-1-99bfb7fb22d9@collabora.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/es8328.c | 15 ++++----------- + 1 file changed, 4 insertions(+), 11 deletions(-) + +diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c +index 0bd9ba5a11b4e..43792e175d75f 100644 +--- a/sound/soc/codecs/es8328.c ++++ b/sound/soc/codecs/es8328.c +@@ -234,7 +234,6 @@ static const struct snd_kcontrol_new es8328_right_line_controls = + + /* Left Mixer */ + static const struct snd_kcontrol_new es8328_left_mixer_controls[] = { +- SOC_DAPM_SINGLE("Playback Switch", ES8328_DACCONTROL17, 7, 1, 0), + SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL17, 6, 1, 0), + SOC_DAPM_SINGLE("Right Playback Switch", ES8328_DACCONTROL18, 7, 1, 0), + SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL18, 6, 1, 0), +@@ -244,7 +243,6 @@ static const struct snd_kcontrol_new es8328_left_mixer_controls[] = { + static const struct snd_kcontrol_new es8328_right_mixer_controls[] = { + SOC_DAPM_SINGLE("Left Playback Switch", ES8328_DACCONTROL19, 7, 1, 0), + SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL19, 6, 1, 0), +- SOC_DAPM_SINGLE("Playback Switch", ES8328_DACCONTROL20, 7, 1, 0), + SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL20, 6, 1, 0), + }; + +@@ -337,10 +335,10 @@ static const struct snd_soc_dapm_widget es8328_dapm_widgets[] = { + SND_SOC_DAPM_DAC("Left DAC", "Left Playback", ES8328_DACPOWER, + ES8328_DACPOWER_LDAC_OFF, 1), + +- SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, ++ SND_SOC_DAPM_MIXER("Left Mixer", ES8328_DACCONTROL17, 7, 0, + &es8328_left_mixer_controls[0], + ARRAY_SIZE(es8328_left_mixer_controls)), +- SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0, ++ SND_SOC_DAPM_MIXER("Right Mixer", ES8328_DACCONTROL20, 7, 0, + &es8328_right_mixer_controls[0], + ARRAY_SIZE(es8328_right_mixer_controls)), + +@@ -419,19 +417,14 @@ static const struct snd_soc_dapm_route es8328_dapm_routes[] = { + { "Right Line Mux", "PGA", "Right PGA Mux" }, + { "Right Line Mux", "Differential", "Differential Mux" }, + +- { "Left Out 1", NULL, "Left DAC" }, +- { "Right Out 1", NULL, "Right DAC" }, +- { "Left Out 2", NULL, "Left DAC" }, +- { "Right Out 2", NULL, "Right DAC" }, +- +- { "Left Mixer", "Playback Switch", "Left DAC" }, ++ { "Left Mixer", NULL, "Left DAC" }, + { "Left Mixer", "Left Bypass Switch", "Left Line Mux" }, + { "Left Mixer", "Right Playback Switch", "Right DAC" }, + { "Left Mixer", "Right Bypass Switch", "Right Line Mux" }, + + { "Right Mixer", "Left Playback Switch", "Left DAC" }, + { "Right Mixer", "Left Bypass Switch", "Left Line Mux" }, +- { "Right Mixer", "Playback Switch", "Right DAC" }, ++ { "Right Mixer", NULL, "Right DAC" }, + { "Right Mixer", "Right Bypass Switch", "Right Line Mux" }, + + { "DAC DIG", NULL, "DAC STM" }, +-- +2.39.5 + diff --git a/queue-6.6/bluetooth-l2cap-fix-l2cap_ecred_conn_rsp-response.patch b/queue-6.6/bluetooth-l2cap-fix-l2cap_ecred_conn_rsp-response.patch new file mode 100644 index 0000000000..c55b5f2cf2 --- /dev/null +++ b/queue-6.6/bluetooth-l2cap-fix-l2cap_ecred_conn_rsp-response.patch @@ -0,0 +1,99 @@ +From e432d8287631bbf435682cf0ffe1044ba1005e6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Feb 2025 10:30:25 -0500 +Subject: Bluetooth: L2CAP: Fix L2CAP_ECRED_CONN_RSP response + +From: Luiz Augusto von Dentz + +[ Upstream commit b25120e1d5f2ebb3db00af557709041f47f7f3d0 ] + +L2CAP_ECRED_CONN_RSP needs to respond DCID in the same order received as +SCID but the order is reversed due to use of list_add which actually +prepend channels to the list so the response is reversed: + +> ACL Data RX: Handle 16 flags 0x02 dlen 26 + LE L2CAP: Enhanced Credit Connection Request (0x17) ident 2 len 18 + PSM: 39 (0x0027) + MTU: 256 + MPS: 251 + Credits: 65535 + Source CID: 116 + Source CID: 117 + Source CID: 118 + Source CID: 119 + Source CID: 120 +< ACL Data TX: Handle 16 flags 0x00 dlen 26 + LE L2CAP: Enhanced Credit Connection Response (0x18) ident 2 len 18 + MTU: 517 + MPS: 247 + Credits: 3 + Result: Connection successful (0x0000) + Destination CID: 68 + Destination CID: 67 + Destination CID: 66 + Destination CID: 65 + Destination CID: 64 + +Also make sure the response don't include channels that are not on +BT_CONNECT2 since the chan->ident can be set to the same value as in the +following trace: + +< ACL Data TX: Handle 16 flags 0x00 dlen 12 + LE L2CAP: LE Flow Control Credit (0x16) ident 6 len 4 + Source CID: 64 + Credits: 1 +... +> ACL Data RX: Handle 16 flags 0x02 dlen 18 + LE L2CAP: Enhanced Credit Connection Request (0x17) ident 6 len 10 + PSM: 39 (0x0027) + MTU: 517 + MPS: 251 + Credits: 255 + Source CID: 70 +< ACL Data TX: Handle 16 flags 0x00 dlen 20 + LE L2CAP: Enhanced Credit Connection Response (0x18) ident 6 len 12 + MTU: 517 + MPS: 247 + Credits: 3 + Result: Connection successful (0x0000) + Destination CID: 64 + Destination CID: 68 + +Closes: https://github.com/bluez/bluez/issues/1094 +Fixes: 9aa9d9473f15 ("Bluetooth: L2CAP: Fix responding with wrong PDU type") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index acb148759bd04..304ebb31cebba 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -636,7 +636,8 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) + test_bit(FLAG_HOLD_HCI_CONN, &chan->flags)) + hci_conn_hold(conn->hcon); + +- list_add(&chan->list, &conn->chan_l); ++ /* Append to the list since the order matters for ECRED */ ++ list_add_tail(&chan->list, &conn->chan_l); + } + + void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) +@@ -3774,7 +3775,11 @@ static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data) + { + struct l2cap_ecred_rsp_data *rsp = data; + +- if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags)) ++ /* Check if channel for outgoing connection or if it wasn't deferred ++ * since in those cases it must be skipped. ++ */ ++ if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags) || ++ !test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags)) + return; + + /* Reset ident so only one response is sent */ +-- +2.39.5 + diff --git a/queue-6.6/firmware-cs_dsp-remove-async-regmap-writes.patch b/queue-6.6/firmware-cs_dsp-remove-async-regmap-writes.patch new file mode 100644 index 0000000000..1c6db36c06 --- /dev/null +++ b/queue-6.6/firmware-cs_dsp-remove-async-regmap-writes.patch @@ -0,0 +1,115 @@ +From 1af766cb83ec94cdd5550239bc5e1db39194a181 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 13:18:42 +0000 +Subject: firmware: cs_dsp: Remove async regmap writes + +From: Richard Fitzgerald + +[ Upstream commit fe08b7d5085a9774abc30c26d5aebc5b9cdd6091 ] + +Change calls to async regmap write functions to use the normal +blocking writes so that the cs35l56 driver can use spi_bus_lock() to +gain exclusive access to the SPI bus. + +As this is part of a fix, it makes only the minimal change to swap the +functions to the blocking equivalents. There's no need to risk +reworking the buffer allocation logic that is now partially redundant. + +The async writes are a 12-year-old workaround for inefficiency of +synchronous writes in the SPI subsystem. The SPI subsystem has since +been changed to avoid the overheads, so this workaround should not be +necessary. + +The cs35l56 driver needs to use spi_bus_lock() prevent bus activity +while it is soft-resetting the cs35l56. But spi_bus_lock() is +incompatible with spi_async() calls, which will fail with -EBUSY. + +Fixes: 8a731fd37f8b ("ASoC: cs35l56: Move utility functions to shared file") +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20250225131843.113752-2-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/firmware/cirrus/cs_dsp.c | 24 ++++++------------------ + 1 file changed, 6 insertions(+), 18 deletions(-) + +diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c +index e62ffffe5fb8d..4ce5681be18f0 100644 +--- a/drivers/firmware/cirrus/cs_dsp.c ++++ b/drivers/firmware/cirrus/cs_dsp.c +@@ -1562,8 +1562,8 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, + goto out_fw; + } + +- ret = regmap_raw_write_async(regmap, reg, buf->buf, +- le32_to_cpu(region->len)); ++ ret = regmap_raw_write(regmap, reg, buf->buf, ++ le32_to_cpu(region->len)); + if (ret != 0) { + cs_dsp_err(dsp, + "%s.%d: Failed to write %d bytes at %d in %s: %d\n", +@@ -1578,12 +1578,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, + regions++; + } + +- ret = regmap_async_complete(regmap); +- if (ret != 0) { +- cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret); +- goto out_fw; +- } +- + if (pos > firmware->size) + cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", + file, regions, pos - firmware->size); +@@ -1591,7 +1585,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, + cs_dsp_debugfs_save_wmfwname(dsp, file); + + out_fw: +- regmap_async_complete(regmap); + cs_dsp_buf_free(&buf_list); + kfree(text); + +@@ -2287,8 +2280,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware + cs_dsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n", + file, blocks, le32_to_cpu(blk->len), + reg); +- ret = regmap_raw_write_async(regmap, reg, buf->buf, +- le32_to_cpu(blk->len)); ++ ret = regmap_raw_write(regmap, reg, buf->buf, ++ le32_to_cpu(blk->len)); + if (ret != 0) { + cs_dsp_err(dsp, + "%s.%d: Failed to write to %x in %s: %d\n", +@@ -2300,10 +2293,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware + blocks++; + } + +- ret = regmap_async_complete(regmap); +- if (ret != 0) +- cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret); +- + if (pos > firmware->size) + cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", + file, blocks, pos - firmware->size); +@@ -2311,7 +2300,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware + cs_dsp_debugfs_save_binname(dsp, file); + + out_fw: +- regmap_async_complete(regmap); + cs_dsp_buf_free(&buf_list); + kfree(text); + +@@ -2523,8 +2511,8 @@ static int cs_dsp_adsp2_enable_core(struct cs_dsp *dsp) + { + int ret; + +- ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL, +- ADSP2_SYS_ENA, ADSP2_SYS_ENA); ++ ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, ++ ADSP2_SYS_ENA, ADSP2_SYS_ENA); + if (ret != 0) + return ret; + +-- +2.39.5 + diff --git a/queue-6.6/ice-add-e830-device-ids-mac-type-and-registers.patch b/queue-6.6/ice-add-e830-device-ids-mac-type-and-registers.patch new file mode 100644 index 0000000000..0fb6da8338 --- /dev/null +++ b/queue-6.6/ice-add-e830-device-ids-mac-type-and-registers.patch @@ -0,0 +1,476 @@ +From 501cc7612ede11cc680f1256ede3d8af9c1327f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Oct 2023 14:41:52 -0700 +Subject: ice: Add E830 device IDs, MAC type and registers + +From: Paul Greenwalt + +[ Upstream commit ba1124f58afd37d9ff155d4ab7c9f209346aaed9 ] + +E830 is the 200G NIC family which uses the ice driver. + +Add specific E830 registers. Embed macros to use proper register based on +(hw)->mac_type & name those macros to [ORIGINAL]_BY_MAC(hw). Registers +only available on one of the macs will need to be explicitly referred to +as E800_NAME instead of just NAME. PTP is not yet supported. + +Co-developed-by: Milena Olech +Signed-off-by: Milena Olech +Co-developed-by: Dan Nowlin +Signed-off-by: Dan Nowlin +Co-developed-by: Scott Taylor +Signed-off-by: Scott Taylor +Co-developed-by: Pawel Chmielewski +Signed-off-by: Pawel Chmielewski +Reviewed-by: Simon Horman +Signed-off-by: Paul Greenwalt +Tested-by: Tony Brelinski +Signed-off-by: Jacob Keller +Link: https://lore.kernel.org/r/20231025214157.1222758-2-jacob.e.keller@intel.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 79990cf5e7ad ("ice: Fix deinitializing VF in error path") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_common.c | 71 ++++++++++++------- + drivers/net/ethernet/intel/ice/ice_devids.h | 10 ++- + .../net/ethernet/intel/ice/ice_ethtool_fdir.c | 24 ++++--- + .../net/ethernet/intel/ice/ice_hw_autogen.h | 52 ++++++++++---- + drivers/net/ethernet/intel/ice/ice_main.c | 13 ++-- + drivers/net/ethernet/intel/ice/ice_type.h | 3 +- + .../ethernet/intel/ice/ice_virtchnl_fdir.c | 29 +++++--- + 7 files changed, 141 insertions(+), 61 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index 80deca45ab599..983332cbace21 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -1,5 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0 +-/* Copyright (c) 2018, Intel Corporation. */ ++/* Copyright (c) 2018-2023, Intel Corporation. */ + + #include "ice_common.h" + #include "ice_sched.h" +@@ -153,6 +153,12 @@ static int ice_set_mac_type(struct ice_hw *hw) + case ICE_DEV_ID_E823L_SFP: + hw->mac_type = ICE_MAC_GENERIC; + break; ++ case ICE_DEV_ID_E830_BACKPLANE: ++ case ICE_DEV_ID_E830_QSFP56: ++ case ICE_DEV_ID_E830_SFP: ++ case ICE_DEV_ID_E830_SFP_DD: ++ hw->mac_type = ICE_MAC_E830; ++ break; + default: + hw->mac_type = ICE_MAC_UNKNOWN; + break; +@@ -684,8 +690,7 @@ static void + ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw, + struct ice_aqc_set_mac_cfg *cmd) + { +- u16 fc_thres_val, tx_timer_val; +- u32 val; ++ u32 val, fc_thres_m; + + /* We read back the transmit timer and FC threshold value of + * LFC. Thus, we will use index = +@@ -694,19 +699,32 @@ ice_fill_tx_timer_and_fc_thresh(struct ice_hw *hw, + * Also, because we are operating on transmit timer and FC + * threshold of LFC, we don't turn on any bit in tx_tmr_priority + */ +-#define IDX_OF_LFC PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX +- +- /* Retrieve the transmit timer */ +- val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(IDX_OF_LFC)); +- tx_timer_val = val & +- PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M; +- cmd->tx_tmr_value = cpu_to_le16(tx_timer_val); +- +- /* Retrieve the FC threshold */ +- val = rd32(hw, PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(IDX_OF_LFC)); +- fc_thres_val = val & PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M; +- +- cmd->fc_refresh_threshold = cpu_to_le16(fc_thres_val); ++#define E800_IDX_OF_LFC E800_PRTMAC_HSEC_CTL_TX_PS_QNT_MAX ++#define E800_REFRESH_TMR E800_PRTMAC_HSEC_CTL_TX_PS_RFSH_TMR ++ ++ if (hw->mac_type == ICE_MAC_E830) { ++ /* Retrieve the transmit timer */ ++ val = rd32(hw, E830_PRTMAC_CL01_PS_QNT); ++ cmd->tx_tmr_value = ++ le16_encode_bits(val, E830_PRTMAC_CL01_PS_QNT_CL0_M); ++ ++ /* Retrieve the fc threshold */ ++ val = rd32(hw, E830_PRTMAC_CL01_QNT_THR); ++ fc_thres_m = E830_PRTMAC_CL01_QNT_THR_CL0_M; ++ } else { ++ /* Retrieve the transmit timer */ ++ val = rd32(hw, ++ E800_PRTMAC_HSEC_CTL_TX_PS_QNT(E800_IDX_OF_LFC)); ++ cmd->tx_tmr_value = ++ le16_encode_bits(val, ++ E800_PRTMAC_HSEC_CTL_TX_PS_QNT_M); ++ ++ /* Retrieve the fc threshold */ ++ val = rd32(hw, ++ E800_REFRESH_TMR(E800_IDX_OF_LFC)); ++ fc_thres_m = E800_PRTMAC_HSEC_CTL_TX_PS_RFSH_TMR_M; ++ } ++ cmd->fc_refresh_threshold = le16_encode_bits(val, fc_thres_m); + } + + /** +@@ -2389,16 +2407,21 @@ ice_parse_1588_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p, + static void + ice_parse_fdir_func_caps(struct ice_hw *hw, struct ice_hw_func_caps *func_p) + { +- u32 reg_val, val; ++ u32 reg_val, gsize, bsize; + + reg_val = rd32(hw, GLQF_FD_SIZE); +- val = (reg_val & GLQF_FD_SIZE_FD_GSIZE_M) >> +- GLQF_FD_SIZE_FD_GSIZE_S; +- func_p->fd_fltr_guar = +- ice_get_num_per_func(hw, val); +- val = (reg_val & GLQF_FD_SIZE_FD_BSIZE_M) >> +- GLQF_FD_SIZE_FD_BSIZE_S; +- func_p->fd_fltr_best_effort = val; ++ switch (hw->mac_type) { ++ case ICE_MAC_E830: ++ gsize = FIELD_GET(E830_GLQF_FD_SIZE_FD_GSIZE_M, reg_val); ++ bsize = FIELD_GET(E830_GLQF_FD_SIZE_FD_BSIZE_M, reg_val); ++ break; ++ case ICE_MAC_E810: ++ default: ++ gsize = FIELD_GET(E800_GLQF_FD_SIZE_FD_GSIZE_M, reg_val); ++ bsize = FIELD_GET(E800_GLQF_FD_SIZE_FD_BSIZE_M, reg_val); ++ } ++ func_p->fd_fltr_guar = ice_get_num_per_func(hw, gsize); ++ func_p->fd_fltr_best_effort = bsize; + + ice_debug(hw, ICE_DBG_INIT, "func caps: fd_fltr_guar = %d\n", + func_p->fd_fltr_guar); +diff --git a/drivers/net/ethernet/intel/ice/ice_devids.h b/drivers/net/ethernet/intel/ice/ice_devids.h +index 6d560d1c74a4a..a2d384dbfc767 100644 +--- a/drivers/net/ethernet/intel/ice/ice_devids.h ++++ b/drivers/net/ethernet/intel/ice/ice_devids.h +@@ -1,5 +1,5 @@ + /* SPDX-License-Identifier: GPL-2.0 */ +-/* Copyright (c) 2018, Intel Corporation. */ ++/* Copyright (c) 2018-2023, Intel Corporation. */ + + #ifndef _ICE_DEVIDS_H_ + #define _ICE_DEVIDS_H_ +@@ -16,6 +16,14 @@ + #define ICE_DEV_ID_E823L_1GBE 0x124F + /* Intel(R) Ethernet Connection E823-L for QSFP */ + #define ICE_DEV_ID_E823L_QSFP 0x151D ++/* Intel(R) Ethernet Controller E830-C for backplane */ ++#define ICE_DEV_ID_E830_BACKPLANE 0x12D1 ++/* Intel(R) Ethernet Controller E830-C for QSFP */ ++#define ICE_DEV_ID_E830_QSFP56 0x12D2 ++/* Intel(R) Ethernet Controller E830-C for SFP */ ++#define ICE_DEV_ID_E830_SFP 0x12D3 ++/* Intel(R) Ethernet Controller E830-C for SFP-DD */ ++#define ICE_DEV_ID_E830_SFP_DD 0x12D4 + /* Intel(R) Ethernet Controller E810-C for backplane */ + #define ICE_DEV_ID_E810C_BACKPLANE 0x1591 + /* Intel(R) Ethernet Controller E810-C for QSFP */ +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c +index b6bbf2376ef5c..d43b642cbc01c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c +@@ -1,5 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0 +-/* Copyright (C) 2018-2020, Intel Corporation. */ ++/* Copyright (C) 2018-2023, Intel Corporation. */ + + /* flow director ethtool support for ice */ + +@@ -540,16 +540,24 @@ int ice_fdir_num_avail_fltr(struct ice_hw *hw, struct ice_vsi *vsi) + /* total guaranteed filters assigned to this VSI */ + num_guar = vsi->num_gfltr; + +- /* minus the guaranteed filters programed by this VSI */ +- num_guar -= (rd32(hw, VSIQF_FD_CNT(vsi_num)) & +- VSIQF_FD_CNT_FD_GCNT_M) >> VSIQF_FD_CNT_FD_GCNT_S; +- + /* total global best effort filters */ + num_be = hw->func_caps.fd_fltr_best_effort; + +- /* minus the global best effort filters programmed */ +- num_be -= (rd32(hw, GLQF_FD_CNT) & GLQF_FD_CNT_FD_BCNT_M) >> +- GLQF_FD_CNT_FD_BCNT_S; ++ /* Subtract the number of programmed filters from the global values */ ++ switch (hw->mac_type) { ++ case ICE_MAC_E830: ++ num_guar -= FIELD_GET(E830_VSIQF_FD_CNT_FD_GCNT_M, ++ rd32(hw, VSIQF_FD_CNT(vsi_num))); ++ num_be -= FIELD_GET(E830_GLQF_FD_CNT_FD_BCNT_M, ++ rd32(hw, GLQF_FD_CNT)); ++ break; ++ case ICE_MAC_E810: ++ default: ++ num_guar -= FIELD_GET(E800_VSIQF_FD_CNT_FD_GCNT_M, ++ rd32(hw, VSIQF_FD_CNT(vsi_num))); ++ num_be -= FIELD_GET(E800_GLQF_FD_CNT_FD_BCNT_M, ++ rd32(hw, GLQF_FD_CNT)); ++ } + + return num_guar + num_be; + } +diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +index 531cc2194741e..67519a985b327 100644 +--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h ++++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +@@ -1,5 +1,5 @@ + /* SPDX-License-Identifier: GPL-2.0 */ +-/* Copyright (c) 2018, Intel Corporation. */ ++/* Copyright (c) 2018-2023, Intel Corporation. */ + + /* Machine-generated file */ + +@@ -284,11 +284,11 @@ + #define VPLAN_TX_QBASE_VFNUMQ_M ICE_M(0xFF, 16) + #define VPLAN_TXQ_MAPENA(_VF) (0x00073800 + ((_VF) * 4)) + #define VPLAN_TXQ_MAPENA_TX_ENA_M BIT(0) +-#define PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(_i) (0x001E36E0 + ((_i) * 32)) +-#define PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX 8 +-#define PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_M ICE_M(0xFFFF, 0) +-#define PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(_i) (0x001E3800 + ((_i) * 32)) +-#define PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_M ICE_M(0xFFFF, 0) ++#define E800_PRTMAC_HSEC_CTL_TX_PS_QNT(_i) (0x001E36E0 + ((_i) * 32)) ++#define E800_PRTMAC_HSEC_CTL_TX_PS_QNT_MAX 8 ++#define E800_PRTMAC_HSEC_CTL_TX_PS_QNT_M GENMASK(15, 0) ++#define E800_PRTMAC_HSEC_CTL_TX_PS_RFSH_TMR(_i) (0x001E3800 + ((_i) * 32)) ++#define E800_PRTMAC_HSEC_CTL_TX_PS_RFSH_TMR_M GENMASK(15, 0) + #define GL_MDCK_TX_TDPU 0x00049348 + #define GL_MDCK_TX_TDPU_RCU_ANTISPOOF_ITR_DIS_M BIT(1) + #define GL_MDET_RX 0x00294C00 +@@ -311,7 +311,11 @@ + #define GL_MDET_TX_PQM_MAL_TYPE_S 26 + #define GL_MDET_TX_PQM_MAL_TYPE_M ICE_M(0x1F, 26) + #define GL_MDET_TX_PQM_VALID_M BIT(31) +-#define GL_MDET_TX_TCLAN 0x000FC068 ++#define GL_MDET_TX_TCLAN_BY_MAC(hw) \ ++ ((hw)->mac_type == ICE_MAC_E830 ? E830_GL_MDET_TX_TCLAN : \ ++ E800_GL_MDET_TX_TCLAN) ++#define E800_GL_MDET_TX_TCLAN 0x000FC068 ++#define E830_GL_MDET_TX_TCLAN 0x000FCCC0 + #define GL_MDET_TX_TCLAN_QNUM_S 0 + #define GL_MDET_TX_TCLAN_QNUM_M ICE_M(0x7FFF, 0) + #define GL_MDET_TX_TCLAN_VF_NUM_S 15 +@@ -325,7 +329,11 @@ + #define PF_MDET_RX_VALID_M BIT(0) + #define PF_MDET_TX_PQM 0x002D2C80 + #define PF_MDET_TX_PQM_VALID_M BIT(0) +-#define PF_MDET_TX_TCLAN 0x000FC000 ++#define PF_MDET_TX_TCLAN_BY_MAC(hw) \ ++ ((hw)->mac_type == ICE_MAC_E830 ? E830_PF_MDET_TX_TCLAN : \ ++ E800_PF_MDET_TX_TCLAN) ++#define E800_PF_MDET_TX_TCLAN 0x000FC000 ++#define E830_PF_MDET_TX_TCLAN 0x000FCC00 + #define PF_MDET_TX_TCLAN_VALID_M BIT(0) + #define VP_MDET_RX(_VF) (0x00294400 + ((_VF) * 4)) + #define VP_MDET_RX_VALID_M BIT(0) +@@ -335,6 +343,8 @@ + #define VP_MDET_TX_TCLAN_VALID_M BIT(0) + #define VP_MDET_TX_TDPU(_VF) (0x00040000 + ((_VF) * 4)) + #define VP_MDET_TX_TDPU_VALID_M BIT(0) ++#define E800_GL_MNG_FWSM_FW_MODES_M GENMASK(2, 0) ++#define E830_GL_MNG_FWSM_FW_MODES_M GENMASK(1, 0) + #define GL_MNG_FWSM 0x000B6134 + #define GL_MNG_FWSM_FW_LOADING_M BIT(30) + #define GLNVM_FLA 0x000B6108 +@@ -363,13 +373,18 @@ + #define GL_PWR_MODE_CTL_CAR_MAX_BW_S 30 + #define GL_PWR_MODE_CTL_CAR_MAX_BW_M ICE_M(0x3, 30) + #define GLQF_FD_CNT 0x00460018 ++#define E800_GLQF_FD_CNT_FD_GCNT_M GENMASK(14, 0) ++#define E830_GLQF_FD_CNT_FD_GCNT_M GENMASK(15, 0) + #define GLQF_FD_CNT_FD_BCNT_S 16 +-#define GLQF_FD_CNT_FD_BCNT_M ICE_M(0x7FFF, 16) ++#define E800_GLQF_FD_CNT_FD_BCNT_M GENMASK(30, 16) ++#define E830_GLQF_FD_CNT_FD_BCNT_M GENMASK(31, 16) + #define GLQF_FD_SIZE 0x00460010 + #define GLQF_FD_SIZE_FD_GSIZE_S 0 +-#define GLQF_FD_SIZE_FD_GSIZE_M ICE_M(0x7FFF, 0) ++#define E800_GLQF_FD_SIZE_FD_GSIZE_M GENMASK(14, 0) ++#define E830_GLQF_FD_SIZE_FD_GSIZE_M GENMASK(15, 0) + #define GLQF_FD_SIZE_FD_BSIZE_S 16 +-#define GLQF_FD_SIZE_FD_BSIZE_M ICE_M(0x7FFF, 16) ++#define E800_GLQF_FD_SIZE_FD_BSIZE_M GENMASK(30, 16) ++#define E830_GLQF_FD_SIZE_FD_BSIZE_M GENMASK(31, 16) + #define GLQF_FDINSET(_i, _j) (0x00412000 + ((_i) * 4 + (_j) * 512)) + #define GLQF_FDMASK(_i) (0x00410800 + ((_i) * 4)) + #define GLQF_FDMASK_MAX_INDEX 31 +@@ -388,6 +403,10 @@ + #define GLQF_HMASK_SEL(_i) (0x00410000 + ((_i) * 4)) + #define GLQF_HMASK_SEL_MAX_INDEX 127 + #define GLQF_HMASK_SEL_MASK_SEL_S 0 ++#define E800_PFQF_FD_CNT_FD_GCNT_M GENMASK(14, 0) ++#define E830_PFQF_FD_CNT_FD_GCNT_M GENMASK(15, 0) ++#define E800_PFQF_FD_CNT_FD_BCNT_M GENMASK(30, 16) ++#define E830_PFQF_FD_CNT_FD_BCNT_M GENMASK(31, 16) + #define PFQF_FD_ENA 0x0043A000 + #define PFQF_FD_ENA_FD_ENA_M BIT(0) + #define PFQF_FD_SIZE 0x00460100 +@@ -478,6 +497,7 @@ + #define GLTSYN_SYNC_DLAY 0x00088818 + #define GLTSYN_TGT_H_0(_i) (0x00088930 + ((_i) * 4)) + #define GLTSYN_TGT_L_0(_i) (0x00088928 + ((_i) * 4)) ++#define GLTSYN_TIME_0(_i) (0x000888C8 + ((_i) * 4)) + #define GLTSYN_TIME_H(_i) (0x000888D8 + ((_i) * 4)) + #define GLTSYN_TIME_L(_i) (0x000888D0 + ((_i) * 4)) + #define PFHH_SEM 0x000A4200 /* Reset Source: PFR */ +@@ -486,9 +506,11 @@ + #define PFTSYN_SEM_BUSY_M BIT(0) + #define VSIQF_FD_CNT(_VSI) (0x00464000 + ((_VSI) * 4)) + #define VSIQF_FD_CNT_FD_GCNT_S 0 +-#define VSIQF_FD_CNT_FD_GCNT_M ICE_M(0x3FFF, 0) ++#define E800_VSIQF_FD_CNT_FD_GCNT_M GENMASK(13, 0) ++#define E830_VSIQF_FD_CNT_FD_GCNT_M GENMASK(15, 0) + #define VSIQF_FD_CNT_FD_BCNT_S 16 +-#define VSIQF_FD_CNT_FD_BCNT_M ICE_M(0x3FFF, 16) ++#define E800_VSIQF_FD_CNT_FD_BCNT_M GENMASK(29, 16) ++#define E830_VSIQF_FD_CNT_FD_BCNT_M GENMASK(31, 16) + #define VSIQF_FD_SIZE(_VSI) (0x00462000 + ((_VSI) * 4)) + #define VSIQF_HKEY_MAX_INDEX 12 + #define PFPM_APM 0x000B8080 +@@ -500,6 +522,10 @@ + #define PFPM_WUS_MAG_M BIT(1) + #define PFPM_WUS_MNG_M BIT(3) + #define PFPM_WUS_FW_RST_WK_M BIT(31) ++#define E830_PRTMAC_CL01_PS_QNT 0x001E32A0 ++#define E830_PRTMAC_CL01_PS_QNT_CL0_M GENMASK(15, 0) ++#define E830_PRTMAC_CL01_QNT_THR 0x001E3320 ++#define E830_PRTMAC_CL01_QNT_THR_CL0_M GENMASK(15, 0) + #define VFINT_DYN_CTLN(_i) (0x00003800 + ((_i) * 4)) + #define VFINT_DYN_CTLN_CLEARPBA_M BIT(1) + +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 9f12c9a0fe296..ef5d43f2804e7 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -1,5 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0 +-/* Copyright (c) 2018, Intel Corporation. */ ++/* Copyright (c) 2018-2023, Intel Corporation. */ + + /* Intel(R) Ethernet Connection E800 Series Linux Driver */ + +@@ -1748,7 +1748,7 @@ static void ice_handle_mdd_event(struct ice_pf *pf) + wr32(hw, GL_MDET_TX_PQM, 0xffffffff); + } + +- reg = rd32(hw, GL_MDET_TX_TCLAN); ++ reg = rd32(hw, GL_MDET_TX_TCLAN_BY_MAC(hw)); + if (reg & GL_MDET_TX_TCLAN_VALID_M) { + u8 pf_num = (reg & GL_MDET_TX_TCLAN_PF_NUM_M) >> + GL_MDET_TX_TCLAN_PF_NUM_S; +@@ -1762,7 +1762,7 @@ static void ice_handle_mdd_event(struct ice_pf *pf) + if (netif_msg_tx_err(pf)) + dev_info(dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n", + event, queue, pf_num, vf_num); +- wr32(hw, GL_MDET_TX_TCLAN, 0xffffffff); ++ wr32(hw, GL_MDET_TX_TCLAN_BY_MAC(hw), U32_MAX); + } + + reg = rd32(hw, GL_MDET_RX); +@@ -1790,9 +1790,9 @@ static void ice_handle_mdd_event(struct ice_pf *pf) + dev_info(dev, "Malicious Driver Detection event TX_PQM detected on PF\n"); + } + +- reg = rd32(hw, PF_MDET_TX_TCLAN); ++ reg = rd32(hw, PF_MDET_TX_TCLAN_BY_MAC(hw)); + if (reg & PF_MDET_TX_TCLAN_VALID_M) { +- wr32(hw, PF_MDET_TX_TCLAN, 0xFFFF); ++ wr32(hw, PF_MDET_TX_TCLAN_BY_MAC(hw), 0xffff); + if (netif_msg_tx_err(pf)) + dev_info(dev, "Malicious Driver Detection event TX_TCLAN detected on PF\n"); + } +@@ -3873,7 +3873,8 @@ static void ice_set_pf_caps(struct ice_pf *pf) + } + + clear_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags); +- if (func_caps->common_cap.ieee_1588) ++ if (func_caps->common_cap.ieee_1588 && ++ !(pf->hw.mac_type == ICE_MAC_E830)) + set_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags); + + pf->max_pf_txqs = func_caps->common_cap.num_txq; +diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h +index 5e353b0cbe6f7..35ee5b29ea34e 100644 +--- a/drivers/net/ethernet/intel/ice/ice_type.h ++++ b/drivers/net/ethernet/intel/ice/ice_type.h +@@ -1,5 +1,5 @@ + /* SPDX-License-Identifier: GPL-2.0 */ +-/* Copyright (c) 2018, Intel Corporation. */ ++/* Copyright (c) 2018-2023, Intel Corporation. */ + + #ifndef _ICE_TYPE_H_ + #define _ICE_TYPE_H_ +@@ -129,6 +129,7 @@ enum ice_set_fc_aq_failures { + enum ice_mac_type { + ICE_MAC_UNKNOWN = 0, + ICE_MAC_E810, ++ ICE_MAC_E830, + ICE_MAC_GENERIC, + }; + +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +index 974c71490d97c..3ca5f44dea26e 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +@@ -1,5 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0 +-/* Copyright (C) 2021, Intel Corporation. */ ++/* Copyright (C) 2021-2023, Intel Corporation. */ + + #include "ice.h" + #include "ice_base.h" +@@ -1421,8 +1421,8 @@ ice_vc_fdir_irq_handler(struct ice_vsi *ctrl_vsi, + */ + static void ice_vf_fdir_dump_info(struct ice_vf *vf) + { ++ u32 fd_size, fd_cnt, fd_size_g, fd_cnt_g, fd_size_b, fd_cnt_b; + struct ice_vsi *vf_vsi; +- u32 fd_size, fd_cnt; + struct device *dev; + struct ice_pf *pf; + struct ice_hw *hw; +@@ -1441,12 +1441,25 @@ static void ice_vf_fdir_dump_info(struct ice_vf *vf) + + fd_size = rd32(hw, VSIQF_FD_SIZE(vsi_num)); + fd_cnt = rd32(hw, VSIQF_FD_CNT(vsi_num)); +- dev_dbg(dev, "VF %d: space allocated: guar:0x%x, be:0x%x, space consumed: guar:0x%x, be:0x%x\n", +- vf->vf_id, +- (fd_size & VSIQF_FD_CNT_FD_GCNT_M) >> VSIQF_FD_CNT_FD_GCNT_S, +- (fd_size & VSIQF_FD_CNT_FD_BCNT_M) >> VSIQF_FD_CNT_FD_BCNT_S, +- (fd_cnt & VSIQF_FD_CNT_FD_GCNT_M) >> VSIQF_FD_CNT_FD_GCNT_S, +- (fd_cnt & VSIQF_FD_CNT_FD_BCNT_M) >> VSIQF_FD_CNT_FD_BCNT_S); ++ switch (hw->mac_type) { ++ case ICE_MAC_E830: ++ fd_size_g = FIELD_GET(E830_VSIQF_FD_CNT_FD_GCNT_M, fd_size); ++ fd_size_b = FIELD_GET(E830_VSIQF_FD_CNT_FD_BCNT_M, fd_size); ++ fd_cnt_g = FIELD_GET(E830_VSIQF_FD_CNT_FD_GCNT_M, fd_cnt); ++ fd_cnt_b = FIELD_GET(E830_VSIQF_FD_CNT_FD_BCNT_M, fd_cnt); ++ break; ++ case ICE_MAC_E810: ++ default: ++ fd_size_g = FIELD_GET(E800_VSIQF_FD_CNT_FD_GCNT_M, fd_size); ++ fd_size_b = FIELD_GET(E800_VSIQF_FD_CNT_FD_BCNT_M, fd_size); ++ fd_cnt_g = FIELD_GET(E800_VSIQF_FD_CNT_FD_GCNT_M, fd_cnt); ++ fd_cnt_b = FIELD_GET(E800_VSIQF_FD_CNT_FD_BCNT_M, fd_cnt); ++ } ++ ++ dev_dbg(dev, "VF %d: Size in the FD table: guaranteed:0x%x, best effort:0x%x\n", ++ vf->vf_id, fd_size_g, fd_size_b); ++ dev_dbg(dev, "VF %d: Filter counter in the FD table: guaranteed:0x%x, best effort:0x%x\n", ++ vf->vf_id, fd_cnt_g, fd_cnt_b); + } + + /** +-- +2.39.5 + diff --git a/queue-6.6/ice-add-e830-hw-vf-mailbox-message-limit-support.patch b/queue-6.6/ice-add-e830-hw-vf-mailbox-message-limit-support.patch new file mode 100644 index 0000000000..6fa12123c9 --- /dev/null +++ b/queue-6.6/ice-add-e830-hw-vf-mailbox-message-limit-support.patch @@ -0,0 +1,289 @@ +From 07b5cfb88e640ac0e8ef5c39cb38fc13c9bb25d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Aug 2024 17:26:16 -0400 +Subject: ice: add E830 HW VF mailbox message limit support + +From: Paul Greenwalt + +[ Upstream commit 59f4d59b25aec39a015c0949f4ec235c7a839c44 ] + +E830 adds hardware support to prevent the VF from overflowing the PF +mailbox with VIRTCHNL messages. E830 will use the hardware feature +(ICE_F_MBX_LIMIT) instead of the software solution ice_is_malicious_vf(). + +To prevent a VF from overflowing the PF, the PF sets the number of +messages per VF that can be in the PF's mailbox queue +(ICE_MBX_OVERFLOW_WATERMARK). When the PF processes a message from a VF, +the PF decrements the per VF message count using the E830_MBX_VF_DEC_TRIG +register. + +Signed-off-by: Paul Greenwalt +Reviewed-by: Alexander Lobakin +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Stable-dep-of: 79990cf5e7ad ("ice: Fix deinitializing VF in error path") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice.h | 1 + + .../net/ethernet/intel/ice/ice_hw_autogen.h | 3 ++ + drivers/net/ethernet/intel/ice/ice_lib.c | 3 ++ + drivers/net/ethernet/intel/ice/ice_main.c | 24 ++++++++++---- + drivers/net/ethernet/intel/ice/ice_sriov.c | 3 +- + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 26 +++++++++++++-- + drivers/net/ethernet/intel/ice/ice_vf_mbx.c | 32 +++++++++++++++++++ + drivers/net/ethernet/intel/ice/ice_vf_mbx.h | 9 ++++++ + drivers/net/ethernet/intel/ice/ice_virtchnl.c | 8 +++-- + 9 files changed, 96 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index f943964ec05ae..e29a7ffd5f143 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -202,6 +202,7 @@ enum ice_feature { + ICE_F_GNSS, + ICE_F_ROCE_LAG, + ICE_F_SRIOV_LAG, ++ ICE_F_MBX_LIMIT, + ICE_F_MAX + }; + +diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +index 67519a985b327..96f70c0a96598 100644 +--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h ++++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +@@ -528,5 +528,8 @@ + #define E830_PRTMAC_CL01_QNT_THR_CL0_M GENMASK(15, 0) + #define VFINT_DYN_CTLN(_i) (0x00003800 + ((_i) * 4)) + #define VFINT_DYN_CTLN_CLEARPBA_M BIT(1) ++#define E830_MBX_PF_IN_FLIGHT_VF_MSGS_THRESH 0x00234000 ++#define E830_MBX_VF_DEC_TRIG(_VF) (0x00233800 + (_VF) * 4) ++#define E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(_VF) (0x00233000 + (_VF) * 4) + + #endif /* _ICE_HW_AUTOGEN_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c +index 3a0ef56d3edca..1fc4805353eb5 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -4023,6 +4023,9 @@ void ice_init_feature_support(struct ice_pf *pf) + default: + break; + } ++ ++ if (pf->hw.mac_type == ICE_MAC_E830) ++ ice_set_feature_support(pf, ICE_F_MBX_LIMIT); + } + + /** +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index ef5d43f2804e7..0ae7bdfff83fb 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -1514,12 +1514,20 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) + ice_vf_lan_overflow_event(pf, &event); + break; + case ice_mbx_opc_send_msg_to_pf: +- data.num_msg_proc = i; +- data.num_pending_arq = pending; +- data.max_num_msgs_mbx = hw->mailboxq.num_rq_entries; +- data.async_watermark_val = ICE_MBX_OVERFLOW_WATERMARK; ++ if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT)) { ++ ice_vc_process_vf_msg(pf, &event, NULL); ++ ice_mbx_vf_dec_trig_e830(hw, &event); ++ } else { ++ u16 val = hw->mailboxq.num_rq_entries; ++ ++ data.max_num_msgs_mbx = val; ++ val = ICE_MBX_OVERFLOW_WATERMARK; ++ data.async_watermark_val = val; ++ data.num_msg_proc = i; ++ data.num_pending_arq = pending; + +- ice_vc_process_vf_msg(pf, &event, &data); ++ ice_vc_process_vf_msg(pf, &event, &data); ++ } + break; + case ice_aqc_opc_fw_logging: + ice_output_fw_log(hw, &event.desc, event.msg_buf); +@@ -3920,7 +3928,11 @@ static int ice_init_pf(struct ice_pf *pf) + + mutex_init(&pf->vfs.table_lock); + hash_init(pf->vfs.table); +- ice_mbx_init_snapshot(&pf->hw); ++ if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT)) ++ wr32(&pf->hw, E830_MBX_PF_IN_FLIGHT_VF_MSGS_THRESH, ++ ICE_MBX_OVERFLOW_WATERMARK); ++ else ++ ice_mbx_init_snapshot(&pf->hw); + + return 0; + } +diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c +index 31314e7540f8c..b82c47f8865b4 100644 +--- a/drivers/net/ethernet/intel/ice/ice_sriov.c ++++ b/drivers/net/ethernet/intel/ice/ice_sriov.c +@@ -195,7 +195,8 @@ void ice_free_vfs(struct ice_pf *pf) + } + + /* clear malicious info since the VF is getting released */ +- list_del(&vf->mbx_info.list_entry); ++ if (!ice_is_feature_supported(pf, ICE_F_MBX_LIMIT)) ++ list_del(&vf->mbx_info.list_entry); + + mutex_unlock(&vf->cfg_lock); + } +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +index 03b9d7d748518..3f80ba02f634e 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +@@ -701,6 +701,23 @@ ice_vf_clear_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m) + return 0; + } + ++/** ++ * ice_reset_vf_mbx_cnt - reset VF mailbox message count ++ * @vf: pointer to the VF structure ++ * ++ * This function clears the VF mailbox message count, and should be called on ++ * VF reset. ++ */ ++static void ice_reset_vf_mbx_cnt(struct ice_vf *vf) ++{ ++ struct ice_pf *pf = vf->pf; ++ ++ if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT)) ++ ice_mbx_vf_clear_cnt_e830(&pf->hw, vf->vf_id); ++ else ++ ice_mbx_clear_malvf(&vf->mbx_info); ++} ++ + /** + * ice_reset_all_vfs - reset all allocated VFs in one go + * @pf: pointer to the PF structure +@@ -727,7 +744,7 @@ void ice_reset_all_vfs(struct ice_pf *pf) + + /* clear all malicious info if the VFs are getting reset */ + ice_for_each_vf(pf, bkt, vf) +- ice_mbx_clear_malvf(&vf->mbx_info); ++ ice_reset_vf_mbx_cnt(vf); + + /* If VFs have been disabled, there is no need to reset */ + if (test_and_set_bit(ICE_VF_DIS, pf->state)) { +@@ -944,7 +961,7 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) + ice_eswitch_update_repr(vsi); + + /* if the VF has been reset allow it to come up again */ +- ice_mbx_clear_malvf(&vf->mbx_info); ++ ice_reset_vf_mbx_cnt(vf); + + out_unlock: + if (lag && lag->bonded && lag->primary && +@@ -994,7 +1011,10 @@ void ice_initialize_vf_entry(struct ice_vf *vf) + ice_vf_fdir_init(vf); + + /* Initialize mailbox info for this VF */ +- ice_mbx_init_vf_info(&pf->hw, &vf->mbx_info); ++ if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT)) ++ ice_mbx_vf_clear_cnt_e830(&pf->hw, vf->vf_id); ++ else ++ ice_mbx_init_vf_info(&pf->hw, &vf->mbx_info); + + mutex_init(&vf->cfg_lock); + } +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_mbx.c b/drivers/net/ethernet/intel/ice/ice_vf_mbx.c +index 40cb4ba0789ce..75c8113e58ee9 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_mbx.c ++++ b/drivers/net/ethernet/intel/ice/ice_vf_mbx.c +@@ -210,6 +210,38 @@ ice_mbx_detect_malvf(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info, + return 0; + } + ++/** ++ * ice_mbx_vf_dec_trig_e830 - Decrements the VF mailbox queue counter ++ * @hw: pointer to the HW struct ++ * @event: pointer to the control queue receive event ++ * ++ * This function triggers to decrement the counter ++ * MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT when the driver replenishes ++ * the buffers at the PF mailbox queue. ++ */ ++void ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw, ++ const struct ice_rq_event_info *event) ++{ ++ u16 vfid = le16_to_cpu(event->desc.retval); ++ ++ wr32(hw, E830_MBX_VF_DEC_TRIG(vfid), 1); ++} ++ ++/** ++ * ice_mbx_vf_clear_cnt_e830 - Clear the VF mailbox queue count ++ * @hw: pointer to the HW struct ++ * @vf_id: VF ID in the PF space ++ * ++ * This function clears the counter MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT, and should ++ * be called when a VF is created and on VF reset. ++ */ ++void ice_mbx_vf_clear_cnt_e830(const struct ice_hw *hw, u16 vf_id) ++{ ++ u32 reg = rd32(hw, E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(vf_id)); ++ ++ wr32(hw, E830_MBX_VF_DEC_TRIG(vf_id), reg); ++} ++ + /** + * ice_mbx_vf_state_handler - Handle states of the overflow algorithm + * @hw: pointer to the HW struct +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_mbx.h b/drivers/net/ethernet/intel/ice/ice_vf_mbx.h +index 44bc030d17e07..684de89e5c5ed 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_mbx.h ++++ b/drivers/net/ethernet/intel/ice/ice_vf_mbx.h +@@ -19,6 +19,9 @@ ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval, + u8 *msg, u16 msglen, struct ice_sq_cd *cd); + + u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed); ++void ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw, ++ const struct ice_rq_event_info *event); ++void ice_mbx_vf_clear_cnt_e830(const struct ice_hw *hw, u16 vf_id); + int + ice_mbx_vf_state_handler(struct ice_hw *hw, struct ice_mbx_data *mbx_data, + struct ice_mbx_vf_info *vf_info, bool *report_malvf); +@@ -47,5 +50,11 @@ static inline void ice_mbx_init_snapshot(struct ice_hw *hw) + { + } + ++static inline void ++ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw, ++ const struct ice_rq_event_info *event) ++{ ++} ++ + #endif /* CONFIG_PCI_IOV */ + #endif /* _ICE_VF_MBX_H_ */ +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c +index 9f7268bb2ee3b..e709b10a29761 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c +@@ -3899,8 +3899,10 @@ ice_is_malicious_vf(struct ice_vf *vf, struct ice_mbx_data *mbxdata) + * @event: pointer to the AQ event + * @mbxdata: information used to detect VF attempting mailbox overflow + * +- * called from the common asq/arq handler to +- * process request from VF ++ * Called from the common asq/arq handler to process request from VF. When this ++ * flow is used for devices with hardware VF to PF message queue overflow ++ * support (ICE_F_MBX_LIMIT) mbxdata is set to NULL and ice_is_malicious_vf ++ * check is skipped. + */ + void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event, + struct ice_mbx_data *mbxdata) +@@ -3926,7 +3928,7 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event, + mutex_lock(&vf->cfg_lock); + + /* Check if the VF is trying to overflow the mailbox */ +- if (ice_is_malicious_vf(vf, mbxdata)) ++ if (mbxdata && ice_is_malicious_vf(vf, mbxdata)) + goto finish; + + /* Check if VF is disabled. */ +-- +2.39.5 + diff --git a/queue-6.6/ice-fix-deinitializing-vf-in-error-path.patch b/queue-6.6/ice-fix-deinitializing-vf-in-error-path.patch new file mode 100644 index 0000000000..7022fc7da0 --- /dev/null +++ b/queue-6.6/ice-fix-deinitializing-vf-in-error-path.patch @@ -0,0 +1,114 @@ +From 39b588255bfb95ec6cfad6a7b454ddfaf54d7544 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 11:06:41 -0800 +Subject: ice: Fix deinitializing VF in error path + +From: Marcin Szycik + +[ Upstream commit 79990cf5e7aded76d0c092c9f5ed31eb1c75e02c ] + +If ice_ena_vfs() fails after calling ice_create_vf_entries(), it frees +all VFs without removing them from snapshot PF-VF mailbox list, leading +to list corruption. + +Reproducer: + devlink dev eswitch set $PF1_PCI mode switchdev + ip l s $PF1 up + ip l s $PF1 promisc on + sleep 1 + echo 1 > /sys/class/net/$PF1/device/sriov_numvfs + sleep 1 + echo 1 > /sys/class/net/$PF1/device/sriov_numvfs + +Trace (minimized): + list_add corruption. next->prev should be prev (ffff8882e241c6f0), but was 0000000000000000. (next=ffff888455da1330). + kernel BUG at lib/list_debug.c:29! + RIP: 0010:__list_add_valid_or_report+0xa6/0x100 + ice_mbx_init_vf_info+0xa7/0x180 [ice] + ice_initialize_vf_entry+0x1fa/0x250 [ice] + ice_sriov_configure+0x8d7/0x1520 [ice] + ? __percpu_ref_switch_mode+0x1b1/0x5d0 + ? __pfx_ice_sriov_configure+0x10/0x10 [ice] + +Sometimes a KASAN report can be seen instead with a similar stack trace: + BUG: KASAN: use-after-free in __list_add_valid_or_report+0xf1/0x100 + +VFs are added to this list in ice_mbx_init_vf_info(), but only removed +in ice_free_vfs(). Move the removing to ice_free_vf_entries(), which is +also being called in other places where VFs are being removed (including +ice_free_vfs() itself). + +Fixes: 8cd8a6b17d27 ("ice: move VF overflow message count into struct ice_mbx_vf_info") +Reported-by: Sujai Buvaneswaran +Closes: https://lore.kernel.org/intel-wired-lan/PH0PR11MB50138B635F2E5CEB7075325D961F2@PH0PR11MB5013.namprd11.prod.outlook.com +Reviewed-by: Martyna Szapar-Mudlaw +Signed-off-by: Marcin Szycik +Reviewed-by: Simon Horman +Tested-by: Sujai Buvaneswaran +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20250224190647.3601930-2-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_sriov.c | 5 +---- + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 8 ++++++++ + drivers/net/ethernet/intel/ice/ice_vf_lib_private.h | 1 + + 3 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c +index b82c47f8865b4..56345fe653707 100644 +--- a/drivers/net/ethernet/intel/ice/ice_sriov.c ++++ b/drivers/net/ethernet/intel/ice/ice_sriov.c +@@ -36,6 +36,7 @@ static void ice_free_vf_entries(struct ice_pf *pf) + + hash_for_each_safe(vfs->table, bkt, tmp, vf, entry) { + hash_del_rcu(&vf->entry); ++ ice_deinitialize_vf_entry(vf); + ice_put_vf(vf); + } + } +@@ -194,10 +195,6 @@ void ice_free_vfs(struct ice_pf *pf) + wr32(hw, GLGEN_VFLRSTAT(reg_idx), BIT(bit_idx)); + } + +- /* clear malicious info since the VF is getting released */ +- if (!ice_is_feature_supported(pf, ICE_F_MBX_LIMIT)) +- list_del(&vf->mbx_info.list_entry); +- + mutex_unlock(&vf->cfg_lock); + } + +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +index 3f80ba02f634e..58f9ac81dfbb2 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +@@ -1019,6 +1019,14 @@ void ice_initialize_vf_entry(struct ice_vf *vf) + mutex_init(&vf->cfg_lock); + } + ++void ice_deinitialize_vf_entry(struct ice_vf *vf) ++{ ++ struct ice_pf *pf = vf->pf; ++ ++ if (!ice_is_feature_supported(pf, ICE_F_MBX_LIMIT)) ++ list_del(&vf->mbx_info.list_entry); ++} ++ + /** + * ice_dis_vf_qs - Disable the VF queues + * @vf: pointer to the VF structure +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib_private.h b/drivers/net/ethernet/intel/ice/ice_vf_lib_private.h +index 0c7e77c0a09fa..5392b04049862 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib_private.h ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib_private.h +@@ -24,6 +24,7 @@ + #endif + + void ice_initialize_vf_entry(struct ice_vf *vf); ++void ice_deinitialize_vf_entry(struct ice_vf *vf); + void ice_dis_vf_qs(struct ice_vf *vf); + int ice_check_vf_init(struct ice_vf *vf); + enum virtchnl_status_code ice_err_to_virt_err(int err); +-- +2.39.5 + diff --git a/queue-6.6/include-net-add-static-inline-dst_dev_overhead-to-ds.patch b/queue-6.6/include-net-add-static-inline-dst_dev_overhead-to-ds.patch new file mode 100644 index 0000000000..83eb05067e --- /dev/null +++ b/queue-6.6/include-net-add-static-inline-dst_dev_overhead-to-ds.patch @@ -0,0 +1,49 @@ +From 7a1b819ee42597e7c986cd11e44fa1bbc8d0cb35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 13:49:42 +0100 +Subject: include: net: add static inline dst_dev_overhead() to dst.h + +From: Justin Iurman + +[ Upstream commit 0600cf40e9b36fe17f9c9f04d4f9cef249eaa5e7 ] + +Add static inline dst_dev_overhead() function to include/net/dst.h. This +helper function is used by ioam6_iptunnel, rpl_iptunnel and +seg6_iptunnel to get the dev's overhead based on a cache entry +(dst_entry). If the cache is empty, the default and generic value +skb->mac_len is returned. Otherwise, LL_RESERVED_SPACE() over dst's dev +is returned. + +Signed-off-by: Justin Iurman +Cc: Alexander Lobakin +Cc: Vadim Fedorenko +Signed-off-by: Paolo Abeni +Stable-dep-of: c64a0727f9b1 ("net: ipv6: fix dst ref loop on input in seg6 lwt") +Signed-off-by: Sasha Levin +--- + include/net/dst.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/include/net/dst.h b/include/net/dst.h +index 78884429deed8..16b7b99b5f309 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -448,6 +448,15 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout) + dst->expires = expires; + } + ++static inline unsigned int dst_dev_overhead(struct dst_entry *dst, ++ struct sk_buff *skb) ++{ ++ if (likely(dst)) ++ return LL_RESERVED_SPACE(dst->dev); ++ ++ return skb->mac_len; ++} ++ + INDIRECT_CALLABLE_DECLARE(int ip6_output(struct net *, struct sock *, + struct sk_buff *)); + INDIRECT_CALLABLE_DECLARE(int ip_output(struct net *, struct sock *, +-- +2.39.5 + diff --git a/queue-6.6/ipv4-convert-icmp_route_lookup-to-dscp_t.patch b/queue-6.6/ipv4-convert-icmp_route_lookup-to-dscp_t.patch new file mode 100644 index 0000000000..a09b21f325 --- /dev/null +++ b/queue-6.6/ipv4-convert-icmp_route_lookup-to-dscp_t.patch @@ -0,0 +1,81 @@ +From b4c73d305965ba8c42fd456d485fe39ff8ca3e1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Oct 2024 21:28:37 +0200 +Subject: ipv4: Convert icmp_route_lookup() to dscp_t. + +From: Guillaume Nault + +[ Upstream commit 913c83a610bb7dd8e5952a2b4663e1feec0b5de6 ] + +Pass a dscp_t variable to icmp_route_lookup(), instead of a plain u8, +to prevent accidental setting of ECN bits in ->flowi4_tos. Rename that +variable ("tos" -> "dscp") to make the intent clear. + +While there, reorganise the function parameters to fill up horizontal +space. + +Signed-off-by: Guillaume Nault +Reviewed-by: David Ahern +Link: https://patch.msgid.link/294fead85c6035bcdc5fcf9a6bb4ce8798c45ba1.1727807926.git.gnault@redhat.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part") +Signed-off-by: Sasha Levin +--- + net/ipv4/icmp.c | 19 +++++++++---------- + 1 file changed, 9 insertions(+), 10 deletions(-) + +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index a154339845dd4..855fcef829e2c 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -484,13 +484,11 @@ static struct net_device *icmp_get_route_lookup_dev(struct sk_buff *skb) + return route_lookup_dev; + } + +-static struct rtable *icmp_route_lookup(struct net *net, +- struct flowi4 *fl4, ++static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4, + struct sk_buff *skb_in, +- const struct iphdr *iph, +- __be32 saddr, u8 tos, u32 mark, +- int type, int code, +- struct icmp_bxm *param) ++ const struct iphdr *iph, __be32 saddr, ++ dscp_t dscp, u32 mark, int type, ++ int code, struct icmp_bxm *param) + { + struct net_device *route_lookup_dev; + struct rtable *rt, *rt2; +@@ -503,7 +501,7 @@ static struct rtable *icmp_route_lookup(struct net *net, + fl4->saddr = saddr; + fl4->flowi4_mark = mark; + fl4->flowi4_uid = sock_net_uid(net, NULL); +- fl4->flowi4_tos = tos & INET_DSCP_MASK; ++ fl4->flowi4_tos = inet_dscp_to_dsfield(dscp); + fl4->flowi4_proto = IPPROTO_ICMP; + fl4->fl4_icmp_type = type; + fl4->fl4_icmp_code = code; +@@ -551,7 +549,7 @@ static struct rtable *icmp_route_lookup(struct net *net, + orefdst = skb_in->_skb_refdst; /* save old refdst */ + skb_dst_set(skb_in, NULL); + err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr, +- tos, rt2->dst.dev); ++ inet_dscp_to_dsfield(dscp), rt2->dst.dev); + + dst_release(&rt2->dst); + rt2 = skb_rtable(skb_in); +@@ -747,8 +745,9 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info, + ipc.opt = &icmp_param.replyopts.opt; + ipc.sockc.mark = mark; + +- rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, mark, +- type, code, &icmp_param); ++ rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, ++ inet_dsfield_to_dscp(tos), mark, type, code, ++ &icmp_param); + if (IS_ERR(rt)) + goto out_unlock; + +-- +2.39.5 + diff --git a/queue-6.6/ipv4-convert-ip_route_input-to-dscp_t.patch b/queue-6.6/ipv4-convert-ip_route_input-to-dscp_t.patch new file mode 100644 index 0000000000..c70a718b1e --- /dev/null +++ b/queue-6.6/ipv4-convert-ip_route_input-to-dscp_t.patch @@ -0,0 +1,156 @@ +From 1f5ac6c1fb081886bc9deec7224c8ae398e8bd95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Oct 2024 21:28:43 +0200 +Subject: ipv4: Convert ip_route_input() to dscp_t. + +From: Guillaume Nault + +[ Upstream commit 7e863e5db6185b1add0df4cb01b31a4ed1c4b738 ] + +Pass a dscp_t variable to ip_route_input(), instead of a plain u8, to +prevent accidental setting of ECN bits in ->flowi4_tos. + +Callers of ip_route_input() to consider are: + + * input_action_end_dx4_finish() and input_action_end_dt4() in + net/ipv6/seg6_local.c. These functions set the tos parameter to 0, + which is already a valid dscp_t value, so they don't need to be + adjusted for the new prototype. + + * icmp_route_lookup(), which already has a dscp_t variable to pass as + parameter. We just need to remove the inet_dscp_to_dsfield() + conversion. + + * br_nf_pre_routing_finish(), ip_options_rcv_srr() and ip4ip6_err(), + which get the DSCP directly from IPv4 headers. Define a helper to + read the .tos field of struct iphdr as dscp_t, so that these + function don't have to do the conversion manually. + +While there, declare *iph as const in br_nf_pre_routing_finish(), +declare its local variables in reverse-christmas-tree order and move +the "err = ip_route_input()" assignment out of the conditional to avoid +checkpatch warning. + +Signed-off-by: Guillaume Nault +Reviewed-by: David Ahern +Link: https://patch.msgid.link/e9d40781d64d3d69f4c79ac8a008b8d67a033e8d.1727807926.git.gnault@redhat.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part") +Signed-off-by: Sasha Levin +--- + include/net/ip.h | 5 +++++ + include/net/route.h | 5 +++-- + net/bridge/br_netfilter_hooks.c | 8 +++++--- + net/ipv4/icmp.c | 2 +- + net/ipv4/ip_options.c | 3 ++- + net/ipv6/ip6_tunnel.c | 4 ++-- + 6 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/include/net/ip.h b/include/net/ip.h +index 7db5912e0c5f6..d8bf1f0a6919c 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -415,6 +415,11 @@ int ip_decrease_ttl(struct iphdr *iph) + return --iph->ttl; + } + ++static inline dscp_t ip4h_dscp(const struct iphdr *ip4h) ++{ ++ return inet_dsfield_to_dscp(ip4h->tos); ++} ++ + static inline int ip_mtu_locked(const struct dst_entry *dst) + { + const struct rtable *rt = (const struct rtable *)dst; +diff --git a/include/net/route.h b/include/net/route.h +index 0171e9e1bbea3..27c17aff0bbe1 100644 +--- a/include/net/route.h ++++ b/include/net/route.h +@@ -200,12 +200,13 @@ int ip_route_use_hint(struct sk_buff *skb, __be32 dst, __be32 src, + const struct sk_buff *hint); + + static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src, +- u8 tos, struct net_device *devin) ++ dscp_t dscp, struct net_device *devin) + { + int err; + + rcu_read_lock(); +- err = ip_route_input_noref(skb, dst, src, tos, devin); ++ err = ip_route_input_noref(skb, dst, src, inet_dscp_to_dsfield(dscp), ++ devin); + if (!err) { + skb_dst_force(skb); + if (!skb_dst(skb)) +diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c +index a1cfa75bbadb9..2a4958e995f2d 100644 +--- a/net/bridge/br_netfilter_hooks.c ++++ b/net/bridge/br_netfilter_hooks.c +@@ -366,9 +366,9 @@ br_nf_ipv4_daddr_was_changed(const struct sk_buff *skb, + */ + static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_buff *skb) + { +- struct net_device *dev = skb->dev, *br_indev; +- struct iphdr *iph = ip_hdr(skb); + struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); ++ struct net_device *dev = skb->dev, *br_indev; ++ const struct iphdr *iph = ip_hdr(skb); + struct rtable *rt; + int err; + +@@ -386,7 +386,9 @@ static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_ + } + nf_bridge->in_prerouting = 0; + if (br_nf_ipv4_daddr_was_changed(skb, nf_bridge)) { +- if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { ++ err = ip_route_input(skb, iph->daddr, iph->saddr, ++ ip4h_dscp(iph), dev); ++ if (err) { + struct in_device *in_dev = __in_dev_get_rcu(dev); + + /* If err equals -EHOSTUNREACH the error is due to a +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index 855fcef829e2c..94501bb30c431 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -549,7 +549,7 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4, + orefdst = skb_in->_skb_refdst; /* save old refdst */ + skb_dst_set(skb_in, NULL); + err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr, +- inet_dscp_to_dsfield(dscp), rt2->dst.dev); ++ dscp, rt2->dst.dev); + + dst_release(&rt2->dst); + rt2 = skb_rtable(skb_in); +diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c +index a9e22a098872f..b4c59708fc095 100644 +--- a/net/ipv4/ip_options.c ++++ b/net/ipv4/ip_options.c +@@ -617,7 +617,8 @@ int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev) + + orefdst = skb->_skb_refdst; + skb_dst_set(skb, NULL); +- err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, dev); ++ err = ip_route_input(skb, nexthop, iph->saddr, ip4h_dscp(iph), ++ dev); + rt2 = skb_rtable(skb); + if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) { + skb_dst_drop(skb); +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 97905d4174eca..d645d022ce774 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -628,8 +628,8 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + } + skb_dst_set(skb2, &rt->dst); + } else { +- if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, +- skb2->dev) || ++ if (ip_route_input(skb2, eiph->daddr, eiph->saddr, ++ ip4h_dscp(eiph), skb2->dev) || + skb_dst(skb2)->dev->type != ARPHRD_TUNNEL6) + goto out; + } +-- +2.39.5 + diff --git a/queue-6.6/ipv4-icmp-pass-full-ds-field-to-ip_route_input.patch b/queue-6.6/ipv4-icmp-pass-full-ds-field-to-ip_route_input.patch new file mode 100644 index 0000000000..c4695d6ec0 --- /dev/null +++ b/queue-6.6/ipv4-icmp-pass-full-ds-field-to-ip_route_input.patch @@ -0,0 +1,44 @@ +From eaa55bd0afe35cd82c838b5f0529129575fbff78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Aug 2024 15:52:49 +0300 +Subject: ipv4: icmp: Pass full DS field to ip_route_input() + +From: Ido Schimmel + +[ Upstream commit 1c6f50b37f711b831d78973dad0df1da99ad0014 ] + +Align the ICMP code to other callers of ip_route_input() and pass the +full DS field. In the future this will allow us to perform a route +lookup according to the full DSCP value. + +No functional changes intended since the upper DSCP bits are masked when +comparing against the TOS selectors in FIB rules and routes. + +Signed-off-by: Ido Schimmel +Reviewed-by: Guillaume Nault +Acked-by: Florian Westphal +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20240821125251.1571445-11-idosch@nvidia.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part") +Signed-off-by: Sasha Levin +--- + net/ipv4/icmp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index b05fa424ad5ce..3807a269e0755 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -550,7 +550,7 @@ static struct rtable *icmp_route_lookup(struct net *net, + orefdst = skb_in->_skb_refdst; /* save old refdst */ + skb_dst_set(skb_in, NULL); + err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr, +- RT_TOS(tos), rt2->dst.dev); ++ tos, rt2->dst.dev); + + dst_release(&rt2->dst); + rt2 = skb_rtable(skb_in); +-- +2.39.5 + diff --git a/queue-6.6/ipv4-icmp-unmask-upper-dscp-bits-in-icmp_route_looku.patch b/queue-6.6/ipv4-icmp-unmask-upper-dscp-bits-in-icmp_route_looku.patch new file mode 100644 index 0000000000..993f4e67be --- /dev/null +++ b/queue-6.6/ipv4-icmp-unmask-upper-dscp-bits-in-icmp_route_looku.patch @@ -0,0 +1,51 @@ +From 70d2a1e3e8e18f517f1bbaba8ea03231ce283ccb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Aug 2024 09:54:50 +0300 +Subject: ipv4: icmp: Unmask upper DSCP bits in icmp_route_lookup() + +From: Ido Schimmel + +[ Upstream commit 4805646c42e51d2fbf142864d281473ad453ad5d ] + +The function is called to resolve a route for an ICMP message that is +sent in response to a situation. Based on the type of the generated ICMP +message, the function is either passed the DS field of the packet that +generated the ICMP message or a DS field that is derived from it. + +Unmask the upper DSCP bits before resolving and output route via +ip_route_output_key_hash() so that in the future the lookup could be +performed according to the full DSCP value. + +Signed-off-by: Ido Schimmel +Reviewed-by: Guillaume Nault +Signed-off-by: David S. Miller +Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part") +Signed-off-by: Sasha Levin +--- + net/ipv4/icmp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index 3807a269e0755..a154339845dd4 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -93,6 +93,7 @@ + #include + #include + #include ++#include + #define CREATE_TRACE_POINTS + #include + +@@ -502,7 +503,7 @@ static struct rtable *icmp_route_lookup(struct net *net, + fl4->saddr = saddr; + fl4->flowi4_mark = mark; + fl4->flowi4_uid = sock_net_uid(net, NULL); +- fl4->flowi4_tos = RT_TOS(tos); ++ fl4->flowi4_tos = tos & INET_DSCP_MASK; + fl4->flowi4_proto = IPPROTO_ICMP; + fl4->fl4_icmp_type = type; + fl4->fl4_icmp_code = code; +-- +2.39.5 + diff --git a/queue-6.6/ipvlan-ensure-network-headers-are-in-skb-linear-part.patch b/queue-6.6/ipvlan-ensure-network-headers-are-in-skb-linear-part.patch new file mode 100644 index 0000000000..2559930af4 --- /dev/null +++ b/queue-6.6/ipvlan-ensure-network-headers-are-in-skb-linear-part.patch @@ -0,0 +1,113 @@ +From 780f70c5379b6105e22db80c146e21614c591a03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 15:53:36 +0000 +Subject: ipvlan: ensure network headers are in skb linear part + +From: Eric Dumazet + +[ Upstream commit 27843ce6ba3d3122b65066550fe33fb8839f8aef ] + +syzbot found that ipvlan_process_v6_outbound() was assuming +the IPv6 network header isis present in skb->head [1] + +Add the needed pskb_network_may_pull() calls for both +IPv4 and IPv6 handlers. + +[1] +BUG: KMSAN: uninit-value in __ipv6_addr_type+0xa2/0x490 net/ipv6/addrconf_core.c:47 + __ipv6_addr_type+0xa2/0x490 net/ipv6/addrconf_core.c:47 + ipv6_addr_type include/net/ipv6.h:555 [inline] + ip6_route_output_flags_noref net/ipv6/route.c:2616 [inline] + ip6_route_output_flags+0x51/0x720 net/ipv6/route.c:2651 + ip6_route_output include/net/ip6_route.h:93 [inline] + ipvlan_route_v6_outbound+0x24e/0x520 drivers/net/ipvlan/ipvlan_core.c:476 + ipvlan_process_v6_outbound drivers/net/ipvlan/ipvlan_core.c:491 [inline] + ipvlan_process_outbound drivers/net/ipvlan/ipvlan_core.c:541 [inline] + ipvlan_xmit_mode_l3 drivers/net/ipvlan/ipvlan_core.c:605 [inline] + ipvlan_queue_xmit+0xd72/0x1780 drivers/net/ipvlan/ipvlan_core.c:671 + ipvlan_start_xmit+0x5b/0x210 drivers/net/ipvlan/ipvlan_main.c:223 + __netdev_start_xmit include/linux/netdevice.h:5150 [inline] + netdev_start_xmit include/linux/netdevice.h:5159 [inline] + xmit_one net/core/dev.c:3735 [inline] + dev_hard_start_xmit+0x247/0xa20 net/core/dev.c:3751 + sch_direct_xmit+0x399/0xd40 net/sched/sch_generic.c:343 + qdisc_restart net/sched/sch_generic.c:408 [inline] + __qdisc_run+0x14da/0x35d0 net/sched/sch_generic.c:416 + qdisc_run+0x141/0x4d0 include/net/pkt_sched.h:127 + net_tx_action+0x78b/0x940 net/core/dev.c:5484 + handle_softirqs+0x1a0/0x7c0 kernel/softirq.c:561 + __do_softirq+0x14/0x1a kernel/softirq.c:595 + do_softirq+0x9a/0x100 kernel/softirq.c:462 + __local_bh_enable_ip+0x9f/0xb0 kernel/softirq.c:389 + local_bh_enable include/linux/bottom_half.h:33 [inline] + rcu_read_unlock_bh include/linux/rcupdate.h:919 [inline] + __dev_queue_xmit+0x2758/0x57d0 net/core/dev.c:4611 + dev_queue_xmit include/linux/netdevice.h:3311 [inline] + packet_xmit+0x9c/0x6c0 net/packet/af_packet.c:276 + packet_snd net/packet/af_packet.c:3132 [inline] + packet_sendmsg+0x93e0/0xa7e0 net/packet/af_packet.c:3164 + sock_sendmsg_nosec net/socket.c:718 [inline] + +Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") +Reported-by: syzbot+93ab4a777bafb9d9f960@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/67b74f01.050a0220.14d86d.02d8.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Mahesh Bandewar +Link: https://patch.msgid.link/20250220155336.61884-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ipvlan/ipvlan_core.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c +index fd591ddb3884d..ca62188a317ad 100644 +--- a/drivers/net/ipvlan/ipvlan_core.c ++++ b/drivers/net/ipvlan/ipvlan_core.c +@@ -416,20 +416,25 @@ struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h, + + static noinline_for_stack int ipvlan_process_v4_outbound(struct sk_buff *skb) + { +- const struct iphdr *ip4h = ip_hdr(skb); + struct net_device *dev = skb->dev; + struct net *net = dev_net(dev); +- struct rtable *rt; + int err, ret = NET_XMIT_DROP; ++ const struct iphdr *ip4h; ++ struct rtable *rt; + struct flowi4 fl4 = { + .flowi4_oif = dev->ifindex, +- .flowi4_tos = inet_dscp_to_dsfield(ip4h_dscp(ip4h)), + .flowi4_flags = FLOWI_FLAG_ANYSRC, + .flowi4_mark = skb->mark, +- .daddr = ip4h->daddr, +- .saddr = ip4h->saddr, + }; + ++ if (!pskb_network_may_pull(skb, sizeof(struct iphdr))) ++ goto err; ++ ++ ip4h = ip_hdr(skb); ++ fl4.daddr = ip4h->daddr; ++ fl4.saddr = ip4h->saddr; ++ fl4.flowi4_tos = inet_dscp_to_dsfield(ip4h_dscp(ip4h)); ++ + rt = ip_route_output_flow(net, &fl4, NULL); + if (IS_ERR(rt)) + goto err; +@@ -488,6 +493,12 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb) + struct net_device *dev = skb->dev; + int err, ret = NET_XMIT_DROP; + ++ if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) { ++ DEV_STATS_INC(dev, tx_errors); ++ kfree_skb(skb); ++ return ret; ++ } ++ + err = ipvlan_route_v6_outbound(dev, skb); + if (unlikely(err)) { + DEV_STATS_INC(dev, tx_errors); +-- +2.39.5 + diff --git a/queue-6.6/ipvlan-prepare-ipvlan_process_v4_outbound-to-future-.patch b/queue-6.6/ipvlan-prepare-ipvlan_process_v4_outbound-to-future-.patch new file mode 100644 index 0000000000..ea59be7ecc --- /dev/null +++ b/queue-6.6/ipvlan-prepare-ipvlan_process_v4_outbound-to-future-.patch @@ -0,0 +1,50 @@ +From 758cc51f1434bef5c1bf34280c51d0424d634c6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Oct 2024 13:43:11 +0100 +Subject: ipvlan: Prepare ipvlan_process_v4_outbound() to future .flowi4_tos + conversion. + +From: Guillaume Nault + +[ Upstream commit 0c30d6eedd1ec0c1382bcab9576d26413cd278a3 ] + +Use ip4h_dscp() to get the DSCP from the IPv4 header, then convert the +dscp_t value to __u8 with inet_dscp_to_dsfield(). + +Then, when we'll convert .flowi4_tos to dscp_t, we'll just have to drop +the inet_dscp_to_dsfield() call. + +Signed-off-by: Guillaume Nault +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/f48335504a05b3587e0081a9b4511e0761571ca5.1730292157.git.gnault@redhat.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part") +Signed-off-by: Sasha Levin +--- + drivers/net/ipvlan/ipvlan_core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c +index b1afcb8740de1..fd591ddb3884d 100644 +--- a/drivers/net/ipvlan/ipvlan_core.c ++++ b/drivers/net/ipvlan/ipvlan_core.c +@@ -3,6 +3,7 @@ + */ + + #include ++#include + + #include "ipvlan.h" + +@@ -422,7 +423,7 @@ static noinline_for_stack int ipvlan_process_v4_outbound(struct sk_buff *skb) + int err, ret = NET_XMIT_DROP; + struct flowi4 fl4 = { + .flowi4_oif = dev->ifindex, +- .flowi4_tos = ip4h->tos & INET_DSCP_MASK, ++ .flowi4_tos = inet_dscp_to_dsfield(ip4h_dscp(ip4h)), + .flowi4_flags = FLOWI_FLAG_ANYSRC, + .flowi4_mark = skb->mark, + .daddr = ip4h->daddr, +-- +2.39.5 + diff --git a/queue-6.6/ipvlan-unmask-upper-dscp-bits-in-ipvlan_process_v4_o.patch b/queue-6.6/ipvlan-unmask-upper-dscp-bits-in-ipvlan_process_v4_o.patch new file mode 100644 index 0000000000..63ab8bee80 --- /dev/null +++ b/queue-6.6/ipvlan-unmask-upper-dscp-bits-in-ipvlan_process_v4_o.patch @@ -0,0 +1,47 @@ +From 3d279e5cc30561c9c3c9203b804ab81b0ddb0284 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Aug 2024 09:54:57 +0300 +Subject: ipvlan: Unmask upper DSCP bits in ipvlan_process_v4_outbound() + +From: Ido Schimmel + +[ Upstream commit 939cd1abf080c629552a9c5e6db4c0509d13e4c7 ] + +Unmask the upper DSCP bits when calling ip_route_output_flow() so that +in the future it could perform the FIB lookup according to the full DSCP +value. + +Signed-off-by: Ido Schimmel +Reviewed-by: Guillaume Nault +Signed-off-by: David S. Miller +Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part") +Signed-off-by: Sasha Levin +--- + drivers/net/ipvlan/ipvlan_core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c +index fef4eff7753a7..b1afcb8740de1 100644 +--- a/drivers/net/ipvlan/ipvlan_core.c ++++ b/drivers/net/ipvlan/ipvlan_core.c +@@ -2,6 +2,8 @@ + /* Copyright (c) 2014 Mahesh Bandewar + */ + ++#include ++ + #include "ipvlan.h" + + static u32 ipvlan_jhash_secret __read_mostly; +@@ -420,7 +422,7 @@ static noinline_for_stack int ipvlan_process_v4_outbound(struct sk_buff *skb) + int err, ret = NET_XMIT_DROP; + struct flowi4 fl4 = { + .flowi4_oif = dev->ifindex, +- .flowi4_tos = RT_TOS(ip4h->tos), ++ .flowi4_tos = ip4h->tos & INET_DSCP_MASK, + .flowi4_flags = FLOWI_FLAG_ANYSRC, + .flowi4_mark = skb->mark, + .daddr = ip4h->daddr, +-- +2.39.5 + diff --git a/queue-6.6/ipvs-always-clear-ipvs_property-flag-in-skb_scrub_pa.patch b/queue-6.6/ipvs-always-clear-ipvs_property-flag-in-skb_scrub_pa.patch new file mode 100644 index 0000000000..12cb04f443 --- /dev/null +++ b/queue-6.6/ipvs-always-clear-ipvs_property-flag-in-skb_scrub_pa.patch @@ -0,0 +1,51 @@ +From fe74c8df03cdb1fe7dd7f34e5fdb09c8a979bd5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Feb 2025 11:35:18 +0800 +Subject: ipvs: Always clear ipvs_property flag in skb_scrub_packet() + +From: Philo Lu + +[ Upstream commit de2c211868b9424f9aa9b3432c4430825bafb41b ] + +We found an issue when using bpf_redirect with ipvs NAT mode after +commit ff70202b2d1a ("dev_forward_skb: do not scrub skb mark within +the same name space"). Particularly, we use bpf_redirect to return +the skb directly back to the netif it comes from, i.e., xnet is +false in skb_scrub_packet(), and then ipvs_property is preserved +and SNAT is skipped in the rx path. + +ipvs_property has been already cleared when netns is changed in +commit 2b5ec1a5f973 ("netfilter/ipvs: clear ipvs_property flag when +SKB net namespace changed"). This patch just clears it in spite of +netns. + +Fixes: 2b5ec1a5f973 ("netfilter/ipvs: clear ipvs_property flag when SKB net namespace changed") +Signed-off-by: Philo Lu +Acked-by: Julian Anastasov +Link: https://patch.msgid.link/20250222033518.126087-1-lulie@linux.alibaba.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/core/skbuff.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index f0a9ef1aeaa29..21a83e26f004b 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -5867,11 +5867,11 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet) + skb->offload_fwd_mark = 0; + skb->offload_l3_fwd_mark = 0; + #endif ++ ipvs_reset(skb); + + if (!xnet) + return; + +- ipvs_reset(skb); + skb->mark = 0; + skb_clear_tstamp(skb); + } +-- +2.39.5 + diff --git a/queue-6.6/net-cadence-macb-synchronize-stats-calculations.patch b/queue-6.6/net-cadence-macb-synchronize-stats-calculations.patch new file mode 100644 index 0000000000..c4c788f924 --- /dev/null +++ b/queue-6.6/net-cadence-macb-synchronize-stats-calculations.patch @@ -0,0 +1,115 @@ +From 5f967074e928edfd13030bdc257df5c9b7f16517 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 11:29:50 -0500 +Subject: net: cadence: macb: Synchronize stats calculations + +From: Sean Anderson + +[ Upstream commit fa52f15c745ce55261b92873676f64f7348cfe82 ] + +Stats calculations involve a RMW to add the stat update to the existing +value. This is currently not protected by any synchronization mechanism, +so data races are possible. Add a spinlock to protect the update. The +reader side could be protected using u64_stats, but we would still need +a spinlock for the update side anyway. And we always do an update +immediately before reading the stats anyway. + +Fixes: 89e5785fc8a6 ("[PATCH] Atmel MACB ethernet driver") +Signed-off-by: Sean Anderson +Link: https://patch.msgid.link/20250220162950.95941-1-sean.anderson@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cadence/macb.h | 2 ++ + drivers/net/ethernet/cadence/macb_main.c | 12 ++++++++++-- + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h +index 78c972bb1d962..9fb5a18e056d4 100644 +--- a/drivers/net/ethernet/cadence/macb.h ++++ b/drivers/net/ethernet/cadence/macb.h +@@ -1270,6 +1270,8 @@ struct macb { + struct clk *rx_clk; + struct clk *tsu_clk; + struct net_device *dev; ++ /* Protects hw_stats and ethtool_stats */ ++ spinlock_t stats_lock; + union { + struct macb_stats macb; + struct gem_stats gem; +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 8f61731e4554b..4325d0ace1f26 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -1992,10 +1992,12 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) + + if (status & MACB_BIT(ISR_ROVR)) { + /* We missed at least one packet */ ++ spin_lock(&bp->stats_lock); + if (macb_is_gem(bp)) + bp->hw_stats.gem.rx_overruns++; + else + bp->hw_stats.macb.rx_overruns++; ++ spin_unlock(&bp->stats_lock); + + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + queue_writel(queue, ISR, MACB_BIT(ISR_ROVR)); +@@ -3084,6 +3086,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp) + if (!netif_running(bp->dev)) + return nstat; + ++ spin_lock_irq(&bp->stats_lock); + gem_update_stats(bp); + + nstat->rx_errors = (hwstat->rx_frame_check_sequence_errors + +@@ -3113,6 +3116,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp) + nstat->tx_aborted_errors = hwstat->tx_excessive_collisions; + nstat->tx_carrier_errors = hwstat->tx_carrier_sense_errors; + nstat->tx_fifo_errors = hwstat->tx_underrun; ++ spin_unlock_irq(&bp->stats_lock); + + return nstat; + } +@@ -3120,12 +3124,13 @@ static struct net_device_stats *gem_get_stats(struct macb *bp) + static void gem_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) + { +- struct macb *bp; ++ struct macb *bp = netdev_priv(dev); + +- bp = netdev_priv(dev); ++ spin_lock_irq(&bp->stats_lock); + gem_update_stats(bp); + memcpy(data, &bp->ethtool_stats, sizeof(u64) + * (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES)); ++ spin_unlock_irq(&bp->stats_lock); + } + + static int gem_get_sset_count(struct net_device *dev, int sset) +@@ -3175,6 +3180,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) + return gem_get_stats(bp); + + /* read stats from hardware */ ++ spin_lock_irq(&bp->stats_lock); + macb_update_stats(bp); + + /* Convert HW stats into netdevice stats */ +@@ -3208,6 +3214,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) + nstat->tx_carrier_errors = hwstat->tx_carrier_errors; + nstat->tx_fifo_errors = hwstat->tx_underruns; + /* Don't know about heartbeat or window errors... */ ++ spin_unlock_irq(&bp->stats_lock); + + return nstat; + } +@@ -5063,6 +5070,7 @@ static int macb_probe(struct platform_device *pdev) + } + } + spin_lock_init(&bp->lock); ++ spin_lock_init(&bp->stats_lock); + + /* setup capabilities */ + macb_configure_caps(bp, macb_config); +-- +2.39.5 + diff --git a/queue-6.6/net-clear-old-fragment-checksum-value-in-napi_reuse_.patch b/queue-6.6/net-clear-old-fragment-checksum-value-in-napi_reuse_.patch new file mode 100644 index 0000000000..7d28d1be04 --- /dev/null +++ b/queue-6.6/net-clear-old-fragment-checksum-value-in-napi_reuse_.patch @@ -0,0 +1,77 @@ +From 1da4afde5e7a03e11a335f061a5b964ee6cef29a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 13:28:52 +0200 +Subject: net: Clear old fragment checksum value in napi_reuse_skb + +From: Mohammad Heib + +[ Upstream commit 49806fe6e61b045b5be8610e08b5a3083c109aa0 ] + +In certain cases, napi_get_frags() returns an skb that points to an old +received fragment, This skb may have its skb->ip_summed, csum, and other +fields set from previous fragment handling. + +Some network drivers set skb->ip_summed to either CHECKSUM_COMPLETE or +CHECKSUM_UNNECESSARY when getting skb from napi_get_frags(), while +others only set skb->ip_summed when RX checksum offload is enabled on +the device, and do not set any value for skb->ip_summed when hardware +checksum offload is disabled, assuming that the skb->ip_summed +initiated to zero by napi_reuse_skb, ionic driver for example will +ignore/unset any value for the ip_summed filed if HW checksum offload is +disabled, and if we have a situation where the user disables the +checksum offload during a traffic that could lead to the following +errors shown in the kernel logs: + +dump_stack_lvl+0x34/0x48 + __skb_gro_checksum_complete+0x7e/0x90 +tcp6_gro_receive+0xc6/0x190 +ipv6_gro_receive+0x1ec/0x430 +dev_gro_receive+0x188/0x360 +? ionic_rx_clean+0x25a/0x460 [ionic] +napi_gro_frags+0x13c/0x300 +? __pfx_ionic_rx_service+0x10/0x10 [ionic] +ionic_rx_service+0x67/0x80 [ionic] +ionic_cq_service+0x58/0x90 [ionic] +ionic_txrx_napi+0x64/0x1b0 [ionic] + __napi_poll+0x27/0x170 +net_rx_action+0x29c/0x370 +handle_softirqs+0xce/0x270 +__irq_exit_rcu+0xa3/0xc0 +common_interrupt+0x80/0xa0 + + +This inconsistency sometimes leads to checksum validation issues in the +upper layers of the network stack. + +To resolve this, this patch clears the skb->ip_summed value for each +reused skb in by napi_reuse_skb(), ensuring that the caller is responsible +for setting the correct checksum status. This eliminates potential +checksum validation issues caused by improper handling of +skb->ip_summed. + +Fixes: 76620aafd66f ("gro: New frags interface to avoid copying shinfo") +Signed-off-by: Mohammad Heib +Reviewed-by: Shannon Nelson +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20250225112852.2507709-1-mheib@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/gro.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/core/gro.c b/net/core/gro.c +index 85d3f686ba539..397cf59842503 100644 +--- a/net/core/gro.c ++++ b/net/core/gro.c +@@ -627,6 +627,7 @@ static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) + skb->pkt_type = PACKET_HOST; + + skb->encapsulation = 0; ++ skb->ip_summed = CHECKSUM_NONE; + skb_shinfo(skb)->gso_type = 0; + skb_shinfo(skb)->gso_size = 0; + if (unlikely(skb->slow_gro)) { +-- +2.39.5 + diff --git a/queue-6.6/net-ipv4-add-tracepoint-for-icmp_send.patch b/queue-6.6/net-ipv4-add-tracepoint-for-icmp_send.patch new file mode 100644 index 0000000000..7f1654bd0b --- /dev/null +++ b/queue-6.6/net-ipv4-add-tracepoint-for-icmp_send.patch @@ -0,0 +1,153 @@ +From 5f7e86e0c0f27b236744e76c0401105ea5c909e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 May 2024 15:41:03 +0800 +Subject: net/ipv4: add tracepoint for icmp_send + +From: Peilin He + +[ Upstream commit db3efdcf70c752e8a8deb16071d8e693c3ef8746 ] + +Introduce a tracepoint for icmp_send, which can help users to get more +detail information conveniently when icmp abnormal events happen. + +1. Giving an usecase example: +============================= +When an application experiences packet loss due to an unreachable UDP +destination port, the kernel will send an exception message through the +icmp_send function. By adding a trace point for icmp_send, developers or +system administrators can obtain detailed information about the UDP +packet loss, including the type, code, source address, destination address, +source port, and destination port. This facilitates the trouble-shooting +of UDP packet loss issues especially for those network-service +applications. + +2. Operation Instructions: +========================== +Switch to the tracing directory. + cd /sys/kernel/tracing +Filter for destination port unreachable. + echo "type==3 && code==3" > events/icmp/icmp_send/filter +Enable trace event. + echo 1 > events/icmp/icmp_send/enable + +3. Result View: +================ + udp_client_erro-11370 [002] ...s.12 124.728002: + icmp_send: icmp_send: type=3, code=3. + From 127.0.0.1:41895 to 127.0.0.1:6666 ulen=23 + skbaddr=00000000589b167a + +Signed-off-by: Peilin He +Signed-off-by: xu xin +Reviewed-by: Yunkai Zhang +Cc: Yang Yang +Cc: Liu Chun +Cc: Xuexin Jiang +Reviewed-by: Steven Rostedt (Google) +Signed-off-by: David S. Miller +Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part") +Signed-off-by: Sasha Levin +--- + include/trace/events/icmp.h | 67 +++++++++++++++++++++++++++++++++++++ + net/ipv4/icmp.c | 4 +++ + 2 files changed, 71 insertions(+) + create mode 100644 include/trace/events/icmp.h + +diff --git a/include/trace/events/icmp.h b/include/trace/events/icmp.h +new file mode 100644 +index 0000000000000..31559796949a7 +--- /dev/null ++++ b/include/trace/events/icmp.h +@@ -0,0 +1,67 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM icmp ++ ++#if !defined(_TRACE_ICMP_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_ICMP_H ++ ++#include ++#include ++ ++TRACE_EVENT(icmp_send, ++ ++ TP_PROTO(const struct sk_buff *skb, int type, int code), ++ ++ TP_ARGS(skb, type, code), ++ ++ TP_STRUCT__entry( ++ __field(const void *, skbaddr) ++ __field(int, type) ++ __field(int, code) ++ __array(__u8, saddr, 4) ++ __array(__u8, daddr, 4) ++ __field(__u16, sport) ++ __field(__u16, dport) ++ __field(unsigned short, ulen) ++ ), ++ ++ TP_fast_assign( ++ struct iphdr *iph = ip_hdr(skb); ++ struct udphdr *uh = udp_hdr(skb); ++ int proto_4 = iph->protocol; ++ __be32 *p32; ++ ++ __entry->skbaddr = skb; ++ __entry->type = type; ++ __entry->code = code; ++ ++ if (proto_4 != IPPROTO_UDP || (u8 *)uh < skb->head || ++ (u8 *)uh + sizeof(struct udphdr) ++ > skb_tail_pointer(skb)) { ++ __entry->sport = 0; ++ __entry->dport = 0; ++ __entry->ulen = 0; ++ } else { ++ __entry->sport = ntohs(uh->source); ++ __entry->dport = ntohs(uh->dest); ++ __entry->ulen = ntohs(uh->len); ++ } ++ ++ p32 = (__be32 *) __entry->saddr; ++ *p32 = iph->saddr; ++ ++ p32 = (__be32 *) __entry->daddr; ++ *p32 = iph->daddr; ++ ), ++ ++ TP_printk("icmp_send: type=%d, code=%d. From %pI4:%u to %pI4:%u ulen=%d skbaddr=%p", ++ __entry->type, __entry->code, ++ __entry->saddr, __entry->sport, __entry->daddr, ++ __entry->dport, __entry->ulen, __entry->skbaddr) ++); ++ ++#endif /* _TRACE_ICMP_H */ ++ ++/* This part must be outside protection */ ++#include ++ +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index a21d32b3ae6c3..b05fa424ad5ce 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -93,6 +93,8 @@ + #include + #include + #include ++#define CREATE_TRACE_POINTS ++#include + + /* + * Build xmit assembly blocks +@@ -778,6 +780,8 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info, + if (!fl4.saddr) + fl4.saddr = htonl(INADDR_DUMMY); + ++ trace_icmp_send(skb_in, type, code); ++ + icmp_push_reply(sk, &icmp_param, &fl4, &ipc, &rt); + ende: + ip_rt_put(rt); +-- +2.39.5 + diff --git a/queue-6.6/net-ipv6-fix-dst-ref-loop-on-input-in-rpl-lwt.patch b/queue-6.6/net-ipv6-fix-dst-ref-loop-on-input-in-rpl-lwt.patch new file mode 100644 index 0000000000..d674bf4280 --- /dev/null +++ b/queue-6.6/net-ipv6-fix-dst-ref-loop-on-input-in-rpl-lwt.patch @@ -0,0 +1,60 @@ +From 9c46ffddb63eb47b2d722b5b31ed57b2af8cd686 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 18:51:39 +0100 +Subject: net: ipv6: fix dst ref loop on input in rpl lwt + +From: Justin Iurman + +[ Upstream commit 13e55fbaec176119cff68a7e1693b251c8883c5f ] + +Prevent a dst ref loop on input in rpl_iptunnel. + +Fixes: a7a29f9c361f ("net: ipv6: add rpl sr tunnel") +Cc: Alexander Aring +Cc: Ido Schimmel +Reviewed-by: Ido Schimmel +Signed-off-by: Justin Iurman +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv6/rpl_iptunnel.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/net/ipv6/rpl_iptunnel.c b/net/ipv6/rpl_iptunnel.c +index 7ba22d2f2bfef..28fc7fae57972 100644 +--- a/net/ipv6/rpl_iptunnel.c ++++ b/net/ipv6/rpl_iptunnel.c +@@ -259,10 +259,18 @@ static int rpl_input(struct sk_buff *skb) + { + struct dst_entry *orig_dst = skb_dst(skb); + struct dst_entry *dst = NULL; ++ struct lwtunnel_state *lwtst; + struct rpl_lwt *rlwt; + int err; + +- rlwt = rpl_lwt_lwtunnel(orig_dst->lwtstate); ++ /* We cannot dereference "orig_dst" once ip6_route_input() or ++ * skb_dst_drop() is called. However, in order to detect a dst loop, we ++ * need the address of its lwtstate. So, save the address of lwtstate ++ * now and use it later as a comparison. ++ */ ++ lwtst = orig_dst->lwtstate; ++ ++ rlwt = rpl_lwt_lwtunnel(lwtst); + + local_bh_disable(); + dst = dst_cache_get(&rlwt->cache); +@@ -275,7 +283,9 @@ static int rpl_input(struct sk_buff *skb) + if (!dst) { + ip6_route_input(skb); + dst = skb_dst(skb); +- if (!dst->error) { ++ ++ /* cache only if we don't create a dst reference loop */ ++ if (!dst->error && lwtst != dst->lwtstate) { + local_bh_disable(); + dst_cache_set_ip6(&rlwt->cache, dst, + &ipv6_hdr(skb)->saddr); +-- +2.39.5 + diff --git a/queue-6.6/net-ipv6-fix-dst-ref-loop-on-input-in-seg6-lwt.patch b/queue-6.6/net-ipv6-fix-dst-ref-loop-on-input-in-seg6-lwt.patch new file mode 100644 index 0000000000..1e3682e753 --- /dev/null +++ b/queue-6.6/net-ipv6-fix-dst-ref-loop-on-input-in-seg6-lwt.patch @@ -0,0 +1,60 @@ +From b937bba0778e423c4daee8b997d8aac0abcdcfa0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 18:51:38 +0100 +Subject: net: ipv6: fix dst ref loop on input in seg6 lwt + +From: Justin Iurman + +[ Upstream commit c64a0727f9b1cbc63a5538c8c0014e9a175ad864 ] + +Prevent a dst ref loop on input in seg6_iptunnel. + +Fixes: af4a2209b134 ("ipv6: sr: use dst_cache in seg6_input") +Cc: David Lebrun +Cc: Ido Schimmel +Reviewed-by: Ido Schimmel +Signed-off-by: Justin Iurman +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv6/seg6_iptunnel.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c +index 4bf937bfc2633..c44e4c0824e0d 100644 +--- a/net/ipv6/seg6_iptunnel.c ++++ b/net/ipv6/seg6_iptunnel.c +@@ -472,10 +472,18 @@ static int seg6_input_core(struct net *net, struct sock *sk, + { + struct dst_entry *orig_dst = skb_dst(skb); + struct dst_entry *dst = NULL; ++ struct lwtunnel_state *lwtst; + struct seg6_lwt *slwt; + int err; + +- slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); ++ /* We cannot dereference "orig_dst" once ip6_route_input() or ++ * skb_dst_drop() is called. However, in order to detect a dst loop, we ++ * need the address of its lwtstate. So, save the address of lwtstate ++ * now and use it later as a comparison. ++ */ ++ lwtst = orig_dst->lwtstate; ++ ++ slwt = seg6_lwt_lwtunnel(lwtst); + + local_bh_disable(); + dst = dst_cache_get(&slwt->cache); +@@ -488,7 +496,9 @@ static int seg6_input_core(struct net *net, struct sock *sk, + if (!dst) { + ip6_route_input(skb); + dst = skb_dst(skb); +- if (!dst->error) { ++ ++ /* cache only if we don't create a dst reference loop */ ++ if (!dst->error && lwtst != dst->lwtstate) { + local_bh_disable(); + dst_cache_set_ip6(&slwt->cache, dst, + &ipv6_hdr(skb)->saddr); +-- +2.39.5 + diff --git a/queue-6.6/net-ipv6-rpl_iptunnel-mitigate-2-realloc-issue.patch b/queue-6.6/net-ipv6-rpl_iptunnel-mitigate-2-realloc-issue.patch new file mode 100644 index 0000000000..c696fed8cf --- /dev/null +++ b/queue-6.6/net-ipv6-rpl_iptunnel-mitigate-2-realloc-issue.patch @@ -0,0 +1,154 @@ +From ce7db97ce7d371c3d7767ccbe7a7343eee5bce92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 13:49:45 +0100 +Subject: net: ipv6: rpl_iptunnel: mitigate 2-realloc issue + +From: Justin Iurman + +[ Upstream commit 985ec6f5e6235242191370628acb73d7a9f0c0ea ] + +This patch mitigates the two-reallocations issue with rpl_iptunnel by +providing the dst_entry (in the cache) to the first call to +skb_cow_head(). As a result, the very first iteration would still +trigger two reallocations (i.e., empty cache), while next iterations +would only trigger a single reallocation. + +Performance tests before/after applying this patch, which clearly shows +there is no impact (it even shows improvement): +- before: https://ibb.co/nQJhqwc +- after: https://ibb.co/4ZvW6wV + +Signed-off-by: Justin Iurman +Cc: Alexander Aring +Signed-off-by: Paolo Abeni +Stable-dep-of: 13e55fbaec17 ("net: ipv6: fix dst ref loop on input in rpl lwt") +Signed-off-by: Sasha Levin +--- + net/ipv6/rpl_iptunnel.c | 46 ++++++++++++++++++++++------------------- + 1 file changed, 25 insertions(+), 21 deletions(-) + +diff --git a/net/ipv6/rpl_iptunnel.c b/net/ipv6/rpl_iptunnel.c +index db3c19a42e1ca..7ba22d2f2bfef 100644 +--- a/net/ipv6/rpl_iptunnel.c ++++ b/net/ipv6/rpl_iptunnel.c +@@ -125,7 +125,8 @@ static void rpl_destroy_state(struct lwtunnel_state *lwt) + } + + static int rpl_do_srh_inline(struct sk_buff *skb, const struct rpl_lwt *rlwt, +- const struct ipv6_rpl_sr_hdr *srh) ++ const struct ipv6_rpl_sr_hdr *srh, ++ struct dst_entry *cache_dst) + { + struct ipv6_rpl_sr_hdr *isrh, *csrh; + const struct ipv6hdr *oldhdr; +@@ -153,7 +154,7 @@ static int rpl_do_srh_inline(struct sk_buff *skb, const struct rpl_lwt *rlwt, + + hdrlen = ((csrh->hdrlen + 1) << 3); + +- err = skb_cow_head(skb, hdrlen + skb->mac_len); ++ err = skb_cow_head(skb, hdrlen + dst_dev_overhead(cache_dst, skb)); + if (unlikely(err)) { + kfree(buf); + return err; +@@ -186,7 +187,8 @@ static int rpl_do_srh_inline(struct sk_buff *skb, const struct rpl_lwt *rlwt, + return 0; + } + +-static int rpl_do_srh(struct sk_buff *skb, const struct rpl_lwt *rlwt) ++static int rpl_do_srh(struct sk_buff *skb, const struct rpl_lwt *rlwt, ++ struct dst_entry *cache_dst) + { + struct dst_entry *dst = skb_dst(skb); + struct rpl_iptunnel_encap *tinfo; +@@ -196,7 +198,7 @@ static int rpl_do_srh(struct sk_buff *skb, const struct rpl_lwt *rlwt) + + tinfo = rpl_encap_lwtunnel(dst->lwtstate); + +- return rpl_do_srh_inline(skb, rlwt, tinfo->srh); ++ return rpl_do_srh_inline(skb, rlwt, tinfo->srh, cache_dst); + } + + static int rpl_output(struct net *net, struct sock *sk, struct sk_buff *skb) +@@ -208,14 +210,14 @@ static int rpl_output(struct net *net, struct sock *sk, struct sk_buff *skb) + + rlwt = rpl_lwt_lwtunnel(orig_dst->lwtstate); + +- err = rpl_do_srh(skb, rlwt); +- if (unlikely(err)) +- goto drop; +- + local_bh_disable(); + dst = dst_cache_get(&rlwt->cache); + local_bh_enable(); + ++ err = rpl_do_srh(skb, rlwt, dst); ++ if (unlikely(err)) ++ goto drop; ++ + if (unlikely(!dst)) { + struct ipv6hdr *hdr = ipv6_hdr(skb); + struct flowi6 fl6; +@@ -237,15 +239,15 @@ static int rpl_output(struct net *net, struct sock *sk, struct sk_buff *skb) + local_bh_disable(); + dst_cache_set_ip6(&rlwt->cache, dst, &fl6.saddr); + local_bh_enable(); ++ ++ err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); ++ if (unlikely(err)) ++ goto drop; + } + + skb_dst_drop(skb); + skb_dst_set(skb, dst); + +- err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); +- if (unlikely(err)) +- goto drop; +- + return dst_output(net, sk, skb); + + drop: +@@ -262,29 +264,31 @@ static int rpl_input(struct sk_buff *skb) + + rlwt = rpl_lwt_lwtunnel(orig_dst->lwtstate); + +- err = rpl_do_srh(skb, rlwt); +- if (unlikely(err)) +- goto drop; +- + local_bh_disable(); + dst = dst_cache_get(&rlwt->cache); ++ local_bh_enable(); ++ ++ err = rpl_do_srh(skb, rlwt, dst); ++ if (unlikely(err)) ++ goto drop; + + if (!dst) { + ip6_route_input(skb); + dst = skb_dst(skb); + if (!dst->error) { ++ local_bh_disable(); + dst_cache_set_ip6(&rlwt->cache, dst, + &ipv6_hdr(skb)->saddr); ++ local_bh_enable(); + } ++ ++ err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); ++ if (unlikely(err)) ++ goto drop; + } else { + skb_dst_drop(skb); + skb_dst_set(skb, dst); + } +- local_bh_enable(); +- +- err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); +- if (unlikely(err)) +- goto drop; + + return dst_input(skb); + +-- +2.39.5 + diff --git a/queue-6.6/net-ipv6-seg6_iptunnel-mitigate-2-realloc-issue.patch b/queue-6.6/net-ipv6-seg6_iptunnel-mitigate-2-realloc-issue.patch new file mode 100644 index 0000000000..137bb159fb --- /dev/null +++ b/queue-6.6/net-ipv6-seg6_iptunnel-mitigate-2-realloc-issue.patch @@ -0,0 +1,254 @@ +From 5cf013750e0269b639809878907516dc15ee6437 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Dec 2024 13:49:44 +0100 +Subject: net: ipv6: seg6_iptunnel: mitigate 2-realloc issue + +From: Justin Iurman + +[ Upstream commit 40475b63761abb6f8fdef960d03228a08662c9c4 ] + +This patch mitigates the two-reallocations issue with seg6_iptunnel by +providing the dst_entry (in the cache) to the first call to +skb_cow_head(). As a result, the very first iteration would still +trigger two reallocations (i.e., empty cache), while next iterations +would only trigger a single reallocation. + +Performance tests before/after applying this patch, which clearly shows +the improvement: +- before: https://ibb.co/3Cg4sNH +- after: https://ibb.co/8rQ350r + +Signed-off-by: Justin Iurman +Cc: David Lebrun +Signed-off-by: Paolo Abeni +Stable-dep-of: c64a0727f9b1 ("net: ipv6: fix dst ref loop on input in seg6 lwt") +Signed-off-by: Sasha Levin +--- + net/ipv6/seg6_iptunnel.c | 85 ++++++++++++++++++++++++---------------- + 1 file changed, 52 insertions(+), 33 deletions(-) + +diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c +index 098632adc9b5a..4bf937bfc2633 100644 +--- a/net/ipv6/seg6_iptunnel.c ++++ b/net/ipv6/seg6_iptunnel.c +@@ -124,8 +124,8 @@ static __be32 seg6_make_flowlabel(struct net *net, struct sk_buff *skb, + return flowlabel; + } + +-/* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */ +-int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) ++static int __seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, ++ int proto, struct dst_entry *cache_dst) + { + struct dst_entry *dst = skb_dst(skb); + struct net *net = dev_net(dst->dev); +@@ -137,7 +137,7 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) + hdrlen = (osrh->hdrlen + 1) << 3; + tot_len = hdrlen + sizeof(*hdr); + +- err = skb_cow_head(skb, tot_len + skb->mac_len); ++ err = skb_cow_head(skb, tot_len + dst_dev_overhead(cache_dst, skb)); + if (unlikely(err)) + return err; + +@@ -197,11 +197,18 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) + + return 0; + } ++ ++/* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */ ++int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) ++{ ++ return __seg6_do_srh_encap(skb, osrh, proto, NULL); ++} + EXPORT_SYMBOL_GPL(seg6_do_srh_encap); + + /* encapsulate an IPv6 packet within an outer IPv6 header with reduced SRH */ + static int seg6_do_srh_encap_red(struct sk_buff *skb, +- struct ipv6_sr_hdr *osrh, int proto) ++ struct ipv6_sr_hdr *osrh, int proto, ++ struct dst_entry *cache_dst) + { + __u8 first_seg = osrh->first_segment; + struct dst_entry *dst = skb_dst(skb); +@@ -230,7 +237,7 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb, + + tot_len = red_hdrlen + sizeof(struct ipv6hdr); + +- err = skb_cow_head(skb, tot_len + skb->mac_len); ++ err = skb_cow_head(skb, tot_len + dst_dev_overhead(cache_dst, skb)); + if (unlikely(err)) + return err; + +@@ -317,8 +324,8 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb, + return 0; + } + +-/* insert an SRH within an IPv6 packet, just after the IPv6 header */ +-int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh) ++static int __seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, ++ struct dst_entry *cache_dst) + { + struct ipv6hdr *hdr, *oldhdr; + struct ipv6_sr_hdr *isrh; +@@ -326,7 +333,7 @@ int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh) + + hdrlen = (osrh->hdrlen + 1) << 3; + +- err = skb_cow_head(skb, hdrlen + skb->mac_len); ++ err = skb_cow_head(skb, hdrlen + dst_dev_overhead(cache_dst, skb)); + if (unlikely(err)) + return err; + +@@ -369,9 +376,8 @@ int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh) + + return 0; + } +-EXPORT_SYMBOL_GPL(seg6_do_srh_inline); + +-static int seg6_do_srh(struct sk_buff *skb) ++static int seg6_do_srh(struct sk_buff *skb, struct dst_entry *cache_dst) + { + struct dst_entry *dst = skb_dst(skb); + struct seg6_iptunnel_encap *tinfo; +@@ -384,7 +390,7 @@ static int seg6_do_srh(struct sk_buff *skb) + if (skb->protocol != htons(ETH_P_IPV6)) + return -EINVAL; + +- err = seg6_do_srh_inline(skb, tinfo->srh); ++ err = __seg6_do_srh_inline(skb, tinfo->srh, cache_dst); + if (err) + return err; + break; +@@ -402,9 +408,11 @@ static int seg6_do_srh(struct sk_buff *skb) + return -EINVAL; + + if (tinfo->mode == SEG6_IPTUN_MODE_ENCAP) +- err = seg6_do_srh_encap(skb, tinfo->srh, proto); ++ err = __seg6_do_srh_encap(skb, tinfo->srh, ++ proto, cache_dst); + else +- err = seg6_do_srh_encap_red(skb, tinfo->srh, proto); ++ err = seg6_do_srh_encap_red(skb, tinfo->srh, ++ proto, cache_dst); + + if (err) + return err; +@@ -425,11 +433,13 @@ static int seg6_do_srh(struct sk_buff *skb) + skb_push(skb, skb->mac_len); + + if (tinfo->mode == SEG6_IPTUN_MODE_L2ENCAP) +- err = seg6_do_srh_encap(skb, tinfo->srh, +- IPPROTO_ETHERNET); ++ err = __seg6_do_srh_encap(skb, tinfo->srh, ++ IPPROTO_ETHERNET, ++ cache_dst); + else + err = seg6_do_srh_encap_red(skb, tinfo->srh, +- IPPROTO_ETHERNET); ++ IPPROTO_ETHERNET, ++ cache_dst); + + if (err) + return err; +@@ -444,6 +454,13 @@ static int seg6_do_srh(struct sk_buff *skb) + return 0; + } + ++/* insert an SRH within an IPv6 packet, just after the IPv6 header */ ++int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh) ++{ ++ return __seg6_do_srh_inline(skb, osrh, NULL); ++} ++EXPORT_SYMBOL_GPL(seg6_do_srh_inline); ++ + static int seg6_input_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) + { +@@ -458,31 +475,33 @@ static int seg6_input_core(struct net *net, struct sock *sk, + struct seg6_lwt *slwt; + int err; + +- err = seg6_do_srh(skb); +- if (unlikely(err)) +- goto drop; +- + slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); + + local_bh_disable(); + dst = dst_cache_get(&slwt->cache); ++ local_bh_enable(); ++ ++ err = seg6_do_srh(skb, dst); ++ if (unlikely(err)) ++ goto drop; + + if (!dst) { + ip6_route_input(skb); + dst = skb_dst(skb); + if (!dst->error) { ++ local_bh_disable(); + dst_cache_set_ip6(&slwt->cache, dst, + &ipv6_hdr(skb)->saddr); ++ local_bh_enable(); + } ++ ++ err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); ++ if (unlikely(err)) ++ goto drop; + } else { + skb_dst_drop(skb); + skb_dst_set(skb, dst); + } +- local_bh_enable(); +- +- err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); +- if (unlikely(err)) +- goto drop; + + if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) + return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, +@@ -528,16 +547,16 @@ static int seg6_output_core(struct net *net, struct sock *sk, + struct seg6_lwt *slwt; + int err; + +- err = seg6_do_srh(skb); +- if (unlikely(err)) +- goto drop; +- + slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); + + local_bh_disable(); + dst = dst_cache_get(&slwt->cache); + local_bh_enable(); + ++ err = seg6_do_srh(skb, dst); ++ if (unlikely(err)) ++ goto drop; ++ + if (unlikely(!dst)) { + struct ipv6hdr *hdr = ipv6_hdr(skb); + struct flowi6 fl6; +@@ -559,15 +578,15 @@ static int seg6_output_core(struct net *net, struct sock *sk, + local_bh_disable(); + dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr); + local_bh_enable(); ++ ++ err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); ++ if (unlikely(err)) ++ goto drop; + } + + skb_dst_drop(skb); + skb_dst_set(skb, dst); + +- err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); +- if (unlikely(err)) +- goto drop; +- + if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) + return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, + NULL, skb_dst(skb)->dev, dst_output); +-- +2.39.5 + diff --git a/queue-6.6/net-loopback-avoid-sending-ip-packets-without-an-eth.patch b/queue-6.6/net-loopback-avoid-sending-ip-packets-without-an-eth.patch new file mode 100644 index 0000000000..2b73edd15c --- /dev/null +++ b/queue-6.6/net-loopback-avoid-sending-ip-packets-without-an-eth.patch @@ -0,0 +1,94 @@ +From ab606c5963fded70ebf0bb12963a54d7e4170957 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 09:25:59 +0200 +Subject: net: loopback: Avoid sending IP packets without an Ethernet header + +From: Ido Schimmel + +[ Upstream commit 0e4427f8f587c4b603475468bb3aee9418574893 ] + +After commit 22600596b675 ("ipv4: give an IPv4 dev to blackhole_netdev") +IPv4 neighbors can be constructed on the blackhole net device, but they +are constructed with an output function (neigh_direct_output()) that +simply calls dev_queue_xmit(). The latter will transmit packets via +'skb->dev' which might not be the blackhole net device if dst_dev_put() +switched 'dst->dev' to the blackhole net device while another CPU was +using the dst entry in ip_output(), but after it already initialized +'skb->dev' from 'dst->dev'. + +Specifically, the following can happen: + + CPU1 CPU2 + +udp_sendmsg(sk1) udp_sendmsg(sk2) +udp_send_skb() [...] +ip_output() + skb->dev = skb_dst(skb)->dev + dst_dev_put() + dst->dev = blackhole_netdev +ip_finish_output2() + resolves neigh on dst->dev +neigh_output() +neigh_direct_output() +dev_queue_xmit() + +This will result in IPv4 packets being sent without an Ethernet header +via a valid net device: + +tcpdump: verbose output suppressed, use -v[v]... for full protocol decode +listening on enp9s0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +22:07:02.329668 20:00:40:11:18:fb > 45:00:00:44:f4:94, ethertype Unknown +(0x58c6), length 68: + 0x0000: 8dda 74ca f1ae ca6c ca6c 0098 969c 0400 ..t....l.l...... + 0x0010: 0000 4730 3f18 6800 0000 0000 0000 9971 ..G0?.h........q + 0x0020: c4c9 9055 a157 0a70 9ead bf83 38ca ab38 ...U.W.p....8..8 + 0x0030: 8add ab96 e052 .....R + +Fix by making sure that neighbors are constructed on top of the +blackhole net device with an output function that simply consumes the +packets, in a similar fashion to dst_discard_out() and +blackhole_netdev_xmit(). + +Fixes: 8d7017fd621d ("blackhole_netdev: use blackhole_netdev to invalidate dst entries") +Fixes: 22600596b675 ("ipv4: give an IPv4 dev to blackhole_netdev") +Reported-by: Florian Meister +Closes: https://lore.kernel.org/netdev/20250210084931.23a5c2e4@hermes.local/ +Signed-off-by: Ido Schimmel +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20250220072559.782296-1-idosch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/loopback.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c +index f6eab66c26608..6aa00f62b1f90 100644 +--- a/drivers/net/loopback.c ++++ b/drivers/net/loopback.c +@@ -247,8 +247,22 @@ static netdev_tx_t blackhole_netdev_xmit(struct sk_buff *skb, + return NETDEV_TX_OK; + } + ++static int blackhole_neigh_output(struct neighbour *n, struct sk_buff *skb) ++{ ++ kfree_skb(skb); ++ return 0; ++} ++ ++static int blackhole_neigh_construct(struct net_device *dev, ++ struct neighbour *n) ++{ ++ n->output = blackhole_neigh_output; ++ return 0; ++} ++ + static const struct net_device_ops blackhole_netdev_ops = { + .ndo_start_xmit = blackhole_netdev_xmit, ++ .ndo_neigh_construct = blackhole_neigh_construct, + }; + + /* This is a dst-dummy device used specifically for invalidated +-- +2.39.5 + diff --git a/queue-6.6/net-mlx5-irq-fix-null-string-in-debug-print.patch b/queue-6.6/net-mlx5-irq-fix-null-string-in-debug-print.patch new file mode 100644 index 0000000000..02ec932d5f --- /dev/null +++ b/queue-6.6/net-mlx5-irq-fix-null-string-in-debug-print.patch @@ -0,0 +1,42 @@ +From afbd4a5c9962dca295601d731e1184b2654a8fe0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 09:26:08 +0200 +Subject: net/mlx5: IRQ, Fix null string in debug print + +From: Shay Drory + +[ Upstream commit 2f5a6014eb168a97b24153adccfa663d3b282767 ] + +irq_pool_alloc() debug print can print a null string. +Fix it by providing a default string to print. + +Fixes: 71e084e26414 ("net/mlx5: Allocating a pool of MSI-X vectors for SFs") +Signed-off-by: Shay Drory +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202501141055.SwfIphN0-lkp@intel.com/ +Reviewed-by: Moshe Shemesh +Signed-off-by: Tariq Toukan +Reviewed-by: Kalesh AP +Link: https://patch.msgid.link/20250225072608.526866-4-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +index 6bac8ad70ba60..a8d6fd18c0f55 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +@@ -617,7 +617,7 @@ irq_pool_alloc(struct mlx5_core_dev *dev, int start, int size, char *name, + pool->min_threshold = min_threshold * MLX5_EQ_REFS_PER_IRQ; + pool->max_threshold = max_threshold * MLX5_EQ_REFS_PER_IRQ; + mlx5_core_dbg(dev, "pool->name = %s, pool->size = %d, pool->start = %d", +- name, size, start); ++ name ? name : "mlx5_pcif_pool", size, start); + return pool; + } + +-- +2.39.5 + diff --git a/queue-6.6/net-mvpp2-cls-fixed-non-ip-flow-with-vlan-tag-flow-d.patch b/queue-6.6/net-mvpp2-cls-fixed-non-ip-flow-with-vlan-tag-flow-d.patch new file mode 100644 index 0000000000..d632bf7061 --- /dev/null +++ b/queue-6.6/net-mvpp2-cls-fixed-non-ip-flow-with-vlan-tag-flow-d.patch @@ -0,0 +1,40 @@ +From ad6bcf9b993035f093748d8ed276f2d4d2b5f9a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 20:20:58 -0800 +Subject: net: mvpp2: cls: Fixed Non IP flow, with vlan tag flow defination. + +From: Harshal Chaudhari + +[ Upstream commit 2d253726ff7106b39a44483b6864398bba8a2f74 ] + +Non IP flow, with vlan tag not working as expected while +running below command for vlan-priority. fixed that. + +ethtool -N eth1 flow-type ether vlan 0x8000 vlan-mask 0x1fff action 0 loc 0 + +Fixes: 1274daede3ef ("net: mvpp2: cls: Add steering based on vlan Id and priority.") +Signed-off-by: Harshal Chaudhari +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20250225042058.2643838-1-hchaudhari@marvell.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c +index 40aeaa7bd739f..d2757cc116139 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c +@@ -324,7 +324,7 @@ static const struct mvpp2_cls_flow cls_flows[MVPP2_N_PRS_FLOWS] = { + MVPP2_PRS_RI_VLAN_MASK), + /* Non IP flow, with vlan tag */ + MVPP2_DEF_FLOW(MVPP22_FLOW_ETHERNET, MVPP2_FL_NON_IP_TAG, +- MVPP22_CLS_HEK_OPT_VLAN, ++ MVPP22_CLS_HEK_TAGGED, + 0, 0), + }; + +-- +2.39.5 + diff --git a/queue-6.6/net-set-the-minimum-for-net_hotdata.netdev_budget_us.patch b/queue-6.6/net-set-the-minimum-for-net_hotdata.netdev_budget_us.patch new file mode 100644 index 0000000000..14cc5abfd7 --- /dev/null +++ b/queue-6.6/net-set-the-minimum-for-net_hotdata.netdev_budget_us.patch @@ -0,0 +1,58 @@ +From 115bdcc50be9811c84bd518d9e66ca382aa05389 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 12:07:52 +0100 +Subject: net: set the minimum for net_hotdata.netdev_budget_usecs + +From: Jiri Slaby (SUSE) + +[ Upstream commit c180188ec02281126045414e90d08422a80f75b4 ] + +Commit 7acf8a1e8a28 ("Replace 2 jiffies with sysctl netdev_budget_usecs +to enable softirq tuning") added a possibility to set +net_hotdata.netdev_budget_usecs, but added no lower bound checking. + +Commit a4837980fd9f ("net: revert default NAPI poll timeout to 2 jiffies") +made the *initial* value HZ-dependent, so the initial value is at least +2 jiffies even for lower HZ values (2 ms for 1000 Hz, 8ms for 250 Hz, 20 +ms for 100 Hz). + +But a user still can set improper values by a sysctl. Set .extra1 +(the lower bound) for net_hotdata.netdev_budget_usecs to the same value +as in the latter commit. That is to 2 jiffies. + +Fixes: a4837980fd9f ("net: revert default NAPI poll timeout to 2 jiffies") +Fixes: 7acf8a1e8a28 ("Replace 2 jiffies with sysctl netdev_budget_usecs to enable softirq tuning") +Signed-off-by: Jiri Slaby (SUSE) +Cc: Dmitry Yakunin +Cc: Konstantin Khlebnikov +Link: https://patch.msgid.link/20250220110752.137639-1-jirislaby@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/sysctl_net_core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c +index 0b15272dd2d35..a7fa17b6a1297 100644 +--- a/net/core/sysctl_net_core.c ++++ b/net/core/sysctl_net_core.c +@@ -31,6 +31,7 @@ static int min_sndbuf = SOCK_MIN_SNDBUF; + static int min_rcvbuf = SOCK_MIN_RCVBUF; + static int max_skb_frags = MAX_SKB_FRAGS; + static int min_mem_pcpu_rsv = SK_MEMORY_PCPU_RESERVE; ++static int netdev_budget_usecs_min = 2 * USEC_PER_SEC / HZ; + + static int net_msg_warn; /* Unused, but still a sysctl */ + +@@ -613,7 +614,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = SYSCTL_ZERO, ++ .extra1 = &netdev_budget_usecs_min, + }, + { + .procname = "fb_tunnels_only_for_init_net", +-- +2.39.5 + diff --git a/queue-6.6/net-ti-icss-iep-reject-perout-generation-request.patch b/queue-6.6/net-ti-icss-iep-reject-perout-generation-request.patch new file mode 100644 index 0000000000..77ba400655 --- /dev/null +++ b/queue-6.6/net-ti-icss-iep-reject-perout-generation-request.patch @@ -0,0 +1,60 @@ +From 6ace75c851b68e50bd7b15a4dd78635dd8e45060 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 14:54:41 +0530 +Subject: net: ti: icss-iep: Reject perout generation request + +From: Meghana Malladi + +[ Upstream commit 54e1b4becf5e220be03db4e1be773c1310e8cbbd ] + +IEP driver supports both perout and pps signal generation +but perout feature is faulty with half-cooked support +due to some missing configuration. Remove perout +support from the driver and reject perout requests with +"not supported" error code. + +Fixes: c1e0230eeaab2 ("net: ti: icss-iep: Add IEP driver") +Signed-off-by: Meghana Malladi +Reviewed-by: Vadim Fedorenko +Link: https://patch.msgid.link/20250227092441.1848419-1-m-malladi@ti.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/icssg/icss_iep.c | 21 +-------------------- + 1 file changed, 1 insertion(+), 20 deletions(-) + +diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c +index b491d89de8fb2..3f9a030471fe2 100644 +--- a/drivers/net/ethernet/ti/icssg/icss_iep.c ++++ b/drivers/net/ethernet/ti/icssg/icss_iep.c +@@ -544,26 +544,7 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep, + static int icss_iep_perout_enable(struct icss_iep *iep, + struct ptp_perout_request *req, int on) + { +- int ret = 0; +- +- mutex_lock(&iep->ptp_clk_mutex); +- +- if (iep->pps_enabled) { +- ret = -EBUSY; +- goto exit; +- } +- +- if (iep->perout_enabled == !!on) +- goto exit; +- +- ret = icss_iep_perout_enable_hw(iep, req, on); +- if (!ret) +- iep->perout_enabled = !!on; +- +-exit: +- mutex_unlock(&iep->ptp_clk_mutex); +- +- return ret; ++ return -EOPNOTSUPP; + } + + static int icss_iep_pps_enable(struct icss_iep *iep, int on) +-- +2.39.5 + diff --git a/queue-6.6/net-ti-icss-iep-remove-spinlock-based-synchronizatio.patch b/queue-6.6/net-ti-icss-iep-remove-spinlock-based-synchronizatio.patch new file mode 100644 index 0000000000..c8a9307d0b --- /dev/null +++ b/queue-6.6/net-ti-icss-iep-remove-spinlock-based-synchronizatio.patch @@ -0,0 +1,114 @@ +From 2420ee04fa2078538d1acca1da8a4d82f86ff767 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Jun 2024 16:21:41 +0100 +Subject: net: ti: icss-iep: Remove spinlock-based synchronization + +From: Diogo Ivo + +[ Upstream commit 5758e03cf604aa282b9afa61aec3188c4a9b3fe7 ] + +As all sources of concurrency in hardware register access occur in +non-interrupt context eliminate spinlock-based synchronization and +rely on the mutex-based synchronization that is already present. + +Signed-off-by: Diogo Ivo +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Stable-dep-of: 54e1b4becf5e ("net: ti: icss-iep: Reject perout generation request") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/icssg/icss_iep.c | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c +index f06cdec14ed7a..b491d89de8fb2 100644 +--- a/drivers/net/ethernet/ti/icssg/icss_iep.c ++++ b/drivers/net/ethernet/ti/icssg/icss_iep.c +@@ -110,7 +110,6 @@ struct icss_iep { + struct ptp_clock_info ptp_info; + struct ptp_clock *ptp_clock; + struct mutex ptp_clk_mutex; /* PHC access serializer */ +- spinlock_t irq_lock; /* CMP IRQ vs icss_iep_ptp_enable access */ + u32 def_inc; + s16 slow_cmp_inc; + u32 slow_cmp_count; +@@ -192,14 +191,11 @@ static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns) + */ + static void icss_iep_settime(struct icss_iep *iep, u64 ns) + { +- unsigned long flags; +- + if (iep->ops && iep->ops->settime) { + iep->ops->settime(iep->clockops_data, ns); + return; + } + +- spin_lock_irqsave(&iep->irq_lock, flags); + if (iep->pps_enabled || iep->perout_enabled) + writel(0, iep->base + iep->plat_data->reg_offs[ICSS_IEP_SYNC_CTRL_REG]); + +@@ -210,7 +206,6 @@ static void icss_iep_settime(struct icss_iep *iep, u64 ns) + writel(IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN, + iep->base + iep->plat_data->reg_offs[ICSS_IEP_SYNC_CTRL_REG]); + } +- spin_unlock_irqrestore(&iep->irq_lock, flags); + } + + /** +@@ -549,7 +544,6 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep, + static int icss_iep_perout_enable(struct icss_iep *iep, + struct ptp_perout_request *req, int on) + { +- unsigned long flags; + int ret = 0; + + mutex_lock(&iep->ptp_clk_mutex); +@@ -562,11 +556,9 @@ static int icss_iep_perout_enable(struct icss_iep *iep, + if (iep->perout_enabled == !!on) + goto exit; + +- spin_lock_irqsave(&iep->irq_lock, flags); + ret = icss_iep_perout_enable_hw(iep, req, on); + if (!ret) + iep->perout_enabled = !!on; +- spin_unlock_irqrestore(&iep->irq_lock, flags); + + exit: + mutex_unlock(&iep->ptp_clk_mutex); +@@ -578,7 +570,6 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on) + { + struct ptp_clock_request rq; + struct timespec64 ts; +- unsigned long flags; + int ret = 0; + u64 ns; + +@@ -592,8 +583,6 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on) + if (iep->pps_enabled == !!on) + goto exit; + +- spin_lock_irqsave(&iep->irq_lock, flags); +- + rq.perout.index = 0; + if (on) { + ns = icss_iep_gettime(iep, NULL); +@@ -610,8 +599,6 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on) + if (!ret) + iep->pps_enabled = !!on; + +- spin_unlock_irqrestore(&iep->irq_lock, flags); +- + exit: + mutex_unlock(&iep->ptp_clk_mutex); + +@@ -861,7 +848,6 @@ static int icss_iep_probe(struct platform_device *pdev) + + iep->ptp_info = icss_iep_ptp_info; + mutex_init(&iep->ptp_clk_mutex); +- spin_lock_init(&iep->irq_lock); + dev_set_drvdata(dev, iep); + icss_iep_disable(iep); + +-- +2.39.5 + diff --git a/queue-6.6/rxrpc-rxperf-fix-missing-decoding-of-terminal-magic-.patch b/queue-6.6/rxrpc-rxperf-fix-missing-decoding-of-terminal-magic-.patch new file mode 100644 index 0000000000..abae0183a4 --- /dev/null +++ b/queue-6.6/rxrpc-rxperf-fix-missing-decoding-of-terminal-magic-.patch @@ -0,0 +1,51 @@ +From 3bf0d6c6398248a9e894abe456bca851d46d3fbe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 19:22:44 +0000 +Subject: rxrpc: rxperf: Fix missing decoding of terminal magic cookie + +From: David Howells + +[ Upstream commit c34d999ca3145d9fe858258cc3342ec493f47d2e ] + +The rxperf RPCs seem to have a magic cookie at the end of the request that +was failing to be taken account of by the unmarshalling of the request. +Fix the rxperf code to expect this. + +Fixes: 75bfdbf2fca3 ("rxrpc: Implement an in-kernel rxperf server for testing purposes") +Signed-off-by: David Howells +cc: Marc Dionne +cc: Simon Horman +cc: linux-afs@lists.infradead.org +Link: https://patch.msgid.link/20250218192250.296870-2-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/rxrpc/rxperf.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/net/rxrpc/rxperf.c b/net/rxrpc/rxperf.c +index 085e7892d3104..b1536da2246b8 100644 +--- a/net/rxrpc/rxperf.c ++++ b/net/rxrpc/rxperf.c +@@ -478,6 +478,18 @@ static int rxperf_deliver_request(struct rxperf_call *call) + call->unmarshal++; + fallthrough; + case 2: ++ ret = rxperf_extract_data(call, true); ++ if (ret < 0) ++ return ret; ++ ++ /* Deal with the terminal magic cookie. */ ++ call->iov_len = 4; ++ call->kvec[0].iov_len = call->iov_len; ++ call->kvec[0].iov_base = call->tmp; ++ iov_iter_kvec(&call->iter, READ, call->kvec, 1, call->iov_len); ++ call->unmarshal++; ++ fallthrough; ++ case 3: + ret = rxperf_extract_data(call, false); + if (ret < 0) + return ret; +-- +2.39.5 + diff --git a/queue-6.6/series b/queue-6.6/series index fa905ef9b9..68f40fb00c 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -14,3 +14,38 @@ rdma-mlx5-fix-ah-static-rate-parsing.patch scsi-core-clear-driver-private-data-when-retrying-re.patch rdma-mlx5-fix-bind-qp-error-cleanup-flow.patch sunrpc-suppress-warnings-for-unused-procfs-functions.patch +alsa-usb-audio-avoid-dropping-midi-events-at-closing.patch +bluetooth-l2cap-fix-l2cap_ecred_conn_rsp-response.patch +rxrpc-rxperf-fix-missing-decoding-of-terminal-magic-.patch +afs-make-it-possible-to-find-the-volumes-that-are-us.patch +afs-fix-the-server_list-to-unuse-a-displaced-server-.patch +net-loopback-avoid-sending-ip-packets-without-an-eth.patch +net-set-the-minimum-for-net_hotdata.netdev_budget_us.patch +net-ipv4-add-tracepoint-for-icmp_send.patch +ipv4-icmp-pass-full-ds-field-to-ip_route_input.patch +ipv4-icmp-unmask-upper-dscp-bits-in-icmp_route_looku.patch +ipvlan-unmask-upper-dscp-bits-in-ipvlan_process_v4_o.patch +ipv4-convert-icmp_route_lookup-to-dscp_t.patch +ipv4-convert-ip_route_input-to-dscp_t.patch +ipvlan-prepare-ipvlan_process_v4_outbound-to-future-.patch +ipvlan-ensure-network-headers-are-in-skb-linear-part.patch +net-cadence-macb-synchronize-stats-calculations.patch +asoc-es8328-fix-route-from-dac-to-output.patch +ipvs-always-clear-ipvs_property-flag-in-skb_scrub_pa.patch +firmware-cs_dsp-remove-async-regmap-writes.patch +alsa-hda-realtek-add-quirks-for-asus-rog-2023-models.patch +alsa-hda-realtek-fix-wrong-mic-setup-for-asus-vivobo.patch +ice-add-e830-device-ids-mac-type-and-registers.patch +ice-add-e830-hw-vf-mailbox-message-limit-support.patch +ice-fix-deinitializing-vf-in-error-path.patch +tcp-defer-ts_recent-changes-until-req-is-owned.patch +net-clear-old-fragment-checksum-value-in-napi_reuse_.patch +net-mvpp2-cls-fixed-non-ip-flow-with-vlan-tag-flow-d.patch +net-mlx5-irq-fix-null-string-in-debug-print.patch +include-net-add-static-inline-dst_dev_overhead-to-ds.patch +net-ipv6-seg6_iptunnel-mitigate-2-realloc-issue.patch +net-ipv6-fix-dst-ref-loop-on-input-in-seg6-lwt.patch +net-ipv6-rpl_iptunnel-mitigate-2-realloc-issue.patch +net-ipv6-fix-dst-ref-loop-on-input-in-rpl-lwt.patch +net-ti-icss-iep-remove-spinlock-based-synchronizatio.patch +net-ti-icss-iep-reject-perout-generation-request.patch diff --git a/queue-6.6/tcp-defer-ts_recent-changes-until-req-is-owned.patch b/queue-6.6/tcp-defer-ts_recent-changes-until-req-is-owned.patch new file mode 100644 index 0000000000..e42f053f5f --- /dev/null +++ b/queue-6.6/tcp-defer-ts_recent-changes-until-req-is-owned.patch @@ -0,0 +1,92 @@ +From b43d8c9aa4e1a682eb9ce40e46858981e94f05e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 17:00:47 +0800 +Subject: tcp: Defer ts_recent changes until req is owned + +From: Wang Hai + +[ Upstream commit 8d52da23b6c68a0f6bad83959ebb61a2cf623c4e ] + +Recently a bug was discovered where the server had entered TCP_ESTABLISHED +state, but the upper layers were not notified. + +The same 5-tuple packet may be processed by different CPUSs, so two +CPUs may receive different ack packets at the same time when the +state is TCP_NEW_SYN_RECV. + +In that case, req->ts_recent in tcp_check_req may be changed concurrently, +which will probably cause the newsk's ts_recent to be incorrectly large. +So that tcp_validate_incoming will fail. At this point, newsk will not be +able to enter the TCP_ESTABLISHED. + +cpu1 cpu2 +tcp_check_req + tcp_check_req + req->ts_recent = rcv_tsval = t1 + req->ts_recent = rcv_tsval = t2 + + syn_recv_sock + tcp_sk(child)->rx_opt.ts_recent = req->ts_recent = t2 // t1 < t2 +tcp_child_process + tcp_rcv_state_process + tcp_validate_incoming + tcp_paws_check + if ((s32)(rx_opt->ts_recent - rx_opt->rcv_tsval) <= paws_win) + // t2 - t1 > paws_win, failed + tcp_v4_do_rcv + tcp_rcv_state_process + // TCP_ESTABLISHED + +The cpu2's skb or a newly received skb will call tcp_v4_do_rcv to get +the newsk into the TCP_ESTABLISHED state, but at this point it is no +longer possible to notify the upper layer application. A notification +mechanism could be added here, but the fix is more complex, so the +current fix is used. + +In tcp_check_req, req->ts_recent is used to assign a value to +tcp_sk(child)->rx_opt.ts_recent, so removing the change in req->ts_recent +and changing tcp_sk(child)->rx_opt.ts_recent directly after owning the +req fixes this bug. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Wang Hai +Reviewed-by: Jason Xing +Reviewed-by: Eric Dumazet +Reviewed-by: Kuniyuki Iwashima +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_minisocks.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c +index cc2b608b1a8e7..ddb90b9057e75 100644 +--- a/net/ipv4/tcp_minisocks.c ++++ b/net/ipv4/tcp_minisocks.c +@@ -754,12 +754,6 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, + + /* In sequence, PAWS is OK. */ + +- /* TODO: We probably should defer ts_recent change once +- * we take ownership of @req. +- */ +- if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_nxt)) +- WRITE_ONCE(req->ts_recent, tmp_opt.rcv_tsval); +- + if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) { + /* Truncate SYN, it is out of window starting + at tcp_rsk(req)->rcv_isn + 1. */ +@@ -808,6 +802,10 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, + if (!child) + goto listen_overflow; + ++ if (own_req && tmp_opt.saw_tstamp && ++ !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_nxt)) ++ tcp_sk(child)->rx_opt.ts_recent = tmp_opt.rcv_tsval; ++ + if (own_req && rsk_drop_req(req)) { + reqsk_queue_removed(&inet_csk(req->rsk_listener)->icsk_accept_queue, req); + inet_csk_reqsk_queue_drop_and_put(req->rsk_listener, req); +-- +2.39.5 + -- 2.47.3