--- /dev/null
+From 0ee4cf301c543492c01c39c5b44433dfe78c5468 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Dec 2023 20:39:02 +0100
+Subject: ARM: sun9i: smp: Fix array-index-out-of-bounds read in
+ sunxi_mc_smp_init
+
+From: Stefan Wahren <wahrenst@gmx.net>
+
+[ Upstream commit 72ad3b772b6d393701df58ba1359b0bb346a19ed ]
+
+Running a multi-arch kernel (multi_v7_defconfig) on a Raspberry Pi 3B+
+with enabled CONFIG_UBSAN triggers the following warning:
+
+ UBSAN: array-index-out-of-bounds in arch/arm/mach-sunxi/mc_smp.c:810:29
+ index 2 is out of range for type 'sunxi_mc_smp_data [2]'
+ CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.7.0-rc6-00248-g5254c0cbc92d
+ Hardware name: BCM2835
+ unwind_backtrace from show_stack+0x10/0x14
+ show_stack from dump_stack_lvl+0x40/0x4c
+ dump_stack_lvl from ubsan_epilogue+0x8/0x34
+ ubsan_epilogue from __ubsan_handle_out_of_bounds+0x78/0x80
+ __ubsan_handle_out_of_bounds from sunxi_mc_smp_init+0xe4/0x4cc
+ sunxi_mc_smp_init from do_one_initcall+0xa0/0x2fc
+ do_one_initcall from kernel_init_freeable+0xf4/0x2f4
+ kernel_init_freeable from kernel_init+0x18/0x158
+ kernel_init from ret_from_fork+0x14/0x28
+
+Since the enabled method couldn't match with any entry from
+sunxi_mc_smp_data, the value of the index shouldn't be used right after
+the loop. So move it after the check of ret in order to have a valid
+index.
+
+Fixes: 1631090e34f5 ("ARM: sun9i: smp: Add is_a83t field")
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Link: https://lore.kernel.org/r/20231228193903.9078-1-wahrenst@gmx.net
+Reviewed-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/mach-sunxi/mc_smp.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-sunxi/mc_smp.c b/arch/arm/mach-sunxi/mc_smp.c
+index 26cbce1353387..b2f5f4f28705f 100644
+--- a/arch/arm/mach-sunxi/mc_smp.c
++++ b/arch/arm/mach-sunxi/mc_smp.c
+@@ -808,12 +808,12 @@ static int __init sunxi_mc_smp_init(void)
+ break;
+ }
+
+- is_a83t = sunxi_mc_smp_data[i].is_a83t;
+-
+ of_node_put(node);
+ if (ret)
+ return -ENODEV;
+
++ is_a83t = sunxi_mc_smp_data[i].is_a83t;
++
+ if (!sunxi_mc_smp_cpu_table_init())
+ return -EINVAL;
+
+--
+2.43.0
+
--- /dev/null
+From fb6265e8f9403d8822dd36a8912e3f23e465957b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jan 2024 03:35:34 +0000
+Subject: asix: Add check for usbnet_get_endpoints
+
+From: Chen Ni <nichen@iscas.ac.cn>
+
+[ Upstream commit eaac6a2d26b65511e164772bec6918fcbc61938e ]
+
+Add check for usbnet_get_endpoints() and return the error if it fails
+in order to transfer the error.
+
+Fixes: 16626b0cc3d5 ("asix: Add a new driver for the AX88172A")
+Signed-off-by: Chen Ni <nichen@iscas.ac.cn>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/ax88172a.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/usb/ax88172a.c b/drivers/net/usb/ax88172a.c
+index 6101d82102e79..bf65262e2256d 100644
+--- a/drivers/net/usb/ax88172a.c
++++ b/drivers/net/usb/ax88172a.c
+@@ -186,7 +186,9 @@ static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf)
+ u8 buf[ETH_ALEN];
+ struct ax88172a_private *priv;
+
+- usbnet_get_endpoints(dev, intf);
++ ret = usbnet_get_endpoints(dev, intf);
++ if (ret)
++ return ret;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+--
+2.43.0
+
--- /dev/null
+From 51aa6d37a344fca4c0bc043f6e7002bd1ef99833 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2020 16:51:52 +0100
+Subject: ASoC: meson: g12a: extract codec-to-codec utils
+
+From: Jerome Brunet <jbrunet@baylibre.com>
+
+[ Upstream commit 9c29fd9bdf92900dc0cc5c2d8f58951a7bdc0f41 ]
+
+The hdmi routing mechanism used on g12a hdmi is also used:
+* other Amlogic SoC types
+* for the internal DAC path
+
+Each of these codec glues are slightly different but the idea
+behind it remains the same. This change extract some helper functions
+from the g12a-tohdmitx driver to make them available for other Amlogic
+codecs.
+
+Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
+Link: https://lore.kernel.org/r/20200213155159.3235792-3-jbrunet@baylibre.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 1e001206804b ("ASoC: meson: g12a-tohdmitx: Validate written enum values")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/meson/Kconfig | 4 +
+ sound/soc/meson/Makefile | 2 +
+ sound/soc/meson/g12a-tohdmitx.c | 219 ++++++-----------------------
+ sound/soc/meson/meson-codec-glue.c | 149 ++++++++++++++++++++
+ sound/soc/meson/meson-codec-glue.h | 32 +++++
+ 5 files changed, 230 insertions(+), 176 deletions(-)
+ create mode 100644 sound/soc/meson/meson-codec-glue.c
+ create mode 100644 sound/soc/meson/meson-codec-glue.h
+
+diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
+index e0d24592ebd70..f9188274f6b0f 100644
+--- a/sound/soc/meson/Kconfig
++++ b/sound/soc/meson/Kconfig
+@@ -85,9 +85,13 @@ config SND_MESON_AXG_PDM
+ Select Y or M to add support for PDM input embedded
+ in the Amlogic AXG SoC family
+
++config SND_MESON_CODEC_GLUE
++ tristate
++
+ config SND_MESON_G12A_TOHDMITX
+ tristate "Amlogic G12A To HDMI TX Control Support"
+ select REGMAP_MMIO
++ select SND_MESON_CODEC_GLUE
+ imply SND_SOC_HDMI_CODEC
+ help
+ Select Y or M to add support for HDMI audio on the g12a SoC
+diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile
+index 1a8b1470ed843..529a807b3f376 100644
+--- a/sound/soc/meson/Makefile
++++ b/sound/soc/meson/Makefile
+@@ -11,6 +11,7 @@ snd-soc-meson-axg-sound-card-objs := axg-card.o
+ snd-soc-meson-axg-spdifin-objs := axg-spdifin.o
+ snd-soc-meson-axg-spdifout-objs := axg-spdifout.o
+ snd-soc-meson-axg-pdm-objs := axg-pdm.o
++snd-soc-meson-codec-glue-objs := meson-codec-glue.o
+ snd-soc-meson-g12a-tohdmitx-objs := g12a-tohdmitx.o
+
+ obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o
+@@ -24,4 +25,5 @@ obj-$(CONFIG_SND_MESON_AXG_SOUND_CARD) += snd-soc-meson-axg-sound-card.o
+ obj-$(CONFIG_SND_MESON_AXG_SPDIFIN) += snd-soc-meson-axg-spdifin.o
+ obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o
+ obj-$(CONFIG_SND_MESON_AXG_PDM) += snd-soc-meson-axg-pdm.o
++obj-$(CONFIG_SND_MESON_CODEC_GLUE) += snd-soc-meson-codec-glue.o
+ obj-$(CONFIG_SND_MESON_G12A_TOHDMITX) += snd-soc-meson-g12a-tohdmitx.o
+diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c
+index cbe47e0cae426..d02825669484a 100644
+--- a/sound/soc/meson/g12a-tohdmitx.c
++++ b/sound/soc/meson/g12a-tohdmitx.c
+@@ -12,112 +12,51 @@
+ #include <sound/soc-dai.h>
+
+ #include <dt-bindings/sound/meson-g12a-tohdmitx.h>
++#include "meson-codec-glue.h"
+
+ #define G12A_TOHDMITX_DRV_NAME "g12a-tohdmitx"
+
+ #define TOHDMITX_CTRL0 0x0
+ #define CTRL0_ENABLE_SHIFT 31
+-#define CTRL0_I2S_DAT_SEL GENMASK(13, 12)
++#define CTRL0_I2S_DAT_SEL_SHIFT 12
++#define CTRL0_I2S_DAT_SEL (0x3 << CTRL0_I2S_DAT_SEL_SHIFT)
+ #define CTRL0_I2S_LRCLK_SEL GENMASK(9, 8)
+ #define CTRL0_I2S_BLK_CAP_INV BIT(7)
+ #define CTRL0_I2S_BCLK_O_INV BIT(6)
+ #define CTRL0_I2S_BCLK_SEL GENMASK(5, 4)
+ #define CTRL0_SPDIF_CLK_CAP_INV BIT(3)
+ #define CTRL0_SPDIF_CLK_O_INV BIT(2)
+-#define CTRL0_SPDIF_SEL BIT(1)
++#define CTRL0_SPDIF_SEL_SHIFT 1
++#define CTRL0_SPDIF_SEL (0x1 << CTRL0_SPDIF_SEL_SHIFT)
+ #define CTRL0_SPDIF_CLK_SEL BIT(0)
+
+-struct g12a_tohdmitx_input {
+- struct snd_soc_pcm_stream params;
+- unsigned int fmt;
+-};
+-
+-static struct snd_soc_dapm_widget *
+-g12a_tohdmitx_get_input(struct snd_soc_dapm_widget *w)
+-{
+- struct snd_soc_dapm_path *p = NULL;
+- struct snd_soc_dapm_widget *in;
+-
+- snd_soc_dapm_widget_for_each_source_path(w, p) {
+- if (!p->connect)
+- continue;
+-
+- /* Check that we still are in the same component */
+- if (snd_soc_dapm_to_component(w->dapm) !=
+- snd_soc_dapm_to_component(p->source->dapm))
+- continue;
+-
+- if (p->source->id == snd_soc_dapm_dai_in)
+- return p->source;
+-
+- in = g12a_tohdmitx_get_input(p->source);
+- if (in)
+- return in;
+- }
+-
+- return NULL;
+-}
+-
+-static struct g12a_tohdmitx_input *
+-g12a_tohdmitx_get_input_data(struct snd_soc_dapm_widget *w)
+-{
+- struct snd_soc_dapm_widget *in =
+- g12a_tohdmitx_get_input(w);
+- struct snd_soc_dai *dai;
+-
+- if (WARN_ON(!in))
+- return NULL;
+-
+- dai = in->priv;
+-
+- return dai->playback_dma_data;
+-}
+-
+ static const char * const g12a_tohdmitx_i2s_mux_texts[] = {
+ "I2S A", "I2S B", "I2S C",
+ };
+
+-static SOC_ENUM_SINGLE_EXT_DECL(g12a_tohdmitx_i2s_mux_enum,
+- g12a_tohdmitx_i2s_mux_texts);
+-
+-static int g12a_tohdmitx_get_input_val(struct snd_soc_component *component,
+- unsigned int mask)
+-{
+- unsigned int val;
+-
+- snd_soc_component_read(component, TOHDMITX_CTRL0, &val);
+- return (val & mask) >> __ffs(mask);
+-}
+-
+-static int g12a_tohdmitx_i2s_mux_get_enum(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct snd_soc_component *component =
+- snd_soc_dapm_kcontrol_component(kcontrol);
+-
+- ucontrol->value.enumerated.item[0] =
+- g12a_tohdmitx_get_input_val(component, CTRL0_I2S_DAT_SEL);
+-
+- return 0;
+-}
+-
+ static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
++ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_soc_component *component =
+ snd_soc_dapm_kcontrol_component(kcontrol);
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+- unsigned int mux = ucontrol->value.enumerated.item[0];
+- unsigned int val = g12a_tohdmitx_get_input_val(component,
+- CTRL0_I2S_DAT_SEL);
++ unsigned int mux, changed;
++
++ mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]);
++ changed = snd_soc_component_test_bits(component, e->reg,
++ CTRL0_I2S_DAT_SEL,
++ FIELD_PREP(CTRL0_I2S_DAT_SEL,
++ mux));
++
++ if (!changed)
++ return 0;
+
+ /* Force disconnect of the mux while updating */
+- if (val != mux)
+- snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL);
++ snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL);
+
+- snd_soc_component_update_bits(component, TOHDMITX_CTRL0,
++ snd_soc_component_update_bits(component, e->reg,
+ CTRL0_I2S_DAT_SEL |
+ CTRL0_I2S_LRCLK_SEL |
+ CTRL0_I2S_BCLK_SEL,
+@@ -130,30 +69,19 @@ static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol,
+ return 1;
+ }
+
++static SOC_ENUM_SINGLE_DECL(g12a_tohdmitx_i2s_mux_enum, TOHDMITX_CTRL0,
++ CTRL0_I2S_DAT_SEL_SHIFT,
++ g12a_tohdmitx_i2s_mux_texts);
++
+ static const struct snd_kcontrol_new g12a_tohdmitx_i2s_mux =
+ SOC_DAPM_ENUM_EXT("I2S Source", g12a_tohdmitx_i2s_mux_enum,
+- g12a_tohdmitx_i2s_mux_get_enum,
++ snd_soc_dapm_get_enum_double,
+ g12a_tohdmitx_i2s_mux_put_enum);
+
+ static const char * const g12a_tohdmitx_spdif_mux_texts[] = {
+ "SPDIF A", "SPDIF B",
+ };
+
+-static SOC_ENUM_SINGLE_EXT_DECL(g12a_tohdmitx_spdif_mux_enum,
+- g12a_tohdmitx_spdif_mux_texts);
+-
+-static int g12a_tohdmitx_spdif_mux_get_enum(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct snd_soc_component *component =
+- snd_soc_dapm_kcontrol_component(kcontrol);
+-
+- ucontrol->value.enumerated.item[0] =
+- g12a_tohdmitx_get_input_val(component, CTRL0_SPDIF_SEL);
+-
+- return 0;
+-}
+-
+ static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -162,13 +90,18 @@ static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol,
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+- unsigned int mux = ucontrol->value.enumerated.item[0];
+- unsigned int val = g12a_tohdmitx_get_input_val(component,
+- CTRL0_SPDIF_SEL);
++ unsigned int mux, changed;
++
++ mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]);
++ changed = snd_soc_component_test_bits(component, TOHDMITX_CTRL0,
++ CTRL0_SPDIF_SEL,
++ FIELD_PREP(CTRL0_SPDIF_SEL, mux));
++
++ if (!changed)
++ return 0;
+
+ /* Force disconnect of the mux while updating */
+- if (val != mux)
+- snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL);
++ snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL);
+
+ snd_soc_component_update_bits(component, TOHDMITX_CTRL0,
+ CTRL0_SPDIF_SEL |
+@@ -181,9 +114,13 @@ static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol,
+ return 0;
+ }
+
++static SOC_ENUM_SINGLE_DECL(g12a_tohdmitx_spdif_mux_enum, TOHDMITX_CTRL0,
++ CTRL0_SPDIF_SEL_SHIFT,
++ g12a_tohdmitx_spdif_mux_texts);
++
+ static const struct snd_kcontrol_new g12a_tohdmitx_spdif_mux =
+ SOC_DAPM_ENUM_EXT("SPDIF Source", g12a_tohdmitx_spdif_mux_enum,
+- g12a_tohdmitx_spdif_mux_get_enum,
++ snd_soc_dapm_get_enum_double,
+ g12a_tohdmitx_spdif_mux_put_enum);
+
+ static const struct snd_kcontrol_new g12a_tohdmitx_out_enable =
+@@ -201,83 +138,13 @@ static const struct snd_soc_dapm_widget g12a_tohdmitx_widgets[] = {
+ &g12a_tohdmitx_out_enable),
+ };
+
+-static int g12a_tohdmitx_input_probe(struct snd_soc_dai *dai)
+-{
+- struct g12a_tohdmitx_input *data;
+-
+- data = kzalloc(sizeof(*data), GFP_KERNEL);
+- if (!data)
+- return -ENOMEM;
+-
+- dai->playback_dma_data = data;
+- return 0;
+-}
+-
+-static int g12a_tohdmitx_input_remove(struct snd_soc_dai *dai)
+-{
+- kfree(dai->playback_dma_data);
+- return 0;
+-}
+-
+-static int g12a_tohdmitx_input_hw_params(struct snd_pcm_substream *substream,
+- struct snd_pcm_hw_params *params,
+- struct snd_soc_dai *dai)
+-{
+- struct g12a_tohdmitx_input *data = dai->playback_dma_data;
+-
+- data->params.rates = snd_pcm_rate_to_rate_bit(params_rate(params));
+- data->params.rate_min = params_rate(params);
+- data->params.rate_max = params_rate(params);
+- data->params.formats = 1 << params_format(params);
+- data->params.channels_min = params_channels(params);
+- data->params.channels_max = params_channels(params);
+- data->params.sig_bits = dai->driver->playback.sig_bits;
+-
+- return 0;
+-}
+-
+-
+-static int g12a_tohdmitx_input_set_fmt(struct snd_soc_dai *dai,
+- unsigned int fmt)
+-{
+- struct g12a_tohdmitx_input *data = dai->playback_dma_data;
+-
+- /* Save the source stream format for the downstream link */
+- data->fmt = fmt;
+- return 0;
+-}
+-
+-static int g12a_tohdmitx_output_startup(struct snd_pcm_substream *substream,
+- struct snd_soc_dai *dai)
+-{
+- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+- struct g12a_tohdmitx_input *in_data =
+- g12a_tohdmitx_get_input_data(dai->capture_widget);
+-
+- if (!in_data)
+- return -ENODEV;
+-
+- if (WARN_ON(!rtd->dai_link->params)) {
+- dev_warn(dai->dev, "codec2codec link expected\n");
+- return -EINVAL;
+- }
+-
+- /* Replace link params with the input params */
+- rtd->dai_link->params = &in_data->params;
+-
+- if (!in_data->fmt)
+- return 0;
+-
+- return snd_soc_runtime_set_dai_fmt(rtd, in_data->fmt);
+-}
+-
+ static const struct snd_soc_dai_ops g12a_tohdmitx_input_ops = {
+- .hw_params = g12a_tohdmitx_input_hw_params,
+- .set_fmt = g12a_tohdmitx_input_set_fmt,
++ .hw_params = meson_codec_glue_input_hw_params,
++ .set_fmt = meson_codec_glue_input_set_fmt,
+ };
+
+ static const struct snd_soc_dai_ops g12a_tohdmitx_output_ops = {
+- .startup = g12a_tohdmitx_output_startup,
++ .startup = meson_codec_glue_output_startup,
+ };
+
+ #define TOHDMITX_SPDIF_FORMATS \
+@@ -304,8 +171,8 @@ static const struct snd_soc_dai_ops g12a_tohdmitx_output_ops = {
+ .id = (xid), \
+ .playback = TOHDMITX_STREAM(xname, "Playback", xfmt, xchmax), \
+ .ops = &g12a_tohdmitx_input_ops, \
+- .probe = g12a_tohdmitx_input_probe, \
+- .remove = g12a_tohdmitx_input_remove, \
++ .probe = meson_codec_glue_input_dai_probe, \
++ .remove = meson_codec_glue_input_dai_remove, \
+ }
+
+ #define TOHDMITX_OUT(xname, xid, xfmt, xchmax) { \
+diff --git a/sound/soc/meson/meson-codec-glue.c b/sound/soc/meson/meson-codec-glue.c
+new file mode 100644
+index 0000000000000..97bbc967e1769
+--- /dev/null
++++ b/sound/soc/meson/meson-codec-glue.c
+@@ -0,0 +1,149 @@
++// SPDX-License-Identifier: GPL-2.0
++//
++// Copyright (c) 2019 BayLibre, SAS.
++// Author: Jerome Brunet <jbrunet@baylibre.com>
++
++#include <linux/module.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/soc-dai.h>
++
++#include "meson-codec-glue.h"
++
++static struct snd_soc_dapm_widget *
++meson_codec_glue_get_input(struct snd_soc_dapm_widget *w)
++{
++ struct snd_soc_dapm_path *p = NULL;
++ struct snd_soc_dapm_widget *in;
++
++ snd_soc_dapm_widget_for_each_source_path(w, p) {
++ if (!p->connect)
++ continue;
++
++ /* Check that we still are in the same component */
++ if (snd_soc_dapm_to_component(w->dapm) !=
++ snd_soc_dapm_to_component(p->source->dapm))
++ continue;
++
++ if (p->source->id == snd_soc_dapm_dai_in)
++ return p->source;
++
++ in = meson_codec_glue_get_input(p->source);
++ if (in)
++ return in;
++ }
++
++ return NULL;
++}
++
++static void meson_codec_glue_input_set_data(struct snd_soc_dai *dai,
++ struct meson_codec_glue_input *data)
++{
++ dai->playback_dma_data = data;
++}
++
++struct meson_codec_glue_input *
++meson_codec_glue_input_get_data(struct snd_soc_dai *dai)
++{
++ return dai->playback_dma_data;
++}
++EXPORT_SYMBOL_GPL(meson_codec_glue_input_get_data);
++
++static struct meson_codec_glue_input *
++meson_codec_glue_output_get_input_data(struct snd_soc_dapm_widget *w)
++{
++ struct snd_soc_dapm_widget *in =
++ meson_codec_glue_get_input(w);
++ struct snd_soc_dai *dai;
++
++ if (WARN_ON(!in))
++ return NULL;
++
++ dai = in->priv;
++
++ return meson_codec_glue_input_get_data(dai);
++}
++
++int meson_codec_glue_input_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params,
++ struct snd_soc_dai *dai)
++{
++ struct meson_codec_glue_input *data =
++ meson_codec_glue_input_get_data(dai);
++
++ data->params.rates = snd_pcm_rate_to_rate_bit(params_rate(params));
++ data->params.rate_min = params_rate(params);
++ data->params.rate_max = params_rate(params);
++ data->params.formats = 1 << params_format(params);
++ data->params.channels_min = params_channels(params);
++ data->params.channels_max = params_channels(params);
++ data->params.sig_bits = dai->driver->playback.sig_bits;
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(meson_codec_glue_input_hw_params);
++
++int meson_codec_glue_input_set_fmt(struct snd_soc_dai *dai,
++ unsigned int fmt)
++{
++ struct meson_codec_glue_input *data =
++ meson_codec_glue_input_get_data(dai);
++
++ /* Save the source stream format for the downstream link */
++ data->fmt = fmt;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(meson_codec_glue_input_set_fmt);
++
++int meson_codec_glue_output_startup(struct snd_pcm_substream *substream,
++ struct snd_soc_dai *dai)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct meson_codec_glue_input *in_data =
++ meson_codec_glue_output_get_input_data(dai->capture_widget);
++
++ if (!in_data)
++ return -ENODEV;
++
++ if (WARN_ON(!rtd->dai_link->params)) {
++ dev_warn(dai->dev, "codec2codec link expected\n");
++ return -EINVAL;
++ }
++
++ /* Replace link params with the input params */
++ rtd->dai_link->params = &in_data->params;
++
++ if (!in_data->fmt)
++ return 0;
++
++ return snd_soc_runtime_set_dai_fmt(rtd, in_data->fmt);
++}
++EXPORT_SYMBOL_GPL(meson_codec_glue_output_startup);
++
++int meson_codec_glue_input_dai_probe(struct snd_soc_dai *dai)
++{
++ struct meson_codec_glue_input *data;
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ meson_codec_glue_input_set_data(dai, data);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(meson_codec_glue_input_dai_probe);
++
++int meson_codec_glue_input_dai_remove(struct snd_soc_dai *dai)
++{
++ struct meson_codec_glue_input *data =
++ meson_codec_glue_input_get_data(dai);
++
++ kfree(data);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(meson_codec_glue_input_dai_remove);
++
++MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
++MODULE_DESCRIPTION("Amlogic Codec Glue Helpers");
++MODULE_LICENSE("GPL v2");
++
+diff --git a/sound/soc/meson/meson-codec-glue.h b/sound/soc/meson/meson-codec-glue.h
+new file mode 100644
+index 0000000000000..07f99446c0c6b
+--- /dev/null
++++ b/sound/soc/meson/meson-codec-glue.h
+@@ -0,0 +1,32 @@
++/* SPDX-License-Identifier: GPL-2.0
++ *
++ * Copyright (c) 2018 Baylibre SAS.
++ * Author: Jerome Brunet <jbrunet@baylibre.com>
++ */
++
++#ifndef _MESON_CODEC_GLUE_H
++#define _MESON_CODEC_GLUE_H
++
++#include <sound/soc.h>
++
++struct meson_codec_glue_input {
++ struct snd_soc_pcm_stream params;
++ unsigned int fmt;
++};
++
++/* Input helpers */
++struct meson_codec_glue_input *
++meson_codec_glue_input_get_data(struct snd_soc_dai *dai);
++int meson_codec_glue_input_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params,
++ struct snd_soc_dai *dai);
++int meson_codec_glue_input_set_fmt(struct snd_soc_dai *dai,
++ unsigned int fmt);
++int meson_codec_glue_input_dai_probe(struct snd_soc_dai *dai);
++int meson_codec_glue_input_dai_remove(struct snd_soc_dai *dai);
++
++/* Output helpers */
++int meson_codec_glue_output_startup(struct snd_pcm_substream *substream,
++ struct snd_soc_dai *dai);
++
++#endif /* _MESON_CODEC_GLUE_H */
+--
+2.43.0
+
--- /dev/null
+From e9203e3757f19216c844168885d6c09acf92153d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jan 2024 18:34:04 +0000
+Subject: ASoC: meson: g12a-tohdmitx: Fix event generation for S/PDIF mux
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit b036d8ef3120b996751495ce25994eea58032a98 ]
+
+When a control changes value the return value from _put() should be 1 so
+we get events generated to userspace notifying applications of the change.
+While the I2S mux gets this right the S/PDIF mux does not, fix the return
+value.
+
+Fixes: c8609f3870f7 ("ASoC: meson: add g12a tohdmitx control")
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20240103-meson-enum-val-v1-4-424af7a8fb91@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/meson/g12a-tohdmitx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c
+index 2f44c138e1dee..c875c350be070 100644
+--- a/sound/soc/meson/g12a-tohdmitx.c
++++ b/sound/soc/meson/g12a-tohdmitx.c
+@@ -117,7 +117,7 @@ static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol,
+
+ snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
+
+- return 0;
++ return 1;
+ }
+
+ static SOC_ENUM_SINGLE_DECL(g12a_tohdmitx_spdif_mux_enum, TOHDMITX_CTRL0,
+--
+2.43.0
+
--- /dev/null
+From 76e63129f04341bd4637686b28f19775a460e601 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jan 2024 18:34:02 +0000
+Subject: ASoC: meson: g12a-tohdmitx: Validate written enum values
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit 1e001206804be3f3d21f4a1cf16e5d059d75643f ]
+
+When writing to an enum we need to verify that the value written is valid
+for the enumeration, the helper function snd_soc_item_enum_to_val() doesn't
+do it since it needs to return an unsigned (and in any case we'd need to
+check the return value).
+
+Fixes: c8609f3870f7 ("ASoC: meson: add g12a tohdmitx control")
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20240103-meson-enum-val-v1-2-424af7a8fb91@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/meson/g12a-tohdmitx.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c
+index d02825669484a..2f44c138e1dee 100644
+--- a/sound/soc/meson/g12a-tohdmitx.c
++++ b/sound/soc/meson/g12a-tohdmitx.c
+@@ -44,6 +44,9 @@ static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol,
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int mux, changed;
+
++ if (ucontrol->value.enumerated.item[0] >= e->items)
++ return -EINVAL;
++
+ mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]);
+ changed = snd_soc_component_test_bits(component, e->reg,
+ CTRL0_I2S_DAT_SEL,
+@@ -92,6 +95,9 @@ static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol,
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int mux, changed;
+
++ if (ucontrol->value.enumerated.item[0] >= e->items)
++ return -EINVAL;
++
+ mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]);
+ changed = snd_soc_component_test_bits(component, TOHDMITX_CTRL0,
+ CTRL0_SPDIF_SEL,
+--
+2.43.0
+
--- /dev/null
+From 261b36212f4dcc4227a3960fe3f8b0caa7a582d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jan 2024 16:59:24 -0800
+Subject: bnxt_en: Remove mis-applied code from bnxt_cfg_ntp_filters()
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit e009b2efb7a8850498796b360043ac25c8d3d28f ]
+
+The 2 lines to check for the BNXT_HWRM_PF_UNLOAD_SP_EVENT bit was
+mis-applied to bnxt_cfg_ntp_filters() and should have been applied to
+bnxt_sp_task().
+
+Fixes: 19241368443f ("bnxt_en: Send PF driver unload notification to all VFs.")
+Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 7f85315744009..2a12a41442611 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -10340,6 +10340,8 @@ static void bnxt_sp_task(struct work_struct *work)
+ bnxt_cfg_ntp_filters(bp);
+ if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event))
+ bnxt_hwrm_exec_fwd_req(bp);
++ if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event))
++ netdev_info(bp->dev, "Receive PF driver unload event!\n");
+ if (test_and_clear_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event)) {
+ bnxt_hwrm_tunnel_dst_port_alloc(
+ bp, bp->vxlan_port,
+@@ -11266,8 +11268,6 @@ static void bnxt_cfg_ntp_filters(struct bnxt *bp)
+ }
+ }
+ }
+- if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event))
+- netdev_info(bp->dev, "Receive PF driver unload event!");
+ }
+
+ #else
+--
+2.43.0
+
--- /dev/null
+From f5a70e0c671d9daf9c8a5dfc7a1ffb2e59cb5cbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Dec 2022 10:10:08 +0100
+Subject: can: raw: add support for SO_MARK
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit 0826e82b8a32e646b7b32ba8b68ba30812028e47 ]
+
+Add support for SO_MARK to the CAN_RAW protocol. This makes it
+possible to add traffic control filters based on the fwmark.
+
+Link: https://lore.kernel.org/all/20221210113653.170346-1-mkl@pengutronix.de
+Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Stable-dep-of: 7f6ca95d16b9 ("net: Implement missing getsockopt(SO_TIMESTAMPING_NEW)")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/can/raw.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/can/raw.c b/net/can/raw.c
+index 2700153262771..2f500d8a0af24 100644
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -826,6 +826,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
+ skb->dev = dev;
+ skb->sk = sk;
+ skb->priority = sk->sk_priority;
++ skb->mark = sk->sk_mark;
+ skb->tstamp = sockc.transmit_time;
+
+ skb_setup_tx_timestamp(skb, sockc.tsflags);
+--
+2.43.0
+
--- /dev/null
+From 441f593b2aca37ef5de4096f16b22b2e27761fa9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Apr 2022 12:31:52 +0200
+Subject: can: raw: add support for SO_TXTIME/SCM_TXTIME
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit 51a0d5e51178fcd147c1b8fdab2ed16b561326db ]
+
+This patch calls into sock_cmsg_send() to parse the user supplied
+control information into a struct sockcm_cookie. Then assign the
+requested transmit time to the skb.
+
+This makes it possible to use the Earliest TXTIME First (ETF) packet
+scheduler with the CAN_RAW protocol. The user can send a CAN_RAW frame
+with a TXTIME and the kernel (with the ETF scheduler) will take care
+of sending it to the network interface.
+
+Link: https://lore.kernel.org/all/20220502091946.1916211-3-mkl@pengutronix.de
+Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Stable-dep-of: 7f6ca95d16b9 ("net: Implement missing getsockopt(SO_TIMESTAMPING_NEW)")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/can/raw.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/net/can/raw.c b/net/can/raw.c
+index bb837019d1724..2700153262771 100644
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -770,6 +770,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
+ {
+ struct sock *sk = sock->sk;
+ struct raw_sock *ro = raw_sk(sk);
++ struct sockcm_cookie sockc;
+ struct sk_buff *skb;
+ struct net_device *dev;
+ int ifindex;
+@@ -815,11 +816,19 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
+ if (err < 0)
+ goto free_skb;
+
+- skb_setup_tx_timestamp(skb, sk->sk_tsflags);
++ sockcm_init(&sockc, sk);
++ if (msg->msg_controllen) {
++ err = sock_cmsg_send(sk, msg, &sockc);
++ if (unlikely(err))
++ goto free_skb;
++ }
+
+ skb->dev = dev;
+ skb->sk = sk;
+ skb->priority = sk->sk_priority;
++ skb->tstamp = sockc.transmit_time;
++
++ skb_setup_tx_timestamp(skb, sockc.tsflags);
+
+ err = can_send(skb, ro->loopback);
+
+--
+2.43.0
+
--- /dev/null
+From faa4d14fabcef705e8648878e038617a0ceff4c2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Nov 2023 11:23:11 +0100
+Subject: i40e: Fix filter input checks to prevent config with invalid values
+
+From: Sudheer Mogilappagari <sudheer.mogilappagari@intel.com>
+
+[ Upstream commit 3e48041d9820c17e0a51599d12e66c6e12a8d08d ]
+
+Prevent VF from configuring filters with unsupported actions or use
+REDIRECT action with invalid tc number. Current checks could cause
+out of bounds access on PF side.
+
+Fixes: e284fc280473 ("i40e: Add and delete cloud filter")
+Reviewed-by: Andrii Staikov <andrii.staikov@intel.com>
+Signed-off-by: Sudheer Mogilappagari <sudheer.mogilappagari@intel.com>
+Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Bharathi Sreenivas <bharathi.sreenivas@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+index 37ce764ed3730..d53e535a447d6 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+@@ -3332,16 +3332,16 @@ static int i40e_validate_cloud_filter(struct i40e_vf *vf,
+ bool found = false;
+ int bkt;
+
+- if (!tc_filter->action) {
++ if (tc_filter->action != VIRTCHNL_ACTION_TC_REDIRECT) {
+ dev_info(&pf->pdev->dev,
+- "VF %d: Currently ADq doesn't support Drop Action\n",
+- vf->vf_id);
++ "VF %d: ADQ doesn't support this action (%d)\n",
++ vf->vf_id, tc_filter->action);
+ goto err;
+ }
+
+ /* action_meta is TC number here to which the filter is applied */
+ if (!tc_filter->action_meta ||
+- tc_filter->action_meta > I40E_MAX_VF_VSI) {
++ tc_filter->action_meta > vf->num_tc) {
+ dev_info(&pf->pdev->dev, "VF %d: Invalid TC number %u\n",
+ vf->vf_id, tc_filter->action_meta);
+ goto err;
+--
+2.43.0
+
--- /dev/null
+From 2c9bb1cbe44e9d6c27f97c554cf8214d40f1f345 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 Dec 2023 15:08:50 +0800
+Subject: i40e: fix use-after-free in i40e_aqc_add_filters()
+
+From: Ke Xiao <xiaoke@sangfor.com.cn>
+
+[ Upstream commit 6a15584e99db8918b60e507539c7446375dcf366 ]
+
+Commit 3116f59c12bd ("i40e: fix use-after-free in
+i40e_sync_filters_subtask()") avoided use-after-free issues,
+by increasing refcount during update the VSI filter list to
+the HW. However, it missed the unicast situation.
+
+When deleting an unicast FDB entry, the i40e driver will release
+the mac_filter, and i40e_service_task will concurrently request
+firmware to add the mac_filter, which will lead to the following
+use-after-free issue.
+
+Fix again for both netdev->uc and netdev->mc.
+
+BUG: KASAN: use-after-free in i40e_aqc_add_filters+0x55c/0x5b0 [i40e]
+Read of size 2 at addr ffff888eb3452d60 by task kworker/8:7/6379
+
+CPU: 8 PID: 6379 Comm: kworker/8:7 Kdump: loaded Tainted: G
+Workqueue: i40e i40e_service_task [i40e]
+Call Trace:
+ dump_stack+0x71/0xab
+ print_address_description+0x6b/0x290
+ kasan_report+0x14a/0x2b0
+ i40e_aqc_add_filters+0x55c/0x5b0 [i40e]
+ i40e_sync_vsi_filters+0x1676/0x39c0 [i40e]
+ i40e_service_task+0x1397/0x2bb0 [i40e]
+ process_one_work+0x56a/0x11f0
+ worker_thread+0x8f/0xf40
+ kthread+0x2a0/0x390
+ ret_from_fork+0x1f/0x40
+
+Allocated by task 21948:
+ kasan_kmalloc+0xa6/0xd0
+ kmem_cache_alloc_trace+0xdb/0x1c0
+ i40e_add_filter+0x11e/0x520 [i40e]
+ i40e_addr_sync+0x37/0x60 [i40e]
+ __hw_addr_sync_dev+0x1f5/0x2f0
+ i40e_set_rx_mode+0x61/0x1e0 [i40e]
+ dev_uc_add_excl+0x137/0x190
+ i40e_ndo_fdb_add+0x161/0x260 [i40e]
+ rtnl_fdb_add+0x567/0x950
+ rtnetlink_rcv_msg+0x5db/0x880
+ netlink_rcv_skb+0x254/0x380
+ netlink_unicast+0x454/0x610
+ netlink_sendmsg+0x747/0xb00
+ sock_sendmsg+0xe2/0x120
+ __sys_sendto+0x1ae/0x290
+ __x64_sys_sendto+0xdd/0x1b0
+ do_syscall_64+0xa0/0x370
+ entry_SYSCALL_64_after_hwframe+0x65/0xca
+
+Freed by task 21948:
+ __kasan_slab_free+0x137/0x190
+ kfree+0x8b/0x1b0
+ __i40e_del_filter+0x116/0x1e0 [i40e]
+ i40e_del_mac_filter+0x16c/0x300 [i40e]
+ i40e_addr_unsync+0x134/0x1b0 [i40e]
+ __hw_addr_sync_dev+0xff/0x2f0
+ i40e_set_rx_mode+0x61/0x1e0 [i40e]
+ dev_uc_del+0x77/0x90
+ rtnl_fdb_del+0x6a5/0x860
+ rtnetlink_rcv_msg+0x5db/0x880
+ netlink_rcv_skb+0x254/0x380
+ netlink_unicast+0x454/0x610
+ netlink_sendmsg+0x747/0xb00
+ sock_sendmsg+0xe2/0x120
+ __sys_sendto+0x1ae/0x290
+ __x64_sys_sendto+0xdd/0x1b0
+ do_syscall_64+0xa0/0x370
+ entry_SYSCALL_64_after_hwframe+0x65/0xca
+
+Fixes: 3116f59c12bd ("i40e: fix use-after-free in i40e_sync_filters_subtask()")
+Fixes: 41c445ff0f48 ("i40e: main driver core")
+Signed-off-by: Ke Xiao <xiaoke@sangfor.com.cn>
+Signed-off-by: Ding Hui <dinghui@sangfor.com.cn>
+Cc: Di Zhu <zhudi2@huawei.com>
+Reviewed-by: Jan Sokolowski <jan.sokolowski@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e_main.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index 3ccc248b1a8a7..b44ba73414831 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -110,12 +110,18 @@ static struct workqueue_struct *i40e_wq;
+ static void netdev_hw_addr_refcnt(struct i40e_mac_filter *f,
+ struct net_device *netdev, int delta)
+ {
++ struct netdev_hw_addr_list *ha_list;
+ struct netdev_hw_addr *ha;
+
+ if (!f || !netdev)
+ return;
+
+- netdev_for_each_mc_addr(ha, netdev) {
++ if (is_unicast_ether_addr(f->macaddr) || is_link_local_ether_addr(f->macaddr))
++ ha_list = &netdev->uc;
++ else
++ ha_list = &netdev->mc;
++
++ netdev_hw_addr_list_for_each(ha, ha_list) {
+ if (ether_addr_equal(ha->addr, f->macaddr)) {
+ ha->refcount += delta;
+ if (ha->refcount <= 0)
+--
+2.43.0
+
--- /dev/null
+From 41f8897d0779f4bb7243d35fed836de51600902e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Dec 2023 14:27:35 +0100
+Subject: i40e: Restore VF MSI-X state during PCI reset
+
+From: Andrii Staikov <andrii.staikov@intel.com>
+
+[ Upstream commit 371e576ff3e8580d91d49026e5d5faebf5565558 ]
+
+During a PCI FLR the MSI-X Enable flag in the VF PCI MSI-X capability
+register will be cleared. This can lead to issues when a VF is
+assigned to a VM because in these cases the VF driver receives no
+indication of the PF PCI error/reset and additionally it is incapable
+of restoring the cleared flag in the hypervisor configuration space
+without fully reinitializing the driver interrupt functionality.
+
+Since the VF driver is unable to easily resolve this condition on its own,
+restore the VF MSI-X flag during the PF PCI reset handling.
+
+Fixes: 19b7960b2da1 ("i40e: implement split PCI error reset handler")
+Co-developed-by: Karen Ostrowska <karen.ostrowska@intel.com>
+Signed-off-by: Karen Ostrowska <karen.ostrowska@intel.com>
+Co-developed-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
+Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Signed-off-by: Andrii Staikov <andrii.staikov@intel.com>
+Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e_main.c | 3 +++
+ .../ethernet/intel/i40e/i40e_virtchnl_pf.c | 26 +++++++++++++++++++
+ .../ethernet/intel/i40e/i40e_virtchnl_pf.h | 3 +++
+ 3 files changed, 32 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index b44ba73414831..fa938281281a4 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -15716,6 +15716,9 @@ static void i40e_pci_error_reset_done(struct pci_dev *pdev)
+ struct i40e_pf *pf = pci_get_drvdata(pdev);
+
+ i40e_reset_and_rebuild(pf, false, false);
++#ifdef CONFIG_PCI_IOV
++ i40e_restore_all_vfs_msi_state(pdev);
++#endif /* CONFIG_PCI_IOV */
+ }
+
+ /**
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+index d53e535a447d6..e79b8dc5c2a5e 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+@@ -99,6 +99,32 @@ void i40e_vc_notify_reset(struct i40e_pf *pf)
+ (u8 *)&pfe, sizeof(struct virtchnl_pf_event));
+ }
+
++#ifdef CONFIG_PCI_IOV
++void i40e_restore_all_vfs_msi_state(struct pci_dev *pdev)
++{
++ u16 vf_id;
++ u16 pos;
++
++ /* Continue only if this is a PF */
++ if (!pdev->is_physfn)
++ return;
++
++ if (!pci_num_vf(pdev))
++ return;
++
++ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
++ if (pos) {
++ struct pci_dev *vf_dev = NULL;
++
++ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &vf_id);
++ while ((vf_dev = pci_get_device(pdev->vendor, vf_id, vf_dev))) {
++ if (vf_dev->is_virtfn && vf_dev->physfn == pdev)
++ pci_restore_msi_state(vf_dev);
++ }
++ }
++}
++#endif /* CONFIG_PCI_IOV */
++
+ /**
+ * i40e_vc_notify_vf_reset
+ * @vf: pointer to the VF structure
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+index 23182731a73d0..75d916714ad8a 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+@@ -141,5 +141,8 @@ int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable);
+
+ void i40e_vc_notify_link_state(struct i40e_pf *pf);
+ void i40e_vc_notify_reset(struct i40e_pf *pf);
++#ifdef CONFIG_PCI_IOV
++void i40e_restore_all_vfs_msi_state(struct pci_dev *pdev);
++#endif /* CONFIG_PCI_IOV */
+
+ #endif /* _I40E_VIRTCHNL_PF_H_ */
+--
+2.43.0
+
--- /dev/null
+From d913c79b96102a56cc4f7a330309eb8f0166791d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 Dec 2023 13:58:36 +0000
+Subject: mm/memory-failure: check the mapcount of the precise page
+
+From: Matthew Wilcox (Oracle) <willy@infradead.org>
+
+[ Upstream commit c79c5a0a00a9457718056b588f312baadf44e471 ]
+
+A process may map only some of the pages in a folio, and might be missed
+if it maps the poisoned page but not the head page. Or it might be
+unnecessarily hit if it maps the head page, but not the poisoned page.
+
+Link: https://lkml.kernel.org/r/20231218135837.3310403-3-willy@infradead.org
+Fixes: 7af446a841a2 ("HWPOISON, hugetlb: enable error handling path for hugepage")
+Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/memory-failure.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/mm/memory-failure.c b/mm/memory-failure.c
+index 9030ab0d9d975..c6453f9ffd4d9 100644
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -986,7 +986,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
+ * This check implies we don't kill processes if their pages
+ * are in the swap cache early. Those are always late kills.
+ */
+- if (!page_mapped(hpage))
++ if (!page_mapped(p))
+ return true;
+
+ if (PageKsm(p)) {
+@@ -1030,10 +1030,10 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
+ if (kill)
+ collect_procs(hpage, &tokill, flags & MF_ACTION_REQUIRED);
+
+- unmap_success = try_to_unmap(hpage, ttu);
++ unmap_success = try_to_unmap(p, ttu);
+ if (!unmap_success)
+ pr_err("Memory failure: %#lx: failed to unmap page (mapcount=%d)\n",
+- pfn, page_mapcount(hpage));
++ pfn, page_mapcount(p));
+
+ /*
+ * try_to_unmap() might put mlocked page in lru cache, so call
+--
+2.43.0
+
--- /dev/null
+From 71959784908d9b9b24f945b2df35b25bc6fac9ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Dec 2023 14:56:38 +0100
+Subject: net: bcmgenet: Fix FCS generation for fragmented skbuffs
+
+From: Adrian Cinal <adriancinal@gmail.com>
+
+[ Upstream commit e584f2ff1e6cc9b1d99e8a6b0f3415940d1b3eb3 ]
+
+The flag DMA_TX_APPEND_CRC was only written to the first DMA descriptor
+in the TX path, where each descriptor corresponds to a single skbuff
+fragment (or the skbuff head). This led to packets with no FCS appearing
+on the wire if the kernel allocated the packet in fragments, which would
+always happen when using PACKET_MMAP/TPACKET (cf. tpacket_fill_skb() in
+net/af_packet.c).
+
+Fixes: 1c1008c793fa ("net: bcmgenet: add main driver file")
+Signed-off-by: Adrian Cinal <adriancinal1@gmail.com>
+Acked-by: Doug Berger <opendmb@gmail.com>
+Acked-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://lore.kernel.org/r/20231228135638.1339245-1-adriancinal1@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+index 750acbf294640..eeadeeec17bab 100644
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+@@ -1648,8 +1648,10 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
+ /* Note: if we ever change from DMA_TX_APPEND_CRC below we
+ * will need to restore software padding of "runt" packets
+ */
++ len_stat |= DMA_TX_APPEND_CRC;
++
+ if (!i) {
+- len_stat |= DMA_TX_APPEND_CRC | DMA_SOP;
++ len_stat |= DMA_SOP;
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ len_stat |= DMA_TX_DO_CSUM;
+ }
+--
+2.43.0
+
--- /dev/null
+From 55f187e0dfd93dc016c60cef248642274ab0d255 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Dec 2023 00:19:01 +0100
+Subject: net: Implement missing getsockopt(SO_TIMESTAMPING_NEW)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jörn-Thorben Hinz <jthinz@mailbox.tu-berlin.de>
+
+[ Upstream commit 7f6ca95d16b96567ce4cf458a2790ff17fa620c3 ]
+
+Commit 9718475e6908 ("socket: Add SO_TIMESTAMPING_NEW") added the new
+socket option SO_TIMESTAMPING_NEW. Setting the option is handled in
+sk_setsockopt(), querying it was not handled in sk_getsockopt(), though.
+
+Following remarks on an earlier submission of this patch, keep the old
+behavior of getsockopt(SO_TIMESTAMPING_OLD) which returns the active
+flags even if they actually have been set through SO_TIMESTAMPING_NEW.
+
+The new getsockopt(SO_TIMESTAMPING_NEW) is stricter, returning flags
+only if they have been set through the same option.
+
+Fixes: 9718475e6908 ("socket: Add SO_TIMESTAMPING_NEW")
+Link: https://lore.kernel.org/lkml/20230703175048.151683-1-jthinz@mailbox.tu-berlin.de/
+Link: https://lore.kernel.org/netdev/0d7cddc9-03fa-43db-a579-14f3e822615b@app.fastmail.com/
+Signed-off-by: Jörn-Thorben Hinz <jthinz@mailbox.tu-berlin.de>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 2c3c5df139345..a3ca522434a6e 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -1309,9 +1309,16 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case SO_LINGER:
++ case SO_TIMESTAMPING_NEW:
+ lv = sizeof(v.ling);
+- v.ling.l_onoff = sock_flag(sk, SOCK_LINGER);
+- v.ling.l_linger = sk->sk_lingertime / HZ;
++ /* For the later-added case SO_TIMESTAMPING_NEW: Be strict about only
++ * returning the flags when they were set through the same option.
++ * Don't change the beviour for the old case SO_TIMESTAMPING_OLD.
++ */
++ if (optname == SO_TIMESTAMPING_OLD || sock_flag(sk, SOCK_TSTAMP_NEW)) {
++ v.ling.l_onoff = sock_flag(sk, SOCK_LINGER);
++ v.ling.l_linger = sk->sk_lingertime / HZ;
++ }
+ break;
+
+ case SO_BSDCOMPAT:
+--
+2.43.0
+
--- /dev/null
+From 0af316372dd6fb4069a2aed54f46e4fcfed359f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jan 2024 09:57:44 +0100
+Subject: net: Implement missing SO_TIMESTAMPING_NEW cmsg support
+
+From: Thomas Lange <thomas@corelatus.se>
+
+[ Upstream commit 382a32018b74f407008615e0e831d05ed28e81cd ]
+
+Commit 9718475e6908 ("socket: Add SO_TIMESTAMPING_NEW") added the new
+socket option SO_TIMESTAMPING_NEW. However, it was never implemented in
+__sock_cmsg_send thus breaking SO_TIMESTAMPING cmsg for platforms using
+SO_TIMESTAMPING_NEW.
+
+Fixes: 9718475e6908 ("socket: Add SO_TIMESTAMPING_NEW")
+Link: https://lore.kernel.org/netdev/6a7281bf-bc4a-4f75-bb88-7011908ae471@app.fastmail.com/
+Signed-off-by: Thomas Lange <thomas@corelatus.se>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://lore.kernel.org/r/20240104085744.49164-1-thomas@corelatus.se
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index a3ca522434a6e..42076a3e12c3c 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -2310,6 +2310,7 @@ int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
+ sockc->mark = *(u32 *)CMSG_DATA(cmsg);
+ break;
+ case SO_TIMESTAMPING_OLD:
++ case SO_TIMESTAMPING_NEW:
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32)))
+ return -EINVAL;
+
+--
+2.43.0
+
--- /dev/null
+From d0e8b2dc79f2badceaf9f4307b2c8e634a7ef3c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Dec 2023 15:02:27 +0800
+Subject: net/qla3xxx: fix potential memleak in ql_alloc_buffer_queues
+
+From: Dinghao Liu <dinghao.liu@zju.edu.cn>
+
+[ Upstream commit 89f45c30172c80e55c887f32f1af8e184124577b ]
+
+When dma_alloc_coherent() fails, we should free qdev->lrg_buf
+to prevent potential memleak.
+
+Fixes: 1357bfcf7106 ("qla3xxx: Dynamically size the rx buffer queue based on the MTU.")
+Signed-off-by: Dinghao Liu <dinghao.liu@zju.edu.cn>
+Link: https://lore.kernel.org/r/20231227070227.10527-1-dinghao.liu@zju.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/qlogic/qla3xxx.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
+index 65cdf1bfbddb8..5d0e65a3b6a83 100644
+--- a/drivers/net/ethernet/qlogic/qla3xxx.c
++++ b/drivers/net/ethernet/qlogic/qla3xxx.c
+@@ -2590,6 +2590,7 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
+
+ if (qdev->lrg_buf_q_alloc_virt_addr == NULL) {
+ netdev_err(qdev->ndev, "lBufQ failed\n");
++ kfree(qdev->lrg_buf);
+ return -ENOMEM;
+ }
+ qdev->lrg_buf_q_virt_addr = qdev->lrg_buf_q_alloc_virt_addr;
+@@ -2614,6 +2615,7 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
+ qdev->lrg_buf_q_alloc_size,
+ qdev->lrg_buf_q_alloc_virt_addr,
+ qdev->lrg_buf_q_alloc_phy_addr);
++ kfree(qdev->lrg_buf);
+ return -ENOMEM;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From ea2fbddcfdf85d30cfb860c12f04955dcc3c02a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 17 Jan 2021 09:15:42 +0100
+Subject: net/qla3xxx: switch from 'pci_' to 'dma_' API
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 41fb4c1ba7478fe34c7e094e124e4ee4513b9763 ]
+
+The wrappers in include/linux/pci-dma-compat.h should go away.
+
+The patch has been generated with the coccinelle script below and has been
+hand modified to replace GFP_ with a correct flag.
+It has been compile tested.
+
+When memory is allocated in 'ql_alloc_net_req_rsp_queues()' GFP_KERNEL can
+be used because it is only called from 'ql_alloc_mem_resources()' which
+already calls 'ql_alloc_buffer_queues()' which uses GFP_KERNEL. (see below)
+
+When memory is allocated in 'ql_alloc_buffer_queues()' GFP_KERNEL can be
+used because this flag is already used just a few line above.
+
+When memory is allocated in 'ql_alloc_small_buffers()' GFP_KERNEL can
+be used because it is only called from 'ql_alloc_mem_resources()' which
+already calls 'ql_alloc_buffer_queues()' which uses GFP_KERNEL. (see above)
+
+When memory is allocated in 'ql_alloc_mem_resources()' GFP_KERNEL can be
+used because this function already calls 'ql_alloc_buffer_queues()' which
+uses GFP_KERNEL. (see above)
+
+While at it, use 'dma_set_mask_and_coherent()' instead of 'dma_set_mask()/
+dma_set_coherent_mask()' in order to slightly simplify code.
+
+@@
+@@
+- PCI_DMA_BIDIRECTIONAL
++ DMA_BIDIRECTIONAL
+
+@@
+@@
+- PCI_DMA_TODEVICE
++ DMA_TO_DEVICE
+
+@@
+@@
+- PCI_DMA_FROMDEVICE
++ DMA_FROM_DEVICE
+
+@@
+@@
+- PCI_DMA_NONE
++ DMA_NONE
+
+@@
+expression e1, e2, e3;
+@@
+- pci_alloc_consistent(e1, e2, e3)
++ dma_alloc_coherent(&e1->dev, e2, e3, GFP_)
+
+@@
+expression e1, e2, e3;
+@@
+- pci_zalloc_consistent(e1, e2, e3)
++ dma_alloc_coherent(&e1->dev, e2, e3, GFP_)
+
+@@
+expression e1, e2, e3, e4;
+@@
+- pci_free_consistent(e1, e2, e3, e4)
++ dma_free_coherent(&e1->dev, e2, e3, e4)
+
+@@
+expression e1, e2, e3, e4;
+@@
+- pci_map_single(e1, e2, e3, e4)
++ dma_map_single(&e1->dev, e2, e3, e4)
+
+@@
+expression e1, e2, e3, e4;
+@@
+- pci_unmap_single(e1, e2, e3, e4)
++ dma_unmap_single(&e1->dev, e2, e3, e4)
+
+@@
+expression e1, e2, e3, e4, e5;
+@@
+- pci_map_page(e1, e2, e3, e4, e5)
++ dma_map_page(&e1->dev, e2, e3, e4, e5)
+
+@@
+expression e1, e2, e3, e4;
+@@
+- pci_unmap_page(e1, e2, e3, e4)
++ dma_unmap_page(&e1->dev, e2, e3, e4)
+
+@@
+expression e1, e2, e3, e4;
+@@
+- pci_map_sg(e1, e2, e3, e4)
++ dma_map_sg(&e1->dev, e2, e3, e4)
+
+@@
+expression e1, e2, e3, e4;
+@@
+- pci_unmap_sg(e1, e2, e3, e4)
++ dma_unmap_sg(&e1->dev, e2, e3, e4)
+
+@@
+expression e1, e2, e3, e4;
+@@
+- pci_dma_sync_single_for_cpu(e1, e2, e3, e4)
++ dma_sync_single_for_cpu(&e1->dev, e2, e3, e4)
+
+@@
+expression e1, e2, e3, e4;
+@@
+- pci_dma_sync_single_for_device(e1, e2, e3, e4)
++ dma_sync_single_for_device(&e1->dev, e2, e3, e4)
+
+@@
+expression e1, e2, e3, e4;
+@@
+- pci_dma_sync_sg_for_cpu(e1, e2, e3, e4)
++ dma_sync_sg_for_cpu(&e1->dev, e2, e3, e4)
+
+@@
+expression e1, e2, e3, e4;
+@@
+- pci_dma_sync_sg_for_device(e1, e2, e3, e4)
++ dma_sync_sg_for_device(&e1->dev, e2, e3, e4)
+
+@@
+expression e1, e2;
+@@
+- pci_dma_mapping_error(e1, e2)
++ dma_mapping_error(&e1->dev, e2)
+
+@@
+expression e1, e2;
+@@
+- pci_set_dma_mask(e1, e2)
++ dma_set_mask(&e1->dev, e2)
+
+@@
+expression e1, e2;
+@@
+- pci_set_consistent_dma_mask(e1, e2)
++ dma_set_coherent_mask(&e1->dev, e2)
+
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Link: https://lore.kernel.org/r/20210117081542.560021-1-christophe.jaillet@wanadoo.fr
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 89f45c30172c ("net/qla3xxx: fix potential memleak in ql_alloc_buffer_queues")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/qlogic/qla3xxx.c | 196 ++++++++++++--------------
+ 1 file changed, 87 insertions(+), 109 deletions(-)
+
+diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
+index 2fa68592210d7..65cdf1bfbddb8 100644
+--- a/drivers/net/ethernet/qlogic/qla3xxx.c
++++ b/drivers/net/ethernet/qlogic/qla3xxx.c
+@@ -316,12 +316,11 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
+ * buffer
+ */
+ skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE);
+- map = pci_map_single(qdev->pdev,
++ map = dma_map_single(&qdev->pdev->dev,
+ lrg_buf_cb->skb->data,
+- qdev->lrg_buffer_len -
+- QL_HEADER_SPACE,
+- PCI_DMA_FROMDEVICE);
+- err = pci_dma_mapping_error(qdev->pdev, map);
++ qdev->lrg_buffer_len - QL_HEADER_SPACE,
++ DMA_FROM_DEVICE);
++ err = dma_mapping_error(&qdev->pdev->dev, map);
+ if (err) {
+ netdev_err(qdev->ndev,
+ "PCI mapping failed with error: %d\n",
+@@ -1803,13 +1802,12 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev)
+ * first buffer
+ */
+ skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE);
+- map = pci_map_single(qdev->pdev,
++ map = dma_map_single(&qdev->pdev->dev,
+ lrg_buf_cb->skb->data,
+- qdev->lrg_buffer_len -
+- QL_HEADER_SPACE,
+- PCI_DMA_FROMDEVICE);
++ qdev->lrg_buffer_len - QL_HEADER_SPACE,
++ DMA_FROM_DEVICE);
+
+- err = pci_dma_mapping_error(qdev->pdev, map);
++ err = dma_mapping_error(&qdev->pdev->dev, map);
+ if (err) {
+ netdev_err(qdev->ndev,
+ "PCI mapping failed with error: %d\n",
+@@ -1944,18 +1942,16 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
+ goto invalid_seg_count;
+ }
+
+- pci_unmap_single(qdev->pdev,
++ dma_unmap_single(&qdev->pdev->dev,
+ dma_unmap_addr(&tx_cb->map[0], mapaddr),
+- dma_unmap_len(&tx_cb->map[0], maplen),
+- PCI_DMA_TODEVICE);
++ dma_unmap_len(&tx_cb->map[0], maplen), DMA_TO_DEVICE);
+ tx_cb->seg_count--;
+ if (tx_cb->seg_count) {
+ for (i = 1; i < tx_cb->seg_count; i++) {
+- pci_unmap_page(qdev->pdev,
+- dma_unmap_addr(&tx_cb->map[i],
+- mapaddr),
++ dma_unmap_page(&qdev->pdev->dev,
++ dma_unmap_addr(&tx_cb->map[i], mapaddr),
+ dma_unmap_len(&tx_cb->map[i], maplen),
+- PCI_DMA_TODEVICE);
++ DMA_TO_DEVICE);
+ }
+ }
+ qdev->ndev->stats.tx_packets++;
+@@ -2022,10 +2018,9 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
+ qdev->ndev->stats.rx_bytes += length;
+
+ skb_put(skb, length);
+- pci_unmap_single(qdev->pdev,
++ dma_unmap_single(&qdev->pdev->dev,
+ dma_unmap_addr(lrg_buf_cb2, mapaddr),
+- dma_unmap_len(lrg_buf_cb2, maplen),
+- PCI_DMA_FROMDEVICE);
++ dma_unmap_len(lrg_buf_cb2, maplen), DMA_FROM_DEVICE);
+ prefetch(skb->data);
+ skb_checksum_none_assert(skb);
+ skb->protocol = eth_type_trans(skb, qdev->ndev);
+@@ -2068,10 +2063,9 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
+ skb2 = lrg_buf_cb2->skb;
+
+ skb_put(skb2, length); /* Just the second buffer length here. */
+- pci_unmap_single(qdev->pdev,
++ dma_unmap_single(&qdev->pdev->dev,
+ dma_unmap_addr(lrg_buf_cb2, mapaddr),
+- dma_unmap_len(lrg_buf_cb2, maplen),
+- PCI_DMA_FROMDEVICE);
++ dma_unmap_len(lrg_buf_cb2, maplen), DMA_FROM_DEVICE);
+ prefetch(skb2->data);
+
+ skb_checksum_none_assert(skb2);
+@@ -2320,9 +2314,9 @@ static int ql_send_map(struct ql3_adapter *qdev,
+ /*
+ * Map the skb buffer first.
+ */
+- map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE);
++ map = dma_map_single(&qdev->pdev->dev, skb->data, len, DMA_TO_DEVICE);
+
+- err = pci_dma_mapping_error(qdev->pdev, map);
++ err = dma_mapping_error(&qdev->pdev->dev, map);
+ if (err) {
+ netdev_err(qdev->ndev, "PCI mapping failed with error: %d\n",
+ err);
+@@ -2358,11 +2352,11 @@ static int ql_send_map(struct ql3_adapter *qdev,
+ (seg == 7 && seg_cnt > 8) ||
+ (seg == 12 && seg_cnt > 13) ||
+ (seg == 17 && seg_cnt > 18)) {
+- map = pci_map_single(qdev->pdev, oal,
++ map = dma_map_single(&qdev->pdev->dev, oal,
+ sizeof(struct oal),
+- PCI_DMA_TODEVICE);
++ DMA_TO_DEVICE);
+
+- err = pci_dma_mapping_error(qdev->pdev, map);
++ err = dma_mapping_error(&qdev->pdev->dev, map);
+ if (err) {
+ netdev_err(qdev->ndev,
+ "PCI mapping outbound address list with error: %d\n",
+@@ -2424,24 +2418,24 @@ static int ql_send_map(struct ql3_adapter *qdev,
+ (seg == 7 && seg_cnt > 8) ||
+ (seg == 12 && seg_cnt > 13) ||
+ (seg == 17 && seg_cnt > 18)) {
+- pci_unmap_single(qdev->pdev,
+- dma_unmap_addr(&tx_cb->map[seg], mapaddr),
+- dma_unmap_len(&tx_cb->map[seg], maplen),
+- PCI_DMA_TODEVICE);
++ dma_unmap_single(&qdev->pdev->dev,
++ dma_unmap_addr(&tx_cb->map[seg], mapaddr),
++ dma_unmap_len(&tx_cb->map[seg], maplen),
++ DMA_TO_DEVICE);
+ oal++;
+ seg++;
+ }
+
+- pci_unmap_page(qdev->pdev,
++ dma_unmap_page(&qdev->pdev->dev,
+ dma_unmap_addr(&tx_cb->map[seg], mapaddr),
+ dma_unmap_len(&tx_cb->map[seg], maplen),
+- PCI_DMA_TODEVICE);
++ DMA_TO_DEVICE);
+ }
+
+- pci_unmap_single(qdev->pdev,
++ dma_unmap_single(&qdev->pdev->dev,
+ dma_unmap_addr(&tx_cb->map[0], mapaddr),
+ dma_unmap_addr(&tx_cb->map[0], maplen),
+- PCI_DMA_TODEVICE);
++ DMA_TO_DEVICE);
+
+ return NETDEV_TX_BUSY;
+
+@@ -2527,9 +2521,8 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
+ wmb();
+
+ qdev->req_q_virt_addr =
+- pci_alloc_consistent(qdev->pdev,
+- (size_t) qdev->req_q_size,
+- &qdev->req_q_phy_addr);
++ dma_alloc_coherent(&qdev->pdev->dev, (size_t)qdev->req_q_size,
++ &qdev->req_q_phy_addr, GFP_KERNEL);
+
+ if ((qdev->req_q_virt_addr == NULL) ||
+ LS_64BITS(qdev->req_q_phy_addr) & (qdev->req_q_size - 1)) {
+@@ -2538,16 +2531,14 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
+ }
+
+ qdev->rsp_q_virt_addr =
+- pci_alloc_consistent(qdev->pdev,
+- (size_t) qdev->rsp_q_size,
+- &qdev->rsp_q_phy_addr);
++ dma_alloc_coherent(&qdev->pdev->dev, (size_t)qdev->rsp_q_size,
++ &qdev->rsp_q_phy_addr, GFP_KERNEL);
+
+ if ((qdev->rsp_q_virt_addr == NULL) ||
+ LS_64BITS(qdev->rsp_q_phy_addr) & (qdev->rsp_q_size - 1)) {
+ netdev_err(qdev->ndev, "rspQ allocation failed\n");
+- pci_free_consistent(qdev->pdev, (size_t) qdev->req_q_size,
+- qdev->req_q_virt_addr,
+- qdev->req_q_phy_addr);
++ dma_free_coherent(&qdev->pdev->dev, (size_t)qdev->req_q_size,
++ qdev->req_q_virt_addr, qdev->req_q_phy_addr);
+ return -ENOMEM;
+ }
+
+@@ -2563,15 +2554,13 @@ static void ql_free_net_req_rsp_queues(struct ql3_adapter *qdev)
+ return;
+ }
+
+- pci_free_consistent(qdev->pdev,
+- qdev->req_q_size,
+- qdev->req_q_virt_addr, qdev->req_q_phy_addr);
++ dma_free_coherent(&qdev->pdev->dev, qdev->req_q_size,
++ qdev->req_q_virt_addr, qdev->req_q_phy_addr);
+
+ qdev->req_q_virt_addr = NULL;
+
+- pci_free_consistent(qdev->pdev,
+- qdev->rsp_q_size,
+- qdev->rsp_q_virt_addr, qdev->rsp_q_phy_addr);
++ dma_free_coherent(&qdev->pdev->dev, qdev->rsp_q_size,
++ qdev->rsp_q_virt_addr, qdev->rsp_q_phy_addr);
+
+ qdev->rsp_q_virt_addr = NULL;
+
+@@ -2595,9 +2584,9 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
+ return -ENOMEM;
+
+ qdev->lrg_buf_q_alloc_virt_addr =
+- pci_alloc_consistent(qdev->pdev,
+- qdev->lrg_buf_q_alloc_size,
+- &qdev->lrg_buf_q_alloc_phy_addr);
++ dma_alloc_coherent(&qdev->pdev->dev,
++ qdev->lrg_buf_q_alloc_size,
++ &qdev->lrg_buf_q_alloc_phy_addr, GFP_KERNEL);
+
+ if (qdev->lrg_buf_q_alloc_virt_addr == NULL) {
+ netdev_err(qdev->ndev, "lBufQ failed\n");
+@@ -2615,15 +2604,16 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
+ qdev->small_buf_q_alloc_size = qdev->small_buf_q_size * 2;
+
+ qdev->small_buf_q_alloc_virt_addr =
+- pci_alloc_consistent(qdev->pdev,
+- qdev->small_buf_q_alloc_size,
+- &qdev->small_buf_q_alloc_phy_addr);
++ dma_alloc_coherent(&qdev->pdev->dev,
++ qdev->small_buf_q_alloc_size,
++ &qdev->small_buf_q_alloc_phy_addr, GFP_KERNEL);
+
+ if (qdev->small_buf_q_alloc_virt_addr == NULL) {
+ netdev_err(qdev->ndev, "Small Buffer Queue allocation failed\n");
+- pci_free_consistent(qdev->pdev, qdev->lrg_buf_q_alloc_size,
+- qdev->lrg_buf_q_alloc_virt_addr,
+- qdev->lrg_buf_q_alloc_phy_addr);
++ dma_free_coherent(&qdev->pdev->dev,
++ qdev->lrg_buf_q_alloc_size,
++ qdev->lrg_buf_q_alloc_virt_addr,
++ qdev->lrg_buf_q_alloc_phy_addr);
+ return -ENOMEM;
+ }
+
+@@ -2640,17 +2630,15 @@ static void ql_free_buffer_queues(struct ql3_adapter *qdev)
+ return;
+ }
+ kfree(qdev->lrg_buf);
+- pci_free_consistent(qdev->pdev,
+- qdev->lrg_buf_q_alloc_size,
+- qdev->lrg_buf_q_alloc_virt_addr,
+- qdev->lrg_buf_q_alloc_phy_addr);
++ dma_free_coherent(&qdev->pdev->dev, qdev->lrg_buf_q_alloc_size,
++ qdev->lrg_buf_q_alloc_virt_addr,
++ qdev->lrg_buf_q_alloc_phy_addr);
+
+ qdev->lrg_buf_q_virt_addr = NULL;
+
+- pci_free_consistent(qdev->pdev,
+- qdev->small_buf_q_alloc_size,
+- qdev->small_buf_q_alloc_virt_addr,
+- qdev->small_buf_q_alloc_phy_addr);
++ dma_free_coherent(&qdev->pdev->dev, qdev->small_buf_q_alloc_size,
++ qdev->small_buf_q_alloc_virt_addr,
++ qdev->small_buf_q_alloc_phy_addr);
+
+ qdev->small_buf_q_virt_addr = NULL;
+
+@@ -2668,9 +2656,9 @@ static int ql_alloc_small_buffers(struct ql3_adapter *qdev)
+ QL_SMALL_BUFFER_SIZE);
+
+ qdev->small_buf_virt_addr =
+- pci_alloc_consistent(qdev->pdev,
+- qdev->small_buf_total_size,
+- &qdev->small_buf_phy_addr);
++ dma_alloc_coherent(&qdev->pdev->dev,
++ qdev->small_buf_total_size,
++ &qdev->small_buf_phy_addr, GFP_KERNEL);
+
+ if (qdev->small_buf_virt_addr == NULL) {
+ netdev_err(qdev->ndev, "Failed to get small buffer memory\n");
+@@ -2703,10 +2691,10 @@ static void ql_free_small_buffers(struct ql3_adapter *qdev)
+ return;
+ }
+ if (qdev->small_buf_virt_addr != NULL) {
+- pci_free_consistent(qdev->pdev,
+- qdev->small_buf_total_size,
+- qdev->small_buf_virt_addr,
+- qdev->small_buf_phy_addr);
++ dma_free_coherent(&qdev->pdev->dev,
++ qdev->small_buf_total_size,
++ qdev->small_buf_virt_addr,
++ qdev->small_buf_phy_addr);
+
+ qdev->small_buf_virt_addr = NULL;
+ }
+@@ -2721,10 +2709,10 @@ static void ql_free_large_buffers(struct ql3_adapter *qdev)
+ lrg_buf_cb = &qdev->lrg_buf[i];
+ if (lrg_buf_cb->skb) {
+ dev_kfree_skb(lrg_buf_cb->skb);
+- pci_unmap_single(qdev->pdev,
++ dma_unmap_single(&qdev->pdev->dev,
+ dma_unmap_addr(lrg_buf_cb, mapaddr),
+ dma_unmap_len(lrg_buf_cb, maplen),
+- PCI_DMA_FROMDEVICE);
++ DMA_FROM_DEVICE);
+ memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb));
+ } else {
+ break;
+@@ -2776,13 +2764,11 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
+ * buffer
+ */
+ skb_reserve(skb, QL_HEADER_SPACE);
+- map = pci_map_single(qdev->pdev,
+- skb->data,
+- qdev->lrg_buffer_len -
+- QL_HEADER_SPACE,
+- PCI_DMA_FROMDEVICE);
++ map = dma_map_single(&qdev->pdev->dev, skb->data,
++ qdev->lrg_buffer_len - QL_HEADER_SPACE,
++ DMA_FROM_DEVICE);
+
+- err = pci_dma_mapping_error(qdev->pdev, map);
++ err = dma_mapping_error(&qdev->pdev->dev, map);
+ if (err) {
+ netdev_err(qdev->ndev,
+ "PCI mapping failed with error: %d\n",
+@@ -2867,8 +2853,8 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
+ * Network Completion Queue Producer Index Register
+ */
+ qdev->shadow_reg_virt_addr =
+- pci_alloc_consistent(qdev->pdev,
+- PAGE_SIZE, &qdev->shadow_reg_phy_addr);
++ dma_alloc_coherent(&qdev->pdev->dev, PAGE_SIZE,
++ &qdev->shadow_reg_phy_addr, GFP_KERNEL);
+
+ if (qdev->shadow_reg_virt_addr != NULL) {
+ qdev->preq_consumer_index = qdev->shadow_reg_virt_addr;
+@@ -2923,10 +2909,9 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
+ err_buffer_queues:
+ ql_free_net_req_rsp_queues(qdev);
+ err_req_rsp:
+- pci_free_consistent(qdev->pdev,
+- PAGE_SIZE,
+- qdev->shadow_reg_virt_addr,
+- qdev->shadow_reg_phy_addr);
++ dma_free_coherent(&qdev->pdev->dev, PAGE_SIZE,
++ qdev->shadow_reg_virt_addr,
++ qdev->shadow_reg_phy_addr);
+
+ return -ENOMEM;
+ }
+@@ -2939,10 +2924,9 @@ static void ql_free_mem_resources(struct ql3_adapter *qdev)
+ ql_free_buffer_queues(qdev);
+ ql_free_net_req_rsp_queues(qdev);
+ if (qdev->shadow_reg_virt_addr != NULL) {
+- pci_free_consistent(qdev->pdev,
+- PAGE_SIZE,
+- qdev->shadow_reg_virt_addr,
+- qdev->shadow_reg_phy_addr);
++ dma_free_coherent(&qdev->pdev->dev, PAGE_SIZE,
++ qdev->shadow_reg_virt_addr,
++ qdev->shadow_reg_phy_addr);
+ qdev->shadow_reg_virt_addr = NULL;
+ }
+ }
+@@ -3643,18 +3627,15 @@ static void ql_reset_work(struct work_struct *work)
+ if (tx_cb->skb) {
+ netdev_printk(KERN_DEBUG, ndev,
+ "Freeing lost SKB\n");
+- pci_unmap_single(qdev->pdev,
+- dma_unmap_addr(&tx_cb->map[0],
+- mapaddr),
+- dma_unmap_len(&tx_cb->map[0], maplen),
+- PCI_DMA_TODEVICE);
++ dma_unmap_single(&qdev->pdev->dev,
++ dma_unmap_addr(&tx_cb->map[0], mapaddr),
++ dma_unmap_len(&tx_cb->map[0], maplen),
++ DMA_TO_DEVICE);
+ for (j = 1; j < tx_cb->seg_count; j++) {
+- pci_unmap_page(qdev->pdev,
+- dma_unmap_addr(&tx_cb->map[j],
+- mapaddr),
+- dma_unmap_len(&tx_cb->map[j],
+- maplen),
+- PCI_DMA_TODEVICE);
++ dma_unmap_page(&qdev->pdev->dev,
++ dma_unmap_addr(&tx_cb->map[j], mapaddr),
++ dma_unmap_len(&tx_cb->map[j], maplen),
++ DMA_TO_DEVICE);
+ }
+ dev_kfree_skb(tx_cb->skb);
+ tx_cb->skb = NULL;
+@@ -3786,13 +3767,10 @@ static int ql3xxx_probe(struct pci_dev *pdev,
+
+ pci_set_master(pdev);
+
+- if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
++ if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)))
+ pci_using_dac = 1;
+- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+- } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
++ else if (!(err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))))
+ pci_using_dac = 0;
+- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+- }
+
+ if (err) {
+ pr_err("%s no usable DMA configuration\n", pci_name(pdev));
+--
+2.43.0
+
--- /dev/null
+From d1cbbf3db417201a8d257cb065aa556ebe802fcb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Dec 2023 09:12:30 -0400
+Subject: net: Save and restore msg_namelen in sock_sendmsg
+
+From: Marc Dionne <marc.dionne@auristor.com>
+
+[ Upstream commit 01b2885d9415152bcb12ff1f7788f500a74ea0ed ]
+
+Commit 86a7e0b69bd5 ("net: prevent rewrite of msg_name in
+sock_sendmsg()") made sock_sendmsg save the incoming msg_name pointer
+and restore it before returning, to insulate the caller against
+msg_name being changed by the called code. If the address length
+was also changed however, we may return with an inconsistent structure
+where the length doesn't match the address, and attempts to reuse it may
+lead to lost packets.
+
+For example, a kernel that doesn't have commit 1c5950fc6fe9 ("udp6: fix
+potential access to stale information") will replace a v4 mapped address
+with its ipv4 equivalent, and shorten namelen accordingly from 28 to 16.
+If the caller attempts to reuse the resulting msg structure, it will have
+the original ipv6 (v4 mapped) address but an incorrect v4 length.
+
+Fixes: 86a7e0b69bd5 ("net: prevent rewrite of msg_name in sock_sendmsg()")
+Signed-off-by: Marc Dionne <marc.dionne@auristor.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/socket.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/socket.c b/net/socket.c
+index 38c26e20511d7..e3a50f107d64d 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -661,6 +661,7 @@ int sock_sendmsg(struct socket *sock, struct msghdr *msg)
+ {
+ struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name;
+ struct sockaddr_storage address;
++ int save_len = msg->msg_namelen;
+ int ret;
+
+ if (msg->msg_name) {
+@@ -670,6 +671,7 @@ int sock_sendmsg(struct socket *sock, struct msghdr *msg)
+
+ ret = __sock_sendmsg(sock, msg);
+ msg->msg_name = save_addr;
++ msg->msg_namelen = save_len;
+
+ return ret;
+ }
+--
+2.43.0
+
--- /dev/null
+From b41009cf4f2057c500dedc997efbbb0c27d29d8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Dec 2023 10:25:31 +0800
+Subject: net: sched: em_text: fix possible memory leak in em_text_destroy()
+
+From: Hangyu Hua <hbh25y@gmail.com>
+
+[ Upstream commit 8fcb0382af6f1ef50936f1be05b8149eb2f88496 ]
+
+m->data needs to be freed when em_text_destroy is called.
+
+Fixes: d675c989ed2d ("[PKT_SCHED]: Packet classification based on textsearch (ematch)")
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Hangyu Hua <hbh25y@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/em_text.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/em_text.c b/net/sched/em_text.c
+index 6f3c1fb2fb44c..f176afb70559e 100644
+--- a/net/sched/em_text.c
++++ b/net/sched/em_text.c
+@@ -97,8 +97,10 @@ static int em_text_change(struct net *net, void *data, int len,
+
+ static void em_text_destroy(struct tcf_ematch *m)
+ {
+- if (EM_TEXT_PRIV(m) && EM_TEXT_PRIV(m)->config)
++ if (EM_TEXT_PRIV(m) && EM_TEXT_PRIV(m)->config) {
+ textsearch_destroy(EM_TEXT_PRIV(m)->config);
++ kfree(EM_TEXT_PRIV(m));
++ }
+ }
+
+ static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m)
+--
+2.43.0
+
--- /dev/null
+From f5752280b642e9f3dc6c4d30a318371cba6f4c0b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Mar 2023 08:07:38 -0800
+Subject: net-timestamp: extend SOF_TIMESTAMPING_OPT_ID to HW timestamps
+
+From: Vadim Fedorenko <vadfed@meta.com>
+
+[ Upstream commit 8ca5a5790b9a1ce147484d2a2c4e66d2553f3d6c ]
+
+When the feature was added it was enabled for SW timestamps only but
+with current hardware the same out-of-order timestamps can be seen.
+Let's expand the area for the feature to all types of timestamps.
+
+Signed-off-by: Vadim Fedorenko <vadfed@meta.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 7f6ca95d16b9 ("net: Implement missing getsockopt(SO_TIMESTAMPING_NEW)")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_output.c | 2 +-
+ net/ipv6/ip6_output.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
+index bf7c2333bc236..0f70c2dbbe5bb 100644
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -993,7 +993,7 @@ static int __ip_append_data(struct sock *sk,
+ mtu = cork->gso_size ? IP_MAX_MTU : cork->fragsize;
+ paged = !!cork->gso_size;
+
+- if (cork->tx_flags & SKBTX_ANY_SW_TSTAMP &&
++ if (cork->tx_flags & SKBTX_ANY_TSTAMP &&
+ sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)
+ tskey = sk->sk_tskey++;
+
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index d3455585e6a8c..c67d634dccd47 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1425,7 +1425,7 @@ static int __ip6_append_data(struct sock *sk,
+ mtu = cork->gso_size ? IP6_MAX_MTU : cork->fragsize;
+ orig_mtu = mtu;
+
+- if (cork->tx_flags & SKBTX_ANY_SW_TSTAMP &&
++ if (cork->tx_flags & SKBTX_ANY_TSTAMP &&
+ sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)
+ tskey = sk->sk_tskey++;
+
+--
+2.43.0
+
--- /dev/null
+From ca4a3af8c76a69f4405024d141d9857b16090aa2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Dec 2023 23:19:43 +0530
+Subject: nfc: llcp_core: Hold a ref to llcp_local->dev when holding a ref to
+ llcp_local
+
+From: Siddh Raman Pant <code@siddh.me>
+
+[ Upstream commit c95f919567d6f1914f13350af61a1b044ac85014 ]
+
+llcp_sock_sendmsg() calls nfc_llcp_send_ui_frame() which in turn calls
+nfc_alloc_send_skb(), which accesses the nfc_dev from the llcp_sock for
+getting the headroom and tailroom needed for skb allocation.
+
+Parallelly the nfc_dev can be freed, as the refcount is decreased via
+nfc_free_device(), leading to a UAF reported by Syzkaller, which can
+be summarized as follows:
+
+(1) llcp_sock_sendmsg() -> nfc_llcp_send_ui_frame()
+ -> nfc_alloc_send_skb() -> Dereference *nfc_dev
+(2) virtual_ncidev_close() -> nci_free_device() -> nfc_free_device()
+ -> put_device() -> nfc_release() -> Free *nfc_dev
+
+When a reference to llcp_local is acquired, we do not acquire the same
+for the nfc_dev. This leads to freeing even when the llcp_local is in
+use, and this is the case with the UAF described above too.
+
+Thus, when we acquire a reference to llcp_local, we should acquire a
+reference to nfc_dev, and release the references appropriately later.
+
+References for llcp_local is initialized in nfc_llcp_register_device()
+(which is called by nfc_register_device()). Thus, we should acquire a
+reference to nfc_dev there.
+
+nfc_unregister_device() calls nfc_llcp_unregister_device() which in
+turn calls nfc_llcp_local_put(). Thus, the reference to nfc_dev is
+appropriately released later.
+
+Reported-and-tested-by: syzbot+bbe84a4010eeea00982d@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=bbe84a4010eeea00982d
+Fixes: c7aa12252f51 ("NFC: Take a reference on the LLCP local pointer when creating a socket")
+Reviewed-by: Suman Ghosh <sumang@marvell.com>
+Signed-off-by: Siddh Raman Pant <code@siddh.me>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_core.c | 39 ++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 36 insertions(+), 3 deletions(-)
+
+diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
+index 92f70686bee0a..da3cb0d29b972 100644
+--- a/net/nfc/llcp_core.c
++++ b/net/nfc/llcp_core.c
+@@ -147,6 +147,13 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device,
+
+ static struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
+ {
++ /* Since using nfc_llcp_local may result in usage of nfc_dev, whenever
++ * we hold a reference to local, we also need to hold a reference to
++ * the device to avoid UAF.
++ */
++ if (!nfc_get_device(local->dev->idx))
++ return NULL;
++
+ kref_get(&local->ref);
+
+ return local;
+@@ -179,10 +186,18 @@ static void local_release(struct kref *ref)
+
+ int nfc_llcp_local_put(struct nfc_llcp_local *local)
+ {
++ struct nfc_dev *dev;
++ int ret;
++
+ if (local == NULL)
+ return 0;
+
+- return kref_put(&local->ref, local_release);
++ dev = local->dev;
++
++ ret = kref_put(&local->ref, local_release);
++ nfc_put_device(dev);
++
++ return ret;
+ }
+
+ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
+@@ -968,8 +983,17 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
+ }
+
+ new_sock = nfc_llcp_sock(new_sk);
+- new_sock->dev = local->dev;
++
+ new_sock->local = nfc_llcp_local_get(local);
++ if (!new_sock->local) {
++ reason = LLCP_DM_REJ;
++ sock_put(&new_sock->sk);
++ release_sock(&sock->sk);
++ sock_put(&sock->sk);
++ goto fail;
++ }
++
++ new_sock->dev = local->dev;
+ new_sock->rw = sock->rw;
+ new_sock->miux = sock->miux;
+ new_sock->nfc_protocol = sock->nfc_protocol;
+@@ -1607,7 +1631,16 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
+ if (local == NULL)
+ return -ENOMEM;
+
+- local->dev = ndev;
++ /* As we are going to initialize local's refcount, we need to get the
++ * nfc_dev to avoid UAF, otherwise there is no point in continuing.
++ * See nfc_llcp_local_get().
++ */
++ local->dev = nfc_get_device(ndev->idx);
++ if (!local->dev) {
++ kfree(local);
++ return -ENODEV;
++ }
++
+ INIT_LIST_HEAD(&local->list);
+ kref_init(&local->ref);
+ mutex_init(&local->sdp_lock);
+--
+2.43.0
+
smb-client-fix-oob-in-smbcalcsize.patch
ring-buffer-fix-wake-ups-when-buffer_percent-is-set-to-100.patch
block-don-t-invalidate-pagecache-for-invalid-falloc-modes.patch
+nfc-llcp_core-hold-a-ref-to-llcp_local-dev-when-hold.patch
+i40e-fix-filter-input-checks-to-prevent-config-with-.patch
+net-sched-em_text-fix-possible-memory-leak-in-em_tex.patch
+net-implement-missing-getsockopt-so_timestamping_new.patch
+can-raw-add-support-for-so_txtime-scm_txtime.patch
+can-raw-add-support-for-so_mark.patch
+net-timestamp-extend-sof_timestamping_opt_id-to-hw-t.patch
+arm-sun9i-smp-fix-array-index-out-of-bounds-read-in-.patch
+net-bcmgenet-fix-fcs-generation-for-fragmented-skbuf.patch
+net-save-and-restore-msg_namelen-in-sock_sendmsg.patch
+i40e-fix-use-after-free-in-i40e_aqc_add_filters.patch
+asoc-meson-g12a-extract-codec-to-codec-utils.patch
+asoc-meson-g12a-tohdmitx-validate-written-enum-value.patch
+asoc-meson-g12a-tohdmitx-fix-event-generation-for-s-.patch
+i40e-restore-vf-msi-x-state-during-pci-reset.patch
+net-qla3xxx-switch-from-pci_-to-dma_-api.patch
+net-qla3xxx-fix-potential-memleak-in-ql_alloc_buffer.patch
+asix-add-check-for-usbnet_get_endpoints.patch
+bnxt_en-remove-mis-applied-code-from-bnxt_cfg_ntp_fi.patch
+net-implement-missing-so_timestamping_new-cmsg-suppo.patch
+mm-memory-failure-check-the-mapcount-of-the-precise-.patch