--- /dev/null
+From 2f6124ec0bc845a8eee569dd3c9791e98ef713e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <dhowells@redhat.com>
+
+[ 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 <dhowells@redhat.com>
+cc: Marc Dionne <marc.dionne@auristor.com>
+cc: Simon Horman <horms@kernel.org>
+cc: linux-afs@lists.infradead.org
+Link: https://patch.msgid.link/20250218192250.296870-5-dhowells@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 2af2962ff6e69060eedc9237acb349589611d3c6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <dhowells@redhat.com>
+
+[ 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 <dhowells@redhat.com>
+cc: Marc Dionne <marc.dionne@auristor.com>
+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 <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 807e707f6e5746d5de17dc033d4ce144ab2d05a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 Dec 2023 15:12:17 +0000
+Subject: ALSA: hda/realtek: Add quirks for ASUS ROG 2023 models
+
+From: Stefan Binding <sbinding@opensource.cirrus.com>
+
+[ 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 <sbinding@opensource.cirrus.com>
+Link: https://lore.kernel.org/r/20231218151221.388745-4-sbinding@opensource.cirrus.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 9e7c6779e353 ("ALSA: hda/realtek: Fix wrong mic setup for ASUS VivoBook 15")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 0eb8c0e646a7a793d915e66ad3a3b4f760fadb18 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 16:45:32 +0100
+Subject: ALSA: hda/realtek: Fix wrong mic setup for ASUS VivoBook 15
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ 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 <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 41a306cb8f3a99d45a7134f76624001f0853b839 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 12:40:24 +0100
+Subject: ALSA: usb-audio: Avoid dropping MIDI events at closing multiple ports
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ 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 <jkeeping@inmusicbrands.com>
+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 <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 7d9bcc04a265005a671afd1d6099faa2f6d7155c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Feb 2025 20:39:57 +0100
+Subject: ASoC: es8328: fix route from DAC to output
+
+From: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
+
+[ 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 <nicolas.frattaroli@collabora.com>
+Link: https://patch.msgid.link/20250222-es8328-route-bludgeoning-v1-1-99bfb7fb22d9@collabora.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From e432d8287631bbf435682cf0ffe1044ba1005e6a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Feb 2025 10:30:25 -0500
+Subject: Bluetooth: L2CAP: Fix L2CAP_ECRED_CONN_RSP response
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ 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 <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 1af766cb83ec94cdd5550239bc5e1db39194a181 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 13:18:42 +0000
+Subject: firmware: cs_dsp: Remove async regmap writes
+
+From: Richard Fitzgerald <rf@opensource.cirrus.com>
+
+[ 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 <rf@opensource.cirrus.com>
+Link: https://patch.msgid.link/20250225131843.113752-2-rf@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 501cc7612ede11cc680f1256ede3d8af9c1327f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Oct 2023 14:41:52 -0700
+Subject: ice: Add E830 device IDs, MAC type and registers
+
+From: Paul Greenwalt <paul.greenwalt@intel.com>
+
+[ 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 <milena.olech@intel.com>
+Signed-off-by: Milena Olech <milena.olech@intel.com>
+Co-developed-by: Dan Nowlin <dan.nowlin@intel.com>
+Signed-off-by: Dan Nowlin <dan.nowlin@intel.com>
+Co-developed-by: Scott Taylor <scott.w.taylor@intel.com>
+Signed-off-by: Scott Taylor <scott.w.taylor@intel.com>
+Co-developed-by: Pawel Chmielewski <pawel.chmielewski@intel.com>
+Signed-off-by: Pawel Chmielewski <pawel.chmielewski@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com>
+Tested-by: Tony Brelinski <tony.brelinski@intel.com>
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://lore.kernel.org/r/20231025214157.1222758-2-jacob.e.keller@intel.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 79990cf5e7ad ("ice: Fix deinitializing VF in error path")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 07b5cfb88e640ac0e8ef5c39cb38fc13c9bb25d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Aug 2024 17:26:16 -0400
+Subject: ice: add E830 HW VF mailbox message limit support
+
+From: Paul Greenwalt <paul.greenwalt@intel.com>
+
+[ 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 <paul.greenwalt@intel.com>
+Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Stable-dep-of: 79990cf5e7ad ("ice: Fix deinitializing VF in error path")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 39b588255bfb95ec6cfad6a7b454ddfaf54d7544 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 11:06:41 -0800
+Subject: ice: Fix deinitializing VF in error path
+
+From: Marcin Szycik <marcin.szycik@linux.intel.com>
+
+[ 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 <sujai.buvaneswaran@intel.com>
+Closes: https://lore.kernel.org/intel-wired-lan/PH0PR11MB50138B635F2E5CEB7075325D961F2@PH0PR11MB5013.namprd11.prod.outlook.com
+Reviewed-by: Martyna Szapar-Mudlaw <martyna.szapar-mudlaw@linux.intel.com>
+Signed-off-by: Marcin Szycik <marcin.szycik@linux.intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Sujai Buvaneswaran <sujai.buvaneswaran@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Link: https://patch.msgid.link/20250224190647.3601930-2-anthony.l.nguyen@intel.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 7a1b819ee42597e7c986cd11e44fa1bbc8d0cb35 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 13:49:42 +0100
+Subject: include: net: add static inline dst_dev_overhead() to dst.h
+
+From: Justin Iurman <justin.iurman@uliege.be>
+
+[ 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 <justin.iurman@uliege.be>
+Cc: Alexander Lobakin <aleksander.lobakin@intel.com>
+Cc: Vadim Fedorenko <vadim.fedorenko@linux.dev>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: c64a0727f9b1 ("net: ipv6: fix dst ref loop on input in seg6 lwt")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From b4c73d305965ba8c42fd456d485fe39ff8ca3e1d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Oct 2024 21:28:37 +0200
+Subject: ipv4: Convert icmp_route_lookup() to dscp_t.
+
+From: Guillaume Nault <gnault@redhat.com>
+
+[ 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 <gnault@redhat.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://patch.msgid.link/294fead85c6035bcdc5fcf9a6bb4ce8798c45ba1.1727807926.git.gnault@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 1f5ac6c1fb081886bc9deec7224c8ae398e8bd95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Oct 2024 21:28:43 +0200
+Subject: ipv4: Convert ip_route_input() to dscp_t.
+
+From: Guillaume Nault <gnault@redhat.com>
+
+[ 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 <gnault@redhat.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://patch.msgid.link/e9d40781d64d3d69f4c79ac8a008b8d67a033e8d.1727807926.git.gnault@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From eaa55bd0afe35cd82c838b5f0529129575fbff78 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 15:52:49 +0300
+Subject: ipv4: icmp: Pass full DS field to ip_route_input()
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ 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 <idosch@nvidia.com>
+Reviewed-by: Guillaume Nault <gnault@redhat.com>
+Acked-by: Florian Westphal <fw@strlen.de>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://patch.msgid.link/20240821125251.1571445-11-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 70d2a1e3e8e18f517f1bbaba8ea03231ce283ccb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Aug 2024 09:54:50 +0300
+Subject: ipv4: icmp: Unmask upper DSCP bits in icmp_route_lookup()
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ 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 <idosch@nvidia.com>
+Reviewed-by: Guillaume Nault <gnault@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <net/ip_fib.h>
+ #include <net/l3mdev.h>
+ #include <net/addrconf.h>
++#include <net/inet_dscp.h>
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/icmp.h>
+
+@@ -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
+
--- /dev/null
+From 780f70c5379b6105e22db80c146e21614c591a03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 15:53:36 +0000
+Subject: ipvlan: ensure network headers are in skb linear part
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ 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 <edumazet@google.com>
+Cc: Mahesh Bandewar <maheshb@google.com>
+Link: https://patch.msgid.link/20250220155336.61884-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 758cc51f1434bef5c1bf34280c51d0424d634c6e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Oct 2024 13:43:11 +0100
+Subject: ipvlan: Prepare ipvlan_process_v4_outbound() to future .flowi4_tos
+ conversion.
+
+From: Guillaume Nault <gnault@redhat.com>
+
+[ 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 <gnault@redhat.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/f48335504a05b3587e0081a9b4511e0761571ca5.1730292157.git.gnault@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <net/inet_dscp.h>
++#include <net/ip.h>
+
+ #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
+
--- /dev/null
+From 3d279e5cc30561c9c3c9203b804ab81b0ddb0284 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Aug 2024 09:54:57 +0300
+Subject: ipvlan: Unmask upper DSCP bits in ipvlan_process_v4_outbound()
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ 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 <idosch@nvidia.com>
+Reviewed-by: Guillaume Nault <gnault@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <maheshb@google.com>
+ */
+
++#include <net/inet_dscp.h>
++
+ #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
+
--- /dev/null
+From fe74c8df03cdb1fe7dd7f34e5fdb09c8a979bd5f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Feb 2025 11:35:18 +0800
+Subject: ipvs: Always clear ipvs_property flag in skb_scrub_packet()
+
+From: Philo Lu <lulie@linux.alibaba.com>
+
+[ 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 <lulie@linux.alibaba.com>
+Acked-by: Julian Anastasov <ja@ssi.bg>
+Link: https://patch.msgid.link/20250222033518.126087-1-lulie@linux.alibaba.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 5f967074e928edfd13030bdc257df5c9b7f16517 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 11:29:50 -0500
+Subject: net: cadence: macb: Synchronize stats calculations
+
+From: Sean Anderson <sean.anderson@linux.dev>
+
+[ 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 <sean.anderson@linux.dev>
+Link: https://patch.msgid.link/20250220162950.95941-1-sean.anderson@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 1da4afde5e7a03e11a335f061a5b964ee6cef29a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 13:28:52 +0200
+Subject: net: Clear old fragment checksum value in napi_reuse_skb
+
+From: Mohammad Heib <mheib@redhat.com>
+
+[ 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:
+<IRQ>
+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
+</IRQ>
+
+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 <mheib@redhat.com>
+Reviewed-by: Shannon Nelson <shannon.nelson@amd.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20250225112852.2507709-1-mheib@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 5f7e86e0c0f27b236744e76c0401105ea5c909e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2024 15:41:03 +0800
+Subject: net/ipv4: add tracepoint for icmp_send
+
+From: Peilin He <he.peilin@zte.com.cn>
+
+[ 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 <he.peilin@zte.com.cn>
+Signed-off-by: xu xin <xu.xin16@zte.com.cn>
+Reviewed-by: Yunkai Zhang <zhang.yunkai@zte.com.cn>
+Cc: Yang Yang <yang.yang29@zte.com.cn>
+Cc: Liu Chun <liu.chun2@zte.com.cn>
+Cc: Xuexin Jiang <jiang.xuexin@zte.com.cn>
+Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 27843ce6ba3d ("ipvlan: ensure network headers are in skb linear part")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <linux/icmp.h>
++#include <linux/tracepoint.h>
++
++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 <trace/define_trace.h>
++
+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 <net/ip_fib.h>
+ #include <net/l3mdev.h>
+ #include <net/addrconf.h>
++#define CREATE_TRACE_POINTS
++#include <trace/events/icmp.h>
+
+ /*
+ * 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
+
--- /dev/null
+From 9c46ffddb63eb47b2d722b5b31ed57b2af8cd686 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 18:51:39 +0100
+Subject: net: ipv6: fix dst ref loop on input in rpl lwt
+
+From: Justin Iurman <justin.iurman@uliege.be>
+
+[ Upstream commit 13e55fbaec176119cff68a7e1693b251c8883c5f ]
+
+Prevent a dst ref loop on input in rpl_iptunnel.
+
+Fixes: a7a29f9c361f ("net: ipv6: add rpl sr tunnel")
+Cc: Alexander Aring <alex.aring@gmail.com>
+Cc: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From b937bba0778e423c4daee8b997d8aac0abcdcfa0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 18:51:38 +0100
+Subject: net: ipv6: fix dst ref loop on input in seg6 lwt
+
+From: Justin Iurman <justin.iurman@uliege.be>
+
+[ 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 <dlebrun@google.com>
+Cc: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From ce7db97ce7d371c3d7767ccbe7a7343eee5bce92 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 13:49:45 +0100
+Subject: net: ipv6: rpl_iptunnel: mitigate 2-realloc issue
+
+From: Justin Iurman <justin.iurman@uliege.be>
+
+[ 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 <justin.iurman@uliege.be>
+Cc: Alexander Aring <aahringo@redhat.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: 13e55fbaec17 ("net: ipv6: fix dst ref loop on input in rpl lwt")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 5cf013750e0269b639809878907516dc15ee6437 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 13:49:44 +0100
+Subject: net: ipv6: seg6_iptunnel: mitigate 2-realloc issue
+
+From: Justin Iurman <justin.iurman@uliege.be>
+
+[ 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 <justin.iurman@uliege.be>
+Cc: David Lebrun <dlebrun@google.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: c64a0727f9b1 ("net: ipv6: fix dst ref loop on input in seg6 lwt")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From ab606c5963fded70ebf0bb12963a54d7e4170957 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 09:25:59 +0200
+Subject: net: loopback: Avoid sending IP packets without an Ethernet header
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ 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 <fmei@sfs.com>
+Closes: https://lore.kernel.org/netdev/20250210084931.23a5c2e4@hermes.local/
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20250220072559.782296-1-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From afbd4a5c9962dca295601d731e1184b2654a8fe0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 09:26:08 +0200
+Subject: net/mlx5: IRQ, Fix null string in debug print
+
+From: Shay Drory <shayd@nvidia.com>
+
+[ 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 <shayd@nvidia.com>
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202501141055.SwfIphN0-lkp@intel.com/
+Reviewed-by: Moshe Shemesh <moshe@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Link: https://patch.msgid.link/20250225072608.526866-4-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From ad6bcf9b993035f093748d8ed276f2d4d2b5f9a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <hchaudhari@marvell.com>
+
+[ 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 <hchaudhari@marvell.com>
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20250225042058.2643838-1-hchaudhari@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 115bdcc50be9811c84bd518d9e66ca382aa05389 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 12:07:52 +0100
+Subject: net: set the minimum for net_hotdata.netdev_budget_usecs
+
+From: Jiri Slaby (SUSE) <jirislaby@kernel.org>
+
+[ 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) <jirislaby@kernel.org>
+Cc: Dmitry Yakunin <zeil@yandex-team.ru>
+Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
+Link: https://patch.msgid.link/20250220110752.137639-1-jirislaby@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 6ace75c851b68e50bd7b15a4dd78635dd8e45060 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 14:54:41 +0530
+Subject: net: ti: icss-iep: Reject perout generation request
+
+From: Meghana Malladi <m-malladi@ti.com>
+
+[ 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 <m-malladi@ti.com>
+Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
+Link: https://patch.msgid.link/20250227092441.1848419-1-m-malladi@ti.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 2420ee04fa2078538d1acca1da8a4d82f86ff767 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jun 2024 16:21:41 +0100
+Subject: net: ti: icss-iep: Remove spinlock-based synchronization
+
+From: Diogo Ivo <diogo.ivo@siemens.com>
+
+[ 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 <diogo.ivo@siemens.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 54e1b4becf5e ("net: ti: icss-iep: Reject perout generation request")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 3bf0d6c6398248a9e894abe456bca851d46d3fbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 19:22:44 +0000
+Subject: rxrpc: rxperf: Fix missing decoding of terminal magic cookie
+
+From: David Howells <dhowells@redhat.com>
+
+[ 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 <dhowells@redhat.com>
+cc: Marc Dionne <marc.dionne@auristor.com>
+cc: Simon Horman <horms@kernel.org>
+cc: linux-afs@lists.infradead.org
+Link: https://patch.msgid.link/20250218192250.296870-2-dhowells@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
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
--- /dev/null
+From b43d8c9aa4e1a682eb9ce40e46858981e94f05e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 17:00:47 +0800
+Subject: tcp: Defer ts_recent changes until req is owned
+
+From: Wang Hai <wanghai38@huawei.com>
+
+[ 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 <wanghai38@huawei.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+